diff --git a/CMakeLists.txt b/CMakeLists.txt index b862a07..a637651 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,7 +98,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "SunOS") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_XOPEN_SOURCE=600") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBSD_COMP") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fpic") - set(PLATFORM_LIBS ${PLATFORM_LIBS} nsl socket) + set(PLATFORM_LIBS ${PLATFORM_LIBS} dl md nsl socket) endif() add_definitions(-DLIBRESSL_INTERNAL) @@ -286,11 +286,21 @@ if(HAVE_MEMMEM) add_definitions(-DHAVE_MEMMEM) endif() +check_include_files(endian.h HAVE_ENDIAN_H) +if(HAVE_ENDIAN_H) + add_definitions(-DHAVE_ENDIAN_H) +endif() + check_include_files(err.h HAVE_ERR_H) if(HAVE_ERR_H) add_definitions(-DHAVE_ERR_H) endif() +check_include_files("sys/types.h;arpa/inet.h;netinet/ip.h" HAVE_NETINET_IP_H) +if(HAVE_NETINET_IP_H) + add_definitions(-DHAVE_NETINET_IP_H) +endif() + if(ENABLE_ASM) if("${CMAKE_C_COMPILER_ABI}" STREQUAL "ELF") if("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "(x86_64|amd64)") @@ -337,30 +347,54 @@ add_definitions(-DSIZEOF_TIME_T=${SIZEOF_TIME_T}) set(OPENSSL_LIBS ssl crypto ${PLATFORM_LIBS}) set(LIBTLS_LIBS tls ${PLATFORM_LIBS}) +# libraries for regression test +if(BUILD_SHARED_LIBS) + set(OPENSSL_TEST_LIBS ssl-static crypto-static ${PLATFORM_LIBS}) + set(LIBTLS_TEST_LIBS tls-static ${PLATFORM_LIBS}) +else() + set(OPENSSL_TEST_LIBS ssl crypto ${PLATFORM_LIBS}) + set(LIBTLS_TEST_LIBS tls ${PLATFORM_LIBS}) +endif() + add_subdirectory(crypto) add_subdirectory(ssl) add_subdirectory(tls) add_subdirectory(include) -if(NOT MSVC) - # Create pkgconfig files. - set(prefix ${CMAKE_INSTALL_PREFIX}) - set(exec_prefix \${prefix}) - set(libdir \${exec_prefix}/${CMAKE_INSTALL_LIBDIR}) - set(includedir \${prefix}/include) - if(PLATFORM_LIBS) - string(REGEX REPLACE ";" " -l" PLATFORM_LDADD ";${PLATFORM_LIBS}") +if (BUILD_APPLE_XCFRAMEWORK) + # Create the super library from object libraries + add_library(LibreSSL_xcframework + $ $ $) + set_target_properties(LibreSSL_xcframework PROPERTIES + OUTPUT_NAME ressl) + + if(ENABLE_LIBRESSL_INSTALL) + install(TARGETS LibreSSL_xcframework + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) + endif(ENABLE_LIBRESSL_INSTALL) +endif(BUILD_APPLE_XCFRAMEWORK) + +if(ENABLE_LIBRESSL_INSTALL) + if(NOT MSVC) + # Create pkgconfig files. + set(prefix ${CMAKE_INSTALL_PREFIX}) + set(exec_prefix \${prefix}) + set(libdir \${exec_prefix}/${CMAKE_INSTALL_LIBDIR}) + set(includedir \${prefix}/include) + if(PLATFORM_LIBS) + string(REGEX REPLACE ";" " -l" PLATFORM_LDADD ";${PLATFORM_LIBS}") + endif() + file(STRINGS "VERSION" VERSION LIMIT_COUNT 1) + file(GLOB OPENSSL_PKGCONFIGS "*.pc.in") + foreach(file ${OPENSSL_PKGCONFIGS}) + get_filename_component(filename ${file} NAME) + string(REPLACE ".in" "" new_file "${filename}") + configure_file(${filename} pkgconfig/${new_file} @ONLY) + endforeach() + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/pkgconfig + DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif() - file(STRINGS "VERSION" VERSION LIMIT_COUNT 1) - file(GLOB OPENSSL_PKGCONFIGS "*.pc.in") - foreach(file ${OPENSSL_PKGCONFIGS}) - get_filename_component(filename ${file} NAME) - string(REPLACE ".in" "" new_file "${filename}") - configure_file(${filename} pkgconfig/${new_file} @ONLY) - endforeach() - install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/pkgconfig - DESTINATION ${CMAKE_INSTALL_LIBDIR}) -endif() +endif(ENABLE_LIBRESSL_INSTALL) if(NOT "${OPENSSLDIR}" STREQUAL "") set(CONF_DIR "${OPENSSLDIR}") diff --git a/ChangeLog b/ChangeLog index 5a458ca..e4dc7ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -28,11 +28,301 @@ history is also available from Git. LibreSSL Portable Release Notes: -3.4.2 - Security fix +3.5.2 - Stable release - * In some situations the X.509 verifier would discard an error on an - unverified certificate chain, resulting in an authentication bypass. - Thanks to Ilya Shipitsin and Timo Steinlein for reporting. + * Bug fixes + - Avoid single byte overread in asn1_parse2(). + - Allow name constraints with a leading dot. From Alex Wilson. + - Relax a check in x509_constraints_dirname() to allow prefixes. + From Alex Wilson. + - Fix NULL dereferences in openssl(1) cms option parsing. + - Do not zero the computed cofactor on ec_guess_cofactor() success. + - Bound cofactor in EC_GROUP_set_generator() to reduce the number of + bogus groups that can be described with nonsensical parameters. + - Avoid various potential segfaults in EVP_PKEY_CTX_free() in low + memory conditions. Reported for HMAC by Masaru Masuda. + - Plug leak in ASN1_TIME_adj_internal(). + - Avoid infinite loop for custom curves of order 1. + Issue reported by Hanno Boeck, comments by David Benjamin. + - Avoid an infinite loop on parsing DSA private keys by validating + that the provided parameters conform to FIPS 186-4. + Issue reported by Hanno Boeck, comments by David Benjamin. + * Compatibility improvements + - Allow non-standard name constraints of the form @domain.com. + * Internal improvements + - Limit OID text conversion to 64 bits per arc. + - Clean up and simplify memory BIO code. + - Reduce number of memmove() calls in memory BIOs. + - Factor out alert handling code in the legacy stack. + - Add sanity checks on p and q in old_dsa_priv_decode() + - Cache the SHA-512 hash instead of the SHA-1 for CRLs. + - Suppress various compiler warnings for old gcc versions. + - Remove free_cont from asn1_d2i_ex_primitive()/asn1_ex_c2i(). + - Rework ownership handling in x509_constraints_validate(). + - Rework ASN1_STRING_set(). + - Remove const from tls1_transcript_hash_value(). + - Clean up and simplify ssl3_renegotiate{,_check}(). + - Rewrite legacy TLS and DTLS unexpected handshake message handling. + - Simplify SSL_do_handshake(). + - Rewrite ASCII/text to ASN.1 object conversion. + - Provide t2i_ASN1_OBJECT_internal() and use it for OBJ_txt2obj(). + - Split armv7 and aarch64 code into separate locations. + - Rewrote openssl(1) ts to use the new option handling and cleaned + up the C code. + - Provide asn1_get_primitive(). + - Convert {c2i,d2i}_ASN1_OBJECT() to CBS. + - Remove the minimum record length checks from dtls1_read_bytes(). + - Clean up {dtls1,ssl3}_read_bytes(). + - Be more careful with embedded and terminating NULs in the new + name constraints code. + - Check EVP_Digest* return codes in openssl(1) ts + - Various minor code cleanup in openssl(1) pkcs12 + - Use calloc() in pkey_hmac_init(). + - Simplify priv_key handling in d2i_ECPrivateKey(). + * Documentation improvements + - Update d2i_ASN1_OBJECT(3) documentation to reflect reality after + refactoring and bug fixes. + - Fixed numerous minor grammar, spelling, wording, and punctuation + issues. + +3.5.1 - Security release + + * A malicious certificate can cause an infinite loop. + Reported by and fix from Tavis Ormandy and David Benjamin, Google. + +3.5.0 - Development release + + * New Features + - The RFC 3779 API was ported from OpenSSL. Many bugs were fixed, + regression tests were added and the code was cleaned up. + - Certificate Transparency was ported from OpenSSL. Many internal + improvements were made, resulting in cleaner and safer code. + Regress coverage was added. libssl does not yet make use of it. + * Portable Improvements + - Fixed various POSIX compliance and other portability issues + found by the port to the Sortix operating system. + - Add libmd as platform specific libraries for Solaris. + Issue reported from (ihsan opencsw org) on libressl ML. + - Set IA-64 compiler flag only if it is HP-UX with IA-64. + Suggested from Larkin Nickle (me larbob org) by libressl ML. + - Enabled and scheduled Coverity scan. + Contributed by Ilya Shipitsin (chipitsine gmail com> on github. + * Compatibility Changes + - Most structs that were previously defined in the following headers + are now opaque as they are in OpenSSL 1.1: + bio.h, bn.h, comp.h, dh.h, dsa.h, evp.h, hmac.h, ocsp.h, rsa.h, + x509.h, x509v3.h, x509_vfy.h + - Switch TLSv1.3 cipher names from AEAD- to OpenSSL's TLS_ + OpenSSL added the TLSv1.3 ciphersuites with "RFC names" instead + of using something consistent with the previous naming. Various + test suites expect these names (instead of checking for the much + more sensible cipher numbers). The old names are still accepted + as aliases. + - Subject alternative names and name constraints are now validated + when they are added to certificates. Various interoperability + problems with stacks that validate certificates more strictly + than OpenSSL can be avoided this way. + - Attempt to opportunistically use the host name for SNI in s_client + * Bug fixes + - In some situations, the verifier would discard the error on an + unvalidated certificate chain. This would happen when the + verification callback was in use, instructing the verifier to + continue unconditionally. This could lead to incorrect decisions + being made in software. + - Avoid an infinite loop in SSL_shutdown() + - Fix another return 0 bug in SSL_shutdown() + - Handle zero byte reads/writes that trigger handshakes in the + TLSv1.3 stack + - A long standing memleak in libtls CRL handling was fixed + * Internal Improvements + - Cache the SHA-512 hash instead of the SHA-1 hash and cache + notBefore and notAfter times when X.509 certificates are parsed. + - The X.509 lookup code has been simplified and cleaned up. + - Fixed numerous issues flagged by coverity and the cryptofuzz + project + - Increased the number of Miller-Rabin checks in DH and DSA + key/parameter generation + - Started using the bytestring API in libcrypto for cleaner and + safer code + - Convert {i2d,d2i}_{,EC_,DSA_,RSA_}PUBKEY{,_bio,_fp}() to templated + ASN1 + - Convert ASN1_OBJECT_new() to calloc() + - Convert ASN1_STRING_type_new() to calloc() + - Rewrite ASN1_STRING_cmp() + - Use calloc() for X509_CRL_METHOD_new() instead of malloc() + - Convert ASN1_PCTX_new() to calloc() + - Replace asn1_tlc_clear and asn1_tlc_clear_nc macros with a + function + - Consolidate {d2i,i2d}_{pr,pu}.c + - Remove handling of a NULL BUF_MEM from asn1_collect() + - Pull the recursion depth check up to the top of asn1_collect() + - Inline collect_data() in asn1_collect() + - Convert asn1_d2i_ex_primitive()/asn1_collect() from BUF_MEM to CBB + - Clean up d2i_ASN1_BOOLEAN() and i2d_ASN1_BOOLEAN() + - Consolidate ASN.1 universal tag type data + - Rewrite ASN.1 identifier/length parsing in CBS + - Make OBJ_obj2nid() work correctly with NID_undef + - tlsext_tick_lifetime_hint is now an uint32_t + - Untangle ssl3_get_message() return values + - Rename tls13_buffer to tls_buffer + - Fold DTLS_STATE_INTERNAL into DTLS1_STATE + - Provide a way to determine our maximum legacy version + - Mop up enc_read_ctx and read_hash + - Fold SSL_SESSION_INTERNAL into SSL_SESSION + - Use ssl_force_want_read in the DTLS code + - Add record processing limit to DTLS code + - Add explicit CBS_contains_zero_byte() check in CBS_strdup() + - Improve SNI hostname validation + - Ensure SSL_set_tlsext_host_name() is given a valid hostname + - Fix a strange check in the auto DH codepath + - Factor out/rewrite DHE key exchange + - Convert server serialisation of DHE parameters/public key to new + functions + - Check DH public key in ssl_kex_peer_public_dhe() + - Move the minimum DHE key size check into ssl_kex_peer_params_dhe() + - Clean up and refactor server side DHE key exchange + - Provide CBS_get_last_u8() + - Provide CBS_get_u64() + - Provide CBS_add_u64() + - Provide various CBS_peek_* functions + - Use CBS_get_last_u8() to find the content type in TLSv1.3 records + - unifdef TLS13_USE_LEGACY_CLIENT_AUTH + - Correct SSL_get_peer_cert_chain() when used with the TLSv1.3 stack + - Only allow zero length key shares when we know we're doing HRR + - Pull key share group/length CBB code up from + tls13_key_share_public() + - Refactor ssl3_get_server_kex_ecdhe() to separate parsing and + validation + - Return 0 on failure from send/get kex functions in the legacy + stack + - Rename tls13_key_share to tls_key_share + - Allocate and free the EVP_AEAD_CTX struct in + tls13_record_protection + - Convert legacy TLS client to tls_key_share + - Convert legacy TLS server to tls_key_share + - Stop attempting to duplicate the public and private key of dh_tmp + - Rename dh_tmp to dhe_params + - Rename CERT to SSL_CERT and CERT_PKEY to SSL_CERT_PKEY + - Clean up pkey handling in ssl3_get_server_key_exchange() + - Fix GOST skip certificate verify handling + - Simplify tlsext_keyshare_server_parse() + - Plumb decode errors through key share parsing code + - Simplify SSL_get_peer_certificate() + - Cleanup/simplify ssl_cert_type() + - The S3I macro was removed + - The openssl(1) cms and smime subcommands option handling was + converted and the C source was cleaned up. + * Documentation improvements + - 45 new manual pages, most of which were written from scratch. + Documentation coverage of ASN.1 and X.509 code has been + significantly improved. + * API additions and removals + - libssl + API additions + SSL_get0_verified_chain SSL_peek_ex SSL_read_ex SSL_write_ex + API stubs for compatibility + SSL_CTX_get_keylog_callback SSL_CTX_get_num_tickets + SSL_CTX_set_keylog_callback SSL_CTX_set_num_tickets + SSL_get_num_tickets SSL_set_num_tickets + - libcrypto + added API (some of these were previously available as macros): + ASIdOrRange_free ASIdOrRange_new ASIdentifierChoice_free + ASIdentifierChoice_new ASIdentifiers_free ASIdentifiers_new + ASN1_TIME_diff ASRange_free ASRange_new BIO_get_callback_ex + BIO_get_init BIO_set_callback_ex BIO_set_next + BIO_set_retry_reason BN_GENCB_set BN_GENCB_set_old + BN_abs_is_word BN_get_flags BN_is_negative + BN_is_odd BN_is_one BN_is_word BN_is_zero BN_set_flags + BN_to_montgomery BN_with_flags BN_zero_ex CTLOG_STORE_free + CTLOG_STORE_get0_log_by_id CTLOG_STORE_load_default_file + CTLOG_STORE_load_file CTLOG_STORE_new CTLOG_free + CTLOG_get0_log_id CTLOG_get0_name CTLOG_get0_public_key + CTLOG_new CTLOG_new_from_base64 CT_POLICY_EVAL_CTX_free + CT_POLICY_EVAL_CTX_get0_cert CT_POLICY_EVAL_CTX_get0_issuer + CT_POLICY_EVAL_CTX_get0_log_store CT_POLICY_EVAL_CTX_get_time + CT_POLICY_EVAL_CTX_new CT_POLICY_EVAL_CTX_set1_cert + CT_POLICY_EVAL_CTX_set1_issuer + CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE + CT_POLICY_EVAL_CTX_set_time DH_get0_g DH_get0_p DH_get0_priv_key + DH_get0_pub_key DH_get0_q DH_get_length DSA_bits DSA_get0_g + DSA_get0_p DSA_get0_priv_key DSA_get0_pub_key DSA_get0_q + ECDSA_SIG_get0_r ECDSA_SIG_get0_s EVP_AEAD_CTX_free + EVP_AEAD_CTX_new EVP_CIPHER_CTX_buf_noconst + EVP_CIPHER_CTX_get_cipher_data EVP_CIPHER_CTX_set_cipher_data + EVP_MD_CTX_md_data EVP_MD_CTX_pkey_ctx EVP_MD_CTX_set_pkey_ctx + EVP_MD_meth_dup EVP_MD_meth_free EVP_MD_meth_new + EVP_MD_meth_set_app_datasize EVP_MD_meth_set_cleanup + EVP_MD_meth_set_copy EVP_MD_meth_set_ctrl EVP_MD_meth_set_final + EVP_MD_meth_set_flags EVP_MD_meth_set_init + EVP_MD_meth_set_input_blocksize EVP_MD_meth_set_result_size + EVP_MD_meth_set_update EVP_PKEY_asn1_set_check + EVP_PKEY_asn1_set_param_check EVP_PKEY_asn1_set_public_check + EVP_PKEY_check EVP_PKEY_meth_set_check + EVP_PKEY_meth_set_param_check EVP_PKEY_meth_set_public_check + EVP_PKEY_param_check EVP_PKEY_public_check FIPS_mode + FIPS_mode_set IPAddressChoice_free IPAddressChoice_new + IPAddressFamily_free IPAddressFamily_new IPAddressOrRange_free + IPAddressOrRange_new IPAddressRange_free IPAddressRange_new + OBJ_get0_data OBJ_length OCSP_resp_get0_certs OCSP_resp_get0_id + OCSP_resp_get0_produced_at OCSP_resp_get0_respdata + OCSP_resp_get0_signature OCSP_resp_get0_signer + OCSP_resp_get0_tbs_sigalg PEM_write_bio_PrivateKey_traditional + RSA_get0_d RSA_get0_dmp1 RSA_get0_dmq1 RSA_get0_e RSA_get0_iqmp + RSA_get0_n RSA_get0_p RSA_get0_pss_params RSA_get0_q + SCT_LIST_free SCT_LIST_print SCT_LIST_validate SCT_free + SCT_get0_extensions SCT_get0_log_id SCT_get0_signature + SCT_get_log_entry_type SCT_get_signature_nid SCT_get_source + SCT_get_timestamp SCT_get_validation_status SCT_get_version + SCT_new SCT_new_from_base64 SCT_print SCT_set0_extensions + SCT_set0_log_id SCT_set0_signature SCT_set1_extensions + SCT_set1_log_id SCT_set1_signature SCT_set_log_entry_type + SCT_set_signature_nid SCT_set_source SCT_set_timestamp + SCT_set_version SCT_validate SCT_validation_status_string + X509_OBJECT_free X509_OBJECT_new X509_REQ_get0_pubkey + X509_SIG_get0 X509_SIG_getm X509_STORE_CTX_get_by_subject + X509_STORE_CTX_get_num_untrusted + X509_STORE_CTX_get_obj_by_subject X509_STORE_CTX_get_verify + X509_STORE_CTX_get_verify_cb X509_STORE_CTX_set0_verified_chain + X509_STORE_CTX_set_current_cert X509_STORE_CTX_set_error_depth + X509_STORE_CTX_set_verify X509_STORE_get_verify + X509_STORE_get_verify_cb X509_STORE_set_verify + X509_get_X509_PUBKEY X509_get_extended_key_usage + X509_get_extension_flags X509_get_key_usage + X509v3_addr_add_inherit X509v3_addr_add_prefix + X509v3_addr_add_range X509v3_addr_canonize X509v3_addr_get_afi + X509v3_addr_get_range X509v3_addr_inherits + X509v3_addr_is_canonical X509v3_addr_subset + X509v3_addr_validate_path X509v3_addr_validate_resource_set + X509v3_asid_add_id_or_range X509v3_asid_add_inherit + X509v3_asid_canonize X509v3_asid_inherits + X509v3_asid_is_canonical X509v3_asid_subset + X509v3_asid_validate_path X509v3_asid_validate_resource_set + d2i_ASIdOrRange d2i_ASIdentifierChoice d2i_ASIdentifiers + d2i_ASRange d2i_IPAddressChoice d2i_IPAddressFamily + d2i_IPAddressOrRange d2i_IPAddressRange d2i_SCT_LIST + i2d_ASIdOrRange i2d_ASIdentifierChoice i2d_ASIdentifiers + i2d_ASRange i2d_IPAddressChoice i2d_IPAddressFamily + i2d_IPAddressOrRange i2d_IPAddressRange i2d_SCT_LIST + i2d_re_X509_CRL_tbs i2d_re_X509_REQ_tbs i2d_re_X509_tbs i2o_SCT + i2o_SCT_LIST o2i_SCT o2i_SCT_LIST + removed API: + ASN1_check_infinite_end ASN1_const_check_infinite_end EVP_dss + EVP_dss1 EVP_ecdsa HMAC_CTX_cleanup HMAC_CTX_init + NETSCAPE_ENCRYPTED_PKEY_free NETSCAPE_ENCRYPTED_PKEY_new + NETSCAPE_PKEY_free NETSCAPE_PKEY_new NETSCAPE_X509_free + NETSCAPE_X509_new OBJ_bsearch_ex_ PEM_SealFinal PEM_SealInit + PEM_SealUpdate PEM_read_X509_CERT_PAIR + PEM_read_bio_X509_CERT_PAIR PEM_write_X509_CERT_PAIR + PEM_write_bio_X509_CERT_PAIR X509_CERT_PAIR_free + X509_CERT_PAIR_new X509_OBJECT_free_contents asn1_do_adb + asn1_do_lock asn1_enc_free asn1_enc_init asn1_enc_restore + asn1_enc_save asn1_ex_c2i asn1_get_choice_selector + asn1_get_field_ptr asn1_set_choice_selector check_defer + d2i_ASN1_BOOLEAN d2i_NETSCAPE_ENCRYPTED_PKEY d2i_NETSCAPE_PKEY + d2i_NETSCAPE_X509 d2i_Netscape_RSA d2i_RSA_NET + d2i_X509_CERT_PAIR i2d_ASN1_BOOLEAN i2d_NETSCAPE_ENCRYPTED_PKEY + i2d_NETSCAPE_PKEY i2d_NETSCAPE_X509 i2d_Netscape_RSA i2d_RSA_NET + i2d_X509_CERT_PAIR name_cmp obj_cleanup_defer 3.4.1 - Stable release diff --git a/README.md b/README.md index 2a04248..26855e6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Built from https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-3.4.2.tar.gz +Built from https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-3.5.2.tar.gz Modifications: - Removed tests/mandocs/pkgconfig/scripts/apps/cmake_uninstall from both filesystem and CMakeLists.txt @@ -14,6 +14,7 @@ Modifications: [![Android_Build Status](https://github.com/libressl-portable/portable/actions/workflows/android_test.yml/badge.svg)](https://github.com/libressl-portable/portable/actions/workflows/android_test.yml) [![Cross_Build Status](https://github.com/libressl-portable/portable/actions/workflows/cross_test.yml/badge.svg)](https://github.com/libressl-portable/portable/actions/workflows/cross_test.yml) [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/libressl.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:libressl) +[![ASan Status](https://github.com/libressl-portable/portable/actions/workflows/linux_test_asan.yml/badge.svg)](https://github.com/libressl-portable/portable/actions/workflows/linux_test_asan.yml) LibreSSL is a fork of [OpenSSL](https://www.openssl.org) 1.0.1g developed by the [OpenBSD](https://www.openbsd.org) project. Our goal is to modernize the codebase, diff --git a/VERSION b/VERSION index ec46c1f..8b7c8d3 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ -3.4.2 +3.5.2 diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt index b1ded85..9b66d9f 100644 --- a/crypto/CMakeLists.txt +++ b/crypto/CMakeLists.txt @@ -1,3 +1,5 @@ +add_definitions(-DLIBRESSL_CRYPTO_INTERNAL) + if(HOST_ASM_ELF_ARMV4) set( ASM_ARMV4_ELF_SRC @@ -231,6 +233,7 @@ set( malloc-wrapper.c mem_clr.c mem_dbg.c + o_fips.c o_init.c o_str.c o_time.c @@ -242,49 +245,38 @@ set( aes/aes_ofb.c aes/aes_wrap.c asn1/a_bitstr.c - asn1/a_bool.c - asn1/a_d2i_fp.c - asn1/a_digest.c - asn1/a_dup.c asn1/a_enum.c - asn1/a_i2d_fp.c asn1/a_int.c asn1/a_mbstr.c asn1/a_object.c asn1/a_octet.c + asn1/a_pkey.c asn1/a_print.c - asn1/a_sign.c + asn1/a_pubkey.c asn1/a_strex.c + asn1/a_string.c asn1/a_strnid.c asn1/a_time.c asn1/a_time_tm.c asn1/a_type.c asn1/a_utf8.c - asn1/a_verify.c asn1/ameth_lib.c asn1/asn1_err.c asn1/asn1_gen.c + asn1/asn1_item.c asn1/asn1_lib.c + asn1/asn1_old.c + asn1/asn1_old_lib.c asn1/asn1_par.c + asn1/asn1_types.c asn1/asn_mime.c asn1/asn_moid.c - asn1/asn_pack.c asn1/bio_asn1.c asn1/bio_ndef.c - asn1/d2i_pr.c - asn1/d2i_pu.c - asn1/evp_asn1.c - asn1/f_enum.c - asn1/f_int.c - asn1/f_string.c - asn1/i2d_pr.c - asn1/i2d_pu.c - asn1/n_pkey.c asn1/nsseq.c asn1/p5_pbe.c asn1/p5_pbev2.c asn1/p8_pkey.c - asn1/t_bitst.c asn1/t_crl.c asn1/t_pkey.c asn1/t_req.c @@ -306,7 +298,6 @@ set( asn1/x_info.c asn1/x_long.c asn1/x_name.c - asn1/x_nx509.c asn1/x_pkey.c asn1/x_pubkey.c asn1/x_req.c @@ -370,6 +361,9 @@ set( buffer/buf_err.c buffer/buf_str.c buffer/buffer.c + bytestring/bs_ber.c + bytestring/bs_cbb.c + bytestring/bs_cbs.c camellia/cmll_cfb.c camellia/cmll_ctr.c camellia/cmll_ecb.c @@ -409,6 +403,16 @@ set( conf/conf_mall.c conf/conf_mod.c conf/conf_sap.c + ct/ct_b64.c + ct/ct_err.c + ct/ct_log.c + ct/ct_oct.c + ct/ct_policy.c + ct/ct_prn.c + ct/ct_sct.c + ct/ct_sct_ctx.c + ct/ct_vfy.c + ct/ct_x509v3.c curve25519/curve25519-generic.c curve25519/curve25519.c des/cbc_cksm.c @@ -550,9 +554,6 @@ set( evp/evp_lib.c evp/evp_pbe.c evp/evp_pkey.c - evp/m_dss.c - evp/m_dss1.c - evp/m_ecdsa.c evp/m_gost2814789.c evp/m_gostr341194.c evp/m_md4.c @@ -636,7 +637,6 @@ set( pem/pem_oth.c pem/pem_pk8.c pem/pem_pkey.c - pem/pem_seal.c pem/pem_sign.c pem/pem_x509.c pem/pem_xaux.c @@ -726,9 +726,11 @@ set( x509/pcy_map.c x509/pcy_node.c x509/pcy_tree.c + x509/x509_addr.c x509/x509_akey.c x509/x509_akeya.c x509/x509_alt.c + x509/x509_asid.c x509/x509_att.c x509/x509_bcons.c x509/x509_bitst.c @@ -875,6 +877,11 @@ if(NOT HAVE_STRSEP) set(EXTRA_EXPORT ${EXTRA_EXPORT} strsep) endif() +if(NOT HAVE_STRTONUM) + set(CRYPTO_SRC ${CRYPTO_SRC} compat/strtonum.c) + set(EXTRA_EXPORT ${EXTRA_EXPORT} strtonum) +endif() + if(NOT HAVE_SYSLOG_R) set(CRYPTO_SRC ${CRYPTO_SRC} compat/syslog_r.c) endif() @@ -975,32 +982,25 @@ target_include_directories(crypto_obj PRIVATE . asn1 + bio bn + bytestring + dh dsa ec ecdh ecdsa evp + hmac modes + ocsp + rsa + x509 ../include/compat PUBLIC ../include) add_library(crypto $) -target_include_directories(crypto - PRIVATE - . - asn1 - bn - dsa - ec - ecdh - ecdsa - evp - modes - ../include/compat - PUBLIC - ../include) export_symbol(crypto ${CMAKE_CURRENT_BINARY_DIR}/crypto_p.sym) target_link_libraries(crypto ${PLATFORM_LIBS}) @@ -1021,3 +1021,10 @@ if(ENABLE_LIBRESSL_INSTALL) RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) endif(ENABLE_LIBRESSL_INSTALL) + +# build static library for regression test +if(BUILD_SHARED_LIBS) + add_library(crypto-static STATIC $) + target_link_libraries(crypto-static ${PLATFORM_LIBS}) +endif() + diff --git a/crypto/VERSION b/crypto/VERSION index b10dcdd..81abba8 100644 --- a/crypto/VERSION +++ b/crypto/VERSION @@ -1 +1 @@ -47:0:0 +49:0:0 diff --git a/crypto/aes/aes-masm-x86_64.S b/crypto/aes/aes-masm-x86_64.S index 9094c72..e99ccf6 100644 --- a/crypto/aes/aes-masm-x86_64.S +++ b/crypto/aes/aes-masm-x86_64.S @@ -1,7 +1,7 @@ ; 1 "crypto/aes/aes-masm-x86_64.S.tmp" ; 1 "" 1 ; 1 "" 3 -; 340 "" 3 +; 343 "" 3 ; 1 "" 1 ; 1 "" 2 ; 1 "crypto/aes/aes-masm-x86_64.S.tmp" 2 diff --git a/crypto/aes/aes_ige.c b/crypto/aes/aes_ige.c index 16ef561..244a5a3 100644 --- a/crypto/aes/aes_ige.c +++ b/crypto/aes/aes_ige.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aes_ige.c,v 1.7 2015/02/10 09:46:30 miod Exp $ */ +/* $OpenBSD: aes_ige.c,v 1.8 2022/01/22 00:43:41 inoguchi Exp $ */ /* ==================================================================== * Copyright (c) 2006 The OpenSSL Project. All rights reserved. * @@ -109,8 +109,8 @@ AES_ige_encrypt(const unsigned char *in, unsigned char *out, size_t length, in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } - memcpy(ivec, ivp->data, AES_BLOCK_SIZE); - memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); + memmove(ivec, ivp->data, AES_BLOCK_SIZE); + memmove(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); } else { aes_block_t tmp, tmp2; aes_block_t iv; @@ -161,8 +161,8 @@ AES_ige_encrypt(const unsigned char *in, unsigned char *out, size_t length, in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } - memcpy(ivec, ivp->data, AES_BLOCK_SIZE); - memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); + memmove(ivec, ivp->data, AES_BLOCK_SIZE); + memmove(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); } else { aes_block_t tmp, tmp2; aes_block_t iv; diff --git a/crypto/aes/aesni-masm-x86_64.S b/crypto/aes/aesni-masm-x86_64.S index f2a2490..7c9224f 100644 --- a/crypto/aes/aesni-masm-x86_64.S +++ b/crypto/aes/aesni-masm-x86_64.S @@ -1,7 +1,7 @@ ; 1 "crypto/aes/aesni-masm-x86_64.S.tmp" ; 1 "" 1 ; 1 "" 3 -; 340 "" 3 +; 343 "" 3 ; 1 "" 1 ; 1 "" 2 ; 1 "crypto/aes/aesni-masm-x86_64.S.tmp" 2 diff --git a/crypto/aes/aesni-sha1-masm-x86_64.S b/crypto/aes/aesni-sha1-masm-x86_64.S index db95881..b87202a 100644 --- a/crypto/aes/aesni-sha1-masm-x86_64.S +++ b/crypto/aes/aesni-sha1-masm-x86_64.S @@ -1,7 +1,7 @@ ; 1 "crypto/aes/aesni-sha1-masm-x86_64.S.tmp" ; 1 "" 1 ; 1 "" 3 -; 340 "" 3 +; 343 "" 3 ; 1 "" 1 ; 1 "" 2 ; 1 "crypto/aes/aesni-sha1-masm-x86_64.S.tmp" 2 diff --git a/crypto/aes/bsaes-masm-x86_64.S b/crypto/aes/bsaes-masm-x86_64.S index 6b1a97d..7049860 100644 --- a/crypto/aes/bsaes-masm-x86_64.S +++ b/crypto/aes/bsaes-masm-x86_64.S @@ -1,7 +1,7 @@ ; 1 "crypto/aes/bsaes-masm-x86_64.S.tmp" ; 1 "" 1 ; 1 "" 3 -; 340 "" 3 +; 343 "" 3 ; 1 "" 1 ; 1 "" 2 ; 1 "crypto/aes/bsaes-masm-x86_64.S.tmp" 2 diff --git a/crypto/aes/vpaes-masm-x86_64.S b/crypto/aes/vpaes-masm-x86_64.S index e10d98d..fa24314 100644 --- a/crypto/aes/vpaes-masm-x86_64.S +++ b/crypto/aes/vpaes-masm-x86_64.S @@ -1,7 +1,7 @@ ; 1 "crypto/aes/vpaes-masm-x86_64.S.tmp" ; 1 "" 1 ; 1 "" 3 -; 340 "" 3 +; 343 "" 3 ; 1 "" 1 ; 1 "" 2 ; 1 "crypto/aes/vpaes-masm-x86_64.S.tmp" 2 diff --git a/crypto/arm_arch.h b/crypto/arm_arch.h index 8c5115e..5ac3b93 100644 --- a/crypto/arm_arch.h +++ b/crypto/arm_arch.h @@ -1,4 +1,4 @@ -/* $OpenBSD: arm_arch.h,v 1.10 2019/07/02 19:31:28 patrick Exp $ */ +/* $OpenBSD: arm_arch.h,v 1.1 2022/03/23 15:13:31 tb Exp $ */ #ifndef __ARM_ARCH_H__ #define __ARM_ARCH_H__ diff --git a/crypto/armcap.c b/crypto/armcap.c index 8c49832..e1a721b 100644 --- a/crypto/armcap.c +++ b/crypto/armcap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: armcap.c,v 1.8 2019/03/13 10:18:30 patrick Exp $ */ +/* $OpenBSD: armcap.c,v 1.1 2022/03/23 15:13:31 tb Exp $ */ #include #include #include diff --git a/crypto/asn1/a_bitstr.c b/crypto/asn1/a_bitstr.c index f217f13..4ffafd5 100644 --- a/crypto/asn1/a_bitstr.c +++ b/crypto/asn1/a_bitstr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: a_bitstr.c,v 1.30 2020/09/03 17:19:27 tb Exp $ */ +/* $OpenBSD: a_bitstr.c,v 1.33 2021/12/25 08:52:44 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -60,7 +60,28 @@ #include #include +#include +#include #include +#include + +const ASN1_ITEM ASN1_BIT_STRING_it = { + .itype = ASN1_ITYPE_PRIMITIVE, + .utype = V_ASN1_BIT_STRING, + .sname = "ASN1_BIT_STRING", +}; + +ASN1_BIT_STRING * +ASN1_BIT_STRING_new(void) +{ + return (ASN1_BIT_STRING *)ASN1_item_new(&ASN1_BIT_STRING_it); +} + +void +ASN1_BIT_STRING_free(ASN1_BIT_STRING *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &ASN1_BIT_STRING_it); +} int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len) @@ -68,6 +89,127 @@ ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len) return ASN1_STRING_set(x, d, len); } +int +ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value) +{ + int w, v, iv; + unsigned char *c; + + w = n/8; + v = 1 << (7 - (n & 0x07)); + iv = ~v; + if (!value) + v = 0; + + if (a == NULL) + return 0; + + a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear, set on write */ + + if ((a->length < (w + 1)) || (a->data == NULL)) { + if (!value) + return(1); /* Don't need to set */ + if ((c = recallocarray(a->data, a->length, w + 1, 1)) == NULL) { + ASN1error(ERR_R_MALLOC_FAILURE); + return 0; + } + a->data = c; + a->length = w + 1; + } + a->data[w] = ((a->data[w]) & iv) | v; + while ((a->length > 0) && (a->data[a->length - 1] == 0)) + a->length--; + + return (1); +} + +int +ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n) +{ + int w, v; + + w = n / 8; + v = 1 << (7 - (n & 0x07)); + if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL)) + return (0); + return ((a->data[w] & v) != 0); +} + +/* + * Checks if the given bit string contains only bits specified by + * the flags vector. Returns 0 if there is at least one bit set in 'a' + * which is not specified in 'flags', 1 otherwise. + * 'len' is the length of 'flags'. + */ +int +ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a, const unsigned char *flags, + int flags_len) +{ + int i, ok; + + /* Check if there is one bit set at all. */ + if (!a || !a->data) + return 1; + + /* Check each byte of the internal representation of the bit string. */ + ok = 1; + for (i = 0; i < a->length && ok; ++i) { + unsigned char mask = i < flags_len ? ~flags[i] : 0xff; + /* We are done if there is an unneeded bit set. */ + ok = (a->data[i] & mask) == 0; + } + return ok; +} + +int +ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs, + BIT_STRING_BITNAME *tbl, int indent) +{ + BIT_STRING_BITNAME *bnam; + char first = 1; + + BIO_printf(out, "%*s", indent, ""); + for (bnam = tbl; bnam->lname; bnam++) { + if (ASN1_BIT_STRING_get_bit(bs, bnam->bitnum)) { + if (!first) + BIO_puts(out, ", "); + BIO_puts(out, bnam->lname); + first = 0; + } + } + BIO_puts(out, "\n"); + return 1; +} + +int +ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, const char *name, int value, + BIT_STRING_BITNAME *tbl) +{ + int bitnum; + + bitnum = ASN1_BIT_STRING_num_asc(name, tbl); + if (bitnum < 0) + return 0; + if (bs) { + if (!ASN1_BIT_STRING_set_bit(bs, bitnum, value)) + return 0; + } + return 1; +} + +int +ASN1_BIT_STRING_num_asc(const char *name, BIT_STRING_BITNAME *tbl) +{ + BIT_STRING_BITNAME *bnam; + + for (bnam = tbl; bnam->lname; bnam++) { + if (!strcmp(bnam->sname, name) || + !strcmp(bnam->lname, name)) + return bnam->bitnum; + } + return -1; +} + int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp) { @@ -192,73 +334,14 @@ c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, const unsigned char **pp, long len) } int -ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value) +i2d_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **out) { - int w, v, iv; - unsigned char *c; - - w = n/8; - v = 1 << (7 - (n & 0x07)); - iv = ~v; - if (!value) - v = 0; - - if (a == NULL) - return 0; - - a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear, set on write */ - - if ((a->length < (w + 1)) || (a->data == NULL)) { - if (!value) - return(1); /* Don't need to set */ - if ((c = recallocarray(a->data, a->length, w + 1, 1)) == NULL) { - ASN1error(ERR_R_MALLOC_FAILURE); - return 0; - } - a->data = c; - a->length = w + 1; - } - a->data[w] = ((a->data[w]) & iv) | v; - while ((a->length > 0) && (a->data[a->length - 1] == 0)) - a->length--; - - return (1); + return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_BIT_STRING_it); } -int -ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n) +ASN1_BIT_STRING * +d2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, const unsigned char **in, long len) { - int w, v; - - w = n / 8; - v = 1 << (7 - (n & 0x07)); - if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL)) - return (0); - return ((a->data[w] & v) != 0); -} - -/* - * Checks if the given bit string contains only bits specified by - * the flags vector. Returns 0 if there is at least one bit set in 'a' - * which is not specified in 'flags', 1 otherwise. - * 'len' is the length of 'flags'. - */ -int -ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a, const unsigned char *flags, - int flags_len) -{ - int i, ok; - - /* Check if there is one bit set at all. */ - if (!a || !a->data) - return 1; - - /* Check each byte of the internal representation of the bit string. */ - ok = 1; - for (i = 0; i < a->length && ok; ++i) { - unsigned char mask = i < flags_len ? ~flags[i] : 0xff; - /* We are done if there is an unneeded bit set. */ - ok = (a->data[i] & mask) == 0; - } - return ok; + return (ASN1_BIT_STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &ASN1_BIT_STRING_it); } diff --git a/crypto/asn1/a_d2i_fp.c b/crypto/asn1/a_d2i_fp.c deleted file mode 100644 index 390a107..0000000 --- a/crypto/asn1/a_d2i_fp.c +++ /dev/null @@ -1,289 +0,0 @@ -/* $OpenBSD: a_d2i_fp.c,v 1.16 2017/01/29 17:49:22 beck Exp $ */ -/* 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.] - */ - -#include -#include - -#include -#include -#include - -static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb); - -#ifndef NO_OLD_ASN1 - -void * -ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x) -{ - BIO *b; - void *ret; - - if ((b = BIO_new(BIO_s_file())) == NULL) { - ASN1error(ERR_R_BUF_LIB); - return (NULL); - } - BIO_set_fp(b, in, BIO_NOCLOSE); - ret = ASN1_d2i_bio(xnew, d2i, b, x); - BIO_free(b); - return (ret); -} - -void * -ASN1_d2i_bio(void *(*xnew)(void), d2i_of_void *d2i, BIO *in, void **x) -{ - 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(x, &p, len); - -err: - if (b != NULL) - BUF_MEM_free(b); - return (ret); -} - -#endif - -void * -ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x) -{ - 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 = (const unsigned char *)b->data; - ret = ASN1_item_d2i(x, &p, len, it); - -err: - if (b != NULL) - BUF_MEM_free(b); - return (ret); -} - -void * -ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x) -{ - BIO *b; - char *ret; - - if ((b = BIO_new(BIO_s_file())) == NULL) { - ASN1error(ERR_R_BUF_LIB); - return (NULL); - } - BIO_set_fp(b, in, BIO_NOCLOSE); - ret = ASN1_item_d2i_bio(it, b, x); - BIO_free(b); - return (ret); -} - -#define HEADER_SIZE 8 -#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024) -static int -asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) -{ - BUF_MEM *b; - unsigned char *p; - int i; - ASN1_const_CTX c; - size_t want = HEADER_SIZE; - int eos = 0; - size_t off = 0; - size_t len = 0; - - b = BUF_MEM_new(); - if (b == NULL) { - ASN1error(ERR_R_MALLOC_FAILURE); - return -1; - } - - ERR_clear_error(); - for (;;) { - if (want >= (len - off)) { - want -= (len - off); - - if (len + want < len || - !BUF_MEM_grow_clean(b, len + want)) { - ASN1error(ERR_R_MALLOC_FAILURE); - goto err; - } - i = BIO_read(in, &(b->data[len]), want); - if ((i < 0) && ((len - off) == 0)) { - ASN1error(ASN1_R_NOT_ENOUGH_DATA); - goto err; - } - if (i > 0) { - if (len + i < len) { - ASN1error(ASN1_R_TOO_LONG); - goto err; - } - len += i; - } - } - /* else data already loaded */ - - p = (unsigned char *) & (b->data[off]); - c.p = p; - c.inf = ASN1_get_object(&(c.p), &(c.slen), &(c.tag), - &(c.xclass), len - off); - if (c.inf & 0x80) { - unsigned long e; - - e = ERR_GET_REASON(ERR_peek_error()); - if (e != ASN1_R_TOO_LONG) - goto err; - else - ERR_clear_error(); /* clear error */ - } - i = c.p - p; /* header length */ - off += i; /* end of data */ - - if (c.inf & 1) { - /* no data body so go round again */ - eos++; - if (eos < 0) { - ASN1error(ASN1_R_HEADER_TOO_LONG); - goto err; - } - want = HEADER_SIZE; - } else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC)) { - /* eos value, so go back and read another header */ - eos--; - if (eos <= 0) - break; - else - want = HEADER_SIZE; - } else { - /* suck in c.slen bytes of data */ - want = c.slen; - if (want > (len - off)) { - size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE; - - want -= (len - off); - if (want > INT_MAX /* BIO_read takes an int length */ || - len+want < len) { - ASN1error(ASN1_R_TOO_LONG); - goto err; - } - while (want > 0) { - /* - * Read content in chunks of increasing size - * so we can return an error for EOF without - * having to allocate the entire content length - * in one go. - */ - size_t chunk = want > chunk_max ? chunk_max : want; - - if (!BUF_MEM_grow_clean(b, len + chunk)) { - ASN1error(ERR_R_MALLOC_FAILURE); - goto err; - } - want -= chunk; - while (chunk > 0) { - i = BIO_read(in, &(b->data[len]), chunk); - if (i <= 0) { - ASN1error(ASN1_R_NOT_ENOUGH_DATA); - goto err; - } - /* - * This can't overflow because |len+want| - * didn't overflow. - */ - len += i; - chunk -= i; - } - if (chunk_max < INT_MAX/2) - chunk_max *= 2; - } - } - if (off + c.slen < off) { - ASN1error(ASN1_R_TOO_LONG); - goto err; - } - off += c.slen; - if (eos <= 0) { - break; - } else - want = HEADER_SIZE; - } - } - - if (off > INT_MAX) { - ASN1error(ASN1_R_TOO_LONG); - goto err; - } - - *pb = b; - return off; - -err: - if (b != NULL) - BUF_MEM_free(b); - return -1; -} diff --git a/crypto/asn1/a_enum.c b/crypto/asn1/a_enum.c index 0952e04..007a421 100644 --- a/crypto/asn1/a_enum.c +++ b/crypto/asn1/a_enum.c @@ -1,4 +1,4 @@ -/* $OpenBSD: a_enum.c,v 1.20 2019/04/28 05:05:56 tb Exp $ */ +/* $OpenBSD: a_enum.c,v 1.23 2021/12/25 13:17:48 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -60,7 +60,9 @@ #include #include +#include #include +#include #include /* @@ -68,6 +70,24 @@ * for comments on encoding see a_int.c */ +const ASN1_ITEM ASN1_ENUMERATED_it = { + .itype = ASN1_ITYPE_PRIMITIVE, + .utype = V_ASN1_ENUMERATED, + .sname = "ASN1_ENUMERATED", +}; + +ASN1_ENUMERATED * +ASN1_ENUMERATED_new(void) +{ + return (ASN1_ENUMERATED *)ASN1_item_new(&ASN1_ENUMERATED_it); +} + +void +ASN1_ENUMERATED_free(ASN1_ENUMERATED *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &ASN1_ENUMERATED_it); +} + int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v) { @@ -175,7 +195,7 @@ BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai) } return (ret); -err: + err: if (ret != ai) ASN1_ENUMERATED_free(ret); return (NULL); @@ -192,3 +212,143 @@ ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn) BN_set_negative(ret, 1); return (ret); } + +/* Based on a_int.c: equivalent ENUMERATED functions */ + +int +i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a) +{ + int i, n = 0; + static const char h[] = "0123456789ABCDEF"; + char buf[2]; + + if (a == NULL) + return (0); + + if (a->length == 0) { + if (BIO_write(bp, "00", 2) != 2) + goto err; + n = 2; + } else { + for (i = 0; i < a->length; i++) { + if ((i != 0) && (i % 35 == 0)) { + if (BIO_write(bp, "\\\n", 2) != 2) + goto err; + n += 2; + } + buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f]; + buf[1] = h[((unsigned char)a->data[i]) & 0x0f]; + if (BIO_write(bp, buf, 2) != 2) + goto err; + n += 2; + } + } + return (n); + + err: + return (-1); +} + +int +a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size) +{ + int ret = 0; + int i, j,k, m,n, again, bufsize; + unsigned char *s = NULL, *sp; + unsigned char *bufp; + int first = 1; + size_t num = 0, slen = 0; + + bs->type = V_ASN1_ENUMERATED; + + bufsize = BIO_gets(bp, buf, size); + for (;;) { + if (bufsize < 1) + goto err_sl; + i = bufsize; + if (buf[i-1] == '\n') + buf[--i] = '\0'; + if (i == 0) + goto err_sl; + if (buf[i-1] == '\r') + buf[--i] = '\0'; + if (i == 0) + goto err_sl; + if (buf[i - 1] == '\\') { + i--; + again = 1; + } else + again = 0; + buf[i] = '\0'; + if (i < 2) + goto err_sl; + + bufp = (unsigned char *)buf; + if (first) { + first = 0; + if ((bufp[0] == '0') && (buf[1] == '0')) { + bufp += 2; + i -= 2; + } + } + k = 0; + if (i % 2 != 0) { + ASN1error(ASN1_R_ODD_NUMBER_OF_CHARS); + goto err; + } + i /= 2; + if (num + i > slen) { + sp = realloc(s, num + i); + if (sp == NULL) { + ASN1error(ERR_R_MALLOC_FAILURE); + goto err; + } + s = sp; + slen = num + i; + } + for (j = 0; j < i; j++, k += 2) { + for (n = 0; n < 2; n++) { + m = bufp[k + n]; + if ((m >= '0') && (m <= '9')) + m -= '0'; + else if ((m >= 'a') && (m <= 'f')) + m = m - 'a' + 10; + else if ((m >= 'A') && (m <= 'F')) + m = m - 'A' + 10; + else { + ASN1error(ASN1_R_NON_HEX_CHARACTERS); + goto err; + } + s[num + j] <<= 4; + s[num + j] |= m; + } + } + num += i; + if (again) + bufsize = BIO_gets(bp, buf, size); + else + break; + } + bs->length = num; + bs->data = s; + return (1); + + err_sl: + ASN1error(ASN1_R_SHORT_LINE); + err: + free(s); + return (ret); +} + +int +i2d_ASN1_ENUMERATED(ASN1_ENUMERATED *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_ENUMERATED_it); +} + +ASN1_ENUMERATED * +d2i_ASN1_ENUMERATED(ASN1_ENUMERATED **a, const unsigned char **in, long len) +{ + return (ASN1_ENUMERATED *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &ASN1_ENUMERATED_it); +} diff --git a/crypto/asn1/a_int.c b/crypto/asn1/a_int.c index d14bd79..c4b40ff 100644 --- a/crypto/asn1/a_int.c +++ b/crypto/asn1/a_int.c @@ -1,4 +1,4 @@ -/* $OpenBSD: a_int.c,v 1.34 2019/04/28 05:03:56 tb Exp $ */ +/* $OpenBSD: a_int.c,v 1.38 2021/12/25 13:17:48 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -61,9 +61,29 @@ #include #include +#include #include +#include #include +const ASN1_ITEM ASN1_INTEGER_it = { + .itype = ASN1_ITYPE_PRIMITIVE, + .utype = V_ASN1_INTEGER, + .sname = "ASN1_INTEGER", +}; + +ASN1_INTEGER * +ASN1_INTEGER_new(void) +{ + return (ASN1_INTEGER *)ASN1_item_new(&ASN1_INTEGER_it); +} + +void +ASN1_INTEGER_free(ASN1_INTEGER *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &ASN1_INTEGER_it); +} + static int ASN1_INTEGER_valid(const ASN1_INTEGER *a) { @@ -101,6 +121,276 @@ ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y) return ret; } +int +ASN1_INTEGER_set(ASN1_INTEGER *a, long v) +{ + int j, k; + unsigned int i; + unsigned char buf[sizeof(long) + 1]; + long d; + + a->type = V_ASN1_INTEGER; + /* XXX ssl/ssl_asn1.c:i2d_SSL_SESSION() depends upon this bound vae */ + if (a->length < (int)(sizeof(long) + 1)) { + free(a->data); + a->data = calloc(1, sizeof(long) + 1); + } + if (a->data == NULL) { + ASN1error(ERR_R_MALLOC_FAILURE); + return (0); + } + d = v; + if (d < 0) { + d = -d; + a->type = V_ASN1_NEG_INTEGER; + } + + for (i = 0; i < sizeof(long); i++) { + if (d == 0) + break; + buf[i] = (int)d & 0xff; + d >>= 8; + } + j = 0; + for (k = i - 1; k >= 0; k--) + a->data[j++] = buf[k]; + a->length = j; + return (1); +} + +/* + * XXX this particular API is a gibbering eidrich horror that makes it + * impossible to determine valid return cases from errors.. "a bit + * ugly" is preserved for posterity, unfortunately this is probably + * unfixable without changing public API + */ +long +ASN1_INTEGER_get(const ASN1_INTEGER *a) +{ + int neg = 0, i; + unsigned long r = 0; + + if (a == NULL) + return (0L); + i = a->type; + if (i == V_ASN1_NEG_INTEGER) + neg = 1; + else if (i != V_ASN1_INTEGER) + return -1; + + if (!ASN1_INTEGER_valid(a)) + return -1; /* XXX best effort */ + + if (a->length > (int)sizeof(long)) { + /* hmm... a bit ugly, return all ones */ + return -1; + } + if (a->data == NULL) + return 0; + + for (i = 0; i < a->length; i++) { + r <<= 8; + r |= (unsigned char)a->data[i]; + } + + if (r > LONG_MAX) + return -1; + + if (neg) + return -(long)r; + return (long)r; +} + +ASN1_INTEGER * +BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai) +{ + ASN1_INTEGER *ret; + int len, j; + + if (ai == NULL) + ret = ASN1_INTEGER_new(); + else + ret = ai; + if (ret == NULL) { + ASN1error(ERR_R_NESTED_ASN1_ERROR); + goto err; + } + + if (!ASN1_INTEGER_valid(ret)) + goto err; + + if (BN_is_negative(bn)) + ret->type = V_ASN1_NEG_INTEGER; + else + ret->type = V_ASN1_INTEGER; + j = BN_num_bits(bn); + len = ((j == 0) ? 0 : ((j / 8) + 1)); + if (ret->length < len + 4) { + unsigned char *new_data = realloc(ret->data, len + 4); + if (!new_data) { + ASN1error(ERR_R_MALLOC_FAILURE); + goto err; + } + ret->data = new_data; + } + ret->length = BN_bn2bin(bn, ret->data); + + /* Correct zero case */ + if (!ret->length) { + ret->data[0] = 0; + ret->length = 1; + } + return (ret); + + err: + if (ret != ai) + ASN1_INTEGER_free(ret); + return (NULL); +} + +BIGNUM * +ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn) +{ + BIGNUM *ret; + + if (!ASN1_INTEGER_valid(ai)) + return (NULL); + + if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL) + ASN1error(ASN1_R_BN_LIB); + else if (ai->type == V_ASN1_NEG_INTEGER) + BN_set_negative(ret, 1); + return (ret); +} + +int +i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a) +{ + int i, n = 0; + static const char h[] = "0123456789ABCDEF"; + char buf[2]; + + if (a == NULL) + return (0); + + if (a->type & V_ASN1_NEG) { + if (BIO_write(bp, "-", 1) != 1) + goto err; + n = 1; + } + + if (a->length == 0) { + if (BIO_write(bp, "00", 2) != 2) + goto err; + n += 2; + } else { + for (i = 0; i < a->length; i++) { + if ((i != 0) && (i % 35 == 0)) { + if (BIO_write(bp, "\\\n", 2) != 2) + goto err; + n += 2; + } + buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f]; + buf[1] = h[((unsigned char)a->data[i]) & 0x0f]; + if (BIO_write(bp, buf, 2) != 2) + goto err; + n += 2; + } + } + return (n); + + err: + return (-1); +} + +int +a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size) +{ + int ret = 0; + int i, j,k, m,n, again, bufsize; + unsigned char *s = NULL, *sp; + unsigned char *bufp; + int num = 0, slen = 0, first = 1; + + bs->type = V_ASN1_INTEGER; + + bufsize = BIO_gets(bp, buf, size); + for (;;) { + if (bufsize < 1) + goto err_sl; + i = bufsize; + if (buf[i - 1] == '\n') + buf[--i] = '\0'; + if (i == 0) + goto err_sl; + if (buf[i - 1] == '\r') + buf[--i] = '\0'; + if (i == 0) + goto err_sl; + if (buf[i - 1] == '\\') { + i--; + again = 1; + } else + again = 0; + buf[i] = '\0'; + if (i < 2) + goto err_sl; + + bufp = (unsigned char *)buf; + if (first) { + first = 0; + if ((bufp[0] == '0') && (buf[1] == '0')) { + bufp += 2; + i -= 2; + } + } + k = 0; + if (i % 2 != 0) { + ASN1error(ASN1_R_ODD_NUMBER_OF_CHARS); + goto err; + } + i /= 2; + if (num + i > slen) { + if ((sp = recallocarray(s, slen, num + i, 1)) == NULL) { + ASN1error(ERR_R_MALLOC_FAILURE); + goto err; + } + s = sp; + slen = num + i; + } + for (j = 0; j < i; j++, k += 2) { + for (n = 0; n < 2; n++) { + m = bufp[k + n]; + if ((m >= '0') && (m <= '9')) + m -= '0'; + else if ((m >= 'a') && (m <= 'f')) + m = m - 'a' + 10; + else if ((m >= 'A') && (m <= 'F')) + m = m - 'A' + 10; + else { + ASN1error(ASN1_R_NON_HEX_CHARACTERS); + goto err; + } + s[num + j] <<= 4; + s[num + j] |= m; + } + } + num += i; + if (again) + bufsize = BIO_gets(bp, buf, size); + else + break; + } + bs->length = num; + bs->data = s; + return (1); + + err_sl: + ASN1error(ASN1_R_SHORT_LINE); + err: + free(s); + return (ret); +} /* * This converts an ASN1 INTEGER into its content encoding. @@ -289,13 +579,25 @@ c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp, long len) *pp = pend; return (ret); -err: + err: ASN1error(i); if (a == NULL || *a != ret) ASN1_INTEGER_free(ret); return (NULL); } +int +i2d_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_INTEGER_it); +} + +ASN1_INTEGER * +d2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **in, long len) +{ + return (ASN1_INTEGER *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &ASN1_INTEGER_it); +} /* This is a version of d2i_ASN1_INTEGER that ignores the sign bit of * ASN1 integers: some broken software can encode a positive INTEGER @@ -364,151 +666,9 @@ d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, long length) *pp = p; return (ret); -err: + err: ASN1error(i); if (a == NULL || *a != ret) ASN1_INTEGER_free(ret); return (NULL); } - -int -ASN1_INTEGER_set(ASN1_INTEGER *a, long v) -{ - int j, k; - unsigned int i; - unsigned char buf[sizeof(long) + 1]; - long d; - - a->type = V_ASN1_INTEGER; - /* XXX ssl/ssl_asn1.c:i2d_SSL_SESSION() depends upon this bound vae */ - if (a->length < (int)(sizeof(long) + 1)) { - free(a->data); - a->data = calloc(1, sizeof(long) + 1); - } - if (a->data == NULL) { - ASN1error(ERR_R_MALLOC_FAILURE); - return (0); - } - d = v; - if (d < 0) { - d = -d; - a->type = V_ASN1_NEG_INTEGER; - } - - for (i = 0; i < sizeof(long); i++) { - if (d == 0) - break; - buf[i] = (int)d & 0xff; - d >>= 8; - } - j = 0; - for (k = i - 1; k >= 0; k--) - a->data[j++] = buf[k]; - a->length = j; - return (1); -} - -/* - * XXX this particular API is a gibbering eidrich horror that makes it - * impossible to determine valid return cases from errors.. "a bit - * ugly" is preserved for posterity, unfortunately this is probably - * unfixable without changing public API - */ -long -ASN1_INTEGER_get(const ASN1_INTEGER *a) -{ - int neg = 0, i; - unsigned long r = 0; - - if (a == NULL) - return (0L); - i = a->type; - if (i == V_ASN1_NEG_INTEGER) - neg = 1; - else if (i != V_ASN1_INTEGER) - return -1; - - if (!ASN1_INTEGER_valid(a)) - return -1; /* XXX best effort */ - - if (a->length > (int)sizeof(long)) { - /* hmm... a bit ugly, return all ones */ - return -1; - } - if (a->data == NULL) - return 0; - - for (i = 0; i < a->length; i++) { - r <<= 8; - r |= (unsigned char)a->data[i]; - } - - if (r > LONG_MAX) - return -1; - - if (neg) - return -(long)r; - return (long)r; -} - -ASN1_INTEGER * -BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai) -{ - ASN1_INTEGER *ret; - int len, j; - - if (ai == NULL) - ret = ASN1_INTEGER_new(); - else - ret = ai; - if (ret == NULL) { - ASN1error(ERR_R_NESTED_ASN1_ERROR); - goto err; - } - - if (!ASN1_INTEGER_valid(ret)) - goto err; - - if (BN_is_negative(bn)) - ret->type = V_ASN1_NEG_INTEGER; - else - ret->type = V_ASN1_INTEGER; - j = BN_num_bits(bn); - len = ((j == 0) ? 0 : ((j / 8) + 1)); - if (ret->length < len + 4) { - unsigned char *new_data = realloc(ret->data, len + 4); - if (!new_data) { - ASN1error(ERR_R_MALLOC_FAILURE); - goto err; - } - ret->data = new_data; - } - ret->length = BN_bn2bin(bn, ret->data); - - /* Correct zero case */ - if (!ret->length) { - ret->data[0] = 0; - ret->length = 1; - } - return (ret); - -err: - if (ret != ai) - ASN1_INTEGER_free(ret); - return (NULL); -} - -BIGNUM * -ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn) -{ - BIGNUM *ret; - - if (!ASN1_INTEGER_valid(ai)) - return (NULL); - - if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL) - ASN1error(ASN1_R_BN_LIB); - else if (ai->type == V_ASN1_NEG_INTEGER) - BN_set_negative(ret, 1); - return (ret); -} diff --git a/crypto/asn1/a_mbstr.c b/crypto/asn1/a_mbstr.c index b7cfba3..8cff3ae 100644 --- a/crypto/asn1/a_mbstr.c +++ b/crypto/asn1/a_mbstr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: a_mbstr.c,v 1.23 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: a_mbstr.c,v 1.24 2021/12/25 13:17:48 jsing Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -248,7 +248,7 @@ ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, traverse_string(in, len, inform, cpyfunc, &p); return str_type; -err: + err: if (free_out) { ASN1_STRING_free(dest); *out = NULL; diff --git a/crypto/asn1/a_object.c b/crypto/asn1/a_object.c index 8600f80..c6e4c77 100644 --- a/crypto/asn1/a_object.c +++ b/crypto/asn1/a_object.c @@ -1,4 +1,4 @@ -/* $OpenBSD: a_object.c,v 1.32 2021/05/01 13:16:30 tb Exp $ */ +/* $OpenBSD: a_object.c,v 1.46 2022/04/10 12:42:33 inoguchi Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -61,313 +61,31 @@ #include #include -#include +#include #include #include #include -int -i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp) -{ - unsigned char *p; - int objsize; +#include "asn1_locl.h" - if ((a == NULL) || (a->data == NULL)) - return (0); - - objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT); - if (pp == NULL) - return objsize; - - p = *pp; - ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL); - memcpy(p, a->data, a->length); - p += a->length; - - *pp = p; - return (objsize); -} - -int -a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num) -{ - int i, first, len = 0, c, use_bn; - char ftmp[24], *tmp = ftmp; - int tmpsize = sizeof ftmp; - const char *p; - unsigned long l; - BIGNUM *bl = NULL; - - if (num == 0) - return (0); - else if (num == -1) - num = strlen(buf); - - p = buf; - c = *(p++); - num--; - if ((c >= '0') && (c <= '2')) { - first= c-'0'; - } else { - ASN1error(ASN1_R_FIRST_NUM_TOO_LARGE); - goto err; - } - - if (num <= 0) { - ASN1error(ASN1_R_MISSING_SECOND_NUMBER); - goto err; - } - c = *(p++); - num--; - for (;;) { - if (num <= 0) - break; - if ((c != '.') && (c != ' ')) { - ASN1error(ASN1_R_INVALID_SEPARATOR); - goto err; - } - l = 0; - use_bn = 0; - for (;;) { - if (num <= 0) - break; - num--; - c = *(p++); - if ((c == ' ') || (c == '.')) - break; - if ((c < '0') || (c > '9')) { - ASN1error(ASN1_R_INVALID_DIGIT); - goto err; - } - if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) { - use_bn = 1; - if (!bl) - bl = BN_new(); - if (!bl || !BN_set_word(bl, l)) - goto err; - } - if (use_bn) { - if (!BN_mul_word(bl, 10L) || - !BN_add_word(bl, c-'0')) - goto err; - } else - l = l * 10L + (long)(c - '0'); - } - if (len == 0) { - if ((first < 2) && (l >= 40)) { - ASN1error(ASN1_R_SECOND_NUMBER_TOO_LARGE); - goto err; - } - if (use_bn) { - if (!BN_add_word(bl, first * 40)) - goto err; - } else - l += (long)first * 40; - } - i = 0; - if (use_bn) { - int blsize; - blsize = BN_num_bits(bl); - blsize = (blsize + 6) / 7; - if (blsize > tmpsize) { - if (tmp != ftmp) - free(tmp); - tmpsize = blsize + 32; - tmp = malloc(tmpsize); - if (!tmp) - goto err; - } - while (blsize--) - tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L); - } else { - - for (;;) { - tmp[i++] = (unsigned char)l & 0x7f; - l >>= 7L; - if (l == 0L) - break; - } - - } - if (out != NULL) { - if (len + i > olen) { - ASN1error(ASN1_R_BUFFER_TOO_SMALL); - goto err; - } - while (--i > 0) - out[len++] = tmp[i]|0x80; - out[len++] = tmp[0]; - } else - len += i; - } - if (tmp != ftmp) - free(tmp); - BN_free(bl); - return (len); - -err: - if (tmp != ftmp) - free(tmp); - BN_free(bl); - return (0); -} - -int -i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a) -{ - return OBJ_obj2txt(buf, buf_len, a, 0); -} - -int -i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a) -{ - char *tmp = NULL; - size_t tlen = 256; - int i = -1; - - if ((a == NULL) || (a->data == NULL)) - return(BIO_write(bp, "NULL", 4)); - if ((tmp = malloc(tlen)) == NULL) - return -1; - i = i2t_ASN1_OBJECT(tmp, tlen, a); - if (i > (int)(tlen - 1)) { - freezero(tmp, tlen); - if ((tmp = malloc(i + 1)) == NULL) - return -1; - tlen = i + 1; - i = i2t_ASN1_OBJECT(tmp, tlen, a); - } - if (i <= 0) - i = BIO_write(bp, "", 9); - else - i = BIO_write(bp, tmp, i); - freezero(tmp, tlen); - return (i); -} - -ASN1_OBJECT * -d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long length) -{ - const unsigned char *p; - long len; - int tag, xclass; - int inf, i; - ASN1_OBJECT *ret = NULL; - - p = *pp; - inf = ASN1_get_object(&p, &len, &tag, &xclass, length); - if (inf & 0x80) { - i = ASN1_R_BAD_OBJECT_HEADER; - goto err; - } - - if (tag != V_ASN1_OBJECT) { - i = ASN1_R_EXPECTING_AN_OBJECT; - goto err; - } - ret = c2i_ASN1_OBJECT(a, &p, len); - if (ret) - *pp = p; - return ret; - -err: - ASN1error(i); - return (NULL); -} - -ASN1_OBJECT * -c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long len) -{ - ASN1_OBJECT *ret; - const unsigned char *p; - unsigned char *data; - int i, length; - - /* - * Sanity check OID encoding: - * - need at least one content octet - * - MSB must be clear in the last octet - * - can't have leading 0x80 in subidentifiers, see: X.690 8.19.2 - */ - if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL || - p[len - 1] & 0x80) { - ASN1error(ASN1_R_INVALID_OBJECT_ENCODING); - return (NULL); - } - - /* Now 0 < len <= INT_MAX, so the cast is safe. */ - length = (int)len; - for (i = 0; i < length; i++, p++) { - if (*p == 0x80 && (!i || !(p[-1] & 0x80))) { - ASN1error(ASN1_R_INVALID_OBJECT_ENCODING); - return (NULL); - } - } - - if ((a == NULL) || ((*a) == NULL) || - !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) { - if ((ret = ASN1_OBJECT_new()) == NULL) - return (NULL); - } else - ret = *a; - - p = *pp; - - /* detach data from object */ - data = (unsigned char *)ret->data; - freezero(data, ret->length); - - data = malloc(length); - if (data == NULL) { - ASN1error(ERR_R_MALLOC_FAILURE); - goto err; - } - - memcpy(data, p, length); - - /* If there are dynamic strings, free them here, and clear the flag. */ - if ((ret->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) != 0) { - free((void *)ret->sn); - free((void *)ret->ln); - ret->flags &= ~ASN1_OBJECT_FLAG_DYNAMIC_STRINGS; - } - - /* reattach data to object, after which it remains const */ - ret->data = data; - ret->length = length; - ret->sn = NULL; - ret->ln = NULL; - ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; - p += length; - - if (a != NULL) - *a = ret; - *pp = p; - return (ret); - -err: - if (a == NULL || ret != *a) - ASN1_OBJECT_free(ret); - return (NULL); -} +const ASN1_ITEM ASN1_OBJECT_it = { + .itype = ASN1_ITYPE_PRIMITIVE, + .utype = V_ASN1_OBJECT, + .sname = "ASN1_OBJECT", +}; ASN1_OBJECT * ASN1_OBJECT_new(void) { - ASN1_OBJECT *ret; + ASN1_OBJECT *a; - ret = malloc(sizeof(ASN1_OBJECT)); - if (ret == NULL) { + if ((a = calloc(1, sizeof(ASN1_OBJECT))) == NULL) { ASN1error(ERR_R_MALLOC_FAILURE); return (NULL); } - ret->length = 0; - ret->data = NULL; - ret->nid = 0; - ret->sn = NULL; - ret->ln = NULL; - ret->flags = ASN1_OBJECT_FLAG_DYNAMIC; - return (ret); + a->flags = ASN1_OBJECT_FLAG_DYNAMIC; + + return a; } void @@ -404,3 +122,539 @@ ASN1_OBJECT_create(int nid, unsigned char *data, int len, ASN1_OBJECT_FLAG_DYNAMIC_DATA; return (OBJ_dup(&o)); } + +static int +oid_add_arc(CBB *cbb, uint64_t arc) +{ + int started = 0; + uint8_t val; + int i; + + for (i = (sizeof(arc) * 8) / 7; i >= 0; i--) { + val = (arc >> (i * 7)) & 0x7f; + if (!started && i != 0 && val == 0) + continue; + if (i > 0) + val |= 0x80; + if (!CBB_add_u8(cbb, val)) + return 0; + started = 1; + } + + return 1; +} + +static int +oid_parse_arc(CBS *cbs, uint64_t *out_arc) +{ + uint64_t arc = 0; + uint8_t val; + + do { + if (!CBS_get_u8(cbs, &val)) + return 0; + if (arc == 0 && val == 0x80) + return 0; + if (out_arc != NULL && arc > (UINT64_MAX >> 7)) + return 0; + arc = (arc << 7) | (val & 0x7f); + } while (val & 0x80); + + if (out_arc != NULL) + *out_arc = arc; + + return 1; +} + +static int +oid_add_arc_txt(CBB *cbb, uint64_t arc, int first) +{ + const char *fmt = ".%llu"; + char s[22]; /* Digits in decimal representation of 2^64-1, plus '.' and NUL. */ + int n; + + if (first) + fmt = "%llu"; + n = snprintf(s, sizeof(s), fmt, (unsigned long long)arc); + if (n < 0 || (size_t)n >= sizeof(s)) + return 0; + if (!CBB_add_bytes(cbb, s, n)) + return 0; + + return 1; +} + +static int +oid_parse_arc_txt(CBS *cbs, uint64_t *out_arc, char *separator, int first) +{ + uint64_t arc = 0; + int digits = 0; + uint8_t val; + + if (!first) { + if (!CBS_get_u8(cbs, &val)) + return 0; + if ((*separator == 0 && val != '.' && val != ' ') || + (*separator != 0 && val != *separator)) { + ASN1error(ASN1_R_INVALID_SEPARATOR); + return 0; + } + *separator = val; + } + + while (CBS_len(cbs) > 0) { + if (!CBS_peek_u8(cbs, &val)) + return 0; + if (val == '.' || val == ' ') + break; + + if (!CBS_get_u8(cbs, &val)) + return 0; + if (val < '0' || val > '9') { + /* For the first arc we treat this as the separator. */ + if (first) { + ASN1error(ASN1_R_INVALID_SEPARATOR); + return 0; + } + ASN1error(ASN1_R_INVALID_DIGIT); + return 0; + } + val -= '0'; + + if (digits > 0 && arc == 0 && val == 0) { + ASN1error(ASN1_R_INVALID_NUMBER); + return 0; + } + digits++; + + if (arc > UINT64_MAX / 10) { + ASN1error(ASN1_R_TOO_LONG); + return 0; + } + arc = arc * 10 + val; + } + + if (digits < 1) { + ASN1error(ASN1_R_INVALID_NUMBER); + return 0; + } + + *out_arc = arc; + + return 1; +} + +static int +a2c_ASN1_OBJECT_internal(CBB *cbb, CBS *cbs) +{ + uint64_t arc, si1, si2; + char separator = 0; + + if (!oid_parse_arc_txt(cbs, &si1, &separator, 1)) + return 0; + + if (CBS_len(cbs) == 0) { + ASN1error(ASN1_R_MISSING_SECOND_NUMBER); + return 0; + } + + if (!oid_parse_arc_txt(cbs, &si2, &separator, 0)) + return 0; + + /* + * X.690 section 8.19 - the first two subidentifiers are encoded as + * (x * 40) + y, with x being limited to [0,1,2]. The second + * subidentifier cannot exceed 39 for x < 2. + */ + if (si1 > 2) { + ASN1error(ASN1_R_FIRST_NUM_TOO_LARGE); + return 0; + } + if ((si1 < 2 && si2 >= 40) || si2 > UINT64_MAX - si1 * 40) { + ASN1error(ASN1_R_SECOND_NUMBER_TOO_LARGE); + return 0; + } + arc = si1 * 40 + si2; + + if (!oid_add_arc(cbb, arc)) + return 0; + + while (CBS_len(cbs) > 0) { + if (!oid_parse_arc_txt(cbs, &arc, &separator, 0)) + return 0; + if (!oid_add_arc(cbb, arc)) + return 0; + } + + return 1; +} + +static int +c2a_ASN1_OBJECT(CBS *cbs, CBB *cbb) +{ + uint64_t arc, si1, si2; + + /* + * X.690 section 8.19 - the first two subidentifiers are encoded as + * (x * 40) + y, with x being limited to [0,1,2]. + */ + if (!oid_parse_arc(cbs, &arc)) + return 0; + if ((si1 = arc / 40) > 2) + si1 = 2; + si2 = arc - si1 * 40; + + if (!oid_add_arc_txt(cbb, si1, 1)) + return 0; + if (!oid_add_arc_txt(cbb, si2, 0)) + return 0; + + while (CBS_len(cbs) > 0) { + if (!oid_parse_arc(cbs, &arc)) + return 0; + if (!oid_add_arc_txt(cbb, arc, 0)) + return 0; + } + + /* NUL terminate. */ + if (!CBB_add_u8(cbb, 0)) + return 0; + + return 1; +} + +int +a2d_ASN1_OBJECT(unsigned char *out, int out_len, const char *in, int in_len) +{ + uint8_t *data = NULL; + size_t data_len; + CBS cbs; + CBB cbb; + int ret = 0; + + memset(&cbb, 0, sizeof(cbb)); + + if (in_len == -1) + in_len = strlen(in); + if (in_len <= 0) + goto err; + + CBS_init(&cbs, in, in_len); + + if (!CBB_init(&cbb, 0)) + goto err; + if (!a2c_ASN1_OBJECT_internal(&cbb, &cbs)) + goto err; + if (!CBB_finish(&cbb, &data, &data_len)) + goto err; + + if (data_len > INT_MAX) + goto err; + + if (out != NULL) { + if (out_len <= 0 || (size_t)out_len < data_len) { + ASN1error(ASN1_R_BUFFER_TOO_SMALL); + goto err; + } + memcpy(out, data, data_len); + } + + ret = (int)data_len; + + err: + CBB_cleanup(&cbb); + free(data); + + return ret; +} + +static int +i2t_ASN1_OBJECT_oid(const ASN1_OBJECT *aobj, CBB *cbb) +{ + CBS cbs; + + CBS_init(&cbs, aobj->data, aobj->length); + + return c2a_ASN1_OBJECT(&cbs, cbb); +} + +static int +i2t_ASN1_OBJECT_name(const ASN1_OBJECT *aobj, CBB *cbb, const char **out_name) +{ + const char *name; + int nid; + + *out_name = NULL; + + if ((nid = OBJ_obj2nid(aobj)) == NID_undef) + return 0; + + if ((name = OBJ_nid2ln(nid)) == NULL) + name = OBJ_nid2sn(nid); + if (name == NULL) + return 0; + + *out_name = name; + + if (!CBB_add_bytes(cbb, name, strlen(name))) + return 0; + + /* NUL terminate. */ + if (!CBB_add_u8(cbb, 0)) + return 0; + + return 1; +} + +static int +i2t_ASN1_OBJECT_cbb(const ASN1_OBJECT *aobj, CBB *cbb, int no_name) +{ + const char *name; + + if (!no_name) { + if (i2t_ASN1_OBJECT_name(aobj, cbb, &name)) + return 1; + if (name != NULL) + return 0; + } + return i2t_ASN1_OBJECT_oid(aobj, cbb); +} + +int +i2t_ASN1_OBJECT_internal(const ASN1_OBJECT *aobj, char *buf, int buf_len, int no_name) +{ + uint8_t *data = NULL; + size_t data_len; + CBB cbb; + int ret = 0; + + if (buf_len < 0) + return 0; + if (buf_len > 0) + buf[0] = '\0'; + + if (!CBB_init(&cbb, 0)) + goto err; + if (!i2t_ASN1_OBJECT_cbb(aobj, &cbb, no_name)) + goto err; + if (!CBB_finish(&cbb, &data, &data_len)) + goto err; + + ret = strlcpy(buf, data, buf_len); + err: + CBB_cleanup(&cbb); + free(data); + + return ret; +} + +int +i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *aobj) +{ + return i2t_ASN1_OBJECT_internal(aobj, buf, buf_len, 0); +} + +ASN1_OBJECT * +t2i_ASN1_OBJECT_internal(const char *oid) +{ + ASN1_OBJECT *aobj = NULL; + uint8_t *data = NULL; + size_t data_len; + CBB cbb; + CBS cbs; + + memset(&cbb, 0, sizeof(cbb)); + + CBS_init(&cbs, oid, strlen(oid)); + + if (!CBB_init(&cbb, 0)) + goto err; + if (!a2c_ASN1_OBJECT_internal(&cbb, &cbs)) + goto err; + if (!CBB_finish(&cbb, &data, &data_len)) + goto err; + + if (data_len > INT_MAX) + goto err; + + if ((aobj = ASN1_OBJECT_new()) == NULL) + goto err; + + aobj->data = data; + aobj->length = (int)data_len; + aobj->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; + data = NULL; + + err: + CBB_cleanup(&cbb); + free(data); + + return aobj; +} + +int +i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *aobj) +{ + uint8_t *data = NULL; + size_t data_len; + CBB cbb; + int ret = -1; + + if (aobj == NULL || aobj->data == NULL) + return BIO_write(bp, "NULL", 4); + + if (!CBB_init(&cbb, 0)) + goto err; + if (!i2t_ASN1_OBJECT_cbb(aobj, &cbb, 0)) { + ret = BIO_write(bp, "", 9); + goto err; + } + if (!CBB_finish(&cbb, &data, &data_len)) + goto err; + + ret = BIO_write(bp, data, strlen(data)); + + err: + CBB_cleanup(&cbb); + free(data); + + return ret; +} + +int +c2i_ASN1_OBJECT_cbs(ASN1_OBJECT **out_aobj, CBS *content) +{ + ASN1_OBJECT *aobj = NULL; + uint8_t *data = NULL; + size_t data_len; + CBS cbs; + + if (out_aobj == NULL || *out_aobj != NULL) + goto err; + + /* Parse and validate OID encoding per X.690 8.19.2. */ + CBS_dup(content, &cbs); + if (CBS_len(&cbs) == 0) { + ASN1error(ASN1_R_INVALID_OBJECT_ENCODING); + goto err; + } + while (CBS_len(&cbs) > 0) { + if (!oid_parse_arc(&cbs, NULL)) { + ASN1error(ASN1_R_INVALID_OBJECT_ENCODING); + goto err; + } + } + + if (!CBS_stow(content, &data, &data_len)) + goto err; + + if (data_len > INT_MAX) + goto err; + + if ((aobj = ASN1_OBJECT_new()) == NULL) + goto err; + + aobj->data = data; + aobj->length = (int)data_len; /* XXX - change length to size_t. */ + aobj->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; + + *out_aobj = aobj; + + return 1; + + err: + ASN1_OBJECT_free(aobj); + free(data); + + return 0; +} + +ASN1_OBJECT * +c2i_ASN1_OBJECT(ASN1_OBJECT **out_aobj, const unsigned char **pp, long len) +{ + ASN1_OBJECT *aobj = NULL; + CBS content; + + if (out_aobj != NULL) { + ASN1_OBJECT_free(*out_aobj); + *out_aobj = NULL; + } + + if (len < 0) { + ASN1error(ASN1_R_LENGTH_ERROR); + return NULL; + } + + CBS_init(&content, *pp, len); + + if (!c2i_ASN1_OBJECT_cbs(&aobj, &content)) + return NULL; + + *pp = CBS_data(&content); + + if (out_aobj != NULL) + *out_aobj = aobj; + + return aobj; +} + +int +i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp) +{ + unsigned char *p; + int objsize; + + if ((a == NULL) || (a->data == NULL)) + return (0); + + objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT); + if (pp == NULL) + return objsize; + + p = *pp; + ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL); + memcpy(p, a->data, a->length); + p += a->length; + + *pp = p; + return (objsize); +} + +ASN1_OBJECT * +d2i_ASN1_OBJECT(ASN1_OBJECT **out_aobj, const unsigned char **pp, long length) +{ + ASN1_OBJECT *aobj = NULL; + uint32_t tag_number; + CBS cbs, content; + + if (out_aobj != NULL) { + ASN1_OBJECT_free(*out_aobj); + *out_aobj = NULL; + } + + if (length < 0) { + ASN1error(ASN1_R_LENGTH_ERROR); + return NULL; + } + + CBS_init(&cbs, *pp, length); + + if (!asn1_get_primitive(&cbs, 0, &tag_number, &content)) { + ASN1error(ASN1_R_BAD_OBJECT_HEADER); + return NULL; + } + if (tag_number != V_ASN1_OBJECT) { + ASN1error(ASN1_R_EXPECTING_AN_OBJECT); + return NULL; + } + + if (!c2i_ASN1_OBJECT_cbs(&aobj, &content)) + return NULL; + + *pp = CBS_data(&content); + + if (out_aobj != NULL) + *out_aobj = aobj; + + return aobj; +} diff --git a/crypto/asn1/a_octet.c b/crypto/asn1/a_octet.c index d998675..c1a2520 100644 --- a/crypto/asn1/a_octet.c +++ b/crypto/asn1/a_octet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: a_octet.c,v 1.10 2015/07/29 14:58:34 jsing Exp $ */ +/* $OpenBSD: a_octet.c,v 1.11 2021/12/25 08:52:44 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -59,6 +59,26 @@ #include #include +#include + +const ASN1_ITEM ASN1_OCTET_STRING_it = { + .itype = ASN1_ITYPE_PRIMITIVE, + .utype = V_ASN1_OCTET_STRING, + .sname = "ASN1_OCTET_STRING", +}; + +ASN1_OCTET_STRING * +ASN1_OCTET_STRING_new(void) +{ + return (ASN1_OCTET_STRING *)ASN1_item_new(&ASN1_OCTET_STRING_it); +} + +void +ASN1_OCTET_STRING_free(ASN1_OCTET_STRING *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &ASN1_OCTET_STRING_it); +} + ASN1_OCTET_STRING * ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x) @@ -77,3 +97,16 @@ ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d, int len) { return ASN1_STRING_set(x, d, len); } + +int +i2d_ASN1_OCTET_STRING(ASN1_OCTET_STRING *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_OCTET_STRING_it); +} + +ASN1_OCTET_STRING * +d2i_ASN1_OCTET_STRING(ASN1_OCTET_STRING **a, const unsigned char **in, long len) +{ + return (ASN1_OCTET_STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &ASN1_OCTET_STRING_it); +} diff --git a/crypto/asn1/d2i_pr.c b/crypto/asn1/a_pkey.c similarity index 92% rename from crypto/asn1/d2i_pr.c rename to crypto/asn1/a_pkey.c index e450dee..3b8dea7 100644 --- a/crypto/asn1/d2i_pr.c +++ b/crypto/asn1/a_pkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: d2i_pr.c,v 1.17 2019/04/10 16:23:55 jsing Exp $ */ +/* $OpenBSD: a_pkey.c,v 1.3 2021/12/25 13:17:48 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -72,6 +72,7 @@ #endif #include "asn1_locl.h" +#include "evp_locl.h" EVP_PKEY * d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp, long length) @@ -117,12 +118,28 @@ d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp, long length) (*a) = ret; return (ret); -err: + err: if (a == NULL || *a != ret) EVP_PKEY_free(ret); return (NULL); } +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 = i2d_PKCS8_PRIV_KEY_INFO(p8, pp); + PKCS8_PRIV_KEY_INFO_free(p8); + return ret; + } + ASN1error(ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); + return (-1); +} + /* This works like d2i_PrivateKey() except it automatically works out the type */ EVP_PKEY * diff --git a/crypto/asn1/d2i_pu.c b/crypto/asn1/a_pubkey.c similarity index 89% rename from crypto/asn1/d2i_pu.c rename to crypto/asn1/a_pubkey.c index 3750265..f3bb5d8 100644 --- a/crypto/asn1/d2i_pu.c +++ b/crypto/asn1/a_pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: d2i_pu.c,v 1.14 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: a_pubkey.c,v 1.3 2021/12/25 13:17:48 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -76,6 +76,8 @@ #include #endif +#include "evp_locl.h" + EVP_PKEY * d2i_PublicKey(int type, EVP_PKEY **a, const unsigned char **pp, long length) { @@ -129,8 +131,30 @@ d2i_PublicKey(int type, EVP_PKEY **a, const unsigned char **pp, long length) (*a) = ret; return (ret); -err: + err: if (a == NULL || *a != ret) EVP_PKEY_free(ret); return (NULL); } + +int +i2d_PublicKey(EVP_PKEY *a, unsigned char **pp) +{ + switch (a->type) { +#ifndef OPENSSL_NO_RSA + case EVP_PKEY_RSA: + return (i2d_RSAPublicKey(a->pkey.rsa, pp)); +#endif +#ifndef OPENSSL_NO_DSA + case EVP_PKEY_DSA: + return (i2d_DSAPublicKey(a->pkey.dsa, pp)); +#endif +#ifndef OPENSSL_NO_EC + case EVP_PKEY_EC: + return (i2o_ECPublicKey(a->pkey.ec, pp)); +#endif + default: + ASN1error(ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); + return (-1); + } +} diff --git a/crypto/asn1/a_sign.c b/crypto/asn1/a_sign.c deleted file mode 100644 index df955be..0000000 --- a/crypto/asn1/a_sign.c +++ /dev/null @@ -1,233 +0,0 @@ -/* $OpenBSD: a_sign.c,v 1.23 2017/05/02 03:59:44 deraadt Exp $ */ -/* 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.] - */ -/* ==================================================================== - * Copyright (c) 1998-2003 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). - * - */ - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "asn1_locl.h" - -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) -{ - EVP_MD_CTX ctx; - EVP_MD_CTX_init(&ctx); - if (!EVP_DigestSignInit(&ctx, NULL, type, NULL, pkey)) { - EVP_MD_CTX_cleanup(&ctx); - return 0; - } - return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, &ctx); -} - - -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) -{ - const EVP_MD *type; - EVP_PKEY *pkey; - unsigned char *buf_in = NULL, *buf_out = NULL; - size_t inl = 0, outl = 0, outll = 0; - int signid, paramtype; - int rv; - - type = EVP_MD_CTX_md(ctx); - pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx); - - if (!type || !pkey) { - ASN1error(ASN1_R_CONTEXT_NOT_INITIALISED); - return 0; - } - - if (pkey->ameth->item_sign) { - rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2, - signature); - if (rv == 1) - outl = signature->length; - /* Return value meanings: - * <=0: error. - * 1: method does everything. - * 2: carry on as normal. - * 3: ASN1 method sets algorithm identifiers: just sign. - */ - if (rv <= 0) - ASN1error(ERR_R_EVP_LIB); - if (rv <= 1) - goto err; - } else - rv = 2; - - if (rv == 2) { - if (type->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) { - if (!pkey->ameth || - !OBJ_find_sigid_by_algs(&signid, - EVP_MD_nid(type), pkey->ameth->pkey_id)) { - ASN1error(ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); - return 0; - } - } else - signid = type->pkey_type; - - if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL) - paramtype = V_ASN1_NULL; - else - paramtype = V_ASN1_UNDEF; - - if (algor1) - X509_ALGOR_set0(algor1, - OBJ_nid2obj(signid), paramtype, NULL); - if (algor2) - X509_ALGOR_set0(algor2, - OBJ_nid2obj(signid), paramtype, NULL); - - } - - inl = ASN1_item_i2d(asn, &buf_in, it); - outll = outl = EVP_PKEY_size(pkey); - buf_out = malloc(outl); - if ((buf_in == NULL) || (buf_out == NULL)) { - outl = 0; - ASN1error(ERR_R_MALLOC_FAILURE); - goto err; - } - - if (!EVP_DigestSignUpdate(ctx, buf_in, inl) || - !EVP_DigestSignFinal(ctx, buf_out, &outl)) { - outl = 0; - ASN1error(ERR_R_EVP_LIB); - goto err; - } - free(signature->data); - signature->data = buf_out; - buf_out = NULL; - signature->length = outl; - /* In the interests of compatibility, I'll make sure that - * the bit string has a 'not-used bits' value of 0 - */ - signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); - signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; - -err: - EVP_MD_CTX_cleanup(ctx); - freezero((char *)buf_in, inl); - freezero((char *)buf_out, outll); - return (outl); -} diff --git a/crypto/asn1/a_strex.c b/crypto/asn1/a_strex.c index 4e3decc..848d1bf 100644 --- a/crypto/asn1/a_strex.c +++ b/crypto/asn1/a_strex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: a_strex.c,v 1.28 2018/05/19 10:46:28 tb Exp $ */ +/* $OpenBSD: a_strex.c,v 1.31 2021/12/25 12:11:57 jsing Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ @@ -322,22 +322,6 @@ do_dump(unsigned long lflags, char_io *io_ch, void *arg, const ASN1_STRING *str) return outlen + 1; } -/* Lookup table to convert tags to character widths, - * 0 = UTF8 encoded, -1 is used for non string types - * otherwise it is the number of bytes per character - */ - -static const signed char tag2nbyte[] = { - -1, -1, -1, -1, -1, /* 0-4 */ - -1, -1, -1, -1, -1, /* 5-9 */ - -1, -1, 0, -1, /* 10-13 */ - -1, -1, -1, -1, /* 15-17 */ - -1, 1, 1, /* 18-20 */ - -1, 1, 1, 1, /* 21-24 */ - -1, 1, -1, /* 25-27 */ - 4, -1, 2 /* 28-30 */ -}; - /* This is the main function, print out an * ASN1_STRING taking note of various escape * and display options. Returns number of @@ -371,19 +355,16 @@ do_print_ex(char_io *io_ch, void *arg, unsigned long lflags, /* Decide what to do with type, either dump content or display it */ - /* Dump everything */ - if (lflags & ASN1_STRFLGS_DUMP_ALL) + if (lflags & ASN1_STRFLGS_DUMP_ALL) { + /* Dump everything. */ type = -1; - /* Ignore the string type */ - else if (lflags & ASN1_STRFLGS_IGNORE_TYPE) + } else if (lflags & ASN1_STRFLGS_IGNORE_TYPE) { + /* Ignore the string type. */ type = 1; - else { - /* Else determine width based on type */ - if ((type > 0) && (type < 31)) - type = tag2nbyte[type]; - else - type = -1; - if ((type == -1) && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN)) + } else { + /* Else determine width based on type. */ + type = asn1_tag2charwidth(type); + if (type == -1 && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN)) type = 1; } @@ -513,7 +494,7 @@ do_name_ex(char_io *io_ch, void *arg, const X509_NAME *n, int indent, else ent = X509_NAME_get_entry(n, i); if (prev != -1) { - if (prev == ent->set) { + if (prev == X509_NAME_ENTRY_set(ent)) { if (!io_ch(arg, sep_mv, sep_mv_len)) return -1; outlen += sep_mv_len; @@ -526,7 +507,7 @@ do_name_ex(char_io *io_ch, void *arg, const X509_NAME *n, int indent, outlen += indent; } } - prev = ent->set; + prev = X509_NAME_ENTRY_set(ent); fn = X509_NAME_ENTRY_get_object(ent); val = X509_NAME_ENTRY_get_data(ent); fn_nid = OBJ_obj2nid(fn); @@ -618,32 +599,3 @@ ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, unsigned long flags) { return do_print_ex(send_fp_chars, fp, flags, str); } - -/* Utility function: convert any string type to UTF8, returns number of bytes - * in output string or a negative error code - */ - -int -ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in) -{ - ASN1_STRING stmp, *str = &stmp; - int mbflag, type, ret; - - if (!in) - return -1; - type = in->type; - if ((type < 0) || (type > 30)) - return -1; - mbflag = tag2nbyte[type]; - if (mbflag == -1) - return -1; - mbflag |= MBSTRING_FLAG; - stmp.data = NULL; - stmp.length = 0; - ret = ASN1_mbstring_copy(&str, in->data, in->length, mbflag, - B_ASN1_UTF8STRING); - if (ret < 0) - return ret; - *out = stmp.data; - return stmp.length; -} diff --git a/crypto/asn1/f_string.c b/crypto/asn1/a_string.c similarity index 52% rename from crypto/asn1/f_string.c rename to crypto/asn1/a_string.c index af17f43..90e363e 100644 --- a/crypto/asn1/f_string.c +++ b/crypto/asn1/a_string.c @@ -1,4 +1,4 @@ -/* $OpenBSD: f_string.c,v 1.18 2018/04/25 11:48:21 tb Exp $ */ +/* $OpenBSD: a_string.c,v 1.7 2022/03/17 17:17:58 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -56,48 +56,283 @@ * [including the GNU Public Licence.] */ -#include +#include +#include +#include #include -#include #include +#include "asn1_locl.h" + +ASN1_STRING * +ASN1_STRING_new(void) +{ + return ASN1_STRING_type_new(V_ASN1_OCTET_STRING); +} + +ASN1_STRING * +ASN1_STRING_type_new(int type) +{ + ASN1_STRING *astr; + + if ((astr = calloc(1, sizeof(ASN1_STRING))) == NULL) { + ASN1error(ERR_R_MALLOC_FAILURE); + return NULL; + } + astr->type = type; + + return astr; +} + +static void +ASN1_STRING_clear(ASN1_STRING *astr) +{ + if (!(astr->flags & ASN1_STRING_FLAG_NDEF)) + freezero(astr->data, astr->length); + + astr->flags &= ~ASN1_STRING_FLAG_NDEF; + astr->data = NULL; + astr->length = 0; +} + +void +ASN1_STRING_free(ASN1_STRING *astr) +{ + if (astr == NULL) + return; + + ASN1_STRING_clear(astr); + + free(astr); +} + int -i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type) +ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b) +{ + int cmp; + + if (a == NULL || b == NULL) + return -1; + if ((cmp = (a->length - b->length)) != 0) + return cmp; + if ((cmp = memcmp(a->data, b->data, a->length)) != 0) + return cmp; + + return (a->type - b->type); +} + +int +ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *src) +{ + if (src == NULL) + return 0; + + if (!ASN1_STRING_set(dst, src->data, src->length)) + return 0; + + dst->type = src->type; + dst->flags = src->flags & ~ASN1_STRING_FLAG_NDEF; + + return 1; +} + +ASN1_STRING * +ASN1_STRING_dup(const ASN1_STRING *src) +{ + ASN1_STRING *astr; + + if (src == NULL) + return NULL; + + if ((astr = ASN1_STRING_new()) == NULL) + return NULL; + if (!ASN1_STRING_copy(astr, src)) { + ASN1_STRING_free(astr); + return NULL; + } + return astr; +} + +int +ASN1_STRING_set(ASN1_STRING *astr, const void *_data, int len) +{ + const char *data = _data; + + if (len == -1) { + size_t slen; + + if (data == NULL) + return 0; + + if ((slen = strlen(data)) > INT_MAX) + return 0; + + len = (int)slen; + } + + ASN1_STRING_clear(astr); + + if (len < 0 || len >= INT_MAX) + return 0; + + if ((astr->data = calloc(1, len + 1)) == NULL) { + ASN1error(ERR_R_MALLOC_FAILURE); + return (0); + } + astr->length = len; + + if (data != NULL) { + memcpy(astr->data, data, len); + astr->data[len] = '\0'; + } + + return 1; +} + +void +ASN1_STRING_set0(ASN1_STRING *astr, void *data, int len) +{ + ASN1_STRING_clear(astr); + + astr->data = data; + astr->length = len; +} + +void +asn1_add_error(const unsigned char *address, int offset) +{ + ERR_asprintf_error_data("offset=%d", offset); +} + +int +ASN1_STRING_length(const ASN1_STRING *astr) +{ + return astr->length; +} + +void +ASN1_STRING_length_set(ASN1_STRING *astr, int len) +{ + /* This is dangerous and unfixable. */ + astr->length = len; +} + +int +ASN1_STRING_type(const ASN1_STRING *astr) +{ + return astr->type; +} + +unsigned char * +ASN1_STRING_data(ASN1_STRING *astr) +{ + return astr->data; +} + +const unsigned char * +ASN1_STRING_get0_data(const ASN1_STRING *astr) +{ + return astr->data; +} + +int +ASN1_STRING_print(BIO *bp, const ASN1_STRING *astr) +{ + int i, n; + char buf[80]; + const char *p; + + if (astr == NULL) + return 0; + + n = 0; + p = (const char *)astr->data; + for (i = 0; i < astr->length; i++) { + if ((p[i] > '~') || ((p[i] < ' ') && + (p[i] != '\n') && (p[i] != '\r'))) + buf[n] = '.'; + else + buf[n] = p[i]; + n++; + if (n >= 80) { + if (BIO_write(bp, buf, n) <= 0) + return 0; + n = 0; + } + } + if (n > 0) { + if (BIO_write(bp, buf, n) <= 0) + return 0; + } + + return 1; +} + +/* + * Utility function: convert any string type to UTF8, returns number of bytes + * in output string or a negative error code + */ +int +ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in) +{ + ASN1_STRING stmp, *str = &stmp; + int mbflag, ret; + + if (in == NULL) + return -1; + + if ((mbflag = asn1_tag2charwidth(in->type)) == -1) + return -1; + + mbflag |= MBSTRING_FLAG; + + stmp.data = NULL; + stmp.length = 0; + ret = ASN1_mbstring_copy(&str, in->data, in->length, mbflag, + B_ASN1_UTF8STRING); + if (ret < 0) + return ret; + *out = stmp.data; + return stmp.length; +} + +int +i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *astr, int type) { int i, n = 0; static const char h[] = "0123456789ABCDEF"; char buf[2]; - if (a == NULL) - return (0); + if (astr == NULL) + return 0; - if (a->length == 0) { + if (astr->length == 0) { if (BIO_write(bp, "0", 1) != 1) goto err; n = 1; } else { - for (i = 0; i < a->length; i++) { + for (i = 0; i < astr->length; i++) { if ((i != 0) && (i % 35 == 0)) { if (BIO_write(bp, "\\\n", 2) != 2) goto err; n += 2; } - buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f]; - buf[1] = h[((unsigned char)a->data[i]) & 0x0f]; + buf[0] = h[((unsigned char)astr->data[i] >> 4) & 0x0f]; + buf[1] = h[((unsigned char)astr->data[i]) & 0x0f]; if (BIO_write(bp, buf, 2) != 2) goto err; n += 2; } } - return (n); + return n; -err: - return (-1); + err: + return -1; } int -a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size) +a2i_ASN1_STRING(BIO *bp, ASN1_STRING *astr, char *buf, int size) { int ret = 0; int i, j, k, m, n, again, bufsize; @@ -125,26 +360,18 @@ a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size) buf[--i] = '\0'; if (i == 0) goto err_sl; - again = (buf[i - 1] == '\\'); - - for (j = i - 1; j > 0; j--) { - if (!(((buf[j] >= '0') && (buf[j] <= '9')) || - ((buf[j] >= 'a') && (buf[j] <= 'f')) || - ((buf[j] >= 'A') && (buf[j] <= 'F')))) { - i = j; - break; - } - } + if (buf[i - 1] == '\\') { + i--; + again = 1; + } else + again = 0; buf[i] = '\0'; - /* We have now cleared all the crap off the end of the - * line */ if (i < 2) goto err_sl; bufp = (unsigned char *)buf; k = 0; - i -= again; if (i % 2 != 0) { ASN1error(ASN1_R_ODD_NUMBER_OF_CHARS); goto err; @@ -182,13 +409,15 @@ a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size) else break; } - bs->length = num; - bs->data = s; - return (1); + astr->length = num; + astr->data = s; -err_sl: + return 1; + + err_sl: ASN1error(ASN1_R_SHORT_LINE); -err: + err: free(s); - return (ret); + + return ret; } diff --git a/crypto/asn1/a_strnid.c b/crypto/asn1/a_strnid.c index 0585f70..034c4d7 100644 --- a/crypto/asn1/a_strnid.c +++ b/crypto/asn1/a_strnid.c @@ -1,4 +1,4 @@ -/* $OpenBSD: a_strnid.c,v 1.21 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: a_strnid.c,v 1.25 2021/12/13 17:55:53 schwarze Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -56,8 +56,9 @@ * */ -#include -#include +#include +#include +#include #include #include @@ -65,12 +66,15 @@ #include static STACK_OF(ASN1_STRING_TABLE) *stable = NULL; + +static ASN1_STRING_TABLE *stable_get(int nid); static void st_free(ASN1_STRING_TABLE *tbl); static int sk_table_cmp(const ASN1_STRING_TABLE * const *a, const ASN1_STRING_TABLE * const *b); -/* This is the global mask for the mbstring functions: this is use to +/* + * This is the global mask for the mbstring functions: this is used to * mask out certain types (such as BMPString and UTF8String) because * certain software (e.g. Netscape) has problems with them. */ @@ -89,7 +93,8 @@ ASN1_STRING_get_default_mask(void) return global_mask; } -/* This function sets the default to various "flavours" of configuration. +/* + * This function sets the default to various "flavours" of configuration * based on an ASCII string. Currently this is: * MASK:XXXX : a numerical mask value. * nobmp : Don't use BMPStrings (just Printable, T61). @@ -103,20 +108,26 @@ ASN1_STRING_set_default_mask_asc(const char *p) { unsigned long mask; char *end; + int save_errno; - if (!strncmp(p, "MASK:", 5)) { - if (!p[5]) + if (strncmp(p, "MASK:", 5) == 0) { + if (p[5] == '\0') return 0; + save_errno = errno; + errno = 0; mask = strtoul(p + 5, &end, 0); - if (*end) + if (errno == ERANGE && mask == ULONG_MAX) return 0; - } else if (!strcmp(p, "nombstr")) + errno = save_errno; + if (*end != '\0') + return 0; + } else if (strcmp(p, "nombstr") == 0) mask = ~((unsigned long)(B_ASN1_BMPSTRING|B_ASN1_UTF8STRING)); - else if (!strcmp(p, "pkix")) + else if (strcmp(p, "pkix") == 0) mask = ~((unsigned long)B_ASN1_T61STRING); - else if (!strcmp(p, "utf8only")) + else if (strcmp(p, "utf8only") == 0) mask = B_ASN1_UTF8STRING; - else if (!strcmp(p, "default")) + else if (strcmp(p, "default") == 0) mask = 0xFFFFFFFFL; else return 0; @@ -124,7 +135,8 @@ ASN1_STRING_set_default_mask_asc(const char *p) return 1; } -/* The following function generates an ASN1_STRING based on limits in a table. +/* + * The following function generates an ASN1_STRING based on limits in a table. * Frequently the types and length of an ASN1_STRING are restricted by a * corresponding OID. For example certificates and certificate requests. */ @@ -137,12 +149,13 @@ ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in, int inlen, ASN1_STRING *str = NULL; unsigned long mask; int ret; - if (!out) + + if (out == NULL) out = &str; tbl = ASN1_STRING_TABLE_get(nid); - if (tbl) { + if (tbl != NULL) { mask = tbl->mask; - if (!(tbl->flags & STABLE_NO_MASK)) + if ((tbl->flags & STABLE_NO_MASK) == 0) mask &= global_mask; ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask, tbl->minsize, tbl->maxsize); @@ -154,7 +167,8 @@ ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in, int inlen, return *out; } -/* Now the tables and helper functions for the string table: +/* + * Now the tables and helper functions for the string table: */ /* size limits: this stuff is taken straight from RFC3280 */ @@ -231,20 +245,59 @@ ASN1_STRING_TABLE * ASN1_STRING_TABLE_get(int nid) { int idx; - ASN1_STRING_TABLE *ttmp; ASN1_STRING_TABLE fnd; fnd.nid = nid; - ttmp = OBJ_bsearch_table(&fnd, tbl_standard, + if (stable != NULL) { + idx = sk_ASN1_STRING_TABLE_find(stable, &fnd); + if (idx >= 0) + return sk_ASN1_STRING_TABLE_value(stable, idx); + } + return OBJ_bsearch_table(&fnd, tbl_standard, sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE)); - if (ttmp) - return ttmp; - if (!stable) +} + +/* + * Return a string table pointer which can be modified: either directly + * from table or a copy of an internal value added to the table. + */ + +static ASN1_STRING_TABLE * +stable_get(int nid) +{ + ASN1_STRING_TABLE *tmp, *rv; + + /* Always need a string table so allocate one if NULL */ + if (stable == NULL) { + stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp); + if (stable == NULL) + return NULL; + } + tmp = ASN1_STRING_TABLE_get(nid); + if (tmp != NULL && (tmp->flags & STABLE_FLAGS_MALLOC) != 0) + return tmp; + + if ((rv = calloc(1, sizeof(*rv))) == NULL) { + ASN1error(ERR_R_MALLOC_FAILURE); return NULL; - idx = sk_ASN1_STRING_TABLE_find(stable, &fnd); - if (idx < 0) + } + if (!sk_ASN1_STRING_TABLE_push(stable, rv)) { + free(rv); return NULL; - return sk_ASN1_STRING_TABLE_value(stable, idx); + } + if (tmp != NULL) { + rv->nid = tmp->nid; + rv->minsize = tmp->minsize; + rv->maxsize = tmp->maxsize; + rv->mask = tmp->mask; + rv->flags = tmp->flags | STABLE_FLAGS_MALLOC; + } else { + rv->nid = nid; + rv->minsize = -1; + rv->maxsize = -1; + rv->flags = STABLE_FLAGS_MALLOC; + } + return rv; } int @@ -252,37 +305,20 @@ ASN1_STRING_TABLE_add(int nid, long minsize, long maxsize, unsigned long mask, unsigned long flags) { ASN1_STRING_TABLE *tmp; - char new_nid = 0; - flags &= ~STABLE_FLAGS_MALLOC; - if (!stable) - stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp); - if (!stable) { + if ((tmp = stable_get(nid)) == NULL) { ASN1error(ERR_R_MALLOC_FAILURE); return 0; } - if (!(tmp = ASN1_STRING_TABLE_get(nid))) { - tmp = malloc(sizeof(ASN1_STRING_TABLE)); - if (!tmp) { - ASN1error(ERR_R_MALLOC_FAILURE); - return 0; - } - tmp->flags = flags | STABLE_FLAGS_MALLOC; - tmp->nid = nid; - new_nid = 1; - } else tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags; - if (minsize != -1) + if (minsize >= 0) tmp->minsize = minsize; - if (maxsize != -1) + if (maxsize >= 0) tmp->maxsize = maxsize; - tmp->mask = mask; - if (new_nid) { - if (sk_ASN1_STRING_TABLE_push(stable, tmp) == 0) { - free(tmp); - ASN1error(ERR_R_MALLOC_FAILURE); - return 0; - } - } + if (mask != 0) + tmp->mask = mask; + if (flags != 0) + tmp->flags = flags | STABLE_FLAGS_MALLOC; + return 1; } @@ -292,7 +328,7 @@ ASN1_STRING_TABLE_cleanup(void) STACK_OF(ASN1_STRING_TABLE) *tmp; tmp = stable; - if (!tmp) + if (tmp == NULL) return; stable = NULL; sk_ASN1_STRING_TABLE_pop_free(tmp, st_free); diff --git a/crypto/asn1/a_time.c b/crypto/asn1/a_time.c index 7a3742f..cd6a790 100644 --- a/crypto/asn1/a_time.c +++ b/crypto/asn1/a_time.c @@ -1,4 +1,4 @@ -/* $OpenBSD: a_time.c,v 1.27 2015/10/19 16:32:37 beck Exp $ */ +/* $OpenBSD: a_time.c,v 1.33 2021/12/25 07:48:09 jsing Exp $ */ /* ==================================================================== * Copyright (c) 1999 The OpenSSL Project. All rights reserved. * @@ -80,6 +80,45 @@ const ASN1_ITEM ASN1_TIME_it = { .sname = "ASN1_TIME", }; +ASN1_TIME * +ASN1_TIME_new(void) +{ + return (ASN1_TIME *)ASN1_item_new(&ASN1_TIME_it); +} + +void +ASN1_TIME_free(ASN1_TIME *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &ASN1_TIME_it); +} + +/* Public API in OpenSSL. Kept internal for now. */ +static int +ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm) +{ + time_t now; + + if (s != NULL) + return ASN1_time_parse(s->data, s->length, tm, 0) != -1; + + time(&now); + memset(tm, 0, sizeof(*tm)); + + return gmtime_r(&now, tm) != NULL; +} + +int +ASN1_TIME_diff(int *pday, int *psec, const ASN1_TIME *from, const ASN1_TIME *to) +{ + struct tm tm_from, tm_to; + + if (!ASN1_TIME_to_tm(from, &tm_from)) + return 0; + if (!ASN1_TIME_to_tm(to, &tm_to)) + return 0; + + return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to); +} ASN1_TIME * d2i_ASN1_TIME(ASN1_TIME **a, const unsigned char **in, long len) @@ -93,15 +132,3 @@ i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **out) { return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_TIME_it); } - -ASN1_TIME * -ASN1_TIME_new(void) -{ - return (ASN1_TIME *)ASN1_item_new(&ASN1_TIME_it); -} - -void -ASN1_TIME_free(ASN1_TIME *a) -{ - ASN1_item_free((ASN1_VALUE *)a, &ASN1_TIME_it); -} diff --git a/crypto/asn1/a_time_tm.c b/crypto/asn1/a_time_tm.c index db93825..5be2ff0 100644 --- a/crypto/asn1/a_time_tm.c +++ b/crypto/asn1/a_time_tm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: a_time_tm.c,v 1.18 2021/08/28 08:22:48 tb Exp $ */ +/* $OpenBSD: a_time_tm.c,v 1.19 2022/03/31 13:04:47 tb Exp $ */ /* * Copyright (c) 2015 Bob Beck * @@ -259,7 +259,7 @@ ASN1_TIME_adj_internal(ASN1_TIME *s, time_t t, int offset_day, long offset_sec, int allocated = 0; struct tm tm; size_t len; - char * p; + char *p; if (gmtime_r(&t, &tm) == NULL) return (NULL); @@ -288,8 +288,10 @@ ASN1_TIME_adj_internal(ASN1_TIME *s, time_t t, int offset_day, long offset_sec, } if (s == NULL) { - if ((s = ASN1_TIME_new()) == NULL) + if ((s = ASN1_TIME_new()) == NULL) { + free(p); return (NULL); + } allocated = 1; } diff --git a/crypto/asn1/a_type.c b/crypto/asn1/a_type.c index a18ffe6..61609c3 100644 --- a/crypto/asn1/a_type.c +++ b/crypto/asn1/a_type.c @@ -1,4 +1,4 @@ -/* $OpenBSD: a_type.c,v 1.21 2019/10/24 16:36:10 jsing Exp $ */ +/* $OpenBSD: a_type.c,v 1.23 2021/12/25 12:19:16 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -56,11 +56,51 @@ * [including the GNU Public Licence.] */ -#include +#include #include +#include #include +typedef struct { + ASN1_INTEGER *num; + ASN1_OCTET_STRING *value; +} ASN1_int_octetstring; + +static const ASN1_TEMPLATE ASN1_INT_OCTETSTRING_seq_tt[] = { + { + .offset = offsetof(ASN1_int_octetstring, num), + .field_name = "num", + .item = &ASN1_INTEGER_it, + }, + { + .offset = offsetof(ASN1_int_octetstring, value), + .field_name = "value", + .item = &ASN1_OCTET_STRING_it, + }, +}; + +const ASN1_ITEM ASN1_INT_OCTETSTRING_it = { + .itype = ASN1_ITYPE_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = ASN1_INT_OCTETSTRING_seq_tt, + .tcount = sizeof(ASN1_INT_OCTETSTRING_seq_tt) / sizeof(ASN1_TEMPLATE), + .size = sizeof(ASN1_int_octetstring), + .sname = "ASN1_INT_OCTETSTRING", +}; + +ASN1_TYPE * +ASN1_TYPE_new(void) +{ + return (ASN1_TYPE *)ASN1_item_new(&ASN1_ANY_it); +} + +void +ASN1_TYPE_free(ASN1_TYPE *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &ASN1_ANY_it); +} + int ASN1_TYPE_get(const ASN1_TYPE *a) { @@ -155,6 +195,108 @@ ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b) return result; } +int +ASN1_TYPE_set_octetstring(ASN1_TYPE *a, const unsigned char *data, int len) +{ + ASN1_STRING *os; + + if ((os = ASN1_OCTET_STRING_new()) == NULL) + return (0); + if (!ASN1_STRING_set(os, data, len)) { + ASN1_OCTET_STRING_free(os); + return (0); + } + ASN1_TYPE_set(a, V_ASN1_OCTET_STRING, os); + return (1); +} + +int +ASN1_TYPE_get_octetstring(const ASN1_TYPE *a, unsigned char *data, int max_len) +{ + int ret, num; + unsigned char *p; + + if ((a->type != V_ASN1_OCTET_STRING) || + (a->value.octet_string == NULL)) { + ASN1error(ASN1_R_DATA_IS_WRONG); + return (-1); + } + p = ASN1_STRING_data(a->value.octet_string); + ret = ASN1_STRING_length(a->value.octet_string); + if (ret < max_len) + num = ret; + else + num = max_len; + memcpy(data, p, num); + return (ret); +} + +int +ASN1_TYPE_set_int_octetstring(ASN1_TYPE *at, long num, const unsigned char *data, + int len) +{ + ASN1_int_octetstring *ios; + ASN1_STRING *sp = NULL; + int ret = 0; + + if ((ios = (ASN1_int_octetstring *)ASN1_item_new( + &ASN1_INT_OCTETSTRING_it)) == NULL) + goto err; + if (!ASN1_INTEGER_set(ios->num, num)) + goto err; + if (!ASN1_OCTET_STRING_set(ios->value, data, len)) + goto err; + + if ((sp = ASN1_item_pack(ios, &ASN1_INT_OCTETSTRING_it, NULL)) == NULL) + goto err; + + ASN1_TYPE_set(at, V_ASN1_SEQUENCE, sp); + sp = NULL; + + ret = 1; + + err: + ASN1_item_free((ASN1_VALUE *)ios, &ASN1_INT_OCTETSTRING_it); + ASN1_STRING_free(sp); + + return ret; +} + +int +ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *at, long *num, unsigned char *data, + int max_len) +{ + ASN1_STRING *sp = at->value.sequence; + ASN1_int_octetstring *ios = NULL; + int ret = -1; + int len; + + if (at->type != V_ASN1_SEQUENCE || sp == NULL) + goto err; + + if ((ios = ASN1_item_unpack(sp, &ASN1_INT_OCTETSTRING_it)) == NULL) + goto err; + + if (num != NULL) + *num = ASN1_INTEGER_get(ios->num); + if (data != NULL) { + len = ASN1_STRING_length(ios->value); + if (len > max_len) + len = max_len; + memcpy(data, ASN1_STRING_data(ios->value), len); + } + + ret = ASN1_STRING_length(ios->value); + + err: + ASN1_item_free((ASN1_VALUE *)ios, &ASN1_INT_OCTETSTRING_it); + + if (ret == -1) + ASN1error(ASN1_R_DATA_IS_WRONG); + + return ret; +} + ASN1_TYPE * ASN1_TYPE_pack_sequence(const ASN1_ITEM *it, void *s, ASN1_TYPE **t) { @@ -185,3 +327,16 @@ ASN1_TYPE_unpack_sequence(const ASN1_ITEM *it, const ASN1_TYPE *t) return NULL; return ASN1_item_unpack(t->value.sequence, it); } + +int +i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_ANY_it); +} + +ASN1_TYPE * +d2i_ASN1_TYPE(ASN1_TYPE **a, const unsigned char **in, long len) +{ + return (ASN1_TYPE *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &ASN1_ANY_it); +} diff --git a/crypto/asn1/ameth_lib.c b/crypto/asn1/ameth_lib.c index 8be8206..8ff5a35 100644 --- a/crypto/asn1/ameth_lib.c +++ b/crypto/asn1/ameth_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ameth_lib.c,v 1.21 2019/11/02 16:06:25 inoguchi Exp $ */ +/* $OpenBSD: ameth_lib.c,v 1.25 2022/01/10 12:10:26 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2006. */ @@ -69,6 +69,7 @@ #endif #include "asn1_locl.h" +#include "evp_locl.h" extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[]; extern const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth; @@ -340,34 +341,21 @@ EVP_PKEY_asn1_new(int id, int flags, const char *pem_str, const char *info) 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; + EVP_PKEY_ASN1_METHOD preserve; - dst->priv_decode = src->priv_decode; - dst->priv_encode = src->priv_encode; - dst->priv_print = src->priv_print; + preserve.pkey_id = dst->pkey_id; + preserve.pkey_base_id = dst->pkey_base_id; + preserve.pkey_flags = dst->pkey_flags; + preserve.pem_str = dst->pem_str; + preserve.info = dst->info; - dst->old_priv_encode = src->old_priv_encode; - dst->old_priv_decode = src->old_priv_decode; + *dst = *src; - 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->sig_print = src->sig_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->pkey_id = preserve.pkey_id; + dst->pkey_base_id = preserve.pkey_base_id; + dst->pkey_flags = preserve.pkey_flags; + dst->pem_str = preserve.pem_str; + dst->info = preserve.info; } void @@ -441,3 +429,24 @@ EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth, { ameth->pkey_ctrl = pkey_ctrl; } + +void +EVP_PKEY_asn1_set_check(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_check)(const EVP_PKEY *pk)) +{ + ameth->pkey_check = pkey_check; +} + +void +EVP_PKEY_asn1_set_public_check(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_public_check)(const EVP_PKEY *pk)) +{ + ameth->pkey_public_check = pkey_public_check; +} + +void +EVP_PKEY_asn1_set_param_check(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_param_check)(const EVP_PKEY *pk)) +{ + ameth->pkey_param_check = pkey_param_check; +} diff --git a/crypto/asn1/asn1_gen.c b/crypto/asn1/asn1_gen.c index ad7802c..d800b77 100644 --- a/crypto/asn1/asn1_gen.c +++ b/crypto/asn1/asn1_gen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: asn1_gen.c,v 1.17 2018/04/25 11:48:21 tb Exp $ */ +/* $OpenBSD: asn1_gen.c,v 1.18 2021/12/25 13:17:48 jsing Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2002. */ @@ -258,7 +258,7 @@ ASN1_generate_v3(const char *str, X509V3_CTX *cnf) /* Obtain new ASN1_TYPE structure */ ret = d2i_ASN1_TYPE(NULL, &cp, len); -err: + err: free(orig_der); free(new_der); @@ -478,7 +478,7 @@ asn1_multi(int utype, const char *section, X509V3_CTX *cnf) der = NULL; -bad: + bad: free(der); if (sk) sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free); @@ -771,9 +771,9 @@ asn1_str2type(const char *str, int format, int utype) atmp->type = utype; return atmp; -bad_str: + bad_str: ERR_asprintf_error_data("string=%s", str); -bad_form: + bad_form: ASN1_TYPE_free(atmp); return NULL; } diff --git a/crypto/asn1/asn1_item.c b/crypto/asn1/asn1_item.c new file mode 100644 index 0000000..108f272 --- /dev/null +++ b/crypto/asn1/asn1_item.c @@ -0,0 +1,639 @@ +/* $OpenBSD: asn1_item.c,v 1.4 2022/01/14 08:38:05 tb Exp $ */ +/* 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2003 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). + * + */ + +#include + +#include +#include +#include +#include + +#include "asn1_locl.h" +#include "evp_locl.h" + +/* + * ASN1_ITEM version of dup: this follows the model above except we don't need + * to allocate the buffer. At some point this could be rewritten to directly dup + * the underlying structure instead of doing and encode and decode. + */ + +int +ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn, + unsigned char *md, unsigned int *len) +{ + int i; + unsigned char *str = NULL; + + i = ASN1_item_i2d(asn, &str, it); + if (!str) + return (0); + + if (!EVP_Digest(str, i, md, len, type, NULL)) { + free(str); + return (0); + } + + free(str); + return (1); +} + +void * +ASN1_item_dup(const ASN1_ITEM *it, void *x) +{ + unsigned char *b = NULL; + const unsigned char *p; + long i; + void *ret; + + if (x == NULL) + return (NULL); + + i = ASN1_item_i2d(x, &b, it); + if (b == NULL) { + ASN1error(ERR_R_MALLOC_FAILURE); + return (NULL); + } + p = b; + ret = ASN1_item_d2i(NULL, &p, i, it); + free(b); + return (ret); +} + +/* Pack an ASN1 object into an ASN1_STRING. */ +ASN1_STRING * +ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct) +{ + ASN1_STRING *octmp; + + if (!oct || !*oct) { + if (!(octmp = ASN1_STRING_new ())) { + ASN1error(ERR_R_MALLOC_FAILURE); + return NULL; + } + } else + octmp = *oct; + + free(octmp->data); + octmp->data = NULL; + + if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) { + ASN1error(ASN1_R_ENCODE_ERROR); + goto err; + } + if (!octmp->data) { + ASN1error(ERR_R_MALLOC_FAILURE); + goto err; + } + if (oct) + *oct = octmp; + return octmp; + err: + if (!oct || octmp != *oct) + ASN1_STRING_free(octmp); + return NULL; +} + +/* Extract an ASN1 object from an ASN1_STRING. */ +void * +ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it) +{ + const unsigned char *p; + void *ret; + + p = oct->data; + if (!(ret = ASN1_item_d2i(NULL, &p, oct->length, it))) + ASN1error(ASN1_R_DECODE_ERROR); + return ret; +} + +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) +{ + EVP_MD_CTX ctx; + EVP_MD_CTX_init(&ctx); + if (!EVP_DigestSignInit(&ctx, NULL, type, NULL, pkey)) { + EVP_MD_CTX_cleanup(&ctx); + return 0; + } + return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, &ctx); +} + +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) +{ + const EVP_MD *type; + EVP_PKEY *pkey; + unsigned char *buf_in = NULL, *buf_out = NULL; + size_t inl = 0, outl = 0, outll = 0; + int signid, paramtype; + int rv; + + type = EVP_MD_CTX_md(ctx); + pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx); + + if (!type || !pkey) { + ASN1error(ASN1_R_CONTEXT_NOT_INITIALISED); + return 0; + } + + if (pkey->ameth->item_sign) { + rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2, + signature); + if (rv == 1) + outl = signature->length; + /* Return value meanings: + * <=0: error. + * 1: method does everything. + * 2: carry on as normal. + * 3: ASN1 method sets algorithm identifiers: just sign. + */ + if (rv <= 0) + ASN1error(ERR_R_EVP_LIB); + if (rv <= 1) + goto err; + } else + rv = 2; + + if (rv == 2) { + if (!pkey->ameth || + !OBJ_find_sigid_by_algs(&signid, EVP_MD_nid(type), + pkey->ameth->pkey_id)) { + ASN1error(ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); + return 0; + } + + if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL) + paramtype = V_ASN1_NULL; + else + paramtype = V_ASN1_UNDEF; + + if (algor1) + X509_ALGOR_set0(algor1, + OBJ_nid2obj(signid), paramtype, NULL); + if (algor2) + X509_ALGOR_set0(algor2, + OBJ_nid2obj(signid), paramtype, NULL); + + } + + inl = ASN1_item_i2d(asn, &buf_in, it); + outll = outl = EVP_PKEY_size(pkey); + buf_out = malloc(outl); + if ((buf_in == NULL) || (buf_out == NULL)) { + outl = 0; + ASN1error(ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!EVP_DigestSignUpdate(ctx, buf_in, inl) || + !EVP_DigestSignFinal(ctx, buf_out, &outl)) { + outl = 0; + ASN1error(ERR_R_EVP_LIB); + goto err; + } + free(signature->data); + signature->data = buf_out; + buf_out = NULL; + signature->length = outl; + /* In the interests of compatibility, I'll make sure that + * the bit string has a 'not-used bits' value of 0 + */ + signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); + signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; + + err: + EVP_MD_CTX_cleanup(ctx); + freezero((char *)buf_in, inl); + freezero((char *)buf_out, outll); + return (outl); +} + +int +ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, + ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey) +{ + EVP_MD_CTX ctx; + unsigned char *buf_in = NULL; + int ret = -1, inl; + + int mdnid, pknid; + + if (!pkey) { + ASN1error(ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + + if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) + { + ASN1error(ASN1_R_INVALID_BIT_STRING_BITS_LEFT); + return -1; + } + + EVP_MD_CTX_init(&ctx); + + /* Convert signature OID into digest and public key OIDs */ + if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->algorithm), &mdnid, &pknid)) { + ASN1error(ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); + goto err; + } + if (mdnid == NID_undef) { + if (!pkey->ameth || !pkey->ameth->item_verify) { + ASN1error(ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); + goto err; + } + ret = pkey->ameth->item_verify(&ctx, it, asn, a, + 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. + */ + if (ret != 2) + goto err; + ret = -1; + } else { + const EVP_MD *type; + type = EVP_get_digestbynid(mdnid); + if (type == NULL) { + ASN1error(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) { + ASN1error(ASN1_R_WRONG_PUBLIC_KEY_TYPE); + goto err; + } + + if (!EVP_DigestVerifyInit(&ctx, NULL, type, NULL, pkey)) { + ASN1error(ERR_R_EVP_LIB); + ret = 0; + goto err; + } + + } + + inl = ASN1_item_i2d(asn, &buf_in, it); + + if (buf_in == NULL) { + ASN1error(ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!EVP_DigestVerifyUpdate(&ctx, buf_in, inl)) { + ASN1error(ERR_R_EVP_LIB); + ret = 0; + goto err; + } + + freezero(buf_in, (unsigned int)inl); + + if (EVP_DigestVerifyFinal(&ctx, signature->data, + (size_t)signature->length) <= 0) { + ASN1error(ERR_R_EVP_LIB); + ret = 0; + goto err; + } + /* we don't need to zero the 'ctx' because we just checked + * public information */ + /* memset(&ctx,0,sizeof(ctx)); */ + ret = 1; + + err: + EVP_MD_CTX_cleanup(&ctx); + return (ret); +} + +#define HEADER_SIZE 8 +#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024) +int +asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) +{ + BUF_MEM *b; + unsigned char *p; + const unsigned char *q; + long slen; + int i, inf, tag, xclass; + size_t want = HEADER_SIZE; + int eos = 0; + size_t off = 0; + size_t len = 0; + + b = BUF_MEM_new(); + if (b == NULL) { + ASN1error(ERR_R_MALLOC_FAILURE); + return -1; + } + + ERR_clear_error(); + for (;;) { + if (want >= (len - off)) { + want -= (len - off); + + if (len + want < len || + !BUF_MEM_grow_clean(b, len + want)) { + ASN1error(ERR_R_MALLOC_FAILURE); + goto err; + } + i = BIO_read(in, &(b->data[len]), want); + if ((i < 0) && ((len - off) == 0)) { + ASN1error(ASN1_R_NOT_ENOUGH_DATA); + goto err; + } + if (i > 0) { + if (len + i < len) { + ASN1error(ASN1_R_TOO_LONG); + goto err; + } + len += i; + } + } + /* else data already loaded */ + + p = (unsigned char *) & (b->data[off]); + q = p; + inf = ASN1_get_object(&q, &slen, &tag, &xclass, len - off); + if (inf & 0x80) { + unsigned long e; + + e = ERR_GET_REASON(ERR_peek_error()); + if (e != ASN1_R_TOO_LONG) + goto err; + else + ERR_clear_error(); /* clear error */ + } + i = q - p; /* header length */ + off += i; /* end of data */ + + if (inf & 1) { + /* no data body so go round again */ + eos++; + if (eos < 0) { + ASN1error(ASN1_R_HEADER_TOO_LONG); + goto err; + } + want = HEADER_SIZE; + } else if (eos && slen == 0 && tag == V_ASN1_EOC) { + /* eos value, so go back and read another header */ + eos--; + if (eos <= 0) + break; + else + want = HEADER_SIZE; + } else { + /* suck in slen bytes of data */ + want = slen; + if (want > (len - off)) { + size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE; + + want -= (len - off); + if (want > INT_MAX /* BIO_read takes an int length */ || + len+want < len) { + ASN1error(ASN1_R_TOO_LONG); + goto err; + } + while (want > 0) { + /* + * Read content in chunks of increasing size + * so we can return an error for EOF without + * having to allocate the entire content length + * in one go. + */ + size_t chunk = want > chunk_max ? chunk_max : want; + + if (!BUF_MEM_grow_clean(b, len + chunk)) { + ASN1error(ERR_R_MALLOC_FAILURE); + goto err; + } + want -= chunk; + while (chunk > 0) { + i = BIO_read(in, &(b->data[len]), chunk); + if (i <= 0) { + ASN1error(ASN1_R_NOT_ENOUGH_DATA); + goto err; + } + /* + * This can't overflow because |len+want| + * didn't overflow. + */ + len += i; + chunk -= i; + } + if (chunk_max < INT_MAX/2) + chunk_max *= 2; + } + } + if (off + slen < off) { + ASN1error(ASN1_R_TOO_LONG); + goto err; + } + off += slen; + if (eos <= 0) { + break; + } else + want = HEADER_SIZE; + } + } + + if (off > INT_MAX) { + ASN1error(ASN1_R_TOO_LONG); + goto err; + } + + *pb = b; + return off; + + err: + if (b != NULL) + BUF_MEM_free(b); + return -1; +} + +void * +ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x) +{ + 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 = (const unsigned char *)b->data; + ret = ASN1_item_d2i(x, &p, len, it); + + err: + if (b != NULL) + BUF_MEM_free(b); + return (ret); +} + +void * +ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x) +{ + BIO *b; + char *ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + ASN1error(ERR_R_BUF_LIB); + return (NULL); + } + BIO_set_fp(b, in, BIO_NOCLOSE); + ret = ASN1_item_d2i_bio(it, b, x); + BIO_free(b); + return (ret); +} + +int +ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x) +{ + unsigned char *b = NULL; + int i, j = 0, n, ret = 1; + + n = ASN1_item_i2d(x, &b, it); + if (b == NULL) { + ASN1error(ERR_R_MALLOC_FAILURE); + return (0); + } + + for (;;) { + i = BIO_write(out, &(b[j]), n); + if (i == n) + break; + if (i <= 0) { + ret = 0; + break; + } + j += i; + n -= i; + } + free(b); + return (ret); +} + +int +ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + ASN1error(ERR_R_BUF_LIB); + return (0); + } + BIO_set_fp(b, out, BIO_NOCLOSE); + ret = ASN1_item_i2d_bio(it, b, x); + BIO_free(b); + return (ret); +} diff --git a/crypto/asn1/asn1_lib.c b/crypto/asn1/asn1_lib.c index d760ccc..6a29c32 100644 --- a/crypto/asn1/asn1_lib.c +++ b/crypto/asn1/asn1_lib.c @@ -1,438 +1,202 @@ -/* $OpenBSD: asn1_lib.c,v 1.45 2020/12/08 15:06:42 tb Exp $ */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* $OpenBSD: asn1_lib.c,v 1.52 2022/03/26 14:47:58 jsing Exp $ */ +/* + * Copyright (c) 2021 Joel Sing * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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.] + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include -#include -#include +#include -#include -#include - -static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, int max); -static void asn1_put_length(unsigned char **pp, int length); +#include "bytestring.h" static int -_asn1_check_infinite_end(const unsigned char **p, long len) +asn1_get_identifier_cbs(CBS *cbs, int der_mode, uint8_t *out_class, + int *out_constructed, uint32_t *out_tag_number) { - /* 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; - return (1); - } - return (0); -} + uint8_t tag_class, tag_val; + int tag_constructed; + uint32_t tag_number; -int -ASN1_check_infinite_end(unsigned char **p, long len) -{ - return _asn1_check_infinite_end((const unsigned char **)p, len); -} + /* + * Decode ASN.1 identifier octets - see ITU-T X.690 section 8.1.2. + */ -int -ASN1_const_check_infinite_end(const unsigned char **p, long len) -{ - return _asn1_check_infinite_end(p, len); -} + *out_class = 0; + *out_constructed = 0; + *out_tag_number = 0; -int -ASN1_get_object(const unsigned char **pp, long *plength, int *ptag, - int *pclass, long omax) -{ - int i, ret; - long l; - const unsigned char *p = *pp; - int tag, xclass, inf; - long max = omax; + if (!CBS_get_u8(cbs, &tag_val)) + return 0; - if (!max) - goto err; - ret = (*p & V_ASN1_CONSTRUCTED); - xclass = (*p & V_ASN1_PRIVATE); - i = *p & V_ASN1_PRIMITIVE_TAG; - if (i == V_ASN1_PRIMITIVE_TAG) { /* high-tag */ - p++; - if (--max == 0) - goto err; - l = 0; - while (*p & 0x80) { - l <<= 7L; - l |= *(p++) & 0x7f; - if (--max == 0) - goto err; - if (l > (INT_MAX >> 7L)) - goto err; - } - l <<= 7L; - l |= *(p++) & 0x7f; - tag = (int)l; - if (--max == 0) - goto err; - } else { - tag = i; - p++; - if (--max == 0) - goto err; - } - *ptag = tag; - *pclass = xclass; - if (!asn1_get_length(&p, &inf, plength, (int)max)) - goto err; + /* + * ASN.1 tag class, encoding (primitive or constructed) and tag number + * are encoded in one or more identifier octets - the first octet + * contains the 2 bit tag class, the 1 bit encoding type and 5 bits + * of tag number. + * + * For tag numbers larger than 30 (0x1e) the 5 bit tag number in the + * first octet is set to all ones (0x1f) - the tag number is then + * encoded in subsequent octets - each of which have a one bit + * continuation flag and 7 bits of tag number in big-endian form. + * The encoding should not contain leading zeros but can for BER. + */ + tag_class = (tag_val >> 6) & 0x3; + tag_constructed = (tag_val >> 5) & 0x1; + tag_number = tag_val & 0x1f; - if (inf && !(ret & V_ASN1_CONSTRUCTED)) - goto err; - - if (*plength > (omax - (p - *pp))) { - ASN1error(ASN1_R_TOO_LONG); - /* Set this so that even if things are not long enough - * the values are set correctly */ - ret |= 0x80; - } - *pp = p; - return (ret | inf); - -err: - ASN1error(ASN1_R_HEADER_TOO_LONG); - return (0x80); -} - -static int -asn1_get_length(const unsigned char **pp, int *inf, long *rl, int max) -{ - const unsigned char *p = *pp; - unsigned long ret = 0; - unsigned int i; - - if (max-- < 1) - return (0); - if (*p == 0x80) { - *inf = 1; - ret = 0; - p++; - } else { - *inf = 0; - i = *p & 0x7f; - if (*(p++) & 0x80) { - if (max < (int)i) - return (0); - /* skip leading zeroes */ - while (i && *p == 0) { - p++; - i--; - } - if (i > sizeof(long)) + /* Long form. */ + if (tag_number == 0x1f) { + tag_number = 0; + do { + if (!CBS_get_u8(cbs, &tag_val)) return 0; - while (i-- > 0) { - ret <<= 8L; - ret |= *(p++); - } - } else - ret = i; + if (der_mode && tag_number == 0 && tag_val == 0x80) + return 0; + if (tag_number > (UINT32_MAX >> 7)) + return 0; + tag_number = tag_number << 7 | (tag_val & 0x7f); + } while ((tag_val & 0x80) != 0); } - if (ret > LONG_MAX) - return 0; - *pp = p; - *rl = (long)ret; - return (1); -} -/* class 0 is constructed - * constructed == 2 for indefinite length constructed */ -void -ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, - int xclass) -{ - unsigned char *p = *pp; - int i, ttag; + *out_class = tag_class; + *out_constructed = tag_constructed; + *out_tag_number = tag_number; - i = (constructed) ? V_ASN1_CONSTRUCTED : 0; - i |= (xclass & V_ASN1_PRIVATE); - if (tag < 31) - *(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG); - else { - *(p++) = i | V_ASN1_PRIMITIVE_TAG; - for(i = 0, ttag = tag; ttag > 0; i++) - ttag >>= 7; - ttag = i; - while (i-- > 0) { - p[i] = tag & 0x7f; - if (i != (ttag - 1)) - p[i] |= 0x80; - tag >>= 7; - } - p += ttag; - } - if (constructed == 2) - *(p++) = 0x80; - else - asn1_put_length(&p, length); - *pp = p; -} - -int -ASN1_put_eoc(unsigned char **pp) -{ - unsigned char *p = *pp; - - *p++ = 0; - *p++ = 0; - *pp = p; - return 2; -} - -static void -asn1_put_length(unsigned char **pp, int length) -{ - unsigned char *p = *pp; - - int i, l; - if (length <= 127) - *(p++) = (unsigned char)length; - else { - l = length; - for (i = 0; l > 0; i++) - l >>= 8; - *(p++) = i | 0x80; - l = i; - while (i-- > 0) { - p[i] = length & 0xff; - length >>= 8; - } - p += l; - } - *pp = p; -} - -int -ASN1_object_size(int constructed, int length, int tag) -{ - int ret; - - ret = length; - ret++; - if (tag >= 31) { - while (tag > 0) { - tag >>= 7; - ret++; - } - } - if (constructed == 2) - return ret + 3; - ret++; - if (length > 127) { - while (length > 0) { - length >>= 8; - ret++; - } - } - return (ret); -} - -int -ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str) -{ - if (str == NULL) - return 0; - dst->type = str->type; - if (!ASN1_STRING_set(dst, str->data, str->length)) - return 0; - dst->flags = str->flags; return 1; } -ASN1_STRING * -ASN1_STRING_dup(const ASN1_STRING *str) +static int +asn1_get_length_cbs(CBS *cbs, int der_mode, int *out_indefinite, + uint32_t *out_length) { - ASN1_STRING *ret; + uint8_t len_bytes; + uint32_t length; + uint8_t val; - if (!str) - return NULL; - ret = ASN1_STRING_new(); - if (!ret) - return NULL; - if (!ASN1_STRING_copy(ret, str)) { - ASN1_STRING_free(ret); - return NULL; + /* + * Decode ASN.1 length octets - see ITU-T X.690 section 8.1.3. + */ + + *out_length = 0; + *out_indefinite = 0; + + if (!CBS_get_u8(cbs, &val)) + return 0; + + /* + * Short form - length is encoded in the lower 7 bits of a single byte. + */ + if (val < 0x80) { + *out_length = val; + return 1; } - return ret; + + /* + * Indefinite length - content continues until an End of Content (EOC) + * marker is reached. Must be used with constructed encoding. + */ + if (val == 0x80) { + *out_indefinite = 1; + return 1; + } + + /* + * Long form - the lower 7 bits of the first byte specifies the number + * of bytes used to encode the length, the following bytes specify the + * length in big-endian form. The encoding should not contain leading + * zeros but can for BER. A length value of 0x7f is invalid. + */ + if ((len_bytes = val & 0x7f) == 0x7f) + return 0; + + length = 0; + + while (len_bytes-- > 0) { + if (!CBS_get_u8(cbs, &val)) + return 0; + if (der_mode && length == 0 && val == 0) + return 0; + if (length > (UINT32_MAX >> 8)) + return 0; + length = (length << 8) | val; + } + + *out_length = length; + + return 1; } int -ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len) +asn1_get_object_cbs(CBS *cbs, int der_mode, uint8_t *out_tag_class, + int *out_constructed, uint32_t *out_tag_number, int *out_indefinite, + uint32_t *out_length) { - const char *data = _data; + int constructed, indefinite; + uint32_t tag_number, length; + uint8_t tag_class; - if (len < 0) { - if (data == NULL) - return (0); - else - len = strlen(data); - } - if ((str->length < len) || (str->data == NULL)) { - unsigned char *tmp; - tmp = realloc(str->data, len + 1); - if (tmp == NULL) { - ASN1error(ERR_R_MALLOC_FAILURE); - return (0); - } - str->data = tmp; - } - str->length = len; - if (data != NULL) { - memmove(str->data, data, len); - } - str->data[str->length] = '\0'; - return (1); -} + *out_tag_class = 0; + *out_constructed = 0; + *out_tag_number = 0; + *out_indefinite = 0; + *out_length = 0; -void -ASN1_STRING_set0(ASN1_STRING *str, void *data, int len) -{ - freezero(str->data, str->length); - str->data = data; - str->length = len; -} + if (!asn1_get_identifier_cbs(cbs, der_mode, &tag_class, &constructed, + &tag_number)) + return 0; + if (!asn1_get_length_cbs(cbs, der_mode, &indefinite, &length)) + return 0; -ASN1_STRING * -ASN1_STRING_new(void) -{ - return (ASN1_STRING_type_new(V_ASN1_OCTET_STRING)); -} + /* Indefinite length can only be used with constructed encoding. */ + if (indefinite && !constructed) + return 0; -ASN1_STRING * -ASN1_STRING_type_new(int type) -{ - ASN1_STRING *ret; + *out_tag_class = tag_class; + *out_constructed = constructed; + *out_tag_number = tag_number; + *out_indefinite = indefinite; + *out_length = length; - ret = malloc(sizeof(ASN1_STRING)); - if (ret == NULL) { - ASN1error(ERR_R_MALLOC_FAILURE); - return (NULL); - } - ret->length = 0; - ret->type = type; - ret->data = NULL; - ret->flags = 0; - return (ret); -} - -void -ASN1_STRING_free(ASN1_STRING *a) -{ - if (a == NULL) - return; - if (a->data != NULL && !(a->flags & ASN1_STRING_FLAG_NDEF)) - freezero(a->data, a->length); - free(a); + return 1; } int -ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b) +asn1_get_primitive(CBS *cbs, int der_mode, uint32_t *out_tag_number, + CBS *out_content) { - int i; + int constructed, indefinite; + uint32_t tag_number, length; + uint8_t tag_class; - if (a == NULL || b == NULL) - return -1; - i = (a->length - b->length); - if (i == 0) { - i = memcmp(a->data, b->data, a->length); - if (i == 0) - return (a->type - b->type); - else - return (i); - } else - return (i); -} + *out_tag_number = 0; -void -asn1_add_error(const unsigned char *address, int offset) -{ - ERR_asprintf_error_data("offset=%d", offset); -} + CBS_init(out_content, NULL, 0); -int -ASN1_STRING_length(const ASN1_STRING *x) -{ - return (x->length); -} + if (!asn1_get_identifier_cbs(cbs, der_mode, &tag_class, &constructed, + &tag_number)) + return 0; + if (!asn1_get_length_cbs(cbs, der_mode, &indefinite, &length)) + return 0; -void -ASN1_STRING_length_set(ASN1_STRING *x, int len) -{ - x->length = len; -} + /* A primitive is not constructed and has a definite length. */ + if (constructed || indefinite) + return 0; -int -ASN1_STRING_type(const ASN1_STRING *x) -{ - return (x->type); -} + if (!CBS_get_bytes(cbs, out_content, length)) + return 0; -unsigned char * -ASN1_STRING_data(ASN1_STRING *x) -{ - return (x->data); -} + *out_tag_number = tag_number; -const unsigned char * -ASN1_STRING_get0_data(const ASN1_STRING *x) -{ - return (x->data); + return 1; } diff --git a/crypto/asn1/asn1_locl.h b/crypto/asn1/asn1_locl.h index 39779d9..756e407 100644 --- a/crypto/asn1/asn1_locl.h +++ b/crypto/asn1/asn1_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: asn1_locl.h,v 1.12 2019/10/24 16:36:10 jsing Exp $ */ +/* $OpenBSD: asn1_locl.h,v 1.24 2022/03/26 14:47:58 jsing Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2006. */ @@ -56,6 +56,8 @@ * */ +#include "bytestring.h" + __BEGIN_HIDDEN_DECLS /* Internal ASN1 structures and functions: not for application use */ @@ -63,6 +65,20 @@ __BEGIN_HIDDEN_DECLS ASN1_TYPE *ASN1_TYPE_pack_sequence(const ASN1_ITEM *it, void *s, ASN1_TYPE **t); void *ASN1_TYPE_unpack_sequence(const ASN1_ITEM *it, const ASN1_TYPE *t); +/* These are used internally in the ASN1_OBJECT to keep track of + * whether the names and data need to be free()ed */ +#define ASN1_OBJECT_FLAG_DYNAMIC 0x01 /* internal use */ +#define ASN1_OBJECT_FLAG_CRITICAL 0x02 /* critical x509v3 object id */ +#define ASN1_OBJECT_FLAG_DYNAMIC_STRINGS 0x04 /* internal use */ +#define ASN1_OBJECT_FLAG_DYNAMIC_DATA 0x08 /* internal use */ +struct asn1_object_st { + const char *sn, *ln; + int nid; + int length; + const unsigned char *data; /* data remains const after init */ + int flags; /* Should we free this one */ +} /* ASN1_OBJECT */; + /* ASN1 print context structure */ struct asn1_pctx_st { @@ -122,6 +138,9 @@ struct evp_pkey_asn1_method_st { int (*item_sign)(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn, X509_ALGOR *alg1, X509_ALGOR *alg2, ASN1_BIT_STRING *sig); + int (*pkey_check)(const EVP_PKEY *pk); + int (*pkey_public_check)(const EVP_PKEY *pk); + int (*pkey_param_check)(const EVP_PKEY *pk); } /* EVP_PKEY_ASN1_METHOD */; /* Method to handle CRL access. @@ -142,6 +161,23 @@ struct x509_crl_method_st { int (*crl_verify)(X509_CRL *crl, EVP_PKEY *pk); }; +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); + +ASN1_VALUE ** asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); + +const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, int nullerr); + +int 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); + +int i2d_ASN1_BOOLEAN(int a, unsigned char **pp); +int d2i_ASN1_BOOLEAN(int *a, const unsigned char **pp, long length); + /* * Unicode codepoint constants */ @@ -155,4 +191,18 @@ struct x509_crl_method_st { int UTF8_getc(const unsigned char *str, int len, unsigned long *val); int UTF8_putc(unsigned char *str, int len, unsigned long value); +int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb); + +int asn1_get_object_cbs(CBS *cbs, int der_mode, uint8_t *out_class, + int *out_constructed, uint32_t *out_tag_number, int *out_indefinite, + uint32_t *out_length); +int asn1_get_primitive(CBS *cbs, int der_mode, uint32_t *out_tag_number, + CBS *out_content); + +int asn1_tag2charwidth(int tag); + +int i2t_ASN1_OBJECT_internal(const ASN1_OBJECT *aobj, char *buf, int buf_len, + int no_name); +ASN1_OBJECT *t2i_ASN1_OBJECT_internal(const char *oid); + __END_HIDDEN_DECLS diff --git a/crypto/asn1/a_i2d_fp.c b/crypto/asn1/asn1_old.c similarity index 82% rename from crypto/asn1/a_i2d_fp.c rename to crypto/asn1/asn1_old.c index 6398978..59e9cdb 100644 --- a/crypto/asn1/a_i2d_fp.c +++ b/crypto/asn1/asn1_old.c @@ -1,4 +1,4 @@ -/* $OpenBSD: a_i2d_fp.c,v 1.15 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: asn1_old.c,v 1.2 2021/12/25 13:17:48 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -56,14 +56,79 @@ * [including the GNU Public Licence.] */ +#include #include #include #include #include +#include "asn1_locl.h" + #ifndef NO_OLD_ASN1 +void * +ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x) +{ + unsigned char *b, *p; + const unsigned char *p2; + int i; + char *ret; + + if (x == NULL) + return (NULL); + + i = i2d(x, NULL); + b = malloc(i + 10); + if (b == NULL) { + ASN1error(ERR_R_MALLOC_FAILURE); + return (NULL); + } + p = b; + i = i2d(x, &p); + p2 = b; + ret = d2i(NULL, &p2, i); + free(b); + return (ret); +} + +void * +ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x) +{ + BIO *b; + void *ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + ASN1error(ERR_R_BUF_LIB); + return (NULL); + } + BIO_set_fp(b, in, BIO_NOCLOSE); + ret = ASN1_d2i_bio(xnew, d2i, b, x); + BIO_free(b); + return (ret); +} + +void * +ASN1_d2i_bio(void *(*xnew)(void), d2i_of_void *d2i, BIO *in, void **x) +{ + 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(x, &p, len); + + err: + if (b != NULL) + BUF_MEM_free(b); + return (ret); +} + int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x) { @@ -113,46 +178,3 @@ ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x) } #endif - -int -ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x) -{ - BIO *b; - int ret; - - if ((b = BIO_new(BIO_s_file())) == NULL) { - ASN1error(ERR_R_BUF_LIB); - return (0); - } - BIO_set_fp(b, out, BIO_NOCLOSE); - ret = ASN1_item_i2d_bio(it, b, x); - BIO_free(b); - return (ret); -} - -int -ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x) -{ - unsigned char *b = NULL; - int i, j = 0, n, ret = 1; - - n = ASN1_item_i2d(x, &b, it); - if (b == NULL) { - ASN1error(ERR_R_MALLOC_FAILURE); - return (0); - } - - for (;;) { - i = BIO_write(out, &(b[j]), n); - if (i == n) - break; - if (i <= 0) { - ret = 0; - break; - } - j += i; - n -= i; - } - free(b); - return (ret); -} diff --git a/crypto/asn1/a_verify.c b/crypto/asn1/asn1_old_lib.c similarity index 57% rename from crypto/asn1/a_verify.c rename to crypto/asn1/asn1_old_lib.c index 6f0cd10..e41a5ea 100644 --- a/crypto/asn1/a_verify.c +++ b/crypto/asn1/asn1_old_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: a_verify.c,v 1.24 2017/05/02 03:59:44 deraadt Exp $ */ +/* $OpenBSD: asn1_old_lib.c,v 1.3 2022/01/14 07:57:17 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -56,112 +56,156 @@ * [including the GNU Public Licence.] */ -#include - +#include #include #include -#include -#include -#include +#include #include -#include -#include -#include #include "asn1_locl.h" +static void asn1_put_length(unsigned char **pp, int length); + int -ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, - ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey) +ASN1_get_object(const unsigned char **pp, long *plength, int *ptag, + int *pclass, long omax) { - EVP_MD_CTX ctx; - unsigned char *buf_in = NULL; - int ret = -1, inl; + int constructed, indefinite; + uint32_t tag_number, length; + uint8_t tag_class; + CBS cbs; + int ret = 0; - int mdnid, pknid; + *pclass = 0; + *ptag = 0; + *plength = 0; - if (!pkey) { - ASN1error(ERR_R_PASSED_NULL_PARAMETER); - return -1; + CBS_init(&cbs, *pp, omax); + + if (!asn1_get_object_cbs(&cbs, 0, &tag_class, &constructed, &tag_number, + &indefinite, &length)) { + ASN1error(ASN1_R_HEADER_TOO_LONG); + return 0x80; } - if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) - { - ASN1error(ASN1_R_INVALID_BIT_STRING_BITS_LEFT); - return -1; + if (tag_number > INT_MAX) { + ASN1error(ASN1_R_HEADER_TOO_LONG); + return 0x80; } - EVP_MD_CTX_init(&ctx); - - /* Convert signature OID into digest and public key OIDs */ - if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->algorithm), &mdnid, &pknid)) { - ASN1error(ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); - goto err; + /* + * API insanity ahead... in this case we add an error to the stack and + * signal an error by setting the 8th bit in the return value... but we + * still provide all of the decoded data. + */ + if (length > CBS_len(&cbs)) { + ASN1error(ASN1_R_TOO_LONG); + ret = 0x80; } - if (mdnid == NID_undef) { - if (!pkey->ameth || !pkey->ameth->item_verify) { - ASN1error(ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); - goto err; + + *pclass = tag_class << 6; + *ptag = tag_number; + *plength = length; + + *pp = CBS_data(&cbs); + + if (constructed) + ret |= 1 << 5; + if (indefinite) + ret |= 1; + + return ret; +} + +/* class 0 is constructed + * constructed == 2 for indefinite length constructed */ +void +ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, + int xclass) +{ + unsigned char *p = *pp; + int i, ttag; + + i = (constructed) ? V_ASN1_CONSTRUCTED : 0; + i |= (xclass & V_ASN1_PRIVATE); + if (tag < 31) + *(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG); + else { + *(p++) = i | V_ASN1_PRIMITIVE_TAG; + for(i = 0, ttag = tag; ttag > 0; i++) + ttag >>= 7; + ttag = i; + while (i-- > 0) { + p[i] = tag & 0x7f; + if (i != (ttag - 1)) + p[i] |= 0x80; + tag >>= 7; } - ret = pkey->ameth->item_verify(&ctx, it, asn, a, - 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. - */ - if (ret != 2) - goto err; - ret = -1; - } else { - const EVP_MD *type; - type = EVP_get_digestbynid(mdnid); - if (type == NULL) { - ASN1error(ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM); - goto err; + p += ttag; + } + if (constructed == 2) + *(p++) = 0x80; + else + asn1_put_length(&p, length); + *pp = p; +} + +int +ASN1_put_eoc(unsigned char **pp) +{ + unsigned char *p = *pp; + + *p++ = 0; + *p++ = 0; + *pp = p; + return 2; +} + +static void +asn1_put_length(unsigned char **pp, int length) +{ + unsigned char *p = *pp; + + int i, l; + if (length <= 127) + *(p++) = (unsigned char)length; + else { + l = length; + for (i = 0; l > 0; i++) + l >>= 8; + *(p++) = i | 0x80; + l = i; + while (i-- > 0) { + p[i] = length & 0xff; + length >>= 8; } + p += l; + } + *pp = p; +} - /* Check public key OID matches public key type */ - if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id) { - ASN1error(ASN1_R_WRONG_PUBLIC_KEY_TYPE); - goto err; +int +ASN1_object_size(int constructed, int length, int tag) +{ + int ret; + + ret = length; + ret++; + if (tag >= 31) { + while (tag > 0) { + tag >>= 7; + ret++; } - - if (!EVP_DigestVerifyInit(&ctx, NULL, type, NULL, pkey)) { - ASN1error(ERR_R_EVP_LIB); - ret = 0; - goto err; + } + if (constructed == 2) + return ret + 3; + ret++; + if (length > 127) { + while (length > 0) { + length >>= 8; + ret++; } - } - - inl = ASN1_item_i2d(asn, &buf_in, it); - - if (buf_in == NULL) { - ASN1error(ERR_R_MALLOC_FAILURE); - goto err; - } - - if (!EVP_DigestVerifyUpdate(&ctx, buf_in, inl)) { - ASN1error(ERR_R_EVP_LIB); - ret = 0; - goto err; - } - - freezero(buf_in, (unsigned int)inl); - - if (EVP_DigestVerifyFinal(&ctx, signature->data, - (size_t)signature->length) <= 0) { - ASN1error(ERR_R_EVP_LIB); - ret = 0; - goto err; - } - /* we don't need to zero the 'ctx' because we just checked - * public information */ - /* memset(&ctx,0,sizeof(ctx)); */ - ret = 1; - -err: - EVP_MD_CTX_cleanup(&ctx); return (ret); } diff --git a/crypto/asn1/asn1_par.c b/crypto/asn1/asn1_par.c index 1ec9b1a..6c14f27 100644 --- a/crypto/asn1/asn1_par.c +++ b/crypto/asn1/asn1_par.c @@ -1,4 +1,4 @@ -/* $OpenBSD: asn1_par.c,v 1.28 2020/01/09 11:27:21 inoguchi Exp $ */ +/* $OpenBSD: asn1_par.c,v 1.34 2022/02/12 03:07:24 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -80,7 +80,8 @@ asn1_print_info(BIO *bp, int tag, int xclass, int constructed, p="prim: "; if (BIO_write(bp, p, 6) < 6) goto err; - BIO_indent(bp, indent, 128); + if (!BIO_indent(bp, indent, 128)) + goto err; p = str; if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE) @@ -97,7 +98,7 @@ asn1_print_info(BIO *bp, int tag, int xclass, int constructed, if (BIO_printf(bp, "%-18s", p) <= 0) goto err; return (1); -err: + err: return (0); } @@ -232,16 +233,13 @@ asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offset, goto end; } } else if (tag == V_ASN1_BOOLEAN) { - int ii; - - opp = op; - ii = d2i_ASN1_BOOLEAN(NULL, &opp, len + hl); - if (ii < 0) { + if (len == 1 && p < tot) { + BIO_printf(bp, ":%u", p[0]); + } else { if (BIO_write(bp, "Bad boolean\n", 12) <= 0) goto end; } - BIO_printf(bp, ":%d", ii); } else if (tag == V_ASN1_BMPSTRING) { /* do the BMP thang */ } else if (tag == V_ASN1_OCTET_STRING) { @@ -375,7 +373,7 @@ asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offset, } ret = 1; -end: + end: if (o != NULL) ASN1_OBJECT_free(o); ASN1_OCTET_STRING_free(os); @@ -384,25 +382,3 @@ end: *pp = p; return (ret); } - -const char * -ASN1_tag2str(int tag) -{ - static const char * const tag2str[] = { - "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */ - "NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */ - "ENUMERATED", "", "UTF8STRING", "", /* 10-13 */ - "", "", "SEQUENCE", "SET", /* 15-17 */ - "NUMERICSTRING", "PRINTABLESTRING", "T61STRING", /* 18-20 */ - "VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME", /* 21-24 */ - "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", /* 25-27 */ - "UNIVERSALSTRING", "", "BMPSTRING" /* 28-30 */ - }; - - 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_types.c b/crypto/asn1/asn1_types.c new file mode 100644 index 0000000..c8e6b23 --- /dev/null +++ b/crypto/asn1/asn1_types.c @@ -0,0 +1,263 @@ +/* $OpenBSD: asn1_types.c,v 1.1 2021/12/14 17:35:21 jsing Exp $ */ +/* + * Copyright (c) 2021 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +struct asn1_type { + const char *name; + uint32_t bit_value; + int char_width; +}; + +/* + * Universal class tag types - ITU X.680. + */ +static const struct asn1_type asn1_types[31] = { + [0] = { + /* Tag 0 (0x00) - Reserved for use by encoding rules */ + .name = "EOC", + .bit_value = 0, + .char_width = -1, + }, + [1] = { + /* Tag 1 (0x01) - Boolean */ + .name = "BOOLEAN", + .bit_value = 0, + .char_width = -1, + }, + [2] = { + /* Tag 2 (0x02) - Integer */ + .name = "INTEGER", + .bit_value = 0, + .char_width = -1, + }, + [3] = { + /* Tag 3 (0x03) - BitString */ + .name = "BIT STRING", + .bit_value = B_ASN1_BIT_STRING, + .char_width = -1, + }, + [4] = { + /* Tag 4 (0x04) - OctetString */ + .name = "OCTET STRING", + .bit_value = B_ASN1_OCTET_STRING, + .char_width = -1, + }, + [5] = { + /* Tag 5 (0x05) - Null */ + .name = "NULL", + .bit_value = 0, + .char_width = -1, + }, + [6] = { + /* Tag 6 (0x06) - Object Identifier */ + .name = "OBJECT", + .bit_value = 0, + .char_width = -1, + }, + [7] = { + /* Tag 7 (0x07) - Object Descriptor */ + .name = "OBJECT DESCRIPTOR", + .bit_value = B_ASN1_UNKNOWN, + .char_width = -1, + }, + [8] = { + /* Tag 8 (0x08) - External */ + .name = "EXTERNAL", + .bit_value = B_ASN1_UNKNOWN, + .char_width = -1, + }, + [9] = { + /* Tag 9 (0x09) - Real */ + .name = "REAL", + .bit_value = B_ASN1_UNKNOWN, + .char_width = -1, + }, + [10] = { + /* Tag 10 (0x0a) - Enumerated */ + .name = "ENUMERATED", + .bit_value = B_ASN1_UNKNOWN, + .char_width = -1, + }, + [11] = { + /* Tag 11 (0x0b) - Embedded PDV */ + .name = "", + .bit_value = B_ASN1_UNKNOWN, + .char_width = -1, + }, + [12] = { + /* Tag 12 (0x0c) - UTF8String */ + .name = "UTF8STRING", + .bit_value = B_ASN1_UTF8STRING, + .char_width = 0, + }, + [13] = { + /* Tag 13 (0x0d) - Relative Object Identifier */ + .name = "", + .bit_value = B_ASN1_UNKNOWN, + .char_width = -1, + }, + [14] = { + /* Tag 14 (0x0e) - Time */ + .name = "", + .bit_value = B_ASN1_UNKNOWN, + .char_width = -1, + }, + [15] = { + /* Tag 15 (0x0f) - Reserved */ + .name = "", + .bit_value = B_ASN1_UNKNOWN, + .char_width = -1, + }, + [16] = { + /* Tag 16 (0x10)- Sequence */ + .name = "SEQUENCE", + .bit_value = B_ASN1_SEQUENCE, + .char_width = -1, + }, + [17] = { + /* Tag 17 (0x11) - Set */ + .name = "SET", + .bit_value = 0, + .char_width = -1, + }, + [18] = { + /* Tag 18 (0x12) - NumericString */ + .name = "NUMERICSTRING", + .bit_value = B_ASN1_NUMERICSTRING, + .char_width = -1, + }, + [19] = { + /* Tag 19 (0x13) - PrintableString */ + .name = "PRINTABLESTRING", + .bit_value = B_ASN1_PRINTABLESTRING, + .char_width = 1, + }, + [20] = { + /* Tag 20 (0x14) - TeletexString (T61String) */ + .name = "T61STRING", + .bit_value = B_ASN1_T61STRING, + .char_width = 1, + }, + [21] = { + /* Tag 21 (0x15) - VideotexString */ + .name = "VIDEOTEXSTRING", + .bit_value = B_ASN1_VIDEOTEXSTRING, + .char_width = -1, + }, + [22] = { + /* Tag 22 (0x16) - IA5String */ + .name = "IA5STRING", + .bit_value = B_ASN1_IA5STRING, + .char_width = 1, + }, + [23] = { + /* Tag 23 (0x17) - UTCTime */ + .name = "UTCTIME", + .bit_value = B_ASN1_UTCTIME, + .char_width = 1, + }, + [24] = { + /* Tag 24 (0x18) - GeneralizedTime */ + .name = "GENERALIZEDTIME", + .bit_value = B_ASN1_GENERALIZEDTIME, + .char_width = 1, + }, + [25] = { + /* Tag 25 (0x19) - GraphicString */ + .name = "GRAPHICSTRING", + .bit_value = B_ASN1_GRAPHICSTRING, + .char_width = -1, + }, + [26] = { + /* Tag 26 (0x1a) - VisibleString (ISO646String) */ + .name = "VISIBLESTRING", + .bit_value = B_ASN1_ISO64STRING, + .char_width = 1, + }, + [27] = { + /* Tag 27 (0x1b) - GeneralString */ + .name = "GENERALSTRING", + .bit_value = B_ASN1_GENERALSTRING, + .char_width = -1, + }, + [28] = { + /* Tag 28 (0x1c) - UniversalString */ + .name = "UNIVERSALSTRING", + .bit_value = B_ASN1_UNIVERSALSTRING, + .char_width = 4, + }, + [29] = { + /* Tag 29 (0x1d) - Unallocated */ + .name = "", + .bit_value = B_ASN1_UNKNOWN, + .char_width = -1, + }, + [30] = { + /* Tag 30 (0x1e) - BMPString */ + .name = "BMPSTRING", + .bit_value = B_ASN1_BMPSTRING, + .char_width = 2, + }, +}; + +static const struct asn1_type * +asn1_type_by_tag(int tag) +{ + if (tag < 0 || tag > 30) + return NULL; + + return &asn1_types[tag]; +} + +int +asn1_tag2charwidth(int tag) +{ + const struct asn1_type *at; + + if ((at = asn1_type_by_tag(tag)) != NULL) + return at->char_width; + + return -1; +} + +unsigned long +ASN1_tag2bit(int tag) +{ + const struct asn1_type *at; + + if ((at = asn1_type_by_tag(tag)) != NULL) + return (unsigned long)at->bit_value; + + return 0; +} + +const char * +ASN1_tag2str(int tag) +{ + const struct asn1_type *at; + + if (tag == V_ASN1_NEG_INTEGER || tag == V_ASN1_NEG_ENUMERATED) + tag &= ~V_ASN1_NEG; + + if ((at = asn1_type_by_tag(tag)) != NULL) + return at->name; + + return "(unknown)"; +} diff --git a/crypto/asn1/asn_mime.c b/crypto/asn1/asn_mime.c index 6bad111..3150214 100644 --- a/crypto/asn1/asn_mime.c +++ b/crypto/asn1/asn_mime.c @@ -1,4 +1,4 @@ -/* $OpenBSD: asn_mime.c,v 1.27 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: asn_mime.c,v 1.29 2021/12/25 13:17:48 jsing Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project. */ @@ -63,6 +63,7 @@ #include #include "asn1_locl.h" +#include "evp_locl.h" /* Generalised MIME like utilities for streaming ASN1. Although many * have a PKCS7/CMS like flavour others are more general purpose. @@ -267,7 +268,7 @@ asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs) ret = 1; -err: + err: return ret; } @@ -778,7 +779,7 @@ STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio) return headers; -merr: + merr: if (mhdr != NULL) mime_hdr_free(mhdr); sk_MIME_HEADER_pop_free(headers, mime_hdr_free); @@ -866,7 +867,7 @@ mime_hdr_new(char *name, char *value) goto err; } return mhdr; -err: + err: free(tmpname); free(tmpval); return NULL; @@ -901,7 +902,7 @@ mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value) goto err; } return 1; -err: + err: free(tmpname); free(tmpval); return 0; diff --git a/crypto/asn1/asn_moid.c b/crypto/asn1/asn_moid.c index 7bf493e..c672f0a 100644 --- a/crypto/asn1/asn_moid.c +++ b/crypto/asn1/asn_moid.c @@ -1,4 +1,4 @@ -/* $OpenBSD: asn_moid.c,v 1.13 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: asn_moid.c,v 1.14 2022/01/07 11:13:54 tb Exp $ */ /* Written by Stephen Henson (steve@openssl.org) for the OpenSSL * project 2001. */ @@ -65,6 +65,8 @@ #include #include +#include "asn1_locl.h" + /* Simple ASN1 OID module: add all objects in a given section */ static int do_create(char *value, char *name); diff --git a/crypto/asn1/bio_asn1.c b/crypto/asn1/bio_asn1.c index 93bcb33..9017786 100644 --- a/crypto/asn1/bio_asn1.c +++ b/crypto/asn1/bio_asn1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bio_asn1.c,v 1.13 2018/05/01 13:29:09 tb Exp $ */ +/* $OpenBSD: bio_asn1.c,v 1.17 2022/01/14 08:40:57 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project. */ @@ -67,6 +67,8 @@ #include #include +#include "bio_local.h" + /* Must be large enough for biggest tag+length */ #define DEFAULT_ASN1_BUF_SIZE 20 @@ -116,9 +118,8 @@ static int asn1_bio_gets(BIO *h, char *str, int size); static long asn1_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int asn1_bio_new(BIO *h); static int asn1_bio_free(BIO *data); -static long asn1_bio_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); +static long asn1_bio_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); -static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size); static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx, asn1_ps_func *cleanup, asn1_bio_state_t next); static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx, @@ -148,35 +149,23 @@ static int asn1_bio_new(BIO *b) { BIO_ASN1_BUF_CTX *ctx; - ctx = malloc(sizeof(BIO_ASN1_BUF_CTX)); - if (!ctx) + + if ((ctx = calloc(1, sizeof(*ctx))) == NULL) return 0; - if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE)) { + + if ((ctx->buf = malloc(DEFAULT_ASN1_BUF_SIZE)) == NULL) { free(ctx); return 0; } + ctx->bufsize = DEFAULT_ASN1_BUF_SIZE; + ctx->asn1_class = V_ASN1_UNIVERSAL; + ctx->asn1_tag = V_ASN1_OCTET_STRING; + ctx->state = ASN1_STATE_START; + b->init = 1; b->ptr = (char *)ctx; b->flags = 0; - return 1; -} -static int -asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size) -{ - ctx->buf = malloc(size); - if (!ctx->buf) - return 0; - ctx->bufsize = size; - ctx->bufpos = 0; - ctx->buflen = 0; - ctx->copylen = 0; - ctx->asn1_class = V_ASN1_UNIVERSAL; - ctx->asn1_tag = V_ASN1_OCTET_STRING; - ctx->ex_buf = NULL; - ctx->ex_pos = 0; - ctx->ex_len = 0; - ctx->state = ASN1_STATE_START; return 1; } @@ -284,7 +273,7 @@ asn1_bio_write(BIO *b, const char *in , int inl) } -done: + done: BIO_clear_retry_flags(b); BIO_copy_next_retry(b); @@ -357,7 +346,7 @@ asn1_bio_gets(BIO *b, char *str, int size) } static long -asn1_bio_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +asn1_bio_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { if (b->next_bio == NULL) return (0); diff --git a/crypto/asn1/bio_ndef.c b/crypto/asn1/bio_ndef.c index 890b141..88b204e 100644 --- a/crypto/asn1/bio_ndef.c +++ b/crypto/asn1/bio_ndef.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bio_ndef.c,v 1.10 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: bio_ndef.c,v 1.11 2021/12/25 13:17:48 jsing Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project. */ @@ -143,7 +143,7 @@ BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it) return sarg.ndef_bio; -err: + err: BIO_free(asn_bio); free(ndef_aux); return NULL; diff --git a/crypto/asn1/evp_asn1.c b/crypto/asn1/evp_asn1.c deleted file mode 100644 index 4b7ebbb..0000000 --- a/crypto/asn1/evp_asn1.c +++ /dev/null @@ -1,193 +0,0 @@ -/* $OpenBSD: evp_asn1.c,v 1.23 2018/11/09 04:20:27 tb Exp $ */ -/* 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.] - */ - -#include -#include - -#include -#include -#include - -int -ASN1_TYPE_set_octetstring(ASN1_TYPE *a, const unsigned char *data, int len) -{ - ASN1_STRING *os; - - if ((os = ASN1_OCTET_STRING_new()) == NULL) - return (0); - if (!ASN1_STRING_set(os, data, len)) { - ASN1_OCTET_STRING_free(os); - return (0); - } - ASN1_TYPE_set(a, V_ASN1_OCTET_STRING, os); - return (1); -} - -int -ASN1_TYPE_get_octetstring(const ASN1_TYPE *a, unsigned char *data, int max_len) -{ - int ret, num; - unsigned char *p; - - if ((a->type != V_ASN1_OCTET_STRING) || - (a->value.octet_string == NULL)) { - ASN1error(ASN1_R_DATA_IS_WRONG); - return (-1); - } - p = ASN1_STRING_data(a->value.octet_string); - ret = ASN1_STRING_length(a->value.octet_string); - if (ret < max_len) - num = ret; - else - num = max_len; - memcpy(data, p, num); - return (ret); -} - -typedef struct { - ASN1_INTEGER *num; - ASN1_OCTET_STRING *value; -} ASN1_int_octetstring; - -static const ASN1_TEMPLATE ASN1_INT_OCTETSTRING_seq_tt[] = { - { - .offset = offsetof(ASN1_int_octetstring, num), - .field_name = "num", - .item = &ASN1_INTEGER_it, - }, - { - .offset = offsetof(ASN1_int_octetstring, value), - .field_name = "value", - .item = &ASN1_OCTET_STRING_it, - }, -}; - -const ASN1_ITEM ASN1_INT_OCTETSTRING_it = { - .itype = ASN1_ITYPE_SEQUENCE, - .utype = V_ASN1_SEQUENCE, - .templates = ASN1_INT_OCTETSTRING_seq_tt, - .tcount = sizeof(ASN1_INT_OCTETSTRING_seq_tt) / sizeof(ASN1_TEMPLATE), - .size = sizeof(ASN1_int_octetstring), - .sname = "ASN1_INT_OCTETSTRING", -}; - -int -ASN1_TYPE_set_int_octetstring(ASN1_TYPE *at, long num, const unsigned char *data, - int len) -{ - ASN1_int_octetstring *ios; - ASN1_STRING *sp = NULL; - int ret = 0; - - if ((ios = (ASN1_int_octetstring *)ASN1_item_new( - &ASN1_INT_OCTETSTRING_it)) == NULL) - goto err; - if (!ASN1_INTEGER_set(ios->num, num)) - goto err; - if (!ASN1_OCTET_STRING_set(ios->value, data, len)) - goto err; - - if ((sp = ASN1_item_pack(ios, &ASN1_INT_OCTETSTRING_it, NULL)) == NULL) - goto err; - - ASN1_TYPE_set(at, V_ASN1_SEQUENCE, sp); - sp = NULL; - - ret = 1; - - err: - ASN1_item_free((ASN1_VALUE *)ios, &ASN1_INT_OCTETSTRING_it); - ASN1_STRING_free(sp); - - return ret; -} - -int -ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *at, long *num, unsigned char *data, - int max_len) -{ - ASN1_STRING *sp = at->value.sequence; - ASN1_int_octetstring *ios = NULL; - int ret = -1; - int len; - - if (at->type != V_ASN1_SEQUENCE || sp == NULL) - goto err; - - if ((ios = ASN1_item_unpack(sp, &ASN1_INT_OCTETSTRING_it)) == NULL) - goto err; - - if (num != NULL) - *num = ASN1_INTEGER_get(ios->num); - if (data != NULL) { - len = ASN1_STRING_length(ios->value); - if (len > max_len) - len = max_len; - memcpy(data, ASN1_STRING_data(ios->value), len); - } - - ret = ASN1_STRING_length(ios->value); - - err: - ASN1_item_free((ASN1_VALUE *)ios, &ASN1_INT_OCTETSTRING_it); - - if (ret == -1) - ASN1error(ASN1_R_DATA_IS_WRONG); - - return ret; -} diff --git a/crypto/asn1/f_enum.c b/crypto/asn1/f_enum.c deleted file mode 100644 index cc4b7df..0000000 --- a/crypto/asn1/f_enum.c +++ /dev/null @@ -1,198 +0,0 @@ -/* $OpenBSD: f_enum.c,v 1.16 2018/04/25 11:48:21 tb Exp $ */ -/* 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.] - */ - -#include - -#include -#include -#include - -/* Based on a_int.c: equivalent ENUMERATED functions */ - -int -i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a) -{ - int i, n = 0; - static const char h[] = "0123456789ABCDEF"; - char buf[2]; - - if (a == NULL) - return (0); - - if (a->length == 0) { - if (BIO_write(bp, "00", 2) != 2) - goto err; - n = 2; - } else { - for (i = 0; i < a->length; i++) { - if ((i != 0) && (i % 35 == 0)) { - if (BIO_write(bp, "\\\n", 2) != 2) - goto err; - n += 2; - } - buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f]; - buf[1] = h[((unsigned char)a->data[i]) & 0x0f]; - if (BIO_write(bp, buf, 2) != 2) - goto err; - n += 2; - } - } - return (n); - -err: - return (-1); -} - -int -a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size) -{ - int ret = 0; - int i, j,k, m,n, again, bufsize; - unsigned char *s = NULL, *sp; - unsigned char *bufp; - int first = 1; - size_t num = 0, slen = 0; - - bs->type = V_ASN1_ENUMERATED; - - bufsize = BIO_gets(bp, buf, size); - for (;;) { - if (bufsize < 1) - goto err_sl; - i = bufsize; - if (buf[i-1] == '\n') - buf[--i] = '\0'; - if (i == 0) - goto err_sl; - if (buf[i-1] == '\r') - buf[--i] = '\0'; - if (i == 0) - goto err_sl; - again = (buf[i - 1] == '\\'); - - for (j = 0; j < i; j++) { - if (!(((buf[j] >= '0') && (buf[j] <= '9')) || - ((buf[j] >= 'a') && (buf[j] <= 'f')) || - ((buf[j] >= 'A') && (buf[j] <= 'F')))) { - i = j; - break; - } - } - buf[i] = '\0'; - /* We have now cleared all the crap off the end of the - * line */ - if (i < 2) - goto err_sl; - - bufp = (unsigned char *)buf; - if (first) { - first = 0; - if ((bufp[0] == '0') && (buf[1] == '0')) { - bufp += 2; - i -= 2; - } - } - k = 0; - i -= again; - if (i % 2 != 0) { - ASN1error(ASN1_R_ODD_NUMBER_OF_CHARS); - goto err; - } - i /= 2; - if (num + i > slen) { - sp = realloc(s, num + i); - if (sp == NULL) { - ASN1error(ERR_R_MALLOC_FAILURE); - goto err; - } - s = sp; - slen = num + i; - } - for (j = 0; j < i; j++, k += 2) { - for (n = 0; n < 2; n++) { - m = bufp[k + n]; - if ((m >= '0') && (m <= '9')) - m -= '0'; - else if ((m >= 'a') && (m <= 'f')) - m = m - 'a' + 10; - else if ((m >= 'A') && (m <= 'F')) - m = m - 'A' + 10; - else { - ASN1error(ASN1_R_NON_HEX_CHARACTERS); - goto err; - } - s[num + j] <<= 4; - s[num + j] |= m; - } - } - num += i; - if (again) - bufsize = BIO_gets(bp, buf, size); - else - break; - } - bs->length = num; - bs->data = s; - return (1); - -err_sl: - ASN1error(ASN1_R_SHORT_LINE); -err: - free(s); - return (ret); -} diff --git a/crypto/asn1/f_int.c b/crypto/asn1/f_int.c deleted file mode 100644 index d03fafe..0000000 --- a/crypto/asn1/f_int.c +++ /dev/null @@ -1,200 +0,0 @@ -/* $OpenBSD: f_int.c,v 1.20 2018/05/13 13:48:08 jsing Exp $ */ -/* 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.] - */ - -#include - -#include -#include -#include - -int -i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a) -{ - int i, n = 0; - static const char h[] = "0123456789ABCDEF"; - char buf[2]; - - if (a == NULL) - return (0); - - if (a->type & V_ASN1_NEG) { - if (BIO_write(bp, "-", 1) != 1) - goto err; - n = 1; - } - - if (a->length == 0) { - if (BIO_write(bp, "00", 2) != 2) - goto err; - n += 2; - } else { - for (i = 0; i < a->length; i++) { - if ((i != 0) && (i % 35 == 0)) { - if (BIO_write(bp, "\\\n", 2) != 2) - goto err; - n += 2; - } - buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f]; - buf[1] = h[((unsigned char)a->data[i]) & 0x0f]; - if (BIO_write(bp, buf, 2) != 2) - goto err; - n += 2; - } - } - return (n); - -err: - return (-1); -} - -int -a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size) -{ - int ret = 0; - int i, j,k, m,n, again, bufsize; - unsigned char *s = NULL, *sp; - unsigned char *bufp; - int num = 0, slen = 0, first = 1; - - bs->type = V_ASN1_INTEGER; - - bufsize = BIO_gets(bp, buf, size); - for (;;) { - if (bufsize < 1) - goto err_sl; - i = bufsize; - if (buf[i - 1] == '\n') - buf[--i] = '\0'; - if (i == 0) - goto err_sl; - if (buf[i - 1] == '\r') - buf[--i] = '\0'; - if (i == 0) - goto err_sl; - again = (buf[i - 1] == '\\'); - - for (j = 0; j < i; j++) { - if (!(((buf[j] >= '0') && (buf[j] <= '9')) || - ((buf[j] >= 'a') && (buf[j] <= 'f')) || - ((buf[j] >= 'A') && (buf[j] <= 'F')))) { - i = j; - break; - } - } - buf[i] = '\0'; - /* We have now cleared all the crap off the end of the - * line */ - if (i < 2) - goto err_sl; - - bufp = (unsigned char *)buf; - if (first) { - first = 0; - if ((bufp[0] == '0') && (buf[1] == '0')) { - bufp += 2; - i -= 2; - } - } - k = 0; - i -= again; - if (i % 2 != 0) { - ASN1error(ASN1_R_ODD_NUMBER_OF_CHARS); - goto err; - } - i /= 2; - if (num + i > slen) { - if ((sp = recallocarray(s, slen, num + i, 1)) == NULL) { - ASN1error(ERR_R_MALLOC_FAILURE); - goto err; - } - s = sp; - slen = num + i; - } - for (j = 0; j < i; j++, k += 2) { - for (n = 0; n < 2; n++) { - m = bufp[k + n]; - if ((m >= '0') && (m <= '9')) - m -= '0'; - else if ((m >= 'a') && (m <= 'f')) - m = m - 'a' + 10; - else if ((m >= 'A') && (m <= 'F')) - m = m - 'A' + 10; - else { - ASN1error(ASN1_R_NON_HEX_CHARACTERS); - goto err; - } - s[num + j] <<= 4; - s[num + j] |= m; - } - } - num += i; - if (again) - bufsize = BIO_gets(bp, buf, size); - else - break; - } - bs->length = num; - bs->data = s; - return (1); - -err_sl: - ASN1error(ASN1_R_SHORT_LINE); -err: - free(s); - return (ret); -} diff --git a/crypto/asn1/i2d_pr.c b/crypto/asn1/i2d_pr.c deleted file mode 100644 index 0b545ae..0000000 --- a/crypto/asn1/i2d_pr.c +++ /dev/null @@ -1,81 +0,0 @@ -/* $OpenBSD: i2d_pr.c,v 1.11 2017/01/29 17:49:22 beck Exp $ */ -/* 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.] - */ - -#include - -#include -#include -#include - -#include "asn1_locl.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 = i2d_PKCS8_PRIV_KEY_INFO(p8, pp); - PKCS8_PRIV_KEY_INFO_free(p8); - return ret; - } - ASN1error(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 index 9baa849..0000000 --- a/crypto/asn1/i2d_pu.c +++ /dev/null @@ -1,98 +0,0 @@ -/* $OpenBSD: i2d_pu.c,v 1.11 2017/01/29 17:49:22 beck Exp $ */ -/* 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.] - */ - -#include - -#include - -#include -#include -#include -#include - -#ifndef OPENSSL_NO_DSA -#include -#endif -#ifndef OPENSSL_NO_EC -#include -#endif -#ifndef OPENSSL_NO_RSA -#include -#endif - -int -i2d_PublicKey(EVP_PKEY *a, unsigned char **pp) -{ - switch (a->type) { -#ifndef OPENSSL_NO_RSA - case EVP_PKEY_RSA: - return (i2d_RSAPublicKey(a->pkey.rsa, pp)); -#endif -#ifndef OPENSSL_NO_DSA - case EVP_PKEY_DSA: - return (i2d_DSAPublicKey(a->pkey.dsa, pp)); -#endif -#ifndef OPENSSL_NO_EC - case EVP_PKEY_EC: - return (i2o_ECPublicKey(a->pkey.ec, pp)); -#endif - default: - ASN1error(ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); - return (-1); - } -} diff --git a/crypto/asn1/n_pkey.c b/crypto/asn1/n_pkey.c deleted file mode 100644 index 6c70316..0000000 --- a/crypto/asn1/n_pkey.c +++ /dev/null @@ -1,432 +0,0 @@ -/* $OpenBSD: n_pkey.c,v 1.32 2018/08/05 13:35:45 bcook Exp $ */ -/* 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.] - */ - -#include -#include - -#include - -#ifndef OPENSSL_NO_RSA -#include -#include -#include -#include -#include -#include - -#ifndef OPENSSL_NO_RC4 - -typedef struct netscape_pkey_st { - long version; - X509_ALGOR *algor; - ASN1_OCTET_STRING *private_key; -} NETSCAPE_PKEY; - -typedef struct netscape_encrypted_pkey_st { - ASN1_OCTET_STRING *os; - /* This is the same structure as DigestInfo so use it: - * although this isn't really anything to do with - * digests. - */ - X509_SIG *enckey; -} NETSCAPE_ENCRYPTED_PKEY; - - -static const ASN1_AUX NETSCAPE_ENCRYPTED_PKEY_aux = { - .flags = ASN1_AFLG_BROKEN, -}; -static const ASN1_TEMPLATE NETSCAPE_ENCRYPTED_PKEY_seq_tt[] = { - { - .offset = offsetof(NETSCAPE_ENCRYPTED_PKEY, os), - .field_name = "os", - .item = &ASN1_OCTET_STRING_it, - }, - { - .offset = offsetof(NETSCAPE_ENCRYPTED_PKEY, enckey), - .field_name = "enckey", - .item = &X509_SIG_it, - }, -}; - -const ASN1_ITEM NETSCAPE_ENCRYPTED_PKEY_it = { - .itype = ASN1_ITYPE_SEQUENCE, - .utype = V_ASN1_SEQUENCE, - .templates = NETSCAPE_ENCRYPTED_PKEY_seq_tt, - .tcount = sizeof(NETSCAPE_ENCRYPTED_PKEY_seq_tt) / sizeof(ASN1_TEMPLATE), - .funcs = &NETSCAPE_ENCRYPTED_PKEY_aux, - .size = sizeof(NETSCAPE_ENCRYPTED_PKEY), - .sname = "NETSCAPE_ENCRYPTED_PKEY", -}; - -NETSCAPE_ENCRYPTED_PKEY *NETSCAPE_ENCRYPTED_PKEY_new(void); -void NETSCAPE_ENCRYPTED_PKEY_free(NETSCAPE_ENCRYPTED_PKEY *a); -NETSCAPE_ENCRYPTED_PKEY *d2i_NETSCAPE_ENCRYPTED_PKEY(NETSCAPE_ENCRYPTED_PKEY **a, const unsigned char **in, long len); -int i2d_NETSCAPE_ENCRYPTED_PKEY(const NETSCAPE_ENCRYPTED_PKEY *a, unsigned char **out); - -NETSCAPE_ENCRYPTED_PKEY * -d2i_NETSCAPE_ENCRYPTED_PKEY(NETSCAPE_ENCRYPTED_PKEY **a, const unsigned char **in, long len) -{ - return (NETSCAPE_ENCRYPTED_PKEY *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, - &NETSCAPE_ENCRYPTED_PKEY_it); -} - -int -i2d_NETSCAPE_ENCRYPTED_PKEY(const NETSCAPE_ENCRYPTED_PKEY *a, unsigned char **out) -{ - return ASN1_item_i2d((ASN1_VALUE *)a, out, &NETSCAPE_ENCRYPTED_PKEY_it); -} - -NETSCAPE_ENCRYPTED_PKEY * -NETSCAPE_ENCRYPTED_PKEY_new(void) -{ - return (NETSCAPE_ENCRYPTED_PKEY *)ASN1_item_new(&NETSCAPE_ENCRYPTED_PKEY_it); -} - -void -NETSCAPE_ENCRYPTED_PKEY_free(NETSCAPE_ENCRYPTED_PKEY *a) -{ - ASN1_item_free((ASN1_VALUE *)a, &NETSCAPE_ENCRYPTED_PKEY_it); -} - -static const ASN1_TEMPLATE NETSCAPE_PKEY_seq_tt[] = { - { - .offset = offsetof(NETSCAPE_PKEY, version), - .field_name = "version", - .item = &LONG_it, - }, - { - .offset = offsetof(NETSCAPE_PKEY, algor), - .field_name = "algor", - .item = &X509_ALGOR_it, - }, - { - .offset = offsetof(NETSCAPE_PKEY, private_key), - .field_name = "private_key", - .item = &ASN1_OCTET_STRING_it, - }, -}; - -const ASN1_ITEM NETSCAPE_PKEY_it = { - .itype = ASN1_ITYPE_SEQUENCE, - .utype = V_ASN1_SEQUENCE, - .templates = NETSCAPE_PKEY_seq_tt, - .tcount = sizeof(NETSCAPE_PKEY_seq_tt) / sizeof(ASN1_TEMPLATE), - .size = sizeof(NETSCAPE_PKEY), - .sname = "NETSCAPE_PKEY", -}; - -NETSCAPE_PKEY *NETSCAPE_PKEY_new(void); -void NETSCAPE_PKEY_free(NETSCAPE_PKEY *a); -NETSCAPE_PKEY *d2i_NETSCAPE_PKEY(NETSCAPE_PKEY **a, const unsigned char **in, long len); -int i2d_NETSCAPE_PKEY(const NETSCAPE_PKEY *a, unsigned char **out); - -NETSCAPE_PKEY * -d2i_NETSCAPE_PKEY(NETSCAPE_PKEY **a, const unsigned char **in, long len) -{ - return (NETSCAPE_PKEY *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, - &NETSCAPE_PKEY_it); -} - -int -i2d_NETSCAPE_PKEY(const NETSCAPE_PKEY *a, unsigned char **out) -{ - return ASN1_item_i2d((ASN1_VALUE *)a, out, &NETSCAPE_PKEY_it); -} - -NETSCAPE_PKEY * -NETSCAPE_PKEY_new(void) -{ - return (NETSCAPE_PKEY *)ASN1_item_new(&NETSCAPE_PKEY_it); -} - -void -NETSCAPE_PKEY_free(NETSCAPE_PKEY *a) -{ - ASN1_item_free((ASN1_VALUE *)a, &NETSCAPE_PKEY_it); -} - -static RSA *d2i_RSA_NET_2(RSA **a, ASN1_OCTET_STRING *os, - int (*cb)(char *buf, int len, const char *prompt, int verify), int sgckey); - -int -i2d_Netscape_RSA(const RSA *a, unsigned char **pp, - int (*cb)(char *buf, int len, const char *prompt, int verify)) -{ - return i2d_RSA_NET(a, pp, cb, 0); -} - -int -i2d_RSA_NET(const RSA *a, unsigned char **pp, - int (*cb)(char *buf, int len, const char *prompt, int verify), int sgckey) -{ - int i, j, ret = 0; - int rsalen, pkeylen, olen; - NETSCAPE_PKEY *pkey = NULL; - NETSCAPE_ENCRYPTED_PKEY *enckey = NULL; - unsigned char buf[256], *zz; - unsigned char key[EVP_MAX_KEY_LENGTH]; - EVP_CIPHER_CTX ctx; - EVP_CIPHER_CTX_init(&ctx); - - if (a == NULL) - return (0); - - if ((pkey = NETSCAPE_PKEY_new()) == NULL) - goto err; - if ((enckey = NETSCAPE_ENCRYPTED_PKEY_new()) == NULL) - goto err; - pkey->version = 0; - - pkey->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption); - if ((pkey->algor->parameter = ASN1_TYPE_new()) == NULL) - goto err; - pkey->algor->parameter->type = V_ASN1_NULL; - - rsalen = i2d_RSAPrivateKey(a, NULL); - - /* Fake some octet strings just for the initial length - * calculation. - */ - pkey->private_key->length = rsalen; - pkeylen = i2d_NETSCAPE_PKEY(pkey, NULL); - enckey->enckey->digest->length = pkeylen; - enckey->os->length = 11; /* "private-key" */ - enckey->enckey->algor->algorithm = OBJ_nid2obj(NID_rc4); - if ((enckey->enckey->algor->parameter = ASN1_TYPE_new()) == NULL) - goto err; - enckey->enckey->algor->parameter->type = V_ASN1_NULL; - - if (pp == NULL) { - olen = i2d_NETSCAPE_ENCRYPTED_PKEY(enckey, NULL); - NETSCAPE_PKEY_free(pkey); - NETSCAPE_ENCRYPTED_PKEY_free(enckey); - return olen; - } - - /* Since its RC4 encrypted length is actual length */ - if ((zz = malloc(rsalen)) == NULL) { - ASN1error(ERR_R_MALLOC_FAILURE); - goto err; - } - - pkey->private_key->data = zz; - /* Write out private key encoding */ - i2d_RSAPrivateKey(a, &zz); - - if ((zz = malloc(pkeylen)) == NULL) { - ASN1error(ERR_R_MALLOC_FAILURE); - goto err; - } - - enckey->enckey->digest->data = zz; - if (!ASN1_STRING_set(enckey->os, "private-key", -1)) { - ASN1error(ERR_R_MALLOC_FAILURE); - goto err; - } - i2d_NETSCAPE_PKEY(pkey, &zz); - - /* Wipe the private key encoding */ - explicit_bzero(pkey->private_key->data, rsalen); - - if (cb == NULL) - cb = EVP_read_pw_string; - i = cb((char *)buf, sizeof(buf), "Enter Private Key password:", 1); - if (i != 0) { - ASN1error(ASN1_R_BAD_PASSWORD_READ); - goto err; - } - i = strlen((char *)buf); - /* If the key is used for SGC the algorithm is modified a little. */ - if (sgckey) { - if (!EVP_Digest(buf, i, buf, NULL, EVP_md5(), NULL)) - goto err; - memcpy(buf + 16, "SGCKEYSALT", 10); - i = 26; - } - - if (!EVP_BytesToKey(EVP_rc4(), EVP_md5(), NULL, buf, i,1, key, NULL)) - goto err; - explicit_bzero(buf, sizeof(buf)); - - /* Encrypt private key in place */ - zz = enckey->enckey->digest->data; - if (!EVP_EncryptInit_ex(&ctx, EVP_rc4(), NULL, key, NULL)) - goto err; - if (!EVP_EncryptUpdate(&ctx, zz, &i, zz, pkeylen)) - goto err; - if (!EVP_EncryptFinal_ex(&ctx, zz + i, &j)) - goto err; - - ret = i2d_NETSCAPE_ENCRYPTED_PKEY(enckey, pp); -err: - EVP_CIPHER_CTX_cleanup(&ctx); - NETSCAPE_ENCRYPTED_PKEY_free(enckey); - NETSCAPE_PKEY_free(pkey); - return (ret); -} - - -RSA * -d2i_Netscape_RSA(RSA **a, const unsigned char **pp, long length, - int (*cb)(char *buf, int len, const char *prompt, int verify)) -{ - return d2i_RSA_NET(a, pp, length, cb, 0); -} - -RSA * -d2i_RSA_NET(RSA **a, const unsigned char **pp, long length, - int (*cb)(char *buf, int len, const char *prompt, int verify), int sgckey) -{ - RSA *ret = NULL; - const unsigned char *p; - NETSCAPE_ENCRYPTED_PKEY *enckey = NULL; - - p = *pp; - - enckey = d2i_NETSCAPE_ENCRYPTED_PKEY(NULL, &p, length); - if (!enckey) { - ASN1error(ASN1_R_DECODING_ERROR); - return NULL; - } - - /* XXX 11 == strlen("private-key") */ - if (enckey->os->length != 11 || - memcmp("private-key", enckey->os->data, 11) != 0) { - ASN1error(ASN1_R_PRIVATE_KEY_HEADER_MISSING); - goto err; - } - if (OBJ_obj2nid(enckey->enckey->algor->algorithm) != NID_rc4) { - ASN1error(ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM); - goto err; - } - if (cb == NULL) - cb = EVP_read_pw_string; - if ((ret = d2i_RSA_NET_2(a, enckey->enckey->digest, cb, - sgckey)) == NULL) - goto err; - - *pp = p; - -err: - NETSCAPE_ENCRYPTED_PKEY_free(enckey); - return ret; - -} - -static RSA * -d2i_RSA_NET_2(RSA **a, ASN1_OCTET_STRING *os, - int (*cb)(char *buf, int len, const char *prompt, int verify), int sgckey) -{ - NETSCAPE_PKEY *pkey = NULL; - RSA *ret = NULL; - int i, j; - unsigned char buf[256]; - const unsigned char *zz; - unsigned char key[EVP_MAX_KEY_LENGTH]; - EVP_CIPHER_CTX ctx; - EVP_CIPHER_CTX_init(&ctx); - - i=cb((char *)buf, sizeof(buf), "Enter Private Key password:",0); - if (i != 0) { - ASN1error(ASN1_R_BAD_PASSWORD_READ); - goto err; - } - - i = strlen((char *)buf); - if (sgckey){ - if (!EVP_Digest(buf, i, buf, NULL, EVP_md5(), NULL)) - goto err; - memcpy(buf + 16, "SGCKEYSALT", 10); - i = 26; - } - - if (!EVP_BytesToKey(EVP_rc4(), EVP_md5(), NULL, buf, i,1, key, NULL)) - goto err; - explicit_bzero(buf, sizeof(buf)); - - if (!EVP_DecryptInit_ex(&ctx, EVP_rc4(), NULL, key, NULL)) - goto err; - if (!EVP_DecryptUpdate(&ctx, os->data, &i, os->data, os->length)) - goto err; - if (!EVP_DecryptFinal_ex(&ctx, &(os->data[i]), &j)) - goto err; - os->length = i + j; - - zz = os->data; - - if ((pkey = d2i_NETSCAPE_PKEY(NULL, &zz, os->length)) == NULL) { - ASN1error(ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY); - goto err; - } - - zz = pkey->private_key->data; - if ((ret = d2i_RSAPrivateKey(a, &zz, - pkey->private_key->length)) == NULL) { - ASN1error(ASN1_R_UNABLE_TO_DECODE_RSA_KEY); - goto err; - } - -err: - EVP_CIPHER_CTX_cleanup(&ctx); - NETSCAPE_PKEY_free(pkey); - return (ret); -} - -#endif /* OPENSSL_NO_RC4 */ - -#endif diff --git a/crypto/asn1/p5_pbe.c b/crypto/asn1/p5_pbe.c index 8fd416a..a150b20 100644 --- a/crypto/asn1/p5_pbe.c +++ b/crypto/asn1/p5_pbe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: p5_pbe.c,v 1.22 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: p5_pbe.c,v 1.23 2021/12/25 13:17:48 jsing Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -159,7 +159,7 @@ PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter, if (X509_ALGOR_set0(algor, OBJ_nid2obj(alg), V_ASN1_SEQUENCE, pbe_str)) return 1; -err: + err: if (pbe != NULL) PBEPARAM_free(pbe); ASN1_STRING_free(pbe_str); diff --git a/crypto/asn1/p5_pbev2.c b/crypto/asn1/p5_pbev2.c index 0105c59..d88a4df 100644 --- a/crypto/asn1/p5_pbev2.c +++ b/crypto/asn1/p5_pbev2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: p5_pbev2.c,v 1.25 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: p5_pbev2.c,v 1.27 2021/12/25 13:17:48 jsing Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999-2004. */ @@ -64,6 +64,8 @@ #include #include +#include "evp_locl.h" + /* PKCS#5 v2.0 password based encryption structures */ static const ASN1_TEMPLATE PBE2PARAM_seq_tt[] = { @@ -272,10 +274,10 @@ PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, unsigned char *salt, return ret; -merr: + merr: ASN1error(ERR_R_MALLOC_FAILURE); -err: + err: PBE2PARAM_free(pbe2); /* Note 'scheme' is freed as part of pbe2 */ X509_ALGOR_free(kalg); @@ -364,7 +366,7 @@ PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen, int prf_nid, PBKDF2PARAM_free(kdf); return keyfunc; -merr: + merr: ASN1error(ERR_R_MALLOC_FAILURE); PBKDF2PARAM_free(kdf); X509_ALGOR_free(keyfunc); diff --git a/crypto/asn1/p8_pkey.c b/crypto/asn1/p8_pkey.c index d2f8e6b..18659a6 100644 --- a/crypto/asn1/p8_pkey.c +++ b/crypto/asn1/p8_pkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: p8_pkey.c,v 1.19 2018/08/24 20:17:33 tb Exp $ */ +/* $OpenBSD: p8_pkey.c,v 1.20 2021/11/01 20:53:08 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -62,6 +62,8 @@ #include #include +#include "x509_lcl.h" + /* Minor tweak to operation: zero private key data */ static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg) diff --git a/crypto/asn1/t_crl.c b/crypto/asn1/t_crl.c index 057b8fe..3ded015 100644 --- a/crypto/asn1/t_crl.c +++ b/crypto/asn1/t_crl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: t_crl.c,v 1.18 2019/05/12 15:56:31 tb Exp $ */ +/* $OpenBSD: t_crl.c,v 1.20 2021/12/25 13:17:48 jsing Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -66,6 +66,8 @@ #include #include +#include "x509_lcl.h" + int X509_CRL_print_fp(FILE *fp, X509_CRL *x) { @@ -138,6 +140,6 @@ X509_CRL_print(BIO *out, X509_CRL *x) return 1; -err: + err: return 0; } diff --git a/crypto/asn1/t_pkey.c b/crypto/asn1/t_pkey.c index b3f7d08..a307381 100644 --- a/crypto/asn1/t_pkey.c +++ b/crypto/asn1/t_pkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: t_pkey.c,v 1.16 2014/07/11 08:44:47 jsing Exp $ */ +/* $OpenBSD: t_pkey.c,v 1.17 2021/12/04 16:08:32 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -62,6 +62,8 @@ #include #include +#include "bn_lcl.h" + int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num, unsigned char *buf, int off) diff --git a/crypto/asn1/t_req.c b/crypto/asn1/t_req.c index a9b14fe..cc9da46 100644 --- a/crypto/asn1/t_req.c +++ b/crypto/asn1/t_req.c @@ -1,4 +1,4 @@ -/* $OpenBSD: t_req.c,v 1.19 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: t_req.c,v 1.21 2021/12/25 13:17:48 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -74,6 +74,8 @@ #include #endif +#include "x509_lcl.h" + int X509_REQ_print_fp(FILE *fp, X509_REQ *x) { @@ -192,7 +194,7 @@ X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags, ii = 0; count = sk_ASN1_TYPE_num( a->value.set); -get_next: + get_next: at = sk_ASN1_TYPE_value( a->value.set, ii); type = at->type; @@ -255,7 +257,7 @@ get_next: return (1); -err: + err: X509error(ERR_R_BUF_LIB); return (0); } diff --git a/crypto/asn1/t_spki.c b/crypto/asn1/t_spki.c index 7f1ed12..56c0956 100644 --- a/crypto/asn1/t_spki.c +++ b/crypto/asn1/t_spki.c @@ -1,4 +1,4 @@ -/* $OpenBSD: t_spki.c,v 1.12 2021/08/24 15:23:03 tb Exp $ */ +/* $OpenBSD: t_spki.c,v 1.13 2021/11/01 20:53:08 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -71,6 +71,8 @@ #include #endif +#include "x509_lcl.h" + /* Print out an SPKI */ int diff --git a/crypto/asn1/t_x509.c b/crypto/asn1/t_x509.c index 42b00a7..563edac 100644 --- a/crypto/asn1/t_x509.c +++ b/crypto/asn1/t_x509.c @@ -1,4 +1,4 @@ -/* $OpenBSD: t_x509.c,v 1.34 2021/07/26 16:54:20 tb Exp $ */ +/* $OpenBSD: t_x509.c,v 1.37 2021/12/25 13:17:48 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -78,6 +78,7 @@ #endif #include "asn1_locl.h" +#include "x509_lcl.h" int X509_print_fp(FILE *fp, X509 *x) @@ -243,7 +244,7 @@ X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, unsigned long cflag) } ret = 1; -err: + err: free(m); return (ret); } @@ -294,7 +295,7 @@ X509_ocspid_print(BIO *bp, X509 *x) return (1); -err: + err: free(der); return (0); } @@ -350,36 +351,6 @@ X509_signature_print(BIO *bp, const X509_ALGOR *sigalg, const ASN1_STRING *sig) return 1; } -int -ASN1_STRING_print(BIO *bp, const ASN1_STRING *v) -{ - int i, n; - char buf[80]; - const char *p; - - if (v == NULL) - return (0); - n = 0; - p = (const char *)v->data; - for (i = 0; i < v->length; i++) { - if ((p[i] > '~') || ((p[i] < ' ') && - (p[i] != '\n') && (p[i] != '\r'))) - buf[n] = '.'; - else - buf[n] = p[i]; - n++; - if (n >= 80) { - if (BIO_write(bp, buf, n) <= 0) - return (0); - n = 0; - } - } - if (n > 0) - if (BIO_write(bp, buf, n) <= 0) - return (0); - return (1); -} - int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm) { @@ -445,7 +416,7 @@ ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm) else return (1); -err: + err: BIO_write(bp, "Bad time value", 14); return (0); } @@ -488,7 +459,7 @@ ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm) else return (1); -err: + err: BIO_write(bp, "Bad time value", 14); return (0); } @@ -534,7 +505,7 @@ X509_NAME_print(BIO *bp, const X509_NAME *name, int obase) ret = 1; if (0) { -err: + err: X509error(ERR_R_BUF_LIB); } free(b); diff --git a/crypto/asn1/t_x509a.c b/crypto/asn1/t_x509a.c index b0346fa..6745318 100644 --- a/crypto/asn1/t_x509a.c +++ b/crypto/asn1/t_x509a.c @@ -1,4 +1,4 @@ -/* $OpenBSD: t_x509a.c,v 1.9 2021/07/10 17:45:16 schwarze Exp $ */ +/* $OpenBSD: t_x509a.c,v 1.10 2021/11/01 20:53:08 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -62,8 +62,9 @@ #include #include -/* X509_CERT_AUX and string set routines - */ +#include "x509_lcl.h" + +/* X509_CERT_AUX and string set routines */ int X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent) diff --git a/crypto/asn1/tasn_dec.c b/crypto/asn1/tasn_dec.c index 4b08e90..d475c99 100644 --- a/crypto/asn1/tasn_dec.c +++ b/crypto/asn1/tasn_dec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tasn_dec.c,v 1.38 2020/12/08 15:06:42 tb Exp $ */ +/* $OpenBSD: tasn_dec.c,v 1.49 2022/03/13 14:58:14 jsing Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ @@ -56,14 +56,18 @@ * */ - +#include #include #include + #include #include -#include #include #include +#include + +#include "asn1_locl.h" +#include "bytestring.h" /* Constructed types with a recursive definition (such as can be found in PKCS7) * could eventually exceed the stack given malicious input with excessive @@ -74,15 +78,16 @@ static int asn1_check_eoc(const unsigned char **in, long len); static int asn1_find_end(const unsigned char **in, long len, char inf); -static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, +static int asn1_collect(CBB *cbb, const unsigned char **in, long len, char inf, int tag, int aclass, int depth); -static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen); - static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *inf, char *cst, const unsigned char **in, long len, int exptag, int expclass, char opt, ASN1_TLC *ctx); +static 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, + int depth); 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); static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, @@ -90,68 +95,44 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx); +static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *content, int len, + int utype, const ASN1_ITEM *it); -/* Table to convert tags to bit values, used for MSTRING type */ -static const unsigned long tag2bit[32] = { - 0, 0, 0, B_ASN1_BIT_STRING, /* tags 0 - 3 */ - B_ASN1_OCTET_STRING, 0, 0, B_ASN1_UNKNOWN,/* tags 4- 7 */ - B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN,/* tags 8-11 */ - B_ASN1_UTF8STRING,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,/* tags 12-15 */ - B_ASN1_SEQUENCE,0,B_ASN1_NUMERICSTRING,B_ASN1_PRINTABLESTRING, /* tags 16-19 */ - B_ASN1_T61STRING,B_ASN1_VIDEOTEXSTRING,B_ASN1_IA5STRING, /* tags 20-22 */ - B_ASN1_UTCTIME, B_ASN1_GENERALIZEDTIME, /* tags 23-24 */ - B_ASN1_GRAPHICSTRING,B_ASN1_ISO64STRING,B_ASN1_GENERALSTRING, /* tags 25-27 */ - B_ASN1_UNIVERSALSTRING,B_ASN1_UNKNOWN,B_ASN1_BMPSTRING,B_ASN1_UNKNOWN, /* tags 28-31 */ -}; - -unsigned long -ASN1_tag2bit(int tag) +static void +asn1_tlc_invalidate(ASN1_TLC *ctx) { - if ((tag < 0) || (tag > 30)) - return 0; - return tag2bit[tag]; + if (ctx != NULL) + ctx->valid = 0; } -/* Macro to initialize and invalidate the cache */ - -#define asn1_tlc_clear(c) if (c) (c)->valid = 0 -/* Version to avoid compiler warning about 'c' always non-NULL */ -#define asn1_tlc_clear_nc(c) (c)->valid = 0 - -/* Decode an ASN1 item, this currently behaves just - * like a standard 'd2i' function. 'in' points to - * a buffer to read the data from, in future we will - * have more advanced versions that can input data - * a piece at a time and 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) { - ASN1_TLC c; ASN1_VALUE *ptmpval = NULL; + ASN1_TLC ctx; - if (!pval) + asn1_tlc_invalidate(&ctx); + + if (pval == NULL) pval = &ptmpval; - asn1_tlc_clear_nc(&c); - if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0) - return *pval; - return NULL; + if (asn1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &ctx, 0) <= 0) + return NULL; + + return *pval; } int ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_TEMPLATE *tt) { - ASN1_TLC c; + ASN1_TLC ctx; - asn1_tlc_clear_nc(&c); - return asn1_template_ex_d2i(pval, in, len, tt, 0, &c, 0); + asn1_tlc_invalidate(&ctx); + + return asn1_template_ex_d2i(pval, in, len, tt, 0, &ctx, 0); } - /* Decode an item, taking care of IMPLICIT tagging, if any. * If 'opt' set and tag mismatch return -1 to handle OPTIONAL */ @@ -466,9 +447,9 @@ asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, return 0; } -auxerr: + auxerr: ASN1error(ASN1_R_AUX_ERROR); -err: + err: if (combine == 0) ASN1_item_ex_free(pval, it); if (errtt) @@ -555,7 +536,7 @@ asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, *in = p; return 1; -err: + err: ASN1_template_free(val, tt); return 0; } @@ -672,7 +653,7 @@ asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, *in = p; return 1; -err: + err: ASN1_template_free(val, tt); return 0; } @@ -683,15 +664,15 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, { int ret = 0, utype; long plen; - char cst, inf, free_cont = 0; + char cst, inf; const unsigned char *p; - BUF_MEM buf; - const unsigned char *cont = NULL; + const unsigned char *content = NULL; + uint8_t *data = NULL; + size_t data_len = 0; + CBB cbb; long len; - buf.length = 0; - buf.max = 0; - buf.data = NULL; + memset(&cbb, 0, sizeof(cbb)); if (!pval) { ASN1error(ASN1_R_ILLEGAL_NULL); @@ -746,69 +727,68 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, * when we have a exact match wont work */ if (utype == V_ASN1_OTHER) { - asn1_tlc_clear(ctx); - } - /* SEQUENCE and SET must be constructed */ - else if (!cst) { + asn1_tlc_invalidate(ctx); + } else if (!cst) { + /* SEQUENCE and SET must be constructed */ ASN1error(ASN1_R_TYPE_NOT_CONSTRUCTED); return 0; } - cont = *in; + content = *in; /* If indefinite length constructed find the real end */ if (inf) { if (!asn1_find_end(&p, plen, inf)) goto err; - len = p - cont; + len = p - content; } else { - len = p - cont + plen; + len = p - content + plen; p += plen; - buf.data = NULL; } } else if (cst) { - /* Should really check the internal tags are correct but + /* + * Should really check the internal tags are correct but * some things may get this wrong. The relevant specs * say that constructed string types should be OCTET STRINGs * internally irrespective of the type. So instead just check * for UNIVERSAL class and ignore the tag. */ - if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0)) { - free_cont = 1; + if (!CBB_init(&cbb, 0)) goto err; - } - len = buf.length; - /* Append a final null to string */ - if (!BUF_MEM_grow_clean(&buf, len + 1)) { - ASN1error(ERR_R_MALLOC_FAILURE); - return 0; - } - buf.data[len] = 0; - cont = (const unsigned char *)buf.data; - free_cont = 1; + if (!asn1_collect(&cbb, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0)) + goto err; + if (!CBB_finish(&cbb, &data, &data_len)) + goto err; + + if (data_len > LONG_MAX) + goto err; + + content = data; + len = data_len; } else { - cont = p; + content = p; len = plen; p += plen; } /* We now have content length and type: translate into a structure */ - if (!asn1_ex_c2i(pval, cont, len, utype, &free_cont, it)) + if (!asn1_ex_c2i(pval, content, len, utype, it)) goto err; *in = p; ret = 1; -err: - if (free_cont && buf.data) - free(buf.data); + err: + CBB_cleanup(&cbb); + freezero(data, data_len); + return ret; } /* Translate ASN1 content octets into a structure */ -int -asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, - char *free_cont, const ASN1_ITEM *it) +static int +asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *content, int len, int utype, + const ASN1_ITEM *it) { ASN1_VALUE **opval = NULL; ASN1_STRING *stmp; @@ -818,10 +798,11 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, if (it->funcs != NULL) { const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; + char free_content = 0; if (pf->prim_c2i == NULL) return 0; - return pf->prim_c2i(pval, cont, len, utype, free_cont, it); + return pf->prim_c2i(pval, content, len, utype, &free_content, it); } /* If ANY type clear type and set pointer to internal value */ @@ -841,7 +822,7 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, } switch (utype) { case V_ASN1_OBJECT: - if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len)) + if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &content, len)) goto err; break; @@ -860,19 +841,19 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, } else { ASN1_BOOLEAN *tbool; tbool = (ASN1_BOOLEAN *)pval; - *tbool = *cont; + *tbool = *content; } break; case V_ASN1_BIT_STRING: - if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len)) + if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &content, len)) goto err; break; case V_ASN1_INTEGER: case V_ASN1_ENUMERATED: tint = (ASN1_INTEGER **)pval; - if (!c2i_ASN1_INTEGER(tint, &cont, len)) + if (!c2i_ASN1_INTEGER(tint, &content, len)) goto err; /* Fixup type to match the expected form */ (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG); @@ -904,10 +885,9 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, ASN1error(ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH); goto err; } - /* All based on ASN1_STRING and handled the same */ - if (!*pval) { - stmp = ASN1_STRING_type_new(utype); - if (!stmp) { + /* All based on ASN1_STRING and handled the same way. */ + if (*pval == NULL) { + if ((stmp = ASN1_STRING_type_new(utype)) == NULL) { ASN1error(ERR_R_MALLOC_FAILURE); goto err; } @@ -916,19 +896,10 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, stmp = (ASN1_STRING *)*pval; stmp->type = utype; } - /* If we've already allocated a buffer use it */ - if (*free_cont) { - free(stmp->data); - stmp->data = (unsigned char *)cont; /* UGLY CAST! RL */ - stmp->length = len; - *free_cont = 0; - } else { - if (!ASN1_STRING_set(stmp, cont, len)) { - ASN1error(ERR_R_MALLOC_FAILURE); - ASN1_STRING_free(stmp); - *pval = NULL; - goto err; - } + if (!ASN1_STRING_set(stmp, content, len)) { + ASN1_STRING_free(stmp); + *pval = NULL; + goto err; } break; } @@ -938,7 +909,7 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, ret = 1; -err: + err: if (!ret) { ASN1_TYPE_free(typ); if (opval) @@ -947,7 +918,6 @@ err: return ret; } - /* This function finds the end of an ASN1 structure when passed its maximum * length, whether it is indefinite length and a pointer to the content. * This is more efficient than calling asn1_collect because it does not @@ -1016,21 +986,21 @@ asn1_find_end(const unsigned char **in, long len, char inf) #endif static int -asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, char inf, +asn1_collect(CBB *cbb, const unsigned char **in, long len, char inf, int tag, int aclass, int depth) { const unsigned char *p, *q; long plen; char cst, ininf; + if (depth > ASN1_MAX_STRING_NEST) { + ASN1error(ASN1_R_NESTED_ASN1_STRING); + return 0; + } + p = *in; inf &= 1; - /* If no buffer and not indefinite length constructed just pass over - * the encoded data */ - if (!buf && !inf) { - *in += len; - return 1; - } + while (len > 0) { q = p; /* Check for EOC */ @@ -1053,15 +1023,14 @@ asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, char inf, /* If indefinite length constructed update max length */ if (cst) { - if (depth >= ASN1_MAX_STRING_NEST) { - ASN1error(ASN1_R_NESTED_ASN1_STRING); - return 0; - } - if (!asn1_collect(buf, &p, plen, ininf, tag, aclass, + if (!asn1_collect(cbb, &p, plen, ininf, tag, aclass, depth + 1)) return 0; - } else if (plen && !collect_data(buf, &p, plen)) - return 0; + } else if (plen > 0) { + if (!CBB_add_bytes(cbb, p, plen)) + return 0; + p += plen; + } len -= p - q; } if (inf) { @@ -1072,22 +1041,6 @@ asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, char inf, return 1; } -static int -collect_data(BUF_MEM *buf, const unsigned char **p, long plen) -{ - int len; - if (buf) { - len = buf->length; - if (!BUF_MEM_grow_clean(buf, len + plen)) { - ASN1error(ERR_R_MALLOC_FAILURE); - return 0; - } - memcpy(buf->data + len, *p, plen); - } - *p += plen; - return 1; -} - /* Check for ASN1 EOC and swallow it if found */ static int @@ -1145,7 +1098,7 @@ asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *inf, */ if (!(i & 0x81) && ((plen + ctx->hdrlen) > len)) { ASN1error(ASN1_R_TOO_LONG); - asn1_tlc_clear(ctx); + asn1_tlc_invalidate(ctx); return 0; } } @@ -1153,7 +1106,7 @@ asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *inf, if (i & 0x80) { ASN1error(ASN1_R_BAD_OBJECT_HEADER); - asn1_tlc_clear(ctx); + asn1_tlc_invalidate(ctx); return 0; } if (exptag >= 0) { @@ -1163,13 +1116,13 @@ asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *inf, */ if (opt) return -1; - asn1_tlc_clear(ctx); + asn1_tlc_invalidate(ctx); ASN1error(ASN1_R_WRONG_TAG); return 0; } /* We have a tag and class match: * assume we are going to do something with it */ - asn1_tlc_clear(ctx); + asn1_tlc_invalidate(ctx); } if (i & 1) diff --git a/crypto/asn1/tasn_enc.c b/crypto/asn1/tasn_enc.c index 5d95f03..ee2320f 100644 --- a/crypto/asn1/tasn_enc.c +++ b/crypto/asn1/tasn_enc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tasn_enc.c,v 1.23 2020/12/08 15:06:42 tb Exp $ */ +/* $OpenBSD: tasn_enc.c,v 1.24 2022/01/07 11:13:54 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ @@ -64,6 +64,8 @@ #include #include +#include "asn1_locl.h" + static int asn1_i2d_ex_primitive(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, diff --git a/crypto/asn1/tasn_fre.c b/crypto/asn1/tasn_fre.c index b621af3..64d3856 100644 --- a/crypto/asn1/tasn_fre.c +++ b/crypto/asn1/tasn_fre.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tasn_fre.c,v 1.17 2019/04/01 15:48:04 jsing Exp $ */ +/* $OpenBSD: tasn_fre.c,v 1.18 2022/01/07 12:24:17 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ @@ -62,6 +62,8 @@ #include #include +#include "asn1_locl.h" + static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine); diff --git a/crypto/asn1/tasn_new.c b/crypto/asn1/tasn_new.c index 7c9bb98..1f17f17 100644 --- a/crypto/asn1/tasn_new.c +++ b/crypto/asn1/tasn_new.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tasn_new.c,v 1.18 2019/04/01 15:48:04 jsing Exp $ */ +/* $OpenBSD: tasn_new.c,v 1.21 2022/01/07 12:24:17 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ @@ -64,6 +64,8 @@ #include #include +#include "asn1_locl.h" + static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine); static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); @@ -103,10 +105,6 @@ asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine) if (!combine) *pval = NULL; -#ifdef CRYPTO_MDEBUG - if (it->sname) - CRYPTO_push_info(it->sname); -#endif switch (it->itype) { case ASN1_ITYPE_EXTERN: @@ -136,10 +134,6 @@ asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine) if (!i) goto auxerr; if (i == 2) { -#ifdef CRYPTO_MDEBUG - if (it->sname) - CRYPTO_pop_info(); -#endif return 1; } } @@ -160,10 +154,6 @@ asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine) if (!i) goto auxerr; if (i == 2) { -#ifdef CRYPTO_MDEBUG - if (it->sname) - CRYPTO_pop_info(); -#endif return 1; } } @@ -183,27 +173,15 @@ asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine) goto auxerr; break; } -#ifdef CRYPTO_MDEBUG - if (it->sname) - CRYPTO_pop_info(); -#endif return 1; -memerr: + memerr: ASN1error(ERR_R_MALLOC_FAILURE); -#ifdef CRYPTO_MDEBUG - if (it->sname) - CRYPTO_pop_info(); -#endif return 0; -auxerr: + auxerr: ASN1error(ASN1_R_AUX_ERROR); ASN1_item_ex_free(pval, it); -#ifdef CRYPTO_MDEBUG - if (it->sname) - CRYPTO_pop_info(); -#endif return 0; } @@ -257,10 +235,6 @@ ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) *pval = NULL; return 1; } -#ifdef CRYPTO_MDEBUG - if (tt->field_name) - CRYPTO_push_info(tt->field_name); -#endif /* If SET OF or SEQUENCE OF, its a STACK */ if (tt->flags & ASN1_TFLG_SK_MASK) { STACK_OF(ASN1_VALUE) *skval; @@ -276,11 +250,7 @@ ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) } /* Otherwise pass it back to the item routine */ ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE); -done: -#ifdef CRYPTO_MDEBUG - if (it->sname) - CRYPTO_pop_info(); -#endif + done: return ret; } diff --git a/crypto/asn1/tasn_prn.c b/crypto/asn1/tasn_prn.c index 4c676d8..54ec56e 100644 --- a/crypto/asn1/tasn_prn.c +++ b/crypto/asn1/tasn_prn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tasn_prn.c,v 1.21 2020/03/24 10:46:38 inoguchi Exp $ */ +/* $OpenBSD: tasn_prn.c,v 1.22 2021/12/03 17:10:49 jsing Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ @@ -84,18 +84,14 @@ ASN1_PCTX default_pctx = { ASN1_PCTX * ASN1_PCTX_new(void) { - ASN1_PCTX *ret; - ret = malloc(sizeof(ASN1_PCTX)); - if (ret == NULL) { + ASN1_PCTX *p; + + if ((p = calloc(1, sizeof(ASN1_PCTX))) == NULL) { ASN1error(ERR_R_MALLOC_FAILURE); return NULL; } - ret->flags = 0; - ret->nm_flags = 0; - ret->cert_flags = 0; - ret->oid_flags = 0; - ret->str_flags = 0; - return ret; + + return p; } void diff --git a/crypto/asn1/tasn_typ.c b/crypto/asn1/tasn_typ.c index 542713a..c373f34 100644 --- a/crypto/asn1/tasn_typ.c +++ b/crypto/asn1/tasn_typ.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tasn_typ.c,v 1.13 2015/07/24 15:09:52 jsing Exp $ */ +/* $OpenBSD: tasn_typ.c,v 1.17 2021/12/26 15:20:21 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ @@ -61,134 +61,6 @@ /* Declarations for string types */ -const ASN1_ITEM ASN1_INTEGER_it = { - .itype = ASN1_ITYPE_PRIMITIVE, - .utype = V_ASN1_INTEGER, - .sname = "ASN1_INTEGER", -}; - -ASN1_INTEGER * -d2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **in, long len) -{ - return (ASN1_INTEGER *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, - &ASN1_INTEGER_it); -} - -int -i2d_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **out) -{ - return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_INTEGER_it); -} - -ASN1_INTEGER * -ASN1_INTEGER_new(void) -{ - return (ASN1_INTEGER *)ASN1_item_new(&ASN1_INTEGER_it); -} - -void -ASN1_INTEGER_free(ASN1_INTEGER *a) -{ - ASN1_item_free((ASN1_VALUE *)a, &ASN1_INTEGER_it); -} - - -const ASN1_ITEM ASN1_ENUMERATED_it = { - .itype = ASN1_ITYPE_PRIMITIVE, - .utype = V_ASN1_ENUMERATED, - .sname = "ASN1_ENUMERATED", -}; - -ASN1_ENUMERATED * -d2i_ASN1_ENUMERATED(ASN1_ENUMERATED **a, const unsigned char **in, long len) -{ - return (ASN1_ENUMERATED *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, - &ASN1_ENUMERATED_it); -} - -int -i2d_ASN1_ENUMERATED(ASN1_ENUMERATED *a, unsigned char **out) -{ - return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_ENUMERATED_it); -} - -ASN1_ENUMERATED * -ASN1_ENUMERATED_new(void) -{ - return (ASN1_ENUMERATED *)ASN1_item_new(&ASN1_ENUMERATED_it); -} - -void -ASN1_ENUMERATED_free(ASN1_ENUMERATED *a) -{ - ASN1_item_free((ASN1_VALUE *)a, &ASN1_ENUMERATED_it); -} - - -const ASN1_ITEM ASN1_BIT_STRING_it = { - .itype = ASN1_ITYPE_PRIMITIVE, - .utype = V_ASN1_BIT_STRING, - .sname = "ASN1_BIT_STRING", -}; - -ASN1_BIT_STRING * -d2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, const unsigned char **in, long len) -{ - return (ASN1_BIT_STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, - &ASN1_BIT_STRING_it); -} - -int -i2d_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **out) -{ - return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_BIT_STRING_it); -} - -ASN1_BIT_STRING * -ASN1_BIT_STRING_new(void) -{ - return (ASN1_BIT_STRING *)ASN1_item_new(&ASN1_BIT_STRING_it); -} - -void -ASN1_BIT_STRING_free(ASN1_BIT_STRING *a) -{ - ASN1_item_free((ASN1_VALUE *)a, &ASN1_BIT_STRING_it); -} - - -const ASN1_ITEM ASN1_OCTET_STRING_it = { - .itype = ASN1_ITYPE_PRIMITIVE, - .utype = V_ASN1_OCTET_STRING, - .sname = "ASN1_OCTET_STRING", -}; - -ASN1_OCTET_STRING * -d2i_ASN1_OCTET_STRING(ASN1_OCTET_STRING **a, const unsigned char **in, long len) -{ - return (ASN1_OCTET_STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, - &ASN1_OCTET_STRING_it); -} - -int -i2d_ASN1_OCTET_STRING(ASN1_OCTET_STRING *a, unsigned char **out) -{ - return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_OCTET_STRING_it); -} - -ASN1_OCTET_STRING * -ASN1_OCTET_STRING_new(void) -{ - return (ASN1_OCTET_STRING *)ASN1_item_new(&ASN1_OCTET_STRING_it); -} - -void -ASN1_OCTET_STRING_free(ASN1_OCTET_STRING *a) -{ - ASN1_item_free((ASN1_VALUE *)a, &ASN1_OCTET_STRING_it); -} - - const ASN1_ITEM ASN1_NULL_it = { .itype = ASN1_ITYPE_PRIMITIVE, .utype = V_ASN1_NULL, @@ -221,13 +93,6 @@ ASN1_NULL_free(ASN1_NULL *a) } -const ASN1_ITEM ASN1_OBJECT_it = { - .itype = ASN1_ITYPE_PRIMITIVE, - .utype = V_ASN1_OBJECT, - .sname = "ASN1_OBJECT", -}; - - const ASN1_ITEM ASN1_UTF8STRING_it = { .itype = ASN1_ITYPE_PRIMITIVE, .utype = V_ASN1_UTF8STRING, @@ -552,13 +417,13 @@ ASN1_BMPSTRING_free(ASN1_BMPSTRING *a) ASN1_item_free((ASN1_VALUE *)a, &ASN1_BMPSTRING_it); } - const ASN1_ITEM ASN1_ANY_it = { .itype = ASN1_ITYPE_PRIMITIVE, .utype = V_ASN1_ANY, .sname = "ASN1_ANY", }; + /* Just swallow an ASN1_SEQUENCE in an ASN1_STRING */ const ASN1_ITEM ASN1_SEQUENCE_it = { @@ -568,31 +433,6 @@ const ASN1_ITEM ASN1_SEQUENCE_it = { }; -ASN1_TYPE * -d2i_ASN1_TYPE(ASN1_TYPE **a, const unsigned char **in, long len) -{ - return (ASN1_TYPE *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, - &ASN1_ANY_it); -} - -int -i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **out) -{ - return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_ANY_it); -} - -ASN1_TYPE * -ASN1_TYPE_new(void) -{ - return (ASN1_TYPE *)ASN1_item_new(&ASN1_ANY_it); -} - -void -ASN1_TYPE_free(ASN1_TYPE *a) -{ - ASN1_item_free((ASN1_VALUE *)a, &ASN1_ANY_it); -} - /* Multistring types */ @@ -712,6 +552,28 @@ const ASN1_ITEM ASN1_BOOLEAN_it = { .sname = "ASN1_BOOLEAN", }; +int +i2d_ASN1_BOOLEAN(int a, unsigned char **out) +{ + return ASN1_item_ex_i2d((ASN1_VALUE **)&a, out, + &ASN1_BOOLEAN_it, -1, 0); +} + +int +d2i_ASN1_BOOLEAN(int *a, const unsigned char **in, long len) +{ + ASN1_BOOLEAN abool; + + if (ASN1_item_ex_d2i((ASN1_VALUE **)&abool, in, len, &ASN1_BOOLEAN_it, + -1, 0, 0, NULL) <= 0) + return -1; + + if (a != NULL) + *a = abool; + + return abool; +} + const ASN1_ITEM ASN1_TBOOLEAN_it = { .itype = ASN1_ITYPE_PRIMITIVE, .utype = V_ASN1_BOOLEAN, diff --git a/crypto/asn1/tasn_utl.c b/crypto/asn1/tasn_utl.c index 391ef01..e64bbe1 100644 --- a/crypto/asn1/tasn_utl.c +++ b/crypto/asn1/tasn_utl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tasn_utl.c,v 1.12 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: tasn_utl.c,v 1.13 2021/12/25 13:17:48 jsing Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ @@ -272,7 +272,7 @@ asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, int nullerr) goto err; return adb->default_tt; -err: + err: /* FIXME: should log the value or OID of unsupported type */ if (nullerr) ASN1error(ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE); diff --git a/crypto/asn1/x_algor.c b/crypto/asn1/x_algor.c index 2013de7..efb0c34 100644 --- a/crypto/asn1/x_algor.c +++ b/crypto/asn1/x_algor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x_algor.c,v 1.22 2018/05/01 19:01:27 tb Exp $ */ +/* $OpenBSD: x_algor.c,v 1.23 2021/12/12 14:27:20 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ @@ -197,12 +197,10 @@ X509_ALGOR_get0(const ASN1_OBJECT **paobj, int *pptype, const void **ppval, void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md) { - int param_type; + int param_type = V_ASN1_NULL; - if (md->flags & EVP_MD_FLAG_DIGALGID_ABSENT) + if ((EVP_MD_flags(md) & EVP_MD_FLAG_DIGALGID_ABSENT) != 0) param_type = V_ASN1_UNDEF; - else - param_type = V_ASN1_NULL; X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL); } diff --git a/crypto/asn1/x_attrib.c b/crypto/asn1/x_attrib.c index 04816ea..47b5afd 100644 --- a/crypto/asn1/x_attrib.c +++ b/crypto/asn1/x_attrib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x_attrib.c,v 1.14 2020/06/04 21:21:03 schwarze Exp $ */ +/* $OpenBSD: x_attrib.c,v 1.16 2021/12/25 13:17:48 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -62,6 +62,8 @@ #include #include +#include "x509_lcl.h" + /* X509_ATTRIBUTE: this has the following form: * * typedef struct x509_attributes_st @@ -192,7 +194,7 @@ X509_ATTRIBUTE_create(int nid, int atrtype, void *value) ASN1_TYPE_set(val, atrtype, value); return (ret); -err: + err: if (ret != NULL) X509_ATTRIBUTE_free(ret); if (val != NULL) diff --git a/crypto/asn1/x_crl.c b/crypto/asn1/x_crl.c index bc1783d..35d9007 100644 --- a/crypto/asn1/x_crl.c +++ b/crypto/asn1/x_crl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x_crl.c,v 1.34 2019/03/13 20:34:00 tb Exp $ */ +/* $OpenBSD: x_crl.c,v 1.37 2022/02/24 22:05:06 beck Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -66,6 +66,7 @@ #include #include "asn1_locl.h" +#include "x509_lcl.h" static int X509_REVOKED_cmp(const X509_REVOKED * const *a, const X509_REVOKED * const *b); @@ -287,9 +288,7 @@ crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg) break; case ASN1_OP_D2I_POST: -#ifndef OPENSSL_NO_SHA - X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL); -#endif + X509_CRL_digest(crl, X509_CRL_HASH_EVP, crl->hash, NULL); crl->idp = X509_CRL_get_ext_d2i(crl, NID_issuing_distribution_point, NULL, NULL); if (crl->idp) @@ -659,14 +658,15 @@ X509_CRL_METHOD_new(int (*crl_init)(X509_CRL *crl), { X509_CRL_METHOD *m; - m = malloc(sizeof(X509_CRL_METHOD)); - if (!m) + if ((m = calloc(1, sizeof(X509_CRL_METHOD))) == NULL) return NULL; + m->crl_init = crl_init; m->crl_free = crl_free; m->crl_lookup = crl_lookup; m->crl_verify = crl_verify; m->flags = X509_CRL_METHOD_DYNAMIC; + return m; } diff --git a/crypto/asn1/x_exten.c b/crypto/asn1/x_exten.c index bb3dffc..aba8973 100644 --- a/crypto/asn1/x_exten.c +++ b/crypto/asn1/x_exten.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x_exten.c,v 1.16 2015/07/24 15:09:52 jsing Exp $ */ +/* $OpenBSD: x_exten.c,v 1.17 2021/11/01 20:53:08 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ @@ -61,6 +61,8 @@ #include #include +#include "x509_lcl.h" + static const ASN1_TEMPLATE X509_EXTENSION_seq_tt[] = { { .offset = offsetof(X509_EXTENSION, object), diff --git a/crypto/asn1/x_name.c b/crypto/asn1/x_name.c index 0961ee3..4c698ac 100644 --- a/crypto/asn1/x_name.c +++ b/crypto/asn1/x_name.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x_name.c,v 1.35 2021/07/04 11:38:37 schwarze Exp $ */ +/* $OpenBSD: x_name.c,v 1.37 2021/12/25 13:17:48 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -65,6 +65,7 @@ #include #include "asn1_locl.h" +#include "x509_lcl.h" typedef STACK_OF(X509_NAME_ENTRY) STACK_OF_X509_NAME_ENTRY; DECLARE_STACK_OF(STACK_OF_X509_NAME_ENTRY) @@ -256,7 +257,7 @@ x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it) *val = (ASN1_VALUE *)ret; return 1; -memerr: + memerr: ASN1error(ERR_R_MALLOC_FAILURE); if (ret) { if (ret->entries) @@ -336,7 +337,7 @@ x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long len, *in = p; return ret; -err: + err: if (nm.x != NULL) X509_NAME_free(nm.x); ASN1error(ERR_R_NESTED_ASN1_ERROR); @@ -421,7 +422,7 @@ x509_name_encode(X509_NAME *a) a->modified = 0; return len; -memerr: + memerr: sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, local_sk_X509_NAME_ENTRY_free); ASN1error(ERR_R_MALLOC_FAILURE); @@ -511,7 +512,7 @@ x509_name_canon(X509_NAME *a) i2d_name_canon(intname, &p); ret = 1; -err: + err: if (tmpentry) X509_NAME_ENTRY_free(tmpentry); if (intname) diff --git a/crypto/asn1/x_nx509.c b/crypto/asn1/x_nx509.c deleted file mode 100644 index 7e18be8..0000000 --- a/crypto/asn1/x_nx509.c +++ /dev/null @@ -1,113 +0,0 @@ -/* $OpenBSD: x_nx509.c,v 1.6 2015/02/11 04:00:39 jsing Exp $ */ -/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL - * project 2005. - */ -/* ==================================================================== - * Copyright (c) 2005 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 - * licensing@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). - * - */ - -#include -#include -#include -#include - -/* Old netscape certificate wrapper format */ - -static const ASN1_TEMPLATE NETSCAPE_X509_seq_tt[] = { - { - .offset = offsetof(NETSCAPE_X509, header), - .field_name = "header", - .item = &ASN1_OCTET_STRING_it, - }, - { - .flags = ASN1_TFLG_OPTIONAL, - .offset = offsetof(NETSCAPE_X509, cert), - .field_name = "cert", - .item = &X509_it, - }, -}; - -const ASN1_ITEM NETSCAPE_X509_it = { - .itype = ASN1_ITYPE_SEQUENCE, - .utype = V_ASN1_SEQUENCE, - .templates = NETSCAPE_X509_seq_tt, - .tcount = sizeof(NETSCAPE_X509_seq_tt) / sizeof(ASN1_TEMPLATE), - .size = sizeof(NETSCAPE_X509), - .sname = "NETSCAPE_X509", -}; - - -NETSCAPE_X509 * -d2i_NETSCAPE_X509(NETSCAPE_X509 **a, const unsigned char **in, long len) -{ - return (NETSCAPE_X509 *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, - &NETSCAPE_X509_it); -} - -int -i2d_NETSCAPE_X509(NETSCAPE_X509 *a, unsigned char **out) -{ - return ASN1_item_i2d((ASN1_VALUE *)a, out, &NETSCAPE_X509_it); -} - -NETSCAPE_X509 * -NETSCAPE_X509_new(void) -{ - return (NETSCAPE_X509 *)ASN1_item_new(&NETSCAPE_X509_it); -} - -void -NETSCAPE_X509_free(NETSCAPE_X509 *a) -{ - ASN1_item_free((ASN1_VALUE *)a, &NETSCAPE_X509_it); -} diff --git a/crypto/asn1/x_pkey.c b/crypto/asn1/x_pkey.c index c946281..fdf0e00 100644 --- a/crypto/asn1/x_pkey.c +++ b/crypto/asn1/x_pkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x_pkey.c,v 1.20 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: x_pkey.c,v 1.21 2021/12/25 13:17:48 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -91,7 +91,7 @@ X509_PKEY_new(void) ret->references = 1; return (ret); -err: + err: if (ret) { X509_ALGOR_free(ret->enc_algor); free(ret); diff --git a/crypto/asn1/x_pubkey.c b/crypto/asn1/x_pubkey.c index ea67419..69be6ed 100644 --- a/crypto/asn1/x_pubkey.c +++ b/crypto/asn1/x_pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x_pubkey.c,v 1.27 2018/03/17 14:55:39 jsing Exp $ */ +/* $OpenBSD: x_pubkey.c,v 1.31 2021/12/25 13:17:48 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -72,6 +72,8 @@ #endif #include "asn1_locl.h" +#include "evp_locl.h" +#include "x509_lcl.h" /* Minor tweak to operation: free up EVP_PKEY */ static int @@ -110,7 +112,6 @@ const ASN1_ITEM X509_PUBKEY_it = { .sname = "X509_PUBKEY", }; - X509_PUBKEY * d2i_X509_PUBKEY(X509_PUBKEY **a, const unsigned char **in, long len) { @@ -168,7 +169,7 @@ X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) return 1; -error: + error: if (pk != NULL) X509_PUBKEY_free(pk); return 0; @@ -221,7 +222,7 @@ X509_PUBKEY_get0(X509_PUBKEY *key) return ret; -error: + error: EVP_PKEY_free(ret); return (NULL); } @@ -239,168 +240,473 @@ X509_PUBKEY_get(X509_PUBKEY *key) return pkey; } -/* Now two pseudo ASN1 routines that take an EVP_PKEY structure - * and encode or decode as X509_PUBKEY +/* + * Decode an X509_PUBKEY into the specified key type. */ - -EVP_PKEY * -d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length) +static int +pubkey_ex_d2i(int pkey_type, ASN1_VALUE **pval, const unsigned char **in, + long len, const ASN1_ITEM *it) { - X509_PUBKEY *xpk; - EVP_PKEY *pktmp; - xpk = d2i_X509_PUBKEY(NULL, pp, length); - if (!xpk) - return NULL; - pktmp = X509_PUBKEY_get(xpk); - X509_PUBKEY_free(xpk); - if (!pktmp) - return NULL; - if (a) { - EVP_PKEY_free(*a); - *a = pktmp; + const ASN1_EXTERN_FUNCS *ef = it->funcs; + const unsigned char *p = *in; + X509_PUBKEY *xpk = NULL; + ASN1_VALUE *key = NULL; + EVP_PKEY *pkey = NULL; + int ret = 0; + + if ((xpk = d2i_X509_PUBKEY(NULL, &p, len)) == NULL) + goto err; + if ((pkey = X509_PUBKEY_get(xpk)) == NULL) + goto err; + + switch (pkey_type) { + case EVP_PKEY_NONE: + key = (ASN1_VALUE *)pkey; + pkey = NULL; + break; + + case EVP_PKEY_DSA: + key = (ASN1_VALUE *)EVP_PKEY_get1_DSA(pkey); + break; + + case EVP_PKEY_RSA: + key = (ASN1_VALUE *)EVP_PKEY_get1_RSA(pkey); + break; + + case EVP_PKEY_EC: + key = (ASN1_VALUE *)EVP_PKEY_get1_EC_KEY(pkey); + break; + + default: + goto err; } - return pktmp; + + if (key == NULL) + goto err; + + ef->asn1_ex_free(pval, it); + + *pval = key; + *in = p; + ret = 1; + + err: + EVP_PKEY_free(pkey); + X509_PUBKEY_free(xpk); + + return ret; } -int -i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp) +/* + * Encode the specified key type into an X509_PUBKEY. + */ +static int +pubkey_ex_i2d(int pkey_type, ASN1_VALUE **pval, unsigned char **out, + const ASN1_ITEM *it) { X509_PUBKEY *xpk = NULL; - int ret; - if (!a) - return 0; - if (!X509_PUBKEY_set(&xpk, a)) - return 0; - ret = i2d_X509_PUBKEY(xpk, pp); + EVP_PKEY *pkey, *pktmp; + int ret = -1; + + if ((pkey = pktmp = EVP_PKEY_new()) == NULL) + goto err; + + switch (pkey_type) { + case EVP_PKEY_NONE: + pkey = (EVP_PKEY *)*pval; + break; + + case EVP_PKEY_DSA: + if (!EVP_PKEY_set1_DSA(pkey, (DSA *)*pval)) + goto err; + break; + + case EVP_PKEY_RSA: + if (!EVP_PKEY_set1_RSA(pkey, (RSA *)*pval)) + goto err; + break; + + case EVP_PKEY_EC: + if (!EVP_PKEY_set1_EC_KEY(pkey, (EC_KEY*)*pval)) + goto err; + break; + + default: + goto err; + } + + if (!X509_PUBKEY_set(&xpk, pkey)) + goto err; + + ret = i2d_X509_PUBKEY(xpk, out); + + err: + EVP_PKEY_free(pktmp); X509_PUBKEY_free(xpk); + return ret; } -/* The following are equivalents but which return RSA and DSA - * keys - */ -#ifndef OPENSSL_NO_RSA -RSA * -d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length) +static int +pkey_pubkey_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it) { - EVP_PKEY *pkey; - RSA *key; - const unsigned char *q; - q = *pp; - pkey = d2i_PUBKEY(NULL, &q, length); - if (!pkey) - return NULL; - key = EVP_PKEY_get1_RSA(pkey); - EVP_PKEY_free(pkey); - if (!key) - return NULL; - *pp = q; - if (a) { - RSA_free(*a); - *a = key; - } - return key; + if ((*pval = (ASN1_VALUE *)EVP_PKEY_new()) == NULL) + return 0; + + return 1; +} + +static void +pkey_pubkey_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + EVP_PKEY_free((EVP_PKEY *)*pval); + *pval = NULL; +} + +static int +pkey_pubkey_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 pubkey_ex_d2i(EVP_PKEY_NONE, pval, in, len, it); +} + +static int +pkey_pubkey_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, + int tag, int aclass) +{ + return pubkey_ex_i2d(EVP_PKEY_NONE, pval, out, it); +} + +const ASN1_EXTERN_FUNCS pkey_pubkey_asn1_ff = { + .app_data = NULL, + .asn1_ex_new = pkey_pubkey_ex_new, + .asn1_ex_free = pkey_pubkey_ex_free, + .asn1_ex_clear = NULL, + .asn1_ex_d2i = pkey_pubkey_ex_d2i, + .asn1_ex_i2d = pkey_pubkey_ex_i2d, + .asn1_ex_print = NULL, +}; + +const ASN1_ITEM EVP_PKEY_PUBKEY_it = { + .itype = ASN1_ITYPE_EXTERN, + .utype = 0, + .templates = NULL, + .tcount = 0, + .funcs = &pkey_pubkey_asn1_ff, + .size = 0, + .sname = NULL, +}; + +EVP_PKEY * +d2i_PUBKEY(EVP_PKEY **pkey, const unsigned char **in, long len) +{ + return (EVP_PKEY *)ASN1_item_d2i((ASN1_VALUE **)pkey, in, len, + &EVP_PKEY_PUBKEY_it); } int -i2d_RSA_PUBKEY(RSA *a, unsigned char **pp) +i2d_PUBKEY(EVP_PKEY *pkey, unsigned char **out) { - EVP_PKEY *pktmp; - int ret; - if (!a) + return ASN1_item_i2d((ASN1_VALUE *)pkey, out, &EVP_PKEY_PUBKEY_it); +} + +EVP_PKEY * +d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **pkey) +{ + return (EVP_PKEY *)ASN1_item_d2i_bio(&EVP_PKEY_PUBKEY_it, bp, + (ASN1_VALUE **)pkey); +} + +int +i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey) +{ + return ASN1_item_i2d_bio(&EVP_PKEY_PUBKEY_it, bp, (ASN1_VALUE *)pkey); +} + +EVP_PKEY * +d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **pkey) +{ + return (EVP_PKEY *)ASN1_item_d2i_fp(&EVP_PKEY_PUBKEY_it, fp, + (ASN1_VALUE **)pkey); +} + +int +i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey) +{ + return ASN1_item_i2d_fp(&EVP_PKEY_PUBKEY_it, fp, (ASN1_VALUE *)pkey); +} + +/* + * The following are equivalents but which return RSA and DSA keys. + */ +#ifndef OPENSSL_NO_RSA + +static int +rsa_pubkey_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + if ((*pval = (ASN1_VALUE *)RSA_new()) == NULL) return 0; - pktmp = EVP_PKEY_new(); - if (!pktmp) { - ASN1error(ERR_R_MALLOC_FAILURE); - return 0; - } - EVP_PKEY_set1_RSA(pktmp, a); - ret = i2d_PUBKEY(pktmp, pp); - EVP_PKEY_free(pktmp); - return ret; + + return 1; +} + +static void +rsa_pubkey_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + RSA_free((RSA *)*pval); + *pval = NULL; +} + +static int +rsa_pubkey_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 pubkey_ex_d2i(EVP_PKEY_RSA, pval, in, len, it); +} + +static int +rsa_pubkey_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, + int tag, int aclass) +{ + return pubkey_ex_i2d(EVP_PKEY_RSA, pval, out, it); +} + +const ASN1_EXTERN_FUNCS rsa_pubkey_asn1_ff = { + .app_data = NULL, + .asn1_ex_new = rsa_pubkey_ex_new, + .asn1_ex_free = rsa_pubkey_ex_free, + .asn1_ex_clear = NULL, + .asn1_ex_d2i = rsa_pubkey_ex_d2i, + .asn1_ex_i2d = rsa_pubkey_ex_i2d, + .asn1_ex_print = NULL, +}; + +const ASN1_ITEM RSA_PUBKEY_it = { + .itype = ASN1_ITYPE_EXTERN, + .utype = 0, + .templates = NULL, + .tcount = 0, + .funcs = &rsa_pubkey_asn1_ff, + .size = 0, + .sname = NULL, +}; + +RSA * +d2i_RSA_PUBKEY(RSA **rsa, const unsigned char **in, long len) +{ + return (RSA *)ASN1_item_d2i((ASN1_VALUE **)rsa, in, len, + &RSA_PUBKEY_it); +} + +int +i2d_RSA_PUBKEY(RSA *rsa, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)rsa, out, &RSA_PUBKEY_it); +} + +RSA * +d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa) +{ + return (RSA *)ASN1_item_d2i_bio(&RSA_PUBKEY_it, bp, (ASN1_VALUE **)rsa); +} + +int +i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa) +{ + return ASN1_item_i2d_bio(&RSA_PUBKEY_it, bp, (ASN1_VALUE *)rsa); +} + +RSA * +d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa) +{ + return (RSA *)ASN1_item_d2i_fp(&RSA_PUBKEY_it, fp, (ASN1_VALUE **)rsa); +} + +int +i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa) +{ + return ASN1_item_i2d_fp(&RSA_PUBKEY_it, fp, (ASN1_VALUE *)rsa); } #endif #ifndef OPENSSL_NO_DSA -DSA * -d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length) + +static int +dsa_pubkey_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it) { - EVP_PKEY *pkey; - DSA *key; - const unsigned char *q; - q = *pp; - pkey = d2i_PUBKEY(NULL, &q, length); - if (!pkey) - return NULL; - key = EVP_PKEY_get1_DSA(pkey); - EVP_PKEY_free(pkey); - if (!key) - return NULL; - *pp = q; - if (a) { - DSA_free(*a); - *a = key; - } - return key; + if ((*pval = (ASN1_VALUE *)DSA_new()) == NULL) + return 0; + + return 1; +} + +static void +dsa_pubkey_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + DSA_free((DSA *)*pval); + *pval = NULL; +} + +static int +dsa_pubkey_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 pubkey_ex_d2i(EVP_PKEY_DSA, pval, in, len, it); +} + +static int +dsa_pubkey_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, + int tag, int aclass) +{ + return pubkey_ex_i2d(EVP_PKEY_DSA, pval, out, it); +} + +const ASN1_EXTERN_FUNCS dsa_pubkey_asn1_ff = { + .app_data = NULL, + .asn1_ex_new = dsa_pubkey_ex_new, + .asn1_ex_free = dsa_pubkey_ex_free, + .asn1_ex_clear = NULL, + .asn1_ex_d2i = dsa_pubkey_ex_d2i, + .asn1_ex_i2d = dsa_pubkey_ex_i2d, + .asn1_ex_print = NULL, +}; + +const ASN1_ITEM DSA_PUBKEY_it = { + .itype = ASN1_ITYPE_EXTERN, + .utype = 0, + .templates = NULL, + .tcount = 0, + .funcs = &dsa_pubkey_asn1_ff, + .size = 0, + .sname = NULL, +}; + +DSA * +d2i_DSA_PUBKEY(DSA **dsa, const unsigned char **in, long len) +{ + return (DSA *)ASN1_item_d2i((ASN1_VALUE **)dsa, in, len, + &DSA_PUBKEY_it); } int -i2d_DSA_PUBKEY(DSA *a, unsigned char **pp) +i2d_DSA_PUBKEY(DSA *dsa, unsigned char **out) { - EVP_PKEY *pktmp; - int ret; - if (!a) - return 0; - pktmp = EVP_PKEY_new(); - if (!pktmp) { - ASN1error(ERR_R_MALLOC_FAILURE); - return 0; - } - EVP_PKEY_set1_DSA(pktmp, a); - ret = i2d_PUBKEY(pktmp, pp); - EVP_PKEY_free(pktmp); - return ret; + return ASN1_item_i2d((ASN1_VALUE *)dsa, out, &DSA_PUBKEY_it); } + +DSA * +d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa) +{ + return (DSA *)ASN1_item_d2i_bio(&DSA_PUBKEY_it, bp, (ASN1_VALUE **)dsa); +} + +int +i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa) +{ + return ASN1_item_i2d_bio(&DSA_PUBKEY_it, bp, (ASN1_VALUE *)dsa); +} + +DSA * +d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa) +{ + return (DSA *)ASN1_item_d2i_fp(&DSA_PUBKEY_it, fp, (ASN1_VALUE **)dsa); +} + +int +i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa) +{ + return ASN1_item_i2d_fp(&DSA_PUBKEY_it, fp, (ASN1_VALUE *)dsa); +} + #endif #ifndef OPENSSL_NO_EC -EC_KEY * -d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length) + +static int +ec_pubkey_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it) { - EVP_PKEY *pkey; - EC_KEY *key; - const unsigned char *q; - q = *pp; - pkey = d2i_PUBKEY(NULL, &q, length); - if (!pkey) - return (NULL); - key = EVP_PKEY_get1_EC_KEY(pkey); - EVP_PKEY_free(pkey); - if (!key) - return (NULL); - *pp = q; - if (a) { - EC_KEY_free(*a); - *a = key; - } - return (key); + if ((*pval = (ASN1_VALUE *)EC_KEY_new()) == NULL) + return 0; + + return 1; +} + +static void +ec_pubkey_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + EC_KEY_free((EC_KEY *)*pval); + *pval = NULL; +} + +static int +ec_pubkey_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 pubkey_ex_d2i(EVP_PKEY_EC, pval, in, len, it); +} + +static int +ec_pubkey_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, + int tag, int aclass) +{ + return pubkey_ex_i2d(EVP_PKEY_EC, pval, out, it); +} + +const ASN1_EXTERN_FUNCS ec_pubkey_asn1_ff = { + .app_data = NULL, + .asn1_ex_new = ec_pubkey_ex_new, + .asn1_ex_free = ec_pubkey_ex_free, + .asn1_ex_clear = NULL, + .asn1_ex_d2i = ec_pubkey_ex_d2i, + .asn1_ex_i2d = ec_pubkey_ex_i2d, + .asn1_ex_print = NULL, +}; + +const ASN1_ITEM EC_PUBKEY_it = { + .itype = ASN1_ITYPE_EXTERN, + .utype = 0, + .templates = NULL, + .tcount = 0, + .funcs = &ec_pubkey_asn1_ff, + .size = 0, + .sname = NULL, +}; + +EC_KEY * +d2i_EC_PUBKEY(EC_KEY **ec, const unsigned char **in, long len) +{ + return (EC_KEY *)ASN1_item_d2i((ASN1_VALUE **)ec, in, len, + &EC_PUBKEY_it); } int -i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp) +i2d_EC_PUBKEY(EC_KEY *ec, unsigned char **out) { - EVP_PKEY *pktmp; - int ret; - if (!a) - return (0); - if ((pktmp = EVP_PKEY_new()) == NULL) { - ASN1error(ERR_R_MALLOC_FAILURE); - return (0); - } - EVP_PKEY_set1_EC_KEY(pktmp, a); - ret = i2d_PUBKEY(pktmp, pp); - EVP_PKEY_free(pktmp); - return (ret); + return ASN1_item_i2d((ASN1_VALUE *)ec, out, &EC_PUBKEY_it); +} + +EC_KEY * +d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **ec) +{ + return (EC_KEY *)ASN1_item_d2i_bio(&EC_PUBKEY_it, bp, (ASN1_VALUE **)ec); +} + +int +i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *ec) +{ + return ASN1_item_i2d_bio(&EC_PUBKEY_it, bp, (ASN1_VALUE *)ec); +} + +EC_KEY * +d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **ec) +{ + return (EC_KEY *)ASN1_item_d2i_fp(&EC_PUBKEY_it, fp, (ASN1_VALUE **)ec); +} + +int +i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *ec) +{ + return ASN1_item_i2d_fp(&EC_PUBKEY_it, fp, (ASN1_VALUE *)ec); } #endif diff --git a/crypto/asn1/x_req.c b/crypto/asn1/x_req.c index eb5210a..38e3790 100644 --- a/crypto/asn1/x_req.c +++ b/crypto/asn1/x_req.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x_req.c,v 1.17 2018/02/22 16:50:30 jsing Exp $ */ +/* $OpenBSD: x_req.c,v 1.18 2021/11/01 20:53:08 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -61,6 +61,8 @@ #include #include +#include "x509_lcl.h" + /* X509_REQ_INFO is handled in an unusual way to get round * invalid encodings. Some broken certificate requests don't * encode the attributes field if it is empty. This is in diff --git a/crypto/asn1/x_sig.c b/crypto/asn1/x_sig.c index 702bc40..6a842da 100644 --- a/crypto/asn1/x_sig.c +++ b/crypto/asn1/x_sig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x_sig.c,v 1.11 2015/02/11 04:00:39 jsing Exp $ */ +/* $OpenBSD: x_sig.c,v 1.13 2021/11/01 20:53:08 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -61,6 +61,8 @@ #include #include +#include "x509_lcl.h" + static const ASN1_TEMPLATE X509_SIG_seq_tt[] = { { .offset = offsetof(X509_SIG, algor), @@ -108,3 +110,22 @@ X509_SIG_free(X509_SIG *a) { ASN1_item_free((ASN1_VALUE *)a, &X509_SIG_it); } + +void +X509_SIG_get0(const X509_SIG *sig, const X509_ALGOR **palg, + const ASN1_OCTET_STRING **pdigest) +{ + if (palg != NULL) + *palg = sig->algor; + if (pdigest != NULL) + *pdigest = sig->digest; +} + +void +X509_SIG_getm(X509_SIG *sig, X509_ALGOR **palg, ASN1_OCTET_STRING **pdigest) +{ + if (palg != NULL) + *palg = sig->algor; + if (pdigest != NULL) + *pdigest = sig->digest; +} diff --git a/crypto/asn1/x_x509.c b/crypto/asn1/x_x509.c index 422f625..7147069 100644 --- a/crypto/asn1/x_x509.c +++ b/crypto/asn1/x_x509.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x_x509.c,v 1.27 2021/09/02 12:41:44 job Exp $ */ +/* $OpenBSD: x_x509.c,v 1.30 2021/12/25 13:17:48 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -65,6 +65,8 @@ #include #include +#include "x509_lcl.h" + static const ASN1_AUX X509_CINF_aux = { .flags = ASN1_AFLG_ENCODING, .enc_offset = offsetof(X509_CINF, enc), @@ -337,7 +339,7 @@ d2i_X509_AUX(X509 **a, const unsigned char **pp, long length) } return ret; -err: + err: X509_free(ret); return NULL; } @@ -353,6 +355,13 @@ i2d_X509_AUX(X509 *a, unsigned char **pp) return length; } +int +i2d_re_X509_tbs(X509 *x, unsigned char **pp) +{ + x->cert_info->enc.modified = 1; + return i2d_X509_CINF(x->cert_info, pp); +} + void X509_get0_signature(const ASN1_BIT_STRING **psig, const X509_ALGOR **palg, const X509 *x) diff --git a/crypto/asn1/x_x509a.c b/crypto/asn1/x_x509a.c index b0d7150..87dc045 100644 --- a/crypto/asn1/x_x509a.c +++ b/crypto/asn1/x_x509a.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x_x509a.c,v 1.15 2018/05/01 19:01:27 tb Exp $ */ +/* $OpenBSD: x_x509a.c,v 1.18 2021/12/25 13:17:48 jsing Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -62,6 +62,8 @@ #include #include +#include "x509_lcl.h" + /* X509_CERT_AUX routines. These are used to encode additional * user modifiable data about a certificate. This data is * appended to the X509 encoding when the *_X509_AUX routines @@ -226,7 +228,7 @@ X509_add1_trust_object(X509 *x, const ASN1_OBJECT *obj) if (rc != 0) return rc; -err: + err: ASN1_OBJECT_free(objtmp); return 0; } @@ -248,7 +250,7 @@ X509_add1_reject_object(X509 *x, const ASN1_OBJECT *obj) if (rc != 0) return rc; -err: + err: ASN1_OBJECT_free(objtmp); return 0; } @@ -270,56 +272,3 @@ X509_reject_clear(X509 *x) x->aux->reject = NULL; } } - -static const ASN1_TEMPLATE X509_CERT_PAIR_seq_tt[] = { - { - .flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL, - .tag = 0, - .offset = offsetof(X509_CERT_PAIR, forward), - .field_name = "forward", - .item = &X509_it, - }, - { - .flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL, - .tag = 1, - .offset = offsetof(X509_CERT_PAIR, reverse), - .field_name = "reverse", - .item = &X509_it, - }, -}; - -const ASN1_ITEM X509_CERT_PAIR_it = { - .itype = ASN1_ITYPE_SEQUENCE, - .utype = V_ASN1_SEQUENCE, - .templates = X509_CERT_PAIR_seq_tt, - .tcount = sizeof(X509_CERT_PAIR_seq_tt) / sizeof(ASN1_TEMPLATE), - .funcs = NULL, - .size = sizeof(X509_CERT_PAIR), - .sname = "X509_CERT_PAIR", -}; - - -X509_CERT_PAIR * -d2i_X509_CERT_PAIR(X509_CERT_PAIR **a, const unsigned char **in, long len) -{ - return (X509_CERT_PAIR *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, - &X509_CERT_PAIR_it); -} - -int -i2d_X509_CERT_PAIR(X509_CERT_PAIR *a, unsigned char **out) -{ - return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_CERT_PAIR_it); -} - -X509_CERT_PAIR * -X509_CERT_PAIR_new(void) -{ - return (X509_CERT_PAIR *)ASN1_item_new(&X509_CERT_PAIR_it); -} - -void -X509_CERT_PAIR_free(X509_CERT_PAIR *a) -{ - ASN1_item_free((ASN1_VALUE *)a, &X509_CERT_PAIR_it); -} diff --git a/crypto/bio/bf_buff.c b/crypto/bio/bf_buff.c index 5b9ee35..aa079c5 100644 --- a/crypto/bio/bf_buff.c +++ b/crypto/bio/bf_buff.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bf_buff.c,v 1.25 2018/05/01 13:29:09 tb Exp $ */ +/* $OpenBSD: bf_buff.c,v 1.27 2022/01/14 08:40:57 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -63,6 +63,8 @@ #include #include +#include "bio_local.h" + static int buffer_write(BIO *h, const char *buf, int num); static int buffer_read(BIO *h, char *buf, int size); static int buffer_puts(BIO *h, const char *str); @@ -70,7 +72,7 @@ static int buffer_gets(BIO *h, char *str, int size); static long buffer_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int buffer_new(BIO *h); static int buffer_free(BIO *data); -static long buffer_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); +static long buffer_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); #define DEFAULT_BUFFER_SIZE 4096 static const BIO_METHOD methods_buffer = { @@ -450,7 +452,7 @@ malloc_error: } static long -buffer_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +buffer_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { long ret = 1; diff --git a/crypto/bio/bf_nbio.c b/crypto/bio/bf_nbio.c index 05fa916..086479e 100644 --- a/crypto/bio/bf_nbio.c +++ b/crypto/bio/bf_nbio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bf_nbio.c,v 1.20 2018/05/01 13:29:09 tb Exp $ */ +/* $OpenBSD: bf_nbio.c,v 1.22 2022/01/14 08:40:57 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -62,6 +62,8 @@ #include +#include "bio_local.h" + /* BIO_put and BIO_get both add to the digest, * BIO_gets returns the digest */ @@ -72,7 +74,7 @@ static int nbiof_gets(BIO *h, char *str, int size); static long nbiof_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int nbiof_new(BIO *h); static int nbiof_free(BIO *data); -static long nbiof_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); +static long nbiof_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); typedef struct nbio_test_st { /* only set if we sent a 'should retry' error */ @@ -221,7 +223,7 @@ nbiof_ctrl(BIO *b, int cmd, long num, void *ptr) } static long -nbiof_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +nbiof_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { long ret = 1; diff --git a/crypto/bio/bf_null.c b/crypto/bio/bf_null.c index 25abb8a..129def8 100644 --- a/crypto/bio/bf_null.c +++ b/crypto/bio/bf_null.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bf_null.c,v 1.12 2018/05/01 13:29:09 tb Exp $ */ +/* $OpenBSD: bf_null.c,v 1.14 2022/01/14 08:40:57 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -61,6 +61,8 @@ #include +#include "bio_local.h" + /* BIO_put and BIO_get both add to the digest, * BIO_gets returns the digest */ @@ -71,7 +73,7 @@ static int nullf_gets(BIO *h, char *str, int size); static long nullf_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int nullf_new(BIO *h); static int nullf_free(BIO *data); -static long nullf_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); +static long nullf_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); static const BIO_METHOD methods_nullf = { .type = BIO_TYPE_NULL_FILTER, @@ -165,7 +167,7 @@ nullf_ctrl(BIO *b, int cmd, long num, void *ptr) } static long -nullf_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +nullf_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { long ret = 1; diff --git a/crypto/bio/bio_cb.c b/crypto/bio/bio_cb.c index 52cdd24..2ca411c 100644 --- a/crypto/bio/bio_cb.c +++ b/crypto/bio/bio_cb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bio_cb.c,v 1.17 2021/03/25 09:26:17 tb Exp $ */ +/* $OpenBSD: bio_cb.c,v 1.18 2022/01/07 09:02:17 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -63,6 +63,8 @@ #include #include +#include "bio_local.h" + long BIO_debug_callback(BIO *bio, int cmd, const char *argp, int argi, long argl, long ret) diff --git a/crypto/bio/bio_err.c b/crypto/bio/bio_err.c index 2920e32..cda693d 100644 --- a/crypto/bio/bio_err.c +++ b/crypto/bio/bio_err.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bio_err.c,v 1.17 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: bio_err.c,v 1.18 2022/01/14 08:40:57 tb Exp $ */ /* ==================================================================== * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved. * @@ -92,6 +92,7 @@ static ERR_STRING_DATA BIO_str_reasons[] = { {ERR_REASON(BIO_R_INVALID_PORT_NUMBER) , "invalid port number"}, {ERR_REASON(BIO_R_IN_USE) , "in use"}, {ERR_REASON(BIO_R_KEEPALIVE) , "keepalive"}, + {ERR_REASON(BIO_R_LENGTH_TOO_LONG) , "too long"}, {ERR_REASON(BIO_R_NBIO_CONNECT_ERROR) , "nbio connect error"}, {ERR_REASON(BIO_R_NO_ACCEPT_PORT_SPECIFIED), "no accept port specified"}, {ERR_REASON(BIO_R_NO_HOSTNAME_SPECIFIED) , "no hostname specified"}, diff --git a/crypto/bio/bio_lib.c b/crypto/bio/bio_lib.c index 7ef1784..0b6c9ec 100644 --- a/crypto/bio/bio_lib.c +++ b/crypto/bio/bio_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bio_lib.c,v 1.29 2019/04/14 17:39:03 jsing Exp $ */ +/* $OpenBSD: bio_lib.c,v 1.35 2022/01/14 08:40:57 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -57,6 +57,7 @@ */ #include +#include #include #include @@ -64,6 +65,57 @@ #include #include +#include "bio_local.h" + +/* + * Helper function to work out whether to call the new style callback or the old + * one, and translate between the two. + * + * This has a long return type for consistency with the old callback. Similarly + * 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) +{ + long ret; + int bareoper; + + if (b->callback_ex != NULL) + return b->callback_ex(b, oper, argp, len, argi, argl, inret, + processed); + + /* + * We have an old style callback, so we will have to do nasty casts and + * check for overflows. + */ + + bareoper = oper & ~BIO_CB_RETURN; + + if (bareoper == BIO_CB_READ || bareoper == BIO_CB_WRITE || + bareoper == BIO_CB_GETS) { + /* In this case len is set and should be used instead of argi. */ + if (len > INT_MAX) + return -1; + argi = (int)len; + } + + if (inret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) { + if (*processed > INT_MAX) + return -1; + inret = *processed; + } + + ret = b->callback(b, oper, argp, argi, argl, inret); + + if (ret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) { + *processed = (size_t)ret; + ret = 1; + } + + return ret; +} + int BIO_get_new_index(void) { @@ -83,6 +135,7 @@ BIO_new(const BIO_METHOD *method) { BIO *ret = NULL; + /* XXX calloc */ ret = malloc(sizeof(BIO)); if (ret == NULL) { BIOerror(ERR_R_MALLOC_FAILURE); @@ -100,6 +153,7 @@ BIO_set(BIO *bio, const BIO_METHOD *method) { bio->method = method; bio->callback = NULL; + bio->callback_ex = NULL; bio->cb_arg = NULL; bio->init = 0; bio->shutdown = 1; @@ -113,29 +167,32 @@ BIO_set(BIO *bio, const BIO_METHOD *method) bio->num_read = 0L; bio->num_write = 0L; CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); - if (method->create != NULL) + if (method->create != NULL) { if (!method->create(bio)) { CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); return (0); } + } return (1); } int BIO_free(BIO *a) { - int i; + int ret; if (a == NULL) return (0); - i = CRYPTO_add(&a->references, -1, CRYPTO_LOCK_BIO); - if (i > 0) + if (CRYPTO_add(&a->references, -1, CRYPTO_LOCK_BIO) > 0) return (1); - if ((a->callback != NULL) && - ((i = (int)a->callback(a, BIO_CB_FREE, NULL, 0, 0L, 1L)) <= 0)) - return (i); + + if (a->callback != NULL || a->callback_ex != NULL) { + if ((ret = (int)bio_call_callback(a, BIO_CB_FREE, NULL, 0, 0, + 0L, 1L, NULL)) <= 0) + return (ret); + } CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data); @@ -170,6 +227,12 @@ BIO_set_data(BIO *a, void *ptr) a->ptr = ptr; } +int +BIO_get_init(BIO *a) +{ + return a->init; +} + void BIO_set_init(BIO *a, int init) { @@ -206,20 +269,30 @@ BIO_set_flags(BIO *b, int flags) b->flags |= flags; } -long -(*BIO_get_callback(const BIO *b))(struct bio_st *, int, const char *, int, - long, long) +BIO_callback_fn +BIO_get_callback(const BIO *b) { return b->callback; } void -BIO_set_callback(BIO *b, long (*cb)(struct bio_st *, int, const char *, int, - long, long)) +BIO_set_callback(BIO *b, BIO_callback_fn cb) { b->callback = cb; } +BIO_callback_fn_ex +BIO_get_callback_ex(const BIO *b) +{ + return b->callback_ex; +} + +void +BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex cb) +{ + b->callback_ex = cb; +} + void BIO_set_callback_arg(BIO *b, char *arg) { @@ -247,8 +320,8 @@ BIO_method_type(const BIO *b) int BIO_read(BIO *b, void *out, int outl) { - int i; - long (*cb)(BIO *, int, const char *, int, long, long); + size_t readbytes = 0; + int ret; if (b == NULL) return (0); @@ -261,33 +334,44 @@ BIO_read(BIO *b, void *out, int outl) return (-2); } - cb = b->callback; - if ((cb != NULL) && - ((i = (int)cb(b, BIO_CB_READ, out, outl, 0L, 1L)) <= 0)) - return (i); + if (b->callback != NULL || b->callback_ex != NULL) { + if ((ret = (int)bio_call_callback(b, BIO_CB_READ, out, outl, 0, + 0L, 1L, NULL)) <= 0) + return (ret); + } if (!b->init) { BIOerror(BIO_R_UNINITIALIZED); return (-2); } - i = b->method->bread(b, out, outl); + if ((ret = b->method->bread(b, out, outl)) > 0) + readbytes = (size_t)ret; - if (i > 0) - b->num_read += (unsigned long)i; + b->num_read += readbytes; - if (cb != NULL) - i = (int)cb(b, BIO_CB_READ|BIO_CB_RETURN, out, outl, - 0L, (long)i); + if (b->callback != NULL || b->callback_ex != NULL) { + ret = (int)bio_call_callback(b, BIO_CB_READ | BIO_CB_RETURN, + out, outl, 0, 0L, (ret > 0) ? 1 : ret, &readbytes); + } - return (i); + if (ret > 0) { + if (readbytes > INT_MAX) { + BIOerror(BIO_R_LENGTH_TOO_LONG); + ret = -1; + } else { + ret = (int)readbytes; + } + } + + return (ret); } int BIO_write(BIO *b, const void *in, int inl) { - int i; - long (*cb)(BIO *, int, const char *, int, long, long); + size_t writebytes = 0; + int ret; if (b == NULL) return (0); @@ -300,95 +384,132 @@ BIO_write(BIO *b, const void *in, int inl) return (-2); } - cb = b->callback; - if ((cb != NULL) && - ((i = (int)cb(b, BIO_CB_WRITE, in, inl, 0L, 1L)) <= 0)) - return (i); + if (b->callback != NULL || b->callback_ex != NULL) { + if ((ret = (int)bio_call_callback(b, BIO_CB_WRITE, in, inl, 0, + 0L, 1L, NULL)) <= 0) + return (ret); + } if (!b->init) { BIOerror(BIO_R_UNINITIALIZED); return (-2); } - i = b->method->bwrite(b, in, inl); + if ((ret = b->method->bwrite(b, in, inl)) > 0) + writebytes = ret; - if (i > 0) - b->num_write += (unsigned long)i; + b->num_write += writebytes; - if (cb != NULL) - i = (int)cb(b, BIO_CB_WRITE|BIO_CB_RETURN, in, inl, - 0L, (long)i); - return (i); + if (b->callback != NULL || b->callback_ex != NULL) { + ret = (int)bio_call_callback(b, BIO_CB_WRITE | BIO_CB_RETURN, + in, inl, 0, 0L, (ret > 0) ? 1 : ret, &writebytes); + } + + if (ret > 0) { + if (writebytes > INT_MAX) { + BIOerror(BIO_R_LENGTH_TOO_LONG); + ret = -1; + } else { + ret = (int)writebytes; + } + } + + return (ret); } int BIO_puts(BIO *b, const char *in) { - int i; - long (*cb)(BIO *, int, const char *, int, long, long); + size_t writebytes = 0; + int ret; - if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) { + if (b == NULL || b->method == NULL || b->method->bputs == NULL) { BIOerror(BIO_R_UNSUPPORTED_METHOD); return (-2); } - cb = b->callback; - - if ((cb != NULL) && - ((i = (int)cb(b, BIO_CB_PUTS, in, 0, 0L, 1L)) <= 0)) - return (i); + if (b->callback != NULL || b->callback_ex != NULL) { + if ((ret = (int)bio_call_callback(b, BIO_CB_PUTS, in, 0, 0, 0L, + 1L, NULL)) <= 0) + return (ret); + } if (!b->init) { BIOerror(BIO_R_UNINITIALIZED); return (-2); } - i = b->method->bputs(b, in); + if ((ret = b->method->bputs(b, in)) > 0) + writebytes = ret; - if (i > 0) - b->num_write += (unsigned long)i; + b->num_write += writebytes; - if (cb != NULL) - i = (int)cb(b, BIO_CB_PUTS|BIO_CB_RETURN, in, 0, 0L, (long)i); - return (i); + if (b->callback != NULL || b->callback_ex != NULL) { + ret = (int)bio_call_callback(b, BIO_CB_PUTS | BIO_CB_RETURN, + in, 0, 0, 0L, (ret > 0) ? 1 : ret, &writebytes); + } + + if (ret > 0) { + if (writebytes > INT_MAX) { + BIOerror(BIO_R_LENGTH_TOO_LONG); + ret = -1; + } else { + ret = (int)writebytes; + } + } + + return (ret); } int BIO_gets(BIO *b, char *in, int inl) { - int i; - long (*cb)(BIO *, int, const char *, int, long, long); + size_t readbytes; + int ret; - if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) { + if (b == NULL || b->method == NULL || b->method->bgets == NULL) { BIOerror(BIO_R_UNSUPPORTED_METHOD); return (-2); } - cb = b->callback; - - if ((cb != NULL) && - ((i = (int)cb(b, BIO_CB_GETS, in, inl, 0L, 1L)) <= 0)) - return (i); + if (b->callback != NULL || b->callback_ex != NULL) { + if ((ret = (int)bio_call_callback(b, BIO_CB_GETS, in, inl, 0, 0L, + 1, NULL)) <= 0) + return (ret); + } if (!b->init) { BIOerror(BIO_R_UNINITIALIZED); return (-2); } - i = b->method->bgets(b, in, inl); + if ((ret = b->method->bgets(b, in, inl)) > 0) + readbytes = ret; - if (cb != NULL) - i = (int)cb(b, BIO_CB_GETS|BIO_CB_RETURN, in, inl, 0L, (long)i); - return (i); + if (b->callback != NULL || b->callback_ex != NULL) { + ret = (int)bio_call_callback(b, BIO_CB_GETS | BIO_CB_RETURN, in, + inl, 0, 0L, (ret > 0) ? 1 : ret, &readbytes); + } + + if (ret > 0) { + if (readbytes > INT_MAX) { + BIOerror(BIO_R_LENGTH_TOO_LONG); + ret = -1; + } else { + ret = (int)readbytes; + } + } + + return (ret); } int BIO_indent(BIO *b, int indent, int max) { - if (indent < 0) - indent = 0; if (indent > max) indent = max; + if (indent < 0) + indent = 0; while (indent--) if (BIO_puts(b, " ") != 1) return 0; @@ -419,54 +540,58 @@ long BIO_ctrl(BIO *b, int cmd, long larg, void *parg) { long ret; - long (*cb)(BIO *, int, const char *, int, long, long); if (b == NULL) return (0); - if ((b->method == NULL) || (b->method->ctrl == NULL)) { + if (b->method == NULL || b->method->ctrl == NULL) { BIOerror(BIO_R_UNSUPPORTED_METHOD); return (-2); } - cb = b->callback; - - if ((cb != NULL) && - ((ret = cb(b, BIO_CB_CTRL, parg, cmd, larg, 1L)) <= 0)) - return (ret); + if (b->callback != NULL || b->callback_ex != NULL) { + if ((ret = bio_call_callback(b, BIO_CB_CTRL, parg, 0, cmd, larg, + 1L, NULL)) <= 0) + return (ret); + } ret = b->method->ctrl(b, cmd, larg, parg); - if (cb != NULL) - ret = cb(b, BIO_CB_CTRL|BIO_CB_RETURN, parg, cmd, larg, ret); + if (b->callback != NULL || b->callback_ex != NULL) { + ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, 0, + cmd, larg, ret, NULL); + } + return (ret); } long -BIO_callback_ctrl(BIO *b, int cmd, - void (*fp)(struct bio_st *, int, const char *, int, long, long)) +BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { long ret; - long (*cb)(BIO *, int, const char *, int, long, long); if (b == NULL) return (0); - if ((b->method == NULL) || (b->method->callback_ctrl == NULL)) { + if (b->method == NULL || b->method->callback_ctrl == NULL || + cmd != BIO_CTRL_SET_CALLBACK) { BIOerror(BIO_R_UNSUPPORTED_METHOD); return (-2); } - cb = b->callback; - - if ((cb != NULL) && - ((ret = cb(b, BIO_CB_CTRL, (void *)&fp, cmd, 0, 1L)) <= 0)) - return (ret); + if (b->callback != NULL || b->callback_ex != NULL) { + if ((ret = bio_call_callback(b, BIO_CB_CTRL, (void *)&fp, 0, + cmd, 0, 1L, NULL)) <= 0) + return (ret); + } ret = b->method->callback_ctrl(b, cmd, fp); - if (cb != NULL) - ret = cb(b, BIO_CB_CTRL|BIO_CB_RETURN, (void *)&fp, cmd, 0, ret); + if (b->callback != NULL || b->callback_ex != NULL) { + ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, + (void *)&fp, 0, cmd, 0, ret, NULL); + } + return (ret); } @@ -552,6 +677,12 @@ BIO_get_retry_reason(BIO *bio) return (bio->retry_reason); } +void +BIO_set_retry_reason(BIO *bio, int reason) +{ + bio->retry_reason = reason; +} + BIO * BIO_find_type(BIO *bio, int type) { @@ -582,6 +713,12 @@ BIO_next(BIO *b) return b->next_bio; } +void +BIO_set_next(BIO *b, BIO *next) +{ + b->next_bio = next; +} + void BIO_free_all(BIO *bio) { @@ -608,6 +745,7 @@ BIO_dup_chain(BIO *in) if ((new_bio = BIO_new(bio->method)) == NULL) goto err; new_bio->callback = bio->callback; + new_bio->callback_ex = bio->callback_ex; new_bio->cb_arg = bio->cb_arg; new_bio->init = bio->init; new_bio->shutdown = bio->shutdown; diff --git a/crypto/asn1/a_bool.c b/crypto/bio/bio_local.h similarity index 64% rename from crypto/asn1/a_bool.c rename to crypto/bio/bio_local.h index e8469be..7e1885f 100644 --- a/crypto/asn1/a_bool.c +++ b/crypto/bio/bio_local.h @@ -1,4 +1,4 @@ -/* $OpenBSD: a_bool.c,v 1.8 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: bio_local.h,v 1.3 2022/01/14 08:40:57 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -56,60 +56,68 @@ * [including the GNU Public Licence.] */ -#include +#ifndef HEADER_BIO_LOCAL_H +#define HEADER_BIO_LOCAL_H -#include -#include +__BEGIN_HIDDEN_DECLS -int -i2d_ASN1_BOOLEAN(int a, unsigned char **pp) -{ - int r; - unsigned char *p; +struct bio_method_st { + int type; + const char *name; + int (*bwrite)(BIO *, const char *, int); + int (*bread)(BIO *, char *, int); + int (*bputs)(BIO *, const char *); + int (*bgets)(BIO *, char *, int); + long (*ctrl)(BIO *, int, long, void *); + int (*create)(BIO *); + int (*destroy)(BIO *); + long (*callback_ctrl)(BIO *, int, BIO_info_cb *); +} /* BIO_METHOD */; - r = ASN1_object_size(0, 1, V_ASN1_BOOLEAN); - if (pp == NULL) - return (r); - p = *pp; +struct bio_st { + const BIO_METHOD *method; + BIO_callback_fn callback; + BIO_callback_fn_ex callback_ex; + char *cb_arg; /* first argument for the callback */ - ASN1_put_object(&p, 0, 1, V_ASN1_BOOLEAN, V_ASN1_UNIVERSAL); - *(p++) = (unsigned char)a; - *pp = p; - return (r); -} + int init; + int shutdown; + int flags; /* extra storage */ + int retry_reason; + int num; + void *ptr; + struct bio_st *next_bio; /* used by filter BIOs */ + struct bio_st *prev_bio; /* used by filter BIOs */ + int references; + unsigned long num_read; + unsigned long num_write; -int -d2i_ASN1_BOOLEAN(int *a, const unsigned char **pp, long length) -{ - int ret = -1; - const unsigned char *p; - long len; - int inf, tag, xclass; - int i = 0; + CRYPTO_EX_DATA ex_data; +} /* BIO */; - p = *pp; - inf = ASN1_get_object(&p, &len, &tag, &xclass, length); - if (inf & 0x80) { - i = ASN1_R_BAD_OBJECT_HEADER; - goto err; - } +typedef struct bio_f_buffer_ctx_struct { + /* Buffers are setup like this: + * + * <---------------------- size -----------------------> + * +---------------------------------------------------+ + * | consumed | remaining | free space | + * +---------------------------------------------------+ + * <-- off --><------- len -------> + */ - if (tag != V_ASN1_BOOLEAN) { - i = ASN1_R_EXPECTING_A_BOOLEAN; - goto err; - } + /* BIO *bio; */ /* this is now in the BIO struct */ + int ibuf_size; /* how big is the input buffer */ + int obuf_size; /* how big is the output buffer */ - if (len != 1) { - i = ASN1_R_BOOLEAN_IS_WRONG_LENGTH; - goto err; - } - ret = (int)*(p++); - if (a != NULL) - (*a) = ret; - *pp = p; - return (ret); + char *ibuf; /* the char array */ + int ibuf_len; /* how many bytes are in it */ + int ibuf_off; /* write/read offset */ -err: - ASN1error(i); - return (ret); -} + char *obuf; /* the char array */ + int obuf_len; /* how many bytes are in it */ + int obuf_off; /* write/read offset */ +} BIO_F_BUFFER_CTX; + +__END_HIDDEN_DECLS + +#endif /* !HEADER_BIO_LOCAL_H */ diff --git a/crypto/bio/bio_meth.c b/crypto/bio/bio_meth.c index 4327c01..d7d100d 100644 --- a/crypto/bio/bio_meth.c +++ b/crypto/bio/bio_meth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bio_meth.c,v 1.6 2018/06/02 04:41:12 tb Exp $ */ +/* $OpenBSD: bio_meth.c,v 1.8 2022/01/14 08:40:57 tb Exp $ */ /* * Copyright (c) 2018 Theo Buehler * @@ -19,6 +19,8 @@ #include +#include "bio_local.h" + BIO_METHOD * BIO_meth_new(int type, const char *name) { @@ -133,15 +135,13 @@ BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy)(BIO *)) long (*BIO_meth_get_callback_ctrl(const BIO_METHOD *biom))(BIO *, int, BIO_info_cb *) { - return - (long (*)(BIO *, int, BIO_info_cb *))biom->callback_ctrl; /* XXX */ + return biom->callback_ctrl; } int BIO_meth_set_callback_ctrl(BIO_METHOD *biom, long (*callback_ctrl)(BIO *, int, BIO_info_cb *)) { - biom->callback_ctrl = - (long (*)(BIO *, int, bio_info_cb *))callback_ctrl; /* XXX */ + biom->callback_ctrl = callback_ctrl; return 1; } diff --git a/crypto/bio/bss_acpt.c b/crypto/bio/bss_acpt.c index c95ddde..a619bd7 100644 --- a/crypto/bio/bss_acpt.c +++ b/crypto/bio/bss_acpt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bss_acpt.c,v 1.29 2018/05/12 18:51:59 tb Exp $ */ +/* $OpenBSD: bss_acpt.c,v 1.30 2022/01/07 09:02:17 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -67,6 +67,8 @@ #include #include +#include "bio_local.h" + #define SOCKET_PROTOCOL IPPROTO_TCP typedef struct bio_accept_st { diff --git a/crypto/bio/bss_bio.c b/crypto/bio/bss_bio.c index 74f86a5..c92d35d 100644 --- a/crypto/bio/bss_bio.c +++ b/crypto/bio/bss_bio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bss_bio.c,v 1.24 2018/05/01 13:29:09 tb Exp $ */ +/* $OpenBSD: bss_bio.c,v 1.25 2022/01/07 09:02:17 tb Exp $ */ /* ==================================================================== * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. * @@ -84,6 +84,8 @@ #include #include +#include "bio_local.h" + static int bio_new(BIO *bio); static int bio_free(BIO *bio); static int bio_read(BIO *bio, char *buf, int size); diff --git a/crypto/bio/bss_conn.c b/crypto/bio/bss_conn.c index 46a37b0..8e30bcc 100644 --- a/crypto/bio/bss_conn.c +++ b/crypto/bio/bss_conn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bss_conn.c,v 1.35 2018/05/12 18:51:59 tb Exp $ */ +/* $OpenBSD: bss_conn.c,v 1.37 2022/01/14 08:40:57 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -70,6 +70,8 @@ #include #include +#include "bio_local.h" + #define SOCKET_PROTOCOL IPPROTO_TCP typedef struct bio_connect_st { @@ -90,7 +92,7 @@ typedef struct bio_connect_st { /* called when the connection is initially made * callback(BIO,state,ret); The callback should return * 'ret'. state is for compatibility with the ssl info_callback */ - int (*info_callback)(const BIO *bio, int state, int ret); + BIO_info_cb *info_callback; } BIO_CONNECT; static int conn_write(BIO *h, const char *buf, int num); @@ -99,7 +101,7 @@ static int conn_puts(BIO *h, const char *str); static long conn_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int conn_new(BIO *h); static int conn_free(BIO *data); -static long conn_callback_ctrl(BIO *h, int cmd, bio_info_cb *); +static long conn_callback_ctrl(BIO *h, int cmd, BIO_info_cb *); static int conn_state(BIO *b, BIO_CONNECT *c); static void conn_close_socket(BIO *data); @@ -124,7 +126,7 @@ conn_state(BIO *b, BIO_CONNECT *c) int ret = -1, i; unsigned long l; char *p, *q; - int (*cb)(const BIO *, int, int) = NULL; + BIO_info_cb *cb = NULL; if (c->info_callback != NULL) cb = c->info_callback; @@ -521,9 +523,7 @@ conn_ctrl(BIO *b, int cmd, long num, void *ptr) BIO_set_conn_hostname(dbio, data->param_hostname); BIO_set_nbio(dbio, data->nbio); - /* FIXME: the cast of the function seems unlikely to be a good idea */ - (void)BIO_set_info_callback(dbio, - (bio_info_cb *)data->info_callback); + (void)BIO_set_info_callback(dbio, data->info_callback); } break; case BIO_CTRL_SET_CALLBACK: @@ -538,9 +538,8 @@ conn_ctrl(BIO *b, int cmd, long num, void *ptr) break; case BIO_CTRL_GET_CALLBACK: { - int (**fptr)(const BIO *bio, int state, int xret); + BIO_info_cb **fptr = ptr; - fptr = (int (**)(const BIO *bio, int state, int xret))ptr; *fptr = data->info_callback; } break; @@ -552,7 +551,7 @@ conn_ctrl(BIO *b, int cmd, long num, void *ptr) } static long -conn_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +conn_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { long ret = 1; BIO_CONNECT *data; @@ -561,9 +560,7 @@ conn_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) switch (cmd) { case BIO_CTRL_SET_CALLBACK: - { - data->info_callback = (int (*)(const struct bio_st *, int, int))fp; - } + data->info_callback = (BIO_info_cb *)fp; break; default: ret = 0; diff --git a/crypto/bio/bss_dgram.c b/crypto/bio/bss_dgram.c index 794b6d1..fa6e2db 100644 --- a/crypto/bio/bss_dgram.c +++ b/crypto/bio/bss_dgram.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bss_dgram.c,v 1.42 2018/05/12 17:47:53 tb Exp $ */ +/* $OpenBSD: bss_dgram.c,v 1.43 2022/01/07 09:02:17 tb Exp $ */ /* * DTLS implementation written by Nagendra Modadugu * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. @@ -72,6 +72,8 @@ #include +#include "bio_local.h" + #ifndef OPENSSL_NO_DGRAM diff --git a/crypto/bio/bss_fd.c b/crypto/bio/bss_fd.c index bbe08ef..7d7c427 100644 --- a/crypto/bio/bss_fd.c +++ b/crypto/bio/bss_fd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bss_fd.c,v 1.19 2018/05/01 13:29:09 tb Exp $ */ +/* $OpenBSD: bss_fd.c,v 1.20 2022/01/07 09:02:17 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -65,6 +65,8 @@ #include +#include "bio_local.h" + static int fd_write(BIO *h, const char *buf, int num); static int fd_read(BIO *h, char *buf, int size); static int fd_puts(BIO *h, const char *str); diff --git a/crypto/bio/bss_file.c b/crypto/bio/bss_file.c index fe93738..0c9b755 100644 --- a/crypto/bio/bss_file.c +++ b/crypto/bio/bss_file.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bss_file.c,v 1.33 2018/05/30 00:23:04 tb Exp $ */ +/* $OpenBSD: bss_file.c,v 1.34 2022/01/07 09:02:17 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -90,6 +90,8 @@ #include #include +#include "bio_local.h" + static int file_write(BIO *h, const char *buf, int num); static int file_read(BIO *h, char *buf, int size); static int file_puts(BIO *h, const char *str); diff --git a/crypto/bio/bss_log.c b/crypto/bio/bss_log.c index 7ef1312..296c87f 100644 --- a/crypto/bio/bss_log.c +++ b/crypto/bio/bss_log.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bss_log.c,v 1.22 2018/05/01 13:29:10 tb Exp $ */ +/* $OpenBSD: bss_log.c,v 1.23 2022/01/07 09:02:17 tb Exp $ */ /* ==================================================================== * Copyright (c) 1999 The OpenSSL Project. All rights reserved. * @@ -70,6 +70,8 @@ #include #include +#include "bio_local.h" + #ifndef NO_SYSLOG static int slg_write(BIO *h, const char *buf, int num); diff --git a/crypto/bio/bss_mem.c b/crypto/bio/bss_mem.c index e76e1ad..2d03083 100644 --- a/crypto/bio/bss_mem.c +++ b/crypto/bio/bss_mem.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bss_mem.c,v 1.17 2018/05/12 18:51:59 tb Exp $ */ +/* $OpenBSD: bss_mem.c,v 1.21 2022/02/19 15:59:12 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -57,6 +57,7 @@ */ #include +#include #include #include @@ -64,13 +65,35 @@ #include #include -static int mem_write(BIO *h, const char *buf, int num); -static int mem_read(BIO *h, char *buf, int size); -static int mem_puts(BIO *h, const char *str); -static int mem_gets(BIO *h, char *str, int size); -static long mem_ctrl(BIO *h, int cmd, long arg1, void *arg2); -static int mem_new(BIO *h); -static int mem_free(BIO *data); +#include "bio_local.h" + +struct bio_mem { + BUF_MEM *buf; + size_t read_offset; +}; + +static size_t +bio_mem_pending(struct bio_mem *bm) +{ + if (bm->read_offset > bm->buf->length) + return 0; + + return bm->buf->length - bm->read_offset; +} + +static uint8_t * +bio_mem_read_ptr(struct bio_mem *bm) +{ + return &bm->buf->data[bm->read_offset]; +} + +static int mem_new(BIO *bio); +static int mem_free(BIO *bio); +static int mem_write(BIO *bio, const char *in, int in_len); +static int mem_read(BIO *bio, char *out, int out_len); +static int mem_puts(BIO *bio, const char *in); +static int mem_gets(BIO *bio, char *out, int out_len); +static long mem_ctrl(BIO *bio, int cmd, long arg1, void *arg2); static const BIO_METHOD mem_method = { .type = BIO_TYPE_MEM, @@ -84,181 +107,207 @@ static const BIO_METHOD mem_method = { .destroy = mem_free }; -/* bio->num is used to hold the value to return on 'empty', if it is - * 0, should_retry is not set */ +/* + * bio->num is used to hold the value to return on 'empty', if it is + * 0, should_retry is not set. + */ const BIO_METHOD * BIO_s_mem(void) { - return (&mem_method); + return &mem_method; } BIO * -BIO_new_mem_buf(const void *buf, int len) +BIO_new_mem_buf(const void *buf, int buf_len) { - BIO *ret; - BUF_MEM *b; - size_t sz; + struct bio_mem *bm; + BIO *bio; - if (!buf) { + if (buf == NULL) { BIOerror(BIO_R_NULL_PARAMETER); return NULL; } - sz = (len < 0) ? strlen(buf) : (size_t)len; - if (!(ret = BIO_new(BIO_s_mem()))) + if (buf_len == -1) + buf_len = strlen(buf); + if (buf_len < 0) { + BIOerror(BIO_R_INVALID_ARGUMENT); return NULL; - b = (BUF_MEM *)ret->ptr; - b->data = (void *)buf; /* Trust in the BIO_FLAGS_MEM_RDONLY flag. */ - b->length = sz; - b->max = sz; - ret->flags |= BIO_FLAGS_MEM_RDONLY; - /* Since this is static data retrying wont help */ - ret->num = 0; - return ret; -} - -static int -mem_new(BIO *bi) -{ - BUF_MEM *b; - - if ((b = BUF_MEM_new()) == NULL) - return (0); - bi->shutdown = 1; - bi->init = 1; - bi->num = -1; - bi->ptr = (char *)b; - return (1); -} - -static int -mem_free(BIO *a) -{ - if (a == NULL) - return (0); - if (a->shutdown) { - if ((a->init) && (a->ptr != NULL)) { - BUF_MEM *b; - b = (BUF_MEM *)a->ptr; - if (a->flags & BIO_FLAGS_MEM_RDONLY) - b->data = NULL; - BUF_MEM_free(b); - a->ptr = NULL; - } - } - return (1); -} - -static int -mem_read(BIO *b, char *out, int outl) -{ - int ret = -1; - BUF_MEM *bm; - - bm = (BUF_MEM *)b->ptr; - BIO_clear_retry_flags(b); - ret = (outl >=0 && (size_t)outl > bm->length) ? (int)bm->length : outl; - if ((out != NULL) && (ret > 0)) { - memcpy(out, bm->data, ret); - bm->length -= ret; - if (b->flags & BIO_FLAGS_MEM_RDONLY) - bm->data += ret; - else { - memmove(&(bm->data[0]), &(bm->data[ret]), bm->length); - } - } else if (bm->length == 0) { - ret = b->num; - if (ret != 0) - BIO_set_retry_read(b); - } - return (ret); -} - -static int -mem_write(BIO *b, const char *in, int inl) -{ - int ret = -1; - int blen; - BUF_MEM *bm; - - bm = (BUF_MEM *)b->ptr; - if (in == NULL) { - BIOerror(BIO_R_NULL_PARAMETER); - goto end; } - if (b->flags & BIO_FLAGS_MEM_RDONLY) { + if ((bio = BIO_new(BIO_s_mem())) == NULL) + return NULL; + + bm = bio->ptr; + bm->buf->data = (void *)buf; /* Trust in the BIO_FLAGS_MEM_RDONLY flag. */ + bm->buf->length = buf_len; + bm->buf->max = buf_len; + bio->flags |= BIO_FLAGS_MEM_RDONLY; + /* Since this is static data retrying will not help. */ + bio->num = 0; + + return bio; +} + +static int +mem_new(BIO *bio) +{ + struct bio_mem *bm; + + if ((bm = calloc(1, sizeof(*bm))) == NULL) + return 0; + if ((bm->buf = BUF_MEM_new()) == NULL) { + free(bm); + return 0; + } + + bio->shutdown = 1; + bio->init = 1; + bio->num = -1; + bio->ptr = bm; + + return 1; +} + +static int +mem_free(BIO *bio) +{ + struct bio_mem *bm; + + if (bio == NULL) + return 0; + if (!bio->init || bio->ptr == NULL) + return 1; + + bm = bio->ptr; + if (bio->shutdown) { + if (bio->flags & BIO_FLAGS_MEM_RDONLY) + bm->buf->data = NULL; + BUF_MEM_free(bm->buf); + } + free(bm); + bio->ptr = NULL; + + return 1; +} + +static int +mem_read(BIO *bio, char *out, int out_len) +{ + struct bio_mem *bm = bio->ptr; + + BIO_clear_retry_flags(bio); + + if (out == NULL || out_len <= 0) + return 0; + + if ((size_t)out_len > bio_mem_pending(bm)) + out_len = bio_mem_pending(bm); + + if (out_len == 0) { + if (bio->num != 0) + BIO_set_retry_read(bio); + return bio->num; + } + + memcpy(out, bio_mem_read_ptr(bm), out_len); + bm->read_offset += out_len; + + return out_len; +} + +static int +mem_write(BIO *bio, const char *in, int in_len) +{ + struct bio_mem *bm = bio->ptr; + size_t buf_len; + + BIO_clear_retry_flags(bio); + + if (in == NULL || in_len <= 0) + return 0; + + if (bio->flags & BIO_FLAGS_MEM_RDONLY) { BIOerror(BIO_R_WRITE_TO_READ_ONLY_BIO); - goto end; + return -1; } - BIO_clear_retry_flags(b); - blen = bm->length; - if (BUF_MEM_grow_clean(bm, blen + inl) != (blen + inl)) - goto end; - memcpy(&(bm->data[blen]), in, inl); - ret = inl; -end: - return (ret); + if (bm->read_offset > 4096) { + memmove(bm->buf->data, bio_mem_read_ptr(bm), + bio_mem_pending(bm)); + bm->buf->length = bio_mem_pending(bm); + bm->read_offset = 0; + } + + /* + * Check for overflow and ensure we do not exceed an int, otherwise we + * cannot tell if BUF_MEM_grow_clean() succeeded. + */ + buf_len = bm->buf->length + in_len; + if (buf_len < bm->buf->length || buf_len > INT_MAX) + return -1; + + if (BUF_MEM_grow_clean(bm->buf, buf_len) != buf_len) + return -1; + + memcpy(&bm->buf->data[buf_len - in_len], in, in_len); + + return in_len; } static long -mem_ctrl(BIO *b, int cmd, long num, void *ptr) +mem_ctrl(BIO *bio, int cmd, long num, void *ptr) { + struct bio_mem *bm = bio->ptr; + void **pptr; long ret = 1; - char **pptr; - - BUF_MEM *bm = (BUF_MEM *)b->ptr; switch (cmd) { case BIO_CTRL_RESET: - if (bm->data != NULL) { - /* For read only case reset to the start again */ - if (b->flags & BIO_FLAGS_MEM_RDONLY) { - bm->data -= bm->max - bm->length; - bm->length = bm->max; - } else { - memset(bm->data, 0, bm->max); - bm->length = 0; + if (bm->buf->data != NULL) { + if (!(bio->flags & BIO_FLAGS_MEM_RDONLY)) { + memset(bm->buf->data, 0, bm->buf->max); + bm->buf->length = 0; } + bm->read_offset = 0; } break; case BIO_CTRL_EOF: - ret = (long)(bm->length == 0); + ret = (long)(bio_mem_pending(bm) == 0); break; case BIO_C_SET_BUF_MEM_EOF_RETURN: - b->num = (int)num; + bio->num = (int)num; break; case BIO_CTRL_INFO: - ret = (long)bm->length; if (ptr != NULL) { - pptr = (char **)ptr; - *pptr = (char *)&(bm->data[0]); + pptr = (void **)ptr; + *pptr = bio_mem_read_ptr(bm); } + ret = (long)bio_mem_pending(bm); break; case BIO_C_SET_BUF_MEM: - mem_free(b); - b->shutdown = (int)num; - b->ptr = ptr; + BUF_MEM_free(bm->buf); + bio->shutdown = (int)num; + bm->buf = ptr; + bm->read_offset = 0; break; case BIO_C_GET_BUF_MEM_PTR: if (ptr != NULL) { - pptr = (char **)ptr; - *pptr = (char *)bm; + pptr = (void **)ptr; + *pptr = bm->buf; } break; case BIO_CTRL_GET_CLOSE: - ret = (long)b->shutdown; + ret = (long)bio->shutdown; break; case BIO_CTRL_SET_CLOSE: - b->shutdown = (int)num; + bio->shutdown = (int)num; break; - case BIO_CTRL_WPENDING: ret = 0L; break; case BIO_CTRL_PENDING: - ret = (long)bm->length; + ret = (long)bio_mem_pending(bm); break; case BIO_CTRL_DUP: case BIO_CTRL_FLUSH: @@ -270,27 +319,29 @@ mem_ctrl(BIO *b, int cmd, long num, void *ptr) ret = 0; break; } - return (ret); + return ret; } static int -mem_gets(BIO *bp, char *buf, int size) +mem_gets(BIO *bio, char *out, int out_len) { - int i, j; - int ret = -1; + struct bio_mem *bm = bio->ptr; + int i, out_max; char *p; - BUF_MEM *bm = (BUF_MEM *)bp->ptr; + int ret = -1; - BIO_clear_retry_flags(bp); - j = bm->length; - if ((size - 1) < j) - j = size - 1; - if (j <= 0) { - *buf = '\0'; + BIO_clear_retry_flags(bio); + + out_max = bio_mem_pending(bm); + if (out_len - 1 < out_max) + out_max = out_len - 1; + if (out_max <= 0) { + *out = '\0'; return 0; } - p = bm->data; - for (i = 0; i < j; i++) { + + p = bio_mem_read_ptr(bm); + for (i = 0; i < out_max; i++) { if (p[i] == '\n') { i++; break; @@ -298,24 +349,17 @@ mem_gets(BIO *bp, char *buf, int size) } /* - * i is now the max num of bytes to copy, either j or up to - * and including the first newline + * i is now the max num of bytes to copy, either out_max or up to and + * including the first newline */ + if ((ret = mem_read(bio, out, i)) > 0) + out[ret] = '\0'; - i = mem_read(bp, buf, i); - if (i > 0) - buf[i] = '\0'; - ret = i; - return (ret); + return ret; } static int -mem_puts(BIO *bp, const char *str) +mem_puts(BIO *bio, const char *in) { - int n, ret; - - n = strlen(str); - ret = mem_write(bp, str, n); - /* memory semantics is that it will always work */ - return (ret); + return mem_write(bio, in, strlen(in)); } diff --git a/crypto/bio/bss_null.c b/crypto/bio/bss_null.c index c6de844..8a15b36 100644 --- a/crypto/bio/bss_null.c +++ b/crypto/bio/bss_null.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bss_null.c,v 1.11 2018/05/01 13:29:10 tb Exp $ */ +/* $OpenBSD: bss_null.c,v 1.12 2022/01/07 09:02:17 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -62,6 +62,8 @@ #include +#include "bio_local.h" + static int null_write(BIO *h, const char *buf, int num); static int null_read(BIO *h, char *buf, int size); static int null_puts(BIO *h, const char *str); diff --git a/crypto/bio/bss_sock.c b/crypto/bio/bss_sock.c index 9c650a8..3b9a87f 100644 --- a/crypto/bio/bss_sock.c +++ b/crypto/bio/bss_sock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bss_sock.c,v 1.24 2018/05/01 13:29:10 tb Exp $ */ +/* $OpenBSD: bss_sock.c,v 1.25 2022/01/07 09:02:17 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -65,6 +65,8 @@ #include +#include "bio_local.h" + static int sock_write(BIO *h, const char *buf, int num); static int sock_read(BIO *h, char *buf, int size); static int sock_puts(BIO *h, const char *str); diff --git a/crypto/bn/bn_exp2.c b/crypto/bn/bn_exp2.c index 372e1ee..c63503f 100644 --- a/crypto/bn/bn_exp2.c +++ b/crypto/bn/bn_exp2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bn_exp2.c,v 1.12 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: bn_exp2.c,v 1.13 2022/02/07 19:49:56 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -136,7 +136,7 @@ BN_mod_exp2_mont(BIGNUM *rr, const BIGNUM *a1, const BIGNUM *p1, bn_check_top(p2); bn_check_top(m); - if (!(m->d[0] & 1)) { + if (!BN_is_odd(m)) { BNerror(BN_R_CALLED_WITH_EVEN_MODULUS); return (0); } diff --git a/crypto/bn/bn_gcd.c b/crypto/bn/bn_gcd.c index 469ae75..d756398 100644 --- a/crypto/bn/bn_gcd.c +++ b/crypto/bn/bn_gcd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bn_gcd.c,v 1.15 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: bn_gcd.c,v 1.16 2021/12/26 15:16:50 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -576,6 +576,9 @@ BN_mod_inverse_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, bn_check_top(a); bn_check_top(n); + BN_init(&local_A); + BN_init(&local_B); + BN_CTX_start(ctx); if ((A = BN_CTX_get(ctx)) == NULL) goto err; @@ -608,10 +611,12 @@ BN_mod_inverse_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, A->neg = 0; if (B->neg || (BN_ucmp(B, A) >= 0)) { - /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, - * BN_div_no_branch will be called eventually. - */ + /* + * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, + * BN_div_no_branch will be called eventually. + */ pB = &local_B; + /* BN_init() done at the top of the function. */ BN_with_flags(pB, B, BN_FLG_CONSTTIME); if (!BN_nnmod(B, pB, A, ctx)) goto err; @@ -633,10 +638,12 @@ BN_mod_inverse_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, * sign*Y*a == A (mod |n|) */ - /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, - * BN_div_no_branch will be called eventually. - */ + /* + * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, + * BN_div_no_branch will be called eventually. + */ pA = &local_A; + /* BN_init() done at the top of the function. */ BN_with_flags(pA, A, BN_FLG_CONSTTIME); /* (D, M) := (A/B, A%B) ... */ @@ -740,6 +747,9 @@ BN_gcd_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, goto err; R = in; + BN_init(&local_A); + BN_init(&local_B); + bn_check_top(a); bn_check_top(n); @@ -768,10 +778,12 @@ BN_gcd_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, A->neg = 0; if (B->neg || (BN_ucmp(B, A) >= 0)) { - /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, - * BN_div_no_branch will be called eventually. - */ + /* + * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, + * BN_div_no_branch will be called eventually. + */ pB = &local_B; + /* BN_init() done at the top of the function. */ BN_with_flags(pB, B, BN_FLG_CONSTTIME); if (!BN_nnmod(B, pB, A, ctx)) goto err; @@ -793,10 +805,12 @@ BN_gcd_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, * sign*Y*a == A (mod |n|) */ - /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, - * BN_div_no_branch will be called eventually. - */ + /* + * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, + * BN_div_no_branch will be called eventually. + */ pA = &local_A; + /* BN_init() done at the top of the function. */ BN_with_flags(pA, A, BN_FLG_CONSTTIME); /* (D, M) := (A/B, A%B) ... */ diff --git a/crypto/bn/bn_lcl.h b/crypto/bn/bn_lcl.h index a165d02..5f16660 100644 --- a/crypto/bn/bn_lcl.h +++ b/crypto/bn/bn_lcl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bn_lcl.h,v 1.30 2018/11/05 23:52:47 tb Exp $ */ +/* $OpenBSD: bn_lcl.h,v 1.31 2022/01/14 08:01:47 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -118,6 +118,50 @@ __BEGIN_HIDDEN_DECLS +struct bignum_st { + BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit chunks. */ + int top; /* Index of last used d +1. */ + /* The next are internal book keeping for bn_expand. */ + int dmax; /* Size of the d array. */ + int neg; /* one if the number is negative */ + int flags; +}; + +/* Used for montgomery multiplication */ +struct bn_mont_ctx_st { + int ri; /* number of bits in R */ + BIGNUM RR; /* used to convert to montgomery form */ + BIGNUM N; /* The modulus */ + BIGNUM Ni; /* R*(1/R mod N) - N*Ni = 1 + * (Ni is only stored for bignum algorithm) */ + BN_ULONG n0[2];/* least significant word(s) of Ni; + (type changed with 0.9.9, was "BN_ULONG n0;" before) */ + int flags; +}; + +/* Used for reciprocal division/mod functions + * It cannot be shared between threads + */ +struct bn_recp_ctx_st { + BIGNUM N; /* the divisor */ + BIGNUM Nr; /* the reciprocal */ + int num_bits; + int shift; + int flags; +}; + +/* Used for slow "generation" functions. */ +struct bn_gencb_st { + unsigned int ver; /* To handle binary (in)compatibility */ + void *arg; /* callback-specific data */ + union { + /* if(ver==1) - handles old style callbacks */ + void (*cb_1)(int, int, void *); + /* if(ver==2) - new callback style */ + int (*cb_2)(int, int, BN_GENCB *); + } cb; +}; + /* * BN_window_bits_for_exponent_size -- macro for sliding window mod_exp functions * diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c index af837ee..6e828f1 100644 --- a/crypto/bn/bn_lib.c +++ b/crypto/bn/bn_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bn_lib.c,v 1.48 2021/09/08 12:19:17 tb Exp $ */ +/* $OpenBSD: bn_lib.c,v 1.53 2021/12/27 15:12:22 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -92,6 +92,63 @@ static int bn_limit_num_high = 8; /* (1<flags = BN_FLG_MALLOCED; + ret->top = 0; + ret->neg = 0; + ret->dmax = 0; + ret->d = NULL; + bn_check_top(ret); + return (ret); +} + +void +BN_init(BIGNUM *a) +{ + memset(a, 0, sizeof(BIGNUM)); + bn_check_top(a); +} + +void +BN_clear(BIGNUM *a) +{ + bn_check_top(a); + if (a->d != NULL) + explicit_bzero(a->d, a->dmax * sizeof(a->d[0])); + a->top = 0; + a->neg = 0; +} + +void +BN_clear_free(BIGNUM *a) +{ + int i; + + if (a == NULL) + return; + bn_check_top(a); + if (a->d != NULL && !(BN_get_flags(a, BN_FLG_STATIC_DATA))) + freezero(a->d, a->dmax * sizeof(a->d[0])); + i = BN_get_flags(a, BN_FLG_MALLOCED); + explicit_bzero(a, sizeof(BIGNUM)); + if (i) + free(a); +} + +void +BN_free(BIGNUM *a) +{ + BN_clear_free(a); +} + void BN_set_params(int mult, int high, int low, int mont) { @@ -137,6 +194,30 @@ BN_get_params(int which) } #endif +void +BN_set_flags(BIGNUM *b, int n) +{ + b->flags |= n; +} + +int +BN_get_flags(const BIGNUM *b, int n) +{ + return b->flags & n; +} + +void +BN_with_flags(BIGNUM *dest, const BIGNUM *b, int flags) +{ + int dest_flags; + + dest_flags = (dest->flags & BN_FLG_MALLOCED) | + (b->flags & ~BN_FLG_MALLOCED) | BN_FLG_STATIC_DATA | flags; + + *dest = *b; + dest->flags = dest_flags; +} + const BIGNUM * BN_value_one(void) { @@ -182,53 +263,6 @@ BN_num_bits(const BIGNUM *a) return ((i * BN_BITS2) + BN_num_bits_word(a->d[i])); } -void -BN_clear_free(BIGNUM *a) -{ - int i; - - if (a == NULL) - return; - bn_check_top(a); - if (a->d != NULL && !(BN_get_flags(a, BN_FLG_STATIC_DATA))) - freezero(a->d, a->dmax * sizeof(a->d[0])); - i = BN_get_flags(a, BN_FLG_MALLOCED); - explicit_bzero(a, sizeof(BIGNUM)); - if (i) - free(a); -} - -void -BN_free(BIGNUM *a) -{ - BN_clear_free(a); -} - -void -BN_init(BIGNUM *a) -{ - memset(a, 0, sizeof(BIGNUM)); - bn_check_top(a); -} - -BIGNUM * -BN_new(void) -{ - BIGNUM *ret; - - if ((ret = malloc(sizeof(BIGNUM))) == NULL) { - BNerror(ERR_R_MALLOC_FAILURE); - return (NULL); - } - ret->flags = BN_FLG_MALLOCED; - ret->top = 0; - ret->neg = 0; - ret->dmax = 0; - ret->d = NULL; - bn_check_top(ret); - return (ret); -} - /* This is used both by bn_expand2() and bn_dup_expand() */ /* The caller MUST check that words > b->dmax before calling this */ static BN_ULONG * @@ -494,16 +528,6 @@ BN_swap(BIGNUM *a, BIGNUM *b) bn_check_top(b); } -void -BN_clear(BIGNUM *a) -{ - bn_check_top(a); - if (a->d != NULL) - explicit_bzero(a->d, a->dmax * sizeof(a->d[0])); - a->top = 0; - a->neg = 0; -} - BN_ULONG BN_get_word(const BIGNUM *a) { @@ -1037,6 +1061,50 @@ BN_swap_ct(BN_ULONG condition, BIGNUM *a, BIGNUM *b, size_t nwords) return 1; } +void +BN_zero_ex(BIGNUM *a) +{ + a->neg = 0; + a->top = 0; + /* XXX: a->flags &= ~BN_FIXED_TOP */ +} + +int +BN_abs_is_word(const BIGNUM *a, const BN_ULONG w) +{ + return (a->top == 1 && a->d[0] == w) || (w == 0 && a->top == 0); +} + +int +BN_is_zero(const BIGNUM *a) +{ + return a->top == 0; +} + +int +BN_is_one(const BIGNUM *a) +{ + return BN_abs_is_word(a, 1) && !a->neg; +} + +int +BN_is_word(const BIGNUM *a, const BN_ULONG w) +{ + return BN_abs_is_word(a, w) && (w == 0 || !a->neg); +} + +int +BN_is_odd(const BIGNUM *a) +{ + return a->top > 0 && (a->d[0] & 1); +} + +int +BN_is_negative(const BIGNUM *a) +{ + return a->neg != 0; +} + BN_GENCB * BN_GENCB_new(void) { @@ -1056,6 +1124,24 @@ BN_GENCB_free(BN_GENCB *cb) free(cb); } +/* Populate a BN_GENCB structure with an "old"-style callback */ +void +BN_GENCB_set_old(BN_GENCB *gencb, void (*cb)(int, int, void *), void *cb_arg) +{ + gencb->ver = 1; + gencb->cb.cb_1 = cb; + gencb->arg = cb_arg; +} + +/* Populate a BN_GENCB structure with a "new"-style callback */ +void +BN_GENCB_set(BN_GENCB *gencb, int (*cb)(int, int, BN_GENCB *), void *cb_arg) +{ + gencb->ver = 2; + gencb->cb.cb_2 = cb; + gencb->arg = cb_arg; +} + void * BN_GENCB_get_arg(BN_GENCB *cb) { diff --git a/crypto/bn/bn_mont.c b/crypto/bn/bn_mont.c index eeac046..e01af70 100644 --- a/crypto/bn/bn_mont.c +++ b/crypto/bn/bn_mont.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bn_mont.c,v 1.26 2017/01/21 11:00:46 beck Exp $ */ +/* $OpenBSD: bn_mont.c,v 1.28 2022/02/07 19:44:23 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -175,6 +175,12 @@ err: return (ret); } +int +BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, BN_CTX *ctx) +{ + return BN_mod_mul_montgomery(r, a, &mont->RR, mont, ctx); +} + #ifdef MONT_WORD static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) @@ -363,6 +369,9 @@ BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) int ret = 0; BIGNUM *Ri, *R; + if (BN_is_zero(mod)) + return 0; + BN_CTX_start(ctx); if ((Ri = BN_CTX_get(ctx)) == NULL) goto err; diff --git a/crypto/bn/bn_nist.c b/crypto/bn/bn_nist.c index b16584d..3a04c47 100644 --- a/crypto/bn/bn_nist.c +++ b/crypto/bn/bn_nist.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bn_nist.c,v 1.18 2016/07/18 01:04:52 bcook Exp $ */ +/* $OpenBSD: bn_nist.c,v 1.19 2021/11/09 18:40:20 bcook Exp $ */ /* * Written by Nils Larsch for the OpenSSL project */ @@ -56,8 +56,7 @@ * */ -#include - +#include #include #include diff --git a/crypto/bn/bn_print.c b/crypto/bn/bn_print.c index d849b86..9b5c753 100644 --- a/crypto/bn/bn_print.c +++ b/crypto/bn/bn_print.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bn_print.c,v 1.32 2021/08/31 11:19:19 tb Exp $ */ +/* $OpenBSD: bn_print.c,v 1.33 2022/01/20 10:53:33 inoguchi Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -310,8 +310,10 @@ BN_dec2bn(BIGNUM **bn, const char *a) l += *a - '0'; a++; if (++j == BN_DEC_NUM) { - BN_mul_word(ret, BN_DEC_CONV); - BN_add_word(ret, l); + if (!BN_mul_word(ret, BN_DEC_CONV)) + goto err; + if (!BN_add_word(ret, l)) + goto err; l = 0; j = 0; } diff --git a/crypto/bn/bn_sqrt.c b/crypto/bn/bn_sqrt.c index 8514f23..4b9638b 100644 --- a/crypto/bn/bn_sqrt.c +++ b/crypto/bn/bn_sqrt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bn_sqrt.c,v 1.9 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: bn_sqrt.c,v 1.10 2022/03/15 15:52:39 tb Exp $ */ /* Written by Lenka Fibikova * and Bodo Moeller for the OpenSSL project. */ /* ==================================================================== @@ -351,21 +351,22 @@ BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) goto vrfy; } - - /* find smallest i such that b^(2^i) = 1 */ - i = 1; - if (!BN_mod_sqr(t, b, p, ctx)) - goto end; - while (!BN_is_one(t)) { - i++; - if (i == e) { - BNerror(BN_R_NOT_A_SQUARE); - goto end; + /* Find the smallest i with 0 < i < e such that b^(2^i) = 1. */ + for (i = 1; i < e; i++) { + if (i == 1) { + if (!BN_mod_sqr(t, b, p, ctx)) + goto end; + } else { + if (!BN_mod_sqr(t, t, p, ctx)) + goto end; } - if (!BN_mod_mul(t, t, t, p, ctx)) - goto end; + if (BN_is_one(t)) + break; + } + if (i >= e) { + BNerror(BN_R_NOT_A_SQUARE); + goto end; } - /* t := y^2^(e - i - 1) */ if (!BN_copy(t, y)) diff --git a/crypto/bn/bn_x931p.c b/crypto/bn/bn_x931p.c index 55ca21c..7fc3b5c 100644 --- a/crypto/bn/bn_x931p.c +++ b/crypto/bn/bn_x931p.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bn_x931p.c,v 1.11 2019/01/20 01:56:59 tb Exp $ */ +/* $OpenBSD: bn_x931p.c,v 1.13 2022/01/20 10:56:22 inoguchi Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2005. */ @@ -139,13 +139,13 @@ BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2, const BIGNUM *Xp, /* First set p to value of Rp */ - if (!BN_mod_inverse_ct(p, p2, p1, ctx)) + if (BN_mod_inverse_ct(p, p2, p1, ctx) == NULL) goto err; if (!BN_mul(p, p, p2, ctx)) goto err; - if (!BN_mod_inverse_ct(t, p1, p2, ctx)) + if (BN_mod_inverse_ct(t, p1, p2, ctx) == NULL) goto err; if (!BN_mul(t, t, p1, ctx)) @@ -154,7 +154,7 @@ BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2, const BIGNUM *Xp, if (!BN_sub(p, p, t)) goto err; - if (p->neg && !BN_add(p, p, p1p2)) + if (BN_is_negative(p) && !BN_add(p, p, p1p2)) goto err; /* p now equals Rp */ @@ -237,7 +237,8 @@ BN_X931_generate_Xpq(BIGNUM *Xp, BIGNUM *Xq, int nbits, BN_CTX *ctx) if (!BN_rand(Xq, nbits, 1, 0)) goto err; /* Check that |Xp - Xq| > 2^(nbits - 100) */ - BN_sub(t, Xp, Xq); + if (!BN_sub(t, Xp, Xq)) + goto err; if (BN_num_bits(t) > (nbits - 100)) break; } diff --git a/crypto/bn/gf2m-masm-x86_64.S b/crypto/bn/gf2m-masm-x86_64.S index 8fcaa2d..a3ce027 100644 --- a/crypto/bn/gf2m-masm-x86_64.S +++ b/crypto/bn/gf2m-masm-x86_64.S @@ -1,7 +1,7 @@ ; 1 "crypto/bn/gf2m-masm-x86_64.S.tmp" ; 1 "" 1 ; 1 "" 3 -; 340 "" 3 +; 343 "" 3 ; 1 "" 1 ; 1 "" 2 ; 1 "crypto/bn/gf2m-masm-x86_64.S.tmp" 2 diff --git a/crypto/bn/modexp512-masm-x86_64.S b/crypto/bn/modexp512-masm-x86_64.S index 453cfac..9626fe3 100644 --- a/crypto/bn/modexp512-masm-x86_64.S +++ b/crypto/bn/modexp512-masm-x86_64.S @@ -1,7 +1,7 @@ ; 1 "crypto/bn/modexp512-masm-x86_64.S.tmp" ; 1 "" 1 ; 1 "" 3 -; 340 "" 3 +; 343 "" 3 ; 1 "" 1 ; 1 "" 2 ; 1 "crypto/bn/modexp512-masm-x86_64.S.tmp" 2 diff --git a/crypto/bn/mont-masm-x86_64.S b/crypto/bn/mont-masm-x86_64.S index c943f15..4896acd 100644 --- a/crypto/bn/mont-masm-x86_64.S +++ b/crypto/bn/mont-masm-x86_64.S @@ -1,7 +1,7 @@ ; 1 "crypto/bn/mont-masm-x86_64.S.tmp" ; 1 "" 1 ; 1 "" 3 -; 340 "" 3 +; 343 "" 3 ; 1 "" 1 ; 1 "" 2 ; 1 "crypto/bn/mont-masm-x86_64.S.tmp" 2 diff --git a/crypto/bn/mont5-masm-x86_64.S b/crypto/bn/mont5-masm-x86_64.S index dbbbe35..cc709e6 100644 --- a/crypto/bn/mont5-masm-x86_64.S +++ b/crypto/bn/mont5-masm-x86_64.S @@ -1,7 +1,7 @@ ; 1 "crypto/bn/mont5-masm-x86_64.S.tmp" ; 1 "" 1 ; 1 "" 3 -; 340 "" 3 +; 343 "" 3 ; 1 "" 1 ; 1 "" 2 ; 1 "crypto/bn/mont5-masm-x86_64.S.tmp" 2 diff --git a/crypto/bytestring/bs_ber.c b/crypto/bytestring/bs_ber.c new file mode 100644 index 0000000..c9779c8 --- /dev/null +++ b/crypto/bytestring/bs_ber.c @@ -0,0 +1,269 @@ +/* $OpenBSD: bs_ber.c,v 1.2 2021/12/15 18:02:39 jsing Exp $ */ +/* + * Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "bytestring.h" + +/* + * kMaxDepth is a just a sanity limit. The code should be such that the length + * of the input being processes always decreases. None the less, a very large + * input could otherwise cause the stack to overflow. + */ +static const unsigned int kMaxDepth = 2048; + +/* Non-strict version that allows a relaxed DER with indefinite form. */ +static int +cbs_nonstrict_get_any_asn1_element(CBS *cbs, CBS *out, unsigned int *out_tag, + size_t *out_header_len) +{ + return cbs_get_any_asn1_element_internal(cbs, out, + out_tag, out_header_len, 0); +} + +/* + * cbs_find_indefinite walks an ASN.1 structure in |orig_in| and sets + * |*indefinite_found| depending on whether an indefinite length element was + * found. The value of |orig_in| is not modified. + * + * Returns one on success (i.e. |*indefinite_found| was set) and zero on error. + */ +static int +cbs_find_indefinite(const CBS *orig_in, char *indefinite_found, + unsigned int depth) +{ + CBS in; + + if (depth > kMaxDepth) + return 0; + + CBS_init(&in, CBS_data(orig_in), CBS_len(orig_in)); + + while (CBS_len(&in) > 0) { + CBS contents; + unsigned int tag; + size_t header_len; + + if (!cbs_nonstrict_get_any_asn1_element(&in, &contents, &tag, + &header_len)) + return 0; + + /* Indefinite form not allowed by DER. */ + if (CBS_len(&contents) == header_len && header_len > 0 && + CBS_data(&contents)[header_len - 1] == 0x80) { + *indefinite_found = 1; + return 1; + } + if (tag & CBS_ASN1_CONSTRUCTED) { + if (!CBS_skip(&contents, header_len) || + !cbs_find_indefinite(&contents, indefinite_found, + depth + 1)) + return 0; + } + } + + *indefinite_found = 0; + return 1; +} + +/* + * is_primitive_type returns true if |tag| likely a primitive type. Normally + * one can just test the "constructed" bit in the tag but, in BER, even + * primitive tags can have the constructed bit if they have indefinite + * length. + */ +static char +is_primitive_type(unsigned int tag) +{ + return (tag & 0xc0) == 0 && + (tag & 0x1f) != (CBS_ASN1_SEQUENCE & 0x1f) && + (tag & 0x1f) != (CBS_ASN1_SET & 0x1f); +} + +/* + * is_eoc returns true if |header_len| and |contents|, as returned by + * |cbs_nonstrict_get_any_asn1_element|, indicate an "end of contents" (EOC) + * value. + */ +static char +is_eoc(size_t header_len, CBS *contents) +{ + const unsigned char eoc[] = {0x0, 0x0}; + + return header_len == 2 && CBS_mem_equal(contents, eoc, 2); +} + +/* + * cbs_convert_indefinite reads data with DER encoding (but relaxed to allow + * indefinite form) from |in| and writes definite form DER data to |out|. If + * |squash_header| is set then the top-level of elements from |in| will not + * have their headers written. This is used when concatenating the fragments of + * an indefinite length, primitive value. If |looking_for_eoc| is set then any + * EOC elements found will cause the function to return after consuming it. + * It returns one on success and zero on error. + */ +static int +cbs_convert_indefinite(CBS *in, CBB *out, char squash_header, + char looking_for_eoc, unsigned int depth) +{ + if (depth > kMaxDepth) + return 0; + + while (CBS_len(in) > 0) { + CBS contents; + unsigned int tag; + size_t header_len; + CBB *out_contents, out_contents_storage; + + if (!cbs_nonstrict_get_any_asn1_element(in, &contents, &tag, + &header_len)) + return 0; + + out_contents = out; + + if (CBS_len(&contents) == header_len) { + if (is_eoc(header_len, &contents)) + return looking_for_eoc; + + if (header_len > 0 && + CBS_data(&contents)[header_len - 1] == 0x80) { + /* + * This is an indefinite length element. If + * it's a SEQUENCE or SET then we just need to + * write the out the contents as normal, but + * with a concrete length prefix. + * + * If it's a something else then the contents + * will be a series of DER elements of the same + * type which need to be concatenated. + */ + const char context_specific = (tag & 0xc0) + == 0x80; + char squash_child_headers = + is_primitive_type(tag); + + /* + * This is a hack, but it sufficies to handle + * NSS's output. If we find an indefinite + * length, context-specific tag with a definite, + * primtive tag inside it, then we assume that + * the context-specific tag is implicit and the + * tags within are fragments of a primitive type + * that need to be concatenated. + */ + if (context_specific && + (tag & CBS_ASN1_CONSTRUCTED)) { + CBS in_copy, inner_contents; + unsigned int inner_tag; + size_t inner_header_len; + + CBS_init(&in_copy, CBS_data(in), + CBS_len(in)); + if (!cbs_nonstrict_get_any_asn1_element( + &in_copy, &inner_contents, + &inner_tag, &inner_header_len)) + return 0; + + if (CBS_len(&inner_contents) > + inner_header_len && + is_primitive_type(inner_tag)) + squash_child_headers = 1; + } + + if (!squash_header) { + unsigned int out_tag = tag; + + if (squash_child_headers) + out_tag &= + ~CBS_ASN1_CONSTRUCTED; + + if (!CBB_add_asn1(out, + &out_contents_storage, out_tag)) + return 0; + + out_contents = &out_contents_storage; + } + + if (!cbs_convert_indefinite(in, out_contents, + squash_child_headers, + 1 /* looking for eoc */, depth + 1)) + return 0; + + if (out_contents != out && !CBB_flush(out)) + return 0; + + continue; + } + } + + if (!squash_header) { + if (!CBB_add_asn1(out, &out_contents_storage, tag)) + return 0; + + out_contents = &out_contents_storage; + } + + if (!CBS_skip(&contents, header_len)) + return 0; + + if (tag & CBS_ASN1_CONSTRUCTED) { + if (!cbs_convert_indefinite(&contents, out_contents, + 0 /* don't squash header */, + 0 /* not looking for eoc */, depth + 1)) + return 0; + } else { + if (!CBB_add_bytes(out_contents, CBS_data(&contents), + CBS_len(&contents))) + return 0; + } + + if (out_contents != out && !CBB_flush(out)) + return 0; + } + + return looking_for_eoc == 0; +} + +int +CBS_asn1_indefinite_to_definite(CBS *in, uint8_t **out, size_t *out_len) +{ + CBB cbb; + + /* + * First, do a quick walk to find any indefinite-length elements. Most + * of the time we hope that there aren't any and thus we can quickly + * return. + */ + char conversion_needed; + if (!cbs_find_indefinite(in, &conversion_needed, 0)) + return 0; + + if (!conversion_needed) { + *out = NULL; + *out_len = 0; + return 1; + } + + if (!CBB_init(&cbb, CBS_len(in))) + return 0; + if (!cbs_convert_indefinite(in, &cbb, 0, 0, 0)) { + CBB_cleanup(&cbb); + return 0; + } + + return CBB_finish(&cbb, out, out_len); +} diff --git a/crypto/bytestring/bs_cbb.c b/crypto/bytestring/bs_cbb.c new file mode 100644 index 0000000..1300931 --- /dev/null +++ b/crypto/bytestring/bs_cbb.c @@ -0,0 +1,480 @@ +/* $OpenBSD: bs_cbb.c,v 1.3 2022/01/06 14:32:55 jsing Exp $ */ +/* + * Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "bytestring.h" + +#define CBB_INITIAL_SIZE 64 + +static int +cbb_init(CBB *cbb, uint8_t *buf, size_t cap) +{ + struct cbb_buffer_st *base; + + if ((base = calloc(1, sizeof(struct cbb_buffer_st))) == NULL) + return 0; + + base->buf = buf; + base->len = 0; + base->cap = cap; + base->can_resize = 1; + + cbb->base = base; + cbb->is_top_level = 1; + + return 1; +} + +int +CBB_init(CBB *cbb, size_t initial_capacity) +{ + uint8_t *buf = NULL; + + memset(cbb, 0, sizeof(*cbb)); + + if (initial_capacity == 0) + initial_capacity = CBB_INITIAL_SIZE; + + if ((buf = calloc(1, initial_capacity)) == NULL) + return 0; + + if (!cbb_init(cbb, buf, initial_capacity)) { + free(buf); + return 0; + } + + return 1; +} + +int +CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) +{ + memset(cbb, 0, sizeof(*cbb)); + + if (!cbb_init(cbb, buf, len)) + return 0; + + cbb->base->can_resize = 0; + + return 1; +} + +void +CBB_cleanup(CBB *cbb) +{ + if (cbb->base) { + if (cbb->base->can_resize) + freezero(cbb->base->buf, cbb->base->cap); + free(cbb->base); + } + cbb->base = NULL; + cbb->child = NULL; +} + +static int +cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out, size_t len) +{ + size_t newlen; + + if (base == NULL) + return 0; + + newlen = base->len + len; + if (newlen < base->len) + /* Overflow */ + return 0; + + if (newlen > base->cap) { + size_t newcap = base->cap * 2; + uint8_t *newbuf; + + if (!base->can_resize) + return 0; + + if (newcap < base->cap || newcap < newlen) + newcap = newlen; + + newbuf = recallocarray(base->buf, base->cap, newcap, 1); + if (newbuf == NULL) + return 0; + + base->buf = newbuf; + base->cap = newcap; + } + + if (out) + *out = base->buf + base->len; + + base->len = newlen; + return 1; +} + +static int +cbb_add_u(CBB *cbb, uint32_t v, size_t len_len) +{ + uint8_t *buf; + size_t i; + + if (len_len == 0) + return 1; + + if (len_len > 4) + return 0; + + if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, &buf, len_len)) + return 0; + + for (i = len_len - 1; i < len_len; i--) { + buf[i] = v; + v >>= 8; + } + return 1; +} + +int +CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) +{ + if (!cbb->is_top_level) + return 0; + + if (!CBB_flush(cbb)) + return 0; + + if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) + /* + * |out_data| and |out_len| can only be NULL if the CBB is + * fixed. + */ + return 0; + + if (out_data != NULL) + *out_data = cbb->base->buf; + + if (out_len != NULL) + *out_len = cbb->base->len; + + cbb->base->buf = NULL; + CBB_cleanup(cbb); + return 1; +} + +/* + * CBB_flush recurses and then writes out any pending length prefix. The current + * length of the underlying base is taken to be the length of the + * length-prefixed data. + */ +int +CBB_flush(CBB *cbb) +{ + size_t child_start, i, len; + + if (cbb->base == NULL) + return 0; + + if (cbb->child == NULL || cbb->pending_len_len == 0) + return 1; + + child_start = cbb->offset + cbb->pending_len_len; + + if (!CBB_flush(cbb->child) || child_start < cbb->offset || + cbb->base->len < child_start) + return 0; + + len = cbb->base->len - child_start; + + if (cbb->pending_is_asn1) { + /* + * For ASN.1, we assumed that we were using short form which + * only requires a single byte for the length octet. + * + * If it turns out that we need long form, we have to move + * the contents along in order to make space for more length + * octets. + */ + size_t len_len = 1; /* total number of length octets */ + uint8_t initial_length_byte; + + /* We already wrote 1 byte for the length. */ + if (cbb->pending_len_len != 1) + return 0; + + /* Check for long form */ + if (len > 0xfffffffe) + return 0; /* 0xffffffff is reserved */ + else if (len > 0xffffff) + len_len = 5; + else if (len > 0xffff) + len_len = 4; + else if (len > 0xff) + len_len = 3; + else if (len > 0x7f) + len_len = 2; + + if (len_len == 1) { + /* For short form, the initial byte is the length. */ + initial_length_byte = len; + len = 0; + + } else { + /* + * For long form, the initial byte is the number of + * subsequent length octets (plus bit 8 set). + */ + initial_length_byte = 0x80 | (len_len - 1); + + /* + * We need to move the contents along in order to make + * space for the long form length octets. + */ + size_t extra_bytes = len_len - 1; + if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) + return 0; + + memmove(cbb->base->buf + child_start + extra_bytes, + cbb->base->buf + child_start, len); + } + cbb->base->buf[cbb->offset++] = initial_length_byte; + cbb->pending_len_len = len_len - 1; + } + + for (i = cbb->pending_len_len - 1; i < cbb->pending_len_len; i--) { + cbb->base->buf[cbb->offset + i] = len; + len >>= 8; + } + if (len != 0) + return 0; + + cbb->child->base = NULL; + cbb->child = NULL; + cbb->pending_len_len = 0; + cbb->pending_is_asn1 = 0; + cbb->offset = 0; + + return 1; +} + +void +CBB_discard_child(CBB *cbb) +{ + if (cbb->child == NULL) + return; + + cbb->base->len = cbb->offset; + + cbb->child->base = NULL; + cbb->child = NULL; + cbb->pending_len_len = 0; + cbb->pending_is_asn1 = 0; + cbb->offset = 0; +} + +static int +cbb_add_length_prefixed(CBB *cbb, CBB *out_contents, size_t len_len) +{ + uint8_t *prefix_bytes; + + if (!CBB_flush(cbb)) + return 0; + + cbb->offset = cbb->base->len; + if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) + return 0; + + memset(prefix_bytes, 0, len_len); + memset(out_contents, 0, sizeof(CBB)); + out_contents->base = cbb->base; + cbb->child = out_contents; + cbb->pending_len_len = len_len; + cbb->pending_is_asn1 = 0; + + return 1; +} + +int +CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) +{ + return cbb_add_length_prefixed(cbb, out_contents, 1); +} + +int +CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) +{ + return cbb_add_length_prefixed(cbb, out_contents, 2); +} + +int +CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) +{ + return cbb_add_length_prefixed(cbb, out_contents, 3); +} + +int +CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned int tag) +{ + if (tag > UINT8_MAX) + return 0; + + /* Long form identifier octets are not supported. */ + if ((tag & 0x1f) == 0x1f) + return 0; + + /* Short-form identifier octet only needs a single byte */ + if (!CBB_flush(cbb) || !CBB_add_u8(cbb, tag)) + return 0; + + /* + * Add 1 byte to cover the short-form length octet case. If it turns + * out we need long-form, it will be extended later. + */ + cbb->offset = cbb->base->len; + if (!CBB_add_u8(cbb, 0)) + return 0; + + memset(out_contents, 0, sizeof(CBB)); + out_contents->base = cbb->base; + cbb->child = out_contents; + cbb->pending_len_len = 1; + cbb->pending_is_asn1 = 1; + + return 1; +} + +int +CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) +{ + uint8_t *dest; + + if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, &dest, len)) + return 0; + + memcpy(dest, data, len); + return 1; +} + +int +CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) +{ + if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, out_data, len)) + return 0; + + memset(*out_data, 0, len); + return 1; +} + +int +CBB_add_u8(CBB *cbb, size_t value) +{ + if (value > UINT8_MAX) + return 0; + + return cbb_add_u(cbb, (uint32_t)value, 1); +} + +int +CBB_add_u16(CBB *cbb, size_t value) +{ + if (value > UINT16_MAX) + return 0; + + return cbb_add_u(cbb, (uint32_t)value, 2); +} + +int +CBB_add_u24(CBB *cbb, size_t value) +{ + if (value > 0xffffffUL) + return 0; + + return cbb_add_u(cbb, (uint32_t)value, 3); +} + +int +CBB_add_u32(CBB *cbb, size_t value) +{ + if (value > 0xffffffffUL) + return 0; + + return cbb_add_u(cbb, (uint32_t)value, 4); +} + +int +CBB_add_u64(CBB *cbb, uint64_t value) +{ + uint32_t a, b; + + a = value >> 32; + b = value & 0xffffffff; + + if (!CBB_add_u32(cbb, a)) + return 0; + return CBB_add_u32(cbb, b); +} + +int +CBB_add_asn1_uint64(CBB *cbb, uint64_t value) +{ + CBB child; + size_t i; + int started = 0; + + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) + return 0; + + for (i = 0; i < 8; i++) { + uint8_t byte = (value >> 8 * (7 - i)) & 0xff; + + /* + * ASN.1 restriction: first 9 bits cannot be all zeroes or + * all ones. Since this function only encodes unsigned + * integers, the only concerns are not encoding leading + * zeros and adding a padding byte if necessary. + * + * In practice, this means: + * 1) Skip leading octets of all zero bits in the value + * 2) After skipping the leading zero octets, if the next 9 + * bits are all ones, add an all zero prefix octet (and + * set the high bit of the prefix octet if negative). + * + * Additionally, for an unsigned value, add an all zero + * prefix if the high bit of the first octet would be one. + */ + if (!started) { + if (byte == 0) + /* Don't encode leading zeros. */ + continue; + + /* + * If the high bit is set, add a padding byte to make it + * unsigned. + */ + if ((byte & 0x80) && !CBB_add_u8(&child, 0)) + return 0; + + started = 1; + } + if (!CBB_add_u8(&child, byte)) + return 0; + } + + /* 0 is encoded as a single 0, not the empty string. */ + if (!started && !CBB_add_u8(&child, 0)) + return 0; + + return CBB_flush(cbb); +} diff --git a/crypto/bytestring/bs_cbs.c b/crypto/bytestring/bs_cbs.c new file mode 100644 index 0000000..e2bb54e --- /dev/null +++ b/crypto/bytestring/bs_cbs.c @@ -0,0 +1,615 @@ +/* $OpenBSD: bs_cbs.c,v 1.2 2021/12/15 18:02:39 jsing Exp $ */ +/* + * Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "bytestring.h" + +void +CBS_init(CBS *cbs, const uint8_t *data, size_t len) +{ + cbs->data = data; + cbs->initial_len = len; + cbs->len = len; +} + +void +CBS_dup(const CBS *cbs, CBS *out) +{ + CBS_init(out, CBS_data(cbs), CBS_len(cbs)); + out->initial_len = cbs->initial_len; +} + +static int +cbs_get(CBS *cbs, const uint8_t **p, size_t n) +{ + if (cbs->len < n) + return 0; + + *p = cbs->data; + cbs->data += n; + cbs->len -= n; + return 1; +} + +static int +cbs_peek(CBS *cbs, const uint8_t **p, size_t n) +{ + if (cbs->len < n) + return 0; + + *p = cbs->data; + return 1; +} + +size_t +CBS_offset(const CBS *cbs) +{ + return cbs->initial_len - cbs->len; +} + +int +CBS_skip(CBS *cbs, size_t len) +{ + const uint8_t *dummy; + return cbs_get(cbs, &dummy, len); +} + +const uint8_t * +CBS_data(const CBS *cbs) +{ + return cbs->data; +} + +size_t +CBS_len(const CBS *cbs) +{ + return cbs->len; +} + +int +CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) +{ + free(*out_ptr); + *out_ptr = NULL; + *out_len = 0; + + if (cbs->len == 0) + return 1; + + if ((*out_ptr = malloc(cbs->len)) == NULL) + return 0; + + memcpy(*out_ptr, cbs->data, cbs->len); + + *out_len = cbs->len; + return 1; +} + +int +CBS_strdup(const CBS *cbs, char **out_ptr) +{ + free(*out_ptr); + *out_ptr = NULL; + + if (CBS_contains_zero_byte(cbs)) + return 0; + + *out_ptr = strndup((const char *)cbs->data, cbs->len); + return (*out_ptr != NULL); +} + +int +CBS_write_bytes(const CBS *cbs, uint8_t *dst, size_t dst_len, size_t *copied) +{ + if (dst_len < cbs->len) + return 0; + + memmove(dst, cbs->data, cbs->len); + + if (copied != NULL) + *copied = cbs->len; + + return 1; +} + +int +CBS_contains_zero_byte(const CBS *cbs) +{ + return memchr(cbs->data, 0, cbs->len) != NULL; +} + +int +CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) +{ + if (len != cbs->len) + return 0; + + return timingsafe_memcmp(cbs->data, data, len) == 0; +} + +static int +cbs_get_u(CBS *cbs, uint32_t *out, size_t len) +{ + uint32_t result = 0; + size_t i; + const uint8_t *data; + + if (len < 1 || len > 4) + return 0; + + if (!cbs_get(cbs, &data, len)) + return 0; + + for (i = 0; i < len; i++) { + result <<= 8; + result |= data[i]; + } + *out = result; + return 1; +} + +int +CBS_get_u8(CBS *cbs, uint8_t *out) +{ + const uint8_t *v; + + if (!cbs_get(cbs, &v, 1)) + return 0; + + *out = *v; + return 1; +} + +int +CBS_get_u16(CBS *cbs, uint16_t *out) +{ + uint32_t v; + + if (!cbs_get_u(cbs, &v, 2)) + return 0; + + *out = v; + return 1; +} + +int +CBS_get_u24(CBS *cbs, uint32_t *out) +{ + return cbs_get_u(cbs, out, 3); +} + +int +CBS_get_u32(CBS *cbs, uint32_t *out) +{ + return cbs_get_u(cbs, out, 4); +} + +int +CBS_get_u64(CBS *cbs, uint64_t *out) +{ + uint32_t a, b; + + if (cbs->len < 8) + return 0; + + if (!CBS_get_u32(cbs, &a)) + return 0; + if (!CBS_get_u32(cbs, &b)) + return 0; + + *out = (uint64_t)a << 32 | b; + return 1; +} + +int +CBS_get_last_u8(CBS *cbs, uint8_t *out) +{ + if (cbs->len == 0) + return 0; + + *out = cbs->data[cbs->len - 1]; + cbs->len--; + return 1; +} + +int +CBS_get_bytes(CBS *cbs, CBS *out, size_t len) +{ + const uint8_t *v; + + if (!cbs_get(cbs, &v, len)) + return 0; + + CBS_init(out, v, len); + return 1; +} + +static int +cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) +{ + uint32_t len; + + if (!cbs_get_u(cbs, &len, len_len)) + return 0; + + return CBS_get_bytes(cbs, out, len); +} + +int +CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) +{ + return cbs_get_length_prefixed(cbs, out, 1); +} + +int +CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) +{ + return cbs_get_length_prefixed(cbs, out, 2); +} + +int +CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) +{ + return cbs_get_length_prefixed(cbs, out, 3); +} + +static int +cbs_peek_u(CBS *cbs, uint32_t *out, size_t len) +{ + uint32_t result = 0; + size_t i; + const uint8_t *data; + + if (len < 1 || len > 4) + return 0; + + if (!cbs_peek(cbs, &data, len)) + return 0; + + for (i = 0; i < len; i++) { + result <<= 8; + result |= data[i]; + } + *out = result; + return 1; +} + +int +CBS_peek_u8(CBS *cbs, uint8_t *out) +{ + const uint8_t *v; + + if (!cbs_peek(cbs, &v, 1)) + return 0; + + *out = *v; + return 1; +} + +int +CBS_peek_u16(CBS *cbs, uint16_t *out) +{ + uint32_t v; + + if (!cbs_peek_u(cbs, &v, 2)) + return 0; + + *out = v; + return 1; +} + +int +CBS_peek_u24(CBS *cbs, uint32_t *out) +{ + return cbs_peek_u(cbs, out, 3); +} + +int +CBS_peek_u32(CBS *cbs, uint32_t *out) +{ + return cbs_peek_u(cbs, out, 4); +} + +int +CBS_peek_last_u8(CBS *cbs, uint8_t *out) +{ + if (cbs->len == 0) + return 0; + + *out = cbs->data[cbs->len - 1]; + return 1; +} + +int +CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned int *out_tag, + size_t *out_header_len) +{ + return cbs_get_any_asn1_element_internal(cbs, out, out_tag, + out_header_len, 1); +} + +/* + * Review X.690 for details on ASN.1 DER encoding. + * + * If non-strict mode is enabled, then DER rules are relaxed + * for indefinite constructs (violates DER but a little closer to BER). + * Non-strict mode should only be used by bs_ber.c + * + * Sections 8, 10 and 11 for DER encoding + */ +int +cbs_get_any_asn1_element_internal(CBS *cbs, CBS *out, unsigned int *out_tag, + size_t *out_header_len, int strict) +{ + uint8_t tag, length_byte; + CBS header = *cbs; + CBS throwaway; + size_t len; + + if (out == NULL) + out = &throwaway; + + /* + * Get identifier octet and length octet. Only 1 octet for each + * is a CBS limitation. + */ + if (!CBS_get_u8(&header, &tag) || !CBS_get_u8(&header, &length_byte)) + return 0; + + /* CBS limitation: long form tags are not supported. */ + if ((tag & 0x1f) == 0x1f) + return 0; + + if (out_tag != NULL) + *out_tag = tag; + + if ((length_byte & 0x80) == 0) { + /* Short form length. */ + len = ((size_t) length_byte) + 2; + if (out_header_len != NULL) + *out_header_len = 2; + + } else { + /* Long form length. */ + const size_t num_bytes = length_byte & 0x7f; + uint32_t len32; + + /* ASN.1 reserved value for future extensions */ + if (num_bytes == 0x7f) + return 0; + + /* Handle indefinite form length */ + if (num_bytes == 0) { + /* DER encoding doesn't allow for indefinite form. */ + if (strict) + return 0; + + /* Primitive cannot use indefinite in BER or DER. */ + if ((tag & CBS_ASN1_CONSTRUCTED) == 0) + return 0; + + /* Constructed, indefinite length allowed in BER. */ + if (out_header_len != NULL) + *out_header_len = 2; + return CBS_get_bytes(cbs, out, 2); + } + + /* CBS limitation. */ + if (num_bytes > 4) + return 0; + + if (!cbs_get_u(&header, &len32, num_bytes)) + return 0; + + /* DER has a minimum length octet requirement. */ + if (len32 < 128) + /* Should have used short form instead */ + return 0; + + if ((len32 >> ((num_bytes - 1) * 8)) == 0) + /* Length should have been at least one byte shorter. */ + return 0; + + len = len32; + if (len + 2 + num_bytes < len) + /* Overflow. */ + return 0; + + len += 2 + num_bytes; + if (out_header_len != NULL) + *out_header_len = 2 + num_bytes; + } + + return CBS_get_bytes(cbs, out, len); +} + +static int +cbs_get_asn1(CBS *cbs, CBS *out, unsigned int tag_value, int skip_header) +{ + size_t header_len; + unsigned int tag; + CBS throwaway; + + if (out == NULL) + out = &throwaway; + + if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) || + tag != tag_value) + return 0; + + if (skip_header && !CBS_skip(out, header_len)) + return 0; + + return 1; +} + +int +CBS_get_asn1(CBS *cbs, CBS *out, unsigned int tag_value) +{ + return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */); +} + +int +CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned int tag_value) +{ + return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */); +} + +int +CBS_peek_asn1_tag(const CBS *cbs, unsigned int tag_value) +{ + if (CBS_len(cbs) < 1) + return 0; + + /* + * Tag number 31 indicates the start of a long form number. + * This is valid in ASN.1, but CBS only supports short form. + */ + if ((tag_value & 0x1f) == 0x1f) + return 0; + + return CBS_data(cbs)[0] == tag_value; +} + +/* Encoding details are in ASN.1: X.690 section 8.3 */ +int +CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) +{ + CBS bytes; + const uint8_t *data; + size_t i, len; + + if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER)) + return 0; + + *out = 0; + data = CBS_data(&bytes); + len = CBS_len(&bytes); + + if (len == 0) + /* An INTEGER is encoded with at least one content octet. */ + return 0; + + if ((data[0] & 0x80) != 0) + /* Negative number. */ + return 0; + + if (data[0] == 0 && len > 1 && (data[1] & 0x80) == 0) + /* Violates smallest encoding rule: excessive leading zeros. */ + return 0; + + for (i = 0; i < len; i++) { + if ((*out >> 56) != 0) + /* Too large to represent as a uint64_t. */ + return 0; + + *out <<= 8; + *out |= data[i]; + } + + return 1; +} + +int +CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned int tag) +{ + if (CBS_peek_asn1_tag(cbs, tag)) { + if (!CBS_get_asn1(cbs, out, tag)) + return 0; + + *out_present = 1; + } else { + *out_present = 0; + } + return 1; +} + +int +CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present, + unsigned int tag) +{ + CBS child; + int present; + + if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) + return 0; + + if (present) { + if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) || + CBS_len(&child) != 0) + return 0; + } else { + CBS_init(out, NULL, 0); + } + if (out_present) + *out_present = present; + + return 1; +} + +int +CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned int tag, + uint64_t default_value) +{ + CBS child; + int present; + + if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) + return 0; + + if (present) { + if (!CBS_get_asn1_uint64(&child, out) || + CBS_len(&child) != 0) + return 0; + } else { + *out = default_value; + } + return 1; +} + +int +CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned int tag, + int default_value) +{ + CBS child, child2; + int present; + + if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) + return 0; + + if (present) { + uint8_t boolean; + + if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) || + CBS_len(&child2) != 1 || CBS_len(&child) != 0) + return 0; + + boolean = CBS_data(&child2)[0]; + if (boolean == 0) + *out = 0; + else if (boolean == 0xff) + *out = 1; + else + return 0; + + } else { + *out = default_value; + } + return 1; +} diff --git a/crypto/bytestring/bytestring.h b/crypto/bytestring/bytestring.h new file mode 100644 index 0000000..d8ef8ff --- /dev/null +++ b/crypto/bytestring/bytestring.h @@ -0,0 +1,566 @@ +/* $OpenBSD: bytestring.h,v 1.3 2022/01/06 14:32:55 jsing Exp $ */ +/* + * Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef OPENSSL_HEADER_BYTESTRING_H +#define OPENSSL_HEADER_BYTESTRING_H + +#include +#include + +__BEGIN_HIDDEN_DECLS + +/* + * Bytestrings are used for parsing and building TLS and ASN.1 messages. + * + * A "CBS" (CRYPTO ByteString) represents a string of bytes in memory and + * provides utility functions for safely parsing length-prefixed structures + * like TLS and ASN.1 from it. + * + * A "CBB" (CRYPTO ByteBuilder) is a memory buffer that grows as needed and + * provides utility functions for building length-prefixed messages. + */ + +/* CRYPTO ByteString */ +typedef struct cbs_st { + const uint8_t *data; + size_t initial_len; + size_t len; +} CBS; + +/* + * CBS_init sets |cbs| to point to |data|. It does not take ownership of + * |data|. + */ +void CBS_init(CBS *cbs, const uint8_t *data, size_t len); + +/* + * CBS_skip advances |cbs| by |len| bytes. It returns one on success and zero + * otherwise. + */ +int CBS_skip(CBS *cbs, size_t len); + +/* + * CBS_data returns a pointer to the contents of |cbs|. + */ +const uint8_t *CBS_data(const CBS *cbs); + +/* + * CBS_len returns the number of bytes remaining in |cbs|. + */ +size_t CBS_len(const CBS *cbs); + +/* + * CBS_offset returns the current offset into the original data of |cbs|. + */ +size_t CBS_offset(const CBS *cbs); + +/* + * CBS_stow copies the current contents of |cbs| into |*out_ptr| and + * |*out_len|. If |*out_ptr| is not NULL, the contents are freed with + * free. It returns one on success and zero on allocation failure. On + * success, |*out_ptr| should be freed with free. If |cbs| is empty, + * |*out_ptr| will be NULL. + */ +int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len); + +/* + * CBS_strdup copies the current contents of |cbs| into |*out_ptr| as a + * NUL-terminated C string. If |*out_ptr| is not NULL, the contents are freed + * with free. It returns one on success and zero on allocation + * failure. On success, |*out_ptr| should be freed with free. + * + * NOTE: If |cbs| contains NUL bytes, the string will be truncated. Call + * |CBS_contains_zero_byte(cbs)| to check for NUL bytes. + */ +int CBS_strdup(const CBS *cbs, char **out_ptr); + +/* + * CBS_write_bytes writes all of the remaining data from |cbs| into |dst| + * if it is at most |dst_len| bytes. If |copied| is not NULL, it will be set + * to the amount copied. It returns one on success and zero otherwise. + */ +int CBS_write_bytes(const CBS *cbs, uint8_t *dst, size_t dst_len, + size_t *copied); + +/* + * CBS_contains_zero_byte returns one if the current contents of |cbs| contains + * a NUL byte and zero otherwise. + */ +int CBS_contains_zero_byte(const CBS *cbs); + +/* + * CBS_mem_equal compares the current contents of |cbs| with the |len| bytes + * starting at |data|. If they're equal, it returns one, otherwise zero. If the + * lengths match, it uses a constant-time comparison. + */ +int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len); + +/* + * CBS_get_u8 sets |*out| to the next uint8_t from |cbs| and advances |cbs|. It + * returns one on success and zero on error. + */ +int CBS_get_u8(CBS *cbs, uint8_t *out); + +/* + * CBS_get_u16 sets |*out| to the next, big-endian uint16_t from |cbs| and + * advances |cbs|. It returns one on success and zero on error. + */ +int CBS_get_u16(CBS *cbs, uint16_t *out); + +/* + * CBS_get_u24 sets |*out| to the next, big-endian 24-bit value from |cbs| and + * advances |cbs|. It returns one on success and zero on error. + */ +int CBS_get_u24(CBS *cbs, uint32_t *out); + +/* + * CBS_get_u32 sets |*out| to the next, big-endian uint32_t value from |cbs| + * and advances |cbs|. It returns one on success and zero on error. + */ +int CBS_get_u32(CBS *cbs, uint32_t *out); + +/* + * CBS_get_u64 sets |*out| to the next, big-endian uint64_t value from |cbs| + * and advances |cbs|. It returns one on success and zero on error. + */ +int CBS_get_u64(CBS *cbs, uint64_t *out); + +/* + * CBS_get_last_u8 sets |*out| to the last uint8_t from |cbs| and shortens + * |cbs|. It returns one on success and zero on error. + */ +int CBS_get_last_u8(CBS *cbs, uint8_t *out); + +/* + * CBS_get_bytes sets |*out| to the next |len| bytes from |cbs| and advances + * |cbs|. It returns one on success and zero on error. + */ +int CBS_get_bytes(CBS *cbs, CBS *out, size_t len); + +/* + * CBS_get_u8_length_prefixed sets |*out| to the contents of an 8-bit, + * length-prefixed value from |cbs| and advances |cbs| over it. It returns one + * on success and zero on error. + */ +int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out); + +/* + * CBS_get_u16_length_prefixed sets |*out| to the contents of a 16-bit, + * big-endian, length-prefixed value from |cbs| and advances |cbs| over it. It + * returns one on success and zero on error. + */ +int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out); + +/* + * CBS_get_u24_length_prefixed sets |*out| to the contents of a 24-bit, + * big-endian, length-prefixed value from |cbs| and advances |cbs| over it. It + * returns one on success and zero on error. + */ +int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out); + +/* + * CBS_peek_u8 sets |*out| to the next uint8_t from |cbs|, but does not advance + * |cbs|. It returns one on success and zero on error. + */ +int CBS_peek_u8(CBS *cbs, uint8_t *out); + +/* + * CBS_peek_u16 sets |*out| to the next, big-endian uint16_t from |cbs|, but + * does not advance |cbs|. It returns one on success and zero on error. + */ +int CBS_peek_u16(CBS *cbs, uint16_t *out); + +/* + * CBS_peek_u24 sets |*out| to the next, big-endian 24-bit value from |cbs|, but + * does not advance |cbs|. It returns one on success and zero on error. + */ +int CBS_peek_u24(CBS *cbs, uint32_t *out); + +/* + * CBS_peek_u32 sets |*out| to the next, big-endian uint32_t value from |cbs|, + * but does not advance |cbs|. It returns one on success and zero on error. + */ +int CBS_peek_u32(CBS *cbs, uint32_t *out); + +/* + * CBS_peek_last_u8 sets |*out| to the last uint8_t from |cbs|, but does not + * shorten |cbs|. It returns one on success and zero on error. + */ +int CBS_peek_last_u8(CBS *cbs, uint8_t *out); + + +/* Parsing ASN.1 */ + +/* + * While an identifier can be multiple octets, this library only handles the + * single octet variety currently. This limits support up to tag number 30 + * since tag number 31 is a reserved value to indicate multiple octets. + */ + +/* Bits 8 and 7: class tag type: See X.690 section 8.1.2.2. */ +#define CBS_ASN1_UNIVERSAL 0x00 +#define CBS_ASN1_APPLICATION 0x40 +#define CBS_ASN1_CONTEXT_SPECIFIC 0x80 +#define CBS_ASN1_PRIVATE 0xc0 + +/* Bit 6: Primitive or constructed: See X.690 section 8.1.2.3. */ +#define CBS_ASN1_PRIMITIVE 0x00 +#define CBS_ASN1_CONSTRUCTED 0x20 + +/* + * Bits 5 to 1 are the tag number. See X.680 section 8.6 for tag numbers of + * the universal class. + */ + +/* + * Common universal identifier octets. + * See X.690 section 8.1 and X.680 section 8.6 for universal tag numbers. + * + * Note: These definitions are the cause of some of the strange behavior in + * CBS's bs_ber.c. + * + * In BER, it is the sender's option to use primitive or constructed for + * bitstring (X.690 section 8.6.1) and octetstring (X.690 section 8.7.1). + * + * In DER, bitstring and octetstring are required to be primitive + * (X.690 section 10.2). + */ +#define CBS_ASN1_BOOLEAN (CBS_ASN1_UNIVERSAL | CBS_ASN1_PRIMITIVE | 0x1) +#define CBS_ASN1_INTEGER (CBS_ASN1_UNIVERSAL | CBS_ASN1_PRIMITIVE | 0x2) +#define CBS_ASN1_BITSTRING (CBS_ASN1_UNIVERSAL | CBS_ASN1_PRIMITIVE | 0x3) +#define CBS_ASN1_OCTETSTRING (CBS_ASN1_UNIVERSAL | CBS_ASN1_PRIMITIVE | 0x4) +#define CBS_ASN1_OBJECT (CBS_ASN1_UNIVERSAL | CBS_ASN1_PRIMITIVE | 0x6) +#define CBS_ASN1_ENUMERATED (CBS_ASN1_UNIVERSAL | CBS_ASN1_PRIMITIVE | 0xa) +#define CBS_ASN1_SEQUENCE (CBS_ASN1_UNIVERSAL | CBS_ASN1_CONSTRUCTED | 0x10) +#define CBS_ASN1_SET (CBS_ASN1_UNIVERSAL | CBS_ASN1_CONSTRUCTED | 0x11) + +/* + * CBS_get_asn1 sets |*out| to the contents of DER-encoded, ASN.1 element (not + * including tag and length bytes) and advances |cbs| over it. The ASN.1 + * element must match |tag_value|. It returns one on success and zero + * on error. + * + * Tag numbers greater than 30 are not supported (i.e. short form only). + */ +int CBS_get_asn1(CBS *cbs, CBS *out, unsigned int tag_value); + +/* + * CBS_get_asn1_element acts like |CBS_get_asn1| but |out| will include the + * ASN.1 header bytes too. + */ +int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned int tag_value); + +/* + * CBS_peek_asn1_tag looks ahead at the next ASN.1 tag and returns one + * if the next ASN.1 element on |cbs| would have tag |tag_value|. If + * |cbs| is empty or the tag does not match, it returns zero. Note: if + * it returns one, CBS_get_asn1 may still fail if the rest of the + * element is malformed. + */ +int CBS_peek_asn1_tag(const CBS *cbs, unsigned int tag_value); + +/* + * CBS_get_any_asn1_element sets |*out| to contain the next ASN.1 element from + * |*cbs| (including header bytes) and advances |*cbs|. It sets |*out_tag| to + * the tag number and |*out_header_len| to the length of the ASN.1 header. + * Each of |out|, |out_tag|, and |out_header_len| may be NULL to ignore + * the value. + * + * Tag numbers greater than 30 are not supported (i.e. short form only). + */ +int CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned int *out_tag, + size_t *out_header_len); + +/* + * CBS_get_asn1_uint64 gets an ASN.1 INTEGER from |cbs| using |CBS_get_asn1| + * and sets |*out| to its value. It returns one on success and zero on error, + * where error includes the integer being negative, or too large to represent + * in 64 bits. + */ +int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out); + +/* + * CBS_get_optional_asn1 gets an optional explicitly-tagged element + * from |cbs| tagged with |tag| and sets |*out| to its contents. If + * present, it sets |*out_present| to one, otherwise zero. It returns + * one on success, whether or not the element was present, and zero on + * decode failure. + */ +int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, + unsigned int tag); + +/* + * CBS_get_optional_asn1_octet_string gets an optional + * explicitly-tagged OCTET STRING from |cbs|. If present, it sets + * |*out| to the string and |*out_present| to one. Otherwise, it sets + * |*out| to empty and |*out_present| to zero. |out_present| may be + * NULL. It returns one on success, whether or not the element was + * present, and zero on decode failure. + */ +int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present, + unsigned int tag); + +/* + * CBS_get_optional_asn1_uint64 gets an optional explicitly-tagged + * INTEGER from |cbs|. If present, it sets |*out| to the + * value. Otherwise, it sets |*out| to |default_value|. It returns one + * on success, whether or not the element was present, and zero on + * decode failure. + */ +int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned int tag, + uint64_t default_value); + +/* + * CBS_get_optional_asn1_bool gets an optional, explicitly-tagged BOOLEAN from + * |cbs|. If present, it sets |*out| to either zero or one, based on the + * boolean. Otherwise, it sets |*out| to |default_value|. It returns one on + * success, whether or not the element was present, and zero on decode + * failure. + */ +int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned int tag, + int default_value); + + +/* + * CRYPTO ByteBuilder. + * + * |CBB| objects allow one to build length-prefixed serialisations. A |CBB| + * object is associated with a buffer and new buffers are created with + * |CBB_init|. Several |CBB| objects can point at the same buffer when a + * length-prefix is pending, however only a single |CBB| can be 'current' at + * any one time. For example, if one calls |CBB_add_u8_length_prefixed| then + * the new |CBB| points at the same buffer as the original. But if the original + * |CBB| is used then the length prefix is written out and the new |CBB| must + * not be used again. + * + * If one needs to force a length prefix to be written out because a |CBB| is + * going out of scope, use |CBB_flush|. + */ + +struct cbb_buffer_st { + uint8_t *buf; + + /* The number of valid bytes. */ + size_t len; + + /* The size of buf. */ + size_t cap; + + /* + * One iff |buf| is owned by this object. If not then |buf| cannot be + * resized. + */ + char can_resize; +}; + +typedef struct cbb_st { + struct cbb_buffer_st *base; + + /* + * offset is the offset from the start of |base->buf| to the position of any + * pending length-prefix. + */ + size_t offset; + + /* child points to a child CBB if a length-prefix is pending. */ + struct cbb_st *child; + + /* + * pending_len_len contains the number of bytes in a pending length-prefix, + * or zero if no length-prefix is pending. + */ + uint8_t pending_len_len; + + char pending_is_asn1; + + /* + * is_top_level is true iff this is a top-level |CBB| (as opposed to a child + * |CBB|). Top-level objects are valid arguments for |CBB_finish|. + */ + char is_top_level; +} CBB; + +/* + * CBB_init initialises |cbb| with |initial_capacity|. Since a |CBB| grows as + * needed, the |initial_capacity| is just a hint. It returns one on success or + * zero on error. + */ +int CBB_init(CBB *cbb, size_t initial_capacity); + +/* + * CBB_init_fixed initialises |cbb| to write to |len| bytes at |buf|. Since + * |buf| cannot grow, trying to write more than |len| bytes will cause CBB + * functions to fail. It returns one on success or zero on error. + */ +int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len); + +/* + * CBB_cleanup frees all resources owned by |cbb| and other |CBB| objects + * writing to the same buffer. This should be used in an error case where a + * serialisation is abandoned. + */ +void CBB_cleanup(CBB *cbb); + +/* + * CBB_finish completes any pending length prefix and sets |*out_data| to a + * malloced buffer and |*out_len| to the length of that buffer. The caller + * takes ownership of the buffer and, unless the buffer was fixed with + * |CBB_init_fixed|, must call |free| when done. + * + * It can only be called on a "top level" |CBB|, i.e. one initialised with + * |CBB_init| or |CBB_init_fixed|. It returns one on success and zero on + * error. + */ +int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len); + +/* + * CBB_flush causes any pending length prefixes to be written out and any child + * |CBB| objects of |cbb| to be invalidated. It returns one on success or zero + * on error. + */ +int CBB_flush(CBB *cbb); + +/* + * CBB_discard_child discards the current unflushed child of |cbb|. Neither the + * child's contents nor the length prefix will be included in the output. + */ +void CBB_discard_child(CBB *cbb); + +/* + * CBB_add_u8_length_prefixed sets |*out_contents| to a new child of |cbb|. The + * data written to |*out_contents| will be prefixed in |cbb| with an 8-bit + * length. It returns one on success or zero on error. + */ +int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents); + +/* + * CBB_add_u16_length_prefixed sets |*out_contents| to a new child of |cbb|. + * The data written to |*out_contents| will be prefixed in |cbb| with a 16-bit, + * big-endian length. It returns one on success or zero on error. + */ +int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents); + +/* + * CBB_add_u24_length_prefixed sets |*out_contents| to a new child of |cbb|. + * The data written to |*out_contents| will be prefixed in |cbb| with a 24-bit, + * big-endian length. It returns one on success or zero on error. + */ +int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents); + +/* + * CBB_add_asn sets |*out_contents| to a |CBB| into which the contents of an + * ASN.1 object can be written. The |tag| argument will be used as the tag for + * the object. Passing in |tag| number 31 will return in an error since only + * single octet identifiers are supported. It returns one on success or zero + * on error. + */ +int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned int tag); + +/* + * CBB_add_bytes appends |len| bytes from |data| to |cbb|. It returns one on + * success and zero otherwise. + */ +int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len); + +/* + * CBB_add_space appends |len| bytes to |cbb| and sets |*out_data| to point to + * the beginning of that space. The caller must then write |len| bytes of + * actual contents to |*out_data|. It returns one on success and zero + * otherwise. + */ +int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len); + +/* + * CBB_add_u8 appends an 8-bit number from |value| to |cbb|. It returns one on + * success and zero otherwise. + */ +int CBB_add_u8(CBB *cbb, size_t value); + +/* + * CBB_add_u8 appends a 16-bit, big-endian number from |value| to |cbb|. It + * returns one on success and zero otherwise. + */ +int CBB_add_u16(CBB *cbb, size_t value); + +/* + * CBB_add_u24 appends a 24-bit, big-endian number from |value| to |cbb|. It + * returns one on success and zero otherwise. + */ +int CBB_add_u24(CBB *cbb, size_t value); + +/* + * CBB_add_u32 appends a 32-bit, big-endian number from |value| to |cbb|. It + * returns one on success and zero otherwise. + */ +int CBB_add_u32(CBB *cbb, size_t value); + +/* + * CBB_add_u64 appends a 64-bit, big-endian number from |value| to |cbb|. It + * returns one on success and zero otherwise. + */ +int CBB_add_u64(CBB *cbb, uint64_t value); + +/* + * CBB_add_asn1_uint64 writes an ASN.1 INTEGER into |cbb| using |CBB_add_asn1| + * and writes |value| in its contents. It returns one on success and zero on + * error. + */ +int CBB_add_asn1_uint64(CBB *cbb, uint64_t value); + +#ifdef LIBRESSL_INTERNAL +/* + * CBS_dup sets |out| to point to cbs's |data| and |len|. It results in two + * CBS that point to the same buffer. + */ +void CBS_dup(const CBS *cbs, CBS *out); + +/* + * cbs_get_any_asn1_element sets |*out| to contain the next ASN.1 element from + * |*cbs| (including header bytes) and advances |*cbs|. It sets |*out_tag| to + * the tag number and |*out_header_len| to the length of the ASN.1 header. If + * strict mode is disabled and the element has indefinite length then |*out| + * will only contain the header. Each of |out|, |out_tag|, and + * |out_header_len| may be NULL to ignore the value. + * + * Tag numbers greater than 30 are not supported (i.e. short form only). + */ +int cbs_get_any_asn1_element_internal(CBS *cbs, CBS *out, unsigned int *out_tag, + size_t *out_header_len, int strict); + +/* + * CBS_asn1_indefinite_to_definite reads an ASN.1 structure from |in|. If it + * finds indefinite-length elements that otherwise appear to be valid DER, it + * attempts to convert the DER-like data to DER and sets |*out| and + * |*out_length| to describe a malloced buffer containing the DER data. + * Additionally, |*in| will be advanced over the ASN.1 data. + * + * If it doesn't find any indefinite-length elements then it sets |*out| to + * NULL and |*in| is unmodified. + * + * This is NOT a conversion from BER to DER. There are many restrictions when + * dealing with DER data. This is only concerned with one: indefinite vs. + * definite form. However, this suffices to handle the PKCS#7 and PKCS#12 output + * from NSS. + * + * It returns one on success and zero otherwise. + */ +int CBS_asn1_indefinite_to_definite(CBS *in, uint8_t **out, size_t *out_len); +#endif /* LIBRESSL_INTERNAL */ + +__END_HIDDEN_DECLS + +#endif /* OPENSSL_HEADER_BYTESTRING_H */ diff --git a/crypto/camellia/cmll-masm-x86_64.S b/crypto/camellia/cmll-masm-x86_64.S index 9941bb9..e1871b5 100644 --- a/crypto/camellia/cmll-masm-x86_64.S +++ b/crypto/camellia/cmll-masm-x86_64.S @@ -1,7 +1,7 @@ ; 1 "crypto/camellia/cmll-masm-x86_64.S.tmp" ; 1 "" 1 ; 1 "" 3 -; 340 "" 3 +; 343 "" 3 ; 1 "" 1 ; 1 "" 2 ; 1 "crypto/camellia/cmll-masm-x86_64.S.tmp" 2 diff --git a/crypto/chacha/chacha-merged.c b/crypto/chacha/chacha-merged.c index 67508f2..d24912d 100644 --- a/crypto/chacha/chacha-merged.c +++ b/crypto/chacha/chacha-merged.c @@ -1,41 +1,38 @@ -/* $OpenBSD: chacha-merged.c,v 1.9 2019/01/22 00:59:21 dlg Exp $ */ +/* $OpenBSD: chacha-merged.c,v 1.10 2021/10/22 17:43:00 tb Exp $ */ /* chacha-merged.c version 20080118 D. J. Bernstein Public domain. */ -#include - #include -#define CHACHA_MINKEYLEN 16 +#define CHACHA_MINKEYLEN 16 #define CHACHA_NONCELEN 8 #define CHACHA_CTRLEN 8 #define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN) #define CHACHA_BLOCKLEN 64 +typedef uint8_t u8; +typedef uint32_t u32; + struct chacha_ctx { - u_int input[16]; - uint8_t ks[CHACHA_BLOCKLEN]; - uint8_t unused; + u32 input[16]; + u8 ks[CHACHA_BLOCKLEN]; + u8 unused; }; -static inline void chacha_keysetup(struct chacha_ctx *x, const u_char *k, - u_int kbits) +static inline void chacha_keysetup(struct chacha_ctx *x, const u8 *k, u32 kbits) __attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN))); -static inline void chacha_ivsetup(struct chacha_ctx *x, const u_char *iv, - const u_char *ctr) +static inline void chacha_ivsetup(struct chacha_ctx *x, const u8 *iv, + const u8 *ctr) __attribute__((__bounded__(__minbytes__, 2, CHACHA_NONCELEN))) __attribute__((__bounded__(__minbytes__, 3, CHACHA_CTRLEN))); -static inline void chacha_encrypt_bytes(struct chacha_ctx *x, const u_char *m, - u_char *c, u_int bytes) +static inline void chacha_encrypt_bytes(struct chacha_ctx *x, const u8 *m, + u8 *c, u32 bytes) __attribute__((__bounded__(__buffer__, 2, 4))) __attribute__((__bounded__(__buffer__, 3, 4))); -typedef unsigned char u8; -typedef unsigned int u32; - typedef struct chacha_ctx chacha_ctx; #define U8C(v) (v##U) @@ -127,7 +124,7 @@ chacha_encrypt_bytes(chacha_ctx *x, const u8 *m, u8 *c, u32 bytes) u32 j8, j9, j10, j11, j12, j13, j14, j15; u8 *ctarget = NULL; u8 tmp[64]; - u_int i; + u32 i; if (!bytes) return; diff --git a/crypto/cmac/cm_ameth.c b/crypto/cmac/cm_ameth.c index e7e7fe0..2695646 100644 --- a/crypto/cmac/cm_ameth.c +++ b/crypto/cmac/cm_ameth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cm_ameth.c,v 1.7 2014/07/12 16:03:37 miod Exp $ */ +/* $OpenBSD: cm_ameth.c,v 1.8 2021/12/12 21:30:13 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2010. */ @@ -57,6 +57,7 @@ #include #include "asn1_locl.h" +#include "evp_locl.h" /* CMAC "ASN1" method. This is just here to indicate the * maximum CMAC output length and to free up a CMAC diff --git a/crypto/cmac/cmac.c b/crypto/cmac/cmac.c index d01ae0f..cd286f8 100644 --- a/crypto/cmac/cmac.c +++ b/crypto/cmac/cmac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmac.c,v 1.10 2015/09/10 15:56:25 jsing Exp $ */ +/* $OpenBSD: cmac.c,v 1.11 2021/12/12 21:30:13 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project. */ @@ -57,6 +57,8 @@ #include +#include "evp_locl.h" + struct CMAC_CTX_st { /* Cipher context to use */ EVP_CIPHER_CTX cctx; diff --git a/crypto/cms/cms_asn1.c b/crypto/cms/cms_asn1.c index ac53fec..cc00aef 100644 --- a/crypto/cms/cms_asn1.c +++ b/crypto/cms/cms_asn1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cms_asn1.c,v 1.18 2019/08/11 10:43:57 jsing Exp $ */ +/* $OpenBSD: cms_asn1.c,v 1.19 2022/01/14 08:16:13 tb Exp $ */ /* * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project. @@ -1323,7 +1323,6 @@ static const ASN1_ADB_TABLE CMS_ContentInfo_adbtbl[] = { static const ASN1_ADB CMS_ContentInfo_adb = { .flags = 0, .offset = offsetof(CMS_ContentInfo, contentType), - .app_items = 0, .tbl = CMS_ContentInfo_adbtbl, .tblcount = sizeof(CMS_ContentInfo_adbtbl) / sizeof(ASN1_ADB_TABLE), .default_tt = &cms_default_tt, diff --git a/crypto/cms/cms_enc.c b/crypto/cms/cms_enc.c index fd2df99..ccbb6a5 100644 --- a/crypto/cms/cms_enc.c +++ b/crypto/cms/cms_enc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cms_enc.c,v 1.20 2019/08/11 11:04:18 jsing Exp $ */ +/* $OpenBSD: cms_enc.c,v 1.21 2022/01/20 10:58:35 inoguchi Exp $ */ /* * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project. @@ -151,7 +151,7 @@ cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec) if (ec->keylen != tkeylen) { /* If necessary set key length */ - if (EVP_CIPHER_CTX_set_key_length(ctx, ec->keylen) <= 0) { + if (!EVP_CIPHER_CTX_set_key_length(ctx, ec->keylen)) { /* * Only reveal failure if debugging so we don't leak information * which may be useful in MMA. diff --git a/crypto/cms/cms_lib.c b/crypto/cms/cms_lib.c index b6580dd..21adef7 100644 --- a/crypto/cms/cms_lib.c +++ b/crypto/cms/cms_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cms_lib.c,v 1.14 2019/08/12 18:13:13 jsing Exp $ */ +/* $OpenBSD: cms_lib.c,v 1.15 2021/11/01 20:53:08 tb Exp $ */ /* * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project. @@ -59,8 +59,9 @@ #include #include #include -#include "cms_lcl.h" +#include "cms_lcl.h" +#include "x509_lcl.h" CMS_ContentInfo * d2i_CMS_ContentInfo(CMS_ContentInfo **a, const unsigned char **in, long len) diff --git a/crypto/cms/cms_pwri.c b/crypto/cms/cms_pwri.c index cf28dfc..eb241a6 100644 --- a/crypto/cms/cms_pwri.c +++ b/crypto/cms/cms_pwri.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cms_pwri.c,v 1.26 2019/08/12 18:04:57 jsing Exp $ */ +/* $OpenBSD: cms_pwri.c,v 1.27 2022/01/19 13:47:44 inoguchi Exp $ */ /* * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project. @@ -126,7 +126,9 @@ CMS_add0_recipient_password(CMS_ContentInfo *cms, int iter, int wrap_nid, if (encalg == NULL) { goto merr; } - ctx = EVP_CIPHER_CTX_new(); + + if ((ctx = EVP_CIPHER_CTX_new()) == NULL) + goto merr; if (EVP_EncryptInit_ex(ctx, kekciph, NULL, NULL, NULL) <= 0) { CMSerror(ERR_R_EVP_LIB); diff --git a/crypto/comp/c_rle.c b/crypto/comp/c_rle.c index 7004c35..93b2f3c 100644 --- a/crypto/comp/c_rle.c +++ b/crypto/comp/c_rle.c @@ -1,10 +1,12 @@ -/* $OpenBSD: c_rle.c,v 1.8 2014/11/03 16:58:28 tedu Exp $ */ +/* $OpenBSD: c_rle.c,v 1.9 2022/01/09 23:50:10 tb Exp $ */ #include #include #include #include #include +#include "comp_local.h" + static int rle_compress_block(COMP_CTX *ctx, unsigned char *out, unsigned int olen, unsigned char *in, unsigned int ilen); static int rle_expand_block(COMP_CTX *ctx, unsigned char *out, diff --git a/crypto/comp/c_zlib.c b/crypto/comp/c_zlib.c index 0cdbb20..bdcd7e0 100644 --- a/crypto/comp/c_zlib.c +++ b/crypto/comp/c_zlib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: c_zlib.c,v 1.20 2018/03/17 16:20:01 beck Exp $ */ +/* $OpenBSD: c_zlib.c,v 1.22 2022/01/14 08:40:57 tb Exp $ */ #include #include #include @@ -6,6 +6,8 @@ #include #include +#include "comp_local.h" + COMP_METHOD *COMP_zlib(void ); static COMP_METHOD zlib_method_nozlib = { @@ -232,7 +234,7 @@ static int bio_zlib_free(BIO *bi); static int bio_zlib_read(BIO *b, char *out, int outl); static int bio_zlib_write(BIO *b, const char *in, int inl); static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr); -static long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp); +static long bio_zlib_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp); static BIO_METHOD bio_meth_zlib = { .type = BIO_TYPE_COMP, @@ -553,7 +555,7 @@ bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr) static long -bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +bio_zlib_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { if (!b->next_bio) return 0; diff --git a/crypto/comp/comp_err.c b/crypto/comp/comp_err.c index be8a8fc..ccc7a28 100644 --- a/crypto/comp/comp_err.c +++ b/crypto/comp/comp_err.c @@ -1,4 +1,4 @@ -/* $OpenBSD: comp_err.c,v 1.10 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: comp_err.c,v 1.11 2022/01/09 23:50:10 tb Exp $ */ /* ==================================================================== * Copyright (c) 1999-2007 The OpenSSL Project. All rights reserved. * @@ -60,6 +60,8 @@ #include #include +#include "comp_local.h" + /* BEGIN ERROR CODES */ #ifndef OPENSSL_NO_ERR diff --git a/crypto/comp/comp_lib.c b/crypto/comp/comp_lib.c index dde238e..3f914a7 100644 --- a/crypto/comp/comp_lib.c +++ b/crypto/comp/comp_lib.c @@ -1,10 +1,12 @@ -/* $OpenBSD: comp_lib.c,v 1.8 2014/11/03 16:58:28 tedu Exp $ */ +/* $OpenBSD: comp_lib.c,v 1.9 2022/01/09 23:50:10 tb Exp $ */ #include #include #include #include #include +#include "comp_local.h" + COMP_CTX * COMP_CTX_new(COMP_METHOD *meth) { diff --git a/crypto/comp/comp_local.h b/crypto/comp/comp_local.h new file mode 100644 index 0000000..fc18887 --- /dev/null +++ b/crypto/comp/comp_local.h @@ -0,0 +1,36 @@ +/* $OpenBSD: comp_local.h,v 1.2 2022/01/14 08:21:12 tb Exp $ */ + +#ifndef HEADER_COMP_LOCAL_H +#define HEADER_COMP_LOCAL_H + +__BEGIN_HIDDEN_DECLS + +struct CMP_CTX; + +struct comp_method_st { + int type; /* NID for compression library */ + const char *name; /* A text string to identify the library */ + int (*init)(COMP_CTX *ctx); + void (*finish)(COMP_CTX *ctx); + int (*compress)(COMP_CTX *ctx, unsigned char *out, unsigned int olen, + unsigned char *in, unsigned int ilen); + int (*expand)(COMP_CTX *ctx, unsigned char *out, unsigned int olen, + unsigned char *in, unsigned int ilen); + /* The following two do NOTHING, but are kept for backward compatibility */ + long (*ctrl)(void); + long (*callback_ctrl)(void); +} /* COMP_METHOD */; + +struct comp_ctx_st { + COMP_METHOD *meth; + unsigned long compress_in; + unsigned long compress_out; + unsigned long expand_in; + unsigned long expand_out; + + CRYPTO_EX_DATA ex_data; +} /* COMP_CTX */; + +__END_HIDDEN_DECLS + +#endif /* !HEADER_COMP_LOCAL_H */ diff --git a/crypto/compat/arc4random.c b/crypto/compat/arc4random.c index 2bb4dbf..6f95d57 100644 --- a/crypto/compat/arc4random.c +++ b/crypto/compat/arc4random.c @@ -1,4 +1,4 @@ -/* $OpenBSD: arc4random.c,v 1.55 2019/03/24 17:56:54 deraadt Exp $ */ +/* $OpenBSD: arc4random.c,v 1.56 2022/02/28 21:56:29 dtucker Exp $ */ /* * Copyright (c) 1996, David Mazieres @@ -78,7 +78,7 @@ _rs_init(u_char *buf, size_t n) _exit(1); } - chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8, 0); + chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8); chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ); } diff --git a/crypto/compat/chacha_private.h b/crypto/compat/chacha_private.h index 7c3680f..b0427b6 100644 --- a/crypto/compat/chacha_private.h +++ b/crypto/compat/chacha_private.h @@ -4,7 +4,7 @@ D. J. Bernstein Public domain. */ -/* $OpenBSD: chacha_private.h,v 1.2 2013/10/04 07:02:27 djm Exp $ */ +/* $OpenBSD: chacha_private.h,v 1.3 2022/02/28 21:56:29 dtucker Exp $ */ typedef unsigned char u8; typedef unsigned int u32; @@ -52,7 +52,7 @@ static const char sigma[16] = "expand 32-byte k"; static const char tau[16] = "expand 16-byte k"; static void -chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ivbits) +chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits) { const char *constants; diff --git a/crypto/compat/getentropy_aix.c b/crypto/compat/getentropy_aix.c index 422e685..7fb857e 100644 --- a/crypto/compat/getentropy_aix.c +++ b/crypto/compat/getentropy_aix.c @@ -1,4 +1,4 @@ -/* $OpenBSD: getentropy_aix.c,v 1.7 2020/05/17 14:44:20 deraadt Exp $ */ +/* $OpenBSD: getentropy_aix.c,v 1.8 2021/10/24 21:24:20 deraadt Exp $ */ /* * Copyright (c) 2015 Michael Felt @@ -134,7 +134,7 @@ start: #ifdef O_CLOEXEC flags |= O_CLOEXEC; #endif - fd = open(path, flags, 0); + fd = open(path, flags); if (fd == -1) { if (errno == EINTR) goto start; diff --git a/crypto/compat/getentropy_hpux.c b/crypto/compat/getentropy_hpux.c index c981880..7188ae5 100644 --- a/crypto/compat/getentropy_hpux.c +++ b/crypto/compat/getentropy_hpux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: getentropy_hpux.c,v 1.7 2020/05/17 14:44:20 deraadt Exp $ */ +/* $OpenBSD: getentropy_hpux.c,v 1.8 2021/10/24 21:24:20 deraadt Exp $ */ /* * Copyright (c) 2014 Theo de Raadt @@ -138,7 +138,7 @@ start: #ifdef O_CLOEXEC flags |= O_CLOEXEC; #endif - fd = open(path, flags, 0); + fd = open(path, flags); if (fd == -1) { if (errno == EINTR) goto start; diff --git a/crypto/compat/getentropy_linux.c b/crypto/compat/getentropy_linux.c index bc7a6be..c7c39c2 100644 --- a/crypto/compat/getentropy_linux.c +++ b/crypto/compat/getentropy_linux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: getentropy_linux.c,v 1.47 2020/05/17 14:44:20 deraadt Exp $ */ +/* $OpenBSD: getentropy_linux.c,v 1.48 2021/10/24 21:24:20 deraadt Exp $ */ /* * Copyright (c) 2014 Theo de Raadt @@ -212,7 +212,7 @@ start: #ifdef O_CLOEXEC flags |= O_CLOEXEC; #endif - fd = open("/dev/urandom", flags, 0); + fd = open("/dev/urandom", flags); if (fd == -1) { if (errno == EINTR) goto start; diff --git a/crypto/compat/getentropy_osx.c b/crypto/compat/getentropy_osx.c index 5d4067b..db028d1 100644 --- a/crypto/compat/getentropy_osx.c +++ b/crypto/compat/getentropy_osx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: getentropy_osx.c,v 1.13 2020/05/17 14:44:20 deraadt Exp $ */ +/* $OpenBSD: getentropy_osx.c,v 1.14 2021/10/24 21:24:20 deraadt Exp $ */ /* * Copyright (c) 2014 Theo de Raadt @@ -158,7 +158,7 @@ start: #ifdef O_CLOEXEC flags |= O_CLOEXEC; #endif - fd = open("/dev/urandom", flags, 0); + fd = open("/dev/urandom", flags); if (fd == -1) { if (errno == EINTR) goto start; diff --git a/crypto/compat/getentropy_solaris.c b/crypto/compat/getentropy_solaris.c index cf5b9bf..e36426c 100644 --- a/crypto/compat/getentropy_solaris.c +++ b/crypto/compat/getentropy_solaris.c @@ -1,4 +1,4 @@ -/* $OpenBSD: getentropy_solaris.c,v 1.14 2020/05/17 14:44:20 deraadt Exp $ */ +/* $OpenBSD: getentropy_solaris.c,v 1.15 2021/10/24 21:24:20 deraadt Exp $ */ /* * Copyright (c) 2014 Theo de Raadt @@ -164,7 +164,7 @@ start: #ifdef O_CLOEXEC flags |= O_CLOEXEC; #endif - fd = open(path, flags, 0); + fd = open(path, flags); if (fd == -1) { if (errno == EINTR) goto start; diff --git a/crypto/compat/strtonum.c b/crypto/compat/strtonum.c new file mode 100644 index 0000000..fdfc72a --- /dev/null +++ b/crypto/compat/strtonum.c @@ -0,0 +1,65 @@ +/* $OpenBSD: strtonum.c,v 1.8 2015/09/13 08:31:48 guenther Exp $ */ + +/* + * Copyright (c) 2004 Ted Unangst and Todd Miller + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#define INVALID 1 +#define TOOSMALL 2 +#define TOOLARGE 3 + +long long +strtonum(const char *numstr, long long minval, long long maxval, + const char **errstrp) +{ + long long ll = 0; + int error = 0; + char *ep; + struct errval { + const char *errstr; + int err; + } ev[4] = { + { NULL, 0 }, + { "invalid", EINVAL }, + { "too small", ERANGE }, + { "too large", ERANGE }, + }; + + ev[0].err = errno; + errno = 0; + if (minval > maxval) { + error = INVALID; + } else { + ll = strtoll(numstr, &ep, 10); + if (numstr == ep || *ep != '\0') + error = INVALID; + else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) + error = TOOSMALL; + else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) + error = TOOLARGE; + } + if (errstrp != NULL) + *errstrp = ev[error].errstr; + errno = ev[error].err; + if (error) + ll = 0; + + return (ll); +} diff --git a/crypto/cpuid-masm-x86_64.S b/crypto/cpuid-masm-x86_64.S index d646821..0dd7baf 100644 --- a/crypto/cpuid-masm-x86_64.S +++ b/crypto/cpuid-masm-x86_64.S @@ -1,7 +1,7 @@ ; 1 "crypto/cpuid-masm-x86_64.S.tmp" ; 1 "" 1 ; 1 "" 3 -; 340 "" 3 +; 343 "" 3 ; 1 "" 1 ; 1 "" 2 ; 1 "crypto/cpuid-masm-x86_64.S.tmp" 2 diff --git a/crypto/cryptlib.h b/crypto/cryptlib.h index d44738b..6c3731d 100644 --- a/crypto/cryptlib.h +++ b/crypto/cryptlib.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cryptlib.h,v 1.25 2016/11/04 17:30:30 miod Exp $ */ +/* $OpenBSD: cryptlib.h,v 1.26 2021/11/24 01:12:43 beck Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -72,6 +72,9 @@ extern "C" { #define X509_CERT_DIR_EVP "SSL_CERT_DIR" #define X509_CERT_FILE_EVP "SSL_CERT_FILE" +#define CTLOG_FILE OPENSSLDIR "/ct_log_list.cnf" +#define CTLOG_FILE_EVP "CTLOG_FILE" + void OPENSSL_cpuid_setup(void); #ifdef __cplusplus diff --git a/crypto/crypto.sym b/crypto/crypto.sym index e690e4f..a2dfa72 100644 --- a/crypto/crypto.sym +++ b/crypto/crypto.sym @@ -16,6 +16,15 @@ AES_set_decrypt_key AES_set_encrypt_key AES_unwrap_key AES_wrap_key +ASIdOrRange_free +ASIdOrRange_it +ASIdOrRange_new +ASIdentifierChoice_free +ASIdentifierChoice_it +ASIdentifierChoice_new +ASIdentifiers_free +ASIdentifiers_it +ASIdentifiers_new ASN1_ANY_it ASN1_BIT_STRING_check ASN1_BIT_STRING_free @@ -30,14 +39,12 @@ ASN1_BIT_STRING_set_bit ASN1_BMPSTRING_free ASN1_BMPSTRING_it ASN1_BMPSTRING_new -ASN1_BOOLEAN_it ASN1_ENUMERATED_free ASN1_ENUMERATED_get ASN1_ENUMERATED_it ASN1_ENUMERATED_new ASN1_ENUMERATED_set ASN1_ENUMERATED_to_BN -ASN1_FBOOLEAN_it ASN1_GENERALIZEDTIME_adj ASN1_GENERALIZEDTIME_check ASN1_GENERALIZEDTIME_free @@ -123,9 +130,9 @@ ASN1_STRING_type_new ASN1_T61STRING_free ASN1_T61STRING_it ASN1_T61STRING_new -ASN1_TBOOLEAN_it ASN1_TIME_adj ASN1_TIME_check +ASN1_TIME_diff ASN1_TIME_free ASN1_TIME_it ASN1_TIME_new @@ -165,8 +172,6 @@ ASN1_VISIBLESTRING_it ASN1_VISIBLESTRING_new ASN1_add_oid_module ASN1_bn_print -ASN1_check_infinite_end -ASN1_const_check_infinite_end ASN1_d2i_bio ASN1_d2i_fp ASN1_dup @@ -214,6 +219,9 @@ ASN1_template_new ASN1_time_parse ASN1_time_tm_clamp_notafter ASN1_time_tm_cmp +ASRange_free +ASRange_it +ASRange_new AUTHORITY_INFO_ACCESS_free AUTHORITY_INFO_ACCESS_it AUTHORITY_INFO_ACCESS_new @@ -272,10 +280,12 @@ BIO_free_all BIO_get_accept_socket BIO_get_callback BIO_get_callback_arg +BIO_get_callback_ex BIO_get_data BIO_get_ex_data BIO_get_ex_new_index BIO_get_host_ip +BIO_get_init BIO_get_new_index BIO_get_port BIO_get_retry_BIO @@ -344,11 +354,14 @@ BIO_s_socket BIO_set BIO_set_callback BIO_set_callback_arg +BIO_set_callback_ex BIO_set_cipher BIO_set_data BIO_set_ex_data BIO_set_flags BIO_set_init +BIO_set_next +BIO_set_retry_reason BIO_set_shutdown BIO_set_tcp_ndelay BIO_snprintf @@ -388,6 +401,8 @@ BN_GENCB_call BN_GENCB_free BN_GENCB_get_arg BN_GENCB_new +BN_GENCB_set +BN_GENCB_set_old BN_GF2m_add BN_GF2m_arr2poly BN_GF2m_mod @@ -420,15 +435,16 @@ BN_RECP_CTX_set BN_X931_derive_prime_ex BN_X931_generate_Xpq BN_X931_generate_prime_ex +BN_abs_is_word BN_add BN_add_word BN_asc2bn BN_bin2bn BN_bn2bin BN_bn2binpad -BN_bn2lebinpad BN_bn2dec BN_bn2hex +BN_bn2lebinpad BN_bn2mpi BN_clear BN_clear_bit @@ -452,6 +468,7 @@ BN_get0_nist_prime_224 BN_get0_nist_prime_256 BN_get0_nist_prime_384 BN_get0_nist_prime_521 +BN_get_flags BN_get_params BN_get_rfc2409_prime_1024 BN_get_rfc2409_prime_768 @@ -465,10 +482,15 @@ BN_get_word BN_hex2bn BN_init BN_is_bit_set +BN_is_negative +BN_is_odd +BN_is_one BN_is_prime BN_is_prime_ex BN_is_prime_fasttest BN_is_prime_fasttest_ex +BN_is_word +BN_is_zero BN_kronecker BN_lebin2bn BN_lshift @@ -519,6 +541,7 @@ BN_reciprocal BN_rshift BN_rshift1 BN_set_bit +BN_set_flags BN_set_negative BN_set_params BN_set_word @@ -528,10 +551,13 @@ BN_sub_word BN_swap BN_to_ASN1_ENUMERATED BN_to_ASN1_INTEGER +BN_to_montgomery BN_uadd BN_ucmp BN_usub BN_value_one +BN_with_flags +BN_zero_ex BUF_MEM_free BUF_MEM_grow BUF_MEM_grow_clean @@ -827,6 +853,27 @@ CRYPTO_strdup CRYPTO_thread_id CRYPTO_xchacha_20 CRYPTO_xts128_encrypt +CTLOG_STORE_free +CTLOG_STORE_get0_log_by_id +CTLOG_STORE_load_default_file +CTLOG_STORE_load_file +CTLOG_STORE_new +CTLOG_free +CTLOG_get0_log_id +CTLOG_get0_name +CTLOG_get0_public_key +CTLOG_new +CTLOG_new_from_base64 +CT_POLICY_EVAL_CTX_free +CT_POLICY_EVAL_CTX_get0_cert +CT_POLICY_EVAL_CTX_get0_issuer +CT_POLICY_EVAL_CTX_get0_log_store +CT_POLICY_EVAL_CTX_get_time +CT_POLICY_EVAL_CTX_new +CT_POLICY_EVAL_CTX_set1_cert +CT_POLICY_EVAL_CTX_set1_issuer +CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE +CT_POLICY_EVAL_CTX_set_time Camellia_cbc_encrypt Camellia_cfb128_encrypt Camellia_cfb1_encrypt @@ -889,11 +936,17 @@ DH_generate_key DH_generate_parameters DH_generate_parameters_ex DH_get0_engine +DH_get0_g DH_get0_key +DH_get0_p DH_get0_pqg +DH_get0_priv_key +DH_get0_pub_key +DH_get0_q DH_get_default_method DH_get_ex_data DH_get_ex_new_index +DH_get_length DH_new DH_new_method DH_set0_key @@ -931,6 +984,7 @@ DSA_SIG_get0 DSA_SIG_it DSA_SIG_new DSA_SIG_set0 +DSA_bits DSA_clear_flags DSA_do_sign DSA_do_verify @@ -940,8 +994,13 @@ DSA_generate_key DSA_generate_parameters DSA_generate_parameters_ex DSA_get0_engine +DSA_get0_g DSA_get0_key +DSA_get0_p DSA_get0_pqg +DSA_get0_priv_key +DSA_get0_pub_key +DSA_get0_q DSA_get_default_method DSA_get_ex_data DSA_get_ex_new_index @@ -1006,6 +1065,8 @@ ECDH_size ECDSA_OpenSSL ECDSA_SIG_free ECDSA_SIG_get0 +ECDSA_SIG_get0_r +ECDSA_SIG_get0_s ECDSA_SIG_it ECDSA_SIG_new ECDSA_SIG_set0 @@ -1392,7 +1453,9 @@ ESS_SIGNING_CERT_free ESS_SIGNING_CERT_it ESS_SIGNING_CERT_new EVP_AEAD_CTX_cleanup +EVP_AEAD_CTX_free EVP_AEAD_CTX_init +EVP_AEAD_CTX_new EVP_AEAD_CTX_open EVP_AEAD_CTX_seal EVP_AEAD_key_length @@ -1401,6 +1464,7 @@ EVP_AEAD_max_tag_len EVP_AEAD_nonce_length EVP_BytesToKey EVP_CIPHER_CTX_block_size +EVP_CIPHER_CTX_buf_noconst EVP_CIPHER_CTX_cipher EVP_CIPHER_CTX_cleanup EVP_CIPHER_CTX_clear_flags @@ -1410,6 +1474,7 @@ EVP_CIPHER_CTX_encrypting EVP_CIPHER_CTX_flags EVP_CIPHER_CTX_free EVP_CIPHER_CTX_get_app_data +EVP_CIPHER_CTX_get_cipher_data EVP_CIPHER_CTX_get_iv EVP_CIPHER_CTX_init EVP_CIPHER_CTX_iv_length @@ -1419,6 +1484,7 @@ EVP_CIPHER_CTX_nid EVP_CIPHER_CTX_rand_key EVP_CIPHER_CTX_reset EVP_CIPHER_CTX_set_app_data +EVP_CIPHER_CTX_set_cipher_data EVP_CIPHER_CTX_set_flags EVP_CIPHER_CTX_set_iv EVP_CIPHER_CTX_set_key_length @@ -1484,14 +1550,30 @@ EVP_MD_CTX_destroy EVP_MD_CTX_free EVP_MD_CTX_init EVP_MD_CTX_md +EVP_MD_CTX_md_data EVP_MD_CTX_new +EVP_MD_CTX_pkey_ctx EVP_MD_CTX_reset EVP_MD_CTX_set_flags +EVP_MD_CTX_set_pkey_ctx EVP_MD_CTX_test_flags EVP_MD_block_size EVP_MD_do_all EVP_MD_do_all_sorted EVP_MD_flags +EVP_MD_meth_dup +EVP_MD_meth_free +EVP_MD_meth_new +EVP_MD_meth_set_app_datasize +EVP_MD_meth_set_cleanup +EVP_MD_meth_set_copy +EVP_MD_meth_set_ctrl +EVP_MD_meth_set_final +EVP_MD_meth_set_flags +EVP_MD_meth_set_init +EVP_MD_meth_set_input_blocksize +EVP_MD_meth_set_result_size +EVP_MD_meth_set_update EVP_MD_pkey_type EVP_MD_size EVP_MD_type @@ -1535,14 +1617,18 @@ EVP_PKEY_asn1_get0 EVP_PKEY_asn1_get0_info EVP_PKEY_asn1_get_count EVP_PKEY_asn1_new +EVP_PKEY_asn1_set_check EVP_PKEY_asn1_set_ctrl EVP_PKEY_asn1_set_free EVP_PKEY_asn1_set_param +EVP_PKEY_asn1_set_param_check EVP_PKEY_asn1_set_private EVP_PKEY_asn1_set_public +EVP_PKEY_asn1_set_public_check EVP_PKEY_assign EVP_PKEY_base_id EVP_PKEY_bits +EVP_PKEY_check EVP_PKEY_cmp EVP_PKEY_cmp_parameters EVP_PKEY_copy_parameters @@ -1582,6 +1668,7 @@ EVP_PKEY_meth_find EVP_PKEY_meth_free EVP_PKEY_meth_get0_info EVP_PKEY_meth_new +EVP_PKEY_meth_set_check EVP_PKEY_meth_set_cleanup EVP_PKEY_meth_set_copy EVP_PKEY_meth_set_ctrl @@ -1590,7 +1677,9 @@ EVP_PKEY_meth_set_derive EVP_PKEY_meth_set_encrypt EVP_PKEY_meth_set_init EVP_PKEY_meth_set_keygen +EVP_PKEY_meth_set_param_check EVP_PKEY_meth_set_paramgen +EVP_PKEY_meth_set_public_check EVP_PKEY_meth_set_sign EVP_PKEY_meth_set_signctx EVP_PKEY_meth_set_verify @@ -1600,11 +1689,13 @@ EVP_PKEY_missing_parameters EVP_PKEY_new EVP_PKEY_new_CMAC_key EVP_PKEY_new_mac_key +EVP_PKEY_param_check EVP_PKEY_paramgen EVP_PKEY_paramgen_init EVP_PKEY_print_params EVP_PKEY_print_private EVP_PKEY_print_public +EVP_PKEY_public_check EVP_PKEY_save_parameters EVP_PKEY_set1_DH EVP_PKEY_set1_DSA @@ -1720,9 +1811,6 @@ EVP_des_ede_ecb EVP_des_ede_ofb EVP_des_ofb EVP_desx_cbc -EVP_dss -EVP_dss1 -EVP_ecdsa EVP_enc_null EVP_get_cipherbyname EVP_get_digestbyname @@ -1772,6 +1860,8 @@ EVP_whirlpool EXTENDED_KEY_USAGE_free EXTENDED_KEY_USAGE_it EXTENDED_KEY_USAGE_new +FIPS_mode +FIPS_mode_set GENERAL_NAMES_free GENERAL_NAMES_it GENERAL_NAMES_new @@ -1823,11 +1913,9 @@ HKDF HKDF_expand HKDF_extract HMAC -HMAC_CTX_cleanup HMAC_CTX_copy HMAC_CTX_free HMAC_CTX_get_md -HMAC_CTX_init HMAC_CTX_new HMAC_CTX_reset HMAC_CTX_set_flags @@ -1835,6 +1923,18 @@ HMAC_Final HMAC_Init HMAC_Init_ex HMAC_Update +IPAddressChoice_free +IPAddressChoice_it +IPAddressChoice_new +IPAddressFamily_free +IPAddressFamily_it +IPAddressFamily_new +IPAddressOrRange_free +IPAddressOrRange_it +IPAddressOrRange_new +IPAddressRange_free +IPAddressRange_it +IPAddressRange_new ISSUING_DIST_POINT_free ISSUING_DIST_POINT_it ISSUING_DIST_POINT_new @@ -1869,12 +1969,6 @@ NCONF_new NETSCAPE_CERT_SEQUENCE_free NETSCAPE_CERT_SEQUENCE_it NETSCAPE_CERT_SEQUENCE_new -NETSCAPE_ENCRYPTED_PKEY_free -NETSCAPE_ENCRYPTED_PKEY_it -NETSCAPE_ENCRYPTED_PKEY_new -NETSCAPE_PKEY_free -NETSCAPE_PKEY_it -NETSCAPE_PKEY_new NETSCAPE_SPKAC_free NETSCAPE_SPKAC_it NETSCAPE_SPKAC_new @@ -1888,9 +1982,6 @@ NETSCAPE_SPKI_print NETSCAPE_SPKI_set_pubkey NETSCAPE_SPKI_sign NETSCAPE_SPKI_verify -NETSCAPE_X509_free -NETSCAPE_X509_it -NETSCAPE_X509_new NOTICEREF_free NOTICEREF_it NOTICEREF_new @@ -1905,7 +1996,6 @@ OBJ_NAME_remove OBJ_add_object OBJ_add_sigid OBJ_bsearch_ -OBJ_bsearch_ex_ OBJ_cleanup OBJ_cmp OBJ_create @@ -1913,6 +2003,8 @@ OBJ_create_objects OBJ_dup OBJ_find_sigid_algs OBJ_find_sigid_by_algs +OBJ_get0_data +OBJ_length OBJ_ln2nid OBJ_new_nid OBJ_nid2ln @@ -2045,6 +2137,13 @@ OCSP_resp_count OCSP_resp_find OCSP_resp_find_status OCSP_resp_get0 +OCSP_resp_get0_certs +OCSP_resp_get0_id +OCSP_resp_get0_produced_at +OCSP_resp_get0_respdata +OCSP_resp_get0_signature +OCSP_resp_get0_signer +OCSP_resp_get0_tbs_sigalg OCSP_response_create OCSP_response_get1_basic OCSP_response_status @@ -2090,9 +2189,6 @@ PEM_ASN1_read PEM_ASN1_read_bio PEM_ASN1_write PEM_ASN1_write_bio -PEM_SealFinal -PEM_SealInit -PEM_SealUpdate PEM_SignFinal PEM_SignInit PEM_SignUpdate @@ -2125,7 +2221,6 @@ PEM_read_RSAPublicKey PEM_read_RSA_PUBKEY PEM_read_X509 PEM_read_X509_AUX -PEM_read_X509_CERT_PAIR PEM_read_X509_CRL PEM_read_X509_REQ PEM_read_bio @@ -2149,7 +2244,6 @@ PEM_read_bio_RSAPublicKey PEM_read_bio_RSA_PUBKEY PEM_read_bio_X509 PEM_read_bio_X509_AUX -PEM_read_bio_X509_CERT_PAIR PEM_read_bio_X509_CRL PEM_read_bio_X509_REQ PEM_write @@ -2174,7 +2268,6 @@ PEM_write_RSAPublicKey PEM_write_RSA_PUBKEY PEM_write_X509 PEM_write_X509_AUX -PEM_write_X509_CERT_PAIR PEM_write_X509_CRL PEM_write_X509_REQ PEM_write_X509_REQ_NEW @@ -2199,12 +2292,12 @@ PEM_write_bio_PKCS8_PRIV_KEY_INFO PEM_write_bio_PUBKEY PEM_write_bio_Parameters PEM_write_bio_PrivateKey +PEM_write_bio_PrivateKey_traditional PEM_write_bio_RSAPrivateKey PEM_write_bio_RSAPublicKey PEM_write_bio_RSA_PUBKEY PEM_write_bio_X509 PEM_write_bio_X509_AUX -PEM_write_bio_X509_CERT_PAIR PEM_write_bio_X509_CRL PEM_write_bio_X509_REQ PEM_write_bio_X509_REQ_NEW @@ -2439,8 +2532,17 @@ RSA_free RSA_generate_key RSA_generate_key_ex RSA_get0_crt_params +RSA_get0_d +RSA_get0_dmp1 +RSA_get0_dmq1 +RSA_get0_e RSA_get0_factors +RSA_get0_iqmp RSA_get0_key +RSA_get0_n +RSA_get0_p +RSA_get0_pss_params +RSA_get0_q RSA_get_default_method RSA_get_ex_data RSA_get_ex_new_index @@ -2516,6 +2618,35 @@ RSA_verify RSA_verify_ASN1_OCTET_STRING RSA_verify_PKCS1_PSS RSA_verify_PKCS1_PSS_mgf1 +SCT_LIST_free +SCT_LIST_print +SCT_LIST_validate +SCT_free +SCT_get0_extensions +SCT_get0_log_id +SCT_get0_signature +SCT_get_log_entry_type +SCT_get_signature_nid +SCT_get_source +SCT_get_timestamp +SCT_get_validation_status +SCT_get_version +SCT_new +SCT_new_from_base64 +SCT_print +SCT_set0_extensions +SCT_set0_log_id +SCT_set0_signature +SCT_set1_extensions +SCT_set1_log_id +SCT_set1_signature +SCT_set_log_entry_type +SCT_set_signature_nid +SCT_set_source +SCT_set_timestamp +SCT_set_version +SCT_validate +SCT_validation_status_string SHA1 SHA1_Final SHA1_Init @@ -2856,9 +2987,6 @@ X509_CERT_AUX_free X509_CERT_AUX_it X509_CERT_AUX_new X509_CERT_AUX_print -X509_CERT_PAIR_free -X509_CERT_PAIR_it -X509_CERT_PAIR_new X509_CINF_free X509_CINF_it X509_CINF_new @@ -2978,11 +3106,12 @@ X509_NAME_print X509_NAME_print_ex X509_NAME_print_ex_fp X509_NAME_set -X509_OBJECT_free_contents +X509_OBJECT_free X509_OBJECT_get0_X509 X509_OBJECT_get0_X509_CRL X509_OBJECT_get_type X509_OBJECT_idx_by_subject +X509_OBJECT_new X509_OBJECT_retrieve_by_subject X509_OBJECT_retrieve_match X509_OBJECT_up_ref_count @@ -3023,6 +3152,7 @@ X509_REQ_digest X509_REQ_dup X509_REQ_extension_nid X509_REQ_free +X509_REQ_get0_pubkey X509_REQ_get0_signature X509_REQ_get1_email X509_REQ_get_attr @@ -3067,6 +3197,8 @@ X509_REVOKED_new X509_REVOKED_set_revocationDate X509_REVOKED_set_serialNumber X509_SIG_free +X509_SIG_get0 +X509_SIG_getm X509_SIG_it X509_SIG_new X509_STORE_CTX_cleanup @@ -3082,6 +3214,7 @@ X509_STORE_CTX_get0_store X509_STORE_CTX_get0_untrusted X509_STORE_CTX_get1_chain X509_STORE_CTX_get1_issuer +X509_STORE_CTX_get_by_subject X509_STORE_CTX_get_chain X509_STORE_CTX_get_current_cert X509_STORE_CTX_get_error @@ -3089,6 +3222,10 @@ X509_STORE_CTX_get_error_depth X509_STORE_CTX_get_ex_data X509_STORE_CTX_get_ex_new_index X509_STORE_CTX_get_explicit_policy +X509_STORE_CTX_get_num_untrusted +X509_STORE_CTX_get_obj_by_subject +X509_STORE_CTX_get_verify +X509_STORE_CTX_get_verify_cb X509_STORE_CTX_init X509_STORE_CTX_new X509_STORE_CTX_purpose_inherit @@ -3096,16 +3233,20 @@ X509_STORE_CTX_set0_crls X509_STORE_CTX_set0_param X509_STORE_CTX_set0_trusted_stack X509_STORE_CTX_set0_untrusted +X509_STORE_CTX_set0_verified_chain X509_STORE_CTX_set_cert X509_STORE_CTX_set_chain +X509_STORE_CTX_set_current_cert X509_STORE_CTX_set_default X509_STORE_CTX_set_depth X509_STORE_CTX_set_error +X509_STORE_CTX_set_error_depth X509_STORE_CTX_set_ex_data X509_STORE_CTX_set_flags X509_STORE_CTX_set_purpose X509_STORE_CTX_set_time X509_STORE_CTX_set_trust +X509_STORE_CTX_set_verify X509_STORE_CTX_set_verify_cb X509_STORE_CTX_trusted_stack X509_STORE_add_cert @@ -3116,8 +3257,9 @@ X509_STORE_get0_objects X509_STORE_get0_param X509_STORE_get1_certs X509_STORE_get1_crls -X509_STORE_get_by_subject X509_STORE_get_ex_data +X509_STORE_get_verify +X509_STORE_get_verify_cb X509_STORE_load_locations X509_STORE_load_mem X509_STORE_new @@ -3128,6 +3270,7 @@ X509_STORE_set_ex_data X509_STORE_set_flags X509_STORE_set_purpose X509_STORE_set_trust +X509_STORE_set_verify X509_STORE_set_verify_cb X509_STORE_up_ref X509_TRUST_add @@ -3209,6 +3352,7 @@ X509_get0_signature X509_get0_tbs_sigalg X509_get1_email X509_get1_ocsp +X509_get_X509_PUBKEY X509_get_default_cert_area X509_get_default_cert_dir X509_get_default_cert_dir_env @@ -3223,7 +3367,10 @@ X509_get_ext_by_OBJ X509_get_ext_by_critical X509_get_ext_count X509_get_ext_d2i +X509_get_extended_key_usage +X509_get_extension_flags X509_get_issuer_name +X509_get_key_usage X509_get_pubkey X509_get_pubkey_parameters X509_get_serialNumber @@ -3301,6 +3448,25 @@ X509at_get_attr_by_NID X509at_get_attr_by_OBJ X509at_get_attr_count X509v3_add_ext +X509v3_addr_add_inherit +X509v3_addr_add_prefix +X509v3_addr_add_range +X509v3_addr_canonize +X509v3_addr_get_afi +X509v3_addr_get_range +X509v3_addr_inherits +X509v3_addr_is_canonical +X509v3_addr_subset +X509v3_addr_validate_path +X509v3_addr_validate_resource_set +X509v3_asid_add_id_or_range +X509v3_asid_add_inherit +X509v3_asid_canonize +X509v3_asid_inherits +X509v3_asid_is_canonical +X509v3_asid_subset +X509v3_asid_validate_path +X509v3_asid_validate_resource_set X509v3_delete_ext X509v3_get_ext X509v3_get_ext_by_NID @@ -3331,16 +3497,6 @@ a2i_GENERAL_NAME a2i_IPADDRESS a2i_IPADDRESS_NC a2i_ipadd -asn1_do_adb -asn1_do_lock -asn1_enc_free -asn1_enc_init -asn1_enc_restore -asn1_enc_save -asn1_ex_c2i -asn1_get_choice_selector -asn1_get_field_ptr -asn1_set_choice_selector b2i_PVK_bio b2i_PrivateKey b2i_PrivateKey_bio @@ -3349,11 +3505,12 @@ b2i_PublicKey_bio c2i_ASN1_BIT_STRING c2i_ASN1_INTEGER c2i_ASN1_OBJECT -check_defer d2i_ACCESS_DESCRIPTION +d2i_ASIdOrRange +d2i_ASIdentifierChoice +d2i_ASIdentifiers d2i_ASN1_BIT_STRING d2i_ASN1_BMPSTRING -d2i_ASN1_BOOLEAN d2i_ASN1_ENUMERATED d2i_ASN1_GENERALIZEDTIME d2i_ASN1_GENERALSTRING @@ -3374,6 +3531,7 @@ d2i_ASN1_UNIVERSALSTRING d2i_ASN1_UTCTIME d2i_ASN1_UTF8STRING d2i_ASN1_VISIBLESTRING +d2i_ASRange d2i_AUTHORITY_INFO_ACCESS d2i_AUTHORITY_KEYID d2i_AutoPrivateKey @@ -3420,15 +3578,15 @@ d2i_EXTENDED_KEY_USAGE d2i_GENERAL_NAME d2i_GENERAL_NAMES d2i_GOST_CIPHER_PARAMS +d2i_IPAddressChoice +d2i_IPAddressFamily +d2i_IPAddressOrRange +d2i_IPAddressRange d2i_ISSUING_DIST_POINT d2i_NETSCAPE_CERT_SEQUENCE -d2i_NETSCAPE_ENCRYPTED_PKEY -d2i_NETSCAPE_PKEY d2i_NETSCAPE_SPKAC d2i_NETSCAPE_SPKI -d2i_NETSCAPE_X509 d2i_NOTICEREF -d2i_Netscape_RSA d2i_OCSP_BASICRESP d2i_OCSP_CERTID d2i_OCSP_CERTSTATUS @@ -3493,12 +3651,12 @@ d2i_RSAPrivateKey_fp d2i_RSAPublicKey d2i_RSAPublicKey_bio d2i_RSAPublicKey_fp -d2i_RSA_NET d2i_RSA_OAEP_PARAMS d2i_RSA_PSS_PARAMS d2i_RSA_PUBKEY d2i_RSA_PUBKEY_bio d2i_RSA_PUBKEY_fp +d2i_SCT_LIST d2i_SXNET d2i_SXNETID d2i_TS_ACCURACY @@ -3522,7 +3680,6 @@ d2i_X509_ALGORS d2i_X509_ATTRIBUTE d2i_X509_AUX d2i_X509_CERT_AUX -d2i_X509_CERT_PAIR d2i_X509_CINF d2i_X509_CRL d2i_X509_CRL_INFO @@ -3562,9 +3719,11 @@ i2b_PublicKey_bio i2c_ASN1_BIT_STRING i2c_ASN1_INTEGER i2d_ACCESS_DESCRIPTION +i2d_ASIdOrRange +i2d_ASIdentifierChoice +i2d_ASIdentifiers i2d_ASN1_BIT_STRING i2d_ASN1_BMPSTRING -i2d_ASN1_BOOLEAN i2d_ASN1_ENUMERATED i2d_ASN1_GENERALIZEDTIME i2d_ASN1_GENERALSTRING @@ -3585,6 +3744,7 @@ i2d_ASN1_UTCTIME i2d_ASN1_UTF8STRING i2d_ASN1_VISIBLESTRING i2d_ASN1_bio_stream +i2d_ASRange i2d_AUTHORITY_INFO_ACCESS i2d_AUTHORITY_KEYID i2d_BASIC_CONSTRAINTS @@ -3631,15 +3791,15 @@ i2d_EXTENDED_KEY_USAGE i2d_GENERAL_NAME i2d_GENERAL_NAMES i2d_GOST_CIPHER_PARAMS +i2d_IPAddressChoice +i2d_IPAddressFamily +i2d_IPAddressOrRange +i2d_IPAddressRange i2d_ISSUING_DIST_POINT i2d_NETSCAPE_CERT_SEQUENCE -i2d_NETSCAPE_ENCRYPTED_PKEY -i2d_NETSCAPE_PKEY i2d_NETSCAPE_SPKAC i2d_NETSCAPE_SPKI -i2d_NETSCAPE_X509 i2d_NOTICEREF -i2d_Netscape_RSA i2d_OCSP_BASICRESP i2d_OCSP_CERTID i2d_OCSP_CERTSTATUS @@ -3710,12 +3870,12 @@ i2d_RSAPrivateKey_fp i2d_RSAPublicKey i2d_RSAPublicKey_bio i2d_RSAPublicKey_fp -i2d_RSA_NET i2d_RSA_OAEP_PARAMS i2d_RSA_PSS_PARAMS i2d_RSA_PUBKEY i2d_RSA_PUBKEY_bio i2d_RSA_PUBKEY_fp +i2d_SCT_LIST i2d_SXNET i2d_SXNETID i2d_TS_ACCURACY @@ -3739,7 +3899,6 @@ i2d_X509_ALGORS i2d_X509_ATTRIBUTE i2d_X509_AUX i2d_X509_CERT_AUX -i2d_X509_CERT_PAIR i2d_X509_CINF i2d_X509_CRL i2d_X509_CRL_INFO @@ -3759,7 +3918,12 @@ i2d_X509_SIG i2d_X509_VAL i2d_X509_bio i2d_X509_fp +i2d_re_X509_CRL_tbs +i2d_re_X509_REQ_tbs +i2d_re_X509_tbs i2o_ECPublicKey +i2o_SCT +i2o_SCT_LIST i2s_ASN1_ENUMERATED i2s_ASN1_ENUMERATED_TABLE i2s_ASN1_INTEGER @@ -3791,9 +3955,9 @@ lh_retrieve lh_stats lh_stats_bio lh_strhash -name_cmp o2i_ECPublicKey -obj_cleanup_defer +o2i_SCT +o2i_SCT_LIST s2i_ASN1_INTEGER s2i_ASN1_OCTET_STRING sk_delete diff --git a/crypto/ct/ct_b64.c b/crypto/ct/ct_b64.c new file mode 100644 index 0000000..bfc69a7 --- /dev/null +++ b/crypto/ct/ct_b64.c @@ -0,0 +1,224 @@ +/* $OpenBSD: ct_b64.c,v 1.6 2021/12/20 17:19:19 jsing Exp $ */ +/* + * Written by Rob Stradling (rob@comodo.com) and Stephen Henson + * (steve@openssl.org) for the OpenSSL project 2014. + */ +/* ==================================================================== + * Copyright (c) 2014 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 + * licensing@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). + * + */ + +#include +#include + +#include +#include +#include + +#include "bytestring.h" +#include "ct_local.h" + +/* + * Decodes the base64 string |in| into |out|. + * A new string will be malloc'd and assigned to |out|. This will be owned by + * the caller. Do not provide a pre-allocated string in |out|. + */ +static int +ct_base64_decode(const char *in, unsigned char **out) +{ + size_t inlen = strlen(in); + int outlen, i; + unsigned char *outbuf = NULL; + + if (inlen == 0) { + *out = NULL; + return 0; + } + + outlen = (inlen / 4) * 3; + outbuf = malloc(outlen); + if (outbuf == NULL) { + CTerror(ERR_R_MALLOC_FAILURE); + goto err; + } + + outlen = EVP_DecodeBlock(outbuf, (unsigned char *)in, inlen); + if (outlen < 0) { + CTerror(CT_R_BASE64_DECODE_ERROR); + goto err; + } + + /* + * Subtract padding bytes from |outlen|. + * Any more than 2 is malformed. + */ + i = 0; + while (in[--inlen] == '=') { + --outlen; + if (++i > 2) + goto err; + } + + *out = outbuf; + return outlen; + err: + free(outbuf); + return -1; +} + +SCT * +SCT_new_from_base64(unsigned char version, const char *logid_base64, + ct_log_entry_type_t entry_type, uint64_t timestamp, + const char *extensions_base64, const char *signature_base64) +{ + unsigned char *dec = NULL; + int declen; + SCT *sct; + CBS cbs; + + if ((sct = SCT_new()) == NULL) { + CTerror(ERR_R_MALLOC_FAILURE); + return NULL; + } + + /* + * RFC6962 section 4.1 says we "MUST NOT expect this to be 0", but we + * can only construct SCT versions that have been defined. + */ + if (!SCT_set_version(sct, version)) { + CTerror(CT_R_SCT_UNSUPPORTED_VERSION); + goto err; + } + + declen = ct_base64_decode(logid_base64, &dec); + if (declen < 0) { + CTerror(X509_R_BASE64_DECODE_ERROR); + goto err; + } + if (!SCT_set0_log_id(sct, dec, declen)) + goto err; + dec = NULL; + + declen = ct_base64_decode(extensions_base64, &dec); + if (declen < 0) { + CTerror(X509_R_BASE64_DECODE_ERROR); + goto err; + } + SCT_set0_extensions(sct, dec, declen); + dec = NULL; + + declen = ct_base64_decode(signature_base64, &dec); + if (declen < 0) { + CTerror(X509_R_BASE64_DECODE_ERROR); + goto err; + } + + CBS_init(&cbs, dec, declen); + if (!o2i_SCT_signature(sct, &cbs)) + goto err; + free(dec); + dec = NULL; + + SCT_set_timestamp(sct, timestamp); + + if (!SCT_set_log_entry_type(sct, entry_type)) + goto err; + + return sct; + + err: + free(dec); + SCT_free(sct); + return NULL; +} + +/* + * Allocate, build and returns a new |ct_log| from input |pkey_base64| + * It returns 1 on success, + * 0 on decoding failure, or invalid parameter if any + * -1 on internal (malloc) failure + */ +int +CTLOG_new_from_base64(CTLOG **ct_log, const char *pkey_base64, const char *name) +{ + unsigned char *pkey_der = NULL; + int pkey_der_len; + const unsigned char *p; + EVP_PKEY *pkey = NULL; + + if (ct_log == NULL) { + CTerror(ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + pkey_der_len = ct_base64_decode(pkey_base64, &pkey_der); + if (pkey_der_len < 0) { + CTerror(CT_R_LOG_CONF_INVALID_KEY); + return 0; + } + + p = pkey_der; + pkey = d2i_PUBKEY(NULL, &p, pkey_der_len); + free(pkey_der); + if (pkey == NULL) { + CTerror(CT_R_LOG_CONF_INVALID_KEY); + return 0; + } + + *ct_log = CTLOG_new(pkey, name); + if (*ct_log == NULL) { + EVP_PKEY_free(pkey); + return 0; + } + + return 1; +} diff --git a/crypto/ct/ct_err.c b/crypto/ct/ct_err.c new file mode 100644 index 0000000..fc9ca0c --- /dev/null +++ b/crypto/ct/ct_err.c @@ -0,0 +1,152 @@ +/* $OpenBSD: ct_err.c,v 1.5 2021/12/18 16:50:40 tb Exp $ */ +/* ==================================================================== + * Copyright (c) 1999-2006 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). + * + */ + +/* NOTE: this file was auto generated by the mkerr.pl script: any changes + * made to it will be overwritten when the script next updates this file, + * only reason strings will be preserved. + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static ERR_STRING_DATA CT_str_functs[] = { + {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_NEW, 0), "CTLOG_new"}, + {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_NEW_FROM_BASE64, 0), + "CTLOG_new_from_base64"}, + {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_NEW_FROM_CONF, 0), + "ctlog_new_from_conf"}, + {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_STORE_LOAD_CTX_NEW, 0), + "ctlog_store_load_ctx_new"}, + {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_STORE_LOAD_FILE, 0), + "CTLOG_STORE_load_file"}, + {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_STORE_LOAD_LOG, 0), + "ctlog_store_load_log"}, + {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_STORE_NEW, 0), "CTLOG_STORE_new"}, + {ERR_PACK(ERR_LIB_CT, CT_F_CT_BASE64_DECODE, 0), "ct_base64_decode"}, + {ERR_PACK(ERR_LIB_CT, CT_F_CT_POLICY_EVAL_CTX_NEW, 0), + "CT_POLICY_EVAL_CTX_new"}, + {ERR_PACK(ERR_LIB_CT, CT_F_CT_V1_LOG_ID_FROM_PKEY, 0), + "ct_v1_log_id_from_pkey"}, + {ERR_PACK(ERR_LIB_CT, CT_F_I2O_SCT, 0), "i2o_SCT"}, + {ERR_PACK(ERR_LIB_CT, CT_F_I2O_SCT_LIST, 0), "i2o_SCT_LIST"}, + {ERR_PACK(ERR_LIB_CT, CT_F_I2O_SCT_SIGNATURE, 0), "i2o_SCT_signature"}, + {ERR_PACK(ERR_LIB_CT, CT_F_O2I_SCT, 0), "o2i_SCT"}, + {ERR_PACK(ERR_LIB_CT, CT_F_O2I_SCT_LIST, 0), "o2i_SCT_LIST"}, + {ERR_PACK(ERR_LIB_CT, CT_F_O2I_SCT_SIGNATURE, 0), "o2i_SCT_signature"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_CTX_NEW, 0), "SCT_CTX_new"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_CTX_VERIFY, 0), "SCT_CTX_verify"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_NEW, 0), "SCT_new"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_NEW_FROM_BASE64, 0), + "SCT_new_from_base64"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET0_LOG_ID, 0), "SCT_set0_log_id"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET1_EXTENSIONS, 0), + "SCT_set1_extensions"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET1_LOG_ID, 0), "SCT_set1_log_id"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET1_SIGNATURE, 0), + "SCT_set1_signature"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET_LOG_ENTRY_TYPE, 0), + "SCT_set_log_entry_type"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET_SIGNATURE_NID, 0), + "SCT_set_signature_nid"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET_VERSION, 0), "SCT_set_version"}, + {0, NULL} +}; + +static ERR_STRING_DATA CT_str_reasons[] = { + {ERR_PACK(ERR_LIB_CT, 0, CT_R_BASE64_DECODE_ERROR), + "base64 decode error"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_INVALID_LOG_ID_LENGTH), + "invalid log id length"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_CONF_INVALID), "log conf invalid"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_CONF_INVALID_KEY), + "log conf invalid key"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_CONF_MISSING_DESCRIPTION), + "log conf missing description"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_CONF_MISSING_KEY), + "log conf missing key"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_KEY_INVALID), "log key invalid"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_FUTURE_TIMESTAMP), + "sct future timestamp"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_INVALID), "sct invalid"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_INVALID_SIGNATURE), + "sct invalid signature"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_LIST_INVALID), "sct list invalid"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_LOG_ID_MISMATCH), + "sct log id mismatch"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_NOT_SET), "sct not set"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_UNSUPPORTED_VERSION), + "sct unsupported version"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_UNRECOGNIZED_SIGNATURE_NID), + "unrecognized signature nid"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_UNSUPPORTED_ENTRY_TYPE), + "unsupported entry type"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_UNSUPPORTED_VERSION), + "unsupported version"}, + {0, NULL} +}; + +#endif + +int +ERR_load_CT_strings(void) +{ + if (ERR_func_error_string(CT_str_functs[0].error) == NULL) { + ERR_load_strings(0, CT_str_functs); + ERR_load_strings(0, CT_str_reasons); + } + return 1; +} diff --git a/crypto/ct/ct_local.h b/crypto/ct/ct_local.h new file mode 100644 index 0000000..cd19ed0 --- /dev/null +++ b/crypto/ct/ct_local.h @@ -0,0 +1,260 @@ +/* $OpenBSD: ct_local.h,v 1.8 2021/12/20 17:19:19 jsing Exp $ */ +/* + * Written by Rob Percival (robpercival@google.com) for the OpenSSL project. + */ +/* ==================================================================== + * Copyright (c) 2016 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 + * licensing@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. + * ==================================================================== + */ + +#include + +#include +#include +#include +#include +#include + +#include "bytestring.h" + +/* Number of bytes in an SCT v1 LogID - see RFC 6962 section 3.2. */ +#define CT_V1_LOG_ID_LEN 32 + +/* Maximum size of an SCT - see RFC 6962 section 3.3. */ +#define MAX_SCT_SIZE 65535 +#define MAX_SCT_LIST_SIZE MAX_SCT_SIZE + +/* + * Macros to write integers in network-byte order. + */ + +#define s2n(s,c) ((c[0]=(unsigned char)(((s)>> 8)&0xff), \ + c[1]=(unsigned char)(((s) )&0xff)),c+=2) + +#define l2n3(l,c) ((c[0]=(unsigned char)(((l)>>16)&0xff), \ + c[1]=(unsigned char)(((l)>> 8)&0xff), \ + c[2]=(unsigned char)(((l) )&0xff)),c+=3) + +#define l2n8(l,c) (*((c)++)=(unsigned char)(((l)>>56)&0xff), \ + *((c)++)=(unsigned char)(((l)>>48)&0xff), \ + *((c)++)=(unsigned char)(((l)>>40)&0xff), \ + *((c)++)=(unsigned char)(((l)>>32)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +/* Signed Certificate Timestamp */ +struct sct_st { + sct_version_t version; + /* If version is not SCT_VERSION_V1, this contains the encoded SCT */ + unsigned char *sct; + size_t sct_len; + /* + * If version is SCT_VERSION_V1, fields below contain components of + * the SCT + */ + unsigned char *log_id; + size_t log_id_len; + /* + * Note, we cannot distinguish between an unset timestamp, and one + * that is set to 0. However since CT didn't exist in 1970, no real + * SCT should ever be set as such. + */ + uint64_t timestamp; + unsigned char *ext; + size_t ext_len; + unsigned char hash_alg; + unsigned char sig_alg; + unsigned char *sig; + size_t sig_len; + /* Log entry type */ + ct_log_entry_type_t entry_type; + /* Where this SCT was found, e.g. certificate, OCSP response, etc. */ + sct_source_t source; + /* The result of the last attempt to validate this SCT. */ + sct_validation_status_t validation_status; +}; + +/* Miscellaneous data that is useful when verifying an SCT */ +struct sct_ctx_st { + /* Public key */ + EVP_PKEY *pkey; + /* Hash of public key */ + unsigned char *pkeyhash; + size_t pkeyhashlen; + /* For pre-certificate: issuer public key hash */ + unsigned char *ihash; + size_t ihashlen; + /* certificate encoding */ + unsigned char *certder; + size_t certderlen; + /* pre-certificate encoding */ + unsigned char *preder; + size_t prederlen; + /* + * milliseconds since epoch (to check that the SCT isn't from the + * future) + */ + uint64_t epoch_time_in_ms; +}; + +/* Context when evaluating whether a Certificate Transparency policy is met */ +struct ct_policy_eval_ctx_st { + X509 *cert; + X509 *issuer; + CTLOG_STORE *log_store; + /* + * milliseconds since epoch (to check that the SCT isn't from the + * future) + */ + uint64_t epoch_time_in_ms; +}; + +/* + * Creates a new context for verifying an SCT. + */ +SCT_CTX *SCT_CTX_new(void); +/* + * Deletes an SCT verification context. + */ +void SCT_CTX_free(SCT_CTX *sctx); + +/* + * Sets the certificate that the SCT was created for. + * If *cert does not have a poison extension, presigner must be NULL. + * If *cert does not have a poison extension, it may have a single SCT + * (NID_ct_precert_scts) extension. + * If either *cert or *presigner have an AKID (NID_authority_key_identifier) + * extension, both must have one. + * Returns 1 on success, 0 on failure. + */ +int SCT_CTX_set1_cert(SCT_CTX *sctx, X509 *cert, X509 *presigner); + +/* + * Sets the issuer of the certificate that the SCT was created for. + * This is just a convenience method to save extracting the public key and + * calling SCT_CTX_set1_issuer_pubkey(). + * Issuer must not be NULL. + * Returns 1 on success, 0 on failure. + */ +int SCT_CTX_set1_issuer(SCT_CTX *sctx, const X509 *issuer); + +/* + * Sets the public key of the issuer of the certificate that the SCT was created + * for. + * The public key must not be NULL. + * Returns 1 on success, 0 on failure. + */ +int SCT_CTX_set1_issuer_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey); + +/* + * Sets the public key of the CT log that the SCT is from. + * Returns 1 on success, 0 on failure. + */ +int SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey); + +/* + * Sets the time to evaluate the SCT against, in milliseconds since the Unix + * epoch. If the SCT's timestamp is after this time, it will be interpreted as + * having been issued in the future. RFC6962 states that "TLS clients MUST + * reject SCTs whose timestamp is in the future", so an SCT will not validate + * in this case. + */ +void SCT_CTX_set_time(SCT_CTX *sctx, uint64_t time_in_ms); + +/* + * Verifies an SCT with the given context. + * Returns 1 if the SCT verifies successfully; any other value indicates + * failure. See EVP_DigestVerifyFinal() for the meaning of those values. + */ +int SCT_CTX_verify(const SCT_CTX *sctx, const SCT *sct); + +/* + * Does this SCT have the minimum fields populated to be usable? + * Returns 1 if so, 0 otherwise. + */ +int SCT_is_complete(const SCT *sct); + +/* + * Does this SCT have the signature-related fields populated? + * Returns 1 if so, 0 otherwise. + * This checks that the signature and hash algorithms are set to supported + * values and that the signature field is set. + */ +int SCT_signature_is_complete(const SCT *sct); + +/* + * TODO(RJPercival): Create an SCT_signature struct and make i2o_SCT_signature + * and o2i_SCT_signature conform to the i2d/d2i conventions. + */ + +/* + * Serialize (to TLS format) an |sct| signature and write it to |out|. + * If |out| is null, no signature will be output but the length will be returned. + * If |out| points to a null pointer, a string will be allocated to hold the + * TLS-format signature. It is the responsibility of the caller to free it. + * If |out| points to an allocated string, the signature will be written to it. + * The length of the signature in TLS format will be returned. + */ +int i2o_SCT_signature(const SCT *sct, unsigned char **out); + +/* + * Parses an SCT signature in TLS format and populates the |sct| with it. + * |in| should be a pointer to a string containing the TLS-format signature. + * |in| will be advanced to the end of the signature if parsing succeeds. + * |len| should be the length of the signature in |in|. + * Returns the number of bytes parsed, or a negative integer if an error occurs. + * If an error occurs, the SCT's signature NID may be updated whilst the + * signature field itself remains unset. + */ +int o2i_SCT_signature(SCT *sct, CBS *cbs); + +/* + * Handlers for Certificate Transparency X509v3/OCSP extensions + */ +extern const X509V3_EXT_METHOD v3_ct_scts[3]; diff --git a/crypto/ct/ct_log.c b/crypto/ct/ct_log.c new file mode 100644 index 0000000..f6e3aa2 --- /dev/null +++ b/crypto/ct/ct_log.c @@ -0,0 +1,365 @@ +/* $OpenBSD: ct_log.c,v 1.5 2021/12/18 16:34:52 tb Exp $ */ +/* Author: Adam Eijdenberg . */ +/* ==================================================================== + * Copyright (c) 1998-2016 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). + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "cryptlib.h" + + +/* + * Information about a CT log server. + */ +struct ctlog_st { + char *name; + uint8_t log_id[CT_V1_HASHLEN]; + EVP_PKEY *public_key; +}; + +/* + * A store for multiple CTLOG instances. + * It takes ownership of any CTLOG instances added to it. + */ +struct ctlog_store_st { + STACK_OF(CTLOG) *logs; +}; + +/* The context when loading a CT log list from a CONF file. */ +typedef struct ctlog_store_load_ctx_st { + CTLOG_STORE *log_store; + CONF *conf; + size_t invalid_log_entries; +} CTLOG_STORE_LOAD_CTX; + +/* + * Creates an empty context for loading a CT log store. + * It should be populated before use. + */ +static CTLOG_STORE_LOAD_CTX *ctlog_store_load_ctx_new(void); + +/* + * Deletes a CT log store load context. + * Does not delete any of the fields. + */ +static void ctlog_store_load_ctx_free(CTLOG_STORE_LOAD_CTX *ctx); + +static CTLOG_STORE_LOAD_CTX * +ctlog_store_load_ctx_new(void) +{ + CTLOG_STORE_LOAD_CTX *ctx = calloc(1, sizeof(*ctx)); + + if (ctx == NULL) + CTerror(ERR_R_MALLOC_FAILURE); + + return ctx; +} + +static void +ctlog_store_load_ctx_free(CTLOG_STORE_LOAD_CTX *ctx) +{ + free(ctx); +} + +/* Converts a log's public key into a SHA256 log ID */ +static int +ct_v1_log_id_from_pkey(EVP_PKEY *pkey, unsigned char log_id[CT_V1_HASHLEN]) +{ + int ret = 0; + unsigned char *pkey_der = NULL; + int pkey_der_len = i2d_PUBKEY(pkey, &pkey_der); + + if (pkey_der_len <= 0) { + CTerror(CT_R_LOG_KEY_INVALID); + goto err; + } + + SHA256(pkey_der, pkey_der_len, log_id); + ret = 1; + err: + free(pkey_der); + return ret; +} + +CTLOG_STORE * +CTLOG_STORE_new(void) +{ + CTLOG_STORE *ret = calloc(1, sizeof(*ret)); + + if (ret == NULL) { + CTerror(ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->logs = sk_CTLOG_new_null(); + if (ret->logs == NULL) + goto err; + + return ret; + err: + free(ret); + return NULL; +} + +void +CTLOG_STORE_free(CTLOG_STORE *store) +{ + if (store != NULL) { + sk_CTLOG_pop_free(store->logs, CTLOG_free); + free(store); + } +} + +static int +ctlog_new_from_conf(CTLOG **ct_log, const CONF *conf, const char *section) +{ + const char *description = NCONF_get_string(conf, section, + "description"); + char *pkey_base64; + + if (description == NULL) { + CTerror(CT_R_LOG_CONF_MISSING_DESCRIPTION); + return 0; + } + + pkey_base64 = NCONF_get_string(conf, section, "key"); + if (pkey_base64 == NULL) { + CTerror(CT_R_LOG_CONF_MISSING_KEY); + return 0; + } + + return CTLOG_new_from_base64(ct_log, pkey_base64, description); +} + +int +CTLOG_STORE_load_default_file(CTLOG_STORE *store) +{ + return CTLOG_STORE_load_file(store, CTLOG_FILE); +} + +/* + * Called by CONF_parse_list, which stops if this returns <= 0, + * Otherwise, one bad log entry would stop loading of any of + * the following log entries. + * It may stop parsing and returns -1 on any internal (malloc) error. + */ +static int +ctlog_store_load_log(const char *log_name, int log_name_len, void *arg) +{ + CTLOG_STORE_LOAD_CTX *load_ctx = arg; + CTLOG *ct_log = NULL; + /* log_name may not be null-terminated, so fix that before using it */ + char *tmp; + int ret = 0; + + /* log_name will be NULL for empty list entries */ + if (log_name == NULL) + return 1; + + tmp = strndup(log_name, log_name_len); + if (tmp == NULL) + goto mem_err; + + ret = ctlog_new_from_conf(&ct_log, load_ctx->conf, tmp); + free(tmp); + + if (ret < 0) { + /* Propagate any internal error */ + return ret; + } + if (ret == 0) { + /* If we can't load this log, record that fact and skip it */ + ++load_ctx->invalid_log_entries; + return 1; + } + + if (!sk_CTLOG_push(load_ctx->log_store->logs, ct_log)) { + goto mem_err; + } + return 1; + + mem_err: + CTLOG_free(ct_log); + CTerror(ERR_R_MALLOC_FAILURE); + return -1; +} + +int +CTLOG_STORE_load_file(CTLOG_STORE *store, const char *file) +{ + int ret = 0; + char *enabled_logs; + CTLOG_STORE_LOAD_CTX* load_ctx = ctlog_store_load_ctx_new(); + + if (load_ctx == NULL) + return 0; + load_ctx->log_store = store; + load_ctx->conf = NCONF_new(NULL); + if (load_ctx->conf == NULL) + goto end; + + if (NCONF_load(load_ctx->conf, file, NULL) <= 0) { + CTerror(CT_R_LOG_CONF_INVALID); + goto end; + } + + enabled_logs = NCONF_get_string(load_ctx->conf, NULL, "enabled_logs"); + if (enabled_logs == NULL) { + CTerror(CT_R_LOG_CONF_INVALID); + goto end; + } + + if (!CONF_parse_list(enabled_logs, ',', 1, ctlog_store_load_log, load_ctx) || + load_ctx->invalid_log_entries > 0) { + CTerror(CT_R_LOG_CONF_INVALID); + goto end; + } + + ret = 1; + end: + NCONF_free(load_ctx->conf); + ctlog_store_load_ctx_free(load_ctx); + return ret; +} + +/* + * Initialize a new CTLOG object. + * Takes ownership of the public key. + * Copies the name. + */ +CTLOG * +CTLOG_new(EVP_PKEY *public_key, const char *name) +{ + CTLOG *ret = calloc(1, sizeof(*ret)); + + if (ret == NULL) { + CTerror(ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->name = strdup(name); + if (ret->name == NULL) { + CTerror(ERR_R_MALLOC_FAILURE); + goto err; + } + + if (ct_v1_log_id_from_pkey(public_key, ret->log_id) != 1) + goto err; + + ret->public_key = public_key; + return ret; + err: + CTLOG_free(ret); + return NULL; +} + +/* Frees CT log and associated structures */ +void +CTLOG_free(CTLOG *log) +{ + if (log != NULL) { + free(log->name); + EVP_PKEY_free(log->public_key); + free(log); + } +} + +const char * +CTLOG_get0_name(const CTLOG *log) +{ + return log->name; +} + +void +CTLOG_get0_log_id(const CTLOG *log, const uint8_t **log_id, size_t *log_id_len) +{ + *log_id = log->log_id; + *log_id_len = CT_V1_HASHLEN; +} + +EVP_PKEY * +CTLOG_get0_public_key(const CTLOG *log) +{ + return log->public_key; +} + +/* + * Given a log ID, finds the matching log. + * Returns NULL if no match found. + */ +const CTLOG * +CTLOG_STORE_get0_log_by_id(const CTLOG_STORE *store, const uint8_t *log_id, + size_t log_id_len) +{ + int i; + + for (i = 0; i < sk_CTLOG_num(store->logs); ++i) { + const CTLOG *log = sk_CTLOG_value(store->logs, i); + if (memcmp(log->log_id, log_id, log_id_len) == 0) + return log; + } + + return NULL; +} diff --git a/crypto/ct/ct_oct.c b/crypto/ct/ct_oct.c new file mode 100644 index 0000000..94e67c6 --- /dev/null +++ b/crypto/ct/ct_oct.c @@ -0,0 +1,458 @@ +/* $OpenBSD: ct_oct.c,v 1.8 2021/12/20 17:23:07 jsing Exp $ */ +/* + * Written by Rob Stradling (rob@comodo.com) and Stephen Henson + * (steve@openssl.org) for the OpenSSL project 2014. + */ +/* ==================================================================== + * Copyright (c) 2014 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 + * licensing@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). + * + */ + +#ifdef OPENSSL_NO_CT +# error "CT is disabled" +#endif + +#include +#include + +#include +#include +#include +#include + +#include "bytestring.h" +#include "ct_local.h" + +int +o2i_SCT_signature(SCT *sct, CBS *cbs) +{ + uint8_t hash_alg, sig_alg; + CBS signature; + + if (sct->version != SCT_VERSION_V1) { + CTerror(CT_R_UNSUPPORTED_VERSION); + return 0; + } + + /* + * Parse a digitally-signed element - see RFC 6962 section 3.2 and + * RFC 5246 sections 4.7 and 7.4.1.4.1. + */ + if (!CBS_get_u8(cbs, &hash_alg)) + goto err_invalid; + if (!CBS_get_u8(cbs, &sig_alg)) + goto err_invalid; + if (!CBS_get_u16_length_prefixed(cbs, &signature)) + goto err_invalid; + if (CBS_len(cbs) != 0) + goto err_invalid; + + /* + * Reject empty signatures since they are invalid for all supported + * algorithms (this really should be done by SCT_set1_signature()). + */ + if (CBS_len(&signature) == 0) + goto err_invalid; + + sct->hash_alg = hash_alg; + sct->sig_alg = sig_alg; + + if (SCT_get_signature_nid(sct) == NID_undef) + goto err_invalid; + + if (!SCT_set1_signature(sct, CBS_data(&signature), CBS_len(&signature))) + return 0; + + return 1; + + err_invalid: + CTerror(CT_R_SCT_INVALID_SIGNATURE); + return 0; +} + +static int +o2i_SCT_internal(SCT **out_sct, CBS *cbs) +{ + SCT *sct = NULL; + uint8_t version; + + *out_sct = NULL; + + if ((sct = SCT_new()) == NULL) + goto err; + + if (CBS_len(cbs) > MAX_SCT_SIZE) + goto err_invalid; + if (!CBS_peek_u8(cbs, &version)) + goto err_invalid; + + sct->version = version; + + if (version == SCT_VERSION_V1) { + CBS extensions, log_id; + uint64_t timestamp; + + /* + * Parse a v1 SignedCertificateTimestamp - see RFC 6962 + * section 3.2. + */ + if (!CBS_get_u8(cbs, &version)) + goto err_invalid; + if (!CBS_get_bytes(cbs, &log_id, CT_V1_LOG_ID_LEN)) + goto err_invalid; + if (!CBS_get_u64(cbs, ×tamp)) + goto err_invalid; + if (!CBS_get_u16_length_prefixed(cbs, &extensions)) + goto err_invalid; + + if (!CBS_stow(&log_id, &sct->log_id, &sct->log_id_len)) + goto err; + + sct->timestamp = timestamp; + + if (!CBS_stow(&extensions, &sct->ext, &sct->ext_len)) + goto err; + + if (!o2i_SCT_signature(sct, cbs)) + goto err; + + if (CBS_len(cbs) != 0) + goto err_invalid; + } else { + /* If not V1 just cache encoding. */ + if (!CBS_stow(cbs, &sct->sct, &sct->sct_len)) + goto err; + } + + *out_sct = sct; + + return 1; + + err_invalid: + CTerror(CT_R_SCT_INVALID); + err: + SCT_free(sct); + + return 0; +} + +SCT * +o2i_SCT(SCT **psct, const unsigned char **in, size_t len) +{ + SCT *sct; + CBS cbs; + + CBS_init(&cbs, *in, len); + + if (psct != NULL) { + SCT_free(*psct); + *psct = NULL; + } + + if (!o2i_SCT_internal(&sct, &cbs)) + return NULL; + + if (psct != NULL) + *psct = sct; + + *in = CBS_data(&cbs); + + return sct; +} + +int +i2o_SCT_signature(const SCT *sct, unsigned char **out) +{ + size_t len; + unsigned char *p = NULL, *pstart = NULL; + + if (!SCT_signature_is_complete(sct)) { + CTerror(CT_R_SCT_INVALID_SIGNATURE); + goto err; + } + + if (sct->version != SCT_VERSION_V1) { + CTerror(CT_R_UNSUPPORTED_VERSION); + goto err; + } + + /* + * (1 byte) Hash algorithm + * (1 byte) Signature algorithm + * (2 bytes + ?) Signature + */ + len = 4 + sct->sig_len; + + if (out != NULL) { + if (*out != NULL) { + p = *out; + *out += len; + } else { + pstart = p = malloc(len); + if (p == NULL) { + CTerror(ERR_R_MALLOC_FAILURE); + goto err; + } + *out = p; + } + + *p++ = sct->hash_alg; + *p++ = sct->sig_alg; + s2n(sct->sig_len, p); + memcpy(p, sct->sig, sct->sig_len); + } + + return len; + err: + free(pstart); + return -1; +} + +int +i2o_SCT(const SCT *sct, unsigned char **out) +{ + size_t len; + unsigned char *p = NULL, *pstart = NULL; + + if (!SCT_is_complete(sct)) { + CTerror(CT_R_SCT_NOT_SET); + goto err; + } + /* + * Fixed-length header: struct { (1 byte) Version sct_version; (32 bytes) + * log_id id; (8 bytes) uint64 timestamp; (2 bytes + ?) CtExtensions + * extensions; (1 byte) Hash algorithm (1 byte) Signature algorithm (2 + * bytes + ?) Signature + */ + if (sct->version == SCT_VERSION_V1) + len = 43 + sct->ext_len + 4 + sct->sig_len; + else + len = sct->sct_len; + + if (out == NULL) + return len; + + if (*out != NULL) { + p = *out; + *out += len; + } else { + pstart = p = malloc(len); + if (p == NULL) { + CTerror(ERR_R_MALLOC_FAILURE); + goto err; + } + *out = p; + } + + if (sct->version == SCT_VERSION_V1) { + *p++ = sct->version; + memcpy(p, sct->log_id, CT_V1_HASHLEN); + p += CT_V1_HASHLEN; + l2n8(sct->timestamp, p); + s2n(sct->ext_len, p); + if (sct->ext_len > 0) { + memcpy(p, sct->ext, sct->ext_len); + p += sct->ext_len; + } + if (i2o_SCT_signature(sct, &p) <= 0) + goto err; + } else { + memcpy(p, sct->sct, len); + } + + return len; + err: + free(pstart); + return -1; +} + +STACK_OF(SCT) * +o2i_SCT_LIST(STACK_OF(SCT) **out_scts, const unsigned char **pp, size_t len) +{ + CBS cbs, cbs_scts, cbs_sct; + STACK_OF(SCT) *scts = NULL; + + CBS_init(&cbs, *pp, len); + + if (CBS_len(&cbs) > MAX_SCT_LIST_SIZE) + goto err_invalid; + if (!CBS_get_u16_length_prefixed(&cbs, &cbs_scts)) + goto err_invalid; + if (CBS_len(&cbs) != 0) + goto err_invalid; + + if (out_scts != NULL) { + SCT_LIST_free(*out_scts); + *out_scts = NULL; + } + + if ((scts = sk_SCT_new_null()) == NULL) + return NULL; + + while (CBS_len(&cbs_scts) > 0) { + SCT *sct; + + if (!CBS_get_u16_length_prefixed(&cbs_scts, &cbs_sct)) + goto err_invalid; + + if (!o2i_SCT_internal(&sct, &cbs_sct)) + goto err; + if (!sk_SCT_push(scts, sct)) { + SCT_free(sct); + goto err; + } + } + + if (out_scts != NULL) + *out_scts = scts; + + *pp = CBS_data(&cbs); + + return scts; + + err_invalid: + CTerror(CT_R_SCT_LIST_INVALID); + err: + SCT_LIST_free(scts); + + return NULL; +} + +int +i2o_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp) +{ + int len, sct_len, i, is_pp_new = 0; + size_t len2; + unsigned char *p = NULL, *p2; + + if (pp != NULL) { + if (*pp == NULL) { + if ((len = i2o_SCT_LIST(a, NULL)) == -1) { + CTerror(CT_R_SCT_LIST_INVALID); + return -1; + } + if ((*pp = malloc(len)) == NULL) { + CTerror(ERR_R_MALLOC_FAILURE); + return -1; + } + is_pp_new = 1; + } + p = *pp + 2; + } + + len2 = 2; + for (i = 0; i < sk_SCT_num(a); i++) { + if (pp != NULL) { + p2 = p; + p += 2; + if ((sct_len = i2o_SCT(sk_SCT_value(a, i), &p)) == -1) + goto err; + s2n(sct_len, p2); + } else { + if ((sct_len = i2o_SCT(sk_SCT_value(a, i), NULL)) == -1) + goto err; + } + len2 += 2 + sct_len; + } + + if (len2 > MAX_SCT_LIST_SIZE) + goto err; + + if (pp != NULL) { + p = *pp; + s2n(len2 - 2, p); + if (!is_pp_new) + *pp += len2; + } + return len2; + + err: + if (is_pp_new) { + free(*pp); + *pp = NULL; + } + return -1; +} + +STACK_OF(SCT) * +d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, long len) +{ + ASN1_OCTET_STRING *oct = NULL; + STACK_OF(SCT) *sk = NULL; + const unsigned char *p; + + p = *pp; + if (d2i_ASN1_OCTET_STRING(&oct, &p, len) == NULL) + return NULL; + + p = oct->data; + if ((sk = o2i_SCT_LIST(a, &p, oct->length)) != NULL) + *pp += len; + + ASN1_OCTET_STRING_free(oct); + return sk; +} + +int +i2d_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **out) +{ + ASN1_OCTET_STRING oct; + int len; + + oct.data = NULL; + if ((oct.length = i2o_SCT_LIST(a, &oct.data)) == -1) + return -1; + + len = i2d_ASN1_OCTET_STRING(&oct, out); + free(oct.data); + return len; +} diff --git a/crypto/asn1/t_bitst.c b/crypto/ct/ct_policy.c similarity index 53% rename from crypto/asn1/t_bitst.c rename to crypto/ct/ct_policy.c index 51515b8..2cb3e69 100644 --- a/crypto/asn1/t_bitst.c +++ b/crypto/ct/ct_policy.c @@ -1,9 +1,10 @@ -/* $OpenBSD: t_bitst.c,v 1.8 2018/04/25 11:48:21 tb Exp $ */ -/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL - * project 1999. +/* $OpenBSD: ct_policy.c,v 1.5 2021/12/18 16:34:52 tb Exp $ */ +/* + * Implementations of Certificate Transparency SCT policies. + * Written by Rob Percival (robpercival@google.com) for the OpenSSL project. */ /* ==================================================================== - * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * Copyright (c) 2016 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 @@ -49,64 +50,104 @@ * 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). - * */ -#include -#include +#ifdef OPENSSL_NO_CT +# error "CT is disabled" +#endif -#include -#include +#include +#include +#include -int -ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs, - BIT_STRING_BITNAME *tbl, int indent) +#include "ct_local.h" + +/* + * Number of seconds in the future that an SCT timestamp can be, by default, + * without being considered invalid. This is added to time() when setting a + * default value for CT_POLICY_EVAL_CTX.epoch_time_in_ms. + * It can be overridden by calling CT_POLICY_EVAL_CTX_set_time(). + */ +static const time_t SCT_CLOCK_DRIFT_TOLERANCE = 300; + +CT_POLICY_EVAL_CTX * +CT_POLICY_EVAL_CTX_new(void) { - BIT_STRING_BITNAME *bnam; - char first = 1; + CT_POLICY_EVAL_CTX *ctx = calloc(1, sizeof(CT_POLICY_EVAL_CTX)); - BIO_printf(out, "%*s", indent, ""); - for (bnam = tbl; bnam->lname; bnam++) { - if (ASN1_BIT_STRING_get_bit(bs, bnam->bitnum)) { - if (!first) - BIO_puts(out, ", "); - BIO_puts(out, bnam->lname); - first = 0; - } + if (ctx == NULL) { + CTerror(ERR_R_MALLOC_FAILURE); + return NULL; } - BIO_puts(out, "\n"); - return 1; + + /* time(NULL) shouldn't ever fail, so don't bother checking for -1. */ + ctx->epoch_time_in_ms = (uint64_t)(time(NULL) + SCT_CLOCK_DRIFT_TOLERANCE) * + 1000; + + return ctx; +} + +void +CT_POLICY_EVAL_CTX_free(CT_POLICY_EVAL_CTX *ctx) +{ + if (ctx == NULL) + return; + X509_free(ctx->cert); + X509_free(ctx->issuer); + free(ctx); } int -ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, const char *name, int value, - BIT_STRING_BITNAME *tbl) +CT_POLICY_EVAL_CTX_set1_cert(CT_POLICY_EVAL_CTX *ctx, X509 *cert) { - int bitnum; - - bitnum = ASN1_BIT_STRING_num_asc(name, tbl); - if (bitnum < 0) + if (!X509_up_ref(cert)) return 0; - if (bs) { - if (!ASN1_BIT_STRING_set_bit(bs, bitnum, value)) - return 0; - } + ctx->cert = cert; return 1; } int -ASN1_BIT_STRING_num_asc(const char *name, BIT_STRING_BITNAME *tbl) +CT_POLICY_EVAL_CTX_set1_issuer(CT_POLICY_EVAL_CTX *ctx, X509 *issuer) { - BIT_STRING_BITNAME *bnam; - - for (bnam = tbl; bnam->lname; bnam++) { - if (!strcmp(bnam->sname, name) || - !strcmp(bnam->lname, name)) - return bnam->bitnum; - } - return -1; + if (!X509_up_ref(issuer)) + return 0; + ctx->issuer = issuer; + return 1; +} + +void +CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(CT_POLICY_EVAL_CTX *ctx, + CTLOG_STORE *log_store) +{ + ctx->log_store = log_store; +} + +void +CT_POLICY_EVAL_CTX_set_time(CT_POLICY_EVAL_CTX *ctx, uint64_t time_in_ms) +{ + ctx->epoch_time_in_ms = time_in_ms; +} + +X509 * +CT_POLICY_EVAL_CTX_get0_cert(const CT_POLICY_EVAL_CTX *ctx) +{ + return ctx->cert; +} + +X509 * +CT_POLICY_EVAL_CTX_get0_issuer(const CT_POLICY_EVAL_CTX *ctx) +{ + return ctx->issuer; +} + +const CTLOG_STORE * +CT_POLICY_EVAL_CTX_get0_log_store(const CT_POLICY_EVAL_CTX *ctx) +{ + return ctx->log_store; +} + +uint64_t +CT_POLICY_EVAL_CTX_get_time(const CT_POLICY_EVAL_CTX *ctx) +{ + return ctx->epoch_time_in_ms; } diff --git a/crypto/ct/ct_prn.c b/crypto/ct/ct_prn.c new file mode 100644 index 0000000..ea4f3b2 --- /dev/null +++ b/crypto/ct/ct_prn.c @@ -0,0 +1,208 @@ +/* $OpenBSD: ct_prn.c,v 1.6 2021/12/18 16:34:52 tb Exp $ */ +/* + * Written by Rob Stradling (rob@comodo.com) and Stephen Henson + * (steve@openssl.org) for the OpenSSL project 2014. + */ +/* ==================================================================== + * Copyright (c) 2014 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 + * licensing@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). + * + */ + +#ifdef OPENSSL_NO_CT +# error "CT is disabled" +#endif + +#include +#include + +#include "ct_local.h" + +/* + * XXX public api in OpenSSL 1.1.0 but this is the only thing that uses it. + * so I am stuffing it here for the moment. + */ +static 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; +} + +static void +SCT_signature_algorithms_print(const SCT *sct, BIO *out) +{ + int nid = SCT_get_signature_nid(sct); + + if (nid == NID_undef) + BIO_printf(out, "%02X%02X", sct->hash_alg, sct->sig_alg); + else + BIO_printf(out, "%s", OBJ_nid2ln(nid)); +} + +static void +timestamp_print(uint64_t timestamp, BIO *out) +{ + ASN1_GENERALIZEDTIME *gen = ASN1_GENERALIZEDTIME_new(); + char genstr[20]; + + if (gen == NULL) + return; + ASN1_GENERALIZEDTIME_adj(gen, (time_t)0, (int)(timestamp / 86400000), + (timestamp % 86400000) / 1000); + /* + * Note GeneralizedTime from ASN1_GENERALIZETIME_adj is always 15 + * characters long with a final Z. Update it with fractional seconds. + */ + snprintf(genstr, sizeof(genstr), "%.14sZ", ASN1_STRING_get0_data(gen)); + if (ASN1_GENERALIZEDTIME_set_string(gen, genstr)) + ASN1_GENERALIZEDTIME_print(out, gen); + ASN1_GENERALIZEDTIME_free(gen); +} + +const char * +SCT_validation_status_string(const SCT *sct) +{ + switch (SCT_get_validation_status(sct)) { + case SCT_VALIDATION_STATUS_NOT_SET: + return "not set"; + case SCT_VALIDATION_STATUS_UNKNOWN_VERSION: + return "unknown version"; + case SCT_VALIDATION_STATUS_UNKNOWN_LOG: + return "unknown log"; + case SCT_VALIDATION_STATUS_UNVERIFIED: + return "unverified"; + case SCT_VALIDATION_STATUS_INVALID: + return "invalid"; + case SCT_VALIDATION_STATUS_VALID: + return "valid"; + } + return "unknown status"; +} + +void +SCT_print(const SCT *sct, BIO *out, int indent, const CTLOG_STORE *log_store) +{ + const CTLOG *log = NULL; + + if (log_store != NULL) { + log = CTLOG_STORE_get0_log_by_id(log_store, sct->log_id, + sct->log_id_len); + } + + BIO_printf(out, "%*sSigned Certificate Timestamp:", indent, ""); + BIO_printf(out, "\n%*sVersion : ", indent + 4, ""); + + if (sct->version != SCT_VERSION_V1) { + BIO_printf(out, "unknown\n%*s", indent + 16, ""); + BIO_hex_string(out, indent + 16, 16, sct->sct, sct->sct_len); + return; + } + + BIO_printf(out, "v1 (0x0)"); + + if (log != NULL) { + BIO_printf(out, "\n%*sLog : %s", indent + 4, "", + CTLOG_get0_name(log)); + } + + BIO_printf(out, "\n%*sLog ID : ", indent + 4, ""); + BIO_hex_string(out, indent + 16, 16, sct->log_id, sct->log_id_len); + + BIO_printf(out, "\n%*sTimestamp : ", indent + 4, ""); + timestamp_print(sct->timestamp, out); + + BIO_printf(out, "\n%*sExtensions: ", indent + 4, ""); + if (sct->ext_len == 0) + BIO_printf(out, "none"); + else + BIO_hex_string(out, indent + 16, 16, sct->ext, sct->ext_len); + + BIO_printf(out, "\n%*sSignature : ", indent + 4, ""); + SCT_signature_algorithms_print(sct, out); + BIO_printf(out, "\n%*s ", indent + 4, ""); + BIO_hex_string(out, indent + 16, 16, sct->sig, sct->sig_len); +} + +void +SCT_LIST_print(const STACK_OF(SCT) *sct_list, BIO *out, int indent, + const char *separator, const CTLOG_STORE *log_store) +{ + int sct_count = sk_SCT_num(sct_list); + int i; + + for (i = 0; i < sct_count; ++i) { + SCT *sct = sk_SCT_value(sct_list, i); + + SCT_print(sct, out, indent, log_store); + if (i < sk_SCT_num(sct_list) - 1) + BIO_printf(out, "%s", separator); + } +} diff --git a/crypto/ct/ct_sct.c b/crypto/ct/ct_sct.c new file mode 100644 index 0000000..a05b0f9 --- /dev/null +++ b/crypto/ct/ct_sct.c @@ -0,0 +1,480 @@ +/* $OpenBSD: ct_sct.c,v 1.8 2022/01/22 00:29:59 inoguchi Exp $ */ +/* + * Written by Rob Stradling (rob@comodo.com), Stephen Henson (steve@openssl.org) + * and Adam Eijdenberg (adam.eijdenberg@gmail.com) for the OpenSSL project 2016. + */ +/* ==================================================================== + * Copyright (c) 2014 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 + * licensing@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). + * + */ + +#ifdef OPENSSL_NO_CT +# error "CT disabled" +#endif + +#include +#include +#include +#include +#include + +#include + +#include "ct_local.h" + +SCT * +SCT_new(void) +{ + SCT *sct = calloc(1, sizeof(*sct)); + + if (sct == NULL) { + CTerror(ERR_R_MALLOC_FAILURE); + return NULL; + } + + sct->entry_type = CT_LOG_ENTRY_TYPE_NOT_SET; + sct->version = SCT_VERSION_NOT_SET; + return sct; +} + +void +SCT_free(SCT *sct) +{ + if (sct == NULL) + return; + + free(sct->log_id); + free(sct->ext); + free(sct->sig); + free(sct->sct); + free(sct); +} + +void +SCT_LIST_free(STACK_OF(SCT) *scts) +{ + sk_SCT_pop_free(scts, SCT_free); +} + +int +SCT_set_version(SCT *sct, sct_version_t version) +{ + if (version != SCT_VERSION_V1) { + CTerror(CT_R_UNSUPPORTED_VERSION); + return 0; + } + sct->version = version; + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; + return 1; +} + +int +SCT_set_log_entry_type(SCT *sct, ct_log_entry_type_t entry_type) +{ + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; + + switch (entry_type) { + case CT_LOG_ENTRY_TYPE_X509: + case CT_LOG_ENTRY_TYPE_PRECERT: + sct->entry_type = entry_type; + return 1; + case CT_LOG_ENTRY_TYPE_NOT_SET: + break; + } + CTerror(CT_R_UNSUPPORTED_ENTRY_TYPE); + return 0; +} + +int +SCT_set0_log_id(SCT *sct, unsigned char *log_id, size_t log_id_len) +{ + if (sct->version == SCT_VERSION_V1 && log_id_len != CT_V1_HASHLEN) { + CTerror(CT_R_INVALID_LOG_ID_LENGTH); + return 0; + } + + free(sct->log_id); + sct->log_id = log_id; + sct->log_id_len = log_id_len; + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; + return 1; +} + +int +SCT_set1_log_id(SCT *sct, const unsigned char *log_id, size_t log_id_len) +{ + if (sct->version == SCT_VERSION_V1 && log_id_len != CT_V1_HASHLEN) { + CTerror(CT_R_INVALID_LOG_ID_LENGTH); + return 0; + } + + free(sct->log_id); + sct->log_id = NULL; + sct->log_id_len = 0; + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; + + if (log_id != NULL && log_id_len > 0) { + sct->log_id = malloc(log_id_len); + if (sct->log_id == NULL) { + CTerror(ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(sct->log_id, log_id, log_id_len); + sct->log_id_len = log_id_len; + } + return 1; +} + + +void +SCT_set_timestamp(SCT *sct, uint64_t timestamp) +{ + sct->timestamp = timestamp; + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; +} + +int +SCT_set_signature_nid(SCT *sct, int nid) +{ + switch (nid) { + case NID_sha256WithRSAEncryption: + sct->hash_alg = 4; /* XXX */ + sct->sig_alg = 1; /* XXX */ + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; + return 1; + case NID_ecdsa_with_SHA256: + sct->hash_alg = 4; /* XXX */ + sct->sig_alg = 3; /* XXX */ + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; + return 1; + default: + CTerror(CT_R_UNRECOGNIZED_SIGNATURE_NID); + return 0; + } +} + +void +SCT_set0_extensions(SCT *sct, unsigned char *ext, size_t ext_len) +{ + free(sct->ext); + sct->ext = ext; + sct->ext_len = ext_len; + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; +} + +int +SCT_set1_extensions(SCT *sct, const unsigned char *ext, size_t ext_len) +{ + free(sct->ext); + sct->ext = NULL; + sct->ext_len = 0; + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; + + if (ext != NULL && ext_len > 0) { + sct->ext = malloc(ext_len); + if (sct->ext == NULL) { + CTerror(ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(sct->ext, ext, ext_len); + sct->ext_len = ext_len; + } + return 1; +} + +void +SCT_set0_signature(SCT *sct, unsigned char *sig, size_t sig_len) +{ + free(sct->sig); + sct->sig = sig; + sct->sig_len = sig_len; + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; +} + +int +SCT_set1_signature(SCT *sct, const unsigned char *sig, size_t sig_len) +{ + free(sct->sig); + sct->sig = NULL; + sct->sig_len = 0; + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; + + if (sig != NULL && sig_len > 0) { + sct->sig = malloc(sig_len); + if (sct->sig == NULL) { + CTerror(ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(sct->sig, sig, sig_len); + sct->sig_len = sig_len; + } + return 1; +} + +sct_version_t +SCT_get_version(const SCT *sct) +{ + return sct->version; +} + +ct_log_entry_type_t +SCT_get_log_entry_type(const SCT *sct) +{ + return sct->entry_type; +} + +size_t +SCT_get0_log_id(const SCT *sct, unsigned char **log_id) +{ + *log_id = sct->log_id; + return sct->log_id_len; +} + +uint64_t +SCT_get_timestamp(const SCT *sct) +{ + return sct->timestamp; +} + +int +SCT_get_signature_nid(const SCT *sct) +{ + if (sct->version == SCT_VERSION_V1) { + /* XXX sigalg numbers */ + if (sct->hash_alg == 4) { + switch (sct->sig_alg) { + case 3: + return NID_ecdsa_with_SHA256; + case 1: + return NID_sha256WithRSAEncryption; + default: + return NID_undef; + } + } + } + return NID_undef; +} + +size_t +SCT_get0_extensions(const SCT *sct, unsigned char **ext) +{ + *ext = sct->ext; + return sct->ext_len; +} + +size_t +SCT_get0_signature(const SCT *sct, unsigned char **sig) +{ + *sig = sct->sig; + return sct->sig_len; +} + +int +SCT_is_complete(const SCT *sct) +{ + switch (sct->version) { + case SCT_VERSION_NOT_SET: + return 0; + case SCT_VERSION_V1: + return sct->log_id != NULL && SCT_signature_is_complete(sct); + default: + return sct->sct != NULL; /* Just need cached encoding */ + } +} + +int +SCT_signature_is_complete(const SCT *sct) +{ + return SCT_get_signature_nid(sct) != NID_undef && + sct->sig != NULL && sct->sig_len > 0; +} + +sct_source_t +SCT_get_source(const SCT *sct) +{ + return sct->source; +} + +int +SCT_set_source(SCT *sct, sct_source_t source) +{ + sct->source = source; + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; + switch (source) { + case SCT_SOURCE_TLS_EXTENSION: + case SCT_SOURCE_OCSP_STAPLED_RESPONSE: + return SCT_set_log_entry_type(sct, CT_LOG_ENTRY_TYPE_X509); + case SCT_SOURCE_X509V3_EXTENSION: + return SCT_set_log_entry_type(sct, CT_LOG_ENTRY_TYPE_PRECERT); + case SCT_SOURCE_UNKNOWN: + break; + } + /* if we aren't sure, leave the log entry type alone */ + return 1; +} + +sct_validation_status_t +SCT_get_validation_status(const SCT *sct) +{ + return sct->validation_status; +} + +int +SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx) +{ + int is_sct_valid = -1; + SCT_CTX *sctx = NULL; + X509_PUBKEY *pub = NULL, *log_pkey = NULL; + const CTLOG *log; + + /* + * With an unrecognized SCT version we don't know what such an SCT means, + * let alone validate one. So we return validation failure (0). + */ + if (sct->version != SCT_VERSION_V1) { + sct->validation_status = SCT_VALIDATION_STATUS_UNKNOWN_VERSION; + return 0; + } + + log = CTLOG_STORE_get0_log_by_id(ctx->log_store, sct->log_id, + sct->log_id_len); + + /* Similarly, an SCT from an unknown log also cannot be validated. */ + if (log == NULL) { + sct->validation_status = SCT_VALIDATION_STATUS_UNKNOWN_LOG; + return 0; + } + + sctx = SCT_CTX_new(); + if (sctx == NULL) + goto err; + + if (X509_PUBKEY_set(&log_pkey, CTLOG_get0_public_key(log)) != 1) + goto err; + if (SCT_CTX_set1_pubkey(sctx, log_pkey) != 1) + goto err; + + if (SCT_get_log_entry_type(sct) == CT_LOG_ENTRY_TYPE_PRECERT) { + EVP_PKEY *issuer_pkey; + + if (ctx->issuer == NULL) { + sct->validation_status = SCT_VALIDATION_STATUS_UNVERIFIED; + goto end; + } + + if ((issuer_pkey = X509_get0_pubkey(ctx->issuer)) == NULL) + goto err; + + if (X509_PUBKEY_set(&pub, issuer_pkey) != 1) + goto err; + if (SCT_CTX_set1_issuer_pubkey(sctx, pub) != 1) + goto err; + } + + SCT_CTX_set_time(sctx, ctx->epoch_time_in_ms); + + /* + * XXX: Potential for optimization. This repeats some idempotent heavy + * lifting on the certificate for each candidate SCT, and appears to not + * use any information in the SCT itself, only the certificate is + * processed. So it may make more sense to to do this just once, perhaps + * associated with the shared (by all SCTs) policy eval ctx. + * + * XXX: Failure here is global (SCT independent) and represents either an + * issue with the certificate (e.g. duplicate extensions) or an out of + * memory condition. When the certificate is incompatible with CT, we just + * mark the SCTs invalid, rather than report a failure to determine the + * validation status. That way, callbacks that want to do "soft" SCT + * processing will not abort handshakes with false positive internal + * errors. Since the function does not distinguish between certificate + * issues (peer's fault) and internal problems (out fault) the safe thing + * to do is to report a validation failure and let the callback or + * application decide what to do. + */ + if (SCT_CTX_set1_cert(sctx, ctx->cert, NULL) != 1) + sct->validation_status = SCT_VALIDATION_STATUS_UNVERIFIED; + else + sct->validation_status = SCT_CTX_verify(sctx, sct) == 1 ? + SCT_VALIDATION_STATUS_VALID : SCT_VALIDATION_STATUS_INVALID; + + end: + is_sct_valid = sct->validation_status == SCT_VALIDATION_STATUS_VALID; + err: + X509_PUBKEY_free(pub); + X509_PUBKEY_free(log_pkey); + SCT_CTX_free(sctx); + + return is_sct_valid; +} + +int +SCT_LIST_validate(const STACK_OF(SCT) *scts, CT_POLICY_EVAL_CTX *ctx) +{ + int are_scts_valid = 1; + int sct_count = scts != NULL ? sk_SCT_num(scts) : 0; + int i; + + for (i = 0; i < sct_count; ++i) { + int is_sct_valid = -1; + SCT *sct = sk_SCT_value(scts, i); + + if (sct == NULL) + continue; + + is_sct_valid = SCT_validate(sct, ctx); + if (is_sct_valid < 0) + return is_sct_valid; + are_scts_valid &= is_sct_valid; + } + + return are_scts_valid; +} diff --git a/crypto/ct/ct_sct_ctx.c b/crypto/ct/ct_sct_ctx.c new file mode 100644 index 0000000..1863058 --- /dev/null +++ b/crypto/ct/ct_sct_ctx.c @@ -0,0 +1,323 @@ +/* $OpenBSD: ct_sct_ctx.c,v 1.5 2021/12/18 16:34:52 tb Exp $ */ +/* + * Written by Rob Stradling (rob@comodo.com) and Stephen Henson + * (steve@openssl.org) for the OpenSSL project 2014. + */ +/* ==================================================================== + * Copyright (c) 2014 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 + * licensing@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). + * + */ + +#ifdef OPENSSL_NO_CT +# error "CT is disabled" +#endif + +#include +#include + +#include +#include +#include + +#include "ct_local.h" + +SCT_CTX * +SCT_CTX_new(void) +{ + SCT_CTX *sctx = calloc(1, sizeof(*sctx)); + + if (sctx == NULL) + CTerror(ERR_R_MALLOC_FAILURE); + + return sctx; +} + +void +SCT_CTX_free(SCT_CTX *sctx) +{ + if (sctx == NULL) + return; + EVP_PKEY_free(sctx->pkey); + free(sctx->pkeyhash); + free(sctx->ihash); + free(sctx->certder); + free(sctx->preder); + free(sctx); +} + +/* + * Finds the index of the first extension with the given NID in cert. + * If there is more than one extension with that NID, *is_duplicated is set to + * 1, otherwise 0 (unless it is NULL). + */ +static int +ct_x509_get_ext(X509 *cert, int nid, int *is_duplicated) +{ + int ret = X509_get_ext_by_NID(cert, nid, -1); + + if (is_duplicated != NULL) + *is_duplicated = ret >= 0 && + X509_get_ext_by_NID(cert, nid, ret) >= 0; + + return ret; +} + +/* + * Modifies a certificate by deleting extensions and copying the issuer and + * AKID from the presigner certificate, if necessary. + * Returns 1 on success, 0 otherwise. + */ +static int +ct_x509_cert_fixup(X509 *cert, X509 *presigner) +{ + int preidx, certidx; + int pre_akid_ext_is_dup, cert_akid_ext_is_dup; + + if (presigner == NULL) + return 1; + + preidx = ct_x509_get_ext(presigner, NID_authority_key_identifier, + &pre_akid_ext_is_dup); + certidx = ct_x509_get_ext(cert, NID_authority_key_identifier, + &cert_akid_ext_is_dup); + + /* An error occurred whilst searching for the extension */ + if (preidx < -1 || certidx < -1) + return 0; + /* Invalid certificate if they contain duplicate extensions */ + if (pre_akid_ext_is_dup || cert_akid_ext_is_dup) + return 0; + /* AKID must be present in both certificate or absent in both */ + if (preidx >= 0 && certidx == -1) + return 0; + if (preidx == -1 && certidx >= 0) + return 0; + /* Copy issuer name */ + if (!X509_set_issuer_name(cert, X509_get_issuer_name(presigner))) + return 0; + if (preidx != -1) { + /* Retrieve and copy AKID encoding */ + X509_EXTENSION *preext = X509_get_ext(presigner, preidx); + X509_EXTENSION *certext = X509_get_ext(cert, certidx); + ASN1_OCTET_STRING *preextdata; + + /* Should never happen */ + if (preext == NULL || certext == NULL) + return 0; + preextdata = X509_EXTENSION_get_data(preext); + if (preextdata == NULL || + !X509_EXTENSION_set_data(certext, preextdata)) + return 0; + } + return 1; +} + +int +SCT_CTX_set1_cert(SCT_CTX *sctx, X509 *cert, X509 *presigner) +{ + unsigned char *certder = NULL, *preder = NULL; + X509 *pretmp = NULL; + int certderlen = 0, prederlen = 0; + int idx = -1; + int poison_ext_is_dup, sct_ext_is_dup; + int poison_idx = ct_x509_get_ext(cert, NID_ct_precert_poison, &poison_ext_is_dup); + + /* Duplicate poison extensions are present - error */ + if (poison_ext_is_dup) + goto err; + + /* If *cert doesn't have a poison extension, it isn't a precert */ + if (poison_idx == -1) { + /* cert isn't a precert, so we shouldn't have a presigner */ + if (presigner != NULL) + goto err; + + certderlen = i2d_X509(cert, &certder); + if (certderlen < 0) + goto err; + } + + /* See if cert has a precert SCTs extension */ + idx = ct_x509_get_ext(cert, NID_ct_precert_scts, &sct_ext_is_dup); + /* Duplicate SCT extensions are present - error */ + if (sct_ext_is_dup) + goto err; + + if (idx >= 0 && poison_idx >= 0) { + /* + * cert can't both contain SCTs (i.e. have an SCT extension) and be a + * precert (i.e. have a poison extension). + */ + goto err; + } + + if (idx == -1) { + idx = poison_idx; + } + + /* + * If either a poison or SCT extension is present, remove it before encoding + * cert. This, along with ct_x509_cert_fixup(), gets a TBSCertificate (see + * RFC5280) from cert, which is what the CT log signed when it produced the + * SCT. + */ + if (idx >= 0) { + X509_EXTENSION *ext; + + /* Take a copy of certificate so we don't modify passed version */ + pretmp = X509_dup(cert); + if (pretmp == NULL) + goto err; + + ext = X509_delete_ext(pretmp, idx); + X509_EXTENSION_free(ext); + + if (!ct_x509_cert_fixup(pretmp, presigner)) + goto err; + + prederlen = i2d_re_X509_tbs(pretmp, &preder); + if (prederlen <= 0) + goto err; + } + + X509_free(pretmp); + + free(sctx->certder); + sctx->certder = certder; + sctx->certderlen = certderlen; + + free(sctx->preder); + sctx->preder = preder; + sctx->prederlen = prederlen; + + return 1; + err: + free(certder); + free(preder); + X509_free(pretmp); + return 0; +} + +static int +ct_public_key_hash(X509_PUBKEY *pkey, unsigned char **hash, size_t *hash_len) +{ + int ret = 0; + unsigned char *md = NULL, *der = NULL; + int der_len; + unsigned int md_len; + + /* Reuse buffer if possible */ + if (*hash != NULL && *hash_len >= SHA256_DIGEST_LENGTH) { + md = *hash; + } else { + md = malloc(SHA256_DIGEST_LENGTH); + if (md == NULL) + goto err; + } + + /* Calculate key hash */ + der_len = i2d_X509_PUBKEY(pkey, &der); + if (der_len <= 0) + goto err; + + if (!EVP_Digest(der, der_len, md, &md_len, EVP_sha256(), NULL)) + goto err; + + if (md != *hash) { + free(*hash); + *hash = md; + *hash_len = SHA256_DIGEST_LENGTH; + } + + md = NULL; + ret = 1; + err: + free(md); + free(der); + return ret; +} + +int +SCT_CTX_set1_issuer(SCT_CTX *sctx, const X509 *issuer) +{ + return SCT_CTX_set1_issuer_pubkey(sctx, X509_get_X509_PUBKEY(issuer)); +} + +int +SCT_CTX_set1_issuer_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey) +{ + return ct_public_key_hash(pubkey, &sctx->ihash, &sctx->ihashlen); +} + +int +SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey) +{ + EVP_PKEY *pkey = X509_PUBKEY_get(pubkey); + + if (pkey == NULL) + return 0; + + if (!ct_public_key_hash(pubkey, &sctx->pkeyhash, &sctx->pkeyhashlen)) { + EVP_PKEY_free(pkey); + return 0; + } + + EVP_PKEY_free(sctx->pkey); + sctx->pkey = pkey; + return 1; +} + +void +SCT_CTX_set_time(SCT_CTX *sctx, uint64_t time_in_ms) +{ + sctx->epoch_time_in_ms = time_in_ms; +} diff --git a/crypto/ct/ct_vfy.c b/crypto/ct/ct_vfy.c new file mode 100644 index 0000000..4241172 --- /dev/null +++ b/crypto/ct/ct_vfy.c @@ -0,0 +1,195 @@ +/* $OpenBSD: ct_vfy.c,v 1.6 2022/01/06 14:34:40 jsing Exp $ */ +/* + * Written by Rob Stradling (rob@comodo.com) and Stephen Henson + * (steve@openssl.org) for the OpenSSL project 2014. + */ +/* ==================================================================== + * Copyright (c) 2014 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 + * licensing@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). + * + */ + +#include + +#include +#include +#include +#include + +#include "ct_local.h" + +typedef enum sct_signature_type_t { + SIGNATURE_TYPE_NOT_SET = -1, + SIGNATURE_TYPE_CERT_TIMESTAMP, + SIGNATURE_TYPE_TREE_HASH +} SCT_SIGNATURE_TYPE; + +/* + * Update encoding for SCT signature verification/generation to supplied + * EVP_MD_CTX. + */ +static int +sct_ctx_update(EVP_MD_CTX *ctx, const SCT_CTX *sctx, const SCT *sct) +{ + CBB cbb, entry, extensions; + uint8_t *data = NULL; + size_t data_len; + int ret = 0; + + memset(&cbb, 0, sizeof(cbb)); + + if (sct->entry_type == CT_LOG_ENTRY_TYPE_NOT_SET) + goto err; + if (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT && sctx->ihash == NULL) + goto err; + + if (!CBB_init(&cbb, 0)) + goto err; + + /* + * Build the digitally-signed struct per RFC 6962 section 3.2. + */ + if (!CBB_add_u8(&cbb, sct->version)) + goto err; + if (!CBB_add_u8(&cbb, SIGNATURE_TYPE_CERT_TIMESTAMP)) + goto err; + if (!CBB_add_u64(&cbb, sct->timestamp)) + goto err; + if (!CBB_add_u16(&cbb, sct->entry_type)) + goto err; + + if (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT) { + if (!CBB_add_bytes(&cbb, sctx->ihash, sctx->ihashlen)) + goto err; + } + + if (!CBB_add_u24_length_prefixed(&cbb, &entry)) + goto err; + if (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT) { + if (sctx->preder == NULL) + goto err; + if (!CBB_add_bytes(&entry, sctx->preder, sctx->prederlen)) + goto err; + } else { + if (sctx->certder == NULL) + goto err; + if (!CBB_add_bytes(&entry, sctx->certder, sctx->certderlen)) + goto err; + } + + if (!CBB_add_u16_length_prefixed(&cbb, &extensions)) + goto err; + if (sct->ext_len > 0) { + if (!CBB_add_bytes(&extensions, sct->ext, sct->ext_len)) + goto err; + } + + if (!CBB_finish(&cbb, &data, &data_len)) + goto err; + + if (!EVP_DigestUpdate(ctx, data, data_len)) + goto err; + + ret = 1; + + err: + CBB_cleanup(&cbb); + free(data); + + return ret; +} + +int +SCT_CTX_verify(const SCT_CTX *sctx, const SCT *sct) +{ + EVP_MD_CTX *ctx = NULL; + int ret = 0; + + if (!SCT_is_complete(sct) || sctx->pkey == NULL || + sct->entry_type == CT_LOG_ENTRY_TYPE_NOT_SET || + (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT && + sctx->ihash == NULL)) { + CTerror(CT_R_SCT_NOT_SET); + return 0; + } + if (sct->version != SCT_VERSION_V1) { + CTerror(CT_R_SCT_UNSUPPORTED_VERSION); + return 0; + } + if (sct->log_id_len != sctx->pkeyhashlen || + memcmp(sct->log_id, sctx->pkeyhash, sctx->pkeyhashlen) != 0) { + CTerror(CT_R_SCT_LOG_ID_MISMATCH); + return 0; + } + if (sct->timestamp > sctx->epoch_time_in_ms) { + CTerror(CT_R_SCT_FUTURE_TIMESTAMP); + return 0; + } + + if ((ctx = EVP_MD_CTX_new()) == NULL) + goto end; + + if (!EVP_DigestVerifyInit(ctx, NULL, EVP_sha256(), NULL, sctx->pkey)) + goto end; + + if (!sct_ctx_update(ctx, sctx, sct)) + goto end; + + /* Verify signature */ + /* If ret < 0 some other error: fall through without setting error */ + if ((ret = EVP_DigestVerifyFinal(ctx, sct->sig, sct->sig_len)) == 0) + CTerror(CT_R_SCT_INVALID_SIGNATURE); + + end: + EVP_MD_CTX_free(ctx); + + return ret; +} diff --git a/crypto/ct/ct_x509v3.c b/crypto/ct/ct_x509v3.c new file mode 100644 index 0000000..59f2975 --- /dev/null +++ b/crypto/ct/ct_x509v3.c @@ -0,0 +1,186 @@ +/* $OpenBSD: ct_x509v3.c,v 1.6 2021/12/25 15:42:32 tb Exp $ */ +/* + * Written by Rob Stradling (rob@comodo.com) and Stephen Henson + * (steve@openssl.org) for the OpenSSL project 2014. + */ +/* ==================================================================== + * Copyright (c) 2014 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 + * licensing@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). + * + */ + +#ifdef OPENSSL_NO_CT +# error "CT is disabled" +#endif + +#include + +#include "ct_local.h" + +static char * +i2s_poison(const X509V3_EXT_METHOD *method, void *val) +{ + return strdup("NULL"); +} + +static void * +s2i_poison(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, const char *str) +{ + return ASN1_NULL_new(); +} + +static int +i2r_SCT_LIST(X509V3_EXT_METHOD *method, STACK_OF(SCT) *sct_list, BIO *out, + int indent) +{ + SCT_LIST_print(sct_list, out, indent, "\n", NULL); + return 1; +} + +static int +set_sct_list_source(STACK_OF(SCT) *s, sct_source_t source) +{ + if (s != NULL) { + int i; + + for (i = 0; i < sk_SCT_num(s); i++) { + int res = SCT_set_source(sk_SCT_value(s, i), source); + + if (res != 1) { + return 0; + } + } + } + return 1; +} + +static STACK_OF(SCT) * +x509_ext_d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, long len) +{ + STACK_OF(SCT) *s = d2i_SCT_LIST(a, pp, len); + + if (set_sct_list_source(s, SCT_SOURCE_X509V3_EXTENSION) != 1) { + SCT_LIST_free(s); + *a = NULL; + return NULL; + } + return s; +} + +static STACK_OF(SCT) * +ocsp_ext_d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, long len) +{ + STACK_OF(SCT) *s = d2i_SCT_LIST(a, pp, len); + + if (set_sct_list_source(s, SCT_SOURCE_OCSP_STAPLED_RESPONSE) != 1) { + SCT_LIST_free(s); + *a = NULL; + return NULL; + } + return s; +} + +/* Handlers for X509v3/OCSP Certificate Transparency extensions */ +const X509V3_EXT_METHOD v3_ct_scts[3] = { + /* X509v3 extension in certificates that contains SCTs */ + [0] = { + .ext_nid = NID_ct_precert_scts, + .ext_flags = 0, + .it = NULL, + .ext_new = NULL, + .ext_free = (X509V3_EXT_FREE)SCT_LIST_free, + .d2i = (X509V3_EXT_D2I)x509_ext_d2i_SCT_LIST, + .i2d = (X509V3_EXT_I2D)i2d_SCT_LIST, + .i2s = NULL, + .s2i = NULL, + .i2v = NULL, + .v2i = NULL, + .i2r = (X509V3_EXT_I2R)i2r_SCT_LIST, + .r2i = NULL, + .usr_data = NULL, + }, + + /* X509v3 extension to mark a certificate as a pre-certificate */ + [1] = { + .ext_nid = NID_ct_precert_poison, + .ext_flags = 0, + .it = &ASN1_NULL_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = i2s_poison, + .s2i = s2i_poison, + .i2v = NULL, + .v2i = NULL, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, + }, + + /* OCSP extension that contains SCTs */ + [2] = { + .ext_nid = NID_ct_cert_scts, + .ext_flags = 0, + .it = NULL, + .ext_new = NULL, + .ext_free = (X509V3_EXT_FREE)SCT_LIST_free, + .d2i = (X509V3_EXT_D2I)ocsp_ext_d2i_SCT_LIST, + .i2d = (X509V3_EXT_I2D)i2d_SCT_LIST, + .i2s = NULL, + .s2i = NULL, + .i2v = NULL, + .v2i = NULL, + .i2r = (X509V3_EXT_I2R)i2r_SCT_LIST, + .r2i = NULL, + .usr_data = NULL, + }, +}; diff --git a/crypto/curve25519/curve25519.c b/crypto/curve25519/curve25519.c index 13b54c3..6df03a3 100644 --- a/crypto/curve25519/curve25519.c +++ b/crypto/curve25519/curve25519.c @@ -1,4 +1,4 @@ -/* $OpenBSD: curve25519.c,v 1.5 2019/05/11 15:55:52 tb Exp $ */ +/* $OpenBSD: curve25519.c,v 1.6 2022/02/08 16:44:23 tb Exp $ */ /* * Copyright (c) 2015, Google Inc. * @@ -3513,7 +3513,7 @@ static void table_select(ge_precomp *t, int pos, signed char b) { * * Preconditions: * a[31] <= 127 */ -void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t *a) { +void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]) { signed char e[64]; signed char carry; ge_p1p1 r; diff --git a/crypto/des/cfb_enc.c b/crypto/des/cfb_enc.c index 59a3e71..4231f46 100644 --- a/crypto/des/cfb_enc.c +++ b/crypto/des/cfb_enc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cfb_enc.c,v 1.13 2015/02/10 09:46:30 miod Exp $ */ +/* $OpenBSD: cfb_enc.c,v 1.14 2021/11/09 18:40:21 bcook Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -57,7 +57,7 @@ */ #include "des_locl.h" -#include +#include /* The input and output are loaded in multiples of 8 bits. * What this means is that if you hame numbits=12 and length=2 diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c index af15fb2..0df7fbc 100644 --- a/crypto/dh/dh_ameth.c +++ b/crypto/dh/dh_ameth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dh_ameth.c,v 1.18 2020/01/04 13:57:43 inoguchi Exp $ */ +/* $OpenBSD: dh_ameth.c,v 1.23 2022/01/20 11:00:34 inoguchi Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2006. */ @@ -10,7 +10,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * 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 @@ -65,6 +65,8 @@ #include #include "asn1_locl.h" +#include "dh_local.h" +#include "evp_locl.h" static void int_dh_free(EVP_PKEY *pkey) @@ -93,7 +95,7 @@ dh_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) goto err; } - pstr = pval; + pstr = pval; pm = pstr->data; pmlen = pstr->length; @@ -178,7 +180,7 @@ err: * that the AlgorithmIdentifier contains the paramaters, the private key * is explcitly included and the pubkey must be recalculated. */ - + static int dh_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8) { @@ -202,7 +204,7 @@ dh_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8) if (!(privkey=d2i_ASN1_INTEGER(NULL, &p, pklen))) goto decerr; - pstr = pval; + pstr = pval; pm = pstr->data; pmlen = pstr->length; if (!(dh = d2i_DHparams(NULL, &pm, pmlen))) @@ -351,7 +353,8 @@ do_dh_print(BIO *bp, const DH *x, int indent, ASN1_PCTX *ctx, int ptype) goto err; } - BIO_indent(bp, indent, 128); + if (!BIO_indent(bp, indent, 128)) + goto err; if (BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0) goto err; indent += 4; @@ -366,7 +369,8 @@ do_dh_print(BIO *bp, const DH *x, int indent, ASN1_PCTX *ctx, int ptype) if (!ASN1_bn_print(bp, "generator:", x->g, m, indent)) goto err; if (x->length != 0) { - BIO_indent(bp, indent, 128); + if (!BIO_indent(bp, indent, 128)) + goto err; if (BIO_printf(bp, "recommended-private-length: %d bits\n", (int)x->length) <= 0) goto err; @@ -464,6 +468,32 @@ DHparams_print(BIO *bp, const DH *x) return do_dh_print(bp, x, 4, NULL, 0); } +static int +dh_pkey_public_check(const EVP_PKEY *pkey) +{ + DH *dh = pkey->pkey.dh; + + if (dh->pub_key == NULL) { + DHerror(DH_R_MISSING_PUBKEY); + return 0; + } + + return DH_check_pub_key_ex(dh, dh->pub_key); +} + +static int +dh_pkey_param_check(const EVP_PKEY *pkey) +{ + DH *dh = pkey->pkey.dh; + + /* + * It would have made more sense to support EVP_PKEY_check() for DH + * keys and call DH_check_ex() there and keeping this as a wrapper + * for DH_param_check_ex(). We follow OpenSSL's choice. + */ + return DH_check_ex(dh); +} + const EVP_PKEY_ASN1_METHOD dh_asn1_meth = { .pkey_id = EVP_PKEY_DH, .pkey_base_id = EVP_PKEY_DH, @@ -491,4 +521,8 @@ const EVP_PKEY_ASN1_METHOD dh_asn1_meth = { .param_print = dh_param_print, .pkey_free = int_dh_free, + + .pkey_check = NULL, + .pkey_public_check = dh_pkey_public_check, + .pkey_param_check = dh_pkey_param_check, }; diff --git a/crypto/dh/dh_asn1.c b/crypto/dh/dh_asn1.c index f485029..10184f0 100644 --- a/crypto/dh/dh_asn1.c +++ b/crypto/dh/dh_asn1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dh_asn1.c,v 1.10 2016/12/30 15:26:49 jsing Exp $ */ +/* $OpenBSD: dh_asn1.c,v 1.11 2022/01/07 09:27:13 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ @@ -63,6 +63,8 @@ #include #include +#include "dh_local.h" + /* Override the default free and new methods */ static int dh_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg) diff --git a/crypto/dh/dh_check.c b/crypto/dh/dh_check.c index a8227d3..1d20952 100644 --- a/crypto/dh/dh_check.c +++ b/crypto/dh/dh_check.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dh_check.c,v 1.17 2019/01/20 01:56:59 tb Exp $ */ +/* $OpenBSD: dh_check.c,v 1.24 2022/01/10 12:00:52 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -60,87 +60,244 @@ #include #include +#include + +#include "bn_lcl.h" +#include "dh_local.h" + +#define DH_NUMBER_ITERATIONS_FOR_PRIME 64 /* - * Check that p is a safe prime and - * if g is 2, 3 or 5, check that it is a suitable generator - * where - * for 2, p mod 24 == 11 - * for 3, p mod 12 == 5 - * for 5, p mod 10 == 3 or 7 - * should hold. + * Check that p is odd and 1 < g < p - 1. The _ex version removes the need of + * inspecting flags and pushes errors on the stack instead. */ int -DH_check(const DH *dh, int *ret) +DH_check_params_ex(const DH *dh) { - int is_prime, ok = 0; - BN_CTX *ctx = NULL; - BN_ULONG l; - BIGNUM *q = NULL; + int flags = 0; - *ret = 0; - ctx = BN_CTX_new(); - if (ctx == NULL) - goto err; - q = BN_new(); - if (q == NULL) - goto err; + if (!DH_check_params(dh, &flags)) + return 0; - if (BN_is_word(dh->g, DH_GENERATOR_2)) { - l = BN_mod_word(dh->p, 24); - if (l == (BN_ULONG)-1) - goto err; - if (l != 11) - *ret |= DH_NOT_SUITABLE_GENERATOR; - } else if (BN_is_word(dh->g, DH_GENERATOR_5)) { - l = BN_mod_word(dh->p, 10); - if (l == (BN_ULONG)-1) - goto err; - if (l != 3 && l != 7) - *ret |= DH_NOT_SUITABLE_GENERATOR; - } else - *ret |= DH_UNABLE_TO_CHECK_GENERATOR; + if ((flags & DH_CHECK_P_NOT_PRIME) != 0) + DHerror(DH_R_CHECK_P_NOT_PRIME); + if ((flags & DH_NOT_SUITABLE_GENERATOR) != 0) + DHerror(DH_R_NOT_SUITABLE_GENERATOR); - is_prime = BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL); - if (is_prime < 0) + return flags == 0; +} + +int +DH_check_params(const DH *dh, int *flags) +{ + BIGNUM *max_g = NULL; + int ok = 0; + + *flags = 0; + + if (!BN_is_odd(dh->p)) + *flags |= DH_CHECK_P_NOT_PRIME; + + /* + * Check that 1 < dh->g < p - 1 + */ + + if (BN_cmp(dh->g, BN_value_one()) <= 0) + *flags |= DH_NOT_SUITABLE_GENERATOR; + /* max_g = p - 1 */ + if ((max_g = BN_dup(dh->p)) == NULL) goto err; - if (is_prime == 0) - *ret |= DH_CHECK_P_NOT_PRIME; - else { - if (!BN_rshift1(q, dh->p)) - goto err; - is_prime = BN_is_prime_ex(q, BN_prime_checks, ctx, NULL); - if (is_prime < 0) - goto err; - if (is_prime == 0) - *ret |= DH_CHECK_P_NOT_SAFE_PRIME; - } + if (!BN_sub_word(max_g, 1)) + goto err; + /* check that g < max_g */ + if (BN_cmp(dh->g, max_g) >= 0) + *flags |= DH_NOT_SUITABLE_GENERATOR; + ok = 1; err: + BN_free(max_g); + + return ok; +} + +/* + * Check that p is a safe prime and that g is a suitable generator. + * The _ex version puts errors on the stack instead of returning flags. + */ + +int +DH_check_ex(const DH *dh) +{ + int flags = 0; + + if (!DH_check(dh, &flags)) + return 0; + + if ((flags & DH_NOT_SUITABLE_GENERATOR) != 0) + DHerror(DH_R_NOT_SUITABLE_GENERATOR); + if ((flags & DH_CHECK_Q_NOT_PRIME) != 0) + DHerror(DH_R_CHECK_Q_NOT_PRIME); + if ((flags & DH_CHECK_INVALID_Q_VALUE) != 0) + DHerror(DH_R_CHECK_INVALID_Q_VALUE); + if ((flags & DH_CHECK_INVALID_J_VALUE) != 0) + DHerror(DH_R_CHECK_INVALID_J_VALUE); + if ((flags & DH_UNABLE_TO_CHECK_GENERATOR) != 0) + DHerror(DH_R_UNABLE_TO_CHECK_GENERATOR); + if ((flags & DH_CHECK_P_NOT_PRIME) != 0) + DHerror(DH_R_CHECK_P_NOT_PRIME); + if ((flags & DH_CHECK_P_NOT_SAFE_PRIME) != 0) + DHerror(DH_R_CHECK_P_NOT_SAFE_PRIME); + + return flags == 0; +} + +int +DH_check(const DH *dh, int *flags) +{ + BN_CTX *ctx = NULL; + int is_prime; + int ok = 0; + + *flags = 0; + + if (!DH_check_params(dh, flags)) + goto err; + + ctx = BN_CTX_new(); + if (ctx == NULL) + goto err; + BN_CTX_start(ctx); + + if (dh->q != NULL) { + BIGNUM *quotient, *residue; + + if ((quotient = BN_CTX_get(ctx)) == NULL) + goto err; + if ((residue = BN_CTX_get(ctx)) == NULL) + goto err; + if ((*flags & DH_NOT_SUITABLE_GENERATOR) == 0) { + /* Check g^q == 1 mod p */ + if (!BN_mod_exp_ct(residue, dh->g, dh->q, dh->p, ctx)) + goto err; + if (!BN_is_one(residue)) + *flags |= DH_NOT_SUITABLE_GENERATOR; + } + is_prime = BN_is_prime_ex(dh->q, DH_NUMBER_ITERATIONS_FOR_PRIME, + ctx, NULL); + if (is_prime < 0) + goto err; + if (is_prime == 0) + *flags |= DH_CHECK_Q_NOT_PRIME; + /* Check p == 1 mod q, i.e., q divides p - 1 */ + if (!BN_div_ct(quotient, residue, dh->p, dh->q, ctx)) + goto err; + if (!BN_is_one(residue)) + *flags |= DH_CHECK_INVALID_Q_VALUE; + if (dh->j != NULL && BN_cmp(dh->j, quotient) != 0) + *flags |= DH_CHECK_INVALID_J_VALUE; + } + + is_prime = BN_is_prime_ex(dh->p, DH_NUMBER_ITERATIONS_FOR_PRIME, + ctx, NULL); + if (is_prime < 0) + goto err; + if (is_prime == 0) + *flags |= DH_CHECK_P_NOT_PRIME; + else if (dh->q == NULL) { + BIGNUM *q; + + if ((q = BN_CTX_get(ctx)) == NULL) + goto err; + if (!BN_rshift1(q, dh->p)) + goto err; + is_prime = BN_is_prime_ex(q, DH_NUMBER_ITERATIONS_FOR_PRIME, + ctx, NULL); + if (is_prime < 0) + goto err; + if (is_prime == 0) + *flags |= DH_CHECK_P_NOT_SAFE_PRIME; + } + + ok = 1; + + err: + BN_CTX_end(ctx); BN_CTX_free(ctx); - BN_free(q); return ok; } int -DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) +DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key) { - BIGNUM *q = NULL; + int flags = 0; - *ret = 0; - q = BN_new(); - if (q == NULL) + if (!DH_check_pub_key(dh, pub_key, &flags)) return 0; - BN_set_word(q, 1); - if (BN_cmp(pub_key, q) <= 0) - *ret |= DH_CHECK_PUBKEY_TOO_SMALL; - BN_copy(q, dh->p); - BN_sub_word(q, 1); - if (BN_cmp(pub_key, q) >= 0) - *ret |= DH_CHECK_PUBKEY_TOO_LARGE; - BN_free(q); - return 1; + if ((flags & DH_CHECK_PUBKEY_TOO_SMALL) != 0) + DHerror(DH_R_CHECK_PUBKEY_TOO_SMALL); + if ((flags & DH_CHECK_PUBKEY_TOO_LARGE) != 0) + DHerror(DH_R_CHECK_PUBKEY_TOO_LARGE); + if ((flags & DH_CHECK_PUBKEY_INVALID) != 0) + DHerror(DH_R_CHECK_PUBKEY_INVALID); + + return flags == 0; +} + +int +DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *flags) +{ + BN_CTX *ctx = NULL; + BIGNUM *max_pub_key; + int ok = 0; + + *flags = 0; + + if ((ctx = BN_CTX_new()) == NULL) + goto err; + BN_CTX_start(ctx); + if ((max_pub_key = BN_CTX_get(ctx)) == NULL) + goto err; + + /* + * Check that 1 < pub_key < dh->p - 1 + */ + + if (BN_cmp(pub_key, BN_value_one()) <= 0) + *flags |= DH_CHECK_PUBKEY_TOO_SMALL; + + /* max_pub_key = dh->p - 1 */ + if (BN_copy(max_pub_key, dh->p) == NULL) + goto err; + if (!BN_sub_word(max_pub_key, 1)) + goto err; + + if (BN_cmp(pub_key, max_pub_key) >= 0) + *flags |= DH_CHECK_PUBKEY_TOO_LARGE; + + /* + * If dh->q is set, check that pub_key^q == 1 mod p + */ + + if (dh->q != NULL) { + BIGNUM *residue; + + if ((residue = BN_CTX_get(ctx)) == NULL) + goto err; + + if (!BN_mod_exp_ct(residue, pub_key, dh->q, dh->p, ctx)) + goto err; + if (!BN_is_one(residue)) + *flags = DH_CHECK_PUBKEY_INVALID; + } + + ok = 1; + + err: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + + return ok; } diff --git a/crypto/dh/dh_depr.c b/crypto/dh/dh_depr.c index 0b75b0b..717482c 100644 --- a/crypto/dh/dh_depr.c +++ b/crypto/dh/dh_depr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dh_depr.c,v 1.6 2014/07/11 08:44:48 jsing Exp $ */ +/* $OpenBSD: dh_depr.c,v 1.7 2021/12/04 16:08:32 tb Exp $ */ /* ==================================================================== * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. * @@ -62,6 +62,8 @@ #include #include +#include "bn_lcl.h" + #ifndef OPENSSL_NO_DEPRECATED DH * DH_generate_parameters(int prime_len, int generator, diff --git a/crypto/dh/dh_err.c b/crypto/dh/dh_err.c index 497f884..a387c37 100644 --- a/crypto/dh/dh_err.c +++ b/crypto/dh/dh_err.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dh_err.c,v 1.16 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: dh_err.c,v 1.17 2022/01/10 12:00:52 tb Exp $ */ /* ==================================================================== * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved. * @@ -90,6 +90,17 @@ static ERR_STRING_DATA DH_str_reasons[]= {ERR_REASON(DH_R_NO_PARAMETERS_SET) ,"no parameters set"}, {ERR_REASON(DH_R_NO_PRIVATE_VALUE) ,"no private value"}, {ERR_REASON(DH_R_PARAMETER_ENCODING_ERROR),"parameter encoding error"}, +{ERR_REASON(DH_R_CHECK_INVALID_J_VALUE) ,"check invalid j value"}, +{ERR_REASON(DH_R_CHECK_INVALID_Q_VALUE) ,"check invalid q value"}, +{ERR_REASON(DH_R_CHECK_PUBKEY_INVALID) ,"check pubkey invalid"}, +{ERR_REASON(DH_R_CHECK_PUBKEY_TOO_LARGE) ,"check pubkey too large"}, +{ERR_REASON(DH_R_CHECK_PUBKEY_TOO_SMALL) ,"check pubkey too small"}, +{ERR_REASON(DH_R_CHECK_P_NOT_PRIME) ,"check p not prime"}, +{ERR_REASON(DH_R_CHECK_P_NOT_SAFE_PRIME) ,"check p not safe prime"}, +{ERR_REASON(DH_R_CHECK_Q_NOT_PRIME) ,"check q not prime"}, +{ERR_REASON(DH_R_MISSING_PUBKEY) ,"missing pubkey"}, +{ERR_REASON(DH_R_NOT_SUITABLE_GENERATOR) ,"not suitable generator"}, +{ERR_REASON(DH_R_UNABLE_TO_CHECK_GENERATOR),"unable to check generator"}, {0,NULL} }; diff --git a/crypto/dh/dh_gen.c b/crypto/dh/dh_gen.c index 9939411..6b49a28 100644 --- a/crypto/dh/dh_gen.c +++ b/crypto/dh/dh_gen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dh_gen.c,v 1.16 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: dh_gen.c,v 1.17 2022/01/07 09:27:13 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -67,6 +67,8 @@ #include #include +#include "dh_local.h" + static int dh_builtin_genparams(DH *ret, int prime_len, int generator, BN_GENCB *cb); diff --git a/crypto/dh/dh_key.c b/crypto/dh/dh_key.c index a77e795..9242931 100644 --- a/crypto/dh/dh_key.c +++ b/crypto/dh/dh_key.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dh_key.c,v 1.36 2018/11/12 17:39:17 tb Exp $ */ +/* $OpenBSD: dh_key.c,v 1.37 2022/01/07 09:27:13 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -63,6 +63,7 @@ #include #include "bn_lcl.h" +#include "dh_local.h" static int generate_key(DH *dh); static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh); diff --git a/crypto/dh/dh_lib.c b/crypto/dh/dh_lib.c index 446bc65..d4d0c9d 100644 --- a/crypto/dh/dh_lib.c +++ b/crypto/dh/dh_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dh_lib.c,v 1.32 2018/05/02 15:48:38 tb Exp $ */ +/* $OpenBSD: dh_lib.c,v 1.36 2022/01/07 09:27:13 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -69,6 +69,8 @@ #include #endif +#include "dh_local.h" + static const DH_METHOD *default_DH_method = NULL; void @@ -273,6 +275,7 @@ DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) if (q != NULL) { BN_free(dh->q); dh->q = q; + dh->length = BN_num_bits(dh->q); } if (g != NULL) { BN_free(dh->g); @@ -306,6 +309,36 @@ DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) return 1; } +const BIGNUM * +DH_get0_p(const DH *dh) +{ + return dh->p; +} + +const BIGNUM * +DH_get0_q(const DH *dh) +{ + return dh->q; +} + +const BIGNUM * +DH_get0_g(const DH *dh) +{ + return dh->g; +} + +const BIGNUM * +DH_get0_priv_key(const DH *dh) +{ + return dh->priv_key; +} + +const BIGNUM * +DH_get0_pub_key(const DH *dh) +{ + return dh->pub_key; +} + void DH_clear_flags(DH *dh, int flags) { @@ -324,6 +357,12 @@ DH_set_flags(DH *dh, int flags) dh->flags |= flags; } +long +DH_get_length(const DH *dh) +{ + return dh->length; +} + int DH_set_length(DH *dh, long length) { diff --git a/crypto/asn1/a_dup.c b/crypto/dh/dh_local.h similarity index 68% rename from crypto/asn1/a_dup.c rename to crypto/dh/dh_local.h index 2e17a1e..928f2c0 100644 --- a/crypto/asn1/a_dup.c +++ b/crypto/dh/dh_local.h @@ -1,4 +1,4 @@ -/* $OpenBSD: a_dup.c,v 1.14 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: dh_local.h,v 1.3 2022/01/14 08:25:44 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -56,63 +56,62 @@ * [including the GNU Public Licence.] */ -#include +#ifndef HEADER_DH_LOCAL_H +#define HEADER_DH_LOCAL_H -#include -#include +__BEGIN_HIDDEN_DECLS -#ifndef NO_OLD_ASN1 +struct dh_method { + const char *name; + /* Methods here */ + int (*generate_key)(DH *dh); + int (*compute_key)(unsigned char *key,const BIGNUM *pub_key,DH *dh); + int (*bn_mod_exp)(const DH *dh, BIGNUM *r, const BIGNUM *a, + const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); + int (*init)(DH *dh); + int (*finish)(DH *dh); + int flags; + char *app_data; + /* If this is non-NULL, it will be used to generate parameters */ + int (*generate_params)(DH *dh, int prime_len, int generator, + BN_GENCB *cb); +}; -void * -ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x) -{ - unsigned char *b, *p; - const unsigned char *p2; - int i; - char *ret; +struct dh_st { + /* This first argument is used to pick up errors when + * a DH is passed instead of a EVP_PKEY */ + int pad; + int version; + BIGNUM *p; + BIGNUM *g; + long length; /* optional */ + BIGNUM *pub_key; /* g^x */ + BIGNUM *priv_key; /* x */ - if (x == NULL) - return (NULL); + int flags; + BN_MONT_CTX *method_mont_p; + /* Place holders if we want to do X9.42 DH */ + BIGNUM *q; + BIGNUM *j; + unsigned char *seed; + int seedlen; + BIGNUM *counter; - i = i2d(x, NULL); - b = malloc(i + 10); - if (b == NULL) { - ASN1error(ERR_R_MALLOC_FAILURE); - return (NULL); - } - p = b; - i = i2d(x, &p); - p2 = b; - ret = d2i(NULL, &p2, i); - free(b); - return (ret); -} + int references; + CRYPTO_EX_DATA ex_data; + const DH_METHOD *meth; + ENGINE *engine; +}; -#endif - -/* ASN1_ITEM version of dup: this follows the model above except we don't need - * to allocate the buffer. At some point this could be rewritten to directly dup - * the underlying structure instead of doing and encode and decode. +/* + * Public API in OpenSSL that we only want to use internally. */ -void * -ASN1_item_dup(const ASN1_ITEM *it, void *x) -{ - unsigned char *b = NULL; - const unsigned char *p; - long i; - void *ret; +int DH_check_params_ex(const DH *dh); +int DH_check_params(const DH *dh, int *flags); +int DH_check_ex(const DH *dh); +int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key); - if (x == NULL) - return (NULL); +__END_HIDDEN_DECLS - i = ASN1_item_i2d(x, &b, it); - if (b == NULL) { - ASN1error(ERR_R_MALLOC_FAILURE); - return (NULL); - } - p = b; - ret = ASN1_item_d2i(NULL, &p, i, it); - free(b); - return (ret); -} +#endif /* !HEADER_DH_LOCAL_H */ diff --git a/crypto/dh/dh_pmeth.c b/crypto/dh/dh_pmeth.c index 24d16ff..d2052a8 100644 --- a/crypto/dh/dh_pmeth.c +++ b/crypto/dh/dh_pmeth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dh_pmeth.c,v 1.10 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: dh_pmeth.c,v 1.12 2022/01/07 09:27:13 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2006. */ @@ -67,6 +67,8 @@ #include #include +#include "bn_lcl.h" +#include "dh_local.h" #include "evp_locl.h" /* DH pkey context structure */ diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c index cfb3323..9b8f09d 100644 --- a/crypto/dsa/dsa_ameth.c +++ b/crypto/dsa/dsa_ameth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dsa_ameth.c,v 1.28 2019/11/01 15:15:35 jsing Exp $ */ +/* $OpenBSD: dsa_ameth.c,v 1.35 2022/04/07 17:38:24 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2006. */ @@ -69,6 +69,8 @@ #include "asn1_locl.h" #include "bn_lcl.h" +#include "dsa_locl.h" +#include "evp_locl.h" static int dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) @@ -131,47 +133,46 @@ static int dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) { DSA *dsa; - void *pval = NULL; - int ptype; + ASN1_INTEGER *pubint = NULL; + ASN1_STRING *str = NULL; + int ptype = V_ASN1_UNDEF; unsigned char *penc = NULL; int penclen; dsa = pkey->pkey.dsa; if (pkey->save_parameters && dsa->p && dsa->q && dsa->g) { - ASN1_STRING *str; - - str = ASN1_STRING_new(); - if (str == NULL) { + if ((str = ASN1_STRING_new()) == NULL) { DSAerror(ERR_R_MALLOC_FAILURE); goto err; } str->length = i2d_DSAparams(dsa, &str->data); if (str->length <= 0) { DSAerror(ERR_R_MALLOC_FAILURE); - ASN1_STRING_free(str); goto err; } - pval = str; ptype = V_ASN1_SEQUENCE; - } else - ptype = V_ASN1_UNDEF; + } - dsa->write_params = 0; + if ((pubint = BN_to_ASN1_INTEGER(dsa->pub_key, NULL)) == NULL) { + DSAerror(ERR_R_MALLOC_FAILURE); + goto err; + } - penclen = i2d_DSAPublicKey(dsa, &penc); + penclen = i2d_ASN1_INTEGER(pubint, &penc); + ASN1_INTEGER_free(pubint); if (penclen <= 0) { DSAerror(ERR_R_MALLOC_FAILURE); goto err; } - if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_DSA), ptype, pval, + if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_DSA), ptype, str, penc, penclen)) return 1; -err: + err: free(penc); - ASN1_STRING_free(pval); + ASN1_STRING_free(str); return 0; } @@ -478,13 +479,32 @@ old_dsa_priv_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) { DSA *dsa; BN_CTX *ctx = NULL; - BIGNUM *j, *p1, *newp1; + BIGNUM *j, *p1, *newp1, *powg; + int qbits; if (!(dsa = d2i_DSAPrivateKey(NULL, pder, derlen))) { DSAerror(ERR_R_DSA_LIB); return 0; } + /* FIPS 186-3 allows only three different sizes for q. */ + qbits = BN_num_bits(dsa->q); + if (qbits != 160 && qbits != 224 && qbits != 256) { + DSAerror(DSA_R_BAD_Q_VALUE); + goto err; + } + if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS) { + DSAerror(DSA_R_MODULUS_TOO_LARGE); + goto err; + } + + /* Check that 1 < g < p. */ + if (BN_cmp(dsa->g, BN_value_one()) <= 0 || + BN_cmp(dsa->g, dsa->p) >= 0) { + DSAerror(DSA_R_PARAMETER_ENCODING_ERROR); /* XXX */ + goto err; + } + ctx = BN_CTX_new(); if (ctx == NULL) goto err; @@ -496,7 +516,8 @@ old_dsa_priv_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) j = BN_CTX_get(ctx); p1 = BN_CTX_get(ctx); newp1 = BN_CTX_get(ctx); - if (j == NULL || p1 == NULL || newp1 == NULL) + powg = BN_CTX_get(ctx); + if (j == NULL || p1 == NULL || newp1 == NULL || powg == NULL) goto err; /* p1 = p - 1 */ if (BN_sub(p1, dsa->p, BN_value_one()) == 0) @@ -512,6 +533,19 @@ old_dsa_priv_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) goto err; } + /* + * Check that g generates a multiplicative subgroup of order q. + * We only check that g^q == 1, so the order is a divisor of q. + * Once we know that q is prime, this is enough. + */ + + if (!BN_mod_exp_ct(powg, dsa->g, dsa->q, dsa->p, ctx)) + goto err; + if (BN_cmp(powg, BN_value_one()) != 0) { + DSAerror(DSA_R_PARAMETER_ENCODING_ERROR); /* XXX */ + goto err; + } + /* * Check that q is not a composite number. */ diff --git a/crypto/dsa/dsa_asn1.c b/crypto/dsa/dsa_asn1.c index 23f08bb..daa970e 100644 --- a/crypto/dsa/dsa_asn1.c +++ b/crypto/dsa/dsa_asn1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dsa_asn1.c,v 1.22 2018/06/14 17:03:19 jsing Exp $ */ +/* $OpenBSD: dsa_asn1.c,v 1.24 2022/01/14 08:29:06 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ @@ -64,6 +64,8 @@ #include #include +#include "dsa_locl.h" + /* Override the default new methods */ static int sig_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg) @@ -327,14 +329,15 @@ i2d_DSAparams_fp(FILE *fp, DSA *a) return ASN1_item_i2d_fp(&DSAparams_it, fp, a); } -/* - * DSA public key is a bit trickier... its effectively a CHOICE type - * decided by a field called write_params which can either write out - * just the public key as an INTEGER or the parameters and public key - * in a SEQUENCE - */ - -static const ASN1_TEMPLATE dsa_pub_internal_seq_tt[] = { +static const ASN1_AUX DSAPublicKey_aux = { + .app_data = NULL, + .flags = 0, + .ref_offset = 0, + .ref_lock = 0, + .asn1_cb = dsa_cb, + .enc_offset = 0, +}; +static const ASN1_TEMPLATE DSAPublicKey_seq_tt[] = { { .flags = 0, .tag = 0, @@ -365,52 +368,16 @@ static const ASN1_TEMPLATE dsa_pub_internal_seq_tt[] = { }, }; -const ASN1_ITEM dsa_pub_internal_it = { +const ASN1_ITEM DSAPublicKey_it = { .itype = ASN1_ITYPE_SEQUENCE, .utype = V_ASN1_SEQUENCE, - .templates = dsa_pub_internal_seq_tt, - .tcount = sizeof(dsa_pub_internal_seq_tt) / sizeof(ASN1_TEMPLATE), - .funcs = NULL, - .size = sizeof(DSA), - .sname = "DSA", -}; - -static const ASN1_AUX DSAPublicKey_aux = { - .app_data = NULL, - .flags = 0, - .ref_offset = 0, - .ref_lock = 0, - .asn1_cb = dsa_cb, - .enc_offset = 0, -}; -static const ASN1_TEMPLATE DSAPublicKey_ch_tt[] = { - { - .flags = 0, - .tag = 0, - .offset = offsetof(DSA, pub_key), - .field_name = "pub_key", - .item = &BIGNUM_it, - }, - { - .flags = 0 | ASN1_TFLG_COMBINE, - .tag = 0, - .offset = 0, - .field_name = NULL, - .item = &dsa_pub_internal_it, - }, -}; - -const ASN1_ITEM DSAPublicKey_it = { - .itype = ASN1_ITYPE_CHOICE, - .utype = offsetof(DSA, write_params), - .templates = DSAPublicKey_ch_tt, - .tcount = sizeof(DSAPublicKey_ch_tt) / sizeof(ASN1_TEMPLATE), + .templates = DSAPublicKey_seq_tt, + .tcount = sizeof(DSAPublicKey_seq_tt) / sizeof(ASN1_TEMPLATE), .funcs = &DSAPublicKey_aux, .size = sizeof(DSA), .sname = "DSA", }; - DSA * d2i_DSAPublicKey(DSA **a, const unsigned char **in, long len) { diff --git a/crypto/dsa/dsa_depr.c b/crypto/dsa/dsa_depr.c index 269cd63..673e700 100644 --- a/crypto/dsa/dsa_depr.c +++ b/crypto/dsa/dsa_depr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dsa_depr.c,v 1.7 2014/10/18 17:20:40 jsing Exp $ */ +/* $OpenBSD: dsa_depr.c,v 1.8 2021/12/04 16:08:32 tb Exp $ */ /* ==================================================================== * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. * @@ -68,6 +68,8 @@ #include #include +#include "bn_lcl.h" + #ifndef OPENSSL_NO_DEPRECATED DSA * DSA_generate_parameters(int bits, unsigned char *seed_in, int seed_len, diff --git a/crypto/dsa/dsa_key.c b/crypto/dsa/dsa_key.c index a0487e9..a5053ec 100644 --- a/crypto/dsa/dsa_key.c +++ b/crypto/dsa/dsa_key.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dsa_key.c,v 1.29 2018/11/09 23:45:19 tb Exp $ */ +/* $OpenBSD: dsa_key.c,v 1.30 2022/01/07 09:35:36 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -65,7 +65,9 @@ #include #include + #include "bn_lcl.h" +#include "dsa_locl.h" static int dsa_builtin_keygen(DSA *dsa); diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c index d5fdd6e..1369c6f 100644 --- a/crypto/dsa/dsa_lib.c +++ b/crypto/dsa/dsa_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dsa_lib.c,v 1.29 2018/04/14 07:09:21 tb Exp $ */ +/* $OpenBSD: dsa_lib.c,v 1.34 2022/01/14 08:29:06 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -74,6 +74,9 @@ #include #endif +#include "dh_local.h" +#include "dsa_locl.h" + static const DSA_METHOD *default_DSA_method = NULL; void @@ -151,7 +154,6 @@ DSA_new_method(ENGINE *engine) ret->pad = 0; ret->version = 0; - ret->write_params = 1; ret->p = NULL; ret->q = NULL; ret->g = NULL; @@ -174,7 +176,7 @@ DSA_new_method(ENGINE *engine) free(ret); ret = NULL; } - + return ret; } @@ -361,6 +363,36 @@ DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) return 1; } +const BIGNUM * +DSA_get0_p(const DSA *d) +{ + return d->p; +} + +const BIGNUM * +DSA_get0_q(const DSA *d) +{ + return d->q; +} + +const BIGNUM * +DSA_get0_g(const DSA *d) +{ + return d->g; +} + +const BIGNUM * +DSA_get0_pub_key(const DSA *d) +{ + return d->pub_key; +} + +const BIGNUM * +DSA_get0_priv_key(const DSA *d) +{ + return d->priv_key; +} + void DSA_clear_flags(DSA *d, int flags) { @@ -384,3 +416,9 @@ DSA_get0_engine(DSA *d) { return d->engine; } + +int +DSA_bits(const DSA *dsa) +{ + return BN_num_bits(dsa->p); +} diff --git a/crypto/dsa/dsa_locl.h b/crypto/dsa/dsa_locl.h index cdb38e0..299c67a 100644 --- a/crypto/dsa/dsa_locl.h +++ b/crypto/dsa/dsa_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dsa_locl.h,v 1.3 2016/12/21 15:49:29 jsing Exp $ */ +/* $OpenBSD: dsa_locl.h,v 1.5 2022/01/14 08:29:06 tb Exp $ */ /* ==================================================================== * Copyright (c) 2007 The OpenSSL Project. All rights reserved. * @@ -57,6 +57,59 @@ __BEGIN_HIDDEN_DECLS +struct DSA_SIG_st { + BIGNUM *r; + BIGNUM *s; +} /* DSA_SIG */; + +struct dsa_method { + const char *name; + DSA_SIG *(*dsa_do_sign)(const unsigned char *dgst, int dlen, DSA *dsa); + int (*dsa_sign_setup)(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, + BIGNUM **rp); + int (*dsa_do_verify)(const unsigned char *dgst, int dgst_len, + DSA_SIG *sig, DSA *dsa); + int (*dsa_mod_exp)(DSA *dsa, BIGNUM *rr, BIGNUM *a1, BIGNUM *p1, + BIGNUM *a2, BIGNUM *p2, BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *in_mont); + int (*bn_mod_exp)(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); /* Can be null */ + int (*init)(DSA *dsa); + int (*finish)(DSA *dsa); + int flags; + char *app_data; + /* If this is non-NULL, it is used to generate DSA parameters */ + int (*dsa_paramgen)(DSA *dsa, int bits, const unsigned char *seed, + int seed_len, int *counter_ret, unsigned long *h_ret, BN_GENCB *cb); + /* If this is non-NULL, it is used to generate DSA keys */ + int (*dsa_keygen)(DSA *dsa); +} /* DSA_METHOD */; + +struct dsa_st { + /* This first variable is used to pick up errors where + * a DSA is passed instead of of a EVP_PKEY */ + int pad; + long version; + BIGNUM *p; + BIGNUM *q; /* == 20 */ + BIGNUM *g; + + BIGNUM *pub_key; /* y public key */ + BIGNUM *priv_key; /* x private key */ + + BIGNUM *kinv; /* Signing pre-calc */ + BIGNUM *r; /* Signing pre-calc */ + + int flags; + /* Normally used to cache montgomery values */ + BN_MONT_CTX *method_mont_p; + int references; + CRYPTO_EX_DATA ex_data; + const DSA_METHOD *meth; + /* functional reference if 'meth' is ENGINE-provided */ + ENGINE *engine; +} /* DSA */; + int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits, const EVP_MD *evpmd, const unsigned char *seed_in, size_t seed_len, unsigned char *seed_out, diff --git a/crypto/dsa/dsa_meth.c b/crypto/dsa/dsa_meth.c index e6f043f..f8ed035 100644 --- a/crypto/dsa/dsa_meth.c +++ b/crypto/dsa/dsa_meth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dsa_meth.c,v 1.1 2018/03/17 15:19:12 tb Exp $ */ +/* $OpenBSD: dsa_meth.c,v 1.2 2022/01/07 09:35:36 tb Exp $ */ /* * Copyright (c) 2018 Theo Buehler * @@ -21,6 +21,8 @@ #include #include +#include "dsa_locl.h" + DSA_METHOD * DSA_meth_new(const char *name, int flags) { diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c index ecf2662..c306fc2 100644 --- a/crypto/dsa/dsa_ossl.c +++ b/crypto/dsa/dsa_ossl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dsa_ossl.c,v 1.42 2019/06/04 18:12:26 tb Exp $ */ +/* $OpenBSD: dsa_ossl.c,v 1.44 2022/02/24 08:35:45 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -67,6 +67,7 @@ #include #include "bn_lcl.h" +#include "dsa_locl.h" static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa); static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, @@ -314,24 +315,25 @@ dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa) BN_CTX *ctx; BIGNUM u1, u2, t1; BN_MONT_CTX *mont = NULL; - int ret = -1, i; + int qbits; + int ret = -1; if (!dsa->p || !dsa->q || !dsa->g) { DSAerror(DSA_R_MISSING_PARAMETERS); return -1; } - i = BN_num_bits(dsa->q); /* FIPS 186-3 allows only three different sizes for q. */ - if (i != 160 && i != 224 && i != 256) { + qbits = BN_num_bits(dsa->q); + if (qbits != 160 && qbits != 224 && qbits != 256) { DSAerror(DSA_R_BAD_Q_VALUE); return -1; } - if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS) { DSAerror(DSA_R_MODULUS_TOO_LARGE); return -1; } + BN_init(&u1); BN_init(&u2); BN_init(&t1); @@ -358,8 +360,8 @@ dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa) * If the digest length is greater than the size of q use the * BN_num_bits(dsa->q) leftmost bits of the digest, see FIPS 186-3, 4.2. */ - if (dgst_len > (i >> 3)) - dgst_len = (i >> 3); + if (dgst_len > (qbits >> 3)) + dgst_len = (qbits >> 3); /* Save m in u1. */ if (BN_bin2bn(dgst, dgst_len, &u1) == NULL) diff --git a/crypto/dsa/dsa_pmeth.c b/crypto/dsa/dsa_pmeth.c index dd0da34..ef89e2b 100644 --- a/crypto/dsa/dsa_pmeth.c +++ b/crypto/dsa/dsa_pmeth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dsa_pmeth.c,v 1.12 2019/09/09 18:06:25 jsing Exp $ */ +/* $OpenBSD: dsa_pmeth.c,v 1.13 2021/12/04 16:08:32 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2006. */ @@ -66,6 +66,7 @@ #include #include +#include "bn_lcl.h" #include "dsa_locl.h" #include "evp_locl.h" diff --git a/crypto/dsa/dsa_sign.c b/crypto/dsa/dsa_sign.c index 0f55ea1..b1fc1db 100644 --- a/crypto/dsa/dsa_sign.c +++ b/crypto/dsa/dsa_sign.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dsa_sign.c,v 1.20 2018/06/14 17:01:49 jsing Exp $ */ +/* $OpenBSD: dsa_sign.c,v 1.21 2022/01/07 09:35:36 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -61,6 +61,8 @@ #include #include +#include "dsa_locl.h" + DSA_SIG * DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) { diff --git a/crypto/dsa/dsa_vrf.c b/crypto/dsa/dsa_vrf.c index 1965338..38f8450 100644 --- a/crypto/dsa/dsa_vrf.c +++ b/crypto/dsa/dsa_vrf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dsa_vrf.c,v 1.16 2014/07/11 08:44:48 jsing Exp $ */ +/* $OpenBSD: dsa_vrf.c,v 1.17 2022/01/07 09:35:36 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -60,6 +60,8 @@ #include +#include "dsa_locl.h" + int DSA_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa) { diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c index 2e73bdd..86f509b 100644 --- a/crypto/ec/ec_ameth.c +++ b/crypto/ec/ec_ameth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ec_ameth.c,v 1.28 2019/09/09 20:26:16 tb Exp $ */ +/* $OpenBSD: ec_ameth.c,v 1.31 2022/01/10 12:10:26 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2006. */ @@ -67,6 +67,8 @@ #include #include "asn1_locl.h" +#include "ec_lcl.h" +#include "evp_locl.h" #ifndef OPENSSL_NO_CMS static int ecdh_cms_decrypt(CMS_RecipientInfo *ri); @@ -619,6 +621,41 @@ ec_pkey_ctrl(EVP_PKEY * pkey, int op, long arg1, void *arg2) } +static int +ec_pkey_check(const EVP_PKEY *pkey) +{ + EC_KEY *eckey = pkey->pkey.ec; + + if (eckey->priv_key == NULL) { + ECerror(EC_R_MISSING_PRIVATE_KEY); + return 0; + } + + return EC_KEY_check_key(eckey); +} + +static int +ec_pkey_public_check(const EVP_PKEY *pkey) +{ + EC_KEY *eckey = pkey->pkey.ec; + + /* This also checks the private key, but oh, well... */ + return EC_KEY_check_key(eckey); +} + +static int +ec_pkey_param_check(const EVP_PKEY *pkey) +{ + EC_KEY *eckey = pkey->pkey.ec; + + if (eckey->group == NULL) { + ECerror(EC_R_MISSING_PARAMETERS); + return 0; + } + + return EC_GROUP_check(eckey->group, NULL); +} + #ifndef OPENSSL_NO_CMS static int @@ -980,5 +1017,9 @@ const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = { .pkey_free = int_ec_free, .pkey_ctrl = ec_pkey_ctrl, .old_priv_decode = old_ec_priv_decode, - .old_priv_encode = old_ec_priv_encode + .old_priv_encode = old_ec_priv_encode, + + .pkey_check = ec_pkey_check, + .pkey_public_check = ec_pkey_public_check, + .pkey_param_check = ec_pkey_param_check, }; diff --git a/crypto/ec/ec_asn1.c b/crypto/ec/ec_asn1.c index befeee9..4cf0bf5 100644 --- a/crypto/ec/ec_asn1.c +++ b/crypto/ec/ec_asn1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ec_asn1.c,v 1.34 2021/08/31 20:14:40 tb Exp $ */ +/* $OpenBSD: ec_asn1.c,v 1.36 2022/03/31 13:00:58 tb Exp $ */ /* * Written by Nils Larsch for the OpenSSL project. */ @@ -295,7 +295,6 @@ static const ASN1_ADB_TABLE X9_62_CHARACTERISTIC_TWO_adbtbl[] = { static const ASN1_ADB X9_62_CHARACTERISTIC_TWO_adb = { .flags = 0, .offset = offsetof(X9_62_CHARACTERISTIC_TWO, type), - .app_items = 0, .tbl = X9_62_CHARACTERISTIC_TWO_adbtbl, .tblcount = sizeof(X9_62_CHARACTERISTIC_TWO_adbtbl) / sizeof(ASN1_ADB_TABLE), .default_tt = &char_two_def_tt, @@ -387,7 +386,6 @@ static const ASN1_ADB_TABLE X9_62_FIELDID_adbtbl[] = { static const ASN1_ADB X9_62_FIELDID_adb = { .flags = 0, .offset = offsetof(X9_62_FIELDID, fieldType), - .app_items = 0, .tbl = X9_62_FIELDID_adbtbl, .tblcount = sizeof(X9_62_FIELDID_adbtbl) / sizeof(ASN1_ADB_TABLE), .default_tt = &fieldID_def_tt, @@ -1287,7 +1285,7 @@ EC_GROUP * d2i_ECPKParameters(EC_GROUP ** a, const unsigned char **in, long len) { EC_GROUP *group = NULL; - ECPKPARAMETERS *params = NULL; + ECPKPARAMETERS *params; if ((params = d2i_ECPKPARAMETERS(NULL, in, len)) == NULL) { ECerror(EC_R_D2I_ECPKPARAMETERS_FAILURE); @@ -1334,13 +1332,8 @@ d2i_ECPrivateKey(EC_KEY ** a, const unsigned char **in, long len) EC_KEY *ret = NULL; EC_PRIVATEKEY *priv_key = NULL; - if ((priv_key = EC_PRIVATEKEY_new()) == NULL) { - ECerror(ERR_R_MALLOC_FAILURE); - return NULL; - } - if ((priv_key = d2i_EC_PRIVATEKEY(&priv_key, in, len)) == NULL) { + if ((priv_key = d2i_EC_PRIVATEKEY(NULL, in, len)) == NULL) { ECerror(ERR_R_EC_LIB); - EC_PRIVATEKEY_free(priv_key); return NULL; } if (a == NULL || *a == NULL) { diff --git a/crypto/ec/ec_kmeth.c b/crypto/ec/ec_kmeth.c index 1fb9e57..4203dff 100644 --- a/crypto/ec/ec_kmeth.c +++ b/crypto/ec/ec_kmeth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ec_kmeth.c,v 1.5 2019/05/10 19:15:06 bcook Exp $ */ +/* $OpenBSD: ec_kmeth.c,v 1.6 2021/12/04 16:08:32 tb Exp $ */ /* * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project. @@ -58,6 +58,7 @@ #endif #include +#include "bn_lcl.h" #include "ec_lcl.h" #include "ecs_locl.h" diff --git a/crypto/ec/ec_lcl.h b/crypto/ec/ec_lcl.h index ced04c7..7a74699 100644 --- a/crypto/ec/ec_lcl.h +++ b/crypto/ec/ec_lcl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ec_lcl.h,v 1.18 2021/09/08 17:29:21 tb Exp $ */ +/* $OpenBSD: ec_lcl.h,v 1.19 2021/12/04 16:08:32 tb Exp $ */ /* * Originally written by Bodo Moeller for the OpenSSL project. */ @@ -76,6 +76,8 @@ #include #include +#include "bn_lcl.h" + __BEGIN_HIDDEN_DECLS #if defined(__SUNPRO_C) diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c index 7cc69f8..4ec17d5 100644 --- a/crypto/ec/ec_lib.c +++ b/crypto/ec/ec_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ec_lib.c,v 1.41 2021/09/12 16:23:19 tb Exp $ */ +/* $OpenBSD: ec_lib.c,v 1.45 2022/04/07 17:37:25 tb Exp $ */ /* * Originally written by Bodo Moeller for the OpenSSL project. */ @@ -114,7 +114,7 @@ EC_GROUP_new(const EC_METHOD * meth) } -void +void EC_GROUP_free(EC_GROUP * group) { if (!group) @@ -135,7 +135,7 @@ EC_GROUP_free(EC_GROUP * group) } -void +void EC_GROUP_clear_free(EC_GROUP * group) { if (!group) @@ -157,7 +157,7 @@ EC_GROUP_clear_free(EC_GROUP * group) } -int +int EC_GROUP_copy(EC_GROUP * dest, const EC_GROUP * src) { EC_EXTRA_DATA *d; @@ -247,7 +247,7 @@ EC_GROUP_method_of(const EC_GROUP *group) } -int +int EC_METHOD_get_field_type(const EC_METHOD *meth) { return meth->field_type; @@ -300,7 +300,7 @@ ec_guess_cofactor(EC_GROUP *group) if (!BN_copy(q, &group->field)) goto err; } - + /* * Compute * h = \lfloor (q + 1)/n \rceil = \lfloor (q + 1 + n/2) / n \rfloor. @@ -321,14 +321,18 @@ ec_guess_cofactor(EC_GROUP *group) goto err; ret = 1; + err: BN_CTX_end(ctx); BN_CTX_free(ctx); - BN_zero(&group->cofactor); + + if (ret != 1) + BN_zero(&group->cofactor); + return ret; } -int +int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor) { @@ -344,10 +348,10 @@ EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, } /* - * Require order >= 1 and enforce an upper bound of at most one bit more + * Require order > 1 and enforce an upper bound of at most one bit more * than the field cardinality due to Hasse's theorem. */ - if (order == NULL || BN_is_zero(order) || BN_is_negative(order) || + if (order == NULL || BN_cmp(order, BN_value_one()) <= 0 || BN_num_bits(order) > BN_num_bits(&group->field) + 1) { ECerror(EC_R_INVALID_GROUP_ORDER); return 0; @@ -381,6 +385,12 @@ EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, } else if (!ec_guess_cofactor(group)) return 0; + /* Use Hasse's theorem to bound the cofactor. */ + if (BN_num_bits(&group->cofactor) > BN_num_bits(&group->field) + 1) { + ECerror(EC_R_INVALID_GROUP_ORDER); + return 0; + } + return 1; } @@ -392,7 +402,7 @@ EC_GROUP_get0_generator(const EC_GROUP *group) } -int +int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) { if (!BN_copy(order, &group->order)) @@ -407,7 +417,7 @@ EC_GROUP_order_bits(const EC_GROUP *group) return group->meth->group_order_bits(group); } -int +int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx) { if (!BN_copy(cofactor, &group->cofactor)) @@ -417,35 +427,35 @@ EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx) } -void +void EC_GROUP_set_curve_name(EC_GROUP * group, int nid) { group->curve_name = nid; } -int +int EC_GROUP_get_curve_name(const EC_GROUP * group) { return group->curve_name; } -void +void EC_GROUP_set_asn1_flag(EC_GROUP * group, int flag) { group->asn1_flag = flag; } -int +int EC_GROUP_get_asn1_flag(const EC_GROUP * group) { return group->asn1_flag; } -void +void EC_GROUP_set_point_conversion_form(EC_GROUP * group, point_conversion_form_t form) { @@ -453,14 +463,14 @@ EC_GROUP_set_point_conversion_form(EC_GROUP * group, } -point_conversion_form_t +point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP * group) { return group->asn1_form; } -size_t +size_t EC_GROUP_set_seed(EC_GROUP * group, const unsigned char *p, size_t len) { if (group->seed) { @@ -487,7 +497,7 @@ EC_GROUP_get0_seed(const EC_GROUP * group) } -size_t +size_t EC_GROUP_get_seed_len(const EC_GROUP * group) { return group->seed_len; @@ -545,7 +555,7 @@ EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, } #endif -int +int EC_GROUP_get_degree(const EC_GROUP * group) { if (group->meth->group_get_degree == 0) { @@ -556,7 +566,7 @@ EC_GROUP_get_degree(const EC_GROUP * group) } -int +int EC_GROUP_check_discriminant(const EC_GROUP * group, BN_CTX * ctx) { if (group->meth->group_check_discriminant == 0) { @@ -567,7 +577,7 @@ EC_GROUP_check_discriminant(const EC_GROUP * group, BN_CTX * ctx) } -int +int EC_GROUP_cmp(const EC_GROUP * a, const EC_GROUP * b, BN_CTX * ctx) { int r = 0; @@ -660,7 +670,7 @@ ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx) } /* this has 'package' visibility */ -int +int EC_EX_DATA_set_data(EC_EXTRA_DATA ** ex_data, void *data, void *(*dup_func) (void *), void (*free_func) (void *), @@ -716,7 +726,7 @@ EC_EX_DATA_get_data(const EC_EXTRA_DATA * ex_data, } /* this has 'package' visibility */ -void +void EC_EX_DATA_free_data(EC_EXTRA_DATA ** ex_data, void *(*dup_func) (void *), void (*free_func) (void *), @@ -743,7 +753,7 @@ EC_EX_DATA_free_data(EC_EXTRA_DATA ** ex_data, } /* this has 'package' visibility */ -void +void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA ** ex_data, void *(*dup_func) (void *), void (*free_func) (void *), @@ -770,7 +780,7 @@ EC_EX_DATA_clear_free_data(EC_EXTRA_DATA ** ex_data, } /* this has 'package' visibility */ -void +void EC_EX_DATA_free_all_data(EC_EXTRA_DATA ** ex_data) { EC_EXTRA_DATA *d; @@ -791,7 +801,7 @@ EC_EX_DATA_free_all_data(EC_EXTRA_DATA ** ex_data) } /* this has 'package' visibility */ -void +void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA ** ex_data) { EC_EXTRA_DATA *d; @@ -842,7 +852,7 @@ EC_POINT_new(const EC_GROUP * group) } -void +void EC_POINT_free(EC_POINT * point) { if (!point) @@ -854,7 +864,7 @@ EC_POINT_free(EC_POINT * point) } -void +void EC_POINT_clear_free(EC_POINT * point) { if (!point) @@ -868,7 +878,7 @@ EC_POINT_clear_free(EC_POINT * point) } -int +int EC_POINT_copy(EC_POINT * dest, const EC_POINT * src) { if (dest->meth->point_copy == 0) { @@ -913,7 +923,7 @@ EC_POINT_method_of(const EC_POINT * point) } -int +int EC_POINT_set_to_infinity(const EC_GROUP * group, EC_POINT * point) { if (group->meth->point_set_to_infinity == 0) { @@ -1041,7 +1051,7 @@ EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *poin } #endif -int +int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) { @@ -1057,7 +1067,7 @@ EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, } -int +int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx) { if (group->meth->dbl == 0) { @@ -1072,7 +1082,7 @@ EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx) } -int +int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) { if (group->meth->invert == 0) { @@ -1087,7 +1097,7 @@ EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) } -int +int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) { if (group->meth->is_at_infinity == 0) { @@ -1102,7 +1112,7 @@ EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) } -int +int EC_POINT_is_on_curve(const EC_GROUP * group, const EC_POINT * point, BN_CTX * ctx) { if (group->meth->is_on_curve == 0) { @@ -1117,7 +1127,7 @@ EC_POINT_is_on_curve(const EC_GROUP * group, const EC_POINT * point, BN_CTX * ct } -int +int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX * ctx) { @@ -1133,7 +1143,7 @@ EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, } -int +int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) { if (group->meth->make_affine == 0) { @@ -1148,7 +1158,7 @@ EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) } -int +int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx) { @@ -1169,7 +1179,7 @@ EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], /* Functions for point multiplication */ -int +int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx) { @@ -1184,22 +1194,22 @@ EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } - + /* Either bP or aG + bP, this is sane. */ if (num == 1 && points != NULL && scalars != NULL) return EC_POINT_mul(group, r, scalar, points[0], scalars[0], ctx); - + /* aG, this is sane */ if (scalar != NULL && points == NULL && scalars == NULL) return EC_POINT_mul(group, r, scalar, NULL, NULL, ctx); - + /* anything else is an error */ ECerror(ERR_R_EC_LIB); return 0; } -int +int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx) { @@ -1241,13 +1251,13 @@ EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, return group->meth->mul_double_nonct(group, r, g_scalar, p_scalar, point, ctx); } - + /* Anything else is an error. */ ECerror(ERR_R_EC_LIB); return 0; } -int +int EC_GROUP_precompute_mult(EC_GROUP * group, BN_CTX * ctx) { if (group->meth->precompute_mult != 0) @@ -1256,7 +1266,7 @@ EC_GROUP_precompute_mult(EC_GROUP * group, BN_CTX * ctx) return 1; /* nothing to do, so report success */ } -int +int EC_GROUP_have_precompute_mult(const EC_GROUP * group) { if (group->meth->have_precompute_mult != 0) @@ -1290,5 +1300,5 @@ ECParameters_dup(EC_KEY *key) if ((len = i2d_ECParameters(key, &p)) > 0) k = d2i_ECParameters(NULL, (const unsigned char **)&p, len); - return (k); + return (k); } diff --git a/crypto/ec/ec_pmeth.c b/crypto/ec/ec_pmeth.c index c57d26a..63e6359 100644 --- a/crypto/ec/ec_pmeth.c +++ b/crypto/ec/ec_pmeth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ec_pmeth.c,v 1.12 2019/09/09 18:06:25 jsing Exp $ */ +/* $OpenBSD: ec_pmeth.c,v 1.13 2021/12/04 16:08:32 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2006. */ @@ -66,6 +66,7 @@ #include #include +#include "bn_lcl.h" #include "ec_lcl.h" #include "ech_locl.h" #include "evp_locl.h" diff --git a/crypto/ec/ecp_smpl.c b/crypto/ec/ecp_smpl.c index 1d0b1d6..6f5280b 100644 --- a/crypto/ec/ecp_smpl.c +++ b/crypto/ec/ecp_smpl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ecp_smpl.c,v 1.33 2021/09/08 17:29:21 tb Exp $ */ +/* $OpenBSD: ecp_smpl.c,v 1.34 2022/01/20 11:02:44 inoguchi Exp $ */ /* Includes code written by Lenka Fibikova * for the OpenSSL project. * Includes code written by Bodo Moeller for the OpenSSL project. @@ -586,7 +586,7 @@ ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP * group, const EC_POIN } } } else { - if (!BN_mod_inverse_ct(Z_1, Z_, &group->field, ctx)) { + if (BN_mod_inverse_ct(Z_1, Z_, &group->field, ctx) == NULL) { ECerror(ERR_R_BN_LIB); goto err; } @@ -1316,7 +1316,7 @@ ec_GFp_simple_points_make_affine(const EC_GROUP * group, size_t num, EC_POINT * /* invert heap[1] */ if (!BN_is_zero(heap[1])) { - if (!BN_mod_inverse_ct(heap[1], heap[1], &group->field, ctx)) { + if (BN_mod_inverse_ct(heap[1], heap[1], &group->field, ctx) == NULL) { ECerror(ERR_R_BN_LIB); goto err; } diff --git a/crypto/ecdh/ech_key.c b/crypto/ecdh/ech_key.c index e59ce8b..797cb01 100644 --- a/crypto/ecdh/ech_key.c +++ b/crypto/ecdh/ech_key.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ech_key.c,v 1.11 2021/04/20 17:23:37 tb Exp $ */ +/* $OpenBSD: ech_key.c,v 1.12 2021/12/04 16:08:32 tb Exp $ */ /* ==================================================================== * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. * @@ -77,6 +77,7 @@ #include #include +#include "bn_lcl.h" #include "ech_locl.h" #include "ec_lcl.h" diff --git a/crypto/ecdsa/ecs_asn1.c b/crypto/ecdsa/ecs_asn1.c index e463858..9a7a044 100644 --- a/crypto/ecdsa/ecs_asn1.c +++ b/crypto/ecdsa/ecs_asn1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ecs_asn1.c,v 1.9 2018/03/17 15:24:44 tb Exp $ */ +/* $OpenBSD: ecs_asn1.c,v 1.10 2022/01/05 20:39:04 tb Exp $ */ /* ==================================================================== * Copyright (c) 2000-2002 The OpenSSL Project. All rights reserved. * @@ -123,6 +123,18 @@ ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) *ps = sig->s; } +const BIGNUM * +ECDSA_SIG_get0_r(const ECDSA_SIG *sig) +{ + return sig->r; +} + +const BIGNUM * +ECDSA_SIG_get0_s(const ECDSA_SIG *sig) +{ + return sig->s; +} + int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) { diff --git a/crypto/ecdsa/ecs_err.c b/crypto/ecdsa/ecs_err.c index 9c5a546..ac8850d 100644 --- a/crypto/ecdsa/ecs_err.c +++ b/crypto/ecdsa/ecs_err.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ecs_err.c,v 1.5 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: ecs_err.c,v 1.6 2022/01/27 20:31:21 tb Exp $ */ /* ==================================================================== * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved. * @@ -62,8 +62,8 @@ #include -#include #include +#include /* BEGIN ERROR CODES */ #ifndef OPENSSL_NO_ERR diff --git a/crypto/ecdsa/ecs_locl.h b/crypto/ecdsa/ecs_locl.h index 0a9f179..a53ec37 100644 --- a/crypto/ecdsa/ecs_locl.h +++ b/crypto/ecdsa/ecs_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ecs_locl.h,v 1.6 2019/01/19 01:07:00 tb Exp $ */ +/* $OpenBSD: ecs_locl.h,v 1.7 2022/01/14 08:31:03 tb Exp $ */ /* * Written by Nils Larsch for the OpenSSL project */ @@ -73,6 +73,11 @@ typedef struct ecdsa_data_st { CRYPTO_EX_DATA ex_data; } ECDSA_DATA; +struct ECDSA_SIG_st { + BIGNUM *r; + BIGNUM *s; +}; + /** ecdsa_check * checks whether ECKEY->meth_data is a pointer to a ECDSA_DATA structure * and if not it removes the old meth_data and creates a ECDSA_DATA structure. diff --git a/crypto/ecdsa/ecs_ossl.c b/crypto/ecdsa/ecs_ossl.c index e7e7a52..0203b01 100644 --- a/crypto/ecdsa/ecs_ossl.c +++ b/crypto/ecdsa/ecs_ossl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ecs_ossl.c,v 1.22 2021/04/20 17:23:37 tb Exp $ */ +/* $OpenBSD: ecs_ossl.c,v 1.24 2022/04/07 17:37:25 tb Exp $ */ /* * Written by Nils Larsch for the OpenSSL project */ @@ -163,6 +163,11 @@ ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) goto err; } + if (BN_cmp(order, BN_value_one()) <= 0) { + ECDSAerror(EC_R_INVALID_GROUP_ORDER); + goto err; + } + /* Preallocate space. */ order_bits = BN_num_bits(order); if (!BN_set_bit(k, order_bits) || @@ -216,7 +221,7 @@ ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) } } while (BN_is_zero(r)); - if (!BN_mod_inverse_ct(k, k, order, ctx)) { + if (BN_mod_inverse_ct(k, k, order, ctx) == NULL) { ECDSAerror(ERR_R_BN_LIB); goto err; } @@ -487,7 +492,7 @@ ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, if (!ecdsa_prepare_digest(dgst, dgst_len, order, m)) goto err; - if (!BN_mod_inverse_ct(u2, sig->s, order, ctx)) { /* w = inv(s) */ + if (BN_mod_inverse_ct(u2, sig->s, order, ctx) == NULL) { /* w = inv(s) */ ECDSAerror(ERR_R_BN_LIB); goto err; } diff --git a/crypto/ecdsa/ecs_sign.c b/crypto/ecdsa/ecs_sign.c index 5beb853..6424a3c 100644 --- a/crypto/ecdsa/ecs_sign.c +++ b/crypto/ecdsa/ecs_sign.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ecs_sign.c,v 1.7 2019/01/19 01:07:00 tb Exp $ */ +/* $OpenBSD: ecs_sign.c,v 1.9 2022/01/27 20:30:29 tb Exp $ */ /* ==================================================================== * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. * @@ -58,7 +58,10 @@ #ifndef OPENSSL_NO_ENGINE #include #endif +#include +#include +#include "bn_lcl.h" #include "ecs_locl.h" #include "ec_lcl.h" diff --git a/crypto/ecdsa/ecs_vrf.c b/crypto/ecdsa/ecs_vrf.c index 4c1bc85..7db5a93 100644 --- a/crypto/ecdsa/ecs_vrf.c +++ b/crypto/ecdsa/ecs_vrf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ecs_vrf.c,v 1.7 2019/01/19 01:12:48 tb Exp $ */ +/* $OpenBSD: ecs_vrf.c,v 1.9 2022/01/27 20:30:29 tb Exp $ */ /* * Written by Nils Larsch for the OpenSSL project */ @@ -58,11 +58,15 @@ #include -#include "ecs_locl.h" -#include "ec_lcl.h" #ifndef OPENSSL_NO_ENGINE #include #endif +#include +#include + +#include "bn_lcl.h" +#include "ecs_locl.h" +#include "ec_lcl.h" /* returns * 1: correct signature diff --git a/crypto/engine/eng_openssl.c b/crypto/engine/eng_openssl.c index f8f6c8f..1a6113b 100644 --- a/crypto/engine/eng_openssl.c +++ b/crypto/engine/eng_openssl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: eng_openssl.c,v 1.13 2018/04/14 07:18:37 tb Exp $ */ +/* $OpenBSD: eng_openssl.c,v 1.15 2022/01/09 23:55:31 tb Exp $ */ /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL * project 2000. */ @@ -84,6 +84,8 @@ #include #endif +#include "evp_locl.h" + /* This testing gunk is implemented (and explained) lower down. It also assumes * the application explicitly calls "ENGINE_load_openssl()" because this is no * longer automatic in ENGINE_load_builtin_engines(). */ @@ -349,18 +351,17 @@ test_sha1_final(EVP_MD_CTX *ctx, unsigned char *md) } static const EVP_MD test_sha_md = { - NID_sha1, - NID_sha1WithRSAEncryption, - SHA_DIGEST_LENGTH, - 0, - test_sha1_init, - test_sha1_update, - test_sha1_final, - NULL, - NULL, - EVP_PKEY_RSA_method, - SHA_CBLOCK, - sizeof(EVP_MD *) + sizeof(SHA_CTX), + .type = NID_sha1, + .pkey_type = NID_sha1WithRSAEncryption, + .md_size = SHA_DIGEST_LENGTH, + .flags = 0, + .init = test_sha1_init, + .update = test_sha1_update, + .final = test_sha1_final, + .copy = NULL, + .cleanup = NULL, + .block_size = SHA_CBLOCK, + .ctx_size = sizeof(EVP_MD *) + sizeof(SHA_CTX), }; static int diff --git a/crypto/err/err_prn.c b/crypto/err/err_prn.c index 4816682..6b5c455 100644 --- a/crypto/err/err_prn.c +++ b/crypto/err/err_prn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: err_prn.c,v 1.18 2017/02/07 15:52:33 jsing Exp $ */ +/* $OpenBSD: err_prn.c,v 1.19 2022/01/07 09:02:18 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -64,6 +64,8 @@ #include #include +#include "bio_local.h" + void ERR_print_errors_cb(int (*cb)(const char *str, size_t len, void *u), void *u) { diff --git a/crypto/evp/bio_b64.c b/crypto/evp/bio_b64.c index 82aaa8b..b61a342 100644 --- a/crypto/evp/bio_b64.c +++ b/crypto/evp/bio_b64.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bio_b64.c,v 1.22 2018/08/24 19:47:25 tb Exp $ */ +/* $OpenBSD: bio_b64.c,v 1.25 2022/01/14 08:40:57 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -63,6 +63,9 @@ #include #include +#include "bio_local.h" +#include "evp_locl.h" + static int b64_write(BIO *h, const char *buf, int num); static int b64_read(BIO *h, char *buf, int size); static int b64_puts(BIO *h, const char *str); @@ -70,7 +73,7 @@ static int b64_puts(BIO *h, const char *str); static long b64_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int b64_new(BIO *h); static int b64_free(BIO *data); -static long b64_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); +static long b64_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); #define B64_BLOCK_SIZE 1024 #define B64_BLOCK_SIZE2 768 #define B64_NONE 0 @@ -547,7 +550,7 @@ again: } static long -b64_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +b64_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { long ret = 1; diff --git a/crypto/evp/bio_enc.c b/crypto/evp/bio_enc.c index 7b55998..2a0f76f 100644 --- a/crypto/evp/bio_enc.c +++ b/crypto/evp/bio_enc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bio_enc.c,v 1.22 2018/08/24 19:30:24 tb Exp $ */ +/* $OpenBSD: bio_enc.c,v 1.26 2022/01/14 08:40:57 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -63,6 +63,9 @@ #include #include +#include "bio_local.h" +#include "evp_locl.h" + static int enc_write(BIO *h, const char *buf, int num); static int enc_read(BIO *h, char *buf, int size); /*static int enc_puts(BIO *h, const char *str); */ @@ -70,7 +73,7 @@ static int enc_read(BIO *h, char *buf, int size); static long enc_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int enc_new(BIO *h); static int enc_free(BIO *data); -static long enc_callback_ctrl(BIO *h, int cmd, bio_info_cb *fps); +static long enc_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fps); #define ENC_BLOCK_SIZE (1024*4) #define BUF_OFFSET (EVP_MAX_BLOCK_LENGTH*2) @@ -370,7 +373,7 @@ again: } static long -enc_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +enc_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { long ret = 1; @@ -384,26 +387,6 @@ enc_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) return (ret); } -/* -void BIO_set_cipher_ctx(b,c) -BIO *b; -EVP_CIPHER_ctx *c; - { - if (b == NULL) return; - - if ((b->callback != NULL) && - (b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,0L) <= 0)) - return; - - b->init=1; - ctx=(BIO_ENC_CTX *)b->ptr; - memcpy(ctx->cipher,c,sizeof(EVP_CIPHER_CTX)); - - if (b->callback != NULL) - b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,1L); - } -*/ - int BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *k, const unsigned char *i, int e) diff --git a/crypto/evp/bio_md.c b/crypto/evp/bio_md.c index 44f7218..4ae5f1f 100644 --- a/crypto/evp/bio_md.c +++ b/crypto/evp/bio_md.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bio_md.c,v 1.15 2018/05/02 15:51:41 tb Exp $ */ +/* $OpenBSD: bio_md.c,v 1.18 2022/01/14 08:40:57 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -62,6 +62,9 @@ #include #include +#include "bio_local.h" +#include "evp_locl.h" + /* BIO_put and BIO_get both add to the digest, * BIO_gets returns the digest */ @@ -72,7 +75,7 @@ static int md_gets(BIO *h, char *str, int size); static long md_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int md_new(BIO *h); static int md_free(BIO *data); -static long md_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); +static long md_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); static const BIO_METHOD methods_md = { .type = BIO_TYPE_MD, @@ -238,7 +241,7 @@ md_ctrl(BIO *b, int cmd, long num, void *ptr) } static long -md_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +md_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { long ret = 1; diff --git a/crypto/evp/c_all.c b/crypto/evp/c_all.c index 9e9d39d..690215c 100644 --- a/crypto/evp/c_all.c +++ b/crypto/evp/c_all.c @@ -1,4 +1,4 @@ -/* $OpenBSD: c_all.c,v 1.26 2019/03/17 18:07:41 tb Exp $ */ +/* $OpenBSD: c_all.c,v 1.27 2022/01/14 08:38:05 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -263,24 +263,10 @@ OpenSSL_add_all_digests_internal(void) EVP_add_digest_alias(SN_md5, "ssl3-md5"); #endif -#if !defined(OPENSSL_NO_SHA) -#ifndef OPENSSL_NO_DSA - EVP_add_digest(EVP_dss()); -#endif -#endif #if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1) EVP_add_digest(EVP_sha1()); EVP_add_digest_alias(SN_sha1, "ssl3-sha1"); EVP_add_digest_alias(SN_sha1WithRSAEncryption, SN_sha1WithRSA); -#ifndef OPENSSL_NO_DSA - EVP_add_digest(EVP_dss1()); - EVP_add_digest_alias(SN_dsaWithSHA1, SN_dsaWithSHA1_2); - EVP_add_digest_alias(SN_dsaWithSHA1, "DSS1"); - EVP_add_digest_alias(SN_dsaWithSHA1, "dss1"); -#endif -#ifndef OPENSSL_NO_ECDSA - EVP_add_digest(EVP_ecdsa()); -#endif #endif #ifndef OPENSSL_NO_GOST diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c index 4cd3565..ecb5292 100644 --- a/crypto/evp/digest.c +++ b/crypto/evp/digest.c @@ -1,4 +1,4 @@ -/* $OpenBSD: digest.c,v 1.31 2019/04/19 17:04:45 jsing Exp $ */ +/* $OpenBSD: digest.c,v 1.34 2022/01/10 10:51:31 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -122,6 +122,8 @@ #include #endif +#include "evp_locl.h" + int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type) { @@ -279,6 +281,14 @@ EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) tmp_buf = NULL; EVP_MD_CTX_cleanup(out); memcpy(out, in, sizeof *out); + out->md_data = NULL; + out->pctx = NULL; + + /* + * Because of the EVP_PKEY_CTX_dup() below, EVP_MD_CTX_cleanup() needs + * to free out->pctx in all cases (even if this flag is set on in). + */ + EVP_MD_CTX_clear_flags(out, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX); if (in->md_data && out->digest->ctx_size) { if (tmp_buf) { @@ -381,7 +391,12 @@ EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx) if (ctx->digest && ctx->digest->ctx_size && ctx->md_data && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE)) freezero(ctx->md_data, ctx->digest->ctx_size); - EVP_PKEY_CTX_free(ctx->pctx); + /* + * If EVP_MD_CTX_FLAG_KEEP_PKEY_CTX is set, EVP_MD_CTX_set_pkey() was + * called and its strange API contract implies we don't own ctx->pctx. + */ + if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX)) + EVP_PKEY_CTX_free(ctx->pctx); #ifndef OPENSSL_NO_ENGINE ENGINE_finish(ctx->engine); #endif diff --git a/crypto/evp/e_aes_cbc_hmac_sha1.c b/crypto/evp/e_aes_cbc_hmac_sha1.c index 9be17e3..eef9c28 100644 --- a/crypto/evp/e_aes_cbc_hmac_sha1.c +++ b/crypto/evp/e_aes_cbc_hmac_sha1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: e_aes_cbc_hmac_sha1.c,v 1.15 2019/04/03 15:33:37 tb Exp $ */ +/* $OpenBSD: e_aes_cbc_hmac_sha1.c,v 1.16 2021/12/12 21:30:13 tb Exp $ */ /* ==================================================================== * Copyright (c) 2011-2013 The OpenSSL Project. All rights reserved. * @@ -59,8 +59,9 @@ #include #include #include -#include "evp_locl.h" + #include "constant_time_locl.h" +#include "evp_locl.h" #define TLS1_1_VERSION 0x0302 diff --git a/crypto/evp/e_camellia.c b/crypto/evp/e_camellia.c index fd12cf9..70dad7e 100644 --- a/crypto/evp/e_camellia.c +++ b/crypto/evp/e_camellia.c @@ -1,4 +1,4 @@ -/* $OpenBSD: e_camellia.c,v 1.8 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: e_camellia.c,v 1.9 2021/12/12 21:30:13 tb Exp $ */ /* ==================================================================== * Copyright (c) 2006 The OpenSSL Project. All rights reserved. * @@ -61,6 +61,7 @@ #include #include #include + #include "evp_locl.h" static int camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, diff --git a/crypto/evp/e_gost2814789.c b/crypto/evp/e_gost2814789.c index 730de4f..7803d95 100644 --- a/crypto/evp/e_gost2814789.c +++ b/crypto/evp/e_gost2814789.c @@ -1,4 +1,4 @@ -/* $OpenBSD: e_gost2814789.c,v 1.4 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: e_gost2814789.c,v 1.5 2021/12/12 21:30:13 tb Exp $ */ /* * Copyright (c) 2014 Dmitry Eremin-Solenikov * Copyright (c) 2005-2006 Cryptocom LTD @@ -48,6 +48,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== */ + #include #include @@ -56,6 +57,7 @@ #include #include #include + #include "evp_locl.h" typedef struct { diff --git a/crypto/evp/e_null.c b/crypto/evp/e_null.c index 65374cc..db79e1e 100644 --- a/crypto/evp/e_null.c +++ b/crypto/evp/e_null.c @@ -1,4 +1,4 @@ -/* $OpenBSD: e_null.c,v 1.14 2014/07/11 08:44:48 jsing Exp $ */ +/* $OpenBSD: e_null.c,v 1.15 2021/12/12 21:30:13 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -62,6 +62,8 @@ #include #include +#include "evp_locl.h" + static int null_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc); static int null_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, diff --git a/crypto/evp/e_rc2.c b/crypto/evp/e_rc2.c index de1b24a..b07fafd 100644 --- a/crypto/evp/e_rc2.c +++ b/crypto/evp/e_rc2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: e_rc2.c,v 1.12 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: e_rc2.c,v 1.14 2022/01/20 11:31:37 inoguchi Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -150,7 +150,8 @@ rc2_meth_to_magic(EVP_CIPHER_CTX *e) { int i; - EVP_CIPHER_CTX_ctrl(e, EVP_CTRL_GET_RC2_KEY_BITS, 0, &i); + if (EVP_CIPHER_CTX_ctrl(e, EVP_CTRL_GET_RC2_KEY_BITS, 0, &i) <= 0) + return (0); if (i == 128) return (RC2_128_MAGIC); else if (i == 64) @@ -199,9 +200,11 @@ rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) return (-1); if (i > 0 && !EVP_CipherInit_ex(c, NULL, NULL, NULL, iv, -1)) return -1; - EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_RC2_KEY_BITS, - key_bits, NULL); - EVP_CIPHER_CTX_set_key_length(c, key_bits / 8); + if (EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_RC2_KEY_BITS, + key_bits, NULL) <= 0) + return -1; + if (!EVP_CIPHER_CTX_set_key_length(c, key_bits / 8)) + return -1; } return (i); } diff --git a/crypto/evp/e_rc4_hmac_md5.c b/crypto/evp/e_rc4_hmac_md5.c index ac73361..b8a6b44 100644 --- a/crypto/evp/e_rc4_hmac_md5.c +++ b/crypto/evp/e_rc4_hmac_md5.c @@ -1,4 +1,4 @@ -/* $OpenBSD: e_rc4_hmac_md5.c,v 1.8 2017/01/31 13:17:21 inoguchi Exp $ */ +/* $OpenBSD: e_rc4_hmac_md5.c,v 1.9 2021/12/12 21:30:13 tb Exp $ */ /* ==================================================================== * Copyright (c) 2011 The OpenSSL Project. All rights reserved. * @@ -60,6 +60,8 @@ #include #include +#include "evp_locl.h" + /* FIXME: surely this is available elsewhere? */ #define EVP_RC4_KEY_SIZE 16 diff --git a/crypto/evp/encode.c b/crypto/evp/encode.c index 2f942a0..30fcd85 100644 --- a/crypto/evp/encode.c +++ b/crypto/evp/encode.c @@ -1,4 +1,4 @@ -/* $OpenBSD: encode.c,v 1.28 2020/03/04 11:53:21 inoguchi Exp $ */ +/* $OpenBSD: encode.c,v 1.29 2021/12/12 21:30:13 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -62,6 +62,8 @@ #include +#include "evp_locl.h" + static unsigned char conv_ascii2bin(unsigned char a); #define conv_bin2ascii(a) (data_bin2ascii[(a)&0x3f]) diff --git a/crypto/evp/evp_aead.c b/crypto/evp/evp_aead.c index 40471b0..93d523a 100644 --- a/crypto/evp/evp_aead.c +++ b/crypto/evp/evp_aead.c @@ -1,4 +1,4 @@ -/* $OpenBSD: evp_aead.c,v 1.6 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: evp_aead.c,v 1.7 2022/01/07 21:58:17 tb Exp $ */ /* * Copyright (c) 2014, Google Inc. * @@ -68,6 +68,22 @@ EVP_AEAD_CTX_cleanup(EVP_AEAD_CTX *ctx) ctx->aead = NULL; } +EVP_AEAD_CTX * +EVP_AEAD_CTX_new(void) +{ + return calloc(1, sizeof(EVP_AEAD_CTX)); +} + +void +EVP_AEAD_CTX_free(EVP_AEAD_CTX *ctx) +{ + if (ctx == NULL) + return; + + EVP_AEAD_CTX_cleanup(ctx); + free(ctx); +} + /* check_alias returns 0 if out points within the buffer determined by in * and in_len and 1 otherwise. * diff --git a/crypto/evp/evp_key.c b/crypto/evp/evp_key.c index 91d0fc0..dcfb94e 100644 --- a/crypto/evp/evp_key.c +++ b/crypto/evp/evp_key.c @@ -1,4 +1,4 @@ -/* $OpenBSD: evp_key.c,v 1.26 2018/08/14 17:59:26 tb Exp $ */ +/* $OpenBSD: evp_key.c,v 1.27 2021/12/12 21:30:13 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -65,6 +65,8 @@ #include #include +#include "evp_locl.h" + /* should be init to zeros. */ static char prompt_string[80]; diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c index 9010773..0e354d6 100644 --- a/crypto/evp/evp_lib.c +++ b/crypto/evp/evp_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: evp_lib.c,v 1.17 2018/09/12 06:35:38 djm Exp $ */ +/* $OpenBSD: evp_lib.c,v 1.24 2022/01/10 13:42:28 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -63,6 +63,9 @@ #include #include +#include "asn1_locl.h" +#include "evp_locl.h" + int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type) { @@ -237,6 +240,23 @@ EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data) ctx->app_data = data; } +void * +EVP_CIPHER_CTX_get_cipher_data(const EVP_CIPHER_CTX *ctx) +{ + return ctx->cipher_data; +} + +void * +EVP_CIPHER_CTX_set_cipher_data(EVP_CIPHER_CTX *ctx, void *cipher_data) +{ + void *old_cipher_data; + + old_cipher_data = ctx->cipher_data; + ctx->cipher_data = cipher_data; + + return old_cipher_data; +} + int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher) { @@ -249,6 +269,12 @@ EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx) return ctx->cipher->iv_len; } +unsigned char * +EVP_CIPHER_CTX_buf_noconst(EVP_CIPHER_CTX *ctx) +{ + return ctx->buf; +} + int EVP_CIPHER_key_length(const EVP_CIPHER *cipher) { @@ -345,6 +371,114 @@ EVP_MD_flags(const EVP_MD *md) return md->flags; } +EVP_MD * +EVP_MD_meth_new(int md_type, int pkey_type) +{ + EVP_MD *md; + + if ((md = calloc(1, sizeof(*md))) == NULL) + return NULL; + + md->type = md_type; + md->pkey_type = pkey_type; + + return md; +} + +EVP_MD * +EVP_MD_meth_dup(const EVP_MD *md) +{ + EVP_MD *to; + + if ((to = EVP_MD_meth_new(md->type, md->pkey_type)) == NULL) + return NULL; + + memcpy(to, md, sizeof(*to)); + + return to; +} + +void +EVP_MD_meth_free(EVP_MD *md) +{ + freezero(md, sizeof(*md)); +} + +int +EVP_MD_meth_set_input_blocksize(EVP_MD *md, int blocksize) +{ + md->block_size = blocksize; + return 1; +} + +int +EVP_MD_meth_set_result_size(EVP_MD *md, int result_size) +{ + md->md_size = result_size; + return 1; +} + +int +EVP_MD_meth_set_app_datasize(EVP_MD *md, int datasize) +{ + md->ctx_size = datasize; + return 1; +} + +int +EVP_MD_meth_set_flags(EVP_MD *md, unsigned long flags) +{ + md->flags = flags; + return 1; +} + +int +EVP_MD_meth_set_init(EVP_MD *md, int (*init)(EVP_MD_CTX *ctx)) +{ + md->init = init; + return 1; +} + +int +EVP_MD_meth_set_update(EVP_MD *md, + int (*update)(EVP_MD_CTX *ctx, const void *data, size_t count)) +{ + md->update = update; + return 1; +} + +int +EVP_MD_meth_set_final(EVP_MD *md, + int (*final)(EVP_MD_CTX *ctx, unsigned char *md)) +{ + md->final = final; + return 1; +} + +int +EVP_MD_meth_set_copy(EVP_MD *md, + int (*copy)(EVP_MD_CTX *to, const EVP_MD_CTX *from)) +{ + md->copy = copy; + return 1; +} + +int +EVP_MD_meth_set_cleanup(EVP_MD *md, + int (*cleanup)(EVP_MD_CTX *ctx)) +{ + md->cleanup = cleanup; + return 1; +} + +int +EVP_MD_meth_set_ctrl(EVP_MD *md, + int (*ctrl)(EVP_MD_CTX *ctx, int cmd, int p1, void *p2)) +{ + md->md_ctrl = ctrl; + return 1; +} + const EVP_MD * EVP_MD_CTX_md(const EVP_MD_CTX *ctx) { @@ -353,6 +487,41 @@ EVP_MD_CTX_md(const EVP_MD_CTX *ctx) return ctx->digest; } +void * +EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx) +{ + return ctx->md_data; +} + +EVP_PKEY_CTX * +EVP_MD_CTX_pkey_ctx(const EVP_MD_CTX *ctx) +{ + return ctx->pctx; +} + +void +EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx) +{ + if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX)) { + EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX); + } else { + EVP_PKEY_CTX_free(ctx->pctx); + } + + ctx->pctx = pctx; + + if (pctx != NULL) { + /* + * For unclear reasons it was decided that the caller keeps + * ownership of pctx. So a flag was invented to make sure we + * don't free it in EVP_MD_CTX_cleanup(). We also need to + * unset it in EVP_MD_CTX_copy_ex(). Fortunately, the flag + * isn't public... + */ + EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX); + } +} + void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags) { diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h index 8df6135..c3d9a6a 100644 --- a/crypto/evp/evp_locl.h +++ b/crypto/evp/evp_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: evp_locl.h,v 1.16 2019/10/29 07:52:17 jsing Exp $ */ +/* $OpenBSD: evp_locl.h,v 1.22 2022/01/14 08:38:05 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ @@ -56,8 +56,134 @@ * */ +#ifndef HEADER_EVP_LOCL_H +#define HEADER_EVP_LOCL_H + __BEGIN_HIDDEN_DECLS +/* + * Don't free md_ctx->pctx in EVP_MD_CTX_cleanup(). Needed for ownership + * handling in EVP_MD_CTX_set_pkey_ctx(). + */ +#define EVP_MD_CTX_FLAG_KEEP_PKEY_CTX 0x0400 + +typedef int evp_sign_method(int type, const unsigned char *m, + unsigned int m_length, unsigned char *sigret, unsigned int *siglen, + void *key); +typedef int evp_verify_method(int type, const unsigned char *m, + unsigned int m_length, const unsigned char *sigbuf, unsigned int siglen, + void *key); + +/* Type needs to be a bit field + * Sub-type needs to be for variations on the method, as in, can it do + * arbitrary encryption.... */ +struct evp_pkey_st { + int type; + int save_type; + int references; + const EVP_PKEY_ASN1_METHOD *ameth; + ENGINE *engine; + union { + char *ptr; +#ifndef OPENSSL_NO_RSA + struct rsa_st *rsa; /* RSA */ +#endif +#ifndef OPENSSL_NO_DSA + struct dsa_st *dsa; /* DSA */ +#endif +#ifndef OPENSSL_NO_DH + struct dh_st *dh; /* DH */ +#endif +#ifndef OPENSSL_NO_EC + struct ec_key_st *ec; /* ECC */ +#endif +#ifndef OPENSSL_NO_GOST + struct gost_key_st *gost; /* GOST */ +#endif + } pkey; + int save_parameters; + STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */ +} /* EVP_PKEY */; + +struct env_md_st { + int type; + int pkey_type; + int md_size; + unsigned long flags; + int (*init)(EVP_MD_CTX *ctx); + int (*update)(EVP_MD_CTX *ctx, const void *data, size_t count); + int (*final)(EVP_MD_CTX *ctx, unsigned char *md); + int (*copy)(EVP_MD_CTX *to, const EVP_MD_CTX *from); + int (*cleanup)(EVP_MD_CTX *ctx); + + int block_size; + int ctx_size; /* how big does the ctx->md_data need to be */ + /* control function */ + int (*md_ctrl)(EVP_MD_CTX *ctx, int cmd, int p1, void *p2); +} /* EVP_MD */; + +struct env_md_ctx_st { + const EVP_MD *digest; + ENGINE *engine; /* functional reference if 'digest' is ENGINE-provided */ + unsigned long flags; + void *md_data; + /* Public key context for sign/verify */ + EVP_PKEY_CTX *pctx; + /* Update function: usually copied from EVP_MD */ + int (*update)(EVP_MD_CTX *ctx, const void *data, size_t count); +} /* EVP_MD_CTX */; + +struct evp_cipher_st { + int nid; + int block_size; + int key_len; /* Default value for variable length ciphers */ + int iv_len; + unsigned long flags; /* Various flags */ + int (*init)(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); /* init key */ + int (*do_cipher)(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl);/* encrypt/decrypt data */ + int (*cleanup)(EVP_CIPHER_CTX *); /* cleanup ctx */ + int ctx_size; /* how big ctx->cipher_data needs to be */ + int (*set_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); /* Populate a ASN1_TYPE with parameters */ + int (*get_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); /* Get parameters from a ASN1_TYPE */ + int (*ctrl)(EVP_CIPHER_CTX *, int type, int arg, void *ptr); /* Miscellaneous operations */ + void *app_data; /* Application data */ +} /* EVP_CIPHER */; + +struct evp_cipher_ctx_st { + const EVP_CIPHER *cipher; + ENGINE *engine; /* functional reference if 'cipher' is ENGINE-provided */ + int encrypt; /* encrypt or decrypt */ + int buf_len; /* number we have left */ + + unsigned char oiv[EVP_MAX_IV_LENGTH]; /* original iv */ + unsigned char iv[EVP_MAX_IV_LENGTH]; /* working iv */ + unsigned char buf[EVP_MAX_BLOCK_LENGTH];/* saved partial block */ + int num; /* used by cfb/ofb/ctr mode */ + + void *app_data; /* application stuff */ + int key_len; /* May change for variable length cipher */ + unsigned long flags; /* Various flags */ + void *cipher_data; /* per EVP data */ + int final_used; + int block_mask; + unsigned char final[EVP_MAX_BLOCK_LENGTH];/* possible final block */ +} /* EVP_CIPHER_CTX */; + +struct evp_Encode_Ctx_st { + + int num; /* number saved in a partial encode/decode */ + int length; /* The length is either the output line length + * (in input bytes) or the shortest input line + * length that is ok. Once decoding begins, + * the length is adjusted up each time a longer + * line is decoded */ + unsigned char enc_data[80]; /* data to encode */ + int line_num; /* number read on current line */ + int expect_nl; +} /* EVP_ENCODE_CTX */; + /* Macros to code block cipher wrappers */ /* Wrapper functions for each cipher mode */ @@ -338,6 +464,10 @@ struct evp_pkey_method_st { int (*ctrl)(EVP_PKEY_CTX *ctx, int type, int p1, void *p2); int (*ctrl_str)(EVP_PKEY_CTX *ctx, const char *type, const char *value); + + int (*check)(EVP_PKEY *pkey); + int (*public_check)(EVP_PKEY *pkey); + int (*param_check)(EVP_PKEY *pkey); } /* EVP_PKEY_METHOD */; void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx); @@ -367,6 +497,16 @@ struct evp_aead_st { const unsigned char *ad, size_t ad_len); }; +/* An EVP_AEAD_CTX represents an AEAD algorithm configured with a specific key + * and message-independent IV. */ +struct evp_aead_ctx_st { + const EVP_AEAD *aead; + /* aead_state is an opaque pointer to the AEAD specific state. */ + void *aead_state; +}; + int EVP_PKEY_CTX_md(EVP_PKEY_CTX *ctx, int optype, int cmd, const char *md_name); __END_HIDDEN_DECLS + +#endif /* !HEADER_EVP_LOCL_H */ diff --git a/crypto/evp/evp_pkey.c b/crypto/evp/evp_pkey.c index 9ff544b..3ba0e1d 100644 --- a/crypto/evp/evp_pkey.c +++ b/crypto/evp/evp_pkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: evp_pkey.c,v 1.23 2018/08/24 20:26:03 tb Exp $ */ +/* $OpenBSD: evp_pkey.c,v 1.24 2021/12/12 21:30:13 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -63,6 +63,7 @@ #include #include "asn1_locl.h" +#include "evp_locl.h" /* Extract a private key from a PKCS8 structure */ diff --git a/crypto/evp/m_dss.c b/crypto/evp/m_dss.c deleted file mode 100644 index d23c9b4..0000000 --- a/crypto/evp/m_dss.c +++ /dev/null @@ -1,117 +0,0 @@ -/* $OpenBSD: m_dss.c,v 1.16 2014/07/11 08:44:48 jsing Exp $ */ -/* 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.] - */ - -#include - -#include - -#include -#include -#include - -#ifndef OPENSSL_NO_DSA -#include -#endif - -#ifndef OPENSSL_NO_SHA - -static int -init(EVP_MD_CTX *ctx) -{ - return SHA1_Init(ctx->md_data); -} - -static int -update(EVP_MD_CTX *ctx, const void *data, size_t count) -{ - return SHA1_Update(ctx->md_data, data, count); -} - -static int -final(EVP_MD_CTX *ctx, unsigned char *md) -{ - return SHA1_Final(md, ctx->md_data); -} - -static const EVP_MD dsa_md = { - .type = NID_dsaWithSHA, - .pkey_type = NID_dsaWithSHA, - .md_size = SHA_DIGEST_LENGTH, - .flags = EVP_MD_FLAG_PKEY_DIGEST, - .init = init, - .update = update, - .final = final, - .copy = NULL, - .cleanup = NULL, -#ifndef OPENSSL_NO_DSA - .sign = (evp_sign_method *)DSA_sign, - .verify = (evp_verify_method *)DSA_verify, - .required_pkey_type = { - EVP_PKEY_DSA, EVP_PKEY_DSA2, EVP_PKEY_DSA3, EVP_PKEY_DSA4, 0, - }, -#endif - .block_size = SHA_CBLOCK, - .ctx_size = sizeof(EVP_MD *) + sizeof(SHA_CTX), -}; - -const EVP_MD * -EVP_dss(void) -{ - return (&dsa_md); -} -#endif diff --git a/crypto/evp/m_dss1.c b/crypto/evp/m_dss1.c deleted file mode 100644 index a906c11..0000000 --- a/crypto/evp/m_dss1.c +++ /dev/null @@ -1,117 +0,0 @@ -/* $OpenBSD: m_dss1.c,v 1.16 2014/07/11 08:44:48 jsing Exp $ */ -/* 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.] - */ - -#include - -#include - -#ifndef OPENSSL_NO_SHA - -#include -#include -#include - -#ifndef OPENSSL_NO_DSA -#include -#endif - -static int -init(EVP_MD_CTX *ctx) -{ - return SHA1_Init(ctx->md_data); -} - -static int -update(EVP_MD_CTX *ctx, const void *data, size_t count) -{ - return SHA1_Update(ctx->md_data, data, count); -} - -static int -final(EVP_MD_CTX *ctx, unsigned char *md) -{ - return SHA1_Final(md, ctx->md_data); -} - -static const EVP_MD dss1_md = { - .type = NID_dsa, - .pkey_type = NID_dsaWithSHA1, - .md_size = SHA_DIGEST_LENGTH, - .flags = EVP_MD_FLAG_PKEY_DIGEST, - .init = init, - .update = update, - .final = final, - .copy = NULL, - .cleanup = NULL, -#ifndef OPENSSL_NO_DSA - .sign = (evp_sign_method *)DSA_sign, - .verify = (evp_verify_method *)DSA_verify, - .required_pkey_type = { - EVP_PKEY_DSA, EVP_PKEY_DSA2, EVP_PKEY_DSA3, EVP_PKEY_DSA4, 0, - }, -#endif - .block_size = SHA_CBLOCK, - .ctx_size = sizeof(EVP_MD *) + sizeof(SHA_CTX), -}; - -const EVP_MD * -EVP_dss1(void) -{ - return (&dss1_md); -} -#endif diff --git a/crypto/evp/m_ecdsa.c b/crypto/evp/m_ecdsa.c deleted file mode 100644 index b9af642..0000000 --- a/crypto/evp/m_ecdsa.c +++ /dev/null @@ -1,166 +0,0 @@ -/* $OpenBSD: m_ecdsa.c,v 1.8 2014/07/11 08:44:48 jsing Exp $ */ -/* ==================================================================== - * Copyright (c) 1998-2002 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). - * - */ -/* 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.] - */ - -#include - -#include - -#include -#include -#include - -#ifndef OPENSSL_NO_SHA - -static int -init(EVP_MD_CTX *ctx) -{ - return SHA1_Init(ctx->md_data); -} - -static int -update(EVP_MD_CTX *ctx, const void *data, size_t count) -{ - return SHA1_Update(ctx->md_data, data, count); -} - -static int -final(EVP_MD_CTX *ctx, unsigned char *md) -{ - return SHA1_Final(md, ctx->md_data); -} - -static const EVP_MD ecdsa_md = { - .type = NID_ecdsa_with_SHA1, - .pkey_type = NID_ecdsa_with_SHA1, - .md_size = SHA_DIGEST_LENGTH, - .flags = EVP_MD_FLAG_PKEY_DIGEST, - .init = init, - .update = update, - .final = final, - .copy = NULL, - .cleanup = NULL, -#ifndef OPENSSL_NO_ECDSA - .sign = (evp_sign_method *)ECDSA_sign, - .verify = (evp_verify_method *)ECDSA_verify, - .required_pkey_type = { - EVP_PKEY_EC, 0, 0, 0, - }, -#endif - .block_size = SHA_CBLOCK, - .ctx_size = sizeof(EVP_MD *) + sizeof(SHA_CTX), -}; - -const EVP_MD * -EVP_ecdsa(void) -{ - return (&ecdsa_md); -} -#endif diff --git a/crypto/evp/m_gost2814789.c b/crypto/evp/m_gost2814789.c index 279af87..7d11ec8 100644 --- a/crypto/evp/m_gost2814789.c +++ b/crypto/evp/m_gost2814789.c @@ -1,4 +1,4 @@ -/* $OpenBSD: m_gost2814789.c,v 1.2 2014/11/09 23:06:50 miod Exp $ */ +/* $OpenBSD: m_gost2814789.c,v 1.3 2021/12/12 21:30:13 tb Exp $ */ /* * Copyright (c) 2014 Dmitry Eremin-Solenikov * Copyright (c) 2005-2006 Cryptocom LTD @@ -48,6 +48,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== */ + #include #ifndef OPENSSL_NO_GOST @@ -56,6 +57,8 @@ #include #include +#include "evp_locl.h" + static int gost2814789_init(EVP_MD_CTX *ctx) { diff --git a/crypto/evp/m_gostr341194.c b/crypto/evp/m_gostr341194.c index 66d9b4f..f479675 100644 --- a/crypto/evp/m_gostr341194.c +++ b/crypto/evp/m_gostr341194.c @@ -1,4 +1,4 @@ -/* $OpenBSD: m_gostr341194.c,v 1.2 2014/11/09 23:06:50 miod Exp $ */ +/* $OpenBSD: m_gostr341194.c,v 1.4 2022/01/14 08:38:05 tb Exp $ */ /* * Copyright (c) 2014 Dmitry Eremin-Solenikov * Copyright (c) 2005-2006 Cryptocom LTD @@ -48,6 +48,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== */ + #include #include @@ -58,6 +59,8 @@ #include #include +#include "evp_locl.h" + static int gostr341194_init(EVP_MD_CTX *ctx) { @@ -81,7 +84,7 @@ static const EVP_MD gostr341194_md = { .type = NID_id_GostR3411_94, .pkey_type = NID_undef, .md_size = GOSTR341194_LENGTH, - .flags = EVP_MD_FLAG_PKEY_METHOD_SIGNATURE, + .flags = 0, .init = gostr341194_init, .update = gostr341194_update, .final = gostr341194_final, diff --git a/crypto/evp/m_md4.c b/crypto/evp/m_md4.c index ab3cc85..9775652 100644 --- a/crypto/evp/m_md4.c +++ b/crypto/evp/m_md4.c @@ -1,4 +1,4 @@ -/* $OpenBSD: m_md4.c,v 1.16 2015/09/14 01:45:03 doug Exp $ */ +/* $OpenBSD: m_md4.c,v 1.18 2022/01/14 08:38:05 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -71,6 +71,8 @@ #include #endif +#include "evp_locl.h" + static int init(EVP_MD_CTX *ctx) { @@ -99,13 +101,6 @@ static const EVP_MD md4_md = { .final = final, .copy = NULL, .cleanup = NULL, -#ifndef OPENSSL_NO_RSA - .sign = (evp_sign_method *)RSA_sign, - .verify = (evp_verify_method *)RSA_verify, - .required_pkey_type = { - EVP_PKEY_RSA, EVP_PKEY_RSA2, 0, 0, - }, -#endif .block_size = MD4_CBLOCK, .ctx_size = sizeof(EVP_MD *) + sizeof(MD4_CTX), }; diff --git a/crypto/evp/m_md5.c b/crypto/evp/m_md5.c index 36cff7a..daa7aee 100644 --- a/crypto/evp/m_md5.c +++ b/crypto/evp/m_md5.c @@ -1,4 +1,4 @@ -/* $OpenBSD: m_md5.c,v 1.15 2014/07/13 09:30:02 miod Exp $ */ +/* $OpenBSD: m_md5.c,v 1.17 2022/01/14 08:38:06 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -71,6 +71,8 @@ #include #endif +#include "evp_locl.h" + static int init(EVP_MD_CTX *ctx) { @@ -99,13 +101,6 @@ static const EVP_MD md5_md = { .final = final, .copy = NULL, .cleanup = NULL, -#ifndef OPENSSL_NO_RSA - .sign = (evp_sign_method *)RSA_sign, - .verify = (evp_verify_method *)RSA_verify, - .required_pkey_type = { - EVP_PKEY_RSA, EVP_PKEY_RSA2, 0, 0, - }, -#endif .block_size = MD5_CBLOCK, .ctx_size = sizeof(EVP_MD *) + sizeof(MD5_CTX), }; diff --git a/crypto/evp/m_md5_sha1.c b/crypto/evp/m_md5_sha1.c index 4e8a0c3..f8bec10 100644 --- a/crypto/evp/m_md5_sha1.c +++ b/crypto/evp/m_md5_sha1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: m_md5_sha1.c,v 1.2 2018/08/10 17:30:29 jsing Exp $ */ +/* $OpenBSD: m_md5_sha1.c,v 1.4 2022/01/14 08:38:06 tb Exp $ */ /* * Copyright (c) 2017 Joel Sing * @@ -24,6 +24,8 @@ #include #endif +#include "evp_locl.h" + struct md5_sha1_ctx { MD5_CTX md5; SHA_CTX sha1; @@ -78,13 +80,6 @@ static const EVP_MD md5_sha1_md = { .final = md5_sha1_final, .block_size = MD5_CBLOCK, /* MD5_CBLOCK == SHA_CBLOCK */ .ctx_size = sizeof(EVP_MD *) + sizeof(struct md5_sha1_ctx), -#ifndef OPENSSL_NO_RSA - .sign = (evp_sign_method *)RSA_sign, - .verify = (evp_verify_method *)RSA_verify, - .required_pkey_type = { - EVP_PKEY_RSA, EVP_PKEY_RSA2, 0, 0, - }, -#endif }; const EVP_MD * diff --git a/crypto/evp/m_null.c b/crypto/evp/m_null.c index 897be3c..4334dec 100644 --- a/crypto/evp/m_null.c +++ b/crypto/evp/m_null.c @@ -1,4 +1,4 @@ -/* $OpenBSD: m_null.c,v 1.9 2014/07/11 08:44:48 jsing Exp $ */ +/* $OpenBSD: m_null.c,v 1.11 2022/01/14 08:38:06 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -62,6 +62,8 @@ #include #include +#include "evp_locl.h" + static int init(EVP_MD_CTX *ctx) { @@ -90,11 +92,6 @@ static const EVP_MD null_md = { .final = final, .copy = NULL, .cleanup = NULL, - .sign = NULL, - .verify = NULL, - .required_pkey_type = { - 0, 0, 0, 0, - }, .block_size = 0, .ctx_size = sizeof(EVP_MD *), }; diff --git a/crypto/evp/m_ripemd.c b/crypto/evp/m_ripemd.c index be7f139..4739783 100644 --- a/crypto/evp/m_ripemd.c +++ b/crypto/evp/m_ripemd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: m_ripemd.c,v 1.12 2014/07/13 09:30:02 miod Exp $ */ +/* $OpenBSD: m_ripemd.c,v 1.14 2022/01/14 08:38:06 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -71,6 +71,8 @@ #include #endif +#include "evp_locl.h" + static int init(EVP_MD_CTX *ctx) { @@ -99,13 +101,6 @@ static const EVP_MD ripemd160_md = { .final = final, .copy = NULL, .cleanup = NULL, -#ifndef OPENSSL_NO_RSA - .sign = (evp_sign_method *)RSA_sign, - .verify = (evp_verify_method *)RSA_verify, - .required_pkey_type = { - EVP_PKEY_RSA, EVP_PKEY_RSA2, 0, 0, - }, -#endif .block_size = RIPEMD160_CBLOCK, .ctx_size = sizeof(EVP_MD *) + sizeof(RIPEMD160_CTX), }; diff --git a/crypto/evp/m_sha1.c b/crypto/evp/m_sha1.c index 13d5b03..a6fb536 100644 --- a/crypto/evp/m_sha1.c +++ b/crypto/evp/m_sha1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: m_sha1.c,v 1.17 2014/07/11 08:44:48 jsing Exp $ */ +/* $OpenBSD: m_sha1.c,v 1.19 2022/01/14 08:38:06 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -70,6 +70,8 @@ #include #endif +#include "evp_locl.h" + static int init(EVP_MD_CTX *ctx) { @@ -92,19 +94,12 @@ static const EVP_MD sha1_md = { .type = NID_sha1, .pkey_type = NID_sha1WithRSAEncryption, .md_size = SHA_DIGEST_LENGTH, - .flags = EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT, + .flags = EVP_MD_FLAG_DIGALGID_ABSENT, .init = init, .update = update, .final = final, .copy = NULL, .cleanup = NULL, -#ifndef OPENSSL_NO_RSA - .sign = (evp_sign_method *)RSA_sign, - .verify = (evp_verify_method *)RSA_verify, - .required_pkey_type = { - EVP_PKEY_RSA, EVP_PKEY_RSA2, 0, 0, - }, -#endif .block_size = SHA_CBLOCK, .ctx_size = sizeof(EVP_MD *) + sizeof(SHA_CTX), }; @@ -149,19 +144,12 @@ static const EVP_MD sha224_md = { .type = NID_sha224, .pkey_type = NID_sha224WithRSAEncryption, .md_size = SHA224_DIGEST_LENGTH, - .flags = EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT, + .flags = EVP_MD_FLAG_DIGALGID_ABSENT, .init = init224, .update = update256, .final = final256, .copy = NULL, .cleanup = NULL, -#ifndef OPENSSL_NO_RSA - .sign = (evp_sign_method *)RSA_sign, - .verify = (evp_verify_method *)RSA_verify, - .required_pkey_type = { - EVP_PKEY_RSA, EVP_PKEY_RSA2, 0, 0, - }, -#endif .block_size = SHA256_CBLOCK, .ctx_size = sizeof(EVP_MD *) + sizeof(SHA256_CTX), }; @@ -176,19 +164,12 @@ static const EVP_MD sha256_md = { .type = NID_sha256, .pkey_type = NID_sha256WithRSAEncryption, .md_size = SHA256_DIGEST_LENGTH, - .flags = EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT, + .flags = EVP_MD_FLAG_DIGALGID_ABSENT, .init = init256, .update = update256, .final = final256, .copy = NULL, .cleanup = NULL, -#ifndef OPENSSL_NO_RSA - .sign = (evp_sign_method *)RSA_sign, - .verify = (evp_verify_method *)RSA_verify, - .required_pkey_type = { - EVP_PKEY_RSA, EVP_PKEY_RSA2, 0, 0, - }, -#endif .block_size = SHA256_CBLOCK, .ctx_size = sizeof(EVP_MD *) + sizeof(SHA256_CTX), }; @@ -229,19 +210,12 @@ static const EVP_MD sha384_md = { .type = NID_sha384, .pkey_type = NID_sha384WithRSAEncryption, .md_size = SHA384_DIGEST_LENGTH, - .flags = EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT, + .flags = EVP_MD_FLAG_DIGALGID_ABSENT, .init = init384, .update = update512, .final = final512, .copy = NULL, .cleanup = NULL, -#ifndef OPENSSL_NO_RSA - .sign = (evp_sign_method *)RSA_sign, - .verify = (evp_verify_method *)RSA_verify, - .required_pkey_type = { - EVP_PKEY_RSA, EVP_PKEY_RSA2, 0, 0, - }, -#endif .block_size = SHA512_CBLOCK, .ctx_size = sizeof(EVP_MD *) + sizeof(SHA512_CTX), }; @@ -256,19 +230,12 @@ static const EVP_MD sha512_md = { .type = NID_sha512, .pkey_type = NID_sha512WithRSAEncryption, .md_size = SHA512_DIGEST_LENGTH, - .flags = EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT, + .flags = EVP_MD_FLAG_DIGALGID_ABSENT, .init = init512, .update = update512, .final = final512, .copy = NULL, .cleanup = NULL, -#ifndef OPENSSL_NO_RSA - .sign = (evp_sign_method *)RSA_sign, - .verify = (evp_verify_method *)RSA_verify, - .required_pkey_type = { - EVP_PKEY_RSA, EVP_PKEY_RSA2, 0, 0, - }, -#endif .block_size = SHA512_CBLOCK, .ctx_size = sizeof(EVP_MD *) + sizeof(SHA512_CTX), }; diff --git a/crypto/evp/m_sm3.c b/crypto/evp/m_sm3.c index 66582b8..ae8b342 100644 --- a/crypto/evp/m_sm3.c +++ b/crypto/evp/m_sm3.c @@ -1,4 +1,4 @@ -/* $OpenBSD: m_sm3.c,v 1.1 2018/11/11 06:53:31 tb Exp $ */ +/* $OpenBSD: m_sm3.c,v 1.3 2022/01/14 08:38:06 tb Exp $ */ /* * Copyright (c) 2018, Ribose Inc * @@ -25,6 +25,8 @@ #include #endif +#include "evp_locl.h" + static int sm3_init(EVP_MD_CTX *ctx) { @@ -47,19 +49,12 @@ static const EVP_MD sm3_md = { .type = NID_sm3, .pkey_type = NID_sm3WithRSAEncryption, .md_size = SM3_DIGEST_LENGTH, - .flags = EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT, + .flags = EVP_MD_FLAG_DIGALGID_ABSENT, .init = sm3_init, .update = sm3_update, .final = sm3_final, .copy = NULL, .cleanup = NULL, -#ifndef OPENSSL_NO_RSA - .sign = (evp_sign_method *)RSA_sign, - .verify = (evp_verify_method *)RSA_verify, - .required_pkey_type = { - EVP_PKEY_RSA, EVP_PKEY_RSA2, 0, 0, - }, -#endif .block_size = SM3_CBLOCK, .ctx_size = sizeof(EVP_MD *) + sizeof(SM3_CTX), }; diff --git a/crypto/evp/m_streebog.c b/crypto/evp/m_streebog.c index 882c785..3f825e3 100644 --- a/crypto/evp/m_streebog.c +++ b/crypto/evp/m_streebog.c @@ -1,4 +1,4 @@ -/* $OpenBSD: m_streebog.c,v 1.2 2014/11/09 23:06:50 miod Exp $ */ +/* $OpenBSD: m_streebog.c,v 1.4 2022/01/14 08:38:06 tb Exp $ */ /* * Copyright (c) 2014 Dmitry Eremin-Solenikov * Copyright (c) 2005-2006 Cryptocom LTD @@ -57,6 +57,8 @@ #include #include +#include "evp_locl.h" + static int streebog_init256(EVP_MD_CTX *ctx) { @@ -97,7 +99,7 @@ static const EVP_MD streebog256_md = { .type = NID_id_tc26_gost3411_2012_256, .pkey_type = NID_undef, .md_size = STREEBOG256_LENGTH, - .flags = EVP_MD_FLAG_PKEY_METHOD_SIGNATURE, + .flags = 0, .init = streebog_init256, .update = streebog_update256, .final = streebog_final256, @@ -109,7 +111,7 @@ static const EVP_MD streebog512_md = { .type = NID_id_tc26_gost3411_2012_512, .pkey_type = NID_undef, .md_size = STREEBOG512_LENGTH, - .flags = EVP_MD_FLAG_PKEY_METHOD_SIGNATURE, + .flags = 0, .init = streebog_init512, .update = streebog_update512, .final = streebog_final512, diff --git a/crypto/evp/m_wp.c b/crypto/evp/m_wp.c index 3f543ac..07ae7ca 100644 --- a/crypto/evp/m_wp.c +++ b/crypto/evp/m_wp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: m_wp.c,v 1.8 2014/07/13 09:30:02 miod Exp $ */ +/* $OpenBSD: m_wp.c,v 1.10 2022/01/14 08:38:06 tb Exp $ */ #include @@ -11,6 +11,8 @@ #include #include +#include "evp_locl.h" + static int init(EVP_MD_CTX *ctx) { @@ -39,11 +41,6 @@ static const EVP_MD whirlpool_md = { .final = final, .copy = NULL, .cleanup = NULL, - .sign = NULL, - .verify = NULL, - .required_pkey_type = { - 0, 0, 0, 0, - }, .block_size = WHIRLPOOL_BBLOCK / 8, .ctx_size = sizeof(EVP_MD *) + sizeof(WHIRLPOOL_CTX), }; diff --git a/crypto/evp/names.c b/crypto/evp/names.c index dfcf9ee..02529ee 100644 --- a/crypto/evp/names.c +++ b/crypto/evp/names.c @@ -1,4 +1,4 @@ -/* $OpenBSD: names.c,v 1.14 2018/03/17 16:20:01 beck Exp $ */ +/* $OpenBSD: names.c,v 1.15 2021/12/12 21:30:13 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -62,6 +62,8 @@ #include #include +#include "evp_locl.h" + int EVP_add_cipher(const EVP_CIPHER *c) { diff --git a/crypto/evp/p5_crpt.c b/crypto/evp/p5_crpt.c index 98e4549..b9482e0 100644 --- a/crypto/evp/p5_crpt.c +++ b/crypto/evp/p5_crpt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: p5_crpt.c,v 1.19 2020/01/12 07:11:13 inoguchi Exp $ */ +/* $OpenBSD: p5_crpt.c,v 1.20 2021/12/12 21:30:13 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -64,6 +64,8 @@ #include #include +#include "evp_locl.h" + /* Doesn't do anything now: Builtin PBE algorithms in static table. */ diff --git a/crypto/evp/p5_crpt2.c b/crypto/evp/p5_crpt2.c index 4bef287..f3585ff 100644 --- a/crypto/evp/p5_crpt2.c +++ b/crypto/evp/p5_crpt2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: p5_crpt2.c,v 1.23 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: p5_crpt2.c,v 1.24 2021/12/12 21:27:37 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -70,6 +70,7 @@ #include #include "evp_locl.h" +#include "hmac_local.h" /* This is an implementation of PKCS#5 v2.0 password based encryption key * derivation function PBKDF2. diff --git a/crypto/evp/p_dec.c b/crypto/evp/p_dec.c index c827c5e..c19cc65 100644 --- a/crypto/evp/p_dec.c +++ b/crypto/evp/p_dec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: p_dec.c,v 1.11 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: p_dec.c,v 1.12 2021/12/12 21:30:13 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -69,6 +69,8 @@ #include #endif +#include "evp_locl.h" + int EVP_PKEY_decrypt_old(unsigned char *key, const unsigned char *ek, int ekl, EVP_PKEY *priv) diff --git a/crypto/evp/p_enc.c b/crypto/evp/p_enc.c index 49c46f1..5553429 100644 --- a/crypto/evp/p_enc.c +++ b/crypto/evp/p_enc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: p_enc.c,v 1.11 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: p_enc.c,v 1.12 2021/12/12 21:30:13 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -69,6 +69,8 @@ #include #endif +#include "evp_locl.h" + int EVP_PKEY_encrypt_old(unsigned char *ek, const unsigned char *key, int key_len, EVP_PKEY *pubk) diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index 9577b10..cdd38e4 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: p_lib.c,v 1.26 2021/03/29 15:57:23 tb Exp $ */ +/* $OpenBSD: p_lib.c,v 1.28 2022/01/20 11:06:24 inoguchi Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -82,6 +82,7 @@ #endif #include "asn1_locl.h" +#include "evp_locl.h" static void EVP_PKEY_free_it(EVP_PKEY *x); @@ -525,7 +526,8 @@ EVP_PKEY_free_it(EVP_PKEY *x) static int unsup_alg(BIO *out, const EVP_PKEY *pkey, int indent, const char *kstr) { - BIO_indent(out, indent, 128); + if (!BIO_indent(out, indent, 128)) + return 0; BIO_printf(out, "%s algorithm \"%s\" unsupported\n", kstr, OBJ_nid2ln(pkey->type)); return 1; diff --git a/crypto/evp/p_open.c b/crypto/evp/p_open.c index 57a4670..e4c59e6 100644 --- a/crypto/evp/p_open.c +++ b/crypto/evp/p_open.c @@ -1,4 +1,4 @@ -/* $OpenBSD: p_open.c,v 1.19 2017/05/02 03:59:44 deraadt Exp $ */ +/* $OpenBSD: p_open.c,v 1.20 2021/12/12 21:30:13 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -69,6 +69,8 @@ #include #include +#include "evp_locl.h" + int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, const unsigned char *ek, int ekl, const unsigned char *iv, EVP_PKEY *priv) diff --git a/crypto/evp/p_sign.c b/crypto/evp/p_sign.c index 6312924..1e33cfb 100644 --- a/crypto/evp/p_sign.c +++ b/crypto/evp/p_sign.c @@ -1,4 +1,4 @@ -/* $OpenBSD: p_sign.c,v 1.14 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: p_sign.c,v 1.16 2022/01/14 08:38:06 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -63,15 +63,18 @@ #include #include +#include "evp_locl.h" + int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, unsigned int *siglen, EVP_PKEY *pkey) { unsigned char m[EVP_MAX_MD_SIZE]; unsigned int m_len; - int i = 0, ok = 0, v; EVP_MD_CTX tmp_ctx; EVP_PKEY_CTX *pkctx = NULL; + size_t sltmp; + int ret = 0; *siglen = 0; EVP_MD_CTX_init(&tmp_ctx); @@ -81,43 +84,21 @@ EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, unsigned int *siglen, goto err; EVP_MD_CTX_cleanup(&tmp_ctx); - if (ctx->digest->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) { - size_t sltmp = (size_t)EVP_PKEY_size(pkey); - i = 0; - pkctx = EVP_PKEY_CTX_new(pkey, NULL); - if (!pkctx) - goto err; - if (EVP_PKEY_sign_init(pkctx) <= 0) - goto err; - if (EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest) <= 0) - goto err; - if (EVP_PKEY_sign(pkctx, sigret, &sltmp, m, m_len) <= 0) - goto err; - *siglen = sltmp; - i = 1; -err: - EVP_PKEY_CTX_free(pkctx); - return i; - } + sltmp = (size_t)EVP_PKEY_size(pkey); - for (i = 0; i < 4; i++) { - v = ctx->digest->required_pkey_type[i]; - if (v == 0) - break; - if (pkey->type == v) { - ok = 1; - break; - } - } - if (!ok) { - EVPerror(EVP_R_WRONG_PUBLIC_KEY_TYPE); - return (0); - } + if ((pkctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) + goto err; + if (EVP_PKEY_sign_init(pkctx) <= 0) + goto err; + if (EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest) <= 0) + goto err; + if (EVP_PKEY_sign(pkctx, sigret, &sltmp, m, m_len) <= 0) + goto err; + *siglen = sltmp; - if (ctx->digest->sign == NULL) { - EVPerror(EVP_R_NO_SIGN_FUNCTION_CONFIGURED); - return (0); - } - return(ctx->digest->sign(ctx->digest->type, m, m_len, sigret, siglen, - pkey->pkey.ptr)); + ret = 1; + + err: + EVP_PKEY_CTX_free(pkctx); + return ret; } diff --git a/crypto/evp/p_verify.c b/crypto/evp/p_verify.c index 7dd752c..d51d1b4 100644 --- a/crypto/evp/p_verify.c +++ b/crypto/evp/p_verify.c @@ -1,4 +1,4 @@ -/* $OpenBSD: p_verify.c,v 1.13 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: p_verify.c,v 1.15 2022/01/14 08:38:06 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -63,15 +63,17 @@ #include #include +#include "evp_locl.h" + int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf, unsigned int siglen, EVP_PKEY *pkey) { unsigned char m[EVP_MAX_MD_SIZE]; unsigned int m_len; - int i = 0, ok = 0, v; EVP_MD_CTX tmp_ctx; EVP_PKEY_CTX *pkctx = NULL; + int ret = 0; EVP_MD_CTX_init(&tmp_ctx); if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx)) @@ -80,39 +82,16 @@ EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf, goto err; EVP_MD_CTX_cleanup(&tmp_ctx); - if (ctx->digest->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) { - i = -1; - pkctx = EVP_PKEY_CTX_new(pkey, NULL); - if (!pkctx) - goto err; - if (EVP_PKEY_verify_init(pkctx) <= 0) - goto err; - if (EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest) <= 0) - goto err; - i = EVP_PKEY_verify(pkctx, sigbuf, siglen, m, m_len); -err: - EVP_PKEY_CTX_free(pkctx); - return i; - } + ret = -1; + if ((pkctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) + goto err; + if (EVP_PKEY_verify_init(pkctx) <= 0) + goto err; + if (EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest) <= 0) + goto err; + ret = EVP_PKEY_verify(pkctx, sigbuf, siglen, m, m_len); - for (i = 0; i < 4; i++) { - v = ctx->digest->required_pkey_type[i]; - if (v == 0) - break; - if (pkey->type == v) { - ok = 1; - break; - } - } - if (!ok) { - EVPerror(EVP_R_WRONG_PUBLIC_KEY_TYPE); - return (-1); - } - if (ctx->digest->verify == NULL) { - EVPerror(EVP_R_NO_VERIFY_FUNCTION_CONFIGURED); - return (0); - } - - return(ctx->digest->verify(ctx->digest->type, m, m_len, - sigbuf, siglen, pkey->pkey.ptr)); + err: + EVP_PKEY_CTX_free(pkctx); + return ret; } diff --git a/crypto/evp/pmeth_gn.c b/crypto/evp/pmeth_gn.c index d1cbdc4..7d921d2 100644 --- a/crypto/evp/pmeth_gn.c +++ b/crypto/evp/pmeth_gn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmeth_gn.c,v 1.6 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: pmeth_gn.c,v 1.10 2022/01/10 12:10:26 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2006. */ @@ -64,6 +64,8 @@ #include #include +#include "asn1_locl.h" +#include "bn_lcl.h" #include "evp_locl.h" int @@ -187,7 +189,7 @@ trans_cb(int a, int b, BN_GENCB *gcb) void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx) { - BN_GENCB_set(cb, trans_cb, ctx) + BN_GENCB_set(cb, trans_cb, ctx); } int @@ -221,3 +223,66 @@ merr: EVP_PKEY_CTX_free(mac_ctx); return mac_key; } + +int +EVP_PKEY_check(EVP_PKEY_CTX *ctx) +{ + EVP_PKEY *pkey; + + if ((pkey = ctx->pkey) == NULL) { + EVPerror(EVP_R_NO_KEY_SET); + return 0; + } + + if (ctx->pmeth->check != NULL) + return ctx->pmeth->check(pkey); + + if (pkey->ameth == NULL || pkey->ameth->pkey_check == NULL) { + EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + + return pkey->ameth->pkey_check(pkey); +} + +int +EVP_PKEY_public_check(EVP_PKEY_CTX *ctx) +{ + EVP_PKEY *pkey; + + if ((pkey = ctx->pkey) == NULL) { + EVPerror(EVP_R_NO_KEY_SET); + return 0; + } + + if (ctx->pmeth->public_check != NULL) + return ctx->pmeth->public_check(pkey); + + if (pkey->ameth == NULL || pkey->ameth->pkey_public_check == NULL) { + EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + + return pkey->ameth->pkey_public_check(pkey); +} + +int +EVP_PKEY_param_check(EVP_PKEY_CTX *ctx) +{ + EVP_PKEY *pkey; + + if ((pkey = ctx->pkey) == NULL) { + EVPerror(EVP_R_NO_KEY_SET); + return 0; + } + + if (ctx->pmeth->param_check != NULL) + return ctx->pmeth->param_check(pkey); + + if (pkey->ameth == NULL || pkey->ameth->pkey_param_check == NULL) { + EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + + return pkey->ameth->pkey_param_check(pkey); +} diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 36bfe8d..d265e2a 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmeth_lib.c,v 1.16 2019/11/01 15:08:57 jsing Exp $ */ +/* $OpenBSD: pmeth_lib.c,v 1.20 2022/01/10 12:10:26 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2006. */ @@ -224,39 +224,12 @@ EVP_PKEY_meth_new(int id, int flags) { EVP_PKEY_METHOD *pmeth; - pmeth = calloc(1, sizeof(EVP_PKEY_METHOD)); - if (!pmeth) + if ((pmeth = calloc(1, sizeof(EVP_PKEY_METHOD))) == NULL) return NULL; pmeth->pkey_id = id; pmeth->flags = flags | EVP_PKEY_FLAG_DYNAMIC; - pmeth->init = 0; - pmeth->copy = 0; - pmeth->cleanup = 0; - pmeth->paramgen_init = 0; - pmeth->paramgen = 0; - pmeth->keygen_init = 0; - pmeth->keygen = 0; - pmeth->sign_init = 0; - pmeth->sign = 0; - pmeth->verify_init = 0; - pmeth->verify = 0; - pmeth->verify_recover_init = 0; - pmeth->verify_recover = 0; - pmeth->signctx_init = 0; - pmeth->signctx = 0; - pmeth->verifyctx_init = 0; - pmeth->verifyctx = 0; - pmeth->encrypt_init = 0; - pmeth->encrypt = 0; - pmeth->decrypt_init = 0; - pmeth->decrypt = 0; - pmeth->derive_init = 0; - pmeth->derive = 0; - pmeth->ctrl = 0; - pmeth->ctrl_str = 0; - return pmeth; } @@ -272,42 +245,15 @@ EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags, const EVP_PKEY_METHOD *meth) void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src) { - dst->init = src->init; - dst->copy = src->copy; - dst->cleanup = src->cleanup; + EVP_PKEY_METHOD preserve; - dst->paramgen_init = src->paramgen_init; - dst->paramgen = src->paramgen; + preserve.pkey_id = dst->pkey_id; + preserve.flags = dst->flags; - dst->keygen_init = src->keygen_init; - dst->keygen = src->keygen; + *dst = *src; - dst->sign_init = src->sign_init; - dst->sign = src->sign; - - dst->verify_init = src->verify_init; - dst->verify = src->verify; - - dst->verify_recover_init = src->verify_recover_init; - dst->verify_recover = src->verify_recover; - - dst->signctx_init = src->signctx_init; - dst->signctx = src->signctx; - - dst->verifyctx_init = src->verifyctx_init; - dst->verifyctx = src->verifyctx; - - dst->encrypt_init = src->encrypt_init; - dst->encrypt = src->encrypt; - - dst->decrypt_init = src->decrypt_init; - dst->decrypt = src->decrypt; - - dst->derive_init = src->derive_init; - dst->derive = src->derive; - - dst->ctrl = src->ctrl; - dst->ctrl_str = src->ctrl_str; + dst->pkey_id = preserve.pkey_id; + dst->flags = preserve.flags; } void @@ -636,3 +582,23 @@ EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth, pmeth->ctrl = ctrl; pmeth->ctrl_str = ctrl_str; } + +void +EVP_PKEY_meth_set_check(EVP_PKEY_METHOD *pmeth, int (*check)(EVP_PKEY *pkey)) +{ + pmeth->check = check; +} + +void +EVP_PKEY_meth_set_public_check(EVP_PKEY_METHOD *pmeth, + int (*public_check)(EVP_PKEY *pkey)) +{ + pmeth->public_check = public_check; +} + +void +EVP_PKEY_meth_set_param_check(EVP_PKEY_METHOD *pmeth, + int (*param_check)(EVP_PKEY *pkey)) +{ + pmeth->param_check = param_check; +} diff --git a/crypto/gost/gost2814789.c b/crypto/gost/gost2814789.c index f1066f2..0841a03 100644 --- a/crypto/gost/gost2814789.c +++ b/crypto/gost/gost2814789.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gost2814789.c,v 1.6 2020/09/12 02:45:05 inoguchi Exp $ */ +/* $OpenBSD: gost2814789.c,v 1.7 2021/11/09 18:40:21 bcook Exp $ */ /* * Copyright (c) 2014 Dmitry Eremin-Solenikov * Copyright (c) 2005-2006 Cryptocom LTD @@ -49,8 +49,7 @@ * ==================================================================== */ -#include - +#include #include #include diff --git a/crypto/gost/gost89imit_ameth.c b/crypto/gost/gost89imit_ameth.c index a2631d9..3fdfa3e 100644 --- a/crypto/gost/gost89imit_ameth.c +++ b/crypto/gost/gost89imit_ameth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gost89imit_ameth.c,v 1.2 2014/11/09 23:06:52 miod Exp $ */ +/* $OpenBSD: gost89imit_ameth.c,v 1.3 2021/12/12 21:30:14 tb Exp $ */ /* * Copyright (c) 2014 Dmitry Eremin-Solenikov * Copyright (c) 2005-2006 Cryptocom LTD @@ -55,6 +55,7 @@ #include #include "asn1_locl.h" +#include "evp_locl.h" static void mackey_free_gost(EVP_PKEY *pk) diff --git a/crypto/gost/gostr341001.c b/crypto/gost/gostr341001.c index bfbd032..a608256 100644 --- a/crypto/gost/gostr341001.c +++ b/crypto/gost/gostr341001.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gostr341001.c,v 1.8 2021/04/20 17:16:38 tb Exp $ */ +/* $OpenBSD: gostr341001.c,v 1.9 2022/01/07 09:40:03 tb Exp $ */ /* * Copyright (c) 2014 Dmitry Eremin-Solenikov * Copyright (c) 2005-2006 Cryptocom LTD @@ -59,6 +59,7 @@ #include #include "bn_lcl.h" +#include "ecs_locl.h" #include "gost_locl.h" /* Convert little-endian byte array into bignum */ diff --git a/crypto/gost/gostr341001_ameth.c b/crypto/gost/gostr341001_ameth.c index 294b654..ce203a6 100644 --- a/crypto/gost/gostr341001_ameth.c +++ b/crypto/gost/gostr341001_ameth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gostr341001_ameth.c,v 1.17 2021/04/20 17:16:38 tb Exp $ */ +/* $OpenBSD: gostr341001_ameth.c,v 1.19 2021/12/26 15:38:49 tb Exp $ */ /* * Copyright (c) 2014 Dmitry Eremin-Solenikov * Copyright (c) 2005-2006 Cryptocom LTD @@ -63,6 +63,7 @@ #include "asn1_locl.h" +#include "evp_locl.h" #include "gost_locl.h" #include "gost_asn1.h" @@ -364,7 +365,8 @@ pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx) BIO_printf(out, "X:"); BN_print(out, X); BIO_printf(out, "\n"); - BIO_indent(out, indent + 3, 128); + if (BIO_indent(out, indent + 3, 128) == 0) + goto err; BIO_printf(out, "Y:"); BN_print(out, Y); BIO_printf(out, "\n"); diff --git a/crypto/gost/gostr341001_pmeth.c b/crypto/gost/gostr341001_pmeth.c index 0eb1d87..ae39b05 100644 --- a/crypto/gost/gostr341001_pmeth.c +++ b/crypto/gost/gostr341001_pmeth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gostr341001_pmeth.c,v 1.14 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: gostr341001_pmeth.c,v 1.16 2022/03/30 07:17:48 tb Exp $ */ /* * Copyright (c) 2014 Dmitry Eremin-Solenikov * Copyright (c) 2005-2006 Cryptocom LTD @@ -62,6 +62,7 @@ #include #include +#include "ecs_locl.h" #include "evp_locl.h" #include "gost_locl.h" #include "gost_asn1.h" @@ -174,7 +175,10 @@ pkey_gost01_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) static void pkey_gost01_cleanup(EVP_PKEY_CTX *ctx) { - struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); + struct gost_pmeth_data *data; + + if ((data = EVP_PKEY_CTX_get_data(ctx)) == NULL) + return; free(data->shared_ukm); free(data); diff --git a/crypto/gost/streebog.c b/crypto/gost/streebog.c index 61bce0e..b237a2c 100644 --- a/crypto/gost/streebog.c +++ b/crypto/gost/streebog.c @@ -1,4 +1,4 @@ -/* $OpenBSD: streebog.c,v 1.6 2019/05/09 22:54:28 tb Exp $ */ +/* $OpenBSD: streebog.c,v 1.7 2021/11/09 18:40:21 bcook Exp $ */ /* * Copyright (c) 2014 Dmitry Eremin-Solenikov * Copyright (c) 2005-2006 Cryptocom LTD @@ -49,8 +49,7 @@ * ==================================================================== */ -#include - +#include #include #include diff --git a/crypto/hkdf/hkdf.c b/crypto/hkdf/hkdf.c index e912481..9adf126 100644 --- a/crypto/hkdf/hkdf.c +++ b/crypto/hkdf/hkdf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hkdf.c,v 1.5 2021/08/27 16:12:33 tb Exp $ */ +/* $OpenBSD: hkdf.c,v 1.7 2021/12/12 21:30:14 tb Exp $ */ /* Copyright (c) 2014, Google Inc. * * Permission to use, copy, modify, and/or distribute this software for any @@ -21,6 +21,9 @@ #include #include +#include "evp_locl.h" +#include "hmac_local.h" + /* https://tools.ietf.org/html/rfc5869#section-2 */ int HKDF(uint8_t *out_key, size_t out_len, const EVP_MD *digest, diff --git a/crypto/hmac/hm_ameth.c b/crypto/hmac/hm_ameth.c index cfa0239..84bb5f0 100644 --- a/crypto/hmac/hm_ameth.c +++ b/crypto/hmac/hm_ameth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hm_ameth.c,v 1.10 2015/09/10 15:56:25 jsing Exp $ */ +/* $OpenBSD: hm_ameth.c,v 1.12 2021/12/12 21:30:14 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2007. */ @@ -60,8 +60,11 @@ #include #include +#include #include "asn1_locl.h" +#include "evp_locl.h" +#include "hmac_local.h" #define HMAC_TEST_PRIVATE_KEY_FORMAT diff --git a/crypto/hmac/hm_pmeth.c b/crypto/hmac/hm_pmeth.c index 390725f..4017f57 100644 --- a/crypto/hmac/hm_pmeth.c +++ b/crypto/hmac/hm_pmeth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hm_pmeth.c,v 1.10 2017/05/02 03:59:44 deraadt Exp $ */ +/* $OpenBSD: hm_pmeth.c,v 1.13 2022/03/30 07:17:48 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2007. */ @@ -65,6 +65,7 @@ #include #include "evp_locl.h" +#include "hmac_local.h" /* HMAC pkey context structure */ @@ -79,13 +80,9 @@ pkey_hmac_init(EVP_PKEY_CTX *ctx) { HMAC_PKEY_CTX *hctx; - hctx = malloc(sizeof(HMAC_PKEY_CTX)); - if (!hctx) + if ((hctx = calloc(1, sizeof(HMAC_PKEY_CTX))) == NULL) return 0; - hctx->md = NULL; - hctx->ktmp.data = NULL; - hctx->ktmp.length = 0; - hctx->ktmp.flags = 0; + hctx->ktmp.type = V_ASN1_OCTET_STRING; HMAC_CTX_init(&hctx->ctx); @@ -119,7 +116,10 @@ pkey_hmac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) static void pkey_hmac_cleanup(EVP_PKEY_CTX *ctx) { - HMAC_PKEY_CTX *hctx = ctx->data; + HMAC_PKEY_CTX *hctx; + + if ((hctx = ctx->data) == NULL) + return; HMAC_CTX_cleanup(&hctx->ctx); freezero(hctx->ktmp.data, hctx->ktmp.length); diff --git a/crypto/hmac/hmac.c b/crypto/hmac/hmac.c index 7bf17ee..5598998 100644 --- a/crypto/hmac/hmac.c +++ b/crypto/hmac/hmac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hmac.c,v 1.25 2018/02/17 14:53:58 jsing Exp $ */ +/* $OpenBSD: hmac.c,v 1.27 2021/12/12 21:30:14 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -63,6 +63,9 @@ #include #include +#include "evp_locl.h" +#include "hmac_local.h" + int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md, ENGINE *impl) diff --git a/crypto/asn1/a_digest.c b/crypto/hmac/hmac_local.h similarity index 85% rename from crypto/asn1/a_digest.c rename to crypto/hmac/hmac_local.h index 5b95adf..5900bc1 100644 --- a/crypto/asn1/a_digest.c +++ b/crypto/hmac/hmac_local.h @@ -1,4 +1,4 @@ -/* $OpenBSD: a_digest.c,v 1.16 2018/04/06 09:19:36 tb Exp $ */ +/* $OpenBSD: hmac_local.h,v 1.3 2022/01/14 08:06:03 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -55,33 +55,29 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +#ifndef HEADER_HMAC_LOCAL_H +#define HEADER_HMAC_LOCAL_H -#include +#include -#include -#include - -#include -#include #include -#include -int -ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn, - unsigned char *md, unsigned int *len) -{ - int i; - unsigned char *str = NULL; +#include "evp_locl.h" - i = ASN1_item_i2d(asn, &str, it); - if (!str) - return (0); +__BEGIN_HIDDEN_DECLS - if (!EVP_Digest(str, i, md, len, type, NULL)) { - free(str); - return (0); - } +struct hmac_ctx_st { + const EVP_MD *md; + EVP_MD_CTX md_ctx; + EVP_MD_CTX i_ctx; + EVP_MD_CTX o_ctx; + unsigned int key_length; + unsigned char key[HMAC_MAX_MD_CBLOCK]; +} /* HMAC_CTX */; - free(str); - return (1); -} +void HMAC_CTX_init(HMAC_CTX *ctx); +void HMAC_CTX_cleanup(HMAC_CTX *ctx); + +__END_HIDDEN_DECLS + +#endif /* !HEADER_HMAC_LOCAL_H */ diff --git a/crypto/md5/md5-masm-x86_64.S b/crypto/md5/md5-masm-x86_64.S index 40019cd..85d0bcb 100644 --- a/crypto/md5/md5-masm-x86_64.S +++ b/crypto/md5/md5-masm-x86_64.S @@ -1,7 +1,7 @@ ; 1 "crypto/md5/md5-masm-x86_64.S.tmp" ; 1 "" 1 ; 1 "" 3 -; 340 "" 3 +; 343 "" 3 ; 1 "" 1 ; 1 "" 2 ; 1 "crypto/md5/md5-masm-x86_64.S.tmp" 2 diff --git a/crypto/modes/cbc128.c b/crypto/modes/cbc128.c index fe45103..c5cf5a6 100644 --- a/crypto/modes/cbc128.c +++ b/crypto/modes/cbc128.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cbc128.c,v 1.4 2015/02/10 09:46:30 miod Exp $ */ +/* $OpenBSD: cbc128.c,v 1.5 2022/01/22 00:45:17 inoguchi Exp $ */ /* ==================================================================== * Copyright (c) 2008 The OpenSSL Project. All rights reserved. * @@ -110,7 +110,7 @@ void CRYPTO_cbc128_encrypt(const unsigned char *in, unsigned char *out, in += 16; out += 16; } - memcpy(ivec,iv,16); + memmove(ivec,iv,16); } void CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out, @@ -148,7 +148,7 @@ void CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out, out += 16; } } - memcpy(ivec,iv,16); + memmove(ivec,iv,16); } else { if (STRICT_ALIGNMENT && ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(size_t) != 0) { diff --git a/crypto/modes/ghash-masm-x86_64.S b/crypto/modes/ghash-masm-x86_64.S index ffdc1b5..09ee8e0 100644 --- a/crypto/modes/ghash-masm-x86_64.S +++ b/crypto/modes/ghash-masm-x86_64.S @@ -1,7 +1,7 @@ ; 1 "crypto/modes/ghash-masm-x86_64.S.tmp" ; 1 "" 1 ; 1 "" 3 -; 340 "" 3 +; 343 "" 3 ; 1 "" 1 ; 1 "" 2 ; 1 "crypto/modes/ghash-masm-x86_64.S.tmp" 2 diff --git a/crypto/modes/modes_lcl.h b/crypto/modes/modes_lcl.h index bfea189..d0126e8 100644 --- a/crypto/modes/modes_lcl.h +++ b/crypto/modes/modes_lcl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: modes_lcl.h,v 1.10 2016/12/21 15:49:29 jsing Exp $ */ +/* $OpenBSD: modes_lcl.h,v 1.11 2021/11/09 18:40:21 bcook Exp $ */ /* ==================================================================== * Copyright (c) 2010 The OpenSSL Project. All rights reserved. * @@ -6,7 +6,7 @@ * ==================================================================== */ -#include +#include #include diff --git a/crypto/modes/xts128.c b/crypto/modes/xts128.c index 0be23d4..2084892 100644 --- a/crypto/modes/xts128.c +++ b/crypto/modes/xts128.c @@ -1,4 +1,4 @@ -/* $OpenBSD: xts128.c,v 1.7 2017/08/13 17:46:24 bcook Exp $ */ +/* $OpenBSD: xts128.c,v 1.8 2021/11/09 18:40:21 bcook Exp $ */ /* ==================================================================== * Copyright (c) 2011 The OpenSSL Project. All rights reserved. * @@ -48,9 +48,10 @@ * ==================================================================== */ -#include #include #include "modes_lcl.h" + +#include #include #ifndef MODES_DEBUG diff --git a/crypto/asn1/asn_pack.c b/crypto/o_fips.c similarity index 64% rename from crypto/asn1/asn_pack.c rename to crypto/o_fips.c index 090beff..b1487e3 100644 --- a/crypto/asn1/asn_pack.c +++ b/crypto/o_fips.c @@ -1,16 +1,16 @@ -/* $OpenBSD: asn_pack.c,v 1.18 2018/10/24 17:57:22 jsing Exp $ */ -/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL - * project 1999. +/* $OpenBSD: o_fips.c,v 1.6 2021/10/23 13:57:00 schwarze Exp $ */ +/* Written by Stephen Henson (steve@openssl.org) for the OpenSSL + * project 2011. */ /* ==================================================================== - * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * Copyright (c) 2011 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. + * 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 @@ -20,12 +20,12 @@ * 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/)" + * 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 - * licensing@OpenSSL.org. + * 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 @@ -34,7 +34,7 @@ * 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/)" + * 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 @@ -56,54 +56,21 @@ * */ -#include - -#include #include -/* Pack an ASN1 object into an ASN1_STRING. */ -ASN1_STRING * -ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct) +#include "cryptlib.h" + +int +FIPS_mode(void) { - ASN1_STRING *octmp; - - if (!oct || !*oct) { - if (!(octmp = ASN1_STRING_new ())) { - ASN1error(ERR_R_MALLOC_FAILURE); - return NULL; - } - } else - octmp = *oct; - - free(octmp->data); - octmp->data = NULL; - - if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) { - ASN1error(ASN1_R_ENCODE_ERROR); - goto err; - } - if (!octmp->data) { - ASN1error(ERR_R_MALLOC_FAILURE); - goto err; - } - if (oct) - *oct = octmp; - return octmp; -err: - if (!oct || octmp != *oct) - ASN1_STRING_free(octmp); - return NULL; + return 0; } -/* Extract an ASN1 object from an ASN1_STRING. */ -void * -ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it) +int +FIPS_mode_set(int r) { - const unsigned char *p; - void *ret; - - p = oct->data; - if (!(ret = ASN1_item_d2i(NULL, &p, oct->length, it))) - ASN1error(ASN1_R_DECODE_ERROR); - return ret; + if (r == 0) + return 1; + CRYPTOerror(CRYPTO_R_FIPS_MODE_NOT_SUPPORTED); + return 0; } diff --git a/crypto/o_time.c b/crypto/o_time.c index 9b2e7e5..3f164c7 100644 --- a/crypto/o_time.c +++ b/crypto/o_time.c @@ -1,4 +1,4 @@ -/* $OpenBSD: o_time.c,v 1.15 2014/06/12 15:49:27 deraadt Exp $ */ +/* $OpenBSD: o_time.c,v 1.16 2021/10/27 09:50:56 beck Exp $ */ /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL * project 2001. */ @@ -72,6 +72,8 @@ static long date_to_julian(int y, int m, int d); static void julian_to_date(long jd, int *y, int *m, int *d); +static int julian_adj(const struct tm *tm, int off_day, long offset_sec, + long *pday, int *psec); int OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec) @@ -131,6 +133,85 @@ OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec) } +int +OPENSSL_gmtime_diff(int *pday, int *psec, const struct tm *from, + const struct tm *to) +{ + int from_sec, to_sec, diff_sec; + long from_jd, to_jd, diff_day; + + if (!julian_adj(from, 0, 0, &from_jd, &from_sec)) + return 0; + if (!julian_adj(to, 0, 0, &to_jd, &to_sec)) + return 0; + diff_day = to_jd - from_jd; + diff_sec = to_sec - from_sec; + /* Adjust differences so both positive or both negative */ + if (diff_day > 0 && diff_sec < 0) { + diff_day--; + diff_sec += SECS_PER_DAY; + } + if (diff_day < 0 && diff_sec > 0) { + diff_day++; + diff_sec -= SECS_PER_DAY; + } + + if (pday) + *pday = (int)diff_day; + if (psec) + *psec = diff_sec; + + return 1; + +} + +/* Convert tm structure and offset into julian day and seconds */ +static int +julian_adj(const struct tm *tm, int off_day, long offset_sec, long *pday, + int *psec) +{ + int time_year, time_month, time_day; + long offset_day, time_jd; + int offset_hms; + + /* split offset into days and day seconds */ + offset_day = offset_sec / SECS_PER_DAY; + /* Avoid sign issues with % operator */ + offset_hms = offset_sec - (offset_day * SECS_PER_DAY); + offset_day += off_day; + /* Add current time seconds to offset */ + offset_hms += tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec; + /* Adjust day seconds if overflow */ + if (offset_hms >= SECS_PER_DAY) { + offset_day++; + offset_hms -= SECS_PER_DAY; + } else if (offset_hms < 0) { + offset_day--; + offset_hms += SECS_PER_DAY; + } + + /* + * Convert date of time structure into a Julian day number. + */ + + time_year = tm->tm_year + 1900; + time_month = tm->tm_mon + 1; + time_day = tm->tm_mday; + + time_jd = date_to_julian(time_year, time_month, time_day); + + /* Work out Julian day of new date */ + time_jd += offset_day; + + if (time_jd < 0) + return 0; + + *pday = time_jd; + *psec = offset_hms; + + return 1; +} + /* Convert date to and from julian day * Uses Fliegel & Van Flandern algorithm */ diff --git a/crypto/o_time.h b/crypto/o_time.h index 8c6301d..064f2cc 100644 --- a/crypto/o_time.h +++ b/crypto/o_time.h @@ -1,4 +1,4 @@ -/* $OpenBSD: o_time.h,v 1.7 2016/12/21 15:49:29 jsing Exp $ */ +/* $OpenBSD: o_time.h,v 1.8 2021/10/27 09:50:56 beck Exp $ */ /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL * project 2001. */ @@ -64,7 +64,8 @@ __BEGIN_HIDDEN_DECLS int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec); +int OPENSSL_gmtime_diff(int *pday, int *psec, const struct tm *from, + const struct tm *to); __END_HIDDEN_DECLS - #endif diff --git a/crypto/objects/obj_dat.c b/crypto/objects/obj_dat.c index db25799..bcb7ee2 100644 --- a/crypto/objects/obj_dat.c +++ b/crypto/objects/obj_dat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: obj_dat.c,v 1.43 2021/09/01 09:42:28 beck Exp $ */ +/* $OpenBSD: obj_dat.c,v 1.49 2022/03/19 17:49:32 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -69,6 +69,8 @@ #include #include +#include "asn1_locl.h" + /* obj_dat.h is generated from objects.h by obj_dat.pl */ #include "obj_dat.h" @@ -456,9 +458,9 @@ OBJ_obj2nid(const ASN1_OBJECT *a) const unsigned int *op; ADDED_OBJ ad, *adp; - if (a == NULL) + if (a == NULL || a->length == 0) return (NID_undef); - if (a->nid != 0) + if (a->nid != NID_undef) return (a->nid); if (added != NULL) { @@ -483,12 +485,7 @@ OBJ_obj2nid(const ASN1_OBJECT *a) ASN1_OBJECT * OBJ_txt2obj(const char *s, int no_name) { - int nid = NID_undef; - ASN1_OBJECT *op = NULL; - unsigned char *buf; - unsigned char *p; - const unsigned char *cp; - int i, j; + int nid; if (!no_name) { if (((nid = OBJ_sn2nid(s)) != NID_undef) || @@ -496,148 +493,16 @@ OBJ_txt2obj(const char *s, int no_name) return OBJ_nid2obj(nid); } - /* Work out size of content octets */ - i = a2d_ASN1_OBJECT(NULL, 0, s, -1); - if (i <= 0) { - /* Don't clear the error */ - /*ERR_clear_error();*/ - return NULL; - } - /* Work out total size */ - j = ASN1_object_size(0, i, V_ASN1_OBJECT); - - if ((buf = malloc(j)) == NULL) - return NULL; - - p = buf; - /* Write out tag+length */ - ASN1_put_object(&p, 0, i, V_ASN1_OBJECT, V_ASN1_UNIVERSAL); - /* Write out contents */ - a2d_ASN1_OBJECT(p, i, s, -1); - - cp = buf; - op = d2i_ASN1_OBJECT(NULL, &cp, j); - free(buf); - return op; + return t2i_ASN1_OBJECT_internal(s); } int -OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name) +OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *aobj, int no_name) { - int i, ret = 0, len, nid, first = 1, use_bn; - BIGNUM *bl = NULL; - unsigned long l; - const unsigned char *p; + if (aobj == NULL || aobj->data == NULL) + return 0; - /* Ensure that, at every state, |buf| is NUL-terminated. */ - if (buf_len > 0) - buf[0] = '\0'; - - if ((a == NULL) || (a->data == NULL)) - goto err; - - if (!no_name && (nid = OBJ_obj2nid(a)) != NID_undef) { - const char *s; - s = OBJ_nid2ln(nid); - if (s == NULL) - s = OBJ_nid2sn(nid); - if (s) { - ret = strlcpy(buf, s, buf_len); - goto out; - } - } - - len = a->length; - p = a->data; - - while (len > 0) { - l = 0; - use_bn = 0; - for (;;) { - unsigned char c = *p++; - len--; - if ((len == 0) && (c & 0x80)) - goto err; - if (use_bn) { - if (!BN_add_word(bl, c & 0x7f)) - goto err; - } else - l |= c & 0x7f; - if (!(c & 0x80)) - break; - if (!use_bn && (l > (ULONG_MAX >> 7L))) { - if (!bl && !(bl = BN_new())) - goto err; - if (!BN_set_word(bl, l)) - goto err; - use_bn = 1; - } - if (use_bn) { - if (!BN_lshift(bl, bl, 7)) - goto err; - } else - l <<= 7L; - } - - if (first) { - first = 0; - if (l >= 80) { - i = 2; - if (use_bn) { - if (!BN_sub_word(bl, 80)) - goto err; - } else - l -= 80; - } else { - i = (int)(l / 40); - l -= (long)(i * 40); - } - if (buf_len > 1) { - *buf++ = i + '0'; - *buf = '\0'; - buf_len--; - } - ret++; - } - - if (use_bn) { - char *bndec; - - bndec = BN_bn2dec(bl); - if (!bndec) - goto err; - i = snprintf(buf, buf_len, ".%s", bndec); - free(bndec); - if (i < 0) - goto err; - if (i >= buf_len) { - buf_len = 0; - } else { - buf += i; - buf_len -= i; - } - ret += i; - } else { - i = snprintf(buf, buf_len, ".%lu", l); - if (i < 0) - goto err; - if (i >= buf_len) { - buf_len = 0; - } else { - buf += i; - buf_len -= i; - } - ret += i; - } - } - - out: - BN_free(bl); - return ret; - - err: - ret = 0; - goto out; + return i2t_ASN1_OBJECT_internal(aobj, buf, buf_len, no_name); } int @@ -814,3 +679,24 @@ OBJ_create(const char *oid, const char *sn, const char *ln) free(buf); return (ok); } + +size_t +OBJ_length(const ASN1_OBJECT *obj) +{ + if (obj == NULL) + return 0; + + if (obj->length < 0) + return 0; + + return obj->length; +} + +const unsigned char * +OBJ_get0_data(const ASN1_OBJECT *obj) +{ + if (obj == NULL) + return NULL; + + return obj->data; +} diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h index 6f50a90..4bfb480 100644 --- a/crypto/objects/obj_dat.h +++ b/crypto/objects/obj_dat.h @@ -62,12 +62,12 @@ * [including the GNU Public Licence.] */ -#define NUM_NID 1016 -#define NUM_SN 1009 -#define NUM_LN 1009 -#define NUM_OBJ 939 +#define NUM_NID 1022 +#define NUM_SN 1015 +#define NUM_LN 1015 +#define NUM_OBJ 945 -static const unsigned char lvalues[6618]={ +static const unsigned char lvalues[6677]={ 0x2A,0x86,0x48,0x86,0xF7,0x0D, /* [ 0] OBJ_rsadsi */ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, /* [ 6] OBJ_pkcs */ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x02, /* [ 13] OBJ_md2 */ @@ -1001,6 +1001,12 @@ static const unsigned char lvalues[6618]={ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x2F,/* [6587] OBJ_id_ct_geofeedCSVwithCRLF */ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x30,/* [6598] OBJ_id_ct_signedChecklist */ 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x1E, /* [6609] OBJ_id_kp_bgpsec_router */ +0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x18, /* [6617] OBJ_tlsfeature */ +0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x31,/* [6625] OBJ_id_ct_ASPA */ +0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x02,/* [6636] OBJ_ct_precert_scts */ +0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x03,/* [6646] OBJ_ct_precert_poison */ +0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x04,/* [6656] OBJ_ct_precert_signer */ +0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x05,/* [6666] OBJ_ct_cert_scts */ }; static const ASN1_OBJECT nid_objs[NUM_NID]={ @@ -2653,6 +2659,16 @@ static const ASN1_OBJECT nid_objs[NUM_NID]={ NID_id_ct_signedChecklist,11,&(lvalues[6598]),0}, {"id-kp-bgpsec-router","BGPsec Router",NID_id_kp_bgpsec_router,8, &(lvalues[6609]),0}, +{"tlsfeature","TLS Feature",NID_tlsfeature,8,&(lvalues[6617]),0}, +{"id-ct-ASPA","id-ct-ASPA",NID_id_ct_ASPA,11,&(lvalues[6625]),0}, +{"ct_precert_scts","CT Precertificate SCTs",NID_ct_precert_scts,10, + &(lvalues[6636]),0}, +{"ct_precert_poison","CT Precertificate Poison",NID_ct_precert_poison, + 10,&(lvalues[6646]),0}, +{"ct_precert_signer","CT Precertificate Signer",NID_ct_precert_signer, + 10,&(lvalues[6656]),0}, +{"ct_cert_scts","CT Certificate SCTs",NID_ct_cert_scts,10, + &(lvalues[6666]),0}, }; static const unsigned int sn_objs[NUM_SN]={ @@ -2955,6 +2971,10 @@ static const unsigned int sn_objs[NUM_SN]={ 884, /* "crossCertificatePair" */ 806, /* "cryptocom" */ 805, /* "cryptopro" */ +1021, /* "ct_cert_scts" */ +1019, /* "ct_precert_poison" */ +1018, /* "ct_precert_scts" */ +1020, /* "ct_precert_signer" */ 500, /* "dITRedirect" */ 451, /* "dNSDomain" */ 495, /* "dSAQuality" */ @@ -3138,6 +3158,7 @@ static const unsigned int sn_objs[NUM_SN]={ 327, /* "id-cmc-statusInfo" */ 331, /* "id-cmc-transactionId" */ 1005, /* "id-cp" */ +1017, /* "id-ct-ASPA" */ 787, /* "id-ct-asciiTextWithCRLF" */ 1013, /* "id-ct-geofeedCSVwithCRLF" */ 1004, /* "id-ct-resourceTaggedAttest" */ @@ -3637,6 +3658,7 @@ static const unsigned int sn_objs[NUM_SN]={ 293, /* "textNotice" */ 133, /* "timeStamping" */ 106, /* "title" */ +1016, /* "tlsfeature" */ 682, /* "tpBasis" */ 375, /* "trustRoot" */ 436, /* "ucl" */ @@ -3679,6 +3701,10 @@ static const unsigned int ln_objs[NUM_LN]={ 285, /* "Biometric Info" */ 179, /* "CA Issuers" */ 785, /* "CA Repository" */ +1021, /* "CT Certificate SCTs" */ +1019, /* "CT Precertificate Poison" */ +1018, /* "CT Precertificate SCTs" */ +1020, /* "CT Precertificate Signer" */ 131, /* "Code Signing" */ 783, /* "Diffie-Hellman based MAC" */ 382, /* "Directory" */ @@ -3798,6 +3824,7 @@ static const unsigned int ln_objs[NUM_LN]={ 1011, /* "Signed Object" */ 143, /* "Strong Extranet ID" */ 398, /* "Subject Information Access" */ +1016, /* "TLS Feature" */ 130, /* "TLS Web Client Authentication" */ 129, /* "TLS Web Server Authentication" */ 133, /* "Time Stamping" */ @@ -4148,6 +4175,7 @@ static const unsigned int ln_objs[NUM_LN]={ 327, /* "id-cmc-statusInfo" */ 331, /* "id-cmc-transactionId" */ 1005, /* "id-cp" */ +1017, /* "id-ct-ASPA" */ 787, /* "id-ct-asciiTextWithCRLF" */ 1013, /* "id-ct-geofeedCSVwithCRLF" */ 1004, /* "id-ct-resourceTaggedAttest" */ @@ -5209,6 +5237,7 @@ static const unsigned int obj_objs[NUM_OBJ]={ 397, /* OBJ_ac_proxying 1 3 6 1 5 5 7 1 10 */ 398, /* OBJ_sinfo_access 1 3 6 1 5 5 7 1 11 */ 663, /* OBJ_proxyCertInfo 1 3 6 1 5 5 7 1 14 */ +1016, /* OBJ_tlsfeature 1 3 6 1 5 5 7 1 24 */ 1006, /* OBJ_sbgp_ipAddrBlockv2 1 3 6 1 5 5 7 1 28 */ 1007, /* OBJ_sbgp_autonomousSysNumv2 1 3 6 1 5 5 7 1 29 */ 164, /* OBJ_id_qt_cps 1 3 6 1 5 5 7 2 1 */ @@ -5532,6 +5561,10 @@ static const unsigned int obj_objs[NUM_OBJ]={ 138, /* OBJ_ms_efs 1 3 6 1 4 1 311 10 3 4 */ 648, /* OBJ_ms_smartcard_login 1 3 6 1 4 1 311 20 2 2 */ 649, /* OBJ_ms_upn 1 3 6 1 4 1 311 20 2 3 */ +1018, /* OBJ_ct_precert_scts 1 3 6 1 4 1 11129 2 4 2 */ +1019, /* OBJ_ct_precert_poison 1 3 6 1 4 1 11129 2 4 3 */ +1020, /* OBJ_ct_precert_signer 1 3 6 1 4 1 11129 2 4 4 */ +1021, /* OBJ_ct_cert_scts 1 3 6 1 4 1 11129 2 4 5 */ 751, /* OBJ_camellia_128_cbc 1 2 392 200011 61 1 1 1 2 */ 752, /* OBJ_camellia_192_cbc 1 2 392 200011 61 1 1 1 3 */ 753, /* OBJ_camellia_256_cbc 1 2 392 200011 61 1 1 1 4 */ @@ -5562,6 +5595,7 @@ static const unsigned int obj_objs[NUM_OBJ]={ 1004, /* OBJ_id_ct_resourceTaggedAttest 1 2 840 113549 1 9 16 1 36 */ 1013, /* OBJ_id_ct_geofeedCSVwithCRLF 1 2 840 113549 1 9 16 1 47 */ 1014, /* OBJ_id_ct_signedChecklist 1 2 840 113549 1 9 16 1 48 */ +1017, /* OBJ_id_ct_ASPA 1 2 840 113549 1 9 16 1 49 */ 212, /* OBJ_id_smime_aa_receiptRequest 1 2 840 113549 1 9 16 2 1 */ 213, /* OBJ_id_smime_aa_securityLabel 1 2 840 113549 1 9 16 2 2 */ 214, /* OBJ_id_smime_aa_mlExpandHistory 1 2 840 113549 1 9 16 2 3 */ diff --git a/crypto/objects/obj_lib.c b/crypto/objects/obj_lib.c index 5327a0c..39cd412 100644 --- a/crypto/objects/obj_lib.c +++ b/crypto/objects/obj_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: obj_lib.c,v 1.15 2018/09/08 10:31:24 tb Exp $ */ +/* $OpenBSD: obj_lib.c,v 1.16 2022/01/07 11:13:54 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -64,6 +64,8 @@ #include #include +#include "asn1_locl.h" + ASN1_OBJECT * OBJ_dup(const ASN1_OBJECT *o) { diff --git a/crypto/ocsp/ocsp_asn.c b/crypto/ocsp/ocsp_asn.c index bb58ca7..3f00fca 100644 --- a/crypto/ocsp/ocsp_asn.c +++ b/crypto/ocsp/ocsp_asn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ocsp_asn.c,v 1.9 2016/11/04 18:35:30 jsing Exp $ */ +/* $OpenBSD: ocsp_asn.c,v 1.10 2022/01/07 09:45:52 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ @@ -59,6 +59,8 @@ #include #include +#include "ocsp_local.h" + static const ASN1_TEMPLATE OCSP_SIGNATURE_seq_tt[] = { { .flags = 0, diff --git a/crypto/ocsp/ocsp_cl.c b/crypto/ocsp/ocsp_cl.c index cb5a2f3..bcc484c 100644 --- a/crypto/ocsp/ocsp_cl.c +++ b/crypto/ocsp/ocsp_cl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ocsp_cl.c,v 1.17 2020/10/09 17:19:35 tb Exp $ */ +/* $OpenBSD: ocsp_cl.c,v 1.21 2022/01/07 09:45:52 tb Exp $ */ /* Written by Tom Titchener for the OpenSSL * project. */ @@ -71,6 +71,8 @@ #include #include +#include "ocsp_local.h" + /* Utility functions related to sending OCSP requests and extracting * relevant information from the response. */ @@ -86,7 +88,7 @@ OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid) if ((one = OCSP_ONEREQ_new()) == NULL) goto err; if (req != NULL) { - if (!sk_OCSP_ONEREQ_push(req->tbsRequest->requestList, one)) + if (!sk_OCSP_ONEREQ_push(req->tbsRequest->requestList, one)) goto err; } OCSP_CERTID_free(one->reqCert); @@ -136,7 +138,7 @@ OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert) if (!sk_X509_push(sig->certs, cert)) return 0; - CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(cert); return 1; } @@ -233,6 +235,55 @@ OCSP_resp_get0(OCSP_BASICRESP *bs, int idx) return sk_OCSP_SINGLERESP_value(bs->tbsResponseData->responses, idx); } +const ASN1_GENERALIZEDTIME * +OCSP_resp_get0_produced_at(const OCSP_BASICRESP *bs) +{ + return bs->tbsResponseData->producedAt; +} + +const STACK_OF(X509) * +OCSP_resp_get0_certs(const OCSP_BASICRESP *bs) +{ + return bs->certs; +} + +int +OCSP_resp_get0_id(const OCSP_BASICRESP *bs, const ASN1_OCTET_STRING **pid, + const X509_NAME **pname) +{ + const OCSP_RESPID *rid = bs->tbsResponseData->responderId; + + if (rid->type == V_OCSP_RESPID_NAME) { + *pname = rid->value.byName; + *pid = NULL; + } else if (rid->type == V_OCSP_RESPID_KEY) { + *pid = rid->value.byKey; + *pname = NULL; + } else { + return 0; + } + + return 1; +} + +const ASN1_OCTET_STRING * +OCSP_resp_get0_signature(const OCSP_BASICRESP *bs) +{ + return bs->signature; +} + +const X509_ALGOR * +OCSP_resp_get0_tbs_sigalg(const OCSP_BASICRESP *bs) +{ + return bs->signatureAlgorithm; +} + +const OCSP_RESPDATA * +OCSP_resp_get0_respdata(const OCSP_BASICRESP *bs) +{ + return bs->tbsResponseData; +} + /* Look single response matching a given certificate ID */ int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last) diff --git a/crypto/ocsp/ocsp_ext.c b/crypto/ocsp/ocsp_ext.c index eb51cfb..1400ad7 100644 --- a/crypto/ocsp/ocsp_ext.c +++ b/crypto/ocsp/ocsp_ext.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ocsp_ext.c,v 1.18 2018/05/14 23:47:10 tb Exp $ */ +/* $OpenBSD: ocsp_ext.c,v 1.20 2022/01/07 09:45:52 tb Exp $ */ /* Written by Tom Titchener for the OpenSSL * project. */ @@ -70,6 +70,9 @@ #include #include +#include "ocsp_local.h" +#include "x509_lcl.h" + /* Standard wrapper functions for extensions */ /* OCSP request extensions */ diff --git a/crypto/ocsp/ocsp_lib.c b/crypto/ocsp/ocsp_lib.c index 53d5160..09bccc0 100644 --- a/crypto/ocsp/ocsp_lib.c +++ b/crypto/ocsp/ocsp_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ocsp_lib.c,v 1.23 2018/08/24 20:03:21 tb Exp $ */ +/* $OpenBSD: ocsp_lib.c,v 1.25 2022/01/22 00:31:23 inoguchi Exp $ */ /* Written by Tom Titchener for the OpenSSL * project. */ @@ -74,6 +74,8 @@ #include #include +#include "ocsp_local.h" + /* Convert a certificate and its issuer to an OCSP_CERTID */ OCSP_CERTID * @@ -94,7 +96,9 @@ OCSP_cert_to_id(const EVP_MD *dgst, const X509 *subject, const X509 *issuer) iname = X509_get_subject_name(issuer); serial = NULL; } - ikey = X509_get0_pubkey_bitstr(issuer); + if ((ikey = X509_get0_pubkey_bitstr(issuer)) == NULL) + return NULL; + return OCSP_cert_id_new(dgst, iname, ikey, serial); } diff --git a/crypto/ocsp/ocsp_local.h b/crypto/ocsp/ocsp_local.h new file mode 100644 index 0000000..bd933b1 --- /dev/null +++ b/crypto/ocsp/ocsp_local.h @@ -0,0 +1,291 @@ +/* $OpenBSD: ocsp_local.h,v 1.2 2022/01/14 08:32:26 tb Exp $ */ +/* Written by Tom Titchener for the OpenSSL + * project. */ + +/* History: + This file was transfered to Richard Levitte from CertCo by Kathy + Weinhold in mid-spring 2000 to be included in OpenSSL or released + as a patch kit. */ + +/* ==================================================================== + * Copyright (c) 1998-2000 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). + * + */ + +#ifndef HEADER_OCSP_LOCAL_H +#define HEADER_OCSP_LOCAL_H + +__BEGIN_HIDDEN_DECLS + +/* CertID ::= SEQUENCE { + * hashAlgorithm AlgorithmIdentifier, + * issuerNameHash OCTET STRING, -- Hash of Issuer's DN + * issuerKeyHash OCTET STRING, -- Hash of Issuers public key (excluding the tag & length fields) + * serialNumber CertificateSerialNumber } + */ +struct ocsp_cert_id_st { + X509_ALGOR *hashAlgorithm; + ASN1_OCTET_STRING *issuerNameHash; + ASN1_OCTET_STRING *issuerKeyHash; + ASN1_INTEGER *serialNumber; +} /* OCSP_CERTID */; + +/* Request ::= SEQUENCE { + * reqCert CertID, + * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL } + */ +struct ocsp_one_request_st { + OCSP_CERTID *reqCert; + STACK_OF(X509_EXTENSION) *singleRequestExtensions; +} /* OCSP_ONEREQ */; + +/* TBSRequest ::= SEQUENCE { + * version [0] EXPLICIT Version DEFAULT v1, + * requestorName [1] EXPLICIT GeneralName OPTIONAL, + * requestList SEQUENCE OF Request, + * requestExtensions [2] EXPLICIT Extensions OPTIONAL } + */ +struct ocsp_req_info_st { + ASN1_INTEGER *version; + GENERAL_NAME *requestorName; + STACK_OF(OCSP_ONEREQ) *requestList; + STACK_OF(X509_EXTENSION) *requestExtensions; +} /* OCSP_REQINFO */; + +/* Signature ::= SEQUENCE { + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING, + * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } + */ +struct ocsp_signature_st { + X509_ALGOR *signatureAlgorithm; + ASN1_BIT_STRING *signature; + STACK_OF(X509) *certs; +} /* OCSP_SIGNATURE */; + +/* OCSPRequest ::= SEQUENCE { + * tbsRequest TBSRequest, + * optionalSignature [0] EXPLICIT Signature OPTIONAL } + */ +struct ocsp_request_st { + OCSP_REQINFO *tbsRequest; + OCSP_SIGNATURE *optionalSignature; /* OPTIONAL */ +} /* OCSP_REQUEST */; + +/* OCSPResponseStatus ::= ENUMERATED { + * successful (0), --Response has valid confirmations + * malformedRequest (1), --Illegal confirmation request + * internalError (2), --Internal error in issuer + * tryLater (3), --Try again later + * --(4) is not used + * sigRequired (5), --Must sign the request + * unauthorized (6) --Request unauthorized + * } + */ + +/* ResponseBytes ::= SEQUENCE { + * responseType OBJECT IDENTIFIER, + * response OCTET STRING } + */ +struct ocsp_resp_bytes_st { + ASN1_OBJECT *responseType; + ASN1_OCTET_STRING *response; +} /* OCSP_RESPBYTES */; + +/* OCSPResponse ::= SEQUENCE { + * responseStatus OCSPResponseStatus, + * responseBytes [0] EXPLICIT ResponseBytes OPTIONAL } + */ +struct ocsp_response_st { + ASN1_ENUMERATED *responseStatus; + OCSP_RESPBYTES *responseBytes; +}; + +/* ResponderID ::= CHOICE { + * byName [1] Name, + * byKey [2] KeyHash } + */ +struct ocsp_responder_id_st { + int type; + union { + X509_NAME* byName; + ASN1_OCTET_STRING *byKey; + } value; +}; + +/* KeyHash ::= OCTET STRING --SHA-1 hash of responder's public key + * --(excluding the tag and length fields) + */ + +/* RevokedInfo ::= SEQUENCE { + * revocationTime GeneralizedTime, + * revocationReason [0] EXPLICIT CRLReason OPTIONAL } + */ +struct ocsp_revoked_info_st { + ASN1_GENERALIZEDTIME *revocationTime; + ASN1_ENUMERATED *revocationReason; +} /* OCSP_REVOKEDINFO */; + +/* CertStatus ::= CHOICE { + * good [0] IMPLICIT NULL, + * revoked [1] IMPLICIT RevokedInfo, + * unknown [2] IMPLICIT UnknownInfo } + */ +struct ocsp_cert_status_st { + int type; + union { + ASN1_NULL *good; + OCSP_REVOKEDINFO *revoked; + ASN1_NULL *unknown; + } value; +} /* OCSP_CERTSTATUS */; + +/* SingleResponse ::= SEQUENCE { + * certID CertID, + * certStatus CertStatus, + * thisUpdate GeneralizedTime, + * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, + * singleExtensions [1] EXPLICIT Extensions OPTIONAL } + */ +struct ocsp_single_response_st { + OCSP_CERTID *certId; + OCSP_CERTSTATUS *certStatus; + ASN1_GENERALIZEDTIME *thisUpdate; + ASN1_GENERALIZEDTIME *nextUpdate; + STACK_OF(X509_EXTENSION) *singleExtensions; +} /* OCSP_SINGLERESP */; + +/* ResponseData ::= SEQUENCE { + * version [0] EXPLICIT Version DEFAULT v1, + * responderID ResponderID, + * producedAt GeneralizedTime, + * responses SEQUENCE OF SingleResponse, + * responseExtensions [1] EXPLICIT Extensions OPTIONAL } + */ +struct ocsp_response_data_st { + ASN1_INTEGER *version; + OCSP_RESPID *responderId; + ASN1_GENERALIZEDTIME *producedAt; + STACK_OF(OCSP_SINGLERESP) *responses; + STACK_OF(X509_EXTENSION) *responseExtensions; +} /* OCSP_RESPDATA */; + +/* BasicOCSPResponse ::= SEQUENCE { + * tbsResponseData ResponseData, + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING, + * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } + */ + /* Note 1: + The value for "signature" is specified in the OCSP rfc2560 as follows: + "The value for the signature SHALL be computed on the hash of the DER + encoding ResponseData." This means that you must hash the DER-encoded + tbsResponseData, and then run it through a crypto-signing function, which + will (at least w/RSA) do a hash-'n'-private-encrypt operation. This seems + a bit odd, but that's the spec. Also note that the data structures do not + leave anywhere to independently specify the algorithm used for the initial + hash. So, we look at the signature-specification algorithm, and try to do + something intelligent. -- Kathy Weinhold, CertCo */ + /* Note 2: + It seems that the mentioned passage from RFC 2560 (section 4.2.1) is open + for interpretation. I've done tests against another responder, and found + that it doesn't do the double hashing that the RFC seems to say one + should. Therefore, all relevant functions take a flag saying which + variant should be used. -- Richard Levitte, OpenSSL team and CeloCom */ +struct ocsp_basic_response_st { + OCSP_RESPDATA *tbsResponseData; + X509_ALGOR *signatureAlgorithm; + ASN1_BIT_STRING *signature; + STACK_OF(X509) *certs; +} /* OCSP_BASICRESP */; + +/* CrlID ::= SEQUENCE { + * crlUrl [0] EXPLICIT IA5String OPTIONAL, + * crlNum [1] EXPLICIT INTEGER OPTIONAL, + * crlTime [2] EXPLICIT GeneralizedTime OPTIONAL } + */ +struct ocsp_crl_id_st { + ASN1_IA5STRING *crlUrl; + ASN1_INTEGER *crlNum; + ASN1_GENERALIZEDTIME *crlTime; +} /* OCSP_CRLID */; + +/* ServiceLocator ::= SEQUENCE { + * issuer Name, + * locator AuthorityInfoAccessSyntax OPTIONAL } + */ +struct ocsp_service_locator_st { + X509_NAME* issuer; + STACK_OF(ACCESS_DESCRIPTION) *locator; +} /* OCSP_SERVICELOC */; + +#define OCSP_REQUEST_sign(o,pkey,md) \ + ASN1_item_sign(&OCSP_REQINFO_it, \ + (o)->optionalSignature->signatureAlgorithm, NULL, \ + (o)->optionalSignature->signature,o->tbsRequest, (pkey), (md)) + +#define OCSP_BASICRESP_sign(o,pkey,md,d) \ + ASN1_item_sign(&OCSP_RESPDATA_it,o->signatureAlgorithm,NULL, \ + (o)->signature,(o)->tbsResponseData,(pkey),(md)) + +#define OCSP_REQUEST_verify(a,r) \ + ASN1_item_verify(&OCSP_REQINFO_it, \ + (a)->optionalSignature->signatureAlgorithm, \ + (a)->optionalSignature->signature, (a)->tbsRequest, (r)) + +#define OCSP_BASICRESP_verify(a,r,d) \ + ASN1_item_verify(&OCSP_RESPDATA_it, \ + (a)->signatureAlgorithm, (a)->signature, (a)->tbsResponseData, (r)) + +__END_HIDDEN_DECLS + +#endif /* !HEADER_OCSP_LOCAL_H */ diff --git a/crypto/ocsp/ocsp_prn.c b/crypto/ocsp/ocsp_prn.c index 37d033a..fecd14b 100644 --- a/crypto/ocsp/ocsp_prn.c +++ b/crypto/ocsp/ocsp_prn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ocsp_prn.c,v 1.8 2015/07/16 02:16:19 miod Exp $ */ +/* $OpenBSD: ocsp_prn.c,v 1.9 2022/01/07 09:45:52 tb Exp $ */ /* Written by Tom Titchener for the OpenSSL * project. */ @@ -66,6 +66,8 @@ #include #include +#include "ocsp_local.h" + static int ocsp_certid_print(BIO *bp, OCSP_CERTID* a, int indent) { diff --git a/crypto/ocsp/ocsp_srv.c b/crypto/ocsp/ocsp_srv.c index a9e0aaa..d235207 100644 --- a/crypto/ocsp/ocsp_srv.c +++ b/crypto/ocsp/ocsp_srv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ocsp_srv.c,v 1.10 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: ocsp_srv.c,v 1.12 2022/01/07 09:45:52 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2001. */ @@ -65,6 +65,8 @@ #include #include +#include "ocsp_local.h" + /* Utility functions related to sending OCSP responses and extracting * relevant information from the request. */ @@ -213,7 +215,7 @@ OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert) if (!sk_X509_push(resp->certs, cert)) return 0; - CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(cert); return 1; } diff --git a/crypto/ocsp/ocsp_vfy.c b/crypto/ocsp/ocsp_vfy.c index ebdd826..0da402f 100644 --- a/crypto/ocsp/ocsp_vfy.c +++ b/crypto/ocsp/ocsp_vfy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ocsp_vfy.c,v 1.15 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: ocsp_vfy.c,v 1.21 2022/01/22 00:33:02 inoguchi Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ @@ -60,6 +60,9 @@ #include #include +#include "ocsp_local.h" +#include "x509_lcl.h" + static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs, X509_STORE *st, unsigned long flags); static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id); @@ -94,10 +97,9 @@ OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, X509_STORE *st, if (!(flags & OCSP_NOSIGS)) { EVP_PKEY *skey; - skey = X509_get_pubkey(signer); + skey = X509_get0_pubkey(signer); if (skey) { ret = OCSP_BASICRESP_verify(bs, skey, 0); - EVP_PKEY_free(skey); } if (!skey || ret <= 0) { OCSPerror(OCSP_R_SIGNATURE_FAILURE); @@ -118,8 +120,11 @@ OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, X509_STORE *st, goto end; } } - } else + } else if (certs != NULL) { + untrusted = certs; + } else { untrusted = bs->certs; + } init_res = X509_STORE_CTX_init(&ctx, st, signer, untrusted); if (!init_res) { ret = -1; @@ -179,6 +184,13 @@ end: return ret; } +int +OCSP_resp_get0_signer(OCSP_BASICRESP *bs, X509 **signer, + STACK_OF(X509) *extra_certs) +{ + return ocsp_find_signer(signer, bs, extra_certs, NULL, 0) > 0; +} + static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs, X509_STORE *st, unsigned long flags) @@ -395,9 +407,9 @@ OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, X509_STORE *store, if (!(flags & OCSP_NOSIGS)) { EVP_PKEY *skey; - skey = X509_get_pubkey(signer); + if ((skey = X509_get0_pubkey(signer)) == NULL) + return 0; ret = OCSP_REQUEST_verify(req, skey); - EVP_PKEY_free(skey); if (ret <= 0) { OCSPerror(OCSP_R_SIGNATURE_FAILURE); return 0; diff --git a/crypto/pem/pem_info.c b/crypto/pem/pem_info.c index 33c1de4..aecdbb2 100644 --- a/crypto/pem/pem_info.c +++ b/crypto/pem/pem_info.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pem_info.c,v 1.24 2020/07/25 11:53:37 schwarze Exp $ */ +/* $OpenBSD: pem_info.c,v 1.25 2021/12/12 21:30:14 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -75,6 +75,8 @@ #include #endif +#include "evp_locl.h" + STACK_OF(X509_INFO) * PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u) diff --git a/crypto/pem/pem_lib.c b/crypto/pem/pem_lib.c index f012679..7b7f810 100644 --- a/crypto/pem/pem_lib.c +++ b/crypto/pem/pem_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pem_lib.c,v 1.49 2019/09/06 17:41:05 jsing Exp $ */ +/* $OpenBSD: pem_lib.c,v 1.50 2021/12/12 21:30:14 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -79,6 +79,7 @@ #endif #include "asn1_locl.h" +#include "evp_locl.h" #define MIN_LENGTH 4 diff --git a/crypto/pem/pem_pkey.c b/crypto/pem/pem_pkey.c index 89181a2..2e58003 100644 --- a/crypto/pem/pem_pkey.c +++ b/crypto/pem/pem_pkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pem_pkey.c,v 1.23 2017/05/02 03:59:44 deraadt Exp $ */ +/* $OpenBSD: pem_pkey.c,v 1.25 2021/12/24 12:59:18 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -74,6 +74,7 @@ #endif #include "asn1_locl.h" +#include "evp_locl.h" int pem_check_suffix(const char *pem_str, const char *suffix); @@ -151,12 +152,21 @@ int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, unsigned char *kstr, int klen, pem_password_cb *cb, void *u) { - char pem_str[80]; - - if (!x->ameth || x->ameth->priv_encode) + if (x->ameth == NULL || x->ameth->priv_encode != NULL) return PEM_write_bio_PKCS8PrivateKey(bp, x, enc, (char *)kstr, klen, cb, u); + return PEM_write_bio_PrivateKey_traditional(bp, x, enc, kstr, klen, cb, + u); +} + +int +PEM_write_bio_PrivateKey_traditional(BIO *bp, EVP_PKEY *x, + const EVP_CIPHER *enc, unsigned char *kstr, int klen, pem_password_cb *cb, + void *u) +{ + char pem_str[80]; + (void) snprintf(pem_str, sizeof(pem_str), "%s PRIVATE KEY", x->ameth->pem_str); return PEM_ASN1_write_bio((i2d_of_void *)i2d_PrivateKey, diff --git a/crypto/pem/pem_seal.c b/crypto/pem/pem_seal.c deleted file mode 100644 index c6d61ff..0000000 --- a/crypto/pem/pem_seal.c +++ /dev/null @@ -1,204 +0,0 @@ -/* $OpenBSD: pem_seal.c,v 1.24 2017/01/29 17:49:23 beck Exp $ */ -/* 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.] - */ - -#include -#include - -#include /* for OPENSSL_NO_RSA */ - -#ifndef OPENSSL_NO_RSA - -#include -#include -#include -#include -#include -#include - -static void -PEM_ENCODE_SEAL_CTX_cleanup(PEM_ENCODE_SEAL_CTX *ctx) -{ - EVP_CIPHER_CTX_cleanup(&ctx->cipher); - EVP_MD_CTX_cleanup(&ctx->md); - explicit_bzero(&ctx->encode, sizeof(ctx->encode)); -} - -int -PEM_SealInit(PEM_ENCODE_SEAL_CTX *ctx, EVP_CIPHER *type, EVP_MD *md_type, - unsigned char **ek, int *ekl, unsigned char *iv, EVP_PKEY **pubk, int npubk) -{ - unsigned char key[EVP_MAX_KEY_LENGTH]; - int ret = -1; - int i, j, max = 0; - char *s = NULL; - - /* - * Make sure ctx is properly initialized so that we can always pass - * it to PEM_ENCODE_SEAL_CTX_cleanup() in the error path. - */ - EVP_EncodeInit(&ctx->encode); - EVP_MD_CTX_init(&ctx->md); - EVP_CIPHER_CTX_init(&ctx->cipher); - - for (i = 0; i < npubk; i++) { - if (pubk[i]->type != EVP_PKEY_RSA) { - PEMerror(PEM_R_PUBLIC_KEY_NO_RSA); - goto err; - } - j = RSA_size(pubk[i]->pkey.rsa); - if (j > max) - max = j; - } - s = reallocarray(NULL, max, 2); - if (s == NULL) { - PEMerror(ERR_R_MALLOC_FAILURE); - goto err; - } - - if (!EVP_SignInit(&ctx->md, md_type)) - goto err; - - ret = EVP_SealInit(&ctx->cipher, type, ek, ekl, iv, pubk, npubk); - if (ret <= 0) - goto err; - - /* base64 encode the keys */ - for (i = 0; i < npubk; i++) { - j = EVP_EncodeBlock((unsigned char *)s, ek[i], - RSA_size(pubk[i]->pkey.rsa)); - ekl[i] = j; - memcpy(ek[i], s, j + 1); - } - - ret = npubk; - - if (0) { -err: - PEM_ENCODE_SEAL_CTX_cleanup(ctx); - } - free(s); - explicit_bzero(key, sizeof(key)); - return (ret); -} - -void -PEM_SealUpdate(PEM_ENCODE_SEAL_CTX *ctx, unsigned char *out, int *outl, - unsigned char *in, int inl) -{ - unsigned char buffer[1600]; - int i, j; - - *outl = 0; - EVP_SignUpdate(&ctx->md, in, inl); - for (;;) { - if (inl <= 0) - break; - if (inl > 1200) - i = 1200; - else - i = inl; - EVP_EncryptUpdate(&ctx->cipher, buffer, &j, in, i); - EVP_EncodeUpdate(&ctx->encode, out, &j, buffer, j); - *outl += j; - out += j; - in += i; - inl -= i; - } -} - -int -PEM_SealFinal(PEM_ENCODE_SEAL_CTX *ctx, unsigned char *sig, int *sigl, - unsigned char *out, int *outl, EVP_PKEY *priv) -{ - unsigned char *s = NULL; - int ret = 0, j; - unsigned int i; - - if (priv->type != EVP_PKEY_RSA) { - PEMerror(PEM_R_PUBLIC_KEY_NO_RSA); - goto err; - } - i = RSA_size(priv->pkey.rsa); - if (i < 100) - i = 100; - s = reallocarray(NULL, i, 2); - if (s == NULL) { - PEMerror(ERR_R_MALLOC_FAILURE); - goto err; - } - - if (!EVP_EncryptFinal_ex(&ctx->cipher, s, (int *)&i)) - goto err; - EVP_EncodeUpdate(&ctx->encode, out, &j, s, i); - *outl = j; - out += j; - EVP_EncodeFinal(&ctx->encode, out, &j); - *outl += j; - - if (!EVP_SignFinal(&ctx->md, s, &i, priv)) - goto err; - *sigl = EVP_EncodeBlock(sig, s, i); - - ret = 1; - -err: - PEM_ENCODE_SEAL_CTX_cleanup(ctx); - free(s); - return (ret); -} -#endif diff --git a/crypto/pem/pem_xaux.c b/crypto/pem/pem_xaux.c index 0dd8152..68a7851 100644 --- a/crypto/pem/pem_xaux.c +++ b/crypto/pem/pem_xaux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pem_xaux.c,v 1.9 2016/09/04 16:10:38 jsing Exp $ */ +/* $OpenBSD: pem_xaux.c,v 1.10 2021/10/31 16:28:50 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2001. */ @@ -92,31 +92,3 @@ PEM_write_bio_X509_AUX(BIO *bp, X509 *x) return PEM_ASN1_write_bio((i2d_of_void *)i2d_X509_AUX, PEM_STRING_X509_TRUSTED, bp, x, NULL, NULL, 0, NULL, NULL); } - -X509_CERT_PAIR * -PEM_read_X509_CERT_PAIR(FILE *fp, X509_CERT_PAIR **x, pem_password_cb *cb, void *u) -{ - return PEM_ASN1_read((d2i_of_void *)d2i_X509_CERT_PAIR, PEM_STRING_X509_PAIR, fp, - (void **)x, cb, u); -} - -int -PEM_write_X509_CERT_PAIR(FILE *fp, X509_CERT_PAIR *x) -{ - return PEM_ASN1_write((i2d_of_void *)i2d_X509_CERT_PAIR, PEM_STRING_X509_PAIR, fp, - x, NULL, NULL, 0, NULL, NULL); -} - -X509_CERT_PAIR * -PEM_read_bio_X509_CERT_PAIR(BIO *bp, X509_CERT_PAIR **x, pem_password_cb *cb, void *u) -{ - return PEM_ASN1_read_bio((d2i_of_void *)d2i_X509_CERT_PAIR, PEM_STRING_X509_PAIR, bp, - (void **)x, cb, u); -} - -int -PEM_write_bio_X509_CERT_PAIR(BIO *bp, X509_CERT_PAIR *x) -{ - return PEM_ASN1_write_bio((i2d_of_void *)i2d_X509_CERT_PAIR, PEM_STRING_X509_PAIR, bp, - x, NULL, NULL, 0, NULL, NULL); -} diff --git a/crypto/pem/pvkfmt.c b/crypto/pem/pvkfmt.c index abb7f7e..dffe1a3 100644 --- a/crypto/pem/pvkfmt.c +++ b/crypto/pem/pvkfmt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pvkfmt.c,v 1.22 2019/07/08 11:56:18 inoguchi Exp $ */ +/* $OpenBSD: pvkfmt.c,v 1.25 2022/01/07 09:55:31 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2005. */ @@ -74,6 +74,9 @@ #include #include "bn_lcl.h" +#include "dsa_locl.h" +#include "evp_locl.h" +#include "rsa_locl.h" /* Utility function: read a DWORD (4 byte unsigned integer) in little endian * format diff --git a/crypto/pkcs12/p12_asn.c b/crypto/pkcs12/p12_asn.c index 3baf8f4..d152063 100644 --- a/crypto/pkcs12/p12_asn.c +++ b/crypto/pkcs12/p12_asn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: p12_asn.c,v 1.9 2015/07/25 17:08:40 jsing Exp $ */ +/* $OpenBSD: p12_asn.c,v 1.10 2022/01/14 08:16:13 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -230,7 +230,6 @@ static const ASN1_ADB_TABLE PKCS12_BAGS_adbtbl[] = { static const ASN1_ADB PKCS12_BAGS_adb = { .flags = 0, .offset = offsetof(PKCS12_BAGS, type), - .app_items = 0, .tbl = PKCS12_BAGS_adbtbl, .tblcount = sizeof(PKCS12_BAGS_adbtbl) / sizeof(ASN1_ADB_TABLE), .default_tt = &bag_default_tt, @@ -369,7 +368,6 @@ static const ASN1_ADB_TABLE PKCS12_SAFEBAG_adbtbl[] = { static const ASN1_ADB PKCS12_SAFEBAG_adb = { .flags = 0, .offset = offsetof(PKCS12_SAFEBAG, type), - .app_items = 0, .tbl = PKCS12_SAFEBAG_adbtbl, .tblcount = sizeof(PKCS12_SAFEBAG_adbtbl) / sizeof(ASN1_ADB_TABLE), .default_tt = &safebag_default_tt, diff --git a/crypto/pkcs12/p12_attr.c b/crypto/pkcs12/p12_attr.c index e8e340a..dc38b7c 100644 --- a/crypto/pkcs12/p12_attr.c +++ b/crypto/pkcs12/p12_attr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: p12_attr.c,v 1.13 2021/07/09 14:07:59 tb Exp $ */ +/* $OpenBSD: p12_attr.c,v 1.14 2021/11/01 20:53:08 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -60,6 +60,8 @@ #include +#include "x509_lcl.h" + /* Add a local keyid to a safebag */ int diff --git a/crypto/pkcs12/p12_decr.c b/crypto/pkcs12/p12_decr.c index 8ac7f17..c352ba5 100644 --- a/crypto/pkcs12/p12_decr.c +++ b/crypto/pkcs12/p12_decr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: p12_decr.c,v 1.20 2021/07/09 14:08:00 tb Exp $ */ +/* $OpenBSD: p12_decr.c,v 1.21 2021/12/12 21:30:14 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -62,6 +62,8 @@ #include #include +#include "evp_locl.h" + /* Encrypt/Decrypt a buffer based on password and algor, result in a * malloc'ed buffer */ diff --git a/crypto/pkcs12/p12_init.c b/crypto/pkcs12/p12_init.c index 637c430..13dbe36 100644 --- a/crypto/pkcs12/p12_init.c +++ b/crypto/pkcs12/p12_init.c @@ -1,4 +1,4 @@ -/* $OpenBSD: p12_init.c,v 1.11 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: p12_init.c,v 1.13 2022/01/20 11:18:49 inoguchi Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -72,8 +72,10 @@ PKCS12_init(int mode) PKCS12error(ERR_R_MALLOC_FAILURE); return NULL; } - ASN1_INTEGER_set(pkcs12->version, 3); - pkcs12->authsafes->type = OBJ_nid2obj(mode); + if (!ASN1_INTEGER_set(pkcs12->version, 3)) + goto err; + if ((pkcs12->authsafes->type = OBJ_nid2obj(mode)) == NULL) + goto err; switch (mode) { case NID_pkcs7_data: if (!(pkcs12->authsafes->d.data = diff --git a/crypto/pkcs12/p12_key.c b/crypto/pkcs12/p12_key.c index 2887948..38d25d2 100644 --- a/crypto/pkcs12/p12_key.c +++ b/crypto/pkcs12/p12_key.c @@ -1,4 +1,4 @@ -/* $OpenBSD: p12_key.c,v 1.27 2021/07/09 14:08:00 tb Exp $ */ +/* $OpenBSD: p12_key.c,v 1.28 2021/12/12 21:30:14 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -63,6 +63,8 @@ #include #include +#include "evp_locl.h" + /* PKCS12 compatible key/IV generation */ #ifndef min #define min(a,b) ((a) < (b) ? (a) : (b)) diff --git a/crypto/pkcs12/p12_mutl.c b/crypto/pkcs12/p12_mutl.c index d45ab07..f3a6ea3 100644 --- a/crypto/pkcs12/p12_mutl.c +++ b/crypto/pkcs12/p12_mutl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: p12_mutl.c,v 1.24 2021/07/09 14:08:00 tb Exp $ */ +/* $OpenBSD: p12_mutl.c,v 1.27 2021/12/12 21:30:14 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -68,6 +68,10 @@ #include #include +#include "evp_locl.h" +#include "hmac_local.h" +#include "x509_lcl.h" + /* Generate a MAC */ int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen, diff --git a/crypto/pkcs12/p12_npas.c b/crypto/pkcs12/p12_npas.c index d6b12ed..62ec368 100644 --- a/crypto/pkcs12/p12_npas.c +++ b/crypto/pkcs12/p12_npas.c @@ -1,4 +1,4 @@ -/* $OpenBSD: p12_npas.c,v 1.13 2018/05/13 14:22:34 tb Exp $ */ +/* $OpenBSD: p12_npas.c,v 1.14 2021/11/01 20:53:08 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -63,6 +63,8 @@ #include #include +#include "x509_lcl.h" + /* PKCS#12 password change routine */ static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass); diff --git a/crypto/pkcs12/p12_p8d.c b/crypto/pkcs12/p12_p8d.c index 0286d4a..ce1b28b 100644 --- a/crypto/pkcs12/p12_p8d.c +++ b/crypto/pkcs12/p12_p8d.c @@ -1,4 +1,4 @@ -/* $OpenBSD: p12_p8d.c,v 1.7 2018/05/13 14:28:14 tb Exp $ */ +/* $OpenBSD: p12_p8d.c,v 1.8 2021/11/01 20:53:08 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2001. */ @@ -60,6 +60,8 @@ #include +#include "x509_lcl.h" + PKCS8_PRIV_KEY_INFO * PKCS8_decrypt(const X509_SIG *p8, const char *pass, int passlen) { diff --git a/crypto/pkcs12/p12_p8e.c b/crypto/pkcs12/p12_p8e.c index 5e3fc64..7f5f61d 100644 --- a/crypto/pkcs12/p12_p8e.c +++ b/crypto/pkcs12/p12_p8e.c @@ -1,4 +1,4 @@ -/* $OpenBSD: p12_p8e.c,v 1.8 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: p12_p8e.c,v 1.9 2021/11/01 20:53:08 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2001. */ @@ -61,6 +61,8 @@ #include #include +#include "x509_lcl.h" + X509_SIG * PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, const char *pass, int passlen, unsigned char *salt, int saltlen, int iter, diff --git a/crypto/pkcs7/pk7_asn1.c b/crypto/pkcs7/pk7_asn1.c index 81e4a01..6665905 100644 --- a/crypto/pkcs7/pk7_asn1.c +++ b/crypto/pkcs7/pk7_asn1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pk7_asn1.c,v 1.12 2015/07/25 15:33:06 jsing Exp $ */ +/* $OpenBSD: pk7_asn1.c,v 1.13 2022/01/14 08:16:13 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ @@ -146,7 +146,6 @@ static const ASN1_ADB_TABLE PKCS7_adbtbl[] = { static const ASN1_ADB PKCS7_adb = { .flags = 0, .offset = offsetof(PKCS7, type), - .app_items = 0, .tbl = PKCS7_adbtbl, .tblcount = sizeof(PKCS7_adbtbl) / sizeof(ASN1_ADB_TABLE), .default_tt = &p7default_tt, diff --git a/crypto/pkcs7/pk7_doit.c b/crypto/pkcs7/pk7_doit.c index 81a72f6..c9d64bc 100644 --- a/crypto/pkcs7/pk7_doit.c +++ b/crypto/pkcs7/pk7_doit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pk7_doit.c,v 1.44 2019/10/04 18:03:55 tb Exp $ */ +/* $OpenBSD: pk7_doit.c,v 1.46 2021/12/12 21:30:14 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -65,6 +65,9 @@ #include #include +#include "evp_locl.h" +#include "x509_lcl.h" + static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, void *value); static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid); diff --git a/crypto/pkcs7/pk7_lib.c b/crypto/pkcs7/pk7_lib.c index afcc179..7e92df1 100644 --- a/crypto/pkcs7/pk7_lib.c +++ b/crypto/pkcs7/pk7_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pk7_lib.c,v 1.21 2020/01/21 10:18:52 inoguchi Exp $ */ +/* $OpenBSD: pk7_lib.c,v 1.23 2021/12/12 21:30:14 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -63,6 +63,8 @@ #include #include "asn1_locl.h" +#include "evp_locl.h" +#include "x509_lcl.h" long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg) diff --git a/crypto/pkcs7/pk7_smime.c b/crypto/pkcs7/pk7_smime.c index bf9f2dd..f11d23e 100644 --- a/crypto/pkcs7/pk7_smime.c +++ b/crypto/pkcs7/pk7_smime.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pk7_smime.c,v 1.22 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: pk7_smime.c,v 1.23 2021/11/01 20:53:08 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project. */ @@ -64,6 +64,8 @@ #include #include +#include "x509_lcl.h" + static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si); PKCS7 * diff --git a/crypto/rc4/rc4-masm-x86_64.S b/crypto/rc4/rc4-masm-x86_64.S index b930d98..a15566e 100644 --- a/crypto/rc4/rc4-masm-x86_64.S +++ b/crypto/rc4/rc4-masm-x86_64.S @@ -1,7 +1,7 @@ ; 1 "crypto/rc4/rc4-masm-x86_64.S.tmp" ; 1 "" 1 ; 1 "" 3 -; 340 "" 3 +; 343 "" 3 ; 1 "" 1 ; 1 "" 2 ; 1 "crypto/rc4/rc4-masm-x86_64.S.tmp" 2 diff --git a/crypto/rc4/rc4-md5-masm-x86_64.S b/crypto/rc4/rc4-md5-masm-x86_64.S index 3357567..0d2e8d5 100644 --- a/crypto/rc4/rc4-md5-masm-x86_64.S +++ b/crypto/rc4/rc4-md5-masm-x86_64.S @@ -1,7 +1,7 @@ ; 1 "crypto/rc4/rc4-md5-masm-x86_64.S.tmp" ; 1 "" 1 ; 1 "" 3 -; 340 "" 3 +; 343 "" 3 ; 1 "" 1 ; 1 "" 2 ; 1 "crypto/rc4/rc4-md5-masm-x86_64.S.tmp" 2 diff --git a/crypto/rc4/rc4_enc.c b/crypto/rc4/rc4_enc.c index bd928b5..aa2766a 100644 --- a/crypto/rc4/rc4_enc.c +++ b/crypto/rc4/rc4_enc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rc4_enc.c,v 1.16 2017/08/13 17:46:24 bcook Exp $ */ +/* $OpenBSD: rc4_enc.c,v 1.17 2021/11/09 18:40:21 bcook Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -56,7 +56,8 @@ * [including the GNU Public Licence.] */ -#include +#include + #include #include "rc4_locl.h" diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c index d373d7c..57fe46a 100644 --- a/crypto/rsa/rsa_ameth.c +++ b/crypto/rsa/rsa_ameth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rsa_ameth.c,v 1.24 2019/11/20 10:46:17 inoguchi Exp $ */ +/* $OpenBSD: rsa_ameth.c,v 1.25 2022/01/10 11:52:43 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2006. */ @@ -916,6 +916,12 @@ rsa_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn, return 2; } +static int +rsa_pkey_check(const EVP_PKEY *pkey) +{ + return RSA_check_key(pkey->pkey.rsa); +} + #ifndef OPENSSL_NO_CMS static RSA_OAEP_PARAMS * rsa_oaep_decode(const X509_ALGOR *alg) @@ -1105,14 +1111,18 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[] = { .old_priv_decode = old_rsa_priv_decode, .old_priv_encode = old_rsa_priv_encode, .item_verify = rsa_item_verify, - .item_sign = rsa_item_sign + .item_sign = rsa_item_sign, + + .pkey_check = rsa_pkey_check, }, { .pkey_id = EVP_PKEY_RSA2, .pkey_base_id = EVP_PKEY_RSA, - .pkey_flags = ASN1_PKEY_ALIAS - } + .pkey_flags = ASN1_PKEY_ALIAS, + + .pkey_check = rsa_pkey_check, + }, }; const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth = { diff --git a/crypto/rsa/rsa_chk.c b/crypto/rsa/rsa_chk.c index 5345d31..ac9dbf7 100644 --- a/crypto/rsa/rsa_chk.c +++ b/crypto/rsa/rsa_chk.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rsa_chk.c,v 1.13 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: rsa_chk.c,v 1.16 2022/01/20 11:08:12 inoguchi Exp $ */ /* ==================================================================== * Copyright (c) 1999 The OpenSSL Project. All rights reserved. * @@ -53,6 +53,7 @@ #include #include "bn_lcl.h" +#include "rsa_locl.h" int RSA_check_key(const RSA *key) @@ -80,6 +81,15 @@ RSA_check_key(const RSA *key) goto err; } + if (BN_is_one(key->e)) { + ret = 0; + RSAerror(RSA_R_BAD_E_VALUE); + } + if (!BN_is_odd(key->e)) { + ret = 0; + RSAerror(RSA_R_BAD_E_VALUE); + } + /* p prime? */ r = BN_is_prime_ex(key->p, BN_prime_checks, NULL, NULL); if (r != 1) { @@ -189,7 +199,7 @@ RSA_check_key(const RSA *key) } /* iqmp = q^-1 mod p? */ - if (!BN_mod_inverse_ct(i, key->q, key->p, ctx)) { + if (BN_mod_inverse_ct(i, key->q, key->p, ctx) == NULL) { ret = -1; goto err; } diff --git a/crypto/rsa/rsa_crpt.c b/crypto/rsa/rsa_crpt.c index a646ded..4fd21cd 100644 --- a/crypto/rsa/rsa_crpt.c +++ b/crypto/rsa/rsa_crpt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rsa_crpt.c,v 1.19 2018/02/18 12:52:13 tb Exp $ */ +/* $OpenBSD: rsa_crpt.c,v 1.20 2022/01/07 09:55:32 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -67,6 +67,7 @@ #include #include "bn_lcl.h" +#include "rsa_locl.h" #ifndef OPENSSL_NO_ENGINE #include diff --git a/crypto/rsa/rsa_depr.c b/crypto/rsa/rsa_depr.c index b830a22..54a669c 100644 --- a/crypto/rsa/rsa_depr.c +++ b/crypto/rsa/rsa_depr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rsa_depr.c,v 1.8 2014/07/11 08:44:49 jsing Exp $ */ +/* $OpenBSD: rsa_depr.c,v 1.9 2021/12/04 16:08:32 tb Exp $ */ /* ==================================================================== * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. * @@ -64,6 +64,8 @@ #include #include +#include "bn_lcl.h" + #ifndef OPENSSL_NO_DEPRECATED RSA * diff --git a/crypto/rsa/rsa_eay.c b/crypto/rsa/rsa_eay.c index 33201a8..0f8c324 100644 --- a/crypto/rsa/rsa_eay.c +++ b/crypto/rsa/rsa_eay.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rsa_eay.c,v 1.51 2019/11/02 13:52:31 jsing Exp $ */ +/* $OpenBSD: rsa_eay.c,v 1.54 2022/01/20 11:10:11 inoguchi Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -119,6 +119,7 @@ #include #include "bn_lcl.h" +#include "rsa_locl.h" static int RSA_eay_public_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding); @@ -446,7 +447,8 @@ RSA_eay_private_encrypt(int flen, const unsigned char *from, unsigned char *to, goto err; if (padding == RSA_X931_PADDING) { - BN_sub(f, rsa->n, ret); + if (!BN_sub(f, rsa->n, ret)) + goto err; if (BN_cmp(ret, f) > 0) res = f; else @@ -753,6 +755,7 @@ RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) goto err; /* compute I mod p */ + BN_init(&c); BN_with_flags(&c, I, BN_FLG_CONSTTIME); if (!BN_mod_ct(r1, &c, rsa->p, ctx)) diff --git a/crypto/rsa/rsa_gen.c b/crypto/rsa/rsa_gen.c index 596eb8e..5f062a7 100644 --- a/crypto/rsa/rsa_gen.c +++ b/crypto/rsa/rsa_gen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rsa_gen.c,v 1.22 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: rsa_gen.c,v 1.25 2022/01/20 11:11:17 inoguchi Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -70,6 +70,7 @@ #include #include "bn_lcl.h" +#include "rsa_locl.h" static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb); @@ -194,12 +195,14 @@ rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) if (!BN_mul(r0, r1, r2, ctx)) /* (p-1)(q-1) */ goto err; + BN_init(&pr0); BN_with_flags(&pr0, r0, BN_FLG_CONSTTIME); - if (!BN_mod_inverse_ct(rsa->d, rsa->e, &pr0, ctx)) /* d */ + if (BN_mod_inverse_ct(rsa->d, rsa->e, &pr0, ctx) == NULL) /* d */ goto err; /* set up d for correct BN_FLG_CONSTTIME flag */ + BN_init(&d); BN_with_flags(&d, rsa->d, BN_FLG_CONSTTIME); /* calculate d mod (p-1) */ @@ -211,8 +214,9 @@ rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) goto err; /* calculate inverse of q mod p */ + BN_init(&p); BN_with_flags(&p, rsa->p, BN_FLG_CONSTTIME); - if (!BN_mod_inverse_ct(rsa->iqmp, rsa->q, &p, ctx)) + if (BN_mod_inverse_ct(rsa->iqmp, rsa->q, &p, ctx) == NULL) goto err; ok = 1; diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c index 0b76aae..ddf3f1b 100644 --- a/crypto/rsa/rsa_lib.c +++ b/crypto/rsa/rsa_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rsa_lib.c,v 1.40 2020/01/17 10:40:03 inoguchi Exp $ */ +/* $OpenBSD: rsa_lib.c,v 1.42 2022/01/07 09:55:32 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -68,6 +68,7 @@ #include #include "evp_locl.h" +#include "rsa_locl.h" #ifndef OPENSSL_NO_ENGINE #include @@ -336,6 +337,60 @@ RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q) return 1; } +const BIGNUM * +RSA_get0_n(const RSA *r) +{ + return r->n; +} + +const BIGNUM * +RSA_get0_e(const RSA *r) +{ + return r->e; +} + +const BIGNUM * +RSA_get0_d(const RSA *r) +{ + return r->d; +} + +const BIGNUM * +RSA_get0_p(const RSA *r) +{ + return r->p; +} + +const BIGNUM * +RSA_get0_q(const RSA *r) +{ + return r->q; +} + +const BIGNUM * +RSA_get0_dmp1(const RSA *r) +{ + return r->dmp1; +} + +const BIGNUM * +RSA_get0_dmq1(const RSA *r) +{ + return r->dmq1; +} + +const BIGNUM * +RSA_get0_iqmp(const RSA *r) +{ + return r->iqmp; +} + +const RSA_PSS_PARAMS * +RSA_get0_pss_params(const RSA *r) +{ + return r->pss; +} + void RSA_clear_flags(RSA *r, int flags) { diff --git a/crypto/rsa/rsa_locl.h b/crypto/rsa/rsa_locl.h index 7036449..9eae2b3 100644 --- a/crypto/rsa/rsa_locl.h +++ b/crypto/rsa/rsa_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rsa_locl.h,v 1.11 2019/11/02 13:47:41 jsing Exp $ */ +/* $OpenBSD: rsa_locl.h,v 1.12 2022/01/14 08:34:39 tb Exp $ */ __BEGIN_HIDDEN_DECLS @@ -8,6 +8,80 @@ __BEGIN_HIDDEN_DECLS #define pkey_is_pss(pkey) (pkey->ameth->pkey_id == EVP_PKEY_RSA_PSS) #define pkey_ctx_is_pss(ctx) (ctx->pmeth->pkey_id == EVP_PKEY_RSA_PSS) +struct rsa_meth_st { + const char *name; + int (*rsa_pub_enc)(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + int (*rsa_pub_dec)(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + int (*rsa_priv_enc)(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + int (*rsa_priv_dec)(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + int (*rsa_mod_exp)(BIGNUM *r0, const BIGNUM *I, RSA *rsa, + BN_CTX *ctx); /* Can be null */ + int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); /* Can be null */ + int (*init)(RSA *rsa); /* called at new */ + int (*finish)(RSA *rsa); /* called at free */ + int flags; /* RSA_METHOD_FLAG_* things */ + char *app_data; /* may be needed! */ +/* New sign and verify functions: some libraries don't allow arbitrary data + * to be signed/verified: this allows them to be used. Note: for this to work + * the RSA_public_decrypt() and RSA_private_encrypt() should *NOT* be used + * RSA_sign(), RSA_verify() should be used instead. Note: for backwards + * compatibility this functionality is only enabled if the RSA_FLAG_SIGN_VER + * option is set in 'flags'. + */ + int (*rsa_sign)(int type, const unsigned char *m, unsigned int m_length, + unsigned char *sigret, unsigned int *siglen, const RSA *rsa); + int (*rsa_verify)(int dtype, const unsigned char *m, + unsigned int m_length, const unsigned char *sigbuf, + unsigned int siglen, const RSA *rsa); +/* If this callback is NULL, the builtin software RSA key-gen will be used. This + * is for behavioural compatibility whilst the code gets rewired, but one day + * it would be nice to assume there are no such things as "builtin software" + * implementations. */ + int (*rsa_keygen)(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb); +}; + +struct rsa_st { + /* The first parameter is used to pickup errors where + * this is passed instead of aEVP_PKEY, it is set to 0 */ + int pad; + long version; + const RSA_METHOD *meth; + + /* functional reference if 'meth' is ENGINE-provided */ + ENGINE *engine; + BIGNUM *n; + BIGNUM *e; + BIGNUM *d; + BIGNUM *p; + BIGNUM *q; + BIGNUM *dmp1; + BIGNUM *dmq1; + BIGNUM *iqmp; + + /* Parameter restrictions for PSS only keys. */ + RSA_PSS_PARAMS *pss; + + /* be careful using this if the RSA structure is shared */ + CRYPTO_EX_DATA ex_data; + int references; + int flags; + + /* Used to cache montgomery values */ + BN_MONT_CTX *_method_mod_n; + BN_MONT_CTX *_method_mod_p; + BN_MONT_CTX *_method_mod_q; + + /* all BIGNUM values are actually in the following data, if it is not + * NULL */ + BN_BLINDING *blinding; + BN_BLINDING *mt_blinding; +}; + RSA_PSS_PARAMS *rsa_pss_params_create(const EVP_MD *sigmd, const EVP_MD *mgf1md, int saltlen); int rsa_pss_get_param(const RSA_PSS_PARAMS *pss, const EVP_MD **pmd, diff --git a/crypto/rsa/rsa_meth.c b/crypto/rsa/rsa_meth.c index 095368b..8ae929d 100644 --- a/crypto/rsa/rsa_meth.c +++ b/crypto/rsa/rsa_meth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rsa_meth.c,v 1.3 2019/06/05 15:41:33 gilles Exp $ */ +/* $OpenBSD: rsa_meth.c,v 1.4 2022/01/07 09:55:32 tb Exp $ */ /* * Copyright (c) 2018 Theo Buehler * @@ -21,6 +21,8 @@ #include #include +#include "rsa_locl.h" + RSA_METHOD * RSA_meth_new(const char *name, int flags) { diff --git a/crypto/rsa/rsa_oaep.c b/crypto/rsa/rsa_oaep.c index e54600b..9326950 100644 --- a/crypto/rsa/rsa_oaep.c +++ b/crypto/rsa/rsa_oaep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rsa_oaep.c,v 1.33 2019/10/17 14:31:56 jsing Exp $ */ +/* $OpenBSD: rsa_oaep.c,v 1.35 2022/02/20 19:16:34 tb Exp $ */ /* * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. * @@ -80,6 +80,7 @@ #include #include "constant_time_locl.h" +#include "evp_locl.h" #include "rsa_locl.h" int @@ -223,17 +224,16 @@ RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, from -= 1 & mask; *--em = *from & mask; } - from = em; /* * The first byte must be zero, however we must not leak if this is * true. See James H. Manger, "A Chosen Ciphertext Attack on RSA * Optimal Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001). */ - good = constant_time_is_zero(from[0]); + good = constant_time_is_zero(em[0]); - maskedseed = from + 1; - maskeddb = from + 1 + mdlen; + maskedseed = em + 1; + maskeddb = em + 1 + mdlen; if (PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md)) goto cleanup; @@ -289,15 +289,16 @@ RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, * should be noted that failure is indistinguishable from normal * operation if |tlen| is fixed by protocol. */ - tlen = constant_time_select_int(constant_time_lt(dblen, tlen), dblen, tlen); + tlen = constant_time_select_int(constant_time_lt(dblen - mdlen - 1, tlen), + dblen - mdlen - 1, tlen); msg_index = constant_time_select_int(good, msg_index, dblen - tlen); mlen = dblen - msg_index; - for (from = db + msg_index, mask = good, i = 0; i < tlen; i++) { - unsigned int equals = constant_time_eq(i, mlen); + for (mask = good, i = 0; i < tlen; i++) { + unsigned int equals = constant_time_eq(msg_index, dblen); - from -= dblen & equals; /* if (i == mlen) rewind */ - mask &= mask ^ equals; /* if (i == mlen) mask = 0 */ - to[i] = constant_time_select_8(mask, from[i], to[i]); + msg_index -= tlen & equals; /* rewind at EOF */ + mask &= ~equals; /* mask = 0 at EOF */ + to[i] = constant_time_select_8(mask, db[msg_index++], to[i]); } /* diff --git a/crypto/rsa/rsa_pmeth.c b/crypto/rsa/rsa_pmeth.c index 008d425..36a2a27 100644 --- a/crypto/rsa/rsa_pmeth.c +++ b/crypto/rsa/rsa_pmeth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rsa_pmeth.c,v 1.32 2019/10/31 14:05:30 jsing Exp $ */ +/* $OpenBSD: rsa_pmeth.c,v 1.33 2021/12/04 16:08:32 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2006. */ @@ -70,6 +70,7 @@ #include #include +#include "bn_lcl.h" #include "evp_locl.h" #include "rsa_locl.h" diff --git a/crypto/rsa/rsa_pss.c b/crypto/rsa/rsa_pss.c index 562f7b2..cce38ef 100644 --- a/crypto/rsa/rsa_pss.c +++ b/crypto/rsa/rsa_pss.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rsa_pss.c,v 1.13 2018/09/05 00:55:33 djm Exp $ */ +/* $OpenBSD: rsa_pss.c,v 1.15 2022/01/07 09:55:32 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2005. */ @@ -66,6 +66,9 @@ #include #include +#include "evp_locl.h" +#include "rsa_locl.h" + static const unsigned char zeroes[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; int diff --git a/crypto/rsa/rsa_sign.c b/crypto/rsa/rsa_sign.c index d205046..bd45a95 100644 --- a/crypto/rsa/rsa_sign.c +++ b/crypto/rsa/rsa_sign.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rsa_sign.c,v 1.32 2021/05/14 18:03:42 tb Exp $ */ +/* $OpenBSD: rsa_sign.c,v 1.34 2022/01/07 11:13:55 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -65,7 +65,9 @@ #include #include +#include "asn1_locl.h" #include "rsa_locl.h" +#include "x509_lcl.h" /* Size of an SSL signature: MD5+SHA1 */ #define SSL_SIG_LENGTH 36 diff --git a/crypto/sha/sha1-masm-x86_64.S b/crypto/sha/sha1-masm-x86_64.S index 36d8732..f520b5a 100644 --- a/crypto/sha/sha1-masm-x86_64.S +++ b/crypto/sha/sha1-masm-x86_64.S @@ -1,7 +1,7 @@ ; 1 "crypto/sha/sha1-masm-x86_64.S.tmp" ; 1 "" 1 ; 1 "" 3 -; 340 "" 3 +; 343 "" 3 ; 1 "" 1 ; 1 "" 2 ; 1 "crypto/sha/sha1-masm-x86_64.S.tmp" 2 diff --git a/crypto/sha/sha256-masm-x86_64.S b/crypto/sha/sha256-masm-x86_64.S index 33c705d..7c182f9 100644 --- a/crypto/sha/sha256-masm-x86_64.S +++ b/crypto/sha/sha256-masm-x86_64.S @@ -1,7 +1,7 @@ ; 1 "crypto/sha/sha256-masm-x86_64.S.tmp" ; 1 "" 1 ; 1 "" 3 -; 340 "" 3 +; 343 "" 3 ; 1 "" 1 ; 1 "" 2 ; 1 "crypto/sha/sha256-masm-x86_64.S.tmp" 2 diff --git a/crypto/sha/sha256.c b/crypto/sha/sha256.c index 9c05d3b..e826ca9 100644 --- a/crypto/sha/sha256.c +++ b/crypto/sha/sha256.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sha256.c,v 1.10 2019/01/21 23:20:31 jsg Exp $ */ +/* $OpenBSD: sha256.c,v 1.11 2021/11/09 18:40:21 bcook Exp $ */ /* ==================================================================== * Copyright (c) 2004 The OpenSSL Project. All rights reserved * according to the OpenSSL license [found in ../../LICENSE]. @@ -9,8 +9,7 @@ #if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA256) -#include - +#include #include #include diff --git a/crypto/sha/sha512-masm-x86_64.S b/crypto/sha/sha512-masm-x86_64.S index 4a2b9af..e964d9c 100644 --- a/crypto/sha/sha512-masm-x86_64.S +++ b/crypto/sha/sha512-masm-x86_64.S @@ -1,7 +1,7 @@ ; 1 "crypto/sha/sha512-masm-x86_64.S.tmp" ; 1 "" 1 ; 1 "" 3 -; 340 "" 3 +; 343 "" 3 ; 1 "" 1 ; 1 "" 2 ; 1 "crypto/sha/sha512-masm-x86_64.S.tmp" 2 diff --git a/crypto/sha/sha512.c b/crypto/sha/sha512.c index 6b95cfa..56a207f 100644 --- a/crypto/sha/sha512.c +++ b/crypto/sha/sha512.c @@ -1,12 +1,11 @@ -/* $OpenBSD: sha512.c,v 1.15 2016/11/04 13:56:05 miod Exp $ */ +/* $OpenBSD: sha512.c,v 1.16 2021/11/09 18:40:21 bcook Exp $ */ /* ==================================================================== * Copyright (c) 2004 The OpenSSL Project. All rights reserved * according to the OpenSSL license [found in ../../LICENSE]. * ==================================================================== */ -#include - +#include #include #include diff --git a/crypto/sha/sha_locl.h b/crypto/sha/sha_locl.h index 46c9a39..5daab29 100644 --- a/crypto/sha/sha_locl.h +++ b/crypto/sha/sha_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sha_locl.h,v 1.23 2016/12/23 23:22:25 patrick Exp $ */ +/* $OpenBSD: sha_locl.h,v 1.24 2021/11/09 18:40:21 bcook Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -186,7 +186,7 @@ int SHA1_Init(SHA_CTX *c) #endif #if !defined(SHA1_ASM) -#include +#include static void HASH_BLOCK_DATA_ORDER (SHA_CTX *c, const void *p, size_t num) { const unsigned char *data=p; diff --git a/crypto/ts/ts_lib.c b/crypto/ts/ts_lib.c index 2935641..b6d50a3 100644 --- a/crypto/ts/ts_lib.c +++ b/crypto/ts/ts_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ts_lib.c,v 1.10 2015/09/10 14:29:22 jsing Exp $ */ +/* $OpenBSD: ts_lib.c,v 1.12 2021/12/04 16:08:32 tb Exp $ */ /* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL * project 2002. */ @@ -64,6 +64,9 @@ #include #include +#include "bn_lcl.h" +#include "x509_lcl.h" + /* Local function declarations. */ /* Function definitions. */ diff --git a/crypto/ts/ts_rsp_sign.c b/crypto/ts/ts_rsp_sign.c index 6125fdd..470cbfb 100644 --- a/crypto/ts/ts_rsp_sign.c +++ b/crypto/ts/ts_rsp_sign.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ts_rsp_sign.c,v 1.23 2019/07/03 03:24:04 deraadt Exp $ */ +/* $OpenBSD: ts_rsp_sign.c,v 1.26 2021/12/12 21:30:14 tb Exp $ */ /* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL * project 2002. */ @@ -65,6 +65,9 @@ #include #include +#include "evp_locl.h" +#include "x509_lcl.h" + /* Private function declarations. */ static ASN1_INTEGER *def_serial_cb(struct TS_resp_ctx *, void *); @@ -847,14 +850,18 @@ ESS_CERT_ID_new_init(X509 *cert, int issuer_needed) { ESS_CERT_ID *cid = NULL; GENERAL_NAME *name = NULL; + unsigned char cert_hash[TS_HASH_LEN]; /* Recompute SHA1 hash of certificate if necessary (side effect). */ X509_check_purpose(cert, -1, 0); if (!(cid = ESS_CERT_ID_new())) goto err; - if (!ASN1_OCTET_STRING_set(cid->hash, cert->sha1_hash, - sizeof(cert->sha1_hash))) + + if (!X509_digest(cert, TS_HASH_EVP, cert_hash, NULL)) + goto err; + + if (!ASN1_OCTET_STRING_set(cid->hash, cert_hash, sizeof(cert_hash))) goto err; /* Setting the issuer/serial if requested. */ diff --git a/crypto/ts/ts_rsp_verify.c b/crypto/ts/ts_rsp_verify.c index 46704df..8b15760 100644 --- a/crypto/ts/ts_rsp_verify.c +++ b/crypto/ts/ts_rsp_verify.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ts_rsp_verify.c,v 1.21 2021/07/02 11:15:08 schwarze Exp $ */ +/* $OpenBSD: ts_rsp_verify.c,v 1.24 2021/12/12 21:30:14 tb Exp $ */ /* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL * project 2002. */ @@ -64,6 +64,9 @@ #include #include +#include "evp_locl.h" +#include "x509_lcl.h" + /* Private function declarations. */ static int TS_verify_cert(X509_STORE *store, STACK_OF(X509) *untrusted, @@ -323,10 +326,14 @@ static int TS_find_cert(STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert) { int i; + unsigned char cert_hash[TS_HASH_LEN]; if (!cert_ids || !cert) return -1; + if (!X509_digest(cert, TS_HASH_EVP, cert_hash, NULL)) + return -1; + /* Recompute SHA1 hash of certificate if necessary (side effect). */ X509_check_purpose(cert, -1, 0); @@ -335,9 +342,8 @@ TS_find_cert(STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert) ESS_CERT_ID *cid = sk_ESS_CERT_ID_value(cert_ids, i); /* Check the SHA-1 hash first. */ - if (cid->hash->length == sizeof(cert->sha1_hash) && - !memcmp(cid->hash->data, cert->sha1_hash, - sizeof(cert->sha1_hash))) { + if (cid->hash->length == TS_HASH_LEN && !memcmp(cid->hash->data, + cert_hash, TS_HASH_LEN)) { /* Check the issuer/serial as well if specified. */ ESS_ISSUER_SERIAL *is = cid->issuer_serial; if (!is || !TS_issuer_serial_cmp(is, cert->cert_info)) diff --git a/crypto/whrlpool/wp-masm-x86_64.S b/crypto/whrlpool/wp-masm-x86_64.S index 78cf97c..71f0c01 100644 --- a/crypto/whrlpool/wp-masm-x86_64.S +++ b/crypto/whrlpool/wp-masm-x86_64.S @@ -1,7 +1,7 @@ ; 1 "crypto/whrlpool/wp-masm-x86_64.S.tmp" ; 1 "" 1 ; 1 "" 3 -; 340 "" 3 +; 343 "" 3 ; 1 "" 1 ; 1 "" 2 ; 1 "crypto/whrlpool/wp-masm-x86_64.S.tmp" 2 diff --git a/crypto/whrlpool/wp_block.c b/crypto/whrlpool/wp_block.c index 1e00a01..b2137d6 100644 --- a/crypto/whrlpool/wp_block.c +++ b/crypto/whrlpool/wp_block.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wp_block.c,v 1.13 2016/11/04 17:30:30 miod Exp $ */ +/* $OpenBSD: wp_block.c,v 1.14 2021/11/09 18:40:21 bcook Exp $ */ /** * The Whirlpool hashing function. * @@ -36,9 +36,9 @@ * */ +#include #include #include -#include #include "wp_locl.h" diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c index 04eada8..fa05f55 100644 --- a/crypto/x509/by_dir.c +++ b/crypto/x509/by_dir.c @@ -1,4 +1,4 @@ -/* $OpenBSD: by_dir.c,v 1.39 2018/08/05 14:17:12 bcook Exp $ */ +/* $OpenBSD: by_dir.c,v 1.41 2021/11/10 14:34:21 schwarze Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -56,6 +56,7 @@ * [including the GNU Public Licence.] */ +#include #include #include @@ -67,10 +68,9 @@ #include #include -#include #include -# include +#include "x509_lcl.h" typedef struct lookup_dir_hashes_st { unsigned long hash; @@ -115,7 +115,7 @@ static X509_LOOKUP_METHOD x509_dir_lookup = { X509_LOOKUP_METHOD * X509_LOOKUP_hash_dir(void) { - return (&x509_dir_lookup); + return &x509_dir_lookup; } static int @@ -139,7 +139,7 @@ dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, ret = add_cert_dir(ld, argp, (int)argl); break; } - return (ret); + return ret; } static int @@ -147,15 +147,18 @@ new_dir(X509_LOOKUP *lu) { BY_DIR *a; - if ((a = malloc(sizeof(BY_DIR))) == NULL) - return (0); + if ((a = malloc(sizeof(*a))) == NULL) { + X509error(ERR_R_MALLOC_FAILURE); + return 0; + } if ((a->buffer = BUF_MEM_new()) == NULL) { + X509error(ERR_R_MALLOC_FAILURE); free(a); - return (0); + return 0; } a->dirs = NULL; lu->method_data = (char *)a; - return (1); + return 1; } static void @@ -179,8 +182,7 @@ static void by_dir_entry_free(BY_DIR_ENTRY *ent) { free(ent->dir); - if (ent->hashes) - sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free); + sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free); free(ent); } @@ -190,10 +192,8 @@ free_dir(X509_LOOKUP *lu) BY_DIR *a; a = (BY_DIR *)lu->method_data; - if (a->dirs != NULL) - sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free); - if (a->buffer != NULL) - BUF_MEM_free(a->buffer); + sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free); + BUF_MEM_free(a->buffer); free(a); } @@ -214,6 +214,7 @@ add_cert_dir(BY_DIR *ctx, const char *dir, int type) do { if ((*p == ':') || (*p == '\0')) { BY_DIR_ENTRY *ent; + ss = s; s = p + 1; len = p - ss; @@ -229,20 +230,20 @@ add_cert_dir(BY_DIR *ctx, const char *dir, int type) continue; if (ctx->dirs == NULL) { ctx->dirs = sk_BY_DIR_ENTRY_new_null(); - if (!ctx->dirs) { + if (ctx->dirs == NULL) { X509error(ERR_R_MALLOC_FAILURE); return 0; } } - ent = malloc(sizeof(BY_DIR_ENTRY)); - if (!ent) { + ent = malloc(sizeof(*ent)); + if (ent == NULL) { X509error(ERR_R_MALLOC_FAILURE); return 0; } ent->dir_type = type; ent->hashes = sk_BY_DIR_HASH_new(by_dir_hash_cmp); ent->dir = strndup(ss, (size_t)len); - if (!ent->dir || !ent->hashes) { + if (ent->dir == NULL || ent->hashes == NULL) { X509error(ERR_R_MALLOC_FAILURE); by_dir_entry_free(ent); return 0; @@ -280,7 +281,7 @@ get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, const char *postfix=""; if (name == NULL) - return (0); + return 0; stmp.type = type; if (type == X509_LU_X509) { @@ -310,6 +311,7 @@ get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, BY_DIR_ENTRY *ent; int idx; BY_DIR_HASH htmp, *hent; + ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i); j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1; if (!BUF_MEM_grow(b, j)) { @@ -358,10 +360,7 @@ get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, /* we have added it to the cache so now pull it out again */ CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); j = sk_X509_OBJECT_find(xl->store_ctx->objs, &stmp); - if (j != -1) - tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, j); - else - tmp = NULL; + tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, j); CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); /* If a CRL, update the last file suffix added for this */ @@ -371,16 +370,14 @@ get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, * Look for entry again in case another thread added * an entry first. */ - if (!hent) { + if (hent == NULL) { htmp.hash = h; idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp); - if (idx >= 0) - hent = sk_BY_DIR_HASH_value( - ent->hashes, idx); + hent = sk_BY_DIR_HASH_value(ent->hashes, idx); } - if (!hent) { - hent = malloc(sizeof(BY_DIR_HASH)); - if (!hent) { + if (hent == NULL) { + hent = malloc(sizeof(*hent)); + if (hent == NULL) { X509error(ERR_R_MALLOC_FAILURE); CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); ok = 0; @@ -406,17 +403,10 @@ get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, ok = 1; ret->type = tmp->type; memcpy(&ret->data, &tmp->data, sizeof(ret->data)); - /* - * If we were going to up the reference count, - * we would need to do it on a perl 'type' basis - */ - /* CRYPTO_add(&tmp->data.x509->references,1, - CRYPTO_LOCK_X509);*/ goto finish; } } finish: - if (b != NULL) - BUF_MEM_free(b); - return (ok); + BUF_MEM_free(b); + return ok; } diff --git a/crypto/x509/by_file.c b/crypto/x509/by_file.c index b2c8ef6..3116b7c 100644 --- a/crypto/x509/by_file.c +++ b/crypto/x509/by_file.c @@ -1,4 +1,4 @@ -/* $OpenBSD: by_file.c,v 1.21 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: by_file.c,v 1.25 2021/11/10 13:57:42 schwarze Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -64,9 +64,10 @@ #include #include #include -#include #include +#include "x509_lcl.h" + static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **ret); @@ -86,7 +87,7 @@ static X509_LOOKUP_METHOD x509_file_lookup = { X509_LOOKUP_METHOD * X509_LOOKUP_file(void) { - return (&x509_file_lookup); + return &x509_file_lookup; } static int @@ -114,7 +115,7 @@ by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, } break; } - return (ok); + return ok; } int @@ -125,9 +126,7 @@ X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type) int i, count = 0; X509 *x = NULL; - if (file == NULL) - return (1); - in = BIO_new(BIO_s_file_internal()); + in = BIO_new(BIO_s_file()); if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) { X509error(ERR_R_SYS_LIB); @@ -136,7 +135,7 @@ X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type) if (type == X509_FILETYPE_PEM) { for (;;) { - x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL); + x = PEM_read_bio_X509_AUX(in, NULL, NULL, ""); if (x == NULL) { if ((ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE) && (count > 0)) { @@ -172,7 +171,7 @@ X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type) err: X509_free(x); BIO_free(in); - return (ret); + return ret; } int @@ -183,9 +182,7 @@ X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type) int i, count = 0; X509_CRL *x = NULL; - if (file == NULL) - return (1); - in = BIO_new(BIO_s_file_internal()); + in = BIO_new(BIO_s_file()); if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) { X509error(ERR_R_SYS_LIB); @@ -194,7 +191,7 @@ X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type) if (type == X509_FILETYPE_PEM) { for (;;) { - x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); + x = PEM_read_bio_X509_CRL(in, NULL, NULL, ""); if (x == NULL) { if ((ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE) && (count > 0)) { @@ -228,10 +225,9 @@ X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type) goto err; } err: - if (x != NULL) - X509_CRL_free(x); + X509_CRL_free(x); BIO_free(in); - return (ret); + return ret; } int @@ -241,6 +237,7 @@ X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type) X509_INFO *itmp; BIO *in; int i, count = 0; + if (type != X509_FILETYPE_PEM) return X509_load_cert_file(ctx, file, type); in = BIO_new_file(file, "r"); @@ -248,7 +245,7 @@ X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type) X509error(ERR_R_SYS_LIB); return 0; } - inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL); + inf = PEM_X509_INFO_read_bio(in, NULL, NULL, ""); BIO_free(in); if (!inf) { X509error(ERR_R_PEM_LIB); @@ -265,6 +262,8 @@ X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type) count++; } } + if (count == 0) + X509error(X509_R_NO_CERTIFICATE_OR_CRL_FOUND); sk_X509_INFO_pop_free(inf, X509_INFO_free); return count; } diff --git a/crypto/x509/by_mem.c b/crypto/x509/by_mem.c index 34d4040..272877f 100644 --- a/crypto/x509/by_mem.c +++ b/crypto/x509/by_mem.c @@ -1,4 +1,4 @@ -/* $OpenBSD: by_mem.c,v 1.4 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: by_mem.c,v 1.5 2021/11/01 20:53:08 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -68,6 +68,8 @@ #include #include +#include "x509_lcl.h" + static int by_mem_ctrl(X509_LOOKUP *, int, const char *, long, char **); static X509_LOOKUP_METHOD x509_mem_lookup = { diff --git a/crypto/x509/ext_dat.h b/crypto/x509/ext_dat.h index 18d60b7..59815c9 100644 --- a/crypto/x509/ext_dat.h +++ b/crypto/x509/ext_dat.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ext_dat.h,v 1.3 2021/09/02 21:27:26 job Exp $ */ +/* $OpenBSD: ext_dat.h,v 1.4 2021/11/24 19:22:14 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -73,6 +73,7 @@ extern X509V3_EXT_METHOD v3_crl_hold, v3_pci; extern X509V3_EXT_METHOD v3_policy_mappings, v3_policy_constraints; extern X509V3_EXT_METHOD v3_name_constraints, v3_inhibit_anyp, v3_idp; extern const X509V3_EXT_METHOD v3_addr, v3_asid; +extern const X509V3_EXT_METHOD v3_ct_scts[3]; /* This table will be searched using OBJ_bsearch so it *must* kept in * order of the ext_nid values. @@ -129,6 +130,11 @@ static const X509V3_EXT_METHOD *standard_exts[] = { &v3_idp, &v3_alt[2], &v3_freshest_crl, +#ifndef OPENSSL_NO_CT + &v3_ct_scts[0], + &v3_ct_scts[1], + &v3_ct_scts[2], +#endif }; /* Number of standard extensions */ diff --git a/crypto/x509/pcy_cache.c b/crypto/x509/pcy_cache.c index 896ba7d..debca30 100644 --- a/crypto/x509/pcy_cache.c +++ b/crypto/x509/pcy_cache.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pcy_cache.c,v 1.1 2020/06/04 15:19:31 jsing Exp $ */ +/* $OpenBSD: pcy_cache.c,v 1.2 2021/11/01 20:53:08 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2004. */ @@ -60,6 +60,7 @@ #include #include "pcy_int.h" +#include "x509_lcl.h" static int policy_data_cmp(const X509_POLICY_DATA * const *a, const X509_POLICY_DATA * const *b); diff --git a/crypto/x509/pcy_map.c b/crypto/x509/pcy_map.c index 287a430..f2e5d32 100644 --- a/crypto/x509/pcy_map.c +++ b/crypto/x509/pcy_map.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pcy_map.c,v 1.1 2020/06/04 15:19:31 jsing Exp $ */ +/* $OpenBSD: pcy_map.c,v 1.2 2021/11/01 20:53:08 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2004. */ @@ -60,6 +60,7 @@ #include #include "pcy_int.h" +#include "x509_lcl.h" /* Set policy mapping entries in cache. * Note: this modifies the passed POLICY_MAPPINGS structure diff --git a/crypto/x509/pcy_tree.c b/crypto/x509/pcy_tree.c index d0f7cd1..284c08e 100644 --- a/crypto/x509/pcy_tree.c +++ b/crypto/x509/pcy_tree.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pcy_tree.c,v 1.1 2020/06/04 15:19:31 jsing Exp $ */ +/* $OpenBSD: pcy_tree.c,v 1.2 2021/11/01 20:53:08 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2004. */ @@ -60,6 +60,7 @@ #include #include "pcy_int.h" +#include "x509_lcl.h" /* Enable this to print out the complete policy tree at various point during * evaluation. diff --git a/crypto/x509/x509_addr.c b/crypto/x509/x509_addr.c index ccc06bb..0353538 100644 --- a/crypto/x509/x509_addr.c +++ b/crypto/x509/x509_addr.c @@ -1,16 +1,66 @@ +/* $OpenBSD: x509_addr.c,v 1.78 2022/03/16 11:44:36 tb Exp $ */ /* - * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * Contributed to the OpenSSL Project by the American Registry for + * Internet Numbers ("ARIN"). + */ +/* ==================================================================== + * Copyright (c) 2006-2016 The OpenSSL Project. 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 + * 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 + * licensing@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). */ /* * Implementation of RFC 3779 section 2.2. */ +#include #include #include #include @@ -23,7 +73,8 @@ #include #include -#include "ext_dat.h" +#include "bytestring.h" +#include "x509_lcl.h" #ifndef OPENSSL_NO_RFC3779 @@ -147,7 +198,6 @@ static const ASN1_TEMPLATE IPAddrBlocks_item_tt = { .item = &IPAddressFamily_it, }; -/* XXX: maybe special? */ static const ASN1_ITEM IPAddrBlocks_it = { .itype = ASN1_ITYPE_PRIMITIVE, .utype = -1, @@ -258,6 +308,60 @@ IPAddressFamily_free(IPAddressFamily *a) ASN1_item_free((ASN1_VALUE *)a, &IPAddressFamily_it); } +/* + * Convenience accessors for IPAddressFamily. + */ + +static int +IPAddressFamily_type(IPAddressFamily *af) +{ + /* XXX - can af->ipAddressChoice == NULL actually happen? */ + if (af == NULL || af->ipAddressChoice == NULL) + return -1; + + switch (af->ipAddressChoice->type) { + case IPAddressChoice_inherit: + case IPAddressChoice_addressesOrRanges: + return af->ipAddressChoice->type; + default: + return -1; + } +} + +static IPAddressOrRanges * +IPAddressFamily_addressesOrRanges(IPAddressFamily *af) +{ + if (IPAddressFamily_type(af) == IPAddressChoice_addressesOrRanges) + return af->ipAddressChoice->u.addressesOrRanges; + + return NULL; +} + +static ASN1_NULL * +IPAddressFamily_inheritance(IPAddressFamily *af) +{ + if (IPAddressFamily_type(af) == IPAddressChoice_inherit) + return af->ipAddressChoice->u.inherit; + + return NULL; +} + +static int +IPAddressFamily_set_inheritance(IPAddressFamily *af) +{ + if (IPAddressFamily_addressesOrRanges(af) != NULL) + return 0; + + if (IPAddressFamily_inheritance(af) != NULL) + return 1; + + if ((af->ipAddressChoice->u.inherit = ASN1_NULL_new()) == NULL) + return 0; + af->ipAddressChoice->type = IPAddressChoice_inherit; + + return 1; +} + /* * How much buffer space do we need for a raw address? */ @@ -280,47 +384,179 @@ length_from_afi(const unsigned afi) } /* - * Extract the AFI from an IPAddressFamily. + * Get AFI and optional SAFI from an IPAddressFamily. All three out arguments + * are optional; if |out_safi| is non-NULL, |safi_is_set| must be non-NULL. */ -unsigned int -X509v3_addr_get_afi(const IPAddressFamily *f) +static int +IPAddressFamily_afi_safi(const IPAddressFamily *af, uint16_t *out_afi, + uint8_t *out_safi, int *safi_is_set) { - if (f == NULL || - f->addressFamily == NULL || - f->addressFamily->data == NULL || - f->addressFamily->length < 2) + CBS cbs; + uint16_t afi; + uint8_t safi = 0; + int got_safi = 0; + + CBS_init(&cbs, af->addressFamily->data, af->addressFamily->length); + + if (!CBS_get_u16(&cbs, &afi)) return 0; - return (f->addressFamily->data[0] << 8) | f->addressFamily->data[1]; + + /* Fetch the optional SAFI. */ + if (CBS_len(&cbs) != 0) { + if (!CBS_get_u8(&cbs, &safi)) + return 0; + got_safi = 1; + } + + /* If there's anything left, it's garbage. */ + if (CBS_len(&cbs) != 0) + return 0; + + /* XXX - error on reserved AFI/SAFI? */ + + if (out_afi != NULL) + *out_afi = afi; + + if (out_safi != NULL) { + *out_safi = safi; + *safi_is_set = got_safi; + } + + return 1; +} + +static int +IPAddressFamily_afi(const IPAddressFamily *af, uint16_t *out_afi) +{ + return IPAddressFamily_afi_safi(af, out_afi, NULL, NULL); +} + +static int +IPAddressFamily_afi_is_valid(const IPAddressFamily *af) +{ + return IPAddressFamily_afi_safi(af, NULL, NULL, NULL); +} + +static int +IPAddressFamily_afi_length(const IPAddressFamily *af, int *out_length) +{ + uint16_t afi; + + *out_length = 0; + + if (!IPAddressFamily_afi(af, &afi)) + return 0; + + *out_length = length_from_afi(afi); + + return 1; +} + +#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) + +/* + * Sort comparison function for a sequence of IPAddressFamily. + * + * The last paragraph of RFC 3779 2.2.3.3 is slightly ambiguous about + * the ordering: I can read it as meaning that IPv6 without a SAFI + * comes before IPv4 with a SAFI, which seems pretty weird. The + * examples in appendix B suggest that the author intended the + * null-SAFI rule to apply only within a single AFI, which is what I + * would have expected and is what the following code implements. + */ +static int +IPAddressFamily_cmp(const IPAddressFamily *const *a_, + const IPAddressFamily *const *b_) +{ + const ASN1_OCTET_STRING *a = (*a_)->addressFamily; + const ASN1_OCTET_STRING *b = (*b_)->addressFamily; + int len, cmp; + + len = MINIMUM(a->length, b->length); + + if ((cmp = memcmp(a->data, b->data, len)) != 0) + return cmp; + + return a->length - b->length; +} + +static IPAddressFamily * +IPAddressFamily_find_in_parent(IPAddrBlocks *parent, IPAddressFamily *child_af) +{ + int index; + + (void)sk_IPAddressFamily_set_cmp_func(parent, IPAddressFamily_cmp); + + if ((index = sk_IPAddressFamily_find(parent, child_af)) < 0) + return NULL; + + return sk_IPAddressFamily_value(parent, index); } /* - * Expand the bitstring form of an address into a raw byte array. - * At the moment this is coded for simplicity, not speed. + * Extract the AFI from an IPAddressFamily. + * + * This is public API. It uses the reserved AFI 0 as an in-band error + * while it doesn't care about the reserved AFI 65535... + */ +unsigned int +X509v3_addr_get_afi(const IPAddressFamily *af) +{ + uint16_t afi; + + /* + * XXX are these NULL checks really sensible? If af is non-NULL, it + * should have both addressFamily and ipAddressChoice... + */ + if (af == NULL || af->addressFamily == NULL || + af->addressFamily->data == NULL) + return 0; + + if (!IPAddressFamily_afi(af, &afi)) + return 0; + + return afi; +} + +/* + * Expand the bitstring form (RFC 3779, section 2.1.2) of an address into + * a raw byte array. At the moment this is coded for simplicity, not speed. + * + * Unused bits in the last octet of |bs| and all bits in subsequent bytes + * of |addr| are set to 0 or 1 depending on whether |fill| is 0 or not. */ static int addr_expand(unsigned char *addr, const ASN1_BIT_STRING *bs, const int length, - const unsigned char fill) + uint8_t fill) { if (bs->length < 0 || bs->length > length) return 0; + + if (fill != 0) + fill = 0xff; + if (bs->length > 0) { + /* XXX - shouldn't this check ASN1_STRING_FLAG_BITS_LEFT? */ + uint8_t unused_bits = bs->flags & 7; + uint8_t mask = (1 << unused_bits) - 1; + memcpy(addr, bs->data, bs->length); - if ((bs->flags & 7) != 0) { - unsigned char mask = 0xFF >> (8 - (bs->flags & 7)); - if (fill == 0) - addr[bs->length - 1] &= ~mask; - else - addr[bs->length - 1] |= mask; - } + + if (fill == 0) + addr[bs->length - 1] &= ~mask; + else + addr[bs->length - 1] |= mask; } + memset(addr + bs->length, fill, length - bs->length); + return 1; } /* - * Extract the prefix length from a bitstring. + * Extract the prefix length from a bitstring: 8 * length - unused bits. */ -#define addr_prefixlen(bs) ((int) ((bs)->length * 8 - ((bs)->flags & 7))) +#define addr_prefix_len(bs) ((int) ((bs)->length * 8 - ((bs)->flags & 7))) /* * i2r handler for one address bitstring. @@ -372,29 +608,37 @@ static int i2r_IPAddressOrRanges(BIO *out, const int indent, const IPAddressOrRanges *aors, const unsigned afi) { + const IPAddressOrRange *aor; + const ASN1_BIT_STRING *prefix; + const IPAddressRange *range; int i; + for (i = 0; i < sk_IPAddressOrRange_num(aors); i++) { - const IPAddressOrRange *aor = sk_IPAddressOrRange_value(aors, i); + aor = sk_IPAddressOrRange_value(aors, i); + BIO_printf(out, "%*s", indent, ""); + switch (aor->type) { case IPAddressOrRange_addressPrefix: - if (!i2r_address(out, afi, 0x00, aor->u.addressPrefix)) + prefix = aor->u.addressPrefix; + + if (!i2r_address(out, afi, 0x00, prefix)) return 0; - BIO_printf(out, "/%d\n", - addr_prefixlen(aor->u.addressPrefix)); + BIO_printf(out, "/%d\n", addr_prefix_len(prefix)); continue; case IPAddressOrRange_addressRange: - if (!i2r_address(out, afi, 0x00, - aor->u.addressRange->min)) + range = aor->u.addressRange; + + if (!i2r_address(out, afi, 0x00, range->min)) return 0; BIO_puts(out, "-"); - if (!i2r_address(out, afi, 0xFF, - aor->u.addressRange->max)) + if (!i2r_address(out, afi, 0xff, range->max)) return 0; BIO_puts(out, "\n"); continue; } } + return 1; } @@ -406,10 +650,17 @@ i2r_IPAddrBlocks(const X509V3_EXT_METHOD *method, void *ext, BIO *out, int indent) { const IPAddrBlocks *addr = ext; - int i; + IPAddressFamily *af; + uint16_t afi; + uint8_t safi; + int i, safi_is_set; + for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { - IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); - const unsigned int afi = X509v3_addr_get_afi(f); + af = sk_IPAddressFamily_value(addr, i); + + if (!IPAddressFamily_afi_safi(af, &afi, &safi, &safi_is_set)) + goto print_addresses; + switch (afi) { case IANA_AFI_IPV4: BIO_printf(out, "%*sIPv4", indent, ""); @@ -421,8 +672,8 @@ i2r_IPAddrBlocks(const X509V3_EXT_METHOD *method, void *ext, BIO *out, BIO_printf(out, "%*sUnknown AFI %u", indent, "", afi); break; } - if (f->addressFamily->length > 2) { - switch (f->addressFamily->data[2]) { + if (safi_is_set) { + switch (safi) { case 1: BIO_puts(out, " (Unicast)"); break; @@ -448,23 +699,23 @@ i2r_IPAddrBlocks(const X509V3_EXT_METHOD *method, void *ext, BIO *out, BIO_puts(out, " (MPLS-labeled VPN)"); break; default: - BIO_printf(out, " (Unknown SAFI %u)", - (unsigned)f->addressFamily->data[2]); + BIO_printf(out, " (Unknown SAFI %u)", safi); break; } } - switch (f->ipAddressChoice->type) { + + print_addresses: + switch (IPAddressFamily_type(af)) { case IPAddressChoice_inherit: BIO_puts(out, ": inherit\n"); break; case IPAddressChoice_addressesOrRanges: BIO_puts(out, ":\n"); - if (!i2r_IPAddressOrRanges(out, - indent + 2, - f->ipAddressChoice-> - u.addressesOrRanges, afi)) + if (!i2r_IPAddressOrRanges(out, indent + 2, + IPAddressFamily_addressesOrRanges(af), afi)) return 0; break; + /* XXX - how should we handle -1 here? */ } } return 1; @@ -485,19 +736,19 @@ IPAddressOrRange_cmp(const IPAddressOrRange *a, const IPAddressOrRange *b, const int length) { unsigned char addr_a[ADDR_RAW_BUF_LEN], addr_b[ADDR_RAW_BUF_LEN]; - int prefixlen_a = 0, prefixlen_b = 0; + int prefix_len_a = 0, prefix_len_b = 0; int r; switch (a->type) { case IPAddressOrRange_addressPrefix: if (!addr_expand(addr_a, a->u.addressPrefix, length, 0x00)) return -1; - prefixlen_a = addr_prefixlen(a->u.addressPrefix); + prefix_len_a = addr_prefix_len(a->u.addressPrefix); break; case IPAddressOrRange_addressRange: if (!addr_expand(addr_a, a->u.addressRange->min, length, 0x00)) return -1; - prefixlen_a = length * 8; + prefix_len_a = length * 8; break; } @@ -505,19 +756,19 @@ IPAddressOrRange_cmp(const IPAddressOrRange *a, const IPAddressOrRange *b, case IPAddressOrRange_addressPrefix: if (!addr_expand(addr_b, b->u.addressPrefix, length, 0x00)) return -1; - prefixlen_b = addr_prefixlen(b->u.addressPrefix); + prefix_len_b = addr_prefix_len(b->u.addressPrefix); break; case IPAddressOrRange_addressRange: if (!addr_expand(addr_b, b->u.addressRange->min, length, 0x00)) return -1; - prefixlen_b = length * 8; + prefix_len_b = length * 8; break; } if ((r = memcmp(addr_a, addr_b, length)) != 0) return r; else - return prefixlen_a - prefixlen_b; + return prefix_len_a - prefix_len_b; } /* @@ -545,6 +796,8 @@ v6IPAddressOrRange_cmp(const IPAddressOrRange *const *a, /* * Calculate whether a range collapses to a prefix. * See last paragraph of RFC 3779 2.2.3.7. + * + * It's the caller's responsibility to ensure that min <= max. */ static int range_should_be_prefix(const unsigned char *min, const unsigned char *max, @@ -553,11 +806,9 @@ range_should_be_prefix(const unsigned char *min, const unsigned char *max, unsigned char mask; int i, j; - if (memcmp(min, max, length) <= 0) - return -1; for (i = 0; i < length && min[i] == max[i]; i++) continue; - for (j = length - 1; j >= 0 && min[j] == 0x00 && max[j] == 0xFF; j--) + for (j = length - 1; j >= 0 && min[j] == 0x00 && max[j] == 0xff; j--) continue; if (i < j) return -1; @@ -574,16 +825,16 @@ range_should_be_prefix(const unsigned char *min, const unsigned char *max, case 0x07: j = 5; break; - case 0x0F: + case 0x0f: j = 4; break; - case 0x1F: + case 0x1f: j = 3; break; - case 0x3F: + case 0x3f: j = 2; break; - case 0x7F: + case 0x7f: j = 1; break; default: @@ -600,24 +851,37 @@ range_should_be_prefix(const unsigned char *min, const unsigned char *max, */ static int make_addressPrefix(IPAddressOrRange **result, unsigned char *addr, - const int prefixlen) + unsigned int afi, int prefix_len) { - int bytelen = (prefixlen + 7) / 8, bitlen = prefixlen % 8; - IPAddressOrRange *aor = IPAddressOrRange_new(); + IPAddressOrRange *aor; + int afi_len, byte_len, bit_len, max_len; - if (aor == NULL) + if (prefix_len < 0) + return 0; + + max_len = 16; + if ((afi_len = length_from_afi(afi)) > 0) + max_len = afi_len; + if (prefix_len > 8 * max_len) + return 0; + + byte_len = (prefix_len + 7) / 8; + bit_len = prefix_len % 8; + + if ((aor = IPAddressOrRange_new()) == NULL) return 0; aor->type = IPAddressOrRange_addressPrefix; - if (aor->u.addressPrefix == NULL && - (aor->u.addressPrefix = ASN1_BIT_STRING_new()) == NULL) + if ((aor->u.addressPrefix = ASN1_BIT_STRING_new()) == NULL) goto err; - if (!ASN1_BIT_STRING_set(aor->u.addressPrefix, addr, bytelen)) + + if (!ASN1_BIT_STRING_set(aor->u.addressPrefix, addr, byte_len)) goto err; + aor->u.addressPrefix->flags &= ~7; aor->u.addressPrefix->flags |= ASN1_STRING_FLAG_BITS_LEFT; - if (bitlen > 0) { - aor->u.addressPrefix->data[bytelen - 1] &= ~(0xFF >> bitlen); - aor->u.addressPrefix->flags |= 8 - bitlen; + if (bit_len > 0) { + aor->u.addressPrefix->data[byte_len - 1] &= ~(0xff >> bit_len); + aor->u.addressPrefix->flags |= 8 - bit_len; } *result = aor; @@ -635,25 +899,22 @@ make_addressPrefix(IPAddressOrRange **result, unsigned char *addr, */ static int make_addressRange(IPAddressOrRange **result, unsigned char *min, - unsigned char *max, const int length) + unsigned char *max, unsigned int afi, int length) { IPAddressOrRange *aor; - int i, prefixlen; + int i, prefix_len; - if ((prefixlen = range_should_be_prefix(min, max, length)) >= 0) - return make_addressPrefix(result, min, prefixlen); + if (memcmp(min, max, length) > 0) + return 0; + + if ((prefix_len = range_should_be_prefix(min, max, length)) >= 0) + return make_addressPrefix(result, min, afi, prefix_len); if ((aor = IPAddressOrRange_new()) == NULL) return 0; aor->type = IPAddressOrRange_addressRange; if ((aor->u.addressRange = IPAddressRange_new()) == NULL) goto err; - if (aor->u.addressRange->min == NULL && - (aor->u.addressRange->min = ASN1_BIT_STRING_new()) == NULL) - goto err; - if (aor->u.addressRange->max == NULL && - (aor->u.addressRange->max = ASN1_BIT_STRING_new()) == NULL) - goto err; for (i = length; i > 0 && min[i - 1] == 0x00; --i) continue; @@ -664,12 +925,12 @@ make_addressRange(IPAddressOrRange **result, unsigned char *min, if (i > 0) { unsigned char b = min[i - 1]; int j = 1; - while ((b & (0xFFU >> j)) != 0) + while ((b & (0xffU >> j)) != 0) ++j; aor->u.addressRange->min->flags |= 8 - j; } - for (i = length; i > 0 && max[i - 1] == 0xFF; --i) + for (i = length; i > 0 && max[i - 1] == 0xff; --i) continue; if (!ASN1_BIT_STRING_set(aor->u.addressRange->max, max, i)) goto err; @@ -678,7 +939,7 @@ make_addressRange(IPAddressOrRange **result, unsigned char *min, if (i > 0) { unsigned char b = max[i - 1]; int j = 1; - while ((b & (0xFFU >> j)) != (0xFFU >> j)) + while ((b & (0xffU >> j)) != (0xffU >> j)) ++j; aor->u.addressRange->max->flags |= 8 - j; } @@ -698,44 +959,54 @@ static IPAddressFamily * make_IPAddressFamily(IPAddrBlocks *addr, const unsigned afi, const unsigned *safi) { - IPAddressFamily *f; - unsigned char key[3]; - int keylen; + IPAddressFamily *af = NULL; + CBB cbb; + CBS cbs; + uint8_t *key = NULL; + size_t keylen; int i; - key[0] = (afi >> 8) & 0xFF; - key[1] = afi & 0xFF; + if (!CBB_init(&cbb, 0)) + goto err; + + /* XXX - should afi <= 65535 and *safi <= 255 be checked here? */ + + if (!CBB_add_u16(&cbb, afi)) + goto err; if (safi != NULL) { - key[2] = *safi & 0xFF; - keylen = 3; - } else { - keylen = 2; + if (!CBB_add_u8(&cbb, *safi)) + goto err; } + if (!CBB_finish(&cbb, &key, &keylen)) + goto err; + for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { - f = sk_IPAddressFamily_value(addr, i); - if (f->addressFamily->length == keylen && - !memcmp(f->addressFamily->data, key, keylen)) - return f; + af = sk_IPAddressFamily_value(addr, i); + + CBS_init(&cbs, af->addressFamily->data, + af->addressFamily->length); + if (CBS_mem_equal(&cbs, key, keylen)) + goto done; } - if ((f = IPAddressFamily_new()) == NULL) + if ((af = IPAddressFamily_new()) == NULL) goto err; - if (f->ipAddressChoice == NULL && - (f->ipAddressChoice = IPAddressChoice_new()) == NULL) + if (!ASN1_OCTET_STRING_set(af->addressFamily, key, keylen)) goto err; - if (f->addressFamily == NULL && - (f->addressFamily = ASN1_OCTET_STRING_new()) == NULL) - goto err; - if (!ASN1_OCTET_STRING_set(f->addressFamily, key, keylen)) - goto err; - if (!sk_IPAddressFamily_push(addr, f)) + if (!sk_IPAddressFamily_push(addr, af)) goto err; - return f; + done: + free(key); + + return af; err: - IPAddressFamily_free(f); + CBB_cleanup(&cbb); + free(key); + IPAddressFamily_free(af); + return NULL; } @@ -746,20 +1017,12 @@ int X509v3_addr_add_inherit(IPAddrBlocks *addr, const unsigned afi, const unsigned *safi) { - IPAddressFamily *f = make_IPAddressFamily(addr, afi, safi); - if (f == NULL || - f->ipAddressChoice == NULL || - (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges && - f->ipAddressChoice->u.addressesOrRanges != NULL)) + IPAddressFamily *af; + + if ((af = make_IPAddressFamily(addr, afi, safi)) == NULL) return 0; - if (f->ipAddressChoice->type == IPAddressChoice_inherit && - f->ipAddressChoice->u.inherit != NULL) - return 1; - if (f->ipAddressChoice->u.inherit == NULL && - (f->ipAddressChoice->u.inherit = ASN1_NULL_new()) == NULL) - return 0; - f->ipAddressChoice->type = IPAddressChoice_inherit; - return 1; + + return IPAddressFamily_set_inheritance(af); } /* @@ -769,20 +1032,21 @@ static IPAddressOrRanges * make_prefix_or_range(IPAddrBlocks *addr, const unsigned afi, const unsigned *safi) { - IPAddressFamily *f = make_IPAddressFamily(addr, afi, safi); + IPAddressFamily *af; IPAddressOrRanges *aors = NULL; - if (f == NULL || - f->ipAddressChoice == NULL || - (f->ipAddressChoice->type == IPAddressChoice_inherit && - f->ipAddressChoice->u.inherit != NULL)) + if ((af = make_IPAddressFamily(addr, afi, safi)) == NULL) return NULL; - if (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges) - aors = f->ipAddressChoice->u.addressesOrRanges; - if (aors != NULL) + + if (IPAddressFamily_inheritance(af) != NULL) + return NULL; + + if ((aors = IPAddressFamily_addressesOrRanges(af)) != NULL) return aors; + if ((aors = sk_IPAddressOrRange_new_null()) == NULL) return NULL; + switch (afi) { case IANA_AFI_IPV4: (void)sk_IPAddressOrRange_set_cmp_func(aors, @@ -793,8 +1057,10 @@ make_prefix_or_range(IPAddrBlocks *addr, const unsigned afi, v6IPAddressOrRange_cmp); break; } - f->ipAddressChoice->type = IPAddressChoice_addressesOrRanges; - f->ipAddressChoice->u.addressesOrRanges = aors; + + af->ipAddressChoice->type = IPAddressChoice_addressesOrRanges; + af->ipAddressChoice->u.addressesOrRanges = aors; + return aors; } @@ -803,16 +1069,23 @@ make_prefix_or_range(IPAddrBlocks *addr, const unsigned afi, */ int X509v3_addr_add_prefix(IPAddrBlocks *addr, const unsigned afi, - const unsigned *safi, unsigned char *a, const int prefixlen) + const unsigned *safi, unsigned char *a, const int prefix_len) { - IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, safi); + IPAddressOrRanges *aors; IPAddressOrRange *aor; - if (aors == NULL || !make_addressPrefix(&aor, a, prefixlen)) + + if ((aors = make_prefix_or_range(addr, afi, safi)) == NULL) return 0; - if (sk_IPAddressOrRange_push(aors, aor)) - return 1; - IPAddressOrRange_free(aor); - return 0; + + if (!make_addressPrefix(&aor, a, afi, prefix_len)) + return 0; + + if (sk_IPAddressOrRange_push(aors, aor) <= 0) { + IPAddressOrRange_free(aor); + return 0; + } + + return 1; } /* @@ -822,17 +1095,41 @@ int X509v3_addr_add_range(IPAddrBlocks *addr, const unsigned afi, const unsigned *safi, unsigned char *min, unsigned char *max) { - IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, safi); + IPAddressOrRanges *aors; IPAddressOrRange *aor; - int length = length_from_afi(afi); - if (aors == NULL) + int length; + + if ((aors = make_prefix_or_range(addr, afi, safi)) == NULL) return 0; - if (!make_addressRange(&aor, min, max, length)) + + length = length_from_afi(afi); + + if (!make_addressRange(&aor, min, max, afi, length)) return 0; - if (sk_IPAddressOrRange_push(aors, aor)) + + if (sk_IPAddressOrRange_push(aors, aor) <= 0) { + IPAddressOrRange_free(aor); + return 0; + } + + return 1; +} + +static int +extract_min_max_bitstr(IPAddressOrRange *aor, ASN1_BIT_STRING **out_min, + ASN1_BIT_STRING **out_max) +{ + switch (aor->type) { + case IPAddressOrRange_addressPrefix: + *out_min = *out_max = aor->u.addressPrefix; return 1; - IPAddressOrRange_free(aor); - return 0; + case IPAddressOrRange_addressRange: + *out_min = aor->u.addressRange->min; + *out_max = aor->u.addressRange->max; + return 1; + default: + return 0; + } } /* @@ -842,18 +1139,18 @@ static int extract_min_max(IPAddressOrRange *aor, unsigned char *min, unsigned char *max, int length) { + ASN1_BIT_STRING *min_bitstr, *max_bitstr; + if (aor == NULL || min == NULL || max == NULL) return 0; - switch (aor->type) { - case IPAddressOrRange_addressPrefix: - return (addr_expand(min, aor->u.addressPrefix, length, 0x00) && - addr_expand(max, aor->u.addressPrefix, length, 0xFF)); - case IPAddressOrRange_addressRange: - return (addr_expand(min, aor->u.addressRange->min, length, - 0x00) && - addr_expand(max, aor->u.addressRange->max, length, 0xFF)); - } - return 0; + + if (!extract_min_max_bitstr(aor, &min_bitstr, &max_bitstr)) + return 0; + + if (!addr_expand(min, min_bitstr, length, 0)) + return 0; + + return addr_expand(max, max_bitstr, length, 1); } /* @@ -863,36 +1160,18 @@ int X509v3_addr_get_range(IPAddressOrRange *aor, const unsigned afi, unsigned char *min, unsigned char *max, const int length) { - int afi_length = length_from_afi(afi); - if (aor == NULL || min == NULL || max == NULL || - afi_length == 0 || length < afi_length || - (aor->type != IPAddressOrRange_addressPrefix && - aor->type != IPAddressOrRange_addressRange) || - !extract_min_max(aor, min, max, afi_length)) + int afi_len; + + if ((afi_len = length_from_afi(afi)) == 0) return 0; - return afi_length; -} + if (length < afi_len) + return 0; -/* - * Sort comparison function for a sequence of IPAddressFamily. - * - * The last paragraph of RFC 3779 2.2.3.3 is slightly ambiguous about - * the ordering: I can read it as meaning that IPv6 without a SAFI - * comes before IPv4 with a SAFI, which seems pretty weird. The - * examples in appendix B suggest that the author intended the - * null-SAFI rule to apply only within a single AFI, which is what I - * would have expected and is what the following code implements. - */ -static int -IPAddressFamily_cmp(const IPAddressFamily *const *a_, - const IPAddressFamily *const *b_) -{ - const ASN1_OCTET_STRING *a = (*a_)->addressFamily; - const ASN1_OCTET_STRING *b = (*b_)->addressFamily; - int len = ((a->length <= b->length) ? a->length : b->length); - int cmp = memcmp(a->data, b->data, len); - return cmp ? cmp : a->length - b->length; + if (!extract_min_max(aor, min, max, afi_len)) + return 0; + + return afi_len; } /* @@ -903,8 +1182,10 @@ X509v3_addr_is_canonical(IPAddrBlocks *addr) { unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN]; + IPAddressFamily *af; IPAddressOrRanges *aors; - int i, j, k; + IPAddressOrRange *aor, *aor_a, *aor_b; + int i, j, k, length; /* * Empty extension is canonical. @@ -918,6 +1199,13 @@ X509v3_addr_is_canonical(IPAddrBlocks *addr) for (i = 0; i < sk_IPAddressFamily_num(addr) - 1; i++) { const IPAddressFamily *a = sk_IPAddressFamily_value(addr, i); const IPAddressFamily *b = sk_IPAddressFamily_value(addr, i + 1); + + /* Check that both have valid AFIs before comparing them. */ + if (!IPAddressFamily_afi_is_valid(a)) + return 0; + if (!IPAddressFamily_afi_is_valid(b)) + return 0; + if (IPAddressFamily_cmp(&a, &b) >= 0) return 0; } @@ -926,38 +1214,37 @@ X509v3_addr_is_canonical(IPAddrBlocks *addr) * Top level's ok, now check each address family. */ for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { - IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); - int length = length_from_afi(X509v3_addr_get_afi(f)); + af = sk_IPAddressFamily_value(addr, i); + + if (!IPAddressFamily_afi_length(af, &length)) + return 0; /* - * Inheritance is canonical. Anything other than inheritance - * or a SEQUENCE OF IPAddressOrRange is an ASN.1 error or - * something. + * If this family has an inheritance element, it is canonical. */ - if (f == NULL || f->ipAddressChoice == NULL) - return 0; - switch (f->ipAddressChoice->type) { - case IPAddressChoice_inherit: + if (IPAddressFamily_inheritance(af) != NULL) continue; - case IPAddressChoice_addressesOrRanges: - break; - default: - return 0; - } /* - * It's an IPAddressOrRanges sequence, check it. + * If this family has neither an inheritance element nor an + * addressesOrRanges, we don't know what this is. */ - aors = f->ipAddressChoice->u.addressesOrRanges; + if ((aors = IPAddressFamily_addressesOrRanges(af)) == NULL) + return 0; + if (sk_IPAddressOrRange_num(aors) == 0) return 0; - for (j = 0; j < sk_IPAddressOrRange_num(aors) - 1; j++) { - IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); - IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, - j + 1); - if (!extract_min_max(a, a_min, a_max, length) || - !extract_min_max(b, b_min, b_max, length)) + for (j = 0; j < sk_IPAddressOrRange_num(aors) - 1; j++) { + aor_a = sk_IPAddressOrRange_value(aors, j); + aor_b = sk_IPAddressOrRange_value(aors, j + 1); + + /* + * XXX - check that both are either a prefix or a range. + */ + + if (!extract_min_max(aor_a, a_min, a_max, length) || + !extract_min_max(aor_b, b_min, b_max, length)) return 0; /* @@ -970,8 +1257,8 @@ X509v3_addr_is_canonical(IPAddrBlocks *addr) return 0; /* - * Punt if adjacent or overlapping. Check for adjacency by - * subtracting one from b_min first. + * Punt if adjacent or overlapping. Check for adjacency + * by subtracting one from b_min first. */ for (k = length - 1; k >= 0 && b_min[k]-- == 0x00; k--) continue; @@ -981,27 +1268,25 @@ X509v3_addr_is_canonical(IPAddrBlocks *addr) /* * Check for range that should be expressed as a prefix. */ - if (a->type == IPAddressOrRange_addressRange && - range_should_be_prefix(a_min, a_max, length) >= 0) + if (aor_a->type == IPAddressOrRange_addressPrefix) + continue; + + if (range_should_be_prefix(a_min, a_max, length) >= 0) return 0; } /* - * Check range to see if it's inverted or should be a + * Check final range to see if it's inverted or should be a * prefix. */ - j = sk_IPAddressOrRange_num(aors) - 1; - { - IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); - if (a != NULL && - a->type == IPAddressOrRange_addressRange) { - if (!extract_min_max(a, a_min, a_max, length)) - return 0; - if (memcmp(a_min, a_max, length) > 0 || - range_should_be_prefix(a_min, a_max, - length) >= 0) - return 0; - } + aor = sk_IPAddressOrRange_value(aors, j); + if (aor->type == IPAddressOrRange_addressRange) { + if (!extract_min_max(aor, a_min, a_max, length)) + return 0; + if (memcmp(a_min, a_max, length) > 0) + return 0; + if (range_should_be_prefix(a_min, a_max, length) >= 0) + return 0; } } @@ -1017,7 +1302,12 @@ X509v3_addr_is_canonical(IPAddrBlocks *addr) static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors, const unsigned afi) { - int i, j, length = length_from_afi(afi); + IPAddressOrRange *a, *b, *merged; + unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; + unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN]; + int i, j, length; + + length = length_from_afi(afi); /* * Sort the IPAddressOrRanges sequence. @@ -1028,10 +1318,8 @@ IPAddressOrRanges_canonize(IPAddressOrRanges *aors, const unsigned afi) * Clean up representation issues, punt on duplicates or overlaps. */ for (i = 0; i < sk_IPAddressOrRange_num(aors) - 1; i++) { - IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, i); - IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, i + 1); - unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; - unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN]; + a = sk_IPAddressOrRange_value(aors, i); + b = sk_IPAddressOrRange_value(aors, i + 1); if (!extract_min_max(a, a_min, a_max, length) || !extract_min_max(b, b_min, b_max, length)) @@ -1056,33 +1344,28 @@ IPAddressOrRanges_canonize(IPAddressOrRanges *aors, const unsigned afi) */ for (j = length - 1; j >= 0 && b_min[j]-- == 0x00; j--) continue; - if (memcmp(a_max, b_min, length) == 0) { - IPAddressOrRange *merged; - if (!make_addressRange(&merged, a_min, b_max, length)) - return 0; - (void)sk_IPAddressOrRange_set(aors, i, merged); - (void)sk_IPAddressOrRange_delete(aors, i + 1); - IPAddressOrRange_free(a); - IPAddressOrRange_free(b); - --i; + + if (memcmp(a_max, b_min, length) != 0) continue; - } + + if (!make_addressRange(&merged, a_min, b_max, afi, length)) + return 0; + sk_IPAddressOrRange_set(aors, i, merged); + (void)sk_IPAddressOrRange_delete(aors, i + 1); + IPAddressOrRange_free(a); + IPAddressOrRange_free(b); + i--; } /* * Check for inverted final range. */ - j = sk_IPAddressOrRange_num(aors) - 1; - { - IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); - if (a != NULL && a->type == IPAddressOrRange_addressRange) { - unsigned char a_min[ADDR_RAW_BUF_LEN], - a_max[ADDR_RAW_BUF_LEN]; - if (!extract_min_max(a, a_min, a_max, length)) - return 0; - if (memcmp(a_min, a_max, length) > 0) - return 0; - } + a = sk_IPAddressOrRange_value(aors, i); + if (a != NULL && a->type == IPAddressOrRange_addressRange) { + if (!extract_min_max(a, a_min, a_max, length)) + return 0; + if (memcmp(a_min, a_max, length) > 0) + return 0; } return 1; @@ -1094,19 +1377,29 @@ IPAddressOrRanges_canonize(IPAddressOrRanges *aors, const unsigned afi) int X509v3_addr_canonize(IPAddrBlocks *addr) { + IPAddressFamily *af; + IPAddressOrRanges *aors; + uint16_t afi; int i; + for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { - IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); - if (f->ipAddressChoice->type == - IPAddressChoice_addressesOrRanges && - !IPAddressOrRanges_canonize(f->ipAddressChoice->u.addressesOrRanges, - X509v3_addr_get_afi(f))) + af = sk_IPAddressFamily_value(addr, i); + + /* Check AFI/SAFI here - IPAddressFamily_cmp() can't error. */ + if (!IPAddressFamily_afi(af, &afi)) + return 0; + + if ((aors = IPAddressFamily_addressesOrRanges(af)) == NULL) + continue; + + if (!IPAddressOrRanges_canonize(aors, afi)) return 0; } + (void)sk_IPAddressFamily_set_cmp_func(addr, IPAddressFamily_cmp); sk_IPAddressFamily_sort(addr); - OPENSSL_assert(X509v3_addr_is_canonical(addr)); - return 1; + + return X509v3_addr_is_canonical(addr); } /* @@ -1132,7 +1425,8 @@ v2i_IPAddrBlocks(const struct v3_ext_method *method, struct v3_ext_ctx *ctx, unsigned char min[ADDR_RAW_BUF_LEN], max[ADDR_RAW_BUF_LEN]; unsigned afi, *safi = NULL, safi_; const char *addr_chars = NULL; - int prefixlen, i1, i2, delim, length; + const char *errstr; + int prefix_len, i1, i2, delim, length; if (!name_cmp(val->name, "IPv4")) { afi = IANA_AFI_IPV4; @@ -1166,14 +1460,44 @@ v2i_IPAddrBlocks(const struct v3_ext_method *method, struct v3_ext_ctx *ctx, * the other input values. */ if (safi != NULL) { - *safi = strtoul(val->value, &t, 0); - t += strspn(t, " \t"); - if (*safi > 0xFF || *t++ != ':') { + unsigned long parsed_safi; + int saved_errno = errno; + + errno = 0; + parsed_safi = strtoul(val->value, &t, 0); + + /* Value must be present, then a tab, space or colon. */ + if (val->value[0] == '\0' || + (*t != '\t' && *t != ' ' && *t != ':')) { X509V3error(X509V3_R_INVALID_SAFI); X509V3_conf_err(val); goto err; } + /* Range and overflow check. */ + if ((errno == ERANGE && parsed_safi == ULONG_MAX) || + parsed_safi > 0xff) { + X509V3error(X509V3_R_INVALID_SAFI); + X509V3_conf_err(val); + goto err; + } + errno = saved_errno; + + *safi = parsed_safi; + + /* Check possible whitespace is followed by a colon. */ t += strspn(t, " \t"); + if (*t != ':') { + X509V3error(X509V3_R_INVALID_SAFI); + X509V3_conf_err(val); + goto err; + } + + /* Skip over colon. */ + t++; + + /* Then over any trailing whitespace. */ + t += strspn(t, " \t"); + s = strdup(t); } else { s = strdup(val->value); @@ -1211,14 +1535,17 @@ v2i_IPAddrBlocks(const struct v3_ext_method *method, struct v3_ext_ctx *ctx, switch (delim) { case '/': - prefixlen = (int)strtoul(s + i2, &t, 10); - if (t == s + i2 || *t != '\0') { + /* length contains the size of the address in bytes. */ + if (length != 4 && length != 16) + goto err; + prefix_len = strtonum(s + i2, 0, 8 * length, &errstr); + if (errstr != NULL) { X509V3error(X509V3_R_EXTENSION_VALUE_ERROR); X509V3_conf_err(val); goto err; } if (!X509v3_addr_add_prefix(addr, afi, safi, min, - prefixlen)) { + prefix_len)) { X509V3error(ERR_R_MALLOC_FAILURE); goto err; } @@ -1280,44 +1607,55 @@ v2i_IPAddrBlocks(const struct v3_ext_method *method, struct v3_ext_ctx *ctx, * OpenSSL dispatch */ const X509V3_EXT_METHOD v3_addr = { - NID_sbgp_ipAddrBlock, /* nid */ - 0, /* flags */ - &IPAddrBlocks_it, - 0, 0, 0, 0, /* old functions, ignored */ - 0, /* i2s */ - 0, /* s2i */ - 0, /* i2v */ - v2i_IPAddrBlocks, /* v2i */ - i2r_IPAddrBlocks, /* i2r */ - 0, /* r2i */ - NULL /* extension-specific data */ + .ext_nid = NID_sbgp_ipAddrBlock, + .ext_flags = 0, + .it = &IPAddrBlocks_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = NULL, + .v2i = v2i_IPAddrBlocks, + .i2r = i2r_IPAddrBlocks, + .r2i = NULL, + .usr_data = NULL, }; /* - * Figure out whether extension sues inheritance. + * Figure out whether extension uses inheritance. */ int X509v3_addr_inherits(IPAddrBlocks *addr) { + IPAddressFamily *af; int i; + if (addr == NULL) return 0; + for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { - IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); - if (f->ipAddressChoice->type == IPAddressChoice_inherit) + af = sk_IPAddressFamily_value(addr, i); + + if (IPAddressFamily_inheritance(af) != NULL) return 1; } + return 0; } /* * Figure out whether parent contains child. + * + * This only works correctly if both parent and child are in canonical form. */ static int addr_contains(IPAddressOrRanges *parent, IPAddressOrRanges *child, int length) { - unsigned char p_min[ADDR_RAW_BUF_LEN], p_max[ADDR_RAW_BUF_LEN]; - unsigned char c_min[ADDR_RAW_BUF_LEN], c_max[ADDR_RAW_BUF_LEN]; + IPAddressOrRange *child_aor, *parent_aor; + uint8_t parent_min[ADDR_RAW_BUF_LEN], parent_max[ADDR_RAW_BUF_LEN]; + uint8_t child_min[ADDR_RAW_BUF_LEN], child_max[ADDR_RAW_BUF_LEN]; int p, c; if (child == NULL || parent == child) @@ -1327,18 +1665,24 @@ addr_contains(IPAddressOrRanges *parent, IPAddressOrRanges *child, int length) p = 0; for (c = 0; c < sk_IPAddressOrRange_num(child); c++) { - if (!extract_min_max(sk_IPAddressOrRange_value(child, c), - c_min, c_max, length)) - return -1; + child_aor = sk_IPAddressOrRange_value(child, c); + + if (!extract_min_max(child_aor, child_min, child_max, length)) + return 0; + for (;; p++) { if (p >= sk_IPAddressOrRange_num(parent)) return 0; - if (!extract_min_max(sk_IPAddressOrRange_value(parent, - p), p_min, p_max, length)) + + parent_aor = sk_IPAddressOrRange_value(parent, p); + + if (!extract_min_max(parent_aor, parent_min, parent_max, + length)) return 0; - if (memcmp(p_max, c_max, length) < 0) + + if (memcmp(parent_max, child_max, length) < 0) continue; - if (memcmp(p_min, c_min, length) > 0) + if (memcmp(parent_min, child_min, length) > 0) return 0; break; } @@ -1348,48 +1692,54 @@ addr_contains(IPAddressOrRanges *parent, IPAddressOrRanges *child, int length) } /* - * Test whether a is a subset of b. + * Test whether |child| is a subset of |parent|. */ int -X509v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b) +X509v3_addr_subset(IPAddrBlocks *child, IPAddrBlocks *parent) { - int i; - if (a == NULL || a == b) + IPAddressFamily *child_af, *parent_af; + IPAddressOrRanges *child_aor, *parent_aor; + int i, length; + + if (child == NULL || child == parent) return 1; - if (b == NULL || X509v3_addr_inherits(a) || X509v3_addr_inherits(b)) + if (parent == NULL) return 0; - (void)sk_IPAddressFamily_set_cmp_func(b, IPAddressFamily_cmp); - for (i = 0; i < sk_IPAddressFamily_num(a); i++) { - IPAddressFamily *fa = sk_IPAddressFamily_value(a, i); - int j = sk_IPAddressFamily_find(b, fa); - IPAddressFamily *fb; - fb = sk_IPAddressFamily_value(b, j); - if (fb == NULL) + + if (X509v3_addr_inherits(child) || X509v3_addr_inherits(parent)) + return 0; + + for (i = 0; i < sk_IPAddressFamily_num(child); i++) { + child_af = sk_IPAddressFamily_value(child, i); + + parent_af = IPAddressFamily_find_in_parent(parent, child_af); + if (parent_af == NULL) return 0; - if (!addr_contains(fb->ipAddressChoice->u.addressesOrRanges, - fa->ipAddressChoice->u.addressesOrRanges, - length_from_afi(X509v3_addr_get_afi(fb)))) + + if (!IPAddressFamily_afi_length(parent_af, &length)) + return 0; + + child_aor = IPAddressFamily_addressesOrRanges(child_af); + parent_aor = IPAddressFamily_addressesOrRanges(parent_af); + + if (!addr_contains(parent_aor, child_aor, length)) return 0; } return 1; } -/* - * Validation error handling via callback. - */ -#define validation_err(_err_) \ - do { \ - if (ctx != NULL) { \ - ctx->error = _err_; \ - ctx->error_depth = i; \ - ctx->current_cert = x; \ - ret = ctx->verify_cb(0, ctx); \ - } else { \ - ret = 0; \ - } \ - if (!ret) \ - goto done; \ - } while (0) +static int +verify_error(X509_STORE_CTX *ctx, X509 *cert, int error, int depth) +{ + if (ctx == NULL) + return 0; + + ctx->current_cert = cert; + ctx->error = error; + ctx->error_depth = depth; + + return ctx->verify_cb(0, ctx); +} /* * Core code for RFC 3779 2.3 path validation. @@ -1400,33 +1750,46 @@ X509v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b) * X509_V_OK. */ static int -addr_validate_path_internal(X509_STORE_CTX *ctx, STACK_OF(X509)*chain, +addr_validate_path_internal(X509_STORE_CTX *ctx, STACK_OF(X509) *chain, IPAddrBlocks *ext) { - IPAddrBlocks *child = NULL; - int i, j, ret = 1; - X509 *x; + IPAddrBlocks *child = NULL, *parent = NULL; + IPAddressFamily *child_af, *parent_af; + IPAddressOrRanges *child_aor, *parent_aor; + X509 *cert = NULL; + int depth = -1; + int i; + unsigned int length; + int ret = 1; - OPENSSL_assert(chain != NULL && sk_X509_num(chain) > 0); - OPENSSL_assert(ctx != NULL || ext != NULL); - OPENSSL_assert(ctx == NULL || ctx->verify_cb != NULL); + /* We need a non-empty chain to test against. */ + if (sk_X509_num(chain) <= 0) + goto err; + /* We need either a store ctx or an extension to work with. */ + if (ctx == NULL && ext == NULL) + goto err; + /* If there is a store ctx, it needs a verify_cb. */ + if (ctx != NULL && ctx->verify_cb == NULL) + goto err; /* * Figure out where to start. If we don't have an extension to check, * we're done. Otherwise, check canonical form and set up for walking * up the chain. */ - if (ext != NULL) { - i = -1; - x = NULL; - } else { - i = 0; - x = sk_X509_value(chain, i); - if ((ext = x->rfc3779_addr) == NULL) + if (ext == NULL) { + depth = 0; + cert = sk_X509_value(chain, depth); + if ((ext = cert->rfc3779_addr) == NULL) goto done; } - if (!X509v3_addr_is_canonical(ext)) - validation_err(X509_V_ERR_INVALID_EXTENSION); + + if (!X509v3_addr_is_canonical(ext)) { + if ((ret = verify_error(ctx, cert, + X509_V_ERR_INVALID_EXTENSION, depth)) == 0) + goto done; + } + (void)sk_IPAddressFamily_set_cmp_func(ext, IPAddressFamily_cmp); if ((child = sk_IPAddressFamily_dup(ext)) == NULL) { X509V3error(ERR_R_MALLOC_FAILURE); @@ -1440,71 +1803,122 @@ addr_validate_path_internal(X509_STORE_CTX *ctx, STACK_OF(X509)*chain, * Now walk up the chain. No cert may list resources that its parent * doesn't list. */ - for (i++; i < sk_X509_num(chain); i++) { - x = sk_X509_value(chain, i); - if (!X509v3_addr_is_canonical(x->rfc3779_addr)) - validation_err(X509_V_ERR_INVALID_EXTENSION); - if (x->rfc3779_addr == NULL) { - for (j = 0; j < sk_IPAddressFamily_num(child); j++) { - IPAddressFamily *fc = sk_IPAddressFamily_value(child, - j); - if (fc->ipAddressChoice->type != - IPAddressChoice_inherit) { - validation_err(X509_V_ERR_UNNESTED_RESOURCE); - break; - } + for (depth++; depth < sk_X509_num(chain); depth++) { + cert = sk_X509_value(chain, depth); + + if ((parent = cert->rfc3779_addr) == NULL) { + for (i = 0; i < sk_IPAddressFamily_num(child); i++) { + child_af = sk_IPAddressFamily_value(child, i); + + if (IPAddressFamily_inheritance(child_af) != + NULL) + continue; + + if ((ret = verify_error(ctx, cert, + X509_V_ERR_UNNESTED_RESOURCE, depth)) == 0) + goto done; + break; } continue; } - (void)sk_IPAddressFamily_set_cmp_func(x->rfc3779_addr, - IPAddressFamily_cmp); - for (j = 0; j < sk_IPAddressFamily_num(child); j++) { - IPAddressFamily *fc = sk_IPAddressFamily_value(child, j); - int k = sk_IPAddressFamily_find(x->rfc3779_addr, fc); - IPAddressFamily *fp = - sk_IPAddressFamily_value(x->rfc3779_addr, k); - if (fp == NULL) { - if (fc->ipAddressChoice->type == - IPAddressChoice_addressesOrRanges) { - validation_err(X509_V_ERR_UNNESTED_RESOURCE); - break; - } + + if (!X509v3_addr_is_canonical(parent)) { + if ((ret = verify_error(ctx, cert, + X509_V_ERR_INVALID_EXTENSION, depth)) == 0) + goto done; + } + + /* + * Check that the child's resources are covered by the parent. + * Each covered resource is replaced with the parent's resource + * covering it, so the next iteration will check that the + * parent's resources are covered by the grandparent. + */ + for (i = 0; i < sk_IPAddressFamily_num(child); i++) { + child_af = sk_IPAddressFamily_value(child, i); + + if ((parent_af = IPAddressFamily_find_in_parent(parent, + child_af)) == NULL) { + /* + * If we have no match in the parent and the + * child inherits, that's fine. + */ + if (IPAddressFamily_inheritance(child_af) != + NULL) + continue; + + /* Otherwise the child isn't covered. */ + if ((ret = verify_error(ctx, cert, + X509_V_ERR_UNNESTED_RESOURCE, depth)) == 0) + goto done; + break; + } + + /* Parent inherits, nothing to do. */ + if (IPAddressFamily_inheritance(parent_af) != NULL) + continue; + + /* Child inherits. Use parent's address family. */ + if (IPAddressFamily_inheritance(child_af) != NULL) { + sk_IPAddressFamily_set(child, i, parent_af); continue; } - if (fp->ipAddressChoice->type == - IPAddressChoice_addressesOrRanges) { - if (fc->ipAddressChoice->type == - IPAddressChoice_inherit || - addr_contains(fp->ipAddressChoice->u.addressesOrRanges, - fc->ipAddressChoice->u.addressesOrRanges, - length_from_afi(X509v3_addr_get_afi(fc)))) - sk_IPAddressFamily_set(child, j, fp); - else - validation_err(X509_V_ERR_UNNESTED_RESOURCE); + + child_aor = IPAddressFamily_addressesOrRanges(child_af); + parent_aor = + IPAddressFamily_addressesOrRanges(parent_af); + + /* + * Child and parent are canonical and neither inherits. + * If either addressesOrRanges is NULL, something's + * very wrong. + */ + if (child_aor == NULL || parent_aor == NULL) + goto err; + + if (!IPAddressFamily_afi_length(child_af, &length)) + goto err; + + /* Now check containment and replace or error. */ + if (addr_contains(parent_aor, child_aor, length)) { + sk_IPAddressFamily_set(child, i, parent_af); + continue; } + + if ((ret = verify_error(ctx, cert, + X509_V_ERR_UNNESTED_RESOURCE, depth)) == 0) + goto done; } } /* * Trust anchor can't inherit. */ - if (x->rfc3779_addr != NULL) { - for (j = 0; j < sk_IPAddressFamily_num(x->rfc3779_addr); j++) { - IPAddressFamily *fp = - sk_IPAddressFamily_value(x->rfc3779_addr, j); - if (fp->ipAddressChoice->type == - IPAddressChoice_inherit && - sk_IPAddressFamily_find(child, fp) >= 0) - validation_err(X509_V_ERR_UNNESTED_RESOURCE); + if ((parent = cert->rfc3779_addr) != NULL) { + for (i = 0; i < sk_IPAddressFamily_num(parent); i++) { + parent_af = sk_IPAddressFamily_value(parent, i); + + if (IPAddressFamily_inheritance(parent_af) == NULL) + continue; + + if ((ret = verify_error(ctx, cert, + X509_V_ERR_UNNESTED_RESOURCE, depth)) == 0) + goto done; } } done: sk_IPAddressFamily_free(child); return ret; -} -#undef validation_err + err: + sk_IPAddressFamily_free(child); + + if (ctx != NULL) + ctx->error = X509_V_ERR_UNSPECIFIED; + + return 0; +} /* * RFC 3779 2.3 path validation -- called from X509_verify_cert(). @@ -1512,9 +1926,7 @@ addr_validate_path_internal(X509_STORE_CTX *ctx, STACK_OF(X509)*chain, int X509v3_addr_validate_path(X509_STORE_CTX *ctx) { - if (ctx->chain == NULL || - sk_X509_num(ctx->chain) == 0 || - ctx->verify_cb == NULL) { + if (sk_X509_num(ctx->chain) <= 0 || ctx->verify_cb == NULL) { ctx->error = X509_V_ERR_UNSPECIFIED; return 0; } @@ -1526,16 +1938,16 @@ X509v3_addr_validate_path(X509_STORE_CTX *ctx) * Test whether chain covers extension. */ int -X509v3_addr_validate_resource_set(STACK_OF(X509)*chain, IPAddrBlocks *ext, +X509v3_addr_validate_resource_set(STACK_OF(X509) *chain, IPAddrBlocks *ext, int allow_inheritance) { if (ext == NULL) return 1; - if (chain == NULL || sk_X509_num(chain) == 0) + if (sk_X509_num(chain) <= 0) return 0; if (!allow_inheritance && X509v3_addr_inherits(ext)) return 0; return addr_validate_path_internal(NULL, chain, ext); } -#endif /* OPENSSL_NO_RFC3779 */ +#endif /* OPENSSL_NO_RFC3779 */ diff --git a/crypto/x509/x509_alt.c b/crypto/x509/x509_alt.c index 5b9f490..8656df8 100644 --- a/crypto/x509/x509_alt.c +++ b/crypto/x509/x509_alt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_alt.c,v 1.2 2021/08/24 15:23:03 tb Exp $ */ +/* $OpenBSD: x509_alt.c,v 1.12 2022/03/26 16:34:21 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project. */ @@ -63,6 +63,8 @@ #include #include +#include "x509_internal.h" + static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, @@ -612,8 +614,11 @@ GENERAL_NAME * v2i_GENERAL_NAME_ex(GENERAL_NAME *out, const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc) { - int type; + uint8_t *bytes = NULL; char *name, *value; + GENERAL_NAME *ret; + size_t len = 0; + int type; name = cnf->name; value = cnf->value; @@ -643,7 +648,67 @@ v2i_GENERAL_NAME_ex(GENERAL_NAME *out, const X509V3_EXT_METHOD *method, return NULL; } - return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc); + ret = a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc); + if (ret == NULL) + return NULL; + + /* + * Validate what we have for sanity. + */ + + if (is_nc) { + struct x509_constraints_name *constraints_name = NULL; + + if (!x509_constraints_validate(ret, &constraints_name, NULL)) { + X509V3error(X509V3_R_BAD_OBJECT); + ERR_asprintf_error_data("name=%s", name); + goto err; + } + x509_constraints_name_free(constraints_name); + return ret; + } + + type = x509_constraints_general_to_bytes(ret, &bytes, &len); + switch (type) { + case GEN_DNS: + if (!x509_constraints_valid_sandns(bytes, len)) { + X509V3error(X509V3_R_BAD_OBJECT); + ERR_asprintf_error_data("name=%s value='%.*s'", name, + (int)len, bytes); + goto err; + } + break; + case GEN_URI: + if (!x509_constraints_uri_host(bytes, len, NULL)) { + X509V3error(X509V3_R_BAD_OBJECT); + ERR_asprintf_error_data("name=%s value='%.*s'", name, + (int)len, bytes); + goto err; + } + break; + case GEN_EMAIL: + if (!x509_constraints_parse_mailbox(bytes, len, NULL)) { + X509V3error(X509V3_R_BAD_OBJECT); + ERR_asprintf_error_data("name=%s value='%.*s'", name, + (int)len, bytes); + goto err; + } + break; + case GEN_IPADD: + if (len != 4 && len != 16) { + X509V3error(X509V3_R_BAD_IP_ADDRESS); + ERR_asprintf_error_data("name=%s len=%zu", name, len); + goto err; + } + break; + default: + break; + } + return ret; + err: + if (out == NULL) + GENERAL_NAME_free(ret); + return NULL; } static int diff --git a/crypto/x509/x509_asid.c b/crypto/x509/x509_asid.c index ed99ca7..c82f2f3 100644 --- a/crypto/x509/x509_asid.c +++ b/crypto/x509/x509_asid.c @@ -1,17 +1,65 @@ +/* $OpenBSD: x509_asid.c,v 1.30 2021/12/25 15:46:05 tb Exp $ */ /* - * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * Contributed to the OpenSSL Project by the American Registry for + * Internet Numbers ("ARIN"). + */ +/* ==================================================================== + * Copyright (c) 2006-2018 The OpenSSL Project. 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 + * 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 + * licensing@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). */ /* * Implementation of RFC 3779 section 3.2. */ -#include #include #include #include @@ -25,7 +73,7 @@ #include #include -#include "ext_dat.h" +#include "x509_lcl.h" #ifndef OPENSSL_NO_RFC3779 @@ -312,7 +360,7 @@ ASIdOrRange_cmp(const ASIdOrRange *const *a_, const ASIdOrRange *const *b_) { const ASIdOrRange *a = *a_, *b = *b_; - /* XXX: these asserts need to be replaced */ + /* XXX: these asserts need to be replaced */ OPENSSL_assert((a->type == ASIdOrRange_id && a->u.id != NULL) || (a->type == ASIdOrRange_range && a->u.range != NULL && a->u.range->min != NULL && a->u.range->max != NULL)); @@ -425,8 +473,6 @@ X509v3_asid_add_id_or_range(ASIdentifiers *asid, int which, ASN1_INTEGER *min, static int extract_min_max(ASIdOrRange *aor, ASN1_INTEGER **min, ASN1_INTEGER **max) { - OPENSSL_assert(aor != NULL); - switch (aor->type) { case ASIdOrRange_id: *min = aor->u.id; @@ -602,7 +648,8 @@ ASIdentifierChoice_canonize(ASIdentifierChoice *choice) /* * Make sure we're properly sorted (paranoia). */ - OPENSSL_assert(ASN1_INTEGER_cmp(a_min, b_min) <= 0); + if (ASN1_INTEGER_cmp(a_min, b_min) > 0) + goto done; /* * Punt inverted ranges. @@ -689,7 +736,8 @@ ASIdentifierChoice_canonize(ASIdentifierChoice *choice) } /* Paranoia */ - OPENSSL_assert(ASIdentifierChoice_is_canonical(choice)); + if (!ASIdentifierChoice_is_canonical(choice)) + goto done; ret = 1; @@ -830,17 +878,20 @@ v2i_ASIdentifiers(const struct v3_ext_method *method, struct v3_ext_ctx *ctx, * OpenSSL dispatch. */ const X509V3_EXT_METHOD v3_asid = { - NID_sbgp_autonomousSysNum, /* nid */ - 0, /* flags */ - &ASIdentifiers_it, /* template */ - 0, 0, 0, 0, /* old functions, ignored */ - 0, /* i2s */ - 0, /* s2i */ - 0, /* i2v */ - v2i_ASIdentifiers, /* v2i */ - i2r_ASIdentifiers, /* i2r */ - 0, /* r2i */ - NULL /* extension-specific data */ + .ext_nid = NID_sbgp_autonomousSysNum, + .ext_flags = 0, + .it = &ASIdentifiers_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = NULL, + .v2i = v2i_ASIdentifiers, + .i2r = i2r_ASIdentifiers, + .r2i = NULL, + .usr_data = NULL, }; /* @@ -930,16 +981,22 @@ X509v3_asid_subset(ASIdentifiers *a, ASIdentifiers *b) * Core code for RFC 3779 3.3 path validation. */ static int -asid_validate_path_internal(X509_STORE_CTX *ctx, STACK_OF(X509)*chain, +asid_validate_path_internal(X509_STORE_CTX *ctx, STACK_OF(X509) *chain, ASIdentifiers *ext) { ASIdOrRanges *child_as = NULL, *child_rdi = NULL; int i, ret = 1, inherit_as = 0, inherit_rdi = 0; X509 *x; - OPENSSL_assert(chain != NULL && sk_X509_num(chain) > 0); - OPENSSL_assert(ctx != NULL || ext != NULL); - OPENSSL_assert(ctx == NULL || ctx->verify_cb != NULL); + /* We need a non-empty chain to test against. */ + if (sk_X509_num(chain) <= 0) + goto err; + /* We need either a store ctx or an extension to work with. */ + if (ctx == NULL && ext == NULL) + goto err; + /* If there is a store ctx, it needs a verify_cb. */ + if (ctx != NULL && ctx->verify_cb == NULL) + goto err; /* * Figure out where to start. If we don't have an extension to @@ -984,7 +1041,6 @@ asid_validate_path_internal(X509_STORE_CTX *ctx, STACK_OF(X509)*chain, */ for (i++; i < sk_X509_num(chain); i++) { x = sk_X509_value(chain, i); - OPENSSL_assert(x != NULL); if (x->rfc3779_asid == NULL) { if (child_as != NULL || child_rdi != NULL) @@ -1031,7 +1087,9 @@ asid_validate_path_internal(X509_STORE_CTX *ctx, STACK_OF(X509)*chain, /* * Trust anchor can't inherit. */ - OPENSSL_assert(x != NULL); + + if (x == NULL) + goto err; if (x->rfc3779_asid != NULL) { if (x->rfc3779_asid->asnum != NULL && @@ -1044,6 +1102,12 @@ asid_validate_path_internal(X509_STORE_CTX *ctx, STACK_OF(X509)*chain, done: return ret; + + err: + if (ctx != NULL) + ctx->error = X509_V_ERR_UNSPECIFIED; + + return 0; } #undef validation_err @@ -1054,9 +1118,7 @@ asid_validate_path_internal(X509_STORE_CTX *ctx, STACK_OF(X509)*chain, int X509v3_asid_validate_path(X509_STORE_CTX *ctx) { - if (ctx->chain == NULL || - sk_X509_num(ctx->chain) == 0 || - ctx->verify_cb == NULL) { + if (sk_X509_num(ctx->chain) <= 0 || ctx->verify_cb == NULL) { ctx->error = X509_V_ERR_UNSPECIFIED; return 0; } @@ -1068,12 +1130,12 @@ X509v3_asid_validate_path(X509_STORE_CTX *ctx) * Test whether chain covers extension. */ int -X509v3_asid_validate_resource_set(STACK_OF(X509)*chain, ASIdentifiers *ext, +X509v3_asid_validate_resource_set(STACK_OF(X509) *chain, ASIdentifiers *ext, int allow_inheritance) { if (ext == NULL) return 1; - if (chain == NULL || sk_X509_num(chain) == 0) + if (sk_X509_num(chain) <= 0) return 0; if (!allow_inheritance && X509v3_asid_inherits(ext)) return 0; diff --git a/crypto/x509/x509_att.c b/crypto/x509/x509_att.c index 1479b91..38aa063 100644 --- a/crypto/x509/x509_att.c +++ b/crypto/x509/x509_att.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_att.c,v 1.17 2018/05/18 19:21:33 tb Exp $ */ +/* $OpenBSD: x509_att.c,v 1.18 2021/11/01 20:53:08 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -66,6 +66,8 @@ #include #include +#include "x509_lcl.h" + int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x) { diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c index 6d6e840..4fd8d78 100644 --- a/crypto/x509/x509_cmp.c +++ b/crypto/x509/x509_cmp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_cmp.c,v 1.35 2019/03/13 20:34:00 tb Exp $ */ +/* $OpenBSD: x509_cmp.c,v 1.39 2022/02/24 22:05:06 beck Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -68,6 +68,9 @@ #include #include +#include "evp_locl.h" +#include "x509_lcl.h" + int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b) { @@ -140,7 +143,7 @@ X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b) int X509_CRL_match(const X509_CRL *a, const X509_CRL *b) { - return memcmp(a->sha1_hash, b->sha1_hash, 20); + return memcmp(a->hash, b->hash, X509_CRL_HASH_LEN); } #endif @@ -213,7 +216,7 @@ X509_cmp(const X509 *a, const X509 *b) X509_check_purpose((X509 *)a, -1, 0); X509_check_purpose((X509 *)b, -1, 0); - return memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH); + return memcmp(a->hash, b->hash, X509_CERT_HASH_LEN); } #endif diff --git a/crypto/x509/x509_conf.c b/crypto/x509/x509_conf.c index 8bf2d10..cd703fc 100644 --- a/crypto/x509/x509_conf.c +++ b/crypto/x509/x509_conf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_conf.c,v 1.1 2020/06/04 15:19:31 jsing Exp $ */ +/* $OpenBSD: x509_conf.c,v 1.2 2021/11/01 20:53:08 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -66,6 +66,8 @@ #include #include +#include "x509_lcl.h" + static int v3_check_critical(const char **value); static int v3_check_generic(const char **value); static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, diff --git a/crypto/x509/x509_constraints.c b/crypto/x509/x509_constraints.c index db33bf1..533bbbf 100644 --- a/crypto/x509/x509_constraints.c +++ b/crypto/x509/x509_constraints.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_constraints.c,v 1.17 2021/09/23 15:49:48 jsing Exp $ */ +/* $OpenBSD: x509_constraints.c,v 1.26 2022/03/26 16:34:21 tb Exp $ */ /* * Copyright (c) 2020 Bob Beck * @@ -390,7 +390,7 @@ x509_constraints_parse_mailbox(uint8_t *candidate, size_t len, } if (c == '@') { if (wi == 0) - goto bad;; + goto bad; if (candidate_local != NULL) goto bad; candidate_local = strdup(working); @@ -424,9 +424,14 @@ x509_constraints_parse_mailbox(uint8_t *candidate, size_t len, strlen(candidate_domain))) goto bad; - name->local = candidate_local; - name->name = candidate_domain; - name->type = GEN_EMAIL; + if (name != NULL) { + name->local = candidate_local; + name->name = candidate_domain; + name->type = GEN_EMAIL; + } else { + free(candidate_local); + free(candidate_domain); + } return 1; bad: free(candidate_local); @@ -511,7 +516,8 @@ x509_constraints_uri_host(uint8_t *uri, size_t len, char **hostpart) host = authority; if (!x509_constraints_valid_host(host, hostlen)) return 0; - *hostpart = strndup(host, hostlen); + if (hostpart != NULL) + *hostpart = strndup(host, hostlen); return 1; } @@ -630,7 +636,11 @@ int x509_constraints_dirname(uint8_t *dirname, size_t dlen, uint8_t *constraint, size_t len) { - if (len != dlen) + /* + * The constraint must be a prefix in DER format, so it can't be + * longer than the name it is checked against. + */ + if (len > dlen) return 0; return (memcmp(constraint, dirname, len) == 0); } @@ -647,35 +657,45 @@ x509_constraints_general_to_bytes(GENERAL_NAME *name, uint8_t **bytes, if (name->type == GEN_DNS) { ASN1_IA5STRING *aname = name->d.dNSName; + *bytes = aname->data; - *len = strlen(aname->data); + *len = aname->length; + return name->type; } if (name->type == GEN_EMAIL) { ASN1_IA5STRING *aname = name->d.rfc822Name; + *bytes = aname->data; - *len = strlen(aname->data); + *len = aname->length; + return name->type; } if (name->type == GEN_URI) { ASN1_IA5STRING *aname = name->d.uniformResourceIdentifier; + *bytes = aname->data; - *len = strlen(aname->data); + *len = aname->length; + return name->type; } if (name->type == GEN_DIRNAME) { X509_NAME *dname = name->d.directoryName; + if (!dname->modified || i2d_X509_NAME(dname, NULL) >= 0) { *bytes = dname->canon_enc; *len = dname->canon_enclen; + return name->type; } } if (name->type == GEN_IPADD) { *bytes = name->d.ip->data; *len = name->d.ip->length; + return name->type; } + return 0; } @@ -713,7 +733,7 @@ x509_constraints_extract_names(struct x509_constraints_names *names, *error = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; goto err; } - if ((vname->name = strdup(bytes)) == NULL) { + if ((vname->name = strndup(bytes, len)) == NULL) { *error = X509_V_ERR_OUT_OF_MEM; goto err; } @@ -741,15 +761,15 @@ x509_constraints_extract_names(struct x509_constraints_names *names, vname->type = GEN_URI; break; case GEN_DIRNAME: + if (len == 0) { + *error = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + goto err; + } if (bytes == NULL || ((vname->der = malloc(len)) == NULL)) { *error = X509_V_ERR_OUT_OF_MEM; goto err; } - if (len == 0) { - *error = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; - goto err; - } memcpy(vname->der, bytes, len); vname->der_len = len; vname->type = GEN_DIRNAME; @@ -759,8 +779,7 @@ x509_constraints_extract_names(struct x509_constraints_names *names, vname->af = AF_INET; if (len == 16) vname->af = AF_INET6; - if (vname->af != AF_INET && vname->af != - AF_INET6) { + if (vname->af != AF_INET && vname->af != AF_INET6) { *error = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; goto err; } @@ -887,21 +906,34 @@ x509_constraints_extract_names(struct x509_constraints_names *names, */ int x509_constraints_validate(GENERAL_NAME *constraint, - struct x509_constraints_name *name, int *error) + struct x509_constraints_name **out_name, int *out_error) { uint8_t *bytes = NULL; size_t len = 0; + struct x509_constraints_name *name; + int error = X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX; int name_type; + if (out_name == NULL || *out_name != NULL) + return 0; + + if (out_error != NULL) + *out_error = 0; + + if ((name = x509_constraints_name_new()) == NULL) { + error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + name_type = x509_constraints_general_to_bytes(constraint, &bytes, &len); switch (name_type) { case GEN_DIRNAME: - if (bytes == NULL || (name->der = malloc(len)) == NULL) { - *error = X509_V_ERR_OUT_OF_MEM; - return 0; - } if (len == 0) goto err; /* XXX The RFCs are delightfully vague */ + if (bytes == NULL || (name->der = malloc(len)) == NULL) { + error = X509_V_ERR_OUT_OF_MEM; + goto err; + } memcpy(name->der, bytes, len); name->der_len = len; name->type = GEN_DIRNAME; @@ -909,24 +941,31 @@ x509_constraints_validate(GENERAL_NAME *constraint, case GEN_DNS: if (!x509_constraints_valid_domain_constraint(bytes, len)) goto err; - if ((name->name = strdup(bytes)) == NULL) { - *error = X509_V_ERR_OUT_OF_MEM; - return 0; + if ((name->name = strndup(bytes, len)) == NULL) { + error = X509_V_ERR_OUT_OF_MEM; + goto err; } name->type = GEN_DNS; break; case GEN_EMAIL: - if (memchr(bytes, '@', len) != NULL) { + if (len > 0 && memchr(bytes + 1, '@', len - 1) != NULL) { if (!x509_constraints_parse_mailbox(bytes, len, name)) goto err; - } else { - if (!x509_constraints_valid_domain_constraint(bytes, - len)) - goto err; - if ((name->name = strdup(bytes)) == NULL) { - *error = X509_V_ERR_OUT_OF_MEM; - return 0; - } + break; + } + /* + * Mail constraints of the form @domain.com are accepted by + * OpenSSL and Microsoft. + */ + if (len > 0 && bytes[0] == '@') { + bytes++; + len--; + } + if (!x509_constraints_valid_domain_constraint(bytes, len)) + goto err; + if ((name->name = strndup(bytes, len)) == NULL) { + error = X509_V_ERR_OUT_OF_MEM; + goto err; } name->type = GEN_EMAIL; break; @@ -944,15 +983,25 @@ x509_constraints_validate(GENERAL_NAME *constraint, case GEN_URI: if (!x509_constraints_valid_domain_constraint(bytes, len)) goto err; - name->name = strdup(bytes); + if ((name->name = strndup(bytes, len)) == NULL) { + error = X509_V_ERR_OUT_OF_MEM; + goto err; + } name->type = GEN_URI; break; default: break; } + + *out_name = name; + return 1; + err: - *error = X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX; + x509_constraints_name_free(name); + if (out_error != NULL) + *out_error = error; + return 0; } @@ -962,7 +1011,7 @@ x509_constraints_extract_constraints(X509 *cert, struct x509_constraints_names *excluded, int *error) { - struct x509_constraints_name *vname; + struct x509_constraints_name *vname = NULL; NAME_CONSTRAINTS *nc = cert->nc; GENERAL_SUBTREE *subtree; int i; @@ -977,24 +1026,20 @@ x509_constraints_extract_constraints(X509 *cert, *error = X509_V_ERR_SUBTREE_MINMAX; return 0; } - if ((vname = x509_constraints_name_new()) == NULL) { - *error = X509_V_ERR_OUT_OF_MEM; + if (!x509_constraints_validate(subtree->base, &vname, error)) return 0; - } - if (x509_constraints_validate(subtree->base, vname, error) == - 0) { - x509_constraints_name_free(vname); - return 0; - } if (vname->type == 0) { x509_constraints_name_free(vname); + vname = NULL; continue; } if (!x509_constraints_names_add(permitted, vname)) { x509_constraints_name_free(vname); + vname = NULL; *error = X509_V_ERR_OUT_OF_MEM; return 0; } + vname = NULL; } for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->excludedSubtrees); i++) { @@ -1003,24 +1048,20 @@ x509_constraints_extract_constraints(X509 *cert, *error = X509_V_ERR_SUBTREE_MINMAX; return 0; } - if ((vname = x509_constraints_name_new()) == NULL) { - *error = X509_V_ERR_OUT_OF_MEM; + if (!x509_constraints_validate(subtree->base, &vname, error)) return 0; - } - if (x509_constraints_validate(subtree->base, vname, error) == - 0) { - x509_constraints_name_free(vname); - return 0; - } if (vname->type == 0) { x509_constraints_name_free(vname); + vname = NULL; continue; } if (!x509_constraints_names_add(excluded, vname)) { x509_constraints_name_free(vname); + vname = NULL; *error = X509_V_ERR_OUT_OF_MEM; return 0; } + vname = NULL; } return 1; diff --git a/crypto/x509/x509_cpols.c b/crypto/x509/x509_cpols.c index 2ace607..93527a4 100644 --- a/crypto/x509/x509_cpols.c +++ b/crypto/x509/x509_cpols.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_cpols.c,v 1.2 2021/08/24 15:23:03 tb Exp $ */ +/* $OpenBSD: x509_cpols.c,v 1.4 2022/01/14 08:16:13 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -66,6 +66,7 @@ #include #include "pcy_int.h" +#include "x509_lcl.h" /* Certificate policies extension support: this one is a bit complex... */ @@ -232,7 +233,6 @@ static const ASN1_ADB_TABLE POLICYQUALINFO_adbtbl[] = { static const ASN1_ADB POLICYQUALINFO_adb = { .flags = 0, .offset = offsetof(POLICYQUALINFO, pqualid), - .app_items = 0, .tbl = POLICYQUALINFO_adbtbl, .tblcount = sizeof(POLICYQUALINFO_adbtbl) / sizeof(ASN1_ADB_TABLE), .default_tt = &policydefault_tt, diff --git a/crypto/x509/x509_crld.c b/crypto/x509/x509_crld.c index ff60a88..6b6f795 100644 --- a/crypto/x509/x509_crld.c +++ b/crypto/x509/x509_crld.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_crld.c,v 1.1 2020/06/04 15:19:31 jsing Exp $ */ +/* $OpenBSD: x509_crld.c,v 1.2 2021/11/01 20:53:08 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -65,6 +65,8 @@ #include #include +#include "x509_lcl.h" + static void *v2i_crld(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out, diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c index cac734d..a8e9155 100644 --- a/crypto/x509/x509_err.c +++ b/crypto/x509/x509_err.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_err.c,v 1.15 2020/06/05 16:51:12 jsing Exp $ */ +/* $OpenBSD: x509_err.c,v 1.16 2021/11/10 13:57:42 schwarze Exp $ */ /* ==================================================================== * Copyright (c) 1999-2006 The OpenSSL Project. All rights reserved. * @@ -96,6 +96,7 @@ static ERR_STRING_DATA X509_str_reasons[] = { {ERR_REASON(X509_R_LOADING_CERT_DIR) , "loading cert dir"}, {ERR_REASON(X509_R_LOADING_DEFAULTS) , "loading defaults"}, {ERR_REASON(X509_R_METHOD_NOT_SUPPORTED) , "method not supported"}, + {ERR_REASON(X509_R_NO_CERTIFICATE_OR_CRL_FOUND), "no certificate or crl found"}, {ERR_REASON(X509_R_NO_CERT_SET_FOR_US_TO_VERIFY), "no cert set for us to verify"}, {ERR_REASON(X509_R_PUBLIC_KEY_DECODE_ERROR), "public key decode error"}, {ERR_REASON(X509_R_PUBLIC_KEY_ENCODE_ERROR), "public key encode error"}, diff --git a/crypto/x509/x509_ext.c b/crypto/x509/x509_ext.c index 21374a2..1445951 100644 --- a/crypto/x509/x509_ext.c +++ b/crypto/x509/x509_ext.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_ext.c,v 1.12 2018/05/18 19:28:27 tb Exp $ */ +/* $OpenBSD: x509_ext.c,v 1.13 2021/11/01 20:53:08 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -65,6 +65,8 @@ #include #include +#include "x509_lcl.h" + int X509_CRL_get_ext_count(const X509_CRL *x) { diff --git a/crypto/x509/x509_internal.h b/crypto/x509/x509_internal.h index 9878b6f..c6ce522 100644 --- a/crypto/x509/x509_internal.h +++ b/crypto/x509/x509_internal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_internal.h,v 1.12.2.1 2021/11/24 09:28:55 tb Exp $ */ +/* $OpenBSD: x509_internal.h,v 1.18 2022/03/14 21:15:49 tb Exp $ */ /* * Copyright (c) 2020 Bob Beck * @@ -22,6 +22,8 @@ #include +#include "x509_lcl.h" + /* Hard limits on structure size and number of signature checks. */ #define X509_VERIFY_MAX_CHAINS 8 /* Max validated chains */ #define X509_VERIFY_MAX_CHAIN_CERTS 32 /* Max depth of a chain */ @@ -94,18 +96,20 @@ int x509_vfy_callback_indicate_completion(X509_STORE_CTX *ctx); void x509v3_cache_extensions(X509 *x); X509 *x509_vfy_lookup_cert_match(X509_STORE_CTX *ctx, X509 *x); -int x509_verify_asn1_time_to_tm(const ASN1_TIME *atime, struct tm *tm, - int notafter); +time_t x509_verify_asn1_time_to_time_t(const ASN1_TIME *atime, int notafter); struct x509_verify_ctx *x509_verify_ctx_new_from_xsc(X509_STORE_CTX *xsc); void x509_constraints_name_clear(struct x509_constraints_name *name); +void x509_constraints_name_free(struct x509_constraints_name *name); int x509_constraints_names_add(struct x509_constraints_names *names, struct x509_constraints_name *name); struct x509_constraints_names *x509_constraints_names_dup( struct x509_constraints_names *names); void x509_constraints_names_clear(struct x509_constraints_names *names); struct x509_constraints_names *x509_constraints_names_new(size_t names_max); +int x509_constraints_general_to_bytes(GENERAL_NAME *name, uint8_t **bytes, + size_t *len); void x509_constraints_names_free(struct x509_constraints_names *names); int x509_constraints_valid_host(uint8_t *name, size_t len); int x509_constraints_valid_sandns(uint8_t *name, size_t len); @@ -123,11 +127,14 @@ int x509_constraints_extract_names(struct x509_constraints_names *names, int x509_constraints_extract_constraints(X509 *cert, struct x509_constraints_names *permitted, struct x509_constraints_names *excluded, int *error); +int x509_constraints_validate(GENERAL_NAME *constraint, + struct x509_constraints_name **out_name, int *error); int x509_constraints_check(struct x509_constraints_names *names, struct x509_constraints_names *permitted, struct x509_constraints_names *excluded, int *error); int x509_constraints_chain(STACK_OF(X509) *chain, int *error, int *depth); +void x509_verify_cert_info_populate(X509 *cert); __END_HIDDEN_DECLS diff --git a/crypto/x509/x509_lcl.h b/crypto/x509/x509_lcl.h index 3e83b66..e7eb733 100644 --- a/crypto/x509/x509_lcl.h +++ b/crypto/x509/x509_lcl.h @@ -56,8 +56,329 @@ * */ +#ifndef HEADER_X509_LCL_H +#define HEADER_X509_LCL_H + __BEGIN_HIDDEN_DECLS +#define TS_HASH_EVP EVP_sha1() +#define TS_HASH_LEN SHA_DIGEST_LENGTH + +#define X509_CERT_HASH_EVP EVP_sha512() +#define X509_CERT_HASH_LEN SHA512_DIGEST_LENGTH +#define X509_CRL_HASH_EVP EVP_sha512() +#define X509_CRL_HASH_LEN SHA512_DIGEST_LENGTH + +struct X509_pubkey_st { + X509_ALGOR *algor; + ASN1_BIT_STRING *public_key; + EVP_PKEY *pkey; +}; + +struct X509_sig_st { + X509_ALGOR *algor; + ASN1_OCTET_STRING *digest; +} /* X509_SIG */; + +struct X509_name_entry_st { + ASN1_OBJECT *object; + ASN1_STRING *value; + int set; + int size; /* temp variable */ +} /* X509_NAME_ENTRY */; + +/* we always keep X509_NAMEs in 2 forms. */ +struct X509_name_st { + STACK_OF(X509_NAME_ENTRY) *entries; + int modified; /* true if 'bytes' needs to be built */ +#ifndef OPENSSL_NO_BUFFER + BUF_MEM *bytes; +#else + char *bytes; +#endif +/* unsigned long hash; Keep the hash around for lookups */ + unsigned char *canon_enc; + int canon_enclen; +} /* X509_NAME */; + +struct X509_extension_st { + ASN1_OBJECT *object; + ASN1_BOOLEAN critical; + ASN1_OCTET_STRING *value; +} /* X509_EXTENSION */; + +struct x509_attributes_st { + ASN1_OBJECT *object; + int single; /* 0 for a set, 1 for a single item (which is wrong) */ + union { + char *ptr; +/* 0 */ STACK_OF(ASN1_TYPE) *set; +/* 1 */ ASN1_TYPE *single; + } value; +} /* X509_ATTRIBUTE */; + +struct X509_req_info_st { + ASN1_ENCODING enc; + ASN1_INTEGER *version; + X509_NAME *subject; + X509_PUBKEY *pubkey; + /* d=2 hl=2 l= 0 cons: cont: 00 */ + STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */ +} /* X509_REQ_INFO */; + +struct X509_req_st { + X509_REQ_INFO *req_info; + X509_ALGOR *sig_alg; + ASN1_BIT_STRING *signature; + int references; +} /* X509_REQ */; + +/* + * This stuff is certificate "auxiliary info" it contains details which are + * useful in certificate stores and databases. When used this is tagged onto + * the end of the certificate itself. + */ +struct x509_cert_aux_st { + STACK_OF(ASN1_OBJECT) *trust; /* trusted uses */ + STACK_OF(ASN1_OBJECT) *reject; /* rejected uses */ + ASN1_UTF8STRING *alias; /* "friendly name" */ + ASN1_OCTET_STRING *keyid; /* key id of private key */ + STACK_OF(X509_ALGOR) *other; /* other unspecified info */ +} /* X509_CERT_AUX */; + +struct x509_cinf_st { + ASN1_INTEGER *version; /* [ 0 ] default of v1 */ + ASN1_INTEGER *serialNumber; + X509_ALGOR *signature; + X509_NAME *issuer; + X509_VAL *validity; + X509_NAME *subject; + X509_PUBKEY *key; + ASN1_BIT_STRING *issuerUID; /* [ 1 ] optional in v2 */ + ASN1_BIT_STRING *subjectUID; /* [ 2 ] optional in v2 */ + STACK_OF(X509_EXTENSION) *extensions; /* [ 3 ] optional in v3 */ + ASN1_ENCODING enc; +} /* X509_CINF */; + +struct x509_st { + X509_CINF *cert_info; + X509_ALGOR *sig_alg; + ASN1_BIT_STRING *signature; + int valid; + int references; + char *name; + CRYPTO_EX_DATA ex_data; + /* These contain copies of various extension values */ + long ex_pathlen; + long ex_pcpathlen; + unsigned long ex_flags; + unsigned long ex_kusage; + unsigned long ex_xkusage; + unsigned long ex_nscert; + ASN1_OCTET_STRING *skid; + AUTHORITY_KEYID *akid; + X509_POLICY_CACHE *policy_cache; + STACK_OF(DIST_POINT) *crldp; + STACK_OF(GENERAL_NAME) *altname; + NAME_CONSTRAINTS *nc; +#ifndef OPENSSL_NO_RFC3779 + STACK_OF(IPAddressFamily) *rfc3779_addr; + struct ASIdentifiers_st *rfc3779_asid; +#endif + unsigned char hash[X509_CERT_HASH_LEN]; + time_t not_before; + time_t not_after; + X509_CERT_AUX *aux; +} /* X509 */; + +struct x509_revoked_st { + ASN1_INTEGER *serialNumber; + ASN1_TIME *revocationDate; + STACK_OF(X509_EXTENSION) /* optional */ *extensions; + /* Set up if indirect CRL */ + STACK_OF(GENERAL_NAME) *issuer; + /* Revocation reason */ + int reason; + int sequence; /* load sequence */ +}; + +struct X509_crl_info_st { + ASN1_INTEGER *version; + X509_ALGOR *sig_alg; + X509_NAME *issuer; + ASN1_TIME *lastUpdate; + ASN1_TIME *nextUpdate; + STACK_OF(X509_REVOKED) *revoked; + STACK_OF(X509_EXTENSION) /* [0] */ *extensions; + ASN1_ENCODING enc; +} /* X509_CRL_INFO */; + +struct X509_crl_st { + /* actual signature */ + X509_CRL_INFO *crl; + X509_ALGOR *sig_alg; + ASN1_BIT_STRING *signature; + int references; + int flags; + /* Copies of various extensions */ + AUTHORITY_KEYID *akid; + ISSUING_DIST_POINT *idp; + /* Convenient breakdown of IDP */ + int idp_flags; + int idp_reasons; + /* CRL and base CRL numbers for delta processing */ + ASN1_INTEGER *crl_number; + ASN1_INTEGER *base_crl_number; + unsigned char hash[X509_CRL_HASH_LEN]; + STACK_OF(GENERAL_NAMES) *issuers; + const X509_CRL_METHOD *meth; + void *meth_data; +} /* X509_CRL */; + +struct pkcs8_priv_key_info_st { + ASN1_INTEGER *version; + X509_ALGOR *pkeyalg; + ASN1_OCTET_STRING *pkey; + STACK_OF(X509_ATTRIBUTE) *attributes; +}; + +struct x509_object_st { + /* one of the above types */ + int type; + union { + X509 *x509; + X509_CRL *crl; + } data; +} /* X509_OBJECT */; + +struct x509_lookup_method_st { + const char *name; + int (*new_item)(X509_LOOKUP *ctx); + void (*free)(X509_LOOKUP *ctx); + int (*init)(X509_LOOKUP *ctx); + int (*shutdown)(X509_LOOKUP *ctx); + int (*ctrl)(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, + char **ret); + int (*get_by_subject)(X509_LOOKUP *ctx, int type, X509_NAME *name, + X509_OBJECT *ret); + int (*get_by_issuer_serial)(X509_LOOKUP *ctx, int type, X509_NAME *name, + ASN1_INTEGER *serial,X509_OBJECT *ret); + int (*get_by_fingerprint)(X509_LOOKUP *ctx, int type, + const unsigned char *bytes, int len, X509_OBJECT *ret); + int (*get_by_alias)(X509_LOOKUP *ctx, int type, const char *str, + int len, X509_OBJECT *ret); +} /* X509_LOOKUP_METHOD */; + +struct X509_VERIFY_PARAM_st { + char *name; + time_t check_time; /* Time to use */ + unsigned long inh_flags; /* Inheritance flags */ + unsigned long flags; /* Various verify flags */ + int purpose; /* purpose to check untrusted certificates */ + int trust; /* trust setting to check */ + int depth; /* Verify depth */ + STACK_OF(ASN1_OBJECT) *policies; /* Permissible policies */ + X509_VERIFY_PARAM_ID *id; /* opaque ID data */ +} /* X509_VERIFY_PARAM */; + +/* + * This is used to hold everything. It is used for all certificate + * validation. Once we have a certificate chain, the 'verify' + * function is then called to actually check the cert chain. + */ +struct x509_store_st { + /* The following is a cache of trusted certs */ + STACK_OF(X509_OBJECT) *objs; /* Cache of all objects */ + + /* These are external lookup methods */ + STACK_OF(X509_LOOKUP) *get_cert_methods; + + X509_VERIFY_PARAM *param; + + /* Callbacks for various operations */ + int (*verify)(X509_STORE_CTX *ctx); /* called to verify a certificate */ + int (*verify_cb)(int ok,X509_STORE_CTX *ctx); /* error callback */ + int (*get_issuer)(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); /* get issuers cert from ctx */ + int (*check_issued)(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); /* check issued */ + int (*check_revocation)(X509_STORE_CTX *ctx); /* Check revocation status of chain */ + int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); /* retrieve CRL */ + int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */ + int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */ + STACK_OF(X509) * (*lookup_certs)(X509_STORE_CTX *ctx, X509_NAME *nm); + STACK_OF(X509_CRL) * (*lookup_crls)(X509_STORE_CTX *ctx, X509_NAME *nm); + int (*cleanup)(X509_STORE_CTX *ctx); + + CRYPTO_EX_DATA ex_data; + int references; +} /* X509_STORE */; + +/* This is the functions plus an instance of the local variables. */ +struct x509_lookup_st { + int init; /* have we been started */ + X509_LOOKUP_METHOD *method; /* the functions */ + char *method_data; /* method data */ + + X509_STORE *store_ctx; /* who owns us */ +} /* X509_LOOKUP */; + +/* + * This is used when verifying cert chains. Since the gathering of the cert + * chain can take some time (and has to be 'retried'), this needs to be kept + * and passed around. + */ +struct x509_store_ctx_st { + X509_STORE *store; + int current_method; /* used when looking up certs */ + + /* The following are set by the caller */ + X509 *cert; /* The cert to check */ + STACK_OF(X509) *untrusted; /* chain of X509s - untrusted - passed in */ + STACK_OF(X509_CRL) *crls; /* set of CRLs passed in */ + + X509_VERIFY_PARAM *param; + void *other_ctx; /* Other info for use with get_issuer() */ + + /* Callbacks for various operations */ + int (*verify)(X509_STORE_CTX *ctx); /* called to verify a certificate */ + int (*verify_cb)(int ok,X509_STORE_CTX *ctx); /* error callback */ + int (*get_issuer)(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); /* get issuers cert from ctx */ + int (*check_issued)(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); /* check issued */ + int (*check_revocation)(X509_STORE_CTX *ctx); /* Check revocation status of chain */ + int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); /* retrieve CRL */ + int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */ + int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */ + int (*check_policy)(X509_STORE_CTX *ctx); + STACK_OF(X509) * (*lookup_certs)(X509_STORE_CTX *ctx, X509_NAME *nm); + STACK_OF(X509_CRL) * (*lookup_crls)(X509_STORE_CTX *ctx, X509_NAME *nm); + int (*cleanup)(X509_STORE_CTX *ctx); + + /* The following is built up */ + int valid; /* if 0, rebuild chain */ + int num_untrusted; /* number of untrusted certs in chain */ + STACK_OF(X509) *chain; /* chain of X509s - built up and trusted */ + X509_POLICY_TREE *tree; /* Valid policy tree */ + + int explicit_policy; /* Require explicit policy value */ + + /* When something goes wrong, this is why */ + int error_depth; + int error; + X509 *current_cert; + X509 *current_issuer; /* cert currently being tested as valid issuer */ + X509_CRL *current_crl; /* current CRL */ + + int current_crl_score; /* score of current CRL */ + unsigned int current_reasons; /* Reason mask */ + + X509_STORE_CTX *parent; /* For CRL path validation: parent context */ + + CRYPTO_EX_DATA ex_data; +} /* X509_STORE_CTX */; + int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int quiet); +int name_cmp(const char *name, const char *cmp); + __END_HIDDEN_DECLS + +#endif /* !HEADER_X509_LCL_H */ diff --git a/crypto/x509/x509_lib.c b/crypto/x509/x509_lib.c index 211d0ad..a518d5b 100644 --- a/crypto/x509/x509_lib.c +++ b/crypto/x509/x509_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_lib.c,v 1.2 2020/09/14 11:35:32 beck Exp $ */ +/* $OpenBSD: x509_lib.c,v 1.3 2021/11/01 20:53:08 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -64,6 +64,7 @@ #include #include "ext_dat.h" +#include "x509_lcl.h" static STACK_OF(X509V3_EXT_METHOD) *ext_list = NULL; diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c index 315eddf..90d7549 100644 --- a/crypto/x509/x509_lu.c +++ b/crypto/x509/x509_lu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_lu.c,v 1.31 2021/10/06 08:29:41 claudio Exp $ */ +/* $OpenBSD: x509_lu.c,v 1.55 2022/01/14 07:53:45 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -57,6 +57,7 @@ */ #include +#include #include #include @@ -64,27 +65,24 @@ #include #include "x509_lcl.h" -static void X509_OBJECT_dec_ref_count(X509_OBJECT *a); - X509_LOOKUP * X509_LOOKUP_new(X509_LOOKUP_METHOD *method) { - X509_LOOKUP *ret; + X509_LOOKUP *lu; - ret = malloc(sizeof(X509_LOOKUP)); - if (ret == NULL) - return NULL; - - ret->init = 0; - ret->skip = 0; - ret->method = method; - ret->method_data = NULL; - ret->store_ctx = NULL; - if ((method->new_item != NULL) && !method->new_item(ret)) { - free(ret); + if ((lu = calloc(1, sizeof(*lu))) == NULL) { + X509error(ERR_R_MALLOC_FAILURE); return NULL; } - return ret; + + lu->method = method; + + if (method->new_item != NULL && !method->new_item(lu)) { + free(lu); + return NULL; + } + + return lu; } void @@ -92,8 +90,8 @@ X509_LOOKUP_free(X509_LOOKUP *ctx) { if (ctx == NULL) return; - if ((ctx->method != NULL) && (ctx->method->free != NULL)) - (*ctx->method->free)(ctx); + if (ctx->method != NULL && ctx->method->free != NULL) + ctx->method->free(ctx); free(ctx); } @@ -102,10 +100,9 @@ X509_LOOKUP_init(X509_LOOKUP *ctx) { if (ctx->method == NULL) return 0; - if (ctx->method->init != NULL) - return ctx->method->init(ctx); - else + if (ctx->method->init == NULL) return 1; + return ctx->method->init(ctx); } int @@ -113,10 +110,9 @@ X509_LOOKUP_shutdown(X509_LOOKUP *ctx) { if (ctx->method == NULL) return 0; - if (ctx->method->shutdown != NULL) - return ctx->method->shutdown(ctx); - else + if (ctx->method->shutdown == NULL) return 1; + return ctx->method->shutdown(ctx); } int @@ -125,48 +121,44 @@ X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, { if (ctx->method == NULL) return -1; - if (ctx->method->ctrl != NULL) - return ctx->method->ctrl(ctx, cmd, argc, argl, ret); - else + if (ctx->method->ctrl == NULL) return 1; + return ctx->method->ctrl(ctx, cmd, argc, argl, ret); } int -X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name, +X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, X509_NAME *name, X509_OBJECT *ret) { - if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL)) - return X509_LU_FAIL; - if (ctx->skip) + if (ctx->method == NULL || ctx->method->get_by_subject == NULL) return 0; return ctx->method->get_by_subject(ctx, type, name, ret); } int -X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name, - ASN1_INTEGER *serial, X509_OBJECT *ret) +X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + X509_NAME *name, ASN1_INTEGER *serial, X509_OBJECT *ret) { - if ((ctx->method == NULL) || - (ctx->method->get_by_issuer_serial == NULL)) - return X509_LU_FAIL; + if (ctx->method == NULL || ctx->method->get_by_issuer_serial == NULL) + return 0; return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret); } int -X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type, +X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, const unsigned char *bytes, int len, X509_OBJECT *ret) { - if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL)) - return X509_LU_FAIL; + if (ctx->method == NULL || ctx->method->get_by_fingerprint == NULL) + return 0; return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret); } int -X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, const char *str, int len, - X509_OBJECT *ret) +X509_LOOKUP_by_alias(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, const char *str, + int len, X509_OBJECT *ret) { - if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL)) - return X509_LU_FAIL; + if (ctx->method == NULL || ctx->method->get_by_alias == NULL) + return 0; return ctx->method->get_by_alias(ctx, type, str, len, ret); } @@ -175,276 +167,267 @@ x509_object_cmp(const X509_OBJECT * const *a, const X509_OBJECT * const *b) { int ret; - ret = ((*a)->type - (*b)->type); - if (ret) + if ((ret = (*a)->type - (*b)->type) != 0) return ret; + switch ((*a)->type) { case X509_LU_X509: - ret = X509_subject_name_cmp((*a)->data.x509, (*b)->data.x509); - break; + return X509_subject_name_cmp((*a)->data.x509, (*b)->data.x509); case X509_LU_CRL: - ret = X509_CRL_cmp((*a)->data.crl, (*b)->data.crl); - break; - default: - /* abort(); */ - return 0; + return X509_CRL_cmp((*a)->data.crl, (*b)->data.crl); } - return ret; + return 0; } X509_STORE * X509_STORE_new(void) { - X509_STORE *ret; + X509_STORE *store; - if ((ret = malloc(sizeof(X509_STORE))) == NULL) - return NULL; - ret->objs = sk_X509_OBJECT_new(x509_object_cmp); - ret->cache = 1; - ret->get_cert_methods = sk_X509_LOOKUP_new_null(); - ret->verify = 0; - ret->verify_cb = 0; - - if ((ret->param = X509_VERIFY_PARAM_new()) == NULL) + if ((store = calloc(1, sizeof(*store))) == NULL) goto err; - ret->get_issuer = 0; - ret->check_issued = 0; - ret->check_revocation = 0; - ret->get_crl = 0; - ret->check_crl = 0; - ret->cert_crl = 0; - ret->lookup_certs = 0; - ret->lookup_crls = 0; - ret->cleanup = 0; - - if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data)) + if ((store->objs = sk_X509_OBJECT_new(x509_object_cmp)) == NULL) + goto err; + if ((store->get_cert_methods = sk_X509_LOOKUP_new_null()) == NULL) + goto err; + if ((store->param = X509_VERIFY_PARAM_new()) == NULL) goto err; - ret->references = 1; - return ret; + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, store, + &store->ex_data)) + goto err; + + store->references = 1; + + return store; + + err: + X509error(ERR_R_MALLOC_FAILURE); + X509_STORE_free(store); -err: - X509_VERIFY_PARAM_free(ret->param); - sk_X509_LOOKUP_free(ret->get_cert_methods); - sk_X509_OBJECT_free(ret->objs); - free(ret); return NULL; } -static void +X509_OBJECT * +X509_OBJECT_new(void) +{ + X509_OBJECT *obj; + + if ((obj = calloc(1, sizeof(*obj))) == NULL) { + X509error(ERR_R_MALLOC_FAILURE); + return NULL; + } + + obj->type = X509_LU_NONE; + + return obj; +} + +void X509_OBJECT_free(X509_OBJECT *a) { - X509_OBJECT_free_contents(a); + if (a == NULL) + return; + + switch (a->type) { + case X509_LU_X509: + X509_free(a->data.x509); + break; + case X509_LU_CRL: + X509_CRL_free(a->data.crl); + break; + } + free(a); } void -X509_STORE_free(X509_STORE *vfy) +X509_STORE_free(X509_STORE *store) { - int i; STACK_OF(X509_LOOKUP) *sk; X509_LOOKUP *lu; + int i; - if (vfy == NULL) + if (store == NULL) return; - i = CRYPTO_add(&vfy->references, -1, CRYPTO_LOCK_X509_STORE); - if (i > 0) + if (CRYPTO_add(&store->references, -1, CRYPTO_LOCK_X509_STORE) > 0) return; - sk = vfy->get_cert_methods; + sk = store->get_cert_methods; for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) { lu = sk_X509_LOOKUP_value(sk, i); X509_LOOKUP_shutdown(lu); X509_LOOKUP_free(lu); } sk_X509_LOOKUP_free(sk); - sk_X509_OBJECT_pop_free(vfy->objs, X509_OBJECT_free); + sk_X509_OBJECT_pop_free(store->objs, X509_OBJECT_free); - CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, vfy, &vfy->ex_data); - X509_VERIFY_PARAM_free(vfy->param); - free(vfy); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, store, &store->ex_data); + X509_VERIFY_PARAM_free(store->param); + free(store); } int -X509_STORE_up_ref(X509_STORE *x) +X509_STORE_up_ref(X509_STORE *store) { - int refs = CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509_STORE); - return (refs > 1) ? 1 : 0; + return CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE) > 1; } X509_LOOKUP * -X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m) +X509_STORE_add_lookup(X509_STORE *store, X509_LOOKUP_METHOD *method) { - int i; STACK_OF(X509_LOOKUP) *sk; X509_LOOKUP *lu; + int i; - sk = v->get_cert_methods; + sk = store->get_cert_methods; for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) { lu = sk_X509_LOOKUP_value(sk, i); - if (m == lu->method) { + if (method == lu->method) { return lu; } } - /* a new one */ - lu = X509_LOOKUP_new(m); - if (lu == NULL) + + if ((lu = X509_LOOKUP_new(method)) == NULL) + return NULL; + + lu->store_ctx = store; + if (sk_X509_LOOKUP_push(store->get_cert_methods, lu) <= 0) { + X509error(ERR_R_MALLOC_FAILURE); + X509_LOOKUP_free(lu); return NULL; - else { - lu->store_ctx = v; - if (sk_X509_LOOKUP_push(v->get_cert_methods, lu)) - return lu; - else { - X509_LOOKUP_free(lu); - return NULL; - } } + + return lu; +} + +X509_OBJECT * +X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type, + X509_NAME *name) +{ + X509_OBJECT *obj; + + if ((obj = X509_OBJECT_new()) == NULL) + return NULL; + if (!X509_STORE_CTX_get_by_subject(vs, type, name, obj)) { + X509_OBJECT_free(obj); + return NULL; + } + + return obj; } int -X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name, - X509_OBJECT *ret) +X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type, + X509_NAME *name, X509_OBJECT *ret) { - X509_STORE *ctx = vs->ctx; + X509_STORE *ctx = vs->store; X509_LOOKUP *lu; X509_OBJECT stmp, *tmp; - int i, j; + int i; if (ctx == NULL) return 0; + memset(&stmp, 0, sizeof(stmp)); + CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name); CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); if (tmp == NULL || type == X509_LU_CRL) { - for (i = vs->current_method; - i < sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) { + for (i = 0; i < sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) { lu = sk_X509_LOOKUP_value(ctx->get_cert_methods, i); - j = X509_LOOKUP_by_subject(lu, type, name, &stmp); - if (j < 0) { - vs->current_method = j; - return j; - } else if (j) { + if (X509_LOOKUP_by_subject(lu, type, name, &stmp) != 0) { tmp = &stmp; break; } } - vs->current_method = 0; if (tmp == NULL) return 0; } -/* if (ret->data.ptr != NULL) - X509_OBJECT_free_contents(ret); */ + if (!X509_OBJECT_up_ref_count(tmp)) + return 0; - ret->type = tmp->type; - ret->data.ptr = tmp->data.ptr; - - X509_OBJECT_up_ref_count(ret); + *ret = *tmp; return 1; } +/* Add obj to the store. Takes ownership of obj. */ +static int +X509_STORE_add_object(X509_STORE *store, X509_OBJECT *obj) +{ + int ret = 0; + + CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + + if (X509_OBJECT_retrieve_match(store->objs, obj) != NULL) { + /* Object is already present in the store. That's fine. */ + ret = 1; + goto out; + } + + if (sk_X509_OBJECT_push(store->objs, obj) <= 0) { + X509error(ERR_R_MALLOC_FAILURE); + goto out; + } + + obj = NULL; + ret = 1; + + out: + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + X509_OBJECT_free(obj); + + return ret; +} + int -X509_STORE_add_cert(X509_STORE *ctx, X509 *x) +X509_STORE_add_cert(X509_STORE *store, X509 *x) { X509_OBJECT *obj; - int ret = 1; if (x == NULL) return 0; - obj = malloc(sizeof(X509_OBJECT)); - if (obj == NULL) { - X509error(ERR_R_MALLOC_FAILURE); + + if ((obj = X509_OBJECT_new()) == NULL) + return 0; + + if (!X509_up_ref(x)) { + X509_OBJECT_free(obj); return 0; } + obj->type = X509_LU_X509; obj->data.x509 = x; - CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); - - X509_OBJECT_up_ref_count(obj); - - if (X509_OBJECT_retrieve_match(ctx->objs, obj)) { - X509error(X509_R_CERT_ALREADY_IN_HASH_TABLE); - ret = 0; - } else { - if (sk_X509_OBJECT_push(ctx->objs, obj) == 0) { - X509error(ERR_R_MALLOC_FAILURE); - ret = 0; - } - } - - if (ret == 0) - X509_OBJECT_dec_ref_count(obj); - - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); - - if (ret == 0) { - obj->data.x509 = NULL; /* owned by the caller */ - X509_OBJECT_free(obj); - } - - return ret; + return X509_STORE_add_object(store, obj); } int -X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x) +X509_STORE_add_crl(X509_STORE *store, X509_CRL *x) { X509_OBJECT *obj; - int ret = 1; if (x == NULL) return 0; - obj = malloc(sizeof(X509_OBJECT)); - if (obj == NULL) { - X509error(ERR_R_MALLOC_FAILURE); + + if ((obj = X509_OBJECT_new()) == NULL) + return 0; + + if (!X509_CRL_up_ref(x)) { + X509_OBJECT_free(obj); return 0; } + obj->type = X509_LU_CRL; obj->data.crl = x; - CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); - - X509_OBJECT_up_ref_count(obj); - - if (X509_OBJECT_retrieve_match(ctx->objs, obj)) { - X509error(X509_R_CERT_ALREADY_IN_HASH_TABLE); - ret = 0; - } else { - if (sk_X509_OBJECT_push(ctx->objs, obj) == 0) { - X509error(ERR_R_MALLOC_FAILURE); - ret = 0; - } - } - - if (ret == 0) - X509_OBJECT_dec_ref_count(obj); - - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); - - if (ret == 0) { - obj->data.crl = NULL; /* owned by the caller */ - X509_OBJECT_free(obj); - } - - return ret; -} - -static void -X509_OBJECT_dec_ref_count(X509_OBJECT *a) -{ - switch (a->type) { - case X509_LU_X509: - CRYPTO_add(&a->data.x509->references, -1, CRYPTO_LOCK_X509); - break; - case X509_LU_CRL: - CRYPTO_add(&a->data.crl->references, -1, CRYPTO_LOCK_X509_CRL); - break; - } + return X509_STORE_add_object(store, obj); } int @@ -459,28 +442,15 @@ X509_OBJECT_up_ref_count(X509_OBJECT *a) return 1; } -int +X509_LOOKUP_TYPE X509_OBJECT_get_type(const X509_OBJECT *a) { return a->type; } -void -X509_OBJECT_free_contents(X509_OBJECT *a) -{ - switch (a->type) { - case X509_LU_X509: - X509_free(a->data.x509); - break; - case X509_LU_CRL: - X509_CRL_free(a->data.crl); - break; - } -} - static int -x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type, X509_NAME *name, - int *pnmatch) +x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, + X509_NAME *name, int *pnmatch) { X509_OBJECT stmp; X509 x509_s; @@ -502,7 +472,6 @@ x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type, X509_NAME *name, crl_info_s.issuer = name; break; default: - /* abort(); */ return -1; } @@ -510,6 +479,7 @@ x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type, X509_NAME *name, if (idx >= 0 && pnmatch) { int tidx; const X509_OBJECT *tobj, *pstmp; + *pnmatch = 1; pstmp = &stmp; for (tidx = idx + 1; tidx < sk_X509_OBJECT_num(h); tidx++) { @@ -523,13 +493,14 @@ x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type, X509_NAME *name, } int -X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type, X509_NAME *name) +X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, + X509_NAME *name) { return x509_object_idx_cnt(h, type, name, NULL); } X509_OBJECT * -X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, int type, +X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, X509_NAME *name) { int idx; @@ -556,103 +527,117 @@ X509_OBJECT_get0_X509_CRL(X509_OBJECT *xo) return NULL; } -STACK_OF(X509) * -X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm) +static STACK_OF(X509) * +X509_get1_certs_from_cache(X509_STORE *store, X509_NAME *name) { - int i, idx, cnt; - STACK_OF(X509) *sk; - X509 *x; + STACK_OF(X509) *sk = NULL; + X509 *x = NULL; X509_OBJECT *obj; + int i, idx, cnt; - if (ctx->ctx == NULL) - return NULL; - sk = sk_X509_new_null(); - if (sk == NULL) - return NULL; CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); - idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt); - if (idx < 0) { - /* Nothing found in cache: do lookup to possibly add new - * objects to cache - */ - X509_OBJECT xobj; - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); - if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj)) { - sk_X509_free(sk); - return NULL; - } - X509_OBJECT_free_contents(&xobj); - CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); - idx = x509_object_idx_cnt(ctx->ctx->objs, - X509_LU_X509, nm, &cnt); - if (idx < 0) { - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); - sk_X509_free(sk); - return NULL; - } - } + + idx = x509_object_idx_cnt(store->objs, X509_LU_X509, name, &cnt); + if (idx < 0) + goto err; + + if ((sk = sk_X509_new_null()) == NULL) + goto err; + for (i = 0; i < cnt; i++, idx++) { - obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx); + obj = sk_X509_OBJECT_value(store->objs, idx); + x = obj->data.x509; - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); - if (!sk_X509_push(sk, x)) { - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); - X509_free(x); - sk_X509_pop_free(sk, X509_free); - return NULL; + if (!X509_up_ref(x)) { + x = NULL; + goto err; } + if (!sk_X509_push(sk, x)) + goto err; } + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + return sk; + err: + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + sk_X509_pop_free(sk, X509_free); + X509_free(x); + + return NULL; +} + +STACK_OF(X509) * +X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *name) +{ + X509_STORE *store = ctx->store; + STACK_OF(X509) *sk; + X509_OBJECT *obj; + + if (store == NULL) + return NULL; + + if ((sk = X509_get1_certs_from_cache(store, name)) != NULL) + return sk; + + /* Nothing found: do lookup to possibly add new objects to cache. */ + obj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_X509, name); + if (obj == NULL) + return NULL; + X509_OBJECT_free(obj); + + return X509_get1_certs_from_cache(store, name); } STACK_OF(X509_CRL) * -X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm) +X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *name) { + X509_STORE *store = ctx->store; + STACK_OF(X509_CRL) *sk = NULL; + X509_CRL *x = NULL; + X509_OBJECT *obj = NULL; int i, idx, cnt; - STACK_OF(X509_CRL) *sk; - X509_CRL *x; - X509_OBJECT *obj, xobj; - if (ctx->ctx == NULL) + if (store == NULL) return NULL; - sk = sk_X509_CRL_new_null(); - if (sk == NULL) - return NULL; - CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); - /* Check cache first */ - idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt); - /* Always do lookup to possibly add new CRLs to cache - */ - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); - if (!X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj)) { - sk_X509_CRL_free(sk); + /* Always do lookup to possibly add new CRLs to cache */ + obj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_CRL, name); + if (obj == NULL) return NULL; - } - X509_OBJECT_free_contents(&xobj); + + X509_OBJECT_free(obj); + obj = NULL; + CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); - idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt); - if (idx < 0) { - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); - sk_X509_CRL_free(sk); - return NULL; - } + idx = x509_object_idx_cnt(store->objs, X509_LU_CRL, name, &cnt); + if (idx < 0) + goto err; + + if ((sk = sk_X509_CRL_new_null()) == NULL) + goto err; for (i = 0; i < cnt; i++, idx++) { - obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx); + obj = sk_X509_OBJECT_value(store->objs, idx); + x = obj->data.crl; - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509_CRL); - if (!sk_X509_CRL_push(sk, x)) { - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); - X509_CRL_free(x); - sk_X509_CRL_pop_free(sk, X509_CRL_free); - return NULL; + if (!X509_CRL_up_ref(x)) { + x = NULL; + goto err; } + if (!sk_X509_CRL_push(sk, x)) + goto err; } + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); return sk; + + err: + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + X509_CRL_free(x); + sk_X509_CRL_pop_free(sk, X509_CRL_free); + return NULL; } X509_OBJECT * @@ -695,47 +680,52 @@ X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x) * -1 some other error. */ int -X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) +X509_STORE_CTX_get1_issuer(X509 **out_issuer, X509_STORE_CTX *ctx, X509 *x) { X509_NAME *xn; - X509_OBJECT obj, *pobj; - int i, ok, idx, ret; + X509_OBJECT *obj, *pobj; + X509 *issuer = NULL; + int i, idx, ret; + + *out_issuer = NULL; - *issuer = NULL; xn = X509_get_issuer_name(x); - ok = X509_STORE_get_by_subject(ctx, X509_LU_X509, xn, &obj); - if (ok != X509_LU_X509) { - if (ok == X509_LU_RETRY) { - X509_OBJECT_free_contents(&obj); - X509error(X509_R_SHOULD_RETRY); - return -1; - } else if (ok != X509_LU_FAIL) { - X509_OBJECT_free_contents(&obj); - /* not good :-(, break anyway */ - return -1; - } + obj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_X509, xn); + if (obj == NULL) + return 0; + + if ((issuer = X509_OBJECT_get0_X509(obj)) == NULL) { + X509_OBJECT_free(obj); return 0; } + if (!X509_up_ref(issuer)) { + X509_OBJECT_free(obj); + return -1; + } + /* If certificate matches all OK */ - if (ctx->check_issued(ctx, x, obj.data.x509)) { - if (x509_check_cert_time(ctx, obj.data.x509, 1)) { - *issuer = obj.data.x509; + if (ctx->check_issued(ctx, x, issuer)) { + if (x509_check_cert_time(ctx, issuer, -1)) { + *out_issuer = issuer; + X509_OBJECT_free(obj); return 1; } } - X509_OBJECT_free_contents(&obj); + X509_free(issuer); + issuer = NULL; + X509_OBJECT_free(obj); + obj = NULL; - if (ctx->ctx == NULL) + if (ctx->store == NULL) return 0; /* Else find index of first cert accepted by 'check_issued' */ - ret = 0; CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); - idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn); + idx = X509_OBJECT_idx_by_subject(ctx->store->objs, X509_LU_X509, xn); if (idx != -1) /* should be true as we've had at least one match */ { /* Look through all matching certs for suitable issuer */ - for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++) { - pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i); + for (i = idx; i < sk_X509_OBJECT_num(ctx->store->objs); i++) { + pobj = sk_X509_OBJECT_value(ctx->store->objs, i); /* See if we've run past the matches */ if (pobj->type != X509_LU_X509) break; @@ -743,22 +733,28 @@ X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) X509_get_subject_name(pobj->data.x509))) break; if (ctx->check_issued(ctx, x, pobj->data.x509)) { - *issuer = pobj->data.x509; - ret = 1; + issuer = pobj->data.x509; /* * If times check, exit with match, * otherwise keep looking. Leave last * match in issuer so we return nearest * match if no certificate time is OK. */ - if (x509_check_cert_time(ctx, *issuer, 1)) + if (x509_check_cert_time(ctx, issuer, -1)) break; } } } + ret = 0; + if (issuer != NULL) { + if (!X509_up_ref(issuer)) { + ret = -1; + } else { + *out_issuer = issuer; + ret = 1; + } + } CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); - if (*issuer) - CRYPTO_add(&(*issuer)->references, 1, CRYPTO_LOCK_X509); return ret; } @@ -818,8 +814,25 @@ X509_STORE_get0_param(X509_STORE *ctx) } void -X509_STORE_set_verify_cb(X509_STORE *ctx, - int (*verify_cb)(int, X509_STORE_CTX *)) +X509_STORE_set_verify(X509_STORE *store, X509_STORE_CTX_verify_fn verify) { - ctx->verify_cb = verify_cb; + store->verify = verify; +} + +X509_STORE_CTX_verify_fn +X509_STORE_get_verify(X509_STORE *store) +{ + return store->verify; +} + +void +X509_STORE_set_verify_cb(X509_STORE *store, X509_STORE_CTX_verify_cb verify_cb) +{ + store->verify_cb = verify_cb; +} + +X509_STORE_CTX_verify_cb +X509_STORE_get_verify_cb(X509_STORE *store) +{ + return store->verify_cb; } diff --git a/crypto/x509/x509_ncons.c b/crypto/x509/x509_ncons.c index 1621f98..6135270 100644 --- a/crypto/x509/x509_ncons.c +++ b/crypto/x509/x509_ncons.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_ncons.c,v 1.4 2020/09/16 18:12:06 beck Exp $ */ +/* $OpenBSD: x509_ncons.c,v 1.5 2021/11/01 20:53:08 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project. */ @@ -64,6 +64,8 @@ #include #include +#include "x509_lcl.h" + static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, diff --git a/crypto/x509/x509_obj.c b/crypto/x509/x509_obj.c index 5c53799..58ffa3a 100644 --- a/crypto/x509/x509_obj.c +++ b/crypto/x509/x509_obj.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_obj.c,v 1.18 2018/05/18 18:19:31 tb Exp $ */ +/* $OpenBSD: x509_obj.c,v 1.19 2021/11/01 20:53:08 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -65,6 +65,8 @@ #include #include +#include "x509_lcl.h" + char * X509_NAME_oneline(const X509_NAME *a, char *buf, int len) { diff --git a/crypto/x509/x509_ocsp.c b/crypto/x509/x509_ocsp.c index 59a2e97..cc55d93 100644 --- a/crypto/x509/x509_ocsp.c +++ b/crypto/x509/x509_ocsp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_ocsp.c,v 1.1 2020/06/04 15:19:31 jsing Exp $ */ +/* $OpenBSD: x509_ocsp.c,v 1.2 2022/01/07 09:45:52 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -69,6 +69,8 @@ #include #include +#include "ocsp_local.h" + /* OCSP extensions and a couple of CRL entry extensions */ diff --git a/crypto/x509/x509_prn.c b/crypto/x509/x509_prn.c index 5c15cc3..4977051 100644 --- a/crypto/x509/x509_prn.c +++ b/crypto/x509/x509_prn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_prn.c,v 1.1 2020/06/04 15:19:32 jsing Exp $ */ +/* $OpenBSD: x509_prn.c,v 1.2 2021/11/01 20:53:08 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -62,6 +62,8 @@ #include #include +#include "x509_lcl.h" + /* Extension printing routines */ static int unknown_ext_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, diff --git a/crypto/x509/x509_purp.c b/crypto/x509/x509_purp.c index 86ee274..a05c038 100644 --- a/crypto/x509/x509_purp.c +++ b/crypto/x509/x509_purp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_purp.c,v 1.7 2021/09/13 15:26:53 claudio Exp $ */ +/* $OpenBSD: x509_purp.c,v 1.13 2021/11/04 23:52:34 beck Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2001. */ @@ -65,6 +65,9 @@ #include #include +#include "x509_internal.h" +#include "x509_lcl.h" + #define V1_ROOT (EXFLAG_V1|EXFLAG_SS) #define ku_reject(x, usage) \ (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage))) @@ -133,7 +136,7 @@ X509_check_purpose(X509 *x, int id, int ca) x509v3_cache_extensions(x); CRYPTO_w_unlock(CRYPTO_LOCK_X509); if (x->ex_flags & EXFLAG_INVALID) - return X509_V_ERR_UNSPECIFIED; + return -1; } if (id == -1) return 1; @@ -447,9 +450,7 @@ x509v3_cache_extensions(X509 *x) if (x->ex_flags & EXFLAG_SET) return; -#ifndef OPENSSL_NO_SHA - X509_digest(x, EVP_sha1(), x->sha1_hash, NULL); -#endif + X509_digest(x, X509_CERT_HASH_EVP, x->hash, NULL); /* V1 should mean no extensions ... */ if (!X509_get_version(x)) @@ -549,6 +550,10 @@ x509v3_cache_extensions(X509 *x) case NID_dvcs: x->ex_xkusage |= XKU_DVCS; break; + + case NID_anyExtendedKeyUsage: + x->ex_xkusage |= XKU_ANYEKU; + break; } } sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free); @@ -612,6 +617,9 @@ x509v3_cache_extensions(X509 *x) break; } } + + x509_verify_cert_info_populate(x); + x->ex_flags |= EXFLAG_SET; } @@ -938,3 +946,39 @@ X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid) } return X509_V_OK; } + +uint32_t +X509_get_extension_flags(X509 *x) +{ + /* Call for side-effect of computing hash and caching extensions */ + if (X509_check_purpose(x, -1, -1) != 1) + return 0; + + return x->ex_flags; +} + +uint32_t +X509_get_key_usage(X509 *x) +{ + /* Call for side-effect of computing hash and caching extensions */ + if (X509_check_purpose(x, -1, -1) != 1) + return 0; + + if (x->ex_flags & EXFLAG_KUSAGE) + return x->ex_kusage; + + return UINT32_MAX; +} + +uint32_t +X509_get_extended_key_usage(X509 *x) +{ + /* Call for side-effect of computing hash and caching extensions */ + if (X509_check_purpose(x, -1, -1) != 1) + return 0; + + if (x->ex_flags & EXFLAG_XKUSAGE) + return x->ex_xkusage; + + return UINT32_MAX; +} diff --git a/crypto/x509/x509_r2x.c b/crypto/x509/x509_r2x.c index 525163b..b3b8aa7 100644 --- a/crypto/x509/x509_r2x.c +++ b/crypto/x509/x509_r2x.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_r2x.c,v 1.11 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: x509_r2x.c,v 1.13 2021/11/03 14:36:21 schwarze Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -66,12 +66,15 @@ #include #include +#include "x509_lcl.h" + X509 * X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey) { X509 *ret = NULL; X509_CINF *xi = NULL; X509_NAME *xn; + EVP_PKEY *pubkey; if ((ret = X509_new()) == NULL) { X509error(ERR_R_MALLOC_FAILURE); @@ -86,14 +89,12 @@ X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey) goto err; if (!ASN1_INTEGER_set(xi->version, 2)) goto err; -/* xi->extensions=ri->attributes; <- bad, should not ever be done - ri->attributes=NULL; */ } xn = X509_REQ_get_subject_name(r); - if (X509_set_subject_name(ret, X509_NAME_dup(xn)) == 0) + if (X509_set_subject_name(ret, xn) == 0) goto err; - if (X509_set_issuer_name(ret, X509_NAME_dup(xn)) == 0) + if (X509_set_issuer_name(ret, xn) == 0) goto err; if (X509_gmtime_adj(xi->validity->notBefore, 0) == NULL) @@ -102,14 +103,16 @@ X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey) (long)60 * 60 * 24 * days) == NULL) goto err; - X509_set_pubkey(ret, X509_REQ_get_pubkey(r)); + if ((pubkey = X509_REQ_get0_pubkey(r)) == NULL) + goto err; + if (!X509_set_pubkey(ret, pubkey)) + goto err; if (!X509_sign(ret, pkey, EVP_md5())) goto err; - if (0) { + return ret; + err: - X509_free(ret); - ret = NULL; - } - return (ret); + X509_free(ret); + return NULL; } diff --git a/crypto/x509/x509_req.c b/crypto/x509/x509_req.c index b44306b..8d5bf58 100644 --- a/crypto/x509/x509_req.c +++ b/crypto/x509/x509_req.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_req.c,v 1.21 2018/05/13 06:48:00 tb Exp $ */ +/* $OpenBSD: x509_req.c,v 1.28 2022/01/22 00:34:48 inoguchi Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -70,6 +70,9 @@ #include #include +#include "evp_locl.h" +#include "x509_lcl.h" + X509_REQ * X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) { @@ -121,13 +124,23 @@ X509_REQ_get_pubkey(X509_REQ *req) return (X509_PUBKEY_get(req->req_info->pubkey)); } +EVP_PKEY * +X509_REQ_get0_pubkey(X509_REQ *req) +{ + if (req == NULL || req->req_info == NULL) + return NULL; + return X509_PUBKEY_get0(req->req_info->pubkey); +} + int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k) { EVP_PKEY *xk = NULL; int ok = 0; - xk = X509_REQ_get_pubkey(x); + if ((xk = X509_REQ_get0_pubkey(x)) == NULL) + return 0; + switch (EVP_PKEY_cmp(xk, k)) { case 1: ok = 1; @@ -155,7 +168,6 @@ X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k) X509error(X509_R_UNKNOWN_KEY_TYPE); } - EVP_PKEY_free(xk); return (ok); } @@ -202,66 +214,43 @@ X509_REQ_get_extensions(X509_REQ *req) int idx, *pnid; const unsigned char *p; - if ((req == NULL) || (req->req_info == NULL) || !ext_nids) - return (NULL); + if (req == NULL || req->req_info == NULL || ext_nids == NULL) + return NULL; for (pnid = ext_nids; *pnid != NID_undef; pnid++) { idx = X509_REQ_get_attr_by_NID(req, *pnid, -1); if (idx == -1) continue; attr = X509_REQ_get_attr(req, idx); - if (attr->single) - ext = attr->value.single; - else if (sk_ASN1_TYPE_num(attr->value.set)) - ext = sk_ASN1_TYPE_value(attr->value.set, 0); + ext = X509_ATTRIBUTE_get0_type(attr, 0); break; } - if (!ext || (ext->type != V_ASN1_SEQUENCE)) + if (ext == NULL || ext->type != V_ASN1_SEQUENCE) return NULL; p = ext->value.sequence->data; - return (STACK_OF(X509_EXTENSION) *)ASN1_item_d2i(NULL, &p, - ext->value.sequence->length, &X509_EXTENSIONS_it); + return d2i_X509_EXTENSIONS(NULL, &p, ext->value.sequence->length); } -/* Add a STACK_OF extensions to a certificate request: allow alternative OIDs - * in case we want to create a non standard one. +/* + * Add a STACK_OF extensions to a certificate request: allow alternative OIDs + * in case we want to create a non-standard one. */ int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts, int nid) { - ASN1_TYPE *at = NULL; - X509_ATTRIBUTE *attr = NULL; + unsigned char *ext = NULL; + int extlen; + int rv; - if (!(at = ASN1_TYPE_new()) || - !(at->value.sequence = ASN1_STRING_new())) - goto err; + extlen = i2d_X509_EXTENSIONS(exts, &ext); + if (extlen <= 0) + return 0; - at->type = V_ASN1_SEQUENCE; - /* Generate encoding of extensions */ - at->value.sequence->length = ASN1_item_i2d((ASN1_VALUE *)exts, - &at->value.sequence->data, &X509_EXTENSIONS_it); - if (!(attr = X509_ATTRIBUTE_new())) - goto err; - if (!(attr->value.set = sk_ASN1_TYPE_new_null())) - goto err; - if (!sk_ASN1_TYPE_push(attr->value.set, at)) - goto err; - at = NULL; - attr->single = 0; - attr->object = OBJ_nid2obj(nid); - if (!req->req_info->attributes) { - if (!(req->req_info->attributes = sk_X509_ATTRIBUTE_new_null())) - goto err; - } - if (!sk_X509_ATTRIBUTE_push(req->req_info->attributes, attr)) - goto err; - return 1; + rv = X509_REQ_add1_attr_by_NID(req, nid, V_ASN1_SEQUENCE, ext, extlen); + free(ext); -err: - X509_ATTRIBUTE_free(attr); - ASN1_TYPE_free(at); - return 0; + return rv; } /* This is the normal usage: use the "official" OID */ @@ -341,3 +330,10 @@ X509_REQ_add1_attr_by_txt(X509_REQ *req, const char *attrname, int type, return 1; return 0; } + +int +i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp) +{ + req->req_info->enc.modified = 1; + return i2d_X509_REQ_INFO(req->req_info, pp); +} diff --git a/crypto/x509/x509_set.c b/crypto/x509/x509_set.c index 1a4b583..5784f22 100644 --- a/crypto/x509/x509_set.c +++ b/crypto/x509/x509_set.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_set.c,v 1.17 2018/08/24 19:55:58 tb Exp $ */ +/* $OpenBSD: x509_set.c,v 1.20 2021/11/01 20:53:08 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -63,6 +63,8 @@ #include #include +#include "x509_lcl.h" + const STACK_OF(X509_EXTENSION) * X509_get0_extensions(const X509 *x) { @@ -216,3 +218,9 @@ X509_get_signature_type(const X509 *x) { return EVP_PKEY_type(OBJ_obj2nid(x->sig_alg->algorithm)); } + +X509_PUBKEY * +X509_get_X509_PUBKEY(const X509 *x) +{ + return x->cert_info->key; +} diff --git a/crypto/x509/x509_skey.c b/crypto/x509/x509_skey.c index a906427..58bb66b 100644 --- a/crypto/x509/x509_skey.c +++ b/crypto/x509/x509_skey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_skey.c,v 1.1 2020/06/04 15:19:32 jsing Exp $ */ +/* $OpenBSD: x509_skey.c,v 1.2 2021/11/01 20:53:08 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -62,6 +62,8 @@ #include #include +#include "x509_lcl.h" + static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str); diff --git a/crypto/x509/x509_trs.c b/crypto/x509/x509_trs.c index 1a60e5a..72d616a 100644 --- a/crypto/x509/x509_trs.c +++ b/crypto/x509/x509_trs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_trs.c,v 1.24 2021/07/23 20:50:28 schwarze Exp $ */ +/* $OpenBSD: x509_trs.c,v 1.25 2021/11/01 20:53:08 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -62,6 +62,8 @@ #include #include +#include "x509_lcl.h" + static int tr_cmp(const X509_TRUST * const *a, const X509_TRUST * const *b); static void trtable_free(X509_TRUST *p); diff --git a/crypto/x509/x509_v3.c b/crypto/x509/x509_v3.c index 524d551..9aefb8d 100644 --- a/crypto/x509/x509_v3.c +++ b/crypto/x509/x509_v3.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_v3.c,v 1.17 2018/05/19 10:54:40 tb Exp $ */ +/* $OpenBSD: x509_v3.c,v 1.18 2021/11/01 20:53:08 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -66,6 +66,8 @@ #include #include +#include "x509_lcl.h" + int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x) { diff --git a/crypto/x509/x509_verify.c b/crypto/x509/x509_verify.c index 5ff7c50..6a73cb7 100644 --- a/crypto/x509/x509_verify.c +++ b/crypto/x509/x509_verify.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_verify.c,v 1.49.2.1 2021/11/24 09:28:56 tb Exp $ */ +/* $OpenBSD: x509_verify.c,v 1.54 2021/11/24 05:38:12 beck Exp $ */ /* * Copyright (c) 2020-2021 Bob Beck * @@ -38,7 +38,58 @@ static int x509_verify_cert_error(struct x509_verify_ctx *ctx, X509 *cert, size_t depth, int error, int ok); static void x509_verify_chain_free(struct x509_verify_chain *chain); -#define X509_VERIFY_CERT_HASH (EVP_sha512()) +/* + * Parse an asn1 to a representable time_t as per RFC 5280 rules. + * Returns -1 if that can't be done for any reason. + */ +time_t +x509_verify_asn1_time_to_time_t(const ASN1_TIME *atime, int notAfter) +{ + struct tm tm = { 0 }; + int type; + + type = ASN1_time_parse(atime->data, atime->length, &tm, atime->type); + if (type == -1) + return -1; + + /* RFC 5280 section 4.1.2.5 */ + if (tm.tm_year < 150 && type != V_ASN1_UTCTIME) + return -1; + if (tm.tm_year >= 150 && type != V_ASN1_GENERALIZEDTIME) + return -1; + + if (notAfter) { + /* + * If we are a completely broken operating system with a + * 32 bit time_t, and we have been told this is a notAfter + * date, limit the date to a 32 bit representable value. + */ + if (!ASN1_time_tm_clamp_notafter(&tm)) + return -1; + } + + /* + * Defensively fail if the time string is not representable as + * a time_t. A time_t must be sane if you care about times after + * Jan 19 2038. + */ + return timegm(&tm); +} + +/* + * Cache certificate hash, and values parsed out of an X509. + * called from cache_extensions() + */ +void +x509_verify_cert_info_populate(X509 *cert) +{ + /* + * Parse and save the cert times, or remember that they + * are unacceptable/unparsable. + */ + cert->not_before = x509_verify_asn1_time_to_time_t(X509_get_notBefore(cert), 0); + cert->not_after = x509_verify_asn1_time_to_time_t(X509_get_notAfter(cert), 1); +} struct x509_verify_chain * x509_verify_chain_new(void) @@ -194,6 +245,7 @@ x509_verify_cert_cache_extensions(X509 *cert) { } if (cert->ex_flags & EXFLAG_INVALID) return 0; + return (cert->ex_flags & EXFLAG_SET); } @@ -244,7 +296,7 @@ x509_verify_ctx_set_xsc_chain(struct x509_verify_ctx *ctx, return 1; /* - * XXX last_untrusted is actually the number of untrusted certs at the + * XXX num_untrusted is the number of untrusted certs at the * bottom of the chain. This works now since we stop at the first * trusted cert. This will need fixing once we allow more than one * trusted certificate. @@ -252,7 +304,7 @@ x509_verify_ctx_set_xsc_chain(struct x509_verify_ctx *ctx, num_untrusted = sk_X509_num(chain->certs); if (is_trusted && num_untrusted > 0) num_untrusted--; - ctx->xsc->last_untrusted = num_untrusted; + ctx->xsc->num_untrusted = num_untrusted; sk_X509_pop_free(ctx->xsc->chain, X509_free); ctx->xsc->chain = X509_chain_up_ref(chain->certs); @@ -352,6 +404,14 @@ x509_verify_ctx_validate_legacy_chain(struct x509_verify_ctx *ctx, if (!x509_vfy_check_chain_extensions(ctx->xsc)) goto err; +#ifndef OPENSSL_NO_RFC3779 + if (!X509v3_asid_validate_path(ctx->xsc)) + goto err; + + if (!X509v3_addr_validate_path(ctx->xsc)) + goto err; +#endif + if (!x509_constraints_chain(ctx->xsc->chain, &ctx->xsc->error, &ctx->xsc->error_depth)) { X509 *cert = sk_X509_value(ctx->xsc->chain, depth); @@ -447,22 +507,15 @@ x509_verify_potential_parent(struct x509_verify_ctx *ctx, X509 *parent, } static int -x509_verify_parent_signature(X509 *parent, X509 *child, - unsigned char *child_md, int *error) +x509_verify_parent_signature(X509 *parent, X509 *child, int *error) { - unsigned char parent_md[EVP_MAX_MD_SIZE] = { 0 }; EVP_PKEY *pkey; int cached; int ret = 0; /* Use cached value if we have it */ - if (child_md != NULL) { - if (!X509_digest(parent, X509_VERIFY_CERT_HASH, parent_md, - NULL)) - return 0; - if ((cached = x509_issuer_cache_find(parent_md, child_md)) >= 0) - return cached; - } + if ((cached = x509_issuer_cache_find(parent->hash, child->hash)) >= 0) + return cached; /* Check signature. Did parent sign child? */ if ((pkey = X509_get_pubkey(parent)) == NULL) { @@ -475,8 +528,7 @@ x509_verify_parent_signature(X509 *parent, X509 *child, ret = 1; /* Add result to cache */ - if (child_md != NULL) - x509_issuer_cache_add(parent_md, child_md, ret); + x509_issuer_cache_add(parent->hash, child->hash, ret); EVP_PKEY_free(pkey); @@ -485,8 +537,8 @@ x509_verify_parent_signature(X509 *parent, X509 *child, static int x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert, - unsigned char *cert_md, int is_root_cert, X509 *candidate, - struct x509_verify_chain *current_chain, int full_chain) + int is_root_cert, X509 *candidate, struct x509_verify_chain *current_chain, + int full_chain) { int depth = sk_X509_num(current_chain->certs); struct x509_verify_chain *new_chain; @@ -506,8 +558,7 @@ x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert, return 0; } - if (!x509_verify_parent_signature(candidate, cert, cert_md, - &ctx->error)) { + if (!x509_verify_parent_signature(candidate, cert, &ctx->error)) { if (!x509_verify_cert_error(ctx, candidate, depth, ctx->error, 0)) return 0; @@ -571,7 +622,6 @@ static void x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, struct x509_verify_chain *current_chain, int full_chain) { - unsigned char cert_md[EVP_MAX_MD_SIZE] = { 0 }; X509 *candidate; int i, depth, count, ret, is_root; @@ -592,11 +642,6 @@ x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, X509_V_ERR_CERT_CHAIN_TOO_LONG, 0)) return; - if (!X509_digest(cert, X509_VERIFY_CERT_HASH, cert_md, NULL) && - !x509_verify_cert_error(ctx, cert, depth, - X509_V_ERR_UNSPECIFIED, 0)) - return; - count = ctx->chains_count; ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY; @@ -632,7 +677,7 @@ x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, is_root = !full_chain || x509_verify_cert_self_signed(candidate); x509_verify_consider_candidate(ctx, cert, - cert_md, is_root, candidate, current_chain, + is_root, candidate, current_chain, full_chain); } X509_free(candidate); @@ -645,7 +690,7 @@ x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, is_root = !full_chain || x509_verify_cert_self_signed(candidate); x509_verify_consider_candidate(ctx, cert, - cert_md, is_root, candidate, current_chain, + is_root, candidate, current_chain, full_chain); } } @@ -657,7 +702,7 @@ x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, candidate = sk_X509_value(ctx->intermediates, i); if (x509_verify_potential_parent(ctx, candidate, cert)) { x509_verify_consider_candidate(ctx, cert, - cert_md, 0, candidate, current_chain, + 0, candidate, current_chain, full_chain); } } @@ -726,7 +771,8 @@ x509_verify_cert_hostname(struct x509_verify_ctx *ctx, X509 *cert, char *name) } static int -x509_verify_set_check_time(struct x509_verify_ctx *ctx) { +x509_verify_set_check_time(struct x509_verify_ctx *ctx) +{ if (ctx->xsc != NULL) { if (ctx->xsc->param->flags & X509_V_FLAG_USE_CHECK_TIME) { ctx->check_time = &ctx->xsc->param->check_time; @@ -740,47 +786,9 @@ x509_verify_set_check_time(struct x509_verify_ctx *ctx) { return 1; } -int -x509_verify_asn1_time_to_tm(const ASN1_TIME *atime, struct tm *tm, int notafter) -{ - int type; - - type = ASN1_time_parse(atime->data, atime->length, tm, atime->type); - if (type == -1) - return 0; - - /* RFC 5280 section 4.1.2.5 */ - if (tm->tm_year < 150 && type != V_ASN1_UTCTIME) - return 0; - if (tm->tm_year >= 150 && type != V_ASN1_GENERALIZEDTIME) - return 0; - - if (notafter) { - /* - * If we are a completely broken operating system with a - * 32 bit time_t, and we have been told this is a notafter - * date, limit the date to a 32 bit representable value. - */ - if (!ASN1_time_tm_clamp_notafter(tm)) - return 0; - } - - /* - * Defensively fail if the time string is not representable as - * a time_t. A time_t must be sane if you care about times after - * Jan 19 2038. - */ - if (timegm(tm) == -1) - return 0; - - return 1; -} - static int -x509_verify_cert_time(int is_notafter, const ASN1_TIME *cert_asn1, - time_t *cmp_time, int *error) +x509_verify_cert_times(X509 *cert, time_t *cmp_time, int *error) { - struct tm cert_tm, when_tm; time_t when; if (cmp_time == NULL) @@ -788,29 +796,21 @@ x509_verify_cert_time(int is_notafter, const ASN1_TIME *cert_asn1, else when = *cmp_time; - if (!x509_verify_asn1_time_to_tm(cert_asn1, &cert_tm, - is_notafter)) { - *error = is_notafter ? - X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD : - X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD; + if (cert->not_before == -1) { + *error = X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD; return 0; } - - if (gmtime_r(&when, &when_tm) == NULL) { - *error = X509_V_ERR_UNSPECIFIED; + if (when < cert->not_before) { + *error = X509_V_ERR_CERT_NOT_YET_VALID; return 0; } - - if (is_notafter) { - if (ASN1_time_tm_cmp(&cert_tm, &when_tm) == -1) { - *error = X509_V_ERR_CERT_HAS_EXPIRED; - return 0; - } - } else { - if (ASN1_time_tm_cmp(&cert_tm, &when_tm) == 1) { - *error = X509_V_ERR_CERT_NOT_YET_VALID; - return 0; - } + if (cert->not_after == -1) { + *error = X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD; + return 0; + } + if (when > cert->not_after) { + *error = X509_V_ERR_CERT_HAS_EXPIRED; + return 0; } return 1; @@ -916,15 +916,8 @@ x509_verify_cert_valid(struct x509_verify_ctx *ctx, X509 *cert, } if (x509_verify_set_check_time(ctx)) { - if (!x509_verify_cert_time(0, X509_get_notBefore(cert), - ctx->check_time, &ctx->error)) { - if (!x509_verify_cert_error(ctx, cert, depth, - ctx->error, 0)) - return 0; - } - - if (!x509_verify_cert_time(1, X509_get_notAfter(cert), - ctx->check_time, &ctx->error)) { + if (!x509_verify_cert_times(cert, ctx->check_time, + &ctx->error)) { if (!x509_verify_cert_error(ctx, cert, depth, ctx->error, 0)) return 0; diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index 1f52779..9a92996 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_vfy.c,v 1.89.2.1 2021/11/24 09:28:56 tb Exp $ */ +/* $OpenBSD: x509_vfy.c,v 1.101 2022/01/22 00:36:46 inoguchi Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -76,8 +76,6 @@ #include "asn1_locl.h" #include "vpm_int.h" #include "x509_internal.h" -#include "x509_lcl.h" -#include "x509_internal.h" /* CRL score values */ @@ -264,7 +262,7 @@ X509_verify_cert_legacy_build_chain(X509_STORE_CTX *ctx, int *bad, int *out_ok) goto end; } X509_up_ref(ctx->cert); - ctx->last_untrusted = 1; + ctx->num_untrusted = 1; /* We use a temporary STACK so we can chop and hack at it */ if (ctx->untrusted != NULL && @@ -338,7 +336,7 @@ X509_verify_cert_legacy_build_chain(X509_STORE_CTX *ctx, int *bad, int *out_ok) } X509_up_ref(xtmp); (void)sk_X509_delete_ptr(sktmp, xtmp); - ctx->last_untrusted++; + ctx->num_untrusted++; x = xtmp; num++; /* @@ -396,7 +394,7 @@ X509_verify_cert_legacy_build_chain(X509_STORE_CTX *ctx, int *bad, int *out_ok) X509_free(x); x = xtmp; (void)sk_X509_set(ctx->chain, i - 1, x); - ctx->last_untrusted = 0; + ctx->num_untrusted = 0; } } else { /* @@ -404,7 +402,7 @@ X509_verify_cert_legacy_build_chain(X509_STORE_CTX *ctx, int *bad, int *out_ok) * certificate for later use */ chain_ss = sk_X509_pop(ctx->chain); - ctx->last_untrusted--; + ctx->num_untrusted--; num--; j--; x = sk_X509_value(ctx->chain, num - 1); @@ -478,7 +476,7 @@ X509_verify_cert_legacy_build_chain(X509_STORE_CTX *ctx, int *bad, int *out_ok) X509_free(xtmp); num--; } - ctx->last_untrusted = sk_X509_num(ctx->chain); + ctx->num_untrusted = sk_X509_num(ctx->chain); retry = 1; break; } @@ -493,7 +491,7 @@ X509_verify_cert_legacy_build_chain(X509_STORE_CTX *ctx, int *bad, int *out_ok) */ if (trust != X509_TRUST_TRUSTED && !bad_chain) { if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss)) { - if (ctx->last_untrusted >= num) + if (ctx->num_untrusted >= num) ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY; else ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT; @@ -506,7 +504,7 @@ X509_verify_cert_legacy_build_chain(X509_STORE_CTX *ctx, int *bad, int *out_ok) goto end; } num++; - ctx->last_untrusted = num; + ctx->num_untrusted = num; ctx->current_cert = chain_ss; ctx->error = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN; chain_ss = NULL; @@ -549,6 +547,16 @@ X509_verify_cert_legacy(X509_STORE_CTX *ctx) if (!ok) goto end; +#ifndef OPENSSL_NO_RFC3779 + ok = X509v3_asid_validate_path(ctx); + if (!ok) + goto end; + + ok = X509v3_addr_validate_path(ctx); + if (!ok) + goto end; +#endif + ok = check_id(ctx); if (!ok) goto end; @@ -741,7 +749,7 @@ x509_vfy_check_chain_extensions(X509_STORE_CTX *ctx) } /* Check all untrusted certificates */ - for (i = 0; i < ctx->last_untrusted; i++) { + for (i = 0; i < ctx->num_untrusted; i++) { int ret; x = sk_X509_value(ctx->chain, i); if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) && @@ -898,8 +906,8 @@ lookup_cert_match(X509_STORE_CTX *ctx, X509 *x) X509 * x509_vfy_lookup_cert_match(X509_STORE_CTX *ctx, X509 *x) { - if (ctx->lookup_certs == NULL || ctx->ctx == NULL || - ctx->ctx->objs == NULL) + if (ctx->lookup_certs == NULL || ctx->store == NULL || + ctx->store->objs == NULL) return NULL; return lookup_cert_match(ctx, x); } @@ -914,7 +922,7 @@ check_trust(X509_STORE_CTX *ctx) cb = ctx->verify_cb; /* Check all trusted certificates in chain */ - for (i = ctx->last_untrusted; i < sk_X509_num(ctx->chain); i++) { + for (i = ctx->num_untrusted; i < sk_X509_num(ctx->chain); i++) { x = sk_X509_value(ctx->chain, i); ok = X509_check_trust(x, ctx->param->trust, 0); @@ -940,14 +948,14 @@ check_trust(X509_STORE_CTX *ctx) */ if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) { X509 *mx; - if (ctx->last_untrusted < (int)sk_X509_num(ctx->chain)) + if (ctx->num_untrusted < (int)sk_X509_num(ctx->chain)) return X509_TRUST_TRUSTED; x = sk_X509_value(ctx->chain, 0); mx = lookup_cert_match(ctx, x); if (mx) { (void)sk_X509_set(ctx->chain, 0, mx); X509_free(x); - ctx->last_untrusted = 0; + ctx->num_untrusted = 0; return X509_TRUST_TRUSTED; } } @@ -1072,17 +1080,17 @@ err: static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify) { - time_t *ptime = NULL; + time_t *ptime; int i; - if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) - return (1); - - if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) - ptime = &ctx->param->check_time; - if (notify) ctx->current_crl = crl; + if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) + ptime = &ctx->param->check_time; + else if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) + return (1); + else + ptime = NULL; i = X509_cmp_time(X509_CRL_get_lastUpdate(crl), ptime); if (i == 0) { @@ -1407,7 +1415,7 @@ check_crl_path(X509_STORE_CTX *ctx, X509 *x) /* Don't allow recursive CRL path validation */ if (ctx->parent) return 0; - if (!X509_STORE_CTX_init(&crl_ctx, ctx->ctx, x, ctx->untrusted)) { + if (!X509_STORE_CTX_init(&crl_ctx, ctx->store, x, ctx->untrusted)) { ret = -1; goto err; } @@ -1835,6 +1843,18 @@ verify_cb_cert(X509_STORE_CTX *ctx, X509 *x, int depth, int err) return ctx->verify_cb(0, ctx); } + +/* Mimic OpenSSL '0 for failure' ick */ +static int +time_t_bogocmp(time_t a, time_t b) +{ + if (a == -1 || b == -1) + return 0; + if (a <= b) + return -1; + return 1; +} + /* * Check certificate validity times. * @@ -1846,17 +1866,21 @@ verify_cb_cert(X509_STORE_CTX *ctx, X509 *x, int depth, int err) int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth) { - time_t *ptime; + time_t ptime; int i; if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) - ptime = &ctx->param->check_time; + ptime = ctx->param->check_time; else if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) return 1; else - ptime = NULL; + ptime = time(NULL); + + if (x->ex_flags & EXFLAG_SET) + i = time_t_bogocmp(x->not_before, ptime); + else + i = X509_cmp_time(X509_get_notBefore(x), &ptime); - i = X509_cmp_time(X509_get_notBefore(x), ptime); if (i >= 0 && depth < 0) return 0; if (i == 0 && !verify_cb_cert(ctx, x, depth, @@ -1866,7 +1890,11 @@ x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth) X509_V_ERR_CERT_NOT_YET_VALID)) return 0; - i = X509_cmp_time_internal(X509_get_notAfter(x), ptime, 1); + if (x->ex_flags & EXFLAG_SET) + i = time_t_bogocmp(x->not_after, ptime); + else + i = X509_cmp_time_internal(X509_get_notAfter(x), &ptime, 1); + if (i <= 0 && depth < 0) return 0; if (i == 0 && !verify_cb_cert(ctx, x, depth, @@ -1875,6 +1903,7 @@ x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth) if (i < 0 && !verify_cb_cert(ctx, x, depth, X509_V_ERR_CERT_HAS_EXPIRED)) return 0; + return 1; } @@ -1990,30 +2019,23 @@ X509_cmp_current_time(const ASN1_TIME *ctm) * 0 on error. */ static int -X509_cmp_time_internal(const ASN1_TIME *ctm, time_t *cmp_time, int clamp_notafter) +X509_cmp_time_internal(const ASN1_TIME *ctm, time_t *cmp_time, int is_notafter) { - time_t compare; - struct tm tm1, tm2; - int ret = 0; + time_t compare, cert_time; if (cmp_time == NULL) compare = time(NULL); else compare = *cmp_time; - memset(&tm1, 0, sizeof(tm1)); + if ((cert_time = x509_verify_asn1_time_to_time_t(ctm, is_notafter)) == + -1) + return 0; /* invalid time */ - if (!x509_verify_asn1_time_to_tm(ctm, &tm1, clamp_notafter)) - goto out; /* invalid time */ + if (cert_time <= compare) + return -1; /* 0 is used for error, so map same to less than */ - if (gmtime_r(&compare, &tm2) == NULL) - goto out; - - ret = ASN1_time_tm_cmp(&tm1, &tm2); - if (ret == 0) - ret = -1; /* 0 is used for error, so map same to less than */ - out: - return (ret); + return 1; } int @@ -2057,17 +2079,15 @@ X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain) return 1; for (i = 0; i < sk_X509_num(chain); i++) { - ktmp = X509_get_pubkey(sk_X509_value(chain, i)); + ktmp = X509_get0_pubkey(sk_X509_value(chain, i)); if (ktmp == NULL) { X509error(X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY); return 0; } if (!EVP_PKEY_missing_parameters(ktmp)) break; - else { - EVP_PKEY_free(ktmp); + else ktmp = NULL; - } } if (ktmp == NULL) { X509error(X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN); @@ -2076,14 +2096,15 @@ X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain) /* first, populate the other certs */ for (j = i - 1; j >= 0; j--) { - ktmp2 = X509_get_pubkey(sk_X509_value(chain, j)); - EVP_PKEY_copy_parameters(ktmp2, ktmp); - EVP_PKEY_free(ktmp2); + if ((ktmp2 = X509_get0_pubkey(sk_X509_value(chain, j))) == NULL) + return 0; + if (!EVP_PKEY_copy_parameters(ktmp2, ktmp)) + return 0; } if (pkey != NULL) - EVP_PKEY_copy_parameters(pkey, ktmp); - EVP_PKEY_free(ktmp); + if (!EVP_PKEY_copy_parameters(pkey, ktmp)) + return 0; return 1; } @@ -2127,12 +2148,24 @@ X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx) return ctx->error_depth; } +void +X509_STORE_CTX_set_error_depth(X509_STORE_CTX *ctx, int depth) +{ + ctx->error_depth = depth; +} + X509 * X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx) { return ctx->current_cert; } +void +X509_STORE_CTX_set_current_cert(X509_STORE_CTX *ctx, X509 *x) +{ + ctx->current_cert = x; +} + STACK_OF(X509) * X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx) { @@ -2182,7 +2215,7 @@ X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx) X509_STORE * X509_STORE_CTX_get0_store(X509_STORE_CTX *xs) { - return xs->ctx; + return xs->store; } void @@ -2322,7 +2355,7 @@ X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, * may fail should go last to make sure 'ctx' is as consistent as * possible even on early exits. */ - ctx->ctx = store; + ctx->store = store; ctx->cert = x509; ctx->untrusted = chain; @@ -2472,6 +2505,12 @@ X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, time_t t) X509_VERIFY_PARAM_set_time(ctx->param, t); } +int +(*X509_STORE_CTX_get_verify_cb(X509_STORE_CTX *ctx))(int, X509_STORE_CTX *) +{ + return ctx->verify_cb; +} + void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, int (*verify_cb)(int, X509_STORE_CTX *)) @@ -2479,6 +2518,18 @@ X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, ctx->verify_cb = verify_cb; } +int +(*X509_STORE_CTX_get_verify(X509_STORE_CTX *ctx))(X509_STORE_CTX *) +{ + return ctx->verify; +} + +void +X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx, int (*verify)(X509_STORE_CTX *)) +{ + ctx->verify = verify; +} + X509 * X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx) { @@ -2497,6 +2548,13 @@ X509_STORE_CTX_set0_untrusted(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) ctx->untrusted = sk; } +void +X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) +{ + sk_X509_pop_free(ctx->chain, X509_free); + ctx->chain = sk; +} + X509_POLICY_TREE * X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx) { @@ -2509,6 +2567,12 @@ X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx) return ctx->explicit_policy; } +int +X509_STORE_CTX_get_num_untrusted(X509_STORE_CTX *ctx) +{ + return ctx->num_untrusted; +} + int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name) { diff --git a/crypto/x509/x509_vpm.c b/crypto/x509/x509_vpm.c index 42ea6e7..13171e4 100644 --- a/crypto/x509/x509_vpm.c +++ b/crypto/x509/x509_vpm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_vpm.c,v 1.27 2021/09/30 18:23:46 jsing Exp $ */ +/* $OpenBSD: x509_vpm.c,v 1.28 2021/11/01 20:53:08 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2004. */ @@ -67,6 +67,7 @@ #include #include "vpm_int.h" +#include "x509_lcl.h" /* X509_VERIFY_PARAM functions */ diff --git a/crypto/x509/x509cset.c b/crypto/x509/x509cset.c index 182dd8a..b3af77d 100644 --- a/crypto/x509/x509cset.c +++ b/crypto/x509/x509cset.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509cset.c,v 1.14 2018/02/22 17:01:44 jsing Exp $ */ +/* $OpenBSD: x509cset.c,v 1.16 2021/11/01 20:53:08 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2001. */ @@ -63,8 +63,10 @@ #include #include +#include "x509_lcl.h" + int -X509_CRL_up_ref(X509_CRL *x) +X509_CRL_up_ref(X509_CRL *x) { int refs = CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509_CRL); return (refs > 1) ? 1 : 0; @@ -208,3 +210,10 @@ X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial) } return (in != NULL); } + +int +i2d_re_X509_CRL_tbs(X509_CRL *crl, unsigned char **pp) +{ + crl->crl->enc.modified = 1; + return i2d_X509_CRL_INFO(crl->crl, pp); +} diff --git a/crypto/x509/x509name.c b/crypto/x509/x509name.c index 3649d6a..878d787 100644 --- a/crypto/x509/x509name.c +++ b/crypto/x509/x509name.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509name.c,v 1.26 2018/05/30 15:35:45 tb Exp $ */ +/* $OpenBSD: x509name.c,v 1.27 2021/11/01 20:53:08 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -66,6 +66,8 @@ #include #include +#include "x509_lcl.h" + int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len) { diff --git a/crypto/x509/x509rset.c b/crypto/x509/x509rset.c index de02a40..a2dd9e4 100644 --- a/crypto/x509/x509rset.c +++ b/crypto/x509/x509rset.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509rset.c,v 1.7 2018/08/24 19:55:58 tb Exp $ */ +/* $OpenBSD: x509rset.c,v 1.9 2021/11/01 20:53:08 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -63,11 +63,14 @@ #include #include +#include "x509_lcl.h" + int X509_REQ_set_version(X509_REQ *x, long version) { if (x == NULL) return (0); + x->req_info->enc.modified = 1; return (ASN1_INTEGER_set(x->req_info->version, version)); } @@ -82,6 +85,7 @@ X509_REQ_set_subject_name(X509_REQ *x, X509_NAME *name) { if ((x == NULL) || (x->req_info == NULL)) return (0); + x->req_info->enc.modified = 1; return (X509_NAME_set(&x->req_info->subject, name)); } @@ -96,5 +100,6 @@ X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey) { if ((x == NULL) || (x->req_info == NULL)) return (0); + x->req_info->enc.modified = 1; return (X509_PUBKEY_set(&x->req_info->pubkey, pkey)); } diff --git a/crypto/x509/x509type.c b/crypto/x509/x509type.c index 315a5c2..7495b9e 100644 --- a/crypto/x509/x509type.c +++ b/crypto/x509/x509type.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509type.c,v 1.13 2018/05/30 15:59:33 tb Exp $ */ +/* $OpenBSD: x509type.c,v 1.15 2021/12/12 21:30:14 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -62,6 +62,9 @@ #include #include +#include "evp_locl.h" +#include "x509_lcl.h" + int X509_certificate_type(const X509 *x, const EVP_PKEY *pkey) { diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c index 36c12b8..9bcb0c3 100644 --- a/crypto/x509/x_all.c +++ b/crypto/x509/x_all.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x_all.c,v 1.23 2016/12/30 15:24:51 jsing Exp $ */ +/* $OpenBSD: x_all.c,v 1.25 2021/12/03 16:46:50 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -73,6 +73,8 @@ #include #endif +#include "x509_lcl.h" + X509 * d2i_X509_bio(BIO *bp, X509 **x509) { @@ -217,31 +219,6 @@ i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa) { return ASN1_item_i2d_fp(&RSAPublicKey_it, fp, rsa); } - -RSA * -d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa) -{ - return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSA_PUBKEY, bp, rsa); -} - -int -i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa) -{ - return ASN1_i2d_bio_of(RSA, i2d_RSA_PUBKEY, bp, rsa); -} - -int -i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa) -{ - return ASN1_i2d_fp((I2D_OF(void))i2d_RSA_PUBKEY, fp, rsa); -} - -RSA * -d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa) -{ - return ASN1_d2i_fp((void *(*)(void))RSA_new, - (D2I_OF(void))d2i_RSA_PUBKEY, fp, (void **)rsa); -} #endif #ifndef OPENSSL_NO_DSA @@ -268,30 +245,6 @@ i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa) { return ASN1_item_i2d_fp(&DSAPrivateKey_it, fp, dsa); } - -DSA * -d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa) -{ - return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSA_PUBKEY, bp, dsa); -} - -int -i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa) -{ - return ASN1_i2d_bio_of(DSA, i2d_DSA_PUBKEY, bp, dsa); -} - -DSA * -d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa) -{ - return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSA_PUBKEY, fp, dsa); -} - -int -i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa) -{ - return ASN1_i2d_fp_of(DSA, i2d_DSA_PUBKEY, fp, dsa); -} #endif #ifndef OPENSSL_NO_EC @@ -318,29 +271,6 @@ i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey) { return ASN1_i2d_fp_of(EC_KEY, i2d_ECPrivateKey, fp, eckey); } - -EC_KEY * -d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey) -{ - return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, bp, eckey); -} - -int -i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *ecdsa) -{ - return ASN1_i2d_bio_of(EC_KEY, i2d_EC_PUBKEY, bp, ecdsa); -} -EC_KEY * -d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey) -{ - return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, fp, eckey); -} - -int -i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey) -{ - return ASN1_i2d_fp_of(EC_KEY, i2d_EC_PUBKEY, fp, eckey); -} #endif X509_SIG * @@ -421,30 +351,6 @@ i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey) return ASN1_i2d_fp_of(EVP_PKEY, i2d_PrivateKey, fp, pkey); } -EVP_PKEY * -d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a) -{ - return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, bp, a); -} - -int -i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey) -{ - return ASN1_i2d_bio_of(EVP_PKEY, i2d_PUBKEY, bp, pkey); -} - -int -i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey) -{ - return ASN1_i2d_fp_of(EVP_PKEY, i2d_PUBKEY, fp, pkey); -} - -EVP_PKEY * -d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a) -{ - return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, fp, a); -} - int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key) { diff --git a/include/compat/arpa/nameser.h b/include/compat/arpa/nameser.h index 0126a60..eff3b0d 100644 --- a/include/compat/arpa/nameser.h +++ b/include/compat/arpa/nameser.h @@ -4,7 +4,9 @@ */ #ifndef _WIN32 +#ifdef HAVE_ARPA_NAMESER_H #include_next +#endif #else #include diff --git a/include/compat/machine/endian.h b/include/compat/endian.h similarity index 86% rename from include/compat/machine/endian.h rename to include/compat/endian.h index 4dcb60d..1ed255e 100644 --- a/include/compat/machine/endian.h +++ b/include/compat/endian.h @@ -1,6 +1,6 @@ /* * Public domain - * machine/endian.h compatibility shim + * endian.h compatibility shim */ #ifndef LIBCRYPTOCOMPAT_BYTE_ORDER_H_ @@ -21,8 +21,8 @@ #define BYTE_ORDER BIG_ENDIAN #endif -#elif defined(__linux__) || defined(__midipix__) -#include +#elif defined(HAVE_ENDIAN_H) +#include_next #elif defined(__sun) || defined(_AIX) || defined(__hpux) #include @@ -32,9 +32,6 @@ #include #include -#else -#include_next - #endif #ifndef __STRICT_ALIGNMENT diff --git a/include/compat/err.h b/include/compat/err.h index 8b5b635..945a75d 100644 --- a/include/compat/err.h +++ b/include/compat/err.h @@ -72,16 +72,22 @@ warn(const char *fmt, ...) fprintf(stderr, "%s\n", strerror(sverrno)); } +static inline void +vwarnx(const char *fmt, va_list args) +{ + if (fmt != NULL) + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); +} + static inline void warnx(const char *fmt, ...) { va_list ap; va_start(ap, fmt); - if (fmt != NULL) - vfprintf(stderr, fmt, ap); + vwarnx(fmt, ap); va_end(ap); - fprintf(stderr, "\n"); } #endif diff --git a/include/compat/netinet/ip.h b/include/compat/netinet/ip.h index 6019f7d..29f17f3 100644 --- a/include/compat/netinet/ip.h +++ b/include/compat/netinet/ip.h @@ -8,7 +8,9 @@ #endif #ifndef _WIN32 +#ifdef HAVE_NETINET_IP_H #include_next +#endif #else #include #endif diff --git a/include/compat/resolv.h b/include/compat/resolv.h index 42dec07..b804460 100644 --- a/include/compat/resolv.h +++ b/include/compat/resolv.h @@ -12,7 +12,7 @@ #else #include <../include/resolv.h> #endif -#else +#elif defined(HAVE_RESOLV_H) #include_next #endif diff --git a/include/compat/sys/socket.h b/include/compat/sys/socket.h index 10eb05f..2f0b197 100644 --- a/include/compat/sys/socket.h +++ b/include/compat/sys/socket.h @@ -10,6 +10,7 @@ #endif #if !defined(SOCK_NONBLOCK) || !defined(SOCK_CLOEXEC) +#define NEED_SOCKET_FLAGS #define SOCK_CLOEXEC 0x8000 /* set FD_CLOEXEC */ #define SOCK_NONBLOCK 0x4000 /* set O_NONBLOCK */ int bsd_socketpair(int domain, int type, int protocol, int socket_vector[2]); diff --git a/include/openssl/asn1.h b/include/openssl/asn1.h index 76c294a..e569e87 100644 --- a/include/openssl/asn1.h +++ b/include/openssl/asn1.h @@ -1,4 +1,4 @@ -/* $OpenBSD: asn1.h,v 1.54 2020/12/08 15:06:42 tb Exp $ */ +/* $OpenBSD: asn1.h,v 1.62 2022/01/14 08:53:53 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -162,52 +162,6 @@ DECLARE_STACK_OF(X509_ALGOR) #define DECLARE_ASN1_SET_OF(type) /* filled in by mkstack.pl */ #define IMPLEMENT_ASN1_SET_OF(type) /* nothing, no longer needed */ -/* We MUST make sure that, except for constness, asn1_ctx_st and - asn1_const_ctx are exactly the same. Fortunately, as soon as - the old ASN1 parsing macros are gone, we can throw this away - as well... */ -typedef struct asn1_ctx_st { - unsigned char *p;/* work char pointer */ - int eos; /* end of sequence read for indefinite encoding */ - int error; /* error code to use when returning an error */ - int inf; /* constructed if 0x20, indefinite is 0x21 */ - int tag; /* tag from last 'get object' */ - int xclass; /* class from last 'get object' */ - long slen; /* length of last 'get object' */ - unsigned char *max; /* largest value of p allowed */ - unsigned char *q;/* temporary variable */ - unsigned char **pp;/* variable */ - int line; /* used in error processing */ -} ASN1_CTX; - -typedef struct asn1_const_ctx_st { - const unsigned char *p;/* work char pointer */ - int eos; /* end of sequence read for indefinite encoding */ - int error; /* error code to use when returning an error */ - int inf; /* constructed if 0x20, indefinite is 0x21 */ - int tag; /* tag from last 'get object' */ - int xclass; /* class from last 'get object' */ - long slen; /* length of last 'get object' */ - const unsigned char *max; /* largest value of p allowed */ - const unsigned char *q;/* temporary variable */ - const unsigned char **pp;/* variable */ - int line; /* used in error processing */ -} ASN1_const_CTX; - -/* These are used internally in the ASN1_OBJECT to keep track of - * whether the names and data need to be free()ed */ -#define ASN1_OBJECT_FLAG_DYNAMIC 0x01 /* internal use */ -#define ASN1_OBJECT_FLAG_CRITICAL 0x02 /* critical x509v3 object id */ -#define ASN1_OBJECT_FLAG_DYNAMIC_STRINGS 0x04 /* internal use */ -#define ASN1_OBJECT_FLAG_DYNAMIC_DATA 0x08 /* internal use */ -typedef struct asn1_object_st { - const char *sn, *ln; - int nid; - int length; - const unsigned char *data; /* data remains const after init */ - int flags; /* Should we free this one */ -} ASN1_OBJECT; - #define ASN1_STRING_FLAG_BITS_LEFT 0x08 /* Set if 0x07 has bits left value */ /* This indicates that the ASN1_STRING is not a real value but just a place * holder for the location where indefinite length constructed data should @@ -530,11 +484,6 @@ ASN1_SEQUENCE_ANY *d2i_ASN1_SET_ANY(ASN1_SEQUENCE_ANY **a, const unsigned char * int i2d_ASN1_SET_ANY(const ASN1_SEQUENCE_ANY *a, unsigned char **out); extern const ASN1_ITEM ASN1_SET_ANY_it; -typedef struct NETSCAPE_X509_st { - ASN1_OCTET_STRING *header; - X509 *cert; -} NETSCAPE_X509; - /* This is used to contain a list of bit names */ typedef struct BIT_STRING_BITNAME_st { int bitnum; @@ -645,9 +594,6 @@ int ASN1_BIT_STRING_num_asc(const char *name, BIT_STRING_BITNAME *tbl); int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, const char *name, int value, BIT_STRING_BITNAME *tbl); -int i2d_ASN1_BOOLEAN(int a, unsigned char **pp); -int d2i_ASN1_BOOLEAN(int *a, const unsigned char **pp, long length); - ASN1_INTEGER *ASN1_INTEGER_new(void); void ASN1_INTEGER_free(ASN1_INTEGER *a); ASN1_INTEGER *d2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **in, long len); @@ -773,6 +719,9 @@ ASN1_TIME *d2i_ASN1_TIME(ASN1_TIME **a, const unsigned char **in, long len); int i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **out); extern const ASN1_ITEM ASN1_TIME_it; +int ASN1_TIME_diff(int *pday, int *psec, const ASN1_TIME *from, + const ASN1_TIME *to); + extern const ASN1_ITEM ASN1_OCTET_STRING_NDEF_it; ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t); @@ -816,8 +765,6 @@ int ASN1_PRINTABLE_type(const unsigned char *s, int max); /* SPECIALS */ int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag, int *pclass, long omax); -int ASN1_check_infinite_end(unsigned char **p, long len); -int ASN1_const_check_infinite_end(const unsigned char **p, long len); void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, int xclass); int ASN1_put_eoc(unsigned char **pp); @@ -895,14 +842,6 @@ int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent, int unsigned long ASN1_tag2bit(int tag); const char *ASN1_tag2str(int tag); -/* Used to load and write netscape format cert */ - -NETSCAPE_X509 *NETSCAPE_X509_new(void); -void NETSCAPE_X509_free(NETSCAPE_X509 *a); -NETSCAPE_X509 *d2i_NETSCAPE_X509(NETSCAPE_X509 **a, const unsigned char **in, long len); -int i2d_NETSCAPE_X509(NETSCAPE_X509 *a, unsigned char **out); -extern const ASN1_ITEM NETSCAPE_X509_it; - int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s); int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, const unsigned char *data, int len); diff --git a/include/openssl/asn1t.h b/include/openssl/asn1t.h index d6168b6..892c8b7 100644 --- a/include/openssl/asn1t.h +++ b/include/openssl/asn1t.h @@ -1,4 +1,4 @@ -/* $OpenBSD: asn1t.h,v 1.15 2019/08/20 13:10:09 inoguchi Exp $ */ +/* $OpenBSD: asn1t.h,v 1.19 2022/01/14 08:43:06 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ @@ -10,7 +10,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * 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 @@ -92,7 +92,7 @@ extern "C" { /* Macros to aid ASN1 template writing */ #define ASN1_ITEM_TEMPLATE(tname) \ - static const ASN1_TEMPLATE tname##_item_tt + static const ASN1_TEMPLATE tname##_item_tt #define ASN1_ITEM_TEMPLATE_END(tname) \ ;\ @@ -120,29 +120,30 @@ extern "C" { /* This is a ASN1 type which just embeds a template */ - -/* This pair helps declare a SEQUENCE. We can do: + +/* + * This pair helps declare a SEQUENCE. We can do: * - * ASN1_SEQUENCE(stname) = { - * ... SEQUENCE components ... - * } ASN1_SEQUENCE_END(stname) + * ASN1_SEQUENCE(stname) = { + * ... SEQUENCE components ... + * } ASN1_SEQUENCE_END(stname) * - * This will produce an ASN1_ITEM called stname_it + * This will produce an ASN1_ITEM called stname_it * for a structure called stname. * - * If you want the same structure but a different + * If you want the same structure but a different * name then use: * - * ASN1_SEQUENCE(itname) = { - * ... SEQUENCE components ... - * } ASN1_SEQUENCE_END_name(stname, itname) + * ASN1_SEQUENCE(itname) = { + * ... SEQUENCE components ... + * } ASN1_SEQUENCE_END_name(stname, itname) * * This will create an item called itname_it using * a structure called stname. */ #define ASN1_SEQUENCE(tname) \ - static const ASN1_TEMPLATE tname##_seq_tt[] + static const ASN1_TEMPLATE tname##_seq_tt[] #define ASN1_SEQUENCE_END(stname) ASN1_SEQUENCE_END_name(stname, stname) @@ -263,13 +264,14 @@ extern "C" { ASN1_ITEM_end(tname) -/* This pair helps declare a CHOICE type. We can do: +/* + * This pair helps declare a CHOICE type. We can do: * - * ASN1_CHOICE(chname) = { - * ... CHOICE options ... - * ASN1_CHOICE_END(chname) + * ASN1_CHOICE(chname) = { + * ... CHOICE options ... + * ASN1_CHOICE_END(chname) * - * This will produce an ASN1_ITEM called chname_it + * This will produce an ASN1_ITEM called chname_it * for a structure called chname. The structure * definition must look like this: * typedef struct { @@ -279,14 +281,14 @@ extern "C" { * ASN1_SOMEOTHER *opt2; * } value; * } chname; - * + * * the name of the selector must be 'type'. - * to use an alternative selector name use the + * to use an alternative selector name use the * ASN1_CHOICE_END_selector() version. */ #define ASN1_CHOICE(tname) \ - static const ASN1_TEMPLATE tname##_ch_tt[] + static const ASN1_TEMPLATE tname##_ch_tt[] #define ASN1_CHOICE_cb(tname, cb) \ static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \ @@ -437,7 +439,7 @@ extern "C" { /* Macros for the ASN1_ADB structure */ #define ASN1_ADB(name) \ - static const ASN1_ADB_TABLE name##_adbtbl[] + static const ASN1_ADB_TABLE name##_adbtbl[] #define ASN1_ADB_END(name, flags, field, app_table, def, none) \ @@ -456,7 +458,7 @@ extern "C" { #define ADB_ENTRY(val, template) {val, template} #define ASN1_ADB_TEMPLATE(name) \ - static const ASN1_TEMPLATE name##_tt + static const ASN1_TEMPLATE name##_tt #endif /* !LIBRESSL_INTERNAL */ @@ -467,13 +469,11 @@ extern "C" { */ struct ASN1_TEMPLATE_st { -unsigned long flags; /* Various flags */ -long tag; /* tag, not used if no tagging */ -unsigned long offset; /* Offset of this field in structure */ -#ifndef NO_ASN1_FIELD_NAMES -const char *field_name; /* Field name */ -#endif -ASN1_ITEM_EXP *item; /* Relevant ASN1_ITEM or ASN1_ADB */ + unsigned long flags; /* Various flags */ + long tag; /* tag, not used if no tagging */ + unsigned long offset; /* Offset of this field in structure */ + const char *field_name; /* Field name */ + ASN1_ITEM_EXP *item; /* Relevant ASN1_ITEM or ASN1_ADB */ }; /* Macro to extract ASN1_ITEM and ASN1_ADB pointer from ASN1_TEMPLATE */ @@ -487,7 +487,6 @@ typedef struct ASN1_ADB_st ASN1_ADB; struct ASN1_ADB_st { unsigned long flags; /* Various flags */ unsigned long offset; /* Offset of selector field */ - STACK_OF(ASN1_ADB_TABLE) **app_items; /* Application defined items */ const ASN1_ADB_TABLE *tbl; /* Table of possible types */ long tblcount; /* Number of entries in tbl */ const ASN1_TEMPLATE *default_tt; /* Type to use if no match */ @@ -540,24 +539,25 @@ struct ASN1_ADB_TABLE_st { /* context specific EXPLICIT */ #define ASN1_TFLG_EXPLICIT ASN1_TFLG_EXPTAG|ASN1_TFLG_CONTEXT -/* If tagging is in force these determine the - * type of tag to use. Otherwise the tag is - * determined by the underlying type. These - * values reflect the actual octet format. +/* + * If tagging is in force these determine the type of tag to use. Otherwiser + * the tag is determined by the underlying type. These values reflect the + * actual octet format. */ -/* Universal tag */ +/* Universal tag */ #define ASN1_TFLG_UNIVERSAL (0x0<<6) -/* Application tag */ +/* Application tag */ #define ASN1_TFLG_APPLICATION (0x1<<6) -/* Context specific tag */ +/* Context specific tag */ #define ASN1_TFLG_CONTEXT (0x2<<6) -/* Private tag */ +/* Private tag */ #define ASN1_TFLG_PRIVATE (0x3<<6) #define ASN1_TFLG_TAG_CLASS (0x3<<6) -/* These are for ANY DEFINED BY type. In this case +/* + * These are for ANY DEFINED BY type. In this case * the 'item' field points to an ASN1_ADB structure * which contains a table of values to decode the * relevant type @@ -569,7 +569,8 @@ struct ASN1_ADB_TABLE_st { #define ASN1_TFLG_ADB_INT (0x1<<9) -/* This flag means a parent structure is passed +/* + * This flag means a parent structure is passed * instead of the field: this is useful is a * SEQUENCE is being combined with a CHOICE for * example. Since this means the structure and @@ -579,7 +580,8 @@ struct ASN1_ADB_TABLE_st { #define ASN1_TFLG_COMBINE (0x1<<10) -/* This flag when present in a SEQUENCE OF, SET OF +/* + * This flag when present in a SEQUENCE OF, SET OF * or EXPLICIT causes indefinite length constructed * encoding to be used if required. */ @@ -589,15 +591,13 @@ struct ASN1_ADB_TABLE_st { /* This is the actual ASN1 item itself */ struct ASN1_ITEM_st { -char itype; /* The item type, primitive, SEQUENCE, CHOICE or extern */ -long utype; /* underlying type */ -const ASN1_TEMPLATE *templates; /* If SEQUENCE or CHOICE this contains the contents */ -long tcount; /* Number of templates if SEQUENCE or CHOICE */ -const void *funcs; /* functions that handle this type */ -long size; /* Structure size (usually)*/ -#ifndef NO_ASN1_FIELD_NAMES -const char *sname; /* Structure name */ -#endif + char itype; /* The item type, primitive, SEQUENCE, CHOICE or extern */ + long utype; /* underlying type */ + const ASN1_TEMPLATE *templates; /* If SEQUENCE or CHOICE this contains the contents */ + long tcount; /* Number of templates if SEQUENCE or CHOICE */ + const void *funcs; /* functions that handle this type */ + long size; /* Structure size (usually)*/ + const char *sname; /* Structure name */ }; /* These are values for the itype field and @@ -606,7 +606,7 @@ const char *sname; /* Structure name */ * For PRIMITIVE types the underlying type * determines the behaviour if items is NULL. * - * Otherwise templates must contain a single + * Otherwise templates must contain a single * template and the type is treated in the * same way as the type specified in the template. * @@ -620,7 +620,7 @@ const char *sname; /* Structure name */ * selector. * * The 'funcs' field is used for application - * specific functions. + * specific functions. * * The EXTERN type uses a new style d2i/i2d. * The new style should be used where possible @@ -657,7 +657,7 @@ const char *sname; /* Structure name */ * like CHOICE */ -struct ASN1_TLC_st{ +struct ASN1_TLC_st { char valid; /* Values below are valid */ int ret; /* return value */ long plen; /* length */ @@ -680,8 +680,8 @@ typedef int ASN1_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it); typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it); -typedef int ASN1_ex_print_func(BIO *out, ASN1_VALUE **pval, - int indent, const char *fname, +typedef int ASN1_ex_print_func(BIO *out, ASN1_VALUE **pval, + int indent, const char *fname, const ASN1_PCTX *pctx); typedef int ASN1_primitive_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it); @@ -719,7 +719,7 @@ typedef struct ASN1_PRIMITIVE_FUNCS_st { * used. This is most useful where the supplied routines * *almost* do the right thing but need some extra help * at a few points. If the callback returns zero then - * it is assumed a fatal error has occurred and the + * it is assumed a fatal error has occurred and the * main operation should be abandoned. * * If major changes in the default behaviour are required @@ -853,13 +853,13 @@ typedef struct ASN1_STREAM_ARG_st { int i2d_##fname(stname *a, unsigned char **out) \ { \ return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\ - } + } #define IMPLEMENT_ASN1_NDEF_FUNCTION(stname) \ int i2d_##stname##_NDEF(stname *a, unsigned char **out) \ { \ return ASN1_item_ndef_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(stname));\ - } + } /* This includes evil casts to remove const: they will go away when full * ASN1 constification is done. @@ -872,7 +872,7 @@ typedef struct ASN1_STREAM_ARG_st { int i2d_##fname(const stname *a, unsigned char **out) \ { \ return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\ - } + } #define IMPLEMENT_ASN1_DUP_FUNCTION(stname) \ stname * stname##_dup(stname *x) \ @@ -889,7 +889,7 @@ typedef struct ASN1_STREAM_ARG_st { { \ return ASN1_item_print(out, (ASN1_VALUE *)x, indent, \ ASN1_ITEM_rptr(itname), pctx); \ - } + } #define IMPLEMENT_ASN1_FUNCTIONS_const(name) \ IMPLEMENT_ASN1_FUNCTIONS_const_fname(name, name, name) @@ -929,22 +929,6 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLATE *tt); void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it); -int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it); - -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); - -ASN1_VALUE ** asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); - -const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, int nullerr); - -int 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); - #ifdef __cplusplus } #endif diff --git a/include/openssl/bio.h b/include/openssl/bio.h index 9fbf3bc..d4bf8cb 100644 --- a/include/openssl/bio.h +++ b/include/openssl/bio.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bio.h,v 1.45 2018/06/02 04:41:12 tb Exp $ */ +/* $OpenBSD: bio.h,v 1.54 2022/01/14 08:40:57 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -205,8 +205,6 @@ extern "C" { */ #define BIO_FLAGS_MEM_RDONLY 0x200 -typedef struct bio_st BIO; - void BIO_set_flags(BIO *b, int flags); int BIO_test_flags(const BIO *b, int flags); void BIO_clear_flags(BIO *b, int flags); @@ -252,85 +250,39 @@ void BIO_clear_flags(BIO *b, int flags); #define BIO_CB_GETS 0x05 #define BIO_CB_CTRL 0x06 -/* The callback is called before and after the underling operation, - * The BIO_CB_RETURN flag indicates if it is after the call */ +/* + * The callback is called before and after the underling operation, + * the BIO_CB_RETURN flag indicates if it is after the call. + */ #define BIO_CB_RETURN 0x80 #define BIO_CB_return(a) ((a)|BIO_CB_RETURN)) #define BIO_cb_pre(a) (!((a)&BIO_CB_RETURN)) #define BIO_cb_post(a) ((a)&BIO_CB_RETURN) -long (*BIO_get_callback(const BIO *b))(struct bio_st *, int, const char *, - int, long, long); -void BIO_set_callback(BIO *b, - long (*callback)(struct bio_st *, int, const char *, int, long, long)); +typedef long (*BIO_callback_fn)(BIO *b, int oper, const char *argp, int argi, + long argl, long ret); +typedef long (*BIO_callback_fn_ex)(BIO *b, int oper, const char *argp, + size_t len, int argi, long argl, int ret, size_t *processed); + +BIO_callback_fn BIO_get_callback(const BIO *b); +void BIO_set_callback(BIO *b, BIO_callback_fn callback); + +BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b); +void BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex callback); + char *BIO_get_callback_arg(const BIO *b); void BIO_set_callback_arg(BIO *b, char *arg); -const char * BIO_method_name(const BIO *b); +const char *BIO_method_name(const BIO *b); int BIO_method_type(const BIO *b); typedef void bio_info_cb(struct bio_st *, int, const char *, int, long, long); typedef int BIO_info_cb(BIO *, int, int); -typedef struct bio_method_st { - int type; - const char *name; - int (*bwrite)(BIO *, const char *, int); - int (*bread)(BIO *, char *, int); - int (*bputs)(BIO *, const char *); - int (*bgets)(BIO *, char *, int); - long (*ctrl)(BIO *, int, long, void *); - int (*create)(BIO *); - int (*destroy)(BIO *); - long (*callback_ctrl)(BIO *, int, bio_info_cb *); -} BIO_METHOD; - -struct bio_st { - const BIO_METHOD *method; - /* bio, mode, argp, argi, argl, ret */ - long (*callback)(struct bio_st *, int, const char *, int, long, long); - char *cb_arg; /* first argument for the callback */ - - int init; - int shutdown; - int flags; /* extra storage */ - int retry_reason; - int num; - void *ptr; - struct bio_st *next_bio; /* used by filter BIOs */ - struct bio_st *prev_bio; /* used by filter BIOs */ - int references; - unsigned long num_read; - unsigned long num_write; - - CRYPTO_EX_DATA ex_data; -}; +typedef struct bio_method_st BIO_METHOD; DECLARE_STACK_OF(BIO) -typedef struct bio_f_buffer_ctx_struct { - /* Buffers are setup like this: - * - * <---------------------- size -----------------------> - * +---------------------------------------------------+ - * | consumed | remaining | free space | - * +---------------------------------------------------+ - * <-- off --><------- len -------> - */ - - /* BIO *bio; */ /* this is now in the BIO struct */ - int ibuf_size; /* how big is the input buffer */ - int obuf_size; /* how big is the output buffer */ - - char *ibuf; /* the char array */ - int ibuf_len; /* how many bytes are in it */ - int ibuf_off; /* write/read offset */ - - char *obuf; /* the char array */ - int obuf_len; /* how many bytes are in it */ - int obuf_off; /* write/read offset */ -} BIO_F_BUFFER_CTX; - /* Prefix and suffix callback in ASN1 BIO */ typedef int asn1_ps_func(BIO *b, unsigned char **pbuf, int *plen, void *parg); @@ -600,14 +552,14 @@ int BIO_get_new_index(void); const BIO_METHOD *BIO_s_file(void); BIO *BIO_new_file(const char *filename, const char *mode); BIO *BIO_new_fp(FILE *stream, int close_flag); -# define BIO_s_file_internal BIO_s_file BIO *BIO_new(const BIO_METHOD *type); int BIO_set(BIO *a, const BIO_METHOD *type); int BIO_free(BIO *a); int BIO_up_ref(BIO *bio); -void *BIO_get_data(BIO *a); -void BIO_set_data(BIO *a, void *ptr); -void BIO_set_init(BIO *a, int init); +void *BIO_get_data(BIO *a); +void BIO_set_data(BIO *a, void *ptr); +int BIO_get_init(BIO *a); +void BIO_set_init(BIO *a, int init); int BIO_get_shutdown(BIO *a); void BIO_set_shutdown(BIO *a, int shut); void BIO_vfree(BIO *a); @@ -620,8 +572,7 @@ int BIO_write(BIO *b, const void *data, int len) int BIO_puts(BIO *bp, const char *buf); int BIO_indent(BIO *b, int indent, int max); long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg); -long BIO_callback_ctrl(BIO *b, int cmd, - void (*fp)(struct bio_st *, int, const char *, int, long, long)); +long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp); char * BIO_ptr_ctrl(BIO *bp, int cmd, long larg); long BIO_int_ctrl(BIO *bp, int cmd, long larg, int iarg); BIO * BIO_push(BIO *b, BIO *append); @@ -629,8 +580,10 @@ BIO * BIO_pop(BIO *b); void BIO_free_all(BIO *a); BIO * BIO_find_type(BIO *b, int bio_type); BIO * BIO_next(BIO *b); +void BIO_set_next(BIO *b, BIO *next); BIO * BIO_get_retry_BIO(BIO *bio, int *reason); int BIO_get_retry_reason(BIO *bio); +void BIO_set_retry_reason(BIO *bio, int reason); BIO * BIO_dup_chain(BIO *in); int BIO_nread0(BIO *bio, char **buf); @@ -805,6 +758,7 @@ void ERR_load_BIO_strings(void); #define BIO_R_INVALID_PORT_NUMBER 129 #define BIO_R_IN_USE 123 #define BIO_R_KEEPALIVE 109 +#define BIO_R_LENGTH_TOO_LONG 130 #define BIO_R_NBIO_CONNECT_ERROR 110 #define BIO_R_NO_ACCEPT_PORT_SPECIFIED 111 #define BIO_R_NO_HOSTNAME_SPECIFIED 112 diff --git a/include/openssl/blowfish.h b/include/openssl/blowfish.h index 4d2db80..260545e 100644 --- a/include/openssl/blowfish.h +++ b/include/openssl/blowfish.h @@ -1,4 +1,4 @@ -/* $OpenBSD: blowfish.h,v 1.14 2014/07/10 09:01:04 miod Exp $ */ +/* $OpenBSD: blowfish.h,v 1.15 2021/11/30 18:31:36 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -84,11 +84,10 @@ extern "C" { #define BF_ROUNDS 16 #define BF_BLOCK 8 -typedef struct bf_key_st - { +typedef struct bf_key_st { BF_LONG P[BF_ROUNDS+2]; BF_LONG S[4*256]; - } BF_KEY; +} BF_KEY; void BF_set_key(BF_KEY *key, int len, const unsigned char *data); diff --git a/include/openssl/bn.h b/include/openssl/bn.h index 1675111..abf8cfc 100644 --- a/include/openssl/bn.h +++ b/include/openssl/bn.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bn.h,v 1.43 2021/09/10 14:33:44 tb Exp $ */ +/* $OpenBSD: bn.h,v 1.52 2022/01/14 08:01:47 tb Exp $ */ /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -226,10 +226,11 @@ extern "C" { #endif #ifndef OPENSSL_NO_DEPRECATED -#define BN_FLG_FREE 0x8000 /* used for debuging */ +#define BN_FLG_FREE 0x8000 /* used for debugging */ #endif -#define BN_set_flags(b,n) ((b)->flags|=(n)) -#define BN_get_flags(b,n) ((b)->flags&(n)) +void BN_set_flags(BIGNUM *b, int n); +int BN_get_flags(const BIGNUM *b, int n); +void BN_with_flags(BIGNUM *dest, const BIGNUM *src, int flags); /* Values for |top| in BN_rand() */ #define BN_RAND_TOP_ANY -1 @@ -240,79 +241,21 @@ extern "C" { #define BN_RAND_BOTTOM_ANY 0 #define BN_RAND_BOTTOM_ODD 1 -/* get a clone of a BIGNUM with changed flags, for *temporary* use only - * (the two BIGNUMs cannot not be used in parallel!) */ -#define BN_with_flags(dest,b,n) ((dest)->d=(b)->d, \ - (dest)->top=(b)->top, \ - (dest)->dmax=(b)->dmax, \ - (dest)->neg=(b)->neg, \ - (dest)->flags=(((dest)->flags & BN_FLG_MALLOCED) \ - | ((b)->flags & ~BN_FLG_MALLOCED) \ - | BN_FLG_STATIC_DATA \ - | (n))) - -struct bignum_st { - BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit chunks. */ - int top; /* Index of last used d +1. */ - /* The next are internal book keeping for bn_expand. */ - int dmax; /* Size of the d array. */ - int neg; /* one if the number is negative */ - int flags; -}; - -/* Used for montgomery multiplication */ -struct bn_mont_ctx_st { - int ri; /* number of bits in R */ - BIGNUM RR; /* used to convert to montgomery form */ - BIGNUM N; /* The modulus */ - BIGNUM Ni; /* R*(1/R mod N) - N*Ni = 1 - * (Ni is only stored for bignum algorithm) */ - BN_ULONG n0[2];/* least significant word(s) of Ni; - (type changed with 0.9.9, was "BN_ULONG n0;" before) */ - int flags; -}; - -/* Used for reciprocal division/mod functions - * It cannot be shared between threads - */ -struct bn_recp_ctx_st { - BIGNUM N; /* the divisor */ - BIGNUM Nr; /* the reciprocal */ - int num_bits; - int shift; - int flags; -}; - -/* Used for slow "generation" functions. */ -struct bn_gencb_st { - unsigned int ver; /* To handle binary (in)compatibility */ - void *arg; /* callback-specific data */ - union { - /* if(ver==1) - handles old style callbacks */ - void (*cb_1)(int, int, void *); - /* if(ver==2) - new callback style */ - int (*cb_2)(int, int, BN_GENCB *); - } cb; -}; - BN_GENCB *BN_GENCB_new(void); void BN_GENCB_free(BN_GENCB *cb); -void *BN_GENCB_get_arg(BN_GENCB *cb); /* Wrapper function to make using BN_GENCB easier, */ int BN_GENCB_call(BN_GENCB *cb, int a, int b); -/* Macro to populate a BN_GENCB structure with an "old"-style callback */ -#define BN_GENCB_set_old(gencb, callback, cb_arg) { \ - BN_GENCB *tmp_gencb = (gencb); \ - tmp_gencb->ver = 1; \ - tmp_gencb->arg = (cb_arg); \ - tmp_gencb->cb.cb_1 = (callback); } -/* Macro to populate a BN_GENCB structure with a "new"-style callback */ -#define BN_GENCB_set(gencb, callback, cb_arg) { \ - BN_GENCB *tmp_gencb = (gencb); \ - tmp_gencb->ver = 2; \ - tmp_gencb->arg = (cb_arg); \ - tmp_gencb->cb.cb_2 = (callback); } + +/* Populate a BN_GENCB structure with an "old"-style callback */ +void BN_GENCB_set_old(BN_GENCB *gencb, void (*callback)(int, int, void *), + void *cb_arg); + +/* Populate a BN_GENCB structure with a "new"-style callback */ +void BN_GENCB_set(BN_GENCB *gencb, int (*callback)(int, int, BN_GENCB *), + void *cb_arg); + +void *BN_GENCB_get_arg(BN_GENCB *cb); #define BN_prime_checks 0 /* default: select number of iterations based on the size of the number */ @@ -389,24 +332,18 @@ int BN_GENCB_call(BN_GENCB *cb, int a, int b); (b) >= 308 ? 8 : \ (b) >= 55 ? 27 : \ /* b >= 6 */ 34) - + #define BN_num_bytes(a) ((BN_num_bits(a)+7)/8) -/* Note that BN_abs_is_word didn't work reliably for w == 0 until 0.9.8 */ -#define BN_abs_is_word(a,w) ((((a)->top == 1) && ((a)->d[0] == (BN_ULONG)(w))) || \ - (((w) == 0) && ((a)->top == 0))) -#define BN_is_zero(a) ((a)->top == 0) -#define BN_is_one(a) (BN_abs_is_word((a),1) && !(a)->neg) -#define BN_is_word(a,w) (BN_abs_is_word((a),(w)) && (!(w) || !(a)->neg)) -#define BN_is_odd(a) (((a)->top > 0) && ((a)->d[0] & 1)) +int BN_abs_is_word(const BIGNUM *a, const BN_ULONG w); +int BN_is_zero(const BIGNUM *a); +int BN_is_one(const BIGNUM *a); +int BN_is_word(const BIGNUM *a, const BN_ULONG w); +int BN_is_odd(const BIGNUM *a); -#define BN_one(a) (BN_set_word((a),1)) -#define BN_zero_ex(a) \ - do { \ - BIGNUM *_tmp_bn = (a); \ - _tmp_bn->top = 0; \ - _tmp_bn->neg = 0; \ - } while(0) +#define BN_one(a) BN_set_word((a), 1) + +void BN_zero_ex(BIGNUM *a); #ifdef OPENSSL_NO_DEPRECATED #define BN_zero(a) BN_zero_ex(a) @@ -453,11 +390,8 @@ int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx); * \param n 0 if the BIGNUM b should be positive and a value != 0 otherwise */ void BN_set_negative(BIGNUM *b, int n); -/** BN_is_negative returns 1 if the BIGNUM is negative - * \param a pointer to the BIGNUM object - * \return 1 if a < 0 and 0 otherwise - */ -#define BN_is_negative(a) ((a)->neg != 0) + +int BN_is_negative(const BIGNUM *b); #ifndef LIBRESSL_INTERNAL int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, @@ -572,8 +506,8 @@ BN_MONT_CTX *BN_MONT_CTX_new(void ); void BN_MONT_CTX_init(BN_MONT_CTX *ctx); int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_MONT_CTX *mont, BN_CTX *ctx); -#define BN_to_montgomery(r,a,mont,ctx) BN_mod_mul_montgomery(\ - (r),(a),&((mont)->RR),(mont),(ctx)) +int BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx); int BN_from_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, BN_CTX *ctx); void BN_MONT_CTX_free(BN_MONT_CTX *mont); diff --git a/include/openssl/comp.h b/include/openssl/comp.h index fe7397f..7c99ead 100644 --- a/include/openssl/comp.h +++ b/include/openssl/comp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: comp.h,v 1.8 2014/11/03 16:58:28 tedu Exp $ */ +/* $OpenBSD: comp.h,v 1.9 2022/01/14 08:21:12 tb Exp $ */ #ifndef HEADER_COMP_H #define HEADER_COMP_H @@ -9,33 +9,6 @@ extern "C" { #endif -typedef struct comp_ctx_st COMP_CTX; - -typedef struct comp_method_st { - int type; /* NID for compression library */ - const char *name; /* A text string to identify the library */ - int (*init)(COMP_CTX *ctx); - void (*finish)(COMP_CTX *ctx); - int (*compress)(COMP_CTX *ctx, unsigned char *out, unsigned int olen, - unsigned char *in, unsigned int ilen); - int (*expand)(COMP_CTX *ctx, unsigned char *out, unsigned int olen, - unsigned char *in, unsigned int ilen); - /* The following two do NOTHING, but are kept for backward compatibility */ - long (*ctrl)(void); - long (*callback_ctrl)(void); -} COMP_METHOD; - -struct comp_ctx_st { - COMP_METHOD *meth; - unsigned long compress_in; - unsigned long compress_out; - unsigned long expand_in; - unsigned long expand_out; - - CRYPTO_EX_DATA ex_data; -}; - - COMP_CTX *COMP_CTX_new(COMP_METHOD *meth); void COMP_CTX_free(COMP_CTX *ctx); int COMP_compress_block(COMP_CTX *ctx, unsigned char *out, int olen, diff --git a/include/openssl/crypto.h b/include/openssl/crypto.h index 7de8abb..5524fee 100644 --- a/include/openssl/crypto.h +++ b/include/openssl/crypto.h @@ -1,4 +1,4 @@ -/* $OpenBSD: crypto.h,v 1.50 2019/01/19 01:07:00 tb Exp $ */ +/* $OpenBSD: crypto.h,v 1.54 2022/01/14 08:23:25 tb Exp $ */ /* ==================================================================== * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. * @@ -143,15 +143,6 @@ extern "C" { #define SSLEAY_PLATFORM 4 #define SSLEAY_DIR 5 -/* A generic structure to pass assorted data in a expandable way */ -typedef struct openssl_item_st { - int code; - void *value; /* Not used for flag attributes */ - size_t value_size; /* Max size of value for output, length for input */ - size_t *value_length; /* Returned length of value for output */ -} OPENSSL_ITEM; - - /* When changing the CRYPTO_LOCK_* list, be sure to maintain the text lock * names in cryptlib.c */ @@ -205,15 +196,15 @@ typedef struct openssl_item_st { #ifndef CRYPTO_w_lock #define CRYPTO_w_lock(type) \ - CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,__FILE__,__LINE__) + CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,NULL,0) #define CRYPTO_w_unlock(type) \ - CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,__FILE__,__LINE__) + CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,NULL,0) #define CRYPTO_r_lock(type) \ - CRYPTO_lock(CRYPTO_LOCK|CRYPTO_READ,type,__FILE__,__LINE__) + CRYPTO_lock(CRYPTO_LOCK|CRYPTO_READ,type,NULL,0) #define CRYPTO_r_unlock(type) \ - CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_READ,type,__FILE__,__LINE__) + CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_READ,type,NULL,0) #define CRYPTO_add(addr,amount,type) \ - CRYPTO_add_lock(addr,amount,type,__FILE__,__LINE__) + CRYPTO_add_lock(addr,amount,type,NULL,0) #endif /* Some applications as well as some parts of OpenSSL need to allocate @@ -309,19 +300,19 @@ int CRYPTO_is_mem_check_on(void); #define MemCheck_start() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON) #define MemCheck_stop() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF) -#define OPENSSL_malloc(num) CRYPTO_malloc((int)num,__FILE__,__LINE__) -#define OPENSSL_strdup(str) CRYPTO_strdup((str),__FILE__,__LINE__) +#define OPENSSL_malloc(num) CRYPTO_malloc((int)num,NULL,0) +#define OPENSSL_strdup(str) CRYPTO_strdup((str),NULL,0) #define OPENSSL_realloc(addr,num) \ - CRYPTO_realloc((char *)addr,(int)num,__FILE__,__LINE__) + CRYPTO_realloc((char *)addr,(int)num,NULL,0) #define OPENSSL_realloc_clean(addr,old_num,num) \ - CRYPTO_realloc_clean(addr,old_num,num,__FILE__,__LINE__) + CRYPTO_realloc_clean(addr,old_num,num,NULL,0) #define OPENSSL_remalloc(addr,num) \ - CRYPTO_remalloc((char **)addr,(int)num,__FILE__,__LINE__) + CRYPTO_remalloc((char **)addr,(int)num,NULL,0) #define OPENSSL_freeFunc CRYPTO_free #define OPENSSL_free(addr) CRYPTO_free(addr) #define OPENSSL_malloc_locked(num) \ - CRYPTO_malloc_locked((int)num,__FILE__,__LINE__) + CRYPTO_malloc_locked((int)num,NULL,0) #define OPENSSL_free_locked(addr) CRYPTO_free_locked(addr) #endif @@ -457,7 +448,7 @@ void CRYPTO_set_mem_debug_options(long bits); long CRYPTO_get_mem_debug_options(void); #define CRYPTO_push_info(info) \ - CRYPTO_push_info_(info, __FILE__, __LINE__); + CRYPTO_push_info_(info, NULL, 0); int CRYPTO_push_info_(const char *info, const char *file, int line); int CRYPTO_pop_info(void); int CRYPTO_remove_all_info(void); @@ -505,6 +496,9 @@ uint64_t OPENSSL_cpu_caps(void); int OPENSSL_isservice(void); #ifndef LIBRESSL_INTERNAL +int FIPS_mode(void); +int FIPS_mode_set(int r); + void OPENSSL_init(void); /* CRYPTO_memcmp returns zero iff the |len| bytes at |a| and |b| are equal. It diff --git a/include/openssl/ct.h b/include/openssl/ct.h new file mode 100644 index 0000000..2b54903 --- /dev/null +++ b/include/openssl/ct.h @@ -0,0 +1,514 @@ +/* $OpenBSD: ct.h,v 1.6 2021/12/18 16:50:40 tb Exp $ */ +/* + * Public API for Certificate Transparency (CT). + * Written by Rob Percival (robpercival@google.com) for the OpenSSL project. + */ +/* ==================================================================== + * Copyright (c) 2016 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 + * licensing@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. + * ==================================================================== + */ + +#ifndef HEADER_CT_H +#define HEADER_CT_H + +#include + +#ifndef OPENSSL_NO_CT +#include +#include +#include +#include +#ifdef __cplusplus +extern "C" { +#endif + +/* Minimum RSA key size, from RFC6962 */ +#define SCT_MIN_RSA_BITS 2048 + +/* All hashes are SHA256 in v1 of Certificate Transparency */ +#define CT_V1_HASHLEN SHA256_DIGEST_LENGTH + +typedef enum { + CT_LOG_ENTRY_TYPE_NOT_SET = -1, + CT_LOG_ENTRY_TYPE_X509 = 0, + CT_LOG_ENTRY_TYPE_PRECERT = 1 +} ct_log_entry_type_t; + +typedef enum { + SCT_VERSION_NOT_SET = -1, + SCT_VERSION_V1 = 0 +} sct_version_t; + +typedef enum { + SCT_SOURCE_UNKNOWN, + SCT_SOURCE_TLS_EXTENSION, + SCT_SOURCE_X509V3_EXTENSION, + SCT_SOURCE_OCSP_STAPLED_RESPONSE +} sct_source_t; + +typedef enum { + SCT_VALIDATION_STATUS_NOT_SET, + SCT_VALIDATION_STATUS_UNKNOWN_LOG, + SCT_VALIDATION_STATUS_VALID, + SCT_VALIDATION_STATUS_INVALID, + SCT_VALIDATION_STATUS_UNVERIFIED, + SCT_VALIDATION_STATUS_UNKNOWN_VERSION +} sct_validation_status_t; + +DECLARE_STACK_OF(SCT) +DECLARE_STACK_OF(CTLOG) + +/****************************************** + * CT policy evaluation context functions * + ******************************************/ + +/* + * Creates a new, empty policy evaluation context. + * The caller is responsible for calling CT_POLICY_EVAL_CTX_free when finished + * with the CT_POLICY_EVAL_CTX. + */ +CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void); + +/* Deletes a policy evaluation context and anything it owns. */ +void CT_POLICY_EVAL_CTX_free(CT_POLICY_EVAL_CTX *ctx); + +/* Gets the peer certificate that the SCTs are for */ +X509* CT_POLICY_EVAL_CTX_get0_cert(const CT_POLICY_EVAL_CTX *ctx); + +/* + * Sets the certificate associated with the received SCTs. + * Increments the reference count of cert. + * Returns 1 on success, 0 otherwise. + */ +int CT_POLICY_EVAL_CTX_set1_cert(CT_POLICY_EVAL_CTX *ctx, X509 *cert); + +/* Gets the issuer of the aforementioned certificate */ +X509* CT_POLICY_EVAL_CTX_get0_issuer(const CT_POLICY_EVAL_CTX *ctx); + +/* + * Sets the issuer of the certificate associated with the received SCTs. + * Increments the reference count of issuer. + * Returns 1 on success, 0 otherwise. + */ +int CT_POLICY_EVAL_CTX_set1_issuer(CT_POLICY_EVAL_CTX *ctx, X509 *issuer); + +/* Gets the CT logs that are trusted sources of SCTs */ +const CTLOG_STORE *CT_POLICY_EVAL_CTX_get0_log_store(const CT_POLICY_EVAL_CTX *ctx); + +/* Sets the log store that is in use. It must outlive the CT_POLICY_EVAL_CTX. */ +void CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(CT_POLICY_EVAL_CTX *ctx, + CTLOG_STORE *log_store); + +/* + * Gets the time, in milliseconds since the Unix epoch, that will be used as the + * current time when checking whether an SCT was issued in the future. + * Such SCTs will fail validation, as required by RFC6962. + */ +uint64_t CT_POLICY_EVAL_CTX_get_time(const CT_POLICY_EVAL_CTX *ctx); + +/* + * Sets the time to evaluate SCTs against, in milliseconds since the Unix epoch. + * If an SCT's timestamp is after this time, it will be interpreted as having + * been issued in the future. RFC6962 states that "TLS clients MUST reject SCTs + * whose timestamp is in the future", so an SCT will not validate in this case. + */ +void CT_POLICY_EVAL_CTX_set_time(CT_POLICY_EVAL_CTX *ctx, uint64_t time_in_ms); + +/***************** + * SCT functions * + *****************/ + +/* + * Creates a new, blank SCT. + * The caller is responsible for calling SCT_free when finished with the SCT. + */ +SCT *SCT_new(void); + +/* + * Creates a new SCT from some base64-encoded strings. + * The caller is responsible for calling SCT_free when finished with the SCT. + */ +SCT *SCT_new_from_base64(unsigned char version, const char *logid_base64, + ct_log_entry_type_t entry_type, uint64_t timestamp, + const char *extensions_base64, const char *signature_base64); + +/* + * Frees the SCT and the underlying data structures. + */ +void SCT_free(SCT *sct); + +/* + * Free a stack of SCTs, and the underlying SCTs themselves. + * Intended to be compatible with X509V3_EXT_FREE. + */ +void SCT_LIST_free(STACK_OF(SCT) *a); + +/* + * Returns the version of the SCT. + */ +sct_version_t SCT_get_version(const SCT *sct); + +/* + * Set the version of an SCT. + * Returns 1 on success, 0 if the version is unrecognized. + */ +int SCT_set_version(SCT *sct, sct_version_t version); + +/* + * Returns the log entry type of the SCT. + */ +ct_log_entry_type_t SCT_get_log_entry_type(const SCT *sct); + +/* + * Set the log entry type of an SCT. + * Returns 1 on success, 0 otherwise. + */ +int SCT_set_log_entry_type(SCT *sct, ct_log_entry_type_t entry_type); + +/* + * Gets the ID of the log that an SCT came from. + * Ownership of the log ID remains with the SCT. + * Returns the length of the log ID. + */ +size_t SCT_get0_log_id(const SCT *sct, unsigned char **log_id); + +/* + * Set the log ID of an SCT to point directly to the *log_id specified. + * The SCT takes ownership of the specified pointer. + * Returns 1 on success, 0 otherwise. + */ +int SCT_set0_log_id(SCT *sct, unsigned char *log_id, size_t log_id_len); + +/* + * Set the log ID of an SCT. + * This makes a copy of the log_id. + * Returns 1 on success, 0 otherwise. + */ +int SCT_set1_log_id(SCT *sct, const unsigned char *log_id, + size_t log_id_len); + +/* + * Returns the timestamp for the SCT (epoch time in milliseconds). + */ +uint64_t SCT_get_timestamp(const SCT *sct); + +/* + * Set the timestamp of an SCT (epoch time in milliseconds). + */ +void SCT_set_timestamp(SCT *sct, uint64_t timestamp); + +/* + * Return the NID for the signature used by the SCT. + * For CT v1, this will be either NID_sha256WithRSAEncryption or + * NID_ecdsa_with_SHA256 (or NID_undef if incorrect/unset). + */ +int SCT_get_signature_nid(const SCT *sct); + +/* + * Set the signature type of an SCT + * For CT v1, this should be either NID_sha256WithRSAEncryption or + * NID_ecdsa_with_SHA256. + * Returns 1 on success, 0 otherwise. + */ +int SCT_set_signature_nid(SCT *sct, int nid); + +/* + * Set *ext to point to the extension data for the SCT. ext must not be NULL. + * The SCT retains ownership of this pointer. + * Returns length of the data pointed to. + */ +size_t SCT_get0_extensions(const SCT *sct, unsigned char **ext); + +/* + * Set the extensions of an SCT to point directly to the *ext specified. + * The SCT takes ownership of the specified pointer. + */ +void SCT_set0_extensions(SCT *sct, unsigned char *ext, size_t ext_len); + +/* + * Set the extensions of an SCT. + * This takes a copy of the ext. + * Returns 1 on success, 0 otherwise. + */ +int SCT_set1_extensions(SCT *sct, const unsigned char *ext, + size_t ext_len); + +/* + * Set *sig to point to the signature for the SCT. sig must not be NULL. + * The SCT retains ownership of this pointer. + * Returns length of the data pointed to. + */ +size_t SCT_get0_signature(const SCT *sct, unsigned char **sig); + +/* + * Set the signature of an SCT to point directly to the *sig specified. + * The SCT takes ownership of the specified pointer. + */ +void SCT_set0_signature(SCT *sct, unsigned char *sig, size_t sig_len); + +/* + * Set the signature of an SCT to be a copy of the *sig specified. + * Returns 1 on success, 0 otherwise. + */ +int SCT_set1_signature(SCT *sct, const unsigned char *sig, + size_t sig_len); + +/* + * The origin of this SCT, e.g. TLS extension, OCSP response, etc. + */ +sct_source_t SCT_get_source(const SCT *sct); + +/* + * Set the origin of this SCT, e.g. TLS extension, OCSP response, etc. + * Returns 1 on success, 0 otherwise. + */ +int SCT_set_source(SCT *sct, sct_source_t source); + +/* + * Returns a text string describing the validation status of |sct|. + */ +const char *SCT_validation_status_string(const SCT *sct); + +/* + * Pretty-prints an |sct| to |out|. + * It will be indented by the number of spaces specified by |indent|. + * If |logs| is not NULL, it will be used to lookup the CT log that the SCT came + * from, so that the log name can be printed. + */ +void SCT_print(const SCT *sct, BIO *out, int indent, const CTLOG_STORE *logs); + +/* + * Pretty-prints an |sct_list| to |out|. + * It will be indented by the number of spaces specified by |indent|. + * SCTs will be delimited by |separator|. + * If |logs| is not NULL, it will be used to lookup the CT log that each SCT + * came from, so that the log names can be printed. + */ +void SCT_LIST_print(const STACK_OF(SCT) *sct_list, BIO *out, int indent, + const char *separator, const CTLOG_STORE *logs); + +/* + * Gets the last result of validating this SCT. + * If it has not been validated yet, returns SCT_VALIDATION_STATUS_NOT_SET. + */ +sct_validation_status_t SCT_get_validation_status(const SCT *sct); + +/* + * Validates the given SCT with the provided context. + * Sets the "validation_status" field of the SCT. + * Returns 1 if the SCT is valid and the signature verifies. + * Returns 0 if the SCT is invalid or could not be verified. + * Returns -1 if an error occurs. + */ +int SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx); + +/* + * Validates the given list of SCTs with the provided context. + * Sets the "validation_status" field of each SCT. + * Returns 1 if there are no invalid SCTs and all signatures verify. + * Returns 0 if at least one SCT is invalid or could not be verified. + * Returns a negative integer if an error occurs. + */ +int SCT_LIST_validate(const STACK_OF(SCT) *scts, + CT_POLICY_EVAL_CTX *ctx); + + +/********************************* + * SCT parsing and serialisation * + *********************************/ + +/* + * Serialize (to TLS format) a stack of SCTs and return the length. + * "a" must not be NULL. + * If "pp" is NULL, just return the length of what would have been serialized. + * If "pp" is not NULL and "*pp" is null, function will allocate a new pointer + * for data that caller is responsible for freeing (only if function returns + * successfully). + * If "pp" is NULL and "*pp" is not NULL, caller is responsible for ensuring + * that "*pp" is large enough to accept all of the serialized data. + * Returns < 0 on error, >= 0 indicating bytes written (or would have been) + * on success. + */ +int i2o_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp); + +/* + * Convert TLS format SCT list to a stack of SCTs. + * If "a" or "*a" is NULL, a new stack will be created that the caller is + * responsible for freeing (by calling SCT_LIST_free). + * "**pp" and "*pp" must not be NULL. + * Upon success, "*pp" will point to after the last bytes read, and a stack + * will be returned. + * Upon failure, a NULL pointer will be returned, and the position of "*pp" is + * not defined. + */ +STACK_OF(SCT) *o2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, + size_t len); + +/* + * Serialize (to DER format) a stack of SCTs and return the length. + * "a" must not be NULL. + * If "pp" is NULL, just returns the length of what would have been serialized. + * If "pp" is not NULL and "*pp" is null, function will allocate a new pointer + * for data that caller is responsible for freeing (only if function returns + * successfully). + * If "pp" is NULL and "*pp" is not NULL, caller is responsible for ensuring + * that "*pp" is large enough to accept all of the serialized data. + * Returns < 0 on error, >= 0 indicating bytes written (or would have been) + * on success. + */ +int i2d_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp); + +/* + * Parses an SCT list in DER format and returns it. + * If "a" or "*a" is NULL, a new stack will be created that the caller is + * responsible for freeing (by calling SCT_LIST_free). + * "**pp" and "*pp" must not be NULL. + * Upon success, "*pp" will point to after the last bytes read, and a stack + * will be returned. + * Upon failure, a NULL pointer will be returned, and the position of "*pp" is + * not defined. + */ +STACK_OF(SCT) *d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, + long len); + +/* + * Serialize (to TLS format) an |sct| and write it to |out|. + * If |out| is null, no SCT will be output but the length will still be returned. + * If |out| points to a null pointer, a string will be allocated to hold the + * TLS-format SCT. It is the responsibility of the caller to free it. + * If |out| points to an allocated string, the TLS-format SCT will be written + * to it. + * The length of the SCT in TLS format will be returned. + */ +int i2o_SCT(const SCT *sct, unsigned char **out); + +/* + * Parses an SCT in TLS format and returns it. + * If |psct| is not null, it will end up pointing to the parsed SCT. If it + * already points to a non-null pointer, the pointer will be free'd. + * |in| should be a pointer to a string containing the TLS-format SCT. + * |in| will be advanced to the end of the SCT if parsing succeeds. + * |len| should be the length of the SCT in |in|. + * Returns NULL if an error occurs. + * If the SCT is an unsupported version, only the SCT's 'sct' and 'sct_len' + * fields will be populated (with |in| and |len| respectively). + */ +SCT *o2i_SCT(SCT **psct, const unsigned char **in, size_t len); + +/******************** + * CT log functions * + ********************/ + +/* + * Creates a new CT log instance with the given |public_key| and |name|. + * Takes ownership of |public_key| but copies |name|. + * Returns NULL if malloc fails or if |public_key| cannot be converted to DER. + * Should be deleted by the caller using CTLOG_free when no longer needed. + */ +CTLOG *CTLOG_new(EVP_PKEY *public_key, const char *name); + +/* + * Creates a new CTLOG instance with the base64-encoded SubjectPublicKeyInfo DER + * in |pkey_base64|. The |name| is a string to help users identify this log. + * Returns 1 on success, 0 on failure. + * Should be deleted by the caller using CTLOG_free when no longer needed. + */ +int CTLOG_new_from_base64(CTLOG **ct_log, const char *pkey_base64, + const char *name); + +/* + * Deletes a CT log instance and its fields. + */ +void CTLOG_free(CTLOG *log); + +/* Gets the name of the CT log */ +const char *CTLOG_get0_name(const CTLOG *log); +/* Gets the ID of the CT log */ +void CTLOG_get0_log_id(const CTLOG *log, const uint8_t **log_id, + size_t *log_id_len); +/* Gets the public key of the CT log */ +EVP_PKEY *CTLOG_get0_public_key(const CTLOG *log); + +/************************** + * CT log store functions * + **************************/ + +/* + * Creates a new CT log store. + * Should be deleted by the caller using CTLOG_STORE_free when no longer needed. + */ +CTLOG_STORE *CTLOG_STORE_new(void); + +/* + * Deletes a CT log store and all of the CT log instances held within. + */ +void CTLOG_STORE_free(CTLOG_STORE *store); + +/* + * Finds a CT log in the store based on its log ID. + * Returns the CT log, or NULL if no match is found. + */ +const CTLOG *CTLOG_STORE_get0_log_by_id(const CTLOG_STORE *store, + const uint8_t *log_id, size_t log_id_len); + +/* + * Loads a CT log list into a |store| from a |file|. + * Returns 1 if loading is successful, or 0 otherwise. + */ +int CTLOG_STORE_load_file(CTLOG_STORE *store, const char *file); + +/* + * Loads the default CT log list into a |store|. + * Returns 1 if loading is successful, or 0 otherwise. + */ +int CTLOG_STORE_load_default_file(CTLOG_STORE *store); + +#ifdef __cplusplus +} +#endif +#endif +#endif diff --git a/include/openssl/cterr.h b/include/openssl/cterr.h new file mode 100644 index 0000000..07ae519 --- /dev/null +++ b/include/openssl/cterr.h @@ -0,0 +1,127 @@ +/* $OpenBSD: cterr.h,v 1.5 2021/12/18 16:50:40 tb Exp $ */ +/* ==================================================================== + * Copyright (c) 1999-2006 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). + * + */ + +/* NOTE: this file was auto generated by the mkerr.pl script: any changes + * made to it will be overwritten when the script next updates this file, + * only reason strings will be preserved. + */ + +#ifndef HEADER_CTERR_H +# define HEADER_CTERR_H + +# include + +# ifndef OPENSSL_NO_CT + +#ifdef __cplusplus +extern "C" +#endif + +int ERR_load_CT_strings(void); + +/* + * CT function codes. + */ +# define CT_F_CTLOG_NEW 117 +# define CT_F_CTLOG_NEW_FROM_BASE64 118 +# define CT_F_CTLOG_NEW_FROM_CONF 119 +# define CT_F_CTLOG_STORE_LOAD_CTX_NEW 122 +# define CT_F_CTLOG_STORE_LOAD_FILE 123 +# define CT_F_CTLOG_STORE_LOAD_LOG 130 +# define CT_F_CTLOG_STORE_NEW 131 +# define CT_F_CT_BASE64_DECODE 124 +# define CT_F_CT_POLICY_EVAL_CTX_NEW 133 +# define CT_F_CT_V1_LOG_ID_FROM_PKEY 125 +# define CT_F_I2O_SCT 107 +# define CT_F_I2O_SCT_LIST 108 +# define CT_F_I2O_SCT_SIGNATURE 109 +# define CT_F_O2I_SCT 110 +# define CT_F_O2I_SCT_LIST 111 +# define CT_F_O2I_SCT_SIGNATURE 112 +# define CT_F_SCT_CTX_NEW 126 +# define CT_F_SCT_CTX_VERIFY 128 +# define CT_F_SCT_NEW 100 +# define CT_F_SCT_NEW_FROM_BASE64 127 +# define CT_F_SCT_SET0_LOG_ID 101 +# define CT_F_SCT_SET1_EXTENSIONS 114 +# define CT_F_SCT_SET1_LOG_ID 115 +# define CT_F_SCT_SET1_SIGNATURE 116 +# define CT_F_SCT_SET_LOG_ENTRY_TYPE 102 +# define CT_F_SCT_SET_SIGNATURE_NID 103 +# define CT_F_SCT_SET_VERSION 104 + +/* + * CT reason codes. + */ +# define CT_R_BASE64_DECODE_ERROR 108 +# define CT_R_INVALID_LOG_ID_LENGTH 100 +# define CT_R_LOG_CONF_INVALID 109 +# define CT_R_LOG_CONF_INVALID_KEY 110 +# define CT_R_LOG_CONF_MISSING_DESCRIPTION 111 +# define CT_R_LOG_CONF_MISSING_KEY 112 +# define CT_R_LOG_KEY_INVALID 113 +# define CT_R_SCT_FUTURE_TIMESTAMP 116 +# define CT_R_SCT_INVALID 104 +# define CT_R_SCT_INVALID_SIGNATURE 107 +# define CT_R_SCT_LIST_INVALID 105 +# define CT_R_SCT_LOG_ID_MISMATCH 114 +# define CT_R_SCT_NOT_SET 106 +# define CT_R_SCT_UNSUPPORTED_VERSION 115 +# define CT_R_UNRECOGNIZED_SIGNATURE_NID 101 +# define CT_R_UNSUPPORTED_ENTRY_TYPE 102 +# define CT_R_UNSUPPORTED_VERSION 103 + +# endif +#endif diff --git a/include/openssl/dh.h b/include/openssl/dh.h index 082b502..ef10495 100644 --- a/include/openssl/dh.h +++ b/include/openssl/dh.h @@ -1,25 +1,25 @@ -/* $OpenBSD: dh.h,v 1.25 2018/02/22 16:41:04 jsing Exp $ */ +/* $OpenBSD: dh.h,v 1.32 2022/01/14 08:25:44 tb Exp $ */ /* 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: @@ -34,10 +34,10 @@ * 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 + * 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 @@ -49,7 +49,7 @@ * 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 @@ -72,7 +72,7 @@ #ifndef OPENSSL_NO_DEPRECATED #include #endif - + #ifndef OPENSSL_DH_MAX_MODULUS_BITS # define OPENSSL_DH_MAX_MODULUS_BITS 10000 #endif @@ -98,55 +98,6 @@ extern "C" { #endif -/* Already defined in ossl_typ.h */ -/* typedef struct dh_st DH; */ -/* typedef struct dh_method DH_METHOD; */ - -struct dh_method - { - const char *name; - /* Methods here */ - int (*generate_key)(DH *dh); - int (*compute_key)(unsigned char *key,const BIGNUM *pub_key,DH *dh); - int (*bn_mod_exp)(const DH *dh, BIGNUM *r, const BIGNUM *a, - const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, - BN_MONT_CTX *m_ctx); /* Can be null */ - - int (*init)(DH *dh); - int (*finish)(DH *dh); - int flags; - char *app_data; - /* If this is non-NULL, it will be used to generate parameters */ - int (*generate_params)(DH *dh, int prime_len, int generator, BN_GENCB *cb); - }; - -struct dh_st - { - /* This first argument is used to pick up errors when - * a DH is passed instead of a EVP_PKEY */ - int pad; - int version; - BIGNUM *p; - BIGNUM *g; - long length; /* optional */ - BIGNUM *pub_key; /* g^x */ - BIGNUM *priv_key; /* x */ - - int flags; - BN_MONT_CTX *method_mont_p; - /* Place holders if we want to do X9.42 DH */ - BIGNUM *q; - BIGNUM *j; - unsigned char *seed; - int seedlen; - BIGNUM *counter; - - int references; - CRYPTO_EX_DATA ex_data; - const DH_METHOD *meth; - ENGINE *engine; - }; - #define DH_GENERATOR_2 2 /* #define DH_GENERATOR_3 3 */ #define DH_GENERATOR_5 5 @@ -156,10 +107,14 @@ struct dh_st #define DH_CHECK_P_NOT_SAFE_PRIME 0x02 #define DH_UNABLE_TO_CHECK_GENERATOR 0x04 #define DH_NOT_SUITABLE_GENERATOR 0x08 +#define DH_CHECK_Q_NOT_PRIME 0x10 +#define DH_CHECK_INVALID_Q_VALUE 0x20 +#define DH_CHECK_INVALID_J_VALUE 0x40 /* DH_check_pub_key error codes */ #define DH_CHECK_PUBKEY_TOO_SMALL 0x01 #define DH_CHECK_PUBKEY_TOO_LARGE 0x02 +#define DH_CHECK_PUBKEY_INVALID 0x04 /* primes p where (p-1)/2 is prime too are called "safe"; we define this for backward compatibility: */ @@ -195,9 +150,15 @@ void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g); void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key); int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key); +const BIGNUM *DH_get0_p(const DH *dh); +const BIGNUM *DH_get0_q(const DH *dh); +const BIGNUM *DH_get0_g(const DH *dh); +const BIGNUM *DH_get0_priv_key(const DH *dh); +const BIGNUM *DH_get0_pub_key(const DH *dh); void DH_clear_flags(DH *dh, int flags); int DH_test_flags(const DH *dh, int flags); void DH_set_flags(DH *dh, int flags); +long DH_get_length(const DH *dh); int DH_set_length(DH *dh, long length); /* Deprecated version */ @@ -232,7 +193,7 @@ int DHparams_print(char *bp, const DH *x); #define EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN (EVP_PKEY_ALG_CTRL + 1) #define EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR (EVP_PKEY_ALG_CTRL + 2) - + /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes @@ -274,6 +235,17 @@ void ERR_load_DH_strings(void); #define DH_R_NO_PARAMETERS_SET 107 #define DH_R_NO_PRIVATE_VALUE 100 #define DH_R_PARAMETER_ENCODING_ERROR 105 +#define DH_R_CHECK_INVALID_J_VALUE 115 +#define DH_R_CHECK_INVALID_Q_VALUE 116 +#define DH_R_CHECK_PUBKEY_INVALID 122 +#define DH_R_CHECK_PUBKEY_TOO_LARGE 123 +#define DH_R_CHECK_PUBKEY_TOO_SMALL 124 +#define DH_R_CHECK_P_NOT_PRIME 117 +#define DH_R_CHECK_P_NOT_SAFE_PRIME 118 +#define DH_R_CHECK_Q_NOT_PRIME 119 +#define DH_R_MISSING_PUBKEY 125 +#define DH_R_NOT_SUITABLE_GENERATOR 120 +#define DH_R_UNABLE_TO_CHECK_GENERATOR 121 #ifdef __cplusplus } diff --git a/include/openssl/dsa.h b/include/openssl/dsa.h index 61bfc2b..4fafce3 100644 --- a/include/openssl/dsa.h +++ b/include/openssl/dsa.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dsa.h,v 1.30 2018/03/17 15:19:12 tb Exp $ */ +/* $OpenBSD: dsa.h,v 1.35 2022/01/14 08:27:23 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -109,69 +109,7 @@ extern "C" { #endif -/* Already defined in ossl_typ.h */ -/* typedef struct dsa_st DSA; */ -/* typedef struct dsa_method DSA_METHOD; */ - -typedef struct DSA_SIG_st - { - BIGNUM *r; - BIGNUM *s; - } DSA_SIG; - -struct dsa_method - { - const char *name; - DSA_SIG * (*dsa_do_sign)(const unsigned char *dgst, int dlen, DSA *dsa); - int (*dsa_sign_setup)(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, - BIGNUM **rp); - int (*dsa_do_verify)(const unsigned char *dgst, int dgst_len, - DSA_SIG *sig, DSA *dsa); - int (*dsa_mod_exp)(DSA *dsa, BIGNUM *rr, BIGNUM *a1, BIGNUM *p1, - BIGNUM *a2, BIGNUM *p2, BIGNUM *m, BN_CTX *ctx, - BN_MONT_CTX *in_mont); - int (*bn_mod_exp)(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p, - const BIGNUM *m, BN_CTX *ctx, - BN_MONT_CTX *m_ctx); /* Can be null */ - int (*init)(DSA *dsa); - int (*finish)(DSA *dsa); - int flags; - char *app_data; - /* If this is non-NULL, it is used to generate DSA parameters */ - int (*dsa_paramgen)(DSA *dsa, int bits, - const unsigned char *seed, int seed_len, - int *counter_ret, unsigned long *h_ret, - BN_GENCB *cb); - /* If this is non-NULL, it is used to generate DSA keys */ - int (*dsa_keygen)(DSA *dsa); - }; - -struct dsa_st - { - /* This first variable is used to pick up errors where - * a DSA is passed instead of of a EVP_PKEY */ - int pad; - long version; - int write_params; - BIGNUM *p; - BIGNUM *q; /* == 20 */ - BIGNUM *g; - - BIGNUM *pub_key; /* y public key */ - BIGNUM *priv_key; /* x private key */ - - BIGNUM *kinv; /* Signing pre-calc */ - BIGNUM *r; /* Signing pre-calc */ - - int flags; - /* Normally used to cache montgomery values */ - BN_MONT_CTX *method_mont_p; - int references; - CRYPTO_EX_DATA ex_data; - const DSA_METHOD *meth; - /* functional reference if 'meth' is ENGINE-provided */ - ENGINE *engine; - }; +typedef struct DSA_SIG_st DSA_SIG; DSA *d2i_DSAparams_bio(BIO *bp, DSA **a); int i2d_DSAparams_bio(BIO *bp, DSA *a); @@ -202,6 +140,7 @@ void DSA_free(DSA *r); /* "up" the DSA object's reference count */ int DSA_up_ref(DSA *r); int DSA_size(const DSA *); +int DSA_bits(const DSA *d); /* next 4 return -1 on error */ int DSA_sign_setup( DSA *dsa,BN_CTX *ctx_in,BIGNUM **kinvp,BIGNUM **rp); int DSA_sign(int type,const unsigned char *dgst,int dlen, @@ -247,9 +186,12 @@ int DSA_print(BIO *bp, const DSA *x, int off); int DSAparams_print_fp(FILE *fp, const DSA *x); int DSA_print_fp(FILE *bp, const DSA *x, int off); -#define DSS_prime_checks 50 -/* Primality test according to FIPS PUB 186[-1], Appendix 2.1: - * 50 rounds of Rabin-Miller */ +/* + * Primality test according to FIPS PUB 186-4, Appendix C.3. Set the number + * to 64 rounds of Miller-Rabin, which corresponds to 128 bits of security. + * This is necessary for keys of size >= 3072. + */ +#define DSS_prime_checks 64 #define DSA_is_prime(n, callback, cb_arg) \ BN_is_prime(n, DSS_prime_checks, callback, NULL, cb_arg) @@ -264,6 +206,11 @@ void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g); void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key); int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key); +const BIGNUM *DSA_get0_p(const DSA *d); +const BIGNUM *DSA_get0_q(const DSA *d); +const BIGNUM *DSA_get0_g(const DSA *d); +const BIGNUM *DSA_get0_pub_key(const DSA *d); +const BIGNUM *DSA_get0_priv_key(const DSA *d); void DSA_clear_flags(DSA *d, int flags); int DSA_test_flags(const DSA *d, int flags); void DSA_set_flags(DSA *d, int flags); diff --git a/include/openssl/ecdsa.h b/include/openssl/ecdsa.h index c4e107e..eccca65 100644 --- a/include/openssl/ecdsa.h +++ b/include/openssl/ecdsa.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ecdsa.h,v 1.8 2019/01/19 01:17:41 tb Exp $ */ +/* $OpenBSD: ecdsa.h,v 1.11 2022/01/14 08:31:03 tb Exp $ */ /** * \file crypto/ecdsa/ecdsa.h Include file for the OpenSSL ECDSA functions * \author Written by Nils Larsch for the OpenSSL project @@ -85,10 +85,6 @@ struct ecdsa_method { BIGNUM **r); int (*ecdsa_do_verify)(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey); -#if 0 - int (*init)(EC_KEY *eckey); - int (*finish)(EC_KEY *eckey); -#endif int flags; char *app_data; }; @@ -101,11 +97,6 @@ struct ecdsa_method { #define ECDSA_FLAG_FIPS_METHOD 0x1 -struct ECDSA_SIG_st { - BIGNUM *r; - BIGNUM *s; -}; - /** Allocates and initialize a ECDSA_SIG structure * \return pointer to a ECDSA_SIG structure or NULL if an error occurred */ @@ -140,6 +131,9 @@ ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **sig, const unsigned char **pp, long len); */ void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); +const BIGNUM *ECDSA_SIG_get0_r(const ECDSA_SIG *sig); +const BIGNUM *ECDSA_SIG_get0_s(const ECDSA_SIG *sig); + /** Setter for r and s fields of ECDSA_SIG * \param sig pointer to ECDSA_SIG pointer * \param r pointer to BIGNUM for r (may be NULL) diff --git a/include/openssl/err.h b/include/openssl/err.h index 22cdb29..20fa908 100644 --- a/include/openssl/err.h +++ b/include/openssl/err.h @@ -1,4 +1,4 @@ -/* $OpenBSD: err.h,v 1.25 2017/02/20 23:21:19 beck Exp $ */ +/* $OpenBSD: err.h,v 1.26 2021/11/24 01:12:43 beck Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -196,6 +196,7 @@ typedef struct err_state_st { #define ERR_LIB_HMAC 48 #define ERR_LIB_JPAKE 49 #define ERR_LIB_GOST 50 +#define ERR_LIB_CT 51 #define ERR_LIB_USER 128 @@ -234,6 +235,7 @@ typedef struct err_state_st { #define JPAKEerr(f,r) ERR_PUT_error(ERR_LIB_JPAKE,(f),(r),__FILE__,__LINE__) #define GOSTerr(f,r) ERR_PUT_error(ERR_LIB_GOST,(f),(r),__FILE__,__LINE__) #define SSLerr(f,r) ERR_PUT_error(ERR_LIB_SSL,(f),(r),__FILE__,__LINE__) +#define CTerr(f, r) ERR_PUT_error(ERR_LIB_CT,(f),(r),__FILE__,__LINE__) #endif #ifdef LIBRESSL_INTERNAL @@ -270,6 +272,7 @@ typedef struct err_state_st { #define HMACerror(r) ERR_PUT_error(ERR_LIB_HMAC,(0xfff),(r),__FILE__,__LINE__) #define JPAKEerror(r) ERR_PUT_error(ERR_LIB_JPAKE,(0xfff),(r),__FILE__,__LINE__) #define GOSTerror(r) ERR_PUT_error(ERR_LIB_GOST,(0xfff),(r),__FILE__,__LINE__) +#define CTerror(r) ERR_PUT_error(ERR_LIB_CT,(0xfff),(r),__FILE__,__LINE__) #endif #define ERR_PACK(l,f,r) (((((unsigned long)l)&0xffL)<<24L)| \ diff --git a/include/openssl/evp.h b/include/openssl/evp.h index 06c529e..a80cf18 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: evp.h,v 1.83 2021/05/10 17:00:32 tb Exp $ */ +/* $OpenBSD: evp.h,v 1.99 2022/01/14 08:38:05 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -119,82 +119,15 @@ extern "C" { #endif -/* Type needs to be a bit field - * Sub-type needs to be for variations on the method, as in, can it do - * arbitrary encryption.... */ -struct evp_pkey_st { - int type; - int save_type; - int references; - const EVP_PKEY_ASN1_METHOD *ameth; - ENGINE *engine; - union { - char *ptr; -#ifndef OPENSSL_NO_RSA - struct rsa_st *rsa; /* RSA */ -#endif -#ifndef OPENSSL_NO_DSA - struct dsa_st *dsa; /* DSA */ -#endif -#ifndef OPENSSL_NO_DH - struct dh_st *dh; /* DH */ -#endif -#ifndef OPENSSL_NO_EC - struct ec_key_st *ec; /* ECC */ -#endif -#ifndef OPENSSL_NO_GOST - struct gost_key_st *gost; /* GOST */ -#endif - } pkey; - int save_parameters; - STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */ -} /* EVP_PKEY */; - #define EVP_PKEY_MO_SIGN 0x0001 #define EVP_PKEY_MO_VERIFY 0x0002 #define EVP_PKEY_MO_ENCRYPT 0x0004 #define EVP_PKEY_MO_DECRYPT 0x0008 -typedef int evp_sign_method(int type, const unsigned char *m, - unsigned int m_length, unsigned char *sigret, unsigned int *siglen, - void *key); -typedef int evp_verify_method(int type, const unsigned char *m, - unsigned int m_length, const unsigned char *sigbuf, unsigned int siglen, - void *key); - #ifndef EVP_MD -struct env_md_st { - int type; - int pkey_type; - int md_size; - unsigned long flags; - int (*init)(EVP_MD_CTX *ctx); - int (*update)(EVP_MD_CTX *ctx, const void *data, size_t count); - int (*final)(EVP_MD_CTX *ctx, unsigned char *md); - int (*copy)(EVP_MD_CTX *to, const EVP_MD_CTX *from); - int (*cleanup)(EVP_MD_CTX *ctx); - - evp_sign_method *sign; - evp_verify_method *verify; - int required_pkey_type[5]; /*EVP_PKEY_xxx */ - int block_size; - int ctx_size; /* how big does the ctx->md_data need to be */ - /* control function */ - int (*md_ctrl)(EVP_MD_CTX *ctx, int cmd, int p1, void *p2); -} /* EVP_MD */; - #define EVP_MD_FLAG_ONESHOT 0x0001 /* digest can only handle a single * block */ -#define EVP_MD_FLAG_PKEY_DIGEST 0x0002 /* digest is a "clone" digest used - * which is a copy of an existing - * one for a specific public key type. - * EVP_dss1() etc */ - -/* Digest uses EVP_PKEY_METHOD for signing instead of MD specific signing */ - -#define EVP_MD_FLAG_PKEY_METHOD_SIGNATURE 0x0004 - /* DigestAlgorithmIdentifier flags... */ #define EVP_MD_FLAG_DIGALGID_MASK 0x0018 @@ -224,51 +157,8 @@ struct env_md_st { #define EVP_MD_CTRL_ALG_CTRL 0x1000 -#define EVP_PKEY_NULL_method NULL,NULL,{0,0,0,0} - -#ifndef OPENSSL_NO_DSA -#define EVP_PKEY_DSA_method (evp_sign_method *)DSA_sign, \ - (evp_verify_method *)DSA_verify, \ - {EVP_PKEY_DSA,EVP_PKEY_DSA2,EVP_PKEY_DSA3, \ - EVP_PKEY_DSA4,0} -#else -#define EVP_PKEY_DSA_method EVP_PKEY_NULL_method -#endif - -#ifndef OPENSSL_NO_ECDSA -#define EVP_PKEY_ECDSA_method (evp_sign_method *)ECDSA_sign, \ - (evp_verify_method *)ECDSA_verify, \ - {EVP_PKEY_EC,0,0,0} -#else -#define EVP_PKEY_ECDSA_method EVP_PKEY_NULL_method -#endif - -#ifndef OPENSSL_NO_RSA -#define EVP_PKEY_RSA_method (evp_sign_method *)RSA_sign, \ - (evp_verify_method *)RSA_verify, \ - {EVP_PKEY_RSA,EVP_PKEY_RSA2,0,0} -#define EVP_PKEY_RSA_ASN1_OCTET_STRING_method \ - (evp_sign_method *)RSA_sign_ASN1_OCTET_STRING, \ - (evp_verify_method *)RSA_verify_ASN1_OCTET_STRING, \ - {EVP_PKEY_RSA,EVP_PKEY_RSA2,0,0} -#else -#define EVP_PKEY_RSA_method EVP_PKEY_NULL_method -#define EVP_PKEY_RSA_ASN1_OCTET_STRING_method EVP_PKEY_NULL_method -#endif - #endif /* !EVP_MD */ -struct env_md_ctx_st { - const EVP_MD *digest; - ENGINE *engine; /* functional reference if 'digest' is ENGINE-provided */ - unsigned long flags; - void *md_data; - /* Public key context for sign/verify */ - EVP_PKEY_CTX *pctx; - /* Update function: usually copied from EVP_MD */ - int (*update)(EVP_MD_CTX *ctx, const void *data, size_t count); -} /* EVP_MD_CTX */; - /* values for EVP_MD_CTX flags */ #define EVP_MD_CTX_FLAG_ONESHOT 0x0001 /* digest update will be called @@ -295,24 +185,6 @@ struct env_md_ctx_st { #define EVP_MD_CTX_FLAG_NO_INIT 0x0100 /* Don't initialize md_data */ -struct evp_cipher_st { - int nid; - int block_size; - int key_len; /* Default value for variable length ciphers */ - int iv_len; - unsigned long flags; /* Various flags */ - int (*init)(EVP_CIPHER_CTX *ctx, const unsigned char *key, - const unsigned char *iv, int enc); /* init key */ - int (*do_cipher)(EVP_CIPHER_CTX *ctx, unsigned char *out, - const unsigned char *in, size_t inl);/* encrypt/decrypt data */ - int (*cleanup)(EVP_CIPHER_CTX *); /* cleanup ctx */ - int ctx_size; /* how big ctx->cipher_data needs to be */ - int (*set_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); /* Populate a ASN1_TYPE with parameters */ - int (*get_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); /* Get parameters from a ASN1_TYPE */ - int (*ctrl)(EVP_CIPHER_CTX *, int type, int arg, void *ptr); /* Miscellaneous operations */ - void *app_data; /* Application data */ -} /* EVP_CIPHER */; - /* Values for cipher flags */ /* Modes for ciphers */ @@ -327,23 +199,23 @@ struct evp_cipher_st { #define EVP_CIPH_CCM_MODE 0x7 #define EVP_CIPH_XTS_MODE 0x10001 #define EVP_CIPH_WRAP_MODE 0x10002 -#define EVP_CIPH_MODE 0xF0007 +#define EVP_CIPH_MODE 0xF0007 /* Set if variable length cipher */ -#define EVP_CIPH_VARIABLE_LENGTH 0x8 +#define EVP_CIPH_VARIABLE_LENGTH 0x8 /* Set if the iv handling should be done by the cipher itself */ -#define EVP_CIPH_CUSTOM_IV 0x10 +#define EVP_CIPH_CUSTOM_IV 0x10 /* Set if the cipher's init() function should be called if key is NULL */ -#define EVP_CIPH_ALWAYS_CALL_INIT 0x20 +#define EVP_CIPH_ALWAYS_CALL_INIT 0x20 /* Call ctrl() to init cipher parameters */ -#define EVP_CIPH_CTRL_INIT 0x40 +#define EVP_CIPH_CTRL_INIT 0x40 /* Don't use standard key length function */ -#define EVP_CIPH_CUSTOM_KEY_LENGTH 0x80 +#define EVP_CIPH_CUSTOM_KEY_LENGTH 0x80 /* Don't use standard block padding */ -#define EVP_CIPH_NO_PADDING 0x100 +#define EVP_CIPH_NO_PADDING 0x100 /* cipher handles random key generation */ -#define EVP_CIPH_RAND_KEY 0x200 +#define EVP_CIPH_RAND_KEY 0x200 /* cipher has its own additional copying logic */ -#define EVP_CIPH_CUSTOM_COPY 0x400 +#define EVP_CIPH_CUSTOM_COPY 0x400 /* Allow use default ASN1 get/set iv */ #define EVP_CIPH_FLAG_DEFAULT_ASN1 0x1000 /* Buffer length in bits not bytes: CFB1 mode only */ @@ -355,7 +227,7 @@ struct evp_cipher_st { /* Cipher handles any and all padding logic as well * as finalisation. */ -#define EVP_CIPH_FLAG_CUSTOM_CIPHER 0x100000 +#define EVP_CIPH_FLAG_CUSTOM_CIPHER 0x100000 #define EVP_CIPH_FLAG_AEAD_CIPHER 0x200000 /* @@ -367,22 +239,25 @@ struct evp_cipher_st { /* ctrl() values */ #define EVP_CTRL_INIT 0x0 -#define EVP_CTRL_SET_KEY_LENGTH 0x1 -#define EVP_CTRL_GET_RC2_KEY_BITS 0x2 -#define EVP_CTRL_SET_RC2_KEY_BITS 0x3 -#define EVP_CTRL_GET_RC5_ROUNDS 0x4 -#define EVP_CTRL_SET_RC5_ROUNDS 0x5 -#define EVP_CTRL_RAND_KEY 0x6 -#define EVP_CTRL_PBE_PRF_NID 0x7 -#define EVP_CTRL_COPY 0x8 -#define EVP_CTRL_GCM_SET_IVLEN 0x9 -#define EVP_CTRL_GCM_GET_TAG 0x10 -#define EVP_CTRL_GCM_SET_TAG 0x11 +#define EVP_CTRL_SET_KEY_LENGTH 0x1 +#define EVP_CTRL_GET_RC2_KEY_BITS 0x2 +#define EVP_CTRL_SET_RC2_KEY_BITS 0x3 +#define EVP_CTRL_GET_RC5_ROUNDS 0x4 +#define EVP_CTRL_SET_RC5_ROUNDS 0x5 +#define EVP_CTRL_RAND_KEY 0x6 +#define EVP_CTRL_PBE_PRF_NID 0x7 +#define EVP_CTRL_COPY 0x8 +#define EVP_CTRL_AEAD_SET_IVLEN 0x9 +#define EVP_CTRL_AEAD_GET_TAG 0x10 +#define EVP_CTRL_AEAD_SET_TAG 0x11 +#define EVP_CTRL_GCM_SET_IVLEN EVP_CTRL_AEAD_SET_IVLEN +#define EVP_CTRL_GCM_GET_TAG EVP_CTRL_AEAD_GET_TAG +#define EVP_CTRL_GCM_SET_TAG EVP_CTRL_AEAD_SET_TAG #define EVP_CTRL_GCM_SET_IV_FIXED 0x12 #define EVP_CTRL_GCM_IV_GEN 0x13 -#define EVP_CTRL_CCM_SET_IVLEN EVP_CTRL_GCM_SET_IVLEN -#define EVP_CTRL_CCM_GET_TAG EVP_CTRL_GCM_GET_TAG -#define EVP_CTRL_CCM_SET_TAG EVP_CTRL_GCM_SET_TAG +#define EVP_CTRL_CCM_SET_IVLEN EVP_CTRL_AEAD_SET_IVLEN +#define EVP_CTRL_CCM_GET_TAG EVP_CTRL_AEAD_GET_TAG +#define EVP_CTRL_CCM_SET_TAG EVP_CTRL_AEAD_SET_TAG #define EVP_CTRL_CCM_SET_L 0x14 #define EVP_CTRL_CCM_SET_MSGLEN 0x15 /* AEAD cipher deduces payload length and returns number of bytes @@ -410,38 +285,6 @@ typedef struct evp_cipher_info_st { unsigned char iv[EVP_MAX_IV_LENGTH]; } EVP_CIPHER_INFO; -struct evp_cipher_ctx_st { - const EVP_CIPHER *cipher; - ENGINE *engine; /* functional reference if 'cipher' is ENGINE-provided */ - int encrypt; /* encrypt or decrypt */ - int buf_len; /* number we have left */ - - unsigned char oiv[EVP_MAX_IV_LENGTH]; /* original iv */ - unsigned char iv[EVP_MAX_IV_LENGTH]; /* working iv */ - unsigned char buf[EVP_MAX_BLOCK_LENGTH];/* saved partial block */ - int num; /* used by cfb/ofb/ctr mode */ - - void *app_data; /* application stuff */ - int key_len; /* May change for variable length cipher */ - unsigned long flags; /* Various flags */ - void *cipher_data; /* per EVP data */ - int final_used; - int block_mask; - unsigned char final[EVP_MAX_BLOCK_LENGTH];/* possible final block */ -} /* EVP_CIPHER_CTX */; - -typedef struct evp_Encode_Ctx_st { - int num; /* number saved in a partial encode/decode */ - int length; /* The length is either the output line length - * (in input bytes) or the shortest input line - * length that is ok. Once decoding begins, - * the length is adjusted up each time a longer - * line is decoded */ - unsigned char enc_data[80]; /* data to encode */ - int line_num; /* number read on current line */ - int expect_nl; -} EVP_ENCODE_CTX; - /* Password based encryption function */ typedef int (EVP_PBE_KEYGEN)(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md, int en_de); @@ -485,7 +328,28 @@ int EVP_MD_size(const EVP_MD *md); int EVP_MD_block_size(const EVP_MD *md); unsigned long EVP_MD_flags(const EVP_MD *md); +EVP_MD *EVP_MD_meth_new(int md_type, int pkey_type); +void EVP_MD_meth_free(EVP_MD *md); +EVP_MD *EVP_MD_meth_dup(const EVP_MD *md); +int EVP_MD_meth_set_input_blocksize(EVP_MD *md, int blocksize); +int EVP_MD_meth_set_result_size(EVP_MD *md, int resultsize); +int EVP_MD_meth_set_app_datasize(EVP_MD *md, int datasize); +int EVP_MD_meth_set_flags(EVP_MD *md, unsigned long flags); +int EVP_MD_meth_set_init(EVP_MD *md, int (*init)(EVP_MD_CTX *ctx)); +int EVP_MD_meth_set_update(EVP_MD *md, + int (*update)(EVP_MD_CTX *ctx, const void *data, size_t count)); +int EVP_MD_meth_set_final(EVP_MD *md, + int (*final)(EVP_MD_CTX *ctx, unsigned char *md)); +int EVP_MD_meth_set_copy(EVP_MD *md, + int (*copy)(EVP_MD_CTX *to, const EVP_MD_CTX *from)); +int EVP_MD_meth_set_cleanup(EVP_MD *md, int (*cleanup)(EVP_MD_CTX *ctx)); +int EVP_MD_meth_set_ctrl(EVP_MD *md, + int (*ctrl)(EVP_MD_CTX *ctx, int cmd, int p1, void *p2)); + const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx); +void *EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx); +EVP_PKEY_CTX *EVP_MD_CTX_pkey_ctx(const EVP_MD_CTX *ctx); +void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx); #define EVP_MD_CTX_size(e) EVP_MD_size(EVP_MD_CTX_md(e)) #define EVP_MD_CTX_block_size(e) EVP_MD_block_size(EVP_MD_CTX_md(e)) #define EVP_MD_CTX_type(e) EVP_MD_type(EVP_MD_CTX_md(e)) @@ -509,8 +373,11 @@ int EVP_CIPHER_CTX_get_iv(const EVP_CIPHER_CTX *ctx, int EVP_CIPHER_CTX_set_iv(EVP_CIPHER_CTX *ctx, const unsigned char *iv, size_t len); int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in); -void * EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx); +void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx); void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data); +void *EVP_CIPHER_CTX_get_cipher_data(const EVP_CIPHER_CTX *ctx); +void *EVP_CIPHER_CTX_set_cipher_data(EVP_CIPHER_CTX *ctx, void *cipher_data); +unsigned char *EVP_CIPHER_CTX_buf_noconst(EVP_CIPHER_CTX *ctx); #define EVP_CIPHER_CTX_type(c) EVP_CIPHER_type(EVP_CIPHER_CTX_cipher(c)) unsigned long EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx); #define EVP_CIPHER_CTX_mode(e) (EVP_CIPHER_CTX_flags(e) & EVP_CIPH_MODE) @@ -690,9 +557,6 @@ const EVP_MD *EVP_md5_sha1(void); #endif #ifndef OPENSSL_NO_SHA const EVP_MD *EVP_sha1(void); -const EVP_MD *EVP_dss(void); -const EVP_MD *EVP_dss1(void); -const EVP_MD *EVP_ecdsa(void); #endif #ifndef OPENSSL_NO_SHA256 const EVP_MD *EVP_sha224(void); @@ -1067,6 +931,13 @@ void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth, void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth, int (*pkey_ctrl)(EVP_PKEY *pkey, int op, long arg1, void *arg2)); +void EVP_PKEY_asn1_set_check(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_check)(const EVP_PKEY *pk)); +void EVP_PKEY_asn1_set_public_check(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_public_check)(const EVP_PKEY *pk)); +void EVP_PKEY_asn1_set_param_check(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_check)(const EVP_PKEY *pk)); + #define EVP_PKEY_OP_UNDEFINED 0 #define EVP_PKEY_OP_PARAMGEN (1<<1) #define EVP_PKEY_OP_KEYGEN (1<<2) @@ -1113,7 +984,7 @@ void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth, #define EVP_PKEY_CTRL_DIGESTINIT 7 /* Used by GOST key encryption in TLS */ -#define EVP_PKEY_CTRL_SET_IV 8 +#define EVP_PKEY_CTRL_SET_IV 8 #define EVP_PKEY_CTRL_CMS_ENCRYPT 9 #define EVP_PKEY_CTRL_CMS_DECRYPT 10 @@ -1193,6 +1064,9 @@ int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx); int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx); int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); +int EVP_PKEY_check(EVP_PKEY_CTX *ctx); +int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx); +int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx); void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb); EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx); @@ -1259,6 +1133,13 @@ void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth, int (*ctrl)(EVP_PKEY_CTX *ctx, int type, int p1, void *p2), int (*ctrl_str)(EVP_PKEY_CTX *ctx, const char *type, const char *value)); +void EVP_PKEY_meth_set_check(EVP_PKEY_METHOD *pmeth, + int (*check)(EVP_PKEY *pkey)); +void EVP_PKEY_meth_set_public_check(EVP_PKEY_METHOD *pmeth, + int (*public_check)(EVP_PKEY *pkey)); +void EVP_PKEY_meth_set_param_check(EVP_PKEY_METHOD *pmeth, + int (*param_check)(EVP_PKEY *pkey)); + /* Authenticated Encryption with Additional Data. * * AEAD couples confidentiality and integrity in a single primtive. AEAD @@ -1266,7 +1147,6 @@ void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth, * message has a unique, per-message nonce and, optionally, additional data * which is authenticated but not included in the output. */ -struct evp_aead_st; typedef struct evp_aead_st EVP_AEAD; #ifndef OPENSSL_NO_AES @@ -1300,11 +1180,7 @@ size_t EVP_AEAD_max_tag_len(const EVP_AEAD *aead); /* An EVP_AEAD_CTX represents an AEAD algorithm configured with a specific key * and message-independent IV. */ -typedef struct evp_aead_ctx_st { - const EVP_AEAD *aead; - /* aead_state is an opaque pointer to the AEAD specific state. */ - void *aead_state; -} EVP_AEAD_CTX; +typedef struct evp_aead_ctx_st EVP_AEAD_CTX; /* EVP_AEAD_MAX_TAG_LENGTH is the maximum tag length used by any AEAD * defined in this header. */ @@ -1315,7 +1191,15 @@ typedef struct evp_aead_ctx_st { * should be used. */ #define EVP_AEAD_DEFAULT_TAG_LENGTH 0 -/* EVP_AEAD_init initializes the context for the given AEAD algorithm. +/* EVP_AEAD_CTX_new allocates a new context for use with EVP_AEAD_CTX_init. + * It can be cleaned up for reuse with EVP_AEAD_CTX_cleanup and must be freed + * with EVP_AEAD_CTX_free. */ +EVP_AEAD_CTX *EVP_AEAD_CTX_new(void); + +/* EVP_AEAD_CTX_free releases all memory owned by the context. */ +void EVP_AEAD_CTX_free(EVP_AEAD_CTX *ctx); + +/* EVP_AEAD_CTX_init initializes the context for the given AEAD algorithm. * The implementation argument may be NULL to choose the default implementation. * Authentication tags may be truncated by passing a tag length. A tag length * of zero indicates the default tag length should be used. */ diff --git a/include/openssl/hmac.h b/include/openssl/hmac.h index e787c62..ff01ae2 100644 --- a/include/openssl/hmac.h +++ b/include/openssl/hmac.h @@ -1,4 +1,4 @@ -/* $OpenBSD: hmac.h,v 1.13 2018/02/17 14:53:59 jsing Exp $ */ +/* $OpenBSD: hmac.h,v 1.16 2022/01/14 08:06:03 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -72,24 +72,11 @@ extern "C" { #endif -typedef struct hmac_ctx_st { - const EVP_MD *md; - EVP_MD_CTX md_ctx; - EVP_MD_CTX i_ctx; - EVP_MD_CTX o_ctx; - unsigned int key_length; - unsigned char key[HMAC_MAX_MD_CBLOCK]; -} HMAC_CTX; - -#define HMAC_size(e) (EVP_MD_size((e)->md)) +#define HMAC_size(e) (EVP_MD_size(HMAC_CTX_get_md((e)))) HMAC_CTX *HMAC_CTX_new(void); void HMAC_CTX_free(HMAC_CTX *ctx); -void HMAC_CTX_init(HMAC_CTX *ctx); int HMAC_CTX_reset(HMAC_CTX *ctx); -void HMAC_CTX_cleanup(HMAC_CTX *ctx); - -#define HMAC_cleanup(ctx) HMAC_CTX_cleanup(ctx) /* deprecated */ int HMAC_Init(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md); /* deprecated */ diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h index d86324c..5da2b5d 100644 --- a/include/openssl/obj_mac.h +++ b/include/openssl/obj_mac.h @@ -881,6 +881,10 @@ #define NID_id_ct_signedChecklist 1014 #define OBJ_id_ct_signedChecklist OBJ_id_smime_ct,48L +#define SN_id_ct_ASPA "id-ct-ASPA" +#define NID_id_ct_ASPA 1017 +#define OBJ_id_ct_ASPA OBJ_id_smime_ct,49L + #define SN_id_smime_aa_receiptRequest "id-smime-aa-receiptRequest" #define NID_id_smime_aa_receiptRequest 212 #define OBJ_id_smime_aa_receiptRequest OBJ_id_smime_aa,1L @@ -1518,6 +1522,11 @@ #define NID_proxyCertInfo 663 #define OBJ_proxyCertInfo OBJ_id_pe,14L +#define SN_tlsfeature "tlsfeature" +#define LN_tlsfeature "TLS Feature" +#define NID_tlsfeature 1016 +#define OBJ_tlsfeature OBJ_id_pe,24L + #define SN_sbgp_ipAddrBlockv2 "sbgp-ipAddrBlockv2" #define NID_sbgp_ipAddrBlockv2 1006 #define OBJ_sbgp_ipAddrBlockv2 OBJ_id_pe,28L @@ -4221,6 +4230,26 @@ #define SN_dh_cofactor_kdf "dh-cofactor-kdf" #define NID_dh_cofactor_kdf 991 +#define SN_ct_precert_scts "ct_precert_scts" +#define LN_ct_precert_scts "CT Precertificate SCTs" +#define NID_ct_precert_scts 1018 +#define OBJ_ct_precert_scts 1L,3L,6L,1L,4L,1L,11129L,2L,4L,2L + +#define SN_ct_precert_poison "ct_precert_poison" +#define LN_ct_precert_poison "CT Precertificate Poison" +#define NID_ct_precert_poison 1019 +#define OBJ_ct_precert_poison 1L,3L,6L,1L,4L,1L,11129L,2L,4L,3L + +#define SN_ct_precert_signer "ct_precert_signer" +#define LN_ct_precert_signer "CT Precertificate Signer" +#define NID_ct_precert_signer 1020 +#define OBJ_ct_precert_signer 1L,3L,6L,1L,4L,1L,11129L,2L,4L,4L + +#define SN_ct_cert_scts "ct_cert_scts" +#define LN_ct_cert_scts "CT Certificate SCTs" +#define NID_ct_cert_scts 1021 +#define OBJ_ct_cert_scts 1L,3L,6L,1L,4L,1L,11129L,2L,4L,5L + #define SN_teletrust "teletrust" #define NID_teletrust 920 #define OBJ_teletrust OBJ_identified_organization,36L diff --git a/include/openssl/objects.h b/include/openssl/objects.h index c40991b..918928e 100644 --- a/include/openssl/objects.h +++ b/include/openssl/objects.h @@ -1,4 +1,4 @@ -/* $OpenBSD: objects.h,v 1.12 2017/01/21 04:53:22 jsing Exp $ */ +/* $OpenBSD: objects.h,v 1.17 2022/01/14 08:56:00 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -1010,108 +1010,33 @@ int OBJ_txt2nid(const char *s); int OBJ_ln2nid(const char *s); int OBJ_sn2nid(const char *s); int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b); + +#if defined(LIBRESSL_INTERNAL) const void * OBJ_bsearch_(const void *key, const void *base, int num, int size, int (*cmp)(const void *, const void *)); const void * OBJ_bsearch_ex_(const void *key, const void *base, int num, int size, int (*cmp)(const void *, const void *), int flags); - -#ifndef LIBRESSL_INTERNAL - -#define _DECLARE_OBJ_BSEARCH_CMP_FN(scope, type1, type2, nm) \ - static int nm##_cmp_BSEARCH_CMP_FN(const void *, const void *); \ - static int nm##_cmp(type1 const *, type2 const *); \ - scope type2 * OBJ_bsearch_##nm(type1 *key, type2 const *base, int num) - -#define DECLARE_OBJ_BSEARCH_CMP_FN(type1, type2, cmp) \ - _DECLARE_OBJ_BSEARCH_CMP_FN(static, type1, type2, cmp) -#define DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(type1, type2, nm) \ - type2 * OBJ_bsearch_##nm(type1 *key, type2 const *base, int num) - -/* - * Unsolved problem: if a type is actually a pointer type, like - * nid_triple is, then its impossible to get a const where you need - * it. Consider: - * - * typedef int nid_triple[3]; - * const void *a_; - * const nid_triple const *a = a_; - * - * The assignement discards a const because what you really want is: - * - * const int const * const *a = a_; - * - * But if you do that, you lose the fact that a is an array of 3 ints, - * which breaks comparison functions. - * - * Thus we end up having to cast, sadly, or unpack the - * declarations. Or, as I finally did in this case, delcare nid_triple - * to be a struct, which it should have been in the first place. - * - * Ben, August 2008. - * - * Also, strictly speaking not all types need be const, but handling - * the non-constness means a lot of complication, and in practice - * comparison routines do always not touch their arguments. - */ - -#define IMPLEMENT_OBJ_BSEARCH_CMP_FN(type1, type2, nm) \ - static int nm##_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_) \ - { \ - type1 const *a = a_; \ - type2 const *b = b_; \ - return nm##_cmp(a,b); \ - } \ - static type2 *OBJ_bsearch_##nm(type1 *key, type2 const *base, int num) \ - { \ - return (type2 *)OBJ_bsearch_(key, base, num, sizeof(type2), \ - nm##_cmp_BSEARCH_CMP_FN); \ - } \ - extern void dummy_prototype(void) - -#define IMPLEMENT_OBJ_BSEARCH_GLOBAL_CMP_FN(type1, type2, nm) \ - static int nm##_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_) \ - { \ - type1 const *a = a_; \ - type2 const *b = b_; \ - return nm##_cmp(a,b); \ - } \ - type2 *OBJ_bsearch_##nm(type1 *key, type2 const *base, int num) \ - { \ - return (type2 *)OBJ_bsearch_(key, base, num, sizeof(type2), \ - nm##_cmp_BSEARCH_CMP_FN); \ - } \ - extern void dummy_prototype(void) - -#define OBJ_bsearch(type1,key,type2,base,num,cmp) \ - ((type2 *)OBJ_bsearch_(CHECKED_PTR_OF(type1,key),CHECKED_PTR_OF(type2,base), \ - num,sizeof(type2), \ - ((void)CHECKED_PTR_OF(type1,cmp##_type_1), \ - (void)CHECKED_PTR_OF(type2,cmp##_type_2), \ - cmp##_BSEARCH_CMP_FN))) - -#define OBJ_bsearch_ex(type1,key,type2,base,num,cmp,flags) \ - ((type2 *)OBJ_bsearch_ex_(CHECKED_PTR_OF(type1,key),CHECKED_PTR_OF(type2,base), \ - num,sizeof(type2), \ - ((void)CHECKED_PTR_OF(type1,cmp##_type_1), \ - (void)type_2=CHECKED_PTR_OF(type2,cmp##_type_2), \ - cmp##_BSEARCH_CMP_FN)),flags) - -#endif /* !LIBRESSL_INTERNAL */ +#endif int OBJ_new_nid(int num); int OBJ_add_object(const ASN1_OBJECT *obj); int OBJ_create(const char *oid, const char *sn, const char *ln); -void OBJ_cleanup(void ); +void OBJ_cleanup(void); int OBJ_create_objects(BIO *in); +size_t OBJ_length(const ASN1_OBJECT *obj); +const unsigned char *OBJ_get0_data(const ASN1_OBJECT *obj); + int OBJ_find_sigid_algs(int signid, int *pdig_nid, int *ppkey_nid); int OBJ_find_sigid_by_algs(int *psignid, int dig_nid, int pkey_nid); int OBJ_add_sigid(int signid, int dig_id, int pkey_id); void OBJ_sigid_free(void); +#if defined(LIBRESSL_CRYPTO_INTERNAL) extern int obj_cleanup_defer; void check_defer(int nid); +#endif /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes diff --git a/include/openssl/ocsp.h b/include/openssl/ocsp.h index 316fb8e..f869f8a 100644 --- a/include/openssl/ocsp.h +++ b/include/openssl/ocsp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ocsp.h,v 1.16 2018/08/24 20:03:21 tb Exp $ */ +/* $OpenBSD: ocsp.h,v 1.19 2022/01/14 08:32:26 tb Exp $ */ /* Written by Tom Titchener for the OpenSSL * project. */ @@ -73,230 +73,6 @@ extern "C" { #endif -/* Various flags and values */ - -#define OCSP_DEFAULT_NONCE_LENGTH 16 - -#define OCSP_NOCERTS 0x1 -#define OCSP_NOINTERN 0x2 -#define OCSP_NOSIGS 0x4 -#define OCSP_NOCHAIN 0x8 -#define OCSP_NOVERIFY 0x10 -#define OCSP_NOEXPLICIT 0x20 -#define OCSP_NOCASIGN 0x40 -#define OCSP_NODELEGATED 0x80 -#define OCSP_NOCHECKS 0x100 -#define OCSP_TRUSTOTHER 0x200 -#define OCSP_RESPID_KEY 0x400 -#define OCSP_NOTIME 0x800 - -/* CertID ::= SEQUENCE { - * hashAlgorithm AlgorithmIdentifier, - * issuerNameHash OCTET STRING, -- Hash of Issuer's DN - * issuerKeyHash OCTET STRING, -- Hash of Issuers public key (excluding the tag & length fields) - * serialNumber CertificateSerialNumber } - */ -typedef struct ocsp_cert_id_st { - X509_ALGOR *hashAlgorithm; - ASN1_OCTET_STRING *issuerNameHash; - ASN1_OCTET_STRING *issuerKeyHash; - ASN1_INTEGER *serialNumber; -} OCSP_CERTID; - -DECLARE_STACK_OF(OCSP_CERTID) - -/* Request ::= SEQUENCE { - * reqCert CertID, - * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL } - */ -typedef struct ocsp_one_request_st { - OCSP_CERTID *reqCert; - STACK_OF(X509_EXTENSION) *singleRequestExtensions; -} OCSP_ONEREQ; - -DECLARE_STACK_OF(OCSP_ONEREQ) - - -/* TBSRequest ::= SEQUENCE { - * version [0] EXPLICIT Version DEFAULT v1, - * requestorName [1] EXPLICIT GeneralName OPTIONAL, - * requestList SEQUENCE OF Request, - * requestExtensions [2] EXPLICIT Extensions OPTIONAL } - */ -typedef struct ocsp_req_info_st { - ASN1_INTEGER *version; - GENERAL_NAME *requestorName; - STACK_OF(OCSP_ONEREQ) *requestList; - STACK_OF(X509_EXTENSION) *requestExtensions; -} OCSP_REQINFO; - -/* Signature ::= SEQUENCE { - * signatureAlgorithm AlgorithmIdentifier, - * signature BIT STRING, - * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } - */ -typedef struct ocsp_signature_st { - X509_ALGOR *signatureAlgorithm; - ASN1_BIT_STRING *signature; - STACK_OF(X509) *certs; -} OCSP_SIGNATURE; - -/* OCSPRequest ::= SEQUENCE { - * tbsRequest TBSRequest, - * optionalSignature [0] EXPLICIT Signature OPTIONAL } - */ -typedef struct ocsp_request_st { - OCSP_REQINFO *tbsRequest; - OCSP_SIGNATURE *optionalSignature; /* OPTIONAL */ -} OCSP_REQUEST; - -/* OCSPResponseStatus ::= ENUMERATED { - * successful (0), --Response has valid confirmations - * malformedRequest (1), --Illegal confirmation request - * internalError (2), --Internal error in issuer - * tryLater (3), --Try again later - * --(4) is not used - * sigRequired (5), --Must sign the request - * unauthorized (6) --Request unauthorized - * } - */ -#define OCSP_RESPONSE_STATUS_SUCCESSFUL 0 -#define OCSP_RESPONSE_STATUS_MALFORMEDREQUEST 1 -#define OCSP_RESPONSE_STATUS_INTERNALERROR 2 -#define OCSP_RESPONSE_STATUS_TRYLATER 3 -#define OCSP_RESPONSE_STATUS_SIGREQUIRED 5 -#define OCSP_RESPONSE_STATUS_UNAUTHORIZED 6 - -/* ResponseBytes ::= SEQUENCE { - * responseType OBJECT IDENTIFIER, - * response OCTET STRING } - */ -typedef struct ocsp_resp_bytes_st { - ASN1_OBJECT *responseType; - ASN1_OCTET_STRING *response; -} OCSP_RESPBYTES; - -/* OCSPResponse ::= SEQUENCE { - * responseStatus OCSPResponseStatus, - * responseBytes [0] EXPLICIT ResponseBytes OPTIONAL } - */ -struct ocsp_response_st { - ASN1_ENUMERATED *responseStatus; - OCSP_RESPBYTES *responseBytes; -}; - -/* ResponderID ::= CHOICE { - * byName [1] Name, - * byKey [2] KeyHash } - */ -#define V_OCSP_RESPID_NAME 0 -#define V_OCSP_RESPID_KEY 1 -struct ocsp_responder_id_st { - int type; - union { - X509_NAME* byName; - ASN1_OCTET_STRING *byKey; - } value; -}; - -DECLARE_STACK_OF(OCSP_RESPID) -OCSP_RESPID *OCSP_RESPID_new(void); -void OCSP_RESPID_free(OCSP_RESPID *a); -OCSP_RESPID *d2i_OCSP_RESPID(OCSP_RESPID **a, const unsigned char **in, long len); -int i2d_OCSP_RESPID(OCSP_RESPID *a, unsigned char **out); -extern const ASN1_ITEM OCSP_RESPID_it; - -/* KeyHash ::= OCTET STRING --SHA-1 hash of responder's public key - * --(excluding the tag and length fields) - */ - -/* RevokedInfo ::= SEQUENCE { - * revocationTime GeneralizedTime, - * revocationReason [0] EXPLICIT CRLReason OPTIONAL } - */ -typedef struct ocsp_revoked_info_st { - ASN1_GENERALIZEDTIME *revocationTime; - ASN1_ENUMERATED *revocationReason; -} OCSP_REVOKEDINFO; - -/* CertStatus ::= CHOICE { - * good [0] IMPLICIT NULL, - * revoked [1] IMPLICIT RevokedInfo, - * unknown [2] IMPLICIT UnknownInfo } - */ -#define V_OCSP_CERTSTATUS_GOOD 0 -#define V_OCSP_CERTSTATUS_REVOKED 1 -#define V_OCSP_CERTSTATUS_UNKNOWN 2 -typedef struct ocsp_cert_status_st { - int type; - union { - ASN1_NULL *good; - OCSP_REVOKEDINFO *revoked; - ASN1_NULL *unknown; - } value; -} OCSP_CERTSTATUS; - -/* SingleResponse ::= SEQUENCE { - * certID CertID, - * certStatus CertStatus, - * thisUpdate GeneralizedTime, - * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, - * singleExtensions [1] EXPLICIT Extensions OPTIONAL } - */ -typedef struct ocsp_single_response_st { - OCSP_CERTID *certId; - OCSP_CERTSTATUS *certStatus; - ASN1_GENERALIZEDTIME *thisUpdate; - ASN1_GENERALIZEDTIME *nextUpdate; - STACK_OF(X509_EXTENSION) *singleExtensions; -} OCSP_SINGLERESP; - -DECLARE_STACK_OF(OCSP_SINGLERESP) - -/* ResponseData ::= SEQUENCE { - * version [0] EXPLICIT Version DEFAULT v1, - * responderID ResponderID, - * producedAt GeneralizedTime, - * responses SEQUENCE OF SingleResponse, - * responseExtensions [1] EXPLICIT Extensions OPTIONAL } - */ -typedef struct ocsp_response_data_st { - ASN1_INTEGER *version; - OCSP_RESPID *responderId; - ASN1_GENERALIZEDTIME *producedAt; - STACK_OF(OCSP_SINGLERESP) *responses; - STACK_OF(X509_EXTENSION) *responseExtensions; -} OCSP_RESPDATA; - -/* BasicOCSPResponse ::= SEQUENCE { - * tbsResponseData ResponseData, - * signatureAlgorithm AlgorithmIdentifier, - * signature BIT STRING, - * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } - */ - /* Note 1: - The value for "signature" is specified in the OCSP rfc2560 as follows: - "The value for the signature SHALL be computed on the hash of the DER - encoding ResponseData." This means that you must hash the DER-encoded - tbsResponseData, and then run it through a crypto-signing function, which - will (at least w/RSA) do a hash-'n'-private-encrypt operation. This seems - a bit odd, but that's the spec. Also note that the data structures do not - leave anywhere to independently specify the algorithm used for the initial - hash. So, we look at the signature-specification algorithm, and try to do - something intelligent. -- Kathy Weinhold, CertCo */ - /* Note 2: - It seems that the mentioned passage from RFC 2560 (section 4.2.1) is open - for interpretation. I've done tests against another responder, and found - that it doesn't do the double hashing that the RFC seems to say one - should. Therefore, all relevant functions take a flag saying which - variant should be used. -- Richard Levitte, OpenSSL team and CeloCom */ -typedef struct ocsp_basic_response_st { - OCSP_RESPDATA *tbsResponseData; - X509_ALGOR *signatureAlgorithm; - ASN1_BIT_STRING *signature; - STACK_OF(X509) *certs; -} OCSP_BASICRESP; - /* * CRLReason ::= ENUMERATED { * unspecified (0), @@ -318,25 +94,73 @@ typedef struct ocsp_basic_response_st { #define OCSP_REVOKED_STATUS_CERTIFICATEHOLD 6 #define OCSP_REVOKED_STATUS_REMOVEFROMCRL 8 -/* CrlID ::= SEQUENCE { - * crlUrl [0] EXPLICIT IA5String OPTIONAL, - * crlNum [1] EXPLICIT INTEGER OPTIONAL, - * crlTime [2] EXPLICIT GeneralizedTime OPTIONAL } - */ -typedef struct ocsp_crl_id_st { - ASN1_IA5STRING *crlUrl; - ASN1_INTEGER *crlNum; - ASN1_GENERALIZEDTIME *crlTime; -} OCSP_CRLID; -/* ServiceLocator ::= SEQUENCE { - * issuer Name, - * locator AuthorityInfoAccessSyntax OPTIONAL } - */ -typedef struct ocsp_service_locator_st { - X509_NAME* issuer; - STACK_OF(ACCESS_DESCRIPTION) *locator; -} OCSP_SERVICELOC; +/* Various flags and values */ + +#define OCSP_DEFAULT_NONCE_LENGTH 16 + +#define OCSP_NOCERTS 0x1 +#define OCSP_NOINTERN 0x2 +#define OCSP_NOSIGS 0x4 +#define OCSP_NOCHAIN 0x8 +#define OCSP_NOVERIFY 0x10 +#define OCSP_NOEXPLICIT 0x20 +#define OCSP_NOCASIGN 0x40 +#define OCSP_NODELEGATED 0x80 +#define OCSP_NOCHECKS 0x100 +#define OCSP_TRUSTOTHER 0x200 +#define OCSP_RESPID_KEY 0x400 +#define OCSP_NOTIME 0x800 + +typedef struct ocsp_cert_id_st OCSP_CERTID; + +DECLARE_STACK_OF(OCSP_CERTID) + +typedef struct ocsp_one_request_st OCSP_ONEREQ; + +DECLARE_STACK_OF(OCSP_ONEREQ) + +typedef struct ocsp_req_info_st OCSP_REQINFO; +typedef struct ocsp_signature_st OCSP_SIGNATURE; +typedef struct ocsp_request_st OCSP_REQUEST; + +#define OCSP_RESPONSE_STATUS_SUCCESSFUL 0 +#define OCSP_RESPONSE_STATUS_MALFORMEDREQUEST 1 +#define OCSP_RESPONSE_STATUS_INTERNALERROR 2 +#define OCSP_RESPONSE_STATUS_TRYLATER 3 +#define OCSP_RESPONSE_STATUS_SIGREQUIRED 5 +#define OCSP_RESPONSE_STATUS_UNAUTHORIZED 6 + +typedef struct ocsp_resp_bytes_st OCSP_RESPBYTES; + +#define V_OCSP_RESPID_NAME 0 +#define V_OCSP_RESPID_KEY 1 + +DECLARE_STACK_OF(OCSP_RESPID) + +OCSP_RESPID *OCSP_RESPID_new(void); +void OCSP_RESPID_free(OCSP_RESPID *a); +OCSP_RESPID *d2i_OCSP_RESPID(OCSP_RESPID **a, const unsigned char **in, long len); +int i2d_OCSP_RESPID(OCSP_RESPID *a, unsigned char **out); +extern const ASN1_ITEM OCSP_RESPID_it; + +typedef struct ocsp_revoked_info_st OCSP_REVOKEDINFO; + +#define V_OCSP_CERTSTATUS_GOOD 0 +#define V_OCSP_CERTSTATUS_REVOKED 1 +#define V_OCSP_CERTSTATUS_UNKNOWN 2 + +typedef struct ocsp_cert_status_st OCSP_CERTSTATUS; +typedef struct ocsp_single_response_st OCSP_SINGLERESP; + +DECLARE_STACK_OF(OCSP_SINGLERESP) + +typedef struct ocsp_response_data_st OCSP_RESPDATA; + +typedef struct ocsp_basic_response_st OCSP_BASICRESP; + +typedef struct ocsp_crl_id_st OCSP_CRLID; +typedef struct ocsp_service_locator_st OCSP_SERVICELOC; #define PEM_STRING_OCSP_REQUEST "OCSP REQUEST" #define PEM_STRING_OCSP_RESPONSE "OCSP RESPONSE" @@ -357,24 +181,6 @@ typedef struct ocsp_service_locator_st { PEM_ASN1_write_bio((int (*)())i2d_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE,\ bp,(char *)o, NULL,NULL,0,NULL,NULL) -#define OCSP_REQUEST_sign(o,pkey,md) \ - ASN1_item_sign(&OCSP_REQINFO_it, \ - o->optionalSignature->signatureAlgorithm,NULL, \ - o->optionalSignature->signature,o->tbsRequest,pkey,md) - -#define OCSP_BASICRESP_sign(o,pkey,md,d) \ - ASN1_item_sign(&OCSP_RESPDATA_it,o->signatureAlgorithm,NULL, \ - o->signature,o->tbsResponseData,pkey,md) - -#define OCSP_REQUEST_verify(a,r) \ - ASN1_item_verify(&OCSP_REQINFO_it, \ - a->optionalSignature->signatureAlgorithm, \ - a->optionalSignature->signature,a->tbsRequest,r) - -#define OCSP_BASICRESP_verify(a,r,d) \ - ASN1_item_verify(&OCSP_RESPDATA_it, \ - a->signatureAlgorithm,a->signature,a->tbsResponseData,r) - #define ASN1_BIT_STRING_digest(data,type,md,len) \ ASN1_item_digest(&ASN1_BIT_STRING_it,type,data,md,len) @@ -414,8 +220,19 @@ int OCSP_request_sign(OCSP_REQUEST *req, X509 *signer, EVP_PKEY *key, int OCSP_response_status(OCSP_RESPONSE *resp); OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp); +const ASN1_OCTET_STRING *OCSP_resp_get0_signature(const OCSP_BASICRESP *bs); +const X509_ALGOR *OCSP_resp_get0_tbs_sigalg(const OCSP_BASICRESP *bs); +const OCSP_RESPDATA *OCSP_resp_get0_respdata(const OCSP_BASICRESP *bs); +int OCSP_resp_get0_signer(OCSP_BASICRESP *bs, X509 **signer, + STACK_OF(X509) *extra_certs); + int OCSP_resp_count(OCSP_BASICRESP *bs); OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx); +const ASN1_GENERALIZEDTIME *OCSP_resp_get0_produced_at(const OCSP_BASICRESP *bs); +const STACK_OF(X509) *OCSP_resp_get0_certs(const OCSP_BASICRESP *bs); +int OCSP_resp_get0_id(const OCSP_BASICRESP *bs, + const ASN1_OCTET_STRING **pid, const X509_NAME **pname); + int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last); int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason, ASN1_GENERALIZEDTIME **revtime, ASN1_GENERALIZEDTIME **thisupd, diff --git a/include/openssl/opensslfeatures.h b/include/openssl/opensslfeatures.h index ba80520..49a5f15 100644 --- a/include/openssl/opensslfeatures.h +++ b/include/openssl/opensslfeatures.h @@ -84,7 +84,7 @@ /* #define OPENSSL_NO_RC4 */ #define OPENSSL_NO_RC5 /* #define OPENSSL_NO_RDRAND */ -#define OPENSSL_NO_RFC3779 +/* #define OPENSSL_NO_RFC3779 */ /* #define OPENSSL_NO_RMD160 */ /* #define OPENSSL_NO_RSA */ /* #define OPENSSL_NO_SCRYPT */ diff --git a/include/openssl/opensslv.h b/include/openssl/opensslv.h index e06b97e..1cafae6 100644 --- a/include/openssl/opensslv.h +++ b/include/openssl/opensslv.h @@ -1,11 +1,11 @@ -/* $OpenBSD: opensslv.h,v 1.66 2021/09/15 17:14:26 tb Exp $ */ +/* $OpenBSD: opensslv.h,v 1.69 2022/03/15 21:15:08 bcook Exp $ */ #ifndef HEADER_OPENSSLV_H #define HEADER_OPENSSLV_H /* These will change with each release of LibreSSL-portable */ -#define LIBRESSL_VERSION_NUMBER 0x3040200fL +#define LIBRESSL_VERSION_NUMBER 0x3050200fL /* ^ Patch starts here */ -#define LIBRESSL_VERSION_TEXT "LibreSSL 3.4.2" +#define LIBRESSL_VERSION_TEXT "LibreSSL 3.5.2" /* These will never change */ #define OPENSSL_VERSION_NUMBER 0x20000000L diff --git a/include/openssl/ossl_typ.h b/include/openssl/ossl_typ.h index b1a9e0e..f4796ba 100644 --- a/include/openssl/ossl_typ.h +++ b/include/openssl/ossl_typ.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ossl_typ.h,v 1.13 2015/09/30 04:10:07 doug Exp $ */ +/* $OpenBSD: ossl_typ.h,v 1.21 2022/01/14 08:59:30 tb Exp $ */ /* ==================================================================== * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. * @@ -77,6 +77,8 @@ typedef struct asn1_string_st ASN1_STRING; typedef int ASN1_BOOLEAN; typedef int ASN1_NULL; +typedef struct asn1_object_st ASN1_OBJECT; + typedef struct ASN1_ITEM_st ASN1_ITEM; typedef struct asn1_pctx_st ASN1_PCTX; @@ -106,8 +108,12 @@ typedef struct bn_mont_ctx_st BN_MONT_CTX; typedef struct bn_recp_ctx_st BN_RECP_CTX; typedef struct bn_gencb_st BN_GENCB; +typedef struct bio_st BIO; typedef struct buf_mem_st BUF_MEM; +typedef struct comp_ctx_st COMP_CTX; +typedef struct comp_method_st COMP_METHOD; + typedef struct evp_cipher_st EVP_CIPHER; typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX; typedef struct env_md_st EVP_MD; @@ -119,6 +125,10 @@ typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD; typedef struct evp_pkey_method_st EVP_PKEY_METHOD; typedef struct evp_pkey_ctx_st EVP_PKEY_CTX; +typedef struct evp_Encode_Ctx_st EVP_ENCODE_CTX; + +typedef struct hmac_ctx_st HMAC_CTX; + typedef struct dh_st DH; typedef struct dh_method DH_METHOD; @@ -127,6 +137,7 @@ typedef struct dsa_method DSA_METHOD; typedef struct rsa_st RSA; typedef struct rsa_meth_st RSA_METHOD; +typedef struct rsa_pss_params_st RSA_PSS_PARAMS; typedef struct rand_meth_st RAND_METHOD; @@ -143,6 +154,11 @@ typedef struct X509_pubkey_st X509_PUBKEY; typedef struct x509_store_st X509_STORE; typedef struct x509_store_ctx_st X509_STORE_CTX; +typedef struct x509_object_st X509_OBJECT; +typedef struct x509_lookup_st X509_LOOKUP; +typedef struct x509_lookup_method_st X509_LOOKUP_METHOD; +typedef struct X509_VERIFY_PARAM_st X509_VERIFY_PARAM; + typedef struct pkcs8_priv_key_info_st PKCS8_PRIV_KEY_INFO; typedef struct v3_ext_ctx X509V3_CTX; @@ -187,4 +203,10 @@ typedef struct ocsp_req_ctx_st OCSP_REQ_CTX; typedef struct ocsp_response_st OCSP_RESPONSE; typedef struct ocsp_responder_id_st OCSP_RESPID; +typedef struct sct_st SCT; +typedef struct sct_ctx_st SCT_CTX; +typedef struct ctlog_st CTLOG; +typedef struct ctlog_store_st CTLOG_STORE; +typedef struct ct_policy_eval_ctx_st CT_POLICY_EVAL_CTX; + #endif /* def HEADER_OPENSSL_TYPES_H */ diff --git a/include/openssl/pem.h b/include/openssl/pem.h index adc8522..95f1e03 100644 --- a/include/openssl/pem.h +++ b/include/openssl/pem.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pem.h,v 1.19 2018/08/24 19:51:31 tb Exp $ */ +/* $OpenBSD: pem.h,v 1.23 2022/01/14 07:52:24 tb Exp $ */ /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -114,7 +114,6 @@ extern "C" { #define PEM_STRING_X509_OLD "X509 CERTIFICATE" #define PEM_STRING_X509 "CERTIFICATE" -#define PEM_STRING_X509_PAIR "CERTIFICATE PAIR" #define PEM_STRING_X509_TRUSTED "TRUSTED CERTIFICATE" #define PEM_STRING_X509_REQ_OLD "NEW CERTIFICATE REQUEST" #define PEM_STRING_X509_REQ "CERTIFICATE REQUEST" @@ -138,14 +137,6 @@ extern "C" { #define PEM_STRING_PARAMETERS "PARAMETERS" #define PEM_STRING_CMS "CMS" - /* Note that this structure is initialised by PEM_SealInit and cleaned up - by PEM_SealFinal (at least for now) */ -typedef struct PEM_Encode_Seal_st { - EVP_ENCODE_CTX encode; - EVP_MD_CTX md; - EVP_CIPHER_CTX cipher; -} PEM_ENCODE_SEAL_CTX; - /* enc_type is one off */ #define PEM_TYPE_ENCRYPTED 10 #define PEM_TYPE_MIC_ONLY 20 @@ -413,14 +404,6 @@ int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp, STACK_OF(X509_INFO) * PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u); -int PEM_SealInit(PEM_ENCODE_SEAL_CTX *ctx, EVP_CIPHER *type, - EVP_MD *md_type, unsigned char **ek, int *ekl, - unsigned char *iv, EVP_PKEY **pubk, int npubk); -void PEM_SealUpdate(PEM_ENCODE_SEAL_CTX *ctx, unsigned char *out, int *outl, - unsigned char *in, int inl); -int PEM_SealFinal(PEM_ENCODE_SEAL_CTX *ctx, unsigned char *sig, int *sigl, - unsigned char *out, int *outl, EVP_PKEY *priv); - int PEM_SignInit(EVP_MD_CTX *ctx, EVP_MD *type); int PEM_SignUpdate(EVP_MD_CTX *ctx, unsigned char *d, unsigned int cnt); int PEM_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, @@ -435,8 +418,6 @@ DECLARE_PEM_rw(X509, X509) DECLARE_PEM_rw(X509_AUX, X509) -DECLARE_PEM_rw(X509_CERT_PAIR, X509_CERT_PAIR) - DECLARE_PEM_rw(X509_REQ, X509_REQ) DECLARE_PEM_write(X509_REQ_NEW, X509_REQ) @@ -485,6 +466,9 @@ DECLARE_PEM_rw_cb(PrivateKey, EVP_PKEY) DECLARE_PEM_rw(PUBKEY, EVP_PKEY) +int PEM_write_bio_PrivateKey_traditional(BIO *bp, EVP_PKEY *x, + const EVP_CIPHER *enc, unsigned char *kstr, int klen, pem_password_cb *cb, + void *u); int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid, char *kstr, int klen, pem_password_cb *cb, void *u); diff --git a/include/openssl/rsa.h b/include/openssl/rsa.h index 78ac04c..d59fd03 100644 --- a/include/openssl/rsa.h +++ b/include/openssl/rsa.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rsa.h,v 1.51 2019/11/04 12:30:56 jsing Exp $ */ +/* $OpenBSD: rsa.h,v 1.55 2022/01/14 08:34:39 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -80,11 +80,7 @@ extern "C" { #endif -/* Declared already in ossl_typ.h */ -/* typedef struct rsa_st RSA; */ -/* typedef struct rsa_meth_st RSA_METHOD; */ - -typedef struct rsa_pss_params_st { +struct rsa_pss_params_st { X509_ALGOR *hashAlgorithm; X509_ALGOR *maskGenAlgorithm; ASN1_INTEGER *saltLength; @@ -92,7 +88,7 @@ typedef struct rsa_pss_params_st { /* Hash algorithm decoded from maskGenAlgorithm. */ X509_ALGOR *maskHash; -} RSA_PSS_PARAMS; +} /* RSA_PSS_PARAMS */; typedef struct rsa_oaep_params_st { X509_ALGOR *hashFunc; @@ -103,80 +99,6 @@ typedef struct rsa_oaep_params_st { X509_ALGOR *maskHash; } RSA_OAEP_PARAMS; -struct rsa_meth_st { - const char *name; - int (*rsa_pub_enc)(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding); - int (*rsa_pub_dec)(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding); - int (*rsa_priv_enc)(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding); - int (*rsa_priv_dec)(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding); - int (*rsa_mod_exp)(BIGNUM *r0, const BIGNUM *I, RSA *rsa, - BN_CTX *ctx); /* Can be null */ - int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, - const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); /* Can be null */ - int (*init)(RSA *rsa); /* called at new */ - int (*finish)(RSA *rsa); /* called at free */ - int flags; /* RSA_METHOD_FLAG_* things */ - char *app_data; /* may be needed! */ -/* New sign and verify functions: some libraries don't allow arbitrary data - * to be signed/verified: this allows them to be used. Note: for this to work - * the RSA_public_decrypt() and RSA_private_encrypt() should *NOT* be used - * RSA_sign(), RSA_verify() should be used instead. Note: for backwards - * compatibility this functionality is only enabled if the RSA_FLAG_SIGN_VER - * option is set in 'flags'. - */ - int (*rsa_sign)(int type, const unsigned char *m, unsigned int m_length, - unsigned char *sigret, unsigned int *siglen, const RSA *rsa); - int (*rsa_verify)(int dtype, const unsigned char *m, - unsigned int m_length, const unsigned char *sigbuf, - unsigned int siglen, const RSA *rsa); -/* If this callback is NULL, the builtin software RSA key-gen will be used. This - * is for behavioural compatibility whilst the code gets rewired, but one day - * it would be nice to assume there are no such things as "builtin software" - * implementations. */ - int (*rsa_keygen)(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb); -}; - -struct rsa_st { - /* The first parameter is used to pickup errors where - * this is passed instead of aEVP_PKEY, it is set to 0 */ - int pad; - long version; - const RSA_METHOD *meth; - - /* functional reference if 'meth' is ENGINE-provided */ - ENGINE *engine; - BIGNUM *n; - BIGNUM *e; - BIGNUM *d; - BIGNUM *p; - BIGNUM *q; - BIGNUM *dmp1; - BIGNUM *dmq1; - BIGNUM *iqmp; - - /* Parameter restrictions for PSS only keys. */ - RSA_PSS_PARAMS *pss; - - /* be careful using this if the RSA structure is shared */ - CRYPTO_EX_DATA ex_data; - int references; - int flags; - - /* Used to cache montgomery values */ - BN_MONT_CTX *_method_mod_n; - BN_MONT_CTX *_method_mod_p; - BN_MONT_CTX *_method_mod_q; - - /* all BIGNUM values are actually in the following data, if it is not - * NULL */ - BN_BLINDING *blinding; - BN_BLINDING *mt_blinding; -}; - #ifndef OPENSSL_RSA_MAX_MODULUS_BITS # define OPENSSL_RSA_MAX_MODULUS_BITS 16384 #endif @@ -380,18 +302,6 @@ int RSA_print_fp(FILE *fp, const RSA *r, int offset); int RSA_print(BIO *bp, const RSA *r, int offset); #endif -#ifndef OPENSSL_NO_RC4 -int i2d_RSA_NET(const RSA *a, unsigned char **pp, - int (*cb)(char *buf, int len, const char *prompt, int verify), int sgckey); -RSA *d2i_RSA_NET(RSA **a, const unsigned char **pp, long length, - int (*cb)(char *buf, int len, const char *prompt, int verify), int sgckey); - -int i2d_Netscape_RSA(const RSA *a, unsigned char **pp, - int (*cb)(char *buf, int len, const char *prompt, int verify)); -RSA *d2i_Netscape_RSA(RSA **a, const unsigned char **pp, long length, - int (*cb)(char *buf, int len, const char *prompt, int verify)); -#endif - /* The following 2 functions sign and verify a X509_SIG ASN1 object * inside PKCS#1 padded RSA encryption */ int RSA_sign(int type, const unsigned char *m, unsigned int m_length, @@ -470,6 +380,15 @@ void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp); void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q); int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q); +const BIGNUM *RSA_get0_n(const RSA *r); +const BIGNUM *RSA_get0_e(const RSA *r); +const BIGNUM *RSA_get0_d(const RSA *r); +const BIGNUM *RSA_get0_p(const RSA *r); +const BIGNUM *RSA_get0_q(const RSA *r); +const BIGNUM *RSA_get0_dmp1(const RSA *r); +const BIGNUM *RSA_get0_dmq1(const RSA *r); +const BIGNUM *RSA_get0_iqmp(const RSA *r); +const RSA_PSS_PARAMS *RSA_get0_pss_params(const RSA *r); void RSA_clear_flags(RSA *r, int flags); int RSA_test_flags(const RSA *r, int flags); void RSA_set_flags(RSA *r, int flags); diff --git a/include/openssl/safestack.h b/include/openssl/safestack.h index 690912b..e1e7e24 100644 --- a/include/openssl/safestack.h +++ b/include/openssl/safestack.h @@ -1,4 +1,4 @@ -/* $OpenBSD: safestack.h,v 1.18 2019/08/11 14:14:14 jsing Exp $ */ +/* $OpenBSD: safestack.h,v 1.21 2022/01/14 08:59:30 tb Exp $ */ /* ==================================================================== * Copyright (c) 1999 The OpenSSL Project. All rights reserved. * @@ -663,6 +663,28 @@ DECLARE_SPECIAL_STACK_OF(OPENSSL_BLOCK, void) #define sk_CRYPTO_dynlock_sort(st) SKM_sk_sort(CRYPTO_dynlock, (st)) #define sk_CRYPTO_dynlock_is_sorted(st) SKM_sk_is_sorted(CRYPTO_dynlock, (st)) +#define sk_CTLOG_new(cmp) SKM_sk_new(CTLOG, (cmp)) +#define sk_CTLOG_new_null() SKM_sk_new_null(CTLOG) +#define sk_CTLOG_free(st) SKM_sk_free(CTLOG, (st)) +#define sk_CTLOG_num(st) SKM_sk_num(CTLOG, (st)) +#define sk_CTLOG_value(st, i) SKM_sk_value(CTLOG, (st), (i)) +#define sk_CTLOG_set(st, i, val) SKM_sk_set(CTLOG, (st), (i), (val)) +#define sk_CTLOG_zero(st) SKM_sk_zero(CTLOG, (st)) +#define sk_CTLOG_push(st, val) SKM_sk_push(CTLOG, (st), (val)) +#define sk_CTLOG_unshift(st, val) SKM_sk_unshift(CTLOG, (st), (val)) +#define sk_CTLOG_find(st, val) SKM_sk_find(CTLOG, (st), (val)) +#define sk_CTLOG_find_ex(st, val) SKM_sk_find_ex(CTLOG, (st), (val)) +#define sk_CTLOG_delete(st, i) SKM_sk_delete(CTLOG, (st), (i)) +#define sk_CTLOG_delete_ptr(st, ptr) SKM_sk_delete_ptr(CTLOG, (st), (ptr)) +#define sk_CTLOG_insert(st, val, i) SKM_sk_insert(CTLOG, (st), (val), (i)) +#define sk_CTLOG_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CTLOG, (st), (cmp)) +#define sk_CTLOG_dup(st) SKM_sk_dup(CTLOG, st) +#define sk_CTLOG_pop_free(st, free_func) SKM_sk_pop_free(CTLOG, (st), (free_func)) +#define sk_CTLOG_shift(st) SKM_sk_shift(CTLOG, (st)) +#define sk_CTLOG_pop(st) SKM_sk_pop(CTLOG, (st)) +#define sk_CTLOG_sort(st) SKM_sk_sort(CTLOG, (st)) +#define sk_CTLOG_is_sorted(st) SKM_sk_is_sorted(CTLOG, (st)) + #define sk_DIST_POINT_new(cmp) SKM_sk_new(DIST_POINT, (cmp)) #define sk_DIST_POINT_new_null() SKM_sk_new_null(DIST_POINT) #define sk_DIST_POINT_free(st) SKM_sk_free(DIST_POINT, (st)) @@ -1279,6 +1301,28 @@ DECLARE_SPECIAL_STACK_OF(OPENSSL_BLOCK, void) #define sk_POLICY_MAPPING_sort(st) SKM_sk_sort(POLICY_MAPPING, (st)) #define sk_POLICY_MAPPING_is_sorted(st) SKM_sk_is_sorted(POLICY_MAPPING, (st)) +#define sk_SCT_new(cmp) SKM_sk_new(SCT, (cmp)) +#define sk_SCT_new_null() SKM_sk_new_null(SCT) +#define sk_SCT_free(st) SKM_sk_free(SCT, (st)) +#define sk_SCT_num(st) SKM_sk_num(SCT, (st)) +#define sk_SCT_value(st, i) SKM_sk_value(SCT, (st), (i)) +#define sk_SCT_set(st, i, val) SKM_sk_set(SCT, (st), (i), (val)) +#define sk_SCT_zero(st) SKM_sk_zero(SCT, (st)) +#define sk_SCT_push(st, val) SKM_sk_push(SCT, (st), (val)) +#define sk_SCT_unshift(st, val) SKM_sk_unshift(SCT, (st), (val)) +#define sk_SCT_find(st, val) SKM_sk_find(SCT, (st), (val)) +#define sk_SCT_find_ex(st, val) SKM_sk_find_ex(SCT, (st), (val)) +#define sk_SCT_delete(st, i) SKM_sk_delete(SCT, (st), (i)) +#define sk_SCT_delete_ptr(st, ptr) SKM_sk_delete_ptr(SCT, (st), (ptr)) +#define sk_SCT_insert(st, val, i) SKM_sk_insert(SCT, (st), (val), (i)) +#define sk_SCT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SCT, (st), (cmp)) +#define sk_SCT_dup(st) SKM_sk_dup(SCT, st) +#define sk_SCT_pop_free(st, free_func) SKM_sk_pop_free(SCT, (st), (free_func)) +#define sk_SCT_shift(st) SKM_sk_shift(SCT, (st)) +#define sk_SCT_pop(st) SKM_sk_pop(SCT, (st)) +#define sk_SCT_sort(st) SKM_sk_sort(SCT, (st)) +#define sk_SCT_is_sorted(st) SKM_sk_is_sorted(SCT, (st)) + #define sk_SRTP_PROTECTION_PROFILE_new(cmp) SKM_sk_new(SRTP_PROTECTION_PROFILE, (cmp)) #define sk_SRTP_PROTECTION_PROFILE_new_null() SKM_sk_new_null(SRTP_PROTECTION_PROFILE) #define sk_SRTP_PROTECTION_PROFILE_free(st) SKM_sk_free(SRTP_PROTECTION_PROFILE, (st)) diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index 2c208b0..e313268 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl.h,v 1.209 2021/09/14 23:07:18 inoguchi Exp $ */ +/* $OpenBSD: ssl.h,v 1.215 2021/11/01 08:14:36 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -357,9 +357,6 @@ extern "C" { * in SSL_CTX. */ typedef struct ssl_st *ssl_crock_st; -#if defined(LIBRESSL_INTERNAL) -typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT; -#endif typedef struct ssl_method_st SSL_METHOD; typedef struct ssl_cipher_st SSL_CIPHER; typedef struct ssl_session_st SSL_SESSION; @@ -508,6 +505,14 @@ void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)); #define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg)) #define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg)) +typedef void (*SSL_CTX_keylog_cb_func)(const SSL *ssl, const char *line); +void SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb); +SSL_CTX_keylog_cb_func SSL_CTX_get_keylog_callback(const SSL_CTX *ctx); +int SSL_set_num_tickets(SSL *s, size_t num_tickets); +size_t SSL_get_num_tickets(const SSL *s); +int SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets); +size_t SSL_CTX_get_num_tickets(const SSL_CTX *ctx); +STACK_OF(X509) *SSL_get0_verified_chain(const SSL *s); #ifndef LIBRESSL_INTERNAL struct ssl_aead_ctx_st; @@ -537,57 +542,10 @@ typedef int (*GEN_SESSION_CB)(const SSL *ssl, unsigned char *id, typedef struct ssl_comp_st SSL_COMP; #ifdef LIBRESSL_INTERNAL - -struct ssl_comp_st { - int id; - const char *name; -}; - DECLARE_STACK_OF(SSL_COMP) struct lhash_st_SSL_SESSION { int dummy; }; - -struct ssl_ctx_internal_st; - -struct ssl_ctx_st { - const SSL_METHOD *method; - - STACK_OF(SSL_CIPHER) *cipher_list; - - struct x509_store_st /* X509_STORE */ *cert_store; - - /* If timeout is not 0, it is the default timeout value set - * when SSL_new() is called. This has been put in to make - * life easier to set things up */ - long session_timeout; - - int references; - - /* Default values to use in SSL structures follow (these are copied by SSL_new) */ - - STACK_OF(X509) *extra_certs; - - int verify_mode; - unsigned int sid_ctx_length; - unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; - - X509_VERIFY_PARAM *param; - - /* - * XXX - * default_passwd_cb used by python and openvpn, need to keep it until we - * add an accessor - */ - /* Default password callback. */ - pem_password_cb *default_passwd_callback; - - /* Default password callback user data. */ - void *default_passwd_callback_userdata; - - struct ssl_ctx_internal_st *internal; -}; - #endif #define SSL_SESS_CACHE_OFF 0x0000 @@ -703,85 +661,6 @@ void SSL_set_psk_use_session_callback(SSL *s, SSL_psk_use_session_cb_func cb); #define SSL_MAC_FLAG_READ_MAC_STREAM 1 #define SSL_MAC_FLAG_WRITE_MAC_STREAM 2 -#if defined(LIBRESSL_INTERNAL) -struct ssl_internal_st; - -struct ssl_st { - /* protocol version - * (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, DTLS1_VERSION) - */ - int version; - - const SSL_METHOD *method; /* SSLv3 */ - - /* There are 2 BIO's even though they are normally both the - * same. This is so data can be read and written to different - * handlers */ - - BIO *rbio; /* used by SSL_read */ - BIO *wbio; /* used by SSL_write */ - BIO *bbio; /* used during session-id reuse to concatenate - * messages */ - int server; /* are we the server side? - mostly used by SSL_clear*/ - - struct ssl3_state_st *s3; /* SSLv3 variables */ - struct dtls1_state_st *d1; /* DTLSv1 variables */ - - X509_VERIFY_PARAM *param; - - /* crypto */ - STACK_OF(SSL_CIPHER) *cipher_list; - - /* This is used to hold the server certificate used */ - struct cert_st /* CERT */ *cert; - - /* the session_id_context is used to ensure sessions are only reused - * in the appropriate context */ - unsigned int sid_ctx_length; - unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; - - /* This can also be in the session once a session is established */ - SSL_SESSION *session; - - /* Used in SSL2 and SSL3 */ - int verify_mode; /* 0 don't care about verify failure. - * 1 fail if verify fails */ - int error; /* error bytes to be written */ - int error_code; /* actual code */ - - SSL_CTX *ctx; - - long verify_result; - - int references; - - int client_version; /* what was passed, used for - * SSLv3/TLS rollback check */ - - unsigned int max_send_fragment; - - char *tlsext_hostname; - - /* certificate status request info */ - /* Status type or -1 if no status type */ - int tlsext_status_type; - - SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */ -#define session_ctx initial_ctx - - /* - * XXX really should be internal, but is - * touched unnaturally by wpa-supplicant - * and freeradius and other perversions - */ - EVP_CIPHER_CTX *enc_read_ctx; /* cryptographic state */ - EVP_MD_CTX *read_hash; /* used for mac generation */ - - struct ssl_internal_st *internal; -}; - -#endif - #ifdef __cplusplus } #endif @@ -1413,6 +1292,9 @@ int SSL_is_server(const SSL *s); int SSL_read(SSL *ssl, void *buf, int num); int SSL_peek(SSL *ssl, void *buf, int num); int SSL_write(SSL *ssl, const void *buf, int num); +int SSL_read_ex(SSL *ssl, void *buf, size_t num, size_t *bytes_read); +int SSL_peek_ex(SSL *ssl, void *buf, size_t num, size_t *bytes_peeked); +int SSL_write_ex(SSL *ssl, const void *buf, size_t num, size_t *bytes_written); #if defined(LIBRESSL_HAS_TLS1_3) || defined(LIBRESSL_INTERNAL) uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx); diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h index cb06a53..547fb86 100644 --- a/include/openssl/tls1.h +++ b/include/openssl/tls1.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls1.h,v 1.49 2021/09/10 14:57:31 tb Exp $ */ +/* $OpenBSD: tls1.h,v 1.51 2022/02/05 18:18:18 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -722,6 +722,12 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb) #define TLS1_3_TXT_CHACHA20_POLY1305_SHA256 "AEAD-CHACHA20-POLY1305-SHA256" #define TLS1_3_TXT_AES_128_CCM_SHA256 "AEAD-AES128-CCM-SHA256" #define TLS1_3_TXT_AES_128_CCM_8_SHA256 "AEAD-AES128-CCM-8-SHA256" + +#define TLS1_3_RFC_AES_128_GCM_SHA256 "TLS_AES_128_GCM_SHA256" +#define TLS1_3_RFC_AES_256_GCM_SHA384 "TLS_AES_256_GCM_SHA384" +#define TLS1_3_RFC_CHACHA20_POLY1305_SHA256 "TLS_CHACHA20_POLY1305_SHA256" +#define TLS1_3_RFC_AES_128_CCM_SHA256 "TLS_AES_128_CCM_SHA256" +#define TLS1_3_RFC_AES_128_CCM_8_SHA256 "TLS_AES_128_CCM_8_SHA256" #endif #define TLS_CT_RSA_SIGN 1 @@ -761,14 +767,6 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb) #define TLS_MD_MASTER_SECRET_CONST "master secret" #define TLS_MD_MASTER_SECRET_CONST_SIZE 13 -#if defined(LIBRESSL_INTERNAL) -/* TLS Session Ticket extension struct. */ -struct tls_session_ticket_ext_st { - unsigned short length; - void *data; -}; -#endif - #ifdef __cplusplus } #endif diff --git a/include/openssl/x509.h b/include/openssl/x509.h index bb675bd..05872e1 100644 --- a/include/openssl/x509.h +++ b/include/openssl/x509.h @@ -1,4 +1,4 @@ -/* $OpenBSD: x509.h,v 1.76 2021/09/02 12:41:44 job Exp $ */ +/* $OpenBSD: x509.h,v 1.89 2022/01/10 14:13:03 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -140,175 +140,43 @@ extern "C" { #define X509v3_KU_DECIPHER_ONLY 0x8000 #define X509v3_KU_UNDEF 0xffff -typedef struct X509_objects_st - { - int nid; - int (*a2i)(void); - int (*i2a)(void); - } X509_OBJECTS; - -struct X509_algor_st - { +struct X509_algor_st { ASN1_OBJECT *algorithm; ASN1_TYPE *parameter; - } /* X509_ALGOR */; - +} /* X509_ALGOR */; typedef STACK_OF(X509_ALGOR) X509_ALGORS; -typedef struct X509_val_st - { +typedef struct X509_val_st { ASN1_TIME *notBefore; ASN1_TIME *notAfter; - } X509_VAL; +} X509_VAL; -struct X509_pubkey_st - { - X509_ALGOR *algor; - ASN1_BIT_STRING *public_key; - EVP_PKEY *pkey; - }; +typedef struct X509_sig_st X509_SIG; -typedef struct X509_sig_st - { - X509_ALGOR *algor; - ASN1_OCTET_STRING *digest; - } X509_SIG; - -typedef struct X509_name_entry_st - { - ASN1_OBJECT *object; - ASN1_STRING *value; - int set; - int size; /* temp variable */ - } X509_NAME_ENTRY; +typedef struct X509_name_entry_st X509_NAME_ENTRY; DECLARE_STACK_OF(X509_NAME_ENTRY) -/* we always keep X509_NAMEs in 2 forms. */ -struct X509_name_st - { - STACK_OF(X509_NAME_ENTRY) *entries; - int modified; /* true if 'bytes' needs to be built */ -#ifndef OPENSSL_NO_BUFFER - BUF_MEM *bytes; -#else - char *bytes; -#endif -/* unsigned long hash; Keep the hash around for lookups */ - unsigned char *canon_enc; - int canon_enclen; - } /* X509_NAME */; - DECLARE_STACK_OF(X509_NAME) -#define X509_EX_V_NETSCAPE_HACK 0x8000 -#define X509_EX_V_INIT 0x0001 -typedef struct X509_extension_st - { - ASN1_OBJECT *object; - ASN1_BOOLEAN critical; - ASN1_OCTET_STRING *value; - } X509_EXTENSION; +typedef struct X509_extension_st X509_EXTENSION; typedef STACK_OF(X509_EXTENSION) X509_EXTENSIONS; DECLARE_STACK_OF(X509_EXTENSION) -/* a sequence of these are used */ -typedef struct x509_attributes_st - { - ASN1_OBJECT *object; - int single; /* 0 for a set, 1 for a single item (which is wrong) */ - union { - char *ptr; -/* 0 */ STACK_OF(ASN1_TYPE) *set; -/* 1 */ ASN1_TYPE *single; - } value; - } X509_ATTRIBUTE; +typedef struct x509_attributes_st X509_ATTRIBUTE; DECLARE_STACK_OF(X509_ATTRIBUTE) +typedef struct X509_req_info_st X509_REQ_INFO; -typedef struct X509_req_info_st - { - ASN1_ENCODING enc; - ASN1_INTEGER *version; - X509_NAME *subject; - X509_PUBKEY *pubkey; - /* d=2 hl=2 l= 0 cons: cont: 00 */ - STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */ - } X509_REQ_INFO; +typedef struct X509_req_st X509_REQ; -typedef struct X509_req_st - { - X509_REQ_INFO *req_info; - X509_ALGOR *sig_alg; - ASN1_BIT_STRING *signature; - int references; - } X509_REQ; +typedef struct x509_cert_aux_st X509_CERT_AUX; -typedef struct x509_cinf_st - { - ASN1_INTEGER *version; /* [ 0 ] default of v1 */ - ASN1_INTEGER *serialNumber; - X509_ALGOR *signature; - X509_NAME *issuer; - X509_VAL *validity; - X509_NAME *subject; - X509_PUBKEY *key; - ASN1_BIT_STRING *issuerUID; /* [ 1 ] optional in v2 */ - ASN1_BIT_STRING *subjectUID; /* [ 2 ] optional in v2 */ - STACK_OF(X509_EXTENSION) *extensions; /* [ 3 ] optional in v3 */ - ASN1_ENCODING enc; - } X509_CINF; - -/* This stuff is certificate "auxiliary info" - * it contains details which are useful in certificate - * stores and databases. When used this is tagged onto - * the end of the certificate itself - */ - -typedef struct x509_cert_aux_st - { - STACK_OF(ASN1_OBJECT) *trust; /* trusted uses */ - STACK_OF(ASN1_OBJECT) *reject; /* rejected uses */ - ASN1_UTF8STRING *alias; /* "friendly name" */ - ASN1_OCTET_STRING *keyid; /* key id of private key */ - STACK_OF(X509_ALGOR) *other; /* other unspecified info */ - } X509_CERT_AUX; - -struct x509_st - { - X509_CINF *cert_info; - X509_ALGOR *sig_alg; - ASN1_BIT_STRING *signature; - int valid; - int references; - char *name; - CRYPTO_EX_DATA ex_data; - /* These contain copies of various extension values */ - long ex_pathlen; - long ex_pcpathlen; - unsigned long ex_flags; - unsigned long ex_kusage; - unsigned long ex_xkusage; - unsigned long ex_nscert; - ASN1_OCTET_STRING *skid; - AUTHORITY_KEYID *akid; - X509_POLICY_CACHE *policy_cache; - STACK_OF(DIST_POINT) *crldp; - STACK_OF(GENERAL_NAME) *altname; - NAME_CONSTRAINTS *nc; -#ifndef OPENSSL_NO_RFC3779 - STACK_OF(IPAddressFamily) *rfc3779_addr; - struct ASIdentifiers_st *rfc3779_asid; -#endif -#ifndef OPENSSL_NO_SHA - unsigned char sha1_hash[SHA_DIGEST_LENGTH]; -#endif - X509_CERT_AUX *aux; - } /* X509 */; +typedef struct x509_cinf_st X509_CINF; DECLARE_STACK_OF(X509) @@ -325,13 +193,9 @@ typedef struct x509_trust_st { DECLARE_STACK_OF(X509_TRUST) -typedef struct x509_cert_pair_st { - X509 *forward; - X509 *reverse; -} X509_CERT_PAIR; - /* standard trust ids */ +/* OpenSSL changed this to 0 */ #define X509_TRUST_DEFAULT -1 /* Only valid in purpose settings */ #define X509_TRUST_COMPAT 1 @@ -432,61 +296,13 @@ typedef struct x509_cert_pair_st { XN_FLAG_FN_LN | \ XN_FLAG_FN_ALIGN) -struct x509_revoked_st - { - ASN1_INTEGER *serialNumber; - ASN1_TIME *revocationDate; - STACK_OF(X509_EXTENSION) /* optional */ *extensions; - /* Set up if indirect CRL */ - STACK_OF(GENERAL_NAME) *issuer; - /* Revocation reason */ - int reason; - int sequence; /* load sequence */ - }; - DECLARE_STACK_OF(X509_REVOKED) -typedef struct X509_crl_info_st - { - ASN1_INTEGER *version; - X509_ALGOR *sig_alg; - X509_NAME *issuer; - ASN1_TIME *lastUpdate; - ASN1_TIME *nextUpdate; - STACK_OF(X509_REVOKED) *revoked; - STACK_OF(X509_EXTENSION) /* [0] */ *extensions; - ASN1_ENCODING enc; - } X509_CRL_INFO; - -struct X509_crl_st - { - /* actual signature */ - X509_CRL_INFO *crl; - X509_ALGOR *sig_alg; - ASN1_BIT_STRING *signature; - int references; - int flags; - /* Copies of various extensions */ - AUTHORITY_KEYID *akid; - ISSUING_DIST_POINT *idp; - /* Convenient breakdown of IDP */ - int idp_flags; - int idp_reasons; - /* CRL and base CRL numbers for delta processing */ - ASN1_INTEGER *crl_number; - ASN1_INTEGER *base_crl_number; -#ifndef OPENSSL_NO_SHA - unsigned char sha1_hash[SHA_DIGEST_LENGTH]; -#endif - STACK_OF(GENERAL_NAMES) *issuers; - const X509_CRL_METHOD *meth; - void *meth_data; - } /* X509_CRL */; +typedef struct X509_crl_info_st X509_CRL_INFO; DECLARE_STACK_OF(X509_CRL) -typedef struct private_key_st - { +typedef struct private_key_st { int version; /* The PKCS#8 data types */ X509_ALGOR *enc_algor; @@ -504,11 +320,10 @@ typedef struct private_key_st EVP_CIPHER_INFO cipher; int references; - } X509_PKEY; +} X509_PKEY; #ifndef OPENSSL_NO_EVP -typedef struct X509_info_st - { +typedef struct X509_info_st { X509 *x509; X509_CRL *crl; X509_PKEY *x_pkey; @@ -518,7 +333,7 @@ typedef struct X509_info_st char *enc_data; int references; - } X509_INFO; +} X509_INFO; DECLARE_STACK_OF(X509_INFO) #endif @@ -527,64 +342,46 @@ DECLARE_STACK_OF(X509_INFO) * Pat Richard and are used to manipulate * Netscapes spki structures - useful if you are writing a CA web page */ -typedef struct Netscape_spkac_st - { +typedef struct Netscape_spkac_st { X509_PUBKEY *pubkey; ASN1_IA5STRING *challenge; /* challenge sent in atlas >= PR2 */ - } NETSCAPE_SPKAC; +} NETSCAPE_SPKAC; -typedef struct Netscape_spki_st - { +typedef struct Netscape_spki_st { NETSCAPE_SPKAC *spkac; /* signed public key and challenge */ X509_ALGOR *sig_algor; ASN1_BIT_STRING *signature; - } NETSCAPE_SPKI; +} NETSCAPE_SPKI; /* Netscape certificate sequence structure */ -typedef struct Netscape_certificate_sequence - { +typedef struct Netscape_certificate_sequence { ASN1_OBJECT *type; STACK_OF(X509) *certs; - } NETSCAPE_CERT_SEQUENCE; +} NETSCAPE_CERT_SEQUENCE; -/* Unused (and iv length is wrong) -typedef struct CBCParameter_st - { - unsigned char iv[8]; - } CBC_PARAM; -*/ /* Password based encryption structure */ typedef struct PBEPARAM_st { -ASN1_OCTET_STRING *salt; -ASN1_INTEGER *iter; + ASN1_OCTET_STRING *salt; + ASN1_INTEGER *iter; } PBEPARAM; /* Password based encryption V2 structures */ typedef struct PBE2PARAM_st { -X509_ALGOR *keyfunc; -X509_ALGOR *encryption; + X509_ALGOR *keyfunc; + X509_ALGOR *encryption; } PBE2PARAM; typedef struct PBKDF2PARAM_st { -ASN1_TYPE *salt; /* Usually OCTET STRING but could be anything */ -ASN1_INTEGER *iter; -ASN1_INTEGER *keylength; -X509_ALGOR *prf; + /* Usually OCTET STRING but could be anything */ + ASN1_TYPE *salt; + ASN1_INTEGER *iter; + ASN1_INTEGER *keylength; + X509_ALGOR *prf; } PBKDF2PARAM; - -/* PKCS#8 private key info structure */ - -struct pkcs8_priv_key_info_st { - ASN1_INTEGER *version; - X509_ALGOR *pkeyalg; - ASN1_OCTET_STRING *pkey; - STACK_OF(X509_ATTRIBUTE) *attributes; -}; - #ifdef __cplusplus } #endif @@ -596,9 +393,6 @@ struct pkcs8_priv_key_info_st { extern "C" { #endif -#define X509_EXT_PACK_UNKNOWN 1 -#define X509_EXT_PACK_STRING 2 - #define X509_extract_key(x) X509_get_pubkey(x) /*****/ #define X509_REQ_extract_key(a) X509_REQ_get_pubkey(a) #define X509_name_cmp(a,b) X509_NAME_cmp((a),(b)) @@ -606,6 +400,8 @@ extern "C" { int X509_CRL_up_ref(X509_CRL *x); int X509_CRL_get_signature_nid(const X509_CRL *crl); +int i2d_re_X509_CRL_tbs(X509_CRL *req, unsigned char **pp); + const STACK_OF(X509_EXTENSION) *X509_CRL_get0_extensions(const X509_CRL *crl); long X509_CRL_get_version(const X509_CRL *crl); const ASN1_TIME *X509_CRL_get0_lastUpdate(const X509_CRL *crl); @@ -634,10 +430,7 @@ void X509_CRL_METHOD_free(X509_CRL_METHOD *m); void X509_CRL_set_meth_data(X509_CRL *crl, void *dat); void *X509_CRL_get_meth_data(X509_CRL *crl); -/* This one is only used so that a binary form can output, as in - * i2d_X509_NAME(X509_get_X509_PUBKEY(x),&buf) */ -#define X509_get_X509_PUBKEY(x) ((x)->cert_info->key) - +X509_PUBKEY *X509_get_X509_PUBKEY(const X509 *x); const char *X509_verify_cert_error_string(long n); @@ -837,6 +630,11 @@ void X509_SIG_free(X509_SIG *a); X509_SIG *d2i_X509_SIG(X509_SIG **a, const unsigned char **in, long len); int i2d_X509_SIG(X509_SIG *a, unsigned char **out); extern const ASN1_ITEM X509_SIG_it; +void X509_SIG_get0(const X509_SIG *sig, const X509_ALGOR **palg, + const ASN1_OCTET_STRING **pdigest); +void X509_SIG_getm(X509_SIG *sig, X509_ALGOR **palg, + ASN1_OCTET_STRING **pdigest); + X509_REQ_INFO *X509_REQ_INFO_new(void); void X509_REQ_INFO_free(X509_REQ_INFO *a); X509_REQ_INFO *d2i_X509_REQ_INFO(X509_REQ_INFO **a, const unsigned char **in, long len); @@ -895,18 +693,15 @@ X509_CERT_AUX *d2i_X509_CERT_AUX(X509_CERT_AUX **a, const unsigned char **in, lo int i2d_X509_CERT_AUX(X509_CERT_AUX *a, unsigned char **out); extern const ASN1_ITEM X509_CERT_AUX_it; -X509_CERT_PAIR *X509_CERT_PAIR_new(void); -void X509_CERT_PAIR_free(X509_CERT_PAIR *a); -X509_CERT_PAIR *d2i_X509_CERT_PAIR(X509_CERT_PAIR **a, const unsigned char **in, long len); -int i2d_X509_CERT_PAIR(X509_CERT_PAIR *a, unsigned char **out); -extern const ASN1_ITEM X509_CERT_PAIR_it; - int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); int X509_set_ex_data(X509 *r, int idx, void *arg); void *X509_get_ex_data(X509 *r, int idx); int i2d_X509_AUX(X509 *a,unsigned char **pp); X509 * d2i_X509_AUX(X509 **a,const unsigned char **pp,long length); + +int i2d_re_X509_tbs(X509 *x, unsigned char **pp); + void X509_get0_signature(const ASN1_BIT_STRING **psig, const X509_ALGOR **palg, const X509 *x); int X509_get_signature_nid(const X509 *x); @@ -1019,6 +814,8 @@ int X509_REQ_set_subject_name(X509_REQ *req, X509_NAME *name); X509_NAME *X509_REQ_get_subject_name(const X509_REQ *x); int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey); EVP_PKEY * X509_REQ_get_pubkey(X509_REQ *req); +int i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp); +EVP_PKEY * X509_REQ_get0_pubkey(X509_REQ *req); int X509_REQ_extension_nid(int nid); int * X509_REQ_get_extension_nids(void); void X509_REQ_set_extension_nids(int *nids); @@ -1408,6 +1205,7 @@ void ERR_load_X509_strings(void); #define X509_R_LOADING_CERT_DIR 103 #define X509_R_LOADING_DEFAULTS 104 #define X509_R_METHOD_NOT_SUPPORTED 124 +#define X509_R_NO_CERTIFICATE_OR_CRL_FOUND 136 #define X509_R_NO_CERT_SET_FOR_US_TO_VERIFY 105 #define X509_R_PUBLIC_KEY_DECODE_ERROR 125 #define X509_R_PUBLIC_KEY_ENCODE_ERROR 126 diff --git a/include/openssl/x509_verify.h b/include/openssl/x509_verify.h index a097404..d8d2cb0 100644 --- a/include/openssl/x509_verify.h +++ b/include/openssl/x509_verify.h @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_verify.h,v 1.1 2020/09/13 15:06:17 beck Exp $ */ +/* $OpenBSD: x509_verify.h,v 1.2 2021/11/04 23:52:34 beck Exp $ */ /* * Copyright (c) 2020 Bob Beck * @@ -19,6 +19,7 @@ #ifdef LIBRESSL_INTERNAL struct x509_verify_ctx; +struct x509_verify_cert_info; typedef struct x509_verify_ctx X509_VERIFY_CTX; X509_VERIFY_CTX *x509_verify_ctx_new(STACK_OF(X509) *roots); diff --git a/include/openssl/x509_vfy.h b/include/openssl/x509_vfy.h index 57189b9..9a649cb 100644 --- a/include/openssl/x509_vfy.h +++ b/include/openssl/x509_vfy.h @@ -1,25 +1,25 @@ -/* $OpenBSD: x509_vfy.h,v 1.32 2021/02/24 18:01:31 tb Exp $ */ +/* $OpenBSD: x509_vfy.h,v 1.50 2022/01/14 07:53:45 tb Exp $ */ /* 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: @@ -34,10 +34,10 @@ * 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 + * 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 @@ -49,7 +49,7 @@ * 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 @@ -77,197 +77,40 @@ extern "C" { #endif -typedef struct x509_file_st - { - int num_paths; /* number of paths to files or directories */ - int num_alloced; - char **paths; /* the list of paths or directories */ - int *path_type; - } X509_CERT_FILE_CTX; - -/*******************************/ /* -SSL_CTX -> X509_STORE - -> X509_LOOKUP - ->X509_LOOKUP_METHOD - -> X509_LOOKUP - ->X509_LOOKUP_METHOD - -SSL -> X509_STORE_CTX - ->X509_STORE + * SSL_CTX -> X509_STORE + * -> X509_LOOKUP + * ->X509_LOOKUP_METHOD + * -> X509_LOOKUP + * ->X509_LOOKUP_METHOD + * + * SSL -> X509_STORE_CTX + * ->X509_STORE + * + * The X509_STORE holds the tables etc for verification stuff. + * A X509_STORE_CTX is used while validating a single certificate. + * The X509_STORE has X509_LOOKUPs for looking up certs. + * The X509_STORE then calls a function to actually verify the + * certificate chain. + */ -The X509_STORE holds the tables etc for verification stuff. -A X509_STORE_CTX is used while validating a single certificate. -The X509_STORE has X509_LOOKUPs for looking up certs. -The X509_STORE then calls a function to actually verify the -certificate chain. -*/ +typedef enum { + X509_LU_NONE, + X509_LU_X509, + X509_LU_CRL, +} X509_LOOKUP_TYPE; -#define X509_LU_RETRY -1 -#define X509_LU_FAIL 0 -#define X509_LU_X509 1 -#define X509_LU_CRL 2 -#define X509_LU_PKEY 3 - -typedef struct x509_object_st - { - /* one of the above types */ - int type; - union { - char *ptr; - X509 *x509; - X509_CRL *crl; - EVP_PKEY *pkey; - } data; - } X509_OBJECT; - -typedef struct x509_lookup_st X509_LOOKUP; DECLARE_STACK_OF(X509_LOOKUP) DECLARE_STACK_OF(X509_OBJECT) - -/* This is a static that defines the function interface */ -typedef struct x509_lookup_method_st - { - const char *name; - int (*new_item)(X509_LOOKUP *ctx); - void (*free)(X509_LOOKUP *ctx); - int (*init)(X509_LOOKUP *ctx); - int (*shutdown)(X509_LOOKUP *ctx); - int (*ctrl)(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, - char **ret); - int (*get_by_subject)(X509_LOOKUP *ctx, int type, X509_NAME *name, - X509_OBJECT *ret); - int (*get_by_issuer_serial)(X509_LOOKUP *ctx, int type, X509_NAME *name, - ASN1_INTEGER *serial,X509_OBJECT *ret); - int (*get_by_fingerprint)(X509_LOOKUP *ctx, int type, - const unsigned char *bytes, int len, X509_OBJECT *ret); - int (*get_by_alias)(X509_LOOKUP *ctx, int type, const char *str, - int len, X509_OBJECT *ret); - } X509_LOOKUP_METHOD; - -typedef struct X509_VERIFY_PARAM_ID_st X509_VERIFY_PARAM_ID; - -/* This structure hold all parameters associated with a verify operation - * by including an X509_VERIFY_PARAM structure in related structures the - * parameters used can be customized - */ - -typedef struct X509_VERIFY_PARAM_st - { - char *name; - time_t check_time; /* Time to use */ - unsigned long inh_flags; /* Inheritance flags */ - unsigned long flags; /* Various verify flags */ - int purpose; /* purpose to check untrusted certificates */ - int trust; /* trust setting to check */ - int depth; /* Verify depth */ - STACK_OF(ASN1_OBJECT) *policies; /* Permissible policies */ - X509_VERIFY_PARAM_ID *id; /* opaque ID data */ -} X509_VERIFY_PARAM; - DECLARE_STACK_OF(X509_VERIFY_PARAM) -/* This is used to hold everything. It is used for all certificate - * validation. Once we have a certificate chain, the 'verify' - * function is then called to actually check the cert chain. */ -struct x509_store_st - { - /* The following is a cache of trusted certs */ - int cache; /* if true, stash any hits */ - STACK_OF(X509_OBJECT) *objs; /* Cache of all objects */ +/* unused in OpenSSL */ +typedef struct X509_VERIFY_PARAM_ID_st X509_VERIFY_PARAM_ID; - /* These are external lookup methods */ - STACK_OF(X509_LOOKUP) *get_cert_methods; - - X509_VERIFY_PARAM *param; - - /* Callbacks for various operations */ - int (*verify)(X509_STORE_CTX *ctx); /* called to verify a certificate */ - int (*verify_cb)(int ok,X509_STORE_CTX *ctx); /* error callback */ - int (*get_issuer)(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); /* get issuers cert from ctx */ - int (*check_issued)(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); /* check issued */ - int (*check_revocation)(X509_STORE_CTX *ctx); /* Check revocation status of chain */ - int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); /* retrieve CRL */ - int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */ - int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */ - STACK_OF(X509) * (*lookup_certs)(X509_STORE_CTX *ctx, X509_NAME *nm); - STACK_OF(X509_CRL) * (*lookup_crls)(X509_STORE_CTX *ctx, X509_NAME *nm); - int (*cleanup)(X509_STORE_CTX *ctx); - - CRYPTO_EX_DATA ex_data; - int references; - } /* X509_STORE */; int X509_STORE_set_depth(X509_STORE *store, int depth); -#define X509_STORE_set_verify_cb_func(ctx,func) ((ctx)->verify_cb=(func)) -#define X509_STORE_set_verify_func(ctx,func) ((ctx)->verify=(func)) - -/* This is the functions plus an instance of the local variables. */ -struct x509_lookup_st - { - int init; /* have we been started */ - int skip; /* don't use us. */ - X509_LOOKUP_METHOD *method; /* the functions */ - char *method_data; /* method data */ - - X509_STORE *store_ctx; /* who owns us */ - } /* X509_LOOKUP */; - -/* This is a used when verifying cert chains. Since the - * gathering of the cert chain can take some time (and have to be - * 'retried', this needs to be kept and passed around. */ -struct x509_store_ctx_st /* X509_STORE_CTX */ - { - X509_STORE *ctx; - int current_method; /* used when looking up certs */ - - /* The following are set by the caller */ - X509 *cert; /* The cert to check */ - STACK_OF(X509) *untrusted; /* chain of X509s - untrusted - passed in */ - STACK_OF(X509_CRL) *crls; /* set of CRLs passed in */ - - X509_VERIFY_PARAM *param; - void *other_ctx; /* Other info for use with get_issuer() */ - - /* Callbacks for various operations */ - int (*verify)(X509_STORE_CTX *ctx); /* called to verify a certificate */ - int (*verify_cb)(int ok,X509_STORE_CTX *ctx); /* error callback */ - int (*get_issuer)(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); /* get issuers cert from ctx */ - int (*check_issued)(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); /* check issued */ - int (*check_revocation)(X509_STORE_CTX *ctx); /* Check revocation status of chain */ - int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); /* retrieve CRL */ - int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */ - int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */ - int (*check_policy)(X509_STORE_CTX *ctx); - STACK_OF(X509) * (*lookup_certs)(X509_STORE_CTX *ctx, X509_NAME *nm); - STACK_OF(X509_CRL) * (*lookup_crls)(X509_STORE_CTX *ctx, X509_NAME *nm); - int (*cleanup)(X509_STORE_CTX *ctx); - - /* The following is built up */ - int valid; /* if 0, rebuild chain */ - int last_untrusted; /* XXX: number of untrusted certs in chain!!! */ - STACK_OF(X509) *chain; /* chain of X509s - built up and trusted */ - X509_POLICY_TREE *tree; /* Valid policy tree */ - - int explicit_policy; /* Require explicit policy value */ - - /* When something goes wrong, this is why */ - int error_depth; - int error; - X509 *current_cert; - X509 *current_issuer; /* cert currently being tested as valid issuer */ - X509_CRL *current_crl; /* current CRL */ - - int current_crl_score; /* score of current CRL */ - unsigned int current_reasons; /* Reason mask */ - - X509_STORE_CTX *parent; /* For CRL path validation: parent context */ - - CRYPTO_EX_DATA ex_data; - } /* X509_STORE_CTX */; - void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth); #define X509_STORE_CTX_set_app_data(ctx,data) \ @@ -422,21 +265,23 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth); | X509_V_FLAG_INHIBIT_ANY \ | X509_V_FLAG_INHIBIT_MAP) -int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type, +X509_OBJECT *X509_OBJECT_new(void); +void X509_OBJECT_free(X509_OBJECT *a); +int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, X509_NAME *name); -X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,int type,X509_NAME *name); +X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, + X509_LOOKUP_TYPE type, X509_NAME *name); X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x); int X509_OBJECT_up_ref_count(X509_OBJECT *a); -int X509_OBJECT_get_type(const X509_OBJECT *a); -void X509_OBJECT_free_contents(X509_OBJECT *a); +X509_LOOKUP_TYPE X509_OBJECT_get_type(const X509_OBJECT *a); X509 *X509_OBJECT_get0_X509(const X509_OBJECT *xo); X509_CRL *X509_OBJECT_get0_X509_CRL(X509_OBJECT *xo); X509_STORE *X509_STORE_new(void); void X509_STORE_free(X509_STORE *v); int X509_STORE_up_ref(X509_STORE *x); -STACK_OF(X509)* X509_STORE_get1_certs(X509_STORE_CTX *st, X509_NAME *nm); -STACK_OF(X509_CRL)* X509_STORE_get1_crls(X509_STORE_CTX *st, X509_NAME *nm); +STACK_OF(X509) *X509_STORE_get1_certs(X509_STORE_CTX *st, X509_NAME *nm); +STACK_OF(X509_CRL) *X509_STORE_get1_crls(X509_STORE_CTX *st, X509_NAME *nm); STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *xs); void *X509_STORE_get_ex_data(X509_STORE *xs, int idx); int X509_STORE_set_ex_data(X509_STORE *xs, int idx, void *data); @@ -451,8 +296,14 @@ int X509_STORE_set_trust(X509_STORE *ctx, int trust); int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *pm); X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx); +typedef int (*X509_STORE_CTX_verify_cb)(int, X509_STORE_CTX *); + +X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(X509_STORE *); + void X509_STORE_set_verify_cb(X509_STORE *ctx, - int (*verify_cb)(int, X509_STORE_CTX *)); + int (*verify_cb)(int, X509_STORE_CTX *)); +#define X509_STORE_set_verify_cb_func(ctx, func) \ + X509_STORE_set_verify_cb((ctx), (func)) X509_STORE_CTX *X509_STORE_CTX_new(void); @@ -479,8 +330,11 @@ X509_LOOKUP_METHOD *X509_LOOKUP_mem(void); int X509_STORE_add_cert(X509_STORE *ctx, X509 *x); int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x); -int X509_STORE_get_by_subject(X509_STORE_CTX *vs,int type,X509_NAME *name, - X509_OBJECT *ret); +int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type, + X509_NAME *name, X509_OBJECT *ret); +#define X509_STORE_get_by_subject X509_STORE_CTX_get_by_subject +X509_OBJECT *X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs, + X509_LOOKUP_TYPE type, X509_NAME *name); int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **ret); @@ -493,17 +347,17 @@ int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type); X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method); void X509_LOOKUP_free(X509_LOOKUP *ctx); int X509_LOOKUP_init(X509_LOOKUP *ctx); -int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name, - X509_OBJECT *ret); -int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name, - ASN1_INTEGER *serial, X509_OBJECT *ret); -int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type, - const unsigned char *bytes, int len, X509_OBJECT *ret); -int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, const char *str, - int len, X509_OBJECT *ret); +int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + X509_NAME *name, X509_OBJECT *ret); +int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + X509_NAME *name, ASN1_INTEGER *serial, X509_OBJECT *ret); +int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + const unsigned char *bytes, int len, X509_OBJECT *ret); +int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + const char *str, int len, X509_OBJECT *ret); int X509_LOOKUP_shutdown(X509_LOOKUP *ctx); -int X509_STORE_load_locations (X509_STORE *ctx, +int X509_STORE_load_locations(X509_STORE *ctx, const char *file, const char *dir); int X509_STORE_load_mem(X509_STORE *ctx, void *buf, int len); int X509_STORE_set_default_paths(X509_STORE *ctx); @@ -515,7 +369,9 @@ void * X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx,int idx); int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx); void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx,int s); int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set_error_depth(X509_STORE_CTX *ctx, int depth); X509 * X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set_current_cert(X509_STORE_CTX *ctx, X509 *x); X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx); X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx); X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx); @@ -531,11 +387,24 @@ int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags); void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, time_t t); +void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk); +int (*X509_STORE_CTX_get_verify(X509_STORE_CTX *ctx))(X509_STORE_CTX *); +void X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx, + int (*verify)(X509_STORE_CTX *)); +int (*X509_STORE_CTX_get_verify_cb(X509_STORE_CTX *ctx))(int, X509_STORE_CTX *); void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, int (*verify_cb)(int, X509_STORE_CTX *)); - + +typedef int (*X509_STORE_CTX_verify_fn)(X509_STORE_CTX *); + +void X509_STORE_set_verify(X509_STORE *ctx, X509_STORE_CTX_verify_fn verify); +X509_STORE_CTX_verify_fn X509_STORE_get_verify(X509_STORE *ctx); +#define X509_STORE_set_verify_func(ctx, func) \ + X509_STORE_set_verify((ctx), (func)) + X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx); int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx); +int X509_STORE_CTX_get_num_untrusted(X509_STORE_CTX *ctx); X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx); void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param); @@ -547,7 +416,7 @@ X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void); void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param); int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *to, const X509_VERIFY_PARAM *from); -int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, +int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, const X509_VERIFY_PARAM *from); int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name); int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags); @@ -560,7 +429,7 @@ void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth); void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t); int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, ASN1_OBJECT *policy); -int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, +int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, STACK_OF(ASN1_OBJECT) *policies); int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param); int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, const char *name, diff --git a/include/openssl/x509v3.h b/include/openssl/x509v3.h index abe9307..c82ecae 100644 --- a/include/openssl/x509v3.h +++ b/include/openssl/x509v3.h @@ -1,4 +1,4 @@ -/* $OpenBSD: x509v3.h,v 1.5 2021/09/02 13:48:39 job Exp $ */ +/* $OpenBSD: x509v3.h,v 1.14 2022/01/14 09:01:36 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -206,8 +206,6 @@ union { } d; } GENERAL_NAME; -typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES; - typedef struct ACCESS_DESCRIPTION_st { ASN1_OBJECT *method; GENERAL_NAME *location; @@ -219,6 +217,9 @@ typedef STACK_OF(ASN1_OBJECT) EXTENDED_KEY_USAGE; DECLARE_STACK_OF(GENERAL_NAME) +typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES; +DECLARE_STACK_OF(GENERAL_NAMES) + DECLARE_STACK_OF(ACCESS_DESCRIPTION) typedef struct DIST_POINT_NAME_st { @@ -446,7 +447,7 @@ struct ISSUING_DIST_POINT_st #define NS_OBJSIGN_CA 0x01 #define NS_ANY_CA (NS_SSL_CA|NS_SMIME_CA|NS_OBJSIGN_CA) -#define XKU_SSL_SERVER 0x1 +#define XKU_SSL_SERVER 0x1 #define XKU_SSL_CLIENT 0x2 #define XKU_SMIME 0x4 #define XKU_CODE_SIGN 0x8 @@ -454,6 +455,7 @@ struct ISSUING_DIST_POINT_st #define XKU_OCSP_SIGN 0x20 #define XKU_TIMESTAMP 0x40 #define XKU_DVCS 0x80 +#define XKU_ANYEKU 0x100 #define X509_PURPOSE_DYNAMIC 0x1 #define X509_PURPOSE_DYNAMIC_NAME 0x2 @@ -770,7 +772,6 @@ int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, int crit char *hex_to_string(const unsigned char *buffer, long len); unsigned char *string_to_hex(const char *str, long *len); -int name_cmp(const char *name, const char *cmp); void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent, int ml); @@ -798,6 +799,9 @@ char *X509_PURPOSE_get0_sname(const X509_PURPOSE *xp); int X509_PURPOSE_get_trust(const X509_PURPOSE *xp); void X509_PURPOSE_cleanup(void); int X509_PURPOSE_get_id(const X509_PURPOSE *); +uint32_t X509_get_extension_flags(X509 *x); +uint32_t X509_get_key_usage(X509 *x); +uint32_t X509_get_extended_key_usage(X509 *x); STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x); STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x); @@ -842,39 +846,40 @@ int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk, void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent); DECLARE_STACK_OF(X509_POLICY_NODE) -#if defined(LIBRESSL_INTERNAL) #ifndef OPENSSL_NO_RFC3779 typedef struct ASRange_st { - ASN1_INTEGER *min, *max; + ASN1_INTEGER *min; + ASN1_INTEGER *max; } ASRange; -# define ASIdOrRange_id 0 -# define ASIdOrRange_range 1 +#define ASIdOrRange_id 0 +#define ASIdOrRange_range 1 typedef struct ASIdOrRange_st { - int type; - union { - ASN1_INTEGER *id; - ASRange *range; - } u; + int type; + union { + ASN1_INTEGER *id; + ASRange *range; + } u; } ASIdOrRange; typedef STACK_OF(ASIdOrRange) ASIdOrRanges; DECLARE_STACK_OF(ASIdOrRange) -# define ASIdentifierChoice_inherit 0 -# define ASIdentifierChoice_asIdsOrRanges 1 +#define ASIdentifierChoice_inherit 0 +#define ASIdentifierChoice_asIdsOrRanges 1 typedef struct ASIdentifierChoice_st { - int type; - union { - ASN1_NULL *inherit; - ASIdOrRanges *asIdsOrRanges; - } u; + int type; + union { + ASN1_NULL *inherit; + ASIdOrRanges *asIdsOrRanges; + } u; } ASIdentifierChoice; typedef struct ASIdentifiers_st { - ASIdentifierChoice *asnum, *rdi; + ASIdentifierChoice *asnum; + ASIdentifierChoice *rdi; } ASIdentifiers; ASRange *ASRange_new(void); @@ -905,37 +910,38 @@ int i2d_ASIdentifiers(ASIdentifiers *a, unsigned char **out); extern const ASN1_ITEM ASIdentifiers_it; typedef struct IPAddressRange_st { - ASN1_BIT_STRING *min, *max; + ASN1_BIT_STRING *min; + ASN1_BIT_STRING *max; } IPAddressRange; -# define IPAddressOrRange_addressPrefix 0 -# define IPAddressOrRange_addressRange 1 +#define IPAddressOrRange_addressPrefix 0 +#define IPAddressOrRange_addressRange 1 typedef struct IPAddressOrRange_st { - int type; - union { - ASN1_BIT_STRING *addressPrefix; - IPAddressRange *addressRange; - } u; + int type; + union { + ASN1_BIT_STRING *addressPrefix; + IPAddressRange *addressRange; + } u; } IPAddressOrRange; typedef STACK_OF(IPAddressOrRange) IPAddressOrRanges; DECLARE_STACK_OF(IPAddressOrRange) -# define IPAddressChoice_inherit 0 -# define IPAddressChoice_addressesOrRanges 1 +#define IPAddressChoice_inherit 0 +#define IPAddressChoice_addressesOrRanges 1 typedef struct IPAddressChoice_st { - int type; - union { - ASN1_NULL *inherit; - IPAddressOrRanges *addressesOrRanges; - } u; + int type; + union { + ASN1_NULL *inherit; + IPAddressOrRanges *addressesOrRanges; + } u; } IPAddressChoice; typedef struct IPAddressFamily_st { - ASN1_OCTET_STRING *addressFamily; - IPAddressChoice *ipAddressChoice; + ASN1_OCTET_STRING *addressFamily; + IPAddressChoice *ipAddressChoice; } IPAddressFamily; typedef STACK_OF(IPAddressFamily) IPAddrBlocks; @@ -972,8 +978,8 @@ extern const ASN1_ITEM IPAddressFamily_it; /* * API tag for elements of the ASIdentifer SEQUENCE. */ -# define V3_ASID_ASNUM 0 -# define V3_ASID_RDI 1 +#define V3_ASID_ASNUM 0 +#define V3_ASID_RDI 1 /* * AFI values, assigned by IANA. It'd be nice to make the AFI @@ -981,8 +987,9 @@ extern const ASN1_ITEM IPAddressFamily_it; * that would need to be defined for other address families for it to * be worth the trouble. */ -# define IANA_AFI_IPV4 1 -# define IANA_AFI_IPV6 2 +#define IANA_AFI_IPV4 1 +#define IANA_AFI_IPV6 2 + /* * Utilities to construct and extract values from RFC3779 extensions, * since some of the encodings (particularly for IP address prefixes @@ -990,19 +997,17 @@ extern const ASN1_ITEM IPAddressFamily_it; */ int X509v3_asid_add_inherit(ASIdentifiers *asid, int which); int X509v3_asid_add_id_or_range(ASIdentifiers *asid, int which, - ASN1_INTEGER *min, ASN1_INTEGER *max); -int X509v3_addr_add_inherit(IPAddrBlocks *addr, - const unsigned afi, const unsigned *safi); -int X509v3_addr_add_prefix(IPAddrBlocks *addr, - const unsigned afi, const unsigned *safi, - unsigned char *a, const int prefixlen); -int X509v3_addr_add_range(IPAddrBlocks *addr, - const unsigned afi, const unsigned *safi, - unsigned char *min, unsigned char *max); + ASN1_INTEGER *min, ASN1_INTEGER *max); +int X509v3_addr_add_inherit(IPAddrBlocks *addr, const unsigned afi, + const unsigned *safi); +int X509v3_addr_add_prefix(IPAddrBlocks *addr, const unsigned afi, + const unsigned *safi, unsigned char *a, const int prefixlen); +int X509v3_addr_add_range(IPAddrBlocks *addr, const unsigned afi, + const unsigned *safi, unsigned char *min, unsigned char *max); unsigned X509v3_addr_get_afi(const IPAddressFamily *f); int X509v3_addr_get_range(IPAddressOrRange *aor, const unsigned afi, - unsigned char *min, unsigned char *max, - const int length); + unsigned char *min, unsigned char *max, const int length); + /* * Canonical forms. */ @@ -1024,14 +1029,12 @@ int X509v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b); */ int X509v3_asid_validate_path(X509_STORE_CTX *); int X509v3_addr_validate_path(X509_STORE_CTX *); -int X509v3_asid_validate_resource_set(STACK_OF(X509) *chain, - ASIdentifiers *ext, - int allow_inheritance); -int X509v3_addr_validate_resource_set(STACK_OF(X509) *chain, - IPAddrBlocks *ext, int allow_inheritance); +int X509v3_asid_validate_resource_set(STACK_OF(X509) *chain, ASIdentifiers *ext, + int allow_inheritance); +int X509v3_addr_validate_resource_set(STACK_OF(X509) *chain, IPAddrBlocks *ext, + int allow_inheritance); -#endif /* OPENSSL_NO_RFC3779 */ -#endif +#endif /* !OPENSSL_NO_RFC3779 */ /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes diff --git a/include/tls.h b/include/tls.h index de6d257..0c9e497 100644 --- a/include/tls.h +++ b/include/tls.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls.h,v 1.58 2020/01/22 06:44:02 beck Exp $ */ +/* $OpenBSD: tls.h,v 1.62 2022/03/24 15:56:34 tb Exp $ */ /* * Copyright (c) 2014 Joel Sing * diff --git a/ssl/CMakeLists.txt b/ssl/CMakeLists.txt index a772d12..cec2417 100644 --- a/ssl/CMakeLists.txt +++ b/ssl/CMakeLists.txt @@ -1,9 +1,6 @@ set( SSL_SRC bio_ssl.c - bs_ber.c - bs_cbb.c - bs_cbs.c d1_both.c d1_lib.c d1_pkt.c @@ -36,17 +33,17 @@ set( ssl_versions.c t1_enc.c t1_lib.c + tls_buffer.c tls_content.c + tls_key_share.c tls12_key_schedule.c tls12_lib.c tls12_record_layer.c - tls13_buffer.c tls13_client.c tls13_error.c tls13_handshake.c tls13_handshake_msg.c tls13_key_schedule.c - tls13_key_share.c tls13_legacy.c tls13_lib.c tls13_record.c @@ -54,21 +51,33 @@ set( tls13_server.c ) +set( + BS_SRC + bs_ber.c + bs_cbb.c + bs_cbs.c +) + add_library(ssl_obj OBJECT ${SSL_SRC}) target_include_directories(ssl_obj PRIVATE . + ../crypto/bio ../include/compat PUBLIC ../include) -add_library(ssl $) -target_include_directories(ssl +add_library(bs_obj OBJECT ${BS_SRC}) +target_include_directories(bs_obj PRIVATE . - ../include/compat - PUBLIC - ../include) + ../include/compat) + +if(BUILD_SHARED_LIBS) + add_library(ssl $ $) +else() + add_library(ssl $) +endif() export_symbol(ssl ${CMAKE_CURRENT_SOURCE_DIR}/ssl.sym) target_link_libraries(ssl crypto ${PLATFORM_LIBS}) @@ -89,3 +98,10 @@ if(ENABLE_LIBRESSL_INSTALL) RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) endif(ENABLE_LIBRESSL_INSTALL) + +# build static library for regression test +if(BUILD_SHARED_LIBS) + add_library(ssl-static STATIC $) + target_link_libraries(ssl-static crypto-static ${PLATFORM_LIBS}) +endif() + diff --git a/ssl/VERSION b/ssl/VERSION index 5525aec..71e5541 100644 --- a/ssl/VERSION +++ b/ssl/VERSION @@ -1 +1 @@ -50:0:0 +52:0:0 diff --git a/ssl/bio_ssl.c b/ssl/bio_ssl.c index bb40b2a..e86b9d8 100644 --- a/ssl/bio_ssl.c +++ b/ssl/bio_ssl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bio_ssl.c,v 1.31 2021/07/01 17:53:39 jsing Exp $ */ +/* $OpenBSD: bio_ssl.c,v 1.33 2022/01/14 09:12:53 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -66,6 +66,7 @@ #include #include +#include "bio_local.h" #include "ssl_locl.h" static int ssl_write(BIO *h, const char *buf, int num); @@ -74,7 +75,7 @@ static int ssl_puts(BIO *h, const char *str); static long ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int ssl_new(BIO *h); static int ssl_free(BIO *data); -static long ssl_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); +static long ssl_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); typedef struct bio_ssl_st { SSL *ssl; /* The ssl handle :-) */ /* re-negotiate every time the total number of bytes is this size */ @@ -462,7 +463,7 @@ ssl_ctrl(BIO *b, int cmd, long num, void *ptr) } static long -ssl_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +ssl_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { SSL *ssl; BIO_SSL *bs; diff --git a/ssl/bs_cbb.c b/ssl/bs_cbb.c index e17c57e..95e5386 100644 --- a/ssl/bs_cbb.c +++ b/ssl/bs_cbb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bs_cbb.c,v 1.26 2021/05/16 10:58:27 jsing Exp $ */ +/* $OpenBSD: bs_cbb.c,v 1.27 2022/01/06 14:30:30 jsing Exp $ */ /* * Copyright (c) 2014, Google Inc. * @@ -413,6 +413,19 @@ CBB_add_u32(CBB *cbb, size_t value) return cbb_add_u(cbb, (uint32_t)value, 4); } +int +CBB_add_u64(CBB *cbb, uint64_t value) +{ + uint32_t a, b; + + a = value >> 32; + b = value & 0xffffffff; + + if (!CBB_add_u32(cbb, a)) + return 0; + return CBB_add_u32(cbb, b); +} + int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) { diff --git a/ssl/bs_cbs.c b/ssl/bs_cbs.c index 8d55871..63c078c 100644 --- a/ssl/bs_cbs.c +++ b/ssl/bs_cbs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bs_cbs.c,v 1.20 2021/05/16 10:58:27 jsing Exp $ */ +/* $OpenBSD: bs_cbs.c,v 1.24 2021/12/15 17:36:49 jsing Exp $ */ /* * Copyright (c) 2014, Google Inc. * @@ -47,6 +47,16 @@ cbs_get(CBS *cbs, const uint8_t **p, size_t n) return 1; } +static int +cbs_peek(CBS *cbs, const uint8_t **p, size_t n) +{ + if (cbs->len < n) + return 0; + + *p = cbs->data; + return 1; +} + size_t CBS_offset(const CBS *cbs) { @@ -95,6 +105,11 @@ int CBS_strdup(const CBS *cbs, char **out_ptr) { free(*out_ptr); + *out_ptr = NULL; + + if (CBS_contains_zero_byte(cbs)) + return 0; + *out_ptr = strndup((const char *)cbs->data, cbs->len); return (*out_ptr != NULL); } @@ -185,6 +200,34 @@ CBS_get_u32(CBS *cbs, uint32_t *out) return cbs_get_u(cbs, out, 4); } +int +CBS_get_u64(CBS *cbs, uint64_t *out) +{ + uint32_t a, b; + + if (cbs->len < 8) + return 0; + + if (!CBS_get_u32(cbs, &a)) + return 0; + if (!CBS_get_u32(cbs, &b)) + return 0; + + *out = (uint64_t)a << 32 | b; + return 1; +} + +int +CBS_get_last_u8(CBS *cbs, uint8_t *out) +{ + if (cbs->len == 0) + return 0; + + *out = cbs->data[cbs->len - 1]; + cbs->len--; + return 1; +} + int CBS_get_bytes(CBS *cbs, CBS *out, size_t len) { @@ -226,6 +269,73 @@ CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) return cbs_get_length_prefixed(cbs, out, 3); } +static int +cbs_peek_u(CBS *cbs, uint32_t *out, size_t len) +{ + uint32_t result = 0; + size_t i; + const uint8_t *data; + + if (len < 1 || len > 4) + return 0; + + if (!cbs_peek(cbs, &data, len)) + return 0; + + for (i = 0; i < len; i++) { + result <<= 8; + result |= data[i]; + } + *out = result; + return 1; +} + +int +CBS_peek_u8(CBS *cbs, uint8_t *out) +{ + const uint8_t *v; + + if (!cbs_peek(cbs, &v, 1)) + return 0; + + *out = *v; + return 1; +} + +int +CBS_peek_u16(CBS *cbs, uint16_t *out) +{ + uint32_t v; + + if (!cbs_peek_u(cbs, &v, 2)) + return 0; + + *out = v; + return 1; +} + +int +CBS_peek_u24(CBS *cbs, uint32_t *out) +{ + return cbs_peek_u(cbs, out, 3); +} + +int +CBS_peek_u32(CBS *cbs, uint32_t *out) +{ + return cbs_peek_u(cbs, out, 4); +} + +int +CBS_peek_last_u8(CBS *cbs, uint8_t *out) +{ + if (cbs->len == 0) + return 0; + + *out = cbs->data[cbs->len - 1]; + return 1; +} + int CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned int *out_tag, size_t *out_header_len) diff --git a/ssl/bytestring.h b/ssl/bytestring.h index 9e55dd4..022bc68 100644 --- a/ssl/bytestring.h +++ b/ssl/bytestring.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bytestring.h,v 1.19 2021/05/16 10:58:27 jsing Exp $ */ +/* $OpenBSD: bytestring.h,v 1.23 2022/01/06 14:30:30 jsing Exp $ */ /* * Copyright (c) 2014, Google Inc. * @@ -133,6 +133,18 @@ int CBS_get_u24(CBS *cbs, uint32_t *out); */ int CBS_get_u32(CBS *cbs, uint32_t *out); +/* + * CBS_get_u64 sets |*out| to the next, big-endian uint64_t value from |cbs| + * and advances |cbs|. It returns one on success and zero on error. + */ +int CBS_get_u64(CBS *cbs, uint64_t *out); + +/* + * CBS_get_last_u8 sets |*out| to the last uint8_t from |cbs| and shortens + * |cbs|. It returns one on success and zero on error. + */ +int CBS_get_last_u8(CBS *cbs, uint8_t *out); + /* * CBS_get_bytes sets |*out| to the next |len| bytes from |cbs| and advances * |cbs|. It returns one on success and zero on error. @@ -160,6 +172,36 @@ int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out); */ int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out); +/* + * CBS_peek_u8 sets |*out| to the next uint8_t from |cbs|, but does not advance + * |cbs|. It returns one on success and zero on error. + */ +int CBS_peek_u8(CBS *cbs, uint8_t *out); + +/* + * CBS_peek_u16 sets |*out| to the next, big-endian uint16_t from |cbs|, but + * does not advance |cbs|. It returns one on success and zero on error. + */ +int CBS_peek_u16(CBS *cbs, uint16_t *out); + +/* + * CBS_peek_u24 sets |*out| to the next, big-endian 24-bit value from |cbs|, but + * does not advance |cbs|. It returns one on success and zero on error. + */ +int CBS_peek_u24(CBS *cbs, uint32_t *out); + +/* + * CBS_peek_u32 sets |*out| to the next, big-endian uint32_t value from |cbs|, + * but does not advance |cbs|. It returns one on success and zero on error. + */ +int CBS_peek_u32(CBS *cbs, uint32_t *out); + +/* + * CBS_peek_last_u8 sets |*out| to the last uint8_t from |cbs|, but does not + * shorten |cbs|. It returns one on success and zero on error. + */ +int CBS_peek_last_u8(CBS *cbs, uint8_t *out); + /* Parsing ASN.1 */ @@ -466,6 +508,12 @@ int CBB_add_u24(CBB *cbb, size_t value); */ int CBB_add_u32(CBB *cbb, size_t value); +/* + * CBB_add_u64 appends a 64-bit, big-endian number from |value| to |cbb|. It + * returns one on success and zero otherwise. + */ +int CBB_add_u64(CBB *cbb, uint64_t value); + /* * CBB_add_asn1_uint64 writes an ASN.1 INTEGER into |cbb| using |CBB_add_asn1| * and writes |value| in its contents. It returns one on success and zero on diff --git a/ssl/d1_both.c b/ssl/d1_both.c index 4c014be..fd7c07a 100644 --- a/ssl/d1_both.c +++ b/ssl/d1_both.c @@ -1,4 +1,4 @@ -/* $OpenBSD: d1_both.c,v 1.78 2021/09/04 14:24:28 jsing Exp $ */ +/* $OpenBSD: d1_both.c,v 1.81 2022/02/05 14:54:10 jsing Exp $ */ /* * DTLS implementation written by Nagendra Modadugu * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. @@ -216,9 +216,9 @@ dtls1_do_write(SSL *s, int type) size_t overhead; /* AHA! Figure out the MTU, and stick to the right size */ - if (D1I(s)->mtu < dtls1_min_mtu() && + if (s->d1->mtu < dtls1_min_mtu() && !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) { - D1I(s)->mtu = BIO_ctrl(SSL_get_wbio(s), + s->d1->mtu = BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); /* @@ -226,27 +226,27 @@ dtls1_do_write(SSL *s, int type) * doesn't know the MTU (ie., the initial write), so just * make sure we have a reasonable number */ - if (D1I(s)->mtu < dtls1_min_mtu()) { - D1I(s)->mtu = 0; - D1I(s)->mtu = dtls1_guess_mtu(D1I(s)->mtu); + if (s->d1->mtu < dtls1_min_mtu()) { + s->d1->mtu = 0; + s->d1->mtu = dtls1_guess_mtu(s->d1->mtu); BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU, - D1I(s)->mtu, NULL); + s->d1->mtu, NULL); } } - OPENSSL_assert(D1I(s)->mtu >= dtls1_min_mtu()); + OPENSSL_assert(s->d1->mtu >= dtls1_min_mtu()); /* should have something reasonable now */ if (s->internal->init_off == 0 && type == SSL3_RT_HANDSHAKE) OPENSSL_assert(s->internal->init_num == - (int)D1I(s)->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH); + (int)s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH); if (!tls12_record_layer_write_overhead(s->internal->rl, &overhead)) return -1; frag_off = 0; while (s->internal->init_num) { - curr_mtu = D1I(s)->mtu - BIO_wpending(SSL_get_wbio(s)) - + curr_mtu = s->d1->mtu - BIO_wpending(SSL_get_wbio(s)) - DTLS1_RT_HEADER_LENGTH - overhead; if (curr_mtu <= DTLS1_HM_HEADER_LENGTH) { @@ -254,7 +254,7 @@ dtls1_do_write(SSL *s, int type) ret = BIO_flush(SSL_get_wbio(s)); if (ret <= 0) return ret; - curr_mtu = D1I(s)->mtu - DTLS1_RT_HEADER_LENGTH - + curr_mtu = s->d1->mtu - DTLS1_RT_HEADER_LENGTH - overhead; } @@ -279,8 +279,8 @@ dtls1_do_write(SSL *s, int type) dtls1_fix_message_header(s, frag_off, len - DTLS1_HM_HEADER_LENGTH); - if (!dtls1_write_message_header(&D1I(s)->w_msg_hdr, - D1I(s)->w_msg_hdr.frag_off, D1I(s)->w_msg_hdr.frag_len, + if (!dtls1_write_message_header(&s->d1->w_msg_hdr, + s->d1->w_msg_hdr.frag_off, s->d1->w_msg_hdr.frag_len, (unsigned char *)&s->internal->init_buf->data[s->internal->init_off])) return -1; @@ -299,7 +299,7 @@ dtls1_do_write(SSL *s, int type) */ if (BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0) - D1I(s)->mtu = BIO_ctrl(SSL_get_wbio(s), + s->d1->mtu = BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); else return (-1); @@ -313,14 +313,14 @@ dtls1_do_write(SSL *s, int type) OPENSSL_assert(len == (unsigned int)ret); if (type == SSL3_RT_HANDSHAKE && - !D1I(s)->retransmitting) { + !s->d1->retransmitting) { /* * Should not be done for 'Hello Request's, * but in that case we'll ignore the result * anyway */ unsigned char *p = (unsigned char *)&s->internal->init_buf->data[s->internal->init_off]; - const struct hm_header_st *msg_hdr = &D1I(s)->w_msg_hdr; + const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; int xlen; if (frag_off == 0) { @@ -368,40 +368,39 @@ dtls1_do_write(SSL *s, int type) * Read an entire handshake message. Handshake messages arrive in * fragments. */ -long -dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) +int +dtls1_get_message(SSL *s, int st1, int stn, int mt, long max) { - int i, al; struct hm_header_st *msg_hdr; unsigned char *p; unsigned long msg_len; + int i, al, ok; /* * s3->internal->tmp is used to store messages that are unexpected, caused * by the absence of an optional handshake message */ - if (S3I(s)->hs.tls12.reuse_message) { - S3I(s)->hs.tls12.reuse_message = 0; - if ((mt >= 0) && (S3I(s)->hs.tls12.message_type != mt)) { + if (s->s3->hs.tls12.reuse_message) { + s->s3->hs.tls12.reuse_message = 0; + if ((mt >= 0) && (s->s3->hs.tls12.message_type != mt)) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); goto fatal_err; } - *ok = 1; s->internal->init_msg = s->internal->init_buf->data + DTLS1_HM_HEADER_LENGTH; - s->internal->init_num = (int)S3I(s)->hs.tls12.message_size; - return s->internal->init_num; + s->internal->init_num = (int)s->s3->hs.tls12.message_size; + return 1; } - msg_hdr = &D1I(s)->r_msg_hdr; + msg_hdr = &s->d1->r_msg_hdr; memset(msg_hdr, 0, sizeof(struct hm_header_st)); again: - i = dtls1_get_message_fragment(s, st1, stn, max, ok); + i = dtls1_get_message_fragment(s, st1, stn, max, &ok); if (i == DTLS1_HM_BAD_FRAGMENT || i == DTLS1_HM_FRAGMENT_RETRY) /* bad fragment received */ goto again; - else if (i <= 0 && !*ok) + else if (i <= 0 && !ok) return i; p = (unsigned char *)s->internal->init_buf->data; @@ -421,19 +420,17 @@ dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) memset(msg_hdr, 0, sizeof(struct hm_header_st)); /* Don't change sequence numbers while listening */ - if (!D1I(s)->listen) - D1I(s)->handshake_read_seq++; + if (!s->d1->listen) + s->d1->handshake_read_seq++; s->internal->init_msg = s->internal->init_buf->data + DTLS1_HM_HEADER_LENGTH; - return s->internal->init_num; + return 1; fatal_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); - *ok = 0; return -1; } - static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr, int max) { @@ -454,7 +451,7 @@ dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr, int max) return SSL_AD_ILLEGAL_PARAMETER; } - if ( D1I(s)->r_msg_hdr.frag_off == 0) /* first fragment */ + if ( s->d1->r_msg_hdr.frag_off == 0) /* first fragment */ { /* * msg_len is limited to 2^24, but is effectively checked @@ -466,12 +463,12 @@ dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr, int max) return SSL_AD_INTERNAL_ERROR; } - S3I(s)->hs.tls12.message_size = msg_len; - D1I(s)->r_msg_hdr.msg_len = msg_len; - S3I(s)->hs.tls12.message_type = msg_hdr->type; - D1I(s)->r_msg_hdr.type = msg_hdr->type; - D1I(s)->r_msg_hdr.seq = msg_hdr->seq; - } else if (msg_len != D1I(s)->r_msg_hdr.msg_len) { + s->s3->hs.tls12.message_size = msg_len; + s->d1->r_msg_hdr.msg_len = msg_len; + s->s3->hs.tls12.message_type = msg_hdr->type; + s->d1->r_msg_hdr.type = msg_hdr->type; + s->d1->r_msg_hdr.seq = msg_hdr->seq; + } else if (msg_len != s->d1->r_msg_hdr.msg_len) { /* * They must be playing with us! BTW, failure to enforce * upper limit would open possibility for buffer overrun. @@ -497,7 +494,7 @@ dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok) int al; *ok = 0; - item = pqueue_peek(D1I(s)->buffered_messages); + item = pqueue_peek(s->d1->buffered_messages); if (item == NULL) return 0; @@ -507,9 +504,9 @@ dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok) if (frag->reassembly != NULL) return 0; - if (D1I(s)->handshake_read_seq == frag->msg_header.seq) { + if (s->d1->handshake_read_seq == frag->msg_header.seq) { unsigned long frag_len = frag->msg_header.frag_len; - pqueue_pop(D1I(s)->buffered_messages); + pqueue_pop(s->d1->buffered_messages); al = dtls1_preprocess_fragment(s, &frag->msg_header, max); @@ -574,7 +571,7 @@ dtls1_reassemble_fragment(SSL *s, struct hm_header_st* msg_hdr, int *ok) memset(seq64be, 0, sizeof(seq64be)); seq64be[6] = (unsigned char)(msg_hdr->seq >> 8); seq64be[7] = (unsigned char)msg_hdr->seq; - item = pqueue_find(D1I(s)->buffered_messages, seq64be); + item = pqueue_find(s->d1->buffered_messages, seq64be); if (item == NULL) { frag = dtls1_hm_fragment_new(msg_hdr->msg_len, 1); @@ -639,7 +636,7 @@ dtls1_reassemble_fragment(SSL *s, struct hm_header_st* msg_hdr, int *ok) goto err; } - pqueue_insert(D1I(s)->buffered_messages, item); + pqueue_insert(s->d1->buffered_messages, item); } return DTLS1_HM_FRAGMENT_RETRY; @@ -668,7 +665,7 @@ dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok) memset(seq64be, 0, sizeof(seq64be)); seq64be[6] = (unsigned char) (msg_hdr->seq >> 8); seq64be[7] = (unsigned char) msg_hdr->seq; - item = pqueue_find(D1I(s)->buffered_messages, seq64be); + item = pqueue_find(s->d1->buffered_messages, seq64be); /* * If we already have an entry and this one is a fragment, @@ -683,9 +680,9 @@ dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok) * a FINISHED before the SERVER_HELLO, which then must be a stale * retransmit. */ - if (msg_hdr->seq <= D1I(s)->handshake_read_seq || - msg_hdr->seq > D1I(s)->handshake_read_seq + 10 || item != NULL || - (D1I(s)->handshake_read_seq == 0 && + if (msg_hdr->seq <= s->d1->handshake_read_seq || + msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL || + (s->d1->handshake_read_seq == 0 && msg_hdr->type == SSL3_MT_FINISHED)) { unsigned char devnull [256]; @@ -726,7 +723,7 @@ dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok) if (item == NULL) goto err; - pqueue_insert(D1I(s)->buffered_messages, item); + pqueue_insert(s->d1->buffered_messages, item); } return DTLS1_HM_FRAGMENT_RETRY; @@ -780,8 +777,8 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) * While listening, we accept seq 1 (ClientHello with cookie) * although we're still expecting seq 0 (ClientHello) */ - if (msg_hdr.seq != D1I(s)->handshake_read_seq && - !(D1I(s)->listen && msg_hdr.seq == 1)) + if (msg_hdr.seq != s->d1->handshake_read_seq && + !(s->d1->listen && msg_hdr.seq == 1)) return dtls1_process_out_of_seq_message(s, &msg_hdr, ok); len = msg_hdr.msg_len; @@ -791,7 +788,7 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) if (frag_len && frag_len < len) return dtls1_reassemble_fragment(s, &msg_hdr, ok); - if (!s->server && D1I(s)->r_msg_hdr.frag_off == 0 && + if (!s->server && s->d1->r_msg_hdr.frag_off == 0 && wire[0] == SSL3_MT_HELLO_REQUEST) { /* * The server may always send 'Hello Request' messages -- @@ -821,7 +818,7 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) goto fatal_err; /* XDTLS: ressurect this when restart is in place */ - S3I(s)->hs.state = stn; + s->s3->hs.state = stn; if (frag_len > 0) { unsigned char *p = (unsigned char *)s->internal->init_buf->data + DTLS1_HM_HEADER_LENGTH; @@ -847,8 +844,6 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) goto fatal_err; } - *ok = 1; - /* * Note that s->internal->init_num is *not* used as current offset in * s->internal->init_buf->data, but as a counter summing up fragments' @@ -856,6 +851,7 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) * length, we assume we have got all the fragments. */ s->internal->init_num = frag_len; + *ok = 1; return frag_len; fatal_err: @@ -960,15 +956,15 @@ dtls1_buffer_message(SSL *s, int is_ccs) memcpy(frag->fragment, s->internal->init_buf->data, s->internal->init_num); - OPENSSL_assert(D1I(s)->w_msg_hdr.msg_len + + OPENSSL_assert(s->d1->w_msg_hdr.msg_len + (is_ccs ? DTLS1_CCS_HEADER_LENGTH : DTLS1_HM_HEADER_LENGTH) == (unsigned int)s->internal->init_num); - frag->msg_header.msg_len = D1I(s)->w_msg_hdr.msg_len; - frag->msg_header.seq = D1I(s)->w_msg_hdr.seq; - frag->msg_header.type = D1I(s)->w_msg_hdr.type; + frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len; + frag->msg_header.seq = s->d1->w_msg_hdr.seq; + frag->msg_header.type = s->d1->w_msg_hdr.type; frag->msg_header.frag_off = 0; - frag->msg_header.frag_len = D1I(s)->w_msg_hdr.msg_len; + frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len; frag->msg_header.is_ccs = is_ccs; /* save current state*/ @@ -1043,7 +1039,7 @@ dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off, saved_state.session = s->session; saved_state.epoch = tls12_record_layer_write_epoch(s->internal->rl); - D1I(s)->retransmitting = 1; + s->d1->retransmitting = 1; /* restore state in which the message was originally sent */ s->session = frag->msg_header.saved_retransmit_state.session; @@ -1060,7 +1056,7 @@ dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off, saved_state.epoch)) return 0; - D1I(s)->retransmitting = 0; + s->d1->retransmitting = 0; (void)BIO_flush(SSL_get_wbio(s)); return ret; @@ -1089,12 +1085,12 @@ dtls1_set_message_header(SSL *s, unsigned char mt, unsigned long len, unsigned long frag_off, unsigned long frag_len) { /* Don't change sequence numbers while listening */ - if (frag_off == 0 && !D1I(s)->listen) { - D1I(s)->handshake_write_seq = D1I(s)->next_handshake_write_seq; - D1I(s)->next_handshake_write_seq++; + if (frag_off == 0 && !s->d1->listen) { + s->d1->handshake_write_seq = s->d1->next_handshake_write_seq; + s->d1->next_handshake_write_seq++; } - dtls1_set_message_header_int(s, mt, len, D1I(s)->handshake_write_seq, + dtls1_set_message_header_int(s, mt, len, s->d1->handshake_write_seq, frag_off, frag_len); } @@ -1103,7 +1099,7 @@ void dtls1_set_message_header_int(SSL *s, unsigned char mt, unsigned long len, unsigned short seq_num, unsigned long frag_off, unsigned long frag_len) { - struct hm_header_st *msg_hdr = &D1I(s)->w_msg_hdr; + struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; msg_hdr->type = mt; msg_hdr->msg_len = len; @@ -1115,7 +1111,7 @@ dtls1_set_message_header_int(SSL *s, unsigned char mt, unsigned long len, static void dtls1_fix_message_header(SSL *s, unsigned long frag_off, unsigned long frag_len) { - struct hm_header_st *msg_hdr = &D1I(s)->w_msg_hdr; + struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; msg_hdr->frag_off = frag_off; msg_hdr->frag_len = frag_len; diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c index d4280a2..770734e 100644 --- a/ssl/d1_lib.c +++ b/ssl/d1_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: d1_lib.c,v 1.59 2021/08/30 19:12:25 jsing Exp $ */ +/* $OpenBSD: d1_lib.c,v 1.61 2021/10/23 13:36:03 jsing Exp $ */ /* * DTLS implementation written by Nagendra Modadugu * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. @@ -83,20 +83,18 @@ dtls1_new(SSL *s) if ((s->d1 = calloc(1, sizeof(*s->d1))) == NULL) goto err; - if ((s->d1->internal = calloc(1, sizeof(*s->d1->internal))) == NULL) - goto err; - if ((s->d1->internal->unprocessed_rcds.q = pqueue_new()) == NULL) + if ((s->d1->unprocessed_rcds.q = pqueue_new()) == NULL) goto err; - if ((s->d1->internal->buffered_messages = pqueue_new()) == NULL) + if ((s->d1->buffered_messages = pqueue_new()) == NULL) goto err; if ((s->d1->sent_messages = pqueue_new()) == NULL) goto err; - if ((s->d1->internal->buffered_app_data.q = pqueue_new()) == NULL) + if ((s->d1->buffered_app_data.q = pqueue_new()) == NULL) goto err; if (s->server) - s->d1->internal->cookie_len = sizeof(D1I(s)->cookie); + s->d1->cookie_len = sizeof(s->d1->cookie); s->method->ssl_clear(s); return (1); @@ -140,10 +138,10 @@ dtls1_drain_fragments(pqueue queue) static void dtls1_clear_queues(SSL *s) { - dtls1_drain_records(D1I(s)->unprocessed_rcds.q); - dtls1_drain_fragments(D1I(s)->buffered_messages); + dtls1_drain_records(s->d1->unprocessed_rcds.q); + dtls1_drain_fragments(s->d1->buffered_messages); dtls1_drain_fragments(s->d1->sent_messages); - dtls1_drain_records(D1I(s)->buffered_app_data.q); + dtls1_drain_records(s->d1->buffered_app_data.q); } void @@ -154,23 +152,23 @@ dtls1_free(SSL *s) ssl3_free(s); + if (s->d1 == NULL) + return; + dtls1_clear_queues(s); - pqueue_free(D1I(s)->unprocessed_rcds.q); - pqueue_free(D1I(s)->buffered_messages); + pqueue_free(s->d1->unprocessed_rcds.q); + pqueue_free(s->d1->buffered_messages); pqueue_free(s->d1->sent_messages); - pqueue_free(D1I(s)->buffered_app_data.q); + pqueue_free(s->d1->buffered_app_data.q); - freezero(s->d1->internal, sizeof(*s->d1->internal)); freezero(s->d1, sizeof(*s->d1)); - s->d1 = NULL; } void dtls1_clear(SSL *s) { - struct dtls1_state_internal_st *internal; pqueue unprocessed_rcds; pqueue buffered_messages; pqueue sent_messages; @@ -178,34 +176,31 @@ dtls1_clear(SSL *s) unsigned int mtu; if (s->d1) { - unprocessed_rcds = D1I(s)->unprocessed_rcds.q; - buffered_messages = D1I(s)->buffered_messages; + unprocessed_rcds = s->d1->unprocessed_rcds.q; + buffered_messages = s->d1->buffered_messages; sent_messages = s->d1->sent_messages; - buffered_app_data = D1I(s)->buffered_app_data.q; - mtu = D1I(s)->mtu; + buffered_app_data = s->d1->buffered_app_data.q; + mtu = s->d1->mtu; dtls1_clear_queues(s); - memset(s->d1->internal, 0, sizeof(*s->d1->internal)); - internal = s->d1->internal; memset(s->d1, 0, sizeof(*s->d1)); - s->d1->internal = internal; - D1I(s)->unprocessed_rcds.epoch = + s->d1->unprocessed_rcds.epoch = tls12_record_layer_read_epoch(s->internal->rl) + 1; if (s->server) { - D1I(s)->cookie_len = sizeof(D1I(s)->cookie); + s->d1->cookie_len = sizeof(s->d1->cookie); } if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU) { - D1I(s)->mtu = mtu; + s->d1->mtu = mtu; } - D1I(s)->unprocessed_rcds.q = unprocessed_rcds; - D1I(s)->buffered_messages = buffered_messages; + s->d1->unprocessed_rcds.q = unprocessed_rcds; + s->d1->buffered_messages = buffered_messages; s->d1->sent_messages = sent_messages; - D1I(s)->buffered_app_data.q = buffered_app_data; + s->d1->buffered_app_data.q = buffered_app_data; } ssl3_clear(s); @@ -351,7 +346,7 @@ void dtls1_stop_timer(SSL *s) { /* Reset everything */ - memset(&(D1I(s)->timeout), 0, sizeof(struct dtls1_timeout_st)); + memset(&(s->d1->timeout), 0, sizeof(struct dtls1_timeout_st)); memset(&(s->d1->next_timeout), 0, sizeof(struct timeval)); s->d1->timeout_duration = 1; BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, @@ -363,16 +358,16 @@ dtls1_stop_timer(SSL *s) int dtls1_check_timeout_num(SSL *s) { - D1I(s)->timeout.num_alerts++; + s->d1->timeout.num_alerts++; /* Reduce MTU after 2 unsuccessful retransmissions */ - if (D1I(s)->timeout.num_alerts > 2) { - D1I(s)->mtu = BIO_ctrl(SSL_get_wbio(s), + if (s->d1->timeout.num_alerts > 2) { + s->d1->mtu = BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL); } - if (D1I(s)->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) { + if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) { /* fail the connection, enough alerts have been sent */ SSLerror(s, SSL_R_READ_TIMEOUT_EXPIRED); return -1; @@ -394,9 +389,9 @@ dtls1_handle_timeout(SSL *s) if (dtls1_check_timeout_num(s) < 0) return -1; - D1I(s)->timeout.read_timeouts++; - if (D1I(s)->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) { - D1I(s)->timeout.read_timeouts = 1; + s->d1->timeout.read_timeouts++; + if (s->d1->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) { + s->d1->timeout.read_timeouts = 1; } dtls1_start_timer(s); @@ -412,7 +407,7 @@ dtls1_listen(SSL *s, struct sockaddr *client) SSL_clear(s); SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE); - D1I(s)->listen = 1; + s->d1->listen = 1; ret = SSL_accept(s); if (ret <= 0) diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c index aafadf1..456f871 100644 --- a/ssl/d1_pkt.c +++ b/ssl/d1_pkt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: d1_pkt.c,v 1.112 2021/09/04 14:31:54 jsing Exp $ */ +/* $OpenBSD: d1_pkt.c,v 1.123 2022/03/26 15:05:53 jsing Exp $ */ /* * DTLS implementation written by Nagendra Modadugu * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. @@ -113,8 +113,7 @@ * [including the GNU Public Licence.] */ -#include - +#include #include #include @@ -192,12 +191,12 @@ static int dtls1_process_record(SSL *s); static int dtls1_copy_record(SSL *s, DTLS1_RECORD_DATA_INTERNAL *rdata) { - ssl3_release_buffer(&S3I(s)->rbuf); + ssl3_release_buffer(&s->s3->rbuf); s->internal->packet = rdata->packet; s->internal->packet_length = rdata->packet_length; - memcpy(&(S3I(s)->rbuf), &(rdata->rbuf), sizeof(SSL3_BUFFER_INTERNAL)); - memcpy(&(S3I(s)->rrec), &(rdata->rrec), sizeof(SSL3_RECORD_INTERNAL)); + memcpy(&(s->s3->rbuf), &(rdata->rbuf), sizeof(SSL3_BUFFER_INTERNAL)); + memcpy(&(s->s3->rrec), &(rdata->rrec), sizeof(SSL3_RECORD_INTERNAL)); return (1); } @@ -219,15 +218,15 @@ dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority) rdata->packet = s->internal->packet; rdata->packet_length = s->internal->packet_length; - memcpy(&(rdata->rbuf), &(S3I(s)->rbuf), sizeof(SSL3_BUFFER_INTERNAL)); - memcpy(&(rdata->rrec), &(S3I(s)->rrec), sizeof(SSL3_RECORD_INTERNAL)); + memcpy(&(rdata->rbuf), &(s->s3->rbuf), sizeof(SSL3_BUFFER_INTERNAL)); + memcpy(&(rdata->rrec), &(s->s3->rrec), sizeof(SSL3_RECORD_INTERNAL)); item->data = rdata; s->internal->packet = NULL; s->internal->packet_length = 0; - memset(&(S3I(s)->rbuf), 0, sizeof(SSL3_BUFFER_INTERNAL)); - memset(&(S3I(s)->rrec), 0, sizeof(SSL3_RECORD_INTERNAL)); + memset(&(s->s3->rbuf), 0, sizeof(SSL3_BUFFER_INTERNAL)); + memset(&(s->s3->rrec), 0, sizeof(SSL3_RECORD_INTERNAL)); if (!ssl3_setup_buffers(s)) goto err; @@ -271,19 +270,19 @@ static int dtls1_process_buffered_record(SSL *s) { /* Check if epoch is current. */ - if (D1I(s)->unprocessed_rcds.epoch != + if (s->d1->unprocessed_rcds.epoch != tls12_record_layer_read_epoch(s->internal->rl)) return (0); /* Update epoch once all unprocessed records have been processed. */ - if (pqueue_peek(D1I(s)->unprocessed_rcds.q) == NULL) { - D1I(s)->unprocessed_rcds.epoch = + if (pqueue_peek(s->d1->unprocessed_rcds.q) == NULL) { + s->d1->unprocessed_rcds.epoch = tls12_record_layer_read_epoch(s->internal->rl) + 1; return (0); } /* Process one of the records. */ - if (!dtls1_retrieve_buffered_record(s, &D1I(s)->unprocessed_rcds)) + if (!dtls1_retrieve_buffered_record(s, &s->d1->unprocessed_rcds)) return (-1); if (!dtls1_process_record(s)) return (-1); @@ -294,7 +293,7 @@ dtls1_process_buffered_record(SSL *s) static int dtls1_process_record(SSL *s) { - SSL3_RECORD_INTERNAL *rr = &(S3I(s)->rrec); + SSL3_RECORD_INTERNAL *rr = &(s->s3->rrec); uint8_t alert_desc; uint8_t *out; size_t out_len; @@ -350,7 +349,7 @@ dtls1_process_record(SSL *s) int dtls1_get_record(SSL *s) { - SSL3_RECORD_INTERNAL *rr = &(S3I(s)->rrec); + SSL3_RECORD_INTERNAL *rr = &(s->s3->rrec); unsigned char *p = NULL; DTLS1_BITMAP *bitmap; unsigned int is_next_epoch; @@ -449,7 +448,7 @@ dtls1_get_record(SSL *s) * since they arrive from different connections and * would be dropped unnecessarily. */ - if (!(D1I(s)->listen && rr->type == SSL3_RT_HANDSHAKE && + if (!(s->d1->listen && rr->type == SSL3_RT_HANDSHAKE && p != NULL && *p == SSL3_MT_CLIENT_HELLO) && !dtls1_record_replay_check(s, bitmap, rr->seq_num)) goto again; @@ -464,8 +463,8 @@ dtls1_get_record(SSL *s) * anything while listening. */ if (is_next_epoch) { - if ((SSL_in_init(s) || s->internal->in_handshake) && !D1I(s)->listen) { - if (dtls1_buffer_record(s, &(D1I(s)->unprocessed_rcds), + if ((SSL_in_init(s) || s->internal->in_handshake) && !s->d1->listen) { + if (dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), rr->seq_num) < 0) return (-1); /* Mark receipt of record. */ @@ -483,6 +482,179 @@ dtls1_get_record(SSL *s) return (1); } +static int +dtls1_read_handshake_unexpected(SSL *s) +{ + SSL3_RECORD_INTERNAL *rr = &s->s3->rrec; + struct hm_header_st hs_msg_hdr; + CBS cbs; + int ret; + + if (s->internal->in_handshake) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return -1; + } + + if (rr->off != 0) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return -1; + } + + /* Parse handshake message header. */ + CBS_init(&cbs, rr->data, rr->length); + if (!dtls1_get_message_header(&cbs, &hs_msg_hdr)) + return -1; /* XXX - probably should drop/continue. */ + + /* This may just be a stale retransmit. */ + if (rr->epoch != tls12_record_layer_read_epoch(s->internal->rl)) { + rr->length = 0; + return 1; + } + + if (hs_msg_hdr.type == SSL3_MT_HELLO_REQUEST) { + /* + * Incoming HelloRequest messages should only be received by a + * client. A server may send these at any time - a client should + * ignore the message if received in the middle of a handshake. + * See RFC 5246 sections 7.4 and 7.4.1.1. + */ + if (s->server) { + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + /* XXX - should also check frag offset/length. */ + if (hs_msg_hdr.msg_len != 0) { + SSLerror(s, SSL_R_BAD_HELLO_REQUEST); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + return -1; + } + + ssl_msg_callback(s, 0, SSL3_RT_HANDSHAKE, rr->data, + DTLS1_HM_HEADER_LENGTH); + + rr->length = 0; + + /* + * It should be impossible to hit this, but keep the safety + * harness for now... + */ + if (s->session == NULL || s->session->cipher == NULL) + return 1; + + /* + * Ignore this message if we're currently handshaking, + * renegotiation is already pending or renegotiation is disabled + * via flags. + */ + if (!SSL_is_init_finished(s) || s->s3->renegotiate || + (s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) != 0) + return 1; + + s->d1->handshake_read_seq++; + + /* XXX - why is this set here but not in ssl3? */ + s->internal->new_session = 1; + + if (!ssl3_renegotiate(s)) + return 1; + if (!ssl3_renegotiate_check(s)) + return 1; + + } else if (hs_msg_hdr.type == SSL3_MT_CLIENT_HELLO) { + /* + * Incoming ClientHello messages should only be received by a + * server. A client may send these in response to server + * initiated renegotiation (HelloRequest) or in order to + * initiate renegotiation by the client. See RFC 5246 section + * 7.4.1.2. + */ + if (!s->server) { + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + /* + * A client should not be sending a ClientHello unless we're not + * currently handshaking. + */ + if (!SSL_is_init_finished(s)) { + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + if ((s->internal->options & SSL_OP_NO_CLIENT_RENEGOTIATION) != 0) { + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_NO_RENEGOTIATION); + return -1; + } + + if (s->session == NULL || s->session->cipher == NULL) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return -1; + } + + /* Client requested renegotiation but it is not permitted. */ + if (!s->s3->send_connection_binding || + (s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) != 0) { + ssl3_send_alert(s, SSL3_AL_WARNING, + SSL_AD_NO_RENEGOTIATION); + return 1; + } + + s->s3->hs.state = SSL_ST_ACCEPT; + s->internal->renegotiate = 1; + s->internal->new_session = 1; + + } else if (hs_msg_hdr.type == SSL3_MT_FINISHED && s->server) { + /* + * If we are server, we may have a repeated FINISHED of the + * client here, then retransmit our CCS and FINISHED. + */ + if (dtls1_check_timeout_num(s) < 0) + return -1; + + /* XXX - should this be calling ssl_msg_callback()? */ + + dtls1_retransmit_buffered_messages(s); + + rr->length = 0; + + return 1; + + } else { + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + if ((ret = s->internal->handshake_func(s)) < 0) + return ret; + if (ret == 0) { + SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); + return -1; + } + + if (!(s->internal->mode & SSL_MODE_AUTO_RETRY)) { + if (s->s3->rbuf.left == 0) { + ssl_force_want_read(s); + return -1; + } + } + + /* + * We either finished a handshake or ignored the request, now try again + * to obtain the (application) data we were asked for. + */ + return 1; +} + /* Return up to 'len' payload bytes received in 'type' records. * 'type' is one of the following: * @@ -513,80 +685,92 @@ dtls1_get_record(SSL *s) int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) { - int al, i, ret; - unsigned int n; SSL3_RECORD_INTERNAL *rr; + int rrcount = 0; + unsigned int n; + int ret; - if (S3I(s)->rbuf.buf == NULL) /* Not initialized yet */ + if (s->s3->rbuf.buf == NULL) { if (!ssl3_setup_buffers(s)) - return (-1); + return -1; + } - if ((type && - type != SSL3_RT_APPLICATION_DATA && type != SSL3_RT_HANDSHAKE) || - (peek && (type != SSL3_RT_APPLICATION_DATA))) { + if (len < 0) { SSLerror(s, ERR_R_INTERNAL_ERROR); return -1; } - if (!s->internal->in_handshake && SSL_in_init(s)) { - i = s->internal->handshake_func(s); - if (i < 0) - return (i); - if (i == 0) { + if (type != 0 && type != SSL3_RT_APPLICATION_DATA && + type != SSL3_RT_HANDSHAKE) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return -1; + } + if (peek && type != SSL3_RT_APPLICATION_DATA) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return -1; + } + + if (SSL_in_init(s) && !s->internal->in_handshake) { + if ((ret = s->internal->handshake_func(s)) < 0) + return ret; + if (ret == 0) { SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); - return (-1); + return -1; } } start: + /* + * Do not process more than three consecutive records, otherwise the + * peer can cause us to loop indefinitely. Instead, return with an + * SSL_ERROR_WANT_READ so the caller can choose when to handle further + * processing. In the future, the total number of non-handshake and + * non-application data records per connection should probably also be + * limited... + */ + if (rrcount++ >= 3) { + ssl_force_want_read(s); + return -1; + } + s->internal->rwstate = SSL_NOTHING; - /* S3I(s)->rrec.type - is the type of record - * S3I(s)->rrec.data, - data - * S3I(s)->rrec.off, - offset into 'data' for next read - * S3I(s)->rrec.length, - number of bytes. */ - rr = &(S3I(s)->rrec); + rr = &s->s3->rrec; - /* We are not handshaking and have no data yet, - * so process data buffered during the last handshake - * in advance, if any. + /* + * We are not handshaking and have no data yet, so process data buffered + * during the last handshake in advance, if any. */ - if (S3I(s)->hs.state == SSL_ST_OK && rr->length == 0) - dtls1_retrieve_buffered_record(s, &(D1I(s)->buffered_app_data)); + if (s->s3->hs.state == SSL_ST_OK && rr->length == 0) + dtls1_retrieve_buffered_record(s, &s->d1->buffered_app_data); - /* Check for timeout */ if (dtls1_handle_timeout(s) > 0) goto start; - /* get new packet if necessary */ - if ((rr->length == 0) || (s->internal->rstate == SSL_ST_READ_BODY)) { - ret = dtls1_get_record(s); - if (ret <= 0) { - ret = dtls1_read_failed(s, ret); - /* anything other than a timeout is an error */ - if (ret <= 0) - return (ret); - else - goto start; + if (rr->length == 0 || s->internal->rstate == SSL_ST_READ_BODY) { + if ((ret = dtls1_get_record(s)) <= 0) { + /* Anything other than a timeout is an error. */ + if ((ret = dtls1_read_failed(s, ret)) <= 0) + return ret; + goto start; } } - if (D1I(s)->listen && rr->type != SSL3_RT_HANDSHAKE) { + if (s->d1->listen && rr->type != SSL3_RT_HANDSHAKE) { rr->length = 0; goto start; } - /* we now have a packet which can be read and processed */ + /* We now have a packet which can be read and processed. */ - if (S3I(s)->change_cipher_spec /* set when we receive ChangeCipherSpec, - * reset by ssl3_get_finished */ - && (rr->type != SSL3_RT_HANDSHAKE)) { - /* We now have application data between CCS and Finished. + if (s->s3->change_cipher_spec && rr->type != SSL3_RT_HANDSHAKE) { + /* + * We now have application data between CCS and Finished. * Most likely the packets were reordered on their way, so * buffer the application data for later processing rather * than dropping the connection. */ - if (dtls1_buffer_record(s, &(D1I(s)->buffered_app_data), + if (dtls1_buffer_record(s, &s->d1->buffered_app_data, rr->seq_num) < 0) { SSLerror(s, ERR_R_INTERNAL_ERROR); return (-1); @@ -595,35 +779,41 @@ dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) goto start; } - /* If the other end has shut down, throw anything we read away - * (even in 'peek' mode) */ + /* + * If the other end has shut down, throw anything we read away (even in + * 'peek' mode). + */ if (s->internal->shutdown & SSL_RECEIVED_SHUTDOWN) { - rr->length = 0; s->internal->rwstate = SSL_NOTHING; - return (0); + rr->length = 0; + return 0; } /* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */ if (type == rr->type) { - /* make sure that we are not getting application data when we - * are doing a handshake for the first time */ + /* + * Make sure that we are not getting application data when we + * are doing a handshake for the first time. + */ if (SSL_in_init(s) && type == SSL3_RT_APPLICATION_DATA && !tls12_record_layer_read_protected(s->internal->rl)) { - al = SSL_AD_UNEXPECTED_MESSAGE; SSLerror(s, SSL_R_APP_DATA_IN_HANDSHAKE); - goto fatal_err; + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); + return -1; } if (len <= 0) - return (len); + return len; if ((unsigned int)len > rr->length) n = rr->length; else n = (unsigned int)len; - memcpy(buf, &(rr->data[rr->off]), n); + memcpy(buf, &rr->data[rr->off], n); if (!peek) { + memset(&rr->data[rr->off], 0, n); rr->length -= n; rr->off += n; if (rr->length == 0) { @@ -632,7 +822,7 @@ dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) } } - return (n); + return n; } /* @@ -640,134 +830,9 @@ dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) * message, then it was unexpected (Hello Request or Client Hello). */ - { - unsigned int record_min_len = 0; - - if (rr->type == SSL3_RT_HANDSHAKE) { - record_min_len = DTLS1_HM_HEADER_LENGTH; - } else if (rr->type == SSL3_RT_ALERT) { - record_min_len = DTLS1_AL_HEADER_LENGTH; - } else if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) { - record_min_len = DTLS1_CCS_HEADER_LENGTH; - } else if (rr->type == SSL3_RT_APPLICATION_DATA) { - /* - * Application data while renegotiating is allowed. - * Try reading again. - */ - BIO *bio; - - S3I(s)->in_read_app_data = 2; - bio = SSL_get_rbio(s); - s->internal->rwstate = SSL_READING; - BIO_clear_retry_flags(bio); - BIO_set_retry_read(bio); - return (-1); - } else { - /* Not certain if this is the right error handling */ - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerror(s, SSL_R_UNEXPECTED_RECORD); - goto fatal_err; - } - - if (record_min_len > 0 && rr->length < record_min_len) { - s->internal->rstate = SSL_ST_READ_HEADER; - rr->length = 0; - goto start; - } - } - - /* If we are a client, check for an incoming 'Hello Request': */ - if (!s->server && rr->type == SSL3_RT_HANDSHAKE && - rr->length >= DTLS1_HM_HEADER_LENGTH && rr->off == 0 && - rr->data[0] == SSL3_MT_HELLO_REQUEST && - s->session != NULL && s->session->cipher != NULL) { - struct hm_header_st msg_hdr; - CBS cbs; - - CBS_init(&cbs, rr->data, rr->length); - if (!dtls1_get_message_header(&cbs, &msg_hdr)) - return -1; - if (msg_hdr.msg_len != 0) { - al = SSL_AD_DECODE_ERROR; - SSLerror(s, SSL_R_BAD_HELLO_REQUEST); - goto fatal_err; - } - rr->length = 0; - - /* no need to check sequence number on HELLO REQUEST messages */ - - ssl_msg_callback(s, 0, SSL3_RT_HANDSHAKE, rr->data, 4); - - if (SSL_is_init_finished(s) && - !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) && - !S3I(s)->renegotiate) { - D1I(s)->handshake_read_seq++; - s->internal->new_session = 1; - ssl3_renegotiate(s); - if (ssl3_renegotiate_check(s)) { - i = s->internal->handshake_func(s); - if (i < 0) - return (i); - if (i == 0) { - SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); - return (-1); - } - - if (!(s->internal->mode & SSL_MODE_AUTO_RETRY)) { - if (S3I(s)->rbuf.left == 0) /* no read-ahead left? */ - { - BIO *bio; - /* In the case where we try to read application data, - * but we trigger an SSL handshake, we return -1 with - * the retry option set. Otherwise renegotiation may - * cause nasty problems in the blocking world */ - s->internal->rwstate = SSL_READING; - bio = SSL_get_rbio(s); - BIO_clear_retry_flags(bio); - BIO_set_retry_read(bio); - return (-1); - } - } - } - } - /* we either finished a handshake or ignored the request, - * now try again to obtain the (application) data we were asked for */ - rr->length = 0; - goto start; - } - - if (rr->type == SSL3_RT_ALERT && rr->length >= DTLS1_AL_HEADER_LENGTH && - rr->off == 0) { - int alert_level = rr->data[0]; - int alert_descr = rr->data[1]; - - ssl_msg_callback(s, 0, SSL3_RT_ALERT, rr->data, 2); - - ssl_info_callback(s, SSL_CB_READ_ALERT, - (alert_level << 8) | alert_descr); - - if (alert_level == SSL3_AL_WARNING) { - S3I(s)->warn_alert = alert_descr; - if (alert_descr == SSL_AD_CLOSE_NOTIFY) { - s->internal->shutdown |= SSL_RECEIVED_SHUTDOWN; - return (0); - } - } else if (alert_level == SSL3_AL_FATAL) { - s->internal->rwstate = SSL_NOTHING; - S3I(s)->fatal_alert = alert_descr; - SSLerror(s, SSL_AD_REASON_OFFSET + alert_descr); - ERR_asprintf_error_data("SSL alert number %d", - alert_descr); - s->internal->shutdown|=SSL_RECEIVED_SHUTDOWN; - SSL_CTX_remove_session(s->ctx, s->session); - return (0); - } else { - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerror(s, SSL_R_UNKNOWN_ALERT_TYPE); - goto fatal_err; - } - - rr->length = 0; + if (rr->type == SSL3_RT_ALERT) { + if ((ret = ssl3_read_alert(s)) <= 0) + return ret; goto start; } @@ -777,142 +842,48 @@ dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) return (0); } - if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) { - /* 'Change Cipher Spec' is just a single byte, so we know - * exactly what the record payload has to look like */ - /* XDTLS: check that epoch is consistent */ - if ((rr->length != DTLS1_CCS_HEADER_LENGTH) || - (rr->off != 0) || (rr->data[0] != SSL3_MT_CCS)) { - al = SSL_AD_DECODE_ERROR; - SSLerror(s, SSL_R_BAD_CHANGE_CIPHER_SPEC); - goto fatal_err; - } - - ssl_msg_callback(s, 0, SSL3_RT_CHANGE_CIPHER_SPEC, rr->data, 1); - - /* We can't process a CCS now, because previous handshake - * messages are still missing, so just drop it. + if (rr->type == SSL3_RT_APPLICATION_DATA) { + /* + * At this point, we were expecting handshake data, but have + * application data. If the library was running inside + * ssl3_read() (i.e. in_read_app_data is set) and it makes + * sense to read application data at this point (session + * renegotiation not yet started), we will indulge it. */ - if (!D1I(s)->change_cipher_spec_ok) { - rr->length = 0; - goto start; - } - - D1I(s)->change_cipher_spec_ok = 0; - - S3I(s)->change_cipher_spec = 1; - if (!ssl3_do_change_cipher_spec(s)) - goto err; - - rr->length = 0; - goto start; - } - - /* Unexpected handshake message (Client Hello, or protocol violation) */ - if (rr->type == SSL3_RT_HANDSHAKE && - rr->length >= DTLS1_HM_HEADER_LENGTH && rr->off == 0 && - !s->internal->in_handshake) { - struct hm_header_st msg_hdr; - CBS cbs; - - /* this may just be a stale retransmit */ - CBS_init(&cbs, rr->data, rr->length); - if (!dtls1_get_message_header(&cbs, &msg_hdr)) + if (s->s3->in_read_app_data != 0 && + s->s3->total_renegotiations != 0 && + (((s->s3->hs.state & SSL_ST_CONNECT) && + (s->s3->hs.state >= SSL3_ST_CW_CLNT_HELLO_A) && + (s->s3->hs.state <= SSL3_ST_CR_SRVR_HELLO_A)) || ( + (s->s3->hs.state & SSL_ST_ACCEPT) && + (s->s3->hs.state <= SSL3_ST_SW_HELLO_REQ_A) && + (s->s3->hs.state >= SSL3_ST_SR_CLNT_HELLO_A)))) { + s->s3->in_read_app_data = 2; + return -1; + } else { + SSLerror(s, SSL_R_UNEXPECTED_RECORD); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); return -1; - if (rr->epoch != tls12_record_layer_read_epoch(s->internal->rl)) { - rr->length = 0; - goto start; } + } - /* If we are server, we may have a repeated FINISHED of the - * client here, then retransmit our CCS and FINISHED. - */ - if (msg_hdr.type == SSL3_MT_FINISHED) { - if (dtls1_check_timeout_num(s) < 0) - return -1; - - dtls1_retransmit_buffered_messages(s); - rr->length = 0; - goto start; - } - - if (((S3I(s)->hs.state&SSL_ST_MASK) == SSL_ST_OK) && - !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) { - S3I(s)->hs.state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; - s->internal->renegotiate = 1; - s->internal->new_session = 1; - } - i = s->internal->handshake_func(s); - if (i < 0) - return (i); - if (i == 0) { - SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); - return (-1); - } - - if (!(s->internal->mode & SSL_MODE_AUTO_RETRY)) { - if (S3I(s)->rbuf.left == 0) /* no read-ahead left? */ - { - BIO *bio; - /* In the case where we try to read application data, - * but we trigger an SSL handshake, we return -1 with - * the retry option set. Otherwise renegotiation may - * cause nasty problems in the blocking world */ - s->internal->rwstate = SSL_READING; - bio = SSL_get_rbio(s); - BIO_clear_retry_flags(bio); - BIO_set_retry_read(bio); - return (-1); - } - } - rr->length = 0; + if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) { + if ((ret = ssl3_read_change_cipher_spec(s)) <= 0) + return ret; goto start; } - switch (rr->type) { - default: - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerror(s, SSL_R_UNEXPECTED_RECORD); - goto fatal_err; - case SSL3_RT_CHANGE_CIPHER_SPEC: - case SSL3_RT_ALERT: - case SSL3_RT_HANDSHAKE: - /* we already handled all of these, with the possible exception - * of SSL3_RT_HANDSHAKE when s->internal->in_handshake is set, but that - * should not happen when type != rr->type */ - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerror(s, ERR_R_INTERNAL_ERROR); - goto fatal_err; - case SSL3_RT_APPLICATION_DATA: - /* At this point, we were expecting handshake data, - * but have application data. If the library was - * running inside ssl3_read() (i.e. in_read_app_data - * is set) and it makes sense to read application data - * at this point (session renegotiation not yet started), - * we will indulge it. - */ - if (S3I(s)->in_read_app_data && - (S3I(s)->total_renegotiations != 0) && - (((S3I(s)->hs.state & SSL_ST_CONNECT) && - (S3I(s)->hs.state >= SSL3_ST_CW_CLNT_HELLO_A) && - (S3I(s)->hs.state <= SSL3_ST_CR_SRVR_HELLO_A)) || ( - (S3I(s)->hs.state & SSL_ST_ACCEPT) && - (S3I(s)->hs.state <= SSL3_ST_SW_HELLO_REQ_A) && - (S3I(s)->hs.state >= SSL3_ST_SR_CLNT_HELLO_A)))) { - S3I(s)->in_read_app_data = 2; - return (-1); - } else { - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerror(s, SSL_R_UNEXPECTED_RECORD); - goto fatal_err; - } + if (rr->type == SSL3_RT_HANDSHAKE) { + if ((ret = dtls1_read_handshake_unexpected(s)) <= 0) + return ret; + goto start; } - /* not reached */ - fatal_err: - ssl3_send_alert(s, SSL3_AL_FATAL, al); - err: - return (-1); + /* Unknown record type. */ + SSLerror(s, SSL_R_UNEXPECTED_RECORD); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + return -1; } int @@ -957,7 +928,7 @@ dtls1_write_bytes(SSL *s, int type, const void *buf, int len) int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len) { - SSL3_BUFFER_INTERNAL *wb = &(S3I(s)->wbuf); + SSL3_BUFFER_INTERNAL *wb = &(s->s3->wbuf); size_t out_len; CBB cbb; int ret; @@ -974,7 +945,7 @@ do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len) } /* If we have an alert to send, let's send it */ - if (S3I(s)->alert_dispatch) { + if (s->s3->alert_dispatch) { if ((ret = ssl3_dispatch_alert(s)) <= 0) return (ret); /* If it went, fall through and send more stuff. */ @@ -1002,10 +973,10 @@ do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len) * Memorize arguments so that ssl3_write_pending can detect * bad write retries later. */ - S3I(s)->wpend_tot = len; - S3I(s)->wpend_buf = buf; - S3I(s)->wpend_type = type; - S3I(s)->wpend_ret = len; + s->s3->wpend_tot = len; + s->s3->wpend_buf = buf; + s->s3->wpend_type = type; + s->s3->wpend_ret = len; /* We now just need to write the buffer. */ return ssl3_write_pending(s, type, buf, len); @@ -1069,13 +1040,13 @@ dtls1_get_bitmap(SSL *s, SSL3_RECORD_INTERNAL *rr, unsigned int *is_next_epoch) /* In current epoch, accept HM, CCS, DATA, & ALERT */ if (rr->epoch == read_epoch) - return &D1I(s)->bitmap; + return &s->d1->bitmap; /* Only HM and ALERT messages can be from the next epoch */ if (rr->epoch == read_epoch_next && (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) { *is_next_epoch = 1; - return &D1I(s)->next_bitmap; + return &s->d1->next_bitmap; } return NULL; @@ -1084,6 +1055,6 @@ dtls1_get_bitmap(SSL *s, SSL3_RECORD_INTERNAL *rr, unsigned int *is_next_epoch) void dtls1_reset_read_seq_numbers(SSL *s) { - memcpy(&(D1I(s)->bitmap), &(D1I(s)->next_bitmap), sizeof(DTLS1_BITMAP)); - memset(&(D1I(s)->next_bitmap), 0, sizeof(DTLS1_BITMAP)); + memcpy(&(s->d1->bitmap), &(s->d1->next_bitmap), sizeof(DTLS1_BITMAP)); + memset(&(s->d1->next_bitmap), 0, sizeof(DTLS1_BITMAP)); } diff --git a/ssl/d1_srtp.c b/ssl/d1_srtp.c index 70f9453..793fa86 100644 --- a/ssl/d1_srtp.c +++ b/ssl/d1_srtp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: d1_srtp.c,v 1.29 2021/06/11 15:28:13 landry Exp $ */ +/* $OpenBSD: d1_srtp.c,v 1.30 2022/01/28 13:11:56 inoguchi Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -204,7 +204,10 @@ ssl_ctx_make_profiles(const char *profiles_string, if (!srtp_find_profile_by_name(ptr, &p, col ? col - ptr : (int)strlen(ptr))) { - sk_SRTP_PROTECTION_PROFILE_push(profiles, p); + if (!sk_SRTP_PROTECTION_PROFILE_push(profiles, p)) { + sk_SRTP_PROTECTION_PROFILE_free(profiles); + return 1; + } } else { SSLerrorx(SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE); sk_SRTP_PROTECTION_PROFILE_free(profiles); diff --git a/ssl/dtls_locl.h b/ssl/dtls_locl.h index 4cf8827..da5c259 100644 --- a/ssl/dtls_locl.h +++ b/ssl/dtls_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dtls_locl.h,v 1.7 2021/09/04 14:24:28 jsing Exp $ */ +/* $OpenBSD: dtls_locl.h,v 1.10 2021/10/23 13:45:44 jsing Exp $ */ /* * DTLS implementation written by Nagendra Modadugu * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. @@ -77,8 +77,6 @@ typedef struct dtls1_bitmap_st { } DTLS1_BITMAP; struct dtls1_retransmit_state { - EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */ - EVP_MD_CTX *write_hash; /* used for mac generation */ SSL_SESSION *session; unsigned short epoch; }; @@ -124,9 +122,16 @@ typedef struct dtls1_record_data_internal_st { SSL3_RECORD_INTERNAL rrec; } DTLS1_RECORD_DATA_INTERNAL; -struct dtls1_state_internal_st; +struct dtls1_state_st { + /* Buffered (sent) handshake records */ + struct _pqueue *sent_messages; + + /* Indicates when the last handshake msg or heartbeat sent will timeout */ + struct timeval next_timeout; + + /* Timeout duration */ + unsigned short timeout_duration; -typedef struct dtls1_state_internal_st { unsigned int send_cookie; unsigned char cookie[DTLS1_COOKIE_LENGTH]; unsigned char rcvd_cookie[DTLS1_COOKIE_LENGTH]; @@ -169,21 +174,7 @@ typedef struct dtls1_state_internal_st { unsigned int retransmitting; unsigned int change_cipher_spec_ok; -} DTLS1_STATE_INTERNAL; -#define D1I(s) (s->d1->internal) - -typedef struct dtls1_state_st { - /* Buffered (sent) handshake records */ - struct _pqueue *sent_messages; - - /* Indicates when the last handshake msg or heartbeat sent will timeout */ - struct timeval next_timeout; - - /* Timeout duration */ - unsigned short timeout_duration; - - struct dtls1_state_internal_st *internal; -} DTLS1_STATE; +}; int dtls1_do_write(SSL *s, int type); int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek); @@ -223,7 +214,7 @@ void dtls1_free(SSL *s); void dtls1_clear(SSL *s); long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg); -long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok); +int dtls1_get_message(SSL *s, int st1, int stn, int mt, long max); int dtls1_get_record(SSL *s); __END_HIDDEN_DECLS diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c index 1c0286f..e0289d8 100644 --- a/ssl/s3_cbc.c +++ b/ssl/s3_cbc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: s3_cbc.c,v 1.24 2021/05/16 14:10:43 jsing Exp $ */ +/* $OpenBSD: s3_cbc.c,v 1.25 2021/12/09 17:45:49 tb Exp $ */ /* ==================================================================== * Copyright (c) 2012 The OpenSSL Project. All rights reserved. * @@ -404,7 +404,7 @@ ssl3_cbc_digest_record(const EVP_MD_CTX *ctx, unsigned char* md_out, unsigned char first_block[MAX_HASH_BLOCK_SIZE]; unsigned char mac_out[EVP_MAX_MD_SIZE]; unsigned int i, j, md_out_size_u; - EVP_MD_CTX md_ctx; + EVP_MD_CTX *md_ctx; /* mdLengthSize is the number of bytes in the length field that terminates * the hash. */ unsigned int md_length_size = 8; @@ -605,9 +605,10 @@ ssl3_cbc_digest_record(const EVP_MD_CTX *ctx, unsigned char* md_out, mac_out[j] |= block[j]&is_block_b; } - EVP_MD_CTX_init(&md_ctx); - if (!EVP_DigestInit_ex(&md_ctx, ctx->digest, NULL /* engine */)) { - EVP_MD_CTX_cleanup(&md_ctx); + if ((md_ctx = EVP_MD_CTX_new()) == NULL) + return 0; + if (!EVP_DigestInit_ex(md_ctx, EVP_MD_CTX_md(ctx), NULL /* engine */)) { + EVP_MD_CTX_free(md_ctx); return 0; } @@ -615,13 +616,13 @@ ssl3_cbc_digest_record(const EVP_MD_CTX *ctx, unsigned char* md_out, for (i = 0; i < md_block_size; i++) hmac_pad[i] ^= 0x6a; - EVP_DigestUpdate(&md_ctx, hmac_pad, md_block_size); - EVP_DigestUpdate(&md_ctx, mac_out, md_size); + EVP_DigestUpdate(md_ctx, hmac_pad, md_block_size); + EVP_DigestUpdate(md_ctx, mac_out, md_size); - EVP_DigestFinal(&md_ctx, md_out, &md_out_size_u); + EVP_DigestFinal(md_ctx, md_out, &md_out_size_u); if (md_out_size) *md_out_size = md_out_size_u; - EVP_MD_CTX_cleanup(&md_ctx); + EVP_MD_CTX_free(md_ctx); return 1; } diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index e78b70f..624841a 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: s3_lib.c,v 1.215 2021/09/08 12:56:14 tb Exp $ */ +/* $OpenBSD: s3_lib.c,v 1.228 2022/03/17 17:24:37 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -162,6 +162,7 @@ #include "dtls_locl.h" #include "ssl_locl.h" #include "ssl_sigalgs.h" +#include "ssl_tlsext.h" #define SSL3_NUM_CIPHERS (sizeof(ssl3_ciphers) / sizeof(SSL_CIPHER)) @@ -881,7 +882,7 @@ const SSL_CIPHER ssl3_ciphers[] = { /* Cipher 1301 */ { .valid = 1, - .name = TLS1_3_TXT_AES_128_GCM_SHA256, + .name = TLS1_3_RFC_AES_128_GCM_SHA256, .id = TLS1_3_CK_AES_128_GCM_SHA256, .algorithm_mkey = SSL_kTLS1_3, .algorithm_auth = SSL_aTLS1_3, @@ -897,7 +898,7 @@ const SSL_CIPHER ssl3_ciphers[] = { /* Cipher 1302 */ { .valid = 1, - .name = TLS1_3_TXT_AES_256_GCM_SHA384, + .name = TLS1_3_RFC_AES_256_GCM_SHA384, .id = TLS1_3_CK_AES_256_GCM_SHA384, .algorithm_mkey = SSL_kTLS1_3, .algorithm_auth = SSL_aTLS1_3, @@ -913,7 +914,7 @@ const SSL_CIPHER ssl3_ciphers[] = { /* Cipher 1303 */ { .valid = 1, - .name = TLS1_3_TXT_CHACHA20_POLY1305_SHA256, + .name = TLS1_3_RFC_CHACHA20_POLY1305_SHA256, .id = TLS1_3_CK_CHACHA20_POLY1305_SHA256, .algorithm_mkey = SSL_kTLS1_3, .algorithm_auth = SSL_aTLS1_3, @@ -1443,8 +1444,8 @@ ssl3_pending(const SSL *s) if (s->internal->rstate == SSL_ST_READ_BODY) return 0; - return (S3I(s)->rrec.type == SSL3_RT_APPLICATION_DATA) ? - S3I(s)->rrec.length : 0; + return (s->s3->rrec.type == SSL3_RT_APPLICATION_DATA) ? + s->s3->rrec.length : 0; } int @@ -1543,10 +1544,6 @@ ssl3_new(SSL *s) { if ((s->s3 = calloc(1, sizeof(*s->s3))) == NULL) return (0); - if ((S3I(s) = calloc(1, sizeof(*S3I(s)))) == NULL) { - free(s->s3); - return (0); - } s->method->ssl_clear(s); @@ -1562,25 +1559,22 @@ ssl3_free(SSL *s) tls1_cleanup_key_block(s); ssl3_release_read_buffer(s); ssl3_release_write_buffer(s); - freezero(S3I(s)->hs.sigalgs, S3I(s)->hs.sigalgs_len); + freezero(s->s3->hs.sigalgs, s->s3->hs.sigalgs_len); - DH_free(S3I(s)->tmp.dh); - EC_KEY_free(S3I(s)->tmp.ecdh); - freezero(S3I(s)->tmp.x25519, X25519_KEY_LENGTH); + tls_key_share_free(s->s3->hs.key_share); - tls13_key_share_free(S3I(s)->hs.tls13.key_share); - tls13_secrets_destroy(S3I(s)->hs.tls13.secrets); - freezero(S3I(s)->hs.tls13.cookie, S3I(s)->hs.tls13.cookie_len); - tls13_clienthello_hash_clear(&S3I(s)->hs.tls13); + tls13_secrets_destroy(s->s3->hs.tls13.secrets); + freezero(s->s3->hs.tls13.cookie, s->s3->hs.tls13.cookie_len); + tls13_clienthello_hash_clear(&s->s3->hs.tls13); - sk_X509_NAME_pop_free(S3I(s)->hs.tls12.ca_names, X509_NAME_free); + sk_X509_NAME_pop_free(s->s3->hs.tls12.ca_names, X509_NAME_free); + sk_X509_pop_free(s->internal->verified_chain, X509_free); tls1_transcript_free(s); tls1_transcript_hash_free(s); - free(S3I(s)->alpn_selected); + free(s->s3->alpn_selected); - freezero(S3I(s), sizeof(*S3I(s))); freezero(s->s3, sizeof(*s->s3)); s->s3 = NULL; @@ -1589,106 +1583,78 @@ ssl3_free(SSL *s) void ssl3_clear(SSL *s) { - struct ssl3_state_internal_st *internal; unsigned char *rp, *wp; size_t rlen, wlen; tls1_cleanup_key_block(s); - sk_X509_NAME_pop_free(S3I(s)->hs.tls12.ca_names, X509_NAME_free); + sk_X509_NAME_pop_free(s->s3->hs.tls12.ca_names, X509_NAME_free); + sk_X509_pop_free(s->internal->verified_chain, X509_free); + s->internal->verified_chain = NULL; - DH_free(S3I(s)->tmp.dh); - S3I(s)->tmp.dh = NULL; - EC_KEY_free(S3I(s)->tmp.ecdh); - S3I(s)->tmp.ecdh = NULL; - S3I(s)->tmp.ecdh_nid = NID_undef; - freezero(S3I(s)->tmp.x25519, X25519_KEY_LENGTH); - S3I(s)->tmp.x25519 = NULL; + freezero(s->s3->hs.sigalgs, s->s3->hs.sigalgs_len); + s->s3->hs.sigalgs = NULL; + s->s3->hs.sigalgs_len = 0; - freezero(S3I(s)->hs.sigalgs, S3I(s)->hs.sigalgs_len); - S3I(s)->hs.sigalgs = NULL; - S3I(s)->hs.sigalgs_len = 0; + tls_key_share_free(s->s3->hs.key_share); + s->s3->hs.key_share = NULL; - tls13_key_share_free(S3I(s)->hs.tls13.key_share); - S3I(s)->hs.tls13.key_share = NULL; + tls13_secrets_destroy(s->s3->hs.tls13.secrets); + s->s3->hs.tls13.secrets = NULL; + freezero(s->s3->hs.tls13.cookie, s->s3->hs.tls13.cookie_len); + s->s3->hs.tls13.cookie = NULL; + s->s3->hs.tls13.cookie_len = 0; + tls13_clienthello_hash_clear(&s->s3->hs.tls13); - tls13_secrets_destroy(S3I(s)->hs.tls13.secrets); - S3I(s)->hs.tls13.secrets = NULL; - freezero(S3I(s)->hs.tls13.cookie, S3I(s)->hs.tls13.cookie_len); - S3I(s)->hs.tls13.cookie = NULL; - S3I(s)->hs.tls13.cookie_len = 0; - tls13_clienthello_hash_clear(&S3I(s)->hs.tls13); + s->s3->hs.extensions_seen = 0; - S3I(s)->hs.extensions_seen = 0; - - rp = S3I(s)->rbuf.buf; - wp = S3I(s)->wbuf.buf; - rlen = S3I(s)->rbuf.len; - wlen = S3I(s)->wbuf.len; + rp = s->s3->rbuf.buf; + wp = s->s3->wbuf.buf; + rlen = s->s3->rbuf.len; + wlen = s->s3->wbuf.len; tls1_transcript_free(s); tls1_transcript_hash_free(s); - free(S3I(s)->alpn_selected); - S3I(s)->alpn_selected = NULL; - S3I(s)->alpn_selected_len = 0; + free(s->s3->alpn_selected); + s->s3->alpn_selected = NULL; + s->s3->alpn_selected_len = 0; - memset(S3I(s), 0, sizeof(*S3I(s))); - internal = S3I(s); memset(s->s3, 0, sizeof(*s->s3)); - S3I(s) = internal; - S3I(s)->rbuf.buf = rp; - S3I(s)->wbuf.buf = wp; - S3I(s)->rbuf.len = rlen; - S3I(s)->wbuf.len = wlen; + s->s3->rbuf.buf = rp; + s->s3->wbuf.buf = wp; + s->s3->rbuf.len = rlen; + s->s3->wbuf.len = wlen; ssl_free_wbio_buffer(s); /* Not needed... */ - S3I(s)->renegotiate = 0; - S3I(s)->total_renegotiations = 0; - S3I(s)->num_renegotiations = 0; - S3I(s)->in_read_app_data = 0; + s->s3->renegotiate = 0; + s->s3->total_renegotiations = 0; + s->s3->num_renegotiations = 0; + s->s3->in_read_app_data = 0; s->internal->packet_length = 0; s->version = TLS1_VERSION; - S3I(s)->hs.state = SSL_ST_BEFORE|((s->server) ? SSL_ST_ACCEPT : SSL_ST_CONNECT); + s->s3->hs.state = SSL_ST_BEFORE|((s->server) ? SSL_ST_ACCEPT : SSL_ST_CONNECT); } long _SSL_get_peer_tmp_key(SSL *s, EVP_PKEY **key) { EVP_PKEY *pkey = NULL; - SESS_CERT *sc; int ret = 0; *key = NULL; - if (s->session == NULL || SSI(s)->sess_cert == NULL) - return 0; - - sc = SSI(s)->sess_cert; + if (s->s3->hs.key_share == NULL) + goto err; if ((pkey = EVP_PKEY_new()) == NULL) - return 0; - - if (sc->peer_dh_tmp != NULL) { - if (!EVP_PKEY_set1_DH(pkey, sc->peer_dh_tmp)) - goto err; - } else if (sc->peer_ecdh_tmp) { - if (!EVP_PKEY_set1_EC_KEY(pkey, sc->peer_ecdh_tmp)) - goto err; - } else if (sc->peer_x25519_tmp != NULL) { - if (!ssl_kex_dummy_ecdhe_x25519(pkey)) - goto err; - } else if (S3I(s)->hs.tls13.key_share != NULL) { - if (!tls13_key_share_peer_pkey(S3I(s)->hs.tls13.key_share, - pkey)) - goto err; - } else { goto err; - } + if (!tls_key_share_peer_pkey(s->s3->hs.key_share, pkey)) + goto err; *key = pkey; pkey = NULL; @@ -1710,7 +1676,7 @@ _SSL_session_reused(SSL *s) static int _SSL_num_renegotiations(SSL *s) { - return S3I(s)->num_renegotiations; + return s->s3->num_renegotiations; } static int @@ -1718,8 +1684,8 @@ _SSL_clear_num_renegotiations(SSL *s) { int renegs; - renegs = S3I(s)->num_renegotiations; - S3I(s)->num_renegotiations = 0; + renegs = s->s3->num_renegotiations; + s->s3->num_renegotiations = 0; return renegs; } @@ -1727,26 +1693,26 @@ _SSL_clear_num_renegotiations(SSL *s) static int _SSL_total_renegotiations(SSL *s) { - return S3I(s)->total_renegotiations; + return s->s3->total_renegotiations; } static int _SSL_set_tmp_dh(SSL *s, DH *dh) { - DH *dh_tmp; + DH *dhe_params; if (dh == NULL) { SSLerror(s, ERR_R_PASSED_NULL_PARAMETER); return 0; } - if ((dh_tmp = DHparams_dup(dh)) == NULL) { + if ((dhe_params = DHparams_dup(dh)) == NULL) { SSLerror(s, ERR_R_DH_LIB); return 0; } - DH_free(s->cert->dh_tmp); - s->cert->dh_tmp = dh_tmp; + DH_free(s->cert->dhe_params); + s->cert->dhe_params = dhe_params; return 1; } @@ -1754,7 +1720,7 @@ _SSL_set_tmp_dh(SSL *s, DH *dh) static int _SSL_set_dh_auto(SSL *s, int state) { - s->cert->dh_tmp_auto = state; + s->cert->dhe_params_auto = state; return 1; } @@ -1782,17 +1748,21 @@ _SSL_set_ecdh_auto(SSL *s, int state) static int _SSL_set_tlsext_host_name(SSL *s, const char *name) { + int is_ip; + CBS cbs; + free(s->tlsext_hostname); s->tlsext_hostname = NULL; if (name == NULL) return 1; - if (strlen(name) > TLSEXT_MAXLEN_host_name) { + CBS_init(&cbs, name, strlen(name)); + + if (!tlsext_sni_is_valid_hostname(&cbs, &is_ip)) { SSLerror(s, SSL_R_SSL3_EXT_INVALID_SERVERNAME); return 0; } - if ((s->tlsext_hostname = strdup(name)) == NULL) { SSLerror(s, ERR_R_INTERNAL_ERROR); return 0; @@ -1941,7 +1911,7 @@ _SSL_get_signature_nid(SSL *s, int *nid) { const struct ssl_sigalg *sigalg; - if ((sigalg = S3I(s)->hs.our_sigalg) == NULL) + if ((sigalg = s->s3->hs.our_sigalg) == NULL) return 0; *nid = EVP_MD_type(sigalg->md()); @@ -1954,7 +1924,7 @@ _SSL_get_peer_signature_nid(SSL *s, int *nid) { const struct ssl_sigalg *sigalg; - if ((sigalg = S3I(s)->hs.peer_sigalg) == NULL) + if ((sigalg = s->s3->hs.peer_sigalg) == NULL) return 0; *nid = EVP_MD_type(sigalg->md()); @@ -1967,7 +1937,7 @@ SSL_get_signature_type_nid(const SSL *s, int *nid) { const struct ssl_sigalg *sigalg; - if ((sigalg = S3I(s)->hs.our_sigalg) == NULL) + if ((sigalg = s->s3->hs.our_sigalg) == NULL) return 0; *nid = sigalg->key_type; @@ -1983,7 +1953,7 @@ SSL_get_peer_signature_type_nid(const SSL *s, int *nid) { const struct ssl_sigalg *sigalg; - if ((sigalg = S3I(s)->hs.peer_sigalg) == NULL) + if ((sigalg = s->s3->hs.peer_sigalg) == NULL) return 0; *nid = sigalg->key_type; @@ -2143,7 +2113,7 @@ ssl3_callback_ctrl(SSL *s, int cmd, void (*fp)(void)) return 0; case SSL_CTRL_SET_TMP_DH_CB: - s->cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp; + s->cert->dhe_params_cb = (DH *(*)(SSL *, int, int))fp; return 1; case SSL_CTRL_SET_TMP_ECDH_CB: @@ -2161,15 +2131,20 @@ ssl3_callback_ctrl(SSL *s, int cmd, void (*fp)(void)) static int _SSL_CTX_set_tmp_dh(SSL_CTX *ctx, DH *dh) { - DH *dh_tmp; + DH *dhe_params; - if ((dh_tmp = DHparams_dup(dh)) == NULL) { + if (dh == NULL) { + SSLerrorx(ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if ((dhe_params = DHparams_dup(dh)) == NULL) { SSLerrorx(ERR_R_DH_LIB); return 0; } - DH_free(ctx->internal->cert->dh_tmp); - ctx->internal->cert->dh_tmp = dh_tmp; + DH_free(ctx->internal->cert->dhe_params); + ctx->internal->cert->dhe_params = dhe_params; return 1; } @@ -2177,7 +2152,7 @@ _SSL_CTX_set_tmp_dh(SSL_CTX *ctx, DH *dh) static int _SSL_CTX_set_dh_auto(SSL_CTX *ctx, int state) { - ctx->internal->cert->dh_tmp_auto = state; + ctx->internal->cert->dhe_params_auto = state; return 1; } @@ -2464,7 +2439,7 @@ ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void)) return 0; case SSL_CTRL_SET_TMP_DH_CB: - ctx->internal->cert->dh_tmp_cb = + ctx->internal->cert->dhe_params_cb = (DH *(*)(SSL *, int, int))fp; return 1; @@ -2502,7 +2477,7 @@ ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, SSL_CIPHER *c, *ret = NULL; int can_use_ecc; int i, ii, ok; - CERT *cert; + SSL_CERT *cert; /* Let's see which ciphers we can support */ cert = s->cert; @@ -2580,7 +2555,7 @@ ssl3_get_req_cert_types(SSL *s, CBB *cbb) { unsigned long alg_k; - alg_k = S3I(s)->hs.cipher->algorithm_mkey; + alg_k = s->s3->hs.cipher->algorithm_mkey; #ifndef OPENSSL_NO_GOST if ((alg_k & SSL_kGOST) != 0) { @@ -2624,7 +2599,7 @@ ssl3_shutdown(SSL *s) * Don't do anything much if we have not done the handshake or * we don't want to send messages :-) */ - if ((s->internal->quiet_shutdown) || (S3I(s)->hs.state == SSL_ST_BEFORE)) { + if ((s->internal->quiet_shutdown) || (s->s3->hs.state == SSL_ST_BEFORE)) { s->internal->shutdown = (SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); return (1); } @@ -2634,11 +2609,11 @@ ssl3_shutdown(SSL *s) ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_CLOSE_NOTIFY); /* * Our shutdown alert has been sent now, and if it still needs - * to be written, S3I(s)->alert_dispatch will be true + * to be written, s->s3->alert_dispatch will be true */ - if (S3I(s)->alert_dispatch) - return(-1); /* return WANT_WRITE */ - } else if (S3I(s)->alert_dispatch) { + if (s->s3->alert_dispatch) + return (-1); /* return WANT_WRITE */ + } else if (s->s3->alert_dispatch) { /* resend it if not sent */ ret = ssl3_dispatch_alert(s); if (ret == -1) { @@ -2654,12 +2629,12 @@ ssl3_shutdown(SSL *s) /* If we are waiting for a close from our peer, we are closed */ s->method->ssl_read_bytes(s, 0, NULL, 0, 0); if (!(s->internal->shutdown & SSL_RECEIVED_SHUTDOWN)) { - return(-1); /* return WANT_READ */ + return (-1); /* return WANT_READ */ } } if ((s->internal->shutdown == (SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN)) && - !S3I(s)->alert_dispatch) + !s->s3->alert_dispatch) return (1); else return (0); @@ -2670,7 +2645,7 @@ ssl3_write(SSL *s, const void *buf, int len) { errno = 0; - if (S3I(s)->renegotiate) + if (s->s3->renegotiate) ssl3_renegotiate_check(s); return s->method->ssl_write_bytes(s, SSL3_RT_APPLICATION_DATA, @@ -2683,13 +2658,13 @@ ssl3_read_internal(SSL *s, void *buf, int len, int peek) int ret; errno = 0; - if (S3I(s)->renegotiate) + if (s->s3->renegotiate) ssl3_renegotiate_check(s); - S3I(s)->in_read_app_data = 1; + s->s3->in_read_app_data = 1; ret = s->method->ssl_read_bytes(s, SSL3_RT_APPLICATION_DATA, buf, len, peek); - if ((ret == -1) && (S3I(s)->in_read_app_data == 2)) { + if ((ret == -1) && (s->s3->in_read_app_data == 2)) { /* * ssl3_read_bytes decided to call s->internal->handshake_func, * which called ssl3_read_bytes to read handshake data. @@ -2702,7 +2677,7 @@ ssl3_read_internal(SSL *s, void *buf, int len, int peek) buf, len, peek); s->internal->in_handshake--; } else - S3I(s)->in_read_app_data = 0; + s->s3->in_read_app_data = 0; return (ret); } @@ -2723,35 +2698,28 @@ int ssl3_renegotiate(SSL *s) { if (s->internal->handshake_func == NULL) - return (1); + return 1; if (s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) - return (0); + return 0; - S3I(s)->renegotiate = 1; - return (1); + s->s3->renegotiate = 1; + + return 1; } int ssl3_renegotiate_check(SSL *s) { - int ret = 0; + if (!s->s3->renegotiate) + return 0; + if (SSL_in_init(s) || s->s3->rbuf.left != 0 || s->s3->wbuf.left != 0) + return 0; - if (S3I(s)->renegotiate) { - if ((S3I(s)->rbuf.left == 0) && (S3I(s)->wbuf.left == 0) && - !SSL_in_init(s)) { - /* - * If we are the server, and we have sent - * a 'RENEGOTIATE' message, we need to go - * to SSL_ST_ACCEPT. - */ - /* SSL_ST_ACCEPT */ - S3I(s)->hs.state = SSL_ST_RENEGOTIATE; - S3I(s)->renegotiate = 0; - S3I(s)->num_renegotiations++; - S3I(s)->total_renegotiations++; - ret = 1; - } - } - return (ret); + s->s3->hs.state = SSL_ST_RENEGOTIATE; + s->s3->renegotiate = 0; + s->s3->num_renegotiations++; + s->s3->total_renegotiations++; + + return 1; } diff --git a/ssl/ssl.sym b/ssl/ssl.sym index ec329e7..d18bcc4 100644 --- a/ssl/ssl.sym +++ b/ssl/ssl.sym @@ -75,9 +75,11 @@ SSL_CTX_get_default_passwd_cb_userdata SSL_CTX_get_ex_data SSL_CTX_get_ex_new_index SSL_CTX_get_info_callback +SSL_CTX_get_keylog_callback SSL_CTX_get_max_early_data SSL_CTX_get_max_proto_version SSL_CTX_get_min_proto_version +SSL_CTX_get_num_tickets SSL_CTX_get_quiet_shutdown SSL_CTX_get_ssl_method SSL_CTX_get_timeout @@ -117,12 +119,14 @@ SSL_CTX_set_default_verify_paths SSL_CTX_set_ex_data SSL_CTX_set_generate_session_id SSL_CTX_set_info_callback +SSL_CTX_set_keylog_callback SSL_CTX_set_max_early_data SSL_CTX_set_max_proto_version SSL_CTX_set_min_proto_version SSL_CTX_set_msg_callback SSL_CTX_set_next_proto_select_cb SSL_CTX_set_next_protos_advertised_cb +SSL_CTX_set_num_tickets SSL_CTX_set_post_handshake_auth SSL_CTX_set_purpose SSL_CTX_set_quiet_shutdown @@ -202,6 +206,7 @@ SSL_get0_chain_certs SSL_get0_next_proto_negotiated SSL_get0_param SSL_get0_peername +SSL_get0_verified_chain SSL_get1_session SSL_get1_supported_ciphers SSL_get_SSL_CTX @@ -226,6 +231,7 @@ SSL_get_info_callback SSL_get_max_early_data SSL_get_max_proto_version SSL_get_min_proto_version +SSL_get_num_tickets SSL_get_peer_cert_chain SSL_get_peer_certificate SSL_get_peer_finished @@ -258,9 +264,11 @@ SSL_load_client_CA_file SSL_load_error_strings SSL_new SSL_peek +SSL_peek_ex SSL_pending SSL_read SSL_read_early_data +SSL_read_ex SSL_renegotiate SSL_renegotiate_abbreviated SSL_renegotiate_pending @@ -292,6 +300,7 @@ SSL_set_max_early_data SSL_set_max_proto_version SSL_set_min_proto_version SSL_set_msg_callback +SSL_set_num_tickets SSL_set_post_handshake_auth SSL_set_psk_use_session_callback SSL_set_purpose @@ -336,4 +345,5 @@ SSL_version_str SSL_want SSL_write SSL_write_early_data +SSL_write_ex OPENSSL_init_ssl diff --git a/ssl/ssl_algs.c b/ssl/ssl_algs.c index 5ed56b8..5ecbb34 100644 --- a/ssl/ssl_algs.c +++ b/ssl/ssl_algs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_algs.c,v 1.29 2021/05/16 08:24:21 jsing Exp $ */ +/* $OpenBSD: ssl_algs.c,v 1.30 2022/01/14 08:38:48 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -113,7 +113,6 @@ SSL_library_init(void) EVP_add_digest(EVP_sha256()); EVP_add_digest(EVP_sha384()); EVP_add_digest(EVP_sha512()); - EVP_add_digest(EVP_ecdsa()); #ifndef OPENSSL_NO_GOST EVP_add_digest(EVP_gostr341194()); EVP_add_digest(EVP_gost2814789imit()); diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c index 6ff7ca5..70a50ac 100644 --- a/ssl/ssl_asn1.c +++ b/ssl/ssl_asn1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_asn1.c,v 1.59 2021/05/16 14:10:43 jsing Exp $ */ +/* $OpenBSD: ssl_asn1.c,v 1.61 2022/01/11 18:39:28 jsing Exp $ */ /* * Copyright (c) 2016 Joel Sing * @@ -113,8 +113,8 @@ SSL_SESSION_encode(SSL_SESSION *s, unsigned char **out, size_t *out_len, } /* Peer certificate [3]. */ - if (s->peer != NULL) { - if ((len = i2d_X509(s->peer, &peer_cert_bytes)) <= 0) + if (s->peer_cert != NULL) { + if ((len = i2d_X509(s->peer_cert, &peer_cert_bytes)) <= 0) goto err; if (!CBB_add_asn1(&session, &peer_cert, SSLASN1_PEER_CERT_TAG)) goto err; @@ -332,8 +332,8 @@ d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length) s->timeout = (long)timeout; /* Peer certificate [3]. */ - X509_free(s->peer); - s->peer = NULL; + X509_free(s->peer_cert); + s->peer_cert = NULL; if (!CBS_get_optional_asn1(&session, &peer_cert, &present, SSLASN1_PEER_CERT_TAG)) goto err; @@ -342,7 +342,7 @@ d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length) if (data_len > LONG_MAX) goto err; peer_cert_bytes = CBS_data(&peer_cert); - if (d2i_X509(&s->peer, &peer_cert_bytes, + if (d2i_X509(&s->peer_cert, &peer_cert_bytes, (long)data_len) == NULL) goto err; } @@ -388,16 +388,13 @@ d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length) /* Ticket lifetime [9]. */ s->tlsext_tick_lifetime_hint = 0; - /* XXX - tlsext_ticklen is not yet set... */ - if (s->tlsext_ticklen > 0 && s->session_id_length > 0) - s->tlsext_tick_lifetime_hint = -1; if (!CBS_get_optional_asn1_uint64(&session, &lifetime, SSLASN1_LIFETIME_TAG, 0)) goto err; - if (lifetime > LONG_MAX) + if (lifetime > UINT32_MAX) goto err; if (lifetime > 0) - s->tlsext_tick_lifetime_hint = (long)lifetime; + s->tlsext_tick_lifetime_hint = (uint32_t)lifetime; /* Ticket [10]. */ free(s->tlsext_tick); diff --git a/ssl/ssl_both.c b/ssl/ssl_both.c index f3d50d6..cfd3238 100644 --- a/ssl/ssl_both.c +++ b/ssl/ssl_both.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_both.c,v 1.35 2021/09/03 13:19:12 jsing Exp $ */ +/* $OpenBSD: ssl_both.c,v 1.42 2022/02/05 14:54:10 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -168,33 +168,33 @@ ssl3_send_finished(SSL *s, int state_a, int state_b) memset(&cbb, 0, sizeof(cbb)); - if (S3I(s)->hs.state == state_a) { + if (s->s3->hs.state == state_a) { if (!tls12_derive_finished(s)) goto err; /* Copy finished so we can use it for renegotiation checks. */ if (!s->server) { - memcpy(S3I(s)->previous_client_finished, - S3I(s)->hs.finished, S3I(s)->hs.finished_len); - S3I(s)->previous_client_finished_len = - S3I(s)->hs.finished_len; + memcpy(s->s3->previous_client_finished, + s->s3->hs.finished, s->s3->hs.finished_len); + s->s3->previous_client_finished_len = + s->s3->hs.finished_len; } else { - memcpy(S3I(s)->previous_server_finished, - S3I(s)->hs.finished, S3I(s)->hs.finished_len); - S3I(s)->previous_server_finished_len = - S3I(s)->hs.finished_len; + memcpy(s->s3->previous_server_finished, + s->s3->hs.finished, s->s3->hs.finished_len); + s->s3->previous_server_finished_len = + s->s3->hs.finished_len; } if (!ssl3_handshake_msg_start(s, &cbb, &finished, SSL3_MT_FINISHED)) goto err; - if (!CBB_add_bytes(&finished, S3I(s)->hs.finished, - S3I(s)->hs.finished_len)) + if (!CBB_add_bytes(&finished, s->s3->hs.finished, + s->s3->hs.finished_len)) goto err; if (!ssl3_handshake_msg_finish(s, &cbb)) goto err; - S3I(s)->hs.state = state_b; + s->s3->hs.state = state_b; } return (ssl3_handshake_write(s)); @@ -208,41 +208,39 @@ ssl3_send_finished(SSL *s, int state_a, int state_b) int ssl3_get_finished(SSL *s, int a, int b) { - int al, ok, md_len; - long n; + int al, md_len, ret; CBS cbs; /* should actually be 36+4 :-) */ - n = ssl3_get_message(s, a, b, SSL3_MT_FINISHED, 64, &ok); - if (!ok) - return ((int)n); + if ((ret = ssl3_get_message(s, a, b, SSL3_MT_FINISHED, 64)) <= 0) + return ret; /* If this occurs, we have missed a message */ - if (!S3I(s)->change_cipher_spec) { + if (!s->s3->change_cipher_spec) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerror(s, SSL_R_GOT_A_FIN_BEFORE_A_CCS); goto fatal_err; } - S3I(s)->change_cipher_spec = 0; + s->s3->change_cipher_spec = 0; md_len = TLS1_FINISH_MAC_LENGTH; - if (n < 0) { + if (s->internal->init_num < 0) { al = SSL_AD_DECODE_ERROR; SSLerror(s, SSL_R_BAD_DIGEST_LENGTH); goto fatal_err; } - CBS_init(&cbs, s->internal->init_msg, n); + CBS_init(&cbs, s->internal->init_msg, s->internal->init_num); - if (S3I(s)->hs.peer_finished_len != md_len || + if (s->s3->hs.peer_finished_len != md_len || CBS_len(&cbs) != md_len) { al = SSL_AD_DECODE_ERROR; SSLerror(s, SSL_R_BAD_DIGEST_LENGTH); goto fatal_err; } - if (!CBS_mem_equal(&cbs, S3I(s)->hs.peer_finished, CBS_len(&cbs))) { + if (!CBS_mem_equal(&cbs, s->s3->hs.peer_finished, CBS_len(&cbs))) { al = SSL_AD_DECRYPT_ERROR; SSLerror(s, SSL_R_DIGEST_CHECK_FAILED); goto fatal_err; @@ -251,13 +249,13 @@ ssl3_get_finished(SSL *s, int a, int b) /* Copy finished so we can use it for renegotiation checks. */ OPENSSL_assert(md_len <= EVP_MAX_MD_SIZE); if (s->server) { - memcpy(S3I(s)->previous_client_finished, - S3I(s)->hs.peer_finished, md_len); - S3I(s)->previous_client_finished_len = md_len; + memcpy(s->s3->previous_client_finished, + s->s3->hs.peer_finished, md_len); + s->s3->previous_client_finished_len = md_len; } else { - memcpy(S3I(s)->previous_server_finished, - S3I(s)->hs.peer_finished, md_len); - S3I(s)->previous_server_finished_len = md_len; + memcpy(s->s3->previous_server_finished, + s->s3->hs.peer_finished, md_len); + s->s3->previous_server_finished_len = md_len; } return (1); @@ -274,7 +272,7 @@ ssl3_send_change_cipher_spec(SSL *s, int a, int b) memset(&cbb, 0, sizeof(cbb)); - if (S3I(s)->hs.state == a) { + if (s->s3->hs.state == a) { if (!CBB_init_fixed(&cbb, s->internal->init_buf->data, s->internal->init_buf->length)) goto err; @@ -290,14 +288,14 @@ ssl3_send_change_cipher_spec(SSL *s, int a, int b) s->internal->init_off = 0; if (SSL_is_dtls(s)) { - D1I(s)->handshake_write_seq = - D1I(s)->next_handshake_write_seq; + s->d1->handshake_write_seq = + s->d1->next_handshake_write_seq; dtls1_set_message_header_int(s, SSL3_MT_CCS, 0, - D1I(s)->handshake_write_seq, 0, 0); + s->d1->handshake_write_seq, 0, 0); dtls1_buffer_message(s, 1); } - S3I(s)->hs.state = b; + s->s3->hs.state = b; } /* SSL3_ST_CW_CHANGE_B */ @@ -336,7 +334,7 @@ ssl3_add_cert(CBB *cbb, X509 *x) } int -ssl3_output_cert_chain(SSL *s, CBB *cbb, CERT_PKEY *cpk) +ssl3_output_cert_chain(SSL *s, CBB *cbb, SSL_CERT_PKEY *cpk) { X509_STORE_CTX *xs_ctx = NULL; STACK_OF(X509) *chain; @@ -370,7 +368,7 @@ ssl3_output_cert_chain(SSL *s, CBB *cbb, CERT_PKEY *cpk) X509_V_FLAG_LEGACY_VERIFY); X509_verify_cert(xs_ctx); ERR_clear_error(); - chain = xs_ctx->chain; + chain = X509_STORE_CTX_get0_chain(xs_ctx); } for (i = 0; i < sk_X509_num(chain); i++) { @@ -397,8 +395,8 @@ ssl3_output_cert_chain(SSL *s, CBB *cbb, CERT_PKEY *cpk) * The first four bytes (msg_type and length) are read in state 'st1', * the body is read in state 'stn'. */ -long -ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) +int +ssl3_get_message(SSL *s, int st1, int stn, int mt, long max) { unsigned char *p; uint32_t l; @@ -408,25 +406,24 @@ ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) uint8_t u8; if (SSL_is_dtls(s)) - return (dtls1_get_message(s, st1, stn, mt, max, ok)); + return dtls1_get_message(s, st1, stn, mt, max); - if (S3I(s)->hs.tls12.reuse_message) { - S3I(s)->hs.tls12.reuse_message = 0; - if ((mt >= 0) && (S3I(s)->hs.tls12.message_type != mt)) { + if (s->s3->hs.tls12.reuse_message) { + s->s3->hs.tls12.reuse_message = 0; + if ((mt >= 0) && (s->s3->hs.tls12.message_type != mt)) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); goto fatal_err; } - *ok = 1; s->internal->init_msg = s->internal->init_buf->data + SSL3_HM_HEADER_LENGTH; - s->internal->init_num = (int)S3I(s)->hs.tls12.message_size; - return s->internal->init_num; + s->internal->init_num = (int)s->s3->hs.tls12.message_size; + return 1; } p = (unsigned char *)s->internal->init_buf->data; - if (S3I(s)->hs.state == st1) { + if (s->s3->hs.state == st1) { int skip_message; do { @@ -436,7 +433,6 @@ ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) SSL3_HM_HEADER_LENGTH - s->internal->init_num, 0); if (i <= 0) { s->internal->rwstate = SSL_READING; - *ok = 0; return i; } s->internal->init_num += i; @@ -473,7 +469,7 @@ ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) SSLerror(s, ERR_R_BUF_LIB); goto err; } - S3I(s)->hs.tls12.message_type = u8; + s->s3->hs.tls12.message_type = u8; if (l > (unsigned long)max) { al = SSL_AD_ILLEGAL_PARAMETER; @@ -485,8 +481,8 @@ ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) SSLerror(s, ERR_R_BUF_LIB); goto err; } - S3I(s)->hs.tls12.message_size = l; - S3I(s)->hs.state = stn; + s->s3->hs.tls12.message_size = l; + s->s3->hs.state = stn; s->internal->init_msg = s->internal->init_buf->data + SSL3_HM_HEADER_LENGTH; @@ -495,13 +491,12 @@ ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) /* next state (stn) */ p = s->internal->init_msg; - n = S3I(s)->hs.tls12.message_size - s->internal->init_num; + n = s->s3->hs.tls12.message_size - s->internal->init_num; while (n > 0) { i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &p[s->internal->init_num], n, 0); if (i <= 0) { s->internal->rwstate = SSL_READING; - *ok = 0; return i; } s->internal->init_num += i; @@ -518,43 +513,31 @@ ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) (size_t)s->internal->init_num + SSL3_HM_HEADER_LENGTH); } - *ok = 1; - return (s->internal->init_num); + return 1; fatal_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); err: - *ok = 0; - return (-1); + return -1; } int -ssl_cert_type(X509 *x, EVP_PKEY *pkey) +ssl_cert_type(EVP_PKEY *pkey) { - EVP_PKEY *pk; - int ret = -1, i; - if (pkey == NULL) - pk = X509_get_pubkey(x); - else - pk = pkey; - if (pk == NULL) - goto err; + return -1; - i = pk->type; - if (i == EVP_PKEY_RSA) { - ret = SSL_PKEY_RSA; - } else if (i == EVP_PKEY_EC) { - ret = SSL_PKEY_ECC; - } else if (i == NID_id_GostR3410_2001 || - i == NID_id_GostR3410_2001_cc) { - ret = SSL_PKEY_GOST01; + switch (EVP_PKEY_id(pkey)) { + case EVP_PKEY_EC: + return SSL_PKEY_ECC; + case NID_id_GostR3410_2001: + case NID_id_GostR3410_2001_cc: + return SSL_PKEY_GOST01; + case EVP_PKEY_RSA: + return SSL_PKEY_RSA; } - err: - if (!pkey) - EVP_PKEY_free(pk); - return (ret); + return -1; } int @@ -661,16 +644,16 @@ ssl3_setup_read_buffer(SSL *s) align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1); - if (S3I(s)->rbuf.buf == NULL) { + if (s->s3->rbuf.buf == NULL) { len = SSL3_RT_MAX_PLAIN_LENGTH + SSL3_RT_MAX_ENCRYPTED_OVERHEAD + headerlen + align; if ((p = calloc(1, len)) == NULL) goto err; - S3I(s)->rbuf.buf = p; - S3I(s)->rbuf.len = len; + s->s3->rbuf.buf = p; + s->s3->rbuf.len = len; } - s->internal->packet = S3I(s)->rbuf.buf; + s->internal->packet = s->s3->rbuf.buf; return 1; err: @@ -691,7 +674,7 @@ ssl3_setup_write_buffer(SSL *s) align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1); - if (S3I(s)->wbuf.buf == NULL) { + if (s->s3->wbuf.buf == NULL) { len = s->max_send_fragment + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + headerlen + align; if (!(s->internal->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) @@ -700,8 +683,8 @@ ssl3_setup_write_buffer(SSL *s) if ((p = calloc(1, len)) == NULL) goto err; - S3I(s)->wbuf.buf = p; - S3I(s)->wbuf.len = len; + s->s3->wbuf.buf = p; + s->s3->wbuf.len = len; } return 1; @@ -732,11 +715,11 @@ ssl3_release_buffer(SSL3_BUFFER_INTERNAL *b) void ssl3_release_read_buffer(SSL *s) { - ssl3_release_buffer(&S3I(s)->rbuf); + ssl3_release_buffer(&s->s3->rbuf); } void ssl3_release_write_buffer(SSL *s) { - ssl3_release_buffer(&S3I(s)->wbuf); + ssl3_release_buffer(&s->s3->wbuf); } diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index a13ee59..30e99ad 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_cert.c,v 1.83 2021/06/11 11:13:53 jsing Exp $ */ +/* $OpenBSD: ssl_cert.c,v 1.95 2022/02/05 14:54:10 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -158,12 +158,12 @@ SSL_get_ex_data_X509_STORE_CTX_idx(void) return ssl_x509_store_ctx_idx; } -CERT * +SSL_CERT * ssl_cert_new(void) { - CERT *ret; + SSL_CERT *ret; - ret = calloc(1, sizeof(CERT)); + ret = calloc(1, sizeof(SSL_CERT)); if (ret == NULL) { SSLerrorx(ERR_R_MALLOC_FAILURE); return (NULL); @@ -173,13 +173,13 @@ ssl_cert_new(void) return (ret); } -CERT * -ssl_cert_dup(CERT *cert) +SSL_CERT * +ssl_cert_dup(SSL_CERT *cert) { - CERT *ret; + SSL_CERT *ret; int i; - ret = calloc(1, sizeof(CERT)); + ret = calloc(1, sizeof(SSL_CERT)); if (ret == NULL) { SSLerrorx(ERR_R_MALLOC_FAILURE); return (NULL); @@ -195,44 +195,25 @@ ssl_cert_dup(CERT *cert) ret->mask_k = cert->mask_k; ret->mask_a = cert->mask_a; - if (cert->dh_tmp != NULL) { - ret->dh_tmp = DHparams_dup(cert->dh_tmp); - if (ret->dh_tmp == NULL) { + if (cert->dhe_params != NULL) { + ret->dhe_params = DHparams_dup(cert->dhe_params); + if (ret->dhe_params == NULL) { SSLerrorx(ERR_R_DH_LIB); goto err; } - if (cert->dh_tmp->priv_key) { - BIGNUM *b = BN_dup(cert->dh_tmp->priv_key); - if (!b) { - SSLerrorx(ERR_R_BN_LIB); - goto err; - } - ret->dh_tmp->priv_key = b; - } - if (cert->dh_tmp->pub_key) { - BIGNUM *b = BN_dup(cert->dh_tmp->pub_key); - if (!b) { - SSLerrorx(ERR_R_BN_LIB); - goto err; - } - ret->dh_tmp->pub_key = b; - } } - ret->dh_tmp_cb = cert->dh_tmp_cb; - ret->dh_tmp_auto = cert->dh_tmp_auto; + ret->dhe_params_cb = cert->dhe_params_cb; + ret->dhe_params_auto = cert->dhe_params_auto; for (i = 0; i < SSL_PKEY_NUM; i++) { if (cert->pkeys[i].x509 != NULL) { ret->pkeys[i].x509 = cert->pkeys[i].x509; - CRYPTO_add(&ret->pkeys[i].x509->references, 1, - CRYPTO_LOCK_X509); + X509_up_ref(ret->pkeys[i].x509); } if (cert->pkeys[i].privatekey != NULL) { ret->pkeys[i].privatekey = cert->pkeys[i].privatekey; - CRYPTO_add(&ret->pkeys[i].privatekey->references, 1, - CRYPTO_LOCK_EVP_PKEY); - + EVP_PKEY_up_ref(ret->pkeys[i].privatekey); switch (i) { /* * If there was anything special to do for @@ -275,7 +256,7 @@ ssl_cert_dup(CERT *cert) return (ret); err: - DH_free(ret->dh_tmp); + DH_free(ret->dhe_params); for (i = 0; i < SSL_PKEY_NUM; i++) { X509_free(ret->pkeys[i].x509); @@ -288,7 +269,7 @@ ssl_cert_dup(CERT *cert) void -ssl_cert_free(CERT *c) +ssl_cert_free(SSL_CERT *c) { int i; @@ -299,7 +280,7 @@ ssl_cert_free(CERT *c) if (i > 0) return; - DH_free(c->dh_tmp); + DH_free(c->dhe_params); for (i = 0; i < SSL_PKEY_NUM; i++) { X509_free(c->pkeys[i].x509); @@ -311,7 +292,7 @@ ssl_cert_free(CERT *c) } int -ssl_cert_set0_chain(CERT *c, STACK_OF(X509) *chain) +ssl_cert_set0_chain(SSL_CERT *c, STACK_OF(X509) *chain) { if (c->key == NULL) return 0; @@ -323,7 +304,7 @@ ssl_cert_set0_chain(CERT *c, STACK_OF(X509) *chain) } int -ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain) +ssl_cert_set1_chain(SSL_CERT *c, STACK_OF(X509) *chain) { STACK_OF(X509) *new_chain = NULL; @@ -340,7 +321,7 @@ ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain) } int -ssl_cert_add0_chain_cert(CERT *c, X509 *cert) +ssl_cert_add0_chain_cert(SSL_CERT *c, X509 *cert) { if (c->key == NULL) return 0; @@ -356,7 +337,7 @@ ssl_cert_add0_chain_cert(CERT *c, X509 *cert) } int -ssl_cert_add1_chain_cert(CERT *c, X509 *cert) +ssl_cert_add1_chain_cert(SSL_CERT *c, X509 *cert) { if (!ssl_cert_add0_chain_cert(c, cert)) return 0; @@ -366,88 +347,61 @@ ssl_cert_add1_chain_cert(CERT *c, X509 *cert) return 1; } -SESS_CERT * -ssl_sess_cert_new(void) -{ - SESS_CERT *ret; - - ret = calloc(1, sizeof *ret); - if (ret == NULL) { - SSLerrorx(ERR_R_MALLOC_FAILURE); - return NULL; - } - ret->peer_key = &(ret->peer_pkeys[SSL_PKEY_RSA]); - ret->references = 1; - - return ret; -} - -void -ssl_sess_cert_free(SESS_CERT *sc) -{ - int i; - - if (sc == NULL) - return; - - i = CRYPTO_add(&sc->references, -1, CRYPTO_LOCK_SSL_SESS_CERT); - if (i > 0) - return; - - sk_X509_pop_free(sc->cert_chain, X509_free); - for (i = 0; i < SSL_PKEY_NUM; i++) - X509_free(sc->peer_pkeys[i].x509); - - DH_free(sc->peer_dh_tmp); - EC_KEY_free(sc->peer_ecdh_tmp); - free(sc->peer_x25519_tmp); - - free(sc); -} - int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk) { - X509_STORE_CTX ctx; + X509_STORE_CTX *ctx = NULL; X509 *x; - int ret; + int ret = 0; if ((sk == NULL) || (sk_X509_num(sk) == 0)) - return (0); + goto err; + + if ((ctx = X509_STORE_CTX_new()) == NULL) + goto err; x = sk_X509_value(sk, 0); - if (!X509_STORE_CTX_init(&ctx, s->ctx->cert_store, x, sk)) { + if (!X509_STORE_CTX_init(ctx, s->ctx->cert_store, x, sk)) { SSLerror(s, ERR_R_X509_LIB); - return (0); + goto err; } - X509_STORE_CTX_set_ex_data(&ctx, - SSL_get_ex_data_X509_STORE_CTX_idx(), s); + X509_STORE_CTX_set_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), s); /* * We need to inherit the verify parameters. These can be * determined by the context: if its a server it will verify * SSL client certificates or vice versa. */ - X509_STORE_CTX_set_default(&ctx, - s->server ? "ssl_client" : "ssl_server"); + X509_STORE_CTX_set_default(ctx, s->server ? "ssl_client" : "ssl_server"); /* * Anything non-default in "param" should overwrite anything * in the ctx. */ - X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&ctx), s->param); + X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(ctx), s->param); if (s->internal->verify_callback) - X509_STORE_CTX_set_verify_cb(&ctx, s->internal->verify_callback); + X509_STORE_CTX_set_verify_cb(ctx, s->internal->verify_callback); if (s->ctx->internal->app_verify_callback != NULL) - ret = s->ctx->internal->app_verify_callback(&ctx, + ret = s->ctx->internal->app_verify_callback(ctx, s->ctx->internal->app_verify_arg); else - ret = X509_verify_cert(&ctx); + ret = X509_verify_cert(ctx); - s->verify_result = ctx.error; - X509_STORE_CTX_cleanup(&ctx); + s->verify_result = X509_STORE_CTX_get_error(ctx); + sk_X509_pop_free(s->internal->verified_chain, X509_free); + s->internal->verified_chain = NULL; + if (X509_STORE_CTX_get0_chain(ctx) != NULL) { + s->internal->verified_chain = X509_STORE_CTX_get1_chain(ctx); + if (s->internal->verified_chain == NULL) { + SSLerrorx(ERR_R_MALLOC_FAILURE); + ret = 0; + } + } + + err: + X509_STORE_CTX_free(ctx); return (ret); } @@ -508,7 +462,7 @@ SSL_get_client_CA_list(const SSL *s) if (!s->server) { /* We are in the client. */ if ((s->version >> 8) == SSL3_VERSION_MAJOR) - return (S3I(s)->hs.tls12.ca_names); + return (s->s3->hs.tls12.ca_names); else return (NULL); } else { @@ -575,7 +529,7 @@ SSL_load_client_CA_file(const char *file) sk = sk_X509_NAME_new(xname_cmp); - in = BIO_new(BIO_s_file_internal()); + in = BIO_new(BIO_s_file()); if ((sk == NULL) || (in == NULL)) { SSLerrorx(ERR_R_MALLOC_FAILURE); @@ -604,8 +558,10 @@ SSL_load_client_CA_file(const char *file) if (sk_X509_NAME_find(sk, xn) >= 0) X509_NAME_free(xn); else { - sk_X509_NAME_push(sk, xn); - sk_X509_NAME_push(ret, xn); + if (!sk_X509_NAME_push(sk, xn)) + goto err; + if (!sk_X509_NAME_push(ret, xn)) + goto err; } } @@ -644,7 +600,7 @@ SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_cmp); - in = BIO_new(BIO_s_file_internal()); + in = BIO_new(BIO_s_file()); if (in == NULL) { SSLerrorx(ERR_R_MALLOC_FAILURE); @@ -665,7 +621,8 @@ SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, if (sk_X509_NAME_find(stack, xn) >= 0) X509_NAME_free(xn); else - sk_X509_NAME_push(stack, xn); + if (!sk_X509_NAME_push(stack, xn)) + goto err; } ERR_clear_error(); diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c index 0e9941b..2bc9f8e 100644 --- a/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_ciph.c,v 1.124 2021/07/03 16:06:44 jsing Exp $ */ +/* $OpenBSD: ssl_ciph.c,v 1.127 2022/03/05 07:13:48 bket Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -448,7 +448,7 @@ ssl_cipher_get_evp(const SSL_SESSION *ss, const EVP_CIPHER **enc, /* * This function does not handle EVP_AEAD. - * See ssl_cipher_get_aead_evp instead. + * See ssl_cipher_get_evp_aead instead. */ if (ss->cipher->algorithm_mac & SSL_AEAD) return 0; @@ -564,10 +564,10 @@ ssl_get_handshake_evp_md(SSL *s, const EVP_MD **md) *md = NULL; - if (S3I(s)->hs.cipher == NULL) + if (s->s3->hs.cipher == NULL) return 0; - handshake_mac = S3I(s)->hs.cipher->algorithm2 & + handshake_mac = s->s3->hs.cipher->algorithm2 & SSL_HANDSHAKE_MAC_MASK; /* For TLSv1.2 we upgrade the default MD5+SHA1 MAC to SHA256. */ @@ -681,7 +681,10 @@ ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method, int num_of_ciphers, co_list_num = 0; /* actual count of ciphers */ for (i = 0; i < num_of_ciphers; i++) { c = ssl_method->get_cipher(i); - /* drop those that use any of that is not available */ + /* + * Drop any invalid ciphers and any which use unavailable + * algorithms. + */ if ((c != NULL) && c->valid && !(c->algorithm_mkey & disabled_mkey) && !(c->algorithm_auth & disabled_auth) && diff --git a/ssl/ssl_ciphers.c b/ssl/ssl_ciphers.c index 4e4a0d9..3174ae9 100644 --- a/ssl/ssl_ciphers.c +++ b/ssl/ssl_ciphers.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_ciphers.c,v 1.11 2021/03/11 17:14:46 jsing Exp $ */ +/* $OpenBSD: ssl_ciphers.c,v 1.13 2022/02/05 18:18:18 tb Exp $ */ /* * Copyright (c) 2015-2017 Doug Hogan * Copyright (c) 2015-2018, 2020 Joel Sing @@ -96,7 +96,7 @@ ssl_bytes_to_cipher_list(SSL *s, CBS *cbs) uint16_t cipher_value; unsigned long cipher_id; - S3I(s)->send_connection_binding = 0; + s->s3->send_connection_binding = 0; if ((ciphers = sk_SSL_CIPHER_new_null()) == NULL) { SSLerror(s, ERR_R_MALLOC_FAILURE); @@ -123,7 +123,7 @@ ssl_bytes_to_cipher_list(SSL *s, CBS *cbs) goto err; } - S3I(s)->send_connection_binding = 1; + s->s3->send_connection_binding = 1; continue; } @@ -134,8 +134,8 @@ ssl_bytes_to_cipher_list(SSL *s, CBS *cbs) * Fail if the current version is an unexpected * downgrade. */ - if (S3I(s)->hs.negotiated_tls_version < - S3I(s)->hs.our_max_tls_version) { + if (s->s3->hs.negotiated_tls_version < + s->s3->hs.our_max_tls_version) { SSLerror(s, SSL_R_INAPPROPRIATE_FALLBACK); ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INAPPROPRIATE_FALLBACK); @@ -168,28 +168,28 @@ struct ssl_tls13_ciphersuite { static const struct ssl_tls13_ciphersuite ssl_tls13_ciphersuites[] = { { - .name = TLS1_3_TXT_AES_128_GCM_SHA256, - .alias = "TLS_AES_128_GCM_SHA256", + .name = TLS1_3_RFC_AES_128_GCM_SHA256, + .alias = TLS1_3_TXT_AES_128_GCM_SHA256, .cid = TLS1_3_CK_AES_128_GCM_SHA256, }, { - .name = TLS1_3_TXT_AES_256_GCM_SHA384, - .alias = "TLS_AES_256_GCM_SHA384", + .name = TLS1_3_RFC_AES_256_GCM_SHA384, + .alias = TLS1_3_TXT_AES_256_GCM_SHA384, .cid = TLS1_3_CK_AES_256_GCM_SHA384, }, { - .name = TLS1_3_TXT_CHACHA20_POLY1305_SHA256, - .alias = "TLS_CHACHA20_POLY1305_SHA256", + .name = TLS1_3_RFC_CHACHA20_POLY1305_SHA256, + .alias = TLS1_3_TXT_CHACHA20_POLY1305_SHA256, .cid = TLS1_3_CK_CHACHA20_POLY1305_SHA256, }, { - .name = TLS1_3_TXT_AES_128_CCM_SHA256, - .alias = "TLS_AES_128_CCM_SHA256", + .name = TLS1_3_RFC_AES_128_CCM_SHA256, + .alias = TLS1_3_TXT_AES_128_CCM_SHA256, .cid = TLS1_3_CK_AES_128_CCM_SHA256, }, { - .name = TLS1_3_TXT_AES_128_CCM_8_SHA256, - .alias = "TLS_AES_128_CCM_8_SHA256", + .name = TLS1_3_RFC_AES_128_CCM_8_SHA256, + .alias = TLS1_3_TXT_AES_128_CCM_8_SHA256, .cid = TLS1_3_CK_AES_128_CCM_8_SHA256, }, { diff --git a/ssl/ssl_clnt.c b/ssl/ssl_clnt.c index ddab394..607b038 100644 --- a/ssl/ssl_clnt.c +++ b/ssl/ssl_clnt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_clnt.c,v 1.111 2021/09/03 13:18:17 jsing Exp $ */ +/* $OpenBSD: ssl_clnt.c,v 1.141 2022/02/05 14:54:10 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -190,12 +190,12 @@ ssl3_connect(SSL *s) SSL_clear(s); for (;;) { - state = S3I(s)->hs.state; + state = s->s3->hs.state; - switch (S3I(s)->hs.state) { + switch (s->s3->hs.state) { case SSL_ST_RENEGOTIATE: s->internal->renegotiate = 1; - S3I(s)->hs.state = SSL_ST_CONNECT; + s->s3->hs.state = SSL_ST_CONNECT; s->ctx->internal->stats.sess_connect_renegotiate++; /* break */ case SSL_ST_BEFORE: @@ -214,8 +214,8 @@ ssl3_connect(SSL *s) } if (!ssl_supported_tls_version_range(s, - &S3I(s)->hs.our_min_tls_version, - &S3I(s)->hs.our_max_tls_version)) { + &s->s3->hs.our_min_tls_version, + &s->s3->hs.our_max_tls_version)) { SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE); ret = -1; goto end; @@ -241,7 +241,7 @@ ssl3_connect(SSL *s) goto end; } - S3I(s)->hs.state = SSL3_ST_CW_CLNT_HELLO_A; + s->s3->hs.state = SSL3_ST_CW_CLNT_HELLO_A; s->ctx->internal->stats.sess_connect++; s->internal->init_num = 0; @@ -249,7 +249,7 @@ ssl3_connect(SSL *s) /* mark client_random uninitialized */ memset(s->s3->client_random, 0, sizeof(s->s3->client_random)); - D1I(s)->send_cookie = 0; + s->d1->send_cookie = 0; s->internal->hit = 0; } break; @@ -269,11 +269,11 @@ ssl3_connect(SSL *s) if (ret <= 0) goto end; - if (SSL_is_dtls(s) && D1I(s)->send_cookie) { - S3I(s)->hs.state = SSL3_ST_CW_FLUSH; - S3I(s)->hs.tls12.next_state = SSL3_ST_CR_SRVR_HELLO_A; + if (SSL_is_dtls(s) && s->d1->send_cookie) { + s->s3->hs.state = SSL3_ST_CW_FLUSH; + s->s3->hs.tls12.next_state = SSL3_ST_CR_SRVR_HELLO_A; } else - S3I(s)->hs.state = SSL3_ST_CR_SRVR_HELLO_A; + s->s3->hs.state = SSL3_ST_CR_SRVR_HELLO_A; s->internal->init_num = 0; @@ -290,20 +290,20 @@ ssl3_connect(SSL *s) goto end; if (s->internal->hit) { - S3I(s)->hs.state = SSL3_ST_CR_FINISHED_A; + s->s3->hs.state = SSL3_ST_CR_FINISHED_A; if (!SSL_is_dtls(s)) { if (s->internal->tlsext_ticket_expected) { /* receive renewed session ticket */ - S3I(s)->hs.state = SSL3_ST_CR_SESSION_TICKET_A; + s->s3->hs.state = SSL3_ST_CR_SESSION_TICKET_A; } /* No client certificate verification. */ tls1_transcript_free(s); } } else if (SSL_is_dtls(s)) { - S3I(s)->hs.state = DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A; + s->s3->hs.state = DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A; } else { - S3I(s)->hs.state = SSL3_ST_CR_CERT_A; + s->s3->hs.state = SSL3_ST_CR_CERT_A; } s->internal->init_num = 0; break; @@ -314,10 +314,10 @@ ssl3_connect(SSL *s) if (ret <= 0) goto end; dtls1_stop_timer(s); - if (D1I(s)->send_cookie) /* start again, with a cookie */ - S3I(s)->hs.state = SSL3_ST_CW_CLNT_HELLO_A; + if (s->d1->send_cookie) /* start again, with a cookie */ + s->s3->hs.state = SSL3_ST_CW_CLNT_HELLO_A; else - S3I(s)->hs.state = SSL3_ST_CR_CERT_A; + s->s3->hs.state = SSL3_ST_CR_CERT_A; s->internal->init_num = 0; break; @@ -329,25 +329,25 @@ ssl3_connect(SSL *s) if (ret == 2) { s->internal->hit = 1; if (s->internal->tlsext_ticket_expected) - S3I(s)->hs.state = SSL3_ST_CR_SESSION_TICKET_A; + s->s3->hs.state = SSL3_ST_CR_SESSION_TICKET_A; else - S3I(s)->hs.state = SSL3_ST_CR_FINISHED_A; + s->s3->hs.state = SSL3_ST_CR_FINISHED_A; s->internal->init_num = 0; break; } /* Check if it is anon DH/ECDH. */ - if (!(S3I(s)->hs.cipher->algorithm_auth & + if (!(s->s3->hs.cipher->algorithm_auth & SSL_aNULL)) { ret = ssl3_get_server_certificate(s); if (ret <= 0) goto end; if (s->internal->tlsext_status_expected) - S3I(s)->hs.state = SSL3_ST_CR_CERT_STATUS_A; + s->s3->hs.state = SSL3_ST_CR_CERT_STATUS_A; else - S3I(s)->hs.state = SSL3_ST_CR_KEY_EXCH_A; + s->s3->hs.state = SSL3_ST_CR_KEY_EXCH_A; } else { skip = 1; - S3I(s)->hs.state = SSL3_ST_CR_KEY_EXCH_A; + s->s3->hs.state = SSL3_ST_CR_KEY_EXCH_A; } s->internal->init_num = 0; break; @@ -357,7 +357,7 @@ ssl3_connect(SSL *s) ret = ssl3_get_server_key_exchange(s); if (ret <= 0) goto end; - S3I(s)->hs.state = SSL3_ST_CR_CERT_REQ_A; + s->s3->hs.state = SSL3_ST_CR_CERT_REQ_A; s->internal->init_num = 0; /* @@ -375,7 +375,7 @@ ssl3_connect(SSL *s) ret = ssl3_get_certificate_request(s); if (ret <= 0) goto end; - S3I(s)->hs.state = SSL3_ST_CR_SRVR_DONE_A; + s->s3->hs.state = SSL3_ST_CR_SRVR_DONE_A; s->internal->init_num = 0; break; @@ -386,10 +386,10 @@ ssl3_connect(SSL *s) goto end; if (SSL_is_dtls(s)) dtls1_stop_timer(s); - if (S3I(s)->hs.tls12.cert_request) - S3I(s)->hs.state = SSL3_ST_CW_CERT_A; + if (s->s3->hs.tls12.cert_request) + s->s3->hs.state = SSL3_ST_CW_CERT_A; else - S3I(s)->hs.state = SSL3_ST_CW_KEY_EXCH_A; + s->s3->hs.state = SSL3_ST_CW_KEY_EXCH_A; s->internal->init_num = 0; break; @@ -403,7 +403,7 @@ ssl3_connect(SSL *s) ret = ssl3_send_client_certificate(s); if (ret <= 0) goto end; - S3I(s)->hs.state = SSL3_ST_CW_KEY_EXCH_A; + s->s3->hs.state = SSL3_ST_CW_KEY_EXCH_A; s->internal->init_num = 0; break; @@ -430,16 +430,16 @@ ssl3_connect(SSL *s) * message when client's ECDH public key is sent * inside the client certificate. */ - if (S3I(s)->hs.tls12.cert_request == 1) { - S3I(s)->hs.state = SSL3_ST_CW_CERT_VRFY_A; + if (s->s3->hs.tls12.cert_request == 1) { + s->s3->hs.state = SSL3_ST_CW_CERT_VRFY_A; } else { - S3I(s)->hs.state = SSL3_ST_CW_CHANGE_A; - S3I(s)->change_cipher_spec = 0; + s->s3->hs.state = SSL3_ST_CW_CHANGE_A; + s->s3->change_cipher_spec = 0; } if (!SSL_is_dtls(s)) { if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) { - S3I(s)->hs.state = SSL3_ST_CW_CHANGE_A; - S3I(s)->change_cipher_spec = 0; + s->s3->hs.state = SSL3_ST_CW_CHANGE_A; + s->s3->change_cipher_spec = 0; } } @@ -453,9 +453,9 @@ ssl3_connect(SSL *s) ret = ssl3_send_client_verify(s); if (ret <= 0) goto end; - S3I(s)->hs.state = SSL3_ST_CW_CHANGE_A; + s->s3->hs.state = SSL3_ST_CW_CHANGE_A; s->internal->init_num = 0; - S3I(s)->change_cipher_spec = 0; + s->s3->change_cipher_spec = 0; break; case SSL3_ST_CW_CHANGE_A: @@ -467,9 +467,9 @@ ssl3_connect(SSL *s) if (ret <= 0) goto end; - S3I(s)->hs.state = SSL3_ST_CW_FINISHED_A; + s->s3->hs.state = SSL3_ST_CW_FINISHED_A; s->internal->init_num = 0; - s->session->cipher = S3I(s)->hs.cipher; + s->session->cipher = s->s3->hs.cipher; if (!tls1_setup_key_block(s)) { ret = -1; @@ -491,18 +491,18 @@ ssl3_connect(SSL *s) goto end; if (!SSL_is_dtls(s)) s->s3->flags |= SSL3_FLAGS_CCS_OK; - S3I(s)->hs.state = SSL3_ST_CW_FLUSH; + s->s3->hs.state = SSL3_ST_CW_FLUSH; /* clear flags */ if (s->internal->hit) { - S3I(s)->hs.tls12.next_state = SSL_ST_OK; + s->s3->hs.tls12.next_state = SSL_ST_OK; } else { /* Allow NewSessionTicket if ticket expected */ if (s->internal->tlsext_ticket_expected) - S3I(s)->hs.tls12.next_state = + s->s3->hs.tls12.next_state = SSL3_ST_CR_SESSION_TICKET_A; else - S3I(s)->hs.tls12.next_state = + s->s3->hs.tls12.next_state = SSL3_ST_CR_FINISHED_A; } s->internal->init_num = 0; @@ -513,7 +513,7 @@ ssl3_connect(SSL *s) ret = ssl3_get_new_session_ticket(s); if (ret <= 0) goto end; - S3I(s)->hs.state = SSL3_ST_CR_FINISHED_A; + s->s3->hs.state = SSL3_ST_CR_FINISHED_A; s->internal->init_num = 0; break; @@ -522,14 +522,14 @@ ssl3_connect(SSL *s) ret = ssl3_get_cert_status(s); if (ret <= 0) goto end; - S3I(s)->hs.state = SSL3_ST_CR_KEY_EXCH_A; + s->s3->hs.state = SSL3_ST_CR_KEY_EXCH_A; s->internal->init_num = 0; break; case SSL3_ST_CR_FINISHED_A: case SSL3_ST_CR_FINISHED_B: if (SSL_is_dtls(s)) - D1I(s)->change_cipher_spec_ok = 1; + s->d1->change_cipher_spec_ok = 1; else s->s3->flags |= SSL3_FLAGS_CCS_OK; ret = ssl3_get_finished(s, SSL3_ST_CR_FINISHED_A, @@ -540,9 +540,9 @@ ssl3_connect(SSL *s) dtls1_stop_timer(s); if (s->internal->hit) - S3I(s)->hs.state = SSL3_ST_CW_CHANGE_A; + s->s3->hs.state = SSL3_ST_CW_CHANGE_A; else - S3I(s)->hs.state = SSL_ST_OK; + s->s3->hs.state = SSL_ST_OK; s->internal->init_num = 0; break; @@ -553,21 +553,21 @@ ssl3_connect(SSL *s) /* If the write error was fatal, stop trying */ if (!BIO_should_retry(s->wbio)) { s->internal->rwstate = SSL_NOTHING; - S3I(s)->hs.state = S3I(s)->hs.tls12.next_state; + s->s3->hs.state = s->s3->hs.tls12.next_state; } } ret = -1; goto end; } s->internal->rwstate = SSL_NOTHING; - S3I(s)->hs.state = S3I(s)->hs.tls12.next_state; + s->s3->hs.state = s->s3->hs.tls12.next_state; break; case SSL_ST_OK: /* clean a few things up */ tls1_cleanup_key_block(s); - if (S3I(s)->handshake_transcript != NULL) { + if (s->s3->handshake_transcript != NULL) { SSLerror(s, ERR_R_INTERNAL_ERROR); ret = -1; goto end; @@ -595,8 +595,8 @@ ssl3_connect(SSL *s) if (SSL_is_dtls(s)) { /* done with handshaking */ - D1I(s)->handshake_read_seq = 0; - D1I(s)->next_handshake_write_seq = 0; + s->d1->handshake_read_seq = 0; + s->d1->next_handshake_write_seq = 0; } goto end; @@ -610,17 +610,17 @@ ssl3_connect(SSL *s) } /* did we do anything */ - if (!S3I(s)->hs.tls12.reuse_message && !skip) { + if (!s->s3->hs.tls12.reuse_message && !skip) { if (s->internal->debug) { if ((ret = BIO_flush(s->wbio)) <= 0) goto end; } - if (S3I(s)->hs.state != state) { - new_state = S3I(s)->hs.state; - S3I(s)->hs.state = state; + if (s->s3->hs.state != state) { + new_state = s->s3->hs.state; + s->s3->hs.state = state; ssl_info_callback(s, SSL_CB_CONNECT_LOOP, 1); - S3I(s)->hs.state = new_state; + s->s3->hs.state = new_state; } } skip = 0; @@ -643,19 +643,19 @@ ssl3_send_client_hello(SSL *s) memset(&cbb, 0, sizeof(cbb)); - if (S3I(s)->hs.state == SSL3_ST_CW_CLNT_HELLO_A) { + if (s->s3->hs.state == SSL3_ST_CW_CLNT_HELLO_A) { SSL_SESSION *sess = s->session; if (!ssl_max_supported_version(s, &max_version)) { SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE); return (-1); } - s->client_version = s->version = max_version; + s->version = max_version; if (sess == NULL || sess->ssl_version != s->version || (!sess->session_id_length && !sess->tlsext_tick) || - sess->internal->not_resumable) { + sess->not_resumable) { if (!ssl_get_new_session(s, 0)) goto err; } @@ -666,44 +666,14 @@ ssl3_send_client_hello(SSL *s) * HelloVerifyRequest, we must retain the original client * random value. */ - if (!SSL_is_dtls(s) || D1I(s)->send_cookie == 0) + if (!SSL_is_dtls(s) || s->d1->send_cookie == 0) arc4random_buf(s->s3->client_random, SSL3_RANDOM_SIZE); if (!ssl3_handshake_msg_start(s, &cbb, &client_hello, SSL3_MT_CLIENT_HELLO)) goto err; - /* - * Version indicates the negotiated version: for example from - * an SSLv2/v3 compatible client hello). The client_version - * field is the maximum version we permit and it is also - * used in RSA encrypted premaster secrets. Some servers can - * choke if we initially report a higher version then - * renegotiate to a lower one in the premaster secret. This - * didn't happen with TLS 1.0 as most servers supported it - * but it can with TLS 1.1 or later if the server only supports - * 1.0. - * - * Possible scenario with previous logic: - * 1. Client hello indicates TLS 1.2 - * 2. Server hello says TLS 1.0 - * 3. RSA encrypted premaster secret uses 1.2. - * 4. Handhaked proceeds using TLS 1.0. - * 5. Server sends hello request to renegotiate. - * 6. Client hello indicates TLS v1.0 as we now - * know that is maximum server supports. - * 7. Server chokes on RSA encrypted premaster secret - * containing version 1.0. - * - * For interoperability it should be OK to always use the - * maximum version we support in client hello and then rely - * on the checking of version to ensure the servers isn't - * being inconsistent: for example initially negotiating with - * TLS 1.0 and renegotiating with TLS 1.2. We do this by using - * client_version in client hello and not resetting it to - * the negotiated version. - */ - if (!CBB_add_u16(&client_hello, s->client_version)) + if (!CBB_add_u16(&client_hello, s->version)) goto err; /* Random stuff */ @@ -728,14 +698,14 @@ ssl3_send_client_hello(SSL *s) /* DTLS Cookie. */ if (SSL_is_dtls(s)) { - if (D1I(s)->cookie_len > sizeof(D1I(s)->cookie)) { + if (s->d1->cookie_len > sizeof(s->d1->cookie)) { SSLerror(s, ERR_R_INTERNAL_ERROR); goto err; } if (!CBB_add_u8_length_prefixed(&client_hello, &cookie)) goto err; - if (!CBB_add_bytes(&cookie, D1I(s)->cookie, - D1I(s)->cookie_len)) + if (!CBB_add_bytes(&cookie, s->d1->cookie, + s->d1->cookie_len)) goto err; } @@ -764,7 +734,7 @@ ssl3_send_client_hello(SSL *s) if (!ssl3_handshake_msg_finish(s, &cbb)) goto err; - S3I(s)->hs.state = SSL3_ST_CW_CLNT_HELLO_B; + s->s3->hs.state = SSL3_ST_CW_CLNT_HELLO_B; } /* SSL3_ST_CW_CLNT_HELLO_B */ @@ -779,27 +749,26 @@ ssl3_send_client_hello(SSL *s) int ssl3_get_dtls_hello_verify(SSL *s) { - long n; - int al, ok = 0; + CBS hello_verify_request, cookie; size_t cookie_len; uint16_t ssl_version; - CBS hello_verify_request, cookie; + int al, ret; - n = ssl3_get_message(s, DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A, - DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B, -1, s->internal->max_cert_list, &ok); - if (!ok) - return ((int)n); + if ((ret = ssl3_get_message(s, DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A, + DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B, -1, s->internal->max_cert_list)) <= 0) + return ret; - if (S3I(s)->hs.tls12.message_type != DTLS1_MT_HELLO_VERIFY_REQUEST) { - D1I(s)->send_cookie = 0; - S3I(s)->hs.tls12.reuse_message = 1; + if (s->s3->hs.tls12.message_type != DTLS1_MT_HELLO_VERIFY_REQUEST) { + s->d1->send_cookie = 0; + s->s3->hs.tls12.reuse_message = 1; return (1); } - if (n < 0) + if (s->internal->init_num < 0) goto decode_err; - CBS_init(&hello_verify_request, s->internal->init_msg, n); + CBS_init(&hello_verify_request, s->internal->init_msg, + s->internal->init_num); if (!CBS_get_u16(&hello_verify_request, &ssl_version)) goto decode_err; @@ -820,14 +789,14 @@ ssl3_get_dtls_hello_verify(SSL *s) goto fatal_err; } - if (!CBS_write_bytes(&cookie, D1I(s)->cookie, - sizeof(D1I(s)->cookie), &cookie_len)) { - D1I(s)->cookie_len = 0; + if (!CBS_write_bytes(&cookie, s->d1->cookie, + sizeof(s->d1->cookie), &cookie_len)) { + s->d1->cookie_len = 0; al = SSL_AD_ILLEGAL_PARAMETER; goto fatal_err; } - D1I(s)->cookie_len = cookie_len; - D1I(s)->send_cookie = 1; + s->d1->cookie_len = cookie_len; + s->d1->send_cookie = 1; return 1; @@ -848,25 +817,23 @@ ssl3_get_server_hello(SSL *s) const SSL_METHOD *method; unsigned long alg_k; size_t outlen; - int al, ok; - long n; + int al, ret; s->internal->first_packet = 1; - n = ssl3_get_message(s, SSL3_ST_CR_SRVR_HELLO_A, - SSL3_ST_CR_SRVR_HELLO_B, -1, 20000, /* ?? */ &ok); - if (!ok) - return ((int)n); + if ((ret = ssl3_get_message(s, SSL3_ST_CR_SRVR_HELLO_A, + SSL3_ST_CR_SRVR_HELLO_B, -1, 20000 /* ?? */)) <= 0) + return ret; s->internal->first_packet = 0; - if (n < 0) + if (s->internal->init_num < 0) goto decode_err; - CBS_init(&cbs, s->internal->init_msg, n); + CBS_init(&cbs, s->internal->init_msg, s->internal->init_num); if (SSL_is_dtls(s)) { - if (S3I(s)->hs.tls12.message_type == DTLS1_MT_HELLO_VERIFY_REQUEST) { - if (D1I(s)->send_cookie == 0) { - S3I(s)->hs.tls12.reuse_message = 1; + if (s->s3->hs.tls12.message_type == DTLS1_MT_HELLO_VERIFY_REQUEST) { + if (s->d1->send_cookie == 0) { + s->s3->hs.tls12.reuse_message = 1; return (1); } else { /* Already sent a cookie. */ @@ -877,7 +844,7 @@ ssl3_get_server_hello(SSL *s) } } - if (S3I(s)->hs.tls12.message_type != SSL3_MT_SERVER_HELLO) { + if (s->s3->hs.tls12.message_type != SSL3_MT_SERVER_HELLO) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerror(s, SSL_R_BAD_MESSAGE_TYPE); goto fatal_err; @@ -892,10 +859,11 @@ ssl3_get_server_hello(SSL *s) al = SSL_AD_PROTOCOL_VERSION; goto fatal_err; } + s->s3->hs.peer_legacy_version = server_version; s->version = server_version; - S3I(s)->hs.negotiated_tls_version = ssl_tls_version(server_version); - if (S3I(s)->hs.negotiated_tls_version == 0) { + s->s3->hs.negotiated_tls_version = ssl_tls_version(server_version); + if (s->s3->hs.negotiated_tls_version == 0) { SSLerror(s, ERR_R_INTERNAL_ERROR); goto err; } @@ -913,8 +881,8 @@ ssl3_get_server_hello(SSL *s) sizeof(s->s3->server_random), NULL)) goto err; - if (S3I(s)->hs.our_max_tls_version >= TLS1_2_VERSION && - S3I(s)->hs.negotiated_tls_version < S3I(s)->hs.our_max_tls_version) { + if (s->s3->hs.our_max_tls_version >= TLS1_2_VERSION && + s->s3->hs.negotiated_tls_version < s->s3->hs.our_max_tls_version) { /* * RFC 8446 section 4.1.3. We must not downgrade if the server * random value contains the TLS 1.2 or TLS 1.1 magical value. @@ -922,7 +890,7 @@ ssl3_get_server_hello(SSL *s) if (!CBS_skip(&server_random, CBS_len(&server_random) - sizeof(tls13_downgrade_12))) goto err; - if (S3I(s)->hs.negotiated_tls_version == TLS1_2_VERSION && + if (s->s3->hs.negotiated_tls_version == TLS1_2_VERSION && CBS_mem_equal(&server_random, tls13_downgrade_12, sizeof(tls13_downgrade_12))) { al = SSL_AD_ILLEGAL_PARAMETER; @@ -1013,7 +981,7 @@ ssl3_get_server_hello(SSL *s) /* TLS v1.2 only ciphersuites require v1.2 or later. */ if ((cipher->algorithm_ssl & SSL_TLSV1_2) && - S3I(s)->hs.negotiated_tls_version < TLS1_2_VERSION) { + s->s3->hs.negotiated_tls_version < TLS1_2_VERSION) { al = SSL_AD_ILLEGAL_PARAMETER; SSLerror(s, SSL_R_WRONG_CIPHER_RETURNED); goto fatal_err; @@ -1038,7 +1006,7 @@ ssl3_get_server_hello(SSL *s) SSLerror(s, SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED); goto fatal_err; } - S3I(s)->hs.cipher = cipher; + s->s3->hs.cipher = cipher; if (!tls1_transcript_hash_init(s)) goto err; @@ -1047,7 +1015,7 @@ ssl3_get_server_hello(SSL *s) * Don't digest cached records if no sigalgs: we may need them for * client authentication. */ - alg_k = S3I(s)->hs.cipher->algorithm_mkey; + alg_k = s->s3->hs.cipher->algorithm_mkey; if (!(SSL_USE_SIGALGS(s) || (alg_k & SSL_kGOST))) tls1_transcript_free(s); @@ -1076,7 +1044,7 @@ ssl3_get_server_hello(SSL *s) * which doesn't support RI so for the immediate future tolerate RI * absence on initial connect only. */ - if (!S3I(s)->renegotiate_seen && + if (!s->s3->renegotiate_seen && !(s->internal->options & SSL_OP_LEGACY_SERVER_CONNECT)) { al = SSL_AD_HANDSHAKE_FAILURE; SSLerror(s, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); @@ -1103,41 +1071,40 @@ ssl3_get_server_hello(SSL *s) int ssl3_get_server_certificate(SSL *s) { - int al, i, ok, ret = -1; - long n; - CBS cbs, cert_list; - X509 *x = NULL; - const unsigned char *q; - STACK_OF(X509) *sk = NULL; - SESS_CERT *sc; - EVP_PKEY *pkey = NULL; + CBS cbs, cert_list; + X509 *x = NULL; + const unsigned char *q; + STACK_OF(X509) *sk = NULL; + EVP_PKEY *pkey; + int cert_type; + int al, ret; - n = ssl3_get_message(s, SSL3_ST_CR_CERT_A, - SSL3_ST_CR_CERT_B, -1, s->internal->max_cert_list, &ok); - if (!ok) - return ((int)n); + if ((ret = ssl3_get_message(s, SSL3_ST_CR_CERT_A, + SSL3_ST_CR_CERT_B, -1, s->internal->max_cert_list)) <= 0) + return ret; - if (S3I(s)->hs.tls12.message_type == SSL3_MT_SERVER_KEY_EXCHANGE) { - S3I(s)->hs.tls12.reuse_message = 1; + ret = -1; + + if (s->s3->hs.tls12.message_type == SSL3_MT_SERVER_KEY_EXCHANGE) { + s->s3->hs.tls12.reuse_message = 1; return (1); } - if (S3I(s)->hs.tls12.message_type != SSL3_MT_CERTIFICATE) { + if (s->s3->hs.tls12.message_type != SSL3_MT_CERTIFICATE) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerror(s, SSL_R_BAD_MESSAGE_TYPE); goto fatal_err; } - if ((sk = sk_X509_new_null()) == NULL) { SSLerror(s, ERR_R_MALLOC_FAILURE); goto err; } - if (n < 0) + if (s->internal->init_num < 0) goto decode_err; - CBS_init(&cbs, s->internal->init_msg, n); + CBS_init(&cbs, s->internal->init_msg, s->internal->init_num); if (CBS_len(&cbs) < 3) goto decode_err; @@ -1178,62 +1145,45 @@ ssl3_get_server_certificate(SSL *s) x = NULL; } - i = ssl_verify_cert_chain(s, sk); - if ((s->verify_mode != SSL_VERIFY_NONE) && (i <= 0)) { + if (ssl_verify_cert_chain(s, sk) <= 0 && + s->verify_mode != SSL_VERIFY_NONE) { al = ssl_verify_alarm_type(s->verify_result); SSLerror(s, SSL_R_CERTIFICATE_VERIFY_FAILED); goto fatal_err; - } ERR_clear_error(); /* but we keep s->verify_result */ - sc = ssl_sess_cert_new(); - if (sc == NULL) - goto err; - ssl_sess_cert_free(SSI(s)->sess_cert); - SSI(s)->sess_cert = sc; - - sc->cert_chain = sk; /* * Inconsistency alert: cert_chain does include the peer's * certificate, which we don't include in s3_srvr.c */ x = sk_X509_value(sk, 0); - sk = NULL; - /* VRS 19990621: possible memory leak; sk=null ==> !sk_pop_free() @end*/ - pkey = X509_get_pubkey(x); - - if (pkey == NULL || EVP_PKEY_missing_parameters(pkey)) { + if ((pkey = X509_get0_pubkey(x)) == NULL || + EVP_PKEY_missing_parameters(pkey)) { x = NULL; al = SSL3_AL_FATAL; SSLerror(s, SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS); goto fatal_err; } - - i = ssl_cert_type(x, pkey); - if (i < 0) { + if ((cert_type = ssl_cert_type(pkey)) < 0) { x = NULL; al = SSL3_AL_FATAL; SSLerror(s, SSL_R_UNKNOWN_CERTIFICATE_TYPE); goto fatal_err; } - sc->peer_cert_type = i; - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); - /* - * Why would the following ever happen? - * We just created sc a couple of lines ago. - */ - X509_free(sc->peer_pkeys[i].x509); - sc->peer_pkeys[i].x509 = x; - sc->peer_key = &(sc->peer_pkeys[i]); + X509_up_ref(x); + X509_free(s->session->peer_cert); + s->session->peer_cert = x; + s->session->peer_cert_type = cert_type; - X509_free(s->session->peer); - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); - s->session->peer = x; s->session->verify_result = s->verify_result; + sk_X509_pop_free(s->session->cert_chain, X509_free); + s->session->cert_chain = sk; + sk = NULL; + x = NULL; ret = 1; @@ -1246,7 +1196,6 @@ ssl3_get_server_certificate(SSL *s) ssl3_send_alert(s, SSL3_AL_FATAL, al); } err: - EVP_PKEY_free(pkey); X509_free(x); sk_X509_pop_free(sk, X509_free); @@ -1254,239 +1203,132 @@ ssl3_get_server_certificate(SSL *s) } static int -ssl3_get_server_kex_dhe(SSL *s, EVP_PKEY **pkey, CBS *cbs) +ssl3_get_server_kex_dhe(SSL *s, CBS *cbs) { - CBS dhp, dhg, dhpk; - BN_CTX *bn_ctx = NULL; - SESS_CERT *sc = NULL; - DH *dh = NULL; - long alg_a; - int al; + int decode_error, invalid_params, invalid_key; + int nid = NID_dhKeyAgreement; - alg_a = S3I(s)->hs.cipher->algorithm_auth; - sc = SSI(s)->sess_cert; + tls_key_share_free(s->s3->hs.key_share); + if ((s->s3->hs.key_share = tls_key_share_new_nid(nid)) == NULL) + goto err; - if ((dh = DH_new()) == NULL) { - SSLerror(s, ERR_R_DH_LIB); + if (!tls_key_share_peer_params(s->s3->hs.key_share, cbs, + &decode_error, &invalid_params)) { + if (decode_error) { + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + } + goto err; + } + if (!tls_key_share_peer_public(s->s3->hs.key_share, cbs, + &decode_error, &invalid_key)) { + if (decode_error) { + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + } goto err; } - if (!CBS_get_u16_length_prefixed(cbs, &dhp)) - goto decode_err; - if ((dh->p = BN_bin2bn(CBS_data(&dhp), CBS_len(&dhp), NULL)) == NULL) { - SSLerror(s, ERR_R_BN_LIB); - goto err; - } - - if (!CBS_get_u16_length_prefixed(cbs, &dhg)) - goto decode_err; - if ((dh->g = BN_bin2bn(CBS_data(&dhg), CBS_len(&dhg), NULL)) == NULL) { - SSLerror(s, ERR_R_BN_LIB); - goto err; - } - - if (!CBS_get_u16_length_prefixed(cbs, &dhpk)) - goto decode_err; - if ((dh->pub_key = BN_bin2bn(CBS_data(&dhpk), CBS_len(&dhpk), - NULL)) == NULL) { - SSLerror(s, ERR_R_BN_LIB); - goto err; - } - - /* - * Check the strength of the DH key just constructed. - * Discard keys weaker than 1024 bits. - */ - if (DH_size(dh) < 1024 / 8) { + if (invalid_params) { SSLerror(s, SSL_R_BAD_DH_P_LENGTH); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); + goto err; + } + if (invalid_key) { + SSLerror(s, SSL_R_BAD_DH_PUB_KEY_LENGTH); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); goto err; } - if (alg_a & SSL_aRSA) - *pkey = X509_get_pubkey(sc->peer_pkeys[SSL_PKEY_RSA].x509); - else - /* XXX - Anonymous DH, so no certificate or pkey. */ - *pkey = NULL; - - sc->peer_dh_tmp = dh; - - return (1); - - decode_err: - al = SSL_AD_DECODE_ERROR; - SSLerror(s, SSL_R_BAD_PACKET_LENGTH); - ssl3_send_alert(s, SSL3_AL_FATAL, al); + return 1; err: - DH_free(dh); - BN_CTX_free(bn_ctx); - - return (-1); + return 0; } static int -ssl3_get_server_kex_ecdhe_ecp(SSL *s, SESS_CERT *sc, int nid, CBS *public) +ssl3_get_server_kex_ecdhe(SSL *s, CBS *cbs) { - EC_KEY *ecdh = NULL; - int ret = -1; - - /* Extract the server's ephemeral ECDH public key. */ - if ((ecdh = EC_KEY_new()) == NULL) { - SSLerror(s, ERR_R_MALLOC_FAILURE); - goto err; - } - if (!ssl_kex_peer_public_ecdhe_ecp(ecdh, nid, public)) { - SSLerror(s, SSL_R_BAD_ECPOINT); - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - goto err; - } - - sc->peer_nid = nid; - sc->peer_ecdh_tmp = ecdh; - ecdh = NULL; - - ret = 1; - - err: - EC_KEY_free(ecdh); - - return (ret); -} - -static int -ssl3_get_server_kex_ecdhe_ecx(SSL *s, SESS_CERT *sc, int nid, CBS *public) -{ - size_t outlen; - - if (nid != NID_X25519) { - SSLerror(s, ERR_R_INTERNAL_ERROR); - goto err; - } - - if (CBS_len(public) != X25519_KEY_LENGTH) { - SSLerror(s, SSL_R_BAD_ECPOINT); - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - goto err; - } - - if (!CBS_stow(public, &sc->peer_x25519_tmp, &outlen)) { - SSLerror(s, ERR_R_MALLOC_FAILURE); - goto err; - } - - return (1); - - err: - return (-1); -} - -static int -ssl3_get_server_kex_ecdhe(SSL *s, EVP_PKEY **pkey, CBS *cbs) -{ - CBS public; uint8_t curve_type; uint16_t curve_id; - SESS_CERT *sc; - long alg_a; - int nid; - int al; + int decode_error; + CBS public; - alg_a = S3I(s)->hs.cipher->algorithm_auth; - sc = SSI(s)->sess_cert; + if (!CBS_get_u8(cbs, &curve_type)) + goto decode_err; + if (!CBS_get_u16(cbs, &curve_id)) + goto decode_err; /* Only named curves are supported. */ - if (!CBS_get_u8(cbs, &curve_type) || - curve_type != NAMED_CURVE_TYPE || - !CBS_get_u16(cbs, &curve_id)) { - al = SSL_AD_DECODE_ERROR; - SSLerror(s, SSL_R_LENGTH_TOO_SHORT); - goto fatal_err; - } - - /* - * Check that the curve is one of our preferences - if it is not, - * the server has sent us an invalid curve. - */ - if (tls1_check_curve(s, curve_id) != 1) { - al = SSL_AD_DECODE_ERROR; - SSLerror(s, SSL_R_WRONG_CURVE); - goto fatal_err; - } - - if ((nid = tls1_ec_curve_id2nid(curve_id)) == 0) { - al = SSL_AD_INTERNAL_ERROR; - SSLerror(s, SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); - goto fatal_err; + if (curve_type != NAMED_CURVE_TYPE) { + SSLerror(s, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + goto err; } if (!CBS_get_u8_length_prefixed(cbs, &public)) goto decode_err; - if (nid == NID_X25519) { - if (ssl3_get_server_kex_ecdhe_ecx(s, sc, nid, &public) != 1) - goto err; - } else { - if (ssl3_get_server_kex_ecdhe_ecp(s, sc, nid, &public) != 1) - goto err; + /* + * Check that the curve is one of our preferences - if it is not, + * the server has sent us an invalid curve. + */ + if (!tls1_check_curve(s, curve_id)) { + SSLerror(s, SSL_R_WRONG_CURVE); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); + goto err; } - /* - * The ECC/TLS specification does not mention the use of DSA to sign - * ECParameters in the server key exchange message. We do support RSA - * and ECDSA. - */ - if (alg_a & SSL_aRSA) - *pkey = X509_get_pubkey(sc->peer_pkeys[SSL_PKEY_RSA].x509); - else if (alg_a & SSL_aECDSA) - *pkey = X509_get_pubkey(sc->peer_pkeys[SSL_PKEY_ECC].x509); - else - /* XXX - Anonymous ECDH, so no certificate or pkey. */ - *pkey = NULL; + tls_key_share_free(s->s3->hs.key_share); + if ((s->s3->hs.key_share = tls_key_share_new(curve_id)) == NULL) + goto err; - return (1); + if (!tls_key_share_peer_public(s->s3->hs.key_share, &public, + &decode_error, NULL)) { + if (decode_error) + goto decode_err; + goto err; + } + + return 1; decode_err: - al = SSL_AD_DECODE_ERROR; SSLerror(s, SSL_R_BAD_PACKET_LENGTH); - - fatal_err: - ssl3_send_alert(s, SSL3_AL_FATAL, al); - + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); err: - return (-1); + return 0; } int ssl3_get_server_key_exchange(SSL *s) { CBS cbs, signature; - EVP_PKEY *pkey = NULL; - EVP_MD_CTX md_ctx; + EVP_MD_CTX *md_ctx; const unsigned char *param; - long n, alg_k, alg_a; - int al, ok; size_t param_len; + long alg_k, alg_a; + int al, ret; - EVP_MD_CTX_init(&md_ctx); - - alg_k = S3I(s)->hs.cipher->algorithm_mkey; - alg_a = S3I(s)->hs.cipher->algorithm_auth; + alg_k = s->s3->hs.cipher->algorithm_mkey; + alg_a = s->s3->hs.cipher->algorithm_auth; /* * Use same message size as in ssl3_get_certificate_request() * as ServerKeyExchange message may be skipped. */ - n = ssl3_get_message(s, SSL3_ST_CR_KEY_EXCH_A, - SSL3_ST_CR_KEY_EXCH_B, -1, s->internal->max_cert_list, &ok); - if (!ok) - return ((int)n); + if ((ret = ssl3_get_message(s, SSL3_ST_CR_KEY_EXCH_A, + SSL3_ST_CR_KEY_EXCH_B, -1, s->internal->max_cert_list)) <= 0) + return ret; - if (n < 0) + if ((md_ctx = EVP_MD_CTX_new()) == NULL) goto err; - CBS_init(&cbs, s->internal->init_msg, n); + if (s->internal->init_num < 0) + goto err; - if (S3I(s)->hs.tls12.message_type != SSL3_MT_SERVER_KEY_EXCHANGE) { + CBS_init(&cbs, s->internal->init_msg, s->internal->init_num); + + if (s->s3->hs.tls12.message_type != SSL3_MT_SERVER_KEY_EXCHANGE) { /* * Do not skip server key exchange if this cipher suite uses * ephemeral keys. @@ -1497,34 +1339,19 @@ ssl3_get_server_key_exchange(SSL *s) goto fatal_err; } - S3I(s)->hs.tls12.reuse_message = 1; - EVP_MD_CTX_cleanup(&md_ctx); + s->s3->hs.tls12.reuse_message = 1; + EVP_MD_CTX_free(md_ctx); return (1); } - if (SSI(s)->sess_cert != NULL) { - DH_free(SSI(s)->sess_cert->peer_dh_tmp); - SSI(s)->sess_cert->peer_dh_tmp = NULL; - - EC_KEY_free(SSI(s)->sess_cert->peer_ecdh_tmp); - SSI(s)->sess_cert->peer_ecdh_tmp = NULL; - - free(SSI(s)->sess_cert->peer_x25519_tmp); - SSI(s)->sess_cert->peer_x25519_tmp = NULL; - } else { - SSI(s)->sess_cert = ssl_sess_cert_new(); - if (SSI(s)->sess_cert == NULL) - goto err; - } - param = CBS_data(&cbs); param_len = CBS_len(&cbs); if (alg_k & SSL_kDHE) { - if (ssl3_get_server_kex_dhe(s, &pkey, &cbs) != 1) + if (!ssl3_get_server_kex_dhe(s, &cbs)) goto err; } else if (alg_k & SSL_kECDHE) { - if (ssl3_get_server_kex_ecdhe(s, &pkey, &cbs) != 1) + if (!ssl3_get_server_kex_ecdhe(s, &cbs)) goto err; } else if (alg_k != 0) { al = SSL_AD_UNEXPECTED_MESSAGE; @@ -1535,10 +1362,24 @@ ssl3_get_server_key_exchange(SSL *s) param_len -= CBS_len(&cbs); /* if it was signed, check the signature */ - if (pkey != NULL) { + if ((alg_a & SSL_aNULL) == 0) { uint16_t sigalg_value = SIGALG_NONE; const struct ssl_sigalg *sigalg; EVP_PKEY_CTX *pctx; + EVP_PKEY *pkey = NULL; + + if ((alg_a & SSL_aRSA) != 0 && + s->session->peer_cert_type == SSL_PKEY_RSA) { + pkey = X509_get0_pubkey(s->session->peer_cert); + } else if ((alg_a & SSL_aECDSA) != 0 && + s->session->peer_cert_type == SSL_PKEY_ECC) { + pkey = X509_get0_pubkey(s->session->peer_cert); + } + if (pkey == NULL) { + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerror(s, SSL_R_UNKNOWN_CERTIFICATE_TYPE); + goto fatal_err; + } if (SSL_USE_SIGALGS(s)) { if (!CBS_get_u16(&cbs, &sigalg_value)) @@ -1557,12 +1398,12 @@ ssl3_get_server_key_exchange(SSL *s) al = SSL_AD_DECODE_ERROR; goto fatal_err; } - S3I(s)->hs.peer_sigalg = sigalg; + s->s3->hs.peer_sigalg = sigalg; - if (!EVP_DigestVerifyInit(&md_ctx, &pctx, sigalg->md(), + if (!EVP_DigestVerifyInit(md_ctx, &pctx, sigalg->md(), NULL, pkey)) goto err; - if (!EVP_DigestVerifyUpdate(&md_ctx, s->s3->client_random, + if (!EVP_DigestVerifyUpdate(md_ctx, s->s3->client_random, SSL3_RANDOM_SIZE)) goto err; if ((sigalg->flags & SIGALG_FLAG_RSA_PSS) && @@ -1570,23 +1411,17 @@ ssl3_get_server_key_exchange(SSL *s) RSA_PKCS1_PSS_PADDING) || !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1))) goto err; - if (!EVP_DigestVerifyUpdate(&md_ctx, s->s3->server_random, + if (!EVP_DigestVerifyUpdate(md_ctx, s->s3->server_random, SSL3_RANDOM_SIZE)) goto err; - if (!EVP_DigestVerifyUpdate(&md_ctx, param, param_len)) + if (!EVP_DigestVerifyUpdate(md_ctx, param, param_len)) goto err; - if (EVP_DigestVerifyFinal(&md_ctx, CBS_data(&signature), + if (EVP_DigestVerifyFinal(md_ctx, CBS_data(&signature), CBS_len(&signature)) <= 0) { al = SSL_AD_DECRYPT_ERROR; SSLerror(s, SSL_R_BAD_SIGNATURE); goto fatal_err; } - } else { - /* aNULL does not need public keys. */ - if (!(alg_a & SSL_aNULL)) { - SSLerror(s, ERR_R_INTERNAL_ERROR); - goto err; - } } if (CBS_len(&cbs) != 0) { @@ -1595,8 +1430,7 @@ ssl3_get_server_key_exchange(SSL *s) goto fatal_err; } - EVP_PKEY_free(pkey); - EVP_MD_CTX_cleanup(&md_ctx); + EVP_MD_CTX_free(md_ctx); return (1); @@ -1608,8 +1442,7 @@ ssl3_get_server_key_exchange(SSL *s) ssl3_send_alert(s, SSL3_AL_FATAL, al); err: - EVP_PKEY_free(pkey); - EVP_MD_CTX_cleanup(&md_ctx); + EVP_MD_CTX_free(md_ctx); return (-1); } @@ -1617,22 +1450,22 @@ ssl3_get_server_key_exchange(SSL *s) int ssl3_get_certificate_request(SSL *s) { - int ok, ret = 0; - long n; - CBS cert_request, cert_types, rdn_list; - X509_NAME *xn = NULL; - const unsigned char *q; - STACK_OF(X509_NAME) *ca_sk = NULL; + CBS cert_request, cert_types, rdn_list; + X509_NAME *xn = NULL; + const unsigned char *q; + STACK_OF(X509_NAME) *ca_sk = NULL; + int ret; - n = ssl3_get_message(s, SSL3_ST_CR_CERT_REQ_A, - SSL3_ST_CR_CERT_REQ_B, -1, s->internal->max_cert_list, &ok); - if (!ok) - return ((int)n); + if ((ret = ssl3_get_message(s, SSL3_ST_CR_CERT_REQ_A, + SSL3_ST_CR_CERT_REQ_B, -1, s->internal->max_cert_list)) <= 0) + return ret; - S3I(s)->hs.tls12.cert_request = 0; + ret = 0; - if (S3I(s)->hs.tls12.message_type == SSL3_MT_SERVER_DONE) { - S3I(s)->hs.tls12.reuse_message = 1; + s->s3->hs.tls12.cert_request = 0; + + if (s->s3->hs.tls12.message_type == SSL3_MT_SERVER_DONE) { + s->s3->hs.tls12.reuse_message = 1; /* * If we get here we don't need any cached handshake records * as we wont be doing client auth. @@ -1641,22 +1474,22 @@ ssl3_get_certificate_request(SSL *s) return (1); } - if (S3I(s)->hs.tls12.message_type != SSL3_MT_CERTIFICATE_REQUEST) { + if (s->s3->hs.tls12.message_type != SSL3_MT_CERTIFICATE_REQUEST) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); SSLerror(s, SSL_R_WRONG_MESSAGE_TYPE); goto err; } /* TLS does not like anon-DH with client cert */ - if (S3I(s)->hs.cipher->algorithm_auth & SSL_aNULL) { + if (s->s3->hs.cipher->algorithm_auth & SSL_aNULL) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); SSLerror(s, SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER); goto err; } - if (n < 0) + if (s->internal->init_num < 0) goto decode_err; - CBS_init(&cert_request, s->internal->init_msg, n); + CBS_init(&cert_request, s->internal->init_msg, s->internal->init_num); if ((ca_sk = sk_X509_NAME_new(ca_dn_cmp)) == NULL) { SSLerror(s, ERR_R_MALLOC_FAILURE); @@ -1683,8 +1516,8 @@ ssl3_get_certificate_request(SSL *s) SSLerror(s, SSL_R_SIGNATURE_ALGORITHMS_ERROR); goto err; } - if (!CBS_stow(&sigalgs, &S3I(s)->hs.sigalgs, - &S3I(s)->hs.sigalgs_len)) + if (!CBS_stow(&sigalgs, &s->s3->hs.sigalgs, + &s->s3->hs.sigalgs_len)) goto err; } @@ -1736,9 +1569,9 @@ ssl3_get_certificate_request(SSL *s) } /* we should setup a certificate to return.... */ - S3I(s)->hs.tls12.cert_request = 1; - sk_X509_NAME_pop_free(S3I(s)->hs.tls12.ca_names, X509_NAME_free); - S3I(s)->hs.tls12.ca_names = ca_sk; + s->s3->hs.tls12.cert_request = 1; + sk_X509_NAME_pop_free(s->s3->hs.tls12.ca_names, X509_NAME_free); + s->s3->hs.tls12.ca_names = ca_sk; ca_sk = NULL; ret = 1; @@ -1761,44 +1594,39 @@ ca_dn_cmp(const X509_NAME * const *a, const X509_NAME * const *b) int ssl3_get_new_session_ticket(SSL *s) { - int ok, al, ret = 0; - uint32_t lifetime_hint; - long n; - CBS cbs, session_ticket; + uint32_t lifetime_hint; + CBS cbs, session_ticket; + int al, ret; - n = ssl3_get_message(s, SSL3_ST_CR_SESSION_TICKET_A, - SSL3_ST_CR_SESSION_TICKET_B, -1, 16384, &ok); - if (!ok) - return ((int)n); + if ((ret = ssl3_get_message(s, SSL3_ST_CR_SESSION_TICKET_A, + SSL3_ST_CR_SESSION_TICKET_B, -1, 16384)) <= 0) + return ret; - if (S3I(s)->hs.tls12.message_type == SSL3_MT_FINISHED) { - S3I(s)->hs.tls12.reuse_message = 1; + if (s->s3->hs.tls12.message_type == SSL3_MT_FINISHED) { + s->s3->hs.tls12.reuse_message = 1; return (1); } - if (S3I(s)->hs.tls12.message_type != SSL3_MT_NEWSESSION_TICKET) { + if (s->s3->hs.tls12.message_type != SSL3_MT_NEWSESSION_TICKET) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerror(s, SSL_R_BAD_MESSAGE_TYPE); goto fatal_err; } - if (n < 0) { + if (s->internal->init_num < 0) { al = SSL_AD_DECODE_ERROR; SSLerror(s, SSL_R_LENGTH_MISMATCH); goto fatal_err; } - CBS_init(&cbs, s->internal->init_msg, n); + CBS_init(&cbs, s->internal->init_msg, s->internal->init_num); if (!CBS_get_u32(&cbs, &lifetime_hint) || -#if UINT32_MAX > LONG_MAX - lifetime_hint > LONG_MAX || -#endif !CBS_get_u16_length_prefixed(&cbs, &session_ticket) || CBS_len(&cbs) != 0) { al = SSL_AD_DECODE_ERROR; SSLerror(s, SSL_R_LENGTH_MISMATCH); goto fatal_err; } - s->session->tlsext_tick_lifetime_hint = (long)lifetime_hint; + s->session->tlsext_tick_lifetime_hint = lifetime_hint; if (!CBS_stow(&session_ticket, &s->session->tlsext_tick, &s->session->tlsext_ticklen)) { @@ -1825,8 +1653,9 @@ ssl3_get_new_session_ticket(SSL *s) EVP_Digest(CBS_data(&session_ticket), CBS_len(&session_ticket), s->session->session_id, &s->session->session_id_length, EVP_sha256(), NULL); - ret = 1; - return (ret); + + return (1); + fatal_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); err: @@ -1836,24 +1665,20 @@ ssl3_get_new_session_ticket(SSL *s) int ssl3_get_cert_status(SSL *s) { - CBS cert_status, response; - int ok, al; - long n; - uint8_t status_type; + CBS cert_status, response; + uint8_t status_type; + int al, ret; - n = ssl3_get_message(s, SSL3_ST_CR_CERT_STATUS_A, - SSL3_ST_CR_CERT_STATUS_B, -1, 16384, &ok); - if (!ok) - return ((int)n); + if ((ret = ssl3_get_message(s, SSL3_ST_CR_CERT_STATUS_A, + SSL3_ST_CR_CERT_STATUS_B, -1, 16384)) <= 0) + return ret; - if (S3I(s)->hs.tls12.message_type == SSL3_MT_SERVER_KEY_EXCHANGE) { + if (s->s3->hs.tls12.message_type == SSL3_MT_SERVER_KEY_EXCHANGE) { /* * Tell the callback the server did not send us an OSCP * response, and has decided to head directly to key exchange. */ if (s->ctx->internal->tlsext_status_cb) { - int ret; - free(s->internal->tlsext_ocsp_resp); s->internal->tlsext_ocsp_resp = NULL; s->internal->tlsext_ocsp_resp_len = 0; @@ -1871,25 +1696,25 @@ ssl3_get_cert_status(SSL *s) goto fatal_err; } } - S3I(s)->hs.tls12.reuse_message = 1; + s->s3->hs.tls12.reuse_message = 1; return (1); } - if (S3I(s)->hs.tls12.message_type != SSL3_MT_CERTIFICATE && - S3I(s)->hs.tls12.message_type != SSL3_MT_CERTIFICATE_STATUS) { + if (s->s3->hs.tls12.message_type != SSL3_MT_CERTIFICATE && + s->s3->hs.tls12.message_type != SSL3_MT_CERTIFICATE_STATUS) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerror(s, SSL_R_BAD_MESSAGE_TYPE); goto fatal_err; } - if (n < 0) { + if (s->internal->init_num < 0) { /* need at least status type + length */ al = SSL_AD_DECODE_ERROR; SSLerror(s, SSL_R_LENGTH_MISMATCH); goto fatal_err; } - CBS_init(&cert_status, s->internal->init_msg, n); + CBS_init(&cert_status, s->internal->init_msg, s->internal->init_num); if (!CBS_get_u8(&cert_status, &status_type) || CBS_len(&cert_status) < 3) { /* need at least status type + length */ @@ -1942,32 +1767,32 @@ ssl3_get_cert_status(SSL *s) int ssl3_get_server_done(SSL *s) { - int ok, ret = 0; - long n; + int ret; - n = ssl3_get_message(s, SSL3_ST_CR_SRVR_DONE_A, - SSL3_ST_CR_SRVR_DONE_B, SSL3_MT_SERVER_DONE, - 30, /* should be very small, like 0 :-) */ &ok); - if (!ok) - return ((int)n); + if ((ret = ssl3_get_message(s, SSL3_ST_CR_SRVR_DONE_A, + SSL3_ST_CR_SRVR_DONE_B, SSL3_MT_SERVER_DONE, + 30 /* should be very small, like 0 :-) */)) <= 0) + return ret; - if (n > 0) { + if (s->internal->init_num != 0) { /* should contain no data */ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); SSLerror(s, SSL_R_LENGTH_MISMATCH); - return (-1); + return -1; } - ret = 1; - return (ret); + + return 1; } static int -ssl3_send_client_kex_rsa(SSL *s, SESS_CERT *sess_cert, CBB *cbb) +ssl3_send_client_kex_rsa(SSL *s, CBB *cbb) { unsigned char pms[SSL_MAX_MASTER_KEY_LENGTH]; unsigned char *enc_pms = NULL; - EVP_PKEY *pkey = NULL; - int ret = -1; + uint16_t max_legacy_version; + EVP_PKEY *pkey; + RSA *rsa; + int ret = 0; int enc_len; CBB epms; @@ -1975,24 +1800,31 @@ ssl3_send_client_kex_rsa(SSL *s, SESS_CERT *sess_cert, CBB *cbb) * RSA-Encrypted Premaster Secret Message - RFC 5246 section 7.4.7.1. */ - pkey = X509_get_pubkey(sess_cert->peer_pkeys[SSL_PKEY_RSA].x509); - if (pkey == NULL || pkey->type != EVP_PKEY_RSA || - pkey->pkey.rsa == NULL) { + pkey = X509_get0_pubkey(s->session->peer_cert); + if (pkey == NULL || (rsa = EVP_PKEY_get0_RSA(pkey)) == NULL) { SSLerror(s, ERR_R_INTERNAL_ERROR); goto err; } - /* XXX - our max protocol version. */ - pms[0] = s->client_version >> 8; - pms[1] = s->client_version & 0xff; + /* + * Our maximum legacy protocol version - while RFC 5246 section 7.4.7.1 + * says "The latest (newest) version supported by the client", if we're + * doing RSA key exchange then we have to presume that we're talking to + * a server that does not understand the supported versions extension + * and therefore our maximum version is that sent in the ClientHello. + */ + if (!ssl_max_legacy_version(s, &max_legacy_version)) + goto err; + pms[0] = max_legacy_version >> 8; + pms[1] = max_legacy_version & 0xff; arc4random_buf(&pms[2], sizeof(pms) - 2); - if ((enc_pms = malloc(RSA_size(pkey->pkey.rsa))) == NULL) { + if ((enc_pms = malloc(RSA_size(rsa))) == NULL) { SSLerror(s, ERR_R_MALLOC_FAILURE); goto err; } - enc_len = RSA_public_encrypt(sizeof(pms), pms, enc_pms, pkey->pkey.rsa, + enc_len = RSA_public_encrypt(sizeof(pms), pms, enc_pms, rsa, RSA_PKCS1_PADDING); if (enc_len <= 0) { SSLerror(s, SSL_R_BAD_RSA_ENCRYPT); @@ -2013,99 +1845,32 @@ ssl3_send_client_kex_rsa(SSL *s, SESS_CERT *sess_cert, CBB *cbb) err: explicit_bzero(pms, sizeof(pms)); - EVP_PKEY_free(pkey); free(enc_pms); - return (ret); + return ret; } static int -ssl3_send_client_kex_dhe(SSL *s, SESS_CERT *sess_cert, CBB *cbb) +ssl3_send_client_kex_dhe(SSL *s, CBB *cbb) { - DH *dh_srvr = NULL, *dh_clnt = NULL; - unsigned char *key = NULL; - int key_size = 0, key_len; - unsigned char *data; - int ret = -1; - CBB dh_Yc; + uint8_t *key = NULL; + size_t key_len = 0; + int ret = 0; - /* Ensure that we have an ephemeral key for DHE. */ - if (sess_cert->peer_dh_tmp == NULL) { + /* Ensure that we have an ephemeral key from the server for DHE. */ + if (s->s3->hs.key_share == NULL) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); SSLerror(s, SSL_R_UNABLE_TO_FIND_DH_PARAMETERS); goto err; } - dh_srvr = sess_cert->peer_dh_tmp; - /* Generate a new random key. */ - if ((dh_clnt = DHparams_dup(dh_srvr)) == NULL) { - SSLerror(s, ERR_R_DH_LIB); + if (!tls_key_share_generate(s->s3->hs.key_share)) goto err; - } - if (!DH_generate_key(dh_clnt)) { - SSLerror(s, ERR_R_DH_LIB); + if (!tls_key_share_public(s->s3->hs.key_share, cbb)) goto err; - } - if ((key_size = DH_size(dh_clnt)) <= 0) { - SSLerror(s, ERR_R_DH_LIB); - goto err; - } - if ((key = malloc(key_size)) == NULL) { - SSLerror(s, ERR_R_MALLOC_FAILURE); - goto err; - } - if ((key_len = DH_compute_key(key, dh_srvr->pub_key, dh_clnt)) <= 0) { - SSLerror(s, ERR_R_DH_LIB); - goto err; - } - - if (!tls12_derive_master_secret(s, key, key_len)) + if (!tls_key_share_derive(s->s3->hs.key_share, &key, &key_len)) goto err; - if (!CBB_add_u16_length_prefixed(cbb, &dh_Yc)) - goto err; - if (!CBB_add_space(&dh_Yc, &data, BN_num_bytes(dh_clnt->pub_key))) - goto err; - BN_bn2bin(dh_clnt->pub_key, data); - if (!CBB_flush(cbb)) - goto err; - - ret = 1; - - err: - DH_free(dh_clnt); - freezero(key, key_size); - - return (ret); -} - -static int -ssl3_send_client_kex_ecdhe_ecp(SSL *s, SESS_CERT *sc, CBB *cbb) -{ - EC_KEY *ecdh = NULL; - uint8_t *key = NULL; - size_t key_len = 0; - int ret = -1; - CBB ecpoint; - - if ((ecdh = EC_KEY_new()) == NULL) { - SSLerror(s, ERR_R_MALLOC_FAILURE); - goto err; - } - - if (!ssl_kex_generate_ecdhe_ecp(ecdh, sc->peer_nid)) - goto err; - - /* Encode our public key. */ - if (!CBB_add_u8_length_prefixed(cbb, &ecpoint)) - goto err; - if (!ssl_kex_public_ecdhe_ecp(ecdh, &ecpoint)) - goto err; - if (!CBB_flush(cbb)) - goto err; - - if (!ssl_kex_derive_ecdhe_ecp(ecdh, sc->peer_ecdh_tmp, &key, &key_len)) - goto err; if (!tls12_derive_master_secret(s, key, key_len)) goto err; @@ -2113,109 +1878,90 @@ ssl3_send_client_kex_ecdhe_ecp(SSL *s, SESS_CERT *sc, CBB *cbb) err: freezero(key, key_len); - EC_KEY_free(ecdh); - return (ret); + return ret; } static int -ssl3_send_client_kex_ecdhe_ecx(SSL *s, SESS_CERT *sc, CBB *cbb) +ssl3_send_client_kex_ecdhe(SSL *s, CBB *cbb) { - uint8_t *public_key = NULL, *private_key = NULL, *shared_key = NULL; - int ret = -1; - CBB ecpoint; + uint8_t *key = NULL; + size_t key_len = 0; + CBB public; + int ret = 0; - /* Generate X25519 key pair and derive shared key. */ - if ((public_key = malloc(X25519_KEY_LENGTH)) == NULL) - goto err; - if ((private_key = malloc(X25519_KEY_LENGTH)) == NULL) - goto err; - if ((shared_key = malloc(X25519_KEY_LENGTH)) == NULL) - goto err; - X25519_keypair(public_key, private_key); - if (!X25519(shared_key, private_key, sc->peer_x25519_tmp)) - goto err; - - /* Serialize the public key. */ - if (!CBB_add_u8_length_prefixed(cbb, &ecpoint)) - goto err; - if (!CBB_add_bytes(&ecpoint, public_key, X25519_KEY_LENGTH)) - goto err; - if (!CBB_flush(cbb)) - goto err; - - if (!tls12_derive_master_secret(s, shared_key, X25519_KEY_LENGTH)) - goto err; - - ret = 1; - - err: - free(public_key); - freezero(private_key, X25519_KEY_LENGTH); - freezero(shared_key, X25519_KEY_LENGTH); - - return (ret); -} - -static int -ssl3_send_client_kex_ecdhe(SSL *s, SESS_CERT *sc, CBB *cbb) -{ - if (sc->peer_x25519_tmp != NULL) { - if (ssl3_send_client_kex_ecdhe_ecx(s, sc, cbb) != 1) - goto err; - } else if (sc->peer_ecdh_tmp != NULL) { - if (ssl3_send_client_kex_ecdhe_ecp(s, sc, cbb) != 1) - goto err; - } else { + /* Ensure that we have an ephemeral key for ECDHE. */ + if (s->s3->hs.key_share == NULL) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); SSLerror(s, ERR_R_INTERNAL_ERROR); goto err; } - return (1); + if (!tls_key_share_generate(s->s3->hs.key_share)) + goto err; + + if (!CBB_add_u8_length_prefixed(cbb, &public)) + return 0; + if (!tls_key_share_public(s->s3->hs.key_share, &public)) + goto err; + if (!CBB_flush(cbb)) + goto err; + + if (!tls_key_share_derive(s->s3->hs.key_share, &key, &key_len)) + goto err; + + if (!tls12_derive_master_secret(s, key, key_len)) + goto err; + + ret = 1; err: - return (-1); + freezero(key, key_len); + + return ret; } static int -ssl3_send_client_kex_gost(SSL *s, SESS_CERT *sess_cert, CBB *cbb) +ssl3_send_client_kex_gost(SSL *s, CBB *cbb) { unsigned char premaster_secret[32], shared_ukm[32], tmp[256]; - EVP_PKEY *pub_key = NULL; - EVP_PKEY_CTX *pkey_ctx; - X509 *peer_cert; + EVP_PKEY_CTX *pkey_ctx = NULL; + EVP_MD_CTX *ukm_hash = NULL; + EVP_PKEY *pkey; size_t msglen; unsigned int md_len; - EVP_MD_CTX *ukm_hash; - int ret = -1; - int nid; CBB gostblob; + int nid; + int ret = 0; /* Get server sertificate PKEY and create ctx from it */ - peer_cert = sess_cert->peer_pkeys[SSL_PKEY_GOST01].x509; - if (peer_cert == NULL) { + pkey = X509_get0_pubkey(s->session->peer_cert); + if (pkey == NULL || s->session->peer_cert_type != SSL_PKEY_GOST01) { SSLerror(s, SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER); goto err; } - - pub_key = X509_get_pubkey(peer_cert); - pkey_ctx = EVP_PKEY_CTX_new(pub_key, NULL); + if ((pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) { + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto err; + } /* * If we have send a certificate, and certificate key parameters match * those of server certificate, use certificate key for key exchange. * Otherwise, generate ephemeral key pair. */ - EVP_PKEY_encrypt_init(pkey_ctx); + if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0) + goto err; /* Generate session key. */ - arc4random_buf(premaster_secret, 32); + arc4random_buf(premaster_secret, sizeof(premaster_secret)); /* * If we have client certificate, use its secret as peer key. + * XXX - this presumably lacks PFS. */ - if (S3I(s)->hs.tls12.cert_request && s->cert->key->privatekey) { + if (s->s3->hs.tls12.cert_request != 0 && + s->cert->key->privatekey != NULL) { if (EVP_PKEY_derive_set_peer(pkey_ctx, s->cert->key->privatekey) <=0) { /* @@ -2229,23 +1975,24 @@ ssl3_send_client_kex_gost(SSL *s, SESS_CERT *sess_cert, CBB *cbb) /* * Compute shared IV and store it in algorithm-specific context data. */ - ukm_hash = EVP_MD_CTX_new(); - if (ukm_hash == NULL) { + if ((ukm_hash = EVP_MD_CTX_new()) == NULL) { SSLerror(s, ERR_R_MALLOC_FAILURE); goto err; } /* XXX check handshake hash instead. */ - if (S3I(s)->hs.cipher->algorithm2 & SSL_HANDSHAKE_MAC_GOST94) + if (s->s3->hs.cipher->algorithm2 & SSL_HANDSHAKE_MAC_GOST94) nid = NID_id_GostR3411_94; else nid = NID_id_tc26_gost3411_2012_256; if (!EVP_DigestInit(ukm_hash, EVP_get_digestbynid(nid))) goto err; - EVP_DigestUpdate(ukm_hash, s->s3->client_random, SSL3_RANDOM_SIZE); - EVP_DigestUpdate(ukm_hash, s->s3->server_random, SSL3_RANDOM_SIZE); - EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len); - EVP_MD_CTX_free(ukm_hash); + if (!EVP_DigestUpdate(ukm_hash, s->s3->client_random, SSL3_RANDOM_SIZE)) + goto err; + if (!EVP_DigestUpdate(ukm_hash, s->s3->server_random, SSL3_RANDOM_SIZE)) + goto err; + if (!EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len)) + goto err; if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT, EVP_PKEY_CTRL_SET_IV, 8, shared_ukm) < 0) { SSLerror(s, SSL_R_LIBRARY_BUG); @@ -2257,7 +2004,7 @@ ssl3_send_client_kex_gost(SSL *s, SESS_CERT *sess_cert, CBB *cbb) */ msglen = 255; if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, premaster_secret, - 32) < 0) { + sizeof(premaster_secret)) < 0) { SSLerror(s, SSL_R_LIBRARY_BUG); goto err; } @@ -2271,11 +2018,8 @@ ssl3_send_client_kex_gost(SSL *s, SESS_CERT *sess_cert, CBB *cbb) /* Check if pubkey from client certificate was used. */ if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, - NULL) > 0) { - /* Set flag "skip certificate verify". */ + NULL) > 0) s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY; - } - EVP_PKEY_CTX_free(pkey_ctx); if (!tls12_derive_master_secret(s, premaster_secret, 32)) goto err; @@ -2284,45 +2028,38 @@ ssl3_send_client_kex_gost(SSL *s, SESS_CERT *sess_cert, CBB *cbb) err: explicit_bzero(premaster_secret, sizeof(premaster_secret)); - EVP_PKEY_free(pub_key); + EVP_PKEY_CTX_free(pkey_ctx); + EVP_MD_CTX_free(ukm_hash); - return (ret); + return ret; } int ssl3_send_client_key_exchange(SSL *s) { - SESS_CERT *sess_cert; unsigned long alg_k; CBB cbb, kex; memset(&cbb, 0, sizeof(cbb)); - if (S3I(s)->hs.state == SSL3_ST_CW_KEY_EXCH_A) { - alg_k = S3I(s)->hs.cipher->algorithm_mkey; - - if ((sess_cert = SSI(s)->sess_cert) == NULL) { - ssl3_send_alert(s, SSL3_AL_FATAL, - SSL_AD_UNEXPECTED_MESSAGE); - SSLerror(s, ERR_R_INTERNAL_ERROR); - goto err; - } + if (s->s3->hs.state == SSL3_ST_CW_KEY_EXCH_A) { + alg_k = s->s3->hs.cipher->algorithm_mkey; if (!ssl3_handshake_msg_start(s, &cbb, &kex, SSL3_MT_CLIENT_KEY_EXCHANGE)) goto err; if (alg_k & SSL_kRSA) { - if (ssl3_send_client_kex_rsa(s, sess_cert, &kex) != 1) + if (!ssl3_send_client_kex_rsa(s, &kex)) goto err; } else if (alg_k & SSL_kDHE) { - if (ssl3_send_client_kex_dhe(s, sess_cert, &kex) != 1) + if (!ssl3_send_client_kex_dhe(s, &kex)) goto err; } else if (alg_k & SSL_kECDHE) { - if (ssl3_send_client_kex_ecdhe(s, sess_cert, &kex) != 1) + if (!ssl3_send_client_kex_ecdhe(s, &kex)) goto err; } else if (alg_k & SSL_kGOST) { - if (ssl3_send_client_kex_gost(s, sess_cert, &kex) != 1) + if (!ssl3_send_client_kex_gost(s, &kex)) goto err; } else { ssl3_send_alert(s, SSL3_AL_FATAL, @@ -2334,7 +2071,7 @@ ssl3_send_client_key_exchange(SSL *s) if (!ssl3_handshake_msg_finish(s, &cbb)) goto err; - S3I(s)->hs.state = SSL3_ST_CW_KEY_EXCH_B; + s->s3->hs.state = SSL3_ST_CW_KEY_EXCH_B; } /* SSL3_ST_CW_KEY_EXCH_B */ @@ -2352,19 +2089,20 @@ ssl3_send_client_verify_sigalgs(SSL *s, EVP_PKEY *pkey, { CBB cbb_signature; EVP_PKEY_CTX *pctx = NULL; - EVP_MD_CTX mctx; + EVP_MD_CTX *mctx = NULL; const unsigned char *hdata; unsigned char *signature = NULL; size_t signature_len, hdata_len; int ret = 0; - EVP_MD_CTX_init(&mctx); + if ((mctx = EVP_MD_CTX_new()) == NULL) + goto err; if (!tls1_transcript_data(s, &hdata, &hdata_len)) { SSLerror(s, ERR_R_INTERNAL_ERROR); goto err; } - if (!EVP_DigestSignInit(&mctx, &pctx, sigalg->md(), NULL, pkey)) { + if (!EVP_DigestSignInit(mctx, &pctx, sigalg->md(), NULL, pkey)) { SSLerror(s, ERR_R_EVP_LIB); goto err; } @@ -2380,11 +2118,11 @@ ssl3_send_client_verify_sigalgs(SSL *s, EVP_PKEY *pkey, SSLerror(s, ERR_R_EVP_LIB); goto err; } - if (!EVP_DigestSignUpdate(&mctx, hdata, hdata_len)) { + if (!EVP_DigestSignUpdate(mctx, hdata, hdata_len)) { SSLerror(s, ERR_R_EVP_LIB); goto err; } - if (!EVP_DigestSignFinal(&mctx, NULL, &signature_len) || + if (!EVP_DigestSignFinal(mctx, NULL, &signature_len) || signature_len == 0) { SSLerror(s, ERR_R_EVP_LIB); goto err; @@ -2393,7 +2131,7 @@ ssl3_send_client_verify_sigalgs(SSL *s, EVP_PKEY *pkey, SSLerror(s, ERR_R_MALLOC_FAILURE); goto err; } - if (!EVP_DigestSignFinal(&mctx, signature, &signature_len)) { + if (!EVP_DigestSignFinal(mctx, signature, &signature_len)) { SSLerror(s, ERR_R_EVP_LIB); goto err; } @@ -2410,7 +2148,7 @@ ssl3_send_client_verify_sigalgs(SSL *s, EVP_PKEY *pkey, ret = 1; err: - EVP_MD_CTX_cleanup(&mctx); + EVP_MD_CTX_free(mctx); free(signature); return ret; } @@ -2419,6 +2157,7 @@ static int ssl3_send_client_verify_rsa(SSL *s, EVP_PKEY *pkey, CBB *cert_verify) { CBB cbb_signature; + RSA *rsa; unsigned char data[EVP_MAX_MD_SIZE]; unsigned char *signature = NULL; unsigned int signature_len; @@ -2429,8 +2168,10 @@ ssl3_send_client_verify_rsa(SSL *s, EVP_PKEY *pkey, CBB *cert_verify) goto err; if ((signature = calloc(1, EVP_PKEY_size(pkey))) == NULL) goto err; - if (RSA_sign(NID_md5_sha1, data, data_len, signature, - &signature_len, pkey->pkey.rsa) <= 0 ) { + if ((rsa = EVP_PKEY_get0_RSA(pkey)) == NULL) + goto err; + if (RSA_sign(NID_md5_sha1, data, data_len, signature, &signature_len, + rsa) <= 0 ) { SSLerror(s, ERR_R_RSA_LIB); goto err; } @@ -2452,6 +2193,7 @@ static int ssl3_send_client_verify_ec(SSL *s, EVP_PKEY *pkey, CBB *cert_verify) { CBB cbb_signature; + EC_KEY *eckey; unsigned char data[EVP_MAX_MD_SIZE]; unsigned char *signature = NULL; unsigned int signature_len; @@ -2461,8 +2203,10 @@ ssl3_send_client_verify_ec(SSL *s, EVP_PKEY *pkey, CBB *cert_verify) goto err; if ((signature = calloc(1, EVP_PKEY_size(pkey))) == NULL) goto err; - if (!ECDSA_sign(pkey->save_type, &data[MD5_DIGEST_LENGTH], - SHA_DIGEST_LENGTH, signature, &signature_len, pkey->pkey.ec)) { + if ((eckey = EVP_PKEY_get0_EC_KEY(pkey)) == NULL) + goto err; + if (!ECDSA_sign(0, &data[MD5_DIGEST_LENGTH], SHA_DIGEST_LENGTH, + signature, &signature_len, eckey)) { SSLerror(s, ERR_R_ECDSA_LIB); goto err; } @@ -2485,7 +2229,7 @@ static int ssl3_send_client_verify_gost(SSL *s, EVP_PKEY *pkey, CBB *cert_verify) { CBB cbb_signature; - EVP_MD_CTX mctx; + EVP_MD_CTX *mctx; EVP_PKEY_CTX *pctx; const EVP_MD *md; const unsigned char *hdata; @@ -2495,7 +2239,8 @@ ssl3_send_client_verify_gost(SSL *s, EVP_PKEY *pkey, CBB *cert_verify) int nid; int ret = 0; - EVP_MD_CTX_init(&mctx); + if ((mctx = EVP_MD_CTX_new()) == NULL) + goto err; if (!tls1_transcript_data(s, &hdata, &hdata_len)) { SSLerror(s, ERR_R_INTERNAL_ERROR); @@ -2506,7 +2251,7 @@ ssl3_send_client_verify_gost(SSL *s, EVP_PKEY *pkey, CBB *cert_verify) SSLerror(s, ERR_R_EVP_LIB); goto err; } - if (!EVP_DigestSignInit(&mctx, &pctx, md, NULL, pkey)) { + if (!EVP_DigestSignInit(mctx, &pctx, md, NULL, pkey)) { SSLerror(s, ERR_R_EVP_LIB); goto err; } @@ -2515,11 +2260,11 @@ ssl3_send_client_verify_gost(SSL *s, EVP_PKEY *pkey, CBB *cert_verify) SSLerror(s, ERR_R_EVP_LIB); goto err; } - if (!EVP_DigestSignUpdate(&mctx, hdata, hdata_len)) { + if (!EVP_DigestSignUpdate(mctx, hdata, hdata_len)) { SSLerror(s, ERR_R_EVP_LIB); goto err; } - if (!EVP_DigestSignFinal(&mctx, NULL, &signature_len) || + if (!EVP_DigestSignFinal(mctx, NULL, &signature_len) || signature_len == 0) { SSLerror(s, ERR_R_EVP_LIB); goto err; @@ -2528,7 +2273,7 @@ ssl3_send_client_verify_gost(SSL *s, EVP_PKEY *pkey, CBB *cert_verify) SSLerror(s, ERR_R_MALLOC_FAILURE); goto err; } - if (!EVP_DigestSignFinal(&mctx, signature, &signature_len)) { + if (!EVP_DigestSignFinal(mctx, signature, &signature_len)) { SSLerror(s, ERR_R_EVP_LIB); goto err; } @@ -2542,7 +2287,7 @@ ssl3_send_client_verify_gost(SSL *s, EVP_PKEY *pkey, CBB *cert_verify) ret = 1; err: - EVP_MD_CTX_cleanup(&mctx); + EVP_MD_CTX_free(mctx); free(signature); return ret; } @@ -2557,7 +2302,7 @@ ssl3_send_client_verify(SSL *s) memset(&cbb, 0, sizeof(cbb)); - if (S3I(s)->hs.state == SSL3_ST_CW_CERT_VRFY_A) { + if (s->s3->hs.state == SSL3_ST_CW_CERT_VRFY_A) { if (!ssl3_handshake_msg_start(s, &cbb, &cert_verify, SSL3_MT_CERTIFICATE_VERIFY)) goto err; @@ -2567,7 +2312,7 @@ ssl3_send_client_verify(SSL *s) SSLerror(s, SSL_R_SIGNATURE_ALGORITHMS_ERROR); goto err; } - S3I(s)->hs.our_sigalg = sigalg; + s->s3->hs.our_sigalg = sigalg; /* * For TLS v1.2 send signature algorithm and signature using @@ -2577,15 +2322,15 @@ ssl3_send_client_verify(SSL *s) if (!ssl3_send_client_verify_sigalgs(s, pkey, sigalg, &cert_verify)) goto err; - } else if (pkey->type == EVP_PKEY_RSA) { + } else if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) { if (!ssl3_send_client_verify_rsa(s, pkey, &cert_verify)) goto err; - } else if (pkey->type == EVP_PKEY_EC) { + } else if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) { if (!ssl3_send_client_verify_ec(s, pkey, &cert_verify)) goto err; #ifndef OPENSSL_NO_GOST - } else if (pkey->type == NID_id_GostR3410_94 || - pkey->type == NID_id_GostR3410_2001) { + } else if (EVP_PKEY_id(pkey) == NID_id_GostR3410_94 || + EVP_PKEY_id(pkey) == NID_id_GostR3410_2001) { if (!ssl3_send_client_verify_gost(s, pkey, &cert_verify)) goto err; #endif @@ -2599,7 +2344,7 @@ ssl3_send_client_verify(SSL *s) if (!ssl3_handshake_msg_finish(s, &cbb)) goto err; - S3I(s)->hs.state = SSL3_ST_CW_CERT_VRFY_B; + s->s3->hs.state = SSL3_ST_CW_CERT_VRFY_B; } return (ssl3_handshake_write(s)); @@ -2620,16 +2365,16 @@ ssl3_send_client_certificate(SSL *s) memset(&cbb, 0, sizeof(cbb)); - if (S3I(s)->hs.state == SSL3_ST_CW_CERT_A) { + if (s->s3->hs.state == SSL3_ST_CW_CERT_A) { if (s->cert->key->x509 == NULL || s->cert->key->privatekey == NULL) - S3I(s)->hs.state = SSL3_ST_CW_CERT_B; + s->s3->hs.state = SSL3_ST_CW_CERT_B; else - S3I(s)->hs.state = SSL3_ST_CW_CERT_C; + s->s3->hs.state = SSL3_ST_CW_CERT_C; } /* We need to get a client cert */ - if (S3I(s)->hs.state == SSL3_ST_CW_CERT_B) { + if (s->s3->hs.state == SSL3_ST_CW_CERT_B) { /* * If we get an error, we need to * ssl->internal->rwstate = SSL_X509_LOOKUP; return(-1); @@ -2642,7 +2387,7 @@ ssl3_send_client_certificate(SSL *s) } s->internal->rwstate = SSL_NOTHING; if ((i == 1) && (pkey != NULL) && (x509 != NULL)) { - S3I(s)->hs.state = SSL3_ST_CW_CERT_B; + s->s3->hs.state = SSL3_ST_CW_CERT_B; if (!SSL_use_certificate(s, x509) || !SSL_use_PrivateKey(s, pkey)) i = 0; @@ -2654,27 +2399,27 @@ ssl3_send_client_certificate(SSL *s) X509_free(x509); EVP_PKEY_free(pkey); if (i == 0) { - S3I(s)->hs.tls12.cert_request = 2; + s->s3->hs.tls12.cert_request = 2; /* There is no client certificate to verify. */ tls1_transcript_free(s); } /* Ok, we have a cert */ - S3I(s)->hs.state = SSL3_ST_CW_CERT_C; + s->s3->hs.state = SSL3_ST_CW_CERT_C; } - if (S3I(s)->hs.state == SSL3_ST_CW_CERT_C) { + if (s->s3->hs.state == SSL3_ST_CW_CERT_C) { if (!ssl3_handshake_msg_start(s, &cbb, &client_cert, SSL3_MT_CERTIFICATE)) goto err; if (!ssl3_output_cert_chain(s, &client_cert, - (S3I(s)->hs.tls12.cert_request == 2) ? NULL : s->cert->key)) + (s->s3->hs.tls12.cert_request == 2) ? NULL : s->cert->key)) goto err; if (!ssl3_handshake_msg_finish(s, &cbb)) goto err; - S3I(s)->hs.state = SSL3_ST_CW_CERT_D; + s->s3->hs.state = SSL3_ST_CW_CERT_D; } /* SSL3_ST_CW_CERT_D */ @@ -2691,42 +2436,31 @@ ssl3_send_client_certificate(SSL *s) int ssl3_check_cert_and_algorithm(SSL *s) { - int i, idx; - long alg_k, alg_a; - EVP_PKEY *pkey = NULL; - SESS_CERT *sc; - DH *dh; + long alg_k, alg_a; + int nid = NID_undef; + int i; - alg_k = S3I(s)->hs.cipher->algorithm_mkey; - alg_a = S3I(s)->hs.cipher->algorithm_auth; + alg_k = s->s3->hs.cipher->algorithm_mkey; + alg_a = s->s3->hs.cipher->algorithm_auth; /* We don't have a certificate. */ if (alg_a & SSL_aNULL) return (1); - sc = SSI(s)->sess_cert; - if (sc == NULL) { - SSLerror(s, ERR_R_INTERNAL_ERROR); - goto err; - } - dh = SSI(s)->sess_cert->peer_dh_tmp; + if (s->s3->hs.key_share != NULL) + nid = tls_key_share_nid(s->s3->hs.key_share); /* This is the passed certificate. */ - idx = sc->peer_cert_type; - if (idx == SSL_PKEY_ECC) { - if (ssl_check_srvr_ecc_cert_and_alg( - sc->peer_pkeys[idx].x509, s) == 0) { - /* check failed */ + if (s->session->peer_cert_type == SSL_PKEY_ECC) { + if (!ssl_check_srvr_ecc_cert_and_alg(s, s->session->peer_cert)) { SSLerror(s, SSL_R_BAD_ECC_CERT); goto fatal_err; - } else { - return (1); } + return (1); } - pkey = X509_get_pubkey(sc->peer_pkeys[idx].x509); - i = X509_certificate_type(sc->peer_pkeys[idx].x509, pkey); - EVP_PKEY_free(pkey); + + i = X509_certificate_type(s->session->peer_cert, NULL); /* Check that we have a certificate if we require one. */ if ((alg_a & SSL_aRSA) && !has_bits(i, EVP_PK_RSA|EVP_PKT_SIGN)) { @@ -2738,15 +2472,16 @@ ssl3_check_cert_and_algorithm(SSL *s) goto fatal_err; } if ((alg_k & SSL_kDHE) && - !(has_bits(i, EVP_PK_DH|EVP_PKT_EXCH) || (dh != NULL))) { + !(has_bits(i, EVP_PK_DH|EVP_PKT_EXCH) || (nid == NID_dhKeyAgreement))) { SSLerror(s, SSL_R_MISSING_DH_KEY); goto fatal_err; } return (1); + fatal_err: ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); - err: + return (0); } @@ -2759,22 +2494,20 @@ ssl3_check_cert_and_algorithm(SSL *s) int ssl3_check_finished(SSL *s) { - int ok; - long n; + int ret; /* If we have no ticket it cannot be a resumed session. */ if (!s->session->tlsext_tick) return (1); /* this function is called when we really expect a Certificate * message, so permit appropriate message length */ - n = ssl3_get_message(s, SSL3_ST_CR_CERT_A, - SSL3_ST_CR_CERT_B, -1, s->internal->max_cert_list, &ok); - if (!ok) - return ((int)n); + if ((ret = ssl3_get_message(s, SSL3_ST_CR_CERT_A, + SSL3_ST_CR_CERT_B, -1, s->internal->max_cert_list)) <= 0) + return ret; - S3I(s)->hs.tls12.reuse_message = 1; - if ((S3I(s)->hs.tls12.message_type == SSL3_MT_FINISHED) || - (S3I(s)->hs.tls12.message_type == SSL3_MT_NEWSESSION_TICKET)) + s->s3->hs.tls12.reuse_message = 1; + if ((s->s3->hs.tls12.message_type == SSL3_MT_FINISHED) || + (s->s3->hs.tls12.message_type == SSL3_MT_NEWSESSION_TICKET)) return (2); return (1); diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index 9ea7cd4..d4c9fbb 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_err.c,v 1.39 2021/09/10 09:25:29 tb Exp $ */ +/* $OpenBSD: ssl_err.c,v 1.40 2022/02/05 14:54:10 jsing Exp $ */ /* ==================================================================== * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved. * @@ -666,5 +666,5 @@ void SSL_error_internal(const SSL *s, int r, char *f, int l) { ERR_PUT_error(ERR_LIB_SSL, - (SSL_state_func_code(S3I(s)->hs.state)), r, f, l); + (SSL_state_func_code(s->s3->hs.state)), r, f, l); } diff --git a/ssl/ssl_kex.c b/ssl/ssl_kex.c index 9f05fd6..cab2f1c 100644 --- a/ssl/ssl_kex.c +++ b/ssl/ssl_kex.c @@ -1,6 +1,6 @@ -/* $OpenBSD: ssl_kex.c,v 1.2 2020/04/18 14:07:56 jsing Exp $ */ +/* $OpenBSD: ssl_kex.c,v 1.10 2022/01/14 09:11:22 tb Exp $ */ /* - * Copyright (c) 2020 Joel Sing + * Copyright (c) 2020, 2021 Joel Sing * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -17,6 +17,8 @@ #include +#include +#include #include #include #include @@ -24,6 +26,245 @@ #include "bytestring.h" +#define DHE_MINIMUM_BITS 1024 + +int +ssl_kex_generate_dhe(DH *dh, DH *dh_params) +{ + BIGNUM *p = NULL, *g = NULL; + int ret = 0; + + if ((p = BN_dup(DH_get0_p(dh_params))) == NULL) + goto err; + if ((g = BN_dup(DH_get0_g(dh_params))) == NULL) + goto err; + + if (!DH_set0_pqg(dh, p, NULL, g)) + goto err; + p = NULL; + g = NULL; + + if (!DH_generate_key(dh)) + goto err; + + ret = 1; + + err: + BN_free(p); + BN_free(g); + + return ret; +} + +int +ssl_kex_generate_dhe_params_auto(DH *dh, size_t key_bits) +{ + BIGNUM *p = NULL, *g = NULL; + int ret = 0; + + if (key_bits >= 8192) + p = get_rfc3526_prime_8192(NULL); + else if (key_bits >= 4096) + p = get_rfc3526_prime_4096(NULL); + else if (key_bits >= 3072) + p = get_rfc3526_prime_3072(NULL); + else if (key_bits >= 2048) + p = get_rfc3526_prime_2048(NULL); + else if (key_bits >= 1536) + p = get_rfc3526_prime_1536(NULL); + else + p = get_rfc2409_prime_1024(NULL); + + if (p == NULL) + goto err; + + if ((g = BN_new()) == NULL) + goto err; + if (!BN_set_word(g, 2)) + goto err; + + if (!DH_set0_pqg(dh, p, NULL, g)) + goto err; + p = NULL; + g = NULL; + + if (!DH_generate_key(dh)) + goto err; + + ret = 1; + + err: + BN_free(p); + BN_free(g); + + return ret; +} + +int +ssl_kex_params_dhe(DH *dh, CBB *cbb) +{ + int dh_p_len, dh_g_len; + CBB dh_p, dh_g; + uint8_t *data; + + if ((dh_p_len = BN_num_bytes(DH_get0_p(dh))) <= 0) + return 0; + if ((dh_g_len = BN_num_bytes(DH_get0_g(dh))) <= 0) + return 0; + + if (!CBB_add_u16_length_prefixed(cbb, &dh_p)) + return 0; + if (!CBB_add_space(&dh_p, &data, dh_p_len)) + return 0; + if (BN_bn2bin(DH_get0_p(dh), data) != dh_p_len) + return 0; + + if (!CBB_add_u16_length_prefixed(cbb, &dh_g)) + return 0; + if (!CBB_add_space(&dh_g, &data, dh_g_len)) + return 0; + if (BN_bn2bin(DH_get0_g(dh), data) != dh_g_len) + return 0; + + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +int +ssl_kex_public_dhe(DH *dh, CBB *cbb) +{ + uint8_t *data; + int dh_y_len; + CBB dh_y; + + if ((dh_y_len = BN_num_bytes(DH_get0_pub_key(dh))) <= 0) + return 0; + + if (!CBB_add_u16_length_prefixed(cbb, &dh_y)) + return 0; + if (!CBB_add_space(&dh_y, &data, dh_y_len)) + return 0; + if (BN_bn2bin(DH_get0_pub_key(dh), data) != dh_y_len) + return 0; + + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +int +ssl_kex_peer_params_dhe(DH *dh, CBS *cbs, int *decode_error, + int *invalid_params) +{ + BIGNUM *p = NULL, *g = NULL; + CBS dh_p, dh_g; + int ret = 0; + + *decode_error = 0; + *invalid_params = 0; + + if (!CBS_get_u16_length_prefixed(cbs, &dh_p)) { + *decode_error = 1; + goto err; + } + if (!CBS_get_u16_length_prefixed(cbs, &dh_g)) { + *decode_error = 1; + goto err; + } + + if ((p = BN_bin2bn(CBS_data(&dh_p), CBS_len(&dh_p), NULL)) == NULL) + goto err; + if ((g = BN_bin2bn(CBS_data(&dh_g), CBS_len(&dh_g), NULL)) == NULL) + goto err; + + if (!DH_set0_pqg(dh, p, NULL, g)) + goto err; + p = NULL; + g = NULL; + + /* XXX - consider calling DH_check(). */ + + if (DH_bits(dh) < DHE_MINIMUM_BITS) + *invalid_params = 1; + + ret = 1; + + err: + BN_free(p); + BN_free(g); + + return ret; +} + +int +ssl_kex_peer_public_dhe(DH *dh, CBS *cbs, int *decode_error, + int *invalid_key) +{ + BIGNUM *pub_key = NULL; + int check_flags; + CBS dh_y; + int ret = 0; + + *decode_error = 0; + *invalid_key = 0; + + if (!CBS_get_u16_length_prefixed(cbs, &dh_y)) { + *decode_error = 1; + goto err; + } + + if ((pub_key = BN_bin2bn(CBS_data(&dh_y), CBS_len(&dh_y), + NULL)) == NULL) + goto err; + + if (!DH_set0_key(dh, pub_key, NULL)) + goto err; + pub_key = NULL; + + if (!DH_check_pub_key(dh, DH_get0_pub_key(dh), &check_flags)) + goto err; + if (check_flags != 0) + *invalid_key = 1; + + ret = 1; + + err: + BN_free(pub_key); + + return ret; +} + +int +ssl_kex_derive_dhe(DH *dh, DH *dh_peer, + uint8_t **shared_key, size_t *shared_key_len) +{ + uint8_t *key = NULL; + int key_len = 0; + int ret = 0; + + if ((key_len = DH_size(dh)) <= 0) + goto err; + if ((key = calloc(1, key_len)) == NULL) + goto err; + + if ((key_len = DH_compute_key(key, DH_get0_pub_key(dh_peer), dh)) <= 0) + goto err; + + *shared_key = key; + *shared_key_len = key_len; + key = NULL; + + ret = 1; + + err: + freezero(key, key_len); + + return ret; +} + int ssl_kex_dummy_ecdhe_x25519(EVP_PKEY *pkey) { @@ -149,8 +390,8 @@ ssl_kex_derive_ecdhe_ecp(EC_KEY *ecdh, EC_KEY *ecdh_peer, uint8_t **shared_key, size_t *shared_key_len) { const EC_POINT *point; - uint8_t *sk = NULL; - int sk_len = 0; + uint8_t *key = NULL; + int key_len = 0; int ret = 0; if (!EC_GROUP_check(EC_KEY_get0_group(ecdh), NULL)) @@ -161,22 +402,22 @@ ssl_kex_derive_ecdhe_ecp(EC_KEY *ecdh, EC_KEY *ecdh_peer, if ((point = EC_KEY_get0_public_key(ecdh_peer)) == NULL) goto err; - if ((sk_len = ECDH_size(ecdh)) <= 0) + if ((key_len = ECDH_size(ecdh)) <= 0) goto err; - if ((sk = calloc(1, sk_len)) == NULL) + if ((key = calloc(1, key_len)) == NULL) goto err; - if (ECDH_compute_key(sk, sk_len, point, ecdh, NULL) <= 0) + if (ECDH_compute_key(key, key_len, point, ecdh, NULL) <= 0) goto err; - *shared_key = sk; - *shared_key_len = sk_len; - sk = NULL; + *shared_key = key; + *shared_key_len = key_len; + key = NULL; ret = 1; err: - freezero(sk, sk_len); + freezero(key, key_len); return ret; } diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 0f86238..6adc28a 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_lib.c,v 1.268 2021/09/10 08:59:56 tb Exp $ */ +/* $OpenBSD: ssl_lib.c,v 1.290 2022/03/18 18:01:17 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -144,9 +144,9 @@ #include #include +#include #include -#include #include #include #include @@ -264,6 +264,7 @@ SSL_new(SSL_CTX *ctx) s->internal->options = ctx->internal->options; s->internal->mode = ctx->internal->mode; s->internal->max_cert_list = ctx->internal->max_cert_list; + s->internal->num_tickets = ctx->internal->num_tickets; if ((s->cert = ssl_cert_dup(ctx->internal->cert)) == NULL) goto err; @@ -595,8 +596,8 @@ SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio) /* If the output buffering BIO is still in place, remove it */ if (s->bbio != NULL) { if (s->wbio == s->bbio) { - s->wbio = s->wbio->next_bio; - s->bbio->next_bio = NULL; + s->wbio = BIO_next(s->wbio); + BIO_set_next(s->bbio, NULL); } } @@ -731,10 +732,10 @@ SSL_get_finished(const SSL *s, void *buf, size_t count) { size_t ret; - ret = S3I(s)->hs.finished_len; + ret = s->s3->hs.finished_len; if (count > ret) count = ret; - memcpy(buf, S3I(s)->hs.finished, count); + memcpy(buf, s->s3->hs.finished, count); return (ret); } @@ -744,10 +745,10 @@ SSL_get_peer_finished(const SSL *s, void *buf, size_t count) { size_t ret; - ret = S3I(s)->hs.peer_finished_len; + ret = s->s3->hs.peer_finished_len; if (count > ret) count = ret; - memcpy(buf, S3I(s)->hs.peer_finished, count); + memcpy(buf, s->s3->hs.peer_finished, count); return (ret); } @@ -770,6 +771,46 @@ int return (s->internal->verify_callback); } +void +SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb) +{ + ctx->internal->keylog_callback = cb; +} + +SSL_CTX_keylog_cb_func +SSL_CTX_get_keylog_callback(const SSL_CTX *ctx) +{ + return (ctx->internal->keylog_callback); +} + +int +SSL_set_num_tickets(SSL *s, size_t num_tickets) +{ + s->internal->num_tickets = num_tickets; + + return 1; +} + +size_t +SSL_get_num_tickets(const SSL *s) +{ + return s->internal->num_tickets; +} + +int +SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets) +{ + ctx->internal->num_tickets = num_tickets; + + return 1; +} + +size_t +SSL_CTX_get_num_tickets(const SSL_CTX *ctx) +{ + return ctx->internal->num_tickets; +} + int SSL_CTX_get_verify_mode(const SSL_CTX *ctx) { @@ -824,38 +865,36 @@ SSL_pending(const SSL *s) X509 * SSL_get_peer_certificate(const SSL *s) { - X509 *r; + X509 *cert; - if ((s == NULL) || (s->session == NULL)) - r = NULL; - else - r = s->session->peer; + if (s == NULL || s->session == NULL) + return NULL; - if (r == NULL) - return (r); + if ((cert = s->session->peer_cert) == NULL) + return NULL; - CRYPTO_add(&r->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(cert); - return (r); + return cert; } STACK_OF(X509) * SSL_get_peer_cert_chain(const SSL *s) { - STACK_OF(X509) *r; - - if ((s == NULL) || (s->session == NULL) || - (SSI(s)->sess_cert == NULL)) - r = NULL; - else - r = SSI(s)->sess_cert->cert_chain; + if (s == NULL || s->session == NULL) + return NULL; /* * If we are a client, cert_chain includes the peer's own - * certificate; - * if we are a server, it does not. + * certificate; if we are a server, it does not. */ - return (r); + return s->session->cert_chain; +} + +STACK_OF(X509) * +SSL_get0_verified_chain(const SSL *s) +{ + return s->internal->verified_chain; } /* @@ -865,7 +904,7 @@ SSL_get_peer_cert_chain(const SSL *s) int SSL_copy_session_id(SSL *t, const SSL *f) { - CERT *tmp; + SSL_CERT *tmp; /* Do we need to do SSL locking? */ if (!SSL_set_session(t, SSL_get_session(f))) @@ -983,6 +1022,11 @@ SSL_get_default_timeout(const SSL *s) int SSL_read(SSL *s, void *buf, int num) { + if (num < 0) { + SSLerror(s, SSL_R_BAD_LENGTH); + return -1; + } + if (s->internal->handshake_func == NULL) { SSLerror(s, SSL_R_UNINITIALIZED); return (-1); @@ -995,9 +1039,33 @@ SSL_read(SSL *s, void *buf, int num) return ssl3_read(s, buf, num); } +int +SSL_read_ex(SSL *s, void *buf, size_t num, size_t *bytes_read) +{ + int ret; + + /* We simply don't bother supporting enormous reads */ + if (num > INT_MAX) { + SSLerror(s, SSL_R_BAD_LENGTH); + return 0; + } + + ret = SSL_read(s, buf, (int)num); + if (ret < 0) + ret = 0; + *bytes_read = ret; + + return ret > 0; +} + int SSL_peek(SSL *s, void *buf, int num) { + if (num < 0) { + SSLerror(s, SSL_R_BAD_LENGTH); + return -1; + } + if (s->internal->handshake_func == NULL) { SSLerror(s, SSL_R_UNINITIALIZED); return (-1); @@ -1009,9 +1077,33 @@ SSL_peek(SSL *s, void *buf, int num) return ssl3_peek(s, buf, num); } +int +SSL_peek_ex(SSL *s, void *buf, size_t num, size_t *bytes_peeked) +{ + int ret; + + /* We simply don't bother supporting enormous peeks */ + if (num > INT_MAX) { + SSLerror(s, SSL_R_BAD_LENGTH); + return 0; + } + + ret = SSL_peek(s, buf, (int)num); + if (ret < 0) + ret = 0; + *bytes_peeked = ret; + + return ret > 0; +} + int SSL_write(SSL *s, const void *buf, int num) { + if (num < 0) { + SSLerror(s, SSL_R_BAD_LENGTH); + return -1; + } + if (s->internal->handshake_func == NULL) { SSLerror(s, SSL_R_UNINITIALIZED); return (-1); @@ -1025,6 +1117,31 @@ SSL_write(SSL *s, const void *buf, int num) return ssl3_write(s, buf, num); } +int +SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *bytes_written) +{ + int ret; + + /* We simply don't bother supporting enormous writes */ + if (num > INT_MAX) { + SSLerror(s, SSL_R_BAD_LENGTH); + return 0; + } + + if (num == 0) { + /* This API is special */ + bytes_written = 0; + return 1; + } + + ret = SSL_write(s, buf, (int)num); + if (ret < 0) + ret = 0; + *bytes_written = ret; + + return ret > 0; +} + uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx) { @@ -1166,7 +1283,7 @@ SSL_ctrl(SSL *s, int cmd, long larg, void *parg) return (0); #endif if (SSL_is_dtls(s)) { - D1I(s)->mtu = larg; + s->d1->mtu = larg; return (larg); } return (0); @@ -1177,7 +1294,7 @@ SSL_ctrl(SSL *s, int cmd, long larg, void *parg) return (1); case SSL_CTRL_GET_RI_SUPPORT: if (s->s3) - return (S3I(s)->send_connection_binding); + return (s->s3->send_connection_binding); else return (0); default: if (SSL_is_dtls(s)) @@ -1720,8 +1837,8 @@ void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, unsigned int *len) { - *data = ssl->s3->internal->alpn_selected; - *len = ssl->s3->internal->alpn_selected_len; + *data = ssl->s3->alpn_selected; + *len = ssl->s3->alpn_selected_len; } void @@ -2061,22 +2178,11 @@ SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth) X509_VERIFY_PARAM_set_depth(ctx->param, depth); } -static int -ssl_cert_can_sign(X509 *x) -{ - /* This call populates extension flags (ex_flags). */ - X509_check_purpose(x, -1, 0); - - /* Key usage, if present, must allow signing. */ - return ((x->ex_flags & EXFLAG_KUSAGE) == 0 || - (x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE)); -} - void -ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) +ssl_set_cert_masks(SSL_CERT *c, const SSL_CIPHER *cipher) { unsigned long mask_a, mask_k; - CERT_PKEY *cpk; + SSL_CERT_PKEY *cpk; if (c == NULL) return; @@ -2084,12 +2190,14 @@ ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) mask_a = SSL_aNULL | SSL_aTLS1_3; mask_k = SSL_kECDHE | SSL_kTLS1_3; - if (c->dh_tmp != NULL || c->dh_tmp_cb != NULL || c->dh_tmp_auto != 0) + if (c->dhe_params != NULL || c->dhe_params_cb != NULL || + c->dhe_params_auto != 0) mask_k |= SSL_kDHE; cpk = &(c->pkeys[SSL_PKEY_ECC]); if (cpk->x509 != NULL && cpk->privatekey != NULL) { - if (ssl_cert_can_sign(cpk->x509)) + /* Key usage, if present, must allow signing. */ + if (X509_get_key_usage(cpk->x509) & X509v3_KU_DIGITAL_SIGNATURE) mask_a |= SSL_aECDSA; } @@ -2116,29 +2224,25 @@ ssl_using_ecc_cipher(SSL *s) { unsigned long alg_a, alg_k; - alg_a = S3I(s)->hs.cipher->algorithm_auth; - alg_k = S3I(s)->hs.cipher->algorithm_mkey; + alg_a = s->s3->hs.cipher->algorithm_auth; + alg_k = s->s3->hs.cipher->algorithm_mkey; - return SSI(s)->tlsext_ecpointformatlist != NULL && - SSI(s)->tlsext_ecpointformatlist_length > 0 && + return s->session->tlsext_ecpointformatlist != NULL && + s->session->tlsext_ecpointformatlist_length > 0 && ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA)); } int -ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s) +ssl_check_srvr_ecc_cert_and_alg(SSL *s, X509 *x) { - const SSL_CIPHER *cs = S3I(s)->hs.cipher; - unsigned long alg_a; + const SSL_CIPHER *cs = s->s3->hs.cipher; + unsigned long alg_a; alg_a = cs->algorithm_auth; if (alg_a & SSL_aECDSA) { - /* This call populates extension flags (ex_flags). */ - X509_check_purpose(x, -1, 0); - /* Key usage, if present, must allow signing. */ - if ((x->ex_flags & EXFLAG_KUSAGE) && - ((x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE) == 0)) { + if (!(X509_get_key_usage(x) & X509v3_KU_DIGITAL_SIGNATURE)) { SSLerror(s, SSL_R_ECC_CERT_NOT_FOR_SIGNING); return (0); } @@ -2147,17 +2251,17 @@ ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s) return (1); } -CERT_PKEY * +SSL_CERT_PKEY * ssl_get_server_send_pkey(const SSL *s) { - unsigned long alg_a; - CERT *c; - int i; + unsigned long alg_a; + SSL_CERT *c; + int i; c = s->cert; - ssl_set_cert_masks(c, S3I(s)->hs.cipher); + ssl_set_cert_masks(c, s->s3->hs.cipher); - alg_a = S3I(s)->hs.cipher->algorithm_auth; + alg_a = s->s3->hs.cipher->algorithm_auth; if (alg_a & SSL_aECDSA) { i = SSL_PKEY_ECC; @@ -2179,9 +2283,9 @@ ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *cipher, const EVP_MD **pmd, { const struct ssl_sigalg *sigalg = NULL; EVP_PKEY *pkey = NULL; - unsigned long alg_a; - CERT *c; - int idx = -1; + unsigned long alg_a; + SSL_CERT *c; + int idx = -1; alg_a = cipher->algorithm_auth; c = s->cert; @@ -2207,52 +2311,29 @@ ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *cipher, const EVP_MD **pmd, return (pkey); } -DH * -ssl_get_auto_dh(SSL *s) +size_t +ssl_dhe_params_auto_key_bits(SSL *s) { - CERT_PKEY *cpk; - int keylen; - DH *dhp; + SSL_CERT_PKEY *cpk; + int key_bits; - if (s->cert->dh_tmp_auto == 2) { - keylen = 1024; - } else if (S3I(s)->hs.cipher->algorithm_auth & SSL_aNULL) { - keylen = 1024; - if (S3I(s)->hs.cipher->strength_bits == 256) - keylen = 3072; + if (s->cert->dhe_params_auto == 2) { + key_bits = 1024; + } else if (s->s3->hs.cipher->algorithm_auth & SSL_aNULL) { + key_bits = 1024; + if (s->s3->hs.cipher->strength_bits == 256) + key_bits = 3072; } else { if ((cpk = ssl_get_server_send_pkey(s)) == NULL) - return (NULL); - if (cpk->privatekey == NULL || cpk->privatekey->pkey.dh == NULL) - return (NULL); - keylen = EVP_PKEY_bits(cpk->privatekey); + return 0; + if (cpk->privatekey == NULL || + EVP_PKEY_get0_RSA(cpk->privatekey) == NULL) + return 0; + if ((key_bits = EVP_PKEY_bits(cpk->privatekey)) <= 0) + return 0; } - if ((dhp = DH_new()) == NULL) - return (NULL); - - dhp->g = BN_new(); - if (dhp->g != NULL) - BN_set_word(dhp->g, 2); - - if (keylen >= 8192) - dhp->p = get_rfc3526_prime_8192(NULL); - else if (keylen >= 4096) - dhp->p = get_rfc3526_prime_4096(NULL); - else if (keylen >= 3072) - dhp->p = get_rfc3526_prime_3072(NULL); - else if (keylen >= 2048) - dhp->p = get_rfc3526_prime_2048(NULL); - else if (keylen >= 1536) - dhp->p = get_rfc3526_prime_1536(NULL); - else - dhp->p = get_rfc2409_prime_1024(NULL); - - if (dhp->p == NULL || dhp->g == NULL) { - DH_free(dhp); - return (NULL); - } - return (dhp); + return key_bits; } static int @@ -2271,7 +2352,7 @@ ssl_should_update_external_cache(SSL *s, int mode) return 1; /* If it's TLS 1.3, do it to match OpenSSL */ - if (S3I(s)->hs.negotiated_tls_version >= TLS1_3_VERSION) + if (s->s3->hs.negotiated_tls_version >= TLS1_3_VERSION) return 1; return 0; @@ -2296,7 +2377,7 @@ ssl_should_update_internal_cache(SSL *s, int mode) return 0; /* If we are lesser than TLS 1.3, Cache it. */ - if (S3I(s)->hs.negotiated_tls_version < TLS1_3_VERSION) + if (s->s3->hs.negotiated_tls_version < TLS1_3_VERSION) return 1; /* Below this we consider TLS 1.3 or later */ @@ -2406,15 +2487,17 @@ SSL_set_ssl_method(SSL *s, const SSL_METHOD *method) int SSL_get_error(const SSL *s, int i) { - int reason; - unsigned long l; - BIO *bio; + unsigned long l; + int reason; + BIO *bio; if (i > 0) return (SSL_ERROR_NONE); - /* Make things return SSL_ERROR_SYSCALL when doing SSL_do_handshake - * etc, where we do encode the error */ + /* + * Make things return SSL_ERROR_SYSCALL when doing SSL_do_handshake + * etc, where we do encode the error. + */ if ((l = ERR_peek_error()) != 0) { if (ERR_GET_LIB(l) == ERR_LIB_SYS) return (SSL_ERROR_SYSCALL); @@ -2422,7 +2505,7 @@ SSL_get_error(const SSL *s, int i) return (SSL_ERROR_SSL); } - if ((i < 0) && SSL_want_read(s)) { + if (SSL_want_read(s)) { bio = SSL_get_rbio(s); if (BIO_should_read(bio)) { return (SSL_ERROR_WANT_READ); @@ -2449,7 +2532,7 @@ SSL_get_error(const SSL *s, int i) } } - if ((i < 0) && SSL_want_write(s)) { + if (SSL_want_write(s)) { bio = SSL_get_wbio(s); if (BIO_should_write(bio)) { return (SSL_ERROR_WANT_WRITE); @@ -2469,23 +2552,20 @@ SSL_get_error(const SSL *s, int i) return (SSL_ERROR_SYSCALL); } } - if ((i < 0) && SSL_want_x509_lookup(s)) { - return (SSL_ERROR_WANT_X509_LOOKUP); - } - if (i == 0) { - if ((s->internal->shutdown & SSL_RECEIVED_SHUTDOWN) && - (S3I(s)->warn_alert == SSL_AD_CLOSE_NOTIFY)) - return (SSL_ERROR_ZERO_RETURN); - } + if (SSL_want_x509_lookup(s)) + return (SSL_ERROR_WANT_X509_LOOKUP); + + if ((s->internal->shutdown & SSL_RECEIVED_SHUTDOWN) && + (s->s3->warn_alert == SSL_AD_CLOSE_NOTIFY)) + return (SSL_ERROR_ZERO_RETURN); + return (SSL_ERROR_SYSCALL); } int SSL_do_handshake(SSL *s) { - int ret = 1; - if (s->internal->handshake_func == NULL) { SSLerror(s, SSL_R_CONNECTION_TYPE_NOT_SET); return (-1); @@ -2493,10 +2573,10 @@ SSL_do_handshake(SSL *s) s->method->ssl_renegotiate_check(s); - if (SSL_in_init(s) || SSL_in_before(s)) { - ret = s->internal->handshake_func(s); - } - return (ret); + if (!SSL_in_init(s) && !SSL_in_before(s)) + return 1; + + return s->internal->handshake_func(s); } /* @@ -2508,7 +2588,7 @@ SSL_set_accept_state(SSL *s) { s->server = 1; s->internal->shutdown = 0; - S3I(s)->hs.state = SSL_ST_ACCEPT|SSL_ST_BEFORE; + s->s3->hs.state = SSL_ST_ACCEPT|SSL_ST_BEFORE; s->internal->handshake_func = s->method->ssl_accept; ssl_clear_cipher_state(s); } @@ -2518,7 +2598,7 @@ SSL_set_connect_state(SSL *s) { s->server = 0; s->internal->shutdown = 0; - S3I(s)->hs.state = SSL_ST_CONNECT|SSL_ST_BEFORE; + s->s3->hs.state = SSL_ST_CONNECT|SSL_ST_BEFORE; s->internal->handshake_func = s->method->ssl_connect; ssl_clear_cipher_state(s); } @@ -2650,7 +2730,7 @@ SSL_dup(SSL *s) ret->internal->quiet_shutdown = s->internal->quiet_shutdown; ret->internal->shutdown = s->internal->shutdown; /* SSL_dup does not really work at any state, though */ - S3I(ret)->hs.state = S3I(s)->hs.state; + ret->s3->hs.state = s->s3->hs.state; ret->internal->rstate = s->internal->rstate; /* @@ -2696,22 +2776,8 @@ SSL_dup(SSL *s) void ssl_clear_cipher_state(SSL *s) -{ - ssl_clear_cipher_read_state(s); - ssl_clear_cipher_write_state(s); -} - -void -ssl_clear_cipher_read_state(SSL *s) { tls12_record_layer_clear_read_state(s->internal->rl); - tls12_record_layer_read_cipher_hash(s->internal->rl, - &s->enc_read_ctx, &s->read_hash); -} - -void -ssl_clear_cipher_write_state(SSL *s) -{ tls12_record_layer_clear_write_state(s->internal->rl); } @@ -2899,7 +2965,7 @@ SSL_get_SSL_CTX(const SSL *ssl) SSL_CTX * SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx) { - CERT *new_cert; + SSL_CERT *new_cert; if (ctx == NULL) ctx = ssl->initial_ctx; @@ -2951,13 +3017,13 @@ void (*SSL_get_info_callback(const SSL *ssl))(const SSL *ssl, int type, int val) int SSL_state(const SSL *ssl) { - return (S3I(ssl)->hs.state); + return (ssl->s3->hs.state); } void SSL_set_state(SSL *ssl, int state) { - S3I(ssl)->hs.state = state; + ssl->s3->hs.state = state; } void diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 7ff3e07..f0c261b 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_locl.h,v 1.358 2021/08/30 19:25:43 jsing Exp $ */ +/* $OpenBSD: ssl_locl.h,v 1.388 2022/03/17 17:22:16 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -348,12 +348,6 @@ __BEGIN_HIDDEN_DECLS * SSL_aDSS <- DSA_SIGN */ -/* -#define CERT_INVALID 0 -#define CERT_PUBLIC_KEY 1 -#define CERT_PRIVATE_KEY 2 -*/ - /* From ECC-TLS draft, used in encoding the curve type in * ECParameters */ @@ -361,6 +355,39 @@ __BEGIN_HIDDEN_DECLS #define EXPLICIT_CHAR2_CURVE_TYPE 2 #define NAMED_CURVE_TYPE 3 +typedef struct ssl_cert_pkey_st { + X509 *x509; + EVP_PKEY *privatekey; + STACK_OF(X509) *chain; +} SSL_CERT_PKEY; + +typedef struct ssl_cert_st { + /* Current active set */ + /* ALWAYS points to an element of the pkeys array + * Probably it would make more sense to store + * an index, not a pointer. */ + SSL_CERT_PKEY *key; + + SSL_CERT_PKEY pkeys[SSL_PKEY_NUM]; + + /* The following masks are for the key and auth + * algorithms that are supported by the certs below */ + int valid; + unsigned long mask_k; + unsigned long mask_a; + + DH *dhe_params; + DH *(*dhe_params_cb)(SSL *ssl, int is_export, int keysize); + int dhe_params_auto; + + int references; /* >1 only if SSL_copy_session_id is used */ +} SSL_CERT; + +struct ssl_comp_st { + int id; + const char *name; +}; + struct ssl_cipher_st { int valid; const char *name; /* text name */ @@ -407,28 +434,6 @@ struct ssl_method_st { unsigned int enc_flags; /* SSL_ENC_FLAG_* */ }; -typedef struct ssl_session_internal_st { - CRYPTO_EX_DATA ex_data; /* application specific data */ - - /* These are used to make removal of session-ids more - * efficient and to implement a maximum cache size. */ - struct ssl_session_st *prev, *next; - - /* Used to indicate that session resumption is not allowed. - * Applications can also set this bit for a new session via - * not_resumable_session_cb to disable session caching and tickets. */ - int not_resumable; - - /* The cert is the certificate used to establish this connection */ - struct sess_cert_st /* SESS_CERT */ *sess_cert; - - size_t tlsext_ecpointformatlist_length; - uint8_t *tlsext_ecpointformatlist; /* peer's list */ - size_t tlsext_supportedgroups_length; - uint16_t *tlsext_supportedgroups; /* peer's list */ -} SSL_SESSION_INTERNAL; -#define SSI(s) (s->session->internal) - /* Lets make this into an ASN.1 type structure as follows * SSL_SESSION_ID ::= SEQUENCE { * version INTEGER, -- structure version number @@ -470,8 +475,9 @@ struct ssl_session_st { unsigned int sid_ctx_length; unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; - /* This is the cert for the other end. */ - X509 *peer; + /* Peer provided leaf (end-entity) certificate. */ + X509 *peer_cert; + int peer_cert_type; /* when app_verify_callback accepts a session where the peer's certificate * is not ok, we must remember the error for session reuse: */ @@ -491,19 +497,29 @@ struct ssl_session_st { char *tlsext_hostname; /* RFC4507 info */ - unsigned char *tlsext_tick; /* Session ticket */ - size_t tlsext_ticklen; /* Session ticket length */ - long tlsext_tick_lifetime_hint; /* Session lifetime hint in seconds */ + unsigned char *tlsext_tick; /* Session ticket */ + size_t tlsext_ticklen; /* Session ticket length */ + uint32_t tlsext_tick_lifetime_hint; /* Session lifetime hint in seconds */ - struct ssl_session_internal_st *internal; + CRYPTO_EX_DATA ex_data; /* application specific data */ + + /* These are used to make removal of session-ids more + * efficient and to implement a maximum cache size. */ + struct ssl_session_st *prev, *next; + + /* Used to indicate that session resumption is not allowed. + * Applications can also set this bit for a new session via + * not_resumable_session_cb to disable session caching and tickets. */ + int not_resumable; + + STACK_OF(X509) *cert_chain; /* as received from peer */ + + size_t tlsext_ecpointformatlist_length; + uint8_t *tlsext_ecpointformatlist; /* peer's list */ + size_t tlsext_supportedgroups_length; + uint16_t *tlsext_supportedgroups; /* peer's list */ }; -typedef struct cert_pkey_st { - X509 *x509; - EVP_PKEY *privatekey; - STACK_OF(X509) *chain; -} CERT_PKEY; - struct ssl_sigalg; typedef struct ssl_handshake_tls12_st { @@ -533,13 +549,12 @@ typedef struct ssl_handshake_tls13_st { int hrr; /* Certificate selected for use (static pointer). */ - const CERT_PKEY *cpk; + const SSL_CERT_PKEY *cpk; /* Version proposed by peer server. */ uint16_t server_version; uint16_t server_group; - struct tls13_key_share *key_share; struct tls13_secrets *secrets; uint8_t *cookie; @@ -577,6 +592,13 @@ typedef struct ssl_handshake_st { */ uint16_t negotiated_tls_version; + /* + * Legacy version advertised by our peer. For a server this is the + * version specified by the client in the ClientHello message. For a + * client, this is the version provided in the ServerHello message. + */ + uint16_t peer_legacy_version; + /* * Current handshake state - contains one of the SSL3_ST_* values and * is used by the TLSv1.2 state machine, as well as being updated by @@ -598,6 +620,9 @@ typedef struct ssl_handshake_st { uint8_t *sigalgs; size_t sigalgs_len; + /* Key share for ephemeral key exchange. */ + struct tls_key_share *key_share; + /* * Copies of the verify data sent in our finished message and the * verify data received in the finished message sent by our peer. @@ -611,6 +636,14 @@ typedef struct ssl_handshake_st { SSL_HANDSHAKE_TLS13 tls13; } SSL_HANDSHAKE; +typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT; + +/* TLS Session Ticket extension struct. */ +struct tls_session_ticket_ext_st { + unsigned short length; + void *data; +}; + struct tls12_key_block; struct tls12_key_block *tls12_key_block_new(void); @@ -650,8 +683,6 @@ void tls12_record_layer_write_epoch_done(struct tls12_record_layer *rl, void tls12_record_layer_clear_read_state(struct tls12_record_layer *rl); void tls12_record_layer_clear_write_state(struct tls12_record_layer *rl); void tls12_record_layer_reflect_seq_num(struct tls12_record_layer *rl); -void tls12_record_layer_read_cipher_hash(struct tls12_record_layer *rl, - EVP_CIPHER_CTX **cipher, EVP_MD_CTX **hash); int tls12_record_layer_change_read_cipher_state(struct tls12_record_layer *rl, CBS *mac_key, CBS *key, CBS *iv); int tls12_record_layer_change_write_cipher_state(struct tls12_record_layer *rl, @@ -770,7 +801,7 @@ typedef struct ssl_ctx_internal_st { STACK_OF(SSL_CIPHER) *cipher_list_tls13; - struct cert_st /* CERT */ *cert; + SSL_CERT *cert; /* Default values used when no per-SSL value is defined follow */ @@ -830,8 +861,48 @@ typedef struct ssl_ctx_internal_st { uint8_t *tlsext_ecpointformatlist; /* our list */ size_t tlsext_supportedgroups_length; uint16_t *tlsext_supportedgroups; /* our list */ + SSL_CTX_keylog_cb_func keylog_callback; /* Unused. For OpenSSL compatibility. */ + size_t num_tickets; /* Unused, for OpenSSL compatibility */ } SSL_CTX_INTERNAL; +struct ssl_ctx_st { + const SSL_METHOD *method; + + STACK_OF(SSL_CIPHER) *cipher_list; + + struct x509_store_st /* X509_STORE */ *cert_store; + + /* If timeout is not 0, it is the default timeout value set + * when SSL_new() is called. This has been put in to make + * life easier to set things up */ + long session_timeout; + + int references; + + /* Default values to use in SSL structures follow (these are copied by SSL_new) */ + + STACK_OF(X509) *extra_certs; + + int verify_mode; + unsigned int sid_ctx_length; + unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; + + X509_VERIFY_PARAM *param; + + /* + * XXX + * default_passwd_cb used by python and openvpn, need to keep it until we + * add an accessor + */ + /* Default password callback. */ + pem_password_cb *default_passwd_callback; + + /* Default password callback user data. */ + void *default_passwd_callback_userdata; + + struct ssl_ctx_internal_st *internal; +}; + typedef struct ssl_internal_st { struct tls13_ctx *tls13; @@ -971,8 +1042,77 @@ typedef struct ssl_internal_st { int mac_packet; int empty_record_count; + + size_t num_tickets; /* Unused, for OpenSSL compatibility */ + STACK_OF(X509) *verified_chain; } SSL_INTERNAL; +struct ssl_st { + /* protocol version + * (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, DTLS1_VERSION) + */ + int version; + + const SSL_METHOD *method; /* SSLv3 */ + + /* There are 2 BIO's even though they are normally both the + * same. This is so data can be read and written to different + * handlers */ + + BIO *rbio; /* used by SSL_read */ + BIO *wbio; /* used by SSL_write */ + BIO *bbio; /* used during session-id reuse to concatenate + * messages */ + int server; /* are we the server side? - mostly used by SSL_clear*/ + + struct ssl3_state_st *s3; /* SSLv3 variables */ + struct dtls1_state_st *d1; /* DTLSv1 variables */ + + X509_VERIFY_PARAM *param; + + /* crypto */ + STACK_OF(SSL_CIPHER) *cipher_list; + + /* This is used to hold the server certificate used */ + SSL_CERT *cert; + + /* the session_id_context is used to ensure sessions are only reused + * in the appropriate context */ + unsigned int sid_ctx_length; + unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; + + /* This can also be in the session once a session is established */ + SSL_SESSION *session; + + /* Used in SSL2 and SSL3 */ + int verify_mode; /* 0 don't care about verify failure. + * 1 fail if verify fails */ + int error; /* error bytes to be written */ + int error_code; /* actual code */ + + SSL_CTX *ctx; + + long verify_result; + + int references; + + int client_version; /* what was passed, used for + * SSLv3/TLS rollback check */ + + unsigned int max_send_fragment; + + char *tlsext_hostname; + + /* certificate status request info */ + /* Status type or -1 if no status type */ + int tlsext_status_type; + + SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */ +#define session_ctx initial_ctx + + struct ssl_internal_st *internal; +}; + typedef struct ssl3_record_internal_st { int type; /* type of record */ unsigned int length; /* How many bytes available */ @@ -992,7 +1132,12 @@ typedef struct ssl3_buffer_internal_st { int left; /* how many bytes left */ } SSL3_BUFFER_INTERNAL; -typedef struct ssl3_state_internal_st { +typedef struct ssl3_state_st { + long flags; + + unsigned char server_random[SSL3_RANDOM_SIZE]; + unsigned char client_random[SSL3_RANDOM_SIZE]; + SSL3_BUFFER_INTERNAL rbuf; /* read IO goes into here */ SSL3_BUFFER_INTERNAL wbuf; /* write IO goes into here */ @@ -1044,15 +1189,6 @@ typedef struct ssl3_state_internal_st { SSL_HANDSHAKE hs; - struct { - DH *dh; - - EC_KEY *ecdh; /* holds short lived ECDH key */ - int ecdh_nid; - - uint8_t *x25519; - } tmp; - /* Connection binding to prevent renegotiation attacks */ unsigned char previous_client_finished[EVP_MAX_MD_SIZE]; unsigned char previous_client_finished_len; @@ -1073,62 +1209,8 @@ typedef struct ssl3_state_internal_st { */ unsigned char *alpn_selected; size_t alpn_selected_len; -} SSL3_STATE_INTERNAL; -#define S3I(s) (s->s3->internal) - -typedef struct ssl3_state_st { - long flags; - - unsigned char server_random[SSL3_RANDOM_SIZE]; - unsigned char client_random[SSL3_RANDOM_SIZE]; - - struct ssl3_state_internal_st *internal; } SSL3_STATE; -typedef struct cert_st { - /* Current active set */ - CERT_PKEY *key; /* ALWAYS points to an element of the pkeys array - * Probably it would make more sense to store - * an index, not a pointer. */ - - /* The following masks are for the key and auth - * algorithms that are supported by the certs below */ - int valid; - unsigned long mask_k; - unsigned long mask_a; - - DH *dh_tmp; - DH *(*dh_tmp_cb)(SSL *ssl, int is_export, int keysize); - int dh_tmp_auto; - - CERT_PKEY pkeys[SSL_PKEY_NUM]; - - int references; /* >1 only if SSL_copy_session_id is used */ -} CERT; - - -typedef struct sess_cert_st { - STACK_OF(X509) *cert_chain; /* as received from peer */ - - /* The 'peer_...' members are used only by clients. */ - int peer_cert_type; - - CERT_PKEY *peer_key; /* points to an element of peer_pkeys (never NULL!) */ - CERT_PKEY peer_pkeys[SSL_PKEY_NUM]; - /* Obviously we don't have the private keys of these, - * so maybe we shouldn't even use the CERT_PKEY type here. */ - - int peer_nid; - DH *peer_dh_tmp; - EC_KEY *peer_ecdh_tmp; - uint8_t *peer_x25519_tmp; - - int references; /* actually always 1 at the moment */ -} SESS_CERT; - -/*#define SSL_DEBUG */ -/*#define RSA_DEBUG */ - /* * Flag values for enc_flags. */ @@ -1165,6 +1247,7 @@ int ssl_supported_tls_version_range(SSL *s, uint16_t *min_ver, uint16_t *max_ver uint16_t ssl_tls_version(uint16_t version); uint16_t ssl_effective_tls_version(SSL *s); int ssl_max_supported_version(SSL *s, uint16_t *max_ver); +int ssl_max_legacy_version(SSL *s, uint16_t *max_ver); int ssl_max_shared_version(SSL *s, uint16_t peer_ver, uint16_t *max_ver); int ssl_check_version_from_server(SSL *s, uint16_t server_version); int ssl_legacy_stack_version(SSL *s, uint16_t version); @@ -1176,24 +1259,20 @@ const SSL_METHOD *tls_legacy_method(void); const SSL_METHOD *ssl_get_method(uint16_t version); void ssl_clear_cipher_state(SSL *s); -void ssl_clear_cipher_read_state(SSL *s); -void ssl_clear_cipher_write_state(SSL *s); int ssl_clear_bad_session(SSL *s); void ssl_info_callback(const SSL *s, int type, int value); void ssl_msg_callback(SSL *s, int is_write, int content_type, const void *msg_buf, size_t msg_len); -CERT *ssl_cert_new(void); -CERT *ssl_cert_dup(CERT *cert); -void ssl_cert_free(CERT *c); -int ssl_cert_set0_chain(CERT *c, STACK_OF(X509) *chain); -int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain); -int ssl_cert_add0_chain_cert(CERT *c, X509 *cert); -int ssl_cert_add1_chain_cert(CERT *c, X509 *cert); +SSL_CERT *ssl_cert_new(void); +SSL_CERT *ssl_cert_dup(SSL_CERT *cert); +void ssl_cert_free(SSL_CERT *c); +int ssl_cert_set0_chain(SSL_CERT *c, STACK_OF(X509) *chain); +int ssl_cert_set1_chain(SSL_CERT *c, STACK_OF(X509) *chain); +int ssl_cert_add0_chain_cert(SSL_CERT *c, X509 *cert); +int ssl_cert_add1_chain_cert(SSL_CERT *c, X509 *cert); -SESS_CERT *ssl_sess_cert_new(void); -void ssl_sess_cert_free(SESS_CERT *sc); int ssl_get_new_session(SSL *s, int session); int ssl_get_prev_session(SSL *s, CBS *session_id, CBS *ext_block, int *alert); @@ -1219,12 +1298,12 @@ int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk); int ssl_undefined_function(SSL *s); int ssl_undefined_void_function(void); int ssl_undefined_const_function(const SSL *s); -CERT_PKEY *ssl_get_server_send_pkey(const SSL *s); +SSL_CERT_PKEY *ssl_get_server_send_pkey(const SSL *s); EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *c, const EVP_MD **pmd, const struct ssl_sigalg **sap); -DH *ssl_get_auto_dh(SSL *s); -int ssl_cert_type(X509 *x, EVP_PKEY *pkey); -void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher); +size_t ssl_dhe_params_auto_key_bits(SSL *s); +int ssl_cert_type(EVP_PKEY *pkey); +void ssl_set_cert_masks(SSL_CERT *c, const SSL_CIPHER *cipher); STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s); int ssl_has_ecc_ciphers(SSL *s); int ssl_verify_alarm_type(long type); @@ -1240,7 +1319,7 @@ int ssl3_send_change_cipher_spec(SSL *s, int state_a, int state_b); int ssl3_do_write(SSL *s, int type); int ssl3_send_alert(SSL *s, int level, int desc); int ssl3_get_req_cert_types(SSL *s, CBB *cbb); -long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok); +int ssl3_get_message(SSL *s, int st1, int stn, int mt, long max); int ssl3_send_finished(SSL *s, int state_a, int state_b); int ssl3_num_ciphers(void); const SSL_CIPHER *ssl3_get_cipher(unsigned int u); @@ -1251,10 +1330,14 @@ int ssl3_renegotiate(SSL *ssl); int ssl3_renegotiate_check(SSL *ssl); +void ssl_force_want_read(SSL *s); + int ssl3_dispatch_alert(SSL *s); +int ssl3_read_alert(SSL *s); +int ssl3_read_change_cipher_spec(SSL *s); int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek); int ssl3_write_bytes(SSL *s, int type, const void *buf, int len); -int ssl3_output_cert_chain(SSL *s, CBB *cbb, CERT_PKEY *cpk); +int ssl3_output_cert_chain(SSL *s, CBB *cbb, SSL_CERT_PKEY *cpk); SSL_CIPHER *ssl3_choose_cipher(SSL *ssl, STACK_OF(SSL_CIPHER) *clnt, STACK_OF(SSL_CIPHER) *srvr); int ssl3_setup_buffers(SSL *s); @@ -1324,6 +1407,17 @@ int ssl3_get_client_certificate(SSL *s); int ssl3_get_client_key_exchange(SSL *s); int ssl3_get_cert_verify(SSL *s); +int ssl_kex_generate_dhe(DH *dh, DH *dh_params); +int ssl_kex_generate_dhe_params_auto(DH *dh, size_t key_len); +int ssl_kex_params_dhe(DH *dh, CBB *cbb); +int ssl_kex_public_dhe(DH *dh, CBB *cbb); +int ssl_kex_peer_params_dhe(DH *dh, CBS *cbs, int *decode_error, + int *invalid_params); +int ssl_kex_peer_public_dhe(DH *dh, CBS *cbs, int *decode_error, + int *invalid_key); +int ssl_kex_derive_dhe(DH *dh, DH *dh_peer, + uint8_t **shared_key, size_t *shared_key_len); + int ssl_kex_dummy_ecdhe_x25519(EVP_PKEY *pkey); int ssl_kex_generate_ecdhe_ecp(EC_KEY *ecdh, int nid); int ssl_kex_public_ecdhe_ecp(EC_KEY *ecdh, CBB *cbb); @@ -1340,7 +1434,7 @@ void ssl_free_wbio_buffer(SSL *s); int tls1_transcript_hash_init(SSL *s); int tls1_transcript_hash_update(SSL *s, const unsigned char *buf, size_t len); -int tls1_transcript_hash_value(SSL *s, const unsigned char *out, size_t len, +int tls1_transcript_hash_value(SSL *s, unsigned char *out, size_t len, size_t *outlen); void tls1_transcript_hash_free(SSL *s); @@ -1374,7 +1468,7 @@ int tls12_derive_master_secret(SSL *s, uint8_t *premaster_secret, size_t premaster_secret_len); int ssl_using_ecc_cipher(SSL *s); -int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s); +int ssl_check_srvr_ecc_cert_and_alg(SSL *s, X509 *x); void tls1_get_formatlist(SSL *s, int client_formats, const uint8_t **pformats, size_t *pformatslen); diff --git a/ssl/ssl_packet.c b/ssl/ssl_packet.c index af56dce..091685b 100644 --- a/ssl/ssl_packet.c +++ b/ssl/ssl_packet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_packet.c,v 1.12 2021/07/01 17:53:39 jsing Exp $ */ +/* $OpenBSD: ssl_packet.c,v 1.13 2022/02/05 14:54:10 jsing Exp $ */ /* * Copyright (c) 2016, 2017 Joel Sing * @@ -209,10 +209,10 @@ ssl_convert_sslv2_client_hello(SSL *s) if (!CBB_finish(&cbb, &data, &data_len)) goto err; - if (data_len > S3I(s)->rbuf.len) + if (data_len > s->s3->rbuf.len) goto err; - s->internal->packet = S3I(s)->rbuf.buf; + s->internal->packet = s->s3->rbuf.buf; s->internal->packet_length = data_len; memcpy(s->internal->packet, data, data_len); ret = 1; diff --git a/ssl/ssl_pkt.c b/ssl/ssl_pkt.c index 049a7df..3dd0269 100644 --- a/ssl/ssl_pkt.c +++ b/ssl/ssl_pkt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_pkt.c,v 1.50 2021/08/30 19:25:43 jsing Exp $ */ +/* $OpenBSD: ssl_pkt.c,v 1.58 2022/03/26 15:05:53 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -127,21 +127,22 @@ static int ssl3_get_record(SSL *s); * Force a WANT_READ return for certain error conditions where * we don't want to spin internally. */ -static void +void ssl_force_want_read(SSL *s) { - BIO * bio; + BIO *bio; bio = SSL_get_rbio(s); BIO_clear_retry_flags(bio); BIO_set_retry_read(bio); + s->internal->rwstate = SSL_READING; } /* * If extend == 0, obtain new n-byte packet; if extend == 1, increase * packet by another n bytes. - * The packet will be in the sub-array of S3I(s)->rbuf.buf specified + * The packet will be in the sub-array of s->s3->rbuf.buf specified * by s->internal->packet and s->internal->packet_length. * (If s->internal->read_ahead is set, 'max' bytes may be stored in rbuf * [plus s->internal->packet_length bytes if extend == 1].) @@ -149,7 +150,7 @@ ssl_force_want_read(SSL *s) static int ssl3_read_n(SSL *s, int n, int max, int extend) { - SSL3_BUFFER_INTERNAL *rb = &(S3I(s)->rbuf); + SSL3_BUFFER_INTERNAL *rb = &(s->s3->rbuf); int i, len, left; size_t align; unsigned char *pkt; @@ -238,7 +239,7 @@ ssl3_read_n(SSL *s, int n, int max, int extend) } while (left < n) { - /* Now we have len+left bytes at the front of S3I(s)->rbuf.buf + /* Now we have len+left bytes at the front of s->s3->rbuf.buf * and need to read in more until we have len+n (up to * len+max if possible) */ @@ -287,7 +288,7 @@ ssl3_packet_read(SSL *s, int plen) { int n; - n = ssl3_read_n(s, plen, S3I(s)->rbuf.len, 0); + n = ssl3_read_n(s, plen, s->s3->rbuf.len, 0); if (n <= 0) return n; if (s->internal->packet_length < plen) @@ -326,8 +327,8 @@ ssl3_packet_extend(SSL *s, int plen) static int ssl3_get_record(SSL *s) { - SSL3_BUFFER_INTERNAL *rb = &(S3I(s)->rbuf); - SSL3_RECORD_INTERNAL *rr = &(S3I(s)->rrec); + SSL3_BUFFER_INTERNAL *rb = &(s->s3->rbuf); + SSL3_RECORD_INTERNAL *rr = &(s->s3->rrec); uint8_t alert_desc; uint8_t *out; size_t out_len; @@ -482,8 +483,8 @@ ssl3_write_bytes(SSL *s, int type, const void *buf_, int len) } s->internal->rwstate = SSL_NOTHING; - tot = S3I(s)->wnum; - S3I(s)->wnum = 0; + tot = s->s3->wnum; + s->s3->wnum = 0; if (SSL_in_init(s) && !s->internal->in_handshake) { i = s->internal->handshake_func(s); @@ -506,7 +507,7 @@ ssl3_write_bytes(SSL *s, int type, const void *buf_, int len) i = do_ssl3_write(s, type, &(buf[tot]), nw); if (i <= 0) { - S3I(s)->wnum = tot; + s->s3->wnum = tot; return i; } @@ -517,7 +518,7 @@ ssl3_write_bytes(SSL *s, int type, const void *buf_, int len) * empty fragment in ciphersuites with known-IV * weakness. */ - S3I(s)->empty_fragment_done = 0; + s->s3->empty_fragment_done = 0; return tot + i; } @@ -530,7 +531,7 @@ ssl3_write_bytes(SSL *s, int type, const void *buf_, int len) static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, unsigned int len) { - SSL3_BUFFER_INTERNAL *wb = &(S3I(s)->wbuf); + SSL3_BUFFER_INTERNAL *wb = &(s->s3->wbuf); SSL_SESSION *sess = s->session; int need_empty_fragment = 0; size_t align, out_len; @@ -552,7 +553,7 @@ do_ssl3_write(SSL *s, int type, const unsigned char *buf, unsigned int len) return (ssl3_write_pending(s, type, buf, len)); /* If we have an alert to send, let's send it. */ - if (S3I(s)->alert_dispatch) { + if (s->s3->alert_dispatch) { if ((ret = ssl3_dispatch_alert(s)) <= 0) return (ret); /* If it went, fall through and send more stuff. */ @@ -571,9 +572,9 @@ do_ssl3_write(SSL *s, int type, const unsigned char *buf, unsigned int len) * bytes and record version number > TLS 1.0. */ version = s->version; - if (S3I(s)->hs.state == SSL3_ST_CW_CLNT_HELLO_B && + if (s->s3->hs.state == SSL3_ST_CW_CLNT_HELLO_B && !s->internal->renegotiate && - S3I(s)->hs.our_max_tls_version > TLS1_VERSION) + s->s3->hs.our_max_tls_version > TLS1_VERSION) version = TLS1_VERSION; /* @@ -582,8 +583,8 @@ do_ssl3_write(SSL *s, int type, const unsigned char *buf, unsigned int len) * is unnecessary for AEAD. */ if (sess != NULL && tls12_record_layer_write_protected(s->internal->rl)) { - if (S3I(s)->need_empty_fragments && - !S3I(s)->empty_fragment_done && + if (s->s3->need_empty_fragments && + !s->s3->empty_fragment_done && type == SSL3_RT_APPLICATION_DATA) need_empty_fragment = 1; } @@ -608,7 +609,7 @@ do_ssl3_write(SSL *s, int type, const unsigned char *buf, unsigned int len) if (!tls12_record_layer_seal_record(s->internal->rl, type, buf, 0, &cbb)) goto err; - S3I(s)->empty_fragment_done = 1; + s->s3->empty_fragment_done = 1; } if (!tls12_record_layer_seal_record(s->internal->rl, type, buf, len, &cbb)) @@ -623,10 +624,10 @@ do_ssl3_write(SSL *s, int type, const unsigned char *buf, unsigned int len) * Memorize arguments so that ssl3_write_pending can detect * bad write retries later. */ - S3I(s)->wpend_tot = len; - S3I(s)->wpend_buf = buf; - S3I(s)->wpend_type = type; - S3I(s)->wpend_ret = len; + s->s3->wpend_tot = len; + s->s3->wpend_buf = buf; + s->s3->wpend_type = type; + s->s3->wpend_ret = len; /* We now just need to write the buffer. */ return ssl3_write_pending(s, type, buf, len); @@ -637,17 +638,17 @@ do_ssl3_write(SSL *s, int type, const unsigned char *buf, unsigned int len) return -1; } -/* if S3I(s)->wbuf.left != 0, we need to call this */ +/* if s->s3->wbuf.left != 0, we need to call this */ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, unsigned int len) { int i; - SSL3_BUFFER_INTERNAL *wb = &(S3I(s)->wbuf); + SSL3_BUFFER_INTERNAL *wb = &(s->s3->wbuf); /* XXXX */ - if ((S3I(s)->wpend_tot > (int)len) || ((S3I(s)->wpend_buf != buf) && + if ((s->s3->wpend_tot > (int)len) || ((s->s3->wpend_buf != buf) && !(s->internal->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)) || - (S3I(s)->wpend_type != type)) { + (s->s3->wpend_type != type)) { SSLerror(s, SSL_R_BAD_WRITE_RETRY); return (-1); } @@ -669,7 +670,7 @@ ssl3_write_pending(SSL *s, int type, const unsigned char *buf, unsigned int len) !SSL_is_dtls(s)) ssl3_release_write_buffer(s); s->internal->rwstate = SSL_NOTHING; - return (S3I(s)->wpend_ret); + return (s->s3->wpend_ret); } else if (i <= 0) { /* * For DTLS, just drop it. That's kind of the @@ -684,6 +685,299 @@ ssl3_write_pending(SSL *s, int type, const unsigned char *buf, unsigned int len) } } +int +ssl3_read_alert(SSL *s) +{ + SSL3_RECORD_INTERNAL *rr = &s->s3->rrec; + uint8_t alert_level, alert_descr; + + /* + * TLSv1.2 permits an alert to be fragmented across multiple records or + * for multiple alerts to be be coalesced into a single alert record. + * In the case of DTLS, there is no way to reassemble an alert + * fragmented across multiple records, hence a full alert must be + * available in the record. + */ + while (rr->length > 0 && + s->s3->alert_fragment_len < sizeof(s->s3->alert_fragment)) { + s->s3->alert_fragment[s->s3->alert_fragment_len++] = + rr->data[rr->off++]; + rr->length--; + } + if (s->s3->alert_fragment_len < sizeof(s->s3->alert_fragment)) { + if (SSL_is_dtls(s)) { + SSLerror(s, SSL_R_BAD_LENGTH); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + return -1; + } + return 1; + } + + ssl_msg_callback(s, 0, SSL3_RT_ALERT, s->s3->alert_fragment, 2); + + alert_level = s->s3->alert_fragment[0]; + alert_descr = s->s3->alert_fragment[1]; + s->s3->alert_fragment_len = 0; + + ssl_info_callback(s, SSL_CB_READ_ALERT, + (alert_level << 8) | alert_descr); + + if (alert_level == SSL3_AL_WARNING) { + s->s3->warn_alert = alert_descr; + if (alert_descr == SSL_AD_CLOSE_NOTIFY) { + s->internal->shutdown |= SSL_RECEIVED_SHUTDOWN; + return 0; + } + /* We requested renegotiation and the peer rejected it. */ + if (alert_descr == SSL_AD_NO_RENEGOTIATION) { + SSLerror(s, SSL_R_NO_RENEGOTIATION); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_HANDSHAKE_FAILURE); + return -1; + } + } else if (alert_level == SSL3_AL_FATAL) { + s->internal->rwstate = SSL_NOTHING; + s->s3->fatal_alert = alert_descr; + SSLerror(s, SSL_AD_REASON_OFFSET + alert_descr); + ERR_asprintf_error_data("SSL alert number %d", alert_descr); + s->internal->shutdown |= SSL_RECEIVED_SHUTDOWN; + SSL_CTX_remove_session(s->ctx, s->session); + return 0; + } else { + SSLerror(s, SSL_R_UNKNOWN_ALERT_TYPE); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); + return -1; + } + + return 1; +} + +int +ssl3_read_change_cipher_spec(SSL *s) +{ + SSL3_RECORD_INTERNAL *rr = &s->s3->rrec; + + /* + * 'Change Cipher Spec' is just a single byte, so we know exactly what + * the record payload has to look like. + */ + if (rr->length != 1 || rr->off != 0) { + SSLerror(s, SSL_R_BAD_CHANGE_CIPHER_SPEC); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + return -1; + } + if (rr->data[0] != SSL3_MT_CCS) { + SSLerror(s, SSL_R_BAD_CHANGE_CIPHER_SPEC); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); + return -1; + } + + /* XDTLS: check that epoch is consistent */ + + ssl_msg_callback(s, 0, SSL3_RT_CHANGE_CIPHER_SPEC, rr->data, 1); + + /* Check that we have a cipher to change to. */ + if (s->s3->hs.cipher == NULL) { + SSLerror(s, SSL_R_CCS_RECEIVED_EARLY); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + /* Check that we should be receiving a Change Cipher Spec. */ + if (SSL_is_dtls(s)) { + if (!s->d1->change_cipher_spec_ok) { + /* + * We can't process a CCS now, because previous + * handshake messages are still missing, so just + * drop it. + */ + rr->length = 0; + return 1; + } + s->d1->change_cipher_spec_ok = 0; + } else { + if ((s->s3->flags & SSL3_FLAGS_CCS_OK) == 0) { + SSLerror(s, SSL_R_CCS_RECEIVED_EARLY); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + s->s3->flags &= ~SSL3_FLAGS_CCS_OK; + } + + rr->length = 0; + + s->s3->change_cipher_spec = 1; + if (!ssl3_do_change_cipher_spec(s)) + return -1; + + return 1; +} + +static int +ssl3_read_handshake_unexpected(SSL *s) +{ + SSL3_RECORD_INTERNAL *rr = &s->s3->rrec; + uint32_t hs_msg_length; + uint8_t hs_msg_type; + CBS cbs; + int ret; + + /* + * We need four bytes of handshake data so we have a handshake message + * header - this may be in the same record or fragmented across multiple + * records. + */ + while (rr->length > 0 && + s->s3->handshake_fragment_len < sizeof(s->s3->handshake_fragment)) { + s->s3->handshake_fragment[s->s3->handshake_fragment_len++] = + rr->data[rr->off++]; + rr->length--; + } + + if (s->s3->handshake_fragment_len < sizeof(s->s3->handshake_fragment)) + return 1; + + if (s->internal->in_handshake) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return -1; + } + + /* + * This code currently deals with HelloRequest and ClientHello messages - + * anything else is pushed to the handshake_func. Almost all of this + * belongs in the client/server handshake code. + */ + + /* Parse handshake message header. */ + CBS_init(&cbs, s->s3->handshake_fragment, s->s3->handshake_fragment_len); + if (!CBS_get_u8(&cbs, &hs_msg_type)) + return -1; + if (!CBS_get_u24(&cbs, &hs_msg_length)) + return -1; + + if (hs_msg_type == SSL3_MT_HELLO_REQUEST) { + /* + * Incoming HelloRequest messages should only be received by a + * client. A server may send these at any time - a client should + * ignore the message if received in the middle of a handshake. + * See RFC 5246 sections 7.4 and 7.4.1.1. + */ + if (s->server) { + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + if (hs_msg_length != 0) { + SSLerror(s, SSL_R_BAD_HELLO_REQUEST); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + return -1; + } + + ssl_msg_callback(s, 0, SSL3_RT_HANDSHAKE, + s->s3->handshake_fragment, s->s3->handshake_fragment_len); + + s->s3->handshake_fragment_len = 0; + + /* + * It should be impossible to hit this, but keep the safety + * harness for now... + */ + if (s->session == NULL || s->session->cipher == NULL) + return 1; + + /* + * Ignore this message if we're currently handshaking, + * renegotiation is already pending or renegotiation is disabled + * via flags. + */ + if (!SSL_is_init_finished(s) || s->s3->renegotiate || + (s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) != 0) + return 1; + + if (!ssl3_renegotiate(s)) + return 1; + if (!ssl3_renegotiate_check(s)) + return 1; + + } else if (hs_msg_type == SSL3_MT_CLIENT_HELLO) { + /* + * Incoming ClientHello messages should only be received by a + * server. A client may send these in response to server + * initiated renegotiation (HelloRequest) or in order to + * initiate renegotiation by the client. See RFC 5246 section + * 7.4.1.2. + */ + if (!s->server) { + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + /* + * A client should not be sending a ClientHello unless we're not + * currently handshaking. + */ + if (!SSL_is_init_finished(s)) { + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + if ((s->internal->options & SSL_OP_NO_CLIENT_RENEGOTIATION) != 0) { + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_NO_RENEGOTIATION); + return -1; + } + + if (s->session == NULL || s->session->cipher == NULL) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return -1; + } + + /* Client requested renegotiation but it is not permitted. */ + if (!s->s3->send_connection_binding || + (s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) != 0) { + ssl3_send_alert(s, SSL3_AL_WARNING, + SSL_AD_NO_RENEGOTIATION); + return 1; + } + + s->s3->hs.state = SSL_ST_ACCEPT; + s->internal->renegotiate = 1; + s->internal->new_session = 1; + + } else { + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + if ((ret = s->internal->handshake_func(s)) < 0) + return ret; + if (ret == 0) { + SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); + return -1; + } + + if (!(s->internal->mode & SSL_MODE_AUTO_RETRY)) { + if (s->s3->rbuf.left == 0) { + ssl_force_want_read(s); + return -1; + } + } + + /* + * We either finished a handshake or ignored the request, now try again + * to obtain the (application) data we were asked for. + */ + return 1; +} + /* Return up to 'len' payload bytes received in 'type' records. * 'type' is one of the following: * @@ -714,59 +1008,57 @@ ssl3_write_pending(SSL *s, int type, const unsigned char *buf, unsigned int len) int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) { - int al, i, ret, rrcount = 0; - unsigned int n; SSL3_RECORD_INTERNAL *rr; + int rrcount = 0; + unsigned int n; + int ret; - if (S3I(s)->rbuf.buf == NULL) /* Not initialized yet */ + if (s->s3->rbuf.buf == NULL) { if (!ssl3_setup_read_buffer(s)) - return (-1); + return -1; + } if (len < 0) { SSLerror(s, ERR_R_INTERNAL_ERROR); return -1; } - if ((type && type != SSL3_RT_APPLICATION_DATA && - type != SSL3_RT_HANDSHAKE) || - (peek && (type != SSL3_RT_APPLICATION_DATA))) { + if (type != 0 && type != SSL3_RT_APPLICATION_DATA && + type != SSL3_RT_HANDSHAKE) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return -1; + } + if (peek && type != SSL3_RT_APPLICATION_DATA) { SSLerror(s, ERR_R_INTERNAL_ERROR); return -1; } - if ((type == SSL3_RT_HANDSHAKE) && - (S3I(s)->handshake_fragment_len > 0)) { - /* (partially) satisfy request from storage */ - unsigned char *src = S3I(s)->handshake_fragment; + if (type == SSL3_RT_HANDSHAKE && s->s3->handshake_fragment_len > 0) { + /* Partially satisfy request from fragment storage. */ + unsigned char *src = s->s3->handshake_fragment; unsigned char *dst = buf; unsigned int k; /* peek == 0 */ n = 0; - while ((len > 0) && (S3I(s)->handshake_fragment_len > 0)) { + while (len > 0 && s->s3->handshake_fragment_len > 0) { *dst++ = *src++; len--; - S3I(s)->handshake_fragment_len--; + s->s3->handshake_fragment_len--; n++; } /* move any remaining fragment bytes: */ - for (k = 0; k < S3I(s)->handshake_fragment_len; k++) - S3I(s)->handshake_fragment[k] = *src++; + for (k = 0; k < s->s3->handshake_fragment_len; k++) + s->s3->handshake_fragment[k] = *src++; return n; } - /* - * Now S3I(s)->handshake_fragment_len == 0 if - * type == SSL3_RT_HANDSHAKE. - */ - if (!s->internal->in_handshake && SSL_in_init(s)) { - /* type == SSL3_RT_APPLICATION_DATA */ - i = s->internal->handshake_func(s); - if (i < 0) - return (i); - if (i == 0) { + if (SSL_in_init(s) && !s->internal->in_handshake) { + if ((ret = s->internal->handshake_func(s)) < 0) + return ret; + if (ret == 0) { SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); - return (-1); + return -1; } } @@ -786,377 +1078,149 @@ ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) s->internal->rwstate = SSL_NOTHING; - /* - * S3I(s)->rrec.type - is the type of record - * S3I(s)->rrec.data, - data - * S3I(s)->rrec.off, - offset into 'data' for next read - * S3I(s)->rrec.length, - number of bytes. - */ - rr = &(S3I(s)->rrec); + rr = &s->s3->rrec; - /* get new packet if necessary */ - if ((rr->length == 0) || (s->internal->rstate == SSL_ST_READ_BODY)) { - ret = ssl3_get_record(s); - if (ret <= 0) - return (ret); + if (rr->length == 0 || s->internal->rstate == SSL_ST_READ_BODY) { + if ((ret = ssl3_get_record(s)) <= 0) + return ret; } - /* we now have a packet which can be read and processed */ + /* We now have a packet which can be read and processed. */ - if (S3I(s)->change_cipher_spec /* set when we receive ChangeCipherSpec, - * reset by ssl3_get_finished */ - && (rr->type != SSL3_RT_HANDSHAKE)) { - al = SSL_AD_UNEXPECTED_MESSAGE; + if (s->s3->change_cipher_spec && rr->type != SSL3_RT_HANDSHAKE) { SSLerror(s, SSL_R_DATA_BETWEEN_CCS_AND_FINISHED); - goto fatal_err; + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + return -1; } - /* If the other end has shut down, throw anything we read away - * (even in 'peek' mode) */ + /* + * If the other end has shut down, throw anything we read away (even in + * 'peek' mode). + */ if (s->internal->shutdown & SSL_RECEIVED_SHUTDOWN) { - rr->length = 0; s->internal->rwstate = SSL_NOTHING; - return (0); + rr->length = 0; + return 0; } - /* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */ if (type == rr->type) { - /* make sure that we are not getting application data when we - * are doing a handshake for the first time */ + /* + * Make sure that we are not getting application data when we + * are doing a handshake for the first time. + */ if (SSL_in_init(s) && type == SSL3_RT_APPLICATION_DATA && !tls12_record_layer_read_protected(s->internal->rl)) { - al = SSL_AD_UNEXPECTED_MESSAGE; SSLerror(s, SSL_R_APP_DATA_IN_HANDSHAKE); - goto fatal_err; + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); + return -1; } if (len <= 0) - return (len); + return len; if ((unsigned int)len > rr->length) n = rr->length; else n = (unsigned int)len; - memcpy(buf, &(rr->data[rr->off]), n); + memcpy(buf, &rr->data[rr->off], n); if (!peek) { - memset(&(rr->data[rr->off]), 0, n); + memset(&rr->data[rr->off], 0, n); rr->length -= n; rr->off += n; if (rr->length == 0) { s->internal->rstate = SSL_ST_READ_HEADER; rr->off = 0; if (s->internal->mode & SSL_MODE_RELEASE_BUFFERS && - S3I(s)->rbuf.left == 0) + s->s3->rbuf.left == 0) ssl3_release_read_buffer(s); } } - return (n); + + return n; } - - /* If we get here, then type != rr->type; if we have a handshake - * message, then it was unexpected (Hello Request or Client Hello). */ - - { - /* - * In case of record types for which we have 'fragment' - * storage, * fill that so that we can process the data - * at a fixed place. - */ - unsigned int dest_maxlen = 0; - unsigned char *dest = NULL; - unsigned int *dest_len = NULL; - - if (rr->type == SSL3_RT_HANDSHAKE) { - dest_maxlen = sizeof S3I(s)->handshake_fragment; - dest = S3I(s)->handshake_fragment; - dest_len = &S3I(s)->handshake_fragment_len; - } else if (rr->type == SSL3_RT_ALERT) { - dest_maxlen = sizeof S3I(s)->alert_fragment; - dest = S3I(s)->alert_fragment; - dest_len = &S3I(s)->alert_fragment_len; - } - if (dest_maxlen > 0) { - /* available space in 'dest' */ - n = dest_maxlen - *dest_len; - if (rr->length < n) - n = rr->length; /* available bytes */ - - /* now move 'n' bytes: */ - while (n-- > 0) { - dest[(*dest_len)++] = rr->data[rr->off++]; - rr->length--; - } - - if (*dest_len < dest_maxlen) - goto start; /* fragment was too small */ - } - } - - /* S3I(s)->handshake_fragment_len == 4 iff rr->type == SSL3_RT_HANDSHAKE; - * S3I(s)->alert_fragment_len == 2 iff rr->type == SSL3_RT_ALERT. - * (Possibly rr is 'empty' now, i.e. rr->length may be 0.) */ - - /* If we are a client, check for an incoming 'Hello Request': */ - if ((!s->server) && (S3I(s)->handshake_fragment_len >= 4) && - (S3I(s)->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) && - (s->session != NULL) && (s->session->cipher != NULL)) { - S3I(s)->handshake_fragment_len = 0; - - if ((S3I(s)->handshake_fragment[1] != 0) || - (S3I(s)->handshake_fragment[2] != 0) || - (S3I(s)->handshake_fragment[3] != 0)) { - al = SSL_AD_DECODE_ERROR; - SSLerror(s, SSL_R_BAD_HELLO_REQUEST); - goto fatal_err; - } - - ssl_msg_callback(s, 0, SSL3_RT_HANDSHAKE, - S3I(s)->handshake_fragment, 4); - - if (SSL_is_init_finished(s) && - !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) && - !S3I(s)->renegotiate) { - ssl3_renegotiate(s); - if (ssl3_renegotiate_check(s)) { - i = s->internal->handshake_func(s); - if (i < 0) - return (i); - if (i == 0) { - SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); - return (-1); - } - - if (!(s->internal->mode & SSL_MODE_AUTO_RETRY)) { - if (S3I(s)->rbuf.left == 0) { - /* no read-ahead left? */ - /* In the case where we try to read application data, - * but we trigger an SSL handshake, we return -1 with - * the retry option set. Otherwise renegotiation may - * cause nasty problems in the blocking world */ - ssl_force_want_read(s); - return (-1); - } - } - } - } - /* we either finished a handshake or ignored the request, - * now try again to obtain the (application) data we were asked for */ - goto start; - } - /* Disallow client initiated renegotiation if configured. */ - if (s->server && SSL_is_init_finished(s) && - S3I(s)->handshake_fragment_len >= 4 && - S3I(s)->handshake_fragment[0] == SSL3_MT_CLIENT_HELLO && - (s->internal->options & SSL_OP_NO_CLIENT_RENEGOTIATION)) { - al = SSL_AD_NO_RENEGOTIATION; - goto fatal_err; - } - /* If we are a server and get a client hello when renegotiation isn't - * allowed send back a no renegotiation alert and carry on. - * WARNING: experimental code, needs reviewing (steve) + /* + * If we get here, then type != rr->type; if we have a handshake + * message, then it was unexpected (Hello Request or Client Hello). */ - if (s->server && - SSL_is_init_finished(s) && - !S3I(s)->send_connection_binding && - (S3I(s)->handshake_fragment_len >= 4) && - (S3I(s)->handshake_fragment[0] == SSL3_MT_CLIENT_HELLO) && - (s->session != NULL) && (s->session->cipher != NULL)) { - /*S3I(s)->handshake_fragment_len = 0;*/ - rr->length = 0; - ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION); - goto start; - } - if (S3I(s)->alert_fragment_len >= 2) { - int alert_level = S3I(s)->alert_fragment[0]; - int alert_descr = S3I(s)->alert_fragment[1]; - - S3I(s)->alert_fragment_len = 0; - - ssl_msg_callback(s, 0, SSL3_RT_ALERT, - S3I(s)->alert_fragment, 2); - - ssl_info_callback(s, SSL_CB_READ_ALERT, - (alert_level << 8) | alert_descr); - - if (alert_level == SSL3_AL_WARNING) { - S3I(s)->warn_alert = alert_descr; - if (alert_descr == SSL_AD_CLOSE_NOTIFY) { - s->internal->shutdown |= SSL_RECEIVED_SHUTDOWN; - return (0); - } - /* This is a warning but we receive it if we requested - * renegotiation and the peer denied it. Terminate with - * a fatal alert because if application tried to - * renegotiatie it presumably had a good reason and - * expects it to succeed. - * - * In future we might have a renegotiation where we - * don't care if the peer refused it where we carry on. - */ - else if (alert_descr == SSL_AD_NO_RENEGOTIATION) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerror(s, SSL_R_NO_RENEGOTIATION); - goto fatal_err; - } - } else if (alert_level == SSL3_AL_FATAL) { - s->internal->rwstate = SSL_NOTHING; - S3I(s)->fatal_alert = alert_descr; - SSLerror(s, SSL_AD_REASON_OFFSET + alert_descr); - ERR_asprintf_error_data("SSL alert number %d", - alert_descr); - s->internal->shutdown |= SSL_RECEIVED_SHUTDOWN; - SSL_CTX_remove_session(s->ctx, s->session); - return (0); - } else { - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerror(s, SSL_R_UNKNOWN_ALERT_TYPE); - goto fatal_err; - } + if (rr->type == SSL3_RT_ALERT) { + if ((ret = ssl3_read_alert(s)) <= 0) + return ret; goto start; } if (s->internal->shutdown & SSL_SENT_SHUTDOWN) { - /* but we have not received a shutdown */ s->internal->rwstate = SSL_NOTHING; rr->length = 0; - return (0); + return 0; + } + + if (rr->type == SSL3_RT_APPLICATION_DATA) { + /* + * At this point, we were expecting handshake data, but have + * application data. If the library was running inside + * ssl3_read() (i.e. in_read_app_data is set) and it makes + * sense to read application data at this point (session + * renegotiation not yet started), we will indulge it. + */ + if (s->s3->in_read_app_data != 0 && + s->s3->total_renegotiations != 0 && + (((s->s3->hs.state & SSL_ST_CONNECT) && + (s->s3->hs.state >= SSL3_ST_CW_CLNT_HELLO_A) && + (s->s3->hs.state <= SSL3_ST_CR_SRVR_HELLO_A)) || ( + (s->s3->hs.state & SSL_ST_ACCEPT) && + (s->s3->hs.state <= SSL3_ST_SW_HELLO_REQ_A) && + (s->s3->hs.state >= SSL3_ST_SR_CLNT_HELLO_A)))) { + s->s3->in_read_app_data = 2; + return -1; + } else { + SSLerror(s, SSL_R_UNEXPECTED_RECORD); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } } if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) { - /* 'Change Cipher Spec' is just a single byte, so we know - * exactly what the record payload has to look like */ - if ((rr->length != 1) || (rr->off != 0) || - (rr->data[0] != SSL3_MT_CCS)) { - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerror(s, SSL_R_BAD_CHANGE_CIPHER_SPEC); - goto fatal_err; - } - - /* Check we have a cipher to change to */ - if (S3I(s)->hs.cipher == NULL) { - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerror(s, SSL_R_CCS_RECEIVED_EARLY); - goto fatal_err; - } - - /* Check that we should be receiving a Change Cipher Spec. */ - if (!(s->s3->flags & SSL3_FLAGS_CCS_OK)) { - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerror(s, SSL_R_CCS_RECEIVED_EARLY); - goto fatal_err; - } - s->s3->flags &= ~SSL3_FLAGS_CCS_OK; - - rr->length = 0; - - ssl_msg_callback(s, 0, SSL3_RT_CHANGE_CIPHER_SPEC, rr->data, 1); - - S3I(s)->change_cipher_spec = 1; - if (!ssl3_do_change_cipher_spec(s)) - goto err; - else - goto start; - } - - /* Unexpected handshake message (Client Hello, or protocol violation) */ - if ((S3I(s)->handshake_fragment_len >= 4) && !s->internal->in_handshake) { - if (((S3I(s)->hs.state&SSL_ST_MASK) == SSL_ST_OK) && - !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) { - S3I(s)->hs.state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; - s->internal->renegotiate = 1; - s->internal->new_session = 1; - } - i = s->internal->handshake_func(s); - if (i < 0) - return (i); - if (i == 0) { - SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); - return (-1); - } - - if (!(s->internal->mode & SSL_MODE_AUTO_RETRY)) { - if (S3I(s)->rbuf.left == 0) { /* no read-ahead left? */ - /* In the case where we try to read application data, - * but we trigger an SSL handshake, we return -1 with - * the retry option set. Otherwise renegotiation may - * cause nasty problems in the blocking world */ - ssl_force_want_read(s); - return (-1); - } - } + if ((ret = ssl3_read_change_cipher_spec(s)) <= 0) + return ret; goto start; } - switch (rr->type) { - default: - /* - * TLS up to v1.1 just ignores unknown message types: - * TLS v1.2 give an unexpected message alert. - */ - if (s->version >= TLS1_VERSION && - s->version <= TLS1_1_VERSION) { - rr->length = 0; - goto start; - } - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerror(s, SSL_R_UNEXPECTED_RECORD); - goto fatal_err; - case SSL3_RT_CHANGE_CIPHER_SPEC: - case SSL3_RT_ALERT: - case SSL3_RT_HANDSHAKE: - /* we already handled all of these, with the possible exception - * of SSL3_RT_HANDSHAKE when s->internal->in_handshake is set, but that - * should not happen when type != rr->type */ - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerror(s, ERR_R_INTERNAL_ERROR); - goto fatal_err; - case SSL3_RT_APPLICATION_DATA: - /* At this point, we were expecting handshake data, - * but have application data. If the library was - * running inside ssl3_read() (i.e. in_read_app_data - * is set) and it makes sense to read application data - * at this point (session renegotiation not yet started), - * we will indulge it. - */ - if (S3I(s)->in_read_app_data && - (S3I(s)->total_renegotiations != 0) && - (((S3I(s)->hs.state & SSL_ST_CONNECT) && - (S3I(s)->hs.state >= SSL3_ST_CW_CLNT_HELLO_A) && - (S3I(s)->hs.state <= SSL3_ST_CR_SRVR_HELLO_A)) || - ((S3I(s)->hs.state & SSL_ST_ACCEPT) && - (S3I(s)->hs.state <= SSL3_ST_SW_HELLO_REQ_A) && - (S3I(s)->hs.state >= SSL3_ST_SR_CLNT_HELLO_A)))) { - S3I(s)->in_read_app_data = 2; - return (-1); - } else { - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerror(s, SSL_R_UNEXPECTED_RECORD); - goto fatal_err; - } + if (rr->type == SSL3_RT_HANDSHAKE) { + if ((ret = ssl3_read_handshake_unexpected(s)) <= 0) + return ret; + goto start; } - /* not reached */ - fatal_err: - ssl3_send_alert(s, SSL3_AL_FATAL, al); - err: - return (-1); + /* + * Unknown record type - TLSv1.2 sends an unexpected message alert while + * earlier versions silently ignore the record. + */ + if (ssl_effective_tls_version(s) <= TLS1_1_VERSION) { + rr->length = 0; + goto start; + } + SSLerror(s, SSL_R_UNEXPECTED_RECORD); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + return -1; } int ssl3_do_change_cipher_spec(SSL *s) { - if (S3I(s)->hs.tls12.key_block == NULL) { + if (s->s3->hs.tls12.key_block == NULL) { if (s->session == NULL || s->session->master_key_length == 0) { /* might happen if dtls1_read_bytes() calls this */ SSLerror(s, SSL_R_CCS_RECEIVED_EARLY); return (0); } - s->session->cipher = S3I(s)->hs.cipher; + s->session->cipher = s->s3->hs.cipher; if (!tls1_setup_key_block(s)) return (0); } @@ -1178,11 +1242,11 @@ static int ssl3_write_alert(SSL *s) { if (SSL_is_dtls(s)) - return do_dtls1_write(s, SSL3_RT_ALERT, S3I(s)->send_alert, - sizeof(S3I(s)->send_alert)); + return do_dtls1_write(s, SSL3_RT_ALERT, s->s3->send_alert, + sizeof(s->s3->send_alert)); - return do_ssl3_write(s, SSL3_RT_ALERT, S3I(s)->send_alert, - sizeof(S3I(s)->send_alert)); + return do_ssl3_write(s, SSL3_RT_ALERT, s->s3->send_alert, + sizeof(s->s3->send_alert)); } int @@ -1192,15 +1256,15 @@ ssl3_send_alert(SSL *s, int level, int desc) if (level == SSL3_AL_FATAL) SSL_CTX_remove_session(s->ctx, s->session); - S3I(s)->alert_dispatch = 1; - S3I(s)->send_alert[0] = level; - S3I(s)->send_alert[1] = desc; + s->s3->alert_dispatch = 1; + s->s3->send_alert[0] = level; + s->s3->send_alert[1] = desc; /* * If data is still being written out, the alert will be dispatched at * some point in the future. */ - if (S3I(s)->wbuf.left != 0) + if (s->s3->wbuf.left != 0) return -1; return ssl3_dispatch_alert(s); @@ -1211,9 +1275,9 @@ ssl3_dispatch_alert(SSL *s) { int ret; - S3I(s)->alert_dispatch = 0; + s->s3->alert_dispatch = 0; if ((ret = ssl3_write_alert(s)) <= 0) { - S3I(s)->alert_dispatch = 1; + s->s3->alert_dispatch = 1; return ret; } @@ -1222,13 +1286,13 @@ ssl3_dispatch_alert(SSL *s) * If the message does not get sent due to non-blocking IO, * we will not worry too much. */ - if (S3I(s)->send_alert[0] == SSL3_AL_FATAL) + if (s->s3->send_alert[0] == SSL3_AL_FATAL) (void)BIO_flush(s->wbio); - ssl_msg_callback(s, 1, SSL3_RT_ALERT, S3I(s)->send_alert, 2); + ssl_msg_callback(s, 1, SSL3_RT_ALERT, s->s3->send_alert, 2); ssl_info_callback(s, SSL_CB_WRITE_ALERT, - (S3I(s)->send_alert[0] << 8) | S3I(s)->send_alert[1]); + (s->s3->send_alert[0] << 8) | s->s3->send_alert[1]); return ret; } diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c index e3a1e5d..f5c90fc 100644 --- a/ssl/ssl_rsa.c +++ b/ssl/ssl_rsa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_rsa.c,v 1.34 2021/06/11 11:13:53 jsing Exp $ */ +/* $OpenBSD: ssl_rsa.c,v 1.39 2022/02/03 16:33:12 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -66,11 +66,11 @@ #include "ssl_locl.h" -static int ssl_set_cert(CERT *c, X509 *x509); -static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey); -static int use_certificate_chain_bio(BIO *in, CERT *cert, +static int ssl_set_cert(SSL_CERT *c, X509 *x509); +static int ssl_set_pkey(SSL_CERT *c, EVP_PKEY *pkey); +static int use_certificate_chain_bio(BIO *in, SSL_CERT *cert, pem_password_cb *passwd_cb, void *passwd_arg); -static int use_certificate_chain_file(const char *file, CERT *cert, +static int use_certificate_chain_file(const char *file, SSL_CERT *cert, pem_password_cb *passwd_cb, void *passwd_arg); int @@ -91,7 +91,7 @@ SSL_use_certificate_file(SSL *ssl, const char *file, int type) int ret = 0; X509 *x = NULL; - in = BIO_new(BIO_s_file_internal()); + in = BIO_new(BIO_s_file()); if (in == NULL) { SSLerror(ssl, ERR_R_BUF_LIB); goto end; @@ -167,11 +167,11 @@ SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) } static int -ssl_set_pkey(CERT *c, EVP_PKEY *pkey) +ssl_set_pkey(SSL_CERT *c, EVP_PKEY *pkey) { int i; - i = ssl_cert_type(NULL, pkey); + i = ssl_cert_type(pkey); if (i < 0) { SSLerrorx(SSL_R_UNKNOWN_CERTIFICATE_TYPE); return (0); @@ -188,19 +188,18 @@ ssl_set_pkey(CERT *c, EVP_PKEY *pkey) * Don't check the public/private key, this is mostly * for smart cards. */ - if ((pkey->type == EVP_PKEY_RSA) && - (RSA_flags(pkey->pkey.rsa) & RSA_METHOD_FLAG_NO_CHECK)) -; - else - if (!X509_check_private_key(c->pkeys[i].x509, pkey)) { - X509_free(c->pkeys[i].x509); - c->pkeys[i].x509 = NULL; - return 0; + if (EVP_PKEY_id(pkey) != EVP_PKEY_RSA || + !(RSA_flags(EVP_PKEY_get0_RSA(pkey)) & RSA_METHOD_FLAG_NO_CHECK)) { + if (!X509_check_private_key(c->pkeys[i].x509, pkey)) { + X509_free(c->pkeys[i].x509); + c->pkeys[i].x509 = NULL; + return 0; + } } } EVP_PKEY_free(c->pkeys[i].privatekey); - CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); + EVP_PKEY_up_ref(pkey); c->pkeys[i].privatekey = pkey; c->key = &(c->pkeys[i]); @@ -215,7 +214,7 @@ SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type) BIO *in; RSA *rsa = NULL; - in = BIO_new(BIO_s_file_internal()); + in = BIO_new(BIO_s_file()); if (in == NULL) { SSLerror(ssl, ERR_R_BUF_LIB); goto end; @@ -284,7 +283,7 @@ SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type) BIO *in; EVP_PKEY *pkey = NULL; - in = BIO_new(BIO_s_file_internal()); + in = BIO_new(BIO_s_file()); if (in == NULL) { SSLerror(ssl, ERR_R_BUF_LIB); goto end; @@ -344,7 +343,7 @@ SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) } static int -ssl_set_cert(CERT *c, X509 *x) +ssl_set_cert(SSL_CERT *c, X509 *x) { EVP_PKEY *pkey; int i; @@ -355,7 +354,7 @@ ssl_set_cert(CERT *c, X509 *x) return (0); } - i = ssl_cert_type(x, pkey); + i = ssl_cert_type(pkey); if (i < 0) { SSLerrorx(SSL_R_UNKNOWN_CERTIFICATE_TYPE); EVP_PKEY_free(pkey); @@ -363,36 +362,35 @@ ssl_set_cert(CERT *c, X509 *x) } if (c->pkeys[i].privatekey != NULL) { - EVP_PKEY_copy_parameters(pkey, c->pkeys[i].privatekey); + EVP_PKEY *priv_key = c->pkeys[i].privatekey; + + EVP_PKEY_copy_parameters(pkey, priv_key); ERR_clear_error(); /* * Don't check the public/private key, this is mostly * for smart cards. */ - if ((c->pkeys[i].privatekey->type == EVP_PKEY_RSA) && - (RSA_flags(c->pkeys[i].privatekey->pkey.rsa) & - RSA_METHOD_FLAG_NO_CHECK)) -; - else - if (!X509_check_private_key(x, c->pkeys[i].privatekey)) { - /* - * don't fail for a cert/key mismatch, just free - * current private key (when switching to a different - * cert & key, first this function should be used, - * then ssl_set_pkey - */ - EVP_PKEY_free(c->pkeys[i].privatekey); - c->pkeys[i].privatekey = NULL; - /* clear error queue */ - ERR_clear_error(); + if (EVP_PKEY_id(priv_key) != EVP_PKEY_RSA || + !(RSA_flags(EVP_PKEY_get0_RSA(priv_key)) & RSA_METHOD_FLAG_NO_CHECK)) { + if (!X509_check_private_key(x, priv_key)) { + /* + * don't fail for a cert/key mismatch, just free + * current private key (when switching to a + * different cert & key, first this function + * should be used, then ssl_set_pkey. + */ + EVP_PKEY_free(c->pkeys[i].privatekey); + c->pkeys[i].privatekey = NULL; + ERR_clear_error(); + } } } EVP_PKEY_free(pkey); X509_free(c->pkeys[i].x509); - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(x); c->pkeys[i].x509 = x; c->key = &(c->pkeys[i]); @@ -408,7 +406,7 @@ SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) int ret = 0; X509 *x = NULL; - in = BIO_new(BIO_s_file_internal()); + in = BIO_new(BIO_s_file()); if (in == NULL) { SSLerrorx(ERR_R_BUF_LIB); goto end; @@ -489,7 +487,7 @@ SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type) BIO *in; RSA *rsa = NULL; - in = BIO_new(BIO_s_file_internal()); + in = BIO_new(BIO_s_file()); if (in == NULL) { SSLerrorx(ERR_R_BUF_LIB); goto end; @@ -555,7 +553,7 @@ SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) BIO *in; EVP_PKEY *pkey = NULL; - in = BIO_new(BIO_s_file_internal()); + in = BIO_new(BIO_s_file()); if (in == NULL) { SSLerrorx(ERR_R_BUF_LIB); goto end; @@ -612,7 +610,7 @@ SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const unsigned char *d, * sent to the peer in the Certificate message. */ static int -use_certificate_chain_bio(BIO *in, CERT *cert, pem_password_cb *passwd_cb, +use_certificate_chain_bio(BIO *in, SSL_CERT *cert, pem_password_cb *passwd_cb, void *passwd_arg) { X509 *ca, *x = NULL; @@ -655,13 +653,13 @@ use_certificate_chain_bio(BIO *in, CERT *cert, pem_password_cb *passwd_cb, } int -use_certificate_chain_file(const char *file, CERT *cert, +use_certificate_chain_file(const char *file, SSL_CERT *cert, pem_password_cb *passwd_cb, void *passwd_arg) { BIO *in; int ret = 0; - in = BIO_new(BIO_s_file_internal()); + in = BIO_new(BIO_s_file()); if (in == NULL) { SSLerrorx(ERR_R_BUF_LIB); goto end; diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index 4e798e0..44c2e84 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_sess.c,v 1.105 2021/09/08 17:27:33 tb Exp $ */ +/* $OpenBSD: ssl_sess.c,v 1.109 2022/01/11 19:03:15 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -186,13 +186,13 @@ SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg) { - return (CRYPTO_set_ex_data(&s->internal->ex_data, idx, arg)); + return (CRYPTO_set_ex_data(&s->ex_data, idx, arg)); } void * SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx) { - return (CRYPTO_get_ex_data(&s->internal->ex_data, idx)); + return (CRYPTO_get_ex_data(&s->ex_data, idx)); } uint32_t @@ -221,26 +221,21 @@ SSL_SESSION_new(void) SSLerrorx(ERR_R_MALLOC_FAILURE); return (NULL); } - if ((ss->internal = calloc(1, sizeof(*ss->internal))) == NULL) { - free(ss); - SSLerrorx(ERR_R_MALLOC_FAILURE); - return (NULL); - } ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */ ss->references = 1; ss->timeout=60*5+4; /* 5 minute timeout by default */ ss->time = time(NULL); - ss->internal->prev = NULL; - ss->internal->next = NULL; + ss->prev = NULL; + ss->next = NULL; ss->tlsext_hostname = NULL; - ss->internal->tlsext_ecpointformatlist_length = 0; - ss->internal->tlsext_ecpointformatlist = NULL; - ss->internal->tlsext_supportedgroups_length = 0; - ss->internal->tlsext_supportedgroups = NULL; + ss->tlsext_ecpointformatlist_length = 0; + ss->tlsext_ecpointformatlist = NULL; + ss->tlsext_supportedgroups_length = 0; + ss->tlsext_supportedgroups = NULL; - CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->internal->ex_data); + CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); return (ss); } @@ -738,7 +733,7 @@ remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck) CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); if (ret) { - r->internal->not_resumable = 1; + r->not_resumable = 1; if (ctx->internal->remove_session_cb != NULL) ctx->internal->remove_session_cb(ctx, r); SSL_SESSION_free(r); @@ -760,23 +755,22 @@ SSL_SESSION_free(SSL_SESSION *ss) if (i > 0) return; - CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->internal->ex_data); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); explicit_bzero(ss->master_key, sizeof ss->master_key); explicit_bzero(ss->session_id, sizeof ss->session_id); - ssl_sess_cert_free(ss->internal->sess_cert); + sk_X509_pop_free(ss->cert_chain, X509_free); - X509_free(ss->peer); + X509_free(ss->peer_cert); sk_SSL_CIPHER_free(ss->ciphers); free(ss->tlsext_hostname); free(ss->tlsext_tick); - free(ss->internal->tlsext_ecpointformatlist); - free(ss->internal->tlsext_supportedgroups); + free(ss->tlsext_ecpointformatlist); + free(ss->tlsext_supportedgroups); - freezero(ss->internal, sizeof(*ss->internal)); freezero(ss, sizeof(*ss)); } @@ -883,7 +877,7 @@ SSL_SESSION_get0_cipher(const SSL_SESSION *s) X509 * SSL_SESSION_get0_peer(SSL_SESSION *s) { - return s->peer; + return s->peer_cert; } int @@ -1007,7 +1001,7 @@ timeout_doall_arg(SSL_SESSION *s, TIMEOUT_PARAM *p) * save on locking overhead */ (void)lh_SSL_SESSION_delete(p->cache, s); SSL_SESSION_list_remove(p->ctx, s); - s->internal->not_resumable = 1; + s->not_resumable = 1; if (p->ctx->internal->remove_session_cb != NULL) p->ctx->internal->remove_session_cb(p->ctx, s); SSL_SESSION_free(s); @@ -1059,50 +1053,50 @@ ssl_clear_bad_session(SSL *s) static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s) { - if ((s->internal->next == NULL) || (s->internal->prev == NULL)) + if (s->next == NULL || s->prev == NULL) return; - if (s->internal->next == (SSL_SESSION *)&(ctx->internal->session_cache_tail)) { + if (s->next == (SSL_SESSION *)&(ctx->internal->session_cache_tail)) { /* last element in list */ - if (s->internal->prev == (SSL_SESSION *)&(ctx->internal->session_cache_head)) { + if (s->prev == (SSL_SESSION *)&(ctx->internal->session_cache_head)) { /* only one element in list */ ctx->internal->session_cache_head = NULL; ctx->internal->session_cache_tail = NULL; } else { - ctx->internal->session_cache_tail = s->internal->prev; - s->internal->prev->internal->next = + ctx->internal->session_cache_tail = s->prev; + s->prev->next = (SSL_SESSION *)&(ctx->internal->session_cache_tail); } } else { - if (s->internal->prev == (SSL_SESSION *)&(ctx->internal->session_cache_head)) { + if (s->prev == (SSL_SESSION *)&(ctx->internal->session_cache_head)) { /* first element in list */ - ctx->internal->session_cache_head = s->internal->next; - s->internal->next->internal->prev = + ctx->internal->session_cache_head = s->next; + s->next->prev = (SSL_SESSION *)&(ctx->internal->session_cache_head); } else { /* middle of list */ - s->internal->next->internal->prev = s->internal->prev; - s->internal->prev->internal->next = s->internal->next; + s->next->prev = s->prev; + s->prev->next = s->next; } } - s->internal->prev = s->internal->next = NULL; + s->prev = s->next = NULL; } static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s) { - if ((s->internal->next != NULL) && (s->internal->prev != NULL)) + if (s->next != NULL && s->prev != NULL) SSL_SESSION_list_remove(ctx, s); if (ctx->internal->session_cache_head == NULL) { ctx->internal->session_cache_head = s; ctx->internal->session_cache_tail = s; - s->internal->prev = (SSL_SESSION *)&(ctx->internal->session_cache_head); - s->internal->next = (SSL_SESSION *)&(ctx->internal->session_cache_tail); + s->prev = (SSL_SESSION *)&(ctx->internal->session_cache_head); + s->next = (SSL_SESSION *)&(ctx->internal->session_cache_tail); } else { - s->internal->next = ctx->internal->session_cache_head; - s->internal->next->internal->prev = s; - s->internal->prev = (SSL_SESSION *)&(ctx->internal->session_cache_head); + s->next = ctx->internal->session_cache_head; + s->next->prev = s; + s->prev = (SSL_SESSION *)&(ctx->internal->session_cache_head); ctx->internal->session_cache_head = s; } } diff --git a/ssl/ssl_sigalgs.c b/ssl/ssl_sigalgs.c index 765f39d..daf735a 100644 --- a/ssl/ssl_sigalgs.c +++ b/ssl/ssl_sigalgs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_sigalgs.c,v 1.37 2021/06/29 19:36:14 jsing Exp $ */ +/* $OpenBSD: ssl_sigalgs.c,v 1.41 2022/02/05 14:54:10 jsing Exp $ */ /* * Copyright (c) 2018-2020 Bob Beck * Copyright (c) 2021 Joel Sing @@ -209,7 +209,7 @@ ssl_sigalg_from_value(SSL *s, uint16_t value) size_t len; int i; - ssl_sigalgs_for_version(S3I(s)->hs.negotiated_tls_version, + ssl_sigalgs_for_version(s->s3->hs.negotiated_tls_version, &values, &len); for (i = 0; i < len; i++) { @@ -246,9 +246,9 @@ static const struct ssl_sigalg * ssl_sigalg_for_legacy(SSL *s, EVP_PKEY *pkey) { /* Default signature algorithms used for TLSv1.2 and earlier. */ - switch (pkey->type) { + switch (EVP_PKEY_id(pkey)) { case EVP_PKEY_RSA: - if (S3I(s)->hs.negotiated_tls_version < TLS1_2_VERSION) + if (s->s3->hs.negotiated_tls_version < TLS1_2_VERSION) return ssl_sigalg_lookup(SIGALG_RSA_PKCS1_MD5_SHA1); return ssl_sigalg_lookup(SIGALG_RSA_PKCS1_SHA1); case EVP_PKEY_EC: @@ -259,7 +259,7 @@ ssl_sigalg_for_legacy(SSL *s, EVP_PKEY *pkey) #endif } SSLerror(s, SSL_R_UNKNOWN_PKEY_TYPE); - return (NULL); + return NULL; } static int @@ -267,17 +267,17 @@ ssl_sigalg_pkey_ok(SSL *s, const struct ssl_sigalg *sigalg, EVP_PKEY *pkey) { if (sigalg == NULL || pkey == NULL) return 0; - if (sigalg->key_type != pkey->type) + if (sigalg->key_type != EVP_PKEY_id(pkey)) return 0; /* RSA PSS must have a sufficiently large RSA key. */ if ((sigalg->flags & SIGALG_FLAG_RSA_PSS)) { - if (pkey->type != EVP_PKEY_RSA || + if (EVP_PKEY_id(pkey) != EVP_PKEY_RSA || EVP_PKEY_size(pkey) < (2 * EVP_MD_size(sigalg->md()) + 2)) return 0; } - if (S3I(s)->hs.negotiated_tls_version < TLS1_3_VERSION) + if (s->s3->hs.negotiated_tls_version < TLS1_3_VERSION) return 1; /* RSA cannot be used without PSS in TLSv1.3. */ @@ -286,7 +286,7 @@ ssl_sigalg_pkey_ok(SSL *s, const struct ssl_sigalg *sigalg, EVP_PKEY *pkey) return 0; /* Ensure that curve matches for EC keys. */ - if (pkey->type == EVP_PKEY_EC) { + if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) { if (sigalg->curve_nid == 0) return 0; if (EC_GROUP_get_curve_name(EC_KEY_get0_group( @@ -309,20 +309,20 @@ ssl_sigalg_select(SSL *s, EVP_PKEY *pkey) * RFC 5246 allows a TLS 1.2 client to send no sigalgs extension, * in which case the server must use the default. */ - if (S3I(s)->hs.negotiated_tls_version < TLS1_3_VERSION && - S3I(s)->hs.sigalgs == NULL) + if (s->s3->hs.negotiated_tls_version < TLS1_3_VERSION && + s->s3->hs.sigalgs == NULL) return ssl_sigalg_for_legacy(s, pkey); /* * If we get here, we have client or server sent sigalgs, use one. */ - CBS_init(&cbs, S3I(s)->hs.sigalgs, S3I(s)->hs.sigalgs_len); + CBS_init(&cbs, s->s3->hs.sigalgs, s->s3->hs.sigalgs_len); while (CBS_len(&cbs) > 0) { const struct ssl_sigalg *sigalg; uint16_t sigalg_value; if (!CBS_get_u16(&cbs, &sigalg_value)) - return 0; + return NULL; if ((sigalg = ssl_sigalg_from_value(s, sigalg_value)) == NULL) continue; @@ -344,11 +344,11 @@ ssl_sigalg_for_peer(SSL *s, EVP_PKEY *pkey, uint16_t sigalg_value) if ((sigalg = ssl_sigalg_from_value(s, sigalg_value)) == NULL) { SSLerror(s, SSL_R_UNKNOWN_DIGEST); - return (NULL); + return NULL; } if (!ssl_sigalg_pkey_ok(s, sigalg, pkey)) { SSLerror(s, SSL_R_WRONG_SIGNATURE_TYPE); - return (NULL); + return NULL; } return sigalg; diff --git a/ssl/ssl_srvr.c b/ssl/ssl_srvr.c index 3a37fc7..3593950 100644 --- a/ssl/ssl_srvr.c +++ b/ssl/ssl_srvr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_srvr.c,v 1.119 2021/09/03 13:18:01 jsing Exp $ */ +/* $OpenBSD: ssl_srvr.c,v 1.141 2022/02/05 14:54:10 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -183,7 +183,7 @@ ssl3_accept(SSL *s) errno = 0; if (SSL_is_dtls(s)) - listen = D1I(s)->listen; + listen = s->d1->listen; /* init things to blank */ s->internal->in_handshake++; @@ -191,15 +191,15 @@ ssl3_accept(SSL *s) SSL_clear(s); if (SSL_is_dtls(s)) - D1I(s)->listen = listen; + s->d1->listen = listen; for (;;) { - state = S3I(s)->hs.state; + state = s->s3->hs.state; - switch (S3I(s)->hs.state) { + switch (s->s3->hs.state) { case SSL_ST_RENEGOTIATE: s->internal->renegotiate = 1; - /* S3I(s)->hs.state=SSL_ST_ACCEPT; */ + /* s->s3->hs.state=SSL_ST_ACCEPT; */ case SSL_ST_BEFORE: case SSL_ST_ACCEPT: @@ -216,8 +216,8 @@ ssl3_accept(SSL *s) } if (!ssl_supported_tls_version_range(s, - &S3I(s)->hs.our_min_tls_version, - &S3I(s)->hs.our_max_tls_version)) { + &s->s3->hs.our_min_tls_version, + &s->s3->hs.our_max_tls_version)) { SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE); ret = -1; goto end; @@ -234,7 +234,7 @@ ssl3_accept(SSL *s) s->internal->init_num = 0; - if (S3I(s)->hs.state != SSL_ST_RENEGOTIATE) { + if (s->s3->hs.state != SSL_ST_RENEGOTIATE) { /* * Ok, we now need to push on a buffering BIO * so that the output is sent in a way that @@ -250,9 +250,9 @@ ssl3_accept(SSL *s) goto end; } - S3I(s)->hs.state = SSL3_ST_SR_CLNT_HELLO_A; + s->s3->hs.state = SSL3_ST_SR_CLNT_HELLO_A; s->ctx->internal->stats.sess_accept++; - } else if (!SSL_is_dtls(s) && !S3I(s)->send_connection_binding) { + } else if (!SSL_is_dtls(s) && !s->s3->send_connection_binding) { /* * Server attempting to renegotiate with * client that doesn't support secure @@ -265,11 +265,11 @@ ssl3_accept(SSL *s) goto end; } else { /* - * S3I(s)->hs.state == SSL_ST_RENEGOTIATE, + * s->s3->hs.state == SSL_ST_RENEGOTIATE, * we will just send a HelloRequest. */ s->ctx->internal->stats.sess_accept_renegotiate++; - S3I(s)->hs.state = SSL3_ST_SW_HELLO_REQ_A; + s->s3->hs.state = SSL3_ST_SW_HELLO_REQ_A; } break; @@ -284,10 +284,10 @@ ssl3_accept(SSL *s) if (ret <= 0) goto end; if (SSL_is_dtls(s)) - S3I(s)->hs.tls12.next_state = SSL3_ST_SR_CLNT_HELLO_A; + s->s3->hs.tls12.next_state = SSL3_ST_SR_CLNT_HELLO_A; else - S3I(s)->hs.tls12.next_state = SSL3_ST_SW_HELLO_REQ_C; - S3I(s)->hs.state = SSL3_ST_SW_FLUSH; + s->s3->hs.tls12.next_state = SSL3_ST_SW_HELLO_REQ_C; + s->s3->hs.state = SSL3_ST_SW_FLUSH; s->internal->init_num = 0; if (SSL_is_dtls(s)) { @@ -299,7 +299,7 @@ ssl3_accept(SSL *s) break; case SSL3_ST_SW_HELLO_REQ_C: - S3I(s)->hs.state = SSL_ST_OK; + s->s3->hs.state = SSL_ST_OK; break; case SSL3_ST_SR_CLNT_HELLO_A: @@ -314,9 +314,9 @@ ssl3_accept(SSL *s) if (ret == 1 && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) - S3I(s)->hs.state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A; + s->s3->hs.state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A; else - S3I(s)->hs.state = SSL3_ST_SW_SRVR_HELLO_A; + s->s3->hs.state = SSL3_ST_SW_SRVR_HELLO_A; s->internal->init_num = 0; @@ -330,16 +330,16 @@ ssl3_accept(SSL *s) } /* If we're just listening, stop here */ - if (listen && S3I(s)->hs.state == SSL3_ST_SW_SRVR_HELLO_A) { + if (listen && s->s3->hs.state == SSL3_ST_SW_SRVR_HELLO_A) { ret = 2; - D1I(s)->listen = 0; + s->d1->listen = 0; /* * Set expected sequence numbers to * continue the handshake. */ - D1I(s)->handshake_read_seq = 2; - D1I(s)->handshake_write_seq = 1; - D1I(s)->next_handshake_write_seq = 1; + s->d1->handshake_read_seq = 2; + s->d1->handshake_write_seq = 1; + s->d1->next_handshake_write_seq = 1; goto end; } } else { @@ -350,7 +350,7 @@ ssl3_accept(SSL *s) } s->internal->renegotiate = 2; - S3I(s)->hs.state = SSL3_ST_SW_SRVR_HELLO_A; + s->s3->hs.state = SSL3_ST_SW_SRVR_HELLO_A; s->internal->init_num = 0; } break; @@ -360,8 +360,8 @@ ssl3_accept(SSL *s) ret = ssl3_send_dtls_hello_verify_request(s); if (ret <= 0) goto end; - S3I(s)->hs.state = SSL3_ST_SW_FLUSH; - S3I(s)->hs.tls12.next_state = SSL3_ST_SR_CLNT_HELLO_A; + s->s3->hs.state = SSL3_ST_SW_FLUSH; + s->s3->hs.tls12.next_state = SSL3_ST_SR_CLNT_HELLO_A; /* HelloVerifyRequest resets Finished MAC. */ tls1_transcript_reset(s); @@ -378,11 +378,11 @@ ssl3_accept(SSL *s) goto end; if (s->internal->hit) { if (s->internal->tlsext_ticket_expected) - S3I(s)->hs.state = SSL3_ST_SW_SESSION_TICKET_A; + s->s3->hs.state = SSL3_ST_SW_SESSION_TICKET_A; else - S3I(s)->hs.state = SSL3_ST_SW_CHANGE_A; + s->s3->hs.state = SSL3_ST_SW_CHANGE_A; } else { - S3I(s)->hs.state = SSL3_ST_SW_CERT_A; + s->s3->hs.state = SSL3_ST_SW_CERT_A; } s->internal->init_num = 0; break; @@ -390,7 +390,7 @@ ssl3_accept(SSL *s) case SSL3_ST_SW_CERT_A: case SSL3_ST_SW_CERT_B: /* Check if it is anon DH or anon ECDH. */ - if (!(S3I(s)->hs.cipher->algorithm_auth & + if (!(s->s3->hs.cipher->algorithm_auth & SSL_aNULL)) { if (SSL_is_dtls(s)) dtls1_start_timer(s); @@ -398,19 +398,19 @@ ssl3_accept(SSL *s) if (ret <= 0) goto end; if (s->internal->tlsext_status_expected) - S3I(s)->hs.state = SSL3_ST_SW_CERT_STATUS_A; + s->s3->hs.state = SSL3_ST_SW_CERT_STATUS_A; else - S3I(s)->hs.state = SSL3_ST_SW_KEY_EXCH_A; + s->s3->hs.state = SSL3_ST_SW_KEY_EXCH_A; } else { skip = 1; - S3I(s)->hs.state = SSL3_ST_SW_KEY_EXCH_A; + s->s3->hs.state = SSL3_ST_SW_KEY_EXCH_A; } s->internal->init_num = 0; break; case SSL3_ST_SW_KEY_EXCH_A: case SSL3_ST_SW_KEY_EXCH_B: - alg_k = S3I(s)->hs.cipher->algorithm_mkey; + alg_k = s->s3->hs.cipher->algorithm_mkey; /* * Only send if using a DH key exchange. @@ -429,7 +429,7 @@ ssl3_accept(SSL *s) } else skip = 1; - S3I(s)->hs.state = SSL3_ST_SW_CERT_REQ_A; + s->s3->hs.state = SSL3_ST_SW_CERT_REQ_A; s->internal->init_num = 0; break; @@ -453,26 +453,26 @@ ssl3_accept(SSL *s) * s3_clnt.c accepts this for SSL 3). */ if (!(s->verify_mode & SSL_VERIFY_PEER) || - ((s->session->peer != NULL) && + ((s->session->peer_cert != NULL) && (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) || - ((S3I(s)->hs.cipher->algorithm_auth & + ((s->s3->hs.cipher->algorithm_auth & SSL_aNULL) && !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))) { /* No cert request. */ skip = 1; - S3I(s)->hs.tls12.cert_request = 0; - S3I(s)->hs.state = SSL3_ST_SW_SRVR_DONE_A; + s->s3->hs.tls12.cert_request = 0; + s->s3->hs.state = SSL3_ST_SW_SRVR_DONE_A; if (!SSL_is_dtls(s)) tls1_transcript_free(s); } else { - S3I(s)->hs.tls12.cert_request = 1; + s->s3->hs.tls12.cert_request = 1; if (SSL_is_dtls(s)) dtls1_start_timer(s); ret = ssl3_send_certificate_request(s); if (ret <= 0) goto end; - S3I(s)->hs.state = SSL3_ST_SW_SRVR_DONE_A; + s->s3->hs.state = SSL3_ST_SW_SRVR_DONE_A; s->internal->init_num = 0; } break; @@ -484,8 +484,8 @@ ssl3_accept(SSL *s) ret = ssl3_send_server_done(s); if (ret <= 0) goto end; - S3I(s)->hs.tls12.next_state = SSL3_ST_SR_CERT_A; - S3I(s)->hs.state = SSL3_ST_SW_FLUSH; + s->s3->hs.tls12.next_state = SSL3_ST_SR_CERT_A; + s->s3->hs.state = SSL3_ST_SW_FLUSH; s->internal->init_num = 0; break; @@ -506,25 +506,25 @@ ssl3_accept(SSL *s) /* If the write error was fatal, stop trying. */ if (!BIO_should_retry(s->wbio)) { s->internal->rwstate = SSL_NOTHING; - S3I(s)->hs.state = S3I(s)->hs.tls12.next_state; + s->s3->hs.state = s->s3->hs.tls12.next_state; } } ret = -1; goto end; } s->internal->rwstate = SSL_NOTHING; - S3I(s)->hs.state = S3I(s)->hs.tls12.next_state; + s->s3->hs.state = s->s3->hs.tls12.next_state; break; case SSL3_ST_SR_CERT_A: case SSL3_ST_SR_CERT_B: - if (S3I(s)->hs.tls12.cert_request) { + if (s->s3->hs.tls12.cert_request) { ret = ssl3_get_client_certificate(s); if (ret <= 0) goto end; } s->internal->init_num = 0; - S3I(s)->hs.state = SSL3_ST_SR_KEY_EXCH_A; + s->s3->hs.state = SSL3_ST_SR_KEY_EXCH_A; break; case SSL3_ST_SR_KEY_EXCH_A: @@ -534,27 +534,23 @@ ssl3_accept(SSL *s) goto end; if (SSL_is_dtls(s)) { - S3I(s)->hs.state = SSL3_ST_SR_CERT_VRFY_A; + s->s3->hs.state = SSL3_ST_SR_CERT_VRFY_A; s->internal->init_num = 0; } - alg_k = S3I(s)->hs.cipher->algorithm_mkey; - if (ret == 2) { + alg_k = s->s3->hs.cipher->algorithm_mkey; + if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) { /* - * For the ECDH ciphersuites when - * the client sends its ECDH pub key in - * a certificate, the CertificateVerify - * message is not sent. - * Also for GOST ciphersuites when - * the client uses its key from the certificate - * for key exchange. + * A GOST client may use the key from its + * certificate for key exchange, in which case + * the CertificateVerify message is not sent. */ - S3I(s)->hs.state = SSL3_ST_SR_FINISHED_A; + s->s3->hs.state = SSL3_ST_SR_FINISHED_A; s->internal->init_num = 0; } else if (SSL_USE_SIGALGS(s) || (alg_k & SSL_kGOST)) { - S3I(s)->hs.state = SSL3_ST_SR_CERT_VRFY_A; + s->s3->hs.state = SSL3_ST_SR_CERT_VRFY_A; s->internal->init_num = 0; - if (!s->session->peer) + if (!s->session->peer_cert) break; /* * Freeze the transcript for use during client @@ -562,7 +558,7 @@ ssl3_accept(SSL *s) */ tls1_transcript_freeze(s); } else { - S3I(s)->hs.state = SSL3_ST_SR_CERT_VRFY_A; + s->s3->hs.state = SSL3_ST_SR_CERT_VRFY_A; s->internal->init_num = 0; tls1_transcript_free(s); @@ -572,8 +568,8 @@ ssl3_accept(SSL *s) * a client cert, it can be verified. */ if (!tls1_transcript_hash_value(s, - S3I(s)->hs.tls12.cert_verify, - sizeof(S3I(s)->hs.tls12.cert_verify), + s->s3->hs.tls12.cert_verify, + sizeof(s->s3->hs.tls12.cert_verify), NULL)) { ret = -1; goto end; @@ -584,7 +580,7 @@ ssl3_accept(SSL *s) case SSL3_ST_SR_CERT_VRFY_A: case SSL3_ST_SR_CERT_VRFY_B: if (SSL_is_dtls(s)) - D1I(s)->change_cipher_spec_ok = 1; + s->d1->change_cipher_spec_ok = 1; else s->s3->flags |= SSL3_FLAGS_CCS_OK; @@ -592,14 +588,14 @@ ssl3_accept(SSL *s) ret = ssl3_get_cert_verify(s); if (ret <= 0) goto end; - S3I(s)->hs.state = SSL3_ST_SR_FINISHED_A; + s->s3->hs.state = SSL3_ST_SR_FINISHED_A; s->internal->init_num = 0; break; case SSL3_ST_SR_FINISHED_A: case SSL3_ST_SR_FINISHED_B: if (SSL_is_dtls(s)) - D1I(s)->change_cipher_spec_ok = 1; + s->d1->change_cipher_spec_ok = 1; else s->s3->flags |= SSL3_FLAGS_CCS_OK; ret = ssl3_get_finished(s, SSL3_ST_SR_FINISHED_A, @@ -609,11 +605,11 @@ ssl3_accept(SSL *s) if (SSL_is_dtls(s)) dtls1_stop_timer(s); if (s->internal->hit) - S3I(s)->hs.state = SSL_ST_OK; + s->s3->hs.state = SSL_ST_OK; else if (s->internal->tlsext_ticket_expected) - S3I(s)->hs.state = SSL3_ST_SW_SESSION_TICKET_A; + s->s3->hs.state = SSL3_ST_SW_SESSION_TICKET_A; else - S3I(s)->hs.state = SSL3_ST_SW_CHANGE_A; + s->s3->hs.state = SSL3_ST_SW_CHANGE_A; s->internal->init_num = 0; break; @@ -622,7 +618,7 @@ ssl3_accept(SSL *s) ret = ssl3_send_newsession_ticket(s); if (ret <= 0) goto end; - S3I(s)->hs.state = SSL3_ST_SW_CHANGE_A; + s->s3->hs.state = SSL3_ST_SW_CHANGE_A; s->internal->init_num = 0; break; @@ -631,7 +627,7 @@ ssl3_accept(SSL *s) ret = ssl3_send_cert_status(s); if (ret <= 0) goto end; - S3I(s)->hs.state = SSL3_ST_SW_KEY_EXCH_A; + s->s3->hs.state = SSL3_ST_SW_KEY_EXCH_A; s->internal->init_num = 0; break; @@ -641,9 +637,9 @@ ssl3_accept(SSL *s) SSL3_ST_SW_CHANGE_A, SSL3_ST_SW_CHANGE_B); if (ret <= 0) goto end; - S3I(s)->hs.state = SSL3_ST_SW_FINISHED_A; + s->s3->hs.state = SSL3_ST_SW_FINISHED_A; s->internal->init_num = 0; - s->session->cipher = S3I(s)->hs.cipher; + s->session->cipher = s->s3->hs.cipher; if (!tls1_setup_key_block(s)) { ret = -1; @@ -661,12 +657,12 @@ ssl3_accept(SSL *s) SSL3_ST_SW_FINISHED_B); if (ret <= 0) goto end; - S3I(s)->hs.state = SSL3_ST_SW_FLUSH; + s->s3->hs.state = SSL3_ST_SW_FLUSH; if (s->internal->hit) { - S3I(s)->hs.tls12.next_state = SSL3_ST_SR_FINISHED_A; + s->s3->hs.tls12.next_state = SSL3_ST_SR_FINISHED_A; tls1_transcript_free(s); } else - S3I(s)->hs.tls12.next_state = SSL_ST_OK; + s->s3->hs.tls12.next_state = SSL_ST_OK; s->internal->init_num = 0; break; @@ -674,7 +670,7 @@ ssl3_accept(SSL *s) /* clean a few things up */ tls1_cleanup_key_block(s); - if (S3I(s)->handshake_transcript != NULL) { + if (s->s3->handshake_transcript != NULL) { SSLerror(s, ERR_R_INTERNAL_ERROR); ret = -1; goto end; @@ -706,10 +702,10 @@ ssl3_accept(SSL *s) if (SSL_is_dtls(s)) { /* Done handshaking, next message is client hello. */ - D1I(s)->handshake_read_seq = 0; + s->d1->handshake_read_seq = 0; /* Next message is server hello. */ - D1I(s)->handshake_write_seq = 0; - D1I(s)->next_handshake_write_seq = 0; + s->d1->handshake_write_seq = 0; + s->d1->next_handshake_write_seq = 0; } goto end; /* break; */ @@ -721,18 +717,18 @@ ssl3_accept(SSL *s) /* break; */ } - if (!S3I(s)->hs.tls12.reuse_message && !skip) { + if (!s->s3->hs.tls12.reuse_message && !skip) { if (s->internal->debug) { if ((ret = BIO_flush(s->wbio)) <= 0) goto end; } - if (S3I(s)->hs.state != state) { - new_state = S3I(s)->hs.state; - S3I(s)->hs.state = state; + if (s->s3->hs.state != state) { + new_state = s->s3->hs.state; + s->s3->hs.state = state; ssl_info_callback(s, SSL_CB_ACCEPT_LOOP, 1); - S3I(s)->hs.state = new_state; + s->s3->hs.state = new_state; } } skip = 0; @@ -752,14 +748,14 @@ ssl3_send_hello_request(SSL *s) memset(&cbb, 0, sizeof(cbb)); - if (S3I(s)->hs.state == SSL3_ST_SW_HELLO_REQ_A) { + if (s->s3->hs.state == SSL3_ST_SW_HELLO_REQ_A) { if (!ssl3_handshake_msg_start(s, &cbb, &hello, SSL3_MT_HELLO_REQUEST)) goto err; if (!ssl3_handshake_msg_finish(s, &cbb)) goto err; - S3I(s)->hs.state = SSL3_ST_SW_HELLO_REQ_B; + s->s3->hs.state = SSL3_ST_SW_HELLO_REQ_B; } /* SSL3_ST_SW_HELLO_REQ_B */ @@ -779,8 +775,7 @@ ssl3_get_client_hello(SSL *s) uint16_t client_version; uint8_t comp_method; int comp_null; - int i, j, ok, al, ret = -1, cookie_valid = 0; - long n; + int i, j, al, ret, cookie_valid = 0; unsigned long id; SSL_CIPHER *c; STACK_OF(SSL_CIPHER) *ciphers = NULL; @@ -795,22 +790,22 @@ ssl3_get_client_hello(SSL *s) * If we are SSLv3, we will respond with SSLv3, even if prompted with * TLSv1. */ - if (S3I(s)->hs.state == SSL3_ST_SR_CLNT_HELLO_A) { - S3I(s)->hs.state = SSL3_ST_SR_CLNT_HELLO_B; - } + if (s->s3->hs.state == SSL3_ST_SR_CLNT_HELLO_A) + s->s3->hs.state = SSL3_ST_SR_CLNT_HELLO_B; s->internal->first_packet = 1; - n = ssl3_get_message(s, SSL3_ST_SR_CLNT_HELLO_B, + if ((ret = ssl3_get_message(s, SSL3_ST_SR_CLNT_HELLO_B, SSL3_ST_SR_CLNT_HELLO_C, SSL3_MT_CLIENT_HELLO, - SSL3_RT_MAX_PLAIN_LENGTH, &ok); - if (!ok) - return ((int)n); + SSL3_RT_MAX_PLAIN_LENGTH)) <= 0) + return ret; s->internal->first_packet = 0; - if (n < 0) + ret = -1; + + if (s->internal->init_num < 0) goto err; - CBS_init(&cbs, s->internal->init_msg, n); + CBS_init(&cbs, s->internal->init_msg, s->internal->init_num); /* Parse client hello up until the extensions (if any). */ if (!CBS_get_u16(&cbs, &client_version)) @@ -838,23 +833,23 @@ ssl3_get_client_hello(SSL *s) * (may differ: see RFC 2246, Appendix E, second paragraph) */ if (!ssl_max_shared_version(s, client_version, &shared_version)) { - if ((s->client_version >> 8) == SSL3_VERSION_MAJOR && + if ((client_version >> 8) == SSL3_VERSION_MAJOR && !tls12_record_layer_write_protected(s->internal->rl)) { /* * Similar to ssl3_get_record, send alert using remote * version number. */ - s->version = s->client_version; + s->version = client_version; } SSLerror(s, SSL_R_WRONG_VERSION_NUMBER); al = SSL_AD_PROTOCOL_VERSION; goto fatal_err; } - s->client_version = client_version; + s->s3->hs.peer_legacy_version = client_version; s->version = shared_version; - S3I(s)->hs.negotiated_tls_version = ssl_tls_version(shared_version); - if (S3I(s)->hs.negotiated_tls_version == 0) { + s->s3->hs.negotiated_tls_version = ssl_tls_version(shared_version); + if (s->s3->hs.negotiated_tls_version == 0) { SSLerror(s, ERR_R_INTERNAL_ERROR); goto err; } @@ -925,7 +920,7 @@ ssl3_get_client_hello(SSL *s) * message has not been sent - make sure that it does not cause * an overflow. */ - if (CBS_len(&cookie) > sizeof(D1I(s)->rcvd_cookie)) { + if (CBS_len(&cookie) > sizeof(s->d1->rcvd_cookie)) { al = SSL_AD_DECODE_ERROR; SSLerror(s, SSL_R_COOKIE_MISMATCH); goto fatal_err; @@ -937,21 +932,21 @@ ssl3_get_client_hello(SSL *s) size_t cookie_len; /* XXX - rcvd_cookie seems to only be used here... */ - if (!CBS_write_bytes(&cookie, D1I(s)->rcvd_cookie, - sizeof(D1I(s)->rcvd_cookie), &cookie_len)) + if (!CBS_write_bytes(&cookie, s->d1->rcvd_cookie, + sizeof(s->d1->rcvd_cookie), &cookie_len)) goto err; if (s->ctx->internal->app_verify_cookie_cb != NULL) { if (s->ctx->internal->app_verify_cookie_cb(s, - D1I(s)->rcvd_cookie, cookie_len) == 0) { + s->d1->rcvd_cookie, cookie_len) == 0) { al = SSL_AD_HANDSHAKE_FAILURE; SSLerror(s, SSL_R_COOKIE_MISMATCH); goto fatal_err; } /* else cookie verification succeeded */ /* XXX - can d1->cookie_len > sizeof(rcvd_cookie) ? */ - } else if (timingsafe_memcmp(D1I(s)->rcvd_cookie, - D1I(s)->cookie, D1I(s)->cookie_len) != 0) { + } else if (timingsafe_memcmp(s->d1->rcvd_cookie, + s->d1->cookie, s->d1->cookie_len) != 0) { /* default verification */ al = SSL_AD_HANDSHAKE_FAILURE; SSLerror(s, SSL_R_COOKIE_MISMATCH); @@ -1020,7 +1015,7 @@ ssl3_get_client_hello(SSL *s) if (CBS_len(&cbs) != 0) goto decode_err; - if (!S3I(s)->renegotiate_seen && s->internal->renegotiate) { + if (!s->s3->renegotiate_seen && s->internal->renegotiate) { al = SSL_AD_HANDSHAKE_FAILURE; SSLerror(s, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); goto fatal_err; @@ -1039,8 +1034,8 @@ ssl3_get_client_hello(SSL *s) */ arc4random_buf(s->s3->server_random, SSL3_RANDOM_SIZE); - if (S3I(s)->hs.our_max_tls_version >= TLS1_2_VERSION && - S3I(s)->hs.negotiated_tls_version < S3I(s)->hs.our_max_tls_version) { + if (s->s3->hs.our_max_tls_version >= TLS1_2_VERSION && + s->s3->hs.negotiated_tls_version < s->s3->hs.our_max_tls_version) { /* * RFC 8446 section 4.1.3. If we are downgrading from TLS 1.3 * we must set the last 8 bytes of the server random to magical @@ -1049,7 +1044,7 @@ ssl3_get_client_hello(SSL *s) */ size_t index = SSL3_RANDOM_SIZE - sizeof(tls13_downgrade_12); uint8_t *magic = &s->s3->server_random[index]; - if (S3I(s)->hs.negotiated_tls_version == TLS1_2_VERSION) { + if (s->s3->hs.negotiated_tls_version == TLS1_2_VERSION) { /* Indicate we chose to downgrade to 1.2. */ memcpy(magic, tls13_downgrade_12, sizeof(tls13_downgrade_12)); @@ -1112,15 +1107,15 @@ ssl3_get_client_hello(SSL *s) SSLerror(s, SSL_R_NO_SHARED_CIPHER); goto fatal_err; } - S3I(s)->hs.cipher = c; + s->s3->hs.cipher = c; } else { - S3I(s)->hs.cipher = s->session->cipher; + s->s3->hs.cipher = s->session->cipher; } if (!tls1_transcript_hash_init(s)) goto err; - alg_k = S3I(s)->hs.cipher->algorithm_mkey; + alg_k = s->s3->hs.cipher->algorithm_mkey; if (!(SSL_USE_SIGALGS(s) || (alg_k & SSL_kGOST)) || !(s->verify_mode & SSL_VERIFY_PEER)) tls1_transcript_free(s); @@ -1165,10 +1160,10 @@ ssl3_send_dtls_hello_verify_request(SSL *s) memset(&cbb, 0, sizeof(cbb)); - if (S3I(s)->hs.state == DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A) { + if (s->s3->hs.state == DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A) { if (s->ctx->internal->app_gen_cookie_cb == NULL || - s->ctx->internal->app_gen_cookie_cb(s, D1I(s)->cookie, - &(D1I(s)->cookie_len)) == 0) { + s->ctx->internal->app_gen_cookie_cb(s, s->d1->cookie, + &(s->d1->cookie_len)) == 0) { SSLerror(s, ERR_R_INTERNAL_ERROR); return 0; } @@ -1185,15 +1180,15 @@ ssl3_send_dtls_hello_verify_request(SSL *s) goto err; if (!CBB_add_u8_length_prefixed(&verify, &cookie)) goto err; - if (!CBB_add_bytes(&cookie, D1I(s)->cookie, D1I(s)->cookie_len)) + if (!CBB_add_bytes(&cookie, s->d1->cookie, s->d1->cookie_len)) goto err; if (!ssl3_handshake_msg_finish(s, &cbb)) goto err; - S3I(s)->hs.state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B; + s->s3->hs.state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B; } - /* S3I(s)->hs.state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B */ + /* s->s3->hs.state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B */ return (ssl3_handshake_write(s)); err: @@ -1210,7 +1205,7 @@ ssl3_send_server_hello(SSL *s) memset(&cbb, 0, sizeof(cbb)); - if (S3I(s)->hs.state == SSL3_ST_SW_SRVR_HELLO_A) { + if (s->s3->hs.state == SSL3_ST_SW_SRVR_HELLO_A) { if (!ssl3_handshake_msg_start(s, &cbb, &server_hello, SSL3_MT_SERVER_HELLO)) goto err; @@ -1255,7 +1250,7 @@ ssl3_send_server_hello(SSL *s) /* Cipher suite. */ if (!CBB_add_u16(&server_hello, - ssl3_cipher_get_value(S3I(s)->hs.cipher))) + ssl3_cipher_get_value(s->s3->hs.cipher))) goto err; /* Compression method (null). */ @@ -1288,14 +1283,14 @@ ssl3_send_server_done(SSL *s) memset(&cbb, 0, sizeof(cbb)); - if (S3I(s)->hs.state == SSL3_ST_SW_SRVR_DONE_A) { + if (s->s3->hs.state == SSL3_ST_SW_SRVR_DONE_A) { if (!ssl3_handshake_msg_start(s, &cbb, &done, SSL3_MT_SERVER_DONE)) goto err; if (!ssl3_handshake_msg_finish(s, &cbb)) goto err; - S3I(s)->hs.state = SSL3_ST_SW_SRVR_DONE_B; + s->s3->hs.state = SSL3_ST_SW_SRVR_DONE_B; } /* SSL3_ST_SW_SRVR_DONE_B */ @@ -1310,198 +1305,92 @@ ssl3_send_server_done(SSL *s) static int ssl3_send_server_kex_dhe(SSL *s, CBB *cbb) { - CBB dh_p, dh_g, dh_Ys; - DH *dh = NULL, *dhp; - unsigned char *data; - int al; + int nid = NID_dhKeyAgreement; - if (s->cert->dh_tmp_auto != 0) { - if ((dhp = ssl_get_auto_dh(s)) == NULL) { - al = SSL_AD_INTERNAL_ERROR; + tls_key_share_free(s->s3->hs.key_share); + if ((s->s3->hs.key_share = tls_key_share_new_nid(nid)) == NULL) + goto err; + + if (s->cert->dhe_params_auto != 0) { + size_t key_bits; + + if ((key_bits = ssl_dhe_params_auto_key_bits(s)) == 0) { SSLerror(s, ERR_R_INTERNAL_ERROR); - goto fatal_err; + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_INTERNAL_ERROR); + goto err; } - } else - dhp = s->cert->dh_tmp; + tls_key_share_set_key_bits(s->s3->hs.key_share, + key_bits); + } else { + DH *dh_params = s->cert->dhe_params; - if (dhp == NULL && s->cert->dh_tmp_cb != NULL) - dhp = s->cert->dh_tmp_cb(s, 0, - SSL_C_PKEYLENGTH(S3I(s)->hs.cipher)); + if (dh_params == NULL && s->cert->dhe_params_cb != NULL) + dh_params = s->cert->dhe_params_cb(s, 0, + SSL_C_PKEYLENGTH(s->s3->hs.cipher)); - if (dhp == NULL) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerror(s, SSL_R_MISSING_TMP_DH_KEY); - goto fatal_err; + if (dh_params == NULL) { + SSLerror(s, SSL_R_MISSING_TMP_DH_KEY); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_HANDSHAKE_FAILURE); + goto err; + } + + if (!tls_key_share_set_dh_params(s->s3->hs.key_share, dh_params)) + goto err; } - if (S3I(s)->tmp.dh != NULL) { - SSLerror(s, ERR_R_INTERNAL_ERROR); - goto err; - } - - if (s->cert->dh_tmp_auto != 0) { - dh = dhp; - } else if ((dh = DHparams_dup(dhp)) == NULL) { - SSLerror(s, ERR_R_DH_LIB); - goto err; - } - S3I(s)->tmp.dh = dh; - if (!DH_generate_key(dh)) { - SSLerror(s, ERR_R_DH_LIB); - goto err; - } - - /* - * Serialize the DH parameters and public key. - */ - if (!CBB_add_u16_length_prefixed(cbb, &dh_p)) - goto err; - if (!CBB_add_space(&dh_p, &data, BN_num_bytes(dh->p))) - goto err; - BN_bn2bin(dh->p, data); - - if (!CBB_add_u16_length_prefixed(cbb, &dh_g)) - goto err; - if (!CBB_add_space(&dh_g, &data, BN_num_bytes(dh->g))) - goto err; - BN_bn2bin(dh->g, data); - - if (!CBB_add_u16_length_prefixed(cbb, &dh_Ys)) - goto err; - if (!CBB_add_space(&dh_Ys, &data, BN_num_bytes(dh->pub_key))) - goto err; - BN_bn2bin(dh->pub_key, data); - - if (!CBB_flush(cbb)) + if (!tls_key_share_generate(s->s3->hs.key_share)) goto err; - return (1); - - fatal_err: - ssl3_send_alert(s, SSL3_AL_FATAL, al); - err: - return (-1); -} - -static int -ssl3_send_server_kex_ecdhe_ecp(SSL *s, int nid, CBB *cbb) -{ - uint16_t curve_id; - EC_KEY *ecdh; - CBB ecpoint; - int al; - - /* - * Only named curves are supported in ECDH ephemeral key exchanges. - * For supported named curves, curve_id is non-zero. - */ - if ((curve_id = tls1_ec_nid2curve_id(nid)) == 0) { - SSLerror(s, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); + if (!tls_key_share_params(s->s3->hs.key_share, cbb)) goto err; - } - - if (S3I(s)->tmp.ecdh != NULL) { - SSLerror(s, ERR_R_INTERNAL_ERROR); - goto err; - } - - if ((S3I(s)->tmp.ecdh = EC_KEY_new()) == NULL) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerror(s, SSL_R_MISSING_TMP_ECDH_KEY); - goto fatal_err; - } - S3I(s)->tmp.ecdh_nid = nid; - ecdh = S3I(s)->tmp.ecdh; - - if (!ssl_kex_generate_ecdhe_ecp(ecdh, nid)) + if (!tls_key_share_public(s->s3->hs.key_share, cbb)) goto err; - /* - * Encode the public key. - * - * Only named curves are supported in ECDH ephemeral key exchanges. - * In this case the ServerKeyExchange message has: - * [1 byte CurveType], [2 byte CurveName] - * [1 byte length of encoded point], followed by - * the actual encoded point itself. - */ - if (!CBB_add_u8(cbb, NAMED_CURVE_TYPE)) - goto err; - if (!CBB_add_u16(cbb, curve_id)) - goto err; - if (!CBB_add_u8_length_prefixed(cbb, &ecpoint)) - goto err; - if (!ssl_kex_public_ecdhe_ecp(ecdh, &ecpoint)) - goto err; - if (!CBB_flush(cbb)) - goto err; - - return (1); - - fatal_err: - ssl3_send_alert(s, SSL3_AL_FATAL, al); - err: - return (-1); -} - -static int -ssl3_send_server_kex_ecdhe_ecx(SSL *s, int nid, CBB *cbb) -{ - uint8_t *public_key = NULL, *private_key = NULL; - uint16_t curve_id; - CBB ecpoint; - int ret = -1; - - /* Generate an X25519 key pair. */ - if (S3I(s)->tmp.x25519 != NULL) { - SSLerror(s, ERR_R_INTERNAL_ERROR); - goto err; - } - if ((private_key = malloc(X25519_KEY_LENGTH)) == NULL) - goto err; - if ((public_key = malloc(X25519_KEY_LENGTH)) == NULL) - goto err; - X25519_keypair(public_key, private_key); - - /* Serialize public key. */ - if ((curve_id = tls1_ec_nid2curve_id(nid)) == 0) { - SSLerror(s, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); - goto err; - } - - if (!CBB_add_u8(cbb, NAMED_CURVE_TYPE)) - goto err; - if (!CBB_add_u16(cbb, curve_id)) - goto err; - if (!CBB_add_u8_length_prefixed(cbb, &ecpoint)) - goto err; - if (!CBB_add_bytes(&ecpoint, public_key, X25519_KEY_LENGTH)) - goto err; - if (!CBB_flush(cbb)) - goto err; - - S3I(s)->tmp.x25519 = private_key; - private_key = NULL; - ret = 1; + return 1; err: - free(public_key); - freezero(private_key, X25519_KEY_LENGTH); - - return (ret); + return 0; } static int ssl3_send_server_kex_ecdhe(SSL *s, CBB *cbb) { + CBB public; int nid; - nid = tls1_get_shared_curve(s); + if ((nid = tls1_get_shared_curve(s)) == NID_undef) { + SSLerror(s, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + goto err; + } - if (nid == NID_X25519) - return ssl3_send_server_kex_ecdhe_ecx(s, nid, cbb); + tls_key_share_free(s->s3->hs.key_share); + if ((s->s3->hs.key_share = tls_key_share_new_nid(nid)) == NULL) + goto err; - return ssl3_send_server_kex_ecdhe_ecp(s, nid, cbb); + if (!tls_key_share_generate(s->s3->hs.key_share)) + goto err; + + /* + * ECC key exchange - see RFC 8422, section 5.4. + */ + if (!CBB_add_u8(cbb, NAMED_CURVE_TYPE)) + goto err; + if (!CBB_add_u16(cbb, tls_key_share_group(s->s3->hs.key_share))) + goto err; + if (!CBB_add_u8_length_prefixed(cbb, &public)) + goto err; + if (!tls_key_share_public(s->s3->hs.key_share, &public)) + goto err; + if (!CBB_flush(cbb)) + goto err; + + return 1; + + err: + return 0; } int @@ -1515,7 +1404,7 @@ ssl3_send_server_key_exchange(SSL *s) size_t params_len; const EVP_MD *md = NULL; unsigned long type; - EVP_MD_CTX md_ctx; + EVP_MD_CTX *md_ctx = NULL; EVP_PKEY_CTX *pctx; EVP_PKEY *pkey; int al; @@ -1523,9 +1412,10 @@ ssl3_send_server_key_exchange(SSL *s) memset(&cbb, 0, sizeof(cbb)); memset(&cbb_params, 0, sizeof(cbb_params)); - EVP_MD_CTX_init(&md_ctx); + if ((md_ctx = EVP_MD_CTX_new()) == NULL) + goto err; - if (S3I(s)->hs.state == SSL3_ST_SW_KEY_EXCH_A) { + if (s->s3->hs.state == SSL3_ST_SW_KEY_EXCH_A) { if (!ssl3_handshake_msg_start(s, &cbb, &server_kex, SSL3_MT_SERVER_KEY_EXCHANGE)) @@ -1534,12 +1424,12 @@ ssl3_send_server_key_exchange(SSL *s) if (!CBB_init(&cbb_params, 0)) goto err; - type = S3I(s)->hs.cipher->algorithm_mkey; + type = s->s3->hs.cipher->algorithm_mkey; if (type & SSL_kDHE) { - if (ssl3_send_server_kex_dhe(s, &cbb_params) != 1) + if (!ssl3_send_server_kex_dhe(s, &cbb_params)) goto err; } else if (type & SSL_kECDHE) { - if (ssl3_send_server_kex_ecdhe(s, &cbb_params) != 1) + if (!ssl3_send_server_kex_ecdhe(s, &cbb_params)) goto err; } else { al = SSL_AD_HANDSHAKE_FAILURE; @@ -1554,13 +1444,13 @@ ssl3_send_server_key_exchange(SSL *s) goto err; /* Add signature unless anonymous. */ - if (!(S3I(s)->hs.cipher->algorithm_auth & SSL_aNULL)) { - if ((pkey = ssl_get_sign_pkey(s, S3I(s)->hs.cipher, + if (!(s->s3->hs.cipher->algorithm_auth & SSL_aNULL)) { + if ((pkey = ssl_get_sign_pkey(s, s->s3->hs.cipher, &md, &sigalg)) == NULL) { al = SSL_AD_DECODE_ERROR; goto fatal_err; } - S3I(s)->hs.our_sigalg = sigalg; + s->s3->hs.our_sigalg = sigalg; /* Send signature algorithm. */ if (SSL_USE_SIGALGS(s)) { @@ -1571,7 +1461,7 @@ ssl3_send_server_key_exchange(SSL *s) } } - if (!EVP_DigestSignInit(&md_ctx, &pctx, md, NULL, pkey)) { + if (!EVP_DigestSignInit(md_ctx, &pctx, md, NULL, pkey)) { SSLerror(s, ERR_R_EVP_LIB); goto err; } @@ -1582,21 +1472,21 @@ ssl3_send_server_key_exchange(SSL *s) SSLerror(s, ERR_R_EVP_LIB); goto err; } - if (!EVP_DigestSignUpdate(&md_ctx, s->s3->client_random, + if (!EVP_DigestSignUpdate(md_ctx, s->s3->client_random, SSL3_RANDOM_SIZE)) { SSLerror(s, ERR_R_EVP_LIB); goto err; } - if (!EVP_DigestSignUpdate(&md_ctx, s->s3->server_random, + if (!EVP_DigestSignUpdate(md_ctx, s->s3->server_random, SSL3_RANDOM_SIZE)) { SSLerror(s, ERR_R_EVP_LIB); goto err; } - if (!EVP_DigestSignUpdate(&md_ctx, params, params_len)) { + if (!EVP_DigestSignUpdate(md_ctx, params, params_len)) { SSLerror(s, ERR_R_EVP_LIB); goto err; } - if (!EVP_DigestSignFinal(&md_ctx, NULL, &signature_len) || + if (!EVP_DigestSignFinal(md_ctx, NULL, &signature_len) || !signature_len) { SSLerror(s, ERR_R_EVP_LIB); goto err; @@ -1605,7 +1495,7 @@ ssl3_send_server_key_exchange(SSL *s) SSLerror(s, ERR_R_MALLOC_FAILURE); goto err; } - if (!EVP_DigestSignFinal(&md_ctx, signature, &signature_len)) { + if (!EVP_DigestSignFinal(md_ctx, signature, &signature_len)) { SSLerror(s, ERR_R_EVP_LIB); goto err; } @@ -1621,10 +1511,10 @@ ssl3_send_server_key_exchange(SSL *s) if (!ssl3_handshake_msg_finish(s, &cbb)) goto err; - S3I(s)->hs.state = SSL3_ST_SW_KEY_EXCH_B; + s->s3->hs.state = SSL3_ST_SW_KEY_EXCH_B; } - EVP_MD_CTX_cleanup(&md_ctx); + EVP_MD_CTX_free(md_ctx); free(params); free(signature); @@ -1635,7 +1525,7 @@ ssl3_send_server_key_exchange(SSL *s) err: CBB_cleanup(&cbb_params); CBB_cleanup(&cbb); - EVP_MD_CTX_cleanup(&md_ctx); + EVP_MD_CTX_free(md_ctx); free(params); free(signature); @@ -1656,7 +1546,7 @@ ssl3_send_certificate_request(SSL *s) memset(&cbb, 0, sizeof(cbb)); - if (S3I(s)->hs.state == SSL3_ST_SW_CERT_REQ_A) { + if (s->s3->hs.state == SSL3_ST_SW_CERT_REQ_A) { if (!ssl3_handshake_msg_start(s, &cbb, &cert_request, SSL3_MT_CERTIFICATE_REQUEST)) goto err; @@ -1671,7 +1561,7 @@ ssl3_send_certificate_request(SSL *s) &sigalgs)) goto err; if (!ssl_sigalgs_build( - S3I(s)->hs.negotiated_tls_version, &sigalgs)) + s->s3->hs.negotiated_tls_version, &sigalgs)) goto err; } @@ -1697,7 +1587,7 @@ ssl3_send_certificate_request(SSL *s) if (!ssl3_handshake_msg_finish(s, &cbb)) goto err; - S3I(s)->hs.state = SSL3_ST_SW_CERT_REQ_B; + s->s3->hs.state = SSL3_ST_SW_CERT_REQ_B; } /* SSL3_ST_SW_CERT_REQ_B */ @@ -1724,18 +1614,15 @@ ssl3_get_client_kex_rsa(SSL *s, CBS *cbs) arc4random_buf(fakekey, sizeof(fakekey)); - /* XXX - peer max protocol version. */ - fakekey[0] = s->client_version >> 8; - fakekey[1] = s->client_version & 0xff; + fakekey[0] = s->s3->hs.peer_legacy_version >> 8; + fakekey[1] = s->s3->hs.peer_legacy_version & 0xff; pkey = s->cert->pkeys[SSL_PKEY_RSA].privatekey; - if ((pkey == NULL) || (pkey->type != EVP_PKEY_RSA) || - (pkey->pkey.rsa == NULL)) { + if (pkey == NULL || (rsa = EVP_PKEY_get0_RSA(pkey)) == NULL) { al = SSL_AD_HANDSHAKE_FAILURE; SSLerror(s, SSL_R_MISSING_RSA_CERTIFICATE); goto fatal_err; } - rsa = pkey->pkey.rsa; pms_len = RSA_size(rsa); if (pms_len < SSL_MAX_MASTER_KEY_LENGTH) @@ -1761,9 +1648,8 @@ ssl3_get_client_kex_rsa(SSL *s, CBS *cbs) /* SSLerror(s, SSL_R_BAD_RSA_DECRYPT); */ } - /* XXX - peer max version. */ - if ((al == -1) && !((pms[0] == (s->client_version >> 8)) && - (pms[1] == (s->client_version & 0xff)))) { + if ((al == -1) && !((pms[0] == (s->s3->hs.peer_legacy_version >> 8)) && + (pms[1] == (s->s3->hs.peer_legacy_version & 0xff)))) { /* * The premaster secret must contain the same version number * as the ClientHello to detect version rollback attacks @@ -1797,7 +1683,7 @@ ssl3_get_client_kex_rsa(SSL *s, CBS *cbs) freezero(pms, pms_len); - return (1); + return 1; decode_err: al = SSL_AD_DECODE_ERROR; @@ -1807,200 +1693,112 @@ ssl3_get_client_kex_rsa(SSL *s, CBS *cbs) err: freezero(pms, pms_len); - return (-1); + return 0; } static int ssl3_get_client_kex_dhe(SSL *s, CBS *cbs) -{ - int key_size = 0; - int key_is_invalid, key_len, al; - unsigned char *key = NULL; - BIGNUM *bn = NULL; - CBS dh_Yc; - DH *dh; - - if (!CBS_get_u16_length_prefixed(cbs, &dh_Yc)) - goto decode_err; - if (CBS_len(cbs) != 0) - goto decode_err; - - if (S3I(s)->tmp.dh == NULL) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerror(s, SSL_R_MISSING_TMP_DH_KEY); - goto fatal_err; - } - dh = S3I(s)->tmp.dh; - - if ((bn = BN_bin2bn(CBS_data(&dh_Yc), CBS_len(&dh_Yc), NULL)) == NULL) { - SSLerror(s, SSL_R_BN_LIB); - goto err; - } - - if ((key_size = DH_size(dh)) <= 0) { - SSLerror(s, ERR_R_DH_LIB); - goto err; - } - if ((key = malloc(key_size)) == NULL) { - SSLerror(s, ERR_R_MALLOC_FAILURE); - goto err; - } - if (!DH_check_pub_key(dh, bn, &key_is_invalid)) { - al = SSL_AD_INTERNAL_ERROR; - SSLerror(s, ERR_R_DH_LIB); - goto fatal_err; - } - if (key_is_invalid) { - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerror(s, ERR_R_DH_LIB); - goto fatal_err; - } - if ((key_len = DH_compute_key(key, bn, dh)) <= 0) { - al = SSL_AD_INTERNAL_ERROR; - SSLerror(s, ERR_R_DH_LIB); - goto fatal_err; - } - - if (!tls12_derive_master_secret(s, key, key_len)) - goto err; - - DH_free(S3I(s)->tmp.dh); - S3I(s)->tmp.dh = NULL; - - freezero(key, key_size); - BN_clear_free(bn); - - return (1); - - decode_err: - al = SSL_AD_DECODE_ERROR; - SSLerror(s, SSL_R_BAD_PACKET_LENGTH); - fatal_err: - ssl3_send_alert(s, SSL3_AL_FATAL, al); - err: - freezero(key, key_size); - BN_clear_free(bn); - - return (-1); -} - -static int -ssl3_get_client_kex_ecdhe_ecp(SSL *s, CBS *cbs) { uint8_t *key = NULL; size_t key_len = 0; - EC_KEY *ecdh_peer = NULL; - EC_KEY *ecdh; - CBS public; - int ret = -1; + int decode_error, invalid_key; + int ret = 0; - /* - * Use the ephemeral values we saved when generating the - * ServerKeyExchange message. - */ - if ((ecdh = S3I(s)->tmp.ecdh) == NULL) { - SSLerror(s, ERR_R_INTERNAL_ERROR); + if (s->s3->hs.key_share == NULL) { + SSLerror(s, SSL_R_MISSING_TMP_DH_KEY); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); goto err; } - /* - * Get client's public key from encoded point in the ClientKeyExchange - * message. - */ - if (!CBS_get_u8_length_prefixed(cbs, &public)) + if (!tls_key_share_peer_public(s->s3->hs.key_share, cbs, + &decode_error, &invalid_key)) { + if (decode_error) { + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + } goto err; - if (CBS_len(cbs) != 0) + } + if (invalid_key) { + SSLerror(s, SSL_R_BAD_DH_PUB_KEY_LENGTH); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); + goto err; + } + + if (!tls_key_share_derive(s->s3->hs.key_share, &key, &key_len)) goto err; - if ((ecdh_peer = EC_KEY_new()) == NULL) - goto err; - - if (!ssl_kex_peer_public_ecdhe_ecp(ecdh_peer, S3I(s)->tmp.ecdh_nid, - &public)) - goto err; - - /* Derive the shared secret and compute master secret. */ - if (!ssl_kex_derive_ecdhe_ecp(ecdh, ecdh_peer, &key, &key_len)) - goto err; if (!tls12_derive_master_secret(s, key, key_len)) goto err; - EC_KEY_free(S3I(s)->tmp.ecdh); - S3I(s)->tmp.ecdh = NULL; - S3I(s)->tmp.ecdh_nid = NID_undef; - ret = 1; err: freezero(key, key_len); - EC_KEY_free(ecdh_peer); - return (ret); -} - -static int -ssl3_get_client_kex_ecdhe_ecx(SSL *s, CBS *cbs) -{ - uint8_t *shared_key = NULL; - CBS ecpoint; - int ret = -1; - - if (!CBS_get_u8_length_prefixed(cbs, &ecpoint)) - goto err; - if (CBS_len(cbs) != 0) - goto err; - if (CBS_len(&ecpoint) != X25519_KEY_LENGTH) - goto err; - - if ((shared_key = malloc(X25519_KEY_LENGTH)) == NULL) - goto err; - if (!X25519(shared_key, S3I(s)->tmp.x25519, CBS_data(&ecpoint))) - goto err; - - freezero(S3I(s)->tmp.x25519, X25519_KEY_LENGTH); - S3I(s)->tmp.x25519 = NULL; - - if (!tls12_derive_master_secret(s, shared_key, X25519_KEY_LENGTH)) - goto err; - - ret = 1; - - err: - freezero(shared_key, X25519_KEY_LENGTH); - - return (ret); + return ret; } static int ssl3_get_client_kex_ecdhe(SSL *s, CBS *cbs) { - if (S3I(s)->tmp.x25519 != NULL) - return ssl3_get_client_kex_ecdhe_ecx(s, cbs); + uint8_t *key = NULL; + size_t key_len = 0; + int decode_error; + CBS public; + int ret = 0; - return ssl3_get_client_kex_ecdhe_ecp(s, cbs); + if (s->s3->hs.key_share == NULL) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + SSLerror(s, SSL_R_MISSING_TMP_DH_KEY); + goto err; + } + + if (!CBS_get_u8_length_prefixed(cbs, &public)) { + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + goto err; + } + if (!tls_key_share_peer_public(s->s3->hs.key_share, &public, + &decode_error, NULL)) { + if (decode_error) { + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + } + goto err; + } + + if (!tls_key_share_derive(s->s3->hs.key_share, &key, &key_len)) + goto err; + + if (!tls12_derive_master_secret(s, key, key_len)) + goto err; + + ret = 1; + + err: + freezero(key, key_len); + + return ret; } static int ssl3_get_client_kex_gost(SSL *s, CBS *cbs) { - EVP_PKEY_CTX *pkey_ctx; - EVP_PKEY *client_pub_pkey = NULL, *pk = NULL; unsigned char premaster_secret[32]; - unsigned long alg_a; - size_t outlen = 32; + EVP_PKEY_CTX *pkey_ctx = NULL; + EVP_PKEY *client_pubkey; + EVP_PKEY *pkey = NULL; + size_t outlen; CBS gostblob; - int al; - int ret = 0; /* Get our certificate private key*/ - alg_a = S3I(s)->hs.cipher->algorithm_auth; - if (alg_a & SSL_aGOST01) - pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey; + if ((s->s3->hs.cipher->algorithm_auth & SSL_aGOST01) != 0) + pkey = s->cert->pkeys[SSL_PKEY_GOST01].privatekey; - if ((pkey_ctx = EVP_PKEY_CTX_new(pk, NULL)) == NULL) + if ((pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) goto err; if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) - goto gerr; + goto err; /* * If client certificate is present and is of the same type, @@ -2009,9 +1807,8 @@ ssl3_get_client_kex_gost(SSL *s, CBS *cbs) * it is completely valid to use a client certificate for * authorization only. */ - if ((client_pub_pkey = X509_get_pubkey(s->session->peer)) != NULL) { - if (EVP_PKEY_derive_set_peer(pkey_ctx, - client_pub_pkey) <= 0) + if ((client_pubkey = X509_get0_pubkey(s->session->peer_cert)) != NULL) { + if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pubkey) <= 0) ERR_clear_error(); } @@ -2020,69 +1817,67 @@ ssl3_get_client_kex_gost(SSL *s, CBS *cbs) goto decode_err; if (CBS_len(cbs) != 0) goto decode_err; + outlen = sizeof(premaster_secret); if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, CBS_data(&gostblob), CBS_len(&gostblob)) <= 0) { SSLerror(s, SSL_R_DECRYPTION_FAILED); - goto gerr; + goto err; } - if (!tls12_derive_master_secret(s, premaster_secret, 32)) + if (!tls12_derive_master_secret(s, premaster_secret, + sizeof(premaster_secret))) goto err; /* Check if pubkey from client certificate was used */ - if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, - EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0) - ret = 2; - else - ret = 1; - gerr: - EVP_PKEY_free(client_pub_pkey); + if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, + 2, NULL) > 0) + s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY; + + explicit_bzero(premaster_secret, sizeof(premaster_secret)); EVP_PKEY_CTX_free(pkey_ctx); - if (ret) - return (ret); - else - goto err; + + return 1; decode_err: - al = SSL_AD_DECODE_ERROR; SSLerror(s, SSL_R_BAD_PACKET_LENGTH); - ssl3_send_alert(s, SSL3_AL_FATAL, al); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); err: - return (-1); + explicit_bzero(premaster_secret, sizeof(premaster_secret)); + EVP_PKEY_CTX_free(pkey_ctx); + + return 0; } int ssl3_get_client_key_exchange(SSL *s) { unsigned long alg_k; - int al, ok; + int al, ret; CBS cbs; - long n; /* 2048 maxlen is a guess. How long a key does that permit? */ - n = ssl3_get_message(s, SSL3_ST_SR_KEY_EXCH_A, - SSL3_ST_SR_KEY_EXCH_B, SSL3_MT_CLIENT_KEY_EXCHANGE, 2048, &ok); - if (!ok) - return ((int)n); + if ((ret = ssl3_get_message(s, SSL3_ST_SR_KEY_EXCH_A, + SSL3_ST_SR_KEY_EXCH_B, SSL3_MT_CLIENT_KEY_EXCHANGE, 2048)) <= 0) + return ret; - if (n < 0) + if (s->internal->init_num < 0) goto err; - CBS_init(&cbs, s->internal->init_msg, n); + CBS_init(&cbs, s->internal->init_msg, s->internal->init_num); - alg_k = S3I(s)->hs.cipher->algorithm_mkey; + alg_k = s->s3->hs.cipher->algorithm_mkey; if (alg_k & SSL_kRSA) { - if (ssl3_get_client_kex_rsa(s, &cbs) != 1) + if (!ssl3_get_client_kex_rsa(s, &cbs)) goto err; } else if (alg_k & SSL_kDHE) { - if (ssl3_get_client_kex_dhe(s, &cbs) != 1) + if (!ssl3_get_client_kex_dhe(s, &cbs)) goto err; } else if (alg_k & SSL_kECDHE) { - if (ssl3_get_client_kex_ecdhe(s, &cbs) != 1) + if (!ssl3_get_client_kex_ecdhe(s, &cbs)) goto err; } else if (alg_k & SSL_kGOST) { - if (ssl3_get_client_kex_gost(s, &cbs) != 1) + if (!ssl3_get_client_kex_gost(s, &cbs)) goto err; } else { al = SSL_AD_HANDSHAKE_FAILURE; @@ -2110,37 +1905,36 @@ ssl3_get_cert_verify(SSL *s) CBS cbs, signature; const struct ssl_sigalg *sigalg = NULL; uint16_t sigalg_value = SIGALG_NONE; - EVP_PKEY *pkey = NULL; - X509 *peer = NULL; - EVP_MD_CTX mctx; - int al, ok, verify; + EVP_PKEY *pkey; + X509 *peer_cert = NULL; + EVP_MD_CTX *mctx = NULL; + int al, verify; const unsigned char *hdata; size_t hdatalen; int type = 0; - int ret = 0; - long n; + int ret; - EVP_MD_CTX_init(&mctx); + if ((ret = ssl3_get_message(s, SSL3_ST_SR_CERT_VRFY_A, + SSL3_ST_SR_CERT_VRFY_B, -1, SSL3_RT_MAX_PLAIN_LENGTH)) <= 0) + return ret; - n = ssl3_get_message(s, SSL3_ST_SR_CERT_VRFY_A, - SSL3_ST_SR_CERT_VRFY_B, -1, SSL3_RT_MAX_PLAIN_LENGTH, &ok); - if (!ok) - return ((int)n); + ret = 0; - if (n < 0) + if (s->internal->init_num < 0) goto err; - CBS_init(&cbs, s->internal->init_msg, n); + if ((mctx = EVP_MD_CTX_new()) == NULL) + goto err; - if (s->session->peer != NULL) { - peer = s->session->peer; - pkey = X509_get_pubkey(peer); - type = X509_certificate_type(peer, pkey); - } + CBS_init(&cbs, s->internal->init_msg, s->internal->init_num); - if (S3I(s)->hs.tls12.message_type != SSL3_MT_CERTIFICATE_VERIFY) { - S3I(s)->hs.tls12.reuse_message = 1; - if (peer != NULL) { + peer_cert = s->session->peer_cert; + pkey = X509_get0_pubkey(peer_cert); + type = X509_certificate_type(peer_cert, pkey); + + if (s->s3->hs.tls12.message_type != SSL3_MT_CERTIFICATE_VERIFY) { + s->s3->hs.tls12.reuse_message = 1; + if (peer_cert != NULL) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerror(s, SSL_R_MISSING_VERIFY_MESSAGE); goto fatal_err; @@ -2149,7 +1943,7 @@ ssl3_get_cert_verify(SSL *s) goto end; } - if (peer == NULL) { + if (peer_cert == NULL) { SSLerror(s, SSL_R_NO_CLIENT_CERT_RECEIVED); al = SSL_AD_UNEXPECTED_MESSAGE; goto fatal_err; @@ -2161,7 +1955,7 @@ ssl3_get_cert_verify(SSL *s) goto fatal_err; } - if (S3I(s)->change_cipher_spec) { + if (s->s3->change_cipher_spec) { SSLerror(s, SSL_R_CCS_RECEIVED_EARLY); al = SSL_AD_UNEXPECTED_MESSAGE; goto fatal_err; @@ -2190,7 +1984,7 @@ ssl3_get_cert_verify(SSL *s) al = SSL_AD_DECODE_ERROR; goto fatal_err; } - S3I(s)->hs.peer_sigalg = sigalg; + s->s3->hs.peer_sigalg = sigalg; if (SSL_USE_SIGALGS(s)) { EVP_PKEY_CTX *pctx; @@ -2200,7 +1994,7 @@ ssl3_get_cert_verify(SSL *s) al = SSL_AD_INTERNAL_ERROR; goto fatal_err; } - if (!EVP_DigestVerifyInit(&mctx, &pctx, sigalg->md(), + if (!EVP_DigestVerifyInit(mctx, &pctx, sigalg->md(), NULL, pkey)) { SSLerror(s, ERR_R_EVP_LIB); al = SSL_AD_INTERNAL_ERROR; @@ -2220,21 +2014,28 @@ ssl3_get_cert_verify(SSL *s) al = SSL_AD_INTERNAL_ERROR; goto fatal_err; } - if (!EVP_DigestVerifyUpdate(&mctx, hdata, hdatalen)) { + if (!EVP_DigestVerifyUpdate(mctx, hdata, hdatalen)) { SSLerror(s, ERR_R_EVP_LIB); al = SSL_AD_INTERNAL_ERROR; goto fatal_err; } - if (EVP_DigestVerifyFinal(&mctx, CBS_data(&signature), + if (EVP_DigestVerifyFinal(mctx, CBS_data(&signature), CBS_len(&signature)) <= 0) { al = SSL_AD_DECRYPT_ERROR; SSLerror(s, SSL_R_BAD_SIGNATURE); goto fatal_err; } - } else if (pkey->type == EVP_PKEY_RSA) { - verify = RSA_verify(NID_md5_sha1, S3I(s)->hs.tls12.cert_verify, + } else if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) { + RSA *rsa; + + if ((rsa = EVP_PKEY_get0_RSA(pkey)) == NULL) { + al = SSL_AD_INTERNAL_ERROR; + SSLerror(s, ERR_R_EVP_LIB); + goto fatal_err; + } + verify = RSA_verify(NID_md5_sha1, s->s3->hs.tls12.cert_verify, MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, CBS_data(&signature), - CBS_len(&signature), pkey->pkey.rsa); + CBS_len(&signature), rsa); if (verify < 0) { al = SSL_AD_DECRYPT_ERROR; SSLerror(s, SSL_R_BAD_RSA_DECRYPT); @@ -2245,19 +2046,26 @@ ssl3_get_cert_verify(SSL *s) SSLerror(s, SSL_R_BAD_RSA_SIGNATURE); goto fatal_err; } - } else if (pkey->type == EVP_PKEY_EC) { - verify = ECDSA_verify(pkey->save_type, - &(S3I(s)->hs.tls12.cert_verify[MD5_DIGEST_LENGTH]), + } else if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) { + EC_KEY *eckey; + + if ((eckey = EVP_PKEY_get0_EC_KEY(pkey)) == NULL) { + al = SSL_AD_INTERNAL_ERROR; + SSLerror(s, ERR_R_EVP_LIB); + goto fatal_err; + } + verify = ECDSA_verify(0, + &(s->s3->hs.tls12.cert_verify[MD5_DIGEST_LENGTH]), SHA_DIGEST_LENGTH, CBS_data(&signature), - CBS_len(&signature), pkey->pkey.ec); + CBS_len(&signature), eckey); if (verify <= 0) { al = SSL_AD_DECRYPT_ERROR; SSLerror(s, SSL_R_BAD_ECDSA_SIGNATURE); goto fatal_err; } #ifndef OPENSSL_NO_GOST - } else if (pkey->type == NID_id_GostR3410_94 || - pkey->type == NID_id_GostR3410_2001) { + } else if (EVP_PKEY_id(pkey) == NID_id_GostR3410_94 || + EVP_PKEY_id(pkey) == NID_id_GostR3410_2001) { unsigned char sigbuf[128]; unsigned int siglen = sizeof(sigbuf); EVP_PKEY_CTX *pctx; @@ -2280,9 +2088,9 @@ ssl3_get_cert_verify(SSL *s) al = SSL_AD_INTERNAL_ERROR; goto fatal_err; } - if (!EVP_DigestInit_ex(&mctx, md, NULL) || - !EVP_DigestUpdate(&mctx, hdata, hdatalen) || - !EVP_DigestFinal(&mctx, sigbuf, &siglen) || + if (!EVP_DigestInit_ex(mctx, md, NULL) || + !EVP_DigestUpdate(mctx, hdata, hdatalen) || + !EVP_DigestFinal(mctx, sigbuf, &siglen) || (EVP_PKEY_verify_init(pctx) <= 0) || (EVP_PKEY_CTX_set_signature_md(pctx, md) <= 0) || (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_VERIFY, @@ -2320,8 +2128,8 @@ ssl3_get_cert_verify(SSL *s) end: tls1_transcript_free(s); err: - EVP_MD_CTX_cleanup(&mctx); - EVP_PKEY_free(pkey); + EVP_MD_CTX_free(mctx); + return (ret); } @@ -2329,18 +2137,18 @@ int ssl3_get_client_certificate(SSL *s) { CBS cbs, client_certs; - int i, ok, al, ret = -1; X509 *x = NULL; - long n; const unsigned char *q; STACK_OF(X509) *sk = NULL; + int i, al, ret; - n = ssl3_get_message(s, SSL3_ST_SR_CERT_A, SSL3_ST_SR_CERT_B, - -1, s->internal->max_cert_list, &ok); - if (!ok) - return ((int)n); + if ((ret = ssl3_get_message(s, SSL3_ST_SR_CERT_A, SSL3_ST_SR_CERT_B, + -1, s->internal->max_cert_list)) <= 0) + return ret; - if (S3I(s)->hs.tls12.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE) { + ret = -1; + + if (s->s3->hs.tls12.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE) { if ((s->verify_mode & SSL_VERIFY_PEER) && (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) { SSLerror(s, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); @@ -2351,26 +2159,26 @@ ssl3_get_client_certificate(SSL *s) * If tls asked for a client cert, * the client must return a 0 list. */ - if (S3I(s)->hs.tls12.cert_request) { + if (s->s3->hs.tls12.cert_request) { SSLerror(s, SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST ); al = SSL_AD_UNEXPECTED_MESSAGE; goto fatal_err; } - S3I(s)->hs.tls12.reuse_message = 1; + s->s3->hs.tls12.reuse_message = 1; return (1); } - if (S3I(s)->hs.tls12.message_type != SSL3_MT_CERTIFICATE) { + if (s->s3->hs.tls12.message_type != SSL3_MT_CERTIFICATE) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerror(s, SSL_R_WRONG_MESSAGE_TYPE); goto fatal_err; } - if (n < 0) + if (s->internal->init_num < 0) goto decode_err; - CBS_init(&cbs, s->internal->init_msg, n); + CBS_init(&cbs, s->internal->init_msg, s->internal->init_num); if ((sk = sk_X509_new_null()) == NULL) { SSLerror(s, ERR_R_MALLOC_FAILURE); @@ -2430,31 +2238,19 @@ ssl3_get_client_certificate(SSL *s) } } - X509_free(s->session->peer); - s->session->peer = sk_X509_shift(sk); - s->session->verify_result = s->verify_result; - - /* - * With the current implementation, sess_cert will always be NULL - * when we arrive here - */ - if (SSI(s)->sess_cert == NULL) { - SSI(s)->sess_cert = ssl_sess_cert_new(); - if (SSI(s)->sess_cert == NULL) { - SSLerror(s, ERR_R_MALLOC_FAILURE); - goto err; - } - } - sk_X509_pop_free(SSI(s)->sess_cert->cert_chain, X509_free); - SSI(s)->sess_cert->cert_chain = sk; + X509_free(s->session->peer_cert); + s->session->peer_cert = sk_X509_shift(sk); /* * Inconsistency alert: cert_chain does *not* include the * peer's own certificate, while we do include it in s3_clnt.c */ - + sk_X509_pop_free(s->session->cert_chain, X509_free); + s->session->cert_chain = sk; sk = NULL; + s->session->verify_result = s->verify_result; + ret = 1; if (0) { decode_err: @@ -2474,7 +2270,7 @@ int ssl3_send_server_certificate(SSL *s) { CBB cbb, server_cert; - CERT_PKEY *cpk; + SSL_CERT_PKEY *cpk; /* * Server Certificate - RFC 5246, section 7.4.2. @@ -2482,7 +2278,7 @@ ssl3_send_server_certificate(SSL *s) memset(&cbb, 0, sizeof(cbb)); - if (S3I(s)->hs.state == SSL3_ST_SW_CERT_A) { + if (s->s3->hs.state == SSL3_ST_SW_CERT_A) { if ((cpk = ssl_get_server_send_pkey(s)) == NULL) { SSLerror(s, ERR_R_INTERNAL_ERROR); return (0); @@ -2496,7 +2292,7 @@ ssl3_send_server_certificate(SSL *s) if (!ssl3_handshake_msg_finish(s, &cbb)) goto err; - S3I(s)->hs.state = SSL3_ST_SW_CERT_B; + s->s3->hs.state = SSL3_ST_SW_CERT_B; } /* SSL3_ST_SW_CERT_B */ @@ -2521,20 +2317,22 @@ ssl3_send_newsession_ticket(SSL *s) unsigned char key_name[16]; unsigned char *hmac; unsigned int hlen; - EVP_CIPHER_CTX ctx; - HMAC_CTX hctx; + EVP_CIPHER_CTX *ctx = NULL; + HMAC_CTX *hctx = NULL; int len; /* * New Session Ticket - RFC 5077, section 3.3. */ - EVP_CIPHER_CTX_init(&ctx); - HMAC_CTX_init(&hctx); - memset(&cbb, 0, sizeof(cbb)); - if (S3I(s)->hs.state == SSL3_ST_SW_SESSION_TICKET_A) { + if ((ctx = EVP_CIPHER_CTX_new()) == NULL) + goto err; + if ((hctx = HMAC_CTX_new()) == NULL) + goto err; + + if (s->s3->hs.state == SSL3_ST_SW_SESSION_TICKET_A) { if (!ssl3_handshake_msg_start(s, &cbb, &session_ticket, SSL3_MT_NEWSESSION_TICKET)) goto err; @@ -2551,15 +2349,13 @@ ssl3_send_newsession_ticket(SSL *s) */ if (tctx->internal->tlsext_ticket_key_cb != NULL) { if (tctx->internal->tlsext_ticket_key_cb(s, - key_name, iv, &ctx, &hctx, 1) < 0) { - EVP_CIPHER_CTX_cleanup(&ctx); + key_name, iv, ctx, hctx, 1) < 0) goto err; - } } else { arc4random_buf(iv, 16); - EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, + EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, tctx->internal->tlsext_tick_aes_key, iv); - HMAC_Init_ex(&hctx, tctx->internal->tlsext_tick_hmac_key, + HMAC_Init_ex(hctx, tctx->internal->tlsext_tick_hmac_key, 16, EVP_sha256(), NULL); memcpy(key_name, tctx->internal->tlsext_tick_key_name, 16); } @@ -2569,11 +2365,11 @@ ssl3_send_newsession_ticket(SSL *s) if ((enc_session = calloc(1, enc_session_max_len)) == NULL) goto err; enc_session_len = 0; - if (!EVP_EncryptUpdate(&ctx, enc_session, &len, session, + if (!EVP_EncryptUpdate(ctx, enc_session, &len, session, session_len)) goto err; enc_session_len += len; - if (!EVP_EncryptFinal_ex(&ctx, enc_session + enc_session_len, + if (!EVP_EncryptFinal_ex(ctx, enc_session + enc_session_len, &len)) goto err; enc_session_len += len; @@ -2582,14 +2378,14 @@ ssl3_send_newsession_ticket(SSL *s) goto err; /* Generate the HMAC. */ - if (!HMAC_Update(&hctx, key_name, sizeof(key_name))) + if (!HMAC_Update(hctx, key_name, sizeof(key_name))) goto err; - if (!HMAC_Update(&hctx, iv, EVP_CIPHER_CTX_iv_length(&ctx))) + if (!HMAC_Update(hctx, iv, EVP_CIPHER_CTX_iv_length(ctx))) goto err; - if (!HMAC_Update(&hctx, enc_session, enc_session_len)) + if (!HMAC_Update(hctx, enc_session, enc_session_len)) goto err; - if ((hmac_len = HMAC_size(&hctx)) <= 0) + if ((hmac_len = HMAC_size(hctx)) <= 0) goto err; /* @@ -2606,14 +2402,14 @@ ssl3_send_newsession_ticket(SSL *s) goto err; if (!CBB_add_bytes(&ticket, key_name, sizeof(key_name))) goto err; - if (!CBB_add_bytes(&ticket, iv, EVP_CIPHER_CTX_iv_length(&ctx))) + if (!CBB_add_bytes(&ticket, iv, EVP_CIPHER_CTX_iv_length(ctx))) goto err; if (!CBB_add_bytes(&ticket, enc_session, enc_session_len)) goto err; if (!CBB_add_space(&ticket, &hmac, hmac_len)) goto err; - if (!HMAC_Final(&hctx, hmac, &hlen)) + if (!HMAC_Final(hctx, hmac, &hlen)) goto err; if (hlen != hmac_len) goto err; @@ -2621,11 +2417,11 @@ ssl3_send_newsession_ticket(SSL *s) if (!ssl3_handshake_msg_finish(s, &cbb)) goto err; - S3I(s)->hs.state = SSL3_ST_SW_SESSION_TICKET_B; + s->s3->hs.state = SSL3_ST_SW_SESSION_TICKET_B; } - EVP_CIPHER_CTX_cleanup(&ctx); - HMAC_CTX_cleanup(&hctx); + EVP_CIPHER_CTX_free(ctx); + HMAC_CTX_free(hctx); freezero(session, session_len); free(enc_session); @@ -2634,8 +2430,8 @@ ssl3_send_newsession_ticket(SSL *s) err: CBB_cleanup(&cbb); - EVP_CIPHER_CTX_cleanup(&ctx); - HMAC_CTX_cleanup(&hctx); + EVP_CIPHER_CTX_free(ctx); + HMAC_CTX_free(hctx); freezero(session, session_len); free(enc_session); @@ -2649,7 +2445,7 @@ ssl3_send_cert_status(SSL *s) memset(&cbb, 0, sizeof(cbb)); - if (S3I(s)->hs.state == SSL3_ST_SW_CERT_STATUS_A) { + if (s->s3->hs.state == SSL3_ST_SW_CERT_STATUS_A) { if (!ssl3_handshake_msg_start(s, &cbb, &certstatus, SSL3_MT_CERTIFICATE_STATUS)) goto err; @@ -2663,7 +2459,7 @@ ssl3_send_cert_status(SSL *s) if (!ssl3_handshake_msg_finish(s, &cbb)) goto err; - S3I(s)->hs.state = SSL3_ST_SW_CERT_STATUS_B; + s->s3->hs.state = SSL3_ST_SW_CERT_STATUS_B; } /* SSL3_ST_SW_CERT_STATUS_B */ diff --git a/ssl/ssl_stat.c b/ssl/ssl_stat.c index b51538c..5d35528 100644 --- a/ssl/ssl_stat.c +++ b/ssl/ssl_stat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_stat.c,v 1.17 2021/06/13 15:51:10 jsing Exp $ */ +/* $OpenBSD: ssl_stat.c,v 1.18 2022/02/05 14:54:10 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -91,7 +91,7 @@ SSL_state_string_long(const SSL *s) { const char *str; - switch (S3I(s)->hs.state) { + switch (s->s3->hs.state) { case SSL_ST_BEFORE: str = "before SSL initialization"; break; @@ -347,7 +347,7 @@ SSL_state_string(const SSL *s) { const char *str; - switch (S3I(s)->hs.state) { + switch (s->s3->hs.state) { case SSL_ST_BEFORE: str = "PINIT "; break; diff --git a/ssl/ssl_tlsext.c b/ssl/ssl_tlsext.c index 3ad5649..f93f44c 100644 --- a/ssl/ssl_tlsext.c +++ b/ssl/ssl_tlsext.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_tlsext.c,v 1.99 2021/09/10 09:25:29 tb Exp $ */ +/* $OpenBSD: ssl_tlsext.c,v 1.110 2022/02/05 14:54:10 jsing Exp $ */ /* * Copyright (c) 2016, 2017, 2019 Joel Sing * Copyright (c) 2017 Doug Hogan @@ -17,6 +17,11 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include + +#include +#include + #include #include @@ -36,7 +41,7 @@ tlsext_alpn_client_needs(SSL *s, uint16_t msg_type) { /* ALPN protos have been specified and this is the initial handshake */ return s->internal->alpn_client_proto_list != NULL && - S3I(s)->hs.finished_len == 0; + s->s3->hs.finished_len == 0; } int @@ -96,14 +101,14 @@ tlsext_alpn_server_parse(SSL *s, uint16_t msg_types, CBS *cbs, int *alert) s->ctx->internal->alpn_select_cb_arg); if (r == SSL_TLSEXT_ERR_OK) { - free(S3I(s)->alpn_selected); - if ((S3I(s)->alpn_selected = malloc(selected_len)) == NULL) { - S3I(s)->alpn_selected_len = 0; + free(s->s3->alpn_selected); + if ((s->s3->alpn_selected = malloc(selected_len)) == NULL) { + s->s3->alpn_selected_len = 0; *alert = SSL_AD_INTERNAL_ERROR; return 0; } - memcpy(S3I(s)->alpn_selected, selected, selected_len); - S3I(s)->alpn_selected_len = selected_len; + memcpy(s->s3->alpn_selected, selected, selected_len); + s->s3->alpn_selected_len = selected_len; return 1; } @@ -125,7 +130,7 @@ tlsext_alpn_server_parse(SSL *s, uint16_t msg_types, CBS *cbs, int *alert) int tlsext_alpn_server_needs(SSL *s, uint16_t msg_type) { - return S3I(s)->alpn_selected != NULL; + return s->s3->alpn_selected != NULL; } int @@ -139,8 +144,8 @@ tlsext_alpn_server_build(SSL *s, uint16_t msg_type, CBB *cbb) if (!CBB_add_u8_length_prefixed(&list, &selected)) return 0; - if (!CBB_add_bytes(&selected, S3I(s)->alpn_selected, - S3I(s)->alpn_selected_len)) + if (!CBB_add_bytes(&selected, s->s3->alpn_selected, + s->s3->alpn_selected_len)) return 0; if (!CBB_flush(cbb)) @@ -172,8 +177,8 @@ tlsext_alpn_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) if (CBS_len(&proto) == 0) goto err; - if (!CBS_stow(&proto, &(S3I(s)->alpn_selected), - &(S3I(s)->alpn_selected_len))) + if (!CBS_stow(&proto, &(s->s3->alpn_selected), + &(s->s3->alpn_selected_len))) goto err; return 1; @@ -190,7 +195,7 @@ int tlsext_supportedgroups_client_needs(SSL *s, uint16_t msg_type) { return ssl_has_ecc_ciphers(s) || - (S3I(s)->hs.our_max_tls_version >= TLS1_3_VERSION); + (s->s3->hs.our_max_tls_version >= TLS1_3_VERSION); } int @@ -242,8 +247,8 @@ tlsext_supportedgroups_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, uint16_t *groups; int i; - if (S3I(s)->hs.tls13.hrr) { - if (SSI(s)->tlsext_supportedgroups == NULL) { + if (s->s3->hs.tls13.hrr) { + if (s->session->tlsext_supportedgroups == NULL) { *alert = SSL_AD_HANDSHAKE_FAILURE; return 0; } @@ -251,7 +256,7 @@ tlsext_supportedgroups_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, * In the case of TLSv1.3 the client cannot change * the supported groups. */ - if (groups_len != SSI(s)->tlsext_supportedgroups_length) { + if (groups_len != s->session->tlsext_supportedgroups_length) { *alert = SSL_AD_ILLEGAL_PARAMETER; return 0; } @@ -260,7 +265,7 @@ tlsext_supportedgroups_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, if (!CBS_get_u16(&grouplist, &group)) goto err; - if (SSI(s)->tlsext_supportedgroups[i] != group) { + if (s->session->tlsext_supportedgroups[i] != group) { *alert = SSL_AD_ILLEGAL_PARAMETER; return 0; } @@ -269,7 +274,7 @@ tlsext_supportedgroups_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, return 1; } - if (SSI(s)->tlsext_supportedgroups != NULL) + if (s->session->tlsext_supportedgroups != NULL) goto err; if ((groups = reallocarray(NULL, groups_len, @@ -290,8 +295,8 @@ tlsext_supportedgroups_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, goto err; } - SSI(s)->tlsext_supportedgroups = groups; - SSI(s)->tlsext_supportedgroups_length = groups_len; + s->session->tlsext_supportedgroups = groups; + s->session->tlsext_supportedgroups_length = groups_len; } return 1; @@ -383,8 +388,8 @@ tlsext_ecpf_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) } if (!s->internal->hit) { - if (!CBS_stow(&ecpf, &(SSI(s)->tlsext_ecpointformatlist), - &(SSI(s)->tlsext_ecpointformatlist_length))) { + if (!CBS_stow(&ecpf, &(s->session->tlsext_ecpointformatlist), + &(s->session->tlsext_ecpointformatlist_length))) { *alert = SSL_AD_INTERNAL_ERROR; return 0; } @@ -445,8 +450,8 @@ tlsext_ri_client_build(SSL *s, uint16_t msg_type, CBB *cbb) if (!CBB_add_u8_length_prefixed(cbb, &reneg)) return 0; - if (!CBB_add_bytes(&reneg, S3I(s)->previous_client_finished, - S3I(s)->previous_client_finished_len)) + if (!CBB_add_bytes(&reneg, s->s3->previous_client_finished, + s->s3->previous_client_finished_len)) return 0; if (!CBB_flush(cbb)) return 0; @@ -464,15 +469,15 @@ tlsext_ri_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) if (CBS_len(cbs) != 0) goto err; - if (!CBS_mem_equal(&reneg, S3I(s)->previous_client_finished, - S3I(s)->previous_client_finished_len)) { + if (!CBS_mem_equal(&reneg, s->s3->previous_client_finished, + s->s3->previous_client_finished_len)) { SSLerror(s, SSL_R_RENEGOTIATION_MISMATCH); *alert = SSL_AD_HANDSHAKE_FAILURE; return 0; } - S3I(s)->renegotiate_seen = 1; - S3I(s)->send_connection_binding = 1; + s->s3->renegotiate_seen = 1; + s->s3->send_connection_binding = 1; return 1; @@ -485,8 +490,8 @@ tlsext_ri_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) int tlsext_ri_server_needs(SSL *s, uint16_t msg_type) { - return (S3I(s)->hs.negotiated_tls_version < TLS1_3_VERSION && - S3I(s)->send_connection_binding); + return (s->s3->hs.negotiated_tls_version < TLS1_3_VERSION && + s->s3->send_connection_binding); } int @@ -496,11 +501,11 @@ tlsext_ri_server_build(SSL *s, uint16_t msg_type, CBB *cbb) if (!CBB_add_u8_length_prefixed(cbb, &reneg)) return 0; - if (!CBB_add_bytes(&reneg, S3I(s)->previous_client_finished, - S3I(s)->previous_client_finished_len)) + if (!CBB_add_bytes(&reneg, s->s3->previous_client_finished, + s->s3->previous_client_finished_len)) return 0; - if (!CBB_add_bytes(&reneg, S3I(s)->previous_server_finished, - S3I(s)->previous_server_finished_len)) + if (!CBB_add_bytes(&reneg, s->s3->previous_server_finished, + s->s3->previous_server_finished_len)) return 0; if (!CBB_flush(cbb)) return 0; @@ -517,10 +522,10 @@ tlsext_ri_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) * Ensure that the previous client and server values are both not * present, or that they are both present. */ - if ((S3I(s)->previous_client_finished_len == 0 && - S3I(s)->previous_server_finished_len != 0) || - (S3I(s)->previous_client_finished_len != 0 && - S3I(s)->previous_server_finished_len == 0)) { + if ((s->s3->previous_client_finished_len == 0 && + s->s3->previous_server_finished_len != 0) || + (s->s3->previous_client_finished_len != 0 && + s->s3->previous_server_finished_len == 0)) { *alert = SSL_AD_INTERNAL_ERROR; return 0; } @@ -528,31 +533,31 @@ tlsext_ri_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) if (!CBS_get_u8_length_prefixed(cbs, &reneg)) goto err; if (!CBS_get_bytes(&reneg, &prev_client, - S3I(s)->previous_client_finished_len)) + s->s3->previous_client_finished_len)) goto err; if (!CBS_get_bytes(&reneg, &prev_server, - S3I(s)->previous_server_finished_len)) + s->s3->previous_server_finished_len)) goto err; if (CBS_len(&reneg) != 0) goto err; if (CBS_len(cbs) != 0) goto err; - if (!CBS_mem_equal(&prev_client, S3I(s)->previous_client_finished, - S3I(s)->previous_client_finished_len)) { + if (!CBS_mem_equal(&prev_client, s->s3->previous_client_finished, + s->s3->previous_client_finished_len)) { SSLerror(s, SSL_R_RENEGOTIATION_MISMATCH); *alert = SSL_AD_HANDSHAKE_FAILURE; return 0; } - if (!CBS_mem_equal(&prev_server, S3I(s)->previous_server_finished, - S3I(s)->previous_server_finished_len)) { + if (!CBS_mem_equal(&prev_server, s->s3->previous_server_finished, + s->s3->previous_server_finished_len)) { SSLerror(s, SSL_R_RENEGOTIATION_MISMATCH); *alert = SSL_AD_HANDSHAKE_FAILURE; return 0; } - S3I(s)->renegotiate_seen = 1; - S3I(s)->send_connection_binding = 1; + s->s3->renegotiate_seen = 1; + s->s3->send_connection_binding = 1; return 1; @@ -568,17 +573,17 @@ tlsext_ri_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) int tlsext_sigalgs_client_needs(SSL *s, uint16_t msg_type) { - return (S3I(s)->hs.our_max_tls_version >= TLS1_2_VERSION); + return (s->s3->hs.our_max_tls_version >= TLS1_2_VERSION); } int tlsext_sigalgs_client_build(SSL *s, uint16_t msg_type, CBB *cbb) { - uint16_t tls_version = S3I(s)->hs.negotiated_tls_version; + uint16_t tls_version = s->s3->hs.negotiated_tls_version; CBB sigalgs; if (msg_type == SSL_TLSEXT_MSG_CH) - tls_version = S3I(s)->hs.our_min_tls_version; + tls_version = s->s3->hs.our_min_tls_version; if (!CBB_add_u16_length_prefixed(cbb, &sigalgs)) return 0; @@ -599,7 +604,7 @@ tlsext_sigalgs_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) return 0; if (CBS_len(&sigalgs) % 2 != 0 || CBS_len(&sigalgs) > 64) return 0; - if (!CBS_stow(&sigalgs, &S3I(s)->hs.sigalgs, &S3I(s)->hs.sigalgs_len)) + if (!CBS_stow(&sigalgs, &s->s3->hs.sigalgs, &s->s3->hs.sigalgs_len)) return 0; return 1; @@ -608,7 +613,7 @@ tlsext_sigalgs_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) int tlsext_sigalgs_server_needs(SSL *s, uint16_t msg_type) { - return (S3I(s)->hs.negotiated_tls_version >= TLS1_3_VERSION); + return (s->s3->hs.negotiated_tls_version >= TLS1_3_VERSION); } int @@ -618,7 +623,7 @@ tlsext_sigalgs_server_build(SSL *s, uint16_t msg_type, CBB *cbb) if (!CBB_add_u16_length_prefixed(cbb, &sigalgs)) return 0; - if (!ssl_sigalgs_build(S3I(s)->hs.negotiated_tls_version, &sigalgs)) + if (!ssl_sigalgs_build(s->s3->hs.negotiated_tls_version, &sigalgs)) return 0; if (!CBB_flush(cbb)) return 0; @@ -638,7 +643,7 @@ tlsext_sigalgs_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) return 0; if (CBS_len(&sigalgs) % 2 != 0 || CBS_len(&sigalgs) > 64) return 0; - if (!CBS_stow(&sigalgs, &S3I(s)->hs.sigalgs, &S3I(s)->hs.sigalgs_len)) + if (!CBS_stow(&sigalgs, &s->s3->hs.sigalgs, &s->s3->hs.sigalgs_len)) return 0; return 1; @@ -673,6 +678,29 @@ tlsext_sni_client_build(SSL *s, uint16_t msg_type, CBB *cbb) return 1; } +static int +tlsext_sni_is_ip_literal(CBS *cbs, int *is_ip) +{ + union { + struct in_addr ip4; + struct in6_addr ip6; + } addrbuf; + char *hostname = NULL; + + *is_ip = 0; + + if (!CBS_strdup(cbs, &hostname)) + return 0; + + if (inet_pton(AF_INET, hostname, &addrbuf) == 1 || + inet_pton(AF_INET6, hostname, &addrbuf) == 1) + *is_ip = 1; + + free(hostname); + + return 1; +} + /* * Validate that the CBS contains only a hostname consisting of RFC 5890 * compliant A-labels (see RFC 6066 section 3). Not a complete check @@ -680,18 +708,26 @@ tlsext_sni_client_build(SSL *s, uint16_t msg_type, CBB *cbb) * correct structure and character set. */ int -tlsext_sni_is_valid_hostname(CBS *cbs) +tlsext_sni_is_valid_hostname(CBS *cbs, int *is_ip) { uint8_t prev, c = 0; int component = 0; CBS hostname; + *is_ip = 0; + CBS_dup(cbs, &hostname); if (CBS_len(&hostname) > TLSEXT_MAXLEN_host_name) return 0; - while(CBS_len(&hostname) > 0) { + /* An IP literal is invalid as a host name (RFC 6066 section 3). */ + if (!tlsext_sni_is_ip_literal(&hostname, is_ip)) + return 0; + if (*is_ip) + return 0; + + while (CBS_len(&hostname) > 0) { prev = c; if (!CBS_get_u8(&hostname, &c)) return 0; @@ -727,12 +763,14 @@ tlsext_sni_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) { CBS server_name_list, host_name; uint8_t name_type; + int is_ip; if (!CBS_get_u16_length_prefixed(cbs, &server_name_list)) goto err; if (!CBS_get_u8(&server_name_list, &name_type)) goto err; + /* * RFC 6066 section 3, only one type (host_name) is specified. * We do not tolerate unknown types, neither does BoringSSL. @@ -743,22 +781,30 @@ tlsext_sni_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) goto err; } - - if (!CBS_get_u16_length_prefixed(&server_name_list, &host_name)) - goto err; /* * RFC 6066 section 3 specifies a host name must be at least 1 byte * so 0 length is a decode error. */ + if (!CBS_get_u16_length_prefixed(&server_name_list, &host_name)) + goto err; if (CBS_len(&host_name) < 1) goto err; - if (!tlsext_sni_is_valid_hostname(&host_name)) { + if (!tlsext_sni_is_valid_hostname(&host_name, &is_ip)) { + /* + * Various pieces of software have been known to set the SNI + * host name to an IP address, even though that violates the + * RFC. If this is the case, pretend the SNI extension does + * not exist. + */ + if (is_ip) + goto done; + *alert = SSL_AD_ILLEGAL_PARAMETER; goto err; } - if (s->internal->hit || S3I(s)->hs.tls13.hrr) { + if (s->internal->hit || s->s3->hs.tls13.hrr) { if (s->session->tlsext_hostname == NULL) { *alert = SSL_AD_UNRECOGNIZED_NAME; goto err; @@ -777,6 +823,7 @@ tlsext_sni_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) } } + done: /* * RFC 6066 section 3 forbids multiple host names with the same type, * therefore we allow only one entry. @@ -980,7 +1027,7 @@ tlsext_ocsp_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) int tlsext_ocsp_server_needs(SSL *s, uint16_t msg_type) { - if (S3I(s)->hs.negotiated_tls_version >= TLS1_3_VERSION && + if (s->s3->hs.negotiated_tls_version >= TLS1_3_VERSION && s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp && s->ctx->internal->tlsext_status_cb != NULL) { s->internal->tlsext_status_expected = 0; @@ -997,7 +1044,7 @@ tlsext_ocsp_server_build(SSL *s, uint16_t msg_type, CBB *cbb) { CBB ocsp_response; - if (S3I(s)->hs.negotiated_tls_version >= TLS1_3_VERSION) { + if (s->s3->hs.negotiated_tls_version >= TLS1_3_VERSION) { if (!CBB_add_u8(cbb, TLSEXT_STATUSTYPE_ocsp)) return 0; if (!CBB_add_u24_length_prefixed(cbb, &ocsp_response)) @@ -1404,19 +1451,23 @@ tlsext_srtp_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) int tlsext_keyshare_client_needs(SSL *s, uint16_t msg_type) { - return (S3I(s)->hs.our_max_tls_version >= TLS1_3_VERSION); + return (s->s3->hs.our_max_tls_version >= TLS1_3_VERSION); } int tlsext_keyshare_client_build(SSL *s, uint16_t msg_type, CBB *cbb) { - CBB client_shares; + CBB client_shares, key_exchange; if (!CBB_add_u16_length_prefixed(cbb, &client_shares)) return 0; - if (!tls13_key_share_public(S3I(s)->hs.tls13.key_share, - &client_shares)) + if (!CBB_add_u16(&client_shares, + tls_key_share_group(s->s3->hs.key_share))) + return 0; + if (!CBB_add_u16_length_prefixed(&client_shares, &key_exchange)) + return 0; + if (!tls_key_share_public(s->s3->hs.key_share, &key_exchange)) return 0; if (!CBB_flush(cbb)) @@ -1429,16 +1480,17 @@ int tlsext_keyshare_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) { CBS client_shares, key_exchange; + int decode_error; uint16_t group; if (!CBS_get_u16_length_prefixed(cbs, &client_shares)) - goto err; + return 0; while (CBS_len(&client_shares) > 0) { /* Unpack client share. */ if (!CBS_get_u16(&client_shares, &group)) - goto err; + return 0; if (!CBS_get_u16_length_prefixed(&client_shares, &key_exchange)) return 0; @@ -1451,9 +1503,9 @@ tlsext_keyshare_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) * Ignore this client share if we're using earlier than TLSv1.3 * or we've already selected a key share. */ - if (S3I(s)->hs.our_max_tls_version < TLS1_3_VERSION) + if (s->s3->hs.our_max_tls_version < TLS1_3_VERSION) continue; - if (S3I(s)->hs.tls13.key_share != NULL) + if (s->s3->hs.key_share != NULL) continue; /* XXX - consider implementing server preference. */ @@ -1461,42 +1513,51 @@ tlsext_keyshare_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) continue; /* Decode and store the selected key share. */ - S3I(s)->hs.tls13.key_share = tls13_key_share_new(group); - if (S3I(s)->hs.tls13.key_share == NULL) - goto err; - if (!tls13_key_share_peer_public(S3I(s)->hs.tls13.key_share, - group, &key_exchange)) - goto err; + if ((s->s3->hs.key_share = tls_key_share_new(group)) == NULL) { + *alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + if (!tls_key_share_peer_public(s->s3->hs.key_share, + &key_exchange, &decode_error, NULL)) { + if (!decode_error) + *alert = SSL_AD_INTERNAL_ERROR; + return 0; + } } return 1; - - err: - *alert = SSL_AD_DECODE_ERROR; - return 0; } int tlsext_keyshare_server_needs(SSL *s, uint16_t msg_type) { - return (S3I(s)->hs.negotiated_tls_version >= TLS1_3_VERSION && + return (s->s3->hs.negotiated_tls_version >= TLS1_3_VERSION && tlsext_extension_seen(s, TLSEXT_TYPE_key_share)); } int tlsext_keyshare_server_build(SSL *s, uint16_t msg_type, CBB *cbb) { + CBB key_exchange; + /* In the case of a HRR, we only send the server selected group. */ - if (S3I(s)->hs.tls13.hrr) { - if (S3I(s)->hs.tls13.server_group == 0) + if (s->s3->hs.tls13.hrr) { + if (s->s3->hs.tls13.server_group == 0) return 0; - return CBB_add_u16(cbb, S3I(s)->hs.tls13.server_group); + return CBB_add_u16(cbb, s->s3->hs.tls13.server_group); } - if (S3I(s)->hs.tls13.key_share == NULL) + if (s->s3->hs.key_share == NULL) return 0; - if (!tls13_key_share_public(S3I(s)->hs.tls13.key_share, cbb)) + if (!CBB_add_u16(cbb, tls_key_share_group(s->s3->hs.key_share))) + return 0; + if (!CBB_add_u16_length_prefixed(cbb, &key_exchange)) + return 0; + if (!tls_key_share_public(s->s3->hs.key_share, &key_exchange)) + return 0; + + if (!CBB_flush(cbb)) return 0; return 1; @@ -1506,34 +1567,41 @@ int tlsext_keyshare_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) { CBS key_exchange; + int decode_error; uint16_t group; /* Unpack server share. */ if (!CBS_get_u16(cbs, &group)) - goto err; + return 0; if (CBS_len(cbs) == 0) { - /* HRR does not include an actual key share. */ - /* XXX - we should know that we are in a HRR... */ - S3I(s)->hs.tls13.server_group = group; + /* HRR does not include an actual key share, only the group. */ + if (msg_type != SSL_TLSEXT_MSG_HRR) + return 0; + + s->s3->hs.tls13.server_group = group; return 1; } if (!CBS_get_u16_length_prefixed(cbs, &key_exchange)) return 0; - if (S3I(s)->hs.tls13.key_share == NULL) + if (s->s3->hs.key_share == NULL) { + *alert = SSL_AD_INTERNAL_ERROR; return 0; - - if (!tls13_key_share_peer_public(S3I(s)->hs.tls13.key_share, - group, &key_exchange)) - goto err; + } + if (tls_key_share_group(s->s3->hs.key_share) != group) { + *alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + if (!tls_key_share_peer_public(s->s3->hs.key_share, + &key_exchange, &decode_error, NULL)) { + if (!decode_error) + *alert = SSL_AD_INTERNAL_ERROR; + return 0; + } return 1; - - err: - *alert = SSL_AD_DECODE_ERROR; - return 0; } /* @@ -1542,7 +1610,7 @@ tlsext_keyshare_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) int tlsext_versions_client_needs(SSL *s, uint16_t msg_type) { - return (S3I(s)->hs.our_max_tls_version >= TLS1_3_VERSION); + return (s->s3->hs.our_max_tls_version >= TLS1_3_VERSION); } int @@ -1552,8 +1620,8 @@ tlsext_versions_client_build(SSL *s, uint16_t msg_type, CBB *cbb) uint16_t version; CBB versions; - max = S3I(s)->hs.our_max_tls_version; - min = S3I(s)->hs.our_min_tls_version; + max = s->s3->hs.our_max_tls_version; + min = s->s3->hs.our_min_tls_version; if (!CBB_add_u8_length_prefixed(cbb, &versions)) return 0; @@ -1578,8 +1646,8 @@ tlsext_versions_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) uint16_t max, min; uint16_t matched_version = 0; - max = S3I(s)->hs.our_max_tls_version; - min = S3I(s)->hs.our_min_tls_version; + max = s->s3->hs.our_max_tls_version; + min = s->s3->hs.our_min_tls_version; if (!CBS_get_u8_length_prefixed(cbs, &versions)) goto err; @@ -1612,7 +1680,7 @@ tlsext_versions_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) int tlsext_versions_server_needs(SSL *s, uint16_t msg_type) { - return (S3I(s)->hs.negotiated_tls_version >= TLS1_3_VERSION); + return (s->s3->hs.negotiated_tls_version >= TLS1_3_VERSION); } int @@ -1638,7 +1706,7 @@ tlsext_versions_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) } /* XXX test between min and max once initialization code goes in */ - S3I(s)->hs.tls13.server_version = selected_version; + s->s3->hs.tls13.server_version = selected_version; return 1; } @@ -1651,8 +1719,8 @@ tlsext_versions_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) int tlsext_cookie_client_needs(SSL *s, uint16_t msg_type) { - return (S3I(s)->hs.our_max_tls_version >= TLS1_3_VERSION && - S3I(s)->hs.tls13.cookie_len > 0 && S3I(s)->hs.tls13.cookie != NULL); + return (s->s3->hs.our_max_tls_version >= TLS1_3_VERSION && + s->s3->hs.tls13.cookie_len > 0 && s->s3->hs.tls13.cookie != NULL); } int @@ -1663,8 +1731,8 @@ tlsext_cookie_client_build(SSL *s, uint16_t msg_type, CBB *cbb) if (!CBB_add_u16_length_prefixed(cbb, &cookie)) return 0; - if (!CBB_add_bytes(&cookie, S3I(s)->hs.tls13.cookie, - S3I(s)->hs.tls13.cookie_len)) + if (!CBB_add_bytes(&cookie, s->s3->hs.tls13.cookie, + s->s3->hs.tls13.cookie_len)) return 0; if (!CBB_flush(cbb)) @@ -1681,7 +1749,7 @@ tlsext_cookie_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) if (!CBS_get_u16_length_prefixed(cbs, &cookie)) goto err; - if (CBS_len(&cookie) != S3I(s)->hs.tls13.cookie_len) + if (CBS_len(&cookie) != s->s3->hs.tls13.cookie_len) goto err; /* @@ -1689,8 +1757,8 @@ tlsext_cookie_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) * sent - client *MUST* send the same cookie with new CR after * a cookie is sent by the server with an HRR. */ - if (!CBS_mem_equal(&cookie, S3I(s)->hs.tls13.cookie, - S3I(s)->hs.tls13.cookie_len)) { + if (!CBS_mem_equal(&cookie, s->s3->hs.tls13.cookie, + s->s3->hs.tls13.cookie_len)) { /* XXX special cookie mismatch alert? */ *alert = SSL_AD_ILLEGAL_PARAMETER; return 0; @@ -1710,8 +1778,8 @@ tlsext_cookie_server_needs(SSL *s, uint16_t msg_type) * Server needs to set cookie value in tls13 handshake * in order to send one, should only be sent with HRR. */ - return (S3I(s)->hs.our_max_tls_version >= TLS1_3_VERSION && - S3I(s)->hs.tls13.cookie_len > 0 && S3I(s)->hs.tls13.cookie != NULL); + return (s->s3->hs.our_max_tls_version >= TLS1_3_VERSION && + s->s3->hs.tls13.cookie_len > 0 && s->s3->hs.tls13.cookie != NULL); } int @@ -1724,8 +1792,8 @@ tlsext_cookie_server_build(SSL *s, uint16_t msg_type, CBB *cbb) if (!CBB_add_u16_length_prefixed(cbb, &cookie)) return 0; - if (!CBB_add_bytes(&cookie, S3I(s)->hs.tls13.cookie, - S3I(s)->hs.tls13.cookie_len)) + if (!CBB_add_bytes(&cookie, s->s3->hs.tls13.cookie, + s->s3->hs.tls13.cookie_len)) return 0; if (!CBB_flush(cbb)) @@ -1744,8 +1812,8 @@ tlsext_cookie_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) * HRR from a server with a cookie to process after accepting * one from the server in the same handshake */ - if (S3I(s)->hs.tls13.cookie != NULL || - S3I(s)->hs.tls13.cookie_len != 0) { + if (s->s3->hs.tls13.cookie != NULL || + s->s3->hs.tls13.cookie_len != 0) { *alert = SSL_AD_ILLEGAL_PARAMETER; return 0; } @@ -1753,8 +1821,8 @@ tlsext_cookie_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) if (!CBS_get_u16_length_prefixed(cbs, &cookie)) goto err; - if (!CBS_stow(&cookie, &S3I(s)->hs.tls13.cookie, - &S3I(s)->hs.tls13.cookie_len)) + if (!CBS_stow(&cookie, &s->s3->hs.tls13.cookie, + &s->s3->hs.tls13.cookie_len)) goto err; return 1; @@ -1981,7 +2049,7 @@ tlsext_extension_seen(SSL *s, uint16_t type) if (tls_extension_find(type, &idx) == NULL) return 0; - return ((S3I(s)->hs.extensions_seen & (1 << idx)) != 0); + return ((s->s3->hs.extensions_seen & (1 << idx)) != 0); } static const struct tls_extension_funcs * @@ -2081,7 +2149,7 @@ tlsext_parse(SSL *s, int is_server, uint16_t msg_type, CBS *cbs, int *alert) tls_version = ssl_effective_tls_version(s); - S3I(s)->hs.extensions_seen = 0; + s->s3->hs.extensions_seen = 0; /* An empty extensions block is valid. */ if (CBS_len(cbs) == 0) @@ -2123,9 +2191,9 @@ tlsext_parse(SSL *s, int is_server, uint16_t msg_type, CBS *cbs, int *alert) } /* Check for duplicate known extensions. */ - if ((S3I(s)->hs.extensions_seen & (1 << idx)) != 0) + if ((s->s3->hs.extensions_seen & (1 << idx)) != 0) goto err; - S3I(s)->hs.extensions_seen |= (1 << idx); + s->s3->hs.extensions_seen |= (1 << idx); ext = tlsext_funcs(tlsext, is_server); if (!ext->parse(s, msg_type, &extension_data, &alert_desc)) @@ -2147,10 +2215,10 @@ static void tlsext_server_reset_state(SSL *s) { s->tlsext_status_type = -1; - S3I(s)->renegotiate_seen = 0; - free(S3I(s)->alpn_selected); - S3I(s)->alpn_selected = NULL; - S3I(s)->alpn_selected_len = 0; + s->s3->renegotiate_seen = 0; + free(s->s3->alpn_selected); + s->s3->alpn_selected = NULL; + s->s3->alpn_selected_len = 0; s->internal->srtp_profile = NULL; } @@ -2173,10 +2241,10 @@ tlsext_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) static void tlsext_client_reset_state(SSL *s) { - S3I(s)->renegotiate_seen = 0; - free(S3I(s)->alpn_selected); - S3I(s)->alpn_selected = NULL; - S3I(s)->alpn_selected_len = 0; + s->s3->renegotiate_seen = 0; + free(s->s3->alpn_selected); + s->s3->alpn_selected = NULL; + s->s3->alpn_selected_len = 0; } int diff --git a/ssl/ssl_tlsext.h b/ssl/ssl_tlsext.h index 8e0742a..b4c135f 100644 --- a/ssl/ssl_tlsext.h +++ b/ssl/ssl_tlsext.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_tlsext.h,v 1.26 2020/10/11 01:13:04 guenther Exp $ */ +/* $OpenBSD: ssl_tlsext.h,v 1.27 2021/11/01 16:37:17 jsing Exp $ */ /* * Copyright (c) 2016, 2017 Joel Sing * Copyright (c) 2017 Doug Hogan @@ -60,7 +60,7 @@ int tlsext_sni_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert); int tlsext_sni_server_needs(SSL *s, uint16_t msg_type); int tlsext_sni_server_build(SSL *s, uint16_t msg_type, CBB *cbb); int tlsext_sni_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert); -int tlsext_sni_is_valid_hostname(CBS *cbs); +int tlsext_sni_is_valid_hostname(CBS *cbs, int *is_ip); int tlsext_supportedgroups_client_needs(SSL *s, uint16_t msg_type); int tlsext_supportedgroups_client_build(SSL *s, uint16_t msg_type, CBB *cbb); diff --git a/ssl/ssl_transcript.c b/ssl/ssl_transcript.c index 47aa15a..d0af8e6 100644 --- a/ssl/ssl_transcript.c +++ b/ssl/ssl_transcript.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_transcript.c,v 1.5 2021/05/16 14:10:43 jsing Exp $ */ +/* $OpenBSD: ssl_transcript.c,v 1.7 2022/03/17 17:22:16 jsing Exp $ */ /* * Copyright (c) 2017 Joel Sing * @@ -33,11 +33,11 @@ tls1_transcript_hash_init(SSL *s) goto err; } - if ((S3I(s)->handshake_hash = EVP_MD_CTX_new()) == NULL) { + if ((s->s3->handshake_hash = EVP_MD_CTX_new()) == NULL) { SSLerror(s, ERR_R_MALLOC_FAILURE); goto err; } - if (!EVP_DigestInit_ex(S3I(s)->handshake_hash, md, NULL)) { + if (!EVP_DigestInit_ex(s->s3->handshake_hash, md, NULL)) { SSLerror(s, ERR_R_EVP_LIB); goto err; } @@ -62,35 +62,35 @@ tls1_transcript_hash_init(SSL *s) int tls1_transcript_hash_update(SSL *s, const unsigned char *buf, size_t len) { - if (S3I(s)->handshake_hash == NULL) + if (s->s3->handshake_hash == NULL) return 1; - return EVP_DigestUpdate(S3I(s)->handshake_hash, buf, len); + return EVP_DigestUpdate(s->s3->handshake_hash, buf, len); } int -tls1_transcript_hash_value(SSL *s, const unsigned char *out, size_t len, +tls1_transcript_hash_value(SSL *s, unsigned char *out, size_t len, size_t *outlen) { EVP_MD_CTX *mdctx = NULL; unsigned int mdlen; int ret = 0; - if (S3I(s)->handshake_hash == NULL) + if (s->s3->handshake_hash == NULL) goto err; - if (EVP_MD_CTX_size(S3I(s)->handshake_hash) > len) + if (EVP_MD_CTX_size(s->s3->handshake_hash) > len) goto err; if ((mdctx = EVP_MD_CTX_new()) == NULL) { SSLerror(s, ERR_R_MALLOC_FAILURE); goto err; } - if (!EVP_MD_CTX_copy_ex(mdctx, S3I(s)->handshake_hash)) { + if (!EVP_MD_CTX_copy_ex(mdctx, s->s3->handshake_hash)) { SSLerror(s, ERR_R_EVP_LIB); goto err; } - if (!EVP_DigestFinal_ex(mdctx, (unsigned char *)out, &mdlen)) { + if (!EVP_DigestFinal_ex(mdctx, out, &mdlen)) { SSLerror(s, ERR_R_EVP_LIB); goto err; } @@ -108,17 +108,17 @@ tls1_transcript_hash_value(SSL *s, const unsigned char *out, size_t len, void tls1_transcript_hash_free(SSL *s) { - EVP_MD_CTX_free(S3I(s)->handshake_hash); - S3I(s)->handshake_hash = NULL; + EVP_MD_CTX_free(s->s3->handshake_hash); + s->s3->handshake_hash = NULL; } int tls1_transcript_init(SSL *s) { - if (S3I(s)->handshake_transcript != NULL) + if (s->s3->handshake_transcript != NULL) return 0; - if ((S3I(s)->handshake_transcript = BUF_MEM_new()) == NULL) + if ((s->s3->handshake_transcript = BUF_MEM_new()) == NULL) return 0; tls1_transcript_reset(s); @@ -129,8 +129,8 @@ tls1_transcript_init(SSL *s) void tls1_transcript_free(SSL *s) { - BUF_MEM_free(S3I(s)->handshake_transcript); - S3I(s)->handshake_transcript = NULL; + BUF_MEM_free(s->s3->handshake_transcript); + s->s3->handshake_transcript = NULL; } void @@ -143,7 +143,7 @@ tls1_transcript_reset(SSL *s) * or if it failed (and returned zero)... our implementation never * fails with a length of zero, so we trust all is okay... */ - (void)BUF_MEM_grow_clean(S3I(s)->handshake_transcript, 0); + (void)BUF_MEM_grow_clean(s->s3->handshake_transcript, 0); tls1_transcript_unfreeze(s); } @@ -153,22 +153,22 @@ tls1_transcript_append(SSL *s, const unsigned char *buf, size_t len) { size_t olen, nlen; - if (S3I(s)->handshake_transcript == NULL) + if (s->s3->handshake_transcript == NULL) return 1; if (s->s3->flags & TLS1_FLAGS_FREEZE_TRANSCRIPT) return 1; - olen = S3I(s)->handshake_transcript->length; + olen = s->s3->handshake_transcript->length; nlen = olen + len; if (nlen < olen) return 0; - if (BUF_MEM_grow(S3I(s)->handshake_transcript, nlen) == 0) + if (BUF_MEM_grow(s->s3->handshake_transcript, nlen) == 0) return 0; - memcpy(S3I(s)->handshake_transcript->data + olen, buf, len); + memcpy(s->s3->handshake_transcript->data + olen, buf, len); return 1; } @@ -176,11 +176,11 @@ tls1_transcript_append(SSL *s, const unsigned char *buf, size_t len) int tls1_transcript_data(SSL *s, const unsigned char **data, size_t *len) { - if (S3I(s)->handshake_transcript == NULL) + if (s->s3->handshake_transcript == NULL) return 0; - *data = S3I(s)->handshake_transcript->data; - *len = S3I(s)->handshake_transcript->length; + *data = s->s3->handshake_transcript->data; + *len = s->s3->handshake_transcript->length; return 1; } diff --git a/ssl/ssl_txt.c b/ssl/ssl_txt.c index 09b76dd..8718f8c 100644 --- a/ssl/ssl_txt.c +++ b/ssl/ssl_txt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_txt.c,v 1.29 2021/06/11 11:13:53 jsing Exp $ */ +/* $OpenBSD: ssl_txt.c,v 1.31 2021/11/29 18:36:27 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -95,7 +95,7 @@ SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *x) BIO *b; int ret; - if ((b = BIO_new(BIO_s_file_internal())) == NULL) { + if ((b = BIO_new(BIO_s_file())) == NULL) { SSLerrorx(ERR_R_BUF_LIB); return (0); } @@ -152,7 +152,7 @@ SSL_SESSION_print(BIO *bp, const SSL_SESSION *x) } if (x->tlsext_tick_lifetime_hint) { if (BIO_printf(bp, - "\n TLS session ticket lifetime hint: %ld (seconds)", + "\n TLS session ticket lifetime hint: %u (seconds)", x->tlsext_tick_lifetime_hint) <= 0) goto err; } diff --git a/ssl/ssl_versions.c b/ssl/ssl_versions.c index c633b58..4069670 100644 --- a/ssl/ssl_versions.c +++ b/ssl/ssl_versions.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_versions.c,v 1.20 2021/07/01 17:53:39 jsing Exp $ */ +/* $OpenBSD: ssl_versions.c,v 1.22 2022/02/05 14:54:10 jsing Exp $ */ /* * Copyright (c) 2016, 2017 Joel Sing * @@ -224,10 +224,10 @@ ssl_tls_version(uint16_t version) uint16_t ssl_effective_tls_version(SSL *s) { - if (S3I(s)->hs.negotiated_tls_version > 0) - return S3I(s)->hs.negotiated_tls_version; + if (s->s3->hs.negotiated_tls_version > 0) + return s->s3->hs.negotiated_tls_version; - return S3I(s)->hs.our_max_tls_version; + return s->s3->hs.our_max_tls_version; } int @@ -250,6 +250,24 @@ ssl_max_supported_version(SSL *s, uint16_t *max_ver) return 1; } +int +ssl_max_legacy_version(SSL *s, uint16_t *max_ver) +{ + uint16_t max_version; + + if ((max_version = s->s3->hs.our_max_tls_version) > TLS1_2_VERSION) + max_version = TLS1_2_VERSION; + + if (SSL_is_dtls(s)) { + if ((max_version = ssl_tls_to_dtls_version(max_version)) == 0) + return 0; + } + + *max_ver = max_version; + + return 1; +} + int ssl_max_shared_version(SSL *s, uint16_t peer_ver, uint16_t *max_ver) { diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index 65e2063..c996159 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: t1_enc.c,v 1.151 2021/07/01 17:53:39 jsing Exp $ */ +/* $OpenBSD: t1_enc.c,v 1.154 2022/02/05 14:54:10 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -149,8 +149,8 @@ void tls1_cleanup_key_block(SSL *s) { - tls12_key_block_free(S3I(s)->hs.tls12.key_block); - S3I(s)->hs.tls12.key_block = NULL; + tls12_key_block_free(s->s3->hs.tls12.key_block); + s->s3->hs.tls12.key_block = NULL; } /* @@ -164,8 +164,8 @@ tls1_P_hash(const EVP_MD *md, const unsigned char *secret, size_t secret_len, { unsigned char A1[EVP_MAX_MD_SIZE], hmac[EVP_MAX_MD_SIZE]; size_t A1_len, hmac_len; - EVP_MD_CTX ctx; - EVP_PKEY *mac_key; + EVP_MD_CTX *ctx = NULL; + EVP_PKEY *mac_key = NULL; int ret = 0; int chunk; size_t i; @@ -173,42 +173,43 @@ tls1_P_hash(const EVP_MD *md, const unsigned char *secret, size_t secret_len, chunk = EVP_MD_size(md); OPENSSL_assert(chunk >= 0); - EVP_MD_CTX_init(&ctx); + if ((ctx = EVP_MD_CTX_new()) == NULL) + goto err; mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, secret, secret_len); - if (!mac_key) + if (mac_key == NULL) goto err; - if (!EVP_DigestSignInit(&ctx, NULL, md, NULL, mac_key)) + if (!EVP_DigestSignInit(ctx, NULL, md, NULL, mac_key)) goto err; - if (seed1 && !EVP_DigestSignUpdate(&ctx, seed1, seed1_len)) + if (seed1 && !EVP_DigestSignUpdate(ctx, seed1, seed1_len)) goto err; - if (seed2 && !EVP_DigestSignUpdate(&ctx, seed2, seed2_len)) + if (seed2 && !EVP_DigestSignUpdate(ctx, seed2, seed2_len)) goto err; - if (seed3 && !EVP_DigestSignUpdate(&ctx, seed3, seed3_len)) + if (seed3 && !EVP_DigestSignUpdate(ctx, seed3, seed3_len)) goto err; - if (seed4 && !EVP_DigestSignUpdate(&ctx, seed4, seed4_len)) + if (seed4 && !EVP_DigestSignUpdate(ctx, seed4, seed4_len)) goto err; - if (seed5 && !EVP_DigestSignUpdate(&ctx, seed5, seed5_len)) + if (seed5 && !EVP_DigestSignUpdate(ctx, seed5, seed5_len)) goto err; - if (!EVP_DigestSignFinal(&ctx, A1, &A1_len)) + if (!EVP_DigestSignFinal(ctx, A1, &A1_len)) goto err; for (;;) { - if (!EVP_DigestSignInit(&ctx, NULL, md, NULL, mac_key)) + if (!EVP_DigestSignInit(ctx, NULL, md, NULL, mac_key)) goto err; - if (!EVP_DigestSignUpdate(&ctx, A1, A1_len)) + if (!EVP_DigestSignUpdate(ctx, A1, A1_len)) goto err; - if (seed1 && !EVP_DigestSignUpdate(&ctx, seed1, seed1_len)) + if (seed1 && !EVP_DigestSignUpdate(ctx, seed1, seed1_len)) goto err; - if (seed2 && !EVP_DigestSignUpdate(&ctx, seed2, seed2_len)) + if (seed2 && !EVP_DigestSignUpdate(ctx, seed2, seed2_len)) goto err; - if (seed3 && !EVP_DigestSignUpdate(&ctx, seed3, seed3_len)) + if (seed3 && !EVP_DigestSignUpdate(ctx, seed3, seed3_len)) goto err; - if (seed4 && !EVP_DigestSignUpdate(&ctx, seed4, seed4_len)) + if (seed4 && !EVP_DigestSignUpdate(ctx, seed4, seed4_len)) goto err; - if (seed5 && !EVP_DigestSignUpdate(&ctx, seed5, seed5_len)) + if (seed5 && !EVP_DigestSignUpdate(ctx, seed5, seed5_len)) goto err; - if (!EVP_DigestSignFinal(&ctx, hmac, &hmac_len)) + if (!EVP_DigestSignFinal(ctx, hmac, &hmac_len)) goto err; if (hmac_len > out_len) @@ -223,18 +224,18 @@ tls1_P_hash(const EVP_MD *md, const unsigned char *secret, size_t secret_len, if (out_len == 0) break; - if (!EVP_DigestSignInit(&ctx, NULL, md, NULL, mac_key)) + if (!EVP_DigestSignInit(ctx, NULL, md, NULL, mac_key)) goto err; - if (!EVP_DigestSignUpdate(&ctx, A1, A1_len)) + if (!EVP_DigestSignUpdate(ctx, A1, A1_len)) goto err; - if (!EVP_DigestSignFinal(&ctx, A1, &A1_len)) + if (!EVP_DigestSignFinal(ctx, A1, &A1_len)) goto err; } ret = 1; err: EVP_PKEY_free(mac_key); - EVP_MD_CTX_cleanup(&ctx); + EVP_MD_CTX_free(ctx); explicit_bzero(A1, sizeof(A1)); explicit_bzero(hmac, sizeof(hmac)); @@ -256,7 +257,7 @@ tls1_PRF(SSL *s, const unsigned char *secret, size_t secret_len, if (!ssl_get_handshake_evp_md(s, &md)) return (0); - if (md->type == NID_md5_sha1) { + if (EVP_MD_type(md) == NID_md5_sha1) { /* * Partition secret between MD5 and SHA1, then XOR result. * If the secret length is odd, a one byte overlap is used. @@ -302,10 +303,10 @@ tls1_change_cipher_state(SSL *s, int is_write) /* Use client write keys on client write and server read. */ if ((!s->server && is_write) || (s->server && !is_write)) { - tls12_key_block_client_write(S3I(s)->hs.tls12.key_block, + tls12_key_block_client_write(s->s3->hs.tls12.key_block, &mac_key, &key, &iv); } else { - tls12_key_block_server_write(S3I(s)->hs.tls12.key_block, + tls12_key_block_server_write(s->s3->hs.tls12.key_block, &mac_key, &key, &iv); } @@ -315,8 +316,6 @@ tls1_change_cipher_state(SSL *s, int is_write) goto err; if (SSL_is_dtls(s)) dtls1_reset_read_seq_numbers(s); - tls12_record_layer_read_cipher_hash(s->internal->rl, - &s->enc_read_ctx, &s->read_hash); } else { if (!tls12_record_layer_change_write_cipher_state(s->internal->rl, &mac_key, &key, &iv)) @@ -355,7 +354,7 @@ tls1_setup_key_block(SSL *s) * XXX - callers should be changed so that they only call this * function once. */ - if (S3I(s)->hs.tls12.key_block != NULL) + if (s->s3->hs.tls12.key_block != NULL) return (1); if (s->session->cipher && @@ -385,7 +384,7 @@ tls1_setup_key_block(SSL *s) if (!tls12_key_block_generate(key_block, s, aead, cipher, mac_hash)) goto err; - S3I(s)->hs.tls12.key_block = key_block; + s->s3->hs.tls12.key_block = key_block; key_block = NULL; if (!(s->internal->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) && @@ -394,15 +393,15 @@ tls1_setup_key_block(SSL *s) * Enable vulnerability countermeasure for CBC ciphers with * known-IV problem (http://www.openssl.org/~bodo/tls-cbc.txt) */ - S3I(s)->need_empty_fragments = 1; + s->s3->need_empty_fragments = 1; if (s->session->cipher != NULL) { if (s->session->cipher->algorithm_enc == SSL_eNULL) - S3I(s)->need_empty_fragments = 0; + s->s3->need_empty_fragments = 0; #ifndef OPENSSL_NO_RC4 if (s->session->cipher->algorithm_enc == SSL_RC4) - S3I(s)->need_empty_fragments = 0; + s->s3->need_empty_fragments = 0; #endif } } diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 3cb2d8a..fc1ccca 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: t1_lib.c,v 1.182 2021/07/01 17:53:39 jsing Exp $ */ +/* $OpenBSD: t1_lib.c,v 1.186 2022/01/24 13:47:53 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -329,8 +329,8 @@ tls1_get_formatlist(SSL *s, int client_formats, const uint8_t **pformats, size_t *pformatslen) { if (client_formats != 0) { - *pformats = SSI(s)->tlsext_ecpointformatlist; - *pformatslen = SSI(s)->tlsext_ecpointformatlist_length; + *pformats = s->session->tlsext_ecpointformatlist; + *pformatslen = s->session->tlsext_ecpointformatlist_length; return; } @@ -352,8 +352,8 @@ tls1_get_group_list(SSL *s, int client_groups, const uint16_t **pgroups, size_t *pgroupslen) { if (client_groups != 0) { - *pgroups = SSI(s)->tlsext_supportedgroups; - *pgroupslen = SSI(s)->tlsext_supportedgroups_length; + *pgroups = s->session->tlsext_supportedgroups; + *pgroupslen = s->session->tlsext_supportedgroups_length; return; } @@ -569,19 +569,19 @@ tls1_check_ec_key(SSL *s, const uint16_t *curve_id, const uint8_t *comp_id) int tls1_check_ec_server_key(SSL *s) { - CERT_PKEY *cpk = s->cert->pkeys + SSL_PKEY_ECC; + SSL_CERT_PKEY *cpk = s->cert->pkeys + SSL_PKEY_ECC; uint16_t curve_id; uint8_t comp_id; + EC_KEY *eckey; EVP_PKEY *pkey; - int rv; if (cpk->x509 == NULL || cpk->privatekey == NULL) return (0); - if ((pkey = X509_get_pubkey(cpk->x509)) == NULL) + if ((pkey = X509_get0_pubkey(cpk->x509)) == NULL) return (0); - rv = tls1_set_ec_id(&curve_id, &comp_id, pkey->pkey.ec); - EVP_PKEY_free(pkey); - if (rv != 1) + if ((eckey = EVP_PKEY_get0_EC_KEY(pkey)) == NULL) + return (0); + if (!tls1_set_ec_id(&curve_id, &comp_id, eckey)) return (0); return tls1_check_ec_key(s, &curve_id, &comp_id); @@ -634,7 +634,7 @@ ssl_check_clienthello_tlsext_late(SSL *s) if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->internal->tlsext_status_cb) { int r; - CERT_PKEY *certpkey; + SSL_CERT_PKEY *certpkey; certpkey = ssl_get_server_send_pkey(s); /* If no certificate can't return certificate status */ if (certpkey == NULL) { diff --git a/ssl/tls12_lib.c b/ssl/tls12_lib.c index f30f3a7..773ba30 100644 --- a/ssl/tls12_lib.c +++ b/ssl/tls12_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls12_lib.c,v 1.3 2021/05/02 15:57:29 jsing Exp $ */ +/* $OpenBSD: tls12_lib.c,v 1.4 2022/02/05 14:54:10 jsing Exp $ */ /* * Copyright (c) 2021 Joel Sing * @@ -71,12 +71,12 @@ tls12_derive_finished(SSL *s) { if (!s->server) { return tls12_client_finished_verify_data(s, - S3I(s)->hs.finished, sizeof(S3I(s)->hs.finished), - &S3I(s)->hs.finished_len); + s->s3->hs.finished, sizeof(s->s3->hs.finished), + &s->s3->hs.finished_len); } else { return tls12_server_finished_verify_data(s, - S3I(s)->hs.finished, sizeof(S3I(s)->hs.finished), - &S3I(s)->hs.finished_len); + s->s3->hs.finished, sizeof(s->s3->hs.finished), + &s->s3->hs.finished_len); } } @@ -85,12 +85,12 @@ tls12_derive_peer_finished(SSL *s) { if (s->server) { return tls12_client_finished_verify_data(s, - S3I(s)->hs.peer_finished, sizeof(S3I(s)->hs.peer_finished), - &S3I(s)->hs.peer_finished_len); + s->s3->hs.peer_finished, sizeof(s->s3->hs.peer_finished), + &s->s3->hs.peer_finished_len); } else { return tls12_server_finished_verify_data(s, - S3I(s)->hs.peer_finished, sizeof(S3I(s)->hs.peer_finished), - &S3I(s)->hs.peer_finished_len); + s->s3->hs.peer_finished, sizeof(s->s3->hs.peer_finished), + &s->s3->hs.peer_finished_len); } } diff --git a/ssl/tls12_record_layer.c b/ssl/tls12_record_layer.c index 6d7d869..3568e18 100644 --- a/ssl/tls12_record_layer.c +++ b/ssl/tls12_record_layer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls12_record_layer.c,v 1.34 2021/08/30 19:12:25 jsing Exp $ */ +/* $OpenBSD: tls12_record_layer.c,v 1.36 2022/01/14 09:12:15 tb Exp $ */ /* * Copyright (c) 2020 Joel Sing * @@ -61,10 +61,7 @@ tls12_record_protection_new(void) static void tls12_record_protection_clear(struct tls12_record_protection *rp) { - if (rp->aead_ctx != NULL) { - EVP_AEAD_CTX_cleanup(rp->aead_ctx); - freezero(rp->aead_ctx, sizeof(*rp->aead_ctx)); - } + EVP_AEAD_CTX_free(rp->aead_ctx); freezero(rp->aead_nonce, rp->aead_nonce_len); freezero(rp->aead_fixed_nonce, rp->aead_fixed_nonce_len); @@ -355,14 +352,6 @@ tls12_record_layer_clear_write_state(struct tls12_record_layer *rl) rl->write_previous = NULL; } -void -tls12_record_layer_read_cipher_hash(struct tls12_record_layer *rl, - EVP_CIPHER_CTX **cipher, EVP_MD_CTX **hash) -{ - *cipher = rl->read->cipher_ctx; - *hash = rl->read->hash_ctx; -} - void tls12_record_layer_reflect_seq_num(struct tls12_record_layer *rl) { @@ -430,7 +419,7 @@ tls12_record_layer_ccs_aead(struct tls12_record_layer *rl, if (!tls12_record_protection_unused(rp)) return 0; - if ((rp->aead_ctx = calloc(1, sizeof(*rp->aead_ctx))) == NULL) + if ((rp->aead_ctx = EVP_AEAD_CTX_new()) == NULL) return 0; /* AES GCM cipher suites use variable nonce in record. */ diff --git a/ssl/tls13_client.c b/ssl/tls13_client.c index 62c5174..11eb880 100644 --- a/ssl/tls13_client.c +++ b/ssl/tls13_client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_client.c,v 1.86 2021/06/29 19:20:39 jsing Exp $ */ +/* $OpenBSD: tls13_client.c,v 1.94 2022/02/03 16:33:12 jsing Exp $ */ /* * Copyright (c) 2018, 2019 Joel Sing * @@ -36,7 +36,7 @@ tls13_client_init(struct tls13_ctx *ctx) SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE); return 0; } - s->client_version = s->version = ctx->hs->our_max_tls_version; + s->version = ctx->hs->our_max_tls_version; tls13_record_layer_set_retry_after_phh(ctx->rl, (s->internal->mode & SSL_MODE_AUTO_RETRY) != 0); @@ -51,9 +51,9 @@ tls13_client_init(struct tls13_ctx *ctx) tls1_get_group_list(s, 0, &groups, &groups_len); if (groups_len < 1) return 0; - if ((ctx->hs->tls13.key_share = tls13_key_share_new(groups[0])) == NULL) + if ((ctx->hs->key_share = tls_key_share_new(groups[0])) == NULL) return 0; - if (!tls13_key_share_generate(ctx->hs->tls13.key_share)) + if (!tls_key_share_generate(ctx->hs->key_share)) return 0; arc4random_buf(s->s3->client_random, SSL3_RANDOM_SIZE); @@ -92,9 +92,8 @@ tls13_client_hello_build(struct tls13_ctx *ctx, CBB *cbb) SSL *s = ctx->ssl; /* Legacy client version is capped at TLS 1.2. */ - client_version = ctx->hs->our_max_tls_version; - if (client_version > TLS1_2_VERSION) - client_version = TLS1_2_VERSION; + if (!ssl_max_legacy_version(s, &client_version)) + goto err; if (!CBB_add_u16(cbb, client_version)) goto err; @@ -282,6 +281,7 @@ tls13_server_hello_process(struct tls13_ctx *ctx, CBS *cbs) goto err; } ctx->hs->negotiated_tls_version = ctx->hs->tls13.server_version; + ctx->hs->peer_legacy_version = legacy_version; /* The session_id must match. */ if (!CBS_mem_equal(&session_id, ctx->hs->tls13.legacy_session_id, @@ -343,7 +343,7 @@ tls13_client_engage_record_protection(struct tls13_ctx *ctx) /* Derive the shared key and engage record protection. */ - if (!tls13_key_share_derive(ctx->hs->tls13.key_share, &shared_key, + if (!tls_key_share_derive(ctx->hs->key_share, &shared_key, &shared_key_len)) goto err; @@ -442,15 +442,15 @@ tls13_client_hello_retry_send(struct tls13_ctx *ctx, CBB *cbb) */ if (!tls1_check_curve(ctx->ssl, ctx->hs->tls13.server_group)) return 0; /* XXX alert */ - if (ctx->hs->tls13.server_group == tls13_key_share_group(ctx->hs->tls13.key_share)) + if (ctx->hs->tls13.server_group == tls_key_share_group(ctx->hs->key_share)) return 0; /* XXX alert */ /* Switch to new key share. */ - tls13_key_share_free(ctx->hs->tls13.key_share); - if ((ctx->hs->tls13.key_share = - tls13_key_share_new(ctx->hs->tls13.server_group)) == NULL) + tls_key_share_free(ctx->hs->key_share); + if ((ctx->hs->key_share = + tls_key_share_new(ctx->hs->tls13.server_group)) == NULL) return 0; - if (!tls13_key_share_generate(ctx->hs->tls13.key_share)) + if (!tls_key_share_generate(ctx->hs->key_share)) return 0; if (!tls13_client_hello_build(ctx, cbb)) @@ -561,7 +561,7 @@ tls13_server_certificate_recv(struct tls13_ctx *ctx, CBS *cbs) X509 *cert = NULL; EVP_PKEY *pkey; const uint8_t *p; - int cert_idx, alert_desc; + int alert_desc, cert_type; int ret = 0; if ((certs = sk_X509_new_null()) == NULL) @@ -625,26 +625,20 @@ tls13_server_certificate_recv(struct tls13_ctx *ctx, CBS *cbs) goto err; if (EVP_PKEY_missing_parameters(pkey)) goto err; - if ((cert_idx = ssl_cert_type(cert, pkey)) < 0) + if ((cert_type = ssl_cert_type(pkey)) < 0) goto err; - ssl_sess_cert_free(SSI(s)->sess_cert); - if ((SSI(s)->sess_cert = ssl_sess_cert_new()) == NULL) - goto err; - - SSI(s)->sess_cert->cert_chain = certs; - certs = NULL; - X509_up_ref(cert); - SSI(s)->sess_cert->peer_pkeys[cert_idx].x509 = cert; - SSI(s)->sess_cert->peer_key = &(SSI(s)->sess_cert->peer_pkeys[cert_idx]); + X509_free(s->session->peer_cert); + s->session->peer_cert = cert; + s->session->peer_cert_type = cert_type; - X509_free(s->session->peer); - - X509_up_ref(cert); - s->session->peer = cert; s->session->verify_result = s->verify_result; + sk_X509_pop_free(s->session->cert_chain, X509_free); + s->session->cert_chain = certs; + certs = NULL; + if (ctx->ocsp_status_recv_cb != NULL && !ctx->ocsp_status_recv_cb(ctx)) goto err; @@ -696,7 +690,7 @@ tls13_server_certificate_verify_recv(struct tls13_ctx *ctx, CBS *cbs) if (!CBB_finish(&cbb, &sig_content, &sig_content_len)) goto err; - if ((cert = ctx->ssl->session->peer) == NULL) + if ((cert = ctx->ssl->session->peer_cert) == NULL) goto err; if ((pkey = X509_get0_pubkey(cert)) == NULL) goto err; @@ -828,7 +822,7 @@ tls13_server_finished_recv(struct tls13_ctx *ctx, CBS *cbs) } static int -tls13_client_check_certificate(struct tls13_ctx *ctx, CERT_PKEY *cpk, +tls13_client_check_certificate(struct tls13_ctx *ctx, SSL_CERT_PKEY *cpk, int *ok, const struct ssl_sigalg **out_sigalg) { const struct ssl_sigalg *sigalg; @@ -851,12 +845,12 @@ tls13_client_check_certificate(struct tls13_ctx *ctx, CERT_PKEY *cpk, } static int -tls13_client_select_certificate(struct tls13_ctx *ctx, CERT_PKEY **out_cpk, +tls13_client_select_certificate(struct tls13_ctx *ctx, SSL_CERT_PKEY **out_cpk, const struct ssl_sigalg **out_sigalg) { SSL *s = ctx->ssl; const struct ssl_sigalg *sigalg; - CERT_PKEY *cpk; + SSL_CERT_PKEY *cpk; int cert_ok; *out_cpk = NULL; @@ -897,7 +891,7 @@ tls13_client_certificate_send(struct tls13_ctx *ctx, CBB *cbb) CBB cert_request_context, cert_list; const struct ssl_sigalg *sigalg; STACK_OF(X509) *chain; - CERT_PKEY *cpk; + SSL_CERT_PKEY *cpk; X509 *cert; int i, ret = 0; @@ -948,7 +942,7 @@ tls13_client_certificate_verify_send(struct tls13_ctx *ctx, CBB *cbb) EVP_MD_CTX *mdctx = NULL; EVP_PKEY_CTX *pctx; EVP_PKEY *pkey; - const CERT_PKEY *cpk; + const SSL_CERT_PKEY *cpk; CBB sig_cbb; int ret = 0; diff --git a/ssl/tls13_handshake_msg.c b/ssl/tls13_handshake_msg.c index ff6d6d7..67eab31 100644 --- a/ssl/tls13_handshake_msg.c +++ b/ssl/tls13_handshake_msg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_handshake_msg.c,v 1.3 2021/05/16 14:19:04 jsing Exp $ */ +/* $OpenBSD: tls13_handshake_msg.c,v 1.4 2021/10/23 13:12:14 jsing Exp $ */ /* * Copyright (c) 2018, 2019 Joel Sing * @@ -28,7 +28,7 @@ struct tls13_handshake_msg { uint8_t *data; size_t data_len; - struct tls13_buffer *buf; + struct tls_buffer *buf; CBS cbs; CBB cbb; }; @@ -40,7 +40,7 @@ tls13_handshake_msg_new() if ((msg = calloc(1, sizeof(struct tls13_handshake_msg))) == NULL) goto err; - if ((msg->buf = tls13_buffer_new(0)) == NULL) + if ((msg->buf = tls_buffer_new(0)) == NULL) goto err; return msg; @@ -57,7 +57,7 @@ tls13_handshake_msg_free(struct tls13_handshake_msg *msg) if (msg == NULL) return; - tls13_buffer_free(msg->buf); + tls_buffer_free(msg->buf); CBB_cleanup(&msg->cbb); @@ -74,7 +74,7 @@ tls13_handshake_msg_data(struct tls13_handshake_msg *msg, CBS *cbs) int tls13_handshake_msg_set_buffer(struct tls13_handshake_msg *msg, CBS *cbs) { - return tls13_buffer_set_data(msg->buf, cbs); + return tls_buffer_set_data(msg->buf, cbs); } uint8_t @@ -137,12 +137,12 @@ tls13_handshake_msg_recv(struct tls13_handshake_msg *msg, return TLS13_IO_FAILURE; if (msg->msg_type == 0) { - if ((ret = tls13_buffer_extend(msg->buf, + if ((ret = tls_buffer_extend(msg->buf, TLS13_HANDSHAKE_MSG_HEADER_LEN, tls13_handshake_msg_read_cb, rl)) <= 0) return ret; - tls13_buffer_cbs(msg->buf, &cbs); + tls_buffer_cbs(msg->buf, &cbs); if (!CBS_get_u8(&cbs, &msg_type)) return TLS13_IO_FAILURE; @@ -157,12 +157,12 @@ tls13_handshake_msg_recv(struct tls13_handshake_msg *msg, msg->msg_len = msg_len; } - if ((ret = tls13_buffer_extend(msg->buf, + if ((ret = tls_buffer_extend(msg->buf, TLS13_HANDSHAKE_MSG_HEADER_LEN + msg->msg_len, tls13_handshake_msg_read_cb, rl)) <= 0) return ret; - if (!tls13_buffer_finish(msg->buf, &msg->data, &msg->data_len)) + if (!tls_buffer_finish(msg->buf, &msg->data, &msg->data_len)) return TLS13_IO_FAILURE; return TLS13_IO_SUCCESS; diff --git a/ssl/tls13_internal.h b/ssl/tls13_internal.h index 20cb52e..4c3a328 100644 --- a/ssl/tls13_internal.h +++ b/ssl/tls13_internal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_internal.h,v 1.94 2021/09/16 19:25:30 jsing Exp $ */ +/* $OpenBSD: tls13_internal.h,v 1.96 2022/01/05 17:10:02 jsing Exp $ */ /* * Copyright (c) 2018 Bob Beck * Copyright (c) 2018 Theo Buehler @@ -24,6 +24,7 @@ #include #include "bytestring.h" +#include "tls_internal.h" __BEGIN_HIDDEN_DECLS @@ -89,28 +90,10 @@ __BEGIN_HIDDEN_DECLS typedef void (*tls13_alert_cb)(uint8_t _alert_desc, void *_cb_arg); typedef ssize_t (*tls13_phh_recv_cb)(void *_cb_arg, CBS *_cbs); typedef void (*tls13_phh_sent_cb)(void *_cb_arg); -typedef ssize_t (*tls13_read_cb)(void *_buf, size_t _buflen, void *_cb_arg); -typedef ssize_t (*tls13_write_cb)(const void *_buf, size_t _buflen, - void *_cb_arg); -typedef ssize_t (*tls13_flush_cb)(void *_cb_arg); typedef void (*tls13_handshake_message_cb)(void *_cb_arg); typedef void (*tls13_info_cb)(void *_cb_arg, int _state, int _ret); typedef int (*tls13_ocsp_status_cb)(void *_cb_arg); -/* - * Buffers. - */ -struct tls13_buffer; - -struct tls13_buffer *tls13_buffer_new(size_t init_size); -int tls13_buffer_set_data(struct tls13_buffer *buf, CBS *data); -void tls13_buffer_free(struct tls13_buffer *buf); -ssize_t tls13_buffer_extend(struct tls13_buffer *buf, size_t len, - tls13_read_cb read_cb, void *cb_arg); -void tls13_buffer_cbs(struct tls13_buffer *buf, CBS *cbs); -int tls13_buffer_finish(struct tls13_buffer *buf, uint8_t **out, - size_t *out_len); - /* * Secrets. */ @@ -175,33 +158,15 @@ int tls13_derive_application_secrets(struct tls13_secrets *secrets, int tls13_update_client_traffic_secret(struct tls13_secrets *secrets); int tls13_update_server_traffic_secret(struct tls13_secrets *secrets); -/* - * Key shares. - */ -struct tls13_key_share; - -struct tls13_key_share *tls13_key_share_new(uint16_t group_id); -struct tls13_key_share *tls13_key_share_new_nid(int nid); -void tls13_key_share_free(struct tls13_key_share *ks); - -uint16_t tls13_key_share_group(struct tls13_key_share *ks); -int tls13_key_share_peer_pkey(struct tls13_key_share *ks, EVP_PKEY *pkey); -int tls13_key_share_generate(struct tls13_key_share *ks); -int tls13_key_share_public(struct tls13_key_share *ks, CBB *cbb); -int tls13_key_share_peer_public(struct tls13_key_share *ks, uint16_t group, - CBS *cbs); -int tls13_key_share_derive(struct tls13_key_share *ks, uint8_t **shared_key, - size_t *shared_key_len); - /* * Record Layer. */ struct tls13_record_layer; struct tls13_record_layer_callbacks { - tls13_read_cb wire_read; - tls13_write_cb wire_write; - tls13_flush_cb wire_flush; + tls_read_cb wire_read; + tls_write_cb wire_write; + tls_flush_cb wire_flush; tls13_alert_cb alert_recv; tls13_alert_cb alert_sent; tls13_phh_recv_cb phh_recv; diff --git a/ssl/tls13_key_share.c b/ssl/tls13_key_share.c deleted file mode 100644 index 0d1c091..0000000 --- a/ssl/tls13_key_share.c +++ /dev/null @@ -1,324 +0,0 @@ -/* $OpenBSD: tls13_key_share.c,v 1.6 2020/04/18 14:07:56 jsing Exp $ */ -/* - * Copyright (c) 2020 Joel Sing - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#include - -#include "bytestring.h" -#include "ssl_locl.h" -#include "tls13_internal.h" - -struct tls13_key_share { - int nid; - uint16_t group_id; - - EC_KEY *ecdhe; - EC_KEY *ecdhe_peer; - - uint8_t *x25519_public; - uint8_t *x25519_private; - uint8_t *x25519_peer_public; -}; - -struct tls13_key_share * -tls13_key_share_new(uint16_t group_id) -{ - struct tls13_key_share *ks; - int nid; - - if ((nid = tls1_ec_curve_id2nid(group_id)) == 0) - return NULL; - - if ((ks = calloc(1, sizeof(struct tls13_key_share))) == NULL) - return NULL; - - ks->group_id = group_id; - ks->nid = nid; - - return ks; -} - -struct tls13_key_share * -tls13_key_share_new_nid(int nid) -{ - uint16_t group_id; - - if ((group_id = tls1_ec_nid2curve_id(nid)) == 0) - return NULL; - - return tls13_key_share_new(group_id); -} - -void -tls13_key_share_free(struct tls13_key_share *ks) -{ - if (ks == NULL) - return; - - EC_KEY_free(ks->ecdhe); - EC_KEY_free(ks->ecdhe_peer); - - freezero(ks->x25519_public, X25519_KEY_LENGTH); - freezero(ks->x25519_private, X25519_KEY_LENGTH); - freezero(ks->x25519_peer_public, X25519_KEY_LENGTH); - - freezero(ks, sizeof(*ks)); -} - -uint16_t -tls13_key_share_group(struct tls13_key_share *ks) -{ - return ks->group_id; -} - -int -tls13_key_share_peer_pkey(struct tls13_key_share *ks, EVP_PKEY *pkey) -{ - if (ks->nid == NID_X25519 && ks->x25519_peer_public != NULL) { - if (!ssl_kex_dummy_ecdhe_x25519(pkey)) - return 0; - } else if (ks->ecdhe_peer != NULL) { - if (!EVP_PKEY_set1_EC_KEY(pkey, ks->ecdhe_peer)) - return 0; - } else { - return 0; - } - - return 1; -} - -static int -tls13_key_share_generate_ecdhe_ecp(struct tls13_key_share *ks) -{ - EC_KEY *ecdhe = NULL; - int ret = 0; - - if (ks->ecdhe != NULL) - goto err; - - if ((ecdhe = EC_KEY_new()) == NULL) - goto err; - if (!ssl_kex_generate_ecdhe_ecp(ecdhe, ks->nid)) - goto err; - - ks->ecdhe = ecdhe; - ecdhe = NULL; - - ret = 1; - - err: - EC_KEY_free(ecdhe); - - return ret; -} - -static int -tls13_key_share_generate_x25519(struct tls13_key_share *ks) -{ - uint8_t *public = NULL, *private = NULL; - int ret = 0; - - if (ks->x25519_public != NULL || ks->x25519_private != NULL) - goto err; - - if ((public = calloc(1, X25519_KEY_LENGTH)) == NULL) - goto err; - if ((private = calloc(1, X25519_KEY_LENGTH)) == NULL) - goto err; - - X25519_keypair(public, private); - - ks->x25519_public = public; - ks->x25519_private = private; - public = NULL; - private = NULL; - - ret = 1; - - err: - freezero(public, X25519_KEY_LENGTH); - freezero(private, X25519_KEY_LENGTH); - - return ret; -} - -int -tls13_key_share_generate(struct tls13_key_share *ks) -{ - if (ks->nid == NID_X25519) - return tls13_key_share_generate_x25519(ks); - - return tls13_key_share_generate_ecdhe_ecp(ks); -} - -static int -tls13_key_share_public_ecdhe_ecp(struct tls13_key_share *ks, CBB *cbb) -{ - if (ks->ecdhe == NULL) - return 0; - - return ssl_kex_public_ecdhe_ecp(ks->ecdhe, cbb); -} - -static int -tls13_key_share_public_x25519(struct tls13_key_share *ks, CBB *cbb) -{ - if (ks->x25519_public == NULL) - return 0; - - return CBB_add_bytes(cbb, ks->x25519_public, X25519_KEY_LENGTH); -} - -int -tls13_key_share_public(struct tls13_key_share *ks, CBB *cbb) -{ - CBB key_exchange; - - if (!CBB_add_u16(cbb, ks->group_id)) - goto err; - if (!CBB_add_u16_length_prefixed(cbb, &key_exchange)) - goto err; - - if (ks->nid == NID_X25519) { - if (!tls13_key_share_public_x25519(ks, &key_exchange)) - goto err; - } else { - if (!tls13_key_share_public_ecdhe_ecp(ks, &key_exchange)) - goto err; - } - - if (!CBB_flush(cbb)) - goto err; - - return 1; - - err: - return 0; -} - -static int -tls13_key_share_peer_public_ecdhe_ecp(struct tls13_key_share *ks, CBS *cbs) -{ - EC_KEY *ecdhe = NULL; - int ret = 0; - - if (ks->ecdhe_peer != NULL) - goto err; - - if ((ecdhe = EC_KEY_new()) == NULL) - goto err; - if (!ssl_kex_peer_public_ecdhe_ecp(ecdhe, ks->nid, cbs)) - goto err; - - ks->ecdhe_peer = ecdhe; - ecdhe = NULL; - - ret = 1; - - err: - EC_KEY_free(ecdhe); - - return ret; -} - -static int -tls13_key_share_peer_public_x25519(struct tls13_key_share *ks, CBS *cbs) -{ - size_t out_len; - - if (ks->x25519_peer_public != NULL) - return 0; - - if (CBS_len(cbs) != X25519_KEY_LENGTH) - return 0; - - return CBS_stow(cbs, &ks->x25519_peer_public, &out_len); -} - -int -tls13_key_share_peer_public(struct tls13_key_share *ks, uint16_t group, - CBS *cbs) -{ - if (ks->group_id != group) - return 0; - - if (ks->nid == NID_X25519) { - if (!tls13_key_share_peer_public_x25519(ks, cbs)) - return 0; - } else { - if (!tls13_key_share_peer_public_ecdhe_ecp(ks, cbs)) - return 0; - } - - return 1; -} - -static int -tls13_key_share_derive_ecdhe_ecp(struct tls13_key_share *ks, - uint8_t **shared_key, size_t *shared_key_len) -{ - if (ks->ecdhe == NULL || ks->ecdhe_peer == NULL) - return 0; - - return ssl_kex_derive_ecdhe_ecp(ks->ecdhe, ks->ecdhe_peer, - shared_key, shared_key_len); -} - -static int -tls13_key_share_derive_x25519(struct tls13_key_share *ks, - uint8_t **shared_key, size_t *shared_key_len) -{ - uint8_t *sk = NULL; - int ret = 0; - - if (ks->x25519_private == NULL || ks->x25519_peer_public == NULL) - goto err; - - if ((sk = calloc(1, X25519_KEY_LENGTH)) == NULL) - goto err; - if (!X25519(sk, ks->x25519_private, ks->x25519_peer_public)) - goto err; - - *shared_key = sk; - *shared_key_len = X25519_KEY_LENGTH; - sk = NULL; - - ret = 1; - - err: - freezero(sk, X25519_KEY_LENGTH); - - return ret; -} - -int -tls13_key_share_derive(struct tls13_key_share *ks, uint8_t **shared_key, - size_t *shared_key_len) -{ - if (*shared_key != NULL) - return 0; - - *shared_key_len = 0; - - if (ks->nid == NID_X25519) - return tls13_key_share_derive_x25519(ks, shared_key, - shared_key_len); - - return tls13_key_share_derive_ecdhe_ecp(ks, shared_key, - shared_key_len); -} diff --git a/ssl/tls13_legacy.c b/ssl/tls13_legacy.c index f668dd4..27e030f 100644 --- a/ssl/tls13_legacy.c +++ b/ssl/tls13_legacy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_legacy.c,v 1.31 2021/09/16 19:25:30 jsing Exp $ */ +/* $OpenBSD: tls13_legacy.c,v 1.37 2022/02/06 16:08:14 jsing Exp $ */ /* * Copyright (c) 2018, 2019 Joel Sing * @@ -127,7 +127,7 @@ tls13_legacy_error(SSL *ssl) int reason = SSL_R_UNKNOWN; /* If we received a fatal alert we already put an error on the stack. */ - if (S3I(ssl)->fatal_alert != 0) + if (ssl->s3->fatal_alert != 0) return; switch (ctx->error.code) { @@ -229,6 +229,8 @@ tls13_legacy_read_bytes(SSL *ssl, int type, unsigned char *buf, int len, int pee if (ctx == NULL || !ctx->handshake_completed) { if ((ret = ssl->internal->handshake_func(ssl)) <= 0) return ret; + if (len == 0) + return 0; return tls13_legacy_return_code(ssl, TLS13_IO_WANT_POLLIN); } @@ -263,6 +265,8 @@ tls13_legacy_write_bytes(SSL *ssl, int type, const void *vbuf, int len) if (ctx == NULL || !ctx->handshake_completed) { if ((ret = ssl->internal->handshake_func(ssl)) <= 0) return ret; + if (len == 0) + return 0; return tls13_legacy_return_code(ssl, TLS13_IO_WANT_POLLOUT); } @@ -288,7 +292,7 @@ tls13_legacy_write_bytes(SSL *ssl, int type, const void *vbuf, int len) * In the non-SSL_MODE_ENABLE_PARTIAL_WRITE case we have to loop until * we have written out all of the requested data. */ - sent = S3I(ssl)->wnum; + sent = ssl->s3->wnum; if (len < sent) { SSLerror(ssl, SSL_R_BAD_LENGTH); return -1; @@ -296,12 +300,12 @@ tls13_legacy_write_bytes(SSL *ssl, int type, const void *vbuf, int len) n = len - sent; for (;;) { if (n == 0) { - S3I(ssl)->wnum = 0; + ssl->s3->wnum = 0; return sent; } if ((ret = tls13_write_application_data(ctx->rl, &buf[sent], n)) <= 0) { - S3I(ssl)->wnum = sent; + ssl->s3->wnum = sent; return tls13_legacy_return_code(ssl, ret); } sent += ret; @@ -330,8 +334,8 @@ tls13_use_legacy_stack(struct tls13_ctx *ctx) /* Stash any unprocessed data from the last record. */ tls13_record_layer_rcontent(ctx->rl, &cbs); if (CBS_len(&cbs) > 0) { - if (!CBB_init_fixed(&cbb, S3I(s)->rbuf.buf, - S3I(s)->rbuf.len)) + if (!CBB_init_fixed(&cbb, s->s3->rbuf.buf, + s->s3->rbuf.len)) goto err; if (!CBB_add_u8(&cbb, SSL3_RT_HANDSHAKE)) goto err; @@ -344,12 +348,12 @@ tls13_use_legacy_stack(struct tls13_ctx *ctx) if (!CBB_finish(&cbb, NULL, NULL)) goto err; - S3I(s)->rbuf.offset = SSL3_RT_HEADER_LENGTH; - S3I(s)->rbuf.left = CBS_len(&cbs); - S3I(s)->rrec.type = SSL3_RT_HANDSHAKE; - S3I(s)->rrec.length = CBS_len(&cbs); + s->s3->rbuf.offset = SSL3_RT_HEADER_LENGTH; + s->s3->rbuf.left = CBS_len(&cbs); + s->s3->rrec.type = SSL3_RT_HANDSHAKE; + s->s3->rrec.length = CBS_len(&cbs); s->internal->rstate = SSL_ST_READ_BODY; - s->internal->packet = S3I(s)->rbuf.buf; + s->internal->packet = s->s3->rbuf.buf; s->internal->packet_length = SSL3_RT_HEADER_LENGTH; s->internal->mac_packet = 1; } @@ -362,9 +366,9 @@ tls13_use_legacy_stack(struct tls13_ctx *ctx) s->internal->init_buf->length, NULL)) goto err; - S3I(s)->hs.tls12.reuse_message = 1; - S3I(s)->hs.tls12.message_type = tls13_handshake_msg_type(ctx->hs_msg); - S3I(s)->hs.tls12.message_size = CBS_len(&cbs) - SSL3_HM_HEADER_LENGTH; + s->s3->hs.tls12.reuse_message = 1; + s->s3->hs.tls12.message_type = tls13_handshake_msg_type(ctx->hs_msg); + s->s3->hs.tls12.message_size = CBS_len(&cbs) - SSL3_HM_HEADER_LENGTH; return 1; @@ -383,7 +387,7 @@ tls13_use_legacy_client(struct tls13_ctx *ctx) return 0; s->internal->handshake_func = s->method->ssl_connect; - s->client_version = s->version = s->method->max_tls_version; + s->version = s->method->max_tls_version; return 1; } @@ -397,7 +401,7 @@ tls13_use_legacy_server(struct tls13_ctx *ctx) return 0; s->internal->handshake_func = s->method->ssl_accept; - s->client_version = s->version = s->method->max_tls_version; + s->version = s->method->max_tls_version; s->server = 1; return 1; @@ -416,7 +420,7 @@ tls13_legacy_accept(SSL *ssl) } ssl->internal->tls13 = ctx; ctx->ssl = ssl; - ctx->hs = &S3I(ssl)->hs; + ctx->hs = &ssl->s3->hs; if (!tls13_server_init(ctx)) { if (ERR_peek_error() == 0) @@ -445,14 +449,6 @@ tls13_legacy_connect(SSL *ssl) struct tls13_ctx *ctx = ssl->internal->tls13; int ret; -#ifdef TLS13_USE_LEGACY_CLIENT_AUTH - /* XXX drop back to legacy for client auth for now */ - if (ssl->cert->key->privatekey != NULL) { - ssl->method = tls_legacy_client_method(); - return ssl->method->ssl_connect(ssl); - } -#endif - if (ctx == NULL) { if ((ctx = tls13_ctx_new(TLS13_HS_CLIENT)) == NULL) { SSLerror(ssl, ERR_R_INTERNAL_ERROR); /* XXX */ @@ -460,7 +456,7 @@ tls13_legacy_connect(SSL *ssl) } ssl->internal->tls13 = ctx; ctx->ssl = ssl; - ctx->hs = &S3I(ssl)->hs; + ctx->hs = &ssl->s3->hs; if (!tls13_client_init(ctx)) { if (ERR_peek_error() == 0) @@ -491,9 +487,9 @@ tls13_legacy_shutdown(SSL *ssl) ssize_t ret; /* - * We need to return 0 when we have sent a close-notify but have not - * yet received one. We return 1 only once we have sent and received - * close-notify alerts. All other cases return -1 and set internal + * We need to return 0 at the point that we have completed sending a + * close-notify. We return 1 when we have sent and received close-notify + * alerts. All other cases, including EOF, return -1 and set internal * state appropriately. */ if (ctx == NULL || ssl->internal->quiet_shutdown) { @@ -509,13 +505,15 @@ tls13_legacy_shutdown(SSL *ssl) TLS13_ALERT_CLOSE_NOTIFY)) < 0) return tls13_legacy_return_code(ssl, ret); } - if ((ret = tls13_record_layer_send_pending(ctx->rl)) != - TLS13_IO_SUCCESS) + ret = tls13_record_layer_send_pending(ctx->rl); + if (ret == TLS13_IO_EOF) + return -1; + if (ret != TLS13_IO_SUCCESS) return tls13_legacy_return_code(ssl, ret); } else if (!ctx->close_notify_recv) { /* * If there is no application data pending, attempt to read more - * data in order to receive a close notify. This should trigger + * data in order to receive a close-notify. This should trigger * a record to be read from the wire, which may be application * handshake or alert data. Only one attempt is made to match * previous semantics. @@ -524,6 +522,8 @@ tls13_legacy_shutdown(SSL *ssl) if ((ret = tls13_read_application_data(ctx->rl, buf, sizeof(buf))) < 0) return tls13_legacy_return_code(ssl, ret); + if (!ctx->close_notify_recv) + return -1; } } diff --git a/ssl/tls13_lib.c b/ssl/tls13_lib.c index 1a9596a..20d3a38 100644 --- a/ssl/tls13_lib.c +++ b/ssl/tls13_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_lib.c,v 1.62 2021/09/16 19:25:30 jsing Exp $ */ +/* $OpenBSD: tls13_lib.c,v 1.63 2022/02/05 14:54:10 jsing Exp $ */ /* * Copyright (c) 2018, 2019 Joel Sing * Copyright (c) 2019 Bob Beck @@ -111,7 +111,7 @@ tls13_alert_received_cb(uint8_t alert_desc, void *arg) if (alert_desc == TLS13_ALERT_CLOSE_NOTIFY) { ctx->close_notify_recv = 1; ctx->ssl->internal->shutdown |= SSL_RECEIVED_SHUTDOWN; - S3I(ctx->ssl)->warn_alert = alert_desc; + ctx->ssl->s3->warn_alert = alert_desc; return; } @@ -124,7 +124,7 @@ tls13_alert_received_cb(uint8_t alert_desc, void *arg) } /* All other alerts are treated as fatal in TLSv1.3. */ - S3I(ctx->ssl)->fatal_alert = alert_desc; + ctx->ssl->s3->fatal_alert = alert_desc; SSLerror(ctx->ssl, SSL_AD_REASON_OFFSET + alert_desc); ERR_asprintf_error_data("SSL alert number %d", alert_desc); diff --git a/ssl/tls13_record.c b/ssl/tls13_record.c index 3bdaead..2c74466 100644 --- a/ssl/tls13_record.c +++ b/ssl/tls13_record.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_record.c,v 1.8 2021/05/16 14:19:04 jsing Exp $ */ +/* $OpenBSD: tls13_record.c,v 1.9 2021/10/23 13:12:14 jsing Exp $ */ /* * Copyright (c) 2018, 2019 Joel Sing * @@ -26,7 +26,7 @@ struct tls13_record { size_t data_len; CBS cbs; - struct tls13_buffer *buf; + struct tls_buffer *buf; }; struct tls13_record * @@ -36,7 +36,7 @@ tls13_record_new(void) if ((rec = calloc(1, sizeof(struct tls13_record))) == NULL) goto err; - if ((rec->buf = tls13_buffer_new(TLS13_RECORD_MAX_LEN)) == NULL) + if ((rec->buf = tls_buffer_new(TLS13_RECORD_MAX_LEN)) == NULL) goto err; return rec; @@ -53,7 +53,7 @@ tls13_record_free(struct tls13_record *rec) if (rec == NULL) return; - tls13_buffer_free(rec->buf); + tls_buffer_free(rec->buf); freezero(rec->data, rec->data_len); freezero(rec, sizeof(struct tls13_record)); @@ -118,7 +118,7 @@ tls13_record_set_data(struct tls13_record *rec, uint8_t *data, size_t data_len) } ssize_t -tls13_record_recv(struct tls13_record *rec, tls13_read_cb wire_read, +tls13_record_recv(struct tls13_record *rec, tls_read_cb wire_read, void *wire_arg) { uint16_t rec_len, rec_version; @@ -130,11 +130,11 @@ tls13_record_recv(struct tls13_record *rec, tls13_read_cb wire_read, return TLS13_IO_FAILURE; if (rec->content_type == 0) { - if ((ret = tls13_buffer_extend(rec->buf, + if ((ret = tls_buffer_extend(rec->buf, TLS13_RECORD_HEADER_LEN, wire_read, wire_arg)) <= 0) return ret; - tls13_buffer_cbs(rec->buf, &cbs); + tls_buffer_cbs(rec->buf, &cbs); if (!CBS_get_u8(&cbs, &content_type)) return TLS13_IO_FAILURE; @@ -153,18 +153,18 @@ tls13_record_recv(struct tls13_record *rec, tls13_read_cb wire_read, rec->rec_len = rec_len; } - if ((ret = tls13_buffer_extend(rec->buf, + if ((ret = tls_buffer_extend(rec->buf, TLS13_RECORD_HEADER_LEN + rec->rec_len, wire_read, wire_arg)) <= 0) return ret; - if (!tls13_buffer_finish(rec->buf, &rec->data, &rec->data_len)) + if (!tls_buffer_finish(rec->buf, &rec->data, &rec->data_len)) return TLS13_IO_FAILURE; return rec->data_len; } ssize_t -tls13_record_send(struct tls13_record *rec, tls13_write_cb wire_write, +tls13_record_send(struct tls13_record *rec, tls_write_cb wire_write, void *wire_arg) { ssize_t ret; diff --git a/ssl/tls13_record.h b/ssl/tls13_record.h index 4b7ac4f..18e4fa1 100644 --- a/ssl/tls13_record.h +++ b/ssl/tls13_record.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_record.h,v 1.4 2021/05/16 14:20:29 jsing Exp $ */ +/* $OpenBSD: tls13_record.h,v 1.5 2021/10/23 13:12:14 jsing Exp $ */ /* * Copyright (c) 2019 Joel Sing * @@ -56,9 +56,9 @@ int tls13_record_content(struct tls13_record *_rec, CBS *_cbs); void tls13_record_data(struct tls13_record *_rec, CBS *_cbs); int tls13_record_set_data(struct tls13_record *_rec, uint8_t *_data, size_t _data_len); -ssize_t tls13_record_recv(struct tls13_record *_rec, tls13_read_cb _wire_read, +ssize_t tls13_record_recv(struct tls13_record *_rec, tls_read_cb _wire_read, void *_wire_arg); -ssize_t tls13_record_send(struct tls13_record *_rec, tls13_write_cb _wire_write, +ssize_t tls13_record_send(struct tls13_record *_rec, tls_write_cb _wire_write, void *_wire_arg); __END_HIDDEN_DECLS diff --git a/ssl/tls13_record_layer.c b/ssl/tls13_record_layer.c index 6b9f5d1..c68ee3b 100644 --- a/ssl/tls13_record_layer.c +++ b/ssl/tls13_record_layer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_record_layer.c,v 1.64 2021/09/16 19:25:30 jsing Exp $ */ +/* $OpenBSD: tls13_record_layer.c,v 1.67 2022/01/14 09:12:15 tb Exp $ */ /* * Copyright (c) 2018, 2019 Joel Sing * @@ -25,7 +25,7 @@ static ssize_t tls13_record_layer_write_record(struct tls13_record_layer *rl, uint8_t content_type, const uint8_t *content, size_t content_len); struct tls13_record_protection { - EVP_AEAD_CTX aead_ctx; + EVP_AEAD_CTX *aead_ctx; struct tls13_secret iv; struct tls13_secret nonce; uint8_t seq_num[TLS13_RECORD_SEQ_NUM_LEN]; @@ -40,12 +40,12 @@ tls13_record_protection_new(void) void tls13_record_protection_clear(struct tls13_record_protection *rp) { - EVP_AEAD_CTX_cleanup(&rp->aead_ctx); + EVP_AEAD_CTX_free(rp->aead_ctx); tls13_secret_cleanup(&rp->iv); tls13_secret_cleanup(&rp->nonce); - memset(rp->seq_num, 0, sizeof(rp->seq_num)); + memset(rp, 0, sizeof(*rp)); } void @@ -458,6 +458,9 @@ tls13_record_layer_set_traffic_key(const EVP_AEAD *aead, const EVP_MD *hash, tls13_record_protection_clear(rp); + if ((rp->aead_ctx = EVP_AEAD_CTX_new()) == NULL) + return 0; + if (!tls13_secret_init(&rp->iv, EVP_AEAD_nonce_length(aead))) goto err; if (!tls13_secret_init(&rp->nonce, EVP_AEAD_nonce_length(aead))) @@ -470,7 +473,7 @@ tls13_record_layer_set_traffic_key(const EVP_AEAD *aead, const EVP_MD *hash, if (!tls13_hkdf_expand_label(&key, hash, traffic_key, "key", &context)) goto err; - if (!EVP_AEAD_CTX_init(&rp->aead_ctx, aead, key.data, key.len, + if (!EVP_AEAD_CTX_init(rp->aead_ctx, aead, key.data, key.len, EVP_AEAD_DEFAULT_TAG_LENGTH, NULL)) goto err; @@ -528,8 +531,7 @@ tls13_record_layer_open_record_plaintext(struct tls13_record_layer *rl) static int tls13_record_layer_open_record_protected(struct tls13_record_layer *rl) { - CBS header, enc_record; - ssize_t inner_len; + CBS header, enc_record, inner; uint8_t *content = NULL; size_t content_len = 0; uint8_t content_type; @@ -551,7 +553,7 @@ tls13_record_layer_open_record_protected(struct tls13_record_layer *rl) rl->read->seq_num)) goto err; - if (!EVP_AEAD_CTX_open(&rl->read->aead_ctx, + if (!EVP_AEAD_CTX_open(rl->read->aead_ctx, content, &out_len, content_len, rl->read->nonce.data, rl->read->nonce.len, CBS_data(&enc_record), CBS_len(&enc_record), @@ -571,22 +573,24 @@ tls13_record_layer_open_record_protected(struct tls13_record_layer *rl) * it may be followed by padding that consists of one or more zeroes. * Time to hunt for that elusive content type! */ - /* XXX - CBS from end? CBS_get_end_u8()? */ - inner_len = out_len - 1; - while (inner_len >= 0 && content[inner_len] == 0) - inner_len--; - if (inner_len < 0) { + CBS_init(&inner, content, out_len); + content_type = 0; + while (CBS_get_last_u8(&inner, &content_type)) { + if (content_type != 0) + break; + } + if (content_type == 0) { /* Unexpected message per RFC 8446 section 5.4. */ rl->alert = TLS13_ALERT_UNEXPECTED_MESSAGE; goto err; } - if (inner_len > TLS13_RECORD_MAX_PLAINTEXT_LEN) { + if (CBS_len(&inner) > TLS13_RECORD_MAX_PLAINTEXT_LEN) { rl->alert = TLS13_ALERT_RECORD_OVERFLOW; goto err; } - content_type = content[inner_len]; - tls_content_set_data(rl->rcontent, content_type, content, inner_len); + tls_content_set_data(rl->rcontent, content_type, CBS_data(&inner), + CBS_len(&inner)); return 1; @@ -727,7 +731,7 @@ tls13_record_layer_seal_record_protected(struct tls13_record_layer *rl, * this would avoid a copy since the inner would be passed as two * separate pieces. */ - if (!EVP_AEAD_CTX_seal(&rl->write->aead_ctx, + if (!EVP_AEAD_CTX_seal(rl->write->aead_ctx, enc_record, &out_len, enc_record_len, rl->write->nonce.data, rl->write->nonce.len, inner, inner_len, header, header_len)) diff --git a/ssl/tls13_server.c b/ssl/tls13_server.c index d2c7abb..4ac84a8 100644 --- a/ssl/tls13_server.c +++ b/ssl/tls13_server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_server.c,v 1.84 2021/07/01 17:53:39 jsing Exp $ */ +/* $OpenBSD: tls13_server.c,v 1.96 2022/02/03 16:33:12 jsing Exp $ */ /* * Copyright (c) 2019, 2020 Joel Sing * Copyright (c) 2020 Bob Beck @@ -164,6 +164,7 @@ tls13_client_hello_process(struct tls13_ctx *ctx, CBS *cbs) return tls13_use_legacy_server(ctx); } ctx->hs->negotiated_tls_version = TLS1_3_VERSION; + ctx->hs->peer_legacy_version = legacy_version; /* Ensure we send subsequent alerts with the correct record version. */ tls13_record_layer_set_legacy_version(ctx->rl, TLS1_2_VERSION); @@ -294,7 +295,7 @@ tls13_client_hello_recv(struct tls13_ctx *ctx, CBS *cbs) * has been enabled. This would probably mean using either an * INITIAL | WITHOUT_HRR state, or another intermediate state. */ - if (ctx->hs->tls13.key_share != NULL) + if (ctx->hs->key_share != NULL) ctx->handshake_stage.hs_type |= NEGOTIATED | WITHOUT_HRR; /* XXX - check this is the correct point */ @@ -359,8 +360,8 @@ tls13_server_engage_record_protection(struct tls13_ctx *ctx) SSL *s = ctx->ssl; int ret = 0; - if (!tls13_key_share_derive(ctx->hs->tls13.key_share, - &shared_key, &shared_key_len)) + if (!tls_key_share_derive(ctx->hs->key_share, &shared_key, + &shared_key_len)) goto err; s->session->cipher = ctx->hs->cipher; @@ -424,7 +425,7 @@ tls13_server_hello_retry_request_send(struct tls13_ctx *ctx, CBB *cbb) if (!tls13_synthetic_handshake_message(ctx)) return 0; - if (ctx->hs->tls13.key_share != NULL) + if (ctx->hs->key_share != NULL) return 0; if ((nid = tls1_get_shared_curve(ctx->ssl)) == NID_undef) return 0; @@ -484,9 +485,9 @@ tls13_servername_process(struct tls13_ctx *ctx) int tls13_server_hello_send(struct tls13_ctx *ctx, CBB *cbb) { - if (ctx->hs->tls13.key_share == NULL) + if (ctx->hs->key_share == NULL) return 0; - if (!tls13_key_share_generate(ctx->hs->tls13.key_share)) + if (!tls_key_share_generate(ctx->hs->key_share)) return 0; if (!tls13_servername_process(ctx)) return 0; @@ -544,7 +545,7 @@ tls13_server_certificate_request_send(struct tls13_ctx *ctx, CBB *cbb) } static int -tls13_server_check_certificate(struct tls13_ctx *ctx, CERT_PKEY *cpk, +tls13_server_check_certificate(struct tls13_ctx *ctx, SSL_CERT_PKEY *cpk, int *ok, const struct ssl_sigalg **out_sigalg) { const struct ssl_sigalg *sigalg; @@ -556,15 +557,11 @@ tls13_server_check_certificate(struct tls13_ctx *ctx, CERT_PKEY *cpk, if (cpk->x509 == NULL || cpk->privatekey == NULL) goto done; - if (!X509_check_purpose(cpk->x509, -1, 0)) - return 0; - /* * The digitalSignature bit MUST be set if the Key Usage extension is * present as per RFC 8446 section 4.4.2.2. */ - if ((cpk->x509->ex_flags & EXFLAG_KUSAGE) && - !(cpk->x509->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE)) + if (!(X509_get_key_usage(cpk->x509) & X509v3_KU_DIGITAL_SIGNATURE)) goto done; if ((sigalg = ssl_sigalg_select(s, cpk->privatekey)) == NULL) @@ -578,12 +575,12 @@ tls13_server_check_certificate(struct tls13_ctx *ctx, CERT_PKEY *cpk, } static int -tls13_server_select_certificate(struct tls13_ctx *ctx, CERT_PKEY **out_cpk, +tls13_server_select_certificate(struct tls13_ctx *ctx, SSL_CERT_PKEY **out_cpk, const struct ssl_sigalg **out_sigalg) { SSL *s = ctx->ssl; const struct ssl_sigalg *sigalg; - CERT_PKEY *cpk; + SSL_CERT_PKEY *cpk; int cert_ok; *out_cpk = NULL; @@ -619,7 +616,7 @@ tls13_server_certificate_send(struct tls13_ctx *ctx, CBB *cbb) const struct ssl_sigalg *sigalg; X509_STORE_CTX *xsc = NULL; STACK_OF(X509) *chain; - CERT_PKEY *cpk; + SSL_CERT_PKEY *cpk; X509 *cert; int i, ret = 0; @@ -649,7 +646,7 @@ tls13_server_certificate_send(struct tls13_ctx *ctx, CBB *cbb) X509_V_FLAG_LEGACY_VERIFY); X509_verify_cert(xsc); ERR_clear_error(); - chain = xsc->chain; + chain = X509_STORE_CTX_get0_chain(xsc); } if (!CBB_add_u8_length_prefixed(cbb, &cert_request_context)) @@ -700,7 +697,7 @@ tls13_server_certificate_verify_send(struct tls13_ctx *ctx, CBB *cbb) EVP_MD_CTX *mdctx = NULL; EVP_PKEY_CTX *pctx; EVP_PKEY *pkey; - const CERT_PKEY *cpk; + const SSL_CERT_PKEY *cpk; CBB sig_cbb; int ret = 0; @@ -860,7 +857,7 @@ tls13_client_certificate_recv(struct tls13_ctx *ctx, CBS *cbs) X509 *cert = NULL; EVP_PKEY *pkey; const uint8_t *p; - int cert_idx; + int cert_type; int ret = 0; if (!CBS_get_u8_length_prefixed(cbs, &cert_request_context)) @@ -911,33 +908,30 @@ tls13_client_certificate_recv(struct tls13_ctx *ctx, CBS *cbs) } ERR_clear_error(); - cert = sk_X509_value(certs, 0); - X509_up_ref(cert); + /* + * Achtung! Due to API inconsistency, a client includes the peer's leaf + * certificate in the stored certificate chain, while a server does not. + */ + cert = sk_X509_shift(certs); if ((pkey = X509_get0_pubkey(cert)) == NULL) goto err; if (EVP_PKEY_missing_parameters(pkey)) goto err; - if ((cert_idx = ssl_cert_type(cert, pkey)) < 0) + if ((cert_type = ssl_cert_type(pkey)) < 0) goto err; - ssl_sess_cert_free(SSI(s)->sess_cert); - if ((SSI(s)->sess_cert = ssl_sess_cert_new()) == NULL) - goto err; - - SSI(s)->sess_cert->cert_chain = certs; - certs = NULL; - X509_up_ref(cert); - SSI(s)->sess_cert->peer_pkeys[cert_idx].x509 = cert; - SSI(s)->sess_cert->peer_key = &(SSI(s)->sess_cert->peer_pkeys[cert_idx]); + X509_free(s->session->peer_cert); + s->session->peer_cert = cert; + s->session->peer_cert_type = cert_type; - X509_free(s->session->peer); - - X509_up_ref(cert); - s->session->peer = cert; s->session->verify_result = s->verify_result; + sk_X509_pop_free(s->session->cert_chain, X509_free); + s->session->cert_chain = certs; + certs = NULL; + ctx->handshake_stage.hs_type |= WITH_CCV; ret = 1; @@ -986,7 +980,7 @@ tls13_client_certificate_verify_recv(struct tls13_ctx *ctx, CBS *cbs) if (!CBB_finish(&cbb, &sig_content, &sig_content_len)) goto err; - if ((cert = ctx->ssl->session->peer) == NULL) + if ((cert = ctx->ssl->session->peer_cert) == NULL) goto err; if ((pkey = X509_get0_pubkey(cert)) == NULL) goto err; diff --git a/ssl/tls13_buffer.c b/ssl/tls_buffer.c similarity index 64% rename from ssl/tls13_buffer.c rename to ssl/tls_buffer.c index b46ac65..5c0ca7e 100644 --- a/ssl/tls13_buffer.c +++ b/ssl/tls_buffer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_buffer.c,v 1.5 2021/05/16 14:19:04 jsing Exp $ */ +/* $OpenBSD: tls_buffer.c,v 1.1 2021/10/23 13:12:14 jsing Exp $ */ /* * Copyright (c) 2018, 2019 Joel Sing * @@ -15,49 +15,52 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "bytestring.h" -#include "tls13_internal.h" +#include +#include -struct tls13_buffer { +#include "bytestring.h" +#include "tls_internal.h" + +struct tls_buffer { size_t capacity; uint8_t *data; size_t len; size_t offset; }; -static int tls13_buffer_resize(struct tls13_buffer *buf, size_t capacity); +static int tls_buffer_resize(struct tls_buffer *buf, size_t capacity); -struct tls13_buffer * -tls13_buffer_new(size_t init_size) +struct tls_buffer * +tls_buffer_new(size_t init_size) { - struct tls13_buffer *buf = NULL; + struct tls_buffer *buf = NULL; - if ((buf = calloc(1, sizeof(struct tls13_buffer))) == NULL) + if ((buf = calloc(1, sizeof(struct tls_buffer))) == NULL) goto err; - if (!tls13_buffer_resize(buf, init_size)) + if (!tls_buffer_resize(buf, init_size)) goto err; return buf; err: - tls13_buffer_free(buf); + tls_buffer_free(buf); return NULL; } void -tls13_buffer_free(struct tls13_buffer *buf) +tls_buffer_free(struct tls_buffer *buf) { if (buf == NULL) return; freezero(buf->data, buf->capacity); - freezero(buf, sizeof(struct tls13_buffer)); + freezero(buf, sizeof(struct tls_buffer)); } static int -tls13_buffer_resize(struct tls13_buffer *buf, size_t capacity) +tls_buffer_resize(struct tls_buffer *buf, size_t capacity) { uint8_t *data; @@ -74,17 +77,17 @@ tls13_buffer_resize(struct tls13_buffer *buf, size_t capacity) } int -tls13_buffer_set_data(struct tls13_buffer *buf, CBS *data) +tls_buffer_set_data(struct tls_buffer *buf, CBS *data) { - if (!tls13_buffer_resize(buf, CBS_len(data))) + if (!tls_buffer_resize(buf, CBS_len(data))) return 0; memcpy(buf->data, CBS_data(data), CBS_len(data)); return 1; } ssize_t -tls13_buffer_extend(struct tls13_buffer *buf, size_t len, - tls13_read_cb read_cb, void *cb_arg) +tls_buffer_extend(struct tls_buffer *buf, size_t len, + tls_read_cb read_cb, void *cb_arg) { ssize_t ret; @@ -92,10 +95,10 @@ tls13_buffer_extend(struct tls13_buffer *buf, size_t len, return buf->len; if (len < buf->len) - return TLS13_IO_FAILURE; + return TLS_IO_FAILURE; - if (!tls13_buffer_resize(buf, len)) - return TLS13_IO_FAILURE; + if (!tls_buffer_resize(buf, len)) + return TLS_IO_FAILURE; for (;;) { if ((ret = read_cb(&buf->data[buf->len], @@ -103,7 +106,7 @@ tls13_buffer_extend(struct tls13_buffer *buf, size_t len, return ret; if (ret > buf->capacity - buf->len) - return TLS13_IO_FAILURE; + return TLS_IO_FAILURE; buf->len += ret; @@ -113,13 +116,13 @@ tls13_buffer_extend(struct tls13_buffer *buf, size_t len, } void -tls13_buffer_cbs(struct tls13_buffer *buf, CBS *cbs) +tls_buffer_cbs(struct tls_buffer *buf, CBS *cbs) { CBS_init(cbs, buf->data, buf->len); } int -tls13_buffer_finish(struct tls13_buffer *buf, uint8_t **out, size_t *out_len) +tls_buffer_finish(struct tls_buffer *buf, uint8_t **out, size_t *out_len) { if (out == NULL || out_len == NULL) return 0; diff --git a/ssl/tls_internal.h b/ssl/tls_internal.h new file mode 100644 index 0000000..a009635 --- /dev/null +++ b/ssl/tls_internal.h @@ -0,0 +1,83 @@ +/* $OpenBSD: tls_internal.h,v 1.5 2022/01/11 18:28:41 jsing Exp $ */ +/* + * Copyright (c) 2018, 2019, 2021 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HEADER_TLS_INTERNAL_H +#define HEADER_TLS_INTERNAL_H + +#include +#include + +#include "bytestring.h" + +__BEGIN_HIDDEN_DECLS + +#define TLS_IO_SUCCESS 1 +#define TLS_IO_EOF 0 +#define TLS_IO_FAILURE -1 +#define TLS_IO_ALERT -2 +#define TLS_IO_WANT_POLLIN -3 +#define TLS_IO_WANT_POLLOUT -4 +#define TLS_IO_WANT_RETRY -5 /* Retry the previous call immediately. */ + +/* + * Callbacks. + */ +typedef ssize_t (*tls_read_cb)(void *_buf, size_t _buflen, void *_cb_arg); +typedef ssize_t (*tls_write_cb)(const void *_buf, size_t _buflen, + void *_cb_arg); +typedef ssize_t (*tls_flush_cb)(void *_cb_arg); + +/* + * Buffers. + */ +struct tls_buffer; + +struct tls_buffer *tls_buffer_new(size_t init_size); +int tls_buffer_set_data(struct tls_buffer *buf, CBS *data); +void tls_buffer_free(struct tls_buffer *buf); +ssize_t tls_buffer_extend(struct tls_buffer *buf, size_t len, + tls_read_cb read_cb, void *cb_arg); +void tls_buffer_cbs(struct tls_buffer *buf, CBS *cbs); +int tls_buffer_finish(struct tls_buffer *buf, uint8_t **out, size_t *out_len); + +/* + * Key shares. + */ +struct tls_key_share; + +struct tls_key_share *tls_key_share_new(uint16_t group_id); +struct tls_key_share *tls_key_share_new_nid(int nid); +void tls_key_share_free(struct tls_key_share *ks); + +uint16_t tls_key_share_group(struct tls_key_share *ks); +int tls_key_share_nid(struct tls_key_share *ks); +void tls_key_share_set_key_bits(struct tls_key_share *ks, size_t key_bits); +int tls_key_share_set_dh_params(struct tls_key_share *ks, DH *dh_params); +int tls_key_share_peer_pkey(struct tls_key_share *ks, EVP_PKEY *pkey); +int tls_key_share_generate(struct tls_key_share *ks); +int tls_key_share_params(struct tls_key_share *ks, CBB *cbb); +int tls_key_share_public(struct tls_key_share *ks, CBB *cbb); +int tls_key_share_peer_params(struct tls_key_share *ks, CBS *cbs, + int *decode_error, int *invalid_params); +int tls_key_share_peer_public(struct tls_key_share *ks, CBS *cbs, + int *decode_error, int *invalid_key); +int tls_key_share_derive(struct tls_key_share *ks, uint8_t **shared_key, + size_t *shared_key_len); + +__END_HIDDEN_DECLS + +#endif diff --git a/ssl/tls_key_share.c b/ssl/tls_key_share.c new file mode 100644 index 0000000..e5e6c30 --- /dev/null +++ b/ssl/tls_key_share.c @@ -0,0 +1,473 @@ +/* $OpenBSD: tls_key_share.c,v 1.4 2022/01/11 18:28:41 jsing Exp $ */ +/* + * Copyright (c) 2020, 2021 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include + +#include "bytestring.h" +#include "ssl_locl.h" +#include "tls_internal.h" + +struct tls_key_share { + int nid; + uint16_t group_id; + size_t key_bits; + + DH *dhe; + DH *dhe_peer; + + EC_KEY *ecdhe; + EC_KEY *ecdhe_peer; + + uint8_t *x25519_public; + uint8_t *x25519_private; + uint8_t *x25519_peer_public; +}; + +static struct tls_key_share * +tls_key_share_new_internal(int nid, uint16_t group_id) +{ + struct tls_key_share *ks; + + if ((ks = calloc(1, sizeof(struct tls_key_share))) == NULL) + return NULL; + + ks->group_id = group_id; + ks->nid = nid; + + return ks; +} + +struct tls_key_share * +tls_key_share_new(uint16_t group_id) +{ + int nid; + + if ((nid = tls1_ec_curve_id2nid(group_id)) == 0) + return NULL; + + return tls_key_share_new_internal(nid, group_id); +} + +struct tls_key_share * +tls_key_share_new_nid(int nid) +{ + uint16_t group_id = 0; + + if (nid != NID_dhKeyAgreement) { + if ((group_id = tls1_ec_nid2curve_id(nid)) == 0) + return NULL; + } + + return tls_key_share_new_internal(nid, group_id); +} + +void +tls_key_share_free(struct tls_key_share *ks) +{ + if (ks == NULL) + return; + + DH_free(ks->dhe); + DH_free(ks->dhe_peer); + + EC_KEY_free(ks->ecdhe); + EC_KEY_free(ks->ecdhe_peer); + + freezero(ks->x25519_public, X25519_KEY_LENGTH); + freezero(ks->x25519_private, X25519_KEY_LENGTH); + freezero(ks->x25519_peer_public, X25519_KEY_LENGTH); + + freezero(ks, sizeof(*ks)); +} + +uint16_t +tls_key_share_group(struct tls_key_share *ks) +{ + return ks->group_id; +} + +int +tls_key_share_nid(struct tls_key_share *ks) +{ + return ks->nid; +} + +void +tls_key_share_set_key_bits(struct tls_key_share *ks, size_t key_bits) +{ + ks->key_bits = key_bits; +} + +int +tls_key_share_set_dh_params(struct tls_key_share *ks, DH *dh_params) +{ + if (ks->nid != NID_dhKeyAgreement) + return 0; + if (ks->dhe != NULL || ks->dhe_peer != NULL) + return 0; + + if ((ks->dhe = DHparams_dup(dh_params)) == NULL) + return 0; + if ((ks->dhe_peer = DHparams_dup(dh_params)) == NULL) + return 0; + + return 1; +} + +int +tls_key_share_peer_pkey(struct tls_key_share *ks, EVP_PKEY *pkey) +{ + if (ks->nid == NID_dhKeyAgreement && ks->dhe_peer != NULL) + return EVP_PKEY_set1_DH(pkey, ks->dhe_peer); + + if (ks->nid == NID_X25519 && ks->x25519_peer_public != NULL) + return ssl_kex_dummy_ecdhe_x25519(pkey); + + if (ks->ecdhe_peer != NULL) + return EVP_PKEY_set1_EC_KEY(pkey, ks->ecdhe_peer); + + return 0; +} + +static int +tls_key_share_generate_dhe(struct tls_key_share *ks) +{ + /* + * If auto params are not being used then we must already have DH + * parameters set. + */ + if (ks->key_bits == 0) { + if (ks->dhe == NULL) + return 0; + + return ssl_kex_generate_dhe(ks->dhe, ks->dhe); + } + + if (ks->dhe != NULL || ks->dhe_peer != NULL) + return 0; + + if ((ks->dhe = DH_new()) == NULL) + return 0; + if (!ssl_kex_generate_dhe_params_auto(ks->dhe, ks->key_bits)) + return 0; + if ((ks->dhe_peer = DHparams_dup(ks->dhe)) == NULL) + return 0; + + return 1; +} + +static int +tls_key_share_generate_ecdhe_ecp(struct tls_key_share *ks) +{ + EC_KEY *ecdhe = NULL; + int ret = 0; + + if (ks->ecdhe != NULL) + goto err; + + if ((ecdhe = EC_KEY_new()) == NULL) + goto err; + if (!ssl_kex_generate_ecdhe_ecp(ecdhe, ks->nid)) + goto err; + + ks->ecdhe = ecdhe; + ecdhe = NULL; + + ret = 1; + + err: + EC_KEY_free(ecdhe); + + return ret; +} + +static int +tls_key_share_generate_x25519(struct tls_key_share *ks) +{ + uint8_t *public = NULL, *private = NULL; + int ret = 0; + + if (ks->x25519_public != NULL || ks->x25519_private != NULL) + goto err; + + if ((public = calloc(1, X25519_KEY_LENGTH)) == NULL) + goto err; + if ((private = calloc(1, X25519_KEY_LENGTH)) == NULL) + goto err; + + X25519_keypair(public, private); + + ks->x25519_public = public; + ks->x25519_private = private; + public = NULL; + private = NULL; + + ret = 1; + + err: + freezero(public, X25519_KEY_LENGTH); + freezero(private, X25519_KEY_LENGTH); + + return ret; +} + +int +tls_key_share_generate(struct tls_key_share *ks) +{ + if (ks->nid == NID_dhKeyAgreement) + return tls_key_share_generate_dhe(ks); + + if (ks->nid == NID_X25519) + return tls_key_share_generate_x25519(ks); + + return tls_key_share_generate_ecdhe_ecp(ks); +} + +static int +tls_key_share_params_dhe(struct tls_key_share *ks, CBB *cbb) +{ + if (ks->dhe == NULL) + return 0; + + return ssl_kex_params_dhe(ks->dhe, cbb); +} + +int +tls_key_share_params(struct tls_key_share *ks, CBB *cbb) +{ + if (ks->nid == NID_dhKeyAgreement) + return tls_key_share_params_dhe(ks, cbb); + + return 0; +} + +static int +tls_key_share_public_dhe(struct tls_key_share *ks, CBB *cbb) +{ + if (ks->dhe == NULL) + return 0; + + return ssl_kex_public_dhe(ks->dhe, cbb); +} + +static int +tls_key_share_public_ecdhe_ecp(struct tls_key_share *ks, CBB *cbb) +{ + if (ks->ecdhe == NULL) + return 0; + + return ssl_kex_public_ecdhe_ecp(ks->ecdhe, cbb); +} + +static int +tls_key_share_public_x25519(struct tls_key_share *ks, CBB *cbb) +{ + if (ks->x25519_public == NULL) + return 0; + + return CBB_add_bytes(cbb, ks->x25519_public, X25519_KEY_LENGTH); +} + +int +tls_key_share_public(struct tls_key_share *ks, CBB *cbb) +{ + if (ks->nid == NID_dhKeyAgreement) + return tls_key_share_public_dhe(ks, cbb); + + if (ks->nid == NID_X25519) + return tls_key_share_public_x25519(ks, cbb); + + return tls_key_share_public_ecdhe_ecp(ks, cbb); +} + +static int +tls_key_share_peer_params_dhe(struct tls_key_share *ks, CBS *cbs, + int *decode_error, int *invalid_params) +{ + if (ks->dhe != NULL || ks->dhe_peer != NULL) + return 0; + + if ((ks->dhe_peer = DH_new()) == NULL) + return 0; + if (!ssl_kex_peer_params_dhe(ks->dhe_peer, cbs, decode_error, + invalid_params)) + return 0; + if ((ks->dhe = DHparams_dup(ks->dhe_peer)) == NULL) + return 0; + + return 1; +} + +int +tls_key_share_peer_params(struct tls_key_share *ks, CBS *cbs, + int *decode_error, int *invalid_params) +{ + if (ks->nid != NID_dhKeyAgreement) + return 0; + + return tls_key_share_peer_params_dhe(ks, cbs, decode_error, + invalid_params); +} + +static int +tls_key_share_peer_public_dhe(struct tls_key_share *ks, CBS *cbs, + int *decode_error, int *invalid_key) +{ + if (ks->dhe_peer == NULL) + return 0; + + return ssl_kex_peer_public_dhe(ks->dhe_peer, cbs, decode_error, + invalid_key); +} + +static int +tls_key_share_peer_public_ecdhe_ecp(struct tls_key_share *ks, CBS *cbs) +{ + EC_KEY *ecdhe = NULL; + int ret = 0; + + if (ks->ecdhe_peer != NULL) + goto err; + + if ((ecdhe = EC_KEY_new()) == NULL) + goto err; + if (!ssl_kex_peer_public_ecdhe_ecp(ecdhe, ks->nid, cbs)) + goto err; + + ks->ecdhe_peer = ecdhe; + ecdhe = NULL; + + ret = 1; + + err: + EC_KEY_free(ecdhe); + + return ret; +} + +static int +tls_key_share_peer_public_x25519(struct tls_key_share *ks, CBS *cbs, + int *decode_error) +{ + size_t out_len; + + *decode_error = 0; + + if (ks->x25519_peer_public != NULL) + return 0; + + if (CBS_len(cbs) != X25519_KEY_LENGTH) { + *decode_error = 1; + return 0; + } + + return CBS_stow(cbs, &ks->x25519_peer_public, &out_len); +} + +int +tls_key_share_peer_public(struct tls_key_share *ks, CBS *cbs, int *decode_error, + int *invalid_key) +{ + *decode_error = 0; + + if (invalid_key != NULL) + *invalid_key = 0; + + if (ks->nid == NID_dhKeyAgreement) + return tls_key_share_peer_public_dhe(ks, cbs, decode_error, + invalid_key); + + if (ks->nid == NID_X25519) + return tls_key_share_peer_public_x25519(ks, cbs, decode_error); + + return tls_key_share_peer_public_ecdhe_ecp(ks, cbs); +} + +static int +tls_key_share_derive_dhe(struct tls_key_share *ks, + uint8_t **shared_key, size_t *shared_key_len) +{ + if (ks->dhe == NULL || ks->dhe_peer == NULL) + return 0; + + return ssl_kex_derive_dhe(ks->dhe, ks->dhe_peer, shared_key, + shared_key_len); +} + +static int +tls_key_share_derive_ecdhe_ecp(struct tls_key_share *ks, + uint8_t **shared_key, size_t *shared_key_len) +{ + if (ks->ecdhe == NULL || ks->ecdhe_peer == NULL) + return 0; + + return ssl_kex_derive_ecdhe_ecp(ks->ecdhe, ks->ecdhe_peer, + shared_key, shared_key_len); +} + +static int +tls_key_share_derive_x25519(struct tls_key_share *ks, + uint8_t **shared_key, size_t *shared_key_len) +{ + uint8_t *sk = NULL; + int ret = 0; + + if (ks->x25519_private == NULL || ks->x25519_peer_public == NULL) + goto err; + + if ((sk = calloc(1, X25519_KEY_LENGTH)) == NULL) + goto err; + if (!X25519(sk, ks->x25519_private, ks->x25519_peer_public)) + goto err; + + *shared_key = sk; + *shared_key_len = X25519_KEY_LENGTH; + sk = NULL; + + ret = 1; + + err: + freezero(sk, X25519_KEY_LENGTH); + + return ret; +} + +int +tls_key_share_derive(struct tls_key_share *ks, uint8_t **shared_key, + size_t *shared_key_len) +{ + if (*shared_key != NULL) + return 0; + + *shared_key_len = 0; + + if (ks->nid == NID_dhKeyAgreement) + return tls_key_share_derive_dhe(ks, shared_key, + shared_key_len); + + if (ks->nid == NID_X25519) + return tls_key_share_derive_x25519(ks, shared_key, + shared_key_len); + + return tls_key_share_derive_ecdhe_ecp(ks, shared_key, + shared_key_len); +} diff --git a/tls/CMakeLists.txt b/tls/CMakeLists.txt index 9aa10e1..7827a5e 100644 --- a/tls/CMakeLists.txt +++ b/tls/CMakeLists.txt @@ -7,6 +7,7 @@ set( tls_conninfo.c tls_keypair.c tls_server.c + tls_signer.c tls_ocsp.c tls_peer.c tls_util.c @@ -48,12 +49,6 @@ target_include_directories(tls_obj add_library(tls $ $ $) -target_include_directories(tls - PRIVATE - . - ../include/compat - PUBLIC - ../include) export_symbol(tls ${CMAKE_CURRENT_BINARY_DIR}/tls.sym) target_link_libraries(tls ${PLATFORM_LIBS}) @@ -74,3 +69,11 @@ if(ENABLE_LIBRESSL_INSTALL) RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) endif(ENABLE_LIBRESSL_INSTALL) + +# build static library for regression test +if(BUILD_SHARED_LIBS) + add_library(tls-static STATIC $ + $ $) + target_link_libraries(tls-static ${PLATFORM_LIBS}) +endif() + diff --git a/tls/VERSION b/tls/VERSION index 2005c06..4afa027 100644 --- a/tls/VERSION +++ b/tls/VERSION @@ -1 +1 @@ -22:0:0 +25:0:0 diff --git a/tls/tls.c b/tls/tls.c index 262ec3d..ff33ebe 100644 --- a/tls/tls.c +++ b/tls/tls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls.c,v 1.89 2021/02/01 15:35:41 tb Exp $ */ +/* $OpenBSD: tls.c,v 1.94 2022/02/08 19:13:50 tb Exp $ */ /* * Copyright (c) 2014 Joel Sing * @@ -387,6 +387,8 @@ tls_keypair_to_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY **pke static int tls_keypair_setup_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY *pkey) { + RSA_METHOD *rsa_method; + ECDSA_METHOD *ecdsa_method; RSA *rsa = NULL; EC_KEY *eckey = NULL; int ret = -1; @@ -407,6 +409,14 @@ tls_keypair_setup_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY *p tls_set_errorx(ctx, "RSA key setup failure"); goto err; } + if (ctx->config->sign_cb == NULL) + break; + if ((rsa_method = tls_signer_rsa_method()) == NULL || + RSA_set_ex_data(rsa, 1, ctx->config) == 0 || + RSA_set_method(rsa, rsa_method) == 0) { + tls_set_errorx(ctx, "failed to setup RSA key"); + goto err; + } break; case EVP_PKEY_EC: if ((eckey = EVP_PKEY_get1_EC_KEY(pkey)) == NULL || @@ -414,6 +424,14 @@ tls_keypair_setup_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY *p tls_set_errorx(ctx, "EC key setup failure"); goto err; } + if (ctx->config->sign_cb == NULL) + break; + if ((ecdsa_method = tls_signer_ecdsa_method()) == NULL || + ECDSA_set_ex_data(eckey, 1, ctx->config) == 0 || + ECDSA_set_method(eckey, ecdsa_method) == 0) { + tls_set_errorx(ctx, "failed to setup EC key"); + goto err; + } break; default: tls_set_errorx(ctx, "incorrect key type"); @@ -521,7 +539,7 @@ tls_configure_ssl(struct tls *ctx, SSL_CTX *ssl_ctx) } if (ctx->config->verify_time == 0) { - X509_VERIFY_PARAM_set_flags(ssl_ctx->param, + X509_VERIFY_PARAM_set_flags(SSL_CTX_get0_param(ssl_ctx), X509_V_FLAG_NO_CHECK_TIME); } @@ -629,9 +647,8 @@ tls_configure_ssl_verify(struct tls *ctx, SSL_CTX *ssl_ctx, int verify) tls_set_error(ctx, "failed to add crl"); goto err; } - xi->crl = NULL; } - X509_VERIFY_PARAM_set_flags(store->param, + X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); } @@ -747,7 +764,7 @@ tls_ssl_error(struct tls *ctx, SSL *ssl_conn, int ssl_ret, const char *prefix) case SSL_ERROR_WANT_ACCEPT: case SSL_ERROR_WANT_X509_LOOKUP: default: - tls_set_ssl_errorx(ctx, "%s failed (%i)", prefix, ssl_err); + tls_set_ssl_errorx(ctx, "%s failed (%d)", prefix, ssl_err); return (-1); } } diff --git a/tls/tls_bio_cb.c b/tls/tls_bio_cb.c index 0091808..dad9d23 100644 --- a/tls/tls_bio_cb.c +++ b/tls/tls_bio_cb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_bio_cb.c,v 1.19 2017/01/12 16:18:39 jsing Exp $ */ +/* $OpenBSD: tls_bio_cb.c,v 1.20 2022/01/10 23:39:48 tb Exp $ */ /* * Copyright (c) 2016 Tobias Pape * @@ -29,19 +29,41 @@ static int bio_cb_read(BIO *bio, char *buf, int size); static int bio_cb_puts(BIO *bio, const char *str); static long bio_cb_ctrl(BIO *bio, int cmd, long num, void *ptr); -static BIO_METHOD bio_cb_method = { - .type = BIO_TYPE_MEM, - .name = "libtls_callbacks", - .bwrite = bio_cb_write, - .bread = bio_cb_read, - .bputs = bio_cb_puts, - .ctrl = bio_cb_ctrl, -}; +static BIO_METHOD *bio_cb_method; + +static pthread_mutex_t bio_cb_method_lock = PTHREAD_MUTEX_INITIALIZER; + +static void +bio_cb_method_init(void) +{ + BIO_METHOD *bio_method; + + if (bio_cb_method != NULL) + return; + + bio_method = BIO_meth_new(BIO_TYPE_MEM, "libtls_callbacks"); + if (bio_method == NULL) + return; + + BIO_meth_set_write(bio_method, bio_cb_write); + BIO_meth_set_read(bio_method, bio_cb_read); + BIO_meth_set_puts(bio_method, bio_cb_puts); + BIO_meth_set_ctrl(bio_method, bio_cb_ctrl); + + bio_cb_method = bio_method; +} static BIO_METHOD * bio_s_cb(void) { - return (&bio_cb_method); + if (bio_cb_method != NULL) + return (bio_cb_method); + + pthread_mutex_lock(&bio_cb_method_lock); + bio_cb_method_init(); + pthread_mutex_unlock(&bio_cb_method_lock); + + return (bio_cb_method); } static int @@ -57,10 +79,10 @@ bio_cb_ctrl(BIO *bio, int cmd, long num, void *ptr) switch (cmd) { case BIO_CTRL_GET_CLOSE: - ret = (long)bio->shutdown; + ret = (long)BIO_get_shutdown(bio); break; case BIO_CTRL_SET_CLOSE: - bio->shutdown = (int)num; + BIO_set_shutdown(bio, (int)num); break; case BIO_CTRL_DUP: case BIO_CTRL_FLUSH: @@ -69,7 +91,7 @@ bio_cb_ctrl(BIO *bio, int cmd, long num, void *ptr) case BIO_CTRL_GET: case BIO_CTRL_SET: default: - ret = BIO_ctrl(bio->next_bio, cmd, num, ptr); + ret = BIO_ctrl(BIO_next(bio), cmd, num, ptr); } return (ret); @@ -78,7 +100,7 @@ bio_cb_ctrl(BIO *bio, int cmd, long num, void *ptr) static int bio_cb_write(BIO *bio, const char *buf, int num) { - struct tls *ctx = bio->ptr; + struct tls *ctx = BIO_get_data(bio); int rv; BIO_clear_retry_flags(bio); @@ -96,7 +118,7 @@ bio_cb_write(BIO *bio, const char *buf, int num) static int bio_cb_read(BIO *bio, char *buf, int size) { - struct tls *ctx = bio->ptr; + struct tls *ctx = BIO_get_data(bio); int rv; BIO_clear_retry_flags(bio); @@ -115,8 +137,9 @@ int tls_set_cbs(struct tls *ctx, tls_read_cb read_cb, tls_write_cb write_cb, void *cb_arg) { - int rv = -1; + const BIO_METHOD *bio_cb; BIO *bio; + int rv = -1; if (read_cb == NULL || write_cb == NULL) { tls_set_errorx(ctx, "no callbacks provided"); @@ -127,12 +150,16 @@ tls_set_cbs(struct tls *ctx, tls_read_cb read_cb, tls_write_cb write_cb, ctx->write_cb = write_cb; ctx->cb_arg = cb_arg; - if ((bio = BIO_new(bio_s_cb())) == NULL) { + if ((bio_cb = bio_s_cb()) == NULL) { + tls_set_errorx(ctx, "failed to create callback method"); + goto err; + } + if ((bio = BIO_new(bio_cb)) == NULL) { tls_set_errorx(ctx, "failed to create callback i/o"); goto err; } - bio->ptr = ctx; - bio->init = 1; + BIO_set_data(bio, ctx); + BIO_set_init(bio, 1); SSL_set_bio(ctx->ssl_conn, bio, bio); diff --git a/tls/tls_client.c b/tls/tls_client.c index c45684d..1629697 100644 --- a/tls/tls_client.c +++ b/tls/tls_client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_client.c,v 1.47 2021/06/01 20:26:11 tb Exp $ */ +/* $OpenBSD: tls_client.c,v 1.48 2021/10/21 08:38:11 tb Exp $ */ /* * Copyright (c) 2014 Joel Sing * @@ -74,11 +74,8 @@ tls_connect_servername(struct tls *ctx, const char *host, const char *port, goto err; } - /* - * If port is NULL try to extract a port from the specified host, - * otherwise use the default. - */ - if ((p = (char *)port) == NULL) { + /* If port is NULL, try to extract a port from the specified host. */ + if (port == NULL) { ret = tls_host_port(host, &hs, &ps); if (ret == -1) { tls_set_errorx(ctx, "memory allocation failure"); diff --git a/tls/tls_config.c b/tls/tls_config.c index 9144dad..15e218b 100644 --- a/tls/tls_config.c +++ b/tls/tls_config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_config.c,v 1.63 2021/01/21 22:03:25 eric Exp $ */ +/* $OpenBSD: tls_config.c,v 1.65 2022/01/25 21:51:24 eric Exp $ */ /* * Copyright (c) 2014 Joel Sing * @@ -722,7 +722,7 @@ tls_config_set_session_fd(struct tls_config *config, int session_fd) if (sb.st_uid != getuid()) { tls_config_set_errorx(config, "session file has incorrect " - "owner (uid %i != %i)", sb.st_uid, getuid()); + "owner (uid %u != %u)", sb.st_uid, getuid()); return (-1); } mugo = sb.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO); @@ -737,6 +737,17 @@ tls_config_set_session_fd(struct tls_config *config, int session_fd) return (0); } +int +tls_config_set_sign_cb(struct tls_config *config, tls_sign_cb cb, void *cb_arg) +{ + config->use_fake_private_key = 1; + config->skip_private_key_check = 1; + config->sign_cb = cb; + config->sign_cb_arg = cb_arg; + + return (0); +} + int tls_config_set_verify_depth(struct tls_config *config, int verify_depth) { diff --git a/tls/tls_internal.h b/tls/tls_internal.h index 5487b12..ca1d96f 100644 --- a/tls/tls_internal.h +++ b/tls/tls_internal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_internal.h,v 1.78 2021/01/21 19:09:10 eric Exp $ */ +/* $OpenBSD: tls_internal.h,v 1.80 2022/03/24 15:56:34 tb Exp $ */ /* * Copyright (c) 2014 Jeremie Courreges-Anglas * Copyright (c) 2014 Joel Sing @@ -78,6 +78,10 @@ struct tls_ticket_key { time_t time; }; +typedef int (*tls_sign_cb)(void *_cb_arg, const char *_pubkey_hash, + const uint8_t *_input, size_t _input_len, int _padding_type, + uint8_t **_out_signature, size_t *_out_signature_len); + struct tls_config { struct tls_error error; @@ -112,6 +116,8 @@ struct tls_config { int verify_time; int skip_private_key_check; int use_fake_private_key; + tls_sign_cb sign_cb; + void *sign_cb_arg; }; struct tls_conninfo { @@ -291,6 +297,27 @@ int tls_cert_pubkey_hash(X509 *_cert, char **_hash); int tls_password_cb(char *_buf, int _size, int _rwflag, void *_u); +RSA_METHOD *tls_signer_rsa_method(void); +ECDSA_METHOD *tls_signer_ecdsa_method(void); + +#define TLS_PADDING_NONE 0 +#define TLS_PADDING_RSA_PKCS1 1 +#define TLS_PADDING_RSA_X9_31 2 + +int tls_config_set_sign_cb(struct tls_config *_config, tls_sign_cb _cb, + void *_cb_arg); + +struct tls_signer* tls_signer_new(void); +void tls_signer_free(struct tls_signer * _signer); +const char *tls_signer_error(struct tls_signer * _signer); +int tls_signer_add_keypair_file(struct tls_signer *_signer, + const char *_cert_file, const char *_key_file); +int tls_signer_add_keypair_mem(struct tls_signer *_signer, const uint8_t *_cert, + size_t _cert_len, const uint8_t *_key, size_t _key_len); +int tls_signer_sign(struct tls_signer *_signer, const char *_pubkey_hash, + const uint8_t *_input, size_t _input_len, int _padding_type, + uint8_t **_out_signature, size_t *_out_signature_len); + __END_HIDDEN_DECLS /* XXX this function is not fully hidden so relayd can use it */ diff --git a/tls/tls_ocsp.c b/tls/tls_ocsp.c index f00e6bc..83585fa 100644 --- a/tls/tls_ocsp.c +++ b/tls/tls_ocsp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_ocsp.c,v 1.20 2021/03/23 20:04:29 tb Exp $ */ +/* $OpenBSD: tls_ocsp.c,v 1.22 2021/10/31 16:39:32 tb Exp $ */ /* * Copyright (c) 2015 Marko Kreen * Copyright (c) 2016 Bob Beck @@ -128,30 +128,38 @@ tls_ocsp_get_certid(X509 *main_cert, STACK_OF(X509) *extra_certs, { X509_NAME *issuer_name; X509 *issuer; - X509_STORE_CTX storectx; - X509_OBJECT tmpobj; + X509_STORE_CTX *storectx = NULL; + X509_OBJECT *obj = NULL; OCSP_CERTID *cid = NULL; X509_STORE *store; if ((issuer_name = X509_get_issuer_name(main_cert)) == NULL) - return NULL; + goto out; if (extra_certs != NULL) { issuer = X509_find_by_subject(extra_certs, issuer_name); - if (issuer != NULL) - return OCSP_cert_to_id(NULL, main_cert, issuer); + if (issuer != NULL) { + cid = OCSP_cert_to_id(NULL, main_cert, issuer); + goto out; + } } if ((store = SSL_CTX_get_cert_store(ssl_ctx)) == NULL) - return NULL; - if (X509_STORE_CTX_init(&storectx, store, main_cert, extra_certs) != 1) - return NULL; - if (X509_STORE_get_by_subject(&storectx, X509_LU_X509, issuer_name, - &tmpobj) == 1) { - cid = OCSP_cert_to_id(NULL, main_cert, tmpobj.data.x509); - X509_OBJECT_free_contents(&tmpobj); - } - X509_STORE_CTX_cleanup(&storectx); + goto out; + if ((storectx = X509_STORE_CTX_new()) == NULL) + goto out; + if (X509_STORE_CTX_init(storectx, store, main_cert, extra_certs) != 1) + goto out; + if ((obj = X509_STORE_CTX_get_obj_by_subject(storectx, X509_LU_X509, + issuer_name)) == NULL) + goto out; + + cid = OCSP_cert_to_id(NULL, main_cert, X509_OBJECT_get0_X509(obj)); + + out: + X509_STORE_CTX_free(storectx); + X509_OBJECT_free(obj); + return cid; } diff --git a/tls/tls_server.c b/tls/tls_server.c index 0a8ec47..72f797b 100644 --- a/tls/tls_server.c +++ b/tls/tls_server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_server.c,v 1.47 2021/06/14 03:53:59 tb Exp $ */ +/* $OpenBSD: tls_server.c,v 1.48 2022/01/19 11:10:55 inoguchi Exp $ */ /* * Copyright (c) 2014 Joel Sing * @@ -185,10 +185,16 @@ tls_server_ticket_cb(SSL *ssl, unsigned char *keyname, unsigned char *iv, memcpy(keyname, key->key_name, sizeof(key->key_name)); arc4random_buf(iv, EVP_MAX_IV_LENGTH); - EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, - key->aes_key, iv); - HMAC_Init_ex(hctx, key->hmac_key, sizeof(key->hmac_key), - EVP_sha256(), NULL); + if (!EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, + key->aes_key, iv)) { + tls_set_errorx(tls_ctx, "failed to init encrypt"); + return (-1); + } + if (!HMAC_Init_ex(hctx, key->hmac_key, sizeof(key->hmac_key), + EVP_sha256(), NULL)) { + tls_set_errorx(tls_ctx, "failed to init hmac"); + return (-1); + } return (0); } else { /* get key by name */ @@ -196,10 +202,16 @@ tls_server_ticket_cb(SSL *ssl, unsigned char *keyname, unsigned char *iv, if (key == NULL) return (0); - EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, - key->aes_key, iv); - HMAC_Init_ex(hctx, key->hmac_key, sizeof(key->hmac_key), - EVP_sha256(), NULL); + if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, + key->aes_key, iv)) { + tls_set_errorx(tls_ctx, "failed to init decrypt"); + return (-1); + } + if (!HMAC_Init_ex(hctx, key->hmac_key, sizeof(key->hmac_key), + EVP_sha256(), NULL)) { + tls_set_errorx(tls_ctx, "failed to init hmac"); + return (-1); + } /* time to renew the ticket? is it the primary key? */ if (key != &tls_ctx->config->ticket_keys[0]) diff --git a/tls/tls_signer.c b/tls/tls_signer.c new file mode 100644 index 0000000..1f11096 --- /dev/null +++ b/tls/tls_signer.c @@ -0,0 +1,451 @@ +/* $OpenBSD: tls_signer.c,v 1.4 2022/02/01 17:18:38 jsing Exp $ */ +/* + * Copyright (c) 2021 Eric Faurot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include + +#include "tls.h" +#include "tls_internal.h" + +struct tls_signer_key { + char *hash; + RSA *rsa; + EC_KEY *ecdsa; + struct tls_signer_key *next; +}; + +struct tls_signer { + struct tls_error error; + struct tls_signer_key *keys; +}; + +static pthread_mutex_t signer_method_lock = PTHREAD_MUTEX_INITIALIZER; + +struct tls_signer * +tls_signer_new(void) +{ + struct tls_signer *signer; + + if ((signer = calloc(1, sizeof(*signer))) == NULL) + return (NULL); + + return (signer); +} + +void +tls_signer_free(struct tls_signer *signer) +{ + struct tls_signer_key *skey; + + if (signer == NULL) + return; + + tls_error_clear(&signer->error); + + while (signer->keys) { + skey = signer->keys; + signer->keys = skey->next; + RSA_free(skey->rsa); + EC_KEY_free(skey->ecdsa); + free(skey->hash); + free(skey); + } + + free(signer); +} + +const char * +tls_signer_error(struct tls_signer *signer) +{ + return (signer->error.msg); +} + +int +tls_signer_add_keypair_mem(struct tls_signer *signer, const uint8_t *cert, + size_t cert_len, const uint8_t *key, size_t key_len) +{ + struct tls_signer_key *skey = NULL; + char *errstr = "unknown"; + int ssl_err; + EVP_PKEY *pkey = NULL; + X509 *x509 = NULL; + BIO *bio = NULL; + char *hash = NULL; + + /* Compute certificate hash */ + if ((bio = BIO_new_mem_buf(cert, cert_len)) == NULL) { + tls_error_setx(&signer->error, + "failed to create certificate bio"); + goto err; + } + if ((x509 = PEM_read_bio_X509(bio, NULL, tls_password_cb, + NULL)) == NULL) { + if ((ssl_err = ERR_peek_error()) != 0) + errstr = ERR_error_string(ssl_err, NULL); + tls_error_setx(&signer->error, "failed to load certificate: %s", + errstr); + goto err; + } + if (tls_cert_pubkey_hash(x509, &hash) == -1) { + tls_error_setx(&signer->error, + "failed to get certificate hash"); + goto err; + } + + X509_free(x509); + x509 = NULL; + BIO_free(bio); + bio = NULL; + + /* Read private key */ + if ((bio = BIO_new_mem_buf(key, key_len)) == NULL) { + tls_error_setx(&signer->error, "failed to create key bio"); + goto err; + } + if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, tls_password_cb, + NULL)) == NULL) { + tls_error_setx(&signer->error, "failed to read private key"); + goto err; + } + + if ((skey = calloc(1, sizeof(*skey))) == NULL) { + tls_error_set(&signer->error, "failed to create key entry"); + goto err; + } + skey->hash = hash; + if ((skey->rsa = EVP_PKEY_get1_RSA(pkey)) == NULL && + (skey->ecdsa = EVP_PKEY_get1_EC_KEY(pkey)) == NULL) { + tls_error_setx(&signer->error, "unknown key type"); + goto err; + } + + skey->next = signer->keys; + signer->keys = skey; + EVP_PKEY_free(pkey); + BIO_free(bio); + + return (0); + + err: + EVP_PKEY_free(pkey); + X509_free(x509); + BIO_free(bio); + free(hash); + free(skey); + + return (-1); +} + +int +tls_signer_add_keypair_file(struct tls_signer *signer, const char *cert_file, + const char *key_file) +{ + char *cert = NULL, *key = NULL; + size_t cert_len, key_len; + int rv = -1; + + if (tls_config_load_file(&signer->error, "certificate", cert_file, + &cert, &cert_len) == -1) + goto err; + + if (tls_config_load_file(&signer->error, "key", key_file, &key, + &key_len) == -1) + goto err; + + rv = tls_signer_add_keypair_mem(signer, cert, cert_len, key, key_len); + + err: + free(cert); + free(key); + + return (rv); +} + +static int +tls_sign_rsa(struct tls_signer *signer, struct tls_signer_key *skey, + const uint8_t *input, size_t input_len, int padding_type, + uint8_t **out_signature, size_t *out_signature_len) +{ + int rsa_padding, rsa_size, signature_len; + char *signature = NULL; + + *out_signature = NULL; + *out_signature_len = 0; + + if (padding_type == TLS_PADDING_NONE) { + rsa_padding = RSA_NO_PADDING; + } else if (padding_type == TLS_PADDING_RSA_PKCS1) { + rsa_padding = RSA_PKCS1_PADDING; + } else if (padding_type == TLS_PADDING_RSA_X9_31) { + rsa_padding = RSA_X931_PADDING; + } else { + tls_error_setx(&signer->error, "invalid RSA padding type (%d)", + padding_type); + return (-1); + } + + if (input_len > INT_MAX) { + tls_error_setx(&signer->error, "input too large"); + return (-1); + } + if ((rsa_size = RSA_size(skey->rsa)) <= 0) { + tls_error_setx(&signer->error, "invalid RSA size: %d", + rsa_size); + return (-1); + } + if ((signature = calloc(1, rsa_size)) == NULL) { + tls_error_set(&signer->error, "RSA signature"); + return (-1); + } + + if ((signature_len = RSA_private_encrypt((int)input_len, input, + signature, skey->rsa, rsa_padding)) <= 0) { + /* XXX - include further details from libcrypto. */ + tls_error_setx(&signer->error, "RSA signing failed"); + free(signature); + return (-1); + } + + *out_signature = signature; + *out_signature_len = (size_t)signature_len; + + return (0); +} + +static int +tls_sign_ecdsa(struct tls_signer *signer, struct tls_signer_key *skey, + const uint8_t *input, size_t input_len, int padding_type, + uint8_t **out_signature, size_t *out_signature_len) +{ + unsigned char *signature; + int signature_len; + + *out_signature = NULL; + *out_signature_len = 0; + + if (padding_type != TLS_PADDING_NONE) { + tls_error_setx(&signer->error, "invalid ECDSA padding"); + return (-1); + } + + if (input_len > INT_MAX) { + tls_error_setx(&signer->error, "digest too large"); + return (-1); + } + if ((signature_len = ECDSA_size(skey->ecdsa)) <= 0) { + tls_error_setx(&signer->error, "invalid ECDSA size: %d", + signature_len); + return (-1); + } + if ((signature = calloc(1, signature_len)) == NULL) { + tls_error_set(&signer->error, "ECDSA signature"); + return (-1); + } + + if (!ECDSA_sign(0, input, input_len, signature, &signature_len, + skey->ecdsa)) { + /* XXX - include further details from libcrypto. */ + tls_error_setx(&signer->error, "ECDSA signing failed"); + free(signature); + return (-1); + } + + *out_signature = signature; + *out_signature_len = signature_len; + + return (0); +} + +int +tls_signer_sign(struct tls_signer *signer, const char *pubkey_hash, + const uint8_t *input, size_t input_len, int padding_type, + uint8_t **out_signature, size_t *out_signature_len) +{ + struct tls_signer_key *skey; + + *out_signature = NULL; + *out_signature_len = 0; + + for (skey = signer->keys; skey; skey = skey->next) + if (!strcmp(pubkey_hash, skey->hash)) + break; + + if (skey == NULL) { + tls_error_setx(&signer->error, "key not found"); + return (-1); + } + + if (skey->rsa != NULL) + return tls_sign_rsa(signer, skey, input, input_len, + padding_type, out_signature, out_signature_len); + + if (skey->ecdsa != NULL) + return tls_sign_ecdsa(signer, skey, input, input_len, + padding_type, out_signature, out_signature_len); + + tls_error_setx(&signer->error, "unknown key type"); + + return (-1); +} + +static int +tls_rsa_priv_enc(int from_len, const unsigned char *from, unsigned char *to, + RSA *rsa, int rsa_padding) +{ + struct tls_config *config; + uint8_t *signature = NULL; + size_t signature_len = 0; + const char *pubkey_hash; + int padding_type; + + /* + * This function is called via RSA_private_encrypt() and has to conform + * to its calling convention/signature. The caller is required to + * provide a 'to' buffer of at least RSA_size() bytes. + */ + + pubkey_hash = RSA_get_ex_data(rsa, 0); + config = RSA_get_ex_data(rsa, 1); + + if (pubkey_hash == NULL || config == NULL) + goto err; + + if (rsa_padding == RSA_NO_PADDING) { + padding_type = TLS_PADDING_NONE; + } else if (rsa_padding == RSA_PKCS1_PADDING) { + padding_type = TLS_PADDING_RSA_PKCS1; + } else if (rsa_padding == RSA_X931_PADDING) { + padding_type = TLS_PADDING_RSA_X9_31; + } else { + goto err; + } + + if (from_len < 0) + goto err; + + if (config->sign_cb(config->sign_cb_arg, pubkey_hash, from, from_len, + padding_type, &signature, &signature_len) == -1) + goto err; + + if (signature_len > INT_MAX || (int)signature_len > RSA_size(rsa)) + goto err; + + memcpy(to, signature, signature_len); + free(signature); + + return ((int)signature_len); + + err: + free(signature); + + return (-1); +} + +RSA_METHOD * +tls_signer_rsa_method(void) +{ + static RSA_METHOD *rsa_method = NULL; + + pthread_mutex_lock(&signer_method_lock); + + if (rsa_method != NULL) + goto out; + + rsa_method = RSA_meth_new("libtls RSA method", 0); + if (rsa_method == NULL) + goto out; + + RSA_meth_set_priv_enc(rsa_method, tls_rsa_priv_enc); + + out: + pthread_mutex_unlock(&signer_method_lock); + + return (rsa_method); +} + +static ECDSA_SIG * +tls_ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, + const BIGNUM *rp, EC_KEY *eckey) +{ + struct tls_config *config; + ECDSA_SIG *ecdsa_sig = NULL; + uint8_t *signature = NULL; + size_t signature_len = 0; + const unsigned char *p; + const char *pubkey_hash; + + /* + * This function is called via ECDSA_do_sign_ex() and has to conform + * to its calling convention/signature. + */ + + pubkey_hash = ECDSA_get_ex_data(eckey, 0); + config = ECDSA_get_ex_data(eckey, 1); + + if (pubkey_hash == NULL || config == NULL) + goto err; + + if (dgst_len < 0) + goto err; + + if (config->sign_cb(config->sign_cb_arg, pubkey_hash, dgst, dgst_len, + TLS_PADDING_NONE, &signature, &signature_len) == -1) + goto err; + + p = signature; + if ((ecdsa_sig = d2i_ECDSA_SIG(NULL, &p, signature_len)) == NULL) + goto err; + + free(signature); + + return (ecdsa_sig); + + err: + free(signature); + + return (NULL); +} + +ECDSA_METHOD * +tls_signer_ecdsa_method(void) +{ + static ECDSA_METHOD *ecdsa_method = NULL; + + pthread_mutex_lock(&signer_method_lock); + + if (ecdsa_method != NULL) + goto out; + + ecdsa_method = calloc(1, sizeof(*ecdsa_method)); + if (ecdsa_method == NULL) + goto out; + + ecdsa_method->ecdsa_do_sign = tls_ecdsa_do_sign; + ecdsa_method->name = strdup("libtls ECDSA method"); + if (ecdsa_method->name == NULL) { + free(ecdsa_method); + ecdsa_method = NULL; + } + + out: + pthread_mutex_unlock(&signer_method_lock); + + return (ecdsa_method); +}