From 2015c00c4358acac47938318ba24f215d8b3729a Mon Sep 17 00:00:00 2001 From: Hakase Date: Wed, 15 Apr 2020 18:45:34 +0900 Subject: [PATCH] Latest update. --- CHANGES.md | 51 +- Configurations/15-android.conf | 9 +- Configurations/unix-Makefile.tmpl | 1 + Configurations/windows-makefile.tmpl | 19 +- NEWS.md | 11 + NOTES.ANDROID | 16 +- apps/CA.pl.in | 130 +- apps/build.info | 33 +- apps/ca.c | 113 +- apps/cmp_mock_srv.c | 407 ++++++ apps/cmp_mock_srv.h | 34 + apps/dh1024.pem | 10 - apps/dh2048.pem | 14 - apps/dh4096.pem | 19 - apps/dhparam.c | 56 +- apps/dsa.c | 52 +- apps/dsaparam.c | 32 +- apps/ec.c | 26 +- apps/ecparam.c | 33 +- apps/engine.c | 22 +- apps/gendsa.c | 32 +- apps/genrsa.c | 40 +- apps/include/apps.h | 12 +- apps/include/opt.h | 4 +- apps/lib/app_provider.c | 23 + apps/lib/app_x509.c | 134 ++ apps/lib/apps.c | 15 +- apps/lib/build.info | 2 +- apps/ocsp.c | 149 ++- apps/openssl.c | 1 + apps/pkcs12.c | 49 +- apps/pkeyutl.c | 16 - apps/rehash.c | 16 +- apps/req.c | 218 ++-- apps/rsa.c | 56 +- apps/rsautl.c | 34 +- apps/s_server.c | 127 +- apps/spkac.c | 11 +- apps/srp.c | 38 +- apps/ts.c | 46 +- apps/verify.c | 83 +- apps/x509.c | 29 +- crypto/asn1/asn1_item_list.h | 3 +- crypto/asn1/asn1_lib.c | 118 +- crypto/bf/build.info | 10 +- crypto/bio/b_sock2.c | 12 + crypto/bio/bio_lib.c | 2 +- crypto/bio/bss_acpt.c | 13 +- crypto/bio/bss_conn.c | 54 +- crypto/build.info | 5 +- crypto/cast/build.info | 10 +- crypto/cmp/build.info | 3 +- crypto/cmp/cmp_client.c | 881 +++++++++++++ crypto/cmp/cmp_ctx.c | 229 +--- crypto/cmp/cmp_err.c | 41 +- crypto/cmp/cmp_hdr.c | 68 +- crypto/cmp/cmp_http.c | 66 + crypto/cmp/cmp_local.h | 91 +- crypto/cmp/cmp_msg.c | 142 ++- crypto/cmp/cmp_protect.c | 15 +- crypto/cmp/cmp_server.c | 619 +++++++++ crypto/cmp/cmp_status.c | 100 +- crypto/cmp/cmp_util.c | 22 +- crypto/cmp/cmp_vfy.c | 174 ++- crypto/cms/cms_err.c | 2 +- crypto/cms/cms_kari.c | 47 + crypto/conf/conf_lib.c | 10 +- crypto/conf/conf_mod.c | 39 +- crypto/conf/conf_sap.c | 6 - crypto/context.c | 17 + crypto/crmf/crmf_err.c | 13 +- crypto/crmf/crmf_lib.c | 145 +-- crypto/crmf/crmf_local.h | 4 +- crypto/ct/ct_b64.c | 19 +- crypto/ct/ct_local.h | 8 +- crypto/ct/ct_log.c | 74 +- crypto/ct/ct_policy.c | 20 +- crypto/ct/ct_sct.c | 2 +- crypto/ct/ct_sct_ctx.c | 28 +- crypto/ct/ct_vfy.c | 3 +- crypto/der_writer.c | 142 +++ crypto/des/build.info | 17 +- crypto/dh/build.info | 2 +- crypto/dh/dh1024.pem | 5 - crypto/dh/dh192.pem | 3 - crypto/dh/dh2048.pem | 16 - crypto/dh/dh4096.pem | 14 - crypto/dh/dh512.pem | 4 - crypto/dh/dh_ameth.c | 79 +- crypto/dh/dh_backend.c | 56 + crypto/dh/dh_lib.c | 7 +- crypto/dsa/build.info | 4 +- crypto/dsa/dsa_aid.c | 70 -- crypto/dsa/dsa_ameth.c | 79 +- crypto/dsa/dsa_backend.c | 57 + crypto/dsa/dsa_lib.c | 2 +- crypto/ec/build.info | 4 +- crypto/ec/curve25519.c | 10 +- crypto/ec/curve448/curve448_local.h | 9 - crypto/ec/curve448/eddsa.c | 1 + crypto/ec/ec_ameth.c | 98 +- crypto/ec/ec_backend.c | 231 ++++ crypto/ec/ec_check.c | 20 +- crypto/ec/{ec_evp_lib.c => ec_ctrl.c} | 66 + crypto/ec/ec_curve.c | 291 +++-- crypto/ec/ec_key.c | 189 ++- crypto/ec/ec_lib.c | 52 +- crypto/ec/ec_local.h | 4 - crypto/ec/ec_mult.c | 29 +- crypto/ec/ecp_smpl.c | 307 +++-- crypto/ec/ecx_backend.c | 62 + crypto/ec/ecx_backend.h | 20 + crypto/ec/ecx_key.c | 18 +- crypto/ec/ecx_meth.c | 99 +- crypto/engine/eng_list.c | 2 + crypto/err/err_prn.c | 4 +- crypto/err/openssl.txt | 60 +- crypto/err/openssl.txt.old | 52 +- crypto/ess/ess_lib.c | 5 +- crypto/evp/digest.c | 6 +- crypto/evp/evp_err.c | 10 +- crypto/evp/evp_fetch.c | 54 +- crypto/evp/evp_local.h | 12 + crypto/evp/exchange.c | 2 +- crypto/evp/keymgmt_lib.c | 148 ++- crypto/evp/keymgmt_meth.c | 123 +- crypto/evp/m_sigver.c | 118 +- crypto/evp/p_lib.c | 869 ++++++++++--- crypto/evp/pkey_mac.c | 88 +- crypto/evp/pmeth_check.c | 49 +- crypto/evp/pmeth_fn.c | 2 +- crypto/evp/pmeth_gn.c | 314 +++-- crypto/evp/pmeth_lib.c | 122 +- crypto/evp/signature.c | 34 +- crypto/ex_data.c | 49 +- crypto/ffc/build.info | 2 +- crypto/ffc/ffc_backend.c | 44 + crypto/http/http_client.c | 113 +- crypto/http/http_err.c | 14 +- crypto/http/http_lib.c | 71 +- crypto/http/http_local.h | 5 +- crypto/idea/build.info | 11 +- crypto/ocsp/ocsp_cl.c | 2 +- crypto/ocsp/ocsp_ext.c | 2 +- crypto/ocsp/ocsp_lib.c | 2 +- crypto/ocsp/ocsp_srv.c | 57 +- crypto/ocsp/ocsp_vfy.c | 8 +- crypto/packet.c | 55 +- crypto/param_build.c | 129 +- crypto/param_build_set.c | 111 ++ crypto/params.c | 2 + crypto/pkcs12/p12_crt.c | 5 +- crypto/provider_conf.c | 2 +- crypto/provider_core.c | 9 +- crypto/provider_predefined.c | 2 + crypto/rand/drbg_ctr.c | 235 ++-- crypto/rand/rand_local.h | 6 +- crypto/rc2/build.info | 12 +- crypto/rc4/build.info | 6 + crypto/rc5/build.info | 11 +- crypto/rsa/build.info | 5 +- crypto/rsa/rsa_aid.c | 98 -- crypto/rsa/rsa_ameth.c | 80 +- crypto/rsa/rsa_backend.c | 99 ++ crypto/rsa/rsa_lib.c | 98 +- crypto/rsa/rsa_local.h | 34 +- crypto/rsa/rsa_mp_names.c | 76 ++ crypto/rsa/rsa_oaep.c | 39 +- crypto/rsa/rsa_ossl.c | 10 +- crypto/rsa/rsa_pk1.c | 31 +- crypto/rsa/rsa_pss.c | 2 +- crypto/rsa/rsa_sign.c | 55 +- crypto/rsa/rsa_ssl.c | 19 +- crypto/seed/build.info | 10 +- crypto/serializer/serializer_pkey.c | 20 +- crypto/sm2/sm2_pmeth.c | 10 +- crypto/srp/srp_lib.c | 75 +- crypto/srp/srp_vfy.c | 36 +- crypto/store/store_lib.c | 4 +- crypto/store/store_local.h | 2 +- crypto/ts/ts_rsp_verify.c | 39 +- crypto/ui/ui_lib.c | 2 +- crypto/x509/build.info | 2 +- crypto/x509/by_dir.c | 8 +- crypto/x509/by_store.c | 5 +- crypto/x509/ext_dat.h | 1 + crypto/x509/pcy_lib.c | 2 +- crypto/x509/standard_exts.h | 1 + crypto/x509/t_x509.c | 4 +- crypto/x509/v3_crld.c | 2 +- crypto/x509/v3_ist.c | 149 +++ crypto/x509/v3_ncons.c | 6 +- crypto/x509/v3_purp.c | 135 +- crypto/x509/v3_utl.c | 6 +- crypto/x509/x509_cmp.c | 21 +- crypto/x509/x509_local.h | 14 +- crypto/x509/x509_lu.c | 67 +- crypto/x509/x509_r2x.c | 2 +- crypto/x509/x509_set.c | 4 +- crypto/x509/x509_trs.c | 7 +- crypto/x509/x509_vfy.c | 156 ++- crypto/x509/x509_vpm.c | 2 +- crypto/x509/x509cset.c | 2 +- crypto/x509/x509name.c | 16 +- crypto/x509/x509rset.c | 2 +- crypto/x509/x_all.c | 49 +- crypto/x509/x_crl.c | 53 +- crypto/x509/x_name.c | 2 +- crypto/x509/x_req.c | 18 +- crypto/x509/x_x509.c | 26 +- demos/pkcs12/pkread.c | 2 +- demos/pkcs12/pkwrite.c | 2 +- doc/internal/man3/DER_w_begin_sequence.pod | 48 + doc/internal/man3/DER_w_bn.pod | 56 + doc/internal/man3/DER_w_precompiled.pod | 48 + ...INE_SPARSE_ARRAY_OF.pod => OPENSSL_SA.pod} | 4 +- doc/internal/man3/ossl_cmp_hdr_init.pod | 13 +- doc/internal/man3/ossl_cmp_mock_srv_new.pod | 85 ++ .../man3/ossl_cmp_msg_check_received.pod | 86 ++ doc/internal/man3/ossl_cmp_msg_create.pod | 3 +- ..._new.pod => ossl_cmp_pkisi_get_status.pod} | 53 +- doc/internal/man3/s2i_ASN1_UTF8STRING.pod | 6 +- doc/internal/man7/DERlib.pod | 148 +++ doc/man1/CA.pl.pod | 96 +- doc/man1/openssl-asn1parse.pod.in | 2 +- doc/man1/openssl-ca.pod.in | 39 +- doc/man1/openssl-ciphers.pod.in | 17 +- doc/man1/openssl-cms.pod.in | 2 +- doc/man1/openssl-crl.pod.in | 2 +- doc/man1/openssl-ocsp.pod.in | 2 +- doc/man1/openssl-pkcs12.pod.in | 2 +- doc/man1/openssl-pkcs7.pod.in | 2 +- doc/man1/openssl-pkcs8.pod.in | 2 +- doc/man1/openssl-pkey.pod.in | 2 +- doc/man1/openssl-pkeyparam.pod.in | 2 +- doc/man1/openssl-pkeyutl.pod.in | 14 +- doc/man1/openssl-req.pod.in | 36 +- doc/man1/openssl-rsa.pod.in | 2 +- doc/man1/openssl-rsautl.pod.in | 4 +- doc/man1/openssl-s_server.pod.in | 9 + doc/man1/openssl-sess_id.pod.in | 2 +- doc/man1/openssl-smime.pod.in | 2 +- doc/man1/openssl-spkac.pod.in | 2 +- doc/man1/openssl-storeutl.pod.in | 2 +- doc/man1/openssl-ts.pod.in | 2 +- doc/man1/openssl-verify.pod.in | 24 +- doc/man1/openssl-x509.pod.in | 12 +- doc/man1/openssl.pod | 26 +- doc/man3/BIO_get_ex_new_index.pod | 7 +- doc/man3/CONF_modules_free.pod | 2 +- doc/man3/CONF_modules_load_file.pod | 48 +- doc/man3/CRYPTO_get_ex_new_index.pod | 1 + doc/man3/CTLOG_STORE_new.pod | 26 +- doc/man3/CTLOG_new.pod | 36 +- doc/man3/CT_POLICY_EVAL_CTX_new.pod | 20 +- doc/man3/EVP_DigestInit.pod | 92 +- doc/man3/EVP_DigestSignInit.pod | 6 +- doc/man3/EVP_DigestVerifyInit.pod | 29 +- doc/man3/EVP_PKEY_CTX_ctrl.pod | 26 +- doc/man3/EVP_PKEY_fromdata.pod | 2 +- .../{EVP_PKEY_keygen.pod => EVP_PKEY_gen.pod} | 79 +- doc/man3/EVP_PKEY_gettable_params.pod | 108 ++ doc/man3/EVP_PKEY_is_a.pod | 72 ++ doc/man3/EVP_PKEY_set1_RSA.pod | 41 +- doc/man3/EVP_PKEY_set_type.pod | 68 + doc/man3/EVP_aes_128_gcm.pod | 7 + doc/man3/ISSUER_SIGN_TOOL_new.pod | 51 + doc/man3/NCONF_new_with_libctx.pod | 59 + doc/man3/OCSP_response_status.pod | 72 +- doc/man3/OPENSSL_CTX.pod | 12 +- doc/man3/OSSL_CMP_CTX_new.pod | 166 +-- doc/man3/OSSL_CMP_CTX_snprint_PKIStatus.pod | 46 - doc/man3/OSSL_CMP_MSG_get0_header.pod | 18 +- doc/man3/OSSL_CMP_MSG_http_perform.pod | 60 + doc/man3/OSSL_CMP_SRV_CTX_new.pod | 162 +++ doc/man3/OSSL_CMP_STATUSINFO_new.pod | 66 + doc/man3/OSSL_CMP_exec_IR_ses.pod | 172 +++ doc/man3/OSSL_CMP_log_open.pod | 8 +- doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod | 2 +- doc/man3/OSSL_HTTP_transfer.pod | 65 +- doc/man3/OSSL_PARAM.pod | 6 + .../OSSL_PARAM_BLD.pod} | 130 +- doc/man3/OSSL_PARAM_allocate_from_text.pod | 88 +- doc/man3/OSSL_SELF_TEST_new.pod | 2 +- doc/man3/RAND_set_rand_method.pod | 4 +- doc/man3/SRP_Calc_B.pod | 88 ++ doc/man3/SRP_create_verifier.pod | 53 +- doc/man3/SSL_CTX_sess_set_get_cb.pod | 39 +- doc/man3/SSL_CTX_set_tmp_dh_callback.pod | 9 - doc/man3/SSL_accept.pod | 4 +- doc/man3/SSL_connect.pod | 4 +- doc/man3/SSL_do_handshake.pod | 4 +- doc/man3/X509_CRL_get0_by_serial.pod | 2 +- doc/man3/X509_LOOKUP.pod | 6 +- doc/man3/X509_LOOKUP_meth_new.pod | 6 +- doc/man3/X509_NAME_get0_der.pod | 2 +- doc/man3/X509_NAME_get_index_by_NID.pod | 11 +- doc/man3/X509_STORE_CTX_get_error.pod | 10 +- doc/man3/X509_STORE_CTX_new.pod | 68 +- doc/man3/X509_STORE_get0_param.pod | 6 +- doc/man3/X509_STORE_set_verify_cb_func.pod | 38 +- doc/man3/X509_VERIFY_PARAM_set_flags.pod | 2 +- doc/man3/X509_check_ca.pod | 2 + doc/man3/X509_check_purpose.pod | 74 ++ doc/man3/X509_digest.pod | 17 +- doc/man3/X509_dup.pod | 4 + doc/man3/X509_get0_distinguishing_id.pod | 71 ++ doc/man3/X509_get0_sm2_id.pod | 55 - doc/man3/X509_get_extension_flags.pod | 13 +- doc/man3/X509_get_subject_name.pod | 8 +- doc/man3/X509v3_cache_extensions.pod | 43 + doc/man3/d2i_X509.pod | 2 + doc/man5/config.pod | 6 +- doc/man7/EVP_MD-BLAKE2.pod | 46 + doc/man7/EVP_MD-MD2.pod | 34 + doc/man7/EVP_MD-MD4.pod | 34 + doc/man7/EVP_MD-MD5-SHA1.pod | 56 + doc/man7/EVP_MD-MD5.pod | 34 + doc/man7/EVP_MD-MDC2.pod | 50 + doc/man7/EVP_MD-RIPEMD160.pod | 35 + doc/man7/EVP_MD-SHA1.pod | 55 + doc/man7/EVP_MD-SHA2.pod | 77 ++ doc/man7/EVP_MD-SHA3.pod | 46 + doc/man7/EVP_MD-SHAKE.pod | 73 ++ doc/man7/EVP_MD-SM3.pod | 34 + doc/man7/EVP_MD-WHIRLPOOL.pod | 34 + doc/man7/EVP_MD-common.pod | 67 + doc/man7/Ed25519.pod | 2 +- doc/man7/OSSL_PROVIDER-FIPS.pod | 135 +- doc/man7/OSSL_PROVIDER-default.pod | 226 ++++ doc/man7/OSSL_PROVIDER-legacy.pod | 92 ++ doc/man7/OSSL_PROVIDER-null.pod | 35 + doc/man7/X25519.pod | 2 +- doc/man7/provider-digest.pod | 41 +- doc/man7/provider-keymgmt.pod | 161 ++- doc/man7/provider-signature.pod | 183 ++- include/crypto/asn1.h | 8 +- include/crypto/dh.h | 4 + include/crypto/dsa.h | 2 + include/crypto/ec.h | 16 +- include/crypto/ecx.h | 68 +- include/crypto/evp.h | 97 +- include/crypto/rsa.h | 13 +- include/crypto/x509.h | 22 +- include/internal/cryptlib.h | 4 + include/internal/der.h | 84 ++ include/internal/evp.h | 23 + include/internal/ffc.h | 3 + include/internal/packet.h | 17 + include/internal/param_build.h | 76 -- include/internal/param_build_set.h | 27 + include/openssl/asn1err.h | 5 - include/openssl/asyncerr.h | 5 - include/openssl/bio.h | 2 +- include/openssl/bioerr.h | 5 - include/openssl/bnerr.h | 5 - include/openssl/buffererr.h | 5 - include/openssl/cmp.h | 117 +- include/openssl/cmp_util.h | 9 +- include/openssl/cmperr.h | 33 +- include/openssl/cmserr.h | 6 +- include/openssl/comperr.h | 5 - include/openssl/conf.h | 4 + include/openssl/conferr.h | 5 - include/openssl/core.h | 6 + include/openssl/core_names.h | 40 + include/openssl/core_numbers.h | 78 +- include/openssl/crmf.h | 20 +- include/openssl/crmferr.h | 14 +- include/openssl/crypto.h | 4 +- include/openssl/cryptoerr.h | 5 - include/openssl/ct.h | 44 +- include/openssl/cterr.h | 5 - include/openssl/dh.h | 2 +- include/openssl/dherr.h | 5 - include/openssl/dsa.h | 2 +- include/openssl/dsaerr.h | 5 - include/openssl/ec.h | 9 +- include/openssl/ecerr.h | 5 - include/openssl/engineerr.h | 5 - include/openssl/evp.h | 25 +- include/openssl/evperr.h | 14 +- include/openssl/http.h | 20 +- include/openssl/httperr.h | 9 +- include/openssl/kdferr.h | 5 - include/openssl/objectserr.h | 5 - include/openssl/ocsp.h | 14 +- include/openssl/ocsperr.h | 5 - include/openssl/param_build.h | 49 + include/openssl/pemerr.h | 5 - include/openssl/pkcs12err.h | 5 - include/openssl/pkcs7err.h | 5 - include/openssl/randerr.h | 5 - include/openssl/rsa.h | 16 +- include/openssl/rsaerr.h | 5 - include/openssl/self_test.h | 3 +- include/openssl/srp.h | 16 + include/openssl/ssl.h | 3 +- include/openssl/sslerr.h | 11 +- include/openssl/storeerr.h | 5 - include/openssl/tserr.h | 5 - include/openssl/types.h | 1 + include/openssl/ui.h | 2 +- include/openssl/uierr.h | 5 - include/openssl/x509.h | 56 +- include/openssl/x509_vfy.h | 160 +-- include/openssl/x509err.h | 5 - include/openssl/x509v3.h | 14 +- include/openssl/x509v3err.h | 7 +- providers/build.info | 12 +- providers/common/build.info | 2 + providers/common/der/DSA.asn1 | 29 + providers/common/der/EC.asn1 | 83 ++ providers/common/der/RSA.asn1 | 88 ++ providers/common/der/build.info | 25 + providers/common/der/der_dsa.c.in | 59 + providers/common/der/der_dsa.h.in | 21 + providers/common/der/der_ec.c.in | 67 + providers/common/der/der_ec.h.in | 21 + providers/common/der/der_rsa.c.in | 74 ++ providers/common/der/der_rsa.h.in | 21 + providers/common/der/oids_to_c.pm | 111 ++ .../common/include/prov/providercommonerr.h | 3 + providers/common/provider_err.c | 3 + providers/common/provider_util.c | 11 + providers/defltprov.c | 89 +- providers/fips/fipsprov.c | 378 +----- providers/fips/self_test_data.inc | 836 +++++++++++- providers/fips/self_test_kats.c | 274 +++- .../implementations/asymciphers/rsa_enc.c | 3 +- providers/implementations/ciphers/build.info | 20 +- .../implementations/ciphers/cipher_aes_ocb.c | 9 +- .../implementations/ciphers/cipher_des.c | 15 + .../implementations/ciphers/cipher_des_hw.c | 13 +- .../implementations/ciphers/cipher_desx_hw.c | 13 +- .../implementations/ciphers/cipher_tdes.c | 93 +- .../implementations/ciphers/cipher_tdes.h | 10 +- .../ciphers/cipher_tdes_common.c | 124 ++ .../implementations/ciphers/cipher_tdes_hw.c | 9 + .../implementations/ciphers/ciphercommon.c | 9 +- .../ciphers/ciphercommon_block.c | 17 +- .../ciphers/ciphercommon_ccm.c | 2 +- providers/implementations/digests/sha3_prov.c | 2 +- providers/implementations/exchange/build.info | 3 +- .../implementations/exchange/ecdh_exch.c | 7 + .../include/prov/implementations.h | 20 + providers/implementations/keymgmt/build.info | 5 +- providers/implementations/keymgmt/dh_kmgmt.c | 126 +- providers/implementations/keymgmt/dsa_kmgmt.c | 121 +- providers/implementations/keymgmt/ec_kmgmt.c | 594 ++++----- providers/implementations/keymgmt/ecx_kmgmt.c | 192 +-- providers/implementations/keymgmt/rsa_kmgmt.c | 386 +++--- .../serializers/serializer_common.c | 1 + .../serializers/serializer_ecx.c | 32 +- .../serializers/serializer_ecx_priv.c | 25 +- .../serializers/serializer_ecx_pub.c | 21 +- .../serializers/serializer_local.h | 7 +- .../serializers/serializer_rsa.c | 1 - .../implementations/signature/build.info | 13 +- providers/implementations/signature/dsa.c | 41 +- providers/implementations/signature/ecdsa.c | 527 ++++++++ providers/implementations/signature/eddsa.c | 213 ++++ providers/implementations/signature/rsa.c | 42 +- providers/legacyprov.c | 75 +- providers/nullprov.c | 106 ++ ssl/record/rec_layer_s3.c | 1 + ssl/record/record.h | 2 + ssl/record/record_local.h | 2 + ssl/record/ssl3_buffer.c | 4 +- ssl/s3_lib.c | 58 +- ssl/ssl_cert.c | 17 +- ssl/ssl_ciph.c | 4 +- ssl/ssl_err.c | 2 + ssl/ssl_lib.c | 4 +- ssl/ssl_rsa.c | 17 +- ssl/statem/extensions.c | 3 +- ssl/statem/extensions_clnt.c | 32 + ssl/statem/extensions_srvr.c | 36 +- ssl/statem/statem_clnt.c | 56 +- ssl/statem/statem_lib.c | 23 +- ssl/statem/statem_srvr.c | 57 +- ssl/t1_enc.c | 6 +- ssl/t1_lib.c | 83 +- ssl/t1_trce.c | 5 +- ssl/tls_srp.c | 30 +- test/build.info | 56 +- test/certs/ee-pathlen.pem | 17 + test/certs/grfc.pem | 30 + test/certs/setup.sh | 4 +- test/ciphername_test.c | 4 +- test/cmp_client_test.c | 393 ++++++ test/cmp_ctx_test.c | 28 +- test/cmp_hdr_test.c | 17 +- test/cmp_msg_test.c | 14 +- test/cmp_protect_test.c | 35 +- test/cmp_server_test.c | 160 +++ test/cmp_status_test.c | 16 +- test/cmp_testlib.c | 6 + test/cmp_testlib.h | 2 + test/cmp_vfy_test.c | 18 +- test/drbg_extra_test.c | 94 ++ test/drbg_extra_test.h | 188 +++ test/ecdsatest.c | 45 +- test/evp_extra_test.c | 3 +- test/evp_fetch_prov_test.c | 13 +- test/evp_pkey_provided_test.c | 273 +++- test/evp_test.c | 9 +- test/gosttest.c | 10 +- test/http_test.c | 4 +- test/keymgmt_internal_test.c | 88 +- test/ocspapitest.c | 2 +- test/p_test.c | 13 + test/param_build_test.c | 96 +- test/recipes/03-test_fipsinstall.t | 20 +- test/recipes/05-test_rand.t | 2 + test/recipes/20-test_enc.t | 8 +- test/recipes/20-test_enc_more.t | 8 +- test/recipes/20-test_pkeyutl.t | 4 +- test/recipes/20-test_provider.t | 17 +- test/recipes/25-test_req.t | 8 +- test/recipes/25-test_rusext.t | 33 + test/recipes/25-test_rusext_data/grfc.msb | 67 + test/recipes/25-test_rusext_data/grfc.utf8 | 67 + test/recipes/25-test_verify.t | 12 +- test/recipes/30-test_evp.t | 4 +- test/recipes/30-test_evp_data/evpmac.txt | 5 + test/recipes/30-test_evp_data/evppkey.txt | 13 +- test/recipes/30-test_evp_fetch_prov.t | 3 +- .../ED25519.priv.der | Bin 0 -> 48 bytes .../ED25519.priv.pem | 3 + .../ED25519.priv.txt | 9 + .../30-test_evp_pkey_provided/ED25519.pub.der | Bin 0 -> 44 bytes .../30-test_evp_pkey_provided/ED25519.pub.pem | 3 + .../30-test_evp_pkey_provided/ED25519.pub.txt | 5 + .../30-test_evp_pkey_provided/ED448.priv.der | Bin 0 -> 73 bytes .../30-test_evp_pkey_provided/ED448.priv.pem | 4 + .../30-test_evp_pkey_provided/ED448.priv.txt | 11 + .../30-test_evp_pkey_provided/ED448.pub.der | Bin 0 -> 69 bytes .../30-test_evp_pkey_provided/ED448.pub.pem | 4 + .../30-test_evp_pkey_provided/ED448.pub.txt | 6 + test/recipes/65-test_cmp_client.t | 27 + .../65-test_cmp_client_data/client.crt | 13 + .../65-test_cmp_client_data/client.csr | Bin 0 -> 424 bytes .../65-test_cmp_client_data/client.key | 7 + .../65-test_cmp_client_data/server.crt | 17 + .../65-test_cmp_client_data/server.key | 27 + test/recipes/65-test_cmp_server.t | 26 + .../CR_protected_PBM_1234.der | Bin 0 -> 420 bytes test/recipes/80-test_ca.t | 4 +- test/recipes/80-test_cms.t | 15 +- test/recipes/90-test_sslprovider.t | 38 +- test/recipes/95-test_external_krb5.t | 2 +- test/sm2_internal_test.c | 19 +- test/sslapitest.c | 124 +- test/sslprovidertest.c | 99 +- test/ssltestlib.c | 9 +- test/verify_extra_test.c | 32 +- test/wpackettest.c | 67 + util/check-format-test-negatives.c | 717 +++++++++++ util/check-format-test-positives.c | 345 +++++ util/check-format.pl | 1119 +++++++++++++++++ util/find-doc-nits | 294 +++-- util/libcrypto.num | 110 +- util/missingcrypto-internal.txt | 3 + util/missingcrypto.txt | 58 +- util/missingssl-internal.txt | 0 util/mkerr.pl | 1 + util/openssl-format-source | 175 --- util/other-internal.syms | 3 + util/other.syms | 28 +- util/perl/OpenSSL/OID.pm | 392 ++++++ util/perl/OpenSSL/Util/Pod.pm | 3 +- util/wrap.pl | 15 +- 573 files changed, 22943 insertions(+), 6714 deletions(-) create mode 100644 apps/cmp_mock_srv.c create mode 100644 apps/cmp_mock_srv.h delete mode 100644 apps/dh1024.pem delete mode 100644 apps/dh2048.pem delete mode 100644 apps/dh4096.pem create mode 100644 apps/lib/app_x509.c create mode 100644 crypto/cmp/cmp_client.c create mode 100644 crypto/cmp/cmp_http.c create mode 100644 crypto/cmp/cmp_server.c create mode 100644 crypto/der_writer.c delete mode 100644 crypto/dh/dh1024.pem delete mode 100644 crypto/dh/dh192.pem delete mode 100644 crypto/dh/dh2048.pem delete mode 100644 crypto/dh/dh4096.pem delete mode 100644 crypto/dh/dh512.pem create mode 100644 crypto/dh/dh_backend.c delete mode 100644 crypto/dsa/dsa_aid.c create mode 100644 crypto/dsa/dsa_backend.c create mode 100644 crypto/ec/ec_backend.c rename crypto/ec/{ec_evp_lib.c => ec_ctrl.c} (85%) create mode 100644 crypto/ec/ecx_backend.c create mode 100644 crypto/ec/ecx_backend.h create mode 100644 crypto/ffc/ffc_backend.c create mode 100644 crypto/param_build_set.c delete mode 100644 crypto/rsa/rsa_aid.c create mode 100644 crypto/rsa/rsa_backend.c create mode 100644 crypto/rsa/rsa_mp_names.c create mode 100644 crypto/x509/v3_ist.c create mode 100644 doc/internal/man3/DER_w_begin_sequence.pod create mode 100644 doc/internal/man3/DER_w_bn.pod create mode 100644 doc/internal/man3/DER_w_precompiled.pod rename doc/internal/man3/{DEFINE_SPARSE_ARRAY_OF.pod => OPENSSL_SA.pod} (98%) create mode 100644 doc/internal/man3/ossl_cmp_mock_srv_new.pod create mode 100644 doc/internal/man3/ossl_cmp_msg_check_received.pod rename doc/internal/man3/{ossl_cmp_statusinfo_new.pod => ossl_cmp_pkisi_get_status.pod} (58%) create mode 100644 doc/internal/man7/DERlib.pod rename doc/man3/{EVP_PKEY_keygen.pod => EVP_PKEY_gen.pod} (65%) create mode 100644 doc/man3/EVP_PKEY_gettable_params.pod create mode 100644 doc/man3/EVP_PKEY_is_a.pod create mode 100644 doc/man3/EVP_PKEY_set_type.pod create mode 100644 doc/man3/ISSUER_SIGN_TOOL_new.pod create mode 100644 doc/man3/NCONF_new_with_libctx.pod delete mode 100644 doc/man3/OSSL_CMP_CTX_snprint_PKIStatus.pod create mode 100644 doc/man3/OSSL_CMP_MSG_http_perform.pod create mode 100644 doc/man3/OSSL_CMP_SRV_CTX_new.pod create mode 100644 doc/man3/OSSL_CMP_STATUSINFO_new.pod create mode 100644 doc/man3/OSSL_CMP_exec_IR_ses.pod rename doc/{internal/man3/ossl_param_bld_init.pod => man3/OSSL_PARAM_BLD.pod} (52%) create mode 100644 doc/man3/SRP_Calc_B.pod create mode 100644 doc/man3/X509_check_purpose.pod create mode 100644 doc/man3/X509_get0_distinguishing_id.pod delete mode 100644 doc/man3/X509_get0_sm2_id.pod create mode 100644 doc/man3/X509v3_cache_extensions.pod create mode 100644 doc/man7/EVP_MD-BLAKE2.pod create mode 100644 doc/man7/EVP_MD-MD2.pod create mode 100644 doc/man7/EVP_MD-MD4.pod create mode 100644 doc/man7/EVP_MD-MD5-SHA1.pod create mode 100644 doc/man7/EVP_MD-MD5.pod create mode 100644 doc/man7/EVP_MD-MDC2.pod create mode 100644 doc/man7/EVP_MD-RIPEMD160.pod create mode 100644 doc/man7/EVP_MD-SHA1.pod create mode 100644 doc/man7/EVP_MD-SHA2.pod create mode 100644 doc/man7/EVP_MD-SHA3.pod create mode 100644 doc/man7/EVP_MD-SHAKE.pod create mode 100644 doc/man7/EVP_MD-SM3.pod create mode 100644 doc/man7/EVP_MD-WHIRLPOOL.pod create mode 100644 doc/man7/EVP_MD-common.pod create mode 100644 doc/man7/OSSL_PROVIDER-default.pod create mode 100644 doc/man7/OSSL_PROVIDER-legacy.pod create mode 100644 doc/man7/OSSL_PROVIDER-null.pod create mode 100644 include/internal/der.h create mode 100644 include/internal/evp.h delete mode 100644 include/internal/param_build.h create mode 100644 include/internal/param_build_set.h create mode 100644 include/openssl/param_build.h create mode 100644 providers/common/der/DSA.asn1 create mode 100644 providers/common/der/EC.asn1 create mode 100644 providers/common/der/RSA.asn1 create mode 100644 providers/common/der/build.info create mode 100644 providers/common/der/der_dsa.c.in create mode 100644 providers/common/der/der_dsa.h.in create mode 100644 providers/common/der/der_ec.c.in create mode 100644 providers/common/der/der_ec.h.in create mode 100644 providers/common/der/der_rsa.c.in create mode 100644 providers/common/der/der_rsa.h.in create mode 100644 providers/common/der/oids_to_c.pm create mode 100644 providers/implementations/ciphers/cipher_tdes_common.c create mode 100644 providers/implementations/signature/ecdsa.c create mode 100644 providers/implementations/signature/eddsa.c create mode 100644 providers/nullprov.c create mode 100644 test/certs/ee-pathlen.pem create mode 100644 test/certs/grfc.pem create mode 100644 test/cmp_client_test.c create mode 100644 test/cmp_server_test.c create mode 100644 test/drbg_extra_test.c create mode 100644 test/drbg_extra_test.h create mode 100644 test/recipes/25-test_rusext.t create mode 100644 test/recipes/25-test_rusext_data/grfc.msb create mode 100644 test/recipes/25-test_rusext_data/grfc.utf8 create mode 100644 test/recipes/30-test_evp_pkey_provided/ED25519.priv.der create mode 100644 test/recipes/30-test_evp_pkey_provided/ED25519.priv.pem create mode 100644 test/recipes/30-test_evp_pkey_provided/ED25519.priv.txt create mode 100644 test/recipes/30-test_evp_pkey_provided/ED25519.pub.der create mode 100644 test/recipes/30-test_evp_pkey_provided/ED25519.pub.pem create mode 100644 test/recipes/30-test_evp_pkey_provided/ED25519.pub.txt create mode 100644 test/recipes/30-test_evp_pkey_provided/ED448.priv.der create mode 100644 test/recipes/30-test_evp_pkey_provided/ED448.priv.pem create mode 100644 test/recipes/30-test_evp_pkey_provided/ED448.priv.txt create mode 100644 test/recipes/30-test_evp_pkey_provided/ED448.pub.der create mode 100644 test/recipes/30-test_evp_pkey_provided/ED448.pub.pem create mode 100644 test/recipes/30-test_evp_pkey_provided/ED448.pub.txt create mode 100644 test/recipes/65-test_cmp_client.t create mode 100644 test/recipes/65-test_cmp_client_data/client.crt create mode 100644 test/recipes/65-test_cmp_client_data/client.csr create mode 100644 test/recipes/65-test_cmp_client_data/client.key create mode 100644 test/recipes/65-test_cmp_client_data/server.crt create mode 100644 test/recipes/65-test_cmp_client_data/server.key create mode 100644 test/recipes/65-test_cmp_server.t create mode 100644 test/recipes/65-test_cmp_server_data/CR_protected_PBM_1234.der create mode 100644 util/check-format-test-negatives.c create mode 100644 util/check-format-test-positives.c create mode 100755 util/check-format.pl create mode 100644 util/missingcrypto-internal.txt create mode 100644 util/missingssl-internal.txt delete mode 100755 util/openssl-format-source create mode 100644 util/other-internal.syms create mode 100644 util/perl/OpenSSL/OID.pm diff --git a/CHANGES.md b/CHANGES.md index c552e9a0..4b7a73dc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -24,9 +24,28 @@ OpenSSL 3.0 ### Changes between 1.1.1 and 3.0 [xx XXX xxxx] ### - * `ASN1_verify()`, `ASN1_digest()` and `ASN1_sign()` have been deprecated. + * Added OSSL_PARAM_BLD to the public interface. This allows OSSL_PARAM + arrays to be more easily constructed via a series of utility functions. + Create a parameter builder using OSSL_PARAM_BLD_new(), add parameters using + the various push functions and finally convert to a passable OSSL_PARAM + array using OSSL_PARAM_BLD_to_param(). + + *Paul Dale* + + * EVP_PKEY_get0_RSA(), EVP_PKEY_get0_DSA(), EVP_PKEY_get0_DH(), and + EVP_PKEY_get0_EC_KEY() can now handle EVP_PKEYs with provider side + internal keys, if they correspond to one of those built in types. + + *Richard Levitte* + + * Added EVP_PKEY_set_type_by_keymgmt(), to initialise an EVP_PKEY to + contain a provider side internal key. + + *Richard Levitte* + + * ASN1_verify(), ASN1_digest() and ASN1_sign() have been deprecated. They are old functions that we don't use, and that you could disable with - the macro `NO_ASN1_OLD`. This goes all the way back to OpenSSL 0.9.7. + the macro NO_ASN1_OLD. This goes all the way back to OpenSSL 0.9.7. *Richard Levitte* @@ -938,7 +957,33 @@ OpenSSL 3.0 OpenSSL 1.1.1 ------------- -### Changes between 1.1.1d and 1.1.1e [xx XXX xxxx] ### +### Changes between 1.1.1e and 1.1.1f [xx XXX xxxx] ### + + +### Changes between 1.1.1d and 1.1.1e [17 Mar 2020] ### + + * Properly detect EOF while reading in libssl. Previously if we hit an EOF + while reading in libssl then we would report an error back to the + application (SSL_ERROR_SYSCALL) but errno would be 0. We now add + an error to the stack (which means we instead return SSL_ERROR_SSL) and + therefore give a hint as to what went wrong. + + *Matt Caswell* + + * Check that ed25519 and ed448 are allowed by the security level. Previously + signature algorithms not using an MD were not being checked that they were + allowed by the security level. + + *Kurt Roeckx* + + * Fixed SSL_get_servername() behaviour. The behaviour of SSL_get_servername() + was not quite right. The behaviour was not consistent between resumption + and normal handshakes, and also not quite consistent with historical + behaviour. The behaviour in various scenarios has been clarified and + it has been updated to make it match historical behaviour as closely as + possible. + + *Matt Caswell* * *[VMS only]* The header files that the VMS compilers include automatically, `__DECC_INCLUDE_PROLOGUE.H` and `__DECC_INCLUDE_EPILOGUE.H`, use pragmas diff --git a/Configurations/15-android.conf b/Configurations/15-android.conf index b28689a4..d3b2ff6a 100644 --- a/Configurations/15-android.conf +++ b/Configurations/15-android.conf @@ -24,17 +24,17 @@ my $ndk_var; my $ndk; - foreach (qw(ANDROID_NDK_HOME ANDROID_NDK)) { + foreach (qw(ANDROID_NDK_ROOT ANDROID_NDK)) { $ndk_var = $_; $ndk = $ENV{$ndk_var}; last if defined $ndk; } - die "\$ANDROID_NDK_HOME is not defined" if (!$ndk); + die "\$ANDROID_NDK_ROOT is not defined" if (!$ndk); if (!-d "$ndk/platforms" && !-f "$ndk/AndroidVersion.txt") { # $ndk/platforms is traditional "all-inclusive" NDK, while # $ndk/AndroidVersion.txt is so-called standalone toolchain # tailored for specific target down to API level. - die "\$ANDROID_NDK_HOME=$ndk is invalid"; + die "\$ANDROID_NDK_ROOT=$ndk is invalid"; } $ndk = canonpath($ndk); @@ -168,7 +168,8 @@ my %targets = ( cppflags => add(sub { android_ndk()->{cppflags} }), cxxflags => add(sub { android_ndk()->{cflags} }), bn_ops => sub { android_ndk()->{bn_ops} }, - bin_cflags => "-pie", + bin_cflags => "-fPIE", + bin_lflags => "-pie", enable => [ ], }, "android-arm" => { diff --git a/Configurations/unix-Makefile.tmpl b/Configurations/unix-Makefile.tmpl index a0197799..a35ce10c 100644 --- a/Configurations/unix-Makefile.tmpl +++ b/Configurations/unix-Makefile.tmpl @@ -1025,6 +1025,7 @@ errors: qw( include/internal/dso.h include/internal/o_dir.h include/internal/err.h + include/internal/evp.h include/internal/sslconf.h ); our @cryptoskipheaders = ( @sslheaders, qw( include/openssl/conf_api.h diff --git a/Configurations/windows-makefile.tmpl b/Configurations/windows-makefile.tmpl index c49b32f0..04383997 100644 --- a/Configurations/windows-makefile.tmpl +++ b/Configurations/windows-makefile.tmpl @@ -47,19 +47,22 @@ SHLIB_VERSION_NUMBER={- $config{shlib_version} -} LIBS={- join(" ", map { ( platform->sharedlib_import($_), platform->staticlib($_) ) } @{$unified_info{libraries}}) -} SHLIBS={- join(" ", map { platform->sharedlib($_) // () } @{$unified_info{libraries}}) -} SHLIBPDBS={- join(" ", map { platform->sharedlibpdb($_) // () } @{$unified_info{libraries}}) -} -MODULES={- join(" ", map { platform->dso($_) } @{$unified_info{modules}}) -} +MODULES={- our @MODULES = map { platform->dso($_) } @{$unified_info{modules}}; + join(" ", @MODULES) -} MODULEPDBS={- join(" ", map { platform->dsopdb($_) } @{$unified_info{modules}}) -} PROGRAMS={- our @PROGRAMS = map { platform->bin($_) } @{$unified_info{programs}}; join(" ", @PROGRAMS) -} PROGRAMPDBS={- join(" ", map { $_.".pdb" } @{$unified_info{programs}}) -} -SCRIPTS={- join(" ", @{$unified_info{scripts}}) -} +SCRIPTS={- our @SCRIPTS = @{$unified_info{scripts}}; join(" ", @SCRIPTS) -} {- output_off() if $disabled{makedepend}; "" -} DEPS={- join(" ", map { platform->isobj($_) ? platform->dep($_) : () } grep { $unified_info{sources}->{$_}->[0] =~ /\.c$/ } keys %{$unified_info{sources}}); -} {- output_on() if $disabled{makedepend}; "" -} -GENERATED_MANDATORY={- join(" ", @{$unified_info{depends}->{""}} ) -} +GENERATED_MANDATORY={- our @GENERATED_MANDATORY = @{$unified_info{depends}->{""}}; + join(" ", @GENERATED_MANDATORY) -} GENERATED={- # common0.tmpl provides @generated - join(" ", map { platform->convertext($_) } @generated) -} + our @GENERATED = map { platform->convertext($_) } @generated; + join(" ", @GENERATED) -} INSTALL_LIBS={- join(" ", map { quotify1(platform->sharedlib_import($_) @@ -417,10 +420,10 @@ clean: libclean -rmdir /Q /S $(HTMLDOCS5_BLDDIRS) -rmdir /Q /S $(HTMLDOCS7_BLDDIRS) {- join("\n\t", map { "-del /Q /F $_" } @PROGRAMS) -} - -del /Q /F $(MODULES) - -del /Q /F $(SCRIPTS) - -del /Q /F $(GENERATED_MANDATORY) - -del /Q /F $(GENERATED) + {- join("\n\t", map { "-del /Q /F $_" } @MODULES) -} + {- join("\n\t", map { "-del /Q /F $_" } @SCRIPTS) -} + {- join("\n\t", map { "-del /Q /F $_" } @GENERATED_MANDATORY) -} + {- join("\n\t", map { "-del /Q /F $_" } @GENERATED) -} -del /Q /S /F *.d *.obj *.pdb *.ilk *.manifest -del /Q /S /F engines\*.lib engines\*.exp -del /Q /S /F apps\*.lib apps\*.rc apps\*.res apps\*.exp diff --git a/NEWS.md b/NEWS.md index 434f306e..9f29a593 100644 --- a/NEWS.md +++ b/NEWS.md @@ -31,6 +31,7 @@ OpenSSL 3.0 * enable-crypto-mdebug and enable-crypto-mdebug-backtrace were mostly disabled; the project uses address sanitize/leak-detect instead. * Added OSSL_SERIALIZER, a generic serializer API. + * Added OSSL_PARAM_BLD, an easier to use API to OSSL_PARAM. * Added error raising macros, ERR_raise() and ERR_raise_data(). * Deprecated ERR_put_error(). * Added OSSL_PROVIDER_available(), to check provider availibility. @@ -57,6 +58,15 @@ OpenSSL 3.0 OpenSSL 1.1.1 ------------- +### Major changes between OpenSSL 1.1.1e and OpenSSL 1.1.1f [under development] ### + + * + +### Major changes between OpenSSL 1.1.1d and OpenSSL 1.1.1e [17 Mar 2020] ### + + * Fixed an overflow bug in the x64_64 Montgomery squaring procedure + used in exponentiation with 512-bit moduli ([CVE-2019-1551][]) + ### Major changes between OpenSSL 1.1.1c and OpenSSL 1.1.1d [10 Sep 2019] ### * Fixed a fork protection issue ([CVE-2019-1549][]) @@ -1295,6 +1305,7 @@ OpenSSL 0.9.x [CVE-2019-1563]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1563 [CVE-2019-1559]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1559 [CVE-2019-1552]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1552 +[CVE-2019-1551]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1551 [CVE-2019-1549]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1549 [CVE-2019-1547]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1547 [CVE-2019-1543]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1543 diff --git a/NOTES.ANDROID b/NOTES.ANDROID index f19ec71b..57c1ee9d 100644 --- a/NOTES.ANDROID +++ b/NOTES.ANDROID @@ -24,7 +24,7 @@ need to know the prefix to extend your PATH, in order to invoke $(CROSS_COMPILE)clang [*gcc on NDK 19 and lower] and company. (Configure will fail and give you a hint if you get it wrong.) Apart from PATH - adjustment you need to set ANDROID_NDK_HOME environment to point at the + adjustment you need to set ANDROID_NDK_ROOT environment to point at the NDK directory. If you're using a side-by-side NDK the path will look something like /some/where/android-sdk/ndk/, and for a standalone NDK the path will be something like /some/where/android-ndk-. @@ -35,21 +35,21 @@ with N being the numerical value of the target platform version. For example, to compile for Android 10 arm64 with a side-by-side NDK r20.0.5594570 - export ANDROID_NDK_HOME=/home/whoever/Android/android-sdk/ndk/20.0.5594570 - PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$ANDROID_NDK_HOME/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin:$PATH + export ANDROID_NDK_ROOT=/home/whoever/Android/android-sdk/ndk/20.0.5594570 + PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin:$PATH ./Configure android-arm64 -D__ANDROID_API__=29 make Older versions of the NDK have GCC under their common prebuilt tools directory, so the bin path will be slightly different. EG: to compile for ICS on ARM with NDK 10d: - export ANDROID_NDK_HOME=/some/where/android-ndk-10d - PATH=$ANDROID_NDK_HOME/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin:$PATH + export ANDROID_NDK_ROOT=/some/where/android-ndk-10d + PATH=$ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin:$PATH ./Configure android-arm -D__ANDROID_API__=14 make Caveat lector! Earlier OpenSSL versions relied on additional CROSS_SYSROOT - variable set to $ANDROID_NDK_HOME/platforms/android-/arch- to + variable set to $ANDROID_NDK_ROOT/platforms/android-/arch- to appoint headers-n-libraries' location. It's still recognized in order to facilitate migration from older projects. However, since API level appears in CROSS_SYSROOT value, passing -D__ANDROID_API__=N can be in @@ -64,9 +64,9 @@ Another option is to create so called "standalone toolchain" tailored for single specific platform including Android API level, and assign its - location to ANDROID_NDK_HOME. In such case you have to pass matching + location to ANDROID_NDK_ROOT. In such case you have to pass matching target name to Configure and shouldn't use -D__ANDROID_API__=N. PATH - adjustment becomes simpler, $ANDROID_NDK_HOME/bin:$PATH suffices. + adjustment becomes simpler, $ANDROID_NDK_ROOT/bin:$PATH suffices. Running tests (on Linux) ------------------------ diff --git a/apps/CA.pl.in b/apps/CA.pl.in index 12c94524..918534d6 100644 --- a/apps/CA.pl.in +++ b/apps/CA.pl.in @@ -14,57 +14,63 @@ use strict; use warnings; -my $openssl = "openssl"; -if(defined $ENV{'OPENSSL'}) { - $openssl = $ENV{'OPENSSL'}; -} else { - $ENV{'OPENSSL'} = $openssl; -} - my $verbose = 1; +my @OPENSSL_CMDS = ("req", "ca", "pkcs12", "x509", "verify"); -my $OPENSSL_CONFIG = $ENV{"OPENSSL_CONFIG"} || ""; -my $DAYS = "-days 365"; -my $CADAYS = "-days 1095"; # 3 years +my $openssl = $ENV{'OPENSSL'} // "openssl"; +$ENV{'OPENSSL'} = $openssl; +my $OPENSSL_CONFIG = $ENV{"OPENSSL_CONFIG"} // ""; + +# Command invocations. my $REQ = "$openssl req $OPENSSL_CONFIG"; my $CA = "$openssl ca $OPENSSL_CONFIG"; my $VERIFY = "$openssl verify"; my $X509 = "$openssl x509"; my $PKCS12 = "$openssl pkcs12"; -# default openssl.cnf file has setup as per the following +# Default values for various configuration settings. my $CATOP = "./demoCA"; my $CAKEY = "cakey.pem"; my $CAREQ = "careq.pem"; my $CACERT = "cacert.pem"; my $CACRL = "crl.pem"; -my $DIRMODE = 0777; - +my $DAYS = "-days 365"; +my $CADAYS = "-days 1095"; # 3 years my $NEWKEY = "newkey.pem"; my $NEWREQ = "newreq.pem"; my $NEWCERT = "newcert.pem"; my $NEWP12 = "newcert.p12"; -my $RET = 0; -my $WHAT = shift @ARGV || ""; -my @OPENSSL_CMDS = ("req", "ca", "pkcs12", "x509", "verify"); -my %EXTRA = extra_args(\@ARGV, "-extra-"); -my $FILE; -sub extra_args { - my ($args_ref, $arg_prefix) = @_; - my %eargs = map { - if ($_ < $#$args_ref) { - my ($arg, $value) = splice(@$args_ref, $_, 2); - $arg =~ s/$arg_prefix//; - ($arg, $value); - } else { - (); - } - } reverse grep($$args_ref[$_] =~ /$arg_prefix/, 0..$#$args_ref); - my %empty = map { ($_, "") } @OPENSSL_CMDS; - return (%empty, %eargs); +# Commandline parsing +my %EXTRA; +my $WHAT = shift @ARGV || ""; +@ARGV = parse_extra(@ARGV); +my $RET = 0; + +# Split out "-extra-CMD value", and return new |@ARGV|. Fill in +# |EXTRA{CMD}| with list of values. +sub parse_extra +{ + foreach ( @OPENSSL_CMDS ) { + $EXTRA{$_} = ''; + } + + my @result; + while ( scalar(@_) > 0 ) { + my $arg = shift; + if ( $arg !~ m/-extra-([a-z0-9]+)/ ) { + push @result, $arg; + next; + } + $arg =~ s/-extra-//; + die("Unknown \"-${arg}-extra\" option, exiting") + unless scalar grep { $arg eq $_ } @OPENSSL_CMDS; + $EXTRA{$arg} .= " " . shift; + } + return @result; } + # See if reason for a CRL entry is valid; exit if not. sub crl_reason_ok { @@ -113,19 +119,25 @@ sub run if ( $WHAT =~ /^(-\?|-h|-help)$/ ) { - print STDERR "usage: CA.pl -newcert | -newreq | -newreq-nodes | -xsign | -sign | -signCA | -signcert | -crl | -newca [-extra-cmd extra-params]\n"; - print STDERR " CA.pl -pkcs12 [-extra-pkcs12 extra-params] [certname]\n"; - print STDERR " CA.pl -verify [-extra-verify extra-params] certfile ...\n"; - print STDERR " CA.pl -revoke [-extra-ca extra-params] certfile [reason]\n"; + print STDERR <${CATOP}/index.txt"; close OUT; open OUT, ">${CATOP}/crlnumber"; @@ -145,6 +166,7 @@ if ($WHAT eq '-newcert' ) { close OUT; # ask user for existing CA certificate print "CA certificate filename (or enter to create)\n"; + my $FILE; $FILE = "" unless defined($FILE = ); $FILE =~ s{\R$}{}; if ($FILE ne "") { @@ -152,44 +174,42 @@ if ($WHAT eq '-newcert' ) { copy_pemfile($FILE,"${CATOP}/$CACERT", "CERTIFICATE"); } else { print "Making CA certificate ...\n"; - $RET = run("$REQ -new -keyout" - . " ${CATOP}/private/$CAKEY" + $RET = run("$REQ -new -keyout ${CATOP}/private/$CAKEY" . " -out ${CATOP}/$CAREQ $EXTRA{req}"); $RET = run("$CA -create_serial" . " -out ${CATOP}/$CACERT $CADAYS -batch" . " -keyfile ${CATOP}/private/$CAKEY -selfsign" - . " -extensions v3_ca $EXTRA{ca}" - . " -infiles ${CATOP}/$CAREQ") if $RET == 0; + . " -extensions v3_ca" + . " -infiles ${CATOP}/$CAREQ $EXTRA{ca}") if $RET == 0; print "CA certificate is in ${CATOP}/$CACERT\n" if $RET == 0; } } elsif ($WHAT eq '-pkcs12' ) { my $cname = $ARGV[0]; $cname = "My Certificate" unless defined $cname; $RET = run("$PKCS12 -in $NEWCERT -inkey $NEWKEY" - . " -certfile ${CATOP}/$CACERT" - . " -out $NEWP12" + . " -certfile ${CATOP}/$CACERT -out $NEWP12" . " -export -name \"$cname\" $EXTRA{pkcs12}"); print "PKCS #12 file is in $NEWP12\n" if $RET == 0; } elsif ($WHAT eq '-xsign' ) { - $RET = run("$CA -policy policy_anything $EXTRA{ca} -infiles $NEWREQ"); + $RET = run("$CA -policy policy_anything -infiles $NEWREQ $EXTRA{ca}"); } elsif ($WHAT eq '-sign' ) { - $RET = run("$CA -policy policy_anything -out $NEWCERT $EXTRA{ca} -infiles $NEWREQ"); + $RET = run("$CA -policy policy_anything -out $NEWCERT" + . " -infiles $NEWREQ $EXTRA{ca}"); print "Signed certificate is in $NEWCERT\n" if $RET == 0; } elsif ($WHAT eq '-signCA' ) { $RET = run("$CA -policy policy_anything -out $NEWCERT" - . " -extensions v3_ca $EXTRA{ca} -infiles $NEWREQ"); + . " -extensions v3_ca -infiles $NEWREQ $EXTRA{ca}"); print "Signed CA certificate is in $NEWCERT\n" if $RET == 0; } elsif ($WHAT eq '-signcert' ) { $RET = run("$X509 -x509toreq -in $NEWREQ -signkey $NEWREQ" . " -out tmp.pem $EXTRA{x509}"); $RET = run("$CA -policy policy_anything -out $NEWCERT" - . "$EXTRA{ca} -infiles tmp.pem") if $RET == 0; + . "-infiles tmp.pem $EXTRA{ca}") if $RET == 0; print "Signed certificate is in $NEWCERT\n" if $RET == 0; } elsif ($WHAT eq '-verify' ) { my @files = @ARGV ? @ARGV : ( $NEWCERT ); - my $file; - foreach $file (@files) { - my $status = run("$VERIFY \"-CAfile\" ${CATOP}/$CACERT $file $EXTRA{verify}"); + foreach my $file (@files) { + my $status = run("$VERIFY -CAfile ${CATOP}/$CACERT $file $EXTRA{verify}"); $RET = $status if $status != 0; } } elsif ($WHAT eq '-crl' ) { diff --git a/apps/build.info b/apps/build.info index 08f83cc9..e161bd2c 100644 --- a/apps/build.info +++ b/apps/build.info @@ -13,15 +13,40 @@ ENDIF $OPENSSLSRC=\ openssl.c progs.c \ asn1pars.c ca.c ciphers.c cms.c crl.c crl2p7.c dgst.c \ - ec.c ecparam.c enc.c engine.c errstr.c \ + enc.c errstr.c \ genpkey.c genrsa.c kdf.c mac.c nseq.c ocsp.c passwd.c pkcs12.c pkcs7.c \ pkcs8.c pkey.c pkeyparam.c pkeyutl.c prime.c rand.c req.c rsa.c \ rsautl.c s_client.c s_server.c s_time.c sess_id.c smime.c speed.c \ - spkac.c srp.c ts.c verify.c version.c x509.c rehash.c storeutl.c \ + spkac.c verify.c version.c x509.c rehash.c storeutl.c \ list.c info.c provider.c fipsinstall.c +IF[{- !$disabled{'des'} -}] + $OPENSSLSRC=$OPENSSLSRC pkcs12.c +ENDIF +IF[{- !$disabled{'ec'} -}] + $OPENSSLSRC=$OPENSSLSRC ec.c ecparam.c +ENDIF +IF[{- !$disabled{'ocsp'} -}] + $OPENSSLSRC=$OPENSSLSRC ocsp.c +ENDIF +IF[{- !$disabled{'srp'} -}] + $OPENSSLSRC=$OPENSSLSRC srp.c +ENDIF +IF[{- !$disabled{'ts'} -}] + $OPENSSLSRC=$OPENSSLSRC ts.c +ENDIF IF[{- !$disabled{'deprecated-3.0'} -}] - $OPENSSLSRC=$OPENSSLSRC \ - dhparam.c dsa.c dsaparam.c gendsa.c + IF[{- !$disabled{'dh'} -}] + $OPENSSLSRC=$OPENSSLSRC dhparam.c + ENDIF + IF[{- !$disabled{'dsa'} -}] + $OPENSSLSRC=$OPENSSLSRC dsa.c dsaparam.c gendsa.c + ENDIF + IF[{- !$disabled{'engine'} -}] + $OPENSSLSRC=$OPENSSLSRC engine.c + ENDIF +ENDIF +IF[{- !$disabled{'cmp'} -}] + $OPENSSLSRC=$OPENSSLSRC cmp_mock_srv.c ENDIF IF[{- !$disabled{apps} -}] diff --git a/apps/ca.c b/apps/ca.c index e3e2fd2e..a2cd4d98 100644 --- a/apps/ca.c +++ b/apps/ca.c @@ -89,17 +89,20 @@ typedef enum { static char *lookup_conf(const CONF *conf, const char *group, const char *tag); static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, - const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + const EVP_MD *dgst, + STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(OPENSSL_STRING) *vfyopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, const char *subj, unsigned long chtype, int multirdn, int email_dn, const char *startdate, const char *enddate, long days, int batch, const char *ext_sect, CONF *conf, int verbose, unsigned long certopt, unsigned long nameopt, - int default_op, int ext_copy, int selfsign, - unsigned char *sm2_id, size_t sm2idlen); + int default_op, int ext_copy, int selfsign); static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, - const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + const EVP_MD *dgst, + STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(OPENSSL_STRING) *vfyopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, const char *subj, unsigned long chtype, int multirdn, int email_dn, const char *startdate, @@ -142,13 +145,13 @@ typedef enum OPTION_choice { OPT_ENGINE, OPT_VERBOSE, OPT_CONFIG, OPT_NAME, OPT_SUBJ, OPT_UTF8, OPT_CREATE_SERIAL, OPT_MULTIVALUE_RDN, OPT_STARTDATE, OPT_ENDDATE, OPT_DAYS, OPT_MD, OPT_POLICY, OPT_KEYFILE, OPT_KEYFORM, OPT_PASSIN, - OPT_KEY, OPT_CERT, OPT_SELFSIGN, OPT_IN, OPT_OUT, OPT_OUTDIR, + OPT_KEY, OPT_CERT, OPT_SELFSIGN, OPT_IN, OPT_OUT, OPT_OUTDIR, OPT_VFYOPT, OPT_SIGOPT, OPT_NOTEXT, OPT_BATCH, OPT_PRESERVEDN, OPT_NOEMAILDN, OPT_GENCRL, OPT_MSIE_HACK, OPT_CRLDAYS, OPT_CRLHOURS, OPT_CRLSEC, OPT_INFILES, OPT_SS_CERT, OPT_SPKAC, OPT_REVOKE, OPT_VALID, OPT_EXTENSIONS, OPT_EXTFILE, OPT_STATUS, OPT_UPDATEDB, OPT_CRLEXTS, OPT_RAND_SERIAL, - OPT_R_ENUM, OPT_SM2ID, OPT_SM2HEXID, OPT_PROV_ENUM, + OPT_R_ENUM, OPT_PROV_ENUM, /* Do not change the order here; see related case statements below */ OPT_CRL_REASON, OPT_CRL_HOLD, OPT_CRL_COMPROMISE, OPT_CRL_CA_COMPROMISE } OPTION_CHOICE; @@ -197,12 +200,6 @@ const OPTIONS ca_options[] = { "Extension section (override value in config file)"}, {"extfile", OPT_EXTFILE, '<', "Configuration file with X509v3 extensions to add"}, -#ifndef OPENSSL_NO_SM2 - {"sm2-id", OPT_SM2ID, 's', - "Specify an ID string to verify an SM2 certificate request"}, - {"sm2-hex-id", OPT_SM2HEXID, 's', - "Specify a hex ID string to verify an SM2 certificate request"}, -#endif {"preserveDN", OPT_PRESERVEDN, '-', "Don't re-order the DN"}, {"noemailDN", OPT_NOEMAILDN, '-', "Don't add the EMAIL field to the DN"}, @@ -216,6 +213,7 @@ const OPTIONS ca_options[] = { {"selfsign", OPT_SELFSIGN, '-', "Sign a cert with the key associated with it"}, {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, + {"vfyopt", OPT_SIGOPT, 's', "Verification parameter in n:v form"}, OPT_SECTION("Revocation"), {"gencrl", OPT_GENCRL, '-', "Generate a new CRL"}, @@ -257,7 +255,7 @@ int ca_main(int argc, char **argv) CA_DB *db = NULL; DB_ATTR db_attr; STACK_OF(CONF_VALUE) *attribs = NULL; - STACK_OF(OPENSSL_STRING) *sigopts = NULL; + STACK_OF(OPENSSL_STRING) *sigopts = NULL, *vfyopts = NULL; STACK_OF(X509) *cert_sk = NULL; X509_CRL *crl = NULL; const EVP_MD *dgst = NULL; @@ -286,9 +284,6 @@ int ca_main(int argc, char **argv) REVINFO_TYPE rev_type = REV_NONE; X509_REVOKED *r = NULL; OPTION_CHOICE o; - unsigned char *sm2_id = NULL; - size_t sm2_idlen = 0; - int sm2_free = 0; prog = opt_init(argc, argv, ca_options); while ((o = opt_next()) != OPT_EOF) { @@ -385,6 +380,12 @@ opthelp: if (sigopts == NULL || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) goto end; break; + case OPT_VFYOPT: + if (vfyopts == NULL) + vfyopts = sk_OPENSSL_STRING_new_null(); + if (vfyopts == NULL || !sk_OPENSSL_STRING_push(vfyopts, opt_arg())) + goto end; + break; case OPT_NOTEXT: notext = 1; break; @@ -456,30 +457,6 @@ opthelp: case OPT_ENGINE: e = setup_engine(opt_arg(), 0); break; - case OPT_SM2ID: - /* we assume the input is not a hex string */ - if (sm2_id != NULL) { - BIO_printf(bio_err, - "Use one of the options 'sm2-hex-id' or 'sm2-id'\n"); - goto end; - } - sm2_id = (unsigned char *)opt_arg(); - sm2_idlen = strlen((const char *)sm2_id); - break; - case OPT_SM2HEXID: - /* try to parse the input as hex string first */ - if (sm2_id != NULL) { - BIO_printf(bio_err, - "Use one of the options 'sm2-hex-id' or 'sm2-id'\n"); - goto end; - } - sm2_free = 1; - sm2_id = OPENSSL_hexstr2buf(opt_arg(), (long *)&sm2_idlen); - if (sm2_id == NULL) { - BIO_printf(bio_err, "Invalid hex string input\n"); - goto end; - } - break; } } end_of_options: @@ -944,8 +921,8 @@ end_of_options: } if (ss_cert_file != NULL) { total++; - j = certify_cert(&x, ss_cert_file, pkey, x509, dgst, sigopts, - attribs, + j = certify_cert(&x, ss_cert_file, pkey, x509, dgst, + sigopts, vfyopts, attribs, db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, batch, extensions, conf, verbose, certopt, get_nameopt(), default_op, @@ -965,11 +942,11 @@ end_of_options: } if (infile != NULL) { total++; - j = certify(&x, infile, pkey, x509p, dgst, sigopts, attribs, db, + j = certify(&x, infile, pkey, x509p, dgst, sigopts, vfyopts, + attribs, db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, batch, extensions, conf, verbose, - certopt, get_nameopt(), default_op, ext_copy, selfsign, - sm2_id, sm2_idlen); + certopt, get_nameopt(), default_op, ext_copy, selfsign); if (j < 0) goto end; if (j > 0) { @@ -985,11 +962,11 @@ end_of_options: } for (i = 0; i < argc; i++) { total++; - j = certify(&x, argv[i], pkey, x509p, dgst, sigopts, attribs, db, + j = certify(&x, argv[i], pkey, x509p, dgst, sigopts, vfyopts, + attribs, db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, batch, extensions, conf, verbose, - certopt, get_nameopt(), default_op, ext_copy, selfsign, - sm2_id, sm2_idlen); + certopt, get_nameopt(), default_op, ext_copy, selfsign); if (j < 0) goto end; if (j > 0) { @@ -1287,8 +1264,6 @@ end_of_options: ret = 0; end: - if (sm2_free) - OPENSSL_free(sm2_id); if (ret) ERR_print_errors(bio_err); BIO_free_all(Sout); @@ -1302,6 +1277,7 @@ end_of_options: BN_free(crlnumber); free_index(db); sk_OPENSSL_STRING_free(sigopts); + sk_OPENSSL_STRING_free(vfyopts); EVP_PKEY_free(pkey); X509_free(x509); X509_CRL_free(crl); @@ -1320,15 +1296,16 @@ static char *lookup_conf(const CONF *conf, const char *section, const char *tag) } static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, - const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + const EVP_MD *dgst, + STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(OPENSSL_STRING) *vfyopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, const char *subj, unsigned long chtype, int multirdn, int email_dn, const char *startdate, const char *enddate, long days, int batch, const char *ext_sect, CONF *lconf, int verbose, unsigned long certopt, unsigned long nameopt, - int default_op, int ext_copy, int selfsign, - unsigned char *sm2id, size_t sm2idlen) + int default_op, int ext_copy, int selfsign) { X509_REQ *req = NULL; BIO *in = NULL; @@ -1360,26 +1337,7 @@ static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, BIO_printf(bio_err, "error unpacking public key\n"); goto end; } - if (sm2id != NULL) { -#ifndef OPENSSL_NO_SM2 - ASN1_OCTET_STRING *v; - - v = ASN1_OCTET_STRING_new(); - if (v == NULL) { - BIO_printf(bio_err, "error: SM2 ID allocation failed\n"); - goto end; - } - - if (!ASN1_OCTET_STRING_set(v, sm2id, sm2idlen)) { - BIO_printf(bio_err, "error: setting SM2 ID failed\n"); - ASN1_OCTET_STRING_free(v); - goto end; - } - - X509_REQ_set0_sm2_id(req, v); -#endif - } - i = X509_REQ_verify(req, pktmp); + i = do_X509_REQ_verify(req, pktmp, vfyopts); pktmp = NULL; if (i < 0) { ok = 0; @@ -1409,7 +1367,9 @@ static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, } static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, - const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + const EVP_MD *dgst, + STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(OPENSSL_STRING) *vfyopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, const char *subj, unsigned long chtype, int multirdn, int email_dn, const char *startdate, @@ -1433,7 +1393,7 @@ static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x BIO_printf(bio_err, "error unpacking public key\n"); goto end; } - i = X509_verify(req, pktmp); + i = do_X509_verify(req, pktmp, vfyopts); if (i < 0) { ok = 0; BIO_printf(bio_err, "Signature verification problems....\n"); @@ -1470,7 +1430,8 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, CONF *lconf, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy, int selfsign) { - X509_NAME *name = NULL, *CAname = NULL, *subject = NULL; + const X509_NAME *name = NULL; + X509_NAME *CAname = NULL, *subject = NULL; const ASN1_TIME *tm; ASN1_STRING *str, *str2; ASN1_OBJECT *obj; diff --git a/apps/cmp_mock_srv.c b/apps/cmp_mock_srv.c new file mode 100644 index 00000000..8ffe4ca5 --- /dev/null +++ b/apps/cmp_mock_srv.c @@ -0,0 +1,407 @@ +/* + * Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright Siemens AG 2018-2020 + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or atf + * https://www.openssl.org/source/license.html + */ + +#include "apps.h" +#include "cmp_mock_srv.h" + +#include +#include +#include + +/* the context for the CMP mock server */ +typedef struct +{ + X509 *certOut; /* certificate to be returned in cp/ip/kup msg */ + STACK_OF(X509) *chainOut; /* chain of certOut to add to extraCerts field */ + STACK_OF(X509) *caPubsOut; /* certs to return in caPubs field of ip msg */ + OSSL_CMP_PKISI *statusOut; /* status for ip/cp/kup/rp msg unless polling */ + int sendError; /* send error response also on valid requests */ + OSSL_CMP_MSG *certReq; /* ir/cr/p10cr/kur remembered while polling */ + int certReqId; /* id of last ir/cr/kur, used for polling */ + int pollCount; /* number of polls before actual cert response */ + int checkAfterTime; /* time the client should wait between polling */ +} mock_srv_ctx; + + +static void mock_srv_ctx_free(mock_srv_ctx *ctx) +{ + if (ctx == NULL) + return; + + OSSL_CMP_PKISI_free(ctx->statusOut); + X509_free(ctx->certOut); + sk_X509_pop_free(ctx->chainOut, X509_free); + sk_X509_pop_free(ctx->caPubsOut, X509_free); + OSSL_CMP_MSG_free(ctx->certReq); + OPENSSL_free(ctx); +} + +static mock_srv_ctx *mock_srv_ctx_new(void) +{ + mock_srv_ctx *ctx = OPENSSL_zalloc(sizeof(mock_srv_ctx)); + + if (ctx == NULL) + goto err; + + if ((ctx->statusOut = OSSL_CMP_PKISI_new()) == NULL) + goto err; + + ctx->certReqId = -1; + + /* all other elements are initialized to 0 or NULL, respectively */ + return ctx; + err: + mock_srv_ctx_free(ctx); + return NULL; +} + +int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + + if (ctx == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return 0; + } + if (cert == NULL || X509_up_ref(cert)) { + X509_free(ctx->certOut); + ctx->certOut = cert; + return 1; + } + return 0; +} + +int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx, + STACK_OF(X509) *chain) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + STACK_OF(X509) *chain_copy = NULL; + + if (ctx == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return 0; + } + if (chain != NULL && (chain_copy = X509_chain_up_ref(chain)) == NULL) + return 0; + sk_X509_pop_free(ctx->chainOut, X509_free); + ctx->chainOut = chain_copy; + return 1; +} + +int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx, + STACK_OF(X509) *caPubs) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + STACK_OF(X509) *caPubs_copy = NULL; + + if (ctx == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return 0; + } + if (caPubs != NULL && (caPubs_copy = X509_chain_up_ref(caPubs)) == NULL) + return 0; + sk_X509_pop_free(ctx->caPubsOut, X509_free); + ctx->caPubsOut = caPubs_copy; + return 1; +} + +int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status, + int fail_info, const char *text) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + OSSL_CMP_PKISI *si; + + if (ctx == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return 0; + } + if ((si = OSSL_CMP_STATUSINFO_new(status, fail_info, text)) == NULL) + return 0; + OSSL_CMP_PKISI_free(ctx->statusOut); + ctx->statusOut = si; + return 1; +} + +int ossl_cmp_mock_srv_set_send_error(OSSL_CMP_SRV_CTX *srv_ctx, int val) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + + if (ctx == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return 0; + } + ctx->sendError = val != 0; + return 1; +} + +int ossl_cmp_mock_srv_set_pollCount(OSSL_CMP_SRV_CTX *srv_ctx, int count) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + + if (ctx == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return 0; + } + if (count < 0) { + CMPerr(0, CMP_R_INVALID_ARGS); + return 0; + } + ctx->pollCount = count; + return 1; +} + +int ossl_cmp_mock_srv_set_checkAfterTime(OSSL_CMP_SRV_CTX *srv_ctx, int sec) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + + if (ctx == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return 0; + } + ctx->checkAfterTime = sec; + return 1; +} + +static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *cert_req, + int certReqId, + const OSSL_CRMF_MSG *crm, + const X509_REQ *p10cr, + X509 **certOut, + STACK_OF(X509) **chainOut, + STACK_OF(X509) **caPubs) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + OSSL_CMP_PKISI *si = NULL; + + if (ctx == NULL || cert_req == NULL + || certOut == NULL || chainOut == NULL || caPubs == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return NULL; + } + if (ctx->sendError) { + CMPerr(0, CMP_R_ERROR_PROCESSING_MESSAGE); + return NULL; + } + + *certOut = NULL; + *chainOut = NULL; + *caPubs = NULL; + ctx->certReqId = certReqId; + if (ctx->pollCount > 0) { + ctx->pollCount--; + OSSL_CMP_MSG_free(ctx->certReq); + if ((ctx->certReq = OSSL_CMP_MSG_dup(cert_req)) == NULL) + return NULL; + return OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_waiting, 0, NULL); + } + if (ctx->certOut != NULL + && (*certOut = X509_dup(ctx->certOut)) == NULL) + goto err; + if (ctx->chainOut != NULL + && (*chainOut = X509_chain_up_ref(ctx->chainOut)) == NULL) + goto err; + if (ctx->caPubsOut != NULL + && (*caPubs = X509_chain_up_ref(ctx->caPubsOut)) == NULL) + goto err; + if (ctx->statusOut != NULL + && (si = OSSL_CMP_PKISI_dup(ctx->statusOut)) == NULL) + goto err; + return si; + + err: + X509_free(*certOut); + *certOut = NULL; + sk_X509_pop_free(*chainOut, X509_free); + *chainOut = NULL; + sk_X509_pop_free(*caPubs, X509_free); + *caPubs = NULL; + return NULL; +} + +static OSSL_CMP_PKISI *process_rr(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *rr, + const X509_NAME *issuer, + const ASN1_INTEGER *serial) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + + if (ctx == NULL || rr == NULL || issuer == NULL || serial == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return NULL; + } + if (ctx->sendError || ctx->certOut == NULL) { + CMPerr(0, CMP_R_ERROR_PROCESSING_MESSAGE); + return NULL; + } + + /* accept revocation only for the certificate we sent in ir/cr/kur */ + if (X509_NAME_cmp(issuer, X509_get_issuer_name(ctx->certOut)) != 0 + || ASN1_INTEGER_cmp(serial, + X509_get0_serialNumber(ctx->certOut)) != 0) { + CMPerr(0, CMP_R_REQUEST_NOT_ACCEPTED); + return NULL; + } + return OSSL_CMP_PKISI_dup(ctx->statusOut); +} + +static int process_genm(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *genm, + const STACK_OF(OSSL_CMP_ITAV) *in, + STACK_OF(OSSL_CMP_ITAV) **out) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + + if (ctx == NULL || genm == NULL || in == NULL || out == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return 0; + } + if (ctx->sendError) { + CMPerr(0, CMP_R_ERROR_PROCESSING_MESSAGE); + return 0; + } + + *out = sk_OSSL_CMP_ITAV_deep_copy(in, OSSL_CMP_ITAV_dup, + OSSL_CMP_ITAV_free); + return *out != NULL; +} + +static void process_error(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *error, + const OSSL_CMP_PKISI *statusInfo, + const ASN1_INTEGER *errorCode, + const OSSL_CMP_PKIFREETEXT *errorDetails) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + char buf[OSSL_CMP_PKISI_BUFLEN]; + char *sibuf; + int i; + + if (ctx == NULL || error == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return; + } + + BIO_printf(bio_err, "mock server received error:\n"); + + if (statusInfo == NULL) { + BIO_printf(bio_err, "pkiStatusInfo absent\n"); + } else { + sibuf = OSSL_CMP_snprint_PKIStatusInfo(statusInfo, buf, sizeof(buf)); + BIO_printf(bio_err, "pkiStatusInfo: %s\n", + sibuf != NULL ? sibuf: ""); + } + + if (errorCode == NULL) + BIO_printf(bio_err, "errorCode absent\n"); + else + BIO_printf(bio_err, "errorCode: %ld\n", ASN1_INTEGER_get(errorCode)); + + if (sk_ASN1_UTF8STRING_num(errorDetails) <= 0) { + BIO_printf(bio_err, "errorDetails absent\n"); + } else { + /* TODO could use sk_ASN1_UTF8STRING2text() if exported */ + BIO_printf(bio_err, "errorDetails: "); + for (i = 0; i < sk_ASN1_UTF8STRING_num(errorDetails); i++) { + if (i > 0) + BIO_printf(bio_err, ", "); + BIO_printf(bio_err, "\""); + ASN1_STRING_print(bio_err, + sk_ASN1_UTF8STRING_value(errorDetails, i)); + BIO_printf(bio_err, "\""); + } + BIO_printf(bio_err, "\n"); + } +} + +static int process_certConf(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *certConf, int certReqId, + const ASN1_OCTET_STRING *certHash, + const OSSL_CMP_PKISI *si) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + ASN1_OCTET_STRING *digest; + + if (ctx == NULL || certConf == NULL || certHash == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return 0; + } + if (ctx->sendError || ctx->certOut == NULL) { + CMPerr(0, CMP_R_ERROR_PROCESSING_MESSAGE); + return 0; + } + + if (certReqId != ctx->certReqId) { + /* in case of error, invalid reqId -1 */ + CMPerr(0, CMP_R_BAD_REQUEST_ID); + return 0; + } + + if ((digest = X509_digest_sig(ctx->certOut)) == NULL) + return 0; + if (ASN1_OCTET_STRING_cmp(certHash, digest) != 0) { + ASN1_OCTET_STRING_free(digest); + CMPerr(0, CMP_R_CERTHASH_UNMATCHED); + return 0; + } + ASN1_OCTET_STRING_free(digest); + return 1; +} + +static int process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *pollReq, int certReqId, + OSSL_CMP_MSG **certReq, int64_t *check_after) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + + if (ctx == NULL || pollReq == NULL + || certReq == NULL || check_after == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return 0; + } + if (ctx->sendError || ctx->certReq == NULL) { + *certReq = NULL; + CMPerr(0, CMP_R_ERROR_PROCESSING_MESSAGE); + return 0; + } + + if (ctx->pollCount == 0) { + *certReq = ctx->certReq; + ctx->certReq = NULL; + *check_after = 0; + } else { + ctx->pollCount--; + *certReq = NULL; + *check_after = ctx->checkAfterTime; + } + return 1; +} + +OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(void) +{ + OSSL_CMP_SRV_CTX *srv_ctx = OSSL_CMP_SRV_CTX_new(); + mock_srv_ctx *ctx = mock_srv_ctx_new(); + + if (srv_ctx != NULL && ctx != NULL + && OSSL_CMP_SRV_CTX_init(srv_ctx, ctx, process_cert_request, + process_rr, process_genm, process_error, + process_certConf, process_pollReq)) + return srv_ctx; + + mock_srv_ctx_free(ctx); + OSSL_CMP_SRV_CTX_free(srv_ctx); + return NULL; +} + +void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX *srv_ctx) +{ + if (srv_ctx != NULL) + mock_srv_ctx_free(OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx)); + OSSL_CMP_SRV_CTX_free(srv_ctx); +} diff --git a/apps/cmp_mock_srv.h b/apps/cmp_mock_srv.h new file mode 100644 index 00000000..bddc44df --- /dev/null +++ b/apps/cmp_mock_srv.h @@ -0,0 +1,34 @@ +/* + * Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright Siemens AG 2018-2020 + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_APPS_CMP_MOCK_SRV_H +# define OSSL_APPS_CMP_MOCK_SRV_H + +# include +# ifndef OPENSSL_NO_CMP + +# include + +OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(void); +void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX *srv_ctx); + +int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert); +int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx, + STACK_OF(X509) *chain); +int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx, + STACK_OF(X509) *caPubs); +int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status, + int fail_info, const char *text); +int ossl_cmp_mock_srv_set_send_error(OSSL_CMP_SRV_CTX *srv_ctx, int val); +int ossl_cmp_mock_srv_set_pollCount(OSSL_CMP_SRV_CTX *srv_ctx, int count); +int ossl_cmp_mock_srv_set_checkAfterTime(OSSL_CMP_SRV_CTX *srv_ctx, int sec); + +# endif /* !defined(OPENSSL_NO_CMP) */ +#endif /* !defined(OSSL_APPS_CMP_MOCK_SRV_H) */ diff --git a/apps/dh1024.pem b/apps/dh1024.pem deleted file mode 100644 index 813e8a4a..00000000 --- a/apps/dh1024.pem +++ /dev/null @@ -1,10 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR -Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL -/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC ------END DH PARAMETERS----- - -These are the 1024-bit DH parameters from "Internet Key Exchange -Protocol Version 2 (IKEv2)": https://tools.ietf.org/html/rfc5996 - -See https://tools.ietf.org/html/rfc2412 for how they were generated. diff --git a/apps/dh2048.pem b/apps/dh2048.pem deleted file mode 100644 index 288a2099..00000000 --- a/apps/dh2048.pem +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIIBCAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb -IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft -awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT -mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh -fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq -5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAg== ------END DH PARAMETERS----- - -These are the 2048-bit DH parameters from "More Modular Exponential -(MODP) Diffie-Hellman groups for Internet Key Exchange (IKE)": -https://tools.ietf.org/html/rfc3526 - -See https://tools.ietf.org/html/rfc2412 for how they were generated. diff --git a/apps/dh4096.pem b/apps/dh4096.pem deleted file mode 100644 index 08560e12..00000000 --- a/apps/dh4096.pem +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIICCAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb -IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft -awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT -mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh -fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq -5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM -fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq -ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI -ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O -+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI -HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0BjGZ//////////8CAQI= ------END DH PARAMETERS----- - -These are the 4096-bit DH parameters from "More Modular Exponential -(MODP) Diffie-Hellman groups for Internet Key Exchange (IKE)": -https://tools.ietf.org/html/rfc3526 - -See https://tools.ietf.org/html/rfc2412 for how they were generated. diff --git a/apps/dhparam.c b/apps/dhparam.c index 3f694c5a..019a7ce8 100644 --- a/apps/dhparam.c +++ b/apps/dhparam.c @@ -11,28 +11,25 @@ #define OPENSSL_SUPPRESS_DEPRECATED #include -#ifdef OPENSSL_NO_DH -NON_EMPTY_TRANSLATION_UNIT -#else -# include -# include -# include -# include -# include "apps.h" -# include "progs.h" -# include -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include +#include -# ifndef OPENSSL_NO_DSA -# include -# endif +#ifndef OPENSSL_NO_DSA +# include +#endif -# define DEFBITS 2048 +#define DEFBITS 2048 static int dh_cb(int p, int n, BN_GENCB *cb); @@ -50,13 +47,13 @@ const OPTIONS dhparam_options[] = { OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, {"check", OPT_CHECK, '-', "Check the DH parameters"}, -# ifndef OPENSSL_NO_DSA +#ifndef OPENSSL_NO_DSA {"dsaparam", OPT_DSAPARAM, '-', "Read or generate DSA parameters, convert to DH"}, -# endif -# ifndef OPENSSL_NO_ENGINE +#endif +#ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, -# endif +#endif OPT_SECTION("Input"), {"in", OPT_IN, '<', "Input file"}, @@ -167,13 +164,13 @@ int dhparam_main(int argc, char **argv) if (g && !num) num = DEFBITS; -# ifndef OPENSSL_NO_DSA +#ifndef OPENSSL_NO_DSA if (dsaparam && g) { BIO_printf(bio_err, "generator may not be chosen for DSA parameters\n"); goto end; } -# endif +#endif out = bio_open_default(outfile, 'w', outformat); if (out == NULL) @@ -194,7 +191,7 @@ int dhparam_main(int argc, char **argv) BN_GENCB_set(cb, dh_cb, bio_err); -# ifndef OPENSSL_NO_DSA +#ifndef OPENSSL_NO_DSA if (dsaparam) { DSA *dsa = DSA_new(); @@ -217,7 +214,7 @@ int dhparam_main(int argc, char **argv) goto end; } } else -# endif +#endif { dh = DH_new(); BIO_printf(bio_err, @@ -238,7 +235,7 @@ int dhparam_main(int argc, char **argv) if (in == NULL) goto end; -# ifndef OPENSSL_NO_DSA +#ifndef OPENSSL_NO_DSA if (dsaparam) { DSA *dsa; @@ -260,7 +257,7 @@ int dhparam_main(int argc, char **argv) goto end; } } else -# endif +#endif { if (informat == FORMAT_ASN1) { /* @@ -397,4 +394,3 @@ static int dh_cb(int p, int n, BN_GENCB *cb) (void)BIO_flush(BN_GENCB_get_arg(cb)); return 1; } -#endif diff --git a/apps/dsa.c b/apps/dsa.c index 082aa964..200e959f 100644 --- a/apps/dsa.c +++ b/apps/dsa.c @@ -11,23 +11,20 @@ #define OPENSSL_SUPPRESS_DEPRECATED #include -#ifdef OPENSSL_NO_DSA -NON_EMPTY_TRANSLATION_UNIT -#else -# include -# include -# include -# include -# include "apps.h" -# include "progs.h" -# include -# include -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include +#include +#include typedef enum OPTION_choice { OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, @@ -43,14 +40,14 @@ const OPTIONS dsa_options[] = { OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, {"", OPT_CIPHER, '-', "Any supported cipher"}, -# ifndef OPENSSL_NO_RC4 +#ifndef OPENSSL_NO_RC4 {"pvk-strong", OPT_PVK_STRONG, '-', "Enable 'Strong' PVK encoding level (default)"}, {"pvk-weak", OPT_PVK_WEAK, '-', "Enable 'Weak' PVK encoding level"}, {"pvk-none", OPT_PVK_NONE, '-', "Don't enforce PVK encoding"}, -# endif -# ifndef OPENSSL_NO_ENGINE +#endif +#ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, -# endif +#endif OPT_SECTION("Input"), {"in", OPT_IN, 's', "Input key"}, @@ -82,9 +79,9 @@ int dsa_main(int argc, char **argv) OPTION_CHOICE o; int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, noout = 0; int i, modulus = 0, pubin = 0, pubout = 0, ret = 1; -# ifndef OPENSSL_NO_RC4 +#ifndef OPENSSL_NO_RC4 int pvk_encr = 2; -# endif +#endif int private = 0; prog = opt_init(argc, argv, dsa_options); @@ -230,7 +227,7 @@ int dsa_main(int argc, char **argv) i = PEM_write_bio_DSAPrivateKey(out, dsa, enc, NULL, 0, NULL, passout); } -# ifndef OPENSSL_NO_RSA +#ifndef OPENSSL_NO_RSA } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) { EVP_PKEY *pk; pk = EVP_PKEY_new(); @@ -245,13 +242,13 @@ int dsa_main(int argc, char **argv) goto end; } assert(private); -# ifdef OPENSSL_NO_RC4 +# ifdef OPENSSL_NO_RC4 BIO_printf(bio_err, "PVK format not supported\n"); EVP_PKEY_free(pk); goto end; -# else +# else i = i2b_PVK_bio(out, pk, pvk_encr, 0, passout); -# endif +# endif } else if (pubin || pubout) { i = i2b_PublicKey_bio(out, pk); } else { @@ -259,7 +256,7 @@ int dsa_main(int argc, char **argv) i = i2b_PrivateKey_bio(out, pk); } EVP_PKEY_free(pk); -# endif +#endif } else { BIO_printf(bio_err, "bad output format specified for outfile\n"); goto end; @@ -278,4 +275,3 @@ int dsa_main(int argc, char **argv) OPENSSL_free(passout); return ret; } -#endif diff --git a/apps/dsaparam.c b/apps/dsaparam.c index 04e09e79..11f47b44 100644 --- a/apps/dsaparam.c +++ b/apps/dsaparam.c @@ -11,22 +11,19 @@ #define OPENSSL_SUPPRESS_DEPRECATED #include -#ifdef OPENSSL_NO_DSA -NON_EMPTY_TRANSLATION_UNIT -#else -# include -# include -# include -# include -# include "apps.h" -# include "progs.h" -# include -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include +#include static int verbose = 0; @@ -44,9 +41,9 @@ const OPTIONS dsaparam_options[] = { OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, -# ifndef OPENSSL_NO_ENGINE +#ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, -# endif +#endif OPT_SECTION("Input"), {"in", OPT_IN, '<', "Input file"}, @@ -286,4 +283,3 @@ static int dsa_cb(int p, int n, BN_GENCB *cb) (void)BIO_flush(BN_GENCB_get_arg(cb)); return 1; } -#endif diff --git a/apps/ec.c b/apps/ec.c index 6a387992..ba37d806 100644 --- a/apps/ec.c +++ b/apps/ec.c @@ -8,19 +8,16 @@ */ #include -#ifdef OPENSSL_NO_EC -NON_EMPTY_TRANSLATION_UNIT -#else -# include -# include -# include -# include "apps.h" -# include "progs.h" -# include -# include -# include -# include +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include static OPT_PAIR conv_forms[] = { {"compressed", POINT_CONVERSION_COMPRESSED}, @@ -46,9 +43,9 @@ typedef enum OPTION_choice { const OPTIONS ec_options[] = { OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, -# ifndef OPENSSL_NO_ENGINE +#ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -# endif +#endif OPT_SECTION("Input"), {"in", OPT_IN, 's', "Input file"}, @@ -291,4 +288,3 @@ int ec_main(int argc, char **argv) OPENSSL_free(passout); return ret; } -#endif diff --git a/apps/ecparam.c b/apps/ecparam.c index ed4f4f1f..b93c2fa0 100644 --- a/apps/ecparam.c +++ b/apps/ecparam.c @@ -9,22 +9,19 @@ */ #include -#ifdef OPENSSL_NO_EC -NON_EMPTY_TRANSLATION_UNIT -#else -# include -# include -# include -# include -# include "apps.h" -# include "progs.h" -# include -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include +#include typedef enum OPTION_choice { OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, @@ -39,9 +36,9 @@ const OPTIONS ecparam_options[] = { {"help", OPT_HELP, '-', "Display this summary"}, {"list_curves", OPT_LIST_CURVES, '-', "Prints a list of all curve 'short names'"}, -# ifndef OPENSSL_NO_ENGINE +#ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -# endif +#endif {"genkey", OPT_GENKEY, '-', "Generate ec key"}, {"in", OPT_IN, '<', "Input file - default stdin"}, @@ -473,5 +470,3 @@ int ecparam_main(int argc, char **argv) BIO_free_all(out); return ret; } - -#endif diff --git a/apps/engine.c b/apps/engine.c index a71e1110..c070f1f8 100644 --- a/apps/engine.c +++ b/apps/engine.c @@ -8,19 +8,16 @@ */ #include -#ifdef OPENSSL_NO_ENGINE -NON_EMPTY_TRANSLATION_UNIT -#else -# include "apps.h" -# include "progs.h" -# include -# include -# include -# include -# include -# include -# include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include +#include +#include typedef enum OPTION_choice { OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, @@ -491,4 +488,3 @@ int engine_main(int argc, char **argv) BIO_free_all(out); return ret; } -#endif diff --git a/apps/gendsa.c b/apps/gendsa.c index cf24416b..56939c56 100644 --- a/apps/gendsa.c +++ b/apps/gendsa.c @@ -11,22 +11,19 @@ #define OPENSSL_SUPPRESS_DEPRECATED #include -#ifdef OPENSSL_NO_DSA -NON_EMPTY_TRANSLATION_UNIT -#else -# include -# include -# include -# include -# include "apps.h" -# include "progs.h" -# include -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include +#include typedef enum OPTION_choice { OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, @@ -39,9 +36,9 @@ const OPTIONS gendsa_options[] = { OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, -# ifndef OPENSSL_NO_ENGINE +#ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -# endif +#endif OPT_SECTION("Output"), {"out", OPT_OUT, '>', "Output the key to the specified file"}, @@ -162,4 +159,3 @@ int gendsa_main(int argc, char **argv) OPENSSL_free(passout); return ret; } -#endif diff --git a/apps/genrsa.c b/apps/genrsa.c index a7d04fed..b80f07c2 100644 --- a/apps/genrsa.c +++ b/apps/genrsa.c @@ -8,27 +8,24 @@ */ #include -#ifdef OPENSSL_NO_RSA -NON_EMPTY_TRANSLATION_UNIT -#else -# include -# include -# include -# include -# include "apps.h" -# include "progs.h" -# include -# include -# include -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include +#include +#include +#include -# define DEFBITS 2048 -# define DEFPRIMES 2 +#define DEFBITS 2048 +#define DEFPRIMES 2 static int verbose = 0; @@ -46,9 +43,9 @@ const OPTIONS genrsa_options[] = { OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, -# ifndef OPENSSL_NO_ENGINE +#ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -# endif +#endif OPT_SECTION("Input"), {"3", OPT_3, '-', "Use 3 for the E value"}, @@ -224,4 +221,3 @@ static int genrsa_cb(int p, int n, BN_GENCB *cb) (void)BIO_flush(BN_GENCB_get_arg(cb)); return 1; } -#endif diff --git a/apps/include/apps.h b/apps/include/apps.h index 78be6476..f43c12db 100644 --- a/apps/include/apps.h +++ b/apps/include/apps.h @@ -91,7 +91,7 @@ int wrap_password_callback(char *buf, int bufsiz, int verify, void *cb_data); int chopup_args(ARGS *arg, char *buf); int dump_cert_text(BIO *out, X509 *x); -void print_name(BIO *out, const char *title, X509_NAME *nm, +void print_name(BIO *out, const char *title, const X509_NAME *nm, unsigned long lflags); void print_bignum_var(BIO *, const BIGNUM *, const char*, int, unsigned char *); @@ -197,12 +197,17 @@ X509_NAME *parse_name(const char *str, long chtype, int multirdn); void policies_print(X509_STORE_CTX *ctx); int bio_to_mem(unsigned char **out, int maxlen, BIO *in); int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value); +int x509_ctrl_string(X509 *x, const char *value); +int x509_req_ctrl_string(X509_REQ *x, const char *value); int init_gen_str(EVP_PKEY_CTX **pctx, const char *algname, ENGINE *e, int do_param); int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts); +int do_X509_verify(X509 *x, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *vfyopts); int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts); +int do_X509_REQ_verify(X509_REQ *x, EVP_PKEY *pkey, + STACK_OF(OPENSSL_STRING) *vfyopts); int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts); @@ -228,13 +233,13 @@ BIO *app_http_tls_cb(BIO *hbio, /* APP_HTTP_TLS_INFO */ void *arg, int connect, int detail); # ifndef OPENSSL_NO_SOCK ASN1_VALUE *app_http_get_asn1(const char *url, const char *proxy, - const char *proxy_port, SSL_CTX *ssl_ctx, + const char *no_proxy, SSL_CTX *ssl_ctx, const STACK_OF(CONF_VALUE) *headers, long timeout, const char *expected_content_type, const ASN1_ITEM *it); ASN1_VALUE *app_http_post_asn1(const char *host, const char *port, const char *path, const char *proxy, - const char *proxy_port, SSL_CTX *ctx, + const char *no_proxy, SSL_CTX *ctx, const STACK_OF(CONF_VALUE) *headers, const char *content_type, ASN1_VALUE *req, const ASN1_ITEM *req_it, @@ -281,5 +286,6 @@ extern VERIFY_CB_ARGS verify_args; OSSL_PARAM *app_params_new_from_opts(STACK_OF(OPENSSL_STRING) *opts, const OSSL_PARAM *paramdefs); void app_params_free(OSSL_PARAM *params); +void app_providers_cleanup(void); #endif diff --git a/apps/include/opt.h b/apps/include/opt.h index b4257cca..9f82b6f0 100644 --- a/apps/include/opt.h +++ b/apps/include/opt.h @@ -275,8 +275,8 @@ # define OPT_PROV_OPTIONS \ OPT_SECTION("Provider"), \ - { "provider", OPT_PROV_PROVIDER, 's', "Provder to load (can be specified multiple times)" }, \ - { "provider_path", OPT_PROV_PROVIDER_PATH, 's', "Provider load path" } + { "provider_path", OPT_PROV_PROVIDER_PATH, 's', "Provider load path (must be before 'provider' argument if required)" }, \ + { "provider", OPT_PROV_PROVIDER, 's', "Provider to load (can be specified multiple times)" } # define OPT_PROV_CASES \ OPT_PROV__FIRST: case OPT_PROV__LAST: break; \ diff --git a/apps/lib/app_provider.c b/apps/lib/app_provider.c index ac01e882..ca24328a 100644 --- a/apps/lib/app_provider.c +++ b/apps/lib/app_provider.c @@ -10,12 +10,17 @@ #include "apps.h" #include #include +#include + +DEFINE_STACK_OF(OSSL_PROVIDER) /* * See comments in opt_verify for explanation of this. */ enum prov_range { OPT_PROV_ENUM }; +static STACK_OF(OSSL_PROVIDER) *app_providers = NULL; + static int opt_provider_load(const char *provider) { OSSL_PROVIDER *prov; @@ -26,9 +31,27 @@ static int opt_provider_load(const char *provider) opt_getprog(), provider); return 0; } + if (app_providers == NULL) + app_providers = sk_OSSL_PROVIDER_new_null(); + if (app_providers == NULL + || !sk_OSSL_PROVIDER_push(app_providers, prov)) { + app_providers_cleanup(); + return 0; + } return 1; } +static void provider_free(OSSL_PROVIDER *prov) +{ + OSSL_PROVIDER_unload(prov); +} + +void app_providers_cleanup(void) +{ + sk_OSSL_PROVIDER_pop_free(app_providers, provider_free); + app_providers = NULL; +} + static int opt_provider_path(const char *path) { if (path != NULL && *path == '\0') diff --git a/apps/lib/app_x509.c b/apps/lib/app_x509.c new file mode 100644 index 00000000..89c5960f --- /dev/null +++ b/apps/lib/app_x509.c @@ -0,0 +1,134 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "apps.h" + +/* + * X509_ctrl_str() is sorely lacking in libcrypto, but is still needed to + * allow the application to process verification options in a manner similar + * to signature or other options that pass through EVP_PKEY_CTX_ctrl_str(), + * for uniformity. + * + * As soon as more stuff is added, the code will need serious rework. For + * the moment, it only handles the FIPS 196 / SM2 distinguishing ID. + */ +#ifdef EVP_PKEY_CTRL_SET1_ID +static ASN1_OCTET_STRING *mk_octet_string(void *value, size_t value_n) +{ + ASN1_OCTET_STRING *v = ASN1_OCTET_STRING_new(); + + if (v == NULL) { + BIO_printf(bio_err, "error: allocation failed\n"); + } else if (!ASN1_OCTET_STRING_set(v, value, value_n)) { + ASN1_OCTET_STRING_free(v); + v = NULL; + } + return v; +} +#endif + +static int x509_ctrl(void *object, int cmd, void *value, size_t value_n) +{ + switch (cmd) { +#ifdef EVP_PKEY_CTRL_SET1_ID + case EVP_PKEY_CTRL_SET1_ID: + { + ASN1_OCTET_STRING *v = mk_octet_string(value, value_n); + + if (v == NULL) { + BIO_printf(bio_err, + "error: setting distinguishing ID in certificate failed\n"); + return 0; + } + + X509_set0_distinguishing_id(object, v); + return 1; + } +#endif + default: + break; + } + return -2; /* typical EVP_PKEY return for "unsupported" */ +} + +static int x509_req_ctrl(void *object, int cmd, void *value, size_t value_n) +{ + switch (cmd) { +#ifdef EVP_PKEY_CTRL_SET1_ID + case EVP_PKEY_CTRL_SET1_ID: + { + ASN1_OCTET_STRING *v = mk_octet_string(value, value_n); + + if (v == NULL) { + BIO_printf(bio_err, + "error: setting distinguishing ID in certificate signing request failed\n"); + return 0; + } + + X509_REQ_set0_distinguishing_id(object, v); + return 1; + } +#endif + default: + break; + } + return -2; /* typical EVP_PKEY return for "unsupported" */ +} + +static int do_x509_ctrl_string(int (*ctrl)(void *object, int cmd, + void *value, size_t value_n), + void *object, const char *value) +{ + int rv = 0; + char *stmp, *vtmp = NULL; + size_t vtmp_len = 0; + int cmd = 0; /* Will get command values that make sense somehow */ + + stmp = OPENSSL_strdup(value); + if (stmp == NULL) + return -1; + vtmp = strchr(stmp, ':'); + if (vtmp != NULL) { + *vtmp = 0; + vtmp++; + vtmp_len = strlen(vtmp); + } + + if (strcmp(stmp, "distid") == 0) { +#ifdef EVP_PKEY_CTRL_SET1_ID + cmd = EVP_PKEY_CTRL_SET1_ID; /* ... except we put it in X509 */ +#endif + } else if (strcmp(stmp, "hexdistid") == 0) { + long hexid_len = 0; + void *hexid = OPENSSL_hexstr2buf((const char *)vtmp, &hexid_len); + + OPENSSL_free(stmp); + stmp = vtmp = hexid; + vtmp_len = (size_t)hexid_len; +#ifdef EVP_PKEY_CTRL_SET1_ID + cmd = EVP_PKEY_CTRL_SET1_ID; /* ... except we put it in X509 */ +#endif + } + + rv = ctrl(object, cmd, vtmp, vtmp_len); + + OPENSSL_free(stmp); + return rv; +} + +int x509_ctrl_string(X509 *x, const char *value) +{ + return do_x509_ctrl_string(x509_ctrl, x, value); +} + +int x509_req_ctrl_string(X509_REQ *x, const char *value) +{ + return do_x509_ctrl_string(x509_req_ctrl, x, value); +} diff --git a/apps/lib/apps.c b/apps/lib/apps.c index d407c198..7b400a41 100644 --- a/apps/lib/apps.c +++ b/apps/lib/apps.c @@ -968,7 +968,7 @@ static int set_table_opts(unsigned long *flags, const char *arg, return 0; } -void print_name(BIO *out, const char *title, X509_NAME *nm, +void print_name(BIO *out, const char *title, const X509_NAME *nm, unsigned long lflags) { char *buf; @@ -1900,7 +1900,8 @@ static X509_CRL *load_crl_crldp(STACK_OF(DIST_POINT) *crldp) * anything. */ -static STACK_OF(X509_CRL) *crls_http_cb(X509_STORE_CTX *ctx, X509_NAME *nm) +static STACK_OF(X509_CRL) *crls_http_cb(const X509_STORE_CTX *ctx, + const X509_NAME *nm) { X509 *x; STACK_OF(X509_CRL) *crls = NULL; @@ -1989,7 +1990,7 @@ BIO *app_http_tls_cb(BIO *hbio, void *arg, int connect, int detail) } else if (!connect && !detail) { /* disconnecting after error */ const char *hint = tls_error_hint(); if (hint != NULL) - ERR_add_error_data(1, hint); + ERR_add_error_data(2, " : ", hint); /* * If we pop sbio and BIO_free() it this may lead to libssl double free. * Rely on BIO_free_all() done by OSSL_HTTP_transfer() in http_client.c @@ -1999,7 +2000,7 @@ BIO *app_http_tls_cb(BIO *hbio, void *arg, int connect, int detail) } ASN1_VALUE *app_http_get_asn1(const char *url, const char *proxy, - const char *proxy_port, SSL_CTX *ssl_ctx, + const char *no_proxy, SSL_CTX *ssl_ctx, const STACK_OF(CONF_VALUE) *headers, long timeout, const char *expected_content_type, const ASN1_ITEM *it) @@ -2028,7 +2029,7 @@ ASN1_VALUE *app_http_get_asn1(const char *url, const char *proxy, info.use_proxy = proxy != NULL; info.timeout = timeout; info.ssl_ctx = ssl_ctx; - resp = OSSL_HTTP_get_asn1(url, proxy, proxy_port, + resp = OSSL_HTTP_get_asn1(url, proxy, no_proxy, NULL, NULL, app_http_tls_cb, &info, headers, 0 /* maxline */, 0 /* max_resp_len */, timeout, expected_content_type, it); @@ -2041,7 +2042,7 @@ ASN1_VALUE *app_http_get_asn1(const char *url, const char *proxy, ASN1_VALUE *app_http_post_asn1(const char *host, const char *port, const char *path, const char *proxy, - const char *proxy_port, SSL_CTX *ssl_ctx, + const char *no_proxy, SSL_CTX *ssl_ctx, const STACK_OF(CONF_VALUE) *headers, const char *content_type, ASN1_VALUE *req, const ASN1_ITEM *req_it, @@ -2055,7 +2056,7 @@ ASN1_VALUE *app_http_post_asn1(const char *host, const char *port, info.timeout = timeout; info.ssl_ctx = ssl_ctx; return OSSL_HTTP_post_asn1(host, port, path, ssl_ctx != NULL, - proxy, proxy_port, + proxy, no_proxy, NULL, NULL, app_http_tls_cb, &info, headers, content_type, req, req_it, 0 /* maxline */, diff --git a/apps/lib/build.info b/apps/lib/build.info index a7be58b1..129ffce9 100644 --- a/apps/lib/build.info +++ b/apps/lib/build.info @@ -9,7 +9,7 @@ ENDIF # Source for libapps $LIBAPPSSRC=apps.c apps_ui.c opt.c fmt.c s_cb.c s_socket.c app_rand.c \ - columns.c app_params.c names.c app_provider.c + columns.c app_params.c names.c app_provider.c app_x509.c IF[{- !$disabled{apps} -}] LIBS{noinst}=../libapps.a diff --git a/apps/ocsp.c b/apps/ocsp.c index 3c6b8cbd..3fa10797 100644 --- a/apps/ocsp.c +++ b/apps/ocsp.c @@ -9,32 +9,29 @@ #include -#ifdef OPENSSL_NO_OCSP -NON_EMPTY_TRANSLATION_UNIT -#else -# ifdef OPENSSL_SYS_VMS -# define _XOPEN_SOURCE_EXTENDED/* So fd_set and friends get properly defined - * on OpenVMS */ -# endif +#ifdef OPENSSL_SYS_VMS + /* So fd_set and friends get properly defined on OpenVMS */ +# define _XOPEN_SOURCE_EXTENDED +#endif -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include /* Needs to be included before the openssl headers */ -# include "apps.h" -# include "progs.h" -# include "internal/sockets.h" -# include -# include -# include -# include -# include -# include -# include -# include +#include "apps.h" +#include "progs.h" +#include "internal/sockets.h" +#include +#include +#include +#include +#include +#include +#include +#include #ifndef HAVE_FORK # if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS) @@ -50,24 +47,24 @@ NON_EMPTY_TRANSLATION_UNIT # define NO_FORK #endif -# if !defined(NO_FORK) && !defined(OPENSSL_NO_SOCK) \ +#if !defined(NO_FORK) && !defined(OPENSSL_NO_SOCK) \ && !defined(OPENSSL_NO_POSIX_IO) -# define OCSP_DAEMON -# include -# include -# include -# include -# define MAXERRLEN 1000 /* limit error text sent to syslog to 1000 bytes */ -# else -# undef LOG_INFO -# undef LOG_WARNING -# undef LOG_ERR -# define LOG_INFO 0 -# define LOG_WARNING 1 -# define LOG_ERR 2 -# endif +# define OCSP_DAEMON +# include +# include +# include +# include +# define MAXERRLEN 1000 /* limit error text sent to syslog to 1000 bytes */ +#else +# undef LOG_INFO +# undef LOG_WARNING +# undef LOG_ERR +# define LOG_INFO 0 +# define LOG_WARNING 1 +# define LOG_ERR 2 +#endif -# if defined(OPENSSL_SYS_VXWORKS) +#if defined(OPENSSL_SYS_VXWORKS) /* not supported */ int setpgid(pid_t pid, pid_t pgid) { @@ -80,9 +77,9 @@ pid_t fork(void) errno = ENOSYS; return (pid_t) -1; } -# endif +#endif /* Maximum leeway in validity period: default 5 minutes */ -# define MAX_VALIDITY_PERIOD (5 * 60) +#define MAX_VALIDITY_PERIOD (5 * 60) static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, const EVP_MD *cert_id_md, X509 *issuer, @@ -110,13 +107,13 @@ static void log_message(int level, const char *fmt, ...); static char *prog; static int multi = 0; -# ifdef OCSP_DAEMON +#ifdef OCSP_DAEMON static int acfd = (int) INVALID_SOCKET; static int index_changed(CA_DB *); static void spawn_loop(void); static int print_syslog(const char *str, size_t len, void *levPtr); static void socket_timeout(int signum); -# endif +#endif typedef enum OPTION_choice { OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, @@ -160,9 +157,9 @@ const OPTIONS ocsp_options[] = { "Connection timeout (in seconds) to the OCSP responder"}, {"resp_no_certs", OPT_RESP_NO_CERTS, '-', "Don't include any certificates in response"}, -# ifdef OCSP_DAEMON +#ifdef OCSP_DAEMON {"multi", OPT_MULTI, 'p', "run multiple responder processes"}, -# endif +#endif {"no_certs", OPT_NO_CERTS, '-', "Don't include any certificates in signed request"}, {"badsig", OPT_BADSIG, '-', @@ -538,9 +535,9 @@ int ocsp_main(int argc, char **argv) trailing_md = 1; break; case OPT_MULTI: -# ifdef OCSP_DAEMON +#ifdef OCSP_DAEMON multi = atoi(opt_arg()); -# endif +#endif break; case OPT_PROV_CASES: if (!opt_provider(o)) @@ -628,7 +625,7 @@ int ocsp_main(int argc, char **argv) } } -# ifdef OCSP_DAEMON +#ifdef OCSP_DAEMON if (multi && acbio != NULL) spawn_loop(); if (acbio != NULL && req_timeout > 0) @@ -641,7 +638,7 @@ int ocsp_main(int argc, char **argv) redo_accept: if (acbio != NULL) { -# ifdef OCSP_DAEMON +#ifdef OCSP_DAEMON if (index_changed(rdb)) { CA_DB *newrdb = load_index(ridx_filename, NULL); @@ -654,7 +651,7 @@ redo_accept: ridx_filename); } } -# endif +#endif req = NULL; if (!do_responder(&req, &cbio, acbio, req_timeout)) @@ -724,16 +721,16 @@ redo_accept: if (cbio != NULL) send_ocsp_response(cbio, resp); } else if (host != NULL) { -# ifndef OPENSSL_NO_SOCK +#ifndef OPENSSL_NO_SOCK resp = process_responder(req, host, path, port, use_ssl, headers, req_timeout); if (resp == NULL) goto end; -# else +#else BIO_printf(bio_err, "Error creating connect BIO - sockets not supported.\n"); goto end; -# endif +#endif } else if (respin != NULL) { derbio = bio_open_default(respin, 'r', FORMAT_ASN1); if (derbio == NULL) @@ -877,7 +874,7 @@ log_message(int level, const char *fmt, ...) va_list ap; va_start(ap, fmt); -# ifdef OCSP_DAEMON +#ifdef OCSP_DAEMON if (multi) { char buf[1024]; if (vsnprintf(buf, sizeof(buf), fmt, ap) > 0) { @@ -886,7 +883,7 @@ log_message(int level, const char *fmt, ...) if (level >= LOG_ERR) ERR_print_errors_cb(print_syslog, &level); } -# endif +#endif if (!multi) { BIO_printf(bio_err, "%s: ", prog); BIO_vprintf(bio_err, fmt, ap); @@ -895,7 +892,7 @@ log_message(int level, const char *fmt, ...) va_end(ap); } -# ifdef OCSP_DAEMON +#ifdef OCSP_DAEMON static int print_syslog(const char *str, size_t len, void *levPtr) { @@ -1048,7 +1045,7 @@ static void spawn_loop(void) syslog(LOG_INFO, "terminating on signal: %d", termsig); killall(0, kidpids); } -# endif +#endif static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, const EVP_MD *cert_id_md, X509 *issuer, @@ -1081,7 +1078,7 @@ static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, STACK_OF(OCSP_CERTID) *ids) { OCSP_CERTID *id; - X509_NAME *iname; + const X509_NAME *iname; ASN1_BIT_STRING *ikey; ASN1_INTEGER *sno; @@ -1338,11 +1335,11 @@ static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser) static BIO *init_responder(const char *port) { -# ifdef OPENSSL_NO_SOCK +#ifdef OPENSSL_NO_SOCK BIO_printf(bio_err, "Error setting up accept BIO - sockets not supported.\n"); return NULL; -# else +#else BIO *acbio = NULL, *bufbio = NULL; bufbio = BIO_new(BIO_f_buffer()); @@ -1369,10 +1366,10 @@ static BIO *init_responder(const char *port) BIO_free_all(acbio); BIO_free(bufbio); return NULL; -# endif +#endif } -# ifndef OPENSSL_NO_SOCK +#ifndef OPENSSL_NO_SOCK /* * Decode %xx URL-decoding in-place. Ignores mal-formed sequences. */ @@ -1396,22 +1393,22 @@ static int urldecode(char *p) *out = '\0'; return (int)(out - save); } -# endif +#endif -# ifdef OCSP_DAEMON +#ifdef OCSP_DAEMON static void socket_timeout(int signum) { if (acfd != (int)INVALID_SOCKET) (void)shutdown(acfd, SHUT_RD); } -# endif +#endif static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, int timeout) { -# ifdef OPENSSL_NO_SOCK +#ifdef OPENSSL_NO_SOCK return 0; -# else +#else int len; OCSP_REQUEST *req = NULL; char inbuf[2048], reqbuf[2048]; @@ -1429,12 +1426,12 @@ static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, *pcbio = cbio; client = BIO_get_peer_name(cbio); -# ifdef OCSP_DAEMON +# ifdef OCSP_DAEMON if (timeout > 0) { (void) BIO_get_fd(cbio, &acfd); alarm(timeout); } -# endif +# endif /* Read the request line. */ len = BIO_gets(cbio, reqbuf, sizeof(reqbuf)); @@ -1497,11 +1494,11 @@ static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, break; } -# ifdef OCSP_DAEMON +# ifdef OCSP_DAEMON /* Clear alarm before we close the client socket */ alarm(0); timeout = 0; -# endif +# endif /* Try to read OCSP request */ if (getbio != NULL) { @@ -1517,13 +1514,13 @@ static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, *preq = req; out: -# ifdef OCSP_DAEMON +# ifdef OCSP_DAEMON if (timeout > 0) alarm(0); acfd = (int)INVALID_SOCKET; -# endif - return 1; # endif + return 1; +#endif } static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp) @@ -1539,7 +1536,7 @@ static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp) return 1; } -# ifndef OPENSSL_NO_SOCK +#ifndef OPENSSL_NO_SOCK OCSP_RESPONSE *process_responder(OCSP_REQUEST *req, const char *host, const char *path, const char *port, int use_ssl, @@ -1571,6 +1568,4 @@ OCSP_RESPONSE *process_responder(OCSP_REQUEST *req, SSL_CTX_free(ctx); return resp; } -# endif - #endif diff --git a/apps/openssl.c b/apps/openssl.c index cafe4046..558f662e 100644 --- a/apps/openssl.c +++ b/apps/openssl.c @@ -368,6 +368,7 @@ int main(int argc, char *argv[]) } ret = 1; end: + app_providers_cleanup(); OPENSSL_free(default_config_file); lh_FUNCTION_free(prog); OPENSSL_free(arg.argv); diff --git a/apps/pkcs12.c b/apps/pkcs12.c index c2448a74..f5ad9498 100644 --- a/apps/pkcs12.c +++ b/apps/pkcs12.c @@ -8,25 +8,22 @@ */ #include -#if defined(OPENSSL_NO_DES) -NON_EMPTY_TRANSLATION_UNIT -#else -# include -# include -# include -# include "apps.h" -# include "progs.h" -# include -# include -# include -# include +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include -# define NOKEYS 0x1 -# define NOCERTS 0x2 -# define INFO 0x4 -# define CLCERTS 0x8 -# define CACERTS 0x10 +#define NOKEYS 0x1 +#define NOCERTS 0x2 +#define INFO 0x4 +#define CLCERTS 0x8 +#define CACERTS 0x10 #define PASSWD_BUF_SIZE 2048 @@ -64,9 +61,9 @@ typedef enum OPTION_choice { const OPTIONS pkcs12_options[] = { OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, -# ifndef OPENSSL_NO_ENGINE +#ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -# endif +#endif OPT_SECTION("CA"), {"CApath", OPT_CAPATH, '/', "PEM-format directory of CA's"}, @@ -112,15 +109,15 @@ const OPTIONS pkcs12_options[] = { {"keysig", OPT_KEYSIG, '-', "Set MS key signature type"}, OPT_SECTION("Encryption"), -# ifndef OPENSSL_NO_RC2 +#ifndef OPENSSL_NO_RC2 {"descert", OPT_DESCERT, '-', "Encrypt output with 3DES (default RC2-40)"}, {"certpbe", OPT_CERTPBE, 's', "Certificate PBE algorithm (default RC2-40)"}, -# else +#else {"descert", OPT_DESCERT, '-', "Encrypt output with 3DES (the default)"}, {"certpbe", OPT_CERTPBE, 's', "Certificate PBE algorithm (default 3DES)"}, -# endif +#endif {"iter", OPT_ITER, 'p', "Specify the iteration count for encryption key and MAC"}, {"noiter", OPT_NOITER, '-', "Don't use encryption key iteration"}, {"maciter", OPT_MACITER, '-', "Unused, kept for backwards compatibility"}, @@ -141,11 +138,11 @@ int pkcs12_main(int argc, char **argv) char pass[PASSWD_BUF_SIZE] = "", macpass[PASSWD_BUF_SIZE] = ""; int export_cert = 0, options = 0, chain = 0, twopass = 0, keytype = 0; int iter = PKCS12_DEFAULT_ITER, maciter = PKCS12_DEFAULT_ITER; -# ifndef OPENSSL_NO_RC2 +#ifndef OPENSSL_NO_RC2 int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC; -# else +#else int cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; -# endif +#endif int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; int ret = 1, macver = 1, add_lmk = 0, private = 0; int noprompt = 0; @@ -1008,5 +1005,3 @@ static int set_pbe(int *ppbe, const char *str) } return 1; } - -#endif diff --git a/apps/pkeyutl.c b/apps/pkeyutl.c index 7f11b168..7dc558b1 100644 --- a/apps/pkeyutl.c +++ b/apps/pkeyutl.c @@ -550,22 +550,6 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, if (pkey == NULL) goto end; -#ifndef OPENSSL_NO_EC - /* SM2 needs a special treatment */ - if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) { - EC_KEY *eckey = NULL; - const EC_GROUP *group = NULL; - int nid; - - if ((eckey = EVP_PKEY_get0_EC_KEY(pkey)) == NULL - || (group = EC_KEY_get0_group(eckey)) == NULL - || (nid = EC_GROUP_get_curve_name(group)) == 0) - goto end; - if (nid == NID_sm2 - && !EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) - goto end; - } -#endif *pkeysize = EVP_PKEY_size(pkey); ctx = EVP_PKEY_CTX_new(pkey, impl); if (ppkey != NULL) diff --git a/apps/rehash.c b/apps/rehash.c index de540642..e21b1b84 100644 --- a/apps/rehash.c +++ b/apps/rehash.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2013-2014 Timo Teräs * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -233,7 +233,7 @@ static int do_file(const char *filename, const char *fullpath, enum Hash h) { STACK_OF (X509_INFO) *inf = NULL; X509_INFO *x; - X509_NAME *name = NULL; + const X509_NAME *name = NULL; BIO *b; const char *ext; unsigned char digest[EVP_MAX_MD_SIZE]; @@ -274,11 +274,19 @@ static int do_file(const char *filename, const char *fullpath, enum Hash h) if (x->x509 != NULL) { type = TYPE_CERT; name = X509_get_subject_name(x->x509); - X509_digest(x->x509, evpmd, digest, NULL); + if (!X509_digest(x->x509, evpmd, digest, NULL)) { + BIO_printf(bio_err, "out of memory\n"); + ++errs; + goto end; + } } else if (x->crl != NULL) { type = TYPE_CRL; name = X509_CRL_get_issuer(x->crl); - X509_CRL_digest(x->crl, evpmd, digest, NULL); + if (!X509_CRL_digest(x->crl, evpmd, digest, NULL)) { + BIO_printf(bio_err, "out of memory\n"); + ++errs; + goto end; + } } else { ++errs; goto end; diff --git a/apps/req.c b/apps/req.c index 51860172..4d65fc28 100644 --- a/apps/req.c +++ b/apps/req.c @@ -87,11 +87,11 @@ typedef enum OPTION_choice { OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_KEYGEN_ENGINE, OPT_KEY, OPT_PUBKEY, OPT_NEW, OPT_CONFIG, OPT_KEYFORM, OPT_IN, OPT_OUT, OPT_KEYOUT, OPT_PASSIN, OPT_PASSOUT, OPT_NEWKEY, - OPT_PKEYOPT, OPT_SIGOPT, OPT_BATCH, OPT_NEWHDR, OPT_MODULUS, + OPT_PKEYOPT, OPT_SIGOPT, OPT_VFYOPT, OPT_BATCH, OPT_NEWHDR, OPT_MODULUS, OPT_VERIFY, OPT_NODES, OPT_NOOUT, OPT_VERBOSE, OPT_UTF8, OPT_NAMEOPT, OPT_REQOPT, OPT_SUBJ, OPT_SUBJECT, OPT_TEXT, OPT_X509, OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL, OPT_ADDEXT, OPT_EXTENSIONS, - OPT_REQEXTS, OPT_PRECERT, OPT_MD, OPT_SM2ID, OPT_SM2HEXID, + OPT_REQEXTS, OPT_PRECERT, OPT_MD, OPT_SECTION, OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; @@ -143,13 +143,8 @@ const OPTIONS req_options[] = { {"newkey", OPT_NEWKEY, 's', "Specify as type:bits"}, {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"}, {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, + {"vfyopt", OPT_VFYOPT, 's', "Verification parameter in n:v form"}, {"", OPT_MD, '-', "Any supported digest"}, -#ifndef OPENSSL_NO_SM2 - {"sm2-id", OPT_SM2ID, 's', - "Specify an ID string to verify an SM2 certificate request"}, - {"sm2-hex-id", OPT_SM2HEXID, 's', - "Specify a hex ID string to verify an SM2 certificate request"}, -#endif OPT_SECTION("Output"), {"out", OPT_OUT, '>', "Output file"}, @@ -237,7 +232,7 @@ int req_main(int argc, char **argv) ENGINE *e = NULL, *gen_eng = NULL; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *genctx = NULL; - STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL; + STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL, *vfyopts = NULL; LHASH_OF(OPENSSL_STRING) *addexts = NULL; X509 *x509ss = NULL; X509_REQ *req = NULL; @@ -260,9 +255,6 @@ int req_main(int argc, char **argv) int nodes = 0, newhdr = 0, subject = 0, pubkey = 0, precert = 0; long newkey = -1; unsigned long chtype = MBSTRING_ASC, reqflag = 0; - unsigned char *sm2_id = NULL; - size_t sm2_idlen = 0; - int sm2_free = 0; #ifndef OPENSSL_NO_DES cipher = EVP_des_ede3_cbc(); @@ -359,6 +351,12 @@ int req_main(int argc, char **argv) if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) goto opthelp; break; + case OPT_VFYOPT: + if (!vfyopts) + vfyopts = sk_OPENSSL_STRING_new_null(); + if (!vfyopts || !sk_OPENSSL_STRING_push(vfyopts, opt_arg())) + goto opthelp; + break; case OPT_BATCH: batch = 1; break; @@ -446,29 +444,6 @@ int req_main(int argc, char **argv) goto opthelp; digest = md_alg; break; - case OPT_SM2ID: - if (sm2_id != NULL) { - BIO_printf(bio_err, - "Use one of the options 'sm2-hex-id' or 'sm2-id'\n"); - goto end; - } - sm2_id = (unsigned char *)opt_arg(); - sm2_idlen = strlen((const char *)sm2_id); - break; - case OPT_SM2HEXID: - if (sm2_id != NULL) { - BIO_printf(bio_err, - "Use one of the options 'sm2-hex-id' or 'sm2-id'\n"); - goto end; - } - /* try to parse the input as hex string first */ - sm2_free = 1; - sm2_id = OPENSSL_hexstr2buf(opt_arg(), (long *)&sm2_idlen); - if (sm2_id == NULL) { - BIO_printf(bio_err, "Invalid hex string input\n"); - goto end; - } - break; } } argc = opt_num_rest(); @@ -901,27 +876,7 @@ int req_main(int argc, char **argv) goto end; } - if (sm2_id != NULL) { -#ifndef OPENSSL_NO_SM2 - ASN1_OCTET_STRING *v; - - v = ASN1_OCTET_STRING_new(); - if (v == NULL) { - BIO_printf(bio_err, "error: SM2 ID allocation failed\n"); - goto end; - } - - if (!ASN1_OCTET_STRING_set(v, sm2_id, sm2_idlen)) { - BIO_printf(bio_err, "error: setting SM2 ID failed\n"); - ASN1_OCTET_STRING_free(v); - goto end; - } - - X509_REQ_set0_sm2_id(req, v); -#endif - } - - i = X509_REQ_verify(req, tpubkey); + i = do_X509_REQ_verify(req, tpubkey, vfyopts); if (i < 0) { goto end; @@ -1029,8 +984,6 @@ int req_main(int argc, char **argv) } ret = 0; end: - if (sm2_free) - OPENSSL_free(sm2_id); if (ret) { ERR_print_errors(bio_err); } @@ -1043,6 +996,7 @@ int req_main(int argc, char **argv) EVP_PKEY_CTX_free(genctx); sk_OPENSSL_STRING_free(pkeyopts); sk_OPENSSL_STRING_free(sigopts); + sk_OPENSSL_STRING_free(vfyopts); lh_OPENSSL_STRING_doall(addexts, exts_cleanup); lh_OPENSSL_STRING_free(addexts); #ifndef OPENSSL_NO_ENGINE @@ -1153,8 +1107,7 @@ static int prompt_info(X509_REQ *req, char *type, *value; const char *def; CONF_VALUE *v; - X509_NAME *subj; - subj = X509_REQ_get_subject_name(req); + X509_NAME *subj = X509_REQ_get_subject_name(req); if (!batch) { BIO_printf(bio_err, @@ -1239,8 +1192,7 @@ static int prompt_info(X509_REQ *req, return 0; } if (X509_NAME_entry_count(subj) == 0) { - BIO_printf(bio_err, - "error, no objects specified in config file\n"); + BIO_printf(bio_err, "error, no objects specified in config file\n"); return 0; } @@ -1685,32 +1637,71 @@ static int genpkey_cb(EVP_PKEY_CTX *ctx) return 1; } +static int do_pkey_ctx_init(EVP_PKEY_CTX *pkctx, STACK_OF(OPENSSL_STRING) *opts) +{ + int i; + + if (opts == NULL) + return 1; + + for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) { + char *opt = sk_OPENSSL_STRING_value(opts, i); + if (pkey_ctrl_string(pkctx, opt) <= 0) { + BIO_printf(bio_err, "parameter error \"%s\"\n", opt); + ERR_print_errors(bio_err); + return 0; + } + } + + return 1; +} + +static int do_x509_init(X509 *x, STACK_OF(OPENSSL_STRING) *opts) +{ + int i; + + if (opts == NULL) + return 1; + + for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) { + char *opt = sk_OPENSSL_STRING_value(opts, i); + if (x509_ctrl_string(x, opt) <= 0) { + BIO_printf(bio_err, "parameter error \"%s\"\n", opt); + ERR_print_errors(bio_err); + return 0; + } + } + + return 1; +} + +static int do_x509_req_init(X509_REQ *x, STACK_OF(OPENSSL_STRING) *opts) +{ + int i; + + if (opts == NULL) + return 1; + + for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) { + char *opt = sk_OPENSSL_STRING_value(opts, i); + if (x509_req_ctrl_string(x, opt) <= 0) { + BIO_printf(bio_err, "parameter error \"%s\"\n", opt); + ERR_print_errors(bio_err); + return 0; + } + } + + return 1; +} + static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey, const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts) { EVP_PKEY_CTX *pkctx = NULL; - EVP_PKEY_CTX *pctx = NULL; - int i, def_nid, ret = 0; + int def_nid; if (ctx == NULL) - goto err; - if (EVP_PKEY_id(pkey) == EVP_PKEY_SM2) { - pctx = EVP_PKEY_CTX_new(pkey, NULL); - if (pctx == NULL) { - BIO_printf(bio_err, "memory allocation failure.\n"); - goto err; - } - /* set SM2 ID from sig options before calling the real init routine */ - for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) { - char *sigopt = sk_OPENSSL_STRING_value(sigopts, i); - if (pkey_ctrl_string(pctx, sigopt) <= 0) { - BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt); - ERR_print_errors(bio_err); - goto err; - } - } - EVP_MD_CTX_set_pkey_ctx(ctx, pctx); - } + return 0; /* * EVP_PKEY_get_default_digest_nid() returns 2 if the digest is mandatory * for this algorithm. @@ -1720,36 +1711,8 @@ static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey, /* The signing algorithm requires there to be no digest */ md = NULL; } - if (!EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey)) - goto err; - for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) { - char *sigopt = sk_OPENSSL_STRING_value(sigopts, i); - if (pkey_ctrl_string(pkctx, sigopt) <= 0) { - BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt); - ERR_print_errors(bio_err); - goto err; - } - } - - ret = 1; - err: - if (!ret) - EVP_PKEY_CTX_free(pctx); - return ret; -} - -static void do_sign_cleanup(EVP_MD_CTX *ctx, EVP_PKEY *pkey) -{ - /* - * With SM2, do_sign_init() attached an EVP_PKEY_CTX to the EVP_MD_CTX, - * and we have to free it explicitly. - */ - if (EVP_PKEY_id(pkey) == EVP_PKEY_SM2) { - EVP_PKEY_CTX *pctx = EVP_MD_CTX_pkey_ctx(ctx); - - EVP_MD_CTX_set_pkey_ctx(ctx, NULL); - EVP_PKEY_CTX_free(pctx); - } + return EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey) + && do_pkey_ctx_init(pkctx, sigopts); } int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md, @@ -1758,10 +1721,8 @@ int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md, int rv = 0; EVP_MD_CTX *mctx = EVP_MD_CTX_new(); - if (do_sign_init(mctx, pkey, md, sigopts) > 0) { + if (do_sign_init(mctx, pkey, md, sigopts) > 0) rv = (X509_sign_ctx(x, mctx) > 0); - do_sign_cleanup(mctx, pkey); - } EVP_MD_CTX_free(mctx); return rv; } @@ -1772,24 +1733,39 @@ int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md, int rv = 0; EVP_MD_CTX *mctx = EVP_MD_CTX_new(); - if (do_sign_init(mctx, pkey, md, sigopts) > 0) { + if (do_sign_init(mctx, pkey, md, sigopts) > 0) rv = (X509_REQ_sign_ctx(x, mctx) > 0); - do_sign_cleanup(mctx, pkey); - } EVP_MD_CTX_free(mctx); return rv; } +int do_X509_verify(X509 *x, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *vfyopts) +{ + int rv = 0; + + if (do_x509_init(x, vfyopts) > 0) + rv = (X509_verify(x, pkey) > 0); + return rv; +} + +int do_X509_REQ_verify(X509_REQ *x, EVP_PKEY *pkey, + STACK_OF(OPENSSL_STRING) *vfyopts) +{ + int rv = 0; + + if (do_x509_req_init(x, vfyopts) > 0) + rv = (X509_REQ_verify(x, pkey) > 0); + return rv; +} + int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts) { int rv = 0; EVP_MD_CTX *mctx = EVP_MD_CTX_new(); - if (do_sign_init(mctx, pkey, md, sigopts) > 0) { + if (do_sign_init(mctx, pkey, md, sigopts) > 0) rv = (X509_CRL_sign_ctx(x, mctx) > 0); - do_sign_cleanup(mctx, pkey); - } EVP_MD_CTX_free(mctx); return rv; } diff --git a/apps/rsa.c b/apps/rsa.c index 539b0144..81ed2ab7 100644 --- a/apps/rsa.c +++ b/apps/rsa.c @@ -8,23 +8,20 @@ */ #include -#ifdef OPENSSL_NO_RSA -NON_EMPTY_TRANSLATION_UNIT -#else -# include -# include -# include -# include -# include "apps.h" -# include "progs.h" -# include -# include -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include +#include +#include typedef enum OPTION_choice { OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, @@ -42,9 +39,9 @@ const OPTIONS rsa_options[] = { {"help", OPT_HELP, '-', "Display this summary"}, {"check", OPT_CHECK, '-', "Verify key consistency"}, {"", OPT_CIPHER, '-', "Any supported cipher"}, -# ifndef OPENSSL_NO_ENGINE +#ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -# endif +#endif OPT_SECTION("Input"), {"in", OPT_IN, 's', "Input file"}, @@ -63,14 +60,14 @@ const OPTIONS rsa_options[] = { {"text", OPT_TEXT, '-', "Print the key in text"}, {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"}, -# if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4) +#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4) OPT_SECTION("PVK"), {"pvk-strong", OPT_PVK_STRONG, '-', "Enable 'Strong' PVK encoding level (default)"}, {"pvk-weak", OPT_PVK_WEAK, '-', "Enable 'Weak' PVK encoding level"}, {"pvk-none", OPT_PVK_NONE, '-', "Don't enforce PVK encoding"}, -# endif OPT_PROV_OPTIONS, +#endif {NULL} }; @@ -85,9 +82,9 @@ int rsa_main(int argc, char **argv) int i, private = 0; int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, check = 0; int noout = 0, modulus = 0, pubin = 0, pubout = 0, ret = 1; -# if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4) +#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4) int pvk_encr = 2; -# endif +#endif OPTION_CHOICE o; prog = opt_init(argc, argv, rsa_options); @@ -140,9 +137,9 @@ int rsa_main(int argc, char **argv) case OPT_PVK_STRONG: /* pvk_encr:= 2 */ case OPT_PVK_WEAK: /* pvk_encr:= 1 */ case OPT_PVK_NONE: /* pvk_encr:= 0 */ -# if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4) +#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4) pvk_encr = (o - OPT_PVK_NONE); -# endif +#endif break; case OPT_NOOUT: noout = 1; @@ -278,7 +275,7 @@ int rsa_main(int argc, char **argv) i = PEM_write_bio_RSAPrivateKey(out, rsa, enc, NULL, 0, NULL, passout); } -# ifndef OPENSSL_NO_DSA +#ifndef OPENSSL_NO_DSA } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) { EVP_PKEY *pk; pk = EVP_PKEY_new(); @@ -293,13 +290,13 @@ int rsa_main(int argc, char **argv) goto end; } assert(private); -# ifdef OPENSSL_NO_RC4 +# ifdef OPENSSL_NO_RC4 BIO_printf(bio_err, "PVK format not supported\n"); EVP_PKEY_free(pk); goto end; -# else +# else i = i2b_PVK_bio(out, pk, pvk_encr, 0, passout); -# endif +# endif } else if (pubin || pubout) { i = i2b_PublicKey_bio(out, pk); } else { @@ -307,7 +304,7 @@ int rsa_main(int argc, char **argv) i = i2b_PrivateKey_bio(out, pk); } EVP_PKEY_free(pk); -# endif +#endif } else { BIO_printf(bio_err, "bad output format specified for outfile\n"); goto end; @@ -326,4 +323,3 @@ int rsa_main(int argc, char **argv) OPENSSL_free(passout); return ret; } -#endif diff --git a/apps/rsautl.c b/apps/rsautl.c index ddd507ce..ec34ccc9 100644 --- a/apps/rsautl.c +++ b/apps/rsautl.c @@ -8,25 +8,22 @@ */ #include -#ifdef OPENSSL_NO_RSA -NON_EMPTY_TRANSLATION_UNIT -#else -# include "apps.h" -# include "progs.h" -# include -# include -# include -# include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include -# define RSA_SIGN 1 -# define RSA_VERIFY 2 -# define RSA_ENCRYPT 3 -# define RSA_DECRYPT 4 +#define RSA_SIGN 1 +#define RSA_VERIFY 2 +#define RSA_ENCRYPT 3 +#define RSA_DECRYPT 4 -# define KEY_PRIVKEY 1 -# define KEY_PUBKEY 2 -# define KEY_CERT 3 +#define KEY_PRIVKEY 1 +#define KEY_PUBKEY 2 +#define KEY_CERT 3 typedef enum OPTION_choice { OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, @@ -44,9 +41,9 @@ const OPTIONS rsautl_options[] = { {"verify", OPT_VERIFY, '-', "Verify with public key"}, {"encrypt", OPT_ENCRYPT, '-', "Encrypt with public key"}, {"decrypt", OPT_DECRYPT, '-', "Decrypt with private key"}, -# ifndef OPENSSL_NO_ENGINE +#ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -# endif +#endif OPT_SECTION("Input"), {"in", OPT_IN, '<', "Input file"}, @@ -290,4 +287,3 @@ int rsautl_main(int argc, char **argv) OPENSSL_free(passin); return ret; } -#endif diff --git a/apps/s_server.c b/apps/s_server.c index 4016270d..d2864bc6 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -103,6 +103,8 @@ static int keymatexportlen = 20; static int async = 0; +static int use_sendfile = 0; + static const char *session_id_prefix = NULL; #ifndef OPENSSL_NO_DTLS @@ -707,7 +709,7 @@ static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen, if (SSL_select_next_proto ((unsigned char **)out, outlen, alpn_ctx->data, alpn_ctx->len, in, inlen) != OPENSSL_NPN_NEGOTIATED) { - return SSL_TLSEXT_ERR_NOACK; + return SSL_TLSEXT_ERR_ALERT_FATAL; } if (!s_quiet) { @@ -749,7 +751,7 @@ typedef enum OPTION_choice { OPT_SSL3, OPT_TLS1_3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1, OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_LISTEN, OPT_STATELESS, OPT_ID_PREFIX, OPT_SERVERNAME, OPT_SERVERNAME_FATAL, - OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN, + OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN, OPT_SENDFILE, OPT_SRTP_PROFILES, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN, OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_RECV_MAX_EARLY, OPT_EARLY_DATA, OPT_S_NUM_TICKETS, OPT_ANTI_REPLAY, OPT_NO_ANTI_REPLAY, OPT_SCTP_LABEL_BUG, @@ -981,6 +983,9 @@ const OPTIONS s_server_options[] = { #endif {"alpn", OPT_ALPN, 's', "Set the advertised protocols for the ALPN extension (comma-separated list)"}, +#ifndef OPENSSL_NO_KTLS + {"sendfile", OPT_SENDFILE, '-', "Use sendfile to response file with -WWW"}, +#endif OPT_R_OPTIONS, OPT_S_OPTIONS, @@ -1095,6 +1100,7 @@ int s_server_main(int argc, char *argv[]) s_quiet = 0; s_brief = 0; async = 0; + use_sendfile = 0; cctx = SSL_CONF_CTX_new(); vpm = X509_VERIFY_PARAM_new(); @@ -1643,6 +1649,11 @@ int s_server_main(int argc, char *argv[]) case OPT_HTTP_SERVER_BINMODE: http_server_binmode = 1; break; + case OPT_SENDFILE: +#ifndef OPENSSL_NO_KTLS + use_sendfile = 1; +#endif + break; } } argc = opt_num_rest(); @@ -1695,6 +1706,13 @@ int s_server_main(int argc, char *argv[]) } #endif +#ifndef OPENSSL_NO_KTLS + if (use_sendfile && www <= 1) { + BIO_printf(bio_err, "Can't use -sendfile without -WWW or -HTTP\n"); + goto end; + } +#endif + if (!app_passwd(passarg, dpassarg, &pass, &dpass)) { BIO_printf(bio_err, "Error getting password\n"); goto end; @@ -1958,7 +1976,7 @@ int s_server_main(int argc, char *argv[]) BIO_printf(bio_s_out, "Setting secondary ctx parameters\n"); if (sdebug) - ssl_ctx_security_debug(ctx, sdebug); + ssl_ctx_security_debug(ctx2, sdebug); if (session_id_prefix) { if (strlen(session_id_prefix) >= 32) @@ -2093,10 +2111,16 @@ int s_server_main(int argc, char *argv[]) SSL_CTX_set_psk_server_callback(ctx, psk_server_cb); } - if (!SSL_CTX_use_psk_identity_hint(ctx, psk_identity_hint)) { - BIO_printf(bio_err, "error setting PSK identity hint to context\n"); - ERR_print_errors(bio_err); - goto end; + if (psk_identity_hint != NULL) { + if (min_version == TLS1_3_VERSION) { + BIO_printf(bio_s_out, "PSK warning: there is NO identity hint in TLSv1.3\n"); + } else { + if (!SSL_CTX_use_psk_identity_hint(ctx, psk_identity_hint)) { + BIO_printf(bio_err, "error setting PSK identity hint to context\n"); + ERR_print_errors(bio_err); + goto end; + } + } } #endif if (psksessf != NULL) { @@ -3330,38 +3354,79 @@ static int www_body(int s, int stype, int prot, unsigned char *context) "HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n"); } /* send the file */ - for (;;) { - i = BIO_read(file, buf, bufsize); - if (i <= 0) - break; +#ifndef OPENSSL_NO_KTLS + if (use_sendfile) { + FILE *fp = NULL; + int fd; + struct stat st; + off_t offset = 0; + size_t filesize; -#ifdef RENEG - total_bytes += i; - BIO_printf(bio_err, "%d\n", i); - if (total_bytes > 3 * 1024) { - total_bytes = 0; - BIO_printf(bio_err, "RENEGOTIATE\n"); - SSL_renegotiate(con); + BIO_get_fp(file, &fp); + fd = fileno(fp); + if (fstat(fd, &st) < 0) { + BIO_printf(io, "Error fstat '%s'\r\n", p); + ERR_print_errors(io); + goto write_error; } -#endif - for (j = 0; j < i;) { + filesize = st.st_size; + if (((int)BIO_flush(io)) < 0) + goto write_error; + + for (;;) { + i = SSL_sendfile(con, fd, offset, filesize, 0); + if (i < 0) { + BIO_printf(io, "Error SSL_sendfile '%s'\r\n", p); + ERR_print_errors(io); + break; + } else { + offset += i; + filesize -= i; + } + + if (filesize <= 0) { + if (!s_quiet) + BIO_printf(bio_err, "KTLS SENDFILE '%s' OK\n", p); + + break; + } + } + } else +#endif + { + for (;;) { + i = BIO_read(file, buf, bufsize); + if (i <= 0) + break; + #ifdef RENEG - static count = 0; - if (++count == 13) { + total_bytes += i; + BIO_printf(bio_err, "%d\n", i); + if (total_bytes > 3 * 1024) { + total_bytes = 0; + BIO_printf(bio_err, "RENEGOTIATE\n"); SSL_renegotiate(con); } #endif - k = BIO_write(io, &(buf[j]), i - j); - if (k <= 0) { - if (!BIO_should_retry(io) - && !SSL_waiting_for_async(con)) - goto write_error; - else { - BIO_printf(bio_s_out, "rwrite W BLOCK\n"); + + for (j = 0; j < i;) { +#ifdef RENEG + static count = 0; + if (++count == 13) + SSL_renegotiate(con); +#endif + k = BIO_write(io, &(buf[j]), i - j); + if (k <= 0) { + if (!BIO_should_retry(io) + && !SSL_waiting_for_async(con)) { + goto write_error; + } else { + BIO_printf(bio_s_out, "rwrite W BLOCK\n"); + } + } else { + j += k; } - } else { - j += k; } } } diff --git a/apps/spkac.c b/apps/spkac.c index dbd3d452..17c4e5b8 100644 --- a/apps/spkac.c +++ b/apps/spkac.c @@ -145,8 +145,15 @@ int spkac_main(int argc, char **argv) if (challenge != NULL) ASN1_STRING_set(spki->spkac->challenge, challenge, (int)strlen(challenge)); - NETSCAPE_SPKI_set_pubkey(spki, pkey); - NETSCAPE_SPKI_sign(spki, pkey, EVP_md5()); + if (!NETSCAPE_SPKI_set_pubkey(spki, pkey)) { + BIO_printf(bio_err, "Error setting public key\n"); + goto end; + } + i = NETSCAPE_SPKI_sign(spki, pkey, EVP_md5()); + if (i <= 0) { + BIO_printf(bio_err, "Error signing SPKAC\n"); + goto end; + } spkstr = NETSCAPE_SPKI_b64_encode(spki); if (spkstr == NULL) goto end; diff --git a/apps/srp.c b/apps/srp.c index 646e86f1..8fb325fe 100644 --- a/apps/srp.c +++ b/apps/srp.c @@ -12,28 +12,25 @@ */ #include -#ifdef OPENSSL_NO_SRP -NON_EMPTY_TRANSLATION_UNIT -#else -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include "apps.h" -# include "progs.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "apps.h" +#include "progs.h" -# define BASE_SECTION "srp" -# define CONFIG_FILE "openssl.cnf" +#define BASE_SECTION "srp" +#define CONFIG_FILE "openssl.cnf" -# define ENV_DATABASE "srpvfile" -# define ENV_DEFAULT_SRP "default_srp" +#define ENV_DATABASE "srpvfile" +#define ENV_DEFAULT_SRP "default_srp" static int get_index(CA_DB *db, char *id, char type) { @@ -204,9 +201,9 @@ const OPTIONS srp_options[] = { {"verbose", OPT_VERBOSE, '-', "Talk a lot while doing things"}, {"config", OPT_CONFIG, '<', "A config file"}, {"name", OPT_NAME, 's', "The particular srp definition to use"}, -# ifndef OPENSSL_NO_ENGINE +#ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -# endif +#endif OPT_SECTION("Action"), {"add", OPT_ADD, '-', "Add a user and srp verifier"}, @@ -625,4 +622,3 @@ int srp_main(int argc, char **argv) release_engine(e); return ret; } -#endif diff --git a/apps/ts.c b/apps/ts.c index 3d380beb..2f21433a 100644 --- a/apps/ts.c +++ b/apps/ts.c @@ -8,29 +8,26 @@ */ #include -#ifdef OPENSSL_NO_TS -NON_EMPTY_TRANSLATION_UNIT -#else -# include -# include -# include -# include "apps.h" -# include "progs.h" -# include -# include -# include -# include -# include -# include +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include +#include /* Request nonce length, in bits (must be a multiple of 8). */ -# define NONCE_LENGTH 64 +#define NONCE_LENGTH 64 /* Name of config entry that defines the OID file. */ -# define ENV_OID_FILE "oid_file" +#define ENV_OID_FILE "oid_file" /* Is |EXACTLY_ONE| of three pointers set? */ -# define EXACTLY_ONE(a, b, c) \ +#define EXACTLY_ONE(a, b, c) \ (( a && !b && !c) || \ ( b && !a && !c) || \ ( c && !a && !b)) @@ -94,9 +91,9 @@ const OPTIONS ts_options[] = { {"help", OPT_HELP, '-', "Display this summary"}, {"config", OPT_CONFIG, '<', "Configuration file"}, {"section", OPT_SECTION, 's', "Section to use within config file"}, -# ifndef OPENSSL_NO_ENGINE +#ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -# endif +#endif {"inkey", OPT_INKEY, 's', "File with private key for reply"}, {"signer", OPT_SIGNER, 's', "Signer certificate file"}, {"chain", OPT_CHAIN, '<', "File with signer CA chain"}, @@ -146,11 +143,11 @@ static char* opt_helplist[] = { " [-signer tsa_cert.pem] [-inkey private_key.pem]", " [-chain certs_file.pem] [-tspolicy oid]", " [-in file] [-token_in] [-out file] [-token_out]", -# ifndef OPENSSL_NO_ENGINE +#ifndef OPENSSL_NO_ENGINE " [-text] [-engine id]", -# else +#else " [-text]", -# endif +#endif "", " openssl ts -verify -CApath dir -CAfile file.pem -CAstore uri", " -untrusted file.pem [-data file] [-digest hexstring]", @@ -699,10 +696,10 @@ static TS_RESP *create_response(CONF *conf, const char *section, const char *eng goto end; if (!TS_CONF_set_serial(conf, section, serial_cb, resp_ctx)) goto end; -# ifndef OPENSSL_NO_ENGINE +#ifndef OPENSSL_NO_ENGINE if (!TS_CONF_set_crypto_device(conf, section, engine)) goto end; -# endif +#endif if (!TS_CONF_set_signer_cert(conf, section, signer, resp_ctx)) goto end; if (!TS_CONF_set_certs(conf, section, chain, resp_ctx)) @@ -1013,4 +1010,3 @@ static int verify_cb(int ok, X509_STORE_CTX *ctx) { return ok; } -#endif /* ndef OPENSSL_NO_TS */ diff --git a/apps/verify.c b/apps/verify.c index 82ca35e9..f626009f 100644 --- a/apps/verify.c +++ b/apps/verify.c @@ -22,7 +22,7 @@ static int cb(int ok, X509_STORE_CTX *ctx); static int check(X509_STORE *ctx, const char *file, STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, STACK_OF(X509_CRL) *crls, int show_chain, - unsigned char *sm2id, size_t sm2idlen); + STACK_OF(OPENSSL_STRING) *opts); static int v_verbose = 0, vflags = 0; typedef enum OPTION_choice { @@ -30,8 +30,8 @@ typedef enum OPTION_choice { OPT_ENGINE, OPT_CAPATH, OPT_CAFILE, OPT_CASTORE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE, OPT_UNTRUSTED, OPT_TRUSTED, OPT_CRLFILE, OPT_CRL_DOWNLOAD, OPT_SHOW_CHAIN, - OPT_V_ENUM, OPT_NAMEOPT, - OPT_VERBOSE, OPT_SM2ID, OPT_SM2HEXID, + OPT_V_ENUM, OPT_NAMEOPT, OPT_VFYOPT, + OPT_VERBOSE, OPT_PROV_ENUM } OPTION_CHOICE; @@ -67,12 +67,7 @@ const OPTIONS verify_options[] = { "Display information about the certificate chain"}, OPT_V_OPTIONS, -#ifndef OPENSSL_NO_SM2 - {"sm2-id", OPT_SM2ID, 's', - "Specify an ID string to verify an SM2 certificate"}, - {"sm2-hex-id", OPT_SM2HEXID, 's', - "Specify a hex ID string to verify an SM2 certificate"}, -#endif + {"vfyopt", OPT_VFYOPT, 's', "Verification parameter in n:v form"}, OPT_PROV_OPTIONS, @@ -86,15 +81,13 @@ int verify_main(int argc, char **argv) ENGINE *e = NULL; STACK_OF(X509) *untrusted = NULL, *trusted = NULL; STACK_OF(X509_CRL) *crls = NULL; + STACK_OF(OPENSSL_STRING) *vfyopts = NULL; X509_STORE *store = NULL; X509_VERIFY_PARAM *vpm = NULL; const char *prog, *CApath = NULL, *CAfile = NULL, *CAstore = NULL; int noCApath = 0, noCAfile = 0, noCAstore = 0; int vpmtouched = 0, crl_download = 0, show_chain = 0, i = 0, ret = 1; OPTION_CHOICE o; - unsigned char *sm2_id = NULL; - size_t sm2_idlen = 0; - int sm2_free = 0; if ((vpm = X509_VERIFY_PARAM_new()) == NULL) goto end; @@ -104,6 +97,7 @@ int verify_main(int argc, char **argv) switch (o) { case OPT_EOF: case OPT_ERR: + opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; case OPT_HELP: @@ -186,32 +180,15 @@ int verify_main(int argc, char **argv) if (!set_nameopt(opt_arg())) goto end; break; + case OPT_VFYOPT: + if (!vfyopts) + vfyopts = sk_OPENSSL_STRING_new_null(); + if (!vfyopts || !sk_OPENSSL_STRING_push(vfyopts, opt_arg())) + goto opthelp; + break; case OPT_VERBOSE: v_verbose = 1; break; - case OPT_SM2ID: - if (sm2_id != NULL) { - BIO_printf(bio_err, - "Use one of the options 'sm2-hex-id' or 'sm2-id' \n"); - goto end; - } - sm2_id = (unsigned char *)opt_arg(); - sm2_idlen = strlen((const char *)sm2_id); - break; - case OPT_SM2HEXID: - if (sm2_id != NULL) { - BIO_printf(bio_err, - "Use one of the options 'sm2-hex-id' or 'sm2-id' \n"); - goto end; - } - /* try to parse the input as hex string first */ - sm2_free = 1; - sm2_id = OPENSSL_hexstr2buf(opt_arg(), (long *)&sm2_idlen); - if (sm2_id == NULL) { - BIO_printf(bio_err, "Invalid hex string input\n"); - goto end; - } - break; case OPT_PROV_CASES: if (!opt_provider(o)) goto end; @@ -244,23 +221,22 @@ int verify_main(int argc, char **argv) ret = 0; if (argc < 1) { if (check(store, NULL, untrusted, trusted, crls, show_chain, - sm2_id, sm2_idlen) != 1) + vfyopts) != 1) ret = -1; } else { for (i = 0; i < argc; i++) - if (check(store, argv[i], untrusted, trusted, crls, - show_chain, sm2_id, sm2_idlen) != 1) + if (check(store, argv[i], untrusted, trusted, crls, show_chain, + vfyopts) != 1) ret = -1; } end: - if (sm2_free) - OPENSSL_free(sm2_id); X509_VERIFY_PARAM_free(vpm); X509_STORE_free(store); sk_X509_pop_free(untrusted, X509_free); sk_X509_pop_free(trusted, X509_free); sk_X509_CRL_pop_free(crls, X509_CRL_free); + sk_OPENSSL_STRING_free(vfyopts); release_engine(e); return (ret < 0 ? 2 : ret); } @@ -268,7 +244,7 @@ int verify_main(int argc, char **argv) static int check(X509_STORE *ctx, const char *file, STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, STACK_OF(X509_CRL) *crls, int show_chain, - unsigned char *sm2id, size_t sm2idlen) + STACK_OF(OPENSSL_STRING) *opts) { X509 *x = NULL; int i = 0, ret = 0; @@ -280,24 +256,15 @@ static int check(X509_STORE *ctx, const char *file, if (x == NULL) goto end; - if (sm2id != NULL) { -#ifndef OPENSSL_NO_SM2 - ASN1_OCTET_STRING *v; - - v = ASN1_OCTET_STRING_new(); - if (v == NULL) { - BIO_printf(bio_err, "error: SM2 ID allocation failed\n"); - goto end; + if (opts != NULL) { + for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) { + char *opt = sk_OPENSSL_STRING_value(opts, i); + if (x509_ctrl_string(x, opt) <= 0) { + BIO_printf(bio_err, "parameter error \"%s\"\n", opt); + ERR_print_errors(bio_err); + return 0; + } } - - if (!ASN1_OCTET_STRING_set(v, sm2id, sm2idlen)) { - BIO_printf(bio_err, "error: setting SM2 ID failed\n"); - ASN1_OCTET_STRING_free(v); - goto end; - } - - X509_set0_sm2_id(x, v); -#endif } csc = X509_STORE_CTX_new(); diff --git a/apps/x509.c b/apps/x509.c index 3176cf52..e2a68828 100644 --- a/apps/x509.c +++ b/apps/x509.c @@ -33,7 +33,9 @@ #define DEF_DAYS 30 static int callb(int ok, X509_STORE_CTX *ctx); -static int sign(X509 *x, EVP_PKEY *pkey, EVP_PKEY *fkey, int days, int clrext, +static int sign(X509 *x, EVP_PKEY *pkey, EVP_PKEY *fkey, + STACK_OF(OPENSSL_STRING) *sigopts, + int days, int clrext, const EVP_MD *digest, CONF *conf, const char *section, int preserve_dates); static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *digest, @@ -48,7 +50,7 @@ static int print_x509v3_exts(BIO *bio, X509 *x, const char *exts); typedef enum OPTION_choice { OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_INFORM, OPT_OUTFORM, OPT_KEYFORM, OPT_REQ, OPT_CAFORM, - OPT_CAKEYFORM, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE, + OPT_CAKEYFORM, OPT_VFYOPT, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE, OPT_EXTENSIONS, OPT_IN, OPT_OUT, OPT_SIGNKEY, OPT_CA, OPT_CAKEY, OPT_CASERIAL, OPT_SET_SERIAL, OPT_NEW, OPT_FORCE_PUBKEY, OPT_SUBJ, OPT_ADDTRUST, OPT_ADDREJECT, OPT_SETALIAS, OPT_CERTOPT, OPT_NAMEOPT, @@ -80,6 +82,7 @@ const OPTIONS x509_options[] = { {"out", OPT_OUT, '>', "Output file - default stdout"}, {"keyform", OPT_KEYFORM, 'E', "Private key format - default PEM"}, {"req", OPT_REQ, '-', "Input is a certificate request, sign and output"}, + {"vfyopt", OPT_VFYOPT, 's', "Verification parameter in n:v form"}, OPT_SECTION("Output"), {"serial", OPT_SERIAL, '-', "Print serial number value"}, @@ -174,7 +177,7 @@ int x509_main(int argc, char **argv) const unsigned long chtype = MBSTRING_ASC; const int multirdn = 0; STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL; - STACK_OF(OPENSSL_STRING) *sigopts = NULL; + STACK_OF(OPENSSL_STRING) *sigopts = NULL, *vfyopts = NULL; X509 *x = NULL, *xca = NULL; X509_REQ *req = NULL, *rq = NULL; X509_STORE *ctx = NULL; @@ -256,6 +259,12 @@ int x509_main(int argc, char **argv) if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) goto opthelp; break; + case OPT_VFYOPT: + if (!vfyopts) + vfyopts = sk_OPENSSL_STRING_new_null(); + if (!vfyopts || !sk_OPENSSL_STRING_push(vfyopts, opt_arg())) + goto opthelp; + break; case OPT_DAYS: if (preserve_dates) goto opthelp; @@ -576,7 +585,7 @@ int x509_main(int argc, char **argv) BIO_printf(bio_err, "error unpacking public key\n"); goto end; } - i = X509_REQ_verify(req, pkey); + i = do_X509_REQ_verify(req, pkey, vfyopts); if (i < 0) { BIO_printf(bio_err, "Request self-signature verification error\n"); ERR_print_errors(bio_err); @@ -848,8 +857,8 @@ int x509_main(int argc, char **argv) goto end; } - if (!sign(x, Upkey, fkey, days, clrext, digest, extconf, - extsect, preserve_dates)) + if (!sign(x, Upkey, fkey, sigopts, days, clrext, digest, + extconf, extsect, preserve_dates)) goto end; } else if (CA_flag == i) { BIO_printf(bio_err, "Getting CA Private Key\n"); @@ -949,6 +958,7 @@ int x509_main(int argc, char **argv) EVP_PKEY_free(CApkey); EVP_PKEY_free(fkey); sk_OPENSSL_STRING_free(sigopts); + sk_OPENSSL_STRING_free(vfyopts); X509_REQ_free(rq); ASN1_INTEGER_free(sno); sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free); @@ -1106,11 +1116,12 @@ static int callb(int ok, X509_STORE_CTX *ctx) } /* self-issue; self-sign unless a forced public key (fkey) is given */ -static int sign(X509 *x, EVP_PKEY *pkey, EVP_PKEY *fkey, int days, int clrext, +static int sign(X509 *x, EVP_PKEY *pkey, EVP_PKEY *fkey, + STACK_OF(OPENSSL_STRING) *sigopts, + int days, int clrext, const EVP_MD *digest, CONF *conf, const char *section, int preserve_dates) { - if (!X509_set_issuer_name(x, X509_get_subject_name(x))) goto err; if (!preserve_dates && !set_cert_times(x, NULL, NULL, days)) @@ -1129,7 +1140,7 @@ static int sign(X509 *x, EVP_PKEY *pkey, EVP_PKEY *fkey, int days, int clrext, if (!X509V3_EXT_add_nconf(conf, &ctx, section, x)) goto err; } - if (!X509_sign(x, pkey, digest)) + if (!do_X509_sign(x, pkey, digest, sigopts)) goto err; return 1; err: diff --git a/crypto/asn1/asn1_item_list.h b/crypto/asn1/asn1_item_list.h index c8727e57..4cdf1d22 100644 --- a/crypto/asn1/asn1_item_list.h +++ b/crypto/asn1/asn1_item_list.h @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -145,6 +145,7 @@ static ASN1_ITEM_EXP *asn1_item_list[] = { #endif ASN1_ITEM_ref(SXNETID), ASN1_ITEM_ref(SXNET), + ASN1_ITEM_ref(ISSUER_SIGN_TOOL), ASN1_ITEM_ref(USERNOTICE), ASN1_ITEM_ref(X509_ALGORS), ASN1_ITEM_ref(X509_ALGOR), diff --git a/crypto/asn1/asn1_lib.c b/crypto/asn1/asn1_lib.c index 52eb16ba..d8844eab 100644 --- a/crypto/asn1/asn1_lib.c +++ b/crypto/asn1/asn1_lib.c @@ -22,11 +22,13 @@ static int _asn1_check_infinite_end(const unsigned char **p, long len) /* * If there is 0 or 1 byte left, the length check should pick things up */ - if (len <= 0) - return 1; - else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) { - (*p) += 2; + if (len <= 0) { return 1; + } else { + if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) { + (*p) += 2; + return 1; + } } return 0; } @@ -45,7 +47,7 @@ int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag, int *pclass, long omax) { int i, ret; - long l; + long len; const unsigned char *p = *pp; int tag, xclass, inf; long max = omax; @@ -59,18 +61,18 @@ int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag, p++; if (--max == 0) goto err; - l = 0; + len = 0; while (*p & 0x80) { - l <<= 7L; - l |= *(p++) & 0x7f; + len <<= 7L; + len |= *(p++) & 0x7f; if (--max == 0) goto err; - if (l > (INT_MAX >> 7L)) + if (len > (INT_MAX >> 7L)) goto err; } - l <<= 7L; - l |= *(p++) & 0x7f; - tag = (int)l; + len <<= 7L; + len |= *(p++) & 0x7f; + tag = (int)len; if (--max == 0) goto err; } else { @@ -141,8 +143,9 @@ static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, } if (ret > LONG_MAX) return 0; - } else + } else { ret = i; + } } *pp = p; *rl = (long)ret; @@ -160,9 +163,9 @@ void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, i = (constructed) ? V_ASN1_CONSTRUCTED : 0; i |= (xclass & V_ASN1_PRIVATE); - if (tag < 31) + if (tag < 31) { *(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG); - else { + } else { *(p++) = i | V_ASN1_PRIMITIVE_TAG; for (i = 0, ttag = tag; ttag > 0; i++) ttag >>= 7; @@ -185,6 +188,7 @@ void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, int ASN1_put_eoc(unsigned char **pp) { unsigned char *p = *pp; + *p++ = 0; *p++ = 0; *pp = p; @@ -194,20 +198,21 @@ int ASN1_put_eoc(unsigned char **pp) static void asn1_put_length(unsigned char **pp, int length) { unsigned char *p = *pp; - int i, l; - if (length <= 127) + int i, len; + + if (length <= 127) { *(p++) = (unsigned char)length; - else { - l = length; - for (i = 0; l > 0; i++) - l >>= 8; + } else { + len = length; + for (i = 0; len > 0; i++) + len >>= 8; *(p++) = i | 0x80; - l = i; + len = i; while (i-- > 0) { p[i] = length & 0xff; length >>= 8; } - p += l; + p += len; } *pp = p; } @@ -215,6 +220,7 @@ static void asn1_put_length(unsigned char **pp, int length) int ASN1_object_size(int constructed, int length, int tag) { int ret = 1; + if (length < 0) return -1; if (tag >= 31) { @@ -256,6 +262,7 @@ int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str) ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str) { ASN1_STRING *ret; + if (!str) return NULL; ret = ASN1_STRING_new(); @@ -268,18 +275,29 @@ ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str) return ret; } -int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len) +int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len_in) { unsigned char *c; const char *data = _data; + size_t len; - if (len < 0) { + if (len_in < 0) { if (data == NULL) return 0; - else - len = strlen(data); + len = strlen(data); + } else { + len = (size_t)len_in; } - if ((str->length <= len) || (str->data == NULL)) { + /* + * Verify that the length fits within an integer for assignment to + * str->length below. The additional 1 is subtracted to allow for the + * '\0' terminator even though this isn't strictly necessary. + */ + if (len > INT_MAX - 1) { + ASN1err(0, ASN1_R_TOO_LARGE); + return 0; + } + if ((size_t)str->length <= len || str->data == NULL) { c = str->data; str->data = OPENSSL_realloc(c, len + 1); if (str->data == NULL) { @@ -359,8 +377,9 @@ int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b) return a->type - b->type; else return i; - } else + } else { return i; + } } int ASN1_STRING_length(const ASN1_STRING *x) @@ -383,9 +402,48 @@ const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x) return x->data; } -# ifndef OPENSSL_NO_DEPRECATED_1_1_0 +#ifndef OPENSSL_NO_DEPRECATED_1_1_0 unsigned char *ASN1_STRING_data(ASN1_STRING *x) { return x->data; } #endif + +char *sk_ASN1_UTF8STRING2text(STACK_OF(ASN1_UTF8STRING) *text, const char *sep, + size_t max_len /* excluding NUL terminator */) +{ + int i; + ASN1_UTF8STRING *current; + size_t length = 0, sep_len; + char *result = NULL; + char *p; + + if (!ossl_assert(sep != NULL)) + return NULL; + sep_len = strlen(sep); + + for (i = 0; i < sk_ASN1_UTF8STRING_num(text); ++i) { + current = sk_ASN1_UTF8STRING_value(text, i); + if (i > 0) + length += sep_len; + length += ASN1_STRING_length(current); + if (length > max_len) + return NULL; + } + if ((result = OPENSSL_malloc(length + 1)) == NULL) + return NULL; + + for (i = 0, p = result; i < sk_ASN1_UTF8STRING_num(text); ++i) { + current = sk_ASN1_UTF8STRING_value(text, i); + length = ASN1_STRING_length(current); + if (i > 0 && sep_len > 0) { + strncpy(p, sep, sep_len + 1); + p += sep_len; + } + strncpy(p, (const char *)ASN1_STRING_get0_data(current), length); + p += length; + } + *p = '\0'; + + return result; +} diff --git a/crypto/bf/build.info b/crypto/bf/build.info index 59d5bbcf..9fa81878 100644 --- a/crypto/bf/build.info +++ b/crypto/bf/build.info @@ -11,7 +11,15 @@ IF[{- !$disabled{asm} -}] ENDIF ENDIF -SOURCE[../../libcrypto]=bf_skey.c bf_ecb.c bf_cfb64.c bf_ofb64.c $BFASM +$ALL=bf_skey.c bf_ecb.c bf_cfb64.c bf_ofb64.c $BFASM + +SOURCE[../../libcrypto]=$ALL + +# When all deprecated symbols are removed, libcrypto doesn't export the +# blowfish functions, so we must include them directly in liblegacy.a +IF[{- $disabled{'deprecated-3.0'} -}] + SOURCE[../../providers/liblegacy.a]=$ALL +ENDIF GENERATE[bf-586.s]=asm/bf-586.pl DEPEND[bf-586.s]=../perlasm/x86asm.pl ../perlasm/cbc.pl diff --git a/crypto/bio/b_sock2.c b/crypto/bio/b_sock2.c index 942825a8..df13d58c 100644 --- a/crypto/bio/b_sock2.c +++ b/crypto/bio/b_sock2.c @@ -12,6 +12,7 @@ #include #include "bio_local.h" +#include "internal/ktls.h" #include @@ -51,6 +52,17 @@ int BIO_socket(int domain, int socktype, int protocol, int options) BIOerr(BIO_F_BIO_SOCKET, BIO_R_UNABLE_TO_CREATE_SOCKET); return INVALID_SOCKET; } +# ifndef OPENSSL_NO_KTLS + { + /* + * The new socket is created successfully regardless of ktls_enable. + * ktls_enable doesn't change any functionality of the socket, except + * changing the setsockopt to enable the processing of ktls_start. + * Thus, it is not a problem to call it for non-TLS sockets. + */ + ktls_enable(sock); + } +# endif return sock; } diff --git a/crypto/bio/bio_lib.c b/crypto/bio/bio_lib.c index ca1c9fc6..35bd163a 100644 --- a/crypto/bio/bio_lib.c +++ b/crypto/bio/bio_lib.c @@ -750,7 +750,7 @@ int BIO_set_ex_data(BIO *bio, int idx, void *data) return CRYPTO_set_ex_data(&(bio->ex_data), idx, data); } -void *BIO_get_ex_data(BIO *bio, int idx) +void *BIO_get_ex_data(const BIO *bio, int idx) { return CRYPTO_get_ex_data(&(bio->ex_data), idx); } diff --git a/crypto/bio/bss_acpt.c b/crypto/bio/bss_acpt.c index a3b3f21c..d5b29ecf 100644 --- a/crypto/bio/bss_acpt.c +++ b/crypto/bio/bss_acpt.c @@ -222,19 +222,20 @@ static int acpt_state(BIO *b, BIO_ACCEPT *c) break; case ACPT_S_CREATE_SOCKET: - ret = BIO_socket(BIO_ADDRINFO_family(c->addr_iter), - BIO_ADDRINFO_socktype(c->addr_iter), - BIO_ADDRINFO_protocol(c->addr_iter), 0); - if (ret == (int)INVALID_SOCKET) { + s = BIO_socket(BIO_ADDRINFO_family(c->addr_iter), + BIO_ADDRINFO_socktype(c->addr_iter), + BIO_ADDRINFO_protocol(c->addr_iter), 0); + if (s == (int)INVALID_SOCKET) { ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), "calling socket(%s, %s)", c->param_addr, c->param_serv); BIOerr(BIO_F_ACPT_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET); goto exit_loop; } - c->accept_sock = ret; - b->num = ret; + c->accept_sock = s; + b->num = s; c->state = ACPT_S_LISTEN; + s = -1; break; case ACPT_S_LISTEN: diff --git a/crypto/bio/bss_conn.c b/crypto/bio/bss_conn.c index 6c554ff6..87009fb6 100644 --- a/crypto/bio/bss_conn.c +++ b/crypto/bio/bss_conn.c @@ -11,6 +11,7 @@ #include #include "bio_local.h" +#include "internal/ktls.h" #ifndef OPENSSL_NO_SOCK @@ -20,6 +21,9 @@ typedef struct bio_connect_st { char *param_hostname; char *param_service; int connect_mode; +# ifndef OPENSSL_NO_KTLS + unsigned char record_type; +# endif BIO_ADDRINFO *addr_first; const BIO_ADDRINFO *addr_iter; @@ -308,7 +312,12 @@ static int conn_read(BIO *b, char *out, int outl) if (out != NULL) { clear_socket_error(); - ret = readsocket(b->num, out, outl); +# ifndef OPENSSL_NO_KTLS + if (BIO_get_ktls_recv(b)) + ret = ktls_read_record(b->num, out, outl); + else +# endif + ret = readsocket(b->num, out, outl); BIO_clear_retry_flags(b); if (ret <= 0) { if (BIO_sock_should_retry(ret)) @@ -333,7 +342,16 @@ static int conn_write(BIO *b, const char *in, int inl) } clear_socket_error(); - ret = writesocket(b->num, in, inl); +# ifndef OPENSSL_NO_KTLS + if (BIO_should_ktls_ctrl_msg_flag(b)) { + ret = ktls_send_ctrl_message(b->num, data->record_type, in, inl); + if (ret >= 0) { + ret = inl; + BIO_clear_ktls_ctrl_msg_flag(b); + } + } else +# endif + ret = writesocket(b->num, in, inl); BIO_clear_retry_flags(b); if (ret <= 0) { if (BIO_sock_should_retry(ret)) @@ -349,6 +367,13 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr) const char **pptr = NULL; long ret = 1; BIO_CONNECT *data; +# ifndef OPENSSL_NO_KTLS +# ifdef __FreeBSD__ + struct tls_enable *crypto_info; +# else + struct tls12_crypto_info_aes_gcm_128 *crypto_info; +# endif +# endif data = (BIO_CONNECT *)b->ptr; @@ -497,6 +522,31 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_CTRL_EOF: ret = (b->flags & BIO_FLAGS_IN_EOF) != 0 ? 1 : 0; break; +# ifndef OPENSSL_NO_KTLS + case BIO_CTRL_SET_KTLS: +# ifdef __FreeBSD__ + crypto_info = (struct tls_enable *)ptr; +# else + crypto_info = (struct tls12_crypto_info_aes_gcm_128 *)ptr; +# endif + ret = ktls_start(b->num, crypto_info, sizeof(*crypto_info), num); + if (ret) + BIO_set_ktls_flag(b, num); + break; + case BIO_CTRL_GET_KTLS_SEND: + return BIO_should_ktls_flag(b, 1); + case BIO_CTRL_GET_KTLS_RECV: + return BIO_should_ktls_flag(b, 0); + case BIO_CTRL_SET_KTLS_TX_SEND_CTRL_MSG: + BIO_set_ktls_ctrl_msg_flag(b); + data->record_type = num; + ret = 0; + break; + case BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG: + BIO_clear_ktls_ctrl_msg_flag(b); + ret = 0; + break; +# endif default: ret = 0; break; diff --git a/crypto/build.info b/crypto/build.info index a688248a..860b8bb8 100644 --- a/crypto/build.info +++ b/crypto/build.info @@ -70,7 +70,8 @@ SOURCE[../providers/libfips.a]=$CORE_COMMON $UTIL_COMMON=\ cryptlib.c params.c params_from_text.c bsearch.c ex_data.c o_str.c \ ctype.c threads_pthread.c threads_win.c threads_none.c initthread.c \ - context.c sparse_array.c asn1_dsa.c packet.c param_build.c $CPUIDASM + context.c sparse_array.c asn1_dsa.c packet.c param_build.c $CPUIDASM \ + param_build_set.c der_writer.c $UTIL_DEFINE=$CPUIDDEF SOURCE[../libcrypto]=$UTIL_COMMON \ @@ -79,6 +80,7 @@ SOURCE[../libcrypto]=$UTIL_COMMON \ o_fopen.c getenv.c o_init.c o_fips.c init.c trace.c provider.c \ $UPLINKSRC SOURCE[../providers/libfips.a]=$UTIL_COMMON +SOURCE[../providers/liblegacy.a]=$UTIL_COMMON # Implementations are now spread across several libraries, so the defines # need to be applied to all affected libraries and modules. @@ -86,6 +88,7 @@ DEFINE[../libcrypto]=$UTIL_DEFINE $UPLINKDEF DEFINE[../providers/libfips.a]=$UTIL_DEFINE DEFINE[../providers/fips]=$UTIL_DEFINE DEFINE[../providers/libimplementations.a]=$UTIL_DEFINE +DEFINE[../providers/liblegacy.a]=$UTIL_DEFINE DEFINE[../providers/libcommon.a]=$UTIL_DEFINE DEPEND[info.o]=buildinf.h diff --git a/crypto/cast/build.info b/crypto/cast/build.info index e21e6d55..8763f224 100644 --- a/crypto/cast/build.info +++ b/crypto/cast/build.info @@ -12,7 +12,15 @@ IF[{- !$disabled{asm} && !$disabled{pic} -}] ENDIF ENDIF -SOURCE[../../libcrypto]=c_skey.c c_ecb.c $CASTASM c_cfb64.c c_ofb64.c +$ALL=c_skey.c c_ecb.c $CASTASM c_cfb64.c c_ofb64.c + +SOURCE[../../libcrypto]=$ALL + +# When all deprecated symbols are removed, libcrypto doesn't export the +# cast functions, so we must include them directly in liblegacy.a +IF[{- $disabled{'deprecated-3.0'} -}] + SOURCE[../../providers/liblegacy.a]=$ALL +ENDIF GENERATE[cast-586.s]=asm/cast-586.pl DEPEND[cast-586.s]=../perlasm/x86asm.pl ../perlasm/cbc.pl diff --git a/crypto/cmp/build.info b/crypto/cmp/build.info index 41a58993..a2a57c14 100644 --- a/crypto/cmp/build.info +++ b/crypto/cmp/build.info @@ -1,3 +1,4 @@ LIBS=../../libcrypto SOURCE[../../libcrypto]= cmp_asn.c cmp_ctx.c cmp_err.c cmp_util.c \ - cmp_status.c cmp_hdr.c cmp_protect.c cmp_msg.c cmp_vfy.c + cmp_status.c cmp_hdr.c cmp_protect.c cmp_msg.c cmp_vfy.c \ + cmp_server.c cmp_client.c cmp_http.c diff --git a/crypto/cmp/cmp_client.c b/crypto/cmp/cmp_client.c new file mode 100644 index 00000000..604b4ce9 --- /dev/null +++ b/crypto/cmp/cmp_client.c @@ -0,0 +1,881 @@ +/* + * Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright Nokia 2007-2019 + * Copyright Siemens AG 2015-2019 + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cmp_local.h" +#include "internal/cryptlib.h" + +/* explicit #includes not strictly needed since implied by the above: */ +#include +#include +#include +#include +#include + +#include "openssl/cmp_util.h" + +#define IS_CREP(t) ((t) == OSSL_CMP_PKIBODY_IP || (t) == OSSL_CMP_PKIBODY_CP \ + || (t) == OSSL_CMP_PKIBODY_KUP) + +/*- + * Evaluate whether there's an exception (violating the standard) configured for + * handling negative responses without protection or with invalid protection. + * Returns 1 on acceptance, 0 on rejection, or -1 on (internal) error. + */ +static int unprotected_exception(const OSSL_CMP_CTX *ctx, + const OSSL_CMP_MSG *rep, + int invalid_protection, + int expected_type /* ignored here */) +{ + int rcvd_type = ossl_cmp_msg_get_bodytype(rep /* may be NULL */); + const char *msg_type = NULL; + + if (!ossl_assert(ctx != NULL && rep != NULL)) + return -1; + + if (!ctx->unprotectedErrors) + return 0; + + switch (rcvd_type) { + case OSSL_CMP_PKIBODY_ERROR: + msg_type = "error response"; + break; + case OSSL_CMP_PKIBODY_RP: + { + OSSL_CMP_PKISI *si = + ossl_cmp_revrepcontent_get_pkisi(rep->body->value.rp, + OSSL_CMP_REVREQSID); + + if (si == NULL) + return -1; + if (ossl_cmp_pkisi_get_status(si) == OSSL_CMP_PKISTATUS_rejection) + msg_type = "revocation response message with rejection status"; + break; + } + case OSSL_CMP_PKIBODY_PKICONF: + msg_type = "PKI Confirmation message"; + break; + default: + if (IS_CREP(rcvd_type)) { + OSSL_CMP_CERTREPMESSAGE *crepmsg = rep->body->value.ip; + OSSL_CMP_CERTRESPONSE *crep = + ossl_cmp_certrepmessage_get0_certresponse(crepmsg, + -1 /* any rid */); + + if (sk_OSSL_CMP_CERTRESPONSE_num(crepmsg->response) > 1) + return -1; + /* TODO: handle potentially multiple CertResponses in CertRepMsg */ + if (crep == NULL) + return -1; + if (ossl_cmp_pkisi_get_status(crep->status) + == OSSL_CMP_PKISTATUS_rejection) + msg_type = "CertRepMessage with rejection status"; + } + } + if (msg_type == NULL) + return 0; + ossl_cmp_log2(WARN, ctx, "ignoring %s protection of %s", + invalid_protection ? "invalid" : "missing", msg_type); + return 1; +} + + +/* Save error info from PKIStatusInfo field of a certresponse into ctx */ +static int save_statusInfo(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si) +{ + int i; + OSSL_CMP_PKIFREETEXT *ss; + + if (!ossl_assert(ctx != NULL && si != NULL)) + return 0; + + if ((ctx->status = ossl_cmp_pkisi_get_status(si)) < 0) + return 0; + + ctx->failInfoCode = 0; + if (si->failInfo != NULL) { + for (i = 0; i <= OSSL_CMP_PKIFAILUREINFO_MAX; i++) { + if (ASN1_BIT_STRING_get_bit(si->failInfo, i)) + ctx->failInfoCode |= (1 << i); + } + } + + if (!ossl_cmp_ctx_set0_statusString(ctx, sk_ASN1_UTF8STRING_new_null()) + || (ctx->statusString == NULL)) + return 0; + + ss = si->statusString; /* may be NULL */ + for (i = 0; i < sk_ASN1_UTF8STRING_num(ss); i++) { + ASN1_UTF8STRING *str = sk_ASN1_UTF8STRING_value(ss, i); + + if (!sk_ASN1_UTF8STRING_push(ctx->statusString, ASN1_STRING_dup(str))) + return 0; + } + return 1; +} + +/*- + * Perform the generic aspects of sending a request and receiving a response. + * Returns 1 on success and provides the received PKIMESSAGE in *rep. + * Returns 0 on error. + * Regardless of success, caller is responsible for freeing *rep (unless NULL). + */ +static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req, + OSSL_CMP_MSG **rep, int expected_type) +{ + const char *req_type_str = + ossl_cmp_bodytype_to_string(ossl_cmp_msg_get_bodytype(req)); + const char *expected_type_str = ossl_cmp_bodytype_to_string(expected_type); + int msg_timeout; + int bt; + time_t now = time(NULL); + int time_left; + OSSL_CMP_transfer_cb_t transfer_cb = ctx->transfer_cb; + + if (transfer_cb == NULL) + transfer_cb = OSSL_CMP_MSG_http_perform; + + *rep = NULL; + msg_timeout = ctx->msg_timeout; /* backup original value */ + if ((IS_CREP(expected_type) || expected_type == OSSL_CMP_PKIBODY_POLLREP) + && ctx->total_timeout > 0 /* timeout is not infinite */) { + if (now >= ctx->end_time) { + CMPerr(0, CMP_R_TOTAL_TIMEOUT); + return 0; + } + if (!ossl_assert(ctx->end_time - time(NULL) < INT_MAX)) { + /* cannot really happen due to the assignment in do_certreq_seq() */ + CMPerr(0, CMP_R_INVALID_ARGS); + return 0; + } + time_left = (int)(ctx->end_time - now); + if (ctx->msg_timeout == 0 || time_left < ctx->msg_timeout) + ctx->msg_timeout = time_left; + } + + /* should print error queue since transfer_cb may call ERR_clear_error() */ + OSSL_CMP_CTX_print_errors(ctx); + + ossl_cmp_log1(INFO, ctx, "sending %s", req_type_str); + + *rep = (*transfer_cb)(ctx, req); + ctx->msg_timeout = msg_timeout; /* restore original value */ + + if (*rep == NULL) { + CMPerr(0, CMP_R_TRANSFER_ERROR); /* or receiving response */ + ERR_add_error_data(1, req_type_str); + ERR_add_error_data(2, ", expected response: ", expected_type_str); + return 0; + } + + bt = ossl_cmp_msg_get_bodytype(*rep); + /* + * The body type in the 'bt' variable is not yet verified. + * Still we use this preliminary value already for a progress report because + * the following msg verification may also produce log entries and may fail. + */ + ossl_cmp_log1(INFO, ctx, "received %s", ossl_cmp_bodytype_to_string(bt)); + + if ((bt = ossl_cmp_msg_check_received(ctx, *rep, unprotected_exception, + expected_type)) < 0) + return 0; + + if (bt == expected_type + /* as an answer to polling, there could be IP/CP/KUP: */ + || (IS_CREP(bt) && expected_type == OSSL_CMP_PKIBODY_POLLREP)) + return 1; + + /* received message type is not one of the expected ones (e.g., error) */ + CMPerr(0, bt == OSSL_CMP_PKIBODY_ERROR ? CMP_R_RECEIVED_ERROR : + CMP_R_UNEXPECTED_PKIBODY); /* in next line for mkerr.pl */ + + if (bt != OSSL_CMP_PKIBODY_ERROR) { + ERR_add_error_data(3, "message type is '", + ossl_cmp_bodytype_to_string(bt), "'"); + } else { + OSSL_CMP_ERRORMSGCONTENT *emc = (*rep)->body->value.error; + OSSL_CMP_PKISI *si = emc->pKIStatusInfo; + char buf[OSSL_CMP_PKISI_BUFLEN]; + + if (save_statusInfo(ctx, si) + && OSSL_CMP_CTX_snprint_PKIStatus(ctx, buf, sizeof(buf)) != NULL) + ERR_add_error_data(1, buf); + if (emc->errorCode != NULL + && BIO_snprintf(buf, sizeof(buf), "; errorCode: %ld", + ASN1_INTEGER_get(emc->errorCode)) > 0) + ERR_add_error_data(1, buf); + if (emc->errorDetails != NULL) { + char *text = sk_ASN1_UTF8STRING2text(emc->errorDetails, ", ", + OSSL_CMP_PKISI_BUFLEN - 1); + + if (text != NULL) + ERR_add_error_data(2, "; errorDetails: ", text); + OPENSSL_free(text); + } + if (ctx->status != OSSL_CMP_PKISTATUS_rejection) { + CMPerr(0, CMP_R_UNEXPECTED_PKISTATUS); + if (ctx->status == OSSL_CMP_PKISTATUS_waiting) + ctx->status = OSSL_CMP_PKISTATUS_rejection; + } + } + return 0; +} + +/*- + * When a 'waiting' PKIStatus has been received, this function is used to + * poll, which should yield a pollRep or finally a CertRepMessage in ip/cp/kup. + * On receiving a pollRep, which includes a checkAfter value, it return this + * value if sleep == 0, else it sleeps as long as indicated and retries. + * + * A transaction timeout is enabled if ctx->total_timeout is > 0. + * In this case polling will continue until the timeout is reached and then + * polling is done a last time even if this is before the "checkAfter" time. + * + * Returns -1 on receiving pollRep if sleep == 0, setting the checkAfter value. + * Returns 1 on success and provides the received PKIMESSAGE in *rep. + * In this case the caller is responsible for freeing *rep. + * Returns 0 on error (which includes the case that timeout has been reached). + */ +static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid, + OSSL_CMP_MSG **rep, int *checkAfter) +{ + OSSL_CMP_MSG *preq = NULL; + OSSL_CMP_MSG *prep = NULL; + + ossl_cmp_info(ctx, + "received 'waiting' PKIStatus, starting to poll for response"); + *rep = NULL; + for (;;) { + /* TODO: handle potentially multiple poll requests per message */ + if ((preq = ossl_cmp_pollReq_new(ctx, rid)) == NULL) + goto err; + + if (!send_receive_check(ctx, preq, &prep, OSSL_CMP_PKIBODY_POLLREP)) + goto err; + + /* handle potential pollRep */ + if (ossl_cmp_msg_get_bodytype(prep) == OSSL_CMP_PKIBODY_POLLREP) { + OSSL_CMP_POLLREPCONTENT *prc = prep->body->value.pollRep; + OSSL_CMP_POLLREP *pollRep = NULL; + int64_t check_after; + char str[OSSL_CMP_PKISI_BUFLEN]; + int len; + + /* TODO: handle potentially multiple elements in pollRep */ + if (sk_OSSL_CMP_POLLREP_num(prc) > 1) { + CMPerr(0, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED); + goto err; + } + pollRep = ossl_cmp_pollrepcontent_get0_pollrep(prc, rid); + if (pollRep == NULL) + goto err; + + if (!ASN1_INTEGER_get_int64(&check_after, pollRep->checkAfter)) { + CMPerr(0, CMP_R_BAD_CHECKAFTER_IN_POLLREP); + goto err; + } + if (check_after < 0 || (uint64_t)check_after + > (sleep ? ULONG_MAX / 1000 : INT_MAX)) { + CMPerr(0, CMP_R_CHECKAFTER_OUT_OF_RANGE); + if (BIO_snprintf(str, OSSL_CMP_PKISI_BUFLEN, "value = %jd", + check_after) >= 0) + ERR_add_error_data(1, str); + goto err; + } + if (ctx->total_timeout > 0) { /* timeout is not infinite */ + const int exp = 5; /* expected max time per msg round trip */ + int64_t time_left = (int64_t)(ctx->end_time - exp - time(NULL)); + + if (time_left <= 0) { + CMPerr(0, CMP_R_TOTAL_TIMEOUT); + goto err; + } + if (time_left < check_after) + check_after = time_left; + /* poll one last time just when timeout was reached */ + } + + if (pollRep->reason == NULL + || (len = BIO_snprintf(str, OSSL_CMP_PKISI_BUFLEN, + " with reason = '")) < 0) { + *str = '\0'; + } else { + char *text = sk_ASN1_UTF8STRING2text(pollRep->reason, ", ", + sizeof(str) - len - 2); + + if (text == NULL + || BIO_snprintf(str + len, sizeof(str) - len, + "%s'", text) < 0) + *str = '\0'; + OPENSSL_free(text); + } + ossl_cmp_log2(INFO, ctx, + "received polling response%s; checkAfter = %ld seconds", + str, check_after); + + OSSL_CMP_MSG_free(preq); + preq = NULL; + OSSL_CMP_MSG_free(prep); + prep = NULL; + if (sleep) { + ossl_sleep((unsigned long)(1000 * check_after)); + } else { + if (checkAfter != NULL) + *checkAfter = (int)check_after; + return -1; /* exits the loop */ + } + } else { + ossl_cmp_info(ctx, "received ip/cp/kup after polling"); + /* any other body type has been rejected by send_receive_check() */ + break; + } + } + if (prep == NULL) + goto err; + + OSSL_CMP_MSG_free(preq); + *rep = prep; + + return 1; + err: + OSSL_CMP_MSG_free(preq); + OSSL_CMP_MSG_free(prep); + return 0; +} + +/* Send certConf for IR, CR or KUR sequences and check response */ +int ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int fail_info, + const char *txt) +{ + OSSL_CMP_MSG *certConf; + OSSL_CMP_MSG *PKIconf = NULL; + int res = 0; + + /* OSSL_CMP_certConf_new() also checks if all necessary options are set */ + if ((certConf = ossl_cmp_certConf_new(ctx, fail_info, txt)) == NULL) + goto err; + + res = send_receive_check(ctx, certConf, &PKIconf, OSSL_CMP_PKIBODY_PKICONF); + + err: + OSSL_CMP_MSG_free(certConf); + OSSL_CMP_MSG_free(PKIconf); + return res; +} + +/* Send given error and check response */ +int ossl_cmp_exchange_error(OSSL_CMP_CTX *ctx, int status, int fail_info, + const char *txt, int errorCode, const char *details) +{ + OSSL_CMP_MSG *error = NULL; + OSSL_CMP_PKISI *si = NULL; + OSSL_CMP_MSG *PKIconf = NULL; + int res = 0; + + if ((si = OSSL_CMP_STATUSINFO_new(status, fail_info, txt)) == NULL) + goto err; + /* ossl_cmp_error_new() also checks if all necessary options are set */ + if ((error = ossl_cmp_error_new(ctx, si, errorCode, details, 0)) == NULL) + goto err; + + res = send_receive_check(ctx, error, &PKIconf, OSSL_CMP_PKIBODY_PKICONF); + + err: + OSSL_CMP_MSG_free(error); + OSSL_CMP_PKISI_free(si); + OSSL_CMP_MSG_free(PKIconf); + return res; +} + +/*- + * Retrieve a copy of the certificate, if any, from the given CertResponse. + * Take into account PKIStatusInfo of CertResponse in ctx, report it on error. + * Returns NULL if not found or on error. + */ +static X509 *get1_cert_status(OSSL_CMP_CTX *ctx, int bodytype, + OSSL_CMP_CERTRESPONSE *crep) +{ + char buf[OSSL_CMP_PKISI_BUFLEN]; + X509 *crt = NULL; + EVP_PKEY *privkey; + + if (!ossl_assert(ctx != NULL && crep != NULL)) + return NULL; + + privkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1); + switch (ossl_cmp_pkisi_get_status(crep->status)) { + case OSSL_CMP_PKISTATUS_waiting: + ossl_cmp_err(ctx, + "received \"waiting\" status for cert when actually aiming to extract cert"); + CMPerr(0, CMP_R_ENCOUNTERED_WAITING); + goto err; + case OSSL_CMP_PKISTATUS_grantedWithMods: + ossl_cmp_warn(ctx, "received \"grantedWithMods\" for certificate"); + crt = ossl_cmp_certresponse_get1_certificate(privkey, crep); + break; + case OSSL_CMP_PKISTATUS_accepted: + crt = ossl_cmp_certresponse_get1_certificate(privkey, crep); + break; + /* get all information in case of a rejection before going to error */ + case OSSL_CMP_PKISTATUS_rejection: + ossl_cmp_err(ctx, "received \"rejection\" status rather than cert"); + CMPerr(0, CMP_R_REQUEST_REJECTED_BY_SERVER); + goto err; + case OSSL_CMP_PKISTATUS_revocationWarning: + ossl_cmp_warn(ctx, + "received \"revocationWarning\" - a revocation of the cert is imminent"); + crt = ossl_cmp_certresponse_get1_certificate(privkey, crep); + break; + case OSSL_CMP_PKISTATUS_revocationNotification: + ossl_cmp_warn(ctx, + "received \"revocationNotification\" - a revocation of the cert has occurred"); + crt = ossl_cmp_certresponse_get1_certificate(privkey, crep); + break; + case OSSL_CMP_PKISTATUS_keyUpdateWarning: + if (bodytype != OSSL_CMP_PKIBODY_KUR) { + CMPerr(0, CMP_R_ENCOUNTERED_KEYUPDATEWARNING); + goto err; + } + crt = ossl_cmp_certresponse_get1_certificate(privkey, crep); + break; + default: + ossl_cmp_log1(ERROR, ctx, + "received unsupported PKIStatus %d for certificate", + ctx->status); + CMPerr(0, CMP_R_UNKNOWN_PKISTATUS); + goto err; + } + if (crt == NULL) /* according to PKIStatus, we can expect a cert */ + CMPerr(0, CMP_R_CERTIFICATE_NOT_FOUND); + + return crt; + + err: + if (OSSL_CMP_CTX_snprint_PKIStatus(ctx, buf, sizeof(buf)) != NULL) + ERR_add_error_data(1, buf); + return NULL; +} + +/*- + * Callback fn validating that the new certificate can be verified, using + * ctx->certConf_cb_arg, which has been initialized using opt_out_trusted, and + * ctx->untrusted_certs, which at this point already contains ctx->extraCertsIn. + * Returns 0 on acceptance, else a bit field reflecting PKIFailureInfo. + * Quoting from RFC 4210 section 5.1. Overall PKI Message: + * The extraCerts field can contain certificates that may be useful to + * the recipient. For example, this can be used by a CA or RA to + * present an end entity with certificates that it needs to verify its + * own new certificate (if, for example, the CA that issued the end + * entity's certificate is not a root CA for the end entity). Note that + * this field does not necessarily contain a certification path; the + * recipient may have to sort, select from, or otherwise process the + * extra certificates in order to use them. + * Note: While often handy, there is no hard requirement by CMP that + * an EE must be able to validate the certificates it gets enrolled. + */ +int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info, + const char **text) +{ + X509_STORE *out_trusted = OSSL_CMP_CTX_get_certConf_cb_arg(ctx); + (void)text; /* make (artificial) use of var to prevent compiler warning */ + + if (fail_info != 0) /* accept any error flagged by CMP core library */ + return fail_info; + + if (out_trusted != NULL + && !OSSL_CMP_validate_cert_path(ctx, out_trusted, cert)) + fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_incorrectData; + + return fail_info; +} + +/*- + * Perform the generic handling of certificate responses for IR/CR/KUR/P10CR. + * Returns -1 on receiving pollRep if sleep == 0, setting the checkAfter value. + * Returns 1 on success and provides the received PKIMESSAGE in *resp. + * Returns 0 on error (which includes the case that timeout has been reached). + * Regardless of success, caller is responsible for freeing *resp (unless NULL). + */ +static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid, + OSSL_CMP_MSG **resp, int *checkAfter, + int req_type, int expected_type) +{ + EVP_PKEY *rkey = OSSL_CMP_CTX_get0_newPkey(ctx /* may be NULL */, 0); + int fail_info = 0; /* no failure */ + const char *txt = NULL; + OSSL_CMP_CERTREPMESSAGE *crepmsg; + OSSL_CMP_CERTRESPONSE *crep; + X509 *cert; + char *subj = NULL; + int ret = 1; + + retry: + crepmsg = (*resp)->body->value.ip; /* same for cp and kup */ + if (sk_OSSL_CMP_CERTRESPONSE_num(crepmsg->response) > 1) { + CMPerr(0, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED); + return 0; + } + /* TODO: handle potentially multiple CertResponses in CertRepMsg */ + crep = ossl_cmp_certrepmessage_get0_certresponse(crepmsg, rid); + if (crep == NULL) + return 0; + if (!save_statusInfo(ctx, crep->status)) + return 0; + if (rid == -1) { + /* for OSSL_CMP_PKIBODY_P10CR learn CertReqId from response */ + rid = ossl_cmp_asn1_get_int(crep->certReqId); + if (rid == -1) { + CMPerr(0, CMP_R_BAD_REQUEST_ID); + return 0; + } + } + + if (ossl_cmp_pkisi_get_status(crep->status) == OSSL_CMP_PKISTATUS_waiting) { + OSSL_CMP_MSG_free(*resp); + *resp = NULL; + if ((ret = poll_for_response(ctx, sleep, rid, resp, checkAfter)) != 0) { + if (ret == -1) /* at this point implies sleep == 0 */ + return ret; /* waiting */ + goto retry; /* got ip/cp/kup, which may still indicate 'waiting' */ + } else { + CMPerr(0, CMP_R_POLLING_FAILED); + return 0; + } + } + + cert = get1_cert_status(ctx, (*resp)->body->type, crep); + if (cert == NULL) { + ERR_add_error_data(1, "; cannot extract certificate from response"); + return 0; + } + if (!ossl_cmp_ctx_set0_newCert(ctx, cert)) + return 0; + + /* + * if the CMP server returned certificates in the caPubs field, copy them + * to the context so that they can be retrieved if necessary + */ + if (crepmsg->caPubs != NULL + && !ossl_cmp_ctx_set1_caPubs(ctx, crepmsg->caPubs)) + return 0; + + /* copy received extraCerts to ctx->extraCertsIn so they can be retrieved */ + if (!ossl_cmp_ctx_set1_extraCertsIn(ctx, (*resp)->extraCerts)) + return 0; + + subj = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0); + if (rkey != NULL + /* X509_check_private_key() also works if rkey is just public key */ + && !(X509_check_private_key(ctx->newCert, rkey))) { + fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_incorrectData; + txt = "public key in new certificate does not match our enrollment key"; + /*- + * not callling (void)ossl_cmp_exchange_error(ctx, + * OSSL_CMP_PKISTATUS_rejection, fail_info, txt) + * not throwing CMP_R_CERTIFICATE_NOT_ACCEPTED with txt + * not returning 0 + * since we better leave this for any ctx->certConf_cb to decide + */ + } + + /* + * Execute the certification checking callback function possibly set in ctx, + * which can determine whether to accept a newly enrolled certificate. + * It may overrule the pre-decision reflected in 'fail_info' and '*txt'. + */ + if (ctx->certConf_cb + && (fail_info = ctx->certConf_cb(ctx, ctx->newCert, + fail_info, &txt)) != 0) { + if (txt == NULL) + txt = "CMP client application did not accept it"; + } + if (fail_info != 0) /* immediately log error before any certConf exchange */ + ossl_cmp_log1(ERROR, ctx, + "rejecting newly enrolled cert with subject: %s", subj); + + /* + * TODO: better move certConf exchange to do_certreq_seq() such that + * also more low-level errors with CertReqMessages get reported to server + */ + if (!ctx->disableConfirm + && !ossl_cmp_hdr_has_implicitConfirm((*resp)->header)) { + if (!ossl_cmp_exchange_certConf(ctx, fail_info, txt)) + ret = 0; + } + + /* not throwing failure earlier as transfer_cb may call ERR_clear_error() */ + if (fail_info != 0) { + CMPerr(0, CMP_R_CERTIFICATE_NOT_ACCEPTED); + ERR_add_error_data(2, "rejecting newly enrolled cert with subject: ", + subj); + if (txt != NULL) + ERR_add_error_txt("; ", txt); + ret = 0; + } + OPENSSL_free(subj); + return ret; +} + +int OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type, int *checkAfter) +{ + OSSL_CMP_MSG *req = NULL; + OSSL_CMP_MSG *rep = NULL; + int is_p10 = req_type == OSSL_CMP_PKIBODY_P10CR; + int rid = is_p10 ? -1 : OSSL_CMP_CERTREQID; + int rep_type = is_p10 ? OSSL_CMP_PKIBODY_CP : req_type + 1; + int res = 0; + + if (ctx == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return 0; + } + + if (ctx->status != OSSL_CMP_PKISTATUS_waiting) { /* not polling already */ + ctx->status = -1; + if (!ossl_cmp_ctx_set0_newCert(ctx, NULL)) + return 0; + + if (ctx->total_timeout > 0) /* else ctx->end_time is not used */ + ctx->end_time = time(NULL) + ctx->total_timeout; + + req = ossl_cmp_certReq_new(ctx, req_type, 0 /* req_err */); + if (req == NULL) /* also checks if all necessary options are set */ + return 0; + + if (!send_receive_check(ctx, req, &rep, rep_type)) + goto err; + } else { + if (req_type < 0) + return ossl_cmp_exchange_error(ctx, OSSL_CMP_PKISTATUS_rejection, + 0 /* TODO better fail_info value? */, + "polling aborted", 0 /* errorCode */, + "by application"); + res = poll_for_response(ctx, 0 /* no sleep */, rid, &rep, checkAfter); + if (res <= 0) /* waiting or error */ + return res; + } + res = cert_response(ctx, 0 /* no sleep */, rid, &rep, checkAfter, + req_type, rep_type); + + err: + OSSL_CMP_MSG_free(req); + OSSL_CMP_MSG_free(rep); + return res; +} + +/*- + * Do the full sequence CR/IR/KUR/P10CR, CP/IP/KUP/CP, + * certConf, PKIconf, and polling if required. + * Will sleep as long as indicated by the server (according to checkAfter). + * All enrollment options need to be present in the context. + * TODO: another function to request two certificates at once should be created. + * Returns pointer to received certificate, or NULL if none was received. + */ +static X509 *do_certreq_seq(OSSL_CMP_CTX *ctx, int req_type, int req_err, + int rep_type) +{ + OSSL_CMP_MSG *req = NULL; + OSSL_CMP_MSG *rep = NULL; + int rid = (req_type == OSSL_CMP_PKIBODY_P10CR) ? -1 : OSSL_CMP_CERTREQID; + X509 *result = NULL; + + if (ctx == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return NULL; + } + ctx->status = -1; + if (!ossl_cmp_ctx_set0_newCert(ctx, NULL)) + return NULL; + + if (ctx->total_timeout > 0) /* else ctx->end_time is not used */ + ctx->end_time = time(NULL) + ctx->total_timeout; + + /* OSSL_CMP_certreq_new() also checks if all necessary options are set */ + if ((req = ossl_cmp_certReq_new(ctx, req_type, req_err)) == NULL) + goto err; + + if (!send_receive_check(ctx, req, &rep, rep_type)) + goto err; + + if (cert_response(ctx, 1 /* sleep */, rid, &rep, NULL, req_type, rep_type) + <= 0) + goto err; + + result = ctx->newCert; + err: + OSSL_CMP_MSG_free(req); + OSSL_CMP_MSG_free(rep); + return result; +} + +X509 *OSSL_CMP_exec_IR_ses(OSSL_CMP_CTX *ctx) +{ + return do_certreq_seq(ctx, OSSL_CMP_PKIBODY_IR, + CMP_R_ERROR_CREATING_IR, OSSL_CMP_PKIBODY_IP); +} + +X509 *OSSL_CMP_exec_CR_ses(OSSL_CMP_CTX *ctx) +{ + return do_certreq_seq(ctx, OSSL_CMP_PKIBODY_CR, + CMP_R_ERROR_CREATING_CR, OSSL_CMP_PKIBODY_CP); +} + +X509 *OSSL_CMP_exec_KUR_ses(OSSL_CMP_CTX *ctx) +{ + return do_certreq_seq(ctx, OSSL_CMP_PKIBODY_KUR, + CMP_R_ERROR_CREATING_KUR, OSSL_CMP_PKIBODY_KUP); +} + +X509 *OSSL_CMP_exec_P10CR_ses(OSSL_CMP_CTX *ctx) +{ + return do_certreq_seq(ctx, OSSL_CMP_PKIBODY_P10CR, + CMP_R_ERROR_CREATING_P10CR, OSSL_CMP_PKIBODY_CP); +} + +X509 *OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx) +{ + OSSL_CMP_MSG *rr = NULL; + OSSL_CMP_MSG *rp = NULL; + const int num_RevDetails = 1; + const int rsid = OSSL_CMP_REVREQSID; + OSSL_CMP_REVREPCONTENT *rrep = NULL; + OSSL_CMP_PKISI *si = NULL; + char buf[OSSL_CMP_PKISI_BUFLEN]; + X509 *result = NULL; + + if (ctx == NULL) { + CMPerr(0, CMP_R_INVALID_ARGS); + return 0; + } + ctx->status = -1; + + /* OSSL_CMP_rr_new() also checks if all necessary options are set */ + if ((rr = ossl_cmp_rr_new(ctx)) == NULL) + goto end; + + if (!send_receive_check(ctx, rr, &rp, OSSL_CMP_PKIBODY_RP)) + goto end; + + rrep = rp->body->value.rp; + if (sk_OSSL_CMP_PKISI_num(rrep->status) != num_RevDetails) { + CMPerr(0, CMP_R_WRONG_RP_COMPONENT_COUNT); + goto end; + } + + /* evaluate PKIStatus field */ + si = ossl_cmp_revrepcontent_get_pkisi(rrep, rsid); + if (!save_statusInfo(ctx, si)) + goto err; + switch (ossl_cmp_pkisi_get_status(si)) { + case OSSL_CMP_PKISTATUS_accepted: + ossl_cmp_info(ctx, "revocation accepted (PKIStatus=accepted)"); + result = ctx->oldCert; + break; + case OSSL_CMP_PKISTATUS_grantedWithMods: + ossl_cmp_info(ctx, "revocation accepted (PKIStatus=grantedWithMods)"); + result = ctx->oldCert; + break; + case OSSL_CMP_PKISTATUS_rejection: + CMPerr(0, CMP_R_REQUEST_REJECTED_BY_SERVER); + goto err; + case OSSL_CMP_PKISTATUS_revocationWarning: + ossl_cmp_info(ctx, "revocation accepted (PKIStatus=revocationWarning)"); + result = ctx->oldCert; + break; + case OSSL_CMP_PKISTATUS_revocationNotification: + /* interpretation as warning or error depends on CA */ + ossl_cmp_warn(ctx, + "revocation accepted (PKIStatus=revocationNotification)"); + result = ctx->oldCert; + break; + case OSSL_CMP_PKISTATUS_waiting: + case OSSL_CMP_PKISTATUS_keyUpdateWarning: + CMPerr(0, CMP_R_UNEXPECTED_PKISTATUS); + goto err; + default: + CMPerr(0, CMP_R_UNKNOWN_PKISTATUS); + goto err; + } + + /* check any present CertId in optional revCerts field */ + if (rrep->revCerts != NULL) { + OSSL_CRMF_CERTID *cid; + OSSL_CRMF_CERTTEMPLATE *tmpl = + sk_OSSL_CMP_REVDETAILS_value(rr->body->value.rr, rsid)->certDetails; + const X509_NAME *issuer = OSSL_CRMF_CERTTEMPLATE_get0_issuer(tmpl); + ASN1_INTEGER *serial = OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(tmpl); + + if (sk_OSSL_CRMF_CERTID_num(rrep->revCerts) != num_RevDetails) { + CMPerr(0, CMP_R_WRONG_RP_COMPONENT_COUNT); + result = NULL; + goto err; + } + if ((cid = ossl_cmp_revrepcontent_get_CertId(rrep, rsid)) == NULL) { + result = NULL; + goto err; + } + if (X509_NAME_cmp(issuer, OSSL_CRMF_CERTID_get0_issuer(cid)) != 0) { + CMPerr(0, CMP_R_WRONG_CERTID_IN_RP); + result = NULL; + goto err; + } + if (ASN1_INTEGER_cmp(serial, + OSSL_CRMF_CERTID_get0_serialNumber(cid)) != 0) { + CMPerr(0, CMP_R_WRONG_SERIAL_IN_RP); + result = NULL; + goto err; + } + } + + /* check number of any optionally present crls */ + if (rrep->crls != NULL && sk_X509_CRL_num(rrep->crls) != num_RevDetails) { + CMPerr(0, CMP_R_WRONG_RP_COMPONENT_COUNT); + result = NULL; + goto err; + } + + err: + if (result == NULL + && OSSL_CMP_CTX_snprint_PKIStatus(ctx, buf, sizeof(buf)) != NULL) + ERR_add_error_data(1, buf); + + end: + OSSL_CMP_MSG_free(rr); + OSSL_CMP_MSG_free(rp); + return result; +} + +STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx) +{ + OSSL_CMP_MSG *genm; + OSSL_CMP_MSG *genp = NULL; + STACK_OF(OSSL_CMP_ITAV) *rcvd_itavs = NULL; + + if (ctx == NULL) { + CMPerr(0, CMP_R_INVALID_ARGS); + return 0; + } + + if ((genm = ossl_cmp_genm_new(ctx)) == NULL) + goto err; + + if (!send_receive_check(ctx, genm, &genp, OSSL_CMP_PKIBODY_GENP)) + goto err; + + /* received stack of itavs not to be freed with the genp */ + rcvd_itavs = genp->body->value.genp; + genp->body->value.genp = NULL; + + err: + OSSL_CMP_MSG_free(genm); + OSSL_CMP_MSG_free(genp); + + return rcvd_itavs; /* recv_itavs == NULL indicates an error */ +} diff --git a/crypto/cmp/cmp_ctx.c b/crypto/cmp/cmp_ctx.c index 714157a9..9a252cca 100644 --- a/crypto/cmp/cmp_ctx.c +++ b/crypto/cmp/cmp_ctx.c @@ -20,9 +20,7 @@ #include #include -/* - * Get current certificate store containing trusted root CA certs - */ +/* Get current certificate store containing trusted root CA certs */ X509_STORE *OSSL_CMP_CTX_get0_trustedStore(const OSSL_CMP_CTX *ctx) { if (ctx == NULL) { @@ -36,7 +34,6 @@ X509_STORE *OSSL_CMP_CTX_get0_trustedStore(const OSSL_CMP_CTX *ctx) * Set certificate store containing trusted (root) CA certs and possibly CRLs * and a cert verification callback function used for CMP server authentication. * Any already existing store entry is freed. Given NULL, the entry is reset. - * returns 1 on success, 0 on error */ int OSSL_CMP_CTX_set0_trustedStore(OSSL_CMP_CTX *ctx, X509_STORE *store) { @@ -49,9 +46,7 @@ int OSSL_CMP_CTX_set0_trustedStore(OSSL_CMP_CTX *ctx, X509_STORE *store) return 1; } -/* - * Get current list of non-trusted intermediate certs - */ +/* Get current list of non-trusted intermediate certs */ STACK_OF(X509) *OSSL_CMP_CTX_get0_untrusted_certs(const OSSL_CMP_CTX *ctx) { if (ctx == NULL) { @@ -64,7 +59,6 @@ STACK_OF(X509) *OSSL_CMP_CTX_get0_untrusted_certs(const OSSL_CMP_CTX *ctx) /* * Set untrusted certificates for path construction in authentication of * the CMP server and potentially others (TLS server, newly enrolled cert). - * returns 1 on success, 0 on error */ int OSSL_CMP_CTX_set1_untrusted_certs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *certs) { @@ -101,9 +95,7 @@ OSSL_CMP_CTX *OSSL_CMP_CTX_new(void) ctx->status = -1; ctx->failInfoCode = -1; - ctx->serverPort = OSSL_CMP_DEFAULT_PORT; - ctx->proxyPort = OSSL_CMP_DEFAULT_PORT; - ctx->msgtimeout = 2 * 60; + ctx->msg_timeout = 2 * 60; if ((ctx->untrusted_certs = sk_X509_new_null()) == NULL) goto err; @@ -125,9 +117,7 @@ OSSL_CMP_CTX *OSSL_CMP_CTX_new(void) return NULL; } -/* - * Prepare the OSSL_CMP_CTX for next use, partly re-initializing OSSL_CMP_CTX - */ +/* Prepare the OSSL_CMP_CTX for next use, partly re-initializing OSSL_CMP_CTX */ int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx) { if (ctx == NULL) { @@ -148,17 +138,16 @@ int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx) && ossl_cmp_ctx_set1_recipNonce(ctx, NULL); } -/* - * Frees OSSL_CMP_CTX variables allocated in OSSL_CMP_CTX_new() - */ +/* Frees OSSL_CMP_CTX variables allocated in OSSL_CMP_CTX_new() */ void OSSL_CMP_CTX_free(OSSL_CMP_CTX *ctx) { if (ctx == NULL) return; OPENSSL_free(ctx->serverPath); - OPENSSL_free(ctx->serverName); - OPENSSL_free(ctx->proxyName); + OPENSSL_free(ctx->server); + OPENSSL_free(ctx->proxy); + OPENSSL_free(ctx->no_proxy); X509_free(ctx->srvCert); X509_free(ctx->validatedSrvCert); @@ -252,12 +241,8 @@ int ossl_cmp_ctx_set0_validatedSrvCert(OSSL_CMP_CTX *ctx, X509 *cert) return 1; } -/* - * Set callback function for checking if the cert is ok or should - * it be rejected. - * Returns 1 on success, 0 on error - */ -int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_certConf_cb_t cb) +/* Set callback function for checking if the cert is ok or should be rejected */ +int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_certConf_cb_t cb) { if (ctx == NULL) { CMPerr(0, CMP_R_NULL_ARGUMENT); @@ -270,7 +255,6 @@ int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_certConf_cb_t cb) /* * Set argument, respectively a pointer to a structure containing arguments, * optionally to be used by the certConf callback. - * Returns 1 on success, 0 on error */ int OSSL_CMP_CTX_set_certConf_cb_arg(OSSL_CMP_CTX *ctx, void *arg) { @@ -380,11 +364,8 @@ int ossl_cmp_print_log(OSSL_CMP_severity level, const OSSL_CMP_CTX *ctx, return res; } -/* - * Set a callback function for error reporting and logging messages. - * Returns 1 on success, 0 on error - */ -int OSSL_CMP_CTX_set_log_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_log_cb_t cb) +/* Set a callback function for error reporting and logging messages */ +int OSSL_CMP_CTX_set_log_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_log_cb_t cb) { if (ctx == NULL) { CMPerr(0, CMP_R_NULL_ARGUMENT); @@ -411,7 +392,6 @@ void OSSL_CMP_CTX_print_errors(OSSL_CMP_CTX *ctx) /* * Set or clear the reference value to be used for identification * (i.e., the user name) when using PBMAC. - * Returns 1 on success, 0 on error */ int OSSL_CMP_CTX_set1_referenceValue(OSSL_CMP_CTX *ctx, const unsigned char *ref, int len) @@ -424,10 +404,7 @@ int OSSL_CMP_CTX_set1_referenceValue(OSSL_CMP_CTX *ctx, len); } -/* - * Set or clear the password to be used for protecting messages with PBMAC. - * Returns 1 on success, 0 on error - */ +/* Set or clear the password to be used for protecting messages with PBMAC */ int OSSL_CMP_CTX_set1_secretValue(OSSL_CMP_CTX *ctx, const unsigned char *sec, const int len) { @@ -465,7 +442,6 @@ STACK_OF(X509) *OSSL_CMP_CTX_get1_extraCertsIn(const OSSL_CMP_CTX *ctx) /* * Copies any given stack of inbound X509 certificates to extraCertsIn * of the OSSL_CMP_CTX structure so that they may be retrieved later. - * Returns 1 on success, 0 on error. */ int ossl_cmp_ctx_set1_extraCertsIn(OSSL_CMP_CTX *ctx, STACK_OF(X509) *extraCertsIn) @@ -483,7 +459,6 @@ int ossl_cmp_ctx_set1_extraCertsIn(OSSL_CMP_CTX *ctx, /* * Duplicate and set the given stack as the new stack of X509 * certificates to send out in the extraCerts field. - * Returns 1 on success, 0 on error */ int OSSL_CMP_CTX_set1_extraCertsOut(OSSL_CMP_CTX *ctx, STACK_OF(X509) *extraCertsOut) @@ -503,7 +478,6 @@ int OSSL_CMP_CTX_set1_extraCertsOut(OSSL_CMP_CTX *ctx, /* * Add the given policy info object * to the X509_EXTENSIONS of the requested certificate template. - * Returns 1 on success, 0 on error. */ int OSSL_CMP_CTX_push0_policy(OSSL_CMP_CTX *ctx, POLICYINFO *pinfo) { @@ -519,9 +493,7 @@ int OSSL_CMP_CTX_push0_policy(OSSL_CMP_CTX *ctx, POLICYINFO *pinfo) return sk_POLICYINFO_push(ctx->policies, pinfo); } -/* - * Add an ITAV for geninfo of the PKI message header - */ +/* Add an ITAV for geninfo of the PKI message header */ int OSSL_CMP_CTX_push0_geninfo_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav) { if (ctx == NULL) { @@ -531,9 +503,7 @@ int OSSL_CMP_CTX_push0_geninfo_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav) return OSSL_CMP_ITAV_push0_stack_item(&ctx->geninfo_ITAVs, itav); } -/* - * Add an itav for the body of outgoing general messages - */ +/* Add an itav for the body of outgoing general messages */ int OSSL_CMP_CTX_push0_genm_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav) { if (ctx == NULL) { @@ -562,7 +532,6 @@ STACK_OF(X509) *OSSL_CMP_CTX_get1_caPubs(const OSSL_CMP_CTX *ctx) /* * Duplicate and copy the given stack of certificates to the given * OSSL_CMP_CTX structure so that they may be retrieved later. - * Returns 1 on success, 0 on error */ int ossl_cmp_ctx_set1_caPubs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *caPubs) { @@ -614,39 +583,25 @@ int OSSL_CMP_CTX_set1_##FIELD(OSSL_CMP_CTX *ctx, TYPE *val) \ * Pins the server certificate to be directly trusted (even if it is expired) * for verifying response messages. * Cert pointer is not consumed. It may be NULL to clear the entry. - * Returns 1 on success, 0 on error */ DEFINE_OSSL_CMP_CTX_set1_up_ref(srvCert, X509) -/* - * Set the X509 name of the recipient. Set in the PKIHeader. - * returns 1 on success, 0 on error - */ +/* Set the X509 name of the recipient. Set in the PKIHeader */ DEFINE_OSSL_CMP_CTX_set1(recipient, X509_NAME) -/* - * Store the X509 name of the expected sender in the PKIHeader of responses. - * Returns 1 on success, 0 on error - */ +/* Store the X509 name of the expected sender in the PKIHeader of responses */ DEFINE_OSSL_CMP_CTX_set1(expected_sender, X509_NAME) -/* - * Set the X509 name of the issuer. Set in the PKIHeader. - * Returns 1 on success, 0 on error - */ +/* Set the X509 name of the issuer. Set in the PKIHeader */ DEFINE_OSSL_CMP_CTX_set1(issuer, X509_NAME) /* * Set the subject name that will be placed in the certificate * request. This will be the subject name on the received certificate. - * Returns 1 on success, 0 on error */ DEFINE_OSSL_CMP_CTX_set1(subjectName, X509_NAME) -/* - * Set the X.509v3 certificate request extensions to be used in IR/CR/KUR. - * Returns 1 on success, 0 on error - */ +/* Set the X.509v3 certificate request extensions to be used in IR/CR/KUR */ int OSSL_CMP_CTX_set0_reqExtensions(OSSL_CMP_CTX *ctx, X509_EXTENSIONS *exts) { if (ctx == NULL) { @@ -680,7 +635,6 @@ int OSSL_CMP_CTX_reqExtensions_have_SAN(OSSL_CMP_CTX *ctx) /* * Add a GENERAL_NAME structure that will be added to the CRMF * request's extensions field to request subject alternative names. - * Returns 1 on success, 0 on error */ int OSSL_CMP_CTX_push1_subjectAltName(OSSL_CMP_CTX *ctx, const GENERAL_NAME *name) @@ -712,7 +666,6 @@ int OSSL_CMP_CTX_push1_subjectAltName(OSSL_CMP_CTX *ctx, /* * Set our own client certificate, used for example in KUR and when * doing the IR with existing certificate. - * Returns 1 on success, 0 on error */ DEFINE_OSSL_CMP_CTX_set1_up_ref(clCert, X509) @@ -721,19 +674,14 @@ DEFINE_OSSL_CMP_CTX_set1_up_ref(clCert, X509) * or the certificate to be revoked in RR, respectively. * Also used as reference cert (defaulting to clCert) for deriving subject DN * and SANs. Its issuer is used as default recipient in the CMP message header. - * Returns 1 on success, 0 on error */ DEFINE_OSSL_CMP_CTX_set1_up_ref(oldCert, X509) -/* - * Set the PKCS#10 CSR to be sent in P10CR. - * Returns 1 on success, 0 on error - */ +/* Set the PKCS#10 CSR to be sent in P10CR */ DEFINE_OSSL_CMP_CTX_set1(p10CSR, X509_REQ) /* - * Sets the (newly received in IP/KUP/CP) certificate in the context. - * Returns 1 on success, 0 on error + * Set the (newly received in IP/KUP/CP) certificate in the context. * TODO: this only permits for one cert to be enrolled at a time. */ int ossl_cmp_ctx_set0_newCert(OSSL_CMP_CTX *ctx, X509 *cert) @@ -759,16 +707,10 @@ X509 *OSSL_CMP_CTX_get0_newCert(const OSSL_CMP_CTX *ctx) return ctx->newCert; } -/* - * Set the client's current private key. - * Returns 1 on success, 0 on error - */ +/* Set the client's current private key */ DEFINE_OSSL_CMP_CTX_set1_up_ref(pkey, EVP_PKEY) -/* - * Set new key pair. Used e.g. when doing Key Update. - * Returns 1 on success, 0 on error - */ +/* Set new key pair. Used e.g. when doing Key Update */ int OSSL_CMP_CTX_set0_newPkey(OSSL_CMP_CTX *ctx, int priv, EVP_PKEY *pkey) { if (ctx == NULL) { @@ -782,9 +724,7 @@ int OSSL_CMP_CTX_set0_newPkey(OSSL_CMP_CTX *ctx, int priv, EVP_PKEY *pkey) return 1; } -/* - * gets the private/public key to use for certificate enrollment, NULL on error - */ +/* Get the private/public key to use for cert enrollment, or NULL on error */ EVP_PKEY *OSSL_CMP_CTX_get0_newPkey(const OSSL_CMP_CTX *ctx, int priv) { if (ctx == NULL) { @@ -799,10 +739,7 @@ EVP_PKEY *OSSL_CMP_CTX_get0_newPkey(const OSSL_CMP_CTX *ctx, int priv) return ctx->pkey; /* may be NULL */ } -/* - * Sets the given transactionID to the context. - * Returns 1 on success, 0 on error - */ +/* Set the given transactionID to the context */ int OSSL_CMP_CTX_set1_transactionID(OSSL_CMP_CTX *ctx, const ASN1_OCTET_STRING *id) { @@ -813,11 +750,7 @@ int OSSL_CMP_CTX_set1_transactionID(OSSL_CMP_CTX *ctx, return ossl_cmp_asn1_octet_string_set1(&ctx->transactionID, id); } -/* - * sets the given nonce to be used for the recipNonce in the next message to be - * created. - * returns 1 on success, 0 on error - */ +/* Set the nonce to be used for the recipNonce in the message created next */ int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx, const ASN1_OCTET_STRING *nonce) { @@ -826,10 +759,7 @@ int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx, return ossl_cmp_asn1_octet_string_set1(&ctx->recipNonce, nonce); } -/* - * Stores the given nonce as the last senderNonce sent out. - * Returns 1 on success, 0 on error - */ +/* Stores the given nonce as the last senderNonce sent out */ int OSSL_CMP_CTX_set1_senderNonce(OSSL_CMP_CTX *ctx, const ASN1_OCTET_STRING *nonce) { @@ -840,36 +770,16 @@ int OSSL_CMP_CTX_set1_senderNonce(OSSL_CMP_CTX *ctx, return ossl_cmp_asn1_octet_string_set1(&ctx->senderNonce, nonce); } -/* - * Set the host name of the (HTTP) proxy server to use for all connections - * returns 1 on success, 0 on error - */ -DEFINE_OSSL_CMP_CTX_set1(proxyName, char) +/* Set the proxy server to use for HTTP(S) connections */ +DEFINE_OSSL_CMP_CTX_set1(proxy, char) -/* - * Set the (HTTP) host name of the CA server. - * Returns 1 on success, 0 on error - */ -DEFINE_OSSL_CMP_CTX_set1(serverName, char) +/* Set the (HTTP) host name of the CMP server */ +DEFINE_OSSL_CMP_CTX_set1(server, char) -/* - * Sets the (HTTP) proxy port to be used. - * Returns 1 on success, 0 on error - */ -int OSSL_CMP_CTX_set_proxyPort(OSSL_CMP_CTX *ctx, int port) -{ - if (ctx == NULL) { - CMPerr(0, CMP_R_NULL_ARGUMENT); - return 0; - } - ctx->proxyPort = port; - return 1; -} +/* Set the server exclusion list of the HTTP proxy server */ +DEFINE_OSSL_CMP_CTX_set1(no_proxy, char) -/* - * sets the http connect/disconnect callback function to be used for HTTP(S) - * returns 1 on success, 0 on error - */ +/* Set the http connect/disconnect callback function to be used for HTTP(S) */ int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, OSSL_HTTP_bio_cb_t cb) { if (ctx == NULL) { @@ -880,10 +790,7 @@ int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, OSSL_HTTP_bio_cb_t cb) return 1; } -/* - * Set argument optionally to be used by the http connect/disconnect callback. - * Returns 1 on success, 0 on error - */ +/* Set argument optionally to be used by the http connect/disconnect callback */ int OSSL_CMP_CTX_set_http_cb_arg(OSSL_CMP_CTX *ctx, void *arg) { if (ctx == NULL) { @@ -907,11 +814,8 @@ void *OSSL_CMP_CTX_get_http_cb_arg(const OSSL_CMP_CTX *ctx) return ctx->http_cb_arg; } -/* - * Set callback function for sending CMP request and receiving response. - * Returns 1 on success, 0 on error - */ -int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_transfer_cb_t cb) +/* Set callback function for sending CMP request and receiving response */ +int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_transfer_cb_t cb) { if (ctx == NULL) { CMPerr(0, CMP_R_NULL_ARGUMENT); @@ -921,10 +825,7 @@ int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_transfer_cb_t cb) return 1; } -/* - * Set argument optionally to be used by the transfer callback. - * Returns 1 on success, 0 on error - */ +/* Set argument optionally to be used by the transfer callback */ int OSSL_CMP_CTX_set_transfer_cb_arg(OSSL_CMP_CTX *ctx, void *arg) { if (ctx == NULL) { @@ -948,10 +849,7 @@ void *OSSL_CMP_CTX_get_transfer_cb_arg(const OSSL_CMP_CTX *ctx) return ctx->transfer_cb_arg; } -/* - * Sets the (HTTP) server port to be used. - * Returns 1 on success, 0 on error - */ +/** Set the HTTP server port to be used */ int OSSL_CMP_CTX_set_serverPort(OSSL_CMP_CTX *ctx, int port) { if (ctx == NULL) { @@ -962,16 +860,10 @@ int OSSL_CMP_CTX_set_serverPort(OSSL_CMP_CTX *ctx, int port) return 1; } -/* - * Sets the HTTP path to be used on the server (e.g "pkix/"). - * Returns 1 on success, 0 on error - */ +/* Set the HTTP path to be used on the server (e.g "pkix/") */ DEFINE_OSSL_CMP_CTX_set1(serverPath, char) -/* - * Set the failInfo error code as bit encoding in OSSL_CMP_CTX. - * Returns 1 on success, 0 on error - */ +/* Set the failInfo error code as bit encoding in OSSL_CMP_CTX */ int ossl_cmp_ctx_set_failInfoCode(OSSL_CMP_CTX *ctx, int fail_info) { if (!ossl_assert(ctx != NULL)) @@ -993,10 +885,7 @@ int OSSL_CMP_CTX_get_failInfoCode(const OSSL_CMP_CTX *ctx) return ctx->failInfoCode; } -/* - * Sets a Boolean or integer option of the context to the "val" arg. - * Returns 1 on success, 0 on error - */ +/* Set a Boolean or integer option of the context to the "val" arg */ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val) { int min_val; @@ -1010,7 +899,7 @@ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val) case OSSL_CMP_OPT_REVOCATION_REASON: min_val = OCSP_REVOKED_STATUS_NOSTATUS; break; - case OSSL_CMP_OPT_POPOMETHOD: + case OSSL_CMP_OPT_POPO_METHOD: min_val = OSSL_CRMF_POPO_NONE; break; default: @@ -1030,10 +919,10 @@ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val) } ctx->log_verbosity = val; break; - case OSSL_CMP_OPT_IMPLICITCONFIRM: + case OSSL_CMP_OPT_IMPLICIT_CONFIRM: ctx->implicitConfirm = val; break; - case OSSL_CMP_OPT_DISABLECONFIRM: + case OSSL_CMP_OPT_DISABLE_CONFIRM: ctx->disableConfirm = val; break; case OSSL_CMP_OPT_UNPROTECTED_SEND: @@ -1042,7 +931,7 @@ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val) case OSSL_CMP_OPT_UNPROTECTED_ERRORS: ctx->unprotectedErrors = val; break; - case OSSL_CMP_OPT_VALIDITYDAYS: + case OSSL_CMP_OPT_VALIDITY_DAYS: ctx->days = val; break; case OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT: @@ -1057,7 +946,7 @@ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val) case OSSL_CMP_OPT_IGNORE_KEYUSAGE: ctx->ignore_keyusage = val; break; - case OSSL_CMP_OPT_POPOMETHOD: + case OSSL_CMP_OPT_POPO_METHOD: if (val > OSSL_CRMF_POPO_KEYAGREE) { CMPerr(0, CMP_R_INVALID_ARGS); return 0; @@ -1073,11 +962,11 @@ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val) case OSSL_CMP_OPT_MAC_ALGNID: ctx->pbm_mac = val; break; - case OSSL_CMP_OPT_MSGTIMEOUT: - ctx->msgtimeout = val; + case OSSL_CMP_OPT_MSG_TIMEOUT: + ctx->msg_timeout = val; break; - case OSSL_CMP_OPT_TOTALTIMEOUT: - ctx->totaltimeout = val; + case OSSL_CMP_OPT_TOTAL_TIMEOUT: + ctx->total_timeout = val; break; case OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR: ctx->permitTAInExtraCertsForIR = val; @@ -1111,15 +1000,15 @@ int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt) switch (opt) { case OSSL_CMP_OPT_LOG_VERBOSITY: return ctx->log_verbosity; - case OSSL_CMP_OPT_IMPLICITCONFIRM: + case OSSL_CMP_OPT_IMPLICIT_CONFIRM: return ctx->implicitConfirm; - case OSSL_CMP_OPT_DISABLECONFIRM: + case OSSL_CMP_OPT_DISABLE_CONFIRM: return ctx->disableConfirm; case OSSL_CMP_OPT_UNPROTECTED_SEND: return ctx->unprotectedSend; case OSSL_CMP_OPT_UNPROTECTED_ERRORS: return ctx->unprotectedErrors; - case OSSL_CMP_OPT_VALIDITYDAYS: + case OSSL_CMP_OPT_VALIDITY_DAYS: return ctx->days; case OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT: return ctx->SubjectAltName_nodefault; @@ -1129,7 +1018,7 @@ int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt) return ctx->setPoliciesCritical; case OSSL_CMP_OPT_IGNORE_KEYUSAGE: return ctx->ignore_keyusage; - case OSSL_CMP_OPT_POPOMETHOD: + case OSSL_CMP_OPT_POPO_METHOD: return ctx->popoMethod; case OSSL_CMP_OPT_DIGEST_ALGNID: return ctx->digest; @@ -1137,10 +1026,10 @@ int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt) return ctx->pbm_owf; case OSSL_CMP_OPT_MAC_ALGNID: return ctx->pbm_mac; - case OSSL_CMP_OPT_MSGTIMEOUT: - return ctx->msgtimeout; - case OSSL_CMP_OPT_TOTALTIMEOUT: - return ctx->totaltimeout; + case OSSL_CMP_OPT_MSG_TIMEOUT: + return ctx->msg_timeout; + case OSSL_CMP_OPT_TOTAL_TIMEOUT: + return ctx->total_timeout; case OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR: return ctx->permitTAInExtraCertsForIR; case OSSL_CMP_OPT_REVOCATION_REASON: diff --git a/crypto/cmp/cmp_err.c b/crypto/cmp/cmp_err.c index f82ef9e3..0f06fb3b 100644 --- a/crypto/cmp/cmp_err.c +++ b/crypto/cmp/cmp_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -16,26 +16,44 @@ static const ERR_STRING_DATA CMP_str_reasons[] = { {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ALGORITHM_NOT_SUPPORTED), "algorithm not supported"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_BAD_CHECKAFTER_IN_POLLREP), + "bad checkafter in pollrep"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_BAD_REQUEST_ID), "bad request id"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTHASH_UNMATCHED), "certhash unmatched"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTID_NOT_FOUND), "certid not found"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTIFICATE_NOT_ACCEPTED), + "certificate not accepted"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTIFICATE_NOT_FOUND), "certificate not found"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTREQMSG_NOT_FOUND), + "certreqmsg not found"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTRESPONSE_NOT_FOUND), "certresponse not found"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERT_AND_KEY_DO_NOT_MATCH), "cert and key do not match"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CHECKAFTER_OUT_OF_RANGE), + "checkafter out of range"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CHECKING_PBM_NO_SECRET_AVAILABLE), + "checking pbm no secret available"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ENCOUNTERED_KEYUPDATEWARNING), + "encountered keyupdatewarning"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ENCOUNTERED_WAITING), + "encountered waiting"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CALCULATING_PROTECTION), "error calculating protection"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_CERTCONF), "error creating certconf"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_CERTREP), "error creating certrep"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_CR), "error creating cr"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_ERROR), "error creating error"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_GENM), "error creating genm"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_GENP), "error creating genp"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_IR), "error creating ir"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_KUR), "error creating kur"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_P10CR), "error creating p10cr"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_PKICONF), @@ -48,10 +66,14 @@ static const ERR_STRING_DATA CMP_str_reasons[] = { {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_RR), "error creating rr"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_PARSING_PKISTATUS), "error parsing pkistatus"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_PROCESSING_MESSAGE), + "error processing message"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_PROTECTING_MESSAGE), "error protecting message"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_SETTING_CERTHASH), "error setting certhash"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_UNEXPECTED_CERTCONF), + "error unexpected certconf"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_VALIDATING_PROTECTION), "error validating protection"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_EXTRACTING_PUBKEY), @@ -72,6 +94,10 @@ static const ERR_STRING_DATA CMP_str_reasons[] = { "missing sender identification"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_TRUST_STORE), "missing trust store"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED), + "multiple requests not supported"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED), + "multiple responses not supported"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MULTIPLE_SAN_SOURCES), "multiple san sources"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_NO_STDIO), "no stdio"}, @@ -81,23 +107,32 @@ static const ERR_STRING_DATA CMP_str_reasons[] = { {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_PKIBODY_ERROR), "pkibody error"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_PKISTATUSINFO_NOT_FOUND), "pkistatusinfo not found"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_POLLING_FAILED), "polling failed"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_POTENTIALLY_INVALID_CERTIFICATE), "potentially invalid certificate"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_RECEIVED_ERROR), "received error"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_RECIPNONCE_UNMATCHED), "recipnonce unmatched"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_REQUEST_NOT_ACCEPTED), "request not accepted"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_REQUEST_REJECTED_BY_SERVER), + "request rejected by server"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED), "sender generalname type not supported"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG), "srvcert does not validate msg"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TOTAL_TIMEOUT), "total timeout"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TRANSACTIONID_UNMATCHED), "transactionid unmatched"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TRANSFER_ERROR), "transfer error"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKIBODY), "unexpected pkibody"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKISTATUS), + "unexpected pkistatus"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PVNO), "unexpected pvno"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_ALGORITHM_ID), "unknown algorithm id"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_CERT_TYPE), "unknown cert type"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_PKISTATUS), "unknown pkistatus"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_ALGORITHM), "unsupported algorithm"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_KEY_TYPE), @@ -106,7 +141,11 @@ static const ERR_STRING_DATA CMP_str_reasons[] = { "unsupported protection alg dhbasedmac"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_ALGORITHM_OID), "wrong algorithm oid"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_CERTID_IN_RP), "wrong certid in rp"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_PBM_VALUE), "wrong pbm value"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_RP_COMPONENT_COUNT), + "wrong rp component count"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_SERIAL_IN_RP), "wrong serial in rp"}, {0, NULL} }; diff --git a/crypto/cmp/cmp_hdr.c b/crypto/cmp/cmp_hdr.c index 29f477f1..4c213aa8 100644 --- a/crypto/cmp/cmp_hdr.c +++ b/crypto/cmp/cmp_hdr.c @@ -63,31 +63,42 @@ ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr) return hdr->recipNonce; } +int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name) +{ + X509_NAME *null = X509_NAME_new(); + int res = name == NULL || null == NULL + || (name->type == GEN_DIRNAME + && X509_NAME_cmp(name->d.directoryName, null) == 0); + + X509_NAME_free(null); + return res; +} + /* assign to *tgt a copy of src (which may be NULL to indicate an empty DN) */ static int set1_general_name(GENERAL_NAME **tgt, const X509_NAME *src) { - GENERAL_NAME *gen; + GENERAL_NAME *name; if (!ossl_assert(tgt != NULL)) return 0; - if ((gen = GENERAL_NAME_new()) == NULL) + if ((name = GENERAL_NAME_new()) == NULL) goto err; - gen->type = GEN_DIRNAME; + name->type = GEN_DIRNAME; if (src == NULL) { /* NULL-DN */ - if ((gen->d.directoryName = X509_NAME_new()) == NULL) + if ((name->d.directoryName = X509_NAME_new()) == NULL) goto err; - } else if (!X509_NAME_set(&gen->d.directoryName, src)) { + } else if (!X509_NAME_set(&name->d.directoryName, src)) { goto err; } GENERAL_NAME_free(*tgt); - *tgt = gen; + *tgt = name; return 1; err: - GENERAL_NAME_free(gen); + GENERAL_NAME_free(name); return 0; } @@ -153,25 +164,6 @@ int ossl_cmp_hdr_set1_senderKID(OSSL_CMP_PKIHEADER *hdr, } /* push the given text string to the given PKIFREETEXT ft */ -int ossl_cmp_pkifreetext_push_str(OSSL_CMP_PKIFREETEXT *ft, const char *text) -{ - ASN1_UTF8STRING *utf8string; - - if (!ossl_assert(ft != NULL && text != NULL)) - return 0; - if ((utf8string = ASN1_UTF8STRING_new()) == NULL) - return 0; - if (!ASN1_STRING_set(utf8string, text, -1)) - goto err; - if (!sk_ASN1_UTF8STRING_push(ft, utf8string)) - goto err; - return 1; - - err: - ASN1_UTF8STRING_free(utf8string); - return 0; -} - int ossl_cmp_hdr_push0_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text) { if (!ossl_assert(hdr != NULL && text != NULL)) @@ -193,7 +185,8 @@ int ossl_cmp_hdr_push1_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text) && (hdr->freeText = sk_ASN1_UTF8STRING_new_null()) == NULL) return 0; - return ossl_cmp_pkifreetext_push_str(hdr->freeText, (char *)text->data); + return + ossl_cmp_sk_ASN1_UTF8STRING_push_str(hdr->freeText, (char *)text->data); } int ossl_cmp_hdr_generalInfo_push0_item(OSSL_CMP_PKIHEADER *hdr, @@ -205,7 +198,7 @@ int ossl_cmp_hdr_generalInfo_push0_item(OSSL_CMP_PKIHEADER *hdr, } int ossl_cmp_hdr_generalInfo_push1_items(OSSL_CMP_PKIHEADER *hdr, - STACK_OF(OSSL_CMP_ITAV) *itavs) + const STACK_OF(OSSL_CMP_ITAV) *itavs) { int i; OSSL_CMP_ITAV *itav; @@ -250,7 +243,7 @@ int ossl_cmp_hdr_set_implicitConfirm(OSSL_CMP_PKIHEADER *hdr) } /* return 1 if implicitConfirm in the generalInfo field of the header is set */ -int ossl_cmp_hdr_check_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr) +int ossl_cmp_hdr_has_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr) { int itavCount; int i; @@ -273,8 +266,8 @@ int ossl_cmp_hdr_check_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr) /* fill in all fields of the hdr according to the info given in ctx */ int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr) { - X509_NAME *sender; - X509_NAME *rcp = NULL; + const X509_NAME *sender; + const X509_NAME *rcp = NULL; if (!ossl_assert(ctx != NULL && hdr != NULL)) return 0; @@ -283,19 +276,12 @@ int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr) if (!ossl_cmp_hdr_set_pvno(hdr, OSSL_CMP_PVNO)) return 0; - sender = ctx->clCert != NULL ? - X509_get_subject_name(ctx->clCert) : ctx->subjectName; /* * The sender name is copied from the subject of the client cert, if any, - * or else from the the subject name provided for certification requests. - * As required by RFC 4210 section 5.1.1., if the sender name is not known - * to the client it set to NULL-DN. In this case for identification at least - * the senderKID must be set, which we take from any referenceValue given. + * or else from the subject name provided for certification requests. */ - if (sender == NULL && ctx->referenceValue == NULL) { - CMPerr(0, CMP_R_MISSING_SENDER_IDENTIFICATION); - return 0; - } + sender = ctx->clCert != NULL ? + X509_get_subject_name(ctx->clCert) : ctx->subjectName; if (!ossl_cmp_hdr_set1_sender(hdr, sender)) return 0; diff --git a/crypto/cmp/cmp_http.c b/crypto/cmp/cmp_http.c new file mode 100644 index 00000000..20164944 --- /dev/null +++ b/crypto/cmp/cmp_http.c @@ -0,0 +1,66 @@ +/* + * Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright Nokia 2007-2019 + * Copyright Siemens AG 2015-2019 + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#include +#include +#include "internal/sockets.h" + +#include "openssl/cmp.h" +#include "cmp_local.h" + +/* explicit #includes not strictly needed since implied by the above: */ +#include +#include +#include +#include +#include +#include +#include + +/* + * Send the PKIMessage req and on success return the response, else NULL. + * Any previous error queue entries will likely be removed by ERR_clear_error(). + */ +OSSL_CMP_MSG *OSSL_CMP_MSG_http_perform(OSSL_CMP_CTX *ctx, + const OSSL_CMP_MSG *req) +{ + char server_port[32] = { '\0' }; + STACK_OF(CONF_VALUE) *headers = NULL; + const char *const content_type_pkix = "application/pkixcmp"; + OSSL_CMP_MSG *res; + + if (ctx == NULL || req == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return NULL; + } + + if (!X509V3_add_value("Pragma", "no-cache", &headers)) + return NULL; + + if (ctx->serverPort != 0) + BIO_snprintf(server_port, sizeof(server_port), "%d", ctx->serverPort); + + res = (OSSL_CMP_MSG *) + OSSL_HTTP_post_asn1(ctx->server, server_port, ctx->serverPath, + OSSL_CMP_CTX_get_http_cb_arg(ctx) != NULL, + ctx->proxy, ctx->no_proxy, NULL, NULL, + ctx->http_cb, OSSL_CMP_CTX_get_http_cb_arg(ctx), + headers, content_type_pkix, + (ASN1_VALUE *)req, ASN1_ITEM_rptr(OSSL_CMP_MSG), + 0, 0, ctx->msg_timeout, content_type_pkix, + ASN1_ITEM_rptr(OSSL_CMP_MSG)); + + sk_CONF_VALUE_pop_free(headers, X509V3_conf_free); + return res; +} diff --git a/crypto/cmp/cmp_local.h b/crypto/cmp/cmp_local.h index 015a3d4e..c3a080f2 100644 --- a/crypto/cmp/cmp_local.h +++ b/crypto/cmp/cmp_local.h @@ -28,20 +28,20 @@ * this structure is used to store the context for CMP sessions */ struct ossl_cmp_ctx_st { - OSSL_cmp_log_cb_t log_cb; /* log callback for error/debug/etc. output */ + OSSL_CMP_log_cb_t log_cb; /* log callback for error/debug/etc. output */ OSSL_CMP_severity log_verbosity; /* level of verbosity of log output */ /* message transfer */ - OSSL_cmp_transfer_cb_t transfer_cb; /* default: OSSL_CMP_MSG_http_perform */ + OSSL_CMP_transfer_cb_t transfer_cb; /* default: OSSL_CMP_MSG_http_perform */ void *transfer_cb_arg; /* allows to store optional argument to cb */ /* HTTP-based transfer */ char *serverPath; - char *serverName; + char *server; int serverPort; - char *proxyName; - int proxyPort; - int msgtimeout; /* max seconds to wait for each CMP message round trip */ - int totaltimeout; /* maximum number seconds an enrollment may take, incl. */ + char *proxy; + char *no_proxy; + int msg_timeout; /* max seconds to wait for each CMP message round trip */ + int total_timeout; /* max number of seconds an enrollment may take, incl. */ /* attempts polling for a response if a 'waiting' PKIStatus is received */ time_t end_time; /* session start time + totaltimeout */ OSSL_HTTP_bio_cb_t http_cb; @@ -56,7 +56,7 @@ struct ossl_cmp_ctx_st { int unprotectedErrors; X509 *srvCert; /* certificate used to identify the server */ X509 *validatedSrvCert; /* caches any already validated server cert */ - X509_NAME *expected_sender; /* expected sender in pkiheader of response */ + X509_NAME *expected_sender; /* expected sender in header of response */ X509_STORE *trusted; /* trust store maybe w CRLs and cert verify callback */ STACK_OF(X509) *untrusted_certs; /* untrusted (intermediate) certs */ int ignore_keyusage; /* ignore key usage entry when validating certs */ @@ -95,7 +95,7 @@ struct ossl_cmp_ctx_st { int newPkey_priv; /* flag indicating if newPkey contains private key */ X509_NAME *issuer; /* issuer name to used in cert template */ int days; /* Number of days new certificates are asked to be valid for */ - X509_NAME *subjectName; /* subject name to be used in the cert template */ + X509_NAME *subjectName; /* subject name to be used in cert template */ STACK_OF(GENERAL_NAME) *subjectAltNames; /* to add to the cert template */ int SubjectAltName_nodefault; int setSubjectAltNameCritical; @@ -122,7 +122,7 @@ struct ossl_cmp_ctx_st { STACK_OF(X509) *extraCertsIn; /* extraCerts received from server */ /* certificate confirmation */ - OSSL_cmp_certConf_cb_t certConf_cb; /* callback for app checking new cert */ + OSSL_CMP_certConf_cb_t certConf_cb; /* callback for app checking new cert */ void *certConf_cb_arg; /* allows to store an argument individual to cb */ } /* OSSL_CMP_CTX */; @@ -246,7 +246,6 @@ struct ossl_cmp_itav_st { } infoValue; } /* OSSL_CMP_ITAV */; DECLARE_ASN1_FUNCTIONS(OSSL_CMP_ITAV) -DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_ITAV) typedef struct ossl_cmp_certorenccert_st { int type; @@ -284,8 +283,6 @@ struct ossl_cmp_pkisi_st { OSSL_CMP_PKIFREETEXT *statusString; OSSL_CMP_PKIFAILUREINFO *failInfo; } /* OSSL_CMP_PKISI */; -DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PKISI) -DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_PKISI) DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTID) /*- @@ -296,10 +293,11 @@ DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTID) * crlEntryDetails Extensions OPTIONAL * } */ -typedef struct ossl_cmp_revdetails_st { +struct ossl_cmp_revdetails_st { OSSL_CRMF_CERTTEMPLATE *certDetails; X509_EXTENSIONS *crlEntryDetails; -} OSSL_CMP_REVDETAILS; +} /* OSSL_CMP_REVDETAILS */; +typedef struct ossl_cmp_revdetails_st OSSL_CMP_REVDETAILS; DECLARE_ASN1_FUNCTIONS(OSSL_CMP_REVDETAILS) DEFINE_STACK_OF(OSSL_CMP_REVDETAILS) @@ -375,7 +373,6 @@ struct ossl_cmp_certstatus_st { OSSL_CMP_PKISI *statusInfo; } /* OSSL_CMP_CERTSTATUS */; DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTSTATUS) - typedef STACK_OF(OSSL_CMP_CERTSTATUS) OSSL_CMP_CERTCONFIRMCONTENT; DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTCONFIRMCONTENT) @@ -670,7 +667,6 @@ struct ossl_cmp_msg_st { STACK_OF(X509) *extraCerts; /* 1 */ } /* OSSL_CMP_MSG */; DECLARE_ASN1_FUNCTIONS(OSSL_CMP_MSG) -DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_MSG) /*- * ProtectedPart ::= SEQUENCE { @@ -728,17 +724,6 @@ DECLARE_ASN1_FUNCTIONS(CMP_PROTECTEDPART) * } */ -/* - * constants - */ -/* certReqId for the first - and so far only - certificate request */ -# define OSSL_CMP_CERTREQID 0 -/* sequence id for the first - and so far only - revocation request */ -# define OSSL_CMP_REVREQSID 0 -/* - * functions - */ - /* from cmp_asn.c */ int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a); @@ -755,6 +740,9 @@ int ossl_cmp_sk_X509_add1_certs(STACK_OF(X509) *sk, STACK_OF(X509) *certs, int no_self_issued, int no_dups, int prepend); int ossl_cmp_X509_STORE_add1_certs(X509_STORE *store, STACK_OF(X509) *certs, int only_self_issued); +STACK_OF(X509) *ossl_cmp_X509_STORE_get1_certs(X509_STORE *store); +int ossl_cmp_sk_ASN1_UTF8STRING_push_str(STACK_OF(ASN1_UTF8STRING) *sk, + const char *text); int ossl_cmp_asn1_octet_string_set1(ASN1_OCTET_STRING **tgt, const ASN1_OCTET_STRING *src); int ossl_cmp_asn1_octet_string_set1_bytes(ASN1_OCTET_STRING **tgt, @@ -800,32 +788,30 @@ int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx, const ASN1_OCTET_STRING *nonce); /* from cmp_status.c */ -OSSL_CMP_PKISI * -ossl_cmp_statusinfo_new(int status, int fail_info, const char *text); -int ossl_cmp_pkisi_get_pkistatus(const OSSL_CMP_PKISI *statusInfo); +int ossl_cmp_pkisi_get_status(const OSSL_CMP_PKISI *si); const char *ossl_cmp_PKIStatus_to_string(int status); -OSSL_CMP_PKIFREETEXT *ossl_cmp_pkisi_get0_statusstring(const OSSL_CMP_PKISI *si); +OSSL_CMP_PKIFREETEXT *ossl_cmp_pkisi_get0_statusString(const OSSL_CMP_PKISI *si); int ossl_cmp_pkisi_get_pkifailureinfo(const OSSL_CMP_PKISI *si); -int ossl_cmp_pkisi_pkifailureinfo_check(const OSSL_CMP_PKISI *si, int bit_index); +int ossl_cmp_pkisi_check_pkifailureinfo(const OSSL_CMP_PKISI *si, int index); /* from cmp_hdr.c */ int ossl_cmp_hdr_set_pvno(OSSL_CMP_PKIHEADER *hdr, int pvno); int ossl_cmp_hdr_get_pvno(const OSSL_CMP_PKIHEADER *hdr); ASN1_OCTET_STRING *ossl_cmp_hdr_get0_senderNonce(const OSSL_CMP_PKIHEADER *hdr); +int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name); int ossl_cmp_hdr_set1_sender(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm); int ossl_cmp_hdr_set1_recipient(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm); int ossl_cmp_hdr_update_messageTime(OSSL_CMP_PKIHEADER *hdr); int ossl_cmp_hdr_set1_senderKID(OSSL_CMP_PKIHEADER *hdr, const ASN1_OCTET_STRING *senderKID); -int ossl_cmp_pkifreetext_push_str(OSSL_CMP_PKIFREETEXT *ft, const char *text); int ossl_cmp_hdr_push0_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text); int ossl_cmp_hdr_push1_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text); int ossl_cmp_hdr_generalInfo_push0_item(OSSL_CMP_PKIHEADER *hdr, OSSL_CMP_ITAV *itav); int ossl_cmp_hdr_generalInfo_push1_items(OSSL_CMP_PKIHEADER *hdr, - STACK_OF(OSSL_CMP_ITAV) *itavs); + const STACK_OF(OSSL_CMP_ITAV) *itavs); int ossl_cmp_hdr_set_implicitConfirm(OSSL_CMP_PKIHEADER *hdr); -int ossl_cmp_hdr_check_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr); +int ossl_cmp_hdr_has_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr); # define OSSL_CMP_TRANSACTIONID_LENGTH 16 # define OSSL_CMP_SENDERNONCE_LENGTH 16 int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr); @@ -860,6 +846,10 @@ int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr); # define OSSL_CMP_PKIBODY_POLLREQ 25 # define OSSL_CMP_PKIBODY_POLLREP 26 # define OSSL_CMP_PKIBODY_TYPE_MAX OSSL_CMP_PKIBODY_POLLREP +/* certReqId for the first - and so far only - certificate request */ +# define OSSL_CMP_CERTREQID 0 +/* sequence id for the first - and so far only - revocation request */ +# define OSSL_CMP_REVREQSID 0 const char *ossl_cmp_bodytype_to_string(int type); int ossl_cmp_msg_set_bodytype(OSSL_CMP_MSG *msg, int type); int ossl_cmp_msg_get_bodytype(const OSSL_CMP_MSG *msg); @@ -875,24 +865,26 @@ OSSL_CMP_MSG *ossl_cmp_rr_new(OSSL_CMP_CTX *ctx); OSSL_CMP_MSG *ossl_cmp_rp_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si, OSSL_CRMF_CERTID *certId, int unprot_err); OSSL_CMP_MSG *ossl_cmp_pkiconf_new(OSSL_CMP_CTX *ctx); +OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid, + int64_t poll_after); int ossl_cmp_msg_gen_push0_ITAV(OSSL_CMP_MSG *msg, OSSL_CMP_ITAV *itav); int ossl_cmp_msg_gen_push1_ITAVs(OSSL_CMP_MSG *msg, - STACK_OF(OSSL_CMP_ITAV) *itavs); + const STACK_OF(OSSL_CMP_ITAV) *itavs); OSSL_CMP_MSG *ossl_cmp_genm_new(OSSL_CMP_CTX *ctx); -OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx); +OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx, + const STACK_OF(OSSL_CMP_ITAV) *itavs); OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si, int errorCode, - OSSL_CMP_PKIFREETEXT *errorDetails, - int unprotected); -int ossl_cmp_certstatus_set_certHash(OSSL_CMP_CERTSTATUS *certStatus, - const X509 *cert); + const char *details, int unprotected); +int ossl_cmp_certstatus_set0_certHash(OSSL_CMP_CERTSTATUS *certStatus, + ASN1_OCTET_STRING *hash); OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info, const char *text); OSSL_CMP_MSG *ossl_cmp_pollReq_new(OSSL_CMP_CTX *ctx, int crid); OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid, int64_t poll_after); OSSL_CMP_PKISI * -ossl_cmp_revrepcontent_get_pkistatusinfo(OSSL_CMP_REVREPCONTENT *rrep, int rsid); +ossl_cmp_revrepcontent_get_pkisi(OSSL_CMP_REVREPCONTENT *rrep, int rsid); OSSL_CRMF_CERTID *ossl_cmp_revrepcontent_get_CertId(OSSL_CMP_REVREPCONTENT *rrep, int rsid); OSSL_CMP_POLLREP * @@ -904,11 +896,6 @@ ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crepmsg X509 *ossl_cmp_certresponse_get1_certificate(EVP_PKEY *privkey, const OSSL_CMP_CERTRESPONSE *crep); OSSL_CMP_MSG *ossl_cmp_msg_load(const char *file); -/* BIO definitions */ -# define OSSL_d2i_CMP_MSG_bio(bp, p) \ - ASN1_d2i_bio_of(OSSL_CMP_MSG, OSSL_CMP_MSG_new, d2i_OSSL_CMP_MSG, bp, p) -# define OSSL_i2d_CMP_MSG_bio(bp, o) \ - ASN1_i2d_bio_of(OSSL_CMP_MSG, i2d_OSSL_CMP_MSG, bp, o) /* from cmp_protect.c */ ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_MSG *msg, @@ -925,4 +912,10 @@ int ossl_cmp_msg_check_received(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, ossl_cmp_allow_unprotected_cb_t cb, int cb_arg); int ossl_cmp_verify_popo(const OSSL_CMP_MSG *msg, int accept_RAVerified); -#endif /* !defined OSSL_CRYPTO_CMP_LOCAL_H */ +/* from cmp_client.c */ +int ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int fail_info, + const char *txt); +int ossl_cmp_exchange_error(OSSL_CMP_CTX *ctx, int status, int fail_info, + const char *txt, int errorCode, const char *details); + +#endif /* !defined(OSSL_CRYPTO_CMP_LOCAL_H) */ diff --git a/crypto/cmp/cmp_msg.c b/crypto/cmp/cmp_msg.c index c794dc98..7fc51596 100644 --- a/crypto/cmp/cmp_msg.c +++ b/crypto/cmp/cmp_msg.c @@ -185,8 +185,8 @@ OSSL_CMP_MSG *ossl_cmp_msg_create(OSSL_CMP_CTX *ctx, int bodytype) (sk_GENERAL_NAME_num((ctx)->subjectAltNames) > 0 \ || OSSL_CMP_CTX_reqExtensions_have_SAN(ctx) == 1) -static X509_NAME *determine_subj(OSSL_CMP_CTX *ctx, X509 *refcert, - int bodytype) +static const X509_NAME *determine_subj(OSSL_CMP_CTX *ctx, X509 *refcert, + int bodytype) { if (ctx->subjectName != NULL) return ctx->subjectName; @@ -205,18 +205,20 @@ static X509_NAME *determine_subj(OSSL_CMP_CTX *ctx, X509 *refcert, * Create CRMF certificate request message for IR/CR/KUR * returns a pointer to the OSSL_CRMF_MSG on success, NULL on error */ -static OSSL_CRMF_MSG *crm_new(OSSL_CMP_CTX *ctx, int bodytype, - int rid, EVP_PKEY *rkey) +static OSSL_CRMF_MSG *crm_new(OSSL_CMP_CTX *ctx, int bodytype, int rid) { OSSL_CRMF_MSG *crm = NULL; X509 *refcert = ctx->oldCert != NULL ? ctx->oldCert : ctx->clCert; /* refcert defaults to current client cert */ + EVP_PKEY *rkey = OSSL_CMP_CTX_get0_newPkey(ctx, 0); STACK_OF(GENERAL_NAME) *default_sans = NULL; - X509_NAME *subject = determine_subj(ctx, refcert, bodytype); + const X509_NAME *subject = determine_subj(ctx, refcert, bodytype); int crit = ctx->setSubjectAltNameCritical || subject == NULL; /* RFC5280: subjectAltName MUST be critical if subject is null */ X509_EXTENSIONS *exts = NULL; + if (rkey == NULL) + rkey = ctx->pkey; /* default is independent of ctx->oldClCert */ if (rkey == NULL || (bodytype == OSSL_CMP_PKIBODY_KUR && refcert == NULL)) { CMPerr(0, CMP_R_INVALID_ARGS); @@ -300,19 +302,12 @@ static OSSL_CRMF_MSG *crm_new(OSSL_CMP_CTX *ctx, int bodytype, OSSL_CMP_MSG *ossl_cmp_certReq_new(OSSL_CMP_CTX *ctx, int type, int err_code) { - EVP_PKEY *rkey; - EVP_PKEY *privkey; OSSL_CMP_MSG *msg; OSSL_CRMF_MSG *crm = NULL; if (!ossl_assert(ctx != NULL)) return NULL; - rkey = OSSL_CMP_CTX_get0_newPkey(ctx, 0); - if (rkey == NULL) - return NULL; - privkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1); - if (type != OSSL_CMP_PKIBODY_IR && type != OSSL_CMP_PKIBODY_CR && type != OSSL_CMP_PKIBODY_KUR && type != OSSL_CMP_PKIBODY_P10CR) { CMPerr(0, CMP_R_INVALID_ARGS); @@ -329,15 +324,19 @@ OSSL_CMP_MSG *ossl_cmp_certReq_new(OSSL_CMP_CTX *ctx, int type, int err_code) /* body */ /* For P10CR the content has already been set in OSSL_CMP_MSG_create */ if (type != OSSL_CMP_PKIBODY_P10CR) { + EVP_PKEY *privkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1); + + if (privkey == NULL) + privkey = ctx->pkey; /* default is independent of ctx->oldCert */ if (ctx->popoMethod == OSSL_CRMF_POPO_SIGNATURE && privkey == NULL) { CMPerr(0, CMP_R_MISSING_PRIVATE_KEY); goto err; } - if ((crm = crm_new(ctx, type, OSSL_CMP_CERTREQID, rkey)) == NULL - || !OSSL_CRMF_MSG_create_popo(crm, privkey, ctx->digest, - ctx->popoMethod) - /* value.ir is same for cr and kur */ - || !sk_OSSL_CRMF_MSG_push(msg->body->value.ir, crm)) + if ((crm = crm_new(ctx, type, OSSL_CMP_CERTREQID)) == NULL + || !OSSL_CRMF_MSG_create_popo(crm, privkey, ctx->digest, + ctx->popoMethod) + /* value.ir is same for cr and kur */ + || !sk_OSSL_CRMF_MSG_push(msg->body->value.ir, crm)) goto err; crm = NULL; /* TODO: here optional 2nd certreqmsg could be pushed to the stack */ @@ -349,7 +348,8 @@ OSSL_CMP_MSG *ossl_cmp_certReq_new(OSSL_CMP_CTX *ctx, int type, int err_code) return msg; err: - CMPerr(0, err_code); + if (err_code != 0) + CMPerr(0, err_code); OSSL_CRMF_MSG_free(crm); OSSL_CMP_MSG_free(msg); return NULL; @@ -385,7 +385,7 @@ OSSL_CMP_MSG *ossl_cmp_certRep_new(OSSL_CMP_CTX *ctx, int bodytype, || !ASN1_INTEGER_set(resp->certReqId, certReqId)) goto err; - status = ossl_cmp_pkisi_get_pkistatus(resp->status); + status = ossl_cmp_pkisi_get_status(resp->status); if (status != OSSL_CMP_PKISTATUS_rejection && status != OSSL_CMP_PKISTATUS_waiting && cert != NULL) { if (encrypted) { @@ -416,7 +416,7 @@ OSSL_CMP_MSG *ossl_cmp_certRep_new(OSSL_CMP_CTX *ctx, int bodytype, goto err; if (!unprotectedErrors - || ossl_cmp_pkisi_get_pkistatus(si) != OSSL_CMP_PKISTATUS_rejection) + || ossl_cmp_pkisi_get_status(si) != OSSL_CMP_PKISTATUS_rejection) if (!ossl_cmp_msg_protect(ctx, msg)) goto err; @@ -511,7 +511,7 @@ OSSL_CMP_MSG *ossl_cmp_rp_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si, } if (!unprot_err - || ossl_cmp_pkisi_get_pkistatus(si) != OSSL_CMP_PKISTATUS_rejection) + || ossl_cmp_pkisi_get_status(si) != OSSL_CMP_PKISTATUS_rejection) if (!ossl_cmp_msg_protect(ctx, msg)) goto err; @@ -560,7 +560,7 @@ int ossl_cmp_msg_gen_push0_ITAV(OSSL_CMP_MSG *msg, OSSL_CMP_ITAV *itav) } int ossl_cmp_msg_gen_push1_ITAVs(OSSL_CMP_MSG *msg, - STACK_OF(OSSL_CMP_ITAV) *itavs) + const STACK_OF(OSSL_CMP_ITAV) *itavs) { int i; OSSL_CMP_ITAV *itav = NULL; @@ -583,7 +583,9 @@ int ossl_cmp_msg_gen_push1_ITAVs(OSSL_CMP_MSG *msg, * Creates a new General Message/Response with an empty itav stack * returns a pointer to the PKIMessage on success, NULL on error */ -static OSSL_CMP_MSG *gen_new(OSSL_CMP_CTX *ctx, int body_type, int err_code) +static OSSL_CMP_MSG *gen_new(OSSL_CMP_CTX *ctx, + const STACK_OF(OSSL_CMP_ITAV) *itavs, + int body_type, int err_code) { OSSL_CMP_MSG *msg = NULL; @@ -594,7 +596,7 @@ static OSSL_CMP_MSG *gen_new(OSSL_CMP_CTX *ctx, int body_type, int err_code) return NULL; if (ctx->genm_ITAVs != NULL - && !ossl_cmp_msg_gen_push1_ITAVs(msg, ctx->genm_ITAVs)) + && !ossl_cmp_msg_gen_push1_ITAVs(msg, itavs)) goto err; if (!ossl_cmp_msg_protect(ctx, msg)) @@ -610,20 +612,23 @@ static OSSL_CMP_MSG *gen_new(OSSL_CMP_CTX *ctx, int body_type, int err_code) OSSL_CMP_MSG *ossl_cmp_genm_new(OSSL_CMP_CTX *ctx) { - return gen_new(ctx, OSSL_CMP_PKIBODY_GENM, CMP_R_ERROR_CREATING_GENM); + return gen_new(ctx, ctx->genm_ITAVs, + OSSL_CMP_PKIBODY_GENM, CMP_R_ERROR_CREATING_GENM); } -OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx) +OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx, + const STACK_OF(OSSL_CMP_ITAV) *itavs) { - return gen_new(ctx, OSSL_CMP_PKIBODY_GENP, CMP_R_ERROR_CREATING_GENP); + return gen_new(ctx, itavs, + OSSL_CMP_PKIBODY_GENP, CMP_R_ERROR_CREATING_GENP); } OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si, int errorCode, - OSSL_CMP_PKIFREETEXT *errorDetails, - int unprotected) + const char *details, int unprotected) { OSSL_CMP_MSG *msg = NULL; + OSSL_CMP_PKIFREETEXT *ft; if (!ossl_assert(ctx != NULL && si != NULL)) return NULL; @@ -641,11 +646,13 @@ OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si, if (!ASN1_INTEGER_set(msg->body->value.error->errorCode, errorCode)) goto err; } - if (errorDetails != NULL) - if ((msg->body->value.error->errorDetails = - sk_ASN1_UTF8STRING_deep_copy(errorDetails, ASN1_STRING_dup, - ASN1_STRING_free)) == NULL) + if (details != NULL) { + if ((ft = sk_ASN1_UTF8STRING_new_null()) == NULL) goto err; + msg->body->value.error->errorDetails = ft; + if (!ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, details)) + goto err; + } if (!unprotected && !ossl_cmp_msg_protect(ctx, msg)) goto err; @@ -658,44 +665,18 @@ OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si, } /* - * OSSL_CMP_CERTSTATUS_set_certHash() calculates a hash of the certificate, - * using the same hash algorithm as is used to create and verify the - * certificate signature, and places the hash into the certHash field of a - * OSSL_CMP_CERTSTATUS structure. This is used in the certConf message, - * for example, to confirm that the certificate was received successfully. + * Set the certHash field of a OSSL_CMP_CERTSTATUS structure. + * This is used in the certConf message, for example, + * to confirm that the certificate was received successfully. */ -int ossl_cmp_certstatus_set_certHash(OSSL_CMP_CERTSTATUS *certStatus, - const X509 *cert) +int ossl_cmp_certstatus_set0_certHash(OSSL_CMP_CERTSTATUS *certStatus, + ASN1_OCTET_STRING *hash) { - unsigned int len; - unsigned char hash[EVP_MAX_MD_SIZE]; - int md_NID; - const EVP_MD *md = NULL; - - if (!ossl_assert(certStatus != NULL && cert != NULL)) + if (!ossl_assert(certStatus != NULL)) return 0; - - /*- - * select hash algorithm, as stated in Appendix F. Compilable ASN.1 defs: - * the hash of the certificate, using the same hash algorithm - * as is used to create and verify the certificate signature - */ - if (OBJ_find_sigid_algs(X509_get_signature_nid(cert), &md_NID, NULL) - && (md = EVP_get_digestbynid(md_NID)) != NULL) { - if (!X509_digest(cert, md, hash, &len)) - goto err; - if (!ossl_cmp_asn1_octet_string_set1_bytes(&certStatus->certHash, hash, - len)) - goto err; - } else { - CMPerr(0, CMP_R_UNSUPPORTED_ALGORITHM); - return 0; - } - + ASN1_OCTET_STRING_free(certStatus->certHash); + certStatus->certHash = hash; return 1; - err: - CMPerr(0, CMP_R_ERROR_SETTING_CERTHASH); - return 0; } /* @@ -707,6 +688,7 @@ OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info, { OSSL_CMP_MSG *msg = NULL; OSSL_CMP_CERTSTATUS *certStatus = NULL; + ASN1_OCTET_STRING *certHash = NULL; OSSL_CMP_PKISI *sinfo; if (!ossl_assert(ctx != NULL && ctx->newCert != NULL)) @@ -732,8 +714,12 @@ OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info, * the hash of the certificate, using the same hash algorithm * as is used to create and verify the certificate signature */ - if (!ossl_cmp_certstatus_set_certHash(certStatus, ctx->newCert)) + if ((certHash = X509_digest_sig(ctx->newCert)) == NULL) goto err; + + if (!ossl_cmp_certstatus_set0_certHash(certStatus, certHash)) + goto err; + certHash = NULL; /* * For any particular CertStatus, omission of the statusInfo field * indicates ACCEPTANCE of the specified certificate. Alternatively, @@ -742,8 +728,8 @@ OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info, * the CA/RA. */ sinfo = fail_info != 0 ? - ossl_cmp_statusinfo_new(OSSL_CMP_PKISTATUS_rejection, fail_info, text) : - ossl_cmp_statusinfo_new(OSSL_CMP_PKISTATUS_accepted, 0, text); + OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_rejection, fail_info, text) : + OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_accepted, 0, text); if (sinfo == NULL) goto err; certStatus->statusInfo = sinfo; @@ -756,6 +742,7 @@ OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info, err: CMPerr(0, CMP_R_ERROR_CREATING_CERTCONF); OSSL_CMP_MSG_free(msg); + ASN1_OCTET_STRING_free(certHash); return NULL; } @@ -827,7 +814,7 @@ OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid, * returns NULL on error */ OSSL_CMP_PKISI * -ossl_cmp_revrepcontent_get_pkistatusinfo(OSSL_CMP_REVREPCONTENT *rrep, int rsid) +ossl_cmp_revrepcontent_get_pkisi(OSSL_CMP_REVREPCONTENT *rrep, int rsid) { OSSL_CMP_PKISI *status; @@ -990,7 +977,18 @@ OSSL_CMP_MSG *ossl_cmp_msg_load(const char *file) if ((bio = BIO_new_file(file, "rb")) == NULL) return NULL; - msg = OSSL_d2i_CMP_MSG_bio(bio, NULL); + msg = d2i_OSSL_CMP_MSG_bio(bio, NULL); BIO_free(bio); return msg; } + +OSSL_CMP_MSG *d2i_OSSL_CMP_MSG_bio(BIO *bio, OSSL_CMP_MSG **msg) +{ + return ASN1_d2i_bio_of(OSSL_CMP_MSG, OSSL_CMP_MSG_new, + d2i_OSSL_CMP_MSG, bio, msg); +} + +int i2d_OSSL_CMP_MSG_bio(BIO *bio, const OSSL_CMP_MSG *msg) +{ + return ASN1_i2d_bio_of(OSSL_CMP_MSG, i2d_OSSL_CMP_MSG, bio, msg); +} diff --git a/crypto/cmp/cmp_protect.c b/crypto/cmp/cmp_protect.c index c1b4b858..ce20ef20 100644 --- a/crypto/cmp/cmp_protect.c +++ b/crypto/cmp/cmp_protect.c @@ -286,6 +286,8 @@ int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg) * to section 5.1.1 */ subjKeyIDStr = X509_get0_subject_key_id(ctx->clCert); + if (subjKeyIDStr == NULL) + subjKeyIDStr = ctx->referenceValue; /* fallback */ if (subjKeyIDStr != NULL && !ossl_cmp_hdr_set1_senderKID(msg->header, subjKeyIDStr)) goto err; @@ -306,7 +308,18 @@ int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg) } } - return 1; + /* + * As required by RFC 4210 section 5.1.1., if the sender name is not known + * to the client it set to NULL-DN. In this case for identification at least + * the senderKID must be set, where we took the referenceValue as fallback. + */ + + if (ossl_cmp_general_name_is_NULL_DN(msg->header->sender) + && msg->header->senderKID == NULL) + CMPerr(0, CMP_R_MISSING_SENDER_IDENTIFICATION); + else + return 1; + err: CMPerr(0, CMP_R_ERROR_PROTECTING_MESSAGE); return 0; diff --git a/crypto/cmp/cmp_server.c b/crypto/cmp/cmp_server.c new file mode 100644 index 00000000..c5c57fc8 --- /dev/null +++ b/crypto/cmp/cmp_server.c @@ -0,0 +1,619 @@ +/* + * Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright Nokia 2007-2019 + * Copyright Siemens AG 2015-2019 + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* general CMP server functions */ + +#include + +#include "cmp_local.h" + +/* explicit #includes not strictly needed since implied by the above: */ +#include +#include + +/* the context for the generic CMP server */ +struct ossl_cmp_srv_ctx_st +{ + OSSL_CMP_CTX *ctx; /* Client CMP context, partly reused for srv */ + void *custom_ctx; /* pointer to specific server context */ + + OSSL_CMP_SRV_cert_request_cb_t process_cert_request; + OSSL_CMP_SRV_rr_cb_t process_rr; + OSSL_CMP_SRV_genm_cb_t process_genm; + OSSL_CMP_SRV_error_cb_t process_error; + OSSL_CMP_SRV_certConf_cb_t process_certConf; + OSSL_CMP_SRV_pollReq_cb_t process_pollReq; + + int sendUnprotectedErrors; /* Send error and rejection msgs unprotected */ + int acceptUnprotected; /* Accept requests with no/invalid prot. */ + int acceptRAVerified; /* Accept ir/cr/kur with POPO RAVerified */ + int grantImplicitConfirm; /* Grant implicit confirmation if requested */ + +}; /* OSSL_CMP_SRV_CTX */ + +void OSSL_CMP_SRV_CTX_free(OSSL_CMP_SRV_CTX *srv_ctx) +{ + if (srv_ctx == NULL) + return; + + OSSL_CMP_CTX_free(srv_ctx->ctx); + OPENSSL_free(srv_ctx); +} + +OSSL_CMP_SRV_CTX *OSSL_CMP_SRV_CTX_new(void) +{ + OSSL_CMP_SRV_CTX *ctx = OPENSSL_zalloc(sizeof(OSSL_CMP_SRV_CTX)); + + if (ctx == NULL) + goto err; + + if ((ctx->ctx = OSSL_CMP_CTX_new()) == NULL) + goto err; + + /* all other elements are initialized to 0 or NULL, respectively */ + return ctx; + err: + OSSL_CMP_SRV_CTX_free(ctx); + return NULL; +} + +int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx, + OSSL_CMP_SRV_cert_request_cb_t process_cert_request, + OSSL_CMP_SRV_rr_cb_t process_rr, + OSSL_CMP_SRV_genm_cb_t process_genm, + OSSL_CMP_SRV_error_cb_t process_error, + OSSL_CMP_SRV_certConf_cb_t process_certConf, + OSSL_CMP_SRV_pollReq_cb_t process_pollReq) +{ + if (srv_ctx == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return 0; + } + srv_ctx->custom_ctx = custom_ctx; + srv_ctx->process_cert_request = process_cert_request; + srv_ctx->process_rr = process_rr; + srv_ctx->process_genm = process_genm; + srv_ctx->process_error = process_error; + srv_ctx->process_certConf = process_certConf; + srv_ctx->process_pollReq = process_pollReq; + return 1; +} + +OSSL_CMP_CTX *OSSL_CMP_SRV_CTX_get0_cmp_ctx(const OSSL_CMP_SRV_CTX *srv_ctx) +{ + if (srv_ctx == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return NULL; + } + return srv_ctx->ctx; +} + +void *OSSL_CMP_SRV_CTX_get0_custom_ctx(const OSSL_CMP_SRV_CTX *srv_ctx) +{ + if (srv_ctx == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return NULL; + } + return srv_ctx->custom_ctx; +} + +int OSSL_CMP_SRV_CTX_set_send_unprotected_errors(OSSL_CMP_SRV_CTX *srv_ctx, + int val) +{ + if (srv_ctx == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return 0; + } + srv_ctx->sendUnprotectedErrors = val != 0; + return 1; +} + +int OSSL_CMP_SRV_CTX_set_accept_unprotected(OSSL_CMP_SRV_CTX *srv_ctx, int val) +{ + if (srv_ctx == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return 0; + } + srv_ctx->acceptUnprotected = val != 0; + return 1; +} + +int OSSL_CMP_SRV_CTX_set_accept_raverified(OSSL_CMP_SRV_CTX *srv_ctx, int val) +{ + if (srv_ctx == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return 0; + } + srv_ctx->acceptRAVerified = val != 0; + return 1; +} + +int OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(OSSL_CMP_SRV_CTX *srv_ctx, + int val) +{ + if (srv_ctx == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return 0; + } + srv_ctx->grantImplicitConfirm = val != 0; + return 1; +} + +/* + * Processes an ir/cr/p10cr/kur and returns a certification response. + * Only handles the first certification request contained in req + * returns an ip/cp/kup on success and NULL on error + */ +static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req) +{ + OSSL_CMP_MSG *msg = NULL; + OSSL_CMP_PKISI *si = NULL; + X509 *certOut = NULL; + STACK_OF(X509) *chainOut = NULL, *caPubs = NULL; + const OSSL_CRMF_MSG *crm = NULL; + const X509_REQ *p10cr = NULL; + int bodytype; + int certReqId; + + if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL)) + return NULL; + + switch (ossl_cmp_msg_get_bodytype(req)) { + case OSSL_CMP_PKIBODY_P10CR: + case OSSL_CMP_PKIBODY_CR: + bodytype = OSSL_CMP_PKIBODY_CP; + break; + case OSSL_CMP_PKIBODY_IR: + bodytype = OSSL_CMP_PKIBODY_IP; + break; + case OSSL_CMP_PKIBODY_KUR: + bodytype = OSSL_CMP_PKIBODY_KUP; + break; + default: + CMPerr(0, CMP_R_UNEXPECTED_PKIBODY); + return NULL; + } + + if (ossl_cmp_msg_get_bodytype(req) == OSSL_CMP_PKIBODY_P10CR) { + certReqId = OSSL_CMP_CERTREQID; + p10cr = req->body->value.p10cr; + } else { + OSSL_CRMF_MSGS *reqs = req->body->value.ir; /* same for cr and kur */ + + if (sk_OSSL_CRMF_MSG_num(reqs) != 1) { /* TODO: handle case > 1 */ + CMPerr(0, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED); + return NULL; + } + + if ((crm = sk_OSSL_CRMF_MSG_value(reqs, OSSL_CMP_CERTREQID)) == NULL) { + CMPerr(0, CMP_R_CERTREQMSG_NOT_FOUND); + return NULL; + } + certReqId = OSSL_CRMF_MSG_get_certReqId(crm); + } + + if (!ossl_cmp_verify_popo(req, srv_ctx->acceptRAVerified)) { + /* Proof of possession could not be verified */ + si = OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_rejection, + 1 << OSSL_CMP_PKIFAILUREINFO_badPOP, + ERR_reason_error_string(ERR_peek_error())); + if (si == NULL) + return NULL; + } else { + OSSL_CMP_PKIHEADER *hdr = OSSL_CMP_MSG_get0_header(req); + + si = srv_ctx->process_cert_request(srv_ctx, req, certReqId, crm, p10cr, + &certOut, &chainOut, &caPubs); + if (si == NULL) + goto err; + /* set OSSL_CMP_OPT_IMPLICIT_CONFIRM if and only if transaction ends */ + if (!OSSL_CMP_CTX_set_option(srv_ctx->ctx, OSSL_CMP_OPT_IMPLICIT_CONFIRM, + ossl_cmp_hdr_has_implicitConfirm(hdr) + && srv_ctx->grantImplicitConfirm + /* do not set if polling starts: */ + && certOut != NULL)) + goto err; + } + + msg = ossl_cmp_certRep_new(srv_ctx->ctx, bodytype, certReqId, si, + certOut, chainOut, caPubs, 0 /* encrypted */, + srv_ctx->sendUnprotectedErrors); + /* + * TODO when implemented in ossl_cmp_certrep_new(): + * in case OSSL_CRMF_POPO_KEYENC, set encrypted + */ + if (msg == NULL) + CMPerr(0, CMP_R_ERROR_CREATING_CERTREP); + + err: + OSSL_CMP_PKISI_free(si); + X509_free(certOut); + sk_X509_pop_free(chainOut, X509_free); + sk_X509_pop_free(caPubs, X509_free); + return msg; +} + +static OSSL_CMP_MSG *process_rr(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req) +{ + OSSL_CMP_MSG *msg = NULL; + OSSL_CMP_REVDETAILS *details; + OSSL_CRMF_CERTID *certId; + OSSL_CRMF_CERTTEMPLATE *tmpl; + const X509_NAME *issuer; + ASN1_INTEGER *serial; + OSSL_CMP_PKISI *si; + + if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL)) + return NULL; + + if (sk_OSSL_CMP_REVDETAILS_num(req->body->value.rr) != 1) { + /* TODO: handle multiple elements if multiple requests have been sent */ + CMPerr(0, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED); + return NULL; + } + + if ((details = sk_OSSL_CMP_REVDETAILS_value(req->body->value.rr, + OSSL_CMP_REVREQSID)) == NULL) { + CMPerr(0, CMP_R_ERROR_PROCESSING_MESSAGE); + return NULL; + } + + tmpl = details->certDetails; + issuer = OSSL_CRMF_CERTTEMPLATE_get0_issuer(tmpl); + serial = OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(tmpl); + /* here issuer and serial may safely be NULL */ + if ((certId = OSSL_CRMF_CERTID_gen(issuer, serial)) == NULL) + return NULL; + if ((si = srv_ctx->process_rr(srv_ctx, req, issuer, serial)) == NULL) + goto err; + + if ((msg = ossl_cmp_rp_new(srv_ctx->ctx, si, certId, + srv_ctx->sendUnprotectedErrors)) == NULL) + CMPerr(0, CMP_R_ERROR_CREATING_RR); + + err: + OSSL_CRMF_CERTID_free(certId); + OSSL_CMP_PKISI_free(si); + return msg; +} + +/* + * Processes genm and creates a genp message mirroring the contents of the + * incoming message + */ +static OSSL_CMP_MSG *process_genm(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req) +{ + OSSL_CMP_GENMSGCONTENT *itavs; + OSSL_CMP_MSG *msg; + + if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL)) + return NULL; + + if (!srv_ctx->process_genm(srv_ctx, req, req->body->value.genm, &itavs)) + return NULL; + + msg = ossl_cmp_genp_new(srv_ctx->ctx, itavs); + sk_OSSL_CMP_ITAV_pop_free(itavs, OSSL_CMP_ITAV_free); + return msg; +} + +static OSSL_CMP_MSG *process_error(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req) +{ + OSSL_CMP_ERRORMSGCONTENT *errorContent; + OSSL_CMP_MSG *msg; + + if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL)) + return NULL; + errorContent = req->body->value.error; + srv_ctx->process_error(srv_ctx, req, errorContent->pKIStatusInfo, + errorContent->errorCode, errorContent->errorDetails); + + if ((msg = ossl_cmp_pkiconf_new(srv_ctx->ctx)) == NULL) + CMPerr(0, CMP_R_ERROR_CREATING_PKICONF); + return msg; +} + +static OSSL_CMP_MSG *process_certConf(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req) +{ + OSSL_CMP_CTX *ctx; + OSSL_CMP_CERTCONFIRMCONTENT *ccc; + int num; + OSSL_CMP_MSG *msg = NULL; + OSSL_CMP_CERTSTATUS *status = NULL; + + if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL)) + return NULL; + + ctx = srv_ctx->ctx; + ccc = req->body->value.certConf; + num = sk_OSSL_CMP_CERTSTATUS_num(ccc); + + if (OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_IMPLICIT_CONFIRM) == 1) { + CMPerr(0, CMP_R_ERROR_UNEXPECTED_CERTCONF); + return NULL; + } + + if (num == 0) { + ossl_cmp_err(ctx, "certificate rejected by client"); + } else { + if (num > 1) + ossl_cmp_warn(ctx, "All CertStatus but the first will be ignored"); + status = sk_OSSL_CMP_CERTSTATUS_value(ccc, OSSL_CMP_CERTREQID); + } + + if (status != NULL) { + int certReqId = ossl_cmp_asn1_get_int(status->certReqId); + ASN1_OCTET_STRING *certHash = status->certHash; + OSSL_CMP_PKISI *si = status->statusInfo; + + if (!srv_ctx->process_certConf(srv_ctx, req, certReqId, certHash, si)) + return NULL; /* reason code may be: CMP_R_CERTHASH_UNMATCHED */ + + if (si != NULL && ossl_cmp_pkisi_get_status(si) + != OSSL_CMP_PKISTATUS_accepted) { + int pki_status = ossl_cmp_pkisi_get_status(si); + const char *str = ossl_cmp_PKIStatus_to_string(pki_status); + + ossl_cmp_log2(INFO, ctx, "certificate rejected by client %s %s", + str == NULL ? "without" : "with", + str == NULL ? "PKIStatus" : str); + } + } + + if ((msg = ossl_cmp_pkiconf_new(ctx)) == NULL) + CMPerr(0, CMP_R_ERROR_CREATING_PKICONF); + return msg; +} + +static OSSL_CMP_MSG *process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req) +{ + OSSL_CMP_POLLREQCONTENT *prc; + OSSL_CMP_POLLREQ *pr; + int certReqId; + OSSL_CMP_MSG *certReq; + int64_t check_after = 0; + OSSL_CMP_MSG *msg = NULL; + + if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL)) + return NULL; + + prc = req->body->value.pollReq; + if (sk_OSSL_CMP_POLLREQ_num(prc) != 1) { /* TODO: handle case > 1 */ + CMPerr(0, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED); + return NULL; + } + + pr = sk_OSSL_CMP_POLLREQ_value(prc, 0); + certReqId = ossl_cmp_asn1_get_int(pr->certReqId); + if (!srv_ctx->process_pollReq(srv_ctx, req, certReqId, + &certReq, &check_after)) + return NULL; + + if (certReq != NULL) { + msg = process_cert_request(srv_ctx, certReq); + OSSL_CMP_MSG_free(certReq); + } else { + if ((msg = ossl_cmp_pollRep_new(srv_ctx->ctx, certReqId, + check_after)) == NULL) + CMPerr(0, CMP_R_ERROR_CREATING_POLLREP); + } + return msg; +} + +/* + * Determine whether missing/invalid protection of request message is allowed. + * Return 1 on acceptance, 0 on rejection, or -1 on (internal) error. + */ +static int unprotected_exception(const OSSL_CMP_CTX *ctx, + const OSSL_CMP_MSG *req, + int invalid_protection, + int accept_unprotected_requests) +{ + if (!ossl_assert(ctx != NULL && req != NULL)) + return -1; + + if (accept_unprotected_requests) { + ossl_cmp_log1(WARN, ctx, "ignoring %s protection of request message", + invalid_protection ? "invalid" : "missing"); + return 1; + } + if (ossl_cmp_msg_get_bodytype(req) == OSSL_CMP_PKIBODY_ERROR + && OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_UNPROTECTED_ERRORS) == 1) { + ossl_cmp_warn(ctx, "ignoring missing protection of error message"); + return 1; + } + return 0; +} + +/* + * returns created message and NULL on internal error + */ +OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req) +{ + OSSL_CMP_CTX *ctx; + OSSL_CMP_PKIHEADER *hdr; + int req_type, rsp_type; + OSSL_CMP_MSG *rsp = NULL; + + if (srv_ctx == NULL || srv_ctx->ctx == NULL + || req == NULL || req->body == NULL + || (hdr = OSSL_CMP_MSG_get0_header(req)) == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return 0; + } + ctx = srv_ctx->ctx; + + if (hdr->sender->type != GEN_DIRNAME) { + CMPerr(0, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED); + goto err; + } + if (!OSSL_CMP_CTX_set1_recipient(ctx, hdr->sender->d.directoryName)) + goto err; + + req_type = ossl_cmp_msg_get_bodytype(req); + switch (req_type) { + case OSSL_CMP_PKIBODY_IR: + case OSSL_CMP_PKIBODY_CR: + case OSSL_CMP_PKIBODY_P10CR: + case OSSL_CMP_PKIBODY_KUR: + case OSSL_CMP_PKIBODY_RR: + case OSSL_CMP_PKIBODY_GENM: + case OSSL_CMP_PKIBODY_ERROR: + if (ctx->transactionID != NULL) { + char *tid; + + tid = OPENSSL_buf2hexstr(ctx->transactionID->data, + ctx->transactionID->length); + ossl_cmp_log1(WARN, ctx, + "Assuming that last transaction with ID=%s got aborted", + tid); + OPENSSL_free(tid); + } + /* start of a new transaction, set transactionID and senderNonce */ + if (!OSSL_CMP_CTX_set1_transactionID(ctx, hdr->transactionID) + || !ossl_cmp_ctx_set1_recipNonce(ctx, hdr->senderNonce)) + goto err; + break; + default: + /* transactionID should be already initialized */ + if (ctx->transactionID == NULL) { + CMPerr(0, CMP_R_UNEXPECTED_PKIBODY); + /* ignore any (extra) error in next two function calls: */ + (void)OSSL_CMP_CTX_set1_transactionID(ctx, hdr->transactionID); + (void)ossl_cmp_ctx_set1_recipNonce(ctx, hdr->senderNonce); + goto err; + } + } + + if (ossl_cmp_msg_check_received(ctx, req, unprotected_exception, + srv_ctx->acceptUnprotected) < 0) + goto err; + + switch (req_type) { + case OSSL_CMP_PKIBODY_IR: + case OSSL_CMP_PKIBODY_CR: + case OSSL_CMP_PKIBODY_P10CR: + case OSSL_CMP_PKIBODY_KUR: + if (srv_ctx->process_cert_request == NULL) + CMPerr(0, CMP_R_UNEXPECTED_PKIBODY); + else + rsp = process_cert_request(srv_ctx, req); + break; + case OSSL_CMP_PKIBODY_RR: + if (srv_ctx->process_rr == NULL) + CMPerr(0, CMP_R_UNEXPECTED_PKIBODY); + else + rsp = process_rr(srv_ctx, req); + break; + case OSSL_CMP_PKIBODY_GENM: + if (srv_ctx->process_genm == NULL) + CMPerr(0, CMP_R_UNEXPECTED_PKIBODY); + else + rsp = process_genm(srv_ctx, req); + break; + case OSSL_CMP_PKIBODY_ERROR: + if (srv_ctx->process_error == NULL) + CMPerr(0, CMP_R_UNEXPECTED_PKIBODY); + else + rsp = process_error(srv_ctx, req); + break; + case OSSL_CMP_PKIBODY_CERTCONF: + if (srv_ctx->process_certConf == NULL) + CMPerr(0, CMP_R_UNEXPECTED_PKIBODY); + else + rsp = process_certConf(srv_ctx, req); + break; + case OSSL_CMP_PKIBODY_POLLREQ: + if (srv_ctx->process_pollReq == NULL) + CMPerr(0, CMP_R_UNEXPECTED_PKIBODY); + else + rsp = process_pollReq(srv_ctx, req); + break; + default: + /* TODO possibly support further request message types */ + CMPerr(0, CMP_R_UNEXPECTED_PKIBODY); + } + + err: + if (rsp == NULL) { + /* on error, try to respond with CMP error message to client */ + const char *data = NULL; + int flags = 0; + unsigned long err = ERR_peek_error_data(&data, &flags); + int fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_badRequest; + /* TODO fail_info could be more specific */ + OSSL_CMP_PKISI *si = NULL; + + if ((si = OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_rejection, + fail_info, NULL)) == NULL) + return 0; + if (err != 0 && (flags & ERR_TXT_STRING) != 0) + data = ERR_reason_error_string(err); + rsp = ossl_cmp_error_new(srv_ctx->ctx, si, + err != 0 ? ERR_GET_REASON(err) : -1, + data, srv_ctx->sendUnprotectedErrors); + OSSL_CMP_PKISI_free(si); + } + + /* possibly close the transaction */ + rsp_type = + rsp != NULL ? ossl_cmp_msg_get_bodytype(rsp) : OSSL_CMP_PKIBODY_ERROR; + switch (rsp_type) { + case OSSL_CMP_PKIBODY_IP: + case OSSL_CMP_PKIBODY_CP: + case OSSL_CMP_PKIBODY_KUP: + case OSSL_CMP_PKIBODY_RP: + if (OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_IMPLICIT_CONFIRM) == 0) + break; + /* fall through */ + + case OSSL_CMP_PKIBODY_PKICONF: + case OSSL_CMP_PKIBODY_GENP: + case OSSL_CMP_PKIBODY_ERROR: + /* TODO possibly support further terminating response message types */ + (void)OSSL_CMP_CTX_set1_transactionID(ctx, NULL); /* ignore any error */ + + default: /* not closing transaction in other cases */ + break; + } + return rsp; +} + +/* + * Server interface that may substitute OSSL_CMP_MSG_http_perform at the client. + * The OSSL_CMP_SRV_CTX must be set as client_ctx->transfer_cb_arg. + * returns received message on success, else NULL and pushes an element on the + * error stack. + */ +OSSL_CMP_MSG * OSSL_CMP_CTX_server_perform(OSSL_CMP_CTX *client_ctx, + const OSSL_CMP_MSG *req) +{ + OSSL_CMP_SRV_CTX *srv_ctx = NULL; + + if (client_ctx == NULL || req == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return 0; + } + + if ((srv_ctx = OSSL_CMP_CTX_get_transfer_cb_arg(client_ctx)) == NULL) { + CMPerr(0, CMP_R_TRANSFER_ERROR); + return 0; + } + + return OSSL_CMP_SRV_process_request(srv_ctx, req); +} diff --git a/crypto/cmp/cmp_status.c b/crypto/cmp/cmp_status.c index 7ebc57d3..9192cf5e 100644 --- a/crypto/cmp/cmp_status.c +++ b/crypto/cmp/cmp_status.c @@ -28,17 +28,13 @@ /* CMP functions related to PKIStatus */ -int ossl_cmp_pkisi_get_pkistatus(const OSSL_CMP_PKISI *si) +int ossl_cmp_pkisi_get_status(const OSSL_CMP_PKISI *si) { if (!ossl_assert(si != NULL && si->status != NULL)) return -1; return ossl_cmp_asn1_get_int(si->status); } -/* - * return the declared identifier and a short explanation for the PKIStatus - * value as specified in RFC4210, Appendix F. - */ const char *ossl_cmp_PKIStatus_to_string(int status) { switch (status) { @@ -67,27 +63,19 @@ const char *ossl_cmp_PKIStatus_to_string(int status) } } -/* - * returns a pointer to the statusString contained in a PKIStatusInfo - * returns NULL on error - */ -OSSL_CMP_PKIFREETEXT *ossl_cmp_pkisi_get0_statusstring(const OSSL_CMP_PKISI *si) +OSSL_CMP_PKIFREETEXT *ossl_cmp_pkisi_get0_statusString(const OSSL_CMP_PKISI *si) { if (!ossl_assert(si != NULL)) return NULL; return si->statusString; } -/* - * returns the FailureInfo bits of the given PKIStatusInfo - * returns -1 on error - */ int ossl_cmp_pkisi_get_pkifailureinfo(const OSSL_CMP_PKISI *si) { int i; int res = 0; - if (!ossl_assert(si != NULL && si->failInfo != NULL)) + if (!ossl_assert(si != NULL)) return -1; for (i = 0; i <= OSSL_CMP_PKIFAILUREINFO_MAX; i++) if (ASN1_BIT_STRING_get_bit(si->failInfo, i)) @@ -95,12 +83,9 @@ int ossl_cmp_pkisi_get_pkifailureinfo(const OSSL_CMP_PKISI *si) return res; } -/* - * internal function +/*- * convert PKIFailureInfo number to human-readable string - * - * returns pointer to static string - * returns NULL on error + * returns pointer to static string, or NULL on error */ static const char *CMP_PKIFAILUREINFO_to_string(int number) { @@ -164,11 +149,7 @@ static const char *CMP_PKIFAILUREINFO_to_string(int number) } } -/* - * checks PKIFailureInfo bits in a given PKIStatusInfo - * returns 1 if a given bit is set, 0 if not, -1 on error - */ -int ossl_cmp_pkisi_pkifailureinfo_check(const OSSL_CMP_PKISI *si, int bit_index) +int ossl_cmp_pkisi_check_pkifailureinfo(const OSSL_CMP_PKISI *si, int bit_index) { if (!ossl_assert(si != NULL && si->failInfo != NULL)) return -1; @@ -180,16 +161,17 @@ int ossl_cmp_pkisi_pkifailureinfo_check(const OSSL_CMP_PKISI *si, int bit_index) return ASN1_BIT_STRING_get_bit(si->failInfo, bit_index); } -/* +/*- * place human-readable error string created from PKIStatusInfo in given buffer * returns pointer to the same buffer containing the string, or NULL on error */ -char *OSSL_CMP_CTX_snprint_PKIStatus(OSSL_CMP_CTX *ctx, char *buf, - size_t bufsize) +static +char *snprint_PKIStatusInfo_parts(int status, int fail_info, + const OSSL_CMP_PKIFREETEXT *status_strings, + char *buf, size_t bufsize) { - int status, failure, fail_info; + int failure; const char *status_string, *failure_string; - OSSL_CMP_PKIFREETEXT *status_strings; ASN1_UTF8STRING *text; int i; int printed_chars; @@ -197,22 +179,22 @@ char *OSSL_CMP_CTX_snprint_PKIStatus(OSSL_CMP_CTX *ctx, char *buf, int n_status_strings; char *write_ptr = buf; -#define ADVANCE_BUFFER \ - if (printed_chars < 0 || (size_t)printed_chars >= bufsize) \ - return NULL; \ - write_ptr += printed_chars; \ - bufsize -= printed_chars; - - if (ctx == NULL - || buf == NULL - || (status = OSSL_CMP_CTX_get_status(ctx)) < 0 + if (buf == NULL + || status < 0 || (status_string = ossl_cmp_PKIStatus_to_string(status)) == NULL) return NULL; + +#define ADVANCE_BUFFER \ + if (printed_chars < 0 || (size_t)printed_chars >= bufsize) \ + return NULL; \ + write_ptr += printed_chars; \ + bufsize -= printed_chars; + printed_chars = BIO_snprintf(write_ptr, bufsize, "%s", status_string); ADVANCE_BUFFER; /* failInfo is optional and may be empty */ - if ((fail_info = OSSL_CMP_CTX_get_failInfoCode(ctx)) > 0) { + if (fail_info != 0) { printed_chars = BIO_snprintf(write_ptr, bufsize, "; PKIFailureInfo: "); ADVANCE_BUFFER; for (failure = 0; failure <= OSSL_CMP_PKIFAILUREINFO_MAX; failure++) { @@ -220,7 +202,7 @@ char *OSSL_CMP_CTX_snprint_PKIStatus(OSSL_CMP_CTX *ctx, char *buf, failure_string = CMP_PKIFAILUREINFO_to_string(failure); if (failure_string != NULL) { printed_chars = BIO_snprintf(write_ptr, bufsize, "%s%s", - failure > 0 ? ", " : "", + failinfo_found ? ", " : "", failure_string); ADVANCE_BUFFER; failinfo_found = 1; @@ -235,7 +217,6 @@ char *OSSL_CMP_CTX_snprint_PKIStatus(OSSL_CMP_CTX *ctx, char *buf, } /* statusString sequence is optional and may be empty */ - status_strings = OSSL_CMP_CTX_get0_statusString(ctx); n_status_strings = sk_ASN1_UTF8STRING_num(status_strings); if (n_status_strings > 0) { printed_chars = BIO_snprintf(write_ptr, bufsize, "; StatusString%s: ", @@ -253,13 +234,44 @@ char *OSSL_CMP_CTX_snprint_PKIStatus(OSSL_CMP_CTX *ctx, char *buf, return buf; } -/* +char *OSSL_CMP_snprint_PKIStatusInfo(const OSSL_CMP_PKISI *statusInfo, + char *buf, size_t bufsize) +{ + int failure_info; + + if (statusInfo == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return NULL; + } + + failure_info = ossl_cmp_pkisi_get_pkifailureinfo(statusInfo); + + return snprint_PKIStatusInfo_parts(ASN1_INTEGER_get(statusInfo->status), + failure_info, + statusInfo->statusString, buf, bufsize); +} + +char *OSSL_CMP_CTX_snprint_PKIStatus(const OSSL_CMP_CTX *ctx, char *buf, + size_t bufsize) +{ + if (ctx == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return NULL; + } + + return snprint_PKIStatusInfo_parts(OSSL_CMP_CTX_get_status(ctx), + OSSL_CMP_CTX_get_failInfoCode(ctx), + OSSL_CMP_CTX_get0_statusString(ctx), + buf, bufsize); +} + +/*- * Creates a new PKIStatusInfo structure and fills it in * returns a pointer to the structure on success, NULL on error * note: strongly overlaps with TS_RESP_CTX_set_status_info() * and TS_RESP_CTX_add_failure_info() in ../ts/ts_rsp_sign.c */ -OSSL_CMP_PKISI *ossl_cmp_statusinfo_new(int status, int fail_info, +OSSL_CMP_PKISI *OSSL_CMP_STATUSINFO_new(int status, int fail_info, const char *text) { OSSL_CMP_PKISI *si = OSSL_CMP_PKISI_new(); diff --git a/crypto/cmp/cmp_util.c b/crypto/cmp/cmp_util.c index ad4ae664..121b6a17 100644 --- a/crypto/cmp/cmp_util.c +++ b/crypto/cmp/cmp_util.c @@ -144,7 +144,7 @@ int OSSL_CMP_print_to_bio(BIO *bio, const char *component, const char *file, #define ERR_PRINT_BUF_SIZE 4096 /* this is similar to ERR_print_errors_cb, but uses the CMP-specific cb type */ -void OSSL_CMP_print_errors_cb(OSSL_cmp_log_cb_t log_fn) +void OSSL_CMP_print_errors_cb(OSSL_CMP_log_cb_t log_fn) { unsigned long err; char msg[ERR_PRINT_BUF_SIZE]; @@ -320,6 +320,26 @@ STACK_OF(X509) *ossl_cmp_build_cert_chain(STACK_OF(X509) *certs, X509 *cert) return result; } +int ossl_cmp_sk_ASN1_UTF8STRING_push_str(STACK_OF(ASN1_UTF8STRING) *sk, + const char *text) +{ + ASN1_UTF8STRING *utf8string; + + if (!ossl_assert(sk != NULL && text != NULL)) + return 0; + if ((utf8string = ASN1_UTF8STRING_new()) == NULL) + return 0; + if (!ASN1_STRING_set(utf8string, text, -1)) + goto err; + if (!sk_ASN1_UTF8STRING_push(sk, utf8string)) + goto err; + return 1; + + err: + ASN1_UTF8STRING_free(utf8string); + return 0; +} + int ossl_cmp_asn1_octet_string_set1(ASN1_OCTET_STRING **tgt, const ASN1_OCTET_STRING *src) { diff --git a/crypto/cmp/cmp_vfy.c b/crypto/cmp/cmp_vfy.c index 437bc329..11688059 100644 --- a/crypto/cmp/cmp_vfy.c +++ b/crypto/cmp/cmp_vfy.c @@ -167,6 +167,8 @@ int OSSL_CMP_validate_cert_path(OSSL_CMP_CTX *ctx, X509_STORE *trusted_store, CMPerr(0, CMP_R_POTENTIALLY_INVALID_CERTIFICATE); err: + /* directly output any fresh errors, needed for check_msg_find_cert() */ + OSSL_CMP_CTX_print_errors(ctx); X509_STORE_CTX_free(csc); return valid; } @@ -250,17 +252,22 @@ static int cert_acceptable(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg) { X509_STORE *ts = ctx->trusted; - char *sub, *iss; + int self_issued = X509_check_issued(cert, cert) == X509_V_OK; + char *str; X509_VERIFY_PARAM *vpm = ts != NULL ? X509_STORE_get0_param(ts) : NULL; int time_cmp; - ossl_cmp_log2(INFO, ctx, " considering %s %s with..", desc1, desc2); - if ((sub = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0)) != NULL) - ossl_cmp_log1(INFO, ctx, " subject = %s", sub); - if ((iss = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0)) != NULL) - ossl_cmp_log1(INFO, ctx, " issuer = %s", iss); - OPENSSL_free(iss); - OPENSSL_free(sub); + ossl_cmp_log3(INFO, ctx, " considering %s%s %s with..", + self_issued ? "self-issued ": "", desc1, desc2); + if ((str = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0)) != NULL) + ossl_cmp_log1(INFO, ctx, " subject = %s", str); + OPENSSL_free(str); + if (!self_issued) { + str = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0); + if (str != NULL) + ossl_cmp_log1(INFO, ctx, " issuer = %s", str); + OPENSSL_free(str); + } if (already_checked(cert, already_checked1) || already_checked(cert, already_checked2)) { @@ -284,7 +291,7 @@ static int cert_acceptable(OSSL_CMP_CTX *ctx, if (!check_kid(ctx, cert, msg->header->senderKID)) return 0; /* acceptable also if there is no senderKID in msg header */ - ossl_cmp_info(ctx, " cert is acceptable"); + ossl_cmp_info(ctx, " cert seems acceptable"); return 1; } @@ -295,38 +302,49 @@ static int check_msg_valid_cert(OSSL_CMP_CTX *ctx, X509_STORE *store, ossl_cmp_warn(ctx, "msg signature verification failed"); return 0; } - if (!OSSL_CMP_validate_cert_path(ctx, store, scrt)) { - ossl_cmp_warn(ctx, "cert path validation failed"); - return 0; - } - return 1; + if (OSSL_CMP_validate_cert_path(ctx, store, scrt)) + return 1; + + ossl_cmp_warn(ctx, + "msg signature validates but cert path validation failed"); + return 0; } /* * Exceptional handling for 3GPP TS 33.310 [3G/LTE Network Domain Security - * (NDS); Authentication Framework (AF)], only to use for IP and if the ctx - * option is explicitly set: use self-issued certificates from extraCerts as - * trust anchor to validate sender cert and msg - + * (NDS); Authentication Framework (AF)], only to use for IP messages + * and if the ctx option is explicitly set: use self-issued certificates + * from extraCerts as trust anchor to validate sender cert and msg - * provided it also can validate the newly enrolled certificate */ static int check_msg_valid_cert_3gpp(OSSL_CMP_CTX *ctx, X509 *scrt, const OSSL_CMP_MSG *msg) { int valid = 0; - X509_STORE *store = X509_STORE_new(); + X509_STORE *store; - if (store != NULL /* store does not include CRLs */ - && ossl_cmp_X509_STORE_add1_certs(store, msg->extraCerts, - 1 /* self-issued only */)) - valid = check_msg_valid_cert(ctx, store, scrt, msg); - if (valid) { + if (!ctx->permitTAInExtraCertsForIR) + return 0; + + if ((store = X509_STORE_new()) == NULL + || !ossl_cmp_X509_STORE_add1_certs(store, msg->extraCerts, + 1 /* self-issued only */)) + goto err; + + /* store does not include CRLs */ + valid = OSSL_CMP_validate_cert_path(ctx, store, scrt); + if (!valid) { + ossl_cmp_warn(ctx, + "also exceptional 3GPP mode cert path validation failed"); + } else { /* - * verify that the newly enrolled certificate (which is assumed to have - * rid == 0) can also be validated with the same trusted store + * verify that the newly enrolled certificate (which assumed rid == + * OSSL_CMP_CERTREQID) can also be validated with the same trusted store */ EVP_PKEY *privkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1); OSSL_CMP_CERTRESPONSE *crep = - ossl_cmp_certrepmessage_get0_certresponse(msg->body->value.ip, 0); + ossl_cmp_certrepmessage_get0_certresponse(msg->body->value.ip, + OSSL_CMP_CERTREQID); X509 *newcrt = ossl_cmp_certresponse_get1_certificate(privkey, crep); /* * maybe better use get_cert_status() from cmp_client.c, which catches @@ -335,6 +353,8 @@ static int check_msg_valid_cert_3gpp(OSSL_CMP_CTX *ctx, X509 *scrt, valid = OSSL_CMP_validate_cert_path(ctx, store, newcrt); X509_free(newcrt); } + + err: X509_STORE_free(store); return valid; } @@ -393,8 +413,13 @@ static int check_msg_all_certs(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, { int ret = 0; + if (mode_3gpp + && ((!ctx->permitTAInExtraCertsForIR + || ossl_cmp_msg_get_bodytype(msg) != OSSL_CMP_PKIBODY_IP))) + return 0; + ossl_cmp_info(ctx, - mode_3gpp ? "failed; trying now 3GPP mode trusting extraCerts" + mode_3gpp ? "normal mode failed; trying now 3GPP mode trusting extraCerts" : "trying first normal mode using trust store"); if (check_msg_with_certs(ctx, msg->extraCerts, "extraCerts", NULL, NULL, msg, mode_3gpp)) @@ -418,6 +443,12 @@ static int check_msg_all_certs(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, return ret; } +static int no_log_cb(const char *func, const char *file, int line, + OSSL_CMP_severity level, const char *msg) +{ + return 1; +} + /* verify message signature with any acceptable and valid candidate cert */ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg) { @@ -426,7 +457,7 @@ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg) char *sname = NULL; char *skid_str = NULL; const ASN1_OCTET_STRING *skid = msg->header->senderKID; - OSSL_cmp_log_cb_t backup_log_cb = ctx->log_cb; + OSSL_CMP_log_cb_t backup_log_cb = ctx->log_cb; int res = 0; if (sender == NULL || msg->body == NULL) @@ -436,49 +467,52 @@ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg) return 0; } + /* dump any hitherto errors to avoid confusion when printing further ones */ + OSSL_CMP_CTX_print_errors(ctx); + /* * try first cached scrt, used successfully earlier in same transaction, * for validating this and any further msgs where extraCerts may be left out */ - (void)ERR_set_mark(); - if (scrt != NULL - && cert_acceptable(ctx, "previously validated", "sender cert", scrt, - NULL, NULL, msg) - && (check_msg_valid_cert(ctx, ctx->trusted, scrt, msg) + if (scrt != NULL) { + (void)ERR_set_mark(); + ossl_cmp_info(ctx, + "trying to verify msg signature with previously validated cert"); + if (cert_acceptable(ctx, "previously validated", "sender cert", scrt, + NULL, NULL, msg) + && (check_msg_valid_cert(ctx, ctx->trusted, scrt, msg) || check_msg_valid_cert_3gpp(ctx, scrt, msg))) { + (void)ERR_pop_to_mark(); + return 1; + } (void)ERR_pop_to_mark(); - return 1; + /* cached sender cert has shown to be no more successfully usable */ + (void)ossl_cmp_ctx_set0_validatedSrvCert(ctx, NULL); } - (void)ERR_pop_to_mark(); - - /* release any cached sender cert that proved no more successfully usable */ - (void)ossl_cmp_ctx_set0_validatedSrvCert(ctx, NULL); /* enable clearing irrelevant errors in attempts to validate sender certs */ (void)ERR_set_mark(); - ctx->log_cb = NULL; /* temporarily disable logging diagnostic info */ - - if (check_msg_all_certs(ctx, msg, 0 /* using ctx->trusted */) - || check_msg_all_certs(ctx, msg, 1 /* 3gpp */)) { - /* discard any diagnostic info on trying to use certs */ - ctx->log_cb = backup_log_cb; /* restore any logging */ + ctx->log_cb = no_log_cb; /* temporarily disable logging */ + res = check_msg_all_certs(ctx, msg, 0 /* using ctx->trusted */) + || check_msg_all_certs(ctx, msg, 1 /* 3gpp */); + ctx->log_cb = backup_log_cb; + if (res) { + /* discard any diagnostic information on trying to use certs */ (void)ERR_pop_to_mark(); - res = 1; goto end; } /* failed finding a sender cert that verifies the message signature */ - ctx->log_cb = backup_log_cb; /* restore any logging */ (void)ERR_clear_last_mark(); sname = X509_NAME_oneline(sender->d.directoryName, NULL, 0); skid_str = skid == NULL ? NULL : OPENSSL_buf2hexstr(skid->data, skid->length); if (ctx->log_cb != NULL) { - ossl_cmp_info(ctx, "verifying msg signature with valid cert that.."); + ossl_cmp_info(ctx, "trying to verify msg signature with a valid cert that.."); if (sname != NULL) - ossl_cmp_log1(INFO, ctx, "matches msg sender name = %s", sname); + ossl_cmp_log1(INFO, ctx, "matches msg sender = %s", sname); if (skid_str != NULL) - ossl_cmp_log1(INFO, ctx, "matches msg senderKID = %s", skid_str); + ossl_cmp_log1(INFO, ctx, "matches msg senderKID = %s", skid_str); else ossl_cmp_info(ctx, "while msg header does not contain senderKID"); /* re-do the above checks (just) for adding diagnostic information */ @@ -543,6 +577,11 @@ int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg) switch (nid) { /* 5.1.3.1. Shared Secret Information */ case NID_id_PasswordBasedMAC: + if (ctx->secretValue == 0) { + CMPerr(0, CMP_R_CHECKING_PBM_NO_SECRET_AVAILABLE); + break; + } + if (verify_PBMAC(msg, ctx->secretValue)) { /* * RFC 4210, 5.3.2: 'Note that if the PKI Message Protection is @@ -633,8 +672,8 @@ int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg) * * Ensures that: * it has a valid body type - * its protection is valid or absent (allowed only if callback function is - * present and function yields non-zero result using also supplied argument) + * its protection is valid (or invalid/absent, but only if a callback function + * is present and yields a positive result using also the supplied argument) * its transaction ID matches the previous transaction ID stored in ctx (if any) * its recipNonce matches the previous senderNonce stored in the ctx (if any) * @@ -660,35 +699,29 @@ int ossl_cmp_msg_check_received(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, if (msg->header->protectionAlg != 0) { /* detect explicitly permitted exceptions for invalid protection */ if (!OSSL_CMP_validate_msg(ctx, msg) - && (cb == NULL || !(*cb)(ctx, msg, 1, cb_arg))) { + && (cb == NULL || (*cb)(ctx, msg, 1, cb_arg) <= 0)) { CMPerr(0, CMP_R_ERROR_VALIDATING_PROTECTION); return -1; } } else { /* detect explicitly permitted exceptions for missing protection */ - if (cb == NULL || !(*cb)(ctx, msg, 0, cb_arg)) { + if (cb == NULL || (*cb)(ctx, msg, 0, cb_arg) <= 0) { CMPerr(0, CMP_R_MISSING_PROTECTION); return -1; } } - /* - * Store any provided extraCerts in ctx for future use, - * such that they are available to ctx->certConf_cb and - * the peer does not need to send them again in the same transaction. - * For efficiency, the extraCerts are prepended so they get used first. - */ - if (!ossl_cmp_sk_X509_add1_certs(ctx->untrusted_certs, msg->extraCerts, - 0 /* this allows self-issued certs */, - 1 /* no_dups */, 1 /* prepend */)) - return -1; - /* check CMP version number in header */ if (ossl_cmp_hdr_get_pvno(OSSL_CMP_MSG_get0_header(msg)) != OSSL_CMP_PVNO) { CMPerr(0, CMP_R_UNEXPECTED_PVNO); return -1; } + if ((rcvd_type = ossl_cmp_msg_get_bodytype(msg)) < 0) { + CMPerr(0, CMP_R_PKIBODY_ERROR); + return -1; + } + /* compare received transactionID with the expected one in previous msg */ if (ctx->transactionID != NULL && (msg->header->transactionID == NULL @@ -720,10 +753,17 @@ int ossl_cmp_msg_check_received(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, && !OSSL_CMP_CTX_set1_transactionID(ctx, msg->header->transactionID)) return -1; - if ((rcvd_type = ossl_cmp_msg_get_bodytype(msg)) < 0) { - CMPerr(0, CMP_R_PKIBODY_ERROR); + /* + * Store any provided extraCerts in ctx for future use, + * such that they are available to ctx->certConf_cb and + * the peer does not need to send them again in the same transaction. + * For efficiency, the extraCerts are prepended so they get used first. + */ + if (!ossl_cmp_sk_X509_add1_certs(ctx->untrusted_certs, msg->extraCerts, + 0 /* this allows self-issued certs */, + 1 /* no_dups */, 1 /* prepend */)) return -1; - } + return rcvd_type; } diff --git a/crypto/cms/cms_err.c b/crypto/cms/cms_err.c index 98500d7c..526d7735 100644 --- a/crypto/cms/cms_err.c +++ b/crypto/cms/cms_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/cms/cms_kari.c b/crypto/cms/cms_kari.c index 3299e9b5..a44aca65 100644 --- a/crypto/cms/cms_kari.c +++ b/crypto/cms/cms_kari.c @@ -248,6 +248,27 @@ int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms, size_t enckeylen; size_t ceklen; CMS_EncryptedContentInfo *ec; + + { + /* + * TODO(3.0) Remove this when we have functionality to deserialize + * parameters in EVP_PKEY form from an X509_ALGOR. + * This is needed to be able to replace the EC_KEY specific decoding + * that happens in ecdh_cms_set_peerkey() (crypto/ec/ec_ameth.c) + * + * THIS IS TEMPORARY + */ + EVP_PKEY_CTX *pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); + EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx); + + EVP_PKEY_get0(pkey); + if (EVP_PKEY_id(pkey) == EVP_PKEY_NONE) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_DECRYPT, + CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); + goto err; + } + } + enckeylen = rek->encryptedKey->length; enckey = rek->encryptedKey->data; /* Setup all parameters to derive KEK */ @@ -446,6 +467,32 @@ int cms_RecipientInfo_kari_encrypt(const CMS_ContentInfo *cms, STACK_OF(CMS_RecipientEncryptedKey) *reks; int i; + { + /* + * TODO(3.0) Remove this when we have figured out all the details + * need to set up encryption right. With legacy keys, a *lot* is + * happening in the CMS specific EVP_PKEY_ASN1_METHOD functions, + * such as automatically setting a default KDF type, KDF digest, + * all that kind of stuff. + * With EVP_SIGNATURE, setting a default digest is done by getting + * the default MD for the key, and then inject that back into the + * signature implementation... we could do something similar with + * CMS, possibly using CMS specific OSSL_PARAM keys, just like we + * have for certain AlgorithmIdentifier retrievals. + * + * THIS IS TEMPORARY + */ + EVP_PKEY_CTX *pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); + EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx); + + EVP_PKEY_get0(pkey); + if (EVP_PKEY_id(pkey) == EVP_PKEY_NONE) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT, + CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); + return 0; + } + } + if (ri->type != CMS_RECIPINFO_AGREE) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT, CMS_R_NOT_KEY_AGREEMENT); return 0; diff --git a/crypto/conf/conf_lib.c b/crypto/conf/conf_lib.c index 833b7a65..c06718d2 100644 --- a/crypto/conf/conf_lib.c +++ b/crypto/conf/conf_lib.c @@ -174,7 +174,7 @@ int CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out) * the "CONF classic" functions, for consistency. */ -CONF *NCONF_new(CONF_METHOD *meth) +CONF *NCONF_new_with_libctx(OPENSSL_CTX *libctx, CONF_METHOD *meth) { CONF *ret; @@ -183,13 +183,19 @@ CONF *NCONF_new(CONF_METHOD *meth) ret = meth->create(meth); if (ret == NULL) { - CONFerr(CONF_F_NCONF_NEW, ERR_R_MALLOC_FAILURE); + CONFerr(0, ERR_R_MALLOC_FAILURE); return NULL; } + ret->libctx = libctx; return ret; } +CONF *NCONF_new(CONF_METHOD *meth) +{ + return NCONF_new_with_libctx(NULL, meth); +} + void NCONF_free(CONF *conf) { if (conf == NULL) diff --git a/crypto/conf/conf_mod.c b/crypto/conf/conf_mod.c index 86924c1b..2bbf43b9 100644 --- a/crypto/conf/conf_mod.c +++ b/crypto/conf/conf_mod.c @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -13,8 +13,10 @@ #include #include "internal/conf.h" #include "internal/dso.h" +#include "internal/thread_once.h" #include #include +#include #define DSO_mod_init_name "OPENSSL_init" #define DSO_mod_finish_name "OPENSSL_finish" @@ -55,6 +57,8 @@ struct conf_imodule_st { static STACK_OF(CONF_MODULE) *supported_modules = NULL; static STACK_OF(CONF_IMODULE) *initialized_modules = NULL; +static CRYPTO_ONCE load_builtin_modules = CRYPTO_ONCE_STATIC_INIT; + static void module_free(CONF_MODULE *md); static void module_finish(CONF_IMODULE *imod); static int module_run(const CONF *cnf, const char *name, const char *value, @@ -113,22 +117,25 @@ int CONF_modules_load(const CONF *cnf, const char *appname, } -int CONF_modules_load_file(const char *filename, const char *appname, - unsigned long flags) +int CONF_modules_load_file_with_libctx(OPENSSL_CTX *libctx, + const char *filename, + const char *appname, unsigned long flags) { char *file = NULL; CONF *conf = NULL; int ret = 0; - conf = NCONF_new(NULL); + + conf = NCONF_new_with_libctx(libctx, NULL); if (conf == NULL) goto err; if (filename == NULL) { file = CONF_get1_default_config_file(); - if (!file) + if (file == NULL) goto err; - } else + } else { file = (char *)filename; + } if (NCONF_load(conf, file, NULL) <= 0) { if ((flags & CONF_MFLAGS_IGNORE_MISSING_FILE) && @@ -152,12 +159,32 @@ int CONF_modules_load_file(const char *filename, const char *appname, return ret; } +int CONF_modules_load_file(const char *filename, + const char *appname, unsigned long flags) +{ + return CONF_modules_load_file_with_libctx(NULL, filename, appname, flags); +} + +DEFINE_RUN_ONCE_STATIC(do_load_builtin_modules) +{ + OPENSSL_load_builtin_modules(); +#ifndef OPENSSL_NO_ENGINE + /* Need to load ENGINEs */ + ENGINE_load_builtin_engines(); +#endif + ERR_clear_error(); + return 1; +} + static int module_run(const CONF *cnf, const char *name, const char *value, unsigned long flags) { CONF_MODULE *md; int ret; + if (!RUN_ONCE(&load_builtin_modules, do_load_builtin_modules)) + return -1; + md = module_find(name); /* Module not found: try to load DSO */ diff --git a/crypto/conf/conf_sap.c b/crypto/conf/conf_sap.c index 2c5ee2a1..f6288962 100644 --- a/crypto/conf/conf_sap.c +++ b/crypto/conf/conf_sap.c @@ -59,12 +59,6 @@ int openssl_config_int(const OPENSSL_INIT_SETTINGS *settings) filename, appname, flags); #endif - OPENSSL_load_builtin_modules(); -#ifndef OPENSSL_NO_ENGINE - /* Need to load ENGINEs */ - ENGINE_load_builtin_engines(); -#endif - ERR_clear_error(); #ifndef OPENSSL_SYS_UEFI ret = CONF_modules_load_file(filename, appname, flags); #endif diff --git a/crypto/context.c b/crypto/context.c index 02fecf9f..35530174 100644 --- a/crypto/context.c +++ b/crypto/context.c @@ -8,6 +8,7 @@ */ #include "crypto/cryptlib.h" +#include #include "internal/thread_once.h" #include "internal/property.h" @@ -145,6 +146,13 @@ OPENSSL_CTX *OPENSSL_CTX_new(void) return ctx; } +#ifndef FIPS_MODE +int OPENSSL_CTX_load_config(OPENSSL_CTX *ctx, const char *config_file) +{ + return CONF_modules_load_file_with_libctx(ctx, config_file, NULL, 0) > 0; +} +#endif + void OPENSSL_CTX_free(OPENSSL_CTX *ctx) { if (ctx != NULL) @@ -164,6 +172,15 @@ OPENSSL_CTX *openssl_ctx_get_concrete(OPENSSL_CTX *ctx) return ctx; } +int openssl_ctx_is_default(OPENSSL_CTX *ctx) +{ +#ifndef FIPS_MODE + if (ctx == NULL || ctx == default_context) + return 1; +#endif + return 0; +} + static void openssl_ctx_generic_new(void *parent_ign, void *ptr_ign, CRYPTO_EX_DATA *ad, int index, long argl_ign, void *argp) diff --git a/crypto/crmf/crmf_err.c b/crypto/crmf/crmf_err.c index 87e6a2da..159d5b2c 100644 --- a/crypto/crmf/crmf_err.c +++ b/crypto/crmf/crmf_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -30,6 +30,15 @@ static const ERR_STRING_DATA CRMF_str_reasons[] = { "iterationcount below 100"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_MALFORMED_IV), "malformed iv"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_NULL_ARGUMENT), "null argument"}, + {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY), + "popo inconsistent public key"}, + {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_MISSING), "popo missing"}, + {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_MISSING_PUBLIC_KEY), + "popo missing public key"}, + {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_MISSING_SUBJECT), + "popo missing subject"}, + {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED), + "popo raverified not accepted"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_SETTING_MAC_ALGOR_FAILURE), "setting mac algor failure"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_SETTING_OWF_ALGOR_FAILURE), @@ -44,8 +53,6 @@ static const ERR_STRING_DATA CRMF_str_reasons[] = { "unsupported method for creating popo"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_POPO_METHOD), "unsupported popo method"}, - {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_POPO_NOT_ACCEPTED), - "unsupported popo not accepted"}, {0, NULL} }; diff --git a/crypto/crmf/crmf_lib.c b/crypto/crmf/crmf_lib.c index 4d815692..5058f7d2 100644 --- a/crypto/crmf/crmf_lib.c +++ b/crypto/crmf/crmf_lib.c @@ -303,7 +303,7 @@ static int crmf_asn1_get_int(const ASN1_INTEGER *a) return (int)res; } -int OSSL_CRMF_MSG_get_certReqId(OSSL_CRMF_MSG *crm) +int OSSL_CRMF_MSG_get_certReqId(const OSSL_CRMF_MSG *crm) { if (crm == NULL || /* not really needed: */ crm->certReq == NULL) { CRMFerr(CRMF_F_OSSL_CRMF_MSG_GET_CERTREQID, CRMF_R_NULL_ARGUMENT); @@ -367,65 +367,30 @@ static int CRMF_poposigningkey_init(OSSL_CRMF_POPOSIGNINGKEY *ps, OSSL_CRMF_CERTREQUEST *cr, EVP_PKEY *pkey, int dgst) { - int len; - size_t crlen; - size_t siglen; - unsigned char *crder = NULL, *sig = NULL; - int alg_nid = 0; - int md_nid = 0; - const EVP_MD *alg = NULL; - EVP_MD_CTX *ctx = NULL; int ret = 0; + EVP_MD *fetched_md = NULL; + const EVP_MD *md = EVP_get_digestbynid(dgst); if (ps == NULL || cr == NULL || pkey == NULL) { CRMFerr(CRMF_F_CRMF_POPOSIGNINGKEY_INIT, CRMF_R_NULL_ARGUMENT); return 0; } - /* OpenSSL defaults all bit strings to be encoded as ASN.1 NamedBitList */ - ps->signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - ps->signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; + /* If we didn't find legacy MD, we try an implicit fetch */ + if (md == NULL) + md = fetched_md = EVP_MD_fetch(NULL, OBJ_nid2sn(dgst), NULL); - len = i2d_OSSL_CRMF_CERTREQUEST(cr, &crder); - if (len < 0 || crder == NULL) { - CRMFerr(CRMF_F_CRMF_POPOSIGNINGKEY_INIT, CRMF_R_ERROR); - goto err; - } - crlen = (size_t)len; - - if (!OBJ_find_sigid_by_algs(&alg_nid, dgst, EVP_PKEY_id(pkey))) { + if (md == NULL) { CRMFerr(CRMF_F_CRMF_POPOSIGNINGKEY_INIT, CRMF_R_UNSUPPORTED_ALG_FOR_POPSIGNINGKEY); - goto err; + return 0; } - if (!OBJ_find_sigid_algs(alg_nid, &md_nid, NULL) - || (alg = EVP_get_digestbynid(md_nid)) == NULL) { - CRMFerr(CRMF_F_CRMF_POPOSIGNINGKEY_INIT, - CRMF_R_UNSUPPORTED_ALG_FOR_POPSIGNINGKEY); - goto err; - } - if (!X509_ALGOR_set0(ps->algorithmIdentifier, OBJ_nid2obj(alg_nid), - V_ASN1_NULL, NULL) - || (ctx = EVP_MD_CTX_new()) == NULL - || EVP_DigestSignInit(ctx, NULL, alg, NULL, pkey) <= 0 - || EVP_DigestSignUpdate(ctx, crder, crlen) <= 0 - || EVP_DigestSignFinal(ctx, NULL, &siglen) <= 0) { - CRMFerr(CRMF_F_CRMF_POPOSIGNINGKEY_INIT, CRMF_R_ERROR); - goto err; - } - if ((sig = OPENSSL_malloc(siglen)) == NULL) - goto err; - if (EVP_DigestSignFinal(ctx, sig, &siglen) <= 0 - || !ASN1_BIT_STRING_set(ps->signature, sig, siglen)) { - CRMFerr(CRMF_F_CRMF_POPOSIGNINGKEY_INIT, CRMF_R_ERROR); - goto err; - } - ret = 1; - err: - OPENSSL_free(crder); - EVP_MD_CTX_free(ctx); - OPENSSL_free(sig); + ret = ASN1_item_sign(ASN1_ITEM_rptr(OSSL_CRMF_CERTREQUEST), + ps->algorithmIdentifier, NULL, ps->signature, + cr, pkey, md); + + EVP_MD_free(fetched_md); return ret; } @@ -520,21 +485,29 @@ int OSSL_CRMF_MSGS_verify_popo(const OSSL_CRMF_MSGS *reqs, X509_PUBKEY *pubkey = NULL; OSSL_CRMF_POPOSIGNINGKEY *sig = NULL; - if (reqs == NULL - || (req = sk_OSSL_CRMF_MSG_value(reqs, rid)) == NULL - || req->popo == NULL) { - CRMFerr(CRMF_F_OSSL_CRMF_MSGS_VERIFY_POPO, - CRMF_R_NULL_ARGUMENT); + if (reqs == NULL || (req = sk_OSSL_CRMF_MSG_value(reqs, rid)) == NULL) { + CRMFerr(CRMF_F_OSSL_CRMF_MSGS_VERIFY_POPO, CRMF_R_NULL_ARGUMENT); + return 0; + } + + if (req->popo == NULL) { + CRMFerr(0, CRMF_R_POPO_MISSING); return 0; } switch (req->popo->type) { case OSSL_CRMF_POPO_RAVERIFIED: - if (acceptRAVerified) - return 1; + if (!acceptRAVerified) { + CRMFerr(0, CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED); + return 0; + } break; case OSSL_CRMF_POPO_SIGNATURE: pubkey = req->certReq->certTemplate->publicKey; + if (pubkey == NULL) { + CRMFerr(0, CRMF_R_POPO_MISSING_PUBLIC_KEY); + return 0; + } sig = req->popo->value.signature; if (sig->poposkInput != NULL) { /* @@ -542,26 +515,34 @@ int OSSL_CRMF_MSGS_verify_popo(const OSSL_CRMF_MSGS *reqs, * the public key from the certificate template. This MUST be * exactly the same value as contained in the certificate template. */ - const ASN1_ITEM *rptr = ASN1_ITEM_rptr(OSSL_CRMF_POPOSIGNINGKEYINPUT); - - if (pubkey == NULL - || sig->poposkInput->publicKey == NULL - || X509_PUBKEY_cmp(pubkey, sig->poposkInput->publicKey) - || ASN1_item_verify(rptr, sig->algorithmIdentifier, - sig->signature, sig->poposkInput, - X509_PUBKEY_get0(pubkey)) < 1) - break; + if (sig->poposkInput->publicKey == NULL) { + CRMFerr(0, CRMF_R_POPO_MISSING_PUBLIC_KEY); + return 0; + } + if (X509_PUBKEY_cmp(pubkey, sig->poposkInput->publicKey) != 0) { + CRMFerr(0, CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY); + return 0; + } + /* + * TODO check the contents of the authInfo sub-field, + * see RFC 4211 https://tools.ietf.org/html/rfc4211#section-4.1 + */ + if (ASN1_item_verify(ASN1_ITEM_rptr(OSSL_CRMF_POPOSIGNINGKEYINPUT), + sig->algorithmIdentifier, sig->signature, + sig->poposkInput, + X509_PUBKEY_get0(pubkey)) < 1) + return 0; } else { - if (pubkey == NULL - || req->certReq->certTemplate->subject == NULL - || ASN1_item_verify(ASN1_ITEM_rptr(OSSL_CRMF_CERTREQUEST), - sig->algorithmIdentifier, - sig->signature, - req->certReq, - X509_PUBKEY_get0(pubkey)) < 1) - break; + if (req->certReq->certTemplate->subject == NULL) { + CRMFerr(0, CRMF_R_POPO_MISSING_SUBJECT); + return 0; + } + if (ASN1_item_verify(ASN1_ITEM_rptr(OSSL_CRMF_CERTREQUEST), + sig->algorithmIdentifier, sig->signature, + req->certReq, X509_PUBKEY_get0(pubkey)) < 1) + return 0; } - return 1; + break; case OSSL_CRMF_POPO_KEYENC: /* * TODO: when OSSL_CMP_certrep_new() supports encrypted certs, @@ -575,25 +556,25 @@ int OSSL_CRMF_MSGS_verify_popo(const OSSL_CRMF_MSGS *reqs, CRMF_R_UNSUPPORTED_POPO_METHOD); return 0; } - CRMFerr(CRMF_F_OSSL_CRMF_MSGS_VERIFY_POPO, - CRMF_R_UNSUPPORTED_POPO_NOT_ACCEPTED); - return 0; + return 1; } /* retrieves the serialNumber of the given cert template or NULL on error */ -ASN1_INTEGER *OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(OSSL_CRMF_CERTTEMPLATE *tmpl) +ASN1_INTEGER +*OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(const OSSL_CRMF_CERTTEMPLATE *tmpl) { return tmpl != NULL ? tmpl->serialNumber : NULL; } /* retrieves the issuer name of the given cert template or NULL on error */ -X509_NAME *OSSL_CRMF_CERTTEMPLATE_get0_issuer(OSSL_CRMF_CERTTEMPLATE *tmpl) +const X509_NAME + *OSSL_CRMF_CERTTEMPLATE_get0_issuer(const OSSL_CRMF_CERTTEMPLATE *tmpl) { return tmpl != NULL ? tmpl->issuer : NULL; } /* retrieves the issuer name of the given CertId or NULL on error */ -X509_NAME *OSSL_CRMF_CERTID_get0_issuer(const OSSL_CRMF_CERTID *cid) +const X509_NAME *OSSL_CRMF_CERTID_get0_issuer(const OSSL_CRMF_CERTID *cid) { return cid != NULL && cid->issuer->type == GEN_DIRNAME ? cid->issuer->d.directoryName : NULL; @@ -619,9 +600,9 @@ int OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_CERTTEMPLATE *tmpl, CRMFerr(CRMF_F_OSSL_CRMF_CERTTEMPLATE_FILL, CRMF_R_NULL_ARGUMENT); return 0; } - if (subject != NULL && !X509_NAME_set(&tmpl->subject, subject)) + if (subject != NULL && !X509_NAME_set((X509_NAME **)&tmpl->subject, subject)) return 0; - if (issuer != NULL && !X509_NAME_set(&tmpl->issuer, issuer)) + if (issuer != NULL && !X509_NAME_set((X509_NAME **)&tmpl->issuer, issuer)) return 0; if (serial != NULL) { ASN1_INTEGER_free(tmpl->serialNumber); @@ -641,7 +622,7 @@ int OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_CERTTEMPLATE *tmpl, * returns a pointer to the decrypted certificate * returns NULL on error or if no certificate available */ -X509 *OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(OSSL_CRMF_ENCRYPTEDVALUE *ecert, +X509 *OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(const OSSL_CRMF_ENCRYPTEDVALUE *ecert, EVP_PKEY *pkey) { X509 *cert = NULL; /* decrypted certificate */ diff --git a/crypto/crmf/crmf_local.h b/crypto/crmf/crmf_local.h index 3f3f75cf..3b9cbba8 100644 --- a/crypto/crmf/crmf_local.h +++ b/crypto/crmf/crmf_local.h @@ -315,9 +315,9 @@ struct ossl_crmf_certtemplate_st { /* This field is assigned by the CA during certificate creation */ X509_ALGOR *signingAlg; /* signingAlg MUST be omitted */ /* This field is assigned by the CA during certificate creation */ - X509_NAME *issuer; + const X509_NAME *issuer; OSSL_CRMF_OPTIONALVALIDITY *validity; - X509_NAME *subject; + const X509_NAME *subject; X509_PUBKEY *publicKey; ASN1_BIT_STRING *issuerUID; /* deprecated in version 2 */ /* According to rfc 3280: UniqueIdentifier ::= BIT STRING */ diff --git a/crypto/ct/ct_b64.c b/crypto/ct/ct_b64.c index f0800882..2e00cf3e 100644 --- a/crypto/ct/ct_b64.c +++ b/crypto/ct/ct_b64.c @@ -132,7 +132,9 @@ SCT *SCT_new_from_base64(unsigned char version, const char *logid_base64, * 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) +int CTLOG_new_from_base64_with_libctx(CTLOG **ct_log, const char *pkey_base64, + const char *name, OPENSSL_CTX *libctx, + const char *propq) { unsigned char *pkey_der = NULL; int pkey_der_len; @@ -140,13 +142,13 @@ int CTLOG_new_from_base64(CTLOG **ct_log, const char *pkey_base64, const char *n EVP_PKEY *pkey = NULL; if (ct_log == NULL) { - CTerr(CT_F_CTLOG_NEW_FROM_BASE64, ERR_R_PASSED_INVALID_ARGUMENT); + CTerr(0, ERR_R_PASSED_INVALID_ARGUMENT); return 0; } pkey_der_len = ct_base64_decode(pkey_base64, &pkey_der); if (pkey_der_len < 0) { - CTerr(CT_F_CTLOG_NEW_FROM_BASE64, CT_R_LOG_CONF_INVALID_KEY); + CTerr(0, CT_R_LOG_CONF_INVALID_KEY); return 0; } @@ -154,11 +156,11 @@ int CTLOG_new_from_base64(CTLOG **ct_log, const char *pkey_base64, const char *n pkey = d2i_PUBKEY(NULL, &p, pkey_der_len); OPENSSL_free(pkey_der); if (pkey == NULL) { - CTerr(CT_F_CTLOG_NEW_FROM_BASE64, CT_R_LOG_CONF_INVALID_KEY); + CTerr(0, CT_R_LOG_CONF_INVALID_KEY); return 0; } - *ct_log = CTLOG_new(pkey, name); + *ct_log = CTLOG_new_with_libctx(pkey, name, libctx, propq); if (*ct_log == NULL) { EVP_PKEY_free(pkey); return 0; @@ -166,3 +168,10 @@ int CTLOG_new_from_base64(CTLOG **ct_log, const char *pkey_base64, const char *n return 1; } + +int CTLOG_new_from_base64(CTLOG **ct_log, const char *pkey_base64, + const char *name) +{ + return CTLOG_new_from_base64_with_libctx(ct_log, pkey_base64, name, NULL, + NULL); +} diff --git a/crypto/ct/ct_local.h b/crypto/ct/ct_local.h index 456217db..0df2f37f 100644 --- a/crypto/ct/ct_local.h +++ b/crypto/ct/ct_local.h @@ -100,6 +100,9 @@ struct sct_ctx_st { size_t prederlen; /* milliseconds since epoch (to check that the SCT isn't from the future) */ uint64_t epoch_time_in_ms; + + OPENSSL_CTX *libctx; + char *propq; }; /* Context when evaluating whether a Certificate Transparency policy is met */ @@ -109,12 +112,15 @@ struct ct_policy_eval_ctx_st { CTLOG_STORE *log_store; /* milliseconds since epoch (to check that SCTs aren't from the future) */ uint64_t epoch_time_in_ms; + + OPENSSL_CTX *libctx; + char *propq; }; /* * Creates a new context for verifying an SCT. */ -SCT_CTX *SCT_CTX_new(void); +SCT_CTX *SCT_CTX_new(OPENSSL_CTX *ctx, const char *propq); /* * Deletes an SCT verification context. */ diff --git a/crypto/ct/ct_log.c b/crypto/ct/ct_log.c index 695221cb..3da71c32 100644 --- a/crypto/ct/ct_log.c +++ b/crypto/ct/ct_log.c @@ -22,6 +22,8 @@ * Information about a CT log server. */ struct ctlog_st { + OPENSSL_CTX *libctx; + char *propq; char *name; uint8_t log_id[CT_V1_HASHLEN]; EVP_PKEY *public_key; @@ -32,6 +34,8 @@ struct ctlog_st { * It takes ownership of any CTLOG instances added to it. */ struct ctlog_store_st { + OPENSSL_CTX *libctx; + char *propq; STACK_OF(CTLOG) *logs; }; @@ -70,53 +74,78 @@ static void ctlog_store_load_ctx_free(CTLOG_STORE_LOAD_CTX* 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]) +static int ct_v1_log_id_from_pkey(CTLOG *log, EVP_PKEY *pkey) { int ret = 0; unsigned char *pkey_der = NULL; int pkey_der_len = i2d_PUBKEY(pkey, &pkey_der); unsigned int len; + EVP_MD *sha256 = NULL; if (pkey_der_len <= 0) { CTerr(CT_F_CT_V1_LOG_ID_FROM_PKEY, CT_R_LOG_KEY_INVALID); goto err; } + sha256 = EVP_MD_fetch(log->libctx, "SHA2-256", log->propq); + if (sha256 == NULL) { + CTerr(CT_F_CT_V1_LOG_ID_FROM_PKEY, ERR_LIB_EVP); + goto err; + } - ret = EVP_Digest(pkey_der, pkey_der_len, log_id, &len, EVP_sha256(), NULL); + ret = EVP_Digest(pkey_der, pkey_der_len, log->log_id, &len, sha256, + NULL); err: + EVP_MD_free(sha256); OPENSSL_free(pkey_der); return ret; } -CTLOG_STORE *CTLOG_STORE_new(void) +CTLOG_STORE *CTLOG_STORE_new_with_libctx(OPENSSL_CTX *libctx, const char *propq) { CTLOG_STORE *ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { - CTerr(CT_F_CTLOG_STORE_NEW, ERR_R_MALLOC_FAILURE); + CTerr(0, ERR_R_MALLOC_FAILURE); return NULL; } + ret->libctx = libctx; + if (propq != NULL) { + ret->propq = OPENSSL_strdup(propq); + if (ret->propq == NULL) { + CTerr(0, ERR_R_MALLOC_FAILURE); + goto err; + } + } + ret->logs = sk_CTLOG_new_null(); - if (ret->logs == NULL) + if (ret->logs == NULL) { + CTerr(0, ERR_R_MALLOC_FAILURE); goto err; + } return ret; err: - OPENSSL_free(ret); + CTLOG_STORE_free(ret); return NULL; } +CTLOG_STORE *CTLOG_STORE_new(void) +{ + return CTLOG_STORE_new_with_libctx(NULL, NULL); +} + void CTLOG_STORE_free(CTLOG_STORE *store) { if (store != NULL) { + OPENSSL_free(store->propq); sk_CTLOG_pop_free(store->logs, CTLOG_free); OPENSSL_free(store); } } -static int ctlog_new_from_conf(CTLOG **ct_log, const CONF *conf, const char *section) +static int ctlog_new_from_conf(CTLOG_STORE *store, CTLOG **ct_log, + const CONF *conf, const char *section) { const char *description = NCONF_get_string(conf, section, "description"); char *pkey_base64; @@ -132,7 +161,8 @@ static int ctlog_new_from_conf(CTLOG **ct_log, const CONF *conf, const char *sec return 0; } - return CTLOG_new_from_base64(ct_log, pkey_base64, description); + return CTLOG_new_from_base64_with_libctx(ct_log, pkey_base64, description, + store->libctx, store->propq); } int CTLOG_STORE_load_default_file(CTLOG_STORE *store) @@ -168,7 +198,7 @@ static int ctlog_store_load_log(const char *log_name, int log_name_len, if (tmp == NULL) goto mem_err; - ret = ctlog_new_from_conf(&ct_log, load_ctx->conf, tmp); + ret = ctlog_new_from_conf(load_ctx->log_store, &ct_log, load_ctx->conf, tmp); OPENSSL_free(tmp); if (ret < 0) { @@ -234,22 +264,32 @@ end: * Takes ownership of the public key. * Copies the name. */ -CTLOG *CTLOG_new(EVP_PKEY *public_key, const char *name) +CTLOG *CTLOG_new_with_libctx(EVP_PKEY *public_key, const char *name, + OPENSSL_CTX *libctx, const char *propq) { CTLOG *ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { - CTerr(CT_F_CTLOG_NEW, ERR_R_MALLOC_FAILURE); + CTerr(0, ERR_R_MALLOC_FAILURE); return NULL; } + ret->libctx = libctx; + if (propq != NULL) { + ret->name = OPENSSL_strdup(propq); + if (ret->propq == NULL) { + CTerr(0, ERR_R_MALLOC_FAILURE); + goto err; + } + } + ret->name = OPENSSL_strdup(name); if (ret->name == NULL) { - CTerr(CT_F_CTLOG_NEW, ERR_R_MALLOC_FAILURE); + CTerr(0, ERR_R_MALLOC_FAILURE); goto err; } - if (ct_v1_log_id_from_pkey(public_key, ret->log_id) != 1) + if (ct_v1_log_id_from_pkey(ret, public_key) != 1) goto err; ret->public_key = public_key; @@ -259,12 +299,18 @@ err: return NULL; } +CTLOG *CTLOG_new(EVP_PKEY *public_key, const char *name) +{ + return CTLOG_new_with_libctx(public_key, name, NULL, NULL); +} + /* Frees CT log and associated structures */ void CTLOG_free(CTLOG *log) { if (log != NULL) { OPENSSL_free(log->name); EVP_PKEY_free(log->public_key); + OPENSSL_free(log->propq); OPENSSL_free(log); } } diff --git a/crypto/ct/ct_policy.c b/crypto/ct/ct_policy.c index 0305970a..568d8e6d 100644 --- a/crypto/ct/ct_policy.c +++ b/crypto/ct/ct_policy.c @@ -25,15 +25,25 @@ */ static const time_t SCT_CLOCK_DRIFT_TOLERANCE = 300; -CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void) +CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new_with_libctx(OPENSSL_CTX *libctx, + const char *propq) { CT_POLICY_EVAL_CTX *ctx = OPENSSL_zalloc(sizeof(CT_POLICY_EVAL_CTX)); if (ctx == NULL) { - CTerr(CT_F_CT_POLICY_EVAL_CTX_NEW, ERR_R_MALLOC_FAILURE); + CTerr(0, ERR_R_MALLOC_FAILURE); return NULL; } + ctx->libctx = libctx; + if (propq != NULL) { + ctx->propq = OPENSSL_strdup(propq); + if (ctx->propq == NULL) { + CTerr(0, ERR_R_MALLOC_FAILURE); + return NULL; + } + } + /* 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; @@ -41,12 +51,18 @@ CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void) return ctx; } +CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void) +{ + return CT_POLICY_EVAL_CTX_new_with_libctx(NULL, NULL); +} + void CT_POLICY_EVAL_CTX_free(CT_POLICY_EVAL_CTX *ctx) { if (ctx == NULL) return; X509_free(ctx->cert); X509_free(ctx->issuer); + OPENSSL_free(ctx->propq); OPENSSL_free(ctx); } diff --git a/crypto/ct/ct_sct.c b/crypto/ct/ct_sct.c index bd510d9e..aecaf9e1 100644 --- a/crypto/ct/ct_sct.c +++ b/crypto/ct/ct_sct.c @@ -312,7 +312,7 @@ int SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx) return 0; } - sctx = SCT_CTX_new(); + sctx = SCT_CTX_new(ctx->libctx, ctx->propq); if (sctx == NULL) goto err; diff --git a/crypto/ct/ct_sct_ctx.c b/crypto/ct/ct_sct_ctx.c index aa9d2d75..f8ed6b8d 100644 --- a/crypto/ct/ct_sct_ctx.c +++ b/crypto/ct/ct_sct_ctx.c @@ -20,13 +20,23 @@ #include "ct_local.h" -SCT_CTX *SCT_CTX_new(void) +SCT_CTX *SCT_CTX_new(OPENSSL_CTX *libctx, const char *propq) { SCT_CTX *sctx = OPENSSL_zalloc(sizeof(*sctx)); if (sctx == NULL) CTerr(CT_F_SCT_CTX_NEW, ERR_R_MALLOC_FAILURE); + sctx->libctx = libctx; + if (propq != NULL) { + sctx->propq = OPENSSL_strdup(propq); + if (sctx->propq == NULL) { + CTerr(CT_F_SCT_CTX_NEW, ERR_R_MALLOC_FAILURE); + OPENSSL_free(sctx); + return NULL; + } + } + return sctx; } @@ -39,6 +49,7 @@ void SCT_CTX_free(SCT_CTX *sctx) OPENSSL_free(sctx->ihash); OPENSSL_free(sctx->certder); OPENSSL_free(sctx->preder); + OPENSSL_free(sctx->propq); OPENSSL_free(sctx); } @@ -191,13 +202,17 @@ err: return 0; } -__owur static int ct_public_key_hash(X509_PUBKEY *pkey, unsigned char **hash, - size_t *hash_len) +__owur static int ct_public_key_hash(SCT_CTX *sctx, 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; + EVP_MD *sha256 = EVP_MD_fetch(sctx->libctx, "SHA2-256", sctx->propq); + + if (sha256 == NULL) + goto err; /* Reuse buffer if possible */ if (*hash != NULL && *hash_len >= SHA256_DIGEST_LENGTH) { @@ -213,7 +228,7 @@ __owur static int ct_public_key_hash(X509_PUBKEY *pkey, unsigned char **hash, if (der_len <= 0) goto err; - if (!EVP_Digest(der, der_len, md, &md_len, EVP_sha256(), NULL)) + if (!EVP_Digest(der, der_len, md, &md_len, sha256, NULL)) goto err; if (md != *hash) { @@ -225,6 +240,7 @@ __owur static int ct_public_key_hash(X509_PUBKEY *pkey, unsigned char **hash, md = NULL; ret = 1; err: + EVP_MD_free(sha256); OPENSSL_free(md); OPENSSL_free(der); return ret; @@ -237,7 +253,7 @@ int SCT_CTX_set1_issuer(SCT_CTX *sctx, const X509 *issuer) int SCT_CTX_set1_issuer_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey) { - return ct_public_key_hash(pubkey, &sctx->ihash, &sctx->ihashlen); + return ct_public_key_hash(sctx, pubkey, &sctx->ihash, &sctx->ihashlen); } int SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey) @@ -247,7 +263,7 @@ int SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey) if (pkey == NULL) return 0; - if (!ct_public_key_hash(pubkey, &sctx->pkeyhash, &sctx->pkeyhashlen)) { + if (!ct_public_key_hash(sctx, pubkey, &sctx->pkeyhash, &sctx->pkeyhashlen)) { EVP_PKEY_free(pkey); return 0; } diff --git a/crypto/ct/ct_vfy.c b/crypto/ct/ct_vfy.c index f206edd0..1a143241 100644 --- a/crypto/ct/ct_vfy.c +++ b/crypto/ct/ct_vfy.c @@ -122,7 +122,8 @@ int SCT_CTX_verify(const SCT_CTX *sctx, const SCT *sct) if (ctx == NULL) goto end; - if (!EVP_DigestVerifyInit(ctx, NULL, EVP_sha256(), NULL, sctx->pkey)) + if (!EVP_DigestVerifyInit_ex(ctx, NULL, "SHA2-256", sctx->propq, sctx->pkey, + sctx->libctx)) goto end; if (!sct_ctx_update(ctx, sctx, sct)) diff --git a/crypto/der_writer.c b/crypto/der_writer.c new file mode 100644 index 00000000..26fd8859 --- /dev/null +++ b/crypto/der_writer.c @@ -0,0 +1,142 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include "internal/der.h" +#include "crypto/bn.h" + +static int int_start_context(WPACKET *pkt, int tag) +{ + if (tag < 0) + return 1; + if (!ossl_assert(tag <= 30)) + return 0; + return WPACKET_start_sub_packet(pkt); +} + +static int int_end_context(WPACKET *pkt, int tag) +{ + if (tag < 0) + return 1; + if (!ossl_assert(tag <= 30)) + return 0; + return WPACKET_close(pkt) + && WPACKET_put_bytes_u8(pkt, DER_C_CONTEXT | tag); +} + +int DER_w_precompiled(WPACKET *pkt, int tag, + const unsigned char *precompiled, size_t precompiled_n) +{ + return int_start_context(pkt, tag) + && WPACKET_memcpy(pkt, precompiled, precompiled_n) + && int_end_context(pkt, tag); +} + +int DER_w_boolean(WPACKET *pkt, int tag, int b) +{ + return int_start_context(pkt, tag) + && WPACKET_start_sub_packet(pkt) + && (!b || WPACKET_put_bytes_u8(pkt, 0xFF)) + && !WPACKET_close(pkt) + && !WPACKET_put_bytes_u8(pkt, DER_P_BOOLEAN) + && int_end_context(pkt, tag); +} + +static int int_der_w_integer(WPACKET *pkt, int tag, + int (*put_bytes)(WPACKET *pkt, const void *v, + unsigned int *top_byte), + const void *v) +{ + unsigned int top_byte = 0; + + return int_start_context(pkt, tag) + && WPACKET_start_sub_packet(pkt) + && put_bytes(pkt, v, &top_byte) + && ((top_byte & 0x80) == 0 || WPACKET_put_bytes_u8(pkt, 0)) + && WPACKET_close(pkt) + && WPACKET_put_bytes_u8(pkt, DER_P_INTEGER) + && int_end_context(pkt, tag); +} + +static int int_put_bytes_ulong(WPACKET *pkt, const void *v, + unsigned int *top_byte) +{ + const unsigned long *value = v; + unsigned long tmp = *value; + size_t n = 0; + + while (tmp != 0) { + n++; + *top_byte = (tmp & 0xFF); + tmp >>= 8; + } + if (n == 0) + n = 1; + + return WPACKET_put_bytes__(pkt, *value, n); +} + +/* For integers, we only support unsigned values for now */ +int DER_w_ulong(WPACKET *pkt, int tag, unsigned long v) +{ + return int_der_w_integer(pkt, tag, int_put_bytes_ulong, &v); +} + +static int int_put_bytes_bn(WPACKET *pkt, const void *v, + unsigned int *top_byte) +{ + unsigned char *p = NULL; + size_t n = BN_num_bytes(v); + + /* The BIGNUM limbs are in LE order */ + *top_byte = + ((bn_get_words(v) [(n - 1) / BN_BYTES]) >> (8 * ((n - 1) % BN_BYTES))) + & 0xFF; + + if (!WPACKET_allocate_bytes(pkt, n, &p)) + return 0; + if (p != NULL) + BN_bn2bin(v, p); + return 1; +} + +int DER_w_bn(WPACKET *pkt, int tag, const BIGNUM *v) +{ + if (v == NULL || BN_is_negative(v)) + return 0; + if (BN_is_zero(v)) + return DER_w_ulong(pkt, tag, 0); + + return int_der_w_integer(pkt, tag, int_put_bytes_bn, v); +} + +int DER_w_null(WPACKET *pkt, int tag) +{ + return int_start_context(pkt, tag) + && WPACKET_start_sub_packet(pkt) + && WPACKET_close(pkt) + && WPACKET_put_bytes_u8(pkt, DER_P_NULL) + && int_end_context(pkt, tag); +} + +/* Constructed things need a start and an end */ +int DER_w_begin_sequence(WPACKET *pkt, int tag) +{ + return int_start_context(pkt, tag) + && WPACKET_start_sub_packet(pkt); +} + +int DER_w_end_sequence(WPACKET *pkt, int tag) +{ + return WPACKET_close(pkt) + && WPACKET_put_bytes_u8(pkt, DER_F_CONSTRUCTED | DER_P_SEQUENCE) + && int_end_context(pkt, tag); +} diff --git a/crypto/des/build.info b/crypto/des/build.info index 1fbbcdf2..0e5fd171 100644 --- a/crypto/des/build.info +++ b/crypto/des/build.info @@ -15,20 +15,23 @@ ENDIF LIBS=../../libcrypto $COMMON=set_key.c ecb3_enc.c $DESASM -SOURCE[../../libcrypto]=$COMMON\ - ecb_enc.c cbc_enc.c \ - cfb64enc.c cfb64ede.c cfb_enc.c \ - ofb64ede.c ofb64enc.c ofb_enc.c \ - str2key.c pcbc_enc.c qud_cksm.c rand_key.c \ - fcrypt.c xcbc_enc.c cbc_cksm.c +$ALL=$COMMON\ + ecb_enc.c cbc_enc.c \ + cfb64enc.c cfb64ede.c cfb_enc.c \ + ofb64ede.c ofb64enc.c ofb_enc.c \ + str2key.c pcbc_enc.c qud_cksm.c rand_key.c \ + fcrypt.c xcbc_enc.c cbc_cksm.c + +SOURCE[../../libcrypto]=$ALL SOURCE[../../providers/libfips.a]=$COMMON DEFINE[../../libcrypto]=$DESDEF DEFINE[../../providers/libfips.a]=$DESDEF +DEFINE[../../providers/liblegacy.a]=$DESDEF # When all deprecated symbols are removed, libcrypto doesn't export the # DES functions, so we must include them directly in liblegacy.a IF[{- $disabled{'deprecated-3.0'} && !$disabled{"mdc2"} -}] - SOURCE[../../providers/liblegacy.a]=set_key.c $DESASM + SOURCE[../../providers/liblegacy.a]=$ALL DEFINE[../../providers/liblegacy.a]=$DESDEF ENDIF diff --git a/crypto/dh/build.info b/crypto/dh/build.info index 56c085bb..ce0918e7 100644 --- a/crypto/dh/build.info +++ b/crypto/dh/build.info @@ -1,6 +1,6 @@ LIBS=../../libcrypto -$COMMON=dh_lib.c dh_key.c dh_group_params.c dh_check.c +$COMMON=dh_lib.c dh_key.c dh_group_params.c dh_check.c dh_backend.c SOURCE[../../libcrypto]=$COMMON\ dh_asn1.c dh_gen.c dh_err.c dh_depr.c \ diff --git a/crypto/dh/dh1024.pem b/crypto/dh/dh1024.pem deleted file mode 100644 index 81d43f6a..00000000 --- a/crypto/dh/dh1024.pem +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIGHAoGBAJf2QmHKtQXdKCjhPx1ottPb0PMTBH9A6FbaWMsTuKG/K3g6TG1Z1fkq -/Gz/PWk/eLI9TzFgqVAuPvr3q14a1aZeVUMTgo2oO5/y2UHe6VaJ+trqCTat3xlx -/mNbIK9HA2RgPC3gWfVLZQrY+gz3ASHHR5nXWHEyvpuZm7m3h+irAgEC ------END DH PARAMETERS----- diff --git a/crypto/dh/dh192.pem b/crypto/dh/dh192.pem deleted file mode 100644 index 521c0727..00000000 --- a/crypto/dh/dh192.pem +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN DH PARAMETERS----- -MB4CGQDUoLoCULb9LsYm5+/WN992xxbiLQlEuIsCAQM= ------END DH PARAMETERS----- diff --git a/crypto/dh/dh2048.pem b/crypto/dh/dh2048.pem deleted file mode 100644 index 295460f5..00000000 --- a/crypto/dh/dh2048.pem +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIIBCAKCAQEA7ZKJNYJFVcs7+6J2WmkEYb8h86tT0s0h2v94GRFS8Q7B4lW9aG9o -AFO5Imov5Jo0H2XMWTKKvbHbSe3fpxJmw/0hBHAY8H/W91hRGXKCeyKpNBgdL8sh -z22SrkO2qCnHJ6PLAMXy5fsKpFmFor2tRfCzrfnggTXu2YOzzK7q62bmqVdmufEo -pT8igNcLpvZxk5uBDvhakObMym9mX3rAEBoe8PwttggMYiiw7NuJKO4MqD1llGkW -aVM8U2ATsCun1IKHrRxynkE1/MJ86VHeYYX8GZt2YA8z+GuzylIOKcMH6JAWzMwA -Gbatw6QwizOhr9iMjZ0B26TE3X8LvW84wwIBAg== ------END DH PARAMETERS----- ------BEGIN DH PARAMETERS----- -MIIBCAKCAQEArtA3w73zP6Lu3EOQtwogiXt3AXXpuS6yD4BhzNS1pZFyPHk0/an5 -8ydEkPhQZHKDW+BZJxxPLANaTudWo2YT8TgtvUdN6KSgMiEi6McwqDw+SADuvW+F -SKUYFxG6VFIxyEP6xBdf+vhJxEDbRG2EYsHDRRtJ76gp9cSKTHusf2R+4AAVGqnt -gRAbNqtcOar/7FSj+Pl8G3v0Bty0LcCSpbqgYlnv6z+rErQmmC6PPvSz97TDMCok -yKpCE9hFA1zkqK3TH4FmFvGeIaXJUIBZf4mArWuBTjWFW3nmhESRUn1VK3K3x42N -a5k6c2+EhrMFiLjxuH6JZoqL0/E93FF9SwIBAg== ------END DH PARAMETERS----- diff --git a/crypto/dh/dh4096.pem b/crypto/dh/dh4096.pem deleted file mode 100644 index 390943a2..00000000 --- a/crypto/dh/dh4096.pem +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIICCAKCAgEA/urRnb6vkPYc/KEGXWnbCIOaKitq7ySIq9dTH7s+Ri59zs77zty7 -vfVlSe6VFTBWgYjD2XKUFmtqq6CqXMhVX5ElUDoYDpAyTH85xqNFLzFC7nKrff/H -TFKNttp22cZE9V0IPpzedPfnQkE7aUdmF9JnDyv21Z/818O93u1B4r0szdnmEvEF -bKuIxEHX+bp0ZR7RqE1AeifXGJX3d6tsd2PMAObxwwsv55RGkn50vHO4QxtTARr1 -rRUV5j3B3oPMgC7Offxx+98Xn45B1/G0Prp11anDsR1PGwtaCYipqsvMwQUSJtyE -EOQWk+yFkeMe4vWv367eEi0Sd/wnC+TSXBE3pYvpYerJ8n1MceI5GQTdarJ77OW9 -bGTHmxRsLSCM1jpLdPja5jjb4siAa6EHc4qN9c/iFKS3PQPJEnX7pXKBRs5f7AF3 -W3RIGt+G9IVNZfXaS7Z/iCpgzgvKCs0VeqN38QsJGtC1aIkwOeyjPNy2G6jJ4yqH -ovXYt/0mc00vCWeSNS1wren0pR2EiLxX0ypjjgsU1mk/Z3b/+zVf7fZSIB+nDLjb -NPtUlJCVGnAeBK1J1nG3TQicqowOXoM6ISkdaXj5GPJdXHab2+S7cqhKGv5qC7rR -jT6sx7RUr0CNTxzLI7muV2/a4tGmj0PSdXQdsZ7tw7gbXlaWT1+MM2MCAQI= ------END DH PARAMETERS----- - diff --git a/crypto/dh/dh512.pem b/crypto/dh/dh512.pem deleted file mode 100644 index 0a4d863e..00000000 --- a/crypto/dh/dh512.pem +++ /dev/null @@ -1,4 +0,0 @@ ------BEGIN DH PARAMETERS----- -MEYCQQDaWDwW2YUiidDkr3VvTMqS3UvlM7gE+w/tlO+cikQD7VdGUNNpmdsp13Yn -a6LT1BLiGPTdHghM9tgAPnxHdOgzAgEC ------END DH PARAMETERS----- diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c index 14c08424..f5bcee24 100644 --- a/crypto/dh/dh_ameth.c +++ b/crypto/dh/dh_ameth.c @@ -20,10 +20,12 @@ #include "dh_local.h" #include #include "crypto/asn1.h" +#include "crypto/dh.h" #include "crypto/evp.h" #include #include -#include "internal/param_build.h" +#include "openssl/param_build.h" +#include "internal/ffc.h" /* * i2d/d2i like DH parameter functions which use the appropriate routine for @@ -489,48 +491,82 @@ static size_t dh_pkey_dirty_cnt(const EVP_PKEY *pkey) } static int dh_pkey_export_to(const EVP_PKEY *from, void *to_keydata, - EVP_KEYMGMT *to_keymgmt) + EVP_KEYMGMT *to_keymgmt, OPENSSL_CTX *libctx, + const char *propq) { DH *dh = from->pkey.dh; - OSSL_PARAM_BLD tmpl; + OSSL_PARAM_BLD *tmpl; const BIGNUM *p = DH_get0_p(dh), *g = DH_get0_g(dh), *q = DH_get0_q(dh); const BIGNUM *pub_key = DH_get0_pub_key(dh); const BIGNUM *priv_key = DH_get0_priv_key(dh); - OSSL_PARAM *params; - int rv; + OSSL_PARAM *params = NULL; + int selection = 0; + int rv = 0; + + /* + * If the DH method is foreign, then we can't be sure of anything, and + * can therefore not export or pretend to export. + */ + if (dh_get_method(dh) != DH_OpenSSL()) + return 0; if (p == NULL || g == NULL) return 0; - ossl_param_bld_init(&tmpl); - if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_P, p) - || !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_G, g)) + tmpl = OSSL_PARAM_BLD_new(); + if (tmpl == NULL) return 0; + if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, p) + || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, g)) + goto err; if (q != NULL) { - if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_Q, q)) - return 0; + if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q, q)) + goto err; + } + selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS; + if (pub_key != NULL) { + if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key)) + goto err; + selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY; } - /* A key must at least have a public part. */ - if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key)) - return 0; if (priv_key != NULL) { - if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_PRIV_KEY, + if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY, priv_key)) - return 0; + goto err; + selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY; } - if ((params = ossl_param_bld_to_param(&tmpl)) == NULL) - return 0; + if ((params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) + goto err; /* We export, the provider imports */ - rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL, - params); - - ossl_param_bld_free(params); + rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params); + OSSL_PARAM_BLD_free_params(params); +err: + OSSL_PARAM_BLD_free(tmpl); return rv; } +static int dh_pkey_import_from(const OSSL_PARAM params[], void *key) +{ + EVP_PKEY *pkey = key; + DH *dh = DH_new(); + + if (dh == NULL) { + ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!ffc_fromdata(dh_get0_params(dh), params) + || !dh_key_fromdata(dh, params) + || !EVP_PKEY_assign_DH(pkey, dh)) { + DH_free(dh); + return 0; + } + return 1; +} + const EVP_PKEY_ASN1_METHOD dh_asn1_meth = { EVP_PKEY_DH, EVP_PKEY_DH, @@ -573,6 +609,7 @@ const EVP_PKEY_ASN1_METHOD dh_asn1_meth = { dh_pkey_dirty_cnt, dh_pkey_export_to, + dh_pkey_import_from, }; const EVP_PKEY_ASN1_METHOD dhx_asn1_meth = { diff --git a/crypto/dh/dh_backend.c b/crypto/dh/dh_backend.c new file mode 100644 index 00000000..bbeb096d --- /dev/null +++ b/crypto/dh/dh_backend.c @@ -0,0 +1,56 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "crypto/dh.h" + +/* + * The intention with the "backend" source file is to offer backend functions + * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider + * implementations alike. + */ + +int dh_key_fromdata(DH *dh, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *param_priv_key, *param_pub_key; + BIGNUM *priv_key = NULL, *pub_key = NULL; + + if (dh == NULL) + return 0; + + param_priv_key = + OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY); + param_pub_key = + OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY); + + /* + * DH documentation says that a public key must be present if a + * private key is present. + * We want to have at least a public key either way, so we end up + * requiring it unconditionally. + */ + if (param_priv_key != NULL && param_pub_key == NULL) + return 0; + + if ((param_priv_key != NULL + && !OSSL_PARAM_get_BN(param_priv_key, &priv_key)) + || (param_pub_key != NULL + && !OSSL_PARAM_get_BN(param_pub_key, &pub_key))) + goto err; + + if (!DH_set0_key(dh, pub_key, priv_key)) + goto err; + + return 1; + + err: + BN_clear_free(priv_key); + BN_free(pub_key); + return 0; +} diff --git a/crypto/dh/dh_lib.c b/crypto/dh/dh_lib.c index 29152dca..093695c6 100644 --- a/crypto/dh/dh_lib.c +++ b/crypto/dh/dh_lib.c @@ -45,6 +45,11 @@ int DH_set_method(DH *dh, const DH_METHOD *meth) return 1; } +const DH_METHOD *dh_get_method(const DH *dh) +{ + return dh->meth; +} + DH *DH_new(void) { return dh_new_intern(NULL, NULL); @@ -166,7 +171,7 @@ int DH_set_ex_data(DH *d, int idx, void *arg) return CRYPTO_set_ex_data(&d->ex_data, idx, arg); } -void *DH_get_ex_data(DH *d, int idx) +void *DH_get_ex_data(const DH *d, int idx) { return CRYPTO_get_ex_data(&d->ex_data, idx); } diff --git a/crypto/dsa/build.info b/crypto/dsa/build.info index 35a95a2b..fb5a4fee 100644 --- a/crypto/dsa/build.info +++ b/crypto/dsa/build.info @@ -1,7 +1,7 @@ LIBS=../../libcrypto -$COMMON=dsa_sign.c dsa_vrf.c dsa_lib.c dsa_ossl.c dsa_aid.c dsa_check.c \ - dsa_key.c +$COMMON=dsa_sign.c dsa_vrf.c dsa_lib.c dsa_ossl.c dsa_check.c \ + dsa_key.c dsa_backend.c SOURCE[../../libcrypto]=$COMMON\ dsa_gen.c dsa_asn1.c \ diff --git a/crypto/dsa/dsa_aid.c b/crypto/dsa/dsa_aid.c deleted file mode 100644 index 505e2e2f..00000000 --- a/crypto/dsa/dsa_aid.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include - -#include -#include "crypto/dsa.h" - -#define ASN1_SEQUENCE 0x30 -#define ASN1_OID 0x06 - -/* - * id-dsa-with-sha1 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 3 - * } - */ -#define ENCODE_ALGORITHMIDENTIFIER_RFC3279(name, n) \ - static const unsigned char algorithmidentifier_##name##_der[] = { \ - ASN1_SEQUENCE, 0x09, \ - ASN1_OID, 0x07, 1 * 40 + 2, 134, 72, 206, 56, 4, n \ -} - -ENCODE_ALGORITHMIDENTIFIER_RFC3279(sha1, 3); - -/* - * dsaWithSHAx OIDs are of the form: (sigAlgs |n|) - * where sigAlgs OBJECT IDENTIFIER ::= { 2 16 840 1 101 3 4 3 } - */ -#define ENCODE_ALGORITHMIDENTIFIER_SIGALGS(name, n) \ - static const unsigned char algorithmidentifier_##name##_der[] = { \ - ASN1_SEQUENCE, 0x0b, \ - ASN1_OID, 0x09, 2 * 40 + 16, 0x86, 0x48, 1, 101, 3, 4, 3, n \ -} - -ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha224, 1); -ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha256, 2); -ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha384, 3); -ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha512, 4); -ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_224, 5); -ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_256, 6); -ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_384, 7); -ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_512, 8); - -#define MD_CASE(name) \ - case NID_##name: \ - *len = sizeof(algorithmidentifier_##name##_der); \ - return algorithmidentifier_##name##_der - -const unsigned char *dsa_algorithmidentifier_encoding(int md_nid, size_t *len) -{ - switch (md_nid) { - MD_CASE(sha1); - MD_CASE(sha224); - MD_CASE(sha256); - MD_CASE(sha384); - MD_CASE(sha512); - MD_CASE(sha3_224); - MD_CASE(sha3_256); - MD_CASE(sha3_384); - MD_CASE(sha3_512); - default: - return NULL; - } -} diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c index 9715a75d..d63c142f 100644 --- a/crypto/dsa/dsa_ameth.c +++ b/crypto/dsa/dsa_ameth.c @@ -21,8 +21,10 @@ #include #include "internal/cryptlib.h" #include "crypto/asn1.h" +#include "crypto/dsa.h" #include "crypto/evp.h" -#include "internal/param_build.h" +#include "openssl/param_build.h" +#include "internal/ffc.h" #include "dsa_local.h" static int dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) @@ -518,45 +520,81 @@ static size_t dsa_pkey_dirty_cnt(const EVP_PKEY *pkey) } static int dsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata, - EVP_KEYMGMT *to_keymgmt) + EVP_KEYMGMT *to_keymgmt, OPENSSL_CTX *libctx, + const char *propq) { DSA *dsa = from->pkey.dsa; - OSSL_PARAM_BLD tmpl; + OSSL_PARAM_BLD *tmpl; const BIGNUM *p = DSA_get0_p(dsa), *g = DSA_get0_g(dsa); const BIGNUM *q = DSA_get0_q(dsa), *pub_key = DSA_get0_pub_key(dsa); const BIGNUM *priv_key = DSA_get0_priv_key(dsa); OSSL_PARAM *params; - int rv; + int selection = 0; + int rv = 0; + + /* + * If the DSA method is foreign, then we can't be sure of anything, and + * can therefore not export or pretend to export. + */ + if (DSA_get_method(dsa) != DSA_OpenSSL()) + return 0; if (p == NULL || q == NULL || g == NULL) return 0; - ossl_param_bld_init(&tmpl); - if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_P, p) - || !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_Q, q) - || !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_G, g)) - return 0; - if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_PUB_KEY, - pub_key)) + tmpl = OSSL_PARAM_BLD_new(); + if (tmpl == NULL) return 0; + + if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, p) + || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q, q) + || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, g)) + goto err; + selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS; + if (pub_key != NULL) { + if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY, + pub_key)) + goto err; + selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY; + } if (priv_key != NULL) { - if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_PRIV_KEY, + if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY, priv_key)) - return 0; + goto err; + selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY; } - if ((params = ossl_param_bld_to_param(&tmpl)) == NULL) - return 0; + if ((params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) + goto err; /* We export, the provider imports */ - rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL, - params); - - ossl_param_bld_free(params); + rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params); + OSSL_PARAM_BLD_free_params(params); +err: + OSSL_PARAM_BLD_free(tmpl); return rv; } +static int dsa_pkey_import_from(const OSSL_PARAM params[], void *key) +{ + EVP_PKEY *pkey = key; + DSA *dsa = DSA_new(); + + if (dsa == NULL) { + ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!ffc_fromdata(dsa_get0_params(dsa), params) + || !dsa_key_fromdata(dsa, params) + || !EVP_PKEY_assign_DSA(pkey, dsa)) { + DSA_free(dsa); + return 0; + } + return 1; +} + /* NB these are sorted in pkey_id order, lowest first */ const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[5] = { @@ -620,6 +658,7 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[5] = { NULL, NULL, NULL, NULL, dsa_pkey_dirty_cnt, - dsa_pkey_export_to + dsa_pkey_export_to, + dsa_pkey_import_from } }; diff --git a/crypto/dsa/dsa_backend.c b/crypto/dsa/dsa_backend.c new file mode 100644 index 00000000..b927465c --- /dev/null +++ b/crypto/dsa/dsa_backend.c @@ -0,0 +1,57 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "crypto/dsa.h" + +/* + * The intention with the "backend" source file is to offer backend support + * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider + * implementations alike. + */ + +int dsa_key_fromdata(DSA *dsa, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *param_priv_key, *param_pub_key; + BIGNUM *priv_key = NULL, *pub_key = NULL; + + if (dsa == NULL) + return 0; + + param_priv_key = + OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY); + param_pub_key = + OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY); + + /* It's ok if neither half is present */ + if (param_priv_key == NULL && param_pub_key == NULL) + return 1; + + /* + * DH documentation says that a public key must be present if a + * private key is present. + */ + if (param_priv_key != NULL && param_pub_key == NULL) + return 0; + + if (param_pub_key != NULL && !OSSL_PARAM_get_BN(param_pub_key, &pub_key)) + goto err; + if (param_priv_key != NULL && !OSSL_PARAM_get_BN(param_priv_key, &priv_key)) + goto err; + + if (!DSA_set0_key(dsa, pub_key, priv_key)) + goto err; + + return 1; + + err: + BN_clear_free(priv_key); + BN_free(pub_key); + return 0; +} diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c index 154048a3..e3205223 100644 --- a/crypto/dsa/dsa_lib.c +++ b/crypto/dsa/dsa_lib.c @@ -32,7 +32,7 @@ int DSA_set_ex_data(DSA *d, int idx, void *arg) return CRYPTO_set_ex_data(&d->ex_data, idx, arg); } -void *DSA_get_ex_data(DSA *d, int idx) +void *DSA_get_ex_data(const DSA *d, int idx) { return CRYPTO_get_ex_data(&d->ex_data, idx); } diff --git a/crypto/ec/build.info b/crypto/ec/build.info index 0e01d4af..590bbbde 100644 --- a/crypto/ec/build.info +++ b/crypto/ec/build.info @@ -51,9 +51,9 @@ $COMMON=ec_lib.c ecp_smpl.c ecp_mont.c ecp_nist.c ec_cvt.c ec_mult.c \ ecdsa_ossl.c ecdsa_sign.c ecdsa_vrf.c curve25519.c \ curve448/arch_32/f_impl.c curve448/f_generic.c curve448/scalar.c \ curve448/curve448_tables.c curve448/eddsa.c curve448/curve448.c \ - $ECASM + $ECASM ec_backend.c ecx_backend.c SOURCE[../../libcrypto]=$COMMON ec_ameth.c ec_pmeth.c ecx_meth.c ecx_key.c \ - ec_err.c ecdh_kdf.c eck_prn.c ec_evp_lib.c + ec_err.c ecdh_kdf.c eck_prn.c ec_ctrl.c SOURCE[../../providers/libfips.a]=$COMMON # Implementations are now spread across several libraries, so the defines diff --git a/crypto/ec/curve25519.c b/crypto/ec/curve25519.c index 024f7fe1..8db6cdb1 100644 --- a/crypto/ec/curve25519.c +++ b/crypto/ec/curve25519.c @@ -5438,13 +5438,14 @@ static void sc_muladd(uint8_t *s, const uint8_t *a, const uint8_t *b, } int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len, - const uint8_t public_key[32], const uint8_t private_key[32]) + const uint8_t public_key[32], const uint8_t private_key[32], + OPENSSL_CTX *libctx, const char *propq) { uint8_t az[SHA512_DIGEST_LENGTH]; uint8_t nonce[SHA512_DIGEST_LENGTH]; ge_p3 R; uint8_t hram[SHA512_DIGEST_LENGTH]; - EVP_MD *sha512 = EVP_MD_fetch(NULL, SN_sha512, NULL); + EVP_MD *sha512 = EVP_MD_fetch(libctx, SN_sha512, propq); EVP_MD_CTX *hash_ctx = EVP_MD_CTX_new(); unsigned int sz; int res = 0; @@ -5493,7 +5494,8 @@ err: static const char allzeroes[15]; int ED25519_verify(const uint8_t *message, size_t message_len, - const uint8_t signature[64], const uint8_t public_key[32]) + const uint8_t signature[64], const uint8_t public_key[32], + OPENSSL_CTX *libctx, const char *propq) { int i; ge_p3 A; @@ -5548,7 +5550,7 @@ int ED25519_verify(const uint8_t *message, size_t message_len, fe_neg(A.X, A.X); fe_neg(A.T, A.T); - sha512 = EVP_MD_fetch(NULL, SN_sha512, NULL); + sha512 = EVP_MD_fetch(libctx, SN_sha512, propq); if (sha512 == NULL) return 0; hash_ctx = EVP_MD_CTX_new(); diff --git a/crypto/ec/curve448/curve448_local.h b/crypto/ec/curve448/curve448_local.h index 36f960ec..b70a1b54 100644 --- a/crypto/ec/curve448/curve448_local.h +++ b/crypto/ec/curve448/curve448_local.h @@ -10,15 +10,6 @@ # define OSSL_CRYPTO_EC_CURVE448_LOCAL_H # include "curve448utils.h" -int ED448_sign(OPENSSL_CTX *ctx, uint8_t *out_sig, const uint8_t *message, - size_t message_len, const uint8_t public_key[57], - const uint8_t private_key[57], const uint8_t *context, - size_t context_len); - -int ED448_verify(OPENSSL_CTX *ctx, const uint8_t *message, size_t message_len, - const uint8_t signature[114], const uint8_t public_key[57], - const uint8_t *context, size_t context_len); - int ED448ph_sign(OPENSSL_CTX *ctx, uint8_t *out_sig, const uint8_t hash[64], const uint8_t public_key[57], const uint8_t private_key[57], const uint8_t *context, size_t context_len); diff --git a/crypto/ec/curve448/eddsa.c b/crypto/ec/curve448/eddsa.c index b5762cb5..1cd76844 100644 --- a/crypto/ec/curve448/eddsa.c +++ b/crypto/ec/curve448/eddsa.c @@ -12,6 +12,7 @@ #include #include #include +#include "crypto/ecx.h" #include "curve448_local.h" #include "word.h" #include "ed448.h" diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c index d6807661..33712247 100644 --- a/crypto/ec/ec_ameth.c +++ b/crypto/ec/ec_ameth.c @@ -23,7 +23,7 @@ #include "crypto/asn1.h" #include "crypto/evp.h" #include -#include "internal/param_build.h" +#include "openssl/param_build.h" #include "ec_local.h" #ifndef OPENSSL_NO_CMS @@ -611,7 +611,7 @@ int ecparams_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl) if ((curve_name = OBJ_nid2sn(curve_nid)) == NULL) return 0; - if (!ossl_param_bld_push_utf8_string(tmpl, OSSL_PKEY_PARAM_EC_NAME, curve_name, 0)) + if (!OSSL_PARAM_BLD_push_utf8_string(tmpl, OSSL_PKEY_PARAM_EC_NAME, curve_name, 0)) return 0; } @@ -620,47 +620,65 @@ int ecparams_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl) static int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata, - EVP_KEYMGMT *to_keymgmt) + EVP_KEYMGMT *to_keymgmt, OPENSSL_CTX *libctx, + const char *propq) { const EC_KEY *eckey = NULL; const EC_GROUP *ecg = NULL; unsigned char *pub_key_buf = NULL; size_t pub_key_buflen; - OSSL_PARAM_BLD tmpl; + OSSL_PARAM_BLD *tmpl; OSSL_PARAM *params = NULL; const BIGNUM *priv_key = NULL; const EC_POINT *pub_point = NULL; + int selection = 0; int rv = 0; + BN_CTX *bnctx = NULL; if (from == NULL || (eckey = from->pkey.ec) == NULL || (ecg = EC_KEY_get0_group(eckey)) == NULL) return 0; - ossl_param_bld_init(&tmpl); + /* + * If the EC_KEY method is foreign, then we can't be sure of anything, + * and can therefore not export or pretend to export. + */ + if (EC_KEY_get_method(eckey) != EC_KEY_OpenSSL()) + return 0; + + tmpl = OSSL_PARAM_BLD_new(); + if (tmpl == NULL) + return 0; /* export the domain parameters */ - if (!ecparams_to_params(eckey, &tmpl)) - return 0; + if (!ecparams_to_params(eckey, tmpl)) + goto err; + selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS; priv_key = EC_KEY_get0_private_key(eckey); pub_point = EC_KEY_get0_public_key(eckey); - /* public_key must be present, priv_key is optional */ - if (pub_point == NULL) - return 0; + if (pub_point != NULL) { + /* + * EC_POINT_point2buf() can generate random numbers in some + * implementations so we need to ensure we use the correct libctx. + */ + bnctx = BN_CTX_new_ex(libctx); + if (bnctx == NULL) + goto err; - /* convert pub_point to a octet string according to the SECG standard */ - if ((pub_key_buflen = EC_POINT_point2buf(ecg, pub_point, - POINT_CONVERSION_COMPRESSED, - &pub_key_buf, NULL)) == 0) - return 0; - - if (!ossl_param_bld_push_octet_string(&tmpl, - OSSL_PKEY_PARAM_PUB_KEY, - pub_key_buf, - pub_key_buflen)) - goto err; + /* convert pub_point to a octet string according to the SECG standard */ + if ((pub_key_buflen = EC_POINT_point2buf(ecg, pub_point, + POINT_CONVERSION_COMPRESSED, + &pub_key_buf, bnctx)) == 0 + || !OSSL_PARAM_BLD_push_octet_string(tmpl, + OSSL_PKEY_PARAM_PUB_KEY, + pub_key_buf, + pub_key_buflen)) + goto err; + selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY; + } if (priv_key != NULL) { size_t sz; @@ -705,10 +723,11 @@ int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata, goto err; sz = (ecbits + 7 ) / 8; - if (!ossl_param_bld_push_BN_pad(&tmpl, + if (!OSSL_PARAM_BLD_push_BN_pad(tmpl, OSSL_PKEY_PARAM_PRIV_KEY, priv_key, sz)) goto err; + selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY; /* * The ECDH Cofactor Mode is defined only if the EC_KEY actually @@ -719,24 +738,46 @@ int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata, (EC_KEY_get_flags(eckey) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0; /* Export the ECDH_COFACTOR_MODE parameter */ - if (!ossl_param_bld_push_int(&tmpl, + if (!OSSL_PARAM_BLD_push_int(tmpl, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, ecdh_cofactor_mode)) goto err; + selection |= OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS; } - params = ossl_param_bld_to_param(&tmpl); + params = OSSL_PARAM_BLD_to_param(tmpl); /* We export, the provider imports */ - rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL, - params); + rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params); err: - ossl_param_bld_free(params); + OSSL_PARAM_BLD_free(tmpl); + OSSL_PARAM_BLD_free_params(params); OPENSSL_free(pub_key_buf); + BN_CTX_free(bnctx); return rv; } +static int ec_pkey_import_from(const OSSL_PARAM params[], void *key) +{ + EVP_PKEY *pkey = key; + EC_KEY *ec = EC_KEY_new(); + + if (ec == NULL) { + ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!ec_key_domparams_fromdata(ec, params) + || !ec_key_otherparams_fromdata(ec, params) + || !ec_key_fromdata(ec, params, 1) + || !EVP_PKEY_assign_EC_KEY(pkey, ec)) { + EC_KEY_free(ec); + return 0; + } + return 1; +} + const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = { EVP_PKEY_EC, EVP_PKEY_EC, @@ -782,7 +823,8 @@ const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = { 0, /* get_pub_key */ ec_pkey_dirty_cnt, - ec_pkey_export_to + ec_pkey_export_to, + ec_pkey_import_from }; #if !defined(OPENSSL_NO_SM2) diff --git a/crypto/ec/ec_backend.c b/crypto/ec/ec_backend.c new file mode 100644 index 00000000..98dd0ecf --- /dev/null +++ b/crypto/ec/ec_backend.c @@ -0,0 +1,231 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "crypto/bn.h" +#include "crypto/ec.h" + +/* + * The intention with the "backend" source file is to offer backend support + * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider + * implementations alike. + */ + +int ec_set_param_ecdh_cofactor_mode(EC_KEY *ec, const OSSL_PARAM *p) +{ + const EC_GROUP *ecg = EC_KEY_get0_group(ec); + const BIGNUM *cofactor; + int mode; + + if (!OSSL_PARAM_get_int(p, &mode)) + return 0; + + /* + * mode can be only 0 for disable, or 1 for enable here. + * + * This is in contrast with the same parameter on an ECDH EVP_PKEY_CTX that + * also supports mode == -1 with the meaning of "reset to the default for + * the associated key". + */ + if (mode < 0 || mode > 1) + return 0; + + if ((cofactor = EC_GROUP_get0_cofactor(ecg)) == NULL ) + return 0; + + /* ECDH cofactor mode has no effect if cofactor is 1 */ + if (BN_is_one(cofactor)) + return 1; + + if (mode == 1) + EC_KEY_set_flags(ec, EC_FLAG_COFACTOR_ECDH); + else if (mode == 0) + EC_KEY_clear_flags(ec, EC_FLAG_COFACTOR_ECDH); + + return 1; +} + +/* + * Callers of ec_key_fromdata MUST make sure that ec_key_params_fromdata has + * been called before! + * + * This function only gets the bare keypair, domain parameters and other + * parameters are treated separately, and domain parameters are required to + * define a keypair. + */ +int ec_key_fromdata(EC_KEY *ec, const OSSL_PARAM params[], int include_private) +{ + const OSSL_PARAM *param_priv_key = NULL, *param_pub_key = NULL; + BN_CTX *ctx = NULL; + BIGNUM *priv_key = NULL; + unsigned char *pub_key = NULL; + size_t pub_key_len; + const EC_GROUP *ecg = NULL; + EC_POINT *pub_point = NULL; + int ok = 0; + + ecg = EC_KEY_get0_group(ec); + if (ecg == NULL) + return 0; + + param_pub_key = + OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY); + if (include_private) + param_priv_key = + OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY); + + ctx = BN_CTX_new_ex(ec_key_get_libctx(ec)); + if (ctx == NULL) + goto err; + + /* OpenSSL decree: If there's a private key, there must be a public key */ + if (param_priv_key != NULL && param_pub_key == NULL) + goto err; + + if (param_pub_key != NULL) + if (!OSSL_PARAM_get_octet_string(param_pub_key, + (void **)&pub_key, 0, &pub_key_len) + || (pub_point = EC_POINT_new(ecg)) == NULL + || !EC_POINT_oct2point(ecg, pub_point, pub_key, pub_key_len, ctx)) + goto err; + + if (param_priv_key != NULL && include_private) { + int fixed_words; + const BIGNUM *order; + + /* + * Key import/export should never leak the bit length of the secret + * scalar in the key. + * + * For this reason, on export we use padded BIGNUMs with fixed length. + * + * When importing we also should make sure that, even if short lived, + * the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as + * soon as possible, so that any processing of this BIGNUM might opt for + * constant time implementations in the backend. + * + * Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have + * to preallocate the BIGNUM internal buffer to a fixed public size big + * enough that operations performed during the processing never trigger + * a realloc which would leak the size of the scalar through memory + * accesses. + * + * Fixed Length + * ------------ + * + * The order of the large prime subgroup of the curve is our choice for + * a fixed public size, as that is generally the upper bound for + * generating a private key in EC cryptosystems and should fit all valid + * secret scalars. + * + * For padding on export we just use the bit length of the order + * converted to bytes (rounding up). + * + * For preallocating the BIGNUM storage we look at the number of "words" + * required for the internal representation of the order, and we + * preallocate 2 extra "words" in case any of the subsequent processing + * might temporarily overflow the order length. + */ + order = EC_GROUP_get0_order(ecg); + if (order == NULL || BN_is_zero(order)) + goto err; + + fixed_words = bn_get_top(order) + 2; + + if ((priv_key = BN_secure_new()) == NULL) + goto err; + if (bn_wexpand(priv_key, fixed_words) == NULL) + goto err; + BN_set_flags(priv_key, BN_FLG_CONSTTIME); + + if (!OSSL_PARAM_get_BN(param_priv_key, &priv_key)) + goto err; + } + + if (priv_key != NULL + && !EC_KEY_set_private_key(ec, priv_key)) + goto err; + + if (pub_point != NULL + && !EC_KEY_set_public_key(ec, pub_point)) + goto err; + + ok = 1; + + err: + BN_CTX_free(ctx); + BN_clear_free(priv_key); + OPENSSL_free(pub_key); + EC_POINT_free(pub_point); + return ok; +} + +int ec_key_domparams_fromdata(EC_KEY *ec, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *param_ec_name; + EC_GROUP *ecg = NULL; + char *curve_name = NULL; + int ok = 0; + + if (ec == NULL) + return 0; + + param_ec_name = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_NAME); + if (param_ec_name == NULL) { + /* explicit parameters */ + + /* + * TODO(3.0): should we support explicit parameters curves? + */ + return 0; + } else { + /* named curve */ + int curve_nid; + + if (!OSSL_PARAM_get_utf8_string(param_ec_name, &curve_name, 0) + || curve_name == NULL + || (curve_nid = ec_curve_name2nid(curve_name)) == NID_undef) + goto err; + + if ((ecg = EC_GROUP_new_by_curve_name_ex(ec_key_get_libctx(ec), + curve_nid)) == NULL) + goto err; + } + + if (!EC_KEY_set_group(ec, ecg)) + goto err; + + /* + * TODO(3.0): if the group has changed, should we invalidate the private and + * public key? + */ + + ok = 1; + + err: + OPENSSL_free(curve_name); + EC_GROUP_free(ecg); + return ok; +} + +int ec_key_otherparams_fromdata(EC_KEY *ec, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + + if (ec == NULL) + return 0; + + p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH); + if (p != NULL && !ec_set_param_ecdh_cofactor_mode(ec, p)) + return 0; + + return 1; +} diff --git a/crypto/ec/ec_check.c b/crypto/ec/ec_check.c index bb39177d..a4cc8073 100644 --- a/crypto/ec/ec_check.c +++ b/crypto/ec/ec_check.c @@ -19,27 +19,27 @@ int EC_GROUP_check_named_curve(const EC_GROUP *group, int nist_only, BN_CTX *ctx) { - int nid = NID_undef; -#ifndef FIPS_MODE + int nid; BN_CTX *new_ctx = NULL; + if (group == NULL) { + ECerr(0, ERR_R_PASSED_NULL_PARAMETER); + return NID_undef; + } + if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); + ctx = new_ctx = BN_CTX_new_ex(NULL); if (ctx == NULL) { - ECerr(EC_F_EC_GROUP_CHECK_NAMED_CURVE, ERR_R_MALLOC_FAILURE); - goto err; + ECerr(0, ERR_R_MALLOC_FAILURE); + return NID_undef; } } -#endif nid = ec_curve_nid_from_params(group, ctx); if (nid > 0 && nist_only && EC_curve_nid2nist(nid) == NULL) nid = NID_undef; -#ifndef FIPS_MODE - err: - BN_CTX_free(ctx); -#endif + BN_CTX_free(new_ctx); return nid; } diff --git a/crypto/ec/ec_evp_lib.c b/crypto/ec/ec_ctrl.c similarity index 85% rename from crypto/ec/ec_evp_lib.c rename to crypto/ec/ec_ctrl.c index e4d78159..314ebe61 100644 --- a/crypto/ec/ec_evp_lib.c +++ b/crypto/ec/ec_ctrl.c @@ -420,3 +420,69 @@ int EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **pukm) return (int)ukmlen; } + +int EVP_PKEY_CTX_set_ec_paramgen_curve_name(EVP_PKEY_CTX *ctx, + const char *name) +{ + OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END }; + OSSL_PARAM *p = params; + + if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) { + ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); + /* Uses the same return values as EVP_PKEY_CTX_ctrl */ + return -2; + } + + if (name == NULL) + return -1; + + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_NAME, + (char *)name, 0); + return EVP_PKEY_CTX_set_params(ctx, params); +} + +int EVP_PKEY_CTX_get_ec_paramgen_curve_name(EVP_PKEY_CTX *ctx, + char *name, size_t namelen) +{ + OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END }; + OSSL_PARAM *p = params; + + if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) { + ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); + /* Uses the same return values as EVP_PKEY_CTX_ctrl */ + return -2; + } + + if (name == NULL) + return -1; + + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_NAME, + name, namelen); + if (!EVP_PKEY_CTX_get_params(ctx, params)) + return -1; + return 1; +} + +#ifndef FIPS_MODE +int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid) +{ + if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) { + ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); + /* Uses the same return values as EVP_PKEY_CTX_ctrl */ + return -2; + } + + /* Legacy: if key type not EC return error */ + if (ctx->pmeth != NULL + && EVP_PKEY_type(ctx->pmeth->pkey_id) != EVP_PKEY_EC) + return -1; + + if (ctx->op.keymgmt.genctx == NULL) + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, + EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, + EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, + nid, NULL); + + return EVP_PKEY_CTX_set_ec_paramgen_curve_name(ctx, OBJ_nid2sn(nid)); +} +#endif diff --git a/crypto/ec/ec_curve.c b/crypto/ec/ec_curve.c index 5951615e..dd3c2286 100644 --- a/crypto/ec/ec_curve.c +++ b/crypto/ec/ec_curve.c @@ -20,6 +20,7 @@ #include #include #include "internal/nelem.h" +#include "e_os.h" /* strcasecmp required by windows */ typedef struct { int field_type, /* either NID_X9_62_prime_field or @@ -2816,6 +2817,7 @@ static const struct { #endif /* OPENSSL_NO_SM2 */ typedef struct _ec_list_element_st { + const char *name; int nid; const EC_CURVE_DATA *data; const EC_METHOD *(*meth) (void); @@ -2826,15 +2828,15 @@ typedef struct _ec_list_element_st { static const ec_list_element curve_list[] = { /* prime field curves */ /* secg curves */ -# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 - {NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method, - "NIST/SECG curve over a 224 bit prime field"}, + {"secp224r1", NID_secp224r1, &_EC_NIST_PRIME_224.h, +# if !defined(OPENSSL_NO_EC_NISTP_64_GCC_128) + EC_GFp_nistp224_method, # else - {NID_secp224r1, &_EC_NIST_PRIME_224.h, 0, - "NIST/SECG curve over a 224 bit prime field"}, + 0, # endif + "NIST/SECG curve over a 224 bit prime field"}, /* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */ - {NID_secp384r1, &_EC_NIST_PRIME_384.h, + {"secp384r1", NID_secp384r1, &_EC_NIST_PRIME_384.h, # if defined(S390X_EC_ASM) EC_GFp_s390x_nistp384_method, # else @@ -2842,7 +2844,7 @@ static const ec_list_element curve_list[] = { # endif "NIST/SECG curve over a 384 bit prime field"}, - {NID_secp521r1, &_EC_NIST_PRIME_521.h, + {"secp521r1", NID_secp521r1, &_EC_NIST_PRIME_521.h, # if defined(S390X_EC_ASM) EC_GFp_s390x_nistp521_method, # elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128) @@ -2853,9 +2855,9 @@ static const ec_list_element curve_list[] = { "NIST/SECG curve over a 521 bit prime field"}, /* X9.62 curves */ - {NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0, + {"prime192v1", NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0, "NIST/X9.62/SECG curve over a 192 bit prime field"}, - {NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h, + {"prime256v1", NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h, # if defined(ECP_NISTZ256_ASM) EC_GFp_nistz256_method, # elif defined(S390X_EC_ASM) @@ -2870,25 +2872,25 @@ static const ec_list_element curve_list[] = { # ifndef OPENSSL_NO_EC2M /* characteristic two field curves */ /* NIST/SECG curves */ - {NID_sect163k1, &_EC_NIST_CHAR2_163K.h, 0, + {"sect163k1", NID_sect163k1, &_EC_NIST_CHAR2_163K.h, 0, "NIST/SECG/WTLS curve over a 163 bit binary field"}, - {NID_sect163r2, &_EC_NIST_CHAR2_163B.h, 0, + {"sect163r2", NID_sect163r2, &_EC_NIST_CHAR2_163B.h, 0, "NIST/SECG curve over a 163 bit binary field"}, - {NID_sect233k1, &_EC_NIST_CHAR2_233K.h, 0, + {"sect233k1", NID_sect233k1, &_EC_NIST_CHAR2_233K.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field"}, - {NID_sect233r1, &_EC_NIST_CHAR2_233B.h, 0, + {"sect233r1", NID_sect233r1, &_EC_NIST_CHAR2_233B.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field"}, - {NID_sect283k1, &_EC_NIST_CHAR2_283K.h, 0, + {"sect283k1", NID_sect283k1, &_EC_NIST_CHAR2_283K.h, 0, "NIST/SECG curve over a 283 bit binary field"}, - {NID_sect283r1, &_EC_NIST_CHAR2_283B.h, 0, + {"sect283r1", NID_sect283r1, &_EC_NIST_CHAR2_283B.h, 0, "NIST/SECG curve over a 283 bit binary field"}, - {NID_sect409k1, &_EC_NIST_CHAR2_409K.h, 0, + {"sect409k1", NID_sect409k1, &_EC_NIST_CHAR2_409K.h, 0, "NIST/SECG curve over a 409 bit binary field"}, - {NID_sect409r1, &_EC_NIST_CHAR2_409B.h, 0, + {"sect409r1", NID_sect409r1, &_EC_NIST_CHAR2_409B.h, 0, "NIST/SECG curve over a 409 bit binary field"}, - {NID_sect571k1, &_EC_NIST_CHAR2_571K.h, 0, + {"sect571k1", NID_sect571k1, &_EC_NIST_CHAR2_571K.h, 0, "NIST/SECG curve over a 571 bit binary field"}, - {NID_sect571r1, &_EC_NIST_CHAR2_571B.h, 0, + {"sect571r1", NID_sect571r1, &_EC_NIST_CHAR2_571B.h, 0, "NIST/SECG curve over a 571 bit binary field"}, # endif }; @@ -2898,43 +2900,43 @@ static const ec_list_element curve_list[] = { static const ec_list_element curve_list[] = { /* prime field curves */ /* secg curves */ - {NID_secp112r1, &_EC_SECG_PRIME_112R1.h, 0, + {"secp112r1", NID_secp112r1, &_EC_SECG_PRIME_112R1.h, 0, "SECG/WTLS curve over a 112 bit prime field"}, - {NID_secp112r2, &_EC_SECG_PRIME_112R2.h, 0, + {"secp112r2", NID_secp112r2, &_EC_SECG_PRIME_112R2.h, 0, "SECG curve over a 112 bit prime field"}, - {NID_secp128r1, &_EC_SECG_PRIME_128R1.h, 0, + {"secp128r1", NID_secp128r1, &_EC_SECG_PRIME_128R1.h, 0, "SECG curve over a 128 bit prime field"}, - {NID_secp128r2, &_EC_SECG_PRIME_128R2.h, 0, + {"secp128r2", NID_secp128r2, &_EC_SECG_PRIME_128R2.h, 0, "SECG curve over a 128 bit prime field"}, - {NID_secp160k1, &_EC_SECG_PRIME_160K1.h, 0, + {"secp160k1", NID_secp160k1, &_EC_SECG_PRIME_160K1.h, 0, "SECG curve over a 160 bit prime field"}, - {NID_secp160r1, &_EC_SECG_PRIME_160R1.h, 0, + {"secp160r1", NID_secp160r1, &_EC_SECG_PRIME_160R1.h, 0, "SECG curve over a 160 bit prime field"}, - {NID_secp160r2, &_EC_SECG_PRIME_160R2.h, 0, + {"secp160r2", NID_secp160r2, &_EC_SECG_PRIME_160R2.h, 0, "SECG/WTLS curve over a 160 bit prime field"}, /* SECG secp192r1 is the same as X9.62 prime192v1 and hence omitted */ - {NID_secp192k1, &_EC_SECG_PRIME_192K1.h, 0, + {"secp192k1", NID_secp192k1, &_EC_SECG_PRIME_192K1.h, 0, "SECG curve over a 192 bit prime field"}, - {NID_secp224k1, &_EC_SECG_PRIME_224K1.h, 0, + {"secp224k1", NID_secp224k1, &_EC_SECG_PRIME_224K1.h, 0, "SECG curve over a 224 bit prime field"}, # ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 - {NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method, + {"secp224r1", NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method, "NIST/SECG curve over a 224 bit prime field"}, # else - {NID_secp224r1, &_EC_NIST_PRIME_224.h, 0, + {"secp224r1", NID_secp224r1, &_EC_NIST_PRIME_224.h, 0, "NIST/SECG curve over a 224 bit prime field"}, # endif - {NID_secp256k1, &_EC_SECG_PRIME_256K1.h, 0, + {"secp256k1", NID_secp256k1, &_EC_SECG_PRIME_256K1.h, 0, "SECG curve over a 256 bit prime field"}, /* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */ - {NID_secp384r1, &_EC_NIST_PRIME_384.h, + {"secp384r1", NID_secp384r1, &_EC_NIST_PRIME_384.h, # if defined(S390X_EC_ASM) EC_GFp_s390x_nistp384_method, # else 0, # endif "NIST/SECG curve over a 384 bit prime field"}, - {NID_secp521r1, &_EC_NIST_PRIME_521.h, + {"secp521r1", NID_secp521r1, &_EC_NIST_PRIME_521.h, # if defined(S390X_EC_ASM) EC_GFp_s390x_nistp521_method, # elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128) @@ -2944,19 +2946,19 @@ static const ec_list_element curve_list[] = { # endif "NIST/SECG curve over a 521 bit prime field"}, /* X9.62 curves */ - {NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0, + {"prime192v1", NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0, "NIST/X9.62/SECG curve over a 192 bit prime field"}, - {NID_X9_62_prime192v2, &_EC_X9_62_PRIME_192V2.h, 0, + {"prime192v2", NID_X9_62_prime192v2, &_EC_X9_62_PRIME_192V2.h, 0, "X9.62 curve over a 192 bit prime field"}, - {NID_X9_62_prime192v3, &_EC_X9_62_PRIME_192V3.h, 0, + {"prime192v3", NID_X9_62_prime192v3, &_EC_X9_62_PRIME_192V3.h, 0, "X9.62 curve over a 192 bit prime field"}, - {NID_X9_62_prime239v1, &_EC_X9_62_PRIME_239V1.h, 0, + {"prime239v1", NID_X9_62_prime239v1, &_EC_X9_62_PRIME_239V1.h, 0, "X9.62 curve over a 239 bit prime field"}, - {NID_X9_62_prime239v2, &_EC_X9_62_PRIME_239V2.h, 0, + {"prime239v2", NID_X9_62_prime239v2, &_EC_X9_62_PRIME_239V2.h, 0, "X9.62 curve over a 239 bit prime field"}, - {NID_X9_62_prime239v3, &_EC_X9_62_PRIME_239V3.h, 0, + {"prime239v3", NID_X9_62_prime239v3, &_EC_X9_62_PRIME_239V3.h, 0, "X9.62 curve over a 239 bit prime field"}, - {NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h, + {"prime256v1", NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h, # if defined(ECP_NISTZ256_ASM) EC_GFp_nistz256_method, # elif defined(S390X_EC_ASM) @@ -2970,144 +2972,144 @@ static const ec_list_element curve_list[] = { # ifndef OPENSSL_NO_EC2M /* characteristic two field curves */ /* NIST/SECG curves */ - {NID_sect113r1, &_EC_SECG_CHAR2_113R1.h, 0, + {"sect113r1", NID_sect113r1, &_EC_SECG_CHAR2_113R1.h, 0, "SECG curve over a 113 bit binary field"}, - {NID_sect113r2, &_EC_SECG_CHAR2_113R2.h, 0, + {"sect113r2", NID_sect113r2, &_EC_SECG_CHAR2_113R2.h, 0, "SECG curve over a 113 bit binary field"}, - {NID_sect131r1, &_EC_SECG_CHAR2_131R1.h, 0, + { "sect131r1", NID_sect131r1, &_EC_SECG_CHAR2_131R1.h, 0, "SECG/WTLS curve over a 131 bit binary field"}, - {NID_sect131r2, &_EC_SECG_CHAR2_131R2.h, 0, + { "sect131r2", NID_sect131r2, &_EC_SECG_CHAR2_131R2.h, 0, "SECG curve over a 131 bit binary field"}, - {NID_sect163k1, &_EC_NIST_CHAR2_163K.h, 0, + {"sect163k1", NID_sect163k1, &_EC_NIST_CHAR2_163K.h, 0, "NIST/SECG/WTLS curve over a 163 bit binary field"}, - {NID_sect163r1, &_EC_SECG_CHAR2_163R1.h, 0, + {"sect163r1", NID_sect163r1, &_EC_SECG_CHAR2_163R1.h, 0, "SECG curve over a 163 bit binary field"}, - {NID_sect163r2, &_EC_NIST_CHAR2_163B.h, 0, + {"sect163r2", NID_sect163r2, &_EC_NIST_CHAR2_163B.h, 0, "NIST/SECG curve over a 163 bit binary field"}, - {NID_sect193r1, &_EC_SECG_CHAR2_193R1.h, 0, + {"sect193r1", NID_sect193r1, &_EC_SECG_CHAR2_193R1.h, 0, "SECG curve over a 193 bit binary field"}, - {NID_sect193r2, &_EC_SECG_CHAR2_193R2.h, 0, + {"sect193r2", NID_sect193r2, &_EC_SECG_CHAR2_193R2.h, 0, "SECG curve over a 193 bit binary field"}, - {NID_sect233k1, &_EC_NIST_CHAR2_233K.h, 0, + {"sect233k1", NID_sect233k1, &_EC_NIST_CHAR2_233K.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field"}, - {NID_sect233r1, &_EC_NIST_CHAR2_233B.h, 0, + {"sect233r1", NID_sect233r1, &_EC_NIST_CHAR2_233B.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field"}, - {NID_sect239k1, &_EC_SECG_CHAR2_239K1.h, 0, + {"sect239k1", NID_sect239k1, &_EC_SECG_CHAR2_239K1.h, 0, "SECG curve over a 239 bit binary field"}, - {NID_sect283k1, &_EC_NIST_CHAR2_283K.h, 0, + {"sect283k1", NID_sect283k1, &_EC_NIST_CHAR2_283K.h, 0, "NIST/SECG curve over a 283 bit binary field"}, - {NID_sect283r1, &_EC_NIST_CHAR2_283B.h, 0, + {"sect283r1", NID_sect283r1, &_EC_NIST_CHAR2_283B.h, 0, "NIST/SECG curve over a 283 bit binary field"}, - {NID_sect409k1, &_EC_NIST_CHAR2_409K.h, 0, + {"sect409k1", NID_sect409k1, &_EC_NIST_CHAR2_409K.h, 0, "NIST/SECG curve over a 409 bit binary field"}, - {NID_sect409r1, &_EC_NIST_CHAR2_409B.h, 0, + {"sect409r1", NID_sect409r1, &_EC_NIST_CHAR2_409B.h, 0, "NIST/SECG curve over a 409 bit binary field"}, - {NID_sect571k1, &_EC_NIST_CHAR2_571K.h, 0, + {"sect571k1", NID_sect571k1, &_EC_NIST_CHAR2_571K.h, 0, "NIST/SECG curve over a 571 bit binary field"}, - {NID_sect571r1, &_EC_NIST_CHAR2_571B.h, 0, + {"sect571r1", NID_sect571r1, &_EC_NIST_CHAR2_571B.h, 0, "NIST/SECG curve over a 571 bit binary field"}, /* X9.62 curves */ - {NID_X9_62_c2pnb163v1, &_EC_X9_62_CHAR2_163V1.h, 0, + {"c2pnb163v1", NID_X9_62_c2pnb163v1, &_EC_X9_62_CHAR2_163V1.h, 0, "X9.62 curve over a 163 bit binary field"}, - {NID_X9_62_c2pnb163v2, &_EC_X9_62_CHAR2_163V2.h, 0, + {"c2pnb163v2", NID_X9_62_c2pnb163v2, &_EC_X9_62_CHAR2_163V2.h, 0, "X9.62 curve over a 163 bit binary field"}, - {NID_X9_62_c2pnb163v3, &_EC_X9_62_CHAR2_163V3.h, 0, + {"c2pnb163v3", NID_X9_62_c2pnb163v3, &_EC_X9_62_CHAR2_163V3.h, 0, "X9.62 curve over a 163 bit binary field"}, - {NID_X9_62_c2pnb176v1, &_EC_X9_62_CHAR2_176V1.h, 0, + {"c2pnb176v1", NID_X9_62_c2pnb176v1, &_EC_X9_62_CHAR2_176V1.h, 0, "X9.62 curve over a 176 bit binary field"}, - {NID_X9_62_c2tnb191v1, &_EC_X9_62_CHAR2_191V1.h, 0, + {"c2tnb191v1", NID_X9_62_c2tnb191v1, &_EC_X9_62_CHAR2_191V1.h, 0, "X9.62 curve over a 191 bit binary field"}, - {NID_X9_62_c2tnb191v2, &_EC_X9_62_CHAR2_191V2.h, 0, + {"c2tnb191v2", NID_X9_62_c2tnb191v2, &_EC_X9_62_CHAR2_191V2.h, 0, "X9.62 curve over a 191 bit binary field"}, - {NID_X9_62_c2tnb191v3, &_EC_X9_62_CHAR2_191V3.h, 0, + {"c2tnb191v3", NID_X9_62_c2tnb191v3, &_EC_X9_62_CHAR2_191V3.h, 0, "X9.62 curve over a 191 bit binary field"}, - {NID_X9_62_c2pnb208w1, &_EC_X9_62_CHAR2_208W1.h, 0, + {"c2pnb208w1", NID_X9_62_c2pnb208w1, &_EC_X9_62_CHAR2_208W1.h, 0, "X9.62 curve over a 208 bit binary field"}, - {NID_X9_62_c2tnb239v1, &_EC_X9_62_CHAR2_239V1.h, 0, + {"c2tnb239v1", NID_X9_62_c2tnb239v1, &_EC_X9_62_CHAR2_239V1.h, 0, "X9.62 curve over a 239 bit binary field"}, - {NID_X9_62_c2tnb239v2, &_EC_X9_62_CHAR2_239V2.h, 0, + {"c2tnb239v2", NID_X9_62_c2tnb239v2, &_EC_X9_62_CHAR2_239V2.h, 0, "X9.62 curve over a 239 bit binary field"}, - {NID_X9_62_c2tnb239v3, &_EC_X9_62_CHAR2_239V3.h, 0, + {"c2tnb239v3", NID_X9_62_c2tnb239v3, &_EC_X9_62_CHAR2_239V3.h, 0, "X9.62 curve over a 239 bit binary field"}, - {NID_X9_62_c2pnb272w1, &_EC_X9_62_CHAR2_272W1.h, 0, + {"c2pnb272w1", NID_X9_62_c2pnb272w1, &_EC_X9_62_CHAR2_272W1.h, 0, "X9.62 curve over a 272 bit binary field"}, - {NID_X9_62_c2pnb304w1, &_EC_X9_62_CHAR2_304W1.h, 0, + {"c2pnb304w1", NID_X9_62_c2pnb304w1, &_EC_X9_62_CHAR2_304W1.h, 0, "X9.62 curve over a 304 bit binary field"}, - {NID_X9_62_c2tnb359v1, &_EC_X9_62_CHAR2_359V1.h, 0, + {"c2tnb359v1", NID_X9_62_c2tnb359v1, &_EC_X9_62_CHAR2_359V1.h, 0, "X9.62 curve over a 359 bit binary field"}, - {NID_X9_62_c2pnb368w1, &_EC_X9_62_CHAR2_368W1.h, 0, + {"c2pnb368w1", NID_X9_62_c2pnb368w1, &_EC_X9_62_CHAR2_368W1.h, 0, "X9.62 curve over a 368 bit binary field"}, - {NID_X9_62_c2tnb431r1, &_EC_X9_62_CHAR2_431R1.h, 0, + {"c2tnb431r1", NID_X9_62_c2tnb431r1, &_EC_X9_62_CHAR2_431R1.h, 0, "X9.62 curve over a 431 bit binary field"}, /* * the WAP/WTLS curves [unlike SECG, spec has its own OIDs for curves * from X9.62] */ - {NID_wap_wsg_idm_ecid_wtls1, &_EC_WTLS_1.h, 0, + {"wap-wsg-idm-ecid-wtls1", NID_wap_wsg_idm_ecid_wtls1, &_EC_WTLS_1.h, 0, "WTLS curve over a 113 bit binary field"}, - {NID_wap_wsg_idm_ecid_wtls3, &_EC_NIST_CHAR2_163K.h, 0, + {"wap-wsg-idm-ecid-wtls3", NID_wap_wsg_idm_ecid_wtls3, &_EC_NIST_CHAR2_163K.h, 0, "NIST/SECG/WTLS curve over a 163 bit binary field"}, - {NID_wap_wsg_idm_ecid_wtls4, &_EC_SECG_CHAR2_113R1.h, 0, + {"wap-wsg-idm-ecid-wtls4", NID_wap_wsg_idm_ecid_wtls4, &_EC_SECG_CHAR2_113R1.h, 0, "SECG curve over a 113 bit binary field"}, - {NID_wap_wsg_idm_ecid_wtls5, &_EC_X9_62_CHAR2_163V1.h, 0, + {"wap-wsg-idm-ecid-wtls5", NID_wap_wsg_idm_ecid_wtls5, &_EC_X9_62_CHAR2_163V1.h, 0, "X9.62 curve over a 163 bit binary field"}, # endif - {NID_wap_wsg_idm_ecid_wtls6, &_EC_SECG_PRIME_112R1.h, 0, + {"wap-wsg-idm-ecid-wtls6", NID_wap_wsg_idm_ecid_wtls6, &_EC_SECG_PRIME_112R1.h, 0, "SECG/WTLS curve over a 112 bit prime field"}, - {NID_wap_wsg_idm_ecid_wtls7, &_EC_SECG_PRIME_160R2.h, 0, + {"wap-wsg-idm-ecid-wtls7", NID_wap_wsg_idm_ecid_wtls7, &_EC_SECG_PRIME_160R2.h, 0, "SECG/WTLS curve over a 160 bit prime field"}, - {NID_wap_wsg_idm_ecid_wtls8, &_EC_WTLS_8.h, 0, + {"wap-wsg-idm-ecid-wtls8", NID_wap_wsg_idm_ecid_wtls8, &_EC_WTLS_8.h, 0, "WTLS curve over a 112 bit prime field"}, - {NID_wap_wsg_idm_ecid_wtls9, &_EC_WTLS_9.h, 0, + {"wap-wsg-idm-ecid-wtls9", NID_wap_wsg_idm_ecid_wtls9, &_EC_WTLS_9.h, 0, "WTLS curve over a 160 bit prime field"}, # ifndef OPENSSL_NO_EC2M - {NID_wap_wsg_idm_ecid_wtls10, &_EC_NIST_CHAR2_233K.h, 0, + {"wap-wsg-idm-ecid-wtls10", NID_wap_wsg_idm_ecid_wtls10, &_EC_NIST_CHAR2_233K.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field"}, - {NID_wap_wsg_idm_ecid_wtls11, &_EC_NIST_CHAR2_233B.h, 0, + {"wap-wsg-idm-ecid-wtls11", NID_wap_wsg_idm_ecid_wtls11, &_EC_NIST_CHAR2_233B.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field"}, # endif - {NID_wap_wsg_idm_ecid_wtls12, &_EC_WTLS_12.h, 0, + {"wap-wsg-idm-ecid-wtls12", NID_wap_wsg_idm_ecid_wtls12, &_EC_WTLS_12.h, 0, "WTLS curve over a 224 bit prime field"}, # ifndef OPENSSL_NO_EC2M /* IPSec curves */ - {NID_ipsec3, &_EC_IPSEC_155_ID3.h, 0, + {"Oakley-EC2N-3", NID_ipsec3, &_EC_IPSEC_155_ID3.h, 0, "\n\tIPSec/IKE/Oakley curve #3 over a 155 bit binary field.\n" "\tNot suitable for ECDSA.\n\tQuestionable extension field!"}, - {NID_ipsec4, &_EC_IPSEC_185_ID4.h, 0, + {"Oakley-EC2N-4", NID_ipsec4, &_EC_IPSEC_185_ID4.h, 0, "\n\tIPSec/IKE/Oakley curve #4 over a 185 bit binary field.\n" "\tNot suitable for ECDSA.\n\tQuestionable extension field!"}, # endif /* brainpool curves */ - {NID_brainpoolP160r1, &_EC_brainpoolP160r1.h, 0, + {"brainpoolP160r1", NID_brainpoolP160r1, &_EC_brainpoolP160r1.h, 0, "RFC 5639 curve over a 160 bit prime field"}, - {NID_brainpoolP160t1, &_EC_brainpoolP160t1.h, 0, + {"brainpoolP160t1", NID_brainpoolP160t1, &_EC_brainpoolP160t1.h, 0, "RFC 5639 curve over a 160 bit prime field"}, - {NID_brainpoolP192r1, &_EC_brainpoolP192r1.h, 0, + {"brainpoolP192r1", NID_brainpoolP192r1, &_EC_brainpoolP192r1.h, 0, "RFC 5639 curve over a 192 bit prime field"}, - {NID_brainpoolP192t1, &_EC_brainpoolP192t1.h, 0, + {"brainpoolP192t1", NID_brainpoolP192t1, &_EC_brainpoolP192t1.h, 0, "RFC 5639 curve over a 192 bit prime field"}, - {NID_brainpoolP224r1, &_EC_brainpoolP224r1.h, 0, + {"brainpoolP224r1", NID_brainpoolP224r1, &_EC_brainpoolP224r1.h, 0, "RFC 5639 curve over a 224 bit prime field"}, - {NID_brainpoolP224t1, &_EC_brainpoolP224t1.h, 0, + {"brainpoolP224t1", NID_brainpoolP224t1, &_EC_brainpoolP224t1.h, 0, "RFC 5639 curve over a 224 bit prime field"}, - {NID_brainpoolP256r1, &_EC_brainpoolP256r1.h, 0, + {"brainpoolP256r1", NID_brainpoolP256r1, &_EC_brainpoolP256r1.h, 0, "RFC 5639 curve over a 256 bit prime field"}, - {NID_brainpoolP256t1, &_EC_brainpoolP256t1.h, 0, + {"brainpoolP256t1", NID_brainpoolP256t1, &_EC_brainpoolP256t1.h, 0, "RFC 5639 curve over a 256 bit prime field"}, - {NID_brainpoolP320r1, &_EC_brainpoolP320r1.h, 0, + {"brainpoolP320r1", NID_brainpoolP320r1, &_EC_brainpoolP320r1.h, 0, "RFC 5639 curve over a 320 bit prime field"}, - {NID_brainpoolP320t1, &_EC_brainpoolP320t1.h, 0, + {"brainpoolP320t1", NID_brainpoolP320t1, &_EC_brainpoolP320t1.h, 0, "RFC 5639 curve over a 320 bit prime field"}, - {NID_brainpoolP384r1, &_EC_brainpoolP384r1.h, 0, + {"brainpoolP384r1", NID_brainpoolP384r1, &_EC_brainpoolP384r1.h, 0, "RFC 5639 curve over a 384 bit prime field"}, - {NID_brainpoolP384t1, &_EC_brainpoolP384t1.h, 0, + {"brainpoolP384t1", NID_brainpoolP384t1, &_EC_brainpoolP384t1.h, 0, "RFC 5639 curve over a 384 bit prime field"}, - {NID_brainpoolP512r1, &_EC_brainpoolP512r1.h, 0, + {"brainpoolP512r1", NID_brainpoolP512r1, &_EC_brainpoolP512r1.h, 0, "RFC 5639 curve over a 512 bit prime field"}, - {NID_brainpoolP512t1, &_EC_brainpoolP512t1.h, 0, + {"brainpoolP512t1", NID_brainpoolP512t1, &_EC_brainpoolP512t1.h, 0, "RFC 5639 curve over a 512 bit prime field"}, # ifndef OPENSSL_NO_SM2 - {NID_sm2, &_EC_sm2p256v1.h, 0, + {"SM2", NID_sm2, &_EC_sm2p256v1.h, 0, "SM2 curve over a 256 bit prime field"}, # endif }; @@ -3115,6 +3117,68 @@ static const ec_list_element curve_list[] = { #define curve_list_length OSSL_NELEM(curve_list) +static const ec_list_element *ec_curve_nid2curve(int nid) +{ + size_t i; + + if (nid <= 0) + return NULL; + + for (i = 0; i < curve_list_length; i++) { + if (curve_list[i].nid == nid) + return &curve_list[i]; + } + return NULL; +} + +static const ec_list_element *ec_curve_name2curve(const char *name) +{ + size_t i; + + for (i = 0; i < curve_list_length; i++) { + if (strcasecmp(curve_list[i].name, name) == 0) + return &curve_list[i]; + } + return NULL; +} + +const char *ec_curve_nid2name(int nid) +{ + /* + * TODO(3.0) Figure out if we should try to find the nid with + * EC_curve_nid2nist() first, i.e. make it a priority to return + * NIST names if there is one for the NID. This is related to + * the TODO comment in ec_curve_name2nid(). + */ + const ec_list_element *curve = ec_curve_nid2curve(nid); + + if (curve != NULL) + return curve->name; + return NULL; +} + +int ec_curve_name2nid(const char *name) +{ + const ec_list_element *curve = NULL; + int nid; + + if ((nid = EC_curve_nist2nid(name)) != NID_undef) + return nid; + +#ifndef FIPS_MODE + /* + * TODO(3.0) Figure out if we can use other names than the NIST names + * ("B-163", "K-163" & "P-192") in the FIPS module, or if other names + * are allowed as well as long as they lead to the same curve data. + * If only the NIST names are allowed in the FIPS module, we should + * move '#endif' to just before 'return NID_undef'. + */ +#endif + if ((curve = ec_curve_name2curve(name)) != NULL) + return curve->nid; + return NID_undef; +} + static EC_GROUP *ec_group_new_from_data(OPENSSL_CTX *libctx, const ec_list_element curve) { @@ -3226,28 +3290,11 @@ static EC_GROUP *ec_group_new_from_data(OPENSSL_CTX *libctx, EC_GROUP *EC_GROUP_new_by_curve_name_ex(OPENSSL_CTX *libctx, int nid) { - size_t i; EC_GROUP *ret = NULL; + const ec_list_element *curve; - if (nid <= 0) - return NULL; - -#ifdef FIPS_MODE - /* - * Only use approved NIST curves in FIPS. - * NOTE: "B-163", "K-163" & "P-192" can only be used for legacy use - * (i.e- ECDSA signature verification). - */ - if (EC_curve_nid2nist(nid) == NULL) - return NULL; -#endif /* FIPS_MODE */ - for (i = 0; i < curve_list_length; i++) - if (curve_list[i].nid == nid) { - ret = ec_group_new_from_data(libctx, curve_list[i]); - break; - } - - if (ret == NULL) { + if ((curve = ec_curve_nid2curve(nid)) == NULL + || (ret = ec_group_new_from_data(libctx, *curve)) == NULL) { ECerr(EC_F_EC_GROUP_NEW_BY_CURVE_NAME_EX, EC_R_UNKNOWN_GROUP); return NULL; } diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c index 18b544b9..3bbf8227 100644 --- a/crypto/ec/ec_key.c +++ b/crypto/ec/ec_key.c @@ -417,6 +417,120 @@ err: return ret; } +/* + * ECC Key validation as specified in SP800-56A R3. + * Section 5.6.2.3.3 ECC Full Public-Key Validation. + */ +int ec_key_public_check(const EC_KEY *eckey, BN_CTX *ctx) +{ + int ret = 0; + EC_POINT *point = NULL; + const BIGNUM *order = NULL; + + if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) { + ECerr(0, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + /* 5.6.2.3.3 (Step 1): Q != infinity */ + if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) { + ECerr(0, EC_R_POINT_AT_INFINITY); + return 0; + } + + point = EC_POINT_new(eckey->group); + if (point == NULL) + return 0; + + /* 5.6.2.3.3 (Step 2) Test if the public key is in range */ + if (!ec_key_public_range_check(ctx, eckey)) { + ECerr(0, EC_R_COORDINATES_OUT_OF_RANGE); + goto err; + } + + /* 5.6.2.3.3 (Step 3) is the pub_key on the elliptic curve */ + if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) { + ECerr(0, EC_R_POINT_IS_NOT_ON_CURVE); + goto err; + } + + order = eckey->group->order; + if (BN_is_zero(order)) { + ECerr(0, EC_R_INVALID_GROUP_ORDER); + goto err; + } + /* 5.6.2.3.3 (Step 4) : pub_key * order is the point at infinity. */ + if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) { + ECerr(0, ERR_R_EC_LIB); + goto err; + } + if (!EC_POINT_is_at_infinity(eckey->group, point)) { + ECerr(0, EC_R_WRONG_ORDER); + goto err; + } + ret = 1; +err: + EC_POINT_free(point); + return ret; +} + +/* + * ECC Key validation as specified in SP800-56A R3. + * Section 5.6.2.1.2 Owner Assurance of Private-Key Validity + * The private key is in the range [1, order-1] + */ +int ec_key_private_check(const EC_KEY *eckey) +{ + if (eckey == NULL || eckey->group == NULL || eckey->priv_key == NULL) { + ECerr(0, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (BN_cmp(eckey->priv_key, BN_value_one()) < 0 + || BN_cmp(eckey->priv_key, eckey->group->order) >= 0) { + ECerr(0, EC_R_INVALID_PRIVATE_KEY); + return 0; + } + return 1; +} + +/* + * ECC Key validation as specified in SP800-56A R3. + * Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency (b) + * Check if generator * priv_key = pub_key + */ +int ec_key_pairwise_check(const EC_KEY *eckey, BN_CTX *ctx) +{ + int ret = 0; + EC_POINT *point = NULL; + + if (eckey == NULL + || eckey->group == NULL + || eckey->pub_key == NULL + || eckey->priv_key == NULL) { + ECerr(0, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + point = EC_POINT_new(eckey->group); + if (point == NULL) + goto err; + + + if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, NULL, NULL, ctx)) { + ECerr(0, ERR_R_EC_LIB); + goto err; + } + if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) { + ECerr(0, EC_R_INVALID_PRIVATE_KEY); + goto err; + } + ret = 1; +err: + EC_POINT_free(point); + return ret; +} + + /* * ECC Key validation as specified in SP800-56A R3. * Section 5.6.2.3.3 ECC Full Public-Key Validation @@ -431,81 +545,25 @@ int ec_key_simple_check_key(const EC_KEY *eckey) { int ok = 0; BN_CTX *ctx = NULL; - const BIGNUM *order = NULL; - EC_POINT *point = NULL; - if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) { - ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER); + if (eckey == NULL) { + ECerr(0, ERR_R_PASSED_NULL_PARAMETER); return 0; } - - /* 5.6.2.3.3 (Step 1): Q != infinity */ - if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) { - ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_POINT_AT_INFINITY); - goto err; - } - if ((ctx = BN_CTX_new_ex(eckey->libctx)) == NULL) - goto err; + return 0; - if ((point = EC_POINT_new(eckey->group)) == NULL) + if (!ec_key_public_check(eckey, ctx)) goto err; - /* 5.6.2.3.3 (Step 2) Test if the public key is in range */ - if (!ec_key_public_range_check(ctx, eckey)) { - ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_COORDINATES_OUT_OF_RANGE); - goto err; - } - - /* 5.6.2.3.3 (Step 3) is the pub_key on the elliptic curve */ - if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) { - ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE); - goto err; - } - - order = eckey->group->order; - if (BN_is_zero(order)) { - ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_INVALID_GROUP_ORDER); - goto err; - } - /* 5.6.2.3.3 (Step 4) : pub_key * order is the point at infinity. */ - if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) { - ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_EC_LIB); - goto err; - } - if (!EC_POINT_is_at_infinity(eckey->group, point)) { - ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_WRONG_ORDER); - goto err; - } - if (eckey->priv_key != NULL) { - /* - * 5.6.2.1.2 Owner Assurance of Private-Key Validity - * The private key is in the range [1, order-1] - */ - if (BN_cmp(eckey->priv_key, BN_value_one()) < 0 - || BN_cmp(eckey->priv_key, order) >= 0) { - ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_WRONG_ORDER); + if (!ec_key_private_check(eckey) + || !ec_key_pairwise_check(eckey, ctx)) goto err; - } - /* - * Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency (b) - * Check if generator * priv_key = pub_key - */ - if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, - NULL, NULL, ctx)) { - ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_EC_LIB); - goto err; - } - if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) { - ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY); - goto err; - } } ok = 1; - err: +err: BN_CTX_free(ctx); - EC_POINT_free(point); return ok; } @@ -569,6 +627,11 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, } +OPENSSL_CTX *ec_key_get_libctx(const EC_KEY *key) +{ + return key->libctx; +} + const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key) { return key->group; diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c index 078d8b35..f90d8339 100644 --- a/crypto/ec/ec_lib.c +++ b/crypto/ec/ec_lib.c @@ -599,12 +599,7 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) BIGNUM *a1, *a2, *a3, *b1, *b2, *b3; #ifndef FIPS_MODE BN_CTX *ctx_new = NULL; - - if (ctx == NULL) - ctx_new = ctx = BN_CTX_new(); #endif - if (ctx == NULL) - return -1; /* compare the field types */ if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) != @@ -617,6 +612,13 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) if (a->meth->flags & EC_FLAGS_CUSTOM_CURVE) return 0; +#ifndef FIPS_MODE + if (ctx == NULL) + ctx_new = ctx = BN_CTX_new(); +#endif + if (ctx == NULL) + return -1; + BN_CTX_start(ctx); a1 = BN_CTX_get(ctx); a2 = BN_CTX_get(ctx); @@ -1047,7 +1049,24 @@ int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t i = 0; #ifndef FIPS_MODE BN_CTX *new_ctx = NULL; +#endif + if (!ec_point_is_compat(r, group)) { + ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + + if (scalar == NULL && num == 0) + return EC_POINT_set_to_infinity(group, r); + + for (i = 0; i < num; i++) { + if (!ec_point_is_compat(points[i], group)) { + ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + } + +#ifndef FIPS_MODE if (ctx == NULL) ctx = new_ctx = BN_CTX_secure_new(); #endif @@ -1056,21 +1075,6 @@ int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, return 0; } - if ((scalar == NULL) && (num == 0)) { - return EC_POINT_set_to_infinity(group, r); - } - - if (!ec_point_is_compat(r, group)) { - ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS); - return 0; - } - for (i = 0; i < num; i++) { - if (!ec_point_is_compat(points[i], group)) { - ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS); - return 0; - } - } - if (group->meth->mul != NULL) ret = group->meth->mul(group, r, scalar, num, points, scalars, ctx); else @@ -1183,16 +1187,18 @@ static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r, int ret = 0; #ifndef FIPS_MODE BN_CTX *new_ctx = NULL; +#endif + if (group->mont_data == NULL) + return 0; + +#ifndef FIPS_MODE if (ctx == NULL) ctx = new_ctx = BN_CTX_secure_new(); #endif if (ctx == NULL) return 0; - if (group->mont_data == NULL) - goto err; - BN_CTX_start(ctx); if ((e = BN_CTX_get(ctx)) == NULL) goto err; diff --git a/crypto/ec/ec_local.h b/crypto/ec/ec_local.h index dacb2ca0..b5963a7e 100644 --- a/crypto/ec/ec_local.h +++ b/crypto/ec/ec_local.h @@ -679,10 +679,6 @@ ECDSA_SIG *ecdsa_simple_sign_sig(const unsigned char *dgst, int dgst_len, int ecdsa_simple_verify_sig(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey); -int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len, - const uint8_t public_key[32], const uint8_t private_key[32]); -int ED25519_verify(const uint8_t *message, size_t message_len, - const uint8_t signature[64], const uint8_t public_key[32]); void ED25519_public_from_private(uint8_t out_public_key[32], const uint8_t private_key[32]); diff --git a/crypto/ec/ec_mult.c b/crypto/ec/ec_mult.c index 17aacf87..c66276ef 100644 --- a/crypto/ec/ec_mult.c +++ b/crypto/ec/ec_mult.c @@ -266,17 +266,10 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, goto err; } - /*- - * Apply coordinate blinding for EC_POINT. - * - * The underlying EC_METHOD can optionally implement this function: - * ec_point_blind_coordinates() returns 0 in case of errors or 1 on - * success or if coordinate blinding is not implemented for this - * group. - */ - if (!ec_point_blind_coordinates(group, p, ctx)) { - ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_POINT_COORDINATES_BLIND_FAILURE); - goto err; + /* ensure input point is in affine coords for ladder step efficiency */ + if (!p->Z_is_one && !EC_POINT_make_affine(group, p, ctx)) { + ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_EC_LIB); + goto err; } /* Initialize the Montgomery ladder */ @@ -753,6 +746,20 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, if (r_is_at_infinity) { if (!EC_POINT_copy(r, val_sub[i][digit >> 1])) goto err; + + /*- + * Apply coordinate blinding for EC_POINT. + * + * The underlying EC_METHOD can optionally implement this function: + * ec_point_blind_coordinates() returns 0 in case of errors or 1 on + * success or if coordinate blinding is not implemented for this + * group. + */ + if (!ec_point_blind_coordinates(group, r, ctx)) { + ECerr(EC_F_EC_WNAF_MUL, EC_R_POINT_COORDINATES_BLIND_FAILURE); + goto err; + } + r_is_at_infinity = 0; } else { if (!EC_POINT_add diff --git a/crypto/ec/ecp_smpl.c b/crypto/ec/ecp_smpl.c index 005ab1ec..0c25816c 100644 --- a/crypto/ec/ecp_smpl.c +++ b/crypto/ec/ecp_smpl.c @@ -1381,6 +1381,7 @@ int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, * Computes the multiplicative inverse of a in GF(p), storing the result in r. * If a is zero (or equivalent), you'll get a EC_R_CANNOT_INVERT error. * Since we don't have a Mont structure here, SCA hardening is with blinding. + * NB: "a" must be in _decoded_ form. (i.e. field_decode must precede.) */ int ec_GFp_simple_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) @@ -1441,112 +1442,133 @@ int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p, temp = BN_CTX_get(ctx); if (temp == NULL) { ECerr(EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES, ERR_R_MALLOC_FAILURE); - goto err; + goto end; } - /* make sure lambda is not zero */ + /*- + * Make sure lambda is not zero. + * If the RNG fails, we cannot blind but nevertheless want + * code to continue smoothly and not clobber the error stack. + */ do { - if (!BN_priv_rand_range_ex(lambda, group->field, ctx)) { - ECerr(EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES, ERR_R_BN_LIB); - goto err; + ERR_set_mark(); + ret = BN_priv_rand_range_ex(lambda, group->field, ctx); + ERR_pop_to_mark(); + if (ret == 0) { + ret = 1; + goto end; } } while (BN_is_zero(lambda)); /* if field_encode defined convert between representations */ - if (group->meth->field_encode != NULL - && !group->meth->field_encode(group, lambda, lambda, ctx)) - goto err; - if (!group->meth->field_mul(group, p->Z, p->Z, lambda, ctx)) - goto err; - if (!group->meth->field_sqr(group, temp, lambda, ctx)) - goto err; - if (!group->meth->field_mul(group, p->X, p->X, temp, ctx)) - goto err; - if (!group->meth->field_mul(group, temp, temp, lambda, ctx)) - goto err; - if (!group->meth->field_mul(group, p->Y, p->Y, temp, ctx)) - goto err; - p->Z_is_one = 0; + if ((group->meth->field_encode != NULL + && !group->meth->field_encode(group, lambda, lambda, ctx)) + || !group->meth->field_mul(group, p->Z, p->Z, lambda, ctx) + || !group->meth->field_sqr(group, temp, lambda, ctx) + || !group->meth->field_mul(group, p->X, p->X, temp, ctx) + || !group->meth->field_mul(group, temp, temp, lambda, ctx) + || !group->meth->field_mul(group, p->Y, p->Y, temp, ctx)) + goto end; + p->Z_is_one = 0; ret = 1; - err: + end: BN_CTX_end(ctx); return ret; } /*- - * Set s := p, r := 2p. + * Input: + * - p: affine coordinates + * + * Output: + * - s := p, r := 2p: blinded projective (homogeneous) coordinates * * For doubling we use Formula 3 from Izu-Takagi "A fast parallel elliptic curve - * multiplication resistant against side channel attacks" appendix, as described - * at + * multiplication resistant against side channel attacks" appendix, described at * https://hyperelliptic.org/EFD/g1p/auto-shortw-xz.html#doubling-dbl-2002-it-2 + * simplified for Z1=1. * - * The input point p will be in randomized Jacobian projective coords: - * x = X/Z**2, y=Y/Z**3 - * - * The output points p, s, and r are converted to standard (homogeneous) - * projective coords: - * x = X/Z, y=Y/Z + * Blinding uses the equivalence relation (\lambda X, \lambda Y, \lambda Z) + * for any non-zero \lambda that holds for projective (homogeneous) coords. */ int ec_GFp_simple_ladder_pre(const EC_GROUP *group, EC_POINT *r, EC_POINT *s, EC_POINT *p, BN_CTX *ctx) { - BIGNUM *t1, *t2, *t3, *t4, *t5, *t6 = NULL; + BIGNUM *t1, *t2, *t3, *t4, *t5 = NULL; - t1 = r->Z; - t2 = r->Y; + t1 = s->Z; + t2 = r->Z; t3 = s->X; t4 = r->X; t5 = s->Y; - t6 = s->Z; - /* convert p: (X,Y,Z) -> (XZ,Y,Z**3) */ - if (!group->meth->field_mul(group, p->X, p->X, p->Z, ctx) - || !group->meth->field_sqr(group, t1, p->Z, ctx) - || !group->meth->field_mul(group, p->Z, p->Z, t1, ctx) - /* r := 2p */ - || !group->meth->field_sqr(group, t2, p->X, ctx) - || !group->meth->field_sqr(group, t3, p->Z, ctx) - || !group->meth->field_mul(group, t4, t3, group->a, ctx) - || !BN_mod_sub_quick(t5, t2, t4, group->field) - || !BN_mod_add_quick(t2, t2, t4, group->field) - || !group->meth->field_sqr(group, t5, t5, ctx) - || !group->meth->field_mul(group, t6, t3, group->b, ctx) - || !group->meth->field_mul(group, t1, p->X, p->Z, ctx) - || !group->meth->field_mul(group, t4, t1, t6, ctx) - || !BN_mod_lshift_quick(t4, t4, 3, group->field) + if (!p->Z_is_one /* r := 2p */ + || !group->meth->field_sqr(group, t3, p->X, ctx) + || !BN_mod_sub_quick(t4, t3, group->a, group->field) + || !group->meth->field_sqr(group, t4, t4, ctx) + || !group->meth->field_mul(group, t5, p->X, group->b, ctx) + || !BN_mod_lshift_quick(t5, t5, 3, group->field) /* r->X coord output */ - || !BN_mod_sub_quick(r->X, t5, t4, group->field) - || !group->meth->field_mul(group, t1, t1, t2, ctx) - || !group->meth->field_mul(group, t2, t3, t6, ctx) - || !BN_mod_add_quick(t1, t1, t2, group->field) + || !BN_mod_sub_quick(r->X, t4, t5, group->field) + || !BN_mod_add_quick(t1, t3, group->a, group->field) + || !group->meth->field_mul(group, t2, p->X, t1, ctx) + || !BN_mod_add_quick(t2, group->b, t2, group->field) /* r->Z coord output */ - || !BN_mod_lshift_quick(r->Z, t1, 2, group->field) - || !EC_POINT_copy(s, p)) + || !BN_mod_lshift_quick(r->Z, t2, 2, group->field)) + return 0; + + /* make sure lambda (r->Y here for storage) is not zero */ + do { + if (!BN_priv_rand_range_ex(r->Y, group->field, ctx)) + return 0; + } while (BN_is_zero(r->Y)); + + /* make sure lambda (s->Z here for storage) is not zero */ + do { + if (!BN_priv_rand_range_ex(s->Z, group->field, ctx)) + return 0; + } while (BN_is_zero(s->Z)); + + /* if field_encode defined convert between representations */ + if (group->meth->field_encode != NULL + && (!group->meth->field_encode(group, r->Y, r->Y, ctx) + || !group->meth->field_encode(group, s->Z, s->Z, ctx))) + return 0; + + /* blind r and s independently */ + if (!group->meth->field_mul(group, r->Z, r->Z, r->Y, ctx) + || !group->meth->field_mul(group, r->X, r->X, r->Y, ctx) + || !group->meth->field_mul(group, s->X, p->X, s->Z, ctx)) /* s := p */ return 0; r->Z_is_one = 0; s->Z_is_one = 0; - p->Z_is_one = 0; return 1; } /*- - * Differential addition-and-doubling using Eq. (9) and (10) from Izu-Takagi + * Input: + * - s, r: projective (homogeneous) coordinates + * - p: affine coordinates + * + * Output: + * - s := r + s, r := 2r: projective (homogeneous) coordinates + * + * Differential addition-and-doubling using Eq. (9) and (10) from Izu-Takagi * "A fast parallel elliptic curve multiplication resistant against side channel * attacks", as described at - * https://hyperelliptic.org/EFD/g1p/auto-shortw-xz.html#ladder-ladd-2002-it-4 + * https://hyperelliptic.org/EFD/g1p/auto-shortw-xz.html#ladder-mladd-2002-it-4 */ int ec_GFp_simple_ladder_step(const EC_GROUP *group, EC_POINT *r, EC_POINT *s, EC_POINT *p, BN_CTX *ctx) { int ret = 0; - BIGNUM *t0, *t1, *t2, *t3, *t4, *t5, *t6, *t7 = NULL; + BIGNUM *t0, *t1, *t2, *t3, *t4, *t5, *t6 = NULL; BN_CTX_start(ctx); t0 = BN_CTX_get(ctx); @@ -1556,50 +1578,47 @@ int ec_GFp_simple_ladder_step(const EC_GROUP *group, t4 = BN_CTX_get(ctx); t5 = BN_CTX_get(ctx); t6 = BN_CTX_get(ctx); - t7 = BN_CTX_get(ctx); - if (t7 == NULL - || !group->meth->field_mul(group, t0, r->X, s->X, ctx) - || !group->meth->field_mul(group, t1, r->Z, s->Z, ctx) - || !group->meth->field_mul(group, t2, r->X, s->Z, ctx) + if (t6 == NULL + || !group->meth->field_mul(group, t6, r->X, s->X, ctx) + || !group->meth->field_mul(group, t0, r->Z, s->Z, ctx) + || !group->meth->field_mul(group, t4, r->X, s->Z, ctx) || !group->meth->field_mul(group, t3, r->Z, s->X, ctx) - || !group->meth->field_mul(group, t4, group->a, t1, ctx) - || !BN_mod_add_quick(t0, t0, t4, group->field) - || !BN_mod_add_quick(t4, t3, t2, group->field) - || !group->meth->field_mul(group, t0, t4, t0, ctx) - || !group->meth->field_sqr(group, t1, t1, ctx) - || !BN_mod_lshift_quick(t7, group->b, 2, group->field) - || !group->meth->field_mul(group, t1, t7, t1, ctx) - || !BN_mod_lshift1_quick(t0, t0, group->field) - || !BN_mod_add_quick(t0, t1, t0, group->field) - || !BN_mod_sub_quick(t1, t2, t3, group->field) - || !group->meth->field_sqr(group, t1, t1, ctx) - || !group->meth->field_mul(group, t3, t1, p->X, ctx) - || !group->meth->field_mul(group, t0, p->Z, t0, ctx) - /* s->X coord output */ - || !BN_mod_sub_quick(s->X, t0, t3, group->field) - /* s->Z coord output */ - || !group->meth->field_mul(group, s->Z, p->Z, t1, ctx) - || !group->meth->field_sqr(group, t3, r->X, ctx) - || !group->meth->field_sqr(group, t2, r->Z, ctx) - || !group->meth->field_mul(group, t4, t2, group->a, ctx) - || !BN_mod_add_quick(t5, r->X, r->Z, group->field) - || !group->meth->field_sqr(group, t5, t5, ctx) - || !BN_mod_sub_quick(t5, t5, t3, group->field) - || !BN_mod_sub_quick(t5, t5, t2, group->field) - || !BN_mod_sub_quick(t6, t3, t4, group->field) - || !group->meth->field_sqr(group, t6, t6, ctx) - || !group->meth->field_mul(group, t0, t2, t5, ctx) - || !group->meth->field_mul(group, t0, t7, t0, ctx) - /* r->X coord output */ - || !BN_mod_sub_quick(r->X, t6, t0, group->field) + || !group->meth->field_mul(group, t5, group->a, t0, ctx) + || !BN_mod_add_quick(t5, t6, t5, group->field) || !BN_mod_add_quick(t6, t3, t4, group->field) - || !group->meth->field_sqr(group, t3, t2, ctx) - || !group->meth->field_mul(group, t7, t3, t7, ctx) - || !group->meth->field_mul(group, t5, t5, t6, ctx) + || !group->meth->field_mul(group, t5, t6, t5, ctx) + || !group->meth->field_sqr(group, t0, t0, ctx) + || !BN_mod_lshift_quick(t2, group->b, 2, group->field) + || !group->meth->field_mul(group, t0, t2, t0, ctx) || !BN_mod_lshift1_quick(t5, t5, group->field) + || !BN_mod_sub_quick(t3, t4, t3, group->field) + /* s->Z coord output */ + || !group->meth->field_sqr(group, s->Z, t3, ctx) + || !group->meth->field_mul(group, t4, s->Z, p->X, ctx) + || !BN_mod_add_quick(t0, t0, t5, group->field) + /* s->X coord output */ + || !BN_mod_sub_quick(s->X, t0, t4, group->field) + || !group->meth->field_sqr(group, t4, r->X, ctx) + || !group->meth->field_sqr(group, t5, r->Z, ctx) + || !group->meth->field_mul(group, t6, t5, group->a, ctx) + || !BN_mod_add_quick(t1, r->X, r->Z, group->field) + || !group->meth->field_sqr(group, t1, t1, ctx) + || !BN_mod_sub_quick(t1, t1, t4, group->field) + || !BN_mod_sub_quick(t1, t1, t5, group->field) + || !BN_mod_sub_quick(t3, t4, t6, group->field) + || !group->meth->field_sqr(group, t3, t3, ctx) + || !group->meth->field_mul(group, t0, t5, t1, ctx) + || !group->meth->field_mul(group, t0, t2, t0, ctx) + /* r->X coord output */ + || !BN_mod_sub_quick(r->X, t3, t0, group->field) + || !BN_mod_add_quick(t3, t4, t6, group->field) + || !group->meth->field_sqr(group, t4, t5, ctx) + || !group->meth->field_mul(group, t4, t4, t2, ctx) + || !group->meth->field_mul(group, t1, t1, t3, ctx) + || !BN_mod_lshift1_quick(t1, t1, group->field) /* r->Z coord output */ - || !BN_mod_add_quick(r->Z, t7, t5, group->field)) + || !BN_mod_add_quick(r->Z, t4, t1, group->field)) goto err; ret = 1; @@ -1610,17 +1629,23 @@ int ec_GFp_simple_ladder_step(const EC_GROUP *group, } /*- - * Recovers the y-coordinate of r using Eq. (8) from Brier-Joye, "Weierstrass - * Elliptic Curves and Side-Channel Attacks", modified to work in projective - * coordinates and return r in Jacobian projective coordinates. + * Input: + * - s, r: projective (homogeneous) coordinates + * - p: affine coordinates * - * X4 = two*Y1*X2*Z3*Z2*Z1; - * Y4 = two*b*Z3*SQR(Z2*Z1) + Z3*(a*Z2*Z1+X1*X2)*(X1*Z2+X2*Z1) - X3*SQR(X1*Z2-X2*Z1); - * Z4 = two*Y1*Z3*SQR(Z2)*Z1; + * Output: + * - r := (x,y): affine coordinates + * + * Recovers the y-coordinate of r using Eq. (8) from Brier-Joye, "Weierstrass + * Elliptic Curves and Side-Channel Attacks", modified to work in mixed + * projective coords, i.e. p is affine and (r,s) in projective (homogeneous) + * coords, and return r in affine coordinates. + * + * X4 = two*Y1*X2*Z3*Z2; + * Y4 = two*b*Z3*SQR(Z2) + Z3*(a*Z2+X1*X2)*(X1*Z2+X2) - X3*SQR(X1*Z2-X2); + * Z4 = two*Y1*Z3*SQR(Z2); * * Z4 != 0 because: - * - Z1==0 implies p is at infinity, which would have caused an early exit in - * the caller; * - Z2==0 implies r is at infinity (handled by the BN_is_zero(r->Z) branch); * - Z3==0 implies s is at infinity (handled by the BN_is_zero(s->Z) branch); * - Y1==0 implies p has order 2, so either r or s are infinity and handled by @@ -1637,11 +1662,7 @@ int ec_GFp_simple_ladder_post(const EC_GROUP *group, return EC_POINT_set_to_infinity(group, r); if (BN_is_zero(s->Z)) { - /* (X,Y,Z) -> (XZ,YZ**2,Z) */ - if (!group->meth->field_mul(group, r->X, p->X, p->Z, ctx) - || !group->meth->field_sqr(group, r->Z, p->Z, ctx) - || !group->meth->field_mul(group, r->Y, p->Y, r->Z, ctx) - || !BN_copy(r->Z, p->Z) + if (!EC_POINT_copy(r, p) || !EC_POINT_invert(group, r, ctx)) return 0; return 1; @@ -1657,38 +1678,46 @@ int ec_GFp_simple_ladder_post(const EC_GROUP *group, t6 = BN_CTX_get(ctx); if (t6 == NULL - || !BN_mod_lshift1_quick(t0, p->Y, group->field) - || !group->meth->field_mul(group, t1, r->X, p->Z, ctx) - || !group->meth->field_mul(group, t2, r->Z, s->Z, ctx) - || !group->meth->field_mul(group, t2, t1, t2, ctx) - || !group->meth->field_mul(group, t3, t2, t0, ctx) - || !group->meth->field_mul(group, t2, r->Z, p->Z, ctx) - || !group->meth->field_sqr(group, t4, t2, ctx) - || !BN_mod_lshift1_quick(t5, group->b, group->field) - || !group->meth->field_mul(group, t4, t4, t5, ctx) - || !group->meth->field_mul(group, t6, t2, group->a, ctx) - || !group->meth->field_mul(group, t5, r->X, p->X, ctx) - || !BN_mod_add_quick(t5, t6, t5, group->field) - || !group->meth->field_mul(group, t6, r->Z, p->X, ctx) - || !BN_mod_add_quick(t2, t6, t1, group->field) - || !group->meth->field_mul(group, t5, t5, t2, ctx) - || !BN_mod_sub_quick(t6, t6, t1, group->field) - || !group->meth->field_sqr(group, t6, t6, ctx) - || !group->meth->field_mul(group, t6, t6, s->X, ctx) - || !BN_mod_add_quick(t4, t5, t4, group->field) - || !group->meth->field_mul(group, t4, t4, s->Z, ctx) - || !BN_mod_sub_quick(t4, t4, t6, group->field) - || !group->meth->field_sqr(group, t5, r->Z, ctx) - || !group->meth->field_mul(group, r->Z, p->Z, s->Z, ctx) - || !group->meth->field_mul(group, r->Z, t5, r->Z, ctx) - || !group->meth->field_mul(group, r->Z, r->Z, t0, ctx) - /* t3 := X, t4 := Y */ - /* (X,Y,Z) -> (XZ,YZ**2,Z) */ - || !group->meth->field_mul(group, r->X, t3, r->Z, ctx) + || !BN_mod_lshift1_quick(t4, p->Y, group->field) + || !group->meth->field_mul(group, t6, r->X, t4, ctx) + || !group->meth->field_mul(group, t6, s->Z, t6, ctx) + || !group->meth->field_mul(group, t5, r->Z, t6, ctx) + || !BN_mod_lshift1_quick(t1, group->b, group->field) + || !group->meth->field_mul(group, t1, s->Z, t1, ctx) || !group->meth->field_sqr(group, t3, r->Z, ctx) - || !group->meth->field_mul(group, r->Y, t4, t3, ctx)) + || !group->meth->field_mul(group, t2, t3, t1, ctx) + || !group->meth->field_mul(group, t6, r->Z, group->a, ctx) + || !group->meth->field_mul(group, t1, p->X, r->X, ctx) + || !BN_mod_add_quick(t1, t1, t6, group->field) + || !group->meth->field_mul(group, t1, s->Z, t1, ctx) + || !group->meth->field_mul(group, t0, p->X, r->Z, ctx) + || !BN_mod_add_quick(t6, r->X, t0, group->field) + || !group->meth->field_mul(group, t6, t6, t1, ctx) + || !BN_mod_add_quick(t6, t6, t2, group->field) + || !BN_mod_sub_quick(t0, t0, r->X, group->field) + || !group->meth->field_sqr(group, t0, t0, ctx) + || !group->meth->field_mul(group, t0, t0, s->X, ctx) + || !BN_mod_sub_quick(t0, t6, t0, group->field) + || !group->meth->field_mul(group, t1, s->Z, t4, ctx) + || !group->meth->field_mul(group, t1, t3, t1, ctx) + || (group->meth->field_decode != NULL + && !group->meth->field_decode(group, t1, t1, ctx)) + || !group->meth->field_inv(group, t1, t1, ctx) + || (group->meth->field_encode != NULL + && !group->meth->field_encode(group, t1, t1, ctx)) + || !group->meth->field_mul(group, r->X, t5, t1, ctx) + || !group->meth->field_mul(group, r->Y, t0, t1, ctx)) goto err; + if (group->meth->field_set_to_one != NULL) { + if (!group->meth->field_set_to_one(group, r->Z, ctx)) + goto err; + } else { + if (!BN_one(r->Z)) + goto err; + } + + r->Z_is_one = 1; ret = 1; err: diff --git a/crypto/ec/ecx_backend.c b/crypto/ec/ecx_backend.c new file mode 100644 index 00000000..e6133370 --- /dev/null +++ b/crypto/ec/ecx_backend.c @@ -0,0 +1,62 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "crypto/ecx.h" +#include "ecx_backend.h" + +/* + * The intention with the "backend" source file is to offer backend support + * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider + * implementations alike. + */ + +int ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[], + int include_private) +{ + size_t privkeylen = 0, pubkeylen; + const OSSL_PARAM *param_priv_key = NULL, *param_pub_key; + unsigned char *pubkey; + + if (ecx == NULL) + return 0; + + param_pub_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY); + if (include_private) + param_priv_key = + OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY); + /* + * If a private key is present then a public key must also be present. + * Alternatively we've just got a public key. + */ + if (param_pub_key == NULL) + return 0; + + if (param_priv_key != NULL + && !OSSL_PARAM_get_octet_string(param_priv_key, + (void **)&ecx->privkey, ecx->keylen, + &privkeylen)) + return 0; + + pubkey = ecx->pubkey; + if (!OSSL_PARAM_get_octet_string(param_pub_key, + (void **)&pubkey, + sizeof(ecx->pubkey), &pubkeylen)) + return 0; + + if (pubkeylen != ecx->keylen + || (param_priv_key != NULL && privkeylen != ecx->keylen)) + return 0; + + ecx->haspubkey = 1; + + return 1; +} + diff --git a/crypto/ec/ecx_backend.h b/crypto/ec/ecx_backend.h new file mode 100644 index 00000000..50ece17a --- /dev/null +++ b/crypto/ec/ecx_backend.h @@ -0,0 +1,20 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#define ISX448(id) ((id) == EVP_PKEY_X448) +#define IS25519(id) ((id) == EVP_PKEY_X25519 || (id) == EVP_PKEY_ED25519) +#define KEYLENID(id) (IS25519(id) ? X25519_KEYLEN \ + : ((id) == EVP_PKEY_X448 ? X448_KEYLEN \ + : ED448_KEYLEN)) +#define KEYNID2TYPE(id) \ + (IS25519(id) ? ECX_KEY_TYPE_X25519 \ + : ((id) == EVP_PKEY_X448 ? ECX_KEY_TYPE_X448 \ + : ((id) == EVP_PKEY_ED25519 ? ECX_KEY_TYPE_ED25519 \ + : ECX_KEY_TYPE_ED448))) +#define KEYLEN(p) KEYLENID((p)->ameth->pkey_id) diff --git a/crypto/ec/ecx_key.c b/crypto/ec/ecx_key.c index 59643cc6..0b43d26a 100644 --- a/crypto/ec/ecx_key.c +++ b/crypto/ec/ecx_key.c @@ -10,7 +10,7 @@ #include #include "crypto/ecx.h" -ECX_KEY *ecx_key_new(size_t keylen, int haspubkey) +ECX_KEY *ecx_key_new(ECX_KEY_TYPE type, int haspubkey) { ECX_KEY *ret = OPENSSL_zalloc(sizeof(*ret)); @@ -18,7 +18,21 @@ ECX_KEY *ecx_key_new(size_t keylen, int haspubkey) return NULL; ret->haspubkey = haspubkey; - ret->keylen = keylen; + switch (type) { + case ECX_KEY_TYPE_X25519: + ret->keylen = X25519_KEYLEN; + break; + case ECX_KEY_TYPE_X448: + ret->keylen = X448_KEYLEN; + break; + case ECX_KEY_TYPE_ED25519: + ret->keylen = ED25519_KEYLEN; + break; + case ECX_KEY_TYPE_ED448: + ret->keylen = ED448_KEYLEN; + break; + } + ret->type = type; ret->references = 1; ret->lock = CRYPTO_THREAD_lock_new(); diff --git a/crypto/ec/ecx_meth.c b/crypto/ec/ecx_meth.c index 32817562..03d6a7af 100644 --- a/crypto/ec/ecx_meth.c +++ b/crypto/ec/ecx_meth.c @@ -19,20 +19,13 @@ #include #include #include -#include "internal/param_build.h" +#include "openssl/param_build.h" #include "crypto/asn1.h" #include "crypto/evp.h" #include "crypto/ecx.h" #include "ec_local.h" #include "curve448/curve448_local.h" - -#define ISX448(id) ((id) == EVP_PKEY_X448) -#define IS25519(id) ((id) == EVP_PKEY_X25519 || (id) == EVP_PKEY_ED25519) -#define KEYLENID(id) (IS25519(id) ? X25519_KEYLEN \ - : ((id) == EVP_PKEY_X448 ? X448_KEYLEN \ - : ED448_KEYLEN)) -#define KEYLEN(p) KEYLENID((p)->ameth->pkey_id) - +#include "ecx_backend.h" typedef enum { KEY_OP_PUBLIC, @@ -65,7 +58,7 @@ static int ecx_key_op(EVP_PKEY *pkey, int id, const X509_ALGOR *palg, } } - key = ecx_key_new(KEYLENID(id), 1); + key = ecx_key_new(KEYNID2TYPE(id), 1); if (key == NULL) { ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE); return 0; @@ -413,38 +406,67 @@ static size_t ecx_pkey_dirty_cnt(const EVP_PKEY *pkey) } static int ecx_pkey_export_to(const EVP_PKEY *from, void *to_keydata, - EVP_KEYMGMT *to_keymgmt) + EVP_KEYMGMT *to_keymgmt, OPENSSL_CTX *libctx, + const char *propq) { const ECX_KEY *key = from->pkey.ecx; - OSSL_PARAM_BLD tmpl; + OSSL_PARAM_BLD *tmpl = OSSL_PARAM_BLD_new(); OSSL_PARAM *params = NULL; + int selection = 0; int rv = 0; - ossl_param_bld_init(&tmpl); + if (tmpl == NULL) + return 0; /* A key must at least have a public part */ - if (!ossl_param_bld_push_octet_string(&tmpl, OSSL_PKEY_PARAM_PUB_KEY, + if (!OSSL_PARAM_BLD_push_octet_string(tmpl, OSSL_PKEY_PARAM_PUB_KEY, key->pubkey, key->keylen)) goto err; + selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY; if (key->privkey != NULL) { - if (!ossl_param_bld_push_octet_string(&tmpl, + if (!OSSL_PARAM_BLD_push_octet_string(tmpl, OSSL_PKEY_PARAM_PRIV_KEY, key->privkey, key->keylen)) goto err; + selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY; } - params = ossl_param_bld_to_param(&tmpl); + params = OSSL_PARAM_BLD_to_param(tmpl); /* We export, the provider imports */ - rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL, - params); + rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params); err: - ossl_param_bld_free(params); + OSSL_PARAM_BLD_free(tmpl); + OSSL_PARAM_BLD_free_params(params); return rv; } +static int ecx_generic_import_from(const OSSL_PARAM params[], void *key, + int keytype) +{ + EVP_PKEY *pkey = key; + ECX_KEY *ecx = ecx_key_new(KEYNID2TYPE(keytype), 0); + + if (ecx == NULL) { + ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!ecx_key_fromdata(ecx, params, 1) + || !EVP_PKEY_assign(pkey, keytype, ecx)) { + ecx_key_free(ecx); + return 0; + } + return 1; +} + +static int x25519_import_from(const OSSL_PARAM params[], void *key) +{ + return ecx_generic_import_from(params, key, EVP_PKEY_X25519); +} + const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = { EVP_PKEY_X25519, EVP_PKEY_X25519, @@ -487,9 +509,15 @@ const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = { ecx_get_priv_key, ecx_get_pub_key, ecx_pkey_dirty_cnt, - ecx_pkey_export_to + ecx_pkey_export_to, + x25519_import_from }; +static int x448_import_from(const OSSL_PARAM params[], void *key) +{ + return ecx_generic_import_from(params, key, EVP_PKEY_X448); +} + const EVP_PKEY_ASN1_METHOD ecx448_asn1_meth = { EVP_PKEY_X448, EVP_PKEY_X448, @@ -532,7 +560,8 @@ const EVP_PKEY_ASN1_METHOD ecx448_asn1_meth = { ecx_get_priv_key, ecx_get_pub_key, ecx_pkey_dirty_cnt, - ecx_pkey_export_to + ecx_pkey_export_to, + x448_import_from }; static int ecd_size25519(const EVP_PKEY *pkey) @@ -607,6 +636,10 @@ static int ecd_sig_info_set448(X509_SIG_INFO *siginf, const X509_ALGOR *alg, return 1; } +static int ed25519_import_from(const OSSL_PARAM params[], void *key) +{ + return ecx_generic_import_from(params, key, EVP_PKEY_ED25519); +} const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = { EVP_PKEY_ED25519, @@ -648,8 +681,16 @@ const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = { ecx_set_pub_key, ecx_get_priv_key, ecx_get_pub_key, + ecx_pkey_dirty_cnt, + ecx_pkey_export_to, + ed25519_import_from }; +static int ed448_import_from(const OSSL_PARAM params[], void *key) +{ + return ecx_generic_import_from(params, key, EVP_PKEY_ED448); +} + const EVP_PKEY_ASN1_METHOD ed448_asn1_meth = { EVP_PKEY_ED448, EVP_PKEY_ED448, @@ -690,6 +731,9 @@ const EVP_PKEY_ASN1_METHOD ed448_asn1_meth = { ecx_set_pub_key, ecx_get_priv_key, ecx_get_pub_key, + ecx_pkey_dirty_cnt, + ecx_pkey_export_to, + ed448_import_from }; static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) @@ -793,7 +837,8 @@ static int pkey_ecd_digestsign25519(EVP_MD_CTX *ctx, unsigned char *sig, return 0; } - if (ED25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey) == 0) + if (ED25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL, + NULL) == 0) return 0; *siglen = ED25519_SIGSIZE; return 1; @@ -834,7 +879,7 @@ static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig, if (siglen != ED25519_SIGSIZE) return 0; - return ED25519_verify(tbs, tbslen, sig, edkey->pubkey); + return ED25519_verify(tbs, tbslen, sig, edkey->pubkey, NULL, NULL); } static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig, @@ -1100,7 +1145,7 @@ static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - ECX_KEY *key = ecx_key_new(X25519_KEYLEN, 1); + ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_X25519, 1); unsigned char *privkey = NULL, *pubkey; if (key == NULL) { @@ -1142,7 +1187,7 @@ static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - ECX_KEY *key = ecx_key_new(X448_KEYLEN, 1); + ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_X448, 1); unsigned char *privkey = NULL, *pubkey; if (key == NULL) { @@ -1187,7 +1232,7 @@ static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, }; unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH]; - ECX_KEY *key = ecx_key_new(ED25519_KEYLEN, 1); + ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_ED25519, 1); unsigned char *privkey = NULL, *pubkey; unsigned int sz; @@ -1244,7 +1289,7 @@ static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00 }; unsigned char x_dst[57], buff[114]; - ECX_KEY *key = ecx_key_new(ED448_KEYLEN, 1); + ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_ED448, 1); unsigned char *privkey = NULL, *pubkey; EVP_MD_CTX *hashctx = NULL; diff --git a/crypto/engine/eng_list.c b/crypto/engine/eng_list.c index 7659231e..4bd00592 100644 --- a/crypto/engine/eng_list.c +++ b/crypto/engine/eng_list.c @@ -282,6 +282,8 @@ ENGINE *ENGINE_by_id(const char *id) ENGINEerr(ENGINE_F_ENGINE_BY_ID, ERR_R_PASSED_NULL_PARAMETER); return NULL; } + ENGINE_load_builtin_engines(); + if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) { ENGINEerr(ENGINE_F_ENGINE_BY_ID, ERR_R_MALLOC_FAILURE); return NULL; diff --git a/crypto/err/err_prn.c b/crypto/err/err_prn.c index 9a588982..1647d930 100644 --- a/crypto/err/err_prn.c +++ b/crypto/err/err_prn.c @@ -68,7 +68,7 @@ void ERR_add_error_txt(const char *separator, const char *txt) if (separator == NULL) separator = ""; if (err == 0) - put_error(ERR_LIB_CMP, NULL, 0, "", 0); + put_error(ERR_LIB_NONE, NULL, 0, "", 0); do { size_t available_len, data_len; @@ -125,7 +125,7 @@ void ERR_add_error_txt(const char *separator, const char *txt) ERR_add_error_data(2, separator, tmp); OPENSSL_free(tmp); } - put_error(ERR_LIB_CMP, func, err, file, line); + put_error(ERR_GET_LIB(err), func, err, file, line); txt = curr; } else { if (trailing_separator) { diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 71cd9286..2a0e64e9 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -291,6 +291,7 @@ CMS_F_CMS_RECEIPTREQUEST_CREATE0:159:CMS_ReceiptRequest_create0 CMS_F_CMS_RECEIPT_VERIFY:160:cms_Receipt_verify CMS_F_CMS_RECIPIENTINFO_DECRYPT:134:CMS_RecipientInfo_decrypt CMS_F_CMS_RECIPIENTINFO_ENCRYPT:169:CMS_RecipientInfo_encrypt +CMS_F_CMS_RECIPIENTINFO_KARI_DECRYPT:188: CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT:178:cms_RecipientInfo_kari_encrypt CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG:175:CMS_RecipientInfo_kari_get0_alg CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID:173:\ @@ -1310,6 +1311,7 @@ SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE:431:* SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE:601:\ ossl_statem_server_post_process_message SSL_F_OSSL_STATEM_SERVER_POST_WORK:602:ossl_statem_server_post_work +SSL_F_OSSL_STATEM_SERVER_PRE_WORK:640: SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE:603:ossl_statem_server_process_message SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION:418:ossl_statem_server_read_transition SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION:604:\ @@ -1769,6 +1771,7 @@ X509V3_F_DO_DIRNAME:144:do_dirname X509V3_F_DO_EXT_I2D:135:do_ext_i2d X509V3_F_DO_EXT_NCONF:151:do_ext_nconf X509V3_F_GNAMES_FROM_SECTNAME:156:gnames_from_sectname +X509V3_F_I2R_ISSUER_SIGN_TOOL:176: X509V3_F_I2S_ASN1_ENUMERATED:121:i2s_ASN1_ENUMERATED X509V3_F_I2S_ASN1_IA5STRING:149:i2s_ASN1_IA5STRING X509V3_F_I2S_ASN1_INTEGER:120:i2s_ASN1_INTEGER @@ -1808,6 +1811,7 @@ X509V3_F_V2I_GENERAL_NAME_EX:117:v2i_GENERAL_NAME_ex X509V3_F_V2I_IDP:157:v2i_idp X509V3_F_V2I_IPADDRBLOCKS:159:v2i_IPAddrBlocks X509V3_F_V2I_ISSUER_ALT:153:v2i_issuer_alt +X509V3_F_V2I_ISSUER_SIGN_TOOL:175: X509V3_F_V2I_NAME_CONSTRAINTS:147:v2i_NAME_CONSTRAINTS X509V3_F_V2I_POLICY_CONSTRAINTS:146:v2i_POLICY_CONSTRAINTS X509V3_F_V2I_POLICY_MAPPINGS:145:v2i_POLICY_MAPPINGS @@ -2075,17 +2079,28 @@ BN_R_P_IS_NOT_PRIME:112:p is not prime BN_R_TOO_MANY_ITERATIONS:113:too many iterations BN_R_TOO_MANY_TEMPORARY_VARIABLES:109:too many temporary variables CMP_R_ALGORITHM_NOT_SUPPORTED:139:algorithm not supported +CMP_R_BAD_CHECKAFTER_IN_POLLREP:167:bad checkafter in pollrep CMP_R_BAD_REQUEST_ID:108:bad request id +CMP_R_CERTHASH_UNMATCHED:156:certhash unmatched CMP_R_CERTID_NOT_FOUND:109:certid not found +CMP_R_CERTIFICATE_NOT_ACCEPTED:169:certificate not accepted CMP_R_CERTIFICATE_NOT_FOUND:112:certificate not found +CMP_R_CERTREQMSG_NOT_FOUND:157:certreqmsg not found CMP_R_CERTRESPONSE_NOT_FOUND:113:certresponse not found CMP_R_CERT_AND_KEY_DO_NOT_MATCH:114:cert and key do not match +CMP_R_CHECKAFTER_OUT_OF_RANGE:181:checkafter out of range +CMP_R_CHECKING_PBM_NO_SECRET_AVAILABLE:166:checking pbm no secret available +CMP_R_ENCOUNTERED_KEYUPDATEWARNING:176:encountered keyupdatewarning +CMP_R_ENCOUNTERED_WAITING:162:encountered waiting CMP_R_ERROR_CALCULATING_PROTECTION:115:error calculating protection CMP_R_ERROR_CREATING_CERTCONF:116:error creating certconf CMP_R_ERROR_CREATING_CERTREP:117:error creating certrep +CMP_R_ERROR_CREATING_CR:163:error creating cr CMP_R_ERROR_CREATING_ERROR:118:error creating error CMP_R_ERROR_CREATING_GENM:119:error creating genm CMP_R_ERROR_CREATING_GENP:120:error creating genp +CMP_R_ERROR_CREATING_IR:164:error creating ir +CMP_R_ERROR_CREATING_KUR:165:error creating kur CMP_R_ERROR_CREATING_P10CR:121:error creating p10cr CMP_R_ERROR_CREATING_PKICONF:122:error creating pkiconf CMP_R_ERROR_CREATING_POLLREP:123:error creating pollrep @@ -2093,8 +2108,10 @@ CMP_R_ERROR_CREATING_POLLREQ:124:error creating pollreq CMP_R_ERROR_CREATING_RP:125:error creating rp CMP_R_ERROR_CREATING_RR:126:error creating rr CMP_R_ERROR_PARSING_PKISTATUS:107:error parsing pkistatus +CMP_R_ERROR_PROCESSING_MESSAGE:158:error processing message CMP_R_ERROR_PROTECTING_MESSAGE:127:error protecting message CMP_R_ERROR_SETTING_CERTHASH:128:error setting certhash +CMP_R_ERROR_UNEXPECTED_CERTCONF:160:error unexpected certconf CMP_R_ERROR_VALIDATING_PROTECTION:140:error validating protection CMP_R_FAILED_EXTRACTING_PUBKEY:141:failed extracting pubkey CMP_R_FAILURE_OBTAINING_RANDOM:110:failure obtaining random @@ -2107,29 +2124,41 @@ CMP_R_MISSING_PRIVATE_KEY:131:missing private key CMP_R_MISSING_PROTECTION:143:missing protection CMP_R_MISSING_SENDER_IDENTIFICATION:111:missing sender identification CMP_R_MISSING_TRUST_STORE:144:missing trust store +CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED:161:multiple requests not supported +CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED:170:multiple responses not supported CMP_R_MULTIPLE_SAN_SOURCES:102:multiple san sources CMP_R_NO_STDIO:194:no stdio CMP_R_NO_SUITABLE_SENDER_CERT:145:no suitable sender cert CMP_R_NULL_ARGUMENT:103:null argument CMP_R_PKIBODY_ERROR:146:pkibody error CMP_R_PKISTATUSINFO_NOT_FOUND:132:pkistatusinfo not found +CMP_R_POLLING_FAILED:172:polling failed CMP_R_POTENTIALLY_INVALID_CERTIFICATE:147:potentially invalid certificate +CMP_R_RECEIVED_ERROR:180:received error CMP_R_RECIPNONCE_UNMATCHED:148:recipnonce unmatched CMP_R_REQUEST_NOT_ACCEPTED:149:request not accepted +CMP_R_REQUEST_REJECTED_BY_SERVER:182:request rejected by server CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED:150:\ sender generalname type not supported CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG:151:srvcert does not validate msg +CMP_R_TOTAL_TIMEOUT:184:total timeout CMP_R_TRANSACTIONID_UNMATCHED:152:transactionid unmatched +CMP_R_TRANSFER_ERROR:159:transfer error CMP_R_UNEXPECTED_PKIBODY:133:unexpected pkibody +CMP_R_UNEXPECTED_PKISTATUS:185:unexpected pkistatus CMP_R_UNEXPECTED_PVNO:153:unexpected pvno CMP_R_UNKNOWN_ALGORITHM_ID:134:unknown algorithm id CMP_R_UNKNOWN_CERT_TYPE:135:unknown cert type +CMP_R_UNKNOWN_PKISTATUS:186:unknown pkistatus CMP_R_UNSUPPORTED_ALGORITHM:136:unsupported algorithm CMP_R_UNSUPPORTED_KEY_TYPE:137:unsupported key type CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC:154:\ unsupported protection alg dhbasedmac CMP_R_WRONG_ALGORITHM_OID:138:wrong algorithm oid +CMP_R_WRONG_CERTID_IN_RP:187:wrong certid in rp CMP_R_WRONG_PBM_VALUE:155:wrong pbm value +CMP_R_WRONG_RP_COMPONENT_COUNT:188:wrong rp component count +CMP_R_WRONG_SERIAL_IN_RP:173:wrong serial in rp CMS_R_ADD_SIGNER_ERROR:99:add signer error CMS_R_ATTRIBUTE_ERROR:161:attribute error CMS_R_CERTIFICATE_ALREADY_PRESENT:175:certificate already present @@ -2256,6 +2285,11 @@ CRMF_R_FAILURE_OBTAINING_RANDOM:107:failure obtaining random CRMF_R_ITERATIONCOUNT_BELOW_100:108:iterationcount below 100 CRMF_R_MALFORMED_IV:101:malformed iv CRMF_R_NULL_ARGUMENT:109:null argument +CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY:117:popo inconsistent public key +CRMF_R_POPO_MISSING:121:popo missing +CRMF_R_POPO_MISSING_PUBLIC_KEY:118:popo missing public key +CRMF_R_POPO_MISSING_SUBJECT:119:popo missing subject +CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED:120:popo raverified not accepted CRMF_R_SETTING_MAC_ALGOR_FAILURE:110:setting mac algor failure CRMF_R_SETTING_OWF_ALGOR_FAILURE:111:setting owf algor failure CRMF_R_UNSUPPORTED_ALGORITHM:112:unsupported algorithm @@ -2264,7 +2298,6 @@ CRMF_R_UNSUPPORTED_CIPHER:114:unsupported cipher CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO:115:\ unsupported method for creating popo CRMF_R_UNSUPPORTED_POPO_METHOD:116:unsupported popo method -CRMF_R_UNSUPPORTED_POPO_NOT_ACCEPTED:117:unsupported popo not accepted CRYPTO_R_BAD_ALGORITHM_NAME:117:bad algorithm name CRYPTO_R_CONFLICTING_NAMES:118:conflicting names CRYPTO_R_FIPS_MODE_NOT_SUPPORTED:101:fips mode not supported @@ -2489,10 +2522,13 @@ EVP_R_EXPECTING_A_DSA_KEY:129:expecting a dsa key EVP_R_EXPECTING_A_EC_KEY:142:expecting a ec key EVP_R_EXPECTING_A_POLY1305_KEY:164:expecting a poly1305 key EVP_R_EXPECTING_A_SIPHASH_KEY:175:expecting a siphash key +EVP_R_FETCH_FAILED:202:fetch failed EVP_R_FINAL_ERROR:188:final error EVP_R_FIPS_MODE_NOT_SUPPORTED:167:fips mode not supported EVP_R_GET_RAW_KEY_FAILED:182:get raw key failed EVP_R_ILLEGAL_SCRYPT_PARAMETERS:171:illegal scrypt parameters +EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS:204:inaccessible domain parameters +EVP_R_INACCESSIBLE_KEY:203:inaccessible key EVP_R_INITIALIZATION_ERROR:134:initialization error EVP_R_INPUT_NOT_INITIALIZED:111:input not initialized EVP_R_INVALID_CUSTOM_LENGTH:185:invalid custom length @@ -2505,6 +2541,7 @@ EVP_R_INVALID_OPERATION:148:invalid operation EVP_R_INVALID_PROVIDER_FUNCTIONS:193:invalid provider functions EVP_R_INVALID_SALT_LENGTH:186:invalid salt length EVP_R_KEYGEN_FAILURE:120:keygen failure +EVP_R_KEYMGMT_EXPORT_FAILURE:205:keymgmt export failure EVP_R_KEY_SETUP_FAILED:180:key setup failed EVP_R_MEMORY_LIMIT_EXCEEDED:172:memory limit exceeded EVP_R_MESSAGE_DIGEST_IS_NULL:159:message digest is null @@ -2515,6 +2552,7 @@ EVP_R_NOT_XOF_OR_INVALID_LENGTH:178:not XOF or invalid length EVP_R_NO_CIPHER_SET:131:no cipher set EVP_R_NO_DEFAULT_DIGEST:158:no default digest EVP_R_NO_DIGEST_SET:139:no digest set +EVP_R_NO_IMPORT_FUNCTION:206:no import function EVP_R_NO_KEYMGMT_AVAILABLE:199:no keymgmt available EVP_R_NO_KEYMGMT_PRESENT:196:no keymgmt present EVP_R_NO_KEY_SET:154:no key set @@ -2534,6 +2572,7 @@ EVP_R_PUBLIC_KEY_NOT_RSA:106:public key not rsa EVP_R_TOO_MANY_RECORDS:183:too many records EVP_R_UNKNOWN_CIPHER:160:unknown cipher EVP_R_UNKNOWN_DIGEST:161:unknown digest +EVP_R_UNKNOWN_KEY_TYPE:207:unknown key type EVP_R_UNKNOWN_OPTION:169:unknown option EVP_R_UNKNOWN_PBE_ALGORITHM:121:unknown pbe algorithm EVP_R_UNSUPPORTED_ALGORITHM:156:unsupported algorithm @@ -2563,12 +2602,13 @@ HTTP_R_MAX_RESP_LEN_EXCEEDED:117:max resp len exceeded HTTP_R_MISSING_ASN1_ENCODING:110:missing asn1 encoding HTTP_R_MISSING_CONTENT_TYPE:121:missing content type HTTP_R_MISSING_REDIRECT_LOCATION:111:missing redirect location +HTTP_R_RECEIVED_ERROR:105:received error +HTTP_R_RECEIVED_WRONG_HTTP_VERSION:106:received wrong http version HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP:112:redirection from https to http HTTP_R_REDIRECTION_NOT_ENABLED:116:redirection not enabled HTTP_R_RESPONSE_LINE_TOO_LONG:113:response line too long -HTTP_R_SERVER_RESPONSE_PARSE_ERROR:104:server response parse error -HTTP_R_SERVER_SENT_ERROR:105:server sent error -HTTP_R_SERVER_SENT_WRONG_HTTP_VERSION:106:server sent wrong http version +HTTP_R_RESPONSE_PARSE_ERROR:104:response parse error +HTTP_R_SOCK_NOT_SUPPORTED:122:sock not supported HTTP_R_STATUS_CODE_UNSUPPORTED:114:status code unsupported HTTP_R_TLS_NOT_ENABLED:107:tls not enabled HTTP_R_TOO_MANY_REDIRECTIONS:115:too many redirections @@ -2773,11 +2813,13 @@ PROV_R_FAILED_TO_DECRYPT:162:failed to decrypt PROV_R_FAILED_TO_GENERATE_KEY:121:failed to generate key PROV_R_FAILED_TO_GET_PARAMETER:103:failed to get parameter PROV_R_FAILED_TO_SET_PARAMETER:104:failed to set parameter +PROV_R_FAILED_TO_SIGN:175:failed to sign PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE:165:\ illegal or unsupported padding mode PROV_R_INAVLID_UKM_LENGTH:146:inavlid ukm length PROV_R_INVALID_AAD:108:invalid aad PROV_R_INVALID_CONSTANT_LENGTH:157:invalid constant length +PROV_R_INVALID_CURVE:176:invalid curve PROV_R_INVALID_CUSTOM_LENGTH:111:invalid custom length PROV_R_INVALID_DATA:115:invalid data PROV_R_INVALID_DIGEST:122:invalid digest @@ -2817,6 +2859,7 @@ PROV_R_MISSING_XCGHASH:135:missing xcghash PROV_R_NOT_SUPPORTED:136:not supported PROV_R_NOT_XOF_OR_INVALID_LENGTH:113:not xof or invalid length PROV_R_NO_KEY_SET:114:no key set +PROV_R_NO_PARAMETERS_SET:177:no parameters set PROV_R_OUTPUT_BUFFER_TOO_SMALL:106:output buffer too small PROV_R_PSS_SALTLEN_TOO_SMALL:172:pss saltlen too small PROV_R_READ_KEY:159:read key @@ -2970,6 +3013,7 @@ SM2_R_INVALID_ENCODING:104:invalid encoding SM2_R_INVALID_FIELD:105:invalid field SM2_R_NO_PARAMETERS_SET:109:no parameters set SM2_R_USER_ID_TOO_LARGE:106:user id too large +SSL_R_ALGORITHM_FETCH_FAILED:295:algorithm fetch failed SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY:291:\ application data after close notify SSL_R_APP_DATA_IN_HANDSHAKE:100:app data in handshake @@ -3126,8 +3170,8 @@ SSL_R_MISSING_TMP_DH_KEY:171:missing tmp dh key SSL_R_MISSING_TMP_ECDH_KEY:311:missing tmp ecdh key SSL_R_MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA:293:\ mixed handshake and non handshake data -SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS:295:mixed special operator with groups -SSL_R_NESTED_GROUP:296:nested group +SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS:296:mixed special operator with groups +SSL_R_NESTED_GROUP:297:nested group SSL_R_NOT_ON_RECORD_BOUNDARY:182:not on record boundary SSL_R_NOT_REPLACING_CERTIFICATE:289:not replacing certificate SSL_R_NOT_SERVER:284:not server @@ -3235,9 +3279,9 @@ SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES:243:unable to load ssl3 sha1 routines SSL_R_UNEXPECTED_CCS_MESSAGE:262:unexpected ccs message SSL_R_UNEXPECTED_END_OF_EARLY_DATA:178:unexpected end of early data SSL_R_UNEXPECTED_EOF_WHILE_READING:294:unexpected eof while reading -SSL_R_UNEXPECTED_GROUP_CLOSE:297:unexpected group close +SSL_R_UNEXPECTED_GROUP_CLOSE:299:unexpected group close SSL_R_UNEXPECTED_MESSAGE:244:unexpected message -SSL_R_UNEXPECTED_OPERATOR_IN_GROUP:299:unexpected operator in group +SSL_R_UNEXPECTED_OPERATOR_IN_GROUP:305:unexpected operator in group SSL_R_UNEXPECTED_RECORD:245:unexpected record SSL_R_UNINITIALIZED:276:uninitialized SSL_R_UNKNOWN_ALERT_TYPE:246:unknown alert type diff --git a/crypto/err/openssl.txt.old b/crypto/err/openssl.txt.old index f14acc65..12826beb 100644 --- a/crypto/err/openssl.txt.old +++ b/crypto/err/openssl.txt.old @@ -291,6 +291,7 @@ CMS_F_CMS_RECEIPTREQUEST_CREATE0:159:CMS_ReceiptRequest_create0 CMS_F_CMS_RECEIPT_VERIFY:160:cms_Receipt_verify CMS_F_CMS_RECIPIENTINFO_DECRYPT:134:CMS_RecipientInfo_decrypt CMS_F_CMS_RECIPIENTINFO_ENCRYPT:169:CMS_RecipientInfo_encrypt +CMS_F_CMS_RECIPIENTINFO_KARI_DECRYPT:188: CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT:178:cms_RecipientInfo_kari_encrypt CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG:175:CMS_RecipientInfo_kari_get0_alg CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID:173:\ @@ -1310,6 +1311,7 @@ SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE:431:* SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE:601:\ ossl_statem_server_post_process_message SSL_F_OSSL_STATEM_SERVER_POST_WORK:602:ossl_statem_server_post_work +SSL_F_OSSL_STATEM_SERVER_PRE_WORK:640: SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE:603:ossl_statem_server_process_message SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION:418:ossl_statem_server_read_transition SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION:604:\ @@ -1769,6 +1771,7 @@ X509V3_F_DO_DIRNAME:144:do_dirname X509V3_F_DO_EXT_I2D:135:do_ext_i2d X509V3_F_DO_EXT_NCONF:151:do_ext_nconf X509V3_F_GNAMES_FROM_SECTNAME:156:gnames_from_sectname +X509V3_F_I2R_ISSUER_SIGN_TOOL:176: X509V3_F_I2S_ASN1_ENUMERATED:121:i2s_ASN1_ENUMERATED X509V3_F_I2S_ASN1_IA5STRING:149:i2s_ASN1_IA5STRING X509V3_F_I2S_ASN1_INTEGER:120:i2s_ASN1_INTEGER @@ -1808,6 +1811,7 @@ X509V3_F_V2I_GENERAL_NAME_EX:117:v2i_GENERAL_NAME_ex X509V3_F_V2I_IDP:157:v2i_idp X509V3_F_V2I_IPADDRBLOCKS:159:v2i_IPAddrBlocks X509V3_F_V2I_ISSUER_ALT:153:v2i_issuer_alt +X509V3_F_V2I_ISSUER_SIGN_TOOL:175: X509V3_F_V2I_NAME_CONSTRAINTS:147:v2i_NAME_CONSTRAINTS X509V3_F_V2I_POLICY_CONSTRAINTS:146:v2i_POLICY_CONSTRAINTS X509V3_F_V2I_POLICY_MAPPINGS:145:v2i_POLICY_MAPPINGS @@ -2075,17 +2079,28 @@ BN_R_P_IS_NOT_PRIME:112:p is not prime BN_R_TOO_MANY_ITERATIONS:113:too many iterations BN_R_TOO_MANY_TEMPORARY_VARIABLES:109:too many temporary variables CMP_R_ALGORITHM_NOT_SUPPORTED:139:algorithm not supported +CMP_R_BAD_CHECKAFTER_IN_POLLREP:167:bad checkafter in pollrep CMP_R_BAD_REQUEST_ID:108:bad request id +CMP_R_CERTHASH_UNMATCHED:156:certhash unmatched CMP_R_CERTID_NOT_FOUND:109:certid not found +CMP_R_CERTIFICATE_NOT_ACCEPTED:169:certificate not accepted CMP_R_CERTIFICATE_NOT_FOUND:112:certificate not found +CMP_R_CERTREQMSG_NOT_FOUND:157:certreqmsg not found CMP_R_CERTRESPONSE_NOT_FOUND:113:certresponse not found CMP_R_CERT_AND_KEY_DO_NOT_MATCH:114:cert and key do not match +CMP_R_CHECKAFTER_OUT_OF_RANGE:181:checkafter out of range +CMP_R_CHECKING_PBM_NO_SECRET_AVAILABLE:166:checking pbm no secret available +CMP_R_ENCOUNTERED_KEYUPDATEWARNING:176:encountered keyupdatewarning +CMP_R_ENCOUNTERED_WAITING:162:encountered waiting CMP_R_ERROR_CALCULATING_PROTECTION:115:error calculating protection CMP_R_ERROR_CREATING_CERTCONF:116:error creating certconf CMP_R_ERROR_CREATING_CERTREP:117:error creating certrep +CMP_R_ERROR_CREATING_CR:163:error creating cr CMP_R_ERROR_CREATING_ERROR:118:error creating error CMP_R_ERROR_CREATING_GENM:119:error creating genm CMP_R_ERROR_CREATING_GENP:120:error creating genp +CMP_R_ERROR_CREATING_IR:164:error creating ir +CMP_R_ERROR_CREATING_KUR:165:error creating kur CMP_R_ERROR_CREATING_P10CR:121:error creating p10cr CMP_R_ERROR_CREATING_PKICONF:122:error creating pkiconf CMP_R_ERROR_CREATING_POLLREP:123:error creating pollrep @@ -2093,8 +2108,10 @@ CMP_R_ERROR_CREATING_POLLREQ:124:error creating pollreq CMP_R_ERROR_CREATING_RP:125:error creating rp CMP_R_ERROR_CREATING_RR:126:error creating rr CMP_R_ERROR_PARSING_PKISTATUS:107:error parsing pkistatus +CMP_R_ERROR_PROCESSING_MESSAGE:158:error processing message CMP_R_ERROR_PROTECTING_MESSAGE:127:error protecting message CMP_R_ERROR_SETTING_CERTHASH:128:error setting certhash +CMP_R_ERROR_UNEXPECTED_CERTCONF:160:error unexpected certconf CMP_R_ERROR_VALIDATING_PROTECTION:140:error validating protection CMP_R_FAILED_EXTRACTING_PUBKEY:141:failed extracting pubkey CMP_R_FAILURE_OBTAINING_RANDOM:110:failure obtaining random @@ -2107,29 +2124,41 @@ CMP_R_MISSING_PRIVATE_KEY:131:missing private key CMP_R_MISSING_PROTECTION:143:missing protection CMP_R_MISSING_SENDER_IDENTIFICATION:111:missing sender identification CMP_R_MISSING_TRUST_STORE:144:missing trust store +CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED:161:multiple requests not supported +CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED:170:multiple responses not supported CMP_R_MULTIPLE_SAN_SOURCES:102:multiple san sources CMP_R_NO_STDIO:194:no stdio CMP_R_NO_SUITABLE_SENDER_CERT:145:no suitable sender cert CMP_R_NULL_ARGUMENT:103:null argument CMP_R_PKIBODY_ERROR:146:pkibody error CMP_R_PKISTATUSINFO_NOT_FOUND:132:pkistatusinfo not found +CMP_R_POLLING_FAILED:172:polling failed CMP_R_POTENTIALLY_INVALID_CERTIFICATE:147:potentially invalid certificate +CMP_R_RECEIVED_ERROR:180:received error CMP_R_RECIPNONCE_UNMATCHED:148:recipnonce unmatched CMP_R_REQUEST_NOT_ACCEPTED:149:request not accepted +CMP_R_REQUEST_REJECTED_BY_SERVER:182:request rejected by server CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED:150:\ sender generalname type not supported CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG:151:srvcert does not validate msg +CMP_R_TOTAL_TIMEOUT:184:total timeout CMP_R_TRANSACTIONID_UNMATCHED:152:transactionid unmatched +CMP_R_TRANSFER_ERROR:159:transfer error CMP_R_UNEXPECTED_PKIBODY:133:unexpected pkibody +CMP_R_UNEXPECTED_PKISTATUS:185:unexpected pkistatus CMP_R_UNEXPECTED_PVNO:153:unexpected pvno CMP_R_UNKNOWN_ALGORITHM_ID:134:unknown algorithm id CMP_R_UNKNOWN_CERT_TYPE:135:unknown cert type +CMP_R_UNKNOWN_PKISTATUS:186:unknown pkistatus CMP_R_UNSUPPORTED_ALGORITHM:136:unsupported algorithm CMP_R_UNSUPPORTED_KEY_TYPE:137:unsupported key type CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC:154:\ unsupported protection alg dhbasedmac CMP_R_WRONG_ALGORITHM_OID:138:wrong algorithm oid +CMP_R_WRONG_CERTID_IN_RP:187:wrong certid in rp CMP_R_WRONG_PBM_VALUE:155:wrong pbm value +CMP_R_WRONG_RP_COMPONENT_COUNT:188:wrong rp component count +CMP_R_WRONG_SERIAL_IN_RP:173:wrong serial in rp CMS_R_ADD_SIGNER_ERROR:99:add signer error CMS_R_ATTRIBUTE_ERROR:161:attribute error CMS_R_CERTIFICATE_ALREADY_PRESENT:175:certificate already present @@ -2256,6 +2285,11 @@ CRMF_R_FAILURE_OBTAINING_RANDOM:107:failure obtaining random CRMF_R_ITERATIONCOUNT_BELOW_100:108:iterationcount below 100 CRMF_R_MALFORMED_IV:101:malformed iv CRMF_R_NULL_ARGUMENT:109:null argument +CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY:117:popo inconsistent public key +CRMF_R_POPO_MISSING:121:popo missing +CRMF_R_POPO_MISSING_PUBLIC_KEY:118:popo missing public key +CRMF_R_POPO_MISSING_SUBJECT:119:popo missing subject +CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED:120:popo raverified not accepted CRMF_R_SETTING_MAC_ALGOR_FAILURE:110:setting mac algor failure CRMF_R_SETTING_OWF_ALGOR_FAILURE:111:setting owf algor failure CRMF_R_UNSUPPORTED_ALGORITHM:112:unsupported algorithm @@ -2264,7 +2298,6 @@ CRMF_R_UNSUPPORTED_CIPHER:114:unsupported cipher CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO:115:\ unsupported method for creating popo CRMF_R_UNSUPPORTED_POPO_METHOD:116:unsupported popo method -CRMF_R_UNSUPPORTED_POPO_NOT_ACCEPTED:117:unsupported popo not accepted CRYPTO_R_BAD_ALGORITHM_NAME:117:bad algorithm name CRYPTO_R_CONFLICTING_NAMES:118:conflicting names CRYPTO_R_FIPS_MODE_NOT_SUPPORTED:101:fips mode not supported @@ -2489,10 +2522,13 @@ EVP_R_EXPECTING_A_DSA_KEY:129:expecting a dsa key EVP_R_EXPECTING_A_EC_KEY:142:expecting a ec key EVP_R_EXPECTING_A_POLY1305_KEY:164:expecting a poly1305 key EVP_R_EXPECTING_A_SIPHASH_KEY:175:expecting a siphash key +EVP_R_FETCH_FAILED:202:fetch failed EVP_R_FINAL_ERROR:188:final error EVP_R_FIPS_MODE_NOT_SUPPORTED:167:fips mode not supported EVP_R_GET_RAW_KEY_FAILED:182:get raw key failed EVP_R_ILLEGAL_SCRYPT_PARAMETERS:171:illegal scrypt parameters +EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS:204:inaccessible domain parameters +EVP_R_INACCESSIBLE_KEY:203:inaccessible key EVP_R_INITIALIZATION_ERROR:134:initialization error EVP_R_INPUT_NOT_INITIALIZED:111:input not initialized EVP_R_INVALID_CUSTOM_LENGTH:185:invalid custom length @@ -2505,6 +2541,7 @@ EVP_R_INVALID_OPERATION:148:invalid operation EVP_R_INVALID_PROVIDER_FUNCTIONS:193:invalid provider functions EVP_R_INVALID_SALT_LENGTH:186:invalid salt length EVP_R_KEYGEN_FAILURE:120:keygen failure +EVP_R_KEYMGMT_EXPORT_FAILURE:205:keymgmt export failure EVP_R_KEY_SETUP_FAILED:180:key setup failed EVP_R_MEMORY_LIMIT_EXCEEDED:172:memory limit exceeded EVP_R_MESSAGE_DIGEST_IS_NULL:159:message digest is null @@ -2515,6 +2552,7 @@ EVP_R_NOT_XOF_OR_INVALID_LENGTH:178:not XOF or invalid length EVP_R_NO_CIPHER_SET:131:no cipher set EVP_R_NO_DEFAULT_DIGEST:158:no default digest EVP_R_NO_DIGEST_SET:139:no digest set +EVP_R_NO_IMPORT_FUNCTION:206:no import function EVP_R_NO_KEYMGMT_AVAILABLE:199:no keymgmt available EVP_R_NO_KEYMGMT_PRESENT:196:no keymgmt present EVP_R_NO_KEY_SET:154:no key set @@ -2534,6 +2572,7 @@ EVP_R_PUBLIC_KEY_NOT_RSA:106:public key not rsa EVP_R_TOO_MANY_RECORDS:183:too many records EVP_R_UNKNOWN_CIPHER:160:unknown cipher EVP_R_UNKNOWN_DIGEST:161:unknown digest +EVP_R_UNKNOWN_KEY_TYPE:207:unknown key type EVP_R_UNKNOWN_OPTION:169:unknown option EVP_R_UNKNOWN_PBE_ALGORITHM:121:unknown pbe algorithm EVP_R_UNSUPPORTED_ALGORITHM:156:unsupported algorithm @@ -2563,12 +2602,13 @@ HTTP_R_MAX_RESP_LEN_EXCEEDED:117:max resp len exceeded HTTP_R_MISSING_ASN1_ENCODING:110:missing asn1 encoding HTTP_R_MISSING_CONTENT_TYPE:121:missing content type HTTP_R_MISSING_REDIRECT_LOCATION:111:missing redirect location +HTTP_R_RECEIVED_ERROR:105:received error +HTTP_R_RECEIVED_WRONG_HTTP_VERSION:106:received wrong http version HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP:112:redirection from https to http HTTP_R_REDIRECTION_NOT_ENABLED:116:redirection not enabled HTTP_R_RESPONSE_LINE_TOO_LONG:113:response line too long -HTTP_R_SERVER_RESPONSE_PARSE_ERROR:104:server response parse error -HTTP_R_SERVER_SENT_ERROR:105:server sent error -HTTP_R_SERVER_SENT_WRONG_HTTP_VERSION:106:server sent wrong http version +HTTP_R_RESPONSE_PARSE_ERROR:104:response parse error +HTTP_R_SOCK_NOT_SUPPORTED:122:sock not supported HTTP_R_STATUS_CODE_UNSUPPORTED:114:status code unsupported HTTP_R_TLS_NOT_ENABLED:107:tls not enabled HTTP_R_TOO_MANY_REDIRECTIONS:115:too many redirections @@ -2773,11 +2813,13 @@ PROV_R_FAILED_TO_DECRYPT:162:failed to decrypt PROV_R_FAILED_TO_GENERATE_KEY:121:failed to generate key PROV_R_FAILED_TO_GET_PARAMETER:103:failed to get parameter PROV_R_FAILED_TO_SET_PARAMETER:104:failed to set parameter +PROV_R_FAILED_TO_SIGN:175:failed to sign PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE:165:\ illegal or unsupported padding mode PROV_R_INAVLID_UKM_LENGTH:146:inavlid ukm length PROV_R_INVALID_AAD:108:invalid aad PROV_R_INVALID_CONSTANT_LENGTH:157:invalid constant length +PROV_R_INVALID_CURVE:176:invalid curve PROV_R_INVALID_CUSTOM_LENGTH:111:invalid custom length PROV_R_INVALID_DATA:115:invalid data PROV_R_INVALID_DIGEST:122:invalid digest @@ -2817,6 +2859,7 @@ PROV_R_MISSING_XCGHASH:135:missing xcghash PROV_R_NOT_SUPPORTED:136:not supported PROV_R_NOT_XOF_OR_INVALID_LENGTH:113:not xof or invalid length PROV_R_NO_KEY_SET:114:no key set +PROV_R_NO_PARAMETERS_SET:177:no parameters set PROV_R_OUTPUT_BUFFER_TOO_SMALL:106:output buffer too small PROV_R_PSS_SALTLEN_TOO_SMALL:172:pss saltlen too small PROV_R_READ_KEY:159:read key @@ -3076,6 +3119,7 @@ SSL_R_EXTENSION_NOT_RECEIVED:279:extension not received SSL_R_EXTRA_DATA_IN_MESSAGE:153:extra data in message SSL_R_EXT_LENGTH_MISMATCH:163:ext length mismatch SSL_R_FAILED_TO_INIT_ASYNC:405:failed to init async +SSL_R_ALGORITHM_FETCH_FAILED:295:algorithm fetch failed SSL_R_FRAGMENTED_CLIENT_HELLO:401:fragmented client hello SSL_R_GOT_A_FIN_BEFORE_A_CCS:154:got a fin before a ccs SSL_R_HTTPS_PROXY_REQUEST:155:https proxy request diff --git a/crypto/ess/ess_lib.c b/crypto/ess/ess_lib.c index 17c0ea56..a2d6bfe7 100644 --- a/crypto/ess/ess_lib.c +++ b/crypto/ess/ess_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -59,7 +59,8 @@ static ESS_CERT_ID *ESS_CERT_ID_new_init(X509 *cert, int issuer_needed) X509_check_purpose(cert, -1, 0); if ((cid = ESS_CERT_ID_new()) == NULL) goto err; - X509_digest(cert, EVP_sha1(), cert_sha1, NULL); + if (!X509_digest(cert, EVP_sha1(), cert_sha1, NULL)) + goto err; if (!ASN1_OCTET_STRING_set(cid->hash, cert_sha1, SHA_DIGEST_LENGTH)) goto err; diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c index be6fcb58..040a92dc 100644 --- a/crypto/evp/digest.c +++ b/crypto/evp/digest.c @@ -657,12 +657,12 @@ int EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2) size_t sz; OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; - if (ctx == NULL || ctx->digest == NULL) { - ERR_raise(ERR_LIB_EVP, EVP_R_MESSAGE_DIGEST_IS_NULL); + if (ctx == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); return 0; } - if (ctx->digest->prov == NULL) + if (ctx->digest != NULL && ctx->digest->prov == NULL) goto legacy; switch (cmd) { diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c index 62ca87c6..3f2b814f 100644 --- a/crypto/evp/evp_err.c +++ b/crypto/evp/evp_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -64,12 +64,16 @@ static const ERR_STRING_DATA EVP_str_reasons[] = { "expecting a poly1305 key"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_SIPHASH_KEY), "expecting a siphash key"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_FETCH_FAILED), "fetch failed"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_FINAL_ERROR), "final error"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_FIPS_MODE_NOT_SUPPORTED), "fips mode not supported"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_GET_RAW_KEY_FAILED), "get raw key failed"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ILLEGAL_SCRYPT_PARAMETERS), "illegal scrypt parameters"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS), + "inaccessible domain parameters"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INACCESSIBLE_KEY), "inaccessible key"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INITIALIZATION_ERROR), "initialization error"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INPUT_NOT_INITIALIZED), @@ -87,6 +91,8 @@ static const ERR_STRING_DATA EVP_str_reasons[] = { {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_SALT_LENGTH), "invalid salt length"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEYGEN_FAILURE), "keygen failure"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEYMGMT_EXPORT_FAILURE), + "keymgmt export failure"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEY_SETUP_FAILED), "key setup failed"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_MEMORY_LIMIT_EXCEEDED), "memory limit exceeded"}, @@ -102,6 +108,7 @@ static const ERR_STRING_DATA EVP_str_reasons[] = { {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_CIPHER_SET), "no cipher set"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_DEFAULT_DIGEST), "no default digest"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_DIGEST_SET), "no digest set"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_IMPORT_FUNCTION), "no import function"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_KEYMGMT_AVAILABLE), "no keymgmt available"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_KEYMGMT_PRESENT), "no keymgmt present"}, @@ -128,6 +135,7 @@ static const ERR_STRING_DATA EVP_str_reasons[] = { {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_TOO_MANY_RECORDS), "too many records"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_CIPHER), "unknown cipher"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_DIGEST), "unknown digest"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_KEY_TYPE), "unknown key type"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_OPTION), "unknown option"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_PBE_ALGORITHM), "unknown pbe algorithm"}, diff --git a/crypto/evp/evp_fetch.c b/crypto/evp/evp_fetch.c index da7f33e9..e808bf81 100644 --- a/crypto/evp/evp_fetch.c +++ b/crypto/evp/evp_fetch.c @@ -294,9 +294,26 @@ void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id, int (*up_ref_method)(void *), void (*free_method)(void *)) { - return inner_evp_generic_fetch(libctx, - operation_id, 0, name, properties, - new_method, up_ref_method, free_method); + void *ret = inner_evp_generic_fetch(libctx, + operation_id, 0, name, properties, + new_method, up_ref_method, free_method); + + if (ret == NULL) { + int code = EVP_R_FETCH_FAILED; + +#ifdef FIPS_MODE + ERR_raise(ERR_LIB_EVP, code); +#else + ERR_raise_data(ERR_LIB_EVP, code, + "%s, Algorithm (%s), Properties (%s)", + (openssl_ctx_is_default(libctx) + ? "Default library context" + : "Non-default library context"), + name = NULL ? "" : name, + properties == NULL ? "" : properties); +#endif + } + return ret; } /* @@ -314,9 +331,34 @@ void *evp_generic_fetch_by_number(OPENSSL_CTX *libctx, int operation_id, int (*up_ref_method)(void *), void (*free_method)(void *)) { - return inner_evp_generic_fetch(libctx, - operation_id, name_id, NULL, properties, - new_method, up_ref_method, free_method); + void *ret = inner_evp_generic_fetch(libctx, + operation_id, name_id, NULL, + properties, new_method, up_ref_method, + free_method); + + if (ret == NULL) { + int code = EVP_R_FETCH_FAILED; + +#ifdef FIPS_MODE + ERR_raise(ERR_LIB_EVP, code); +#else + { + OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); + const char *name = (namemap == NULL) + ? NULL + : ossl_namemap_num2name(namemap, name_id, 0); + + ERR_raise_data(ERR_LIB_EVP, code, + "%s, Algorithm (%s), Properties (%s)", + (openssl_ctx_is_default(libctx) + ? "Default library context" + : "Non-default library context"), + name = NULL ? "" : name, + properties == NULL ? "" : properties); + } +#endif + } + return ret; } int EVP_set_default_properties(OPENSSL_CTX *libctx, const char *propq) diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h index 774db4da..40f02b34 100644 --- a/crypto/evp/evp_local.h +++ b/crypto/evp/evp_local.h @@ -81,6 +81,16 @@ struct evp_keymgmt_st { OSSL_OP_keymgmt_set_params_fn *set_params; OSSL_OP_keymgmt_settable_params_fn *settable_params; + /* Generation, a complex constructor */ + OSSL_OP_keymgmt_gen_init_fn *gen_init; + OSSL_OP_keymgmt_gen_set_template_fn *gen_set_template; + OSSL_OP_keymgmt_gen_set_params_fn *gen_set_params; + OSSL_OP_keymgmt_gen_settable_params_fn *gen_settable_params; + OSSL_OP_keymgmt_gen_get_params_fn *gen_get_params; + OSSL_OP_keymgmt_gen_gettable_params_fn *gen_gettable_params; + OSSL_OP_keymgmt_gen_fn *gen; + OSSL_OP_keymgmt_gen_cleanup_fn *gen_cleanup; + /* Key object checking */ OSSL_OP_keymgmt_query_operation_name_fn *query_operation_name; OSSL_OP_keymgmt_has_fn *has; @@ -129,9 +139,11 @@ struct evp_signature_st { OSSL_OP_signature_digest_sign_init_fn *digest_sign_init; OSSL_OP_signature_digest_sign_update_fn *digest_sign_update; OSSL_OP_signature_digest_sign_final_fn *digest_sign_final; + OSSL_OP_signature_digest_sign_fn *digest_sign; OSSL_OP_signature_digest_verify_init_fn *digest_verify_init; OSSL_OP_signature_digest_verify_update_fn *digest_verify_update; OSSL_OP_signature_digest_verify_final_fn *digest_verify_final; + OSSL_OP_signature_digest_verify_fn *digest_verify; OSSL_OP_signature_freectx_fn *freectx; OSSL_OP_signature_dupctx_fn *dupctx; OSSL_OP_signature_get_ctx_params_fn *get_ctx_params; diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c index ec5ba03f..3e66e721 100644 --- a/crypto/evp/exchange.c +++ b/crypto/evp/exchange.c @@ -197,7 +197,7 @@ int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx) */ ERR_set_mark(); - if (ctx->engine != NULL || ctx->keytype == NULL) + if (ctx->keymgmt == NULL) goto legacy; /* diff --git a/crypto/evp/keymgmt_lib.c b/crypto/evp/keymgmt_lib.c index 68ccdbb8..6c66bfa7 100644 --- a/crypto/evp/keymgmt_lib.c +++ b/crypto/evp/keymgmt_lib.c @@ -39,13 +39,26 @@ static int try_import(const OSSL_PARAM params[], void *arg) { struct import_data_st *data = arg; + /* + * It's fine if there was no data to transfer, we just end up with an + * empty destination key. + */ + if (params[0].key == NULL) + return 1; + + /* Just in time creation of keydata, if needed */ + if (data->keydata == NULL + && (data->keydata = evp_keymgmt_newdata(data->keymgmt)) == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + return 0; + } + return evp_keymgmt_import(data->keymgmt, data->keydata, data->selection, params); } void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt) { - void *keydata = NULL; struct import_data_st import_data; size_t i = 0; @@ -54,7 +67,7 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt) return NULL; /* If we have an unassigned key, give up */ - if (pk->keymgmt == NULL) + if (pk->keydata == NULL) return NULL; /* If |keymgmt| matches the "origin" |keymgmt|, no more to do */ @@ -91,10 +104,6 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt) if (!ossl_assert(match_type(pk->keymgmt, keymgmt))) return NULL; - /* Create space to import data into */ - if ((keydata = evp_keymgmt_newdata(keymgmt)) == NULL) - return NULL; - /* * We look at the already cached provider keys, and import from the * first that supports it (i.e. use its export function), and export @@ -102,7 +111,7 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt) */ /* Setup for the export callback */ - import_data.keydata = keydata; + import_data.keydata = NULL; /* try_import will create it */ import_data.keymgmt = keymgmt; import_data.selection = OSSL_KEYMGMT_SELECT_ALL; @@ -113,17 +122,17 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt) if (!evp_keymgmt_export(pk->keymgmt, pk->keydata, OSSL_KEYMGMT_SELECT_ALL, &try_import, &import_data)) { /* If there was an error, bail out */ - evp_keymgmt_freedata(keymgmt, keydata); + evp_keymgmt_freedata(keymgmt, import_data.keydata); return NULL; } /* Add the new export to the operation cache */ - if (!evp_keymgmt_util_cache_keydata(pk, i, keymgmt, keydata)) { - evp_keymgmt_freedata(keymgmt, keydata); + if (!evp_keymgmt_util_cache_keydata(pk, i, keymgmt, import_data.keydata)) { + evp_keymgmt_freedata(keymgmt, import_data.keydata); return NULL; } - return keydata; + return import_data.keydata; } void evp_keymgmt_util_clear_operation_cache(EVP_PKEY *pk) @@ -175,7 +184,7 @@ void evp_keymgmt_util_cache_keyinfo(EVP_PKEY *pk) * * This services functions like EVP_PKEY_size, EVP_PKEY_bits, etc */ - if (pk->keymgmt != NULL) { + if (pk->keydata != NULL) { int bits = 0; int security_bits = 0; int size = 0; @@ -197,17 +206,15 @@ void evp_keymgmt_util_cache_keyinfo(EVP_PKEY *pk) void *evp_keymgmt_util_fromdata(EVP_PKEY *target, EVP_KEYMGMT *keymgmt, int selection, const OSSL_PARAM params[]) { - void *keydata = evp_keymgmt_newdata(keymgmt); + void *keydata = NULL; + if ((keydata = evp_keymgmt_newdata(keymgmt)) == NULL + || !evp_keymgmt_import(keymgmt, keydata, selection, params) + || !EVP_PKEY_set_type_by_keymgmt(target, keymgmt)) { + evp_keymgmt_freedata(keymgmt, keydata); + keydata = NULL; + } if (keydata != NULL) { - if (!evp_keymgmt_import(keymgmt, keydata, selection, params) - || !EVP_KEYMGMT_up_ref(keymgmt)) { - evp_keymgmt_freedata(keymgmt, keydata); - return NULL; - } - - evp_keymgmt_util_clear_operation_cache(target); - target->keymgmt = keymgmt; target->keydata = keydata; evp_keymgmt_util_cache_keyinfo(target); } @@ -254,7 +261,17 @@ int evp_keymgmt_util_match(EVP_PKEY *pk1, EVP_PKEY *pk2, int selection) keydata2 = pk2->keydata; if (keymgmt1 != keymgmt2) { - void *tmp_keydata = NULL; + /* + * The condition for a successful cross export is that the + * keydata to be exported is NULL (typed, but otherwise empty + * EVP_PKEY), or that it was possible to export it with + * evp_keymgmt_util_export_to_provider(). + * + * We use |ok| to determine if it's ok to cross export one way, + * but also to determine if we should attempt a cross export + * the other way. There's no point doing it both ways. + */ + int ok = 1; /* Complex case, where the keymgmt differ */ if (keymgmt1 != NULL @@ -270,17 +287,35 @@ int evp_keymgmt_util_match(EVP_PKEY *pk1, EVP_PKEY *pk2, int selection) */ if (keymgmt2 != NULL && keymgmt2->match != NULL) { - tmp_keydata = evp_keymgmt_util_export_to_provider(pk1, keymgmt2); - if (tmp_keydata != NULL) { + void *tmp_keydata = NULL; + + ok = 1; + if (keydata1 != NULL) { + tmp_keydata = + evp_keymgmt_util_export_to_provider(pk1, keymgmt2); + ok = (tmp_keydata != NULL); + } + if (ok) { keymgmt1 = keymgmt2; keydata1 = tmp_keydata; } } - if (tmp_keydata == NULL + /* + * If we've successfully cross exported one way, there's no point + * doing it the other way, hence the |!ok| check. + */ + if (!ok && keymgmt1 != NULL && keymgmt1->match != NULL) { - tmp_keydata = evp_keymgmt_util_export_to_provider(pk2, keymgmt1); - if (tmp_keydata != NULL) { + void *tmp_keydata = NULL; + + ok = 1; + if (keydata2 != NULL) { + tmp_keydata = + evp_keymgmt_util_export_to_provider(pk2, keymgmt1); + ok = (tmp_keydata != NULL); + } + if (ok) { keymgmt2 = keymgmt1; keydata2 = tmp_keydata; } @@ -291,6 +326,13 @@ int evp_keymgmt_util_match(EVP_PKEY *pk1, EVP_PKEY *pk2, int selection) if (keymgmt1 != keymgmt2) return -2; + /* If both keydata are NULL, then they're the same key */ + if (keydata1 == NULL && keydata2 == NULL) + return 1; + /* If only one of the keydata is NULL, then they're different keys */ + if (keydata1 == NULL || keydata2 == NULL) + return 0; + /* If both keydata are non-NULL, we let the backend decide */ return evp_keymgmt_match(keymgmt1, keydata1, keydata2, selection); } @@ -301,23 +343,21 @@ int evp_keymgmt_util_copy(EVP_PKEY *to, EVP_PKEY *from, int selection) void *to_keydata = to->keydata, *alloc_keydata = NULL; /* An unassigned key can't be copied */ - if (from == NULL || from->keymgmt == NULL) + if (from == NULL || from->keydata == NULL) return 0; - /* If |from| doesn't support copying, we fail */ - if (from->keymgmt->copy == NULL) - return 0; - - /* If |to| doesn't have a provider side "origin" yet, create one */ - if (to_keymgmt == NULL) { - to_keydata = alloc_keydata = evp_keymgmt_newdata(from->keymgmt); - if (to_keydata == NULL) + if (to_keymgmt == from->keymgmt && to_keymgmt->copy != NULL) { + /* Make sure there's somewhere to copy to */ + if (to_keydata == NULL + && (to_keydata = evp_keymgmt_newdata(to_keymgmt)) == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); return 0; - to_keymgmt = from->keymgmt; - } + } - if (to_keymgmt == from->keymgmt) { - /* |to| and |from| have the same keymgmt, just copy and be done */ + /* + * |to| and |from| have the same keymgmt, and the copy function is + * implemented, so just copy and be done + */ if (!evp_keymgmt_copy(to_keymgmt, to_keydata, from->keydata, selection)) return 0; @@ -333,20 +373,42 @@ int evp_keymgmt_util_copy(EVP_PKEY *to, EVP_PKEY *from, int selection) evp_keymgmt_freedata(to_keymgmt, alloc_keydata); return 0; } + + /* + * In this case to_keydata was previously unallocated, try_import() + * may have created it for us. + */ + to_keydata = import_data.keydata; } else { ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES); return 0; } if (to->keymgmt == NULL - && !EVP_KEYMGMT_up_ref(to_keymgmt)) { + && !EVP_PKEY_set_type_by_keymgmt(to, to_keymgmt)) { evp_keymgmt_freedata(to_keymgmt, alloc_keydata); return 0; } - evp_keymgmt_util_clear_operation_cache(to); - to->keymgmt = to_keymgmt; to->keydata = to_keydata; evp_keymgmt_util_cache_keyinfo(to); return 1; } + +void *evp_keymgmt_util_gen(EVP_PKEY *target, EVP_KEYMGMT *keymgmt, + void *genctx, OSSL_CALLBACK *cb, void *cbarg) +{ + void *keydata = NULL; + + if ((keydata = evp_keymgmt_gen(keymgmt, genctx, cb, cbarg)) == NULL + || !EVP_PKEY_set_type_by_keymgmt(target, keymgmt)) { + evp_keymgmt_freedata(keymgmt, keydata); + keydata = NULL; + } + if (keydata != NULL) { + target->keydata = keydata; + evp_keymgmt_util_cache_keyinfo(target); + } + + return keydata; +} diff --git a/crypto/evp/keymgmt_meth.c b/crypto/evp/keymgmt_meth.c index f80e6e29..7ea414e8 100644 --- a/crypto/evp/keymgmt_meth.c +++ b/crypto/evp/keymgmt_meth.c @@ -38,7 +38,9 @@ static void *keymgmt_from_dispatch(int name_id, OSSL_PROVIDER *prov) { EVP_KEYMGMT *keymgmt = NULL; - int setparamfncnt = 0, getparamfncnt = 0, importfncnt = 0, exportfncnt = 0; + int setparamfncnt = 0, getparamfncnt = 0; + int setgenparamfncnt = 0, getgenparamfncnt = 0; + int importfncnt = 0, exportfncnt = 0; if ((keymgmt = keymgmt_new()) == NULL) { EVP_KEYMGMT_free(keymgmt); @@ -52,6 +54,51 @@ static void *keymgmt_from_dispatch(int name_id, if (keymgmt->new == NULL) keymgmt->new = OSSL_get_OP_keymgmt_new(fns); break; + case OSSL_FUNC_KEYMGMT_GEN_INIT: + if (keymgmt->gen_init == NULL) + keymgmt->gen_init = OSSL_get_OP_keymgmt_gen_init(fns); + break; + case OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE: + if (keymgmt->gen_set_template == NULL) + keymgmt->gen_set_template = + OSSL_get_OP_keymgmt_gen_set_template(fns); + break; + case OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS: + if (keymgmt->gen_set_params == NULL) { + setgenparamfncnt++; + keymgmt->gen_set_params = + OSSL_get_OP_keymgmt_gen_set_params(fns); + } + break; + case OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS: + if (keymgmt->gen_settable_params == NULL) { + setgenparamfncnt++; + keymgmt->gen_settable_params = + OSSL_get_OP_keymgmt_gen_settable_params(fns); + } + break; + case OSSL_FUNC_KEYMGMT_GEN_GET_PARAMS: + if (keymgmt->gen_get_params == NULL) { + getgenparamfncnt++; + keymgmt->gen_get_params = + OSSL_get_OP_keymgmt_gen_get_params(fns); + } + break; + case OSSL_FUNC_KEYMGMT_GEN_GETTABLE_PARAMS: + if (keymgmt->gen_gettable_params == NULL) { + getgenparamfncnt++; + keymgmt->gen_gettable_params = + OSSL_get_OP_keymgmt_gen_gettable_params(fns); + } + break; + case OSSL_FUNC_KEYMGMT_GEN: + if (keymgmt->gen == NULL) + keymgmt->gen = OSSL_get_OP_keymgmt_gen(fns); + break; + case OSSL_FUNC_KEYMGMT_GEN_CLEANUP: + if (keymgmt->gen_cleanup == NULL) + keymgmt->gen_cleanup = OSSL_get_OP_keymgmt_gen_cleanup(fns); + break; case OSSL_FUNC_KEYMGMT_FREE: if (keymgmt->free == NULL) keymgmt->free = OSSL_get_OP_keymgmt_free(fns); @@ -134,12 +181,17 @@ static void *keymgmt_from_dispatch(int name_id, * export if you can't import or export. */ if (keymgmt->free == NULL - || keymgmt->new == NULL + || (keymgmt->new == NULL && keymgmt->gen == NULL) || keymgmt->has == NULL || (getparamfncnt != 0 && getparamfncnt != 2) || (setparamfncnt != 0 && setparamfncnt != 2) + || (setgenparamfncnt != 0 && setgenparamfncnt != 2) + || (getgenparamfncnt != 0 && getgenparamfncnt != 2) || (importfncnt != 0 && importfncnt != 2) - || (exportfncnt != 0 && exportfncnt != 2)) { + || (exportfncnt != 0 && exportfncnt != 2) + || (keymgmt->gen != NULL + && (keymgmt->gen_init == NULL + || keymgmt->gen_cleanup == NULL))) { EVP_KEYMGMT_free(keymgmt); EVPerr(0, EVP_R_INVALID_PROVIDER_FUNCTIONS); return NULL; @@ -249,6 +301,71 @@ void evp_keymgmt_freedata(const EVP_KEYMGMT *keymgmt, void *keydata) keymgmt->free(keydata); } +void *evp_keymgmt_gen_init(const EVP_KEYMGMT *keymgmt, int selection) +{ + void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt)); + + if (keymgmt->gen_init == NULL) + return NULL; + return keymgmt->gen_init(provctx, selection); +} + +int evp_keymgmt_gen_set_template(const EVP_KEYMGMT *keymgmt, void *genctx, + void *template) +{ + if (keymgmt->gen_set_template == NULL) + return 0; + return keymgmt->gen_set_template(genctx, template); +} + +int evp_keymgmt_gen_set_params(const EVP_KEYMGMT *keymgmt, void *genctx, + const OSSL_PARAM params[]) +{ + if (keymgmt->gen_set_params == NULL) + return 0; + return keymgmt->gen_set_params(genctx, params); +} + +const OSSL_PARAM *evp_keymgmt_gen_settable_params(const EVP_KEYMGMT *keymgmt) +{ + void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt)); + + if (keymgmt->gen_settable_params == NULL) + return NULL; + return keymgmt->gen_settable_params(provctx); +} + +int evp_keymgmt_gen_get_params(const EVP_KEYMGMT *keymgmt, void *genctx, + OSSL_PARAM params[]) +{ + if (keymgmt->gen_get_params == NULL) + return 0; + return keymgmt->gen_get_params(genctx, params); +} + +const OSSL_PARAM *evp_keymgmt_gen_gettable_params(const EVP_KEYMGMT *keymgmt) +{ + void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt)); + + if (keymgmt->gen_gettable_params == NULL) + return NULL; + return keymgmt->gen_gettable_params(provctx); +} + +void *evp_keymgmt_gen(const EVP_KEYMGMT *keymgmt, void *genctx, + OSSL_CALLBACK *cb, void *cbarg) +{ + if (keymgmt->gen == NULL) + return NULL; + return keymgmt->gen(genctx, cb, cbarg); +} + +void evp_keymgmt_gen_cleanup(const EVP_KEYMGMT *keymgmt, void *genctx) +{ + if (keymgmt->gen != NULL) + keymgmt->gen_cleanup(genctx); +} + int evp_keymgmt_get_params(const EVP_KEYMGMT *keymgmt, void *keydata, OSSL_PARAM params[]) { diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c index b6c66722..8dd4207d 100644 --- a/crypto/evp/m_sigver.c +++ b/crypto/evp/m_sigver.c @@ -24,10 +24,22 @@ static int update(EVP_MD_CTX *ctx, const void *data, size_t datalen) return 0; } +/* + * If we get the "NULL" md then the name comes back as "UNDEF". We want to use + * NULL for this. + */ +static const char *canon_mdname(const char *mdname) +{ + if (mdname != NULL && strcmp(mdname, "UNDEF") == 0) + return NULL; + + return mdname; +} + static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, const char *mdname, const char *props, ENGINE *e, EVP_PKEY *pkey, - int ver) + OPENSSL_CTX *libctx, int ver) { EVP_PKEY_CTX *locpctx = NULL; EVP_SIGNATURE *signature = NULL; @@ -47,8 +59,12 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, ctx->provctx = NULL; } - if (ctx->pctx == NULL) - ctx->pctx = EVP_PKEY_CTX_new(pkey, e); + if (ctx->pctx == NULL) { + if (libctx != NULL) + ctx->pctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, props); + else + ctx->pctx = EVP_PKEY_CTX_new(pkey, e); + } if (ctx->pctx == NULL) return 0; @@ -61,7 +77,7 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, */ ERR_set_mark(); - if (locpctx->keytype == NULL) + if (locpctx->engine != NULL || locpctx->keytype == NULL) goto legacy; /* @@ -134,12 +150,12 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, if (type != NULL) { ctx->reqdigest = type; if (mdname == NULL) - mdname = EVP_MD_name(type); + mdname = canon_mdname(EVP_MD_name(type)); } else { if (mdname == NULL && EVP_PKEY_get_default_digest_name(locpctx->pkey, locmdname, sizeof(locmdname))) - mdname = locmdname; + mdname = canon_mdname(locmdname); if (mdname != NULL) { /* @@ -184,6 +200,9 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, */ ERR_pop_to_mark(); + if (type == NULL && mdname != NULL) + type = evp_get_digestbyname_ex(locpctx->libctx, mdname); + if (ctx->pctx->pmeth == NULL) { EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); return 0; @@ -238,35 +257,38 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, * This indicates the current algorithm requires * special treatment before hashing the tbs-message. */ + ctx->pctx->flag_call_digest_custom = 0; if (ctx->pctx->pmeth->digest_custom != NULL) - return ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx); + ctx->pctx->flag_call_digest_custom = 1; return 1; } int EVP_DigestSignInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, - const char *mdname, const char *props, EVP_PKEY *pkey) + const char *mdname, const char *props, EVP_PKEY *pkey, + OPENSSL_CTX *libctx) { - return do_sigver_init(ctx, pctx, NULL, mdname, props, NULL, pkey, 0); + return do_sigver_init(ctx, pctx, NULL, mdname, props, NULL, pkey, libctx, + 0); } int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey) { - return do_sigver_init(ctx, pctx, type, NULL, NULL, e, pkey, 0); + return do_sigver_init(ctx, pctx, type, NULL, NULL, e, pkey, NULL, 0); } int EVP_DigestVerifyInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const char *mdname, const char *props, - EVP_PKEY *pkey) + EVP_PKEY *pkey, OPENSSL_CTX *libctx) { - return do_sigver_init(ctx, pctx, NULL, mdname, props, NULL, pkey, 1); + return do_sigver_init(ctx, pctx, NULL, mdname, props, NULL, pkey, libctx, 1); } int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey) { - return do_sigver_init(ctx, pctx, type, NULL, NULL, e, pkey, 1); + return do_sigver_init(ctx, pctx, type, NULL, NULL, e, pkey, NULL, 1); } #endif /* FIPS_MDOE */ @@ -280,10 +302,21 @@ int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize) || pctx->op.sig.signature == NULL) goto legacy; + if (pctx->op.sig.signature->digest_sign_update == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return pctx->op.sig.signature->digest_sign_update(pctx->op.sig.sigprovctx, data, dsize); legacy: + /* do_sigver_init() checked that |digest_custom| is non-NULL */ + if (pctx->flag_call_digest_custom + && !ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx)) + return 0; + pctx->flag_call_digest_custom = 0; + return EVP_DigestUpdate(ctx, data, dsize); } @@ -297,10 +330,21 @@ int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize) || pctx->op.sig.signature == NULL) goto legacy; + if (pctx->op.sig.signature->digest_verify_update == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return pctx->op.sig.signature->digest_verify_update(pctx->op.sig.sigprovctx, data, dsize); legacy: + /* do_sigver_init() checked that |digest_custom| is non-NULL */ + if (pctx->flag_call_digest_custom + && !ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx)) + return 0; + pctx->flag_call_digest_custom = 0; + return EVP_DigestUpdate(ctx, data, dsize); } @@ -326,6 +370,12 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, return 0; } + /* do_sigver_init() checked that |digest_custom| is non-NULL */ + if (pctx->flag_call_digest_custom + && !ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx)) + return 0; + pctx->flag_call_digest_custom = 0; + if (pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) { if (sigret == NULL) return pctx->pmeth->signctx(pctx, sigret, siglen, ctx); @@ -391,8 +441,22 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen, const unsigned char *tbs, size_t tbslen) { - if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestsign != NULL) - return ctx->pctx->pmeth->digestsign(ctx, sigret, siglen, tbs, tbslen); + EVP_PKEY_CTX *pctx = ctx->pctx; + + if (pctx != NULL + && pctx->operation == EVP_PKEY_OP_SIGNCTX + && pctx->op.sig.sigprovctx != NULL + && pctx->op.sig.signature != NULL) { + if (pctx->op.sig.signature->digest_sign != NULL) + return pctx->op.sig.signature->digest_sign(pctx->op.sig.sigprovctx, + sigret, siglen, SIZE_MAX, + tbs, tbslen); + } else { + /* legacy */ + if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestsign != NULL) + return ctx->pctx->pmeth->digestsign(ctx, sigret, siglen, tbs, tbslen); + } + if (sigret != NULL && EVP_DigestSignUpdate(ctx, tbs, tbslen) <= 0) return 0; return EVP_DigestSignFinal(ctx, sigret, siglen); @@ -422,6 +486,12 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, return 0; } + /* do_sigver_init() checked that |digest_custom| is non-NULL */ + if (pctx->flag_call_digest_custom + && !ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx)) + return 0; + pctx->flag_call_digest_custom = 0; + if (pctx->pmeth->verifyctx != NULL) vctx = 1; else @@ -454,8 +524,22 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, size_t siglen, const unsigned char *tbs, size_t tbslen) { - if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestverify != NULL) - return ctx->pctx->pmeth->digestverify(ctx, sigret, siglen, tbs, tbslen); + EVP_PKEY_CTX *pctx = ctx->pctx; + + if (pctx != NULL + && pctx->operation == EVP_PKEY_OP_VERIFYCTX + && pctx->op.sig.sigprovctx != NULL + && pctx->op.sig.signature != NULL) { + if (pctx->op.sig.signature->digest_verify != NULL) + return pctx->op.sig.signature->digest_verify(pctx->op.sig.sigprovctx, + sigret, siglen, + tbs, tbslen); + } else { + /* legacy */ + if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestverify != NULL) + return ctx->pctx->pmeth->digestverify(ctx, sigret, siglen, tbs, tbslen); + } + if (EVP_DigestVerifyUpdate(ctx, tbs, tbslen) <= 0) return -1; return EVP_DigestVerifyFinal(ctx, sigret, siglen); diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index 586ffaf0..9f04c723 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -32,13 +33,24 @@ #include "crypto/asn1.h" #include "crypto/evp.h" +#include "internal/evp.h" #include "internal/provider.h" #include "evp_local.h" +#include "crypto/ec.h" + +/* TODO remove this when the EVP_PKEY_is_a() #legacy support hack is removed */ +#include "e_os.h" /* strcasecmp on Windows */ + +static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str, + int len, EVP_KEYMGMT *keymgmt); static void evp_pkey_free_it(EVP_PKEY *key); #ifndef FIPS_MODE +/* The type of parameters selected in key parameter functions */ +# define SELECT_PARAMETERS OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS + int EVP_PKEY_bits(const EVP_PKEY *pkey) { if (pkey != NULL) { @@ -84,6 +96,16 @@ int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode) return 0; } +int EVP_PKEY_set_ex_data(EVP_PKEY *key, int idx, void *arg) +{ + return CRYPTO_set_ex_data(&key->ex_data, idx, arg); +} + +void *EVP_PKEY_get_ex_data(const EVP_PKEY *key, int idx) +{ + return CRYPTO_get_ex_data(&key->ex_data, idx); +} + int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) { /* @@ -92,16 +114,35 @@ int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) */ /* - * Only check that type match this early when both keys are legacy. - * If either of them is provided, we let evp_keymgmt_util_copy() - * do this check, after having exported either of them that isn't - * provided. + * If |to| is a legacy key and |from| isn't, we must downgrade |from|. + * If that fails, this function fails. */ - if (to->keymgmt == NULL && from->keymgmt == NULL) { - if (to->type == EVP_PKEY_NONE) { + if (to->type != EVP_PKEY_NONE && from->keymgmt != NULL) + if (!evp_pkey_downgrade((EVP_PKEY *)from)) + return 0; + + /* + * Make sure |to| is typed. Content is less important at this early + * stage. + * + * 1. If |to| is untyped, assign |from|'s key type to it. + * 2. If |to| contains a legacy key, compare its |type| to |from|'s. + * (|from| was already downgraded above) + * + * If |to| is a provided key, there's nothing more to do here, functions + * like evp_keymgmt_util_copy() and evp_pkey_export_to_provider() called + * further down help us find out if they are the same or not. + */ + if (to->type == EVP_PKEY_NONE && to->keymgmt == NULL) { + if (from->type != EVP_PKEY_NONE) { if (EVP_PKEY_set_type(to, from->type) == 0) return 0; - } else if (to->type != from->type) { + } else { + if (EVP_PKEY_set_type_by_keymgmt(to, from->keymgmt) == 0) + return 0; + } + } else if (to->type != EVP_PKEY_NONE) { + if (to->type != from->type) { EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_DIFFERENT_KEY_TYPES); goto err; } @@ -119,34 +160,9 @@ int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) return 0; } - /* - * If |from| is provided, we upgrade |to| to be provided as well. - * This drops the legacy key from |to|. - * evp_pkey_upgrade_to_provider() checks if |to| is already provided, - * we don't need to do that here. - * - * TODO(3.0) We should investigate if that's too aggressive and make - * this scenario unsupported instead. - */ - if (from->keymgmt != NULL) { - EVP_KEYMGMT *tmp_keymgmt = from->keymgmt; - - /* - * The returned pointer is known to be cached, so we don't have to - * save it. However, if it's NULL, something went wrong and we can't - * copy. - */ - if (evp_pkey_upgrade_to_provider(to, NULL, - &tmp_keymgmt, NULL) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); - return 0; - } - } - /* For purely provided keys, we just call the keymgmt utility */ if (to->keymgmt != NULL && from->keymgmt != NULL) - return evp_keymgmt_util_copy(to, (EVP_PKEY *)from, - OSSL_KEYMGMT_SELECT_ALL_PARAMETERS); + return evp_keymgmt_util_copy(to, (EVP_PKEY *)from, SELECT_PARAMETERS); /* * If |to| is provided, we know that |from| is legacy at this point. @@ -159,12 +175,16 @@ int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) evp_pkey_export_to_provider((EVP_PKEY *)from, NULL, &to_keymgmt, NULL); + /* + * If we get a NULL, it could be an internal error, or it could be + * that there's a key mismatch. We're pretending the latter... + */ if (from_keydata == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES); return 0; } return evp_keymgmt_copy(to->keymgmt, to->keydata, from_keydata, - OSSL_KEYMGMT_SELECT_ALL_PARAMETERS); + SELECT_PARAMETERS); } /* Both keys are legacy */ @@ -178,8 +198,7 @@ int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey) { if (pkey != NULL) { if (pkey->keymgmt != NULL) - return !evp_keymgmt_util_has((EVP_PKEY *)pkey, - OSSL_KEYMGMT_SELECT_ALL_PARAMETERS); + return !evp_keymgmt_util_has((EVP_PKEY *)pkey, SELECT_PARAMETERS); else if (pkey->ameth != NULL && pkey->ameth->param_missing != NULL) return pkey->ameth->param_missing(pkey); } @@ -206,20 +225,25 @@ static int evp_pkey_cmp_any(const EVP_PKEY *a, const EVP_PKEY *b, return evp_keymgmt_util_match((EVP_PKEY *)a, (EVP_PKEY *)b, selection); /* - * Here, we know that we have a mixture of legacy and provided keys. - * Try cross export and compare the resulting key data. + * At this point, one of them is provided, the other not. This allows + * us to compare types using legacy NIDs. + */ + if ((a->type != EVP_PKEY_NONE + && !EVP_KEYMGMT_is_a(b->keymgmt, OBJ_nid2sn(a->type))) + || (b->type != EVP_PKEY_NONE + && !EVP_KEYMGMT_is_a(a->keymgmt, OBJ_nid2sn(b->type)))) + return -1; /* not the same key type */ + + /* + * We've determined that they both are the same keytype, so the next + * step is to do a bit of cross export to ensure we have keydata for + * both keys in the same keymgmt. */ keymgmt1 = a->keymgmt; keydata1 = a->keydata; keymgmt2 = b->keymgmt; keydata2 = b->keydata; - if ((keymgmt1 == NULL - && !EVP_KEYMGMT_is_a(keymgmt2, OBJ_nid2sn(a->type))) - || (keymgmt2 == NULL - && !EVP_KEYMGMT_is_a(keymgmt1, OBJ_nid2sn(b->type)))) - return -1; /* not the same key type */ - if (keymgmt2 != NULL && keymgmt2->match != NULL) { tmp_keydata = evp_pkey_export_to_provider((EVP_PKEY *)a, NULL, &keymgmt2, NULL); @@ -252,7 +276,7 @@ int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) */ if (a->keymgmt != NULL || b->keymgmt != NULL) - return evp_pkey_cmp_any(a, b, OSSL_KEYMGMT_SELECT_ALL_PARAMETERS); + return evp_pkey_cmp_any(a, b, SELECT_PARAMETERS); /* All legacy keys */ if (a->type != b->type) @@ -270,9 +294,8 @@ int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) */ if (a->keymgmt != NULL || b->keymgmt != NULL) - return evp_pkey_cmp_any(a, b, - OSSL_KEYMGMT_SELECT_ALL_PARAMETERS - | OSSL_KEYMGMT_SELECT_PUBLIC_KEY); + return evp_pkey_cmp_any(a, b, (SELECT_PARAMETERS + | OSSL_KEYMGMT_SELECT_PUBLIC_KEY)); /* All legacy keys */ if (a->type != b->type) @@ -294,57 +317,6 @@ int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) return -2; } - -/* - * Setup a public key ASN1 method and ENGINE from a NID or a string. If pkey - * is NULL just return 1 or 0 if the algorithm exists. - */ - -static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str, - int len) -{ - const EVP_PKEY_ASN1_METHOD *ameth; - ENGINE **eptr = (e == NULL) ? &e : NULL; - - if (pkey) { - if (pkey->pkey.ptr) - evp_pkey_free_it(pkey); - /* - * If key type matches and a method exists then this lookup has - * succeeded once so just indicate success. - */ - if ((type == pkey->save_type) && pkey->ameth) - return 1; -# ifndef OPENSSL_NO_ENGINE - /* If we have ENGINEs release them */ - ENGINE_finish(pkey->engine); - pkey->engine = NULL; - ENGINE_finish(pkey->pmeth_engine); - pkey->pmeth_engine = NULL; -# endif - } - if (str) - ameth = EVP_PKEY_asn1_find_str(eptr, str, len); - else - ameth = EVP_PKEY_asn1_find(eptr, type); -# ifndef OPENSSL_NO_ENGINE - if (pkey == NULL && eptr != NULL) - ENGINE_finish(e); -# endif - if (ameth == NULL) { - EVPerr(EVP_F_PKEY_SET_TYPE, EVP_R_UNSUPPORTED_ALGORITHM); - return 0; - } - if (pkey) { - pkey->ameth = ameth; - pkey->engine = e; - - pkey->type = pkey->ameth->pkey_id; - pkey->save_type = type; - } - return 1; -} - EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e, const unsigned char *priv, size_t len) @@ -352,7 +324,7 @@ EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e, EVP_PKEY *ret = EVP_PKEY_new(); if (ret == NULL - || !pkey_set_type(ret, e, type, NULL, -1)) { + || !pkey_set_type(ret, e, type, NULL, -1, NULL)) { /* EVPerr already called */ goto err; } @@ -382,7 +354,7 @@ EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e, EVP_PKEY *ret = EVP_PKEY_new(); if (ret == NULL - || !pkey_set_type(ret, e, type, NULL, -1)) { + || !pkey_set_type(ret, e, type, NULL, -1, NULL)) { /* EVPerr already called */ goto err; } @@ -408,6 +380,7 @@ EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e, int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv, size_t *len) { + /* TODO(3.0) Do we need to do anything about provider side keys? */ if (pkey->ameth->get_priv_key == NULL) { EVPerr(EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); @@ -425,6 +398,7 @@ int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv, int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub, size_t *len) { + /* TODO(3.0) Do we need to do anything about provider side keys? */ if (pkey->ameth->get_pub_key == NULL) { EVPerr(EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); @@ -457,8 +431,8 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv, size_t paramsn = 0; if (ret == NULL - || cmctx == NULL - || !pkey_set_type(ret, e, EVP_PKEY_CMAC, NULL, -1)) { + || cmctx == NULL + || !pkey_set_type(ret, e, EVP_PKEY_CMAC, NULL, -1, NULL)) { /* EVPerr already called */ goto err; } @@ -499,12 +473,12 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv, int EVP_PKEY_set_type(EVP_PKEY *pkey, int type) { - return pkey_set_type(pkey, NULL, type, NULL, -1); + return pkey_set_type(pkey, NULL, type, NULL, -1, NULL); } int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len) { - return pkey_set_type(pkey, NULL, EVP_PKEY_NONE, str, len); + return pkey_set_type(pkey, NULL, EVP_PKEY_NONE, str, len, NULL); } int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type) @@ -573,6 +547,10 @@ int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) void *EVP_PKEY_get0(const EVP_PKEY *pkey) { + if (!evp_pkey_downgrade((EVP_PKEY *)pkey)) { + ERR_raise(ERR_LIB_EVP, EVP_R_INACCESSIBLE_KEY); + return NULL; + } return pkey->pkey.ptr; } @@ -628,6 +606,10 @@ int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key) RSA *EVP_PKEY_get0_RSA(const EVP_PKEY *pkey) { + if (!evp_pkey_downgrade((EVP_PKEY *)pkey)) { + ERR_raise(ERR_LIB_EVP, EVP_R_INACCESSIBLE_KEY); + return NULL; + } if (pkey->type != EVP_PKEY_RSA && pkey->type != EVP_PKEY_RSA_PSS) { EVPerr(EVP_F_EVP_PKEY_GET0_RSA, EVP_R_EXPECTING_AN_RSA_KEY); return NULL; @@ -655,6 +637,10 @@ int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key) DSA *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey) { + if (!evp_pkey_downgrade((EVP_PKEY *)pkey)) { + ERR_raise(ERR_LIB_EVP, EVP_R_INACCESSIBLE_KEY); + return NULL; + } if (pkey->type != EVP_PKEY_DSA) { EVPerr(EVP_F_EVP_PKEY_GET0_DSA, EVP_R_EXPECTING_A_DSA_KEY); return NULL; @@ -683,6 +669,10 @@ int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) EC_KEY *EVP_PKEY_get0_EC_KEY(const EVP_PKEY *pkey) { + if (!evp_pkey_downgrade((EVP_PKEY *)pkey)) { + ERR_raise(ERR_LIB_EVP, EVP_R_INACCESSIBLE_KEY); + return NULL; + } if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) { EVPerr(EVP_F_EVP_PKEY_GET0_EC_KEY, EVP_R_EXPECTING_A_EC_KEY); return NULL; @@ -713,6 +703,10 @@ int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key) DH *EVP_PKEY_get0_DH(const EVP_PKEY *pkey) { + if (!evp_pkey_downgrade((EVP_PKEY *)pkey)) { + ERR_raise(ERR_LIB_EVP, EVP_R_INACCESSIBLE_KEY); + return NULL; + } if (pkey->type != EVP_PKEY_DH && pkey->type != EVP_PKEY_DHX) { EVPerr(EVP_F_EVP_PKEY_GET0_DH, EVP_R_EXPECTING_A_DH_KEY); return NULL; @@ -755,6 +749,119 @@ int EVP_PKEY_base_id(const EVP_PKEY *pkey) return EVP_PKEY_type(pkey->type); } +int EVP_PKEY_is_a(const EVP_PKEY *pkey, const char *name) +{ +#ifndef FIPS_MODE + if (pkey->keymgmt == NULL) { + /* + * These hard coded cases are pure hackery to get around the fact + * that names in crypto/objects/objects.txt are a mess. There is + * no "EC", and "RSA" leads to the NID for 2.5.8.1.1, an OID that's + * fallen out in favor of { pkcs-1 1 }, i.e. 1.2.840.113549.1.1.1, + * the NID of which is used for EVP_PKEY_RSA. Strangely enough, + * "DSA" is accurate... but still, better be safe and hard-code + * names that we know. + * TODO Clean this away along with all other #legacy support. + */ + int type; + + if (strcasecmp(name, "RSA") == 0) + type = EVP_PKEY_RSA; +#ifndef OPENSSL_NO_EC + else if (strcasecmp(name, "EC") == 0) + type = EVP_PKEY_EC; +#endif +#ifndef OPENSSL_NO_DSA + else if (strcasecmp(name, "DSA") == 0) + type = EVP_PKEY_DSA; +#endif + else + type = EVP_PKEY_type(OBJ_sn2nid(name)); + return EVP_PKEY_type(pkey->type) == type; + } +#endif + return EVP_KEYMGMT_is_a(pkey->keymgmt, name); +} + +int EVP_PKEY_can_sign(const EVP_PKEY *pkey) +{ + if (pkey->keymgmt == NULL) { + switch (EVP_PKEY_base_id(pkey)) { + case EVP_PKEY_RSA: + return 1; +#ifndef OPENSSL_NO_DSA + case EVP_PKEY_DSA: + return 1; +#endif +#ifndef OPENSSL_NO_EC + case EVP_PKEY_ED25519: + case EVP_PKEY_ED448: + return 1; + case EVP_PKEY_EC: /* Including SM2 */ + return EC_KEY_can_sign(pkey->pkey.ec); +#endif + default: + break; + } + } else { + const OSSL_PROVIDER *prov = EVP_KEYMGMT_provider(pkey->keymgmt); + OPENSSL_CTX *libctx = ossl_provider_library_context(prov); + const char *supported_sig = + pkey->keymgmt->query_operation_name != NULL + ? pkey->keymgmt->query_operation_name(OSSL_OP_SIGNATURE) + : evp_first_name(prov, pkey->keymgmt->name_id); + EVP_SIGNATURE *signature = NULL; + + signature = EVP_SIGNATURE_fetch(libctx, supported_sig, NULL); + if (signature != NULL) { + EVP_SIGNATURE_free(signature); + return 1; + } + } + return 0; +} + +#ifndef OPENSSL_NO_EC +/* + * TODO rewrite when we have proper data extraction functions + * Note: an octet pointer would be desirable! + */ +static OSSL_CALLBACK get_ec_curve_name_cb; +static int get_ec_curve_name_cb(const OSSL_PARAM params[], void *arg) +{ + const OSSL_PARAM *p = NULL; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_NAME)) != NULL) + return OSSL_PARAM_get_utf8_string(p, arg, 0); + + /* If there is no curve name, this is not an EC key */ + return 0; +} + +int evp_pkey_get_EC_KEY_curve_nid(const EVP_PKEY *pkey) +{ + int ret = NID_undef; + + if (pkey->keymgmt == NULL) { + if (EVP_PKEY_base_id(pkey) == EVP_PKEY_EC) { + EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey); + + ret = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); + } + } else if (EVP_PKEY_is_a(pkey, "EC") || EVP_PKEY_is_a(pkey, "SM2")) { + char *curve_name = NULL; + + ret = evp_keymgmt_export(pkey->keymgmt, pkey->keydata, + OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, + get_ec_curve_name_cb, &curve_name); + if (ret) + ret = ec_curve_name2nid(curve_name); + OPENSSL_free(curve_name); + } + + return ret; +} +#endif static int print_reset_indent(BIO **out, int pop_f_prefix, long saved_indent) { @@ -993,10 +1100,192 @@ EVP_PKEY *EVP_PKEY_new(void) ret->lock = CRYPTO_THREAD_lock_new(); if (ret->lock == NULL) { EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE); - OPENSSL_free(ret); - return NULL; + goto err; } +#ifndef FIPS_MODE + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_EVP_PKEY, ret, &ret->ex_data)) { + EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE); + goto err; + } +#endif return ret; + + err: + CRYPTO_THREAD_lock_free(ret->lock); + OPENSSL_free(ret); + return NULL; +} + +/* + * Setup a public key management method. + * + * For legacy keys, either |type| or |str| is expected to have the type + * information. In this case, the setup consists of finding an ASN1 method + * and potentially an ENGINE, and setting those fields in |pkey|. + * + * For provider side keys, |keymgmt| is expected to be non-NULL. In this + * case, the setup consists of setting the |keymgmt| field in |pkey|. + * + * If pkey is NULL just return 1 or 0 if the key management method exists. + */ + +static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str, + int len, EVP_KEYMGMT *keymgmt) +{ +#ifndef FIPS_MODE + const EVP_PKEY_ASN1_METHOD *ameth = NULL; + ENGINE **eptr = (e == NULL) ? &e : NULL; +#endif + + /* + * The setups can't set both legacy and provider side methods. + * It is forbidden + */ + if (!ossl_assert(type == EVP_PKEY_NONE || keymgmt == NULL) + || !ossl_assert(e == NULL || keymgmt == NULL)) { + ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (pkey != NULL) { + int free_it = 0; + +#ifndef FIPS_MODE + free_it = free_it || pkey->pkey.ptr != NULL; +#endif + free_it = free_it || pkey->keydata != NULL; + if (free_it) + evp_pkey_free_it(pkey); +#ifndef FIPS_MODE + /* + * If key type matches and a method exists then this lookup has + * succeeded once so just indicate success. + */ + if (pkey->type != EVP_PKEY_NONE + && type == pkey->save_type + && pkey->ameth != NULL) + return 1; +# ifndef OPENSSL_NO_ENGINE + /* If we have ENGINEs release them */ + ENGINE_finish(pkey->engine); + pkey->engine = NULL; + ENGINE_finish(pkey->pmeth_engine); + pkey->pmeth_engine = NULL; +# endif +#endif + } +#ifndef FIPS_MODE + if (str != NULL) + ameth = EVP_PKEY_asn1_find_str(eptr, str, len); + else if (type != EVP_PKEY_NONE) + ameth = EVP_PKEY_asn1_find(eptr, type); +# ifndef OPENSSL_NO_ENGINE + if (pkey == NULL && eptr != NULL) + ENGINE_finish(e); +# endif +#endif + + + { + int check = 1; + +#ifndef FIPS_MODE + check = check && ameth == NULL; +#endif + check = check && keymgmt == NULL; + if (check) { + EVPerr(EVP_F_PKEY_SET_TYPE, EVP_R_UNSUPPORTED_ALGORITHM); + return 0; + } + } + if (pkey != NULL) { + if (keymgmt != NULL && !EVP_KEYMGMT_up_ref(keymgmt)) { + ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); + return 0; + } + + pkey->keymgmt = keymgmt; + + pkey->save_type = type; + pkey->type = type; + +#ifndef FIPS_MODE + /* + * If the internal "origin" key is provider side, don't save |ameth|. + * The main reason is that |ameth| is one factor to detect that the + * internal "origin" key is a legacy one. + */ + if (keymgmt == NULL) + pkey->ameth = ameth; + pkey->engine = e; + + /* + * The EVP_PKEY_ASN1_METHOD |pkey_id| serves different purposes, + * depending on if we're setting this key to contain a legacy or + * a provider side "origin" key. For a legacy key, we assign it + * to the |type| field, but for a provider side key, we assign it + * to the |save_type| field, because |type| is supposed to be set + * to EVP_PKEY_NONE in that case. + */ + if (keymgmt != NULL) + pkey->save_type = ameth->pkey_id; + else if (pkey->ameth != NULL) + pkey->type = ameth->pkey_id; +#endif + } + return 1; +} + +#ifndef FIPS_MODE +static void find_ameth(const char *name, void *data) +{ + const char **str = data; + + /* + * The error messages from pkey_set_type() are uninteresting here, + * and misleading. + */ + ERR_set_mark(); + + if (pkey_set_type(NULL, NULL, EVP_PKEY_NONE, name, strlen(name), + NULL)) { + if (str[0] == NULL) + str[0] = name; + else if (str[1] == NULL) + str[1] = name; + } + + ERR_pop_to_mark(); +} +#endif + +int EVP_PKEY_set_type_by_keymgmt(EVP_PKEY *pkey, EVP_KEYMGMT *keymgmt) +{ +#ifndef FIPS_MODE +# define EVP_PKEY_TYPE_STR str[0] +# define EVP_PKEY_TYPE_STRLEN (str[0] == NULL ? -1 : (int)strlen(str[0])) + /* + * Find at most two strings that have an associated EVP_PKEY_ASN1_METHOD + * Ideally, only one should be found. If two (or more) are found, the + * match is ambiguous. This should never happen, but... + */ + const char *str[2] = { NULL, NULL }; + + EVP_KEYMGMT_names_do_all(keymgmt, find_ameth, &str); + if (str[1] != NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); + return 0; + } +#else +# define EVP_PKEY_TYPE_STR NULL +# define EVP_PKEY_TYPE_STRLEN -1 +#endif + return pkey_set_type(pkey, NULL, EVP_PKEY_NONE, + EVP_PKEY_TYPE_STR, EVP_PKEY_TYPE_STRLEN, + keymgmt); + +#undef EVP_PKEY_TYPE_STR +#undef EVP_PKEY_TYPE_STRLEN } int EVP_PKEY_up_ref(EVP_PKEY *pkey) @@ -1012,13 +1301,12 @@ int EVP_PKEY_up_ref(EVP_PKEY *pkey) } #ifndef FIPS_MODE -static void evp_pkey_free_legacy(EVP_PKEY *x) +void evp_pkey_free_legacy(EVP_PKEY *x) { if (x->ameth != NULL) { if (x->ameth->pkey_free != NULL) x->ameth->pkey_free(x); x->pkey.ptr = NULL; - x->ameth = NULL; } # ifndef OPENSSL_NO_ENGINE ENGINE_finish(x->engine); @@ -1026,7 +1314,7 @@ static void evp_pkey_free_legacy(EVP_PKEY *x) ENGINE_finish(x->pmeth_engine); x->pmeth_engine = NULL; # endif - x->type = x->save_type = EVP_PKEY_NONE; + x->type = EVP_PKEY_NONE; } #endif /* FIPS_MODE */ @@ -1060,6 +1348,9 @@ void EVP_PKEY_free(EVP_PKEY *x) return; REF_ASSERT_ISNT(i < 0); evp_pkey_free_it(x); +#ifndef FIPS_MODE + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EVP_PKEY, x, &x->ex_data); +#endif CRYPTO_THREAD_lock_free(x->lock); #ifndef FIPS_MODE sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free); @@ -1069,13 +1360,16 @@ void EVP_PKEY_free(EVP_PKEY *x) int EVP_PKEY_size(const EVP_PKEY *pkey) { + int size = 0; + if (pkey != NULL) { - if (pkey->ameth == NULL) - return pkey->cache.size; - else if (pkey->ameth->pkey_size != NULL) - return pkey->ameth->pkey_size(pkey); + size = pkey->cache.size; +#ifndef FIPS_MODE + if (pkey->ameth != NULL && pkey->ameth->pkey_size != NULL) + size = pkey->ameth->pkey_size(pkey); +#endif } - return 0; + return size; } void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx, @@ -1085,10 +1379,20 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx, EVP_KEYMGMT *allocated_keymgmt = NULL; EVP_KEYMGMT *tmp_keymgmt = NULL; void *keydata = NULL; + int check; if (pk == NULL) return NULL; + /* No key data => nothing to export */ + check = 1; +#ifndef FIPS_MODE + check = check && pk->pkey.ptr == NULL; +#endif + check = check && pk->keydata == NULL; + if (check) + return NULL; + #ifndef FIPS_MODE if (pk->pkey.ptr != NULL) { /* @@ -1105,13 +1409,15 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx, *keymgmt = NULL; } - /* If no keymgmt was given or found, get a default keymgmt */ + /* + * If no keymgmt was given or found, get a default keymgmt. We do so by + * letting EVP_PKEY_CTX_new_from_pkey() do it for us, then we steal it. + */ if (tmp_keymgmt == NULL) { EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pk, propquery); - if (ctx != NULL && ctx->keytype != NULL) - tmp_keymgmt = allocated_keymgmt = - EVP_KEYMGMT_fetch(ctx->libctx, ctx->keytype, propquery); + tmp_keymgmt = ctx->keymgmt; + ctx->keymgmt = NULL; EVP_PKEY_CTX_free(ctx); } @@ -1159,7 +1465,7 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx, if ((keydata = evp_keymgmt_newdata(tmp_keymgmt)) == NULL) goto end; - if (!pk->ameth->export_to(pk, keydata, tmp_keymgmt)) { + if (!pk->ameth->export_to(pk, keydata, tmp_keymgmt, libctx, propquery)) { evp_keymgmt_freedata(tmp_keymgmt, keydata); keydata = NULL; goto end; @@ -1212,98 +1518,255 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx, } #ifndef FIPS_MODE -/* - * This differs from exporting in that it releases the legacy key and assigns - * the export keymgmt and keydata to the "origin" provider side key instead - * of the operation cache. - */ -void *evp_pkey_upgrade_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx, - EVP_KEYMGMT **keymgmt, - const char *propquery) +int evp_pkey_downgrade(EVP_PKEY *pk) { - EVP_KEYMGMT *allocated_keymgmt = NULL; - EVP_KEYMGMT *tmp_keymgmt = NULL; - void *keydata = NULL; + EVP_KEYMGMT *keymgmt = pk->keymgmt; + void *keydata = pk->keydata; + int type = pk->save_type; + const char *keytype = NULL; - if (pk == NULL) - return NULL; + /* If this isn't a provider side key, we're done */ + if (keymgmt == NULL) + return 1; + + /* Get the key type name for error reporting */ + if (type != EVP_PKEY_NONE) + keytype = OBJ_nid2sn(type); + else + keytype = + evp_first_name(EVP_KEYMGMT_provider(keymgmt), keymgmt->name_id); /* - * If this key is already "upgraded", this function shouldn't have been - * called. + * |save_type| was set when any of the EVP_PKEY_set_type functions + * was called. It was set to EVP_PKEY_NONE if the key type wasn't + * recognised to be any of the legacy key types, and the downgrade + * isn't possible. */ - if (!ossl_assert(pk->keymgmt == NULL)) - return NULL; - - if (keymgmt != NULL) { - tmp_keymgmt = *keymgmt; - *keymgmt = NULL; + if (type == EVP_PKEY_NONE) { + ERR_raise_data(ERR_LIB_EVP, EVP_R_UNKNOWN_KEY_TYPE, + "key type = %s, can't downgrade", keytype); + return 0; } - /* If the key isn't a legacy one, bail out, but with proper values */ - if (pk->pkey.ptr == NULL) { - tmp_keymgmt = pk->keymgmt; - keydata = pk->keydata; - } else { - /* If the legacy key doesn't have an export function, give up */ - if (pk->ameth->export_to == NULL) - return NULL; - - /* If no keymgmt was given, get a default keymgmt */ - if (tmp_keymgmt == NULL) { - EVP_PKEY_CTX *ctx = - EVP_PKEY_CTX_new_from_pkey(libctx, pk, propquery); - - if (ctx != NULL && ctx->keytype != NULL) - tmp_keymgmt = allocated_keymgmt = - EVP_KEYMGMT_fetch(ctx->libctx, ctx->keytype, propquery); - EVP_PKEY_CTX_free(ctx); - } - - /* If we still don't have a keymgmt, give up */ - if (tmp_keymgmt == NULL) - goto end; - - /* Make sure that the keymgmt key type matches the legacy NID */ - if (!ossl_assert(EVP_KEYMGMT_is_a(tmp_keymgmt, OBJ_nid2sn(pk->type)))) - goto end; - - if ((keydata = evp_keymgmt_newdata(tmp_keymgmt)) == NULL) - goto end; - - if (!pk->ameth->export_to(pk, keydata, tmp_keymgmt) - || !EVP_KEYMGMT_up_ref(tmp_keymgmt)) { - evp_keymgmt_freedata(tmp_keymgmt, keydata); - keydata = NULL; - goto end; - } - - /* - * Clear the operation cache, all the legacy data, as well as the - * dirty counters - */ - evp_pkey_free_legacy(pk); - pk->dirty_cnt_copy = 0; - - evp_keymgmt_util_clear_operation_cache(pk); - pk->keymgmt = tmp_keymgmt; - pk->keydata = keydata; - evp_keymgmt_util_cache_keyinfo(pk); - } - - end: /* - * If nothing was upgraded, |tmp_keymgmt| might point at a freed - * EVP_KEYMGMT, so we clear it to be safe. It shouldn't be useful for - * the caller either way in that case. + * To be able to downgrade, we steal the provider side "origin" keymgmt + * and keydata. We've already grabbed the pointers, so all we need to + * do is clear those pointers in |pk| and then call evp_pkey_free_it(). + * That way, we can restore |pk| if we need to. */ - if (keydata == NULL) - tmp_keymgmt = NULL; + pk->keymgmt = NULL; + pk->keydata = NULL; + evp_pkey_free_it(pk); + if (EVP_PKEY_set_type(pk, type)) { + /* If the key is typed but empty, we're done */ + if (keydata == NULL) { + /* We're dropping the EVP_KEYMGMT */ + EVP_KEYMGMT_free(keymgmt); + return 1; + } - if (keymgmt != NULL) - *keymgmt = tmp_keymgmt; + if (pk->ameth->import_from == NULL) { + ERR_raise_data(ERR_LIB_EVP, EVP_R_NO_IMPORT_FUNCTION, + "key type = %s", keytype); + } else if (evp_keymgmt_export(keymgmt, keydata, + OSSL_KEYMGMT_SELECT_ALL, + pk->ameth->import_from, pk)) { + /* + * Save the provider side data in the operation cache, so they'll + * find it again. evp_pkey_free_it() cleared the cache, so it's + * safe to assume slot zero is free. + * Note that evp_keymgmt_util_cache_keydata() increments keymgmt's + * reference count. + */ + evp_keymgmt_util_cache_keydata(pk, 0, keymgmt, keydata); - EVP_KEYMGMT_free(allocated_keymgmt); - return keydata; + /* Synchronize the dirty count */ + pk->dirty_cnt_copy = pk->ameth->dirty_cnt(pk); + + /* evp_keymgmt_export() increased the refcount... */ + EVP_KEYMGMT_free(keymgmt); + return 1; + } + + ERR_raise_data(ERR_LIB_EVP, EVP_R_KEYMGMT_EXPORT_FAILURE, + "key type = %s", keytype); + } + + /* + * Something went wrong. This could for example happen if the keymgmt + * turns out to be an HSM implementation that refuses to let go of some + * of the key data, typically the private bits. In this case, we restore + * the provider side internal "origin" and leave it at that. + */ + if (!ossl_assert(EVP_PKEY_set_type_by_keymgmt(pk, keymgmt))) { + /* This should not be impossible */ + ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); + return 0; + } + /* EVP_PKEY_set_type_by_keymgmt() increased the refcount... */ + EVP_KEYMGMT_free(keymgmt); + pk->keydata = keydata; + evp_keymgmt_util_cache_keyinfo(pk); + return 0; /* No downgrade, but at least the key is restored */ } #endif /* FIPS_MODE */ + +const OSSL_PARAM *EVP_PKEY_gettable_params(EVP_PKEY *pkey) +{ + if (pkey == NULL + || pkey->keymgmt == NULL + || pkey->keydata == NULL) + return 0; + return evp_keymgmt_gettable_params(pkey->keymgmt); +} + +/* + * For the following methods param->return_size is set to a value + * larger than can be returned by the call to evp_keymgmt_get_params(). + * If it is still this value then the parameter was ignored - and in this + * case it returns an error.. + */ + +int EVP_PKEY_get_bn_param(EVP_PKEY *pkey, const char *key_name, BIGNUM **bn) +{ + int ret = 0; + OSSL_PARAM params[2]; + unsigned char buffer[2048]; + /* + * Use -1 as the terminator here instead of sizeof(buffer) + 1 since + * -1 is less likely to be a valid value. + */ + const size_t not_set = (size_t)-1; + unsigned char *buf = NULL; + size_t buf_sz = 0; + + if (pkey == NULL + || pkey->keymgmt == NULL + || pkey->keydata == NULL + || key_name == NULL + || bn == NULL) + return 0; + + memset(buffer, 0, sizeof(buffer)); + params[0] = OSSL_PARAM_construct_BN(key_name, buffer, sizeof(buffer)); + /* If the return_size is still not_set then we know it was not found */ + params[0].return_size = not_set; + params[1] = OSSL_PARAM_construct_end(); + if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params)) { + if (params[0].return_size == not_set + || params[0].return_size == 0) + return 0; + buf_sz = params[0].return_size; + /* + * If it failed because the buffer was too small then allocate the + * required buffer size and retry. + */ + buf = OPENSSL_zalloc(buf_sz); + if (buf == NULL) + return 0; + params[0].data = buf; + params[0].data_size = buf_sz; + + if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params)) + goto err; + } + /* Fail if the param was not found */ + if (params[0].return_size == not_set) + goto err; + ret = OSSL_PARAM_get_BN(params, bn); +err: + OPENSSL_free(buf); + return ret; +} + +int EVP_PKEY_get_octet_string_param(EVP_PKEY *pkey, const char *key_name, + unsigned char *buf, size_t max_buf_sz, + size_t *out_sz) +{ + OSSL_PARAM params[2]; + const size_t not_set = max_buf_sz + 1; + + if (pkey == NULL + || pkey->keymgmt == NULL + || pkey->keydata == NULL + || key_name == NULL) + return 0; + + params[0] = OSSL_PARAM_construct_octet_string(key_name, buf, max_buf_sz); + params[0].return_size = not_set; + params[1] = OSSL_PARAM_construct_end(); + if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params)) + return 0; + if (params[0].return_size == not_set) + return 0; + if (out_sz != NULL) + *out_sz = params[0].return_size; + return 1; +} + +int EVP_PKEY_get_utf8_string_param(EVP_PKEY *pkey, const char *key_name, + char *str, size_t max_buf_sz, + size_t *out_sz) +{ + OSSL_PARAM params[2]; + const size_t not_set = max_buf_sz + 1; + + if (pkey == NULL + || pkey->keymgmt == NULL + || pkey->keydata == NULL + || key_name == NULL) + return 0; + + params[0] = OSSL_PARAM_construct_utf8_string(key_name, str, max_buf_sz); + params[0].return_size = not_set; + params[1] = OSSL_PARAM_construct_end(); + if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params)) + return 0; + if (params[0].return_size == not_set) + return 0; + if (out_sz != NULL) + *out_sz = params[0].return_size; + return 1; +} + +int EVP_PKEY_get_int_param(EVP_PKEY *pkey, const char *key_name, int *out) +{ + OSSL_PARAM params[2]; + const size_t not_set = sizeof(int) + 1; + + if (pkey == NULL + || pkey->keymgmt == NULL + || pkey->keydata == NULL + || key_name == NULL) + return 0; + + params[0] = OSSL_PARAM_construct_int(key_name, out); + params[0].return_size = not_set; + params[1] = OSSL_PARAM_construct_end(); + if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params)) + return 0; + if (params[0].return_size == not_set) + return 0; + return 1; +} + +int EVP_PKEY_get_size_t_param(EVP_PKEY *pkey, const char *key_name, size_t *out) +{ + OSSL_PARAM params[2]; + const size_t not_set = sizeof(size_t) + 1; + + if (pkey == NULL + || pkey->keymgmt == NULL + || pkey->keydata == NULL + || key_name == NULL) + return 0; + + params[0] = OSSL_PARAM_construct_size_t(key_name, out); + params[0].return_size = not_set; + params[1] = OSSL_PARAM_construct_end(); + if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params)) + return 0; + if (params[0].return_size == not_set) + return 0; + return 1; +} diff --git a/crypto/evp/pkey_mac.c b/crypto/evp/pkey_mac.c index ed3a075f..7452e032 100644 --- a/crypto/evp/pkey_mac.c +++ b/crypto/evp/pkey_mac.c @@ -51,17 +51,31 @@ static int pkey_mac_init(EVP_PKEY_CTX *ctx) MAC_PKEY_CTX *hctx; /* We're being smart and using the same base NIDs for PKEY and for MAC */ int nid = ctx->pmeth->pkey_id; - EVP_MAC *mac = EVP_MAC_fetch(NULL, OBJ_nid2sn(nid), NULL); + EVP_MAC *mac; + + ERR_set_mark(); + mac = EVP_MAC_fetch(ctx->libctx, OBJ_nid2sn(nid), ctx->propquery); + ERR_pop_to_mark(); + + /* + * mac == NULL may actually be ok in some situations. In an + * EVP_PKEY_new_mac_key() call a temporary EVP_PKEY_CTX is created with + * default libctx. We don't actually need the underlying MAC to be present + * to successfully set the key in that case. The resulting EVP_PKEY could + * then be used in some other libctx where the MAC *is* present + */ if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL) { EVPerr(EVP_F_PKEY_MAC_INIT, ERR_R_MALLOC_FAILURE); return 0; } - hctx->ctx = EVP_MAC_CTX_new(mac); - if (hctx->ctx == NULL) { - OPENSSL_free(hctx); - return 0; + if (mac != NULL) { + hctx->ctx = EVP_MAC_CTX_new(mac); + if (hctx->ctx == NULL) { + OPENSSL_free(hctx); + return 0; + } } if (nid == EVP_PKEY_CMAC) { @@ -83,6 +97,13 @@ static int pkey_mac_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src) MAC_PKEY_CTX *sctx, *dctx; sctx = EVP_PKEY_CTX_get_data(src); + + if (sctx->ctx == NULL) { + /* This actually means the fetch failed during the init call */ + EVPerr(0, EVP_R_FETCH_FAILED); + return 0; + } + if (sctx->ctx->data == NULL) return 0; @@ -142,7 +163,7 @@ static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx) MAC_PKEY_CTX *hctx = ctx == NULL ? NULL : EVP_PKEY_CTX_get_data(ctx); if (hctx != NULL) { - EVP_MAC *mac = EVP_MAC_CTX_mac(hctx->ctx); + EVP_MAC *mac = hctx->ctx != NULL ? EVP_MAC_CTX_mac(hctx->ctx) : NULL; switch (hctx->type) { case MAC_TYPE_RAW: @@ -177,8 +198,15 @@ static int pkey_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) break; case MAC_TYPE_MAC: { - EVP_MAC_CTX *cmkey = EVP_MAC_CTX_dup(hctx->ctx); + EVP_MAC_CTX *cmkey; + if (hctx->ctx == NULL) { + /* This actually means the fetch failed during the init call */ + EVPerr(0, EVP_R_FETCH_FAILED); + return 0; + } + + cmkey = EVP_MAC_CTX_dup(hctx->ctx); if (cmkey == NULL) return 0; if (!EVP_MAC_up_ref(EVP_MAC_CTX_mac(hctx->ctx))) @@ -220,6 +248,12 @@ static int pkey_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) hctx->type == MAC_TYPE_RAW && (ctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) != 0; + if (hctx->ctx == NULL) { + /* This actually means the fetch failed during the init call */ + EVPerr(0, EVP_R_FETCH_FAILED); + return 0; + } + if (set_key) { if (!EVP_MAC_is_a(EVP_MAC_CTX_mac(hctx->ctx), OBJ_nid2sn(EVP_PKEY_id(EVP_PKEY_CTX_get0_pkey(ctx))))) @@ -285,6 +319,14 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) ciphname, 0); params[params_n] = OSSL_PARAM_construct_end(); + if (hctx->ctx == NULL) { + /* + * This actually means the fetch failed during the init call + */ + EVPerr(0, EVP_R_FETCH_FAILED); + return 0; + } + if (!EVP_MAC_CTX_set_params(hctx->ctx, params) || !EVP_MAC_init(hctx->ctx)) return 0; @@ -306,8 +348,7 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) if (ctx->pkey == NULL) return 0; - new_mac_ctx = EVP_MAC_CTX_dup((EVP_MAC_CTX *)ctx->pkey - ->pkey.ptr); + new_mac_ctx = EVP_MAC_CTX_dup(ctx->pkey->pkey.ptr); if (new_mac_ctx == NULL) return 0; EVP_MAC_CTX_free(hctx->ctx); @@ -337,6 +378,14 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) params[0] = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE, &size); + if (hctx->ctx == NULL) { + /* + * This actually means the fetch failed during the init call + */ + EVPerr(0, EVP_R_FETCH_FAILED); + return 0; + } + if (!EVP_MAC_CTX_set_params(hctx->ctx, params)) return 0; @@ -373,6 +422,14 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) p2, p1); params[params_n] = OSSL_PARAM_construct_end(); + if (hctx->ctx == NULL) { + /* + * This actually means the fetch failed during the init call + */ + EVPerr(0, EVP_R_FETCH_FAILED); + return 0; + } + return EVP_MAC_CTX_set_params(hctx->ctx, params); } break; @@ -385,6 +442,12 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) case EVP_PKEY_CTRL_DIGESTINIT: switch (hctx->type) { case MAC_TYPE_RAW: + if (hctx->ctx == NULL) { + /* This actually means the fetch failed during the init call */ + EVPerr(0, EVP_R_FETCH_FAILED); + return 0; + } + /* Ensure that we have attached the implementation */ if (!EVP_MAC_init(hctx->ctx)) return 0; @@ -456,6 +519,13 @@ static int pkey_mac_ctrl_str(EVP_PKEY_CTX *ctx, type, value, strlen(value) + 1, NULL)) return 0; params[1] = OSSL_PARAM_construct_end(); + + if (hctx->ctx == NULL) { + /* This actually means the fetch failed during the init call */ + EVPerr(0, EVP_R_FETCH_FAILED); + return 0; + } + ok = EVP_MAC_CTX_set_params(hctx->ctx, params); OPENSSL_free(params[0].data); return ok; diff --git a/crypto/evp/pmeth_check.c b/crypto/evp/pmeth_check.c index c02353d5..587e8ae1 100644 --- a/crypto/evp/pmeth_check.c +++ b/crypto/evp/pmeth_check.c @@ -35,19 +35,24 @@ int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx) return evp_keymgmt_validate(keymgmt, key, OSSL_KEYMGMT_SELECT_PUBLIC_KEY); + if (pkey->type == EVP_PKEY_NONE) + goto not_supported; + +#ifndef FIPS_MODE /* legacy */ /* call customized public key check function first */ if (ctx->pmeth->public_check != NULL) return ctx->pmeth->public_check(pkey); /* use default public key check function in ameth */ - if (pkey->ameth == NULL || pkey->ameth->pkey_public_check == NULL) { - EVPerr(EVP_F_EVP_PKEY_PUBLIC_CHECK, - EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; - } + if (pkey->ameth == NULL || pkey->ameth->pkey_public_check == NULL) + goto not_supported; return pkey->ameth->pkey_public_check(pkey); +#endif + not_supported: + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; } int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx) @@ -68,19 +73,24 @@ int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx) return evp_keymgmt_validate(keymgmt, key, OSSL_KEYMGMT_SELECT_ALL_PARAMETERS); + if (pkey->type == EVP_PKEY_NONE) + goto not_supported; + +#ifndef FIPS_MODE + /* legacy */ /* call customized param check function first */ if (ctx->pmeth->param_check != NULL) return ctx->pmeth->param_check(pkey); - /* legacy */ /* use default param check function in ameth */ - if (pkey->ameth == NULL || pkey->ameth->pkey_param_check == NULL) { - EVPerr(EVP_F_EVP_PKEY_PARAM_CHECK, - EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; - } + if (pkey->ameth == NULL || pkey->ameth->pkey_param_check == NULL) + goto not_supported; return pkey->ameth->pkey_param_check(pkey); +#endif + not_supported: + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; } int EVP_PKEY_private_check(EVP_PKEY_CTX *ctx) @@ -101,6 +111,7 @@ int EVP_PKEY_private_check(EVP_PKEY_CTX *ctx) return evp_keymgmt_validate(keymgmt, key, OSSL_KEYMGMT_SELECT_PRIVATE_KEY); /* not supported for legacy keys */ + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); return -2; } @@ -121,6 +132,7 @@ int EVP_PKEY_pairwise_check(EVP_PKEY_CTX *ctx) if (key != NULL && keymgmt != NULL) return evp_keymgmt_validate(keymgmt, key, OSSL_KEYMGMT_SELECT_KEYPAIR); /* not supported for legacy keys */ + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); return -2; } @@ -141,18 +153,23 @@ int EVP_PKEY_check(EVP_PKEY_CTX *ctx) if (key != NULL && keymgmt != NULL) return evp_keymgmt_validate(keymgmt, key, OSSL_KEYMGMT_SELECT_ALL); + if (pkey->type == EVP_PKEY_NONE) + goto not_supported; + +#ifndef FIPS_MODE /* legacy */ /* call customized check function first */ if (ctx->pmeth->check != NULL) return ctx->pmeth->check(pkey); /* use default check function in ameth */ - if (pkey->ameth == NULL || pkey->ameth->pkey_check == NULL) { - EVPerr(EVP_F_EVP_PKEY_CHECK, - EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; - } + if (pkey->ameth == NULL || pkey->ameth->pkey_check == NULL) + goto not_supported; return pkey->ameth->pkey_check(pkey); +#endif + not_supported: + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; } diff --git a/crypto/evp/pmeth_fn.c b/crypto/evp/pmeth_fn.c index ca0790fc..5d0e21ed 100644 --- a/crypto/evp/pmeth_fn.c +++ b/crypto/evp/pmeth_fn.c @@ -38,7 +38,7 @@ static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation) */ ERR_set_mark(); - if (ctx->keytype == NULL || ctx->engine != NULL) + if (ctx->engine != NULL || ctx->keytype == NULL) goto legacy; /* diff --git a/crypto/evp/pmeth_gn.c b/crypto/evp/pmeth_gn.c index 84149fab..78ed9ec7 100644 --- a/crypto/evp/pmeth_gn.c +++ b/crypto/evp/pmeth_gn.c @@ -9,7 +9,10 @@ #include #include +#include +#include #include "internal/cryptlib.h" +#include "internal/core.h" #include #include #include "crypto/bn.h" @@ -17,102 +20,262 @@ #include "crypto/evp.h" #include "evp_local.h" -#ifndef FIPS_MODE -int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx) +#if !defined(FIPS_MODE) && !defined(OPENSSL_NO_EC) +# define TMP_SM2_HACK +#endif + +/* TODO(3.0) remove when provider SM2 key generation is implemented */ +#ifdef TMP_SM2_HACK +# include +# include +# include "internal/sizes.h" +#endif + +static int gen_init(EVP_PKEY_CTX *ctx, int operation) { - int ret; - if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen) { - EVPerr(EVP_F_EVP_PKEY_PARAMGEN_INIT, - EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; + int ret = 0; + + if (ctx == NULL) + goto not_supported; + + evp_pkey_ctx_free_old_ops(ctx); + ctx->operation = operation; + + if (ctx->keymgmt == NULL || ctx->keymgmt->gen_init == NULL) + goto legacy; + +/* TODO remove when provider SM2 key generation is implemented */ +#ifdef TMP_SM2_HACK + if (ctx->pmeth != NULL && ctx->pmeth->pkey_id == EVP_PKEY_SM2) + goto legacy; +#endif + + switch (operation) { + case EVP_PKEY_OP_PARAMGEN: + ctx->op.keymgmt.genctx = + evp_keymgmt_gen_init(ctx->keymgmt, + OSSL_KEYMGMT_SELECT_ALL_PARAMETERS); + break; + case EVP_PKEY_OP_KEYGEN: + ctx->op.keymgmt.genctx = + evp_keymgmt_gen_init(ctx->keymgmt, OSSL_KEYMGMT_SELECT_KEYPAIR); + break; } - ctx->operation = EVP_PKEY_OP_PARAMGEN; - if (!ctx->pmeth->paramgen_init) - return 1; - ret = ctx->pmeth->paramgen_init(ctx); + + if (ctx->op.keymgmt.genctx == NULL) + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + else + ret = 1; + goto end; + + legacy: +#ifdef FIPS_MODE + goto not_supported; +#else + if (ctx->pmeth == NULL + || (operation == EVP_PKEY_OP_PARAMGEN + && ctx->pmeth->paramgen == NULL) + || (operation == EVP_PKEY_OP_KEYGEN + && ctx->pmeth->keygen == NULL)) + goto not_supported; + + ret = 1; + switch (operation) { + case EVP_PKEY_OP_PARAMGEN: + if (ctx->pmeth->paramgen_init != NULL) + ret = ctx->pmeth->paramgen_init(ctx); + break; + case EVP_PKEY_OP_KEYGEN: + if (ctx->pmeth->keygen_init != NULL) + ret = ctx->pmeth->keygen_init(ctx); + break; + } +#endif + + end: if (ret <= 0) ctx->operation = EVP_PKEY_OP_UNDEFINED; return ret; + + not_supported: + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + ret = -2; + goto end; } -int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) +int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx) { - int ret; - if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen) { - EVPerr(EVP_F_EVP_PKEY_PARAMGEN, - EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; - } - - if (ctx->operation != EVP_PKEY_OP_PARAMGEN) { - EVPerr(EVP_F_EVP_PKEY_PARAMGEN, EVP_R_OPERATON_NOT_INITIALIZED); - return -1; - } - - if (ppkey == NULL) - return -1; - - if (*ppkey == NULL) - *ppkey = EVP_PKEY_new(); - - if (*ppkey == NULL) { - EVPerr(EVP_F_EVP_PKEY_PARAMGEN, ERR_R_MALLOC_FAILURE); - return -1; - } - - ret = ctx->pmeth->paramgen(ctx, *ppkey); - if (ret <= 0) { - EVP_PKEY_free(*ppkey); - *ppkey = NULL; - } - return ret; + return gen_init(ctx, EVP_PKEY_OP_PARAMGEN); } int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx) { - int ret; - if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) { - EVPerr(EVP_F_EVP_PKEY_KEYGEN_INIT, - EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; - } - ctx->operation = EVP_PKEY_OP_KEYGEN; - if (!ctx->pmeth->keygen_init) - return 1; - ret = ctx->pmeth->keygen_init(ctx); - if (ret <= 0) - ctx->operation = EVP_PKEY_OP_UNDEFINED; - return ret; + return gen_init(ctx, EVP_PKEY_OP_KEYGEN); } -int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) +static int ossl_callback_to_pkey_gencb(const OSSL_PARAM params[], void *arg) { - int ret; + EVP_PKEY_CTX *ctx = arg; + const OSSL_PARAM *param = NULL; + int p = -1, n = -1; - if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) { - EVPerr(EVP_F_EVP_PKEY_KEYGEN, - EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; - } - if (ctx->operation != EVP_PKEY_OP_KEYGEN) { - EVPerr(EVP_F_EVP_PKEY_KEYGEN, EVP_R_OPERATON_NOT_INITIALIZED); - return -1; - } + if (ctx->pkey_gencb == NULL) + return 1; /* No callback? That's fine */ + + if ((param = OSSL_PARAM_locate_const(params, OSSL_GEN_PARAM_POTENTIAL)) + == NULL + || !OSSL_PARAM_get_int(param, &p)) + return 0; + if ((param = OSSL_PARAM_locate_const(params, OSSL_GEN_PARAM_ITERATION)) + == NULL + || !OSSL_PARAM_get_int(param, &n)) + return 0; + + ctx->keygen_info[0] = p; + ctx->keygen_info[1] = n; + + return ctx->pkey_gencb(ctx); +} + +int EVP_PKEY_gen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) +{ + int ret = 0; + OSSL_CALLBACK cb; + EVP_PKEY *allocated_pkey = NULL; if (ppkey == NULL) return -1; - if (*ppkey == NULL) - *ppkey = EVP_PKEY_new(); - if (*ppkey == NULL) - return -1; + if (ctx == NULL) + goto not_supported; - ret = ctx->pmeth->keygen(ctx, *ppkey); + if ((ctx->operation & EVP_PKEY_OP_TYPE_GEN) == 0) + goto not_initialized; + + if (*ppkey == NULL) + *ppkey = allocated_pkey = EVP_PKEY_new(); + + if (*ppkey == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + return -1; + } + + if (ctx->op.keymgmt.genctx == NULL) + goto legacy; + + ret = 1; + if (ctx->pkey != NULL) { + EVP_KEYMGMT *tmp_keymgmt = ctx->keymgmt; + void *keydata = + evp_pkey_export_to_provider(ctx->pkey, ctx->libctx, + &tmp_keymgmt, ctx->propquery); + + if (keydata == NULL) + goto not_supported; + ret = evp_keymgmt_gen_set_template(ctx->keymgmt, + ctx->op.keymgmt.genctx, keydata); + } + + /* + * the returned value from evp_keymgmt_util_gen() is cached in *ppkey, + * so we so not need to save it, just check it. + */ + ret = ret + && (evp_keymgmt_util_gen(*ppkey, ctx->keymgmt, ctx->op.keymgmt.genctx, + ossl_callback_to_pkey_gencb, ctx) + != NULL); + +#ifndef FIPS_MODE + /* In case |*ppkey| was originally a legacy key */ + if (ret) + evp_pkey_free_legacy(*ppkey); +#endif + +/* TODO remove when SM2 key have been cleanly separated from EC keys */ +#ifdef TMP_SM2_HACK + /* + * Legacy SM2 keys are implemented as EC_KEY with a twist. The legacy + * key generation detects the SM2 curve and "magically" changes the pkey + * id accordingly. + * Since we don't have SM2 in the provider implementation, we need to + * downgrade the generated provider side key to a legacy one under the + * same conditions. + * + * THIS IS AN UGLY BUT TEMPORARY HACK + */ + { + char curve_name[OSSL_MAX_NAME_SIZE] = ""; + + if (EVP_PKEY_CTX_get_ec_paramgen_curve_name(ctx, curve_name, + sizeof(curve_name)) < 1 + || strcmp(curve_name, "SM2") != 0) + goto end; + } + + if (!evp_pkey_downgrade(*ppkey) + || !EVP_PKEY_set_alias_type(*ppkey, EVP_PKEY_SM2)) + ret = 0; +#endif + goto end; + + legacy: +#ifdef FIPS_MODE + goto not_supported; +#else + if (ctx->pkey && !evp_pkey_downgrade(ctx->pkey)) + goto not_accessible; + switch (ctx->operation) { + case EVP_PKEY_OP_PARAMGEN: + ret = ctx->pmeth->paramgen(ctx, *ppkey); + break; + case EVP_PKEY_OP_KEYGEN: + ret = ctx->pmeth->keygen(ctx, *ppkey); + break; + default: + goto not_supported; + } +#endif + + end: if (ret <= 0) { - EVP_PKEY_free(*ppkey); - *ppkey = NULL; + if (allocated_pkey != NULL) + *ppkey = NULL; + EVP_PKEY_free(allocated_pkey); } return ret; + + not_supported: + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + ret = -2; + goto end; + not_initialized: + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATON_NOT_INITIALIZED); + ret = -1; + goto end; +#ifndef FIPS_MODE + not_accessible: + ERR_raise(ERR_LIB_EVP, EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS); + ret = -1; + goto end; +#endif +} + +int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) +{ + if (ctx->operation != EVP_PKEY_OP_PARAMGEN) { + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATON_NOT_INITIALIZED); + return -1; + } + return EVP_PKEY_gen(ctx, ppkey); +} + +int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) +{ + if (ctx->operation != EVP_PKEY_OP_KEYGEN) { + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATON_NOT_INITIALIZED); + return -1; + } + return EVP_PKEY_gen(ctx, ppkey); } void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb) @@ -152,6 +315,8 @@ int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx) return ctx->keygen_info[idx]; } +#ifndef FIPS_MODE + EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e, const unsigned char *key, int keylen) { @@ -181,13 +346,10 @@ static int fromdata_init(EVP_PKEY_CTX *ctx, int operation) goto not_supported; evp_pkey_ctx_free_old_ops(ctx); - ctx->operation = operation; - if (ctx->keymgmt == NULL) - ctx->keymgmt = EVP_KEYMGMT_fetch(ctx->libctx, ctx->keytype, - ctx->propquery); if (ctx->keymgmt == NULL) goto not_supported; + ctx->operation = operation; return 1; not_supported: diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 906b0815..6a86b26d 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -1,4 +1,3 @@ - /* * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. * @@ -138,12 +137,13 @@ EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags) static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx, EVP_PKEY *pkey, ENGINE *e, - const char *name, const char *propquery, + const char *keytype, const char *propquery, int id) { EVP_PKEY_CTX *ret; const EVP_PKEY_METHOD *pmeth = NULL; + EVP_KEYMGMT *keymgmt = NULL; /* * When using providers, the context is bound to the algo implementation @@ -156,15 +156,11 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx, * If the key doesn't contain anything legacy, then it must be provided, * so we extract the necessary information and use that. */ - if (pkey != NULL && pkey->ameth == NULL) { + if (pkey != NULL && pkey->type == EVP_PKEY_NONE) { /* If we have an engine, something went wrong somewhere... */ if (!ossl_assert(e == NULL)) return NULL; - name = evp_first_name(pkey->keymgmt->prov, pkey->keymgmt->name_id); - /* - * TODO: I wonder if the EVP_PKEY should have the name and propquery - * that were used when building it.... /RL - */ + keytype = evp_first_name(pkey->keymgmt->prov, pkey->keymgmt->name_id); goto common; } #ifndef FIPS_MODE @@ -187,10 +183,10 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx, * since that can only happen internally, it's safe to make an * assertion. */ - if (!ossl_assert(e == NULL || name == NULL)) + if (!ossl_assert(e == NULL || keytype == NULL)) return NULL; if (e == NULL) - name = OBJ_nid2sn(id); + keytype = OBJ_nid2sn(id); # ifndef OPENSSL_NO_ENGINE if (e == NULL && pkey != NULL) @@ -225,6 +221,17 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx, /* END legacy */ #endif /* FIPS_MODE */ common: + /* + * If there's no engine and there's a name, we try fetching a provider + * implementation. + */ + if (e == NULL && keytype != NULL) { + /* This could fail so ignore errors */ + ERR_set_mark(); + keymgmt = EVP_KEYMGMT_fetch(libctx, keytype, propquery); + ERR_pop_to_mark(); + } + ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { #if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) @@ -234,8 +241,9 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx, return NULL; } ret->libctx = libctx; - ret->keytype = name; ret->propquery = propquery; + ret->keytype = keytype; + ret->keymgmt = keymgmt; ret->engine = e; ret->pmeth = pmeth; ret->operation = EVP_PKEY_OP_UNDEFINED; @@ -292,6 +300,9 @@ void evp_pkey_ctx_free_old_ops(EVP_PKEY_CTX *ctx) EVP_ASYM_CIPHER_free(ctx->op.ciph.cipher); ctx->op.ciph.ciphprovctx = NULL; ctx->op.ciph.cipher = NULL; + } else if (EVP_PKEY_CTX_IS_GEN_OP(ctx)) { + if (ctx->op.keymgmt.genctx != NULL && ctx->keymgmt != NULL) + evp_keymgmt_gen_cleanup(ctx->keymgmt, ctx->op.keymgmt.genctx); } #endif } @@ -569,6 +580,12 @@ int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params) && ctx->op.ciph.cipher->set_ctx_params != NULL) return ctx->op.ciph.cipher->set_ctx_params(ctx->op.ciph.ciphprovctx, params); + if (EVP_PKEY_CTX_IS_GEN_OP(ctx) + && ctx->op.keymgmt.genctx != NULL + && ctx->keymgmt != NULL + && ctx->keymgmt->gen_set_params != NULL) + return evp_keymgmt_gen_set_params(ctx->keymgmt, ctx->op.keymgmt.genctx, + params); return 0; } @@ -593,6 +610,12 @@ int EVP_PKEY_CTX_get_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params) && ctx->op.ciph.cipher->get_ctx_params != NULL) return ctx->op.ciph.cipher->get_ctx_params(ctx->op.ciph.ciphprovctx, params); + if (EVP_PKEY_CTX_IS_GEN_OP(ctx) + && ctx->op.keymgmt.genctx != NULL + && ctx->keymgmt != NULL + && ctx->keymgmt->gen_get_params != NULL) + return evp_keymgmt_gen_get_params(ctx->keymgmt, ctx->op.keymgmt.genctx, + params); return 0; } @@ -629,6 +652,10 @@ const OSSL_PARAM *EVP_PKEY_CTX_settable_params(EVP_PKEY_CTX *ctx) && ctx->op.ciph.cipher != NULL && ctx->op.ciph.cipher->settable_ctx_params != NULL) return ctx->op.ciph.cipher->settable_ctx_params(); + if (EVP_PKEY_CTX_IS_GEN_OP(ctx) + && ctx->keymgmt != NULL + && ctx->keymgmt->gen_settable_params != NULL) + return evp_keymgmt_gen_settable_params(ctx->keymgmt); return NULL; } @@ -792,6 +819,8 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype, # ifndef OPENSSL_NO_EC if (keytype == EVP_PKEY_EC) { switch (cmd) { + case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: + return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, p1); case EVP_PKEY_CTRL_EC_ECDH_COFACTOR: if (p1 == -2) { return EVP_PKEY_CTX_get_ecdh_cofactor_mode(ctx); @@ -822,6 +851,30 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype, } } # endif + if (keytype == EVP_PKEY_RSA) { + switch (cmd) { + case EVP_PKEY_CTRL_RSA_OAEP_MD: + return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2); + case EVP_PKEY_CTRL_GET_RSA_OAEP_MD: + return EVP_PKEY_CTX_get_rsa_oaep_md(ctx, p2); + case EVP_PKEY_CTRL_RSA_MGF1_MD: + return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2); + case EVP_PKEY_CTRL_RSA_OAEP_LABEL: + return EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, p2, p1); + case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL: + return EVP_PKEY_CTX_get0_rsa_oaep_label(ctx, (unsigned char **)p2); + case EVP_PKEY_CTRL_RSA_KEYGEN_BITS: + return EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, p1); + case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP: + return EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, p2); + case EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES: + return EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, p1); + } + } + /* + * keytype == -1 is used when several key types share the same structure, + * or for generic controls that are the same across multiple key types. + */ if (keytype == -1) { switch (cmd) { case EVP_PKEY_CTRL_MD: @@ -832,18 +885,8 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype, return EVP_PKEY_CTX_set_rsa_padding(ctx, p1); case EVP_PKEY_CTRL_GET_RSA_PADDING: return EVP_PKEY_CTX_get_rsa_padding(ctx, p2); - case EVP_PKEY_CTRL_RSA_OAEP_MD: - return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2); - case EVP_PKEY_CTRL_GET_RSA_OAEP_MD: - return EVP_PKEY_CTX_get_rsa_oaep_md(ctx, p2); - case EVP_PKEY_CTRL_RSA_MGF1_MD: - return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2); case EVP_PKEY_CTRL_GET_RSA_MGF1_MD: return EVP_PKEY_CTX_get_rsa_oaep_md(ctx, p2); - case EVP_PKEY_CTRL_RSA_OAEP_LABEL: - return EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, p2, p1); - case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL: - return EVP_PKEY_CTX_get0_rsa_oaep_label(ctx, (unsigned char **)p2); case EVP_PKEY_CTRL_RSA_PSS_SALTLEN: return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, p1); case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN: @@ -854,7 +897,8 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype, case EVP_PKEY_CTRL_CMS_DECRYPT: case EVP_PKEY_CTRL_CMS_ENCRYPT: # endif - if (ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS) + /* TODO (3.0) Temporary hack, this should probe */ + if (!EVP_PKEY_is_a(EVP_PKEY_CTX_get0_pkey(ctx), "RSASSA-PSS")) return 1; ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); @@ -878,7 +922,9 @@ int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, || (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) && ctx->op.sig.sigprovctx != NULL) || (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) - && ctx->op.ciph.ciphprovctx != NULL)) + && ctx->op.ciph.ciphprovctx != NULL) + || (EVP_PKEY_CTX_IS_GEN_OP(ctx) + && ctx->op.keymgmt.genctx != NULL)) return legacy_ctrl_to_param(ctx, keytype, optype, cmd, p1, p2); if (ctx->pmeth == NULL || ctx->pmeth->ctrl == NULL) { @@ -920,6 +966,24 @@ int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype, static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name, const char *value) { + + /* Special cases that we intercept */ +# ifndef OPENSSL_NO_EC + /* + * We don't support encoding settings for providers, i.e. the only + * possible encoding is "named_curve", so we simply fail when something + * else is given, and otherwise just pretend all is fine. + */ + if (strcmp(name, "ec_param_enc") == 0) { + if (strcmp(value, "named_curve") == 0) { + return 1; + } else { + ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); + return -2; + } + } +# endif + if (strcmp(name, "rsa_padding_mode") == 0) name = OSSL_ASYM_CIPHER_PARAM_PAD_MODE; else if (strcmp(name, "rsa_mgf1_md") == 0) @@ -930,11 +994,19 @@ static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name, name = OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL; else if (strcmp(name, "rsa_pss_saltlen") == 0) name = OSSL_SIGNATURE_PARAM_PSS_SALTLEN; + else if (strcmp(name, "rsa_keygen_bits") == 0) + name = OSSL_PKEY_PARAM_RSA_BITS; + else if (strcmp(name, "rsa_keygen_pubexp") == 0) + name = OSSL_PKEY_PARAM_RSA_E; + else if (strcmp(name, "rsa_keygen_primes") == 0) + name = OSSL_PKEY_PARAM_RSA_PRIMES; # ifndef OPENSSL_NO_DH else if (strcmp(name, "dh_pad") == 0) name = OSSL_EXCHANGE_PARAM_PAD; # endif # ifndef OPENSSL_NO_EC + else if (strcmp(name, "ec_paramgen_curve") == 0) + name = OSSL_PKEY_PARAM_EC_NAME; else if (strcmp(name, "ecdh_cofactor_mode") == 0) name = OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE; else if (strcmp(name, "ecdh_kdf_md") == 0) @@ -979,7 +1051,9 @@ int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, || (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) && ctx->op.sig.sigprovctx != NULL) || (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) - && ctx->op.ciph.ciphprovctx != NULL)) + && ctx->op.ciph.ciphprovctx != NULL) + || (EVP_PKEY_CTX_IS_GEN_OP(ctx) + && ctx->op.keymgmt.genctx != NULL)) return legacy_ctrl_str_to_param(ctx, name, value); if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl_str) { diff --git a/crypto/evp/signature.c b/crypto/evp/signature.c index 3dfd4041..1f5e570f 100644 --- a/crypto/evp/signature.c +++ b/crypto/evp/signature.c @@ -105,7 +105,6 @@ static void *evp_signature_from_dispatch(int name_id, break; signature->digest_sign_init = OSSL_get_OP_signature_digest_sign_init(fns); - digsignfncnt++; break; case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE: if (signature->digest_sign_update != NULL) @@ -121,12 +120,17 @@ static void *evp_signature_from_dispatch(int name_id, = OSSL_get_OP_signature_digest_sign_final(fns); digsignfncnt++; break; + case OSSL_FUNC_SIGNATURE_DIGEST_SIGN: + if (signature->digest_sign != NULL) + break; + signature->digest_sign + = OSSL_get_OP_signature_digest_sign(fns); + break; case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT: if (signature->digest_verify_init != NULL) break; signature->digest_verify_init = OSSL_get_OP_signature_digest_verify_init(fns); - digverifyfncnt++; break; case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE: if (signature->digest_verify_update != NULL) @@ -142,6 +146,12 @@ static void *evp_signature_from_dispatch(int name_id, = OSSL_get_OP_signature_digest_verify_final(fns); digverifyfncnt++; break; + case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY: + if (signature->digest_verify != NULL) + break; + signature->digest_verify + = OSSL_get_OP_signature_digest_verify(fns); + break; case OSSL_FUNC_SIGNATURE_FREECTX: if (signature->freectx != NULL) break; @@ -216,12 +226,20 @@ static void *evp_signature_from_dispatch(int name_id, && verifyfncnt == 0 && verifyrecfncnt == 0 && digsignfncnt == 0 - && digverifyfncnt == 0) + && digverifyfncnt == 0 + && signature->digest_sign == NULL + && signature->digest_verify == NULL) || (signfncnt != 0 && signfncnt != 2) || (verifyfncnt != 0 && verifyfncnt != 2) || (verifyrecfncnt != 0 && verifyrecfncnt != 2) - || (digsignfncnt != 0 && digsignfncnt != 3) - || (digverifyfncnt != 0 && digverifyfncnt != 3) + || (digsignfncnt != 0 && digsignfncnt != 2) + || (digsignfncnt == 2 && signature->digest_sign_init == NULL) + || (digverifyfncnt != 0 && digverifyfncnt != 2) + || (digverifyfncnt == 2 && signature->digest_verify_init == NULL) + || (signature->digest_sign != NULL + && signature->digest_sign_init == NULL) + || (signature->digest_verify != NULL + && signature->digest_verify_init == NULL) || (gparamfncnt != 0 && gparamfncnt != 2) || (sparamfncnt != 0 && sparamfncnt != 2) || (gmdparamfncnt != 0 && gmdparamfncnt != 2) @@ -234,7 +252,9 @@ static void *evp_signature_from_dispatch(int name_id, * (verify_init verify) or * (verify_recover_init, verify_recover) or * (digest_sign_init, digest_sign_update, digest_sign_final) or - * (digest_verify_init, digest_verify_update, digest_verify_final). + * (digest_verify_init, digest_verify_update, digest_verify_final) or + * (digest_sign_init, digest_sign) or + * (digest_verify_init, digest_verify). * * set_ctx_params and settable_ctx_params are optional, but if one of * them is present then the other one must also be present. The same @@ -339,7 +359,7 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation) */ ERR_set_mark(); - if (ctx->keytype == NULL) + if (ctx->keymgmt == NULL) goto legacy; /* diff --git a/crypto/ex_data.c b/crypto/ex_data.c index 3cffef89..defa2b4b 100644 --- a/crypto/ex_data.c +++ b/crypto/ex_data.c @@ -24,19 +24,18 @@ int do_ex_data_init(OPENSSL_CTX *ctx) /* * Return the EX_CALLBACKS from the |ex_data| array that corresponds to * a given class. On success, *holds the lock.* + * The |global| parameter is assumed to be non null (checked by the caller). */ -static EX_CALLBACKS *get_and_lock(OPENSSL_CTX *ctx, int class_index) +static EX_CALLBACKS *get_and_lock(OSSL_EX_DATA_GLOBAL *global, int class_index) { EX_CALLBACKS *ip; - OSSL_EX_DATA_GLOBAL *global = NULL; if (class_index < 0 || class_index >= CRYPTO_EX_INDEX__COUNT) { CRYPTOerr(CRYPTO_F_GET_AND_LOCK, ERR_R_PASSED_INVALID_ARGUMENT); return NULL; } - global = openssl_ctx_get_ex_data_global(ctx); - if (global == NULL || global->ex_data_lock == NULL) { + if (global->ex_data_lock == NULL) { /* * If we get here, someone (who?) cleaned up the lock, so just * treat it as an error. @@ -111,9 +110,10 @@ int crypto_free_ex_index_ex(OPENSSL_CTX *ctx, int class_index, int idx) if (global == NULL) return 0; - ip = get_and_lock(ctx, class_index); + ip = get_and_lock(global, class_index); if (ip == NULL) return 0; + if (idx < 0 || idx >= sk_EX_CALLBACK_num(ip->meth)) goto err; a = sk_EX_CALLBACK_value(ip->meth, idx); @@ -149,7 +149,7 @@ int crypto_get_ex_new_index_ex(OPENSSL_CTX *ctx, int class_index, long argl, if (global == NULL) return -1; - ip = get_and_lock(ctx, class_index); + ip = get_and_lock(global, class_index); if (ip == NULL) return -1; @@ -216,13 +216,12 @@ int crypto_new_ex_data_ex(OPENSSL_CTX *ctx, int class_index, void *obj, if (global == NULL) return 0; - ip = get_and_lock(ctx, class_index); + ip = get_and_lock(global, class_index); if (ip == NULL) return 0; ad->ctx = ctx; ad->sk = NULL; - mx = sk_EX_CALLBACK_num(ip->meth); if (mx > 0) { if (mx < (int)OSSL_NELEM(stack)) @@ -269,16 +268,19 @@ int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to, EX_CALLBACK **storage = NULL; EX_CALLBACKS *ip; int toret = 0; - OSSL_EX_DATA_GLOBAL *global = openssl_ctx_get_ex_data_global(from->ctx); - - if (global == NULL) - return 0; + OSSL_EX_DATA_GLOBAL *global; to->ctx = from->ctx; if (from->sk == NULL) /* Nothing to copy over */ return 1; - if ((ip = get_and_lock(from->ctx, class_index)) == NULL) + + global = openssl_ctx_get_ex_data_global(from->ctx); + if (global == NULL) + return 0; + + ip = get_and_lock(global, class_index); + if (ip == NULL) return 0; mx = sk_EX_CALLBACK_num(ip->meth); @@ -340,14 +342,15 @@ void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) EX_CALLBACK *f; EX_CALLBACK *stack[10]; EX_CALLBACK **storage = NULL; - OSSL_EX_DATA_GLOBAL *global; + OSSL_EX_DATA_GLOBAL *global = openssl_ctx_get_ex_data_global(ad->ctx); - if ((ip = get_and_lock(ad->ctx, class_index)) == NULL) - goto err; - global = openssl_ctx_get_ex_data_global(ad->ctx); if (global == NULL) goto err; + ip = get_and_lock(global, class_index); + if (ip == NULL) + goto err; + mx = sk_EX_CALLBACK_num(ip->meth); if (mx > 0) { if (mx < (int)OSSL_NELEM(stack)) @@ -392,18 +395,18 @@ int CRYPTO_alloc_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad, EX_CALLBACK *f; EX_CALLBACKS *ip; void *curval; - OSSL_EX_DATA_GLOBAL *global = openssl_ctx_get_ex_data_global(ad->ctx); - - if (global == NULL) - return 0; + OSSL_EX_DATA_GLOBAL *global; curval = CRYPTO_get_ex_data(ad, idx); - /* Already there, no need to allocate */ if (curval != NULL) return 1; - ip = get_and_lock(ad->ctx, class_index); + global = openssl_ctx_get_ex_data_global(ad->ctx); + if (global == NULL) + return 0; + + ip = get_and_lock(global, class_index); if (ip == NULL) return 0; f = sk_EX_CALLBACK_value(ip->meth, idx); diff --git a/crypto/ffc/build.info b/crypto/ffc/build.info index c8bc7e90..a04430d1 100644 --- a/crypto/ffc/build.info +++ b/crypto/ffc/build.info @@ -1,7 +1,7 @@ LIBS=../../libcrypto $COMMON=ffc_params.c ffc_params_generate.c ffc_key_generate.c\ - ffc_params_validate.c ffc_key_validate.c + ffc_params_validate.c ffc_key_validate.c ffc_backend.c SOURCE[../../libcrypto]=$COMMON SOURCE[../../providers/libfips.a]=$COMMON diff --git a/crypto/ffc/ffc_backend.c b/crypto/ffc/ffc_backend.c new file mode 100644 index 00000000..cde9e43d --- /dev/null +++ b/crypto/ffc/ffc_backend.c @@ -0,0 +1,44 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/ffc.h" + +/* + * The intention with the "backend" source file is to offer backend support + * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider + * implementations alike. + */ + +int ffc_fromdata(FFC_PARAMS *ffc, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *param_p, *param_q, *param_g; + BIGNUM *p = NULL, *q = NULL, *g = NULL; + + if (ffc == NULL) + return 0; + + param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_P); + param_q = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_Q); + param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_G); + + if ((param_p != NULL && !OSSL_PARAM_get_BN(param_p, &p)) + || (param_q != NULL && !OSSL_PARAM_get_BN(param_q, &q)) + || (param_g != NULL && !OSSL_PARAM_get_BN(param_g, &g))) + goto err; + + ffc_params_set0_pqg(ffc, p, q, g); + return 1; + + err: + BN_free(p); + BN_free(q); + BN_free(g); + return 0; +} diff --git a/crypto/http/http_client.c b/crypto/http/http_client.c index 124fed0c..4c123f81 100644 --- a/crypto/http/http_client.c +++ b/crypto/http/http_client.c @@ -21,7 +21,7 @@ #include #include #include "internal/sockets.h" -#include "internal/cryptlib.h" +#include "internal/cryptlib.h" /* for ossl_assert() */ #include "http_local.h" @@ -157,7 +157,7 @@ int OSSL_HTTP_REQ_CTX_header(OSSL_HTTP_REQ_CTX *rctx, const char *server, * Section 5.1.2 of RFC 1945 states that the absoluteURI form is only * allowed when using a proxy */ - if (BIO_printf(rctx->mem, "http://%s", server) <= 0) + if (BIO_printf(rctx->mem, OSSL_HTTP_PREFIX"%s", server) <= 0) return 0; if (port != NULL && BIO_printf(rctx->mem, ":%s", port) <= 0) return 0; @@ -330,7 +330,7 @@ static int parse_http_line1(char *line) for (code = line; *code != '\0' && !ossl_isspace(*code); code++) continue; if (*code == '\0') { - HTTPerr(0, HTTP_R_SERVER_RESPONSE_PARSE_ERROR); + HTTPerr(0, HTTP_R_RESPONSE_PARSE_ERROR); return 0; } @@ -339,7 +339,7 @@ static int parse_http_line1(char *line) code++; if (*code == '\0') { - HTTPerr(0, HTTP_R_SERVER_RESPONSE_PARSE_ERROR); + HTTPerr(0, HTTP_R_RESPONSE_PARSE_ERROR); return 0; } @@ -348,7 +348,7 @@ static int parse_http_line1(char *line) continue; if (*reason == '\0') { - HTTPerr(0, HTTP_R_SERVER_RESPONSE_PARSE_ERROR); + HTTPerr(0, HTTP_R_RESPONSE_PARSE_ERROR); return 0; } @@ -385,7 +385,7 @@ static int parse_http_line1(char *line) if (retcode < 400) HTTPerr(0, HTTP_R_STATUS_CODE_UNSUPPORTED); else - HTTPerr(0, HTTP_R_SERVER_SENT_ERROR); + HTTPerr(0, HTTP_R_RECEIVED_ERROR); if (*reason == '\0') ERR_add_error_data(2, "Code=", code); else @@ -577,12 +577,14 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) *line_end = '\0'; } if (value != NULL && line_end != NULL) { - if (rctx->state == OHS_REDIRECT && strcmp(key, "Location") == 0) { + if (rctx->state == OHS_REDIRECT + && strcasecmp(key, "Location") == 0) { rctx->redirection_url = value; return 0; } - if (rctx->expected_ct != NULL && strcmp(key, "Content-Type") == 0) { - if (strcmp(rctx->expected_ct, value) != 0) { + if (rctx->expected_ct != NULL + && strcasecmp(key, "Content-Type") == 0) { + if (strcasecmp(rctx->expected_ct, value) != 0) { HTTPerr(0, HTTP_R_UNEXPECTED_CONTENT_TYPE); ERR_add_error_data(4, "expected=", rctx->expected_ct, ",actual=", value); @@ -590,7 +592,7 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) } rctx->expected_ct = NULL; /* content-type has been found */ } - if (strcmp(key, "Content-Length") == 0) { + if (strcasecmp(key, "Content-Length") == 0) { resp_len = strtoul(value, &line_end, 10); if (line_end == value || *line_end != '\0') { HTTPerr(0, HTTP_R_ERROR_PARSING_CONTENT_LENGTH); @@ -603,7 +605,7 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) } /* Look for blank line: end of headers */ - for (p = rctx->iobuf; *p != '\0' ; p++) { + for (p = rctx->iobuf; *p != '\0'; p++) { if (*p != '\r' && *p != '\n') break; } @@ -690,23 +692,31 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) #ifndef OPENSSL_NO_SOCK /* set up a new connection BIO, to HTTP server or to HTTP(S) proxy if given */ -static BIO *HTTP_new_bio(const char *server, const char *server_port, - const char *proxy, const char *proxy_port) +static BIO *HTTP_new_bio(const char *server /* optionally includes ":port" */, + const char *server_port /* explicit server port */, + const char *proxy /* optionally includes ":port" */) { - const char *host = server; + const char *host = server, *host_end; + char host_name[100]; const char *port = server_port; BIO *cbio; - if (server == NULL) { - HTTPerr(0, ERR_R_PASSED_NULL_PARAMETER); + if (!ossl_assert(server != NULL)) return NULL; - } if (proxy != NULL) { host = proxy; - port = proxy_port; + port = NULL; } - cbio = BIO_new_connect(host); + + host_end = strchr(host, '/'); + if (host_end != NULL && (size_t)(host_end - host) < sizeof(host_name)) { + /* chop trailing string starting with '/' */ + strncpy(host_name, host, host_end - host + 1); + host = host_name; + } + + cbio = BIO_new_connect(host /* optionally includes ":port" */); if (cbio == NULL) goto end; if (port != NULL) @@ -724,7 +734,7 @@ static ASN1_VALUE *BIO_mem_d2i(BIO *mem, const ASN1_ITEM *it) ASN1_VALUE *resp = ASN1_item_d2i(NULL, &p, len, it); if (resp == NULL) - HTTPerr(0, HTTP_R_SERVER_RESPONSE_PARSE_ERROR); + HTTPerr(0, HTTP_R_RESPONSE_PARSE_ERROR); return resp; } @@ -812,7 +822,7 @@ static int update_timeout(int timeout, time_t start_time) * After disconnect the modified BIO will be deallocated using BIO_free_all(). */ BIO *OSSL_HTTP_transfer(const char *server, const char *port, const char *path, - int use_ssl, const char *proxy, const char *proxy_port, + int use_ssl, const char *proxy, const char *no_proxy, BIO *bio, BIO *rbio, OSSL_HTTP_bio_cb_t bio_update_fn, void *arg, const STACK_OF(CONF_VALUE) *headers, @@ -837,17 +847,28 @@ BIO *OSSL_HTTP_transfer(const char *server, const char *port, const char *path, HTTPerr(0, ERR_R_PASSED_INVALID_ARGUMENT); return NULL; } - /* remaining parameters are checked indirectly by the functions called */ - if (bio != NULL) + if (bio != NULL) { cbio = bio; - else + } else { #ifndef OPENSSL_NO_SOCK - if ((cbio = HTTP_new_bio(server, port, proxy, proxy_port)) == NULL) + if (server == NULL) { + HTTPerr(0, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + if (*port == '\0') + port = NULL; + if (port == NULL && strchr(server, ':') == NULL) + port = use_ssl ? OSSL_HTTPS_PORT : OSSL_HTTP_PORT; + proxy = http_adapt_proxy(proxy, no_proxy, server, use_ssl); + if ((cbio = HTTP_new_bio(server, port, proxy)) == NULL) return NULL; #else + HTTPerr(0, HTTP_R_SOCK_NOT_SUPPORTED); return NULL; #endif + } + /* remaining parameters are checked indirectly by the functions called */ (void)ERR_set_mark(); /* prepare removing any spurious libssl errors */ if (rbio == NULL && BIO_connect_retry(cbio, timeout) <= 0) @@ -889,15 +910,17 @@ BIO *OSSL_HTTP_transfer(const char *server, const char *port, const char *path, if (lib == ERR_LIB_SSL || lib == ERR_LIB_HTTP || (lib == ERR_LIB_BIO && reason == BIO_R_CONNECT_TIMEOUT) || (lib == ERR_LIB_BIO && reason == BIO_R_CONNECT_ERROR) -# ifndef OPENSSL_NO_CMP +#ifndef OPENSSL_NO_CMP || (lib == ERR_LIB_CMP && reason == CMP_R_POTENTIALLY_INVALID_CERTIFICATE) -# endif +#endif ) { BIO_snprintf(buf, 200, "server=%s:%s", server, port); ERR_add_error_data(1, buf); + if (proxy != NULL) + ERR_add_error_data(2, " proxy=", proxy); if (err == 0) { - BIO_snprintf(buf, 200, "server has disconnected%s", + BIO_snprintf(buf, 200, " peer has disconnected%s", use_ssl ? " violating the protocol" : ", likely because it requires the use of TLS"); ERR_add_error_data(1, buf); @@ -934,8 +957,7 @@ BIO *OSSL_HTTP_transfer(const char *server, const char *port, const char *path, static int redirection_ok(int n_redir, const char *old_url, const char *new_url) { - static const char https[] = "https:"; - int https_len = 6; /* strlen(https) */ + size_t https_len = strlen(OSSL_HTTPS_NAME":"); if (n_redir >= HTTP_VERSION_MAX_REDIRECTIONS) { HTTPerr(0, HTTP_R_TOO_MANY_REDIRECTIONS); @@ -943,8 +965,8 @@ static int redirection_ok(int n_redir, const char *old_url, const char *new_url) } if (*new_url == '/') /* redirection to same server => same protocol */ return 1; - if (strncmp(old_url, https, https_len) == 0 && - strncmp(new_url, https, https_len) != 0) { + if (strncmp(old_url, OSSL_HTTPS_NAME":", https_len) == 0 && + strncmp(new_url, OSSL_HTTPS_NAME":", https_len) != 0) { HTTPerr(0, HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP); return 0; } @@ -952,7 +974,7 @@ static int redirection_ok(int n_redir, const char *old_url, const char *new_url) } /* Get data via HTTP from server at given URL, potentially with redirection */ -BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *proxy_port, +BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *no_proxy, BIO *bio, BIO *rbio, OSSL_HTTP_bio_cb_t bio_update_fn, void *arg, const STACK_OF(CONF_VALUE) *headers, @@ -980,7 +1002,7 @@ BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *proxy_port, break; new_rpath: - resp = OSSL_HTTP_transfer(host, port, path, use_ssl, proxy, proxy_port, + resp = OSSL_HTTP_transfer(host, port, path, use_ssl, proxy, no_proxy, bio, rbio, bio_update_fn, arg, headers, NULL, NULL, maxline, max_resp_len, @@ -1013,7 +1035,7 @@ BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *proxy_port, /* Get ASN.1-encoded data via HTTP from server at given URL */ ASN1_VALUE *OSSL_HTTP_get_asn1(const char *url, - const char *proxy, const char *proxy_port, + const char *proxy, const char *no_proxy, BIO *bio, BIO *rbio, OSSL_HTTP_bio_cb_t bio_update_fn, void *arg, const STACK_OF(CONF_VALUE) *headers, @@ -1028,7 +1050,7 @@ ASN1_VALUE *OSSL_HTTP_get_asn1(const char *url, HTTPerr(0, ERR_R_PASSED_NULL_PARAMETER); return NULL; } - if ((mem = OSSL_HTTP_get(url, proxy, proxy_port, bio, rbio, bio_update_fn, + if ((mem = OSSL_HTTP_get(url, proxy, no_proxy, bio, rbio, bio_update_fn, arg, headers, maxline, max_resp_len, timeout, expected_content_type, 1 /* expect_asn1 */)) != NULL) @@ -1040,7 +1062,7 @@ ASN1_VALUE *OSSL_HTTP_get_asn1(const char *url, /* Post ASN.1-encoded request via HTTP to server return ASN.1 response */ ASN1_VALUE *OSSL_HTTP_post_asn1(const char *server, const char *port, const char *path, int use_ssl, - const char *proxy, const char *proxy_port, + const char *proxy, const char *no_proxy, BIO *bio, BIO *rbio, OSSL_HTTP_bio_cb_t bio_update_fn, void *arg, const STACK_OF(CONF_VALUE) *headers, @@ -1061,7 +1083,7 @@ ASN1_VALUE *OSSL_HTTP_post_asn1(const char *server, const char *port, /* remaining parameters are checked indirectly */ req_mem = HTTP_asn1_item2bio(req_it, req); - res_mem = OSSL_HTTP_transfer(server, port, path, use_ssl, proxy, proxy_port, + res_mem = OSSL_HTTP_transfer(server, port, path, use_ssl, proxy, no_proxy, bio, rbio, bio_update_fn, arg, headers, content_type, req_mem /* may be NULL */, maxline, @@ -1107,8 +1129,8 @@ int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port, const char *proxyuser, const char *proxypass, int timeout, BIO *bio_err, const char *prog) { -# undef BUF_SIZE -# define BUF_SIZE (8 * 1024) +#undef BUF_SIZE +#define BUF_SIZE (8 * 1024) char *mbuf = OPENSSL_malloc(BUF_SIZE); char *mbufp; int read_len = 0; @@ -1117,11 +1139,13 @@ int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port, int rv; time_t max_time = timeout > 0 ? time(NULL) + timeout : 0; - if (bio == NULL || server == NULL || port == NULL + if (bio == NULL || server == NULL || (bio_err != NULL && prog == NULL)) { HTTPerr(0, ERR_R_PASSED_NULL_PARAMETER); goto end; } + if (port == NULL || *port == '\0') + port = OSSL_HTTPS_PORT; if (mbuf == NULL || fbio == NULL) { BIO_printf(bio_err /* may be NULL */, "%s: out of memory", prog); @@ -1193,7 +1217,7 @@ int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port, /* RFC 7231 4.3.6: any 2xx status code is valid */ if (strncmp(mbuf, HTTP_PREFIX, strlen(HTTP_PREFIX)) != 0) { - HTTPerr(0, HTTP_R_SERVER_RESPONSE_PARSE_ERROR); + HTTPerr(0, HTTP_R_RESPONSE_PARSE_ERROR); BIO_printf(bio_err, "%s: HTTP CONNECT failed, non-HTTP response\n", prog); /* Wrong protocol, not even HTTP, so stop reading headers */ @@ -1201,7 +1225,7 @@ int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port, } mbufp = mbuf + strlen(HTTP_PREFIX); if (strncmp(mbufp, HTTP_VERSION_PATT, strlen(HTTP_VERSION_PATT)) != 0) { - HTTPerr(0, HTTP_R_SERVER_SENT_WRONG_HTTP_VERSION); + HTTPerr(0, HTTP_R_RECEIVED_WRONG_HTTP_VERSION); BIO_printf(bio_err, "%s: HTTP CONNECT failed, bad HTTP version %.*s\n", prog, HTTP_VERSION_STR_LEN, mbufp); @@ -1241,6 +1265,5 @@ int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port, } OPENSSL_free(mbuf); return ret; -# undef BUF_SIZE +#undef BUF_SIZE } - diff --git a/crypto/http/http_err.c b/crypto/http/http_err.c index 86185393..7b6f2951 100644 --- a/crypto/http/http_err.c +++ b/crypto/http/http_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -34,17 +34,19 @@ static const ERR_STRING_DATA HTTP_str_reasons[] = { "missing content type"}, {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_MISSING_REDIRECT_LOCATION), "missing redirect location"}, + {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RECEIVED_ERROR), "received error"}, + {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RECEIVED_WRONG_HTTP_VERSION), + "received wrong http version"}, {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP), "redirection from https to http"}, {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_REDIRECTION_NOT_ENABLED), "redirection not enabled"}, {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RESPONSE_LINE_TOO_LONG), "response line too long"}, - {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_SERVER_RESPONSE_PARSE_ERROR), - "server response parse error"}, - {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_SERVER_SENT_ERROR), "server sent error"}, - {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_SERVER_SENT_WRONG_HTTP_VERSION), - "server sent wrong http version"}, + {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RESPONSE_PARSE_ERROR), + "response parse error"}, + {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_SOCK_NOT_SUPPORTED), + "sock not supported"}, {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_STATUS_CODE_UNSUPPORTED), "status code unsupported"}, {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_TLS_NOT_ENABLED), "tls not enabled"}, diff --git a/crypto/http/http_lib.c b/crypto/http/http_lib.c index 1d7ad042..5da5b1e7 100644 --- a/crypto/http/http_lib.c +++ b/crypto/http/http_lib.c @@ -11,6 +11,9 @@ #include #include #include +#include "internal/cryptlib.h" /* for ossl_assert() */ + +#include "http_local.h" /* * Parse a URL and split it up into host, port and path components and @@ -22,8 +25,11 @@ int OSSL_HTTP_parse_url(const char *url, char **phost, char **pport, { char *p, *buf; char *host; - char *port = "80"; + const char *port = OSSL_HTTP_PORT; + size_t https_len = strlen(OSSL_HTTPS_NAME); + if (!ossl_assert(https_len >= strlen(OSSL_HTTP_NAME))) + return 0; if (url == NULL) { HTTPerr(0, ERR_R_PASSED_NULL_PARAMETER); return 0; @@ -44,16 +50,16 @@ int OSSL_HTTP_parse_url(const char *url, char **phost, char **pport, /* Check for initial colon */ p = strchr(buf, ':'); - if (p == NULL || p - buf > 5 /* strlen("https") */) { + if (p == NULL || (size_t)(p - buf) > https_len) { p = buf; } else { *(p++) = '\0'; - if (strcmp(buf, "https") == 0) { + if (strcmp(buf, OSSL_HTTPS_NAME) == 0) { if (pssl != NULL) *pssl = 1; - port = "443"; - } else if (strcmp(buf, "http") != 0) { + port = OSSL_HTTPS_PORT; + } else if (strcmp(buf, OSSL_HTTP_NAME) != 0) { goto parse_err; } @@ -114,3 +120,58 @@ int OSSL_HTTP_parse_url(const char *url, char **phost, char **pport, OPENSSL_free(buf); return 0; } + +int http_use_proxy(const char *no_proxy, const char *server) +{ + size_t sl; + const char *found = NULL; + + if (!ossl_assert(server != NULL)) + return 0; + sl = strlen(server); + + /* + * using environment variable names, both lowercase and uppercase variants, + * compatible with other HTTP client implementations like wget, curl and git + */ + if (no_proxy == NULL) + no_proxy = getenv("no_proxy"); + if (no_proxy == NULL) + no_proxy = getenv(OPENSSL_NO_PROXY); + if (no_proxy != NULL) + found = strstr(no_proxy, server); + while (found != NULL + && ((found != no_proxy && found[-1] != ' ' && found[-1] != ',') + || (found[sl] != '\0' && found[sl] != ' ' && found[sl] != ','))) + found = strstr(found + 1, server); + return found == NULL; +} + +const char *http_adapt_proxy(const char *proxy, const char *no_proxy, + const char *server, int use_ssl) +{ + const int http_len = strlen(OSSL_HTTP_PREFIX); + const int https_len = strlen(OSSL_HTTPS_PREFIX); + + /* + * using environment variable names, both lowercase and uppercase variants, + * compatible with other HTTP client implementations like wget, curl and git + */ + if (proxy == NULL) + proxy = getenv(use_ssl ? "https_proxy" : "http_proxy"); + if (proxy == NULL) + proxy = getenv(use_ssl ? OPENSSL_HTTP_PROXY : + OPENSSL_HTTPS_PROXY); + if (proxy == NULL) + return NULL; + + /* skip any leading "http://" or "https://" */ + if (strncmp(proxy, OSSL_HTTP_PREFIX, http_len) == 0) + proxy += http_len; + else if (strncmp(proxy, OSSL_HTTPS_PREFIX, https_len) == 0) + proxy += https_len; + + if (*proxy == '\0' || !http_use_proxy(no_proxy, server)) + return NULL; + return proxy; +} diff --git a/crypto/http/http_local.h b/crypto/http/http_local.h index 4e6577f6..64b475b8 100644 --- a/crypto/http/http_local.h +++ b/crypto/http/http_local.h @@ -45,5 +45,8 @@ ASN1_VALUE *HTTP_sendreq_bio(BIO *bio, OSSL_HTTP_bio_cb_t bio_update_fn, ASN1_VALUE *req, const ASN1_ITEM *req_it, int maxline, unsigned long max_resp_len, int timeout, const ASN1_ITEM *rsp_it); +int http_use_proxy(const char *no_proxy, const char *server); +const char *http_adapt_proxy(const char *proxy, const char *no_proxy, + const char *server, int use_ssl); -#endif /* !defined OSSL_CRYPTO_HTTP_LOCAL_H */ +#endif /* !defined(OSSL_CRYPTO_HTTP_LOCAL_H) */ diff --git a/crypto/idea/build.info b/crypto/idea/build.info index 23261237..5441351b 100644 --- a/crypto/idea/build.info +++ b/crypto/idea/build.info @@ -1,3 +1,10 @@ LIBS=../../libcrypto -SOURCE[../../libcrypto]=\ - i_cbc.c i_cfb64.c i_ofb64.c i_ecb.c i_skey.c +$ALL=i_cbc.c i_cfb64.c i_ofb64.c i_ecb.c i_skey.c + +SOURCE[../../libcrypto]=$ALL + +# When all deprecated symbols are removed, libcrypto doesn't export the +# idea functions, so we must include them directly in liblegacy.a +IF[{- $disabled{'deprecated-3.0'} -}] + SOURCE[../../providers/liblegacy.a]=$ALL +ENDIF diff --git a/crypto/ocsp/ocsp_cl.c b/crypto/ocsp/ocsp_cl.c index 8bd55038..6523dfec 100644 --- a/crypto/ocsp/ocsp_cl.c +++ b/crypto/ocsp/ocsp_cl.c @@ -48,7 +48,7 @@ OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid) /* Set requestorName from an X509_NAME structure */ -int OCSP_request_set1_name(OCSP_REQUEST *req, X509_NAME *nm) +int OCSP_request_set1_name(OCSP_REQUEST *req, const X509_NAME *nm) { GENERAL_NAME *gen; diff --git a/crypto/ocsp/ocsp_ext.c b/crypto/ocsp/ocsp_ext.c index bffcf09d..c8b698de 100644 --- a/crypto/ocsp/ocsp_ext.c +++ b/crypto/ocsp/ocsp_ext.c @@ -430,7 +430,7 @@ X509_EXTENSION *OCSP_archive_cutoff_new(char *tim) * two--NID_ad_ocsp, NID_id_ad_caIssuers--and GeneralName value. This method * forces NID_ad_ocsp and uniformResourceLocator [6] IA5String. */ -X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME *issuer, const char **urls) +X509_EXTENSION *OCSP_url_svcloc_new(const X509_NAME *issuer, const char **urls) { X509_EXTENSION *x = NULL; ASN1_IA5STRING *ia5 = NULL; diff --git a/crypto/ocsp/ocsp_lib.c b/crypto/ocsp/ocsp_lib.c index 797ac289..17a7b8eb 100644 --- a/crypto/ocsp/ocsp_lib.c +++ b/crypto/ocsp/ocsp_lib.c @@ -22,7 +22,7 @@ OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, const X509 *subject, const X509 *issuer) { - X509_NAME *iname; + const X509_NAME *iname; const ASN1_INTEGER *serial; ASN1_BIT_STRING *ikey; if (!dgst) diff --git a/crypto/ocsp/ocsp_srv.c b/crypto/ocsp/ocsp_srv.c index 7e0aca16..051747b4 100644 --- a/crypto/ocsp/ocsp_srv.c +++ b/crypto/ocsp/ocsp_srv.c @@ -259,45 +259,67 @@ int OCSP_RESPID_set_by_name(OCSP_RESPID *respid, X509 *cert) return 1; } -int OCSP_RESPID_set_by_key(OCSP_RESPID *respid, X509 *cert) +int OCSP_RESPID_set_by_key_ex(OCSP_RESPID *respid, X509 *cert, + OPENSSL_CTX *libctx, const char *propq) { ASN1_OCTET_STRING *byKey = NULL; unsigned char md[SHA_DIGEST_LENGTH]; + EVP_MD *sha1 = EVP_MD_fetch(libctx, "SHA1", propq); + int ret = 0; + + if (sha1 == NULL) + return 0; /* RFC2560 requires SHA1 */ - if (!X509_pubkey_digest(cert, EVP_sha1(), md, NULL)) - return 0; + if (!X509_pubkey_digest(cert, sha1, md, NULL)) + goto err; byKey = ASN1_OCTET_STRING_new(); if (byKey == NULL) - return 0; + goto err; if (!(ASN1_OCTET_STRING_set(byKey, md, SHA_DIGEST_LENGTH))) { ASN1_OCTET_STRING_free(byKey); - return 0; + goto err; } respid->type = V_OCSP_RESPID_KEY; respid->value.byKey = byKey; - return 1; + ret = 1; + err: + EVP_MD_free(sha1); + return ret; } -int OCSP_RESPID_match(OCSP_RESPID *respid, X509 *cert) +int OCSP_RESPID_set_by_key(OCSP_RESPID *respid, X509 *cert) { + return OCSP_RESPID_set_by_key_ex(respid, cert, NULL, NULL); +} + +int OCSP_RESPID_match_ex(OCSP_RESPID *respid, X509 *cert, OPENSSL_CTX *libctx, + const char *propq) +{ + EVP_MD *sha1 = NULL; + int ret = 0; + if (respid->type == V_OCSP_RESPID_KEY) { unsigned char md[SHA_DIGEST_LENGTH]; + sha1 = EVP_MD_fetch(libctx, "SHA1", propq); + if (sha1 == NULL) + goto err; + if (respid->value.byKey == NULL) - return 0; + goto err; /* RFC2560 requires SHA1 */ - if (!X509_pubkey_digest(cert, EVP_sha1(), md, NULL)) - return 0; + if (!X509_pubkey_digest(cert, sha1, md, NULL)) + goto err; - return (ASN1_STRING_length(respid->value.byKey) == SHA_DIGEST_LENGTH) - && (memcmp(ASN1_STRING_get0_data(respid->value.byKey), md, - SHA_DIGEST_LENGTH) == 0); + ret = (ASN1_STRING_length(respid->value.byKey) == SHA_DIGEST_LENGTH) + && (memcmp(ASN1_STRING_get0_data(respid->value.byKey), md, + SHA_DIGEST_LENGTH) == 0); } else if (respid->type == V_OCSP_RESPID_NAME) { if (respid->value.byName == NULL) return 0; @@ -306,5 +328,12 @@ int OCSP_RESPID_match(OCSP_RESPID *respid, X509 *cert) X509_get_subject_name(cert)) == 0; } - return 0; + err: + EVP_MD_free(sha1); + return ret; +} + +int OCSP_RESPID_match(OCSP_RESPID *respid, X509 *cert) +{ + return OCSP_RESPID_match_ex(respid, cert, NULL, NULL); } diff --git a/crypto/ocsp/ocsp_vfy.c b/crypto/ocsp/ocsp_vfy.c index a364c8a2..421d2f32 100644 --- a/crypto/ocsp/ocsp_vfy.c +++ b/crypto/ocsp/ocsp_vfy.c @@ -22,7 +22,7 @@ static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, STACK_OF(OCSP_SINGLERESP) *sresp); static int ocsp_check_delegated(X509 *x); static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, - X509_NAME *nm, STACK_OF(X509) *certs, + const X509_NAME *nm, STACK_OF(X509) *certs, unsigned long flags); /* Verify a basic response message */ @@ -279,7 +279,7 @@ static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, /* If only one ID to match then do it */ if (cid) { const EVP_MD *dgst; - X509_NAME *iname; + const X509_NAME *iname; int mdlen; unsigned char md[EVP_MAX_MD_SIZE]; if ((dgst = EVP_get_digestbyobj(cid->hashAlgorithm.algorithm)) @@ -340,7 +340,7 @@ int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, X509_STORE *store, unsigned long flags) { X509 *signer; - X509_NAME *nm; + const X509_NAME *nm; GENERAL_NAME *gen; int ret = 0; X509_STORE_CTX *ctx = X509_STORE_CTX_new(); @@ -414,7 +414,7 @@ end: } static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, - X509_NAME *nm, STACK_OF(X509) *certs, + const X509_NAME *nm, STACK_OF(X509) *certs, unsigned long flags) { X509 *signer; diff --git a/crypto/packet.c b/crypto/packet.c index 75a03176..6dacebfe 100644 --- a/crypto/packet.c +++ b/crypto/packet.c @@ -65,8 +65,11 @@ int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes) if (BUF_MEM_grow(pkt->buf, newlen) == 0) return 0; } - if (allocbytes != NULL) + if (allocbytes != NULL) { *allocbytes = WPACKET_get_curr(pkt); + if (pkt->endfirst && *allocbytes != NULL) + *allocbytes -= len; + } return 1; } @@ -74,6 +77,9 @@ int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes) int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len, unsigned char **allocbytes, size_t lenbytes) { + if (pkt->endfirst && lenbytes > 0) + return 0; + if (!WPACKET_reserve_bytes(pkt, lenbytes + len, allocbytes)) return 0; @@ -131,10 +137,25 @@ int WPACKET_init_static_len(WPACKET *pkt, unsigned char *buf, size_t len, pkt->staticbuf = buf; pkt->buf = NULL; pkt->maxsize = (max < len) ? max : len; + pkt->endfirst = 0; return wpacket_intern_init_len(pkt, lenbytes); } +int WPACKET_init_der(WPACKET *pkt, unsigned char *buf, size_t len) +{ + /* Internal API, so should not fail */ + if (!ossl_assert(buf != NULL && len > 0)) + return 0; + + pkt->staticbuf = buf; + pkt->buf = NULL; + pkt->maxsize = len; + pkt->endfirst = 1; + + return wpacket_intern_init_len(pkt, 0); +} + int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes) { /* Internal API, so should not fail */ @@ -144,6 +165,7 @@ int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes) pkt->staticbuf = NULL; pkt->buf = buf; pkt->maxsize = maxmaxsize(lenbytes); + pkt->endfirst = 0; return wpacket_intern_init_len(pkt, lenbytes); } @@ -158,6 +180,17 @@ int WPACKET_init_null(WPACKET *pkt, size_t lenbytes) pkt->staticbuf = NULL; pkt->buf = NULL; pkt->maxsize = maxmaxsize(lenbytes); + pkt->endfirst = 0; + + return wpacket_intern_init_len(pkt, 0); +} + +int WPACKET_init_null_der(WPACKET *pkt) +{ + pkt->staticbuf = NULL; + pkt->buf = NULL; + pkt->maxsize = SIZE_MAX; + pkt->endfirst = 1; return wpacket_intern_init_len(pkt, 0); } @@ -232,6 +265,19 @@ static int wpacket_intern_close(WPACKET *pkt, WPACKET_SUB *sub, int doclose) && !put_value(&buf[sub->packet_len], packlen, sub->lenbytes)) return 0; + } else if (pkt->endfirst && sub->parent != NULL) { + size_t tmplen = packlen; + size_t numlenbytes = 1; + + while ((tmplen = tmplen >> 8) > 0) + numlenbytes++; + if (!WPACKET_put_bytes__(pkt, packlen, numlenbytes)) + return 0; + if (packlen > 0x7f) { + numlenbytes |= 0x80; + if (!WPACKET_put_bytes_u8(pkt, numlenbytes)) + return 0; + } } if (doclose) { @@ -298,6 +344,10 @@ int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes) if (!ossl_assert(pkt->subs != NULL)) return 0; + /* We don't support lenbytes greater than 0 when doing endfirst writing */ + if (lenbytes > 0 && pkt->endfirst) + return 0; + if ((sub = OPENSSL_zalloc(sizeof(*sub))) == NULL) { SSLerr(SSL_F_WPACKET_START_SUB_PACKET_LEN__, ERR_R_MALLOC_FAILURE); return 0; @@ -436,6 +486,9 @@ unsigned char *WPACKET_get_curr(WPACKET *pkt) if (buf == NULL) return NULL; + if (pkt->endfirst) + return buf + pkt->maxsize - pkt->curr; + return buf + pkt->curr; } diff --git a/crypto/param_build.c b/crypto/param_build.c index 7c3b1a59..4f999678 100644 --- a/crypto/param_build.c +++ b/crypto/param_build.c @@ -12,11 +12,44 @@ #include #include #include +#include +#include #include "internal/cryptlib.h" -#include "internal/param_build.h" +#include "openssl/param_build.h" +/* + * Special internal param type to indicate the end of an allocate OSSL_PARAM + * array. + */ #define OSSL_PARAM_ALLOCATED_END 127 +typedef struct { + const char *key; + int type; + int secure; + size_t size; + size_t alloc_blocks; + const BIGNUM *bn; + const void *string; + union { + /* + * These fields are never directly addressed, but their sizes are + * imporant so that all native types can be copied here without overrun. + */ + ossl_intmax_t i; + ossl_uintmax_t u; + double d; + } num; +} OSSL_PARAM_BLD_DEF; + +DEFINE_STACK_OF(OSSL_PARAM_BLD_DEF) + +struct ossl_param_bld_st { + size_t total_blocks; + size_t secure_blocks; + STACK_OF(OSSL_PARAM_BLD_DEF) *params; +}; + typedef union { OSSL_UNION_ALIGN; } OSSL_PARAM_BLD_BLOCK; @@ -32,14 +65,12 @@ static OSSL_PARAM_BLD_DEF *param_push(OSSL_PARAM_BLD *bld, const char *key, int size, size_t alloc, int type, int secure) { - OSSL_PARAM_BLD_DEF *pd; + OSSL_PARAM_BLD_DEF *pd = OPENSSL_zalloc(sizeof(*pd)); - if (bld->curr >= OSSL_PARAM_BLD_MAX) { - CRYPTOerr(CRYPTO_F_PARAM_PUSH, CRYPTO_R_TOO_MANY_RECORDS); + if (pd == NULL) { + CRYPTOerr(CRYPTO_F_PARAM_PUSH, ERR_R_MALLOC_FAILURE); return NULL; } - pd = bld->params + bld->curr++; - memset(pd, 0, sizeof(*pd)); pd->key = key; pd->type = type; pd->size = size; @@ -48,6 +79,10 @@ static OSSL_PARAM_BLD_DEF *param_push(OSSL_PARAM_BLD *bld, const char *key, bld->secure_blocks += pd->alloc_blocks; else bld->total_blocks += pd->alloc_blocks; + if (sk_OSSL_PARAM_BLD_DEF_push(bld->params, pd) <= 0) { + OPENSSL_free(pd); + pd = NULL; + } return pd; } @@ -66,83 +101,107 @@ static int param_push_num(OSSL_PARAM_BLD *bld, const char *key, return 1; } -void ossl_param_bld_init(OSSL_PARAM_BLD *bld) +OSSL_PARAM_BLD *OSSL_PARAM_BLD_new(void) { - memset(bld, 0, sizeof(*bld)); + OSSL_PARAM_BLD *r = OPENSSL_zalloc(sizeof(OSSL_PARAM_BLD)); + + if (r != NULL) { + r->params = sk_OSSL_PARAM_BLD_DEF_new_null(); + if (r->params == NULL) { + OPENSSL_free(r); + r = NULL; + } + } + return r; } -int ossl_param_bld_push_int(OSSL_PARAM_BLD *bld, const char *key, int num) +static void free_all_params(OSSL_PARAM_BLD *bld) +{ + int i, n = sk_OSSL_PARAM_BLD_DEF_num(bld->params); + + for (i = 0; i < n; i++) + OPENSSL_free(sk_OSSL_PARAM_BLD_DEF_pop(bld->params)); +} + +void OSSL_PARAM_BLD_free(OSSL_PARAM_BLD *bld) +{ + free_all_params(bld); + sk_OSSL_PARAM_BLD_DEF_free(bld->params); + OPENSSL_free(bld); +} + +int OSSL_PARAM_BLD_push_int(OSSL_PARAM_BLD *bld, const char *key, int num) { return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_INTEGER); } -int ossl_param_bld_push_uint(OSSL_PARAM_BLD *bld, const char *key, +int OSSL_PARAM_BLD_push_uint(OSSL_PARAM_BLD *bld, const char *key, unsigned int num) { return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_UNSIGNED_INTEGER); } -int ossl_param_bld_push_long(OSSL_PARAM_BLD *bld, const char *key, +int OSSL_PARAM_BLD_push_long(OSSL_PARAM_BLD *bld, const char *key, long int num) { return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_INTEGER); } -int ossl_param_bld_push_ulong(OSSL_PARAM_BLD *bld, const char *key, +int OSSL_PARAM_BLD_push_ulong(OSSL_PARAM_BLD *bld, const char *key, unsigned long int num) { return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_UNSIGNED_INTEGER); } -int ossl_param_bld_push_int32(OSSL_PARAM_BLD *bld, const char *key, +int OSSL_PARAM_BLD_push_int32(OSSL_PARAM_BLD *bld, const char *key, int32_t num) { return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_INTEGER); } -int ossl_param_bld_push_uint32(OSSL_PARAM_BLD *bld, const char *key, +int OSSL_PARAM_BLD_push_uint32(OSSL_PARAM_BLD *bld, const char *key, uint32_t num) { return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_UNSIGNED_INTEGER); } -int ossl_param_bld_push_int64(OSSL_PARAM_BLD *bld, const char *key, +int OSSL_PARAM_BLD_push_int64(OSSL_PARAM_BLD *bld, const char *key, int64_t num) { return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_INTEGER); } -int ossl_param_bld_push_uint64(OSSL_PARAM_BLD *bld, const char *key, +int OSSL_PARAM_BLD_push_uint64(OSSL_PARAM_BLD *bld, const char *key, uint64_t num) { return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_UNSIGNED_INTEGER); } -int ossl_param_bld_push_size_t(OSSL_PARAM_BLD *bld, const char *key, +int OSSL_PARAM_BLD_push_size_t(OSSL_PARAM_BLD *bld, const char *key, size_t num) { return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_UNSIGNED_INTEGER); } -int ossl_param_bld_push_double(OSSL_PARAM_BLD *bld, const char *key, +int OSSL_PARAM_BLD_push_double(OSSL_PARAM_BLD *bld, const char *key, double num) { return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_REAL); } -int ossl_param_bld_push_BN(OSSL_PARAM_BLD *bld, const char *key, +int OSSL_PARAM_BLD_push_BN(OSSL_PARAM_BLD *bld, const char *key, const BIGNUM *bn) { - return ossl_param_bld_push_BN_pad(bld, key, bn, + return OSSL_PARAM_BLD_push_BN_pad(bld, key, bn, bn == NULL ? 0 : BN_num_bytes(bn)); } -int ossl_param_bld_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key, +int OSSL_PARAM_BLD_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key, const BIGNUM *bn, size_t sz) { int n, secure = 0; @@ -168,7 +227,7 @@ int ossl_param_bld_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key, return 1; } -int ossl_param_bld_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key, +int OSSL_PARAM_BLD_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key, const char *buf, size_t bsize) { OSSL_PARAM_BLD_DEF *pd; @@ -187,7 +246,7 @@ int ossl_param_bld_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key, return 1; } -int ossl_param_bld_push_utf8_ptr(OSSL_PARAM_BLD *bld, const char *key, +int OSSL_PARAM_BLD_push_utf8_ptr(OSSL_PARAM_BLD *bld, const char *key, char *buf, size_t bsize) { OSSL_PARAM_BLD_DEF *pd; @@ -206,7 +265,7 @@ int ossl_param_bld_push_utf8_ptr(OSSL_PARAM_BLD *bld, const char *key, return 1; } -int ossl_param_bld_push_octet_string(OSSL_PARAM_BLD *bld, const char *key, +int OSSL_PARAM_BLD_push_octet_string(OSSL_PARAM_BLD *bld, const char *key, const void *buf, size_t bsize) { OSSL_PARAM_BLD_DEF *pd; @@ -223,7 +282,7 @@ int ossl_param_bld_push_octet_string(OSSL_PARAM_BLD *bld, const char *key, return 1; } -int ossl_param_bld_push_octet_ptr(OSSL_PARAM_BLD *bld, const char *key, +int OSSL_PARAM_BLD_push_octet_ptr(OSSL_PARAM_BLD *bld, const char *key, void *buf, size_t bsize) { OSSL_PARAM_BLD_DEF *pd; @@ -244,12 +303,12 @@ static OSSL_PARAM *param_bld_convert(OSSL_PARAM_BLD *bld, OSSL_PARAM *param, OSSL_PARAM_BLD_BLOCK *blk, OSSL_PARAM_BLD_BLOCK *secure) { - size_t i; + int i, num = sk_OSSL_PARAM_BLD_DEF_num(bld->params); OSSL_PARAM_BLD_DEF *pd; void *p; - for (i = 0; i < bld->curr; i++) { - pd = bld->params + i; + for (i = 0; i < num; i++) { + pd = sk_OSSL_PARAM_BLD_DEF_value(bld->params, i); param[i].key = pd->key; param[i].data_type = pd->type; param[i].data_size = pd->size; @@ -288,11 +347,12 @@ static OSSL_PARAM *param_bld_convert(OSSL_PARAM_BLD *bld, OSSL_PARAM *param, return param + i; } -OSSL_PARAM *ossl_param_bld_to_param(OSSL_PARAM_BLD *bld) +OSSL_PARAM *OSSL_PARAM_BLD_to_param(OSSL_PARAM_BLD *bld) { OSSL_PARAM_BLD_BLOCK *blk, *s = NULL; OSSL_PARAM *params, *last; - const size_t p_blks = bytes_to_blocks((1 + bld->curr) * sizeof(*params)); + const int num = sk_OSSL_PARAM_BLD_DEF_num(bld->params); + const size_t p_blks = bytes_to_blocks((1 + num) * sizeof(*params)); const size_t total = ALIGN_SIZE * (p_blks + bld->total_blocks); const size_t ss = ALIGN_SIZE * bld->secure_blocks; @@ -301,12 +361,14 @@ OSSL_PARAM *ossl_param_bld_to_param(OSSL_PARAM_BLD *bld) if (s == NULL) { CRYPTOerr(CRYPTO_F_OSSL_PARAM_BLD_TO_PARAM, CRYPTO_R_SECURE_MALLOC_FAILURE); + OPENSSL_free(bld); return NULL; } } params = OPENSSL_malloc(total); if (params == NULL) { CRYPTOerr(CRYPTO_F_OSSL_PARAM_BLD_TO_PARAM, ERR_R_MALLOC_FAILURE); + OPENSSL_free(bld); OPENSSL_secure_free(s); return NULL; } @@ -315,10 +377,15 @@ OSSL_PARAM *ossl_param_bld_to_param(OSSL_PARAM_BLD *bld) last->data_size = ss; last->data = s; last->data_type = OSSL_PARAM_ALLOCATED_END; + + /* Reset builder for reuse */ + bld->total_blocks = 0; + bld->secure_blocks = 0; + free_all_params(bld); return params; } -void ossl_param_bld_free(OSSL_PARAM *params) +void OSSL_PARAM_BLD_free_params(OSSL_PARAM *params) { if (params != NULL) { OSSL_PARAM *p; diff --git a/crypto/param_build_set.c b/crypto/param_build_set.c new file mode 100644 index 00000000..b74b0d59 --- /dev/null +++ b/crypto/param_build_set.c @@ -0,0 +1,111 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Key Management utility functions to share functionality between the export() + * and get_params() methods. + * export() uses OSSL_PARAM_BLD, and get_params() used the OSSL_PARAM[] to + * fill in parameter data for the same key and data fields. + */ + +#include +#include "internal/param_build_set.h" + +DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM) + +int ossl_param_build_set_int(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, + const char *key, int num) +{ + if (bld != NULL) + return OSSL_PARAM_BLD_push_int(bld, key, num); + p = OSSL_PARAM_locate(p, key); + if (p != NULL) + return OSSL_PARAM_set_int(p, num); + return 1; +} + +int ossl_param_build_set_utf8_string(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, + const char *key, const char *buf) +{ + if (bld != NULL) + return OSSL_PARAM_BLD_push_utf8_string(bld, key, buf, 0); + p = OSSL_PARAM_locate(p, key); + if (p != NULL) + return OSSL_PARAM_set_utf8_string(p, buf); + return 1; +} + +int ossl_param_build_set_octet_string(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, + const char *key, + const unsigned char *data, + size_t data_len) +{ + if (bld != NULL) + return OSSL_PARAM_BLD_push_octet_string(bld, key, data, data_len); + + p = OSSL_PARAM_locate(p, key); + if (p != NULL) + return OSSL_PARAM_set_octet_string(p, data, data_len); + return 1; +} + +int ossl_param_build_set_bn_pad(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, + const char *key, const BIGNUM *bn, size_t sz) +{ + if (bld != NULL) + return OSSL_PARAM_BLD_push_BN_pad(bld, key, bn, sz); + p = OSSL_PARAM_locate(p, key); + if (p != NULL) { + if (sz > p->data_size) + return 0; + /* TODO(3.0) Change to use OSSL_PARAM_set_BN_pad */ + p->data_size = sz; + return OSSL_PARAM_set_BN(p, bn); + } + return 1; +} + +int ossl_param_build_set_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, + const char *key, const BIGNUM *bn) +{ + if (bld != NULL) + return OSSL_PARAM_BLD_push_BN(bld, key, bn); + + p = OSSL_PARAM_locate(p, key); + if (p != NULL) + return OSSL_PARAM_set_BN(p, bn) > 0; + return 1; +} + +int ossl_param_build_set_multi_key_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *params, + const char *names[], + STACK_OF(BIGNUM_const) *stk) +{ + int i, sz = sk_BIGNUM_const_num(stk); + OSSL_PARAM *p; + + + if (bld != NULL) { + for (i = 0; i < sz && names[i] != NULL; ++i) { + if (!OSSL_PARAM_BLD_push_BN(bld, names[i], + sk_BIGNUM_const_value(stk, i))) + return 0; + } + return 1; + } + + for (i = 0; i < sz && names[i] != NULL; ++i) { + p = OSSL_PARAM_locate(params, names[i]); + if (p != NULL) { + if (!OSSL_PARAM_set_BN(p, sk_BIGNUM_const_value(stk, i))) + return 0; + } + } + return 1; +} diff --git a/crypto/params.c b/crypto/params.c index 5d1fc6a6..64d53c50 100644 --- a/crypto/params.c +++ b/crypto/params.c @@ -778,6 +778,8 @@ static int get_string_internal(const OSSL_PARAM *p, void **val, size_t max_len, if (sz == 0) return 1; + if (p->data == NULL) + return 0; if (*val == NULL) { char *const q = OPENSSL_malloc(sz); diff --git a/crypto/pkcs12/p12_crt.c b/crypto/pkcs12/p12_crt.c index 94bd3e16..0e8b419d 100644 --- a/crypto/pkcs12/p12_crt.c +++ b/crypto/pkcs12/p12_crt.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -62,7 +62,8 @@ PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 * if (pkey && cert) { if (!X509_check_private_key(cert, pkey)) return NULL; - X509_digest(cert, EVP_sha1(), keyid, &keyidlen); + if (!X509_digest(cert, EVP_sha1(), keyid, &keyidlen)) + return NULL; } if (cert) { diff --git a/crypto/provider_conf.c b/crypto/provider_conf.c index 9b7a1fff..3bf974e9 100644 --- a/crypto/provider_conf.c +++ b/crypto/provider_conf.c @@ -164,7 +164,7 @@ static int provider_conf_init(CONF_IMODULE *md, const CONF *cnf) for (i = 0; i < sk_CONF_VALUE_num(elist); i++) { cval = sk_CONF_VALUE_value(elist, i); - if (!provider_conf_load(NULL, cval->name, cval->value, cnf)) + if (!provider_conf_load(cnf->libctx, cval->name, cval->value, cnf)) return 0; } diff --git a/crypto/provider_core.c b/crypto/provider_core.c index 026e784b..ef8b3bf5 100644 --- a/crypto/provider_core.c +++ b/crypto/provider_core.c @@ -540,12 +540,13 @@ static int provider_activate(OSSL_PROVIDER *prov) * with the error library number, so we need to make a copy of that * array either way. */ - cnt = 1; /* One for the terminating item */ + cnt = 0; while (reasonstrings[cnt].id != 0) { if (ERR_GET_LIB(reasonstrings[cnt].id) != 0) return 0; cnt++; } + cnt++; /* One for the terminating item */ /* Allocate one extra item for the "library" name */ prov->error_strings = @@ -911,7 +912,7 @@ static int core_pop_error_to_mark(const OSSL_PROVIDER *prov) { return ERR_pop_to_mark(); } -#endif +#endif /* FIPS_MODE */ /* * Functions provided by the core. Blank line separates "families" of related @@ -929,13 +930,13 @@ static const OSSL_DISPATCH core_dispatch_[] = { { OSSL_FUNC_CORE_SET_ERROR_MARK, (void (*)(void))core_set_error_mark }, { OSSL_FUNC_CORE_CLEAR_LAST_ERROR_MARK, (void (*)(void))core_clear_last_error_mark }, - { OSSL_FUNC_CORE_POP_ERROR_TO_MARK, - (void (*)(void))core_pop_error_to_mark }, + { OSSL_FUNC_CORE_POP_ERROR_TO_MARK, (void (*)(void))core_pop_error_to_mark }, { OSSL_FUNC_BIO_NEW_FILE, (void (*)(void))BIO_new_file }, { OSSL_FUNC_BIO_NEW_MEMBUF, (void (*)(void))BIO_new_mem_buf }, { OSSL_FUNC_BIO_READ_EX, (void (*)(void))BIO_read_ex }, { OSSL_FUNC_BIO_FREE, (void (*)(void))BIO_free }, { OSSL_FUNC_BIO_VPRINTF, (void (*)(void))BIO_vprintf }, + { OSSL_FUNC_BIO_VSNPRINTF, (void (*)(void))BIO_vsnprintf }, { OSSL_FUNC_SELF_TEST_CB, (void (*)(void))OSSL_SELF_TEST_get_callback }, #endif { OSSL_FUNC_CRYPTO_MALLOC, (void (*)(void))CRYPTO_malloc }, diff --git a/crypto/provider_predefined.c b/crypto/provider_predefined.c index e65f4610..fdf9a7e1 100644 --- a/crypto/provider_predefined.c +++ b/crypto/provider_predefined.c @@ -11,6 +11,7 @@ #include "provider_local.h" OSSL_provider_init_fn ossl_default_provider_init; +OSSL_provider_init_fn ossl_null_provider_init; OSSL_provider_init_fn fips_intern_provider_init; #ifdef STATIC_LEGACY OSSL_provider_init_fn ossl_legacy_provider_init; @@ -23,6 +24,7 @@ const struct predefined_providers_st predefined_providers[] = { # ifdef STATIC_LEGACY { "legacy", ossl_legacy_provider_init, 0 }, # endif + { "null", ossl_null_provider_init, 0 }, #endif { NULL, NULL, 0 } }; diff --git a/crypto/rand/drbg_ctr.c b/crypto/rand/drbg_ctr.c index 30420ae5..52559fab 100644 --- a/crypto/rand/drbg_ctr.c +++ b/crypto/rand/drbg_ctr.c @@ -12,6 +12,7 @@ #include #include #include +#include "crypto/modes.h" #include "internal/thread_once.h" #include "rand_local.h" @@ -20,19 +21,15 @@ */ static void inc_128(RAND_DRBG_CTR *ctr) { - int i; - unsigned char c; - unsigned char *p = &ctr->V[15]; + unsigned char *p = &ctr->V[0]; + u32 n = 16, c = 1; - for (i = 0; i < 16; i++, p--) { - c = *p; - c++; - *p = c; - if (c != 0) { - /* If we didn't wrap around, we're done. */ - break; - } - } + do { + --n; + c += p[n]; + p[n] = (u8)c; + c >>= 8; + } while (n); } static void ctr_XOR(RAND_DRBG_CTR *ctr, const unsigned char *in, size_t inlen) @@ -65,15 +62,15 @@ static void ctr_XOR(RAND_DRBG_CTR *ctr, const unsigned char *in, size_t inlen) * Process a complete block using BCC algorithm of SP 800-90A 10.3.3 */ __owur static int ctr_BCC_block(RAND_DRBG_CTR *ctr, unsigned char *out, - const unsigned char *in) + const unsigned char *in, int len) { int i, outlen = AES_BLOCK_SIZE; - for (i = 0; i < 16; i++) + for (i = 0; i < len; i++) out[i] ^= in[i]; - if (!EVP_CipherUpdate(ctr->ctx_df, out, &outlen, out, AES_BLOCK_SIZE) - || outlen != AES_BLOCK_SIZE) + if (!EVP_CipherUpdate(ctr->ctx_df, out, &outlen, out, len) + || outlen != len) return 0; return 1; } @@ -84,12 +81,16 @@ __owur static int ctr_BCC_block(RAND_DRBG_CTR *ctr, unsigned char *out, */ __owur static int ctr_BCC_blocks(RAND_DRBG_CTR *ctr, const unsigned char *in) { - if (!ctr_BCC_block(ctr, ctr->KX, in) - || !ctr_BCC_block(ctr, ctr->KX + 16, in)) - return 0; - if (ctr->keylen != 16 && !ctr_BCC_block(ctr, ctr->KX + 32, in)) - return 0; - return 1; + unsigned char in_tmp[48]; + unsigned char num_of_blk = 2; + + memcpy(in_tmp, in, 16); + memcpy(in_tmp + 16, in, 16); + if (ctr->keylen != 16) { + memcpy(in_tmp + 32, in, 16); + num_of_blk = 3; + } + return ctr_BCC_block(ctr, ctr->KX, in_tmp, AES_BLOCK_SIZE * num_of_blk); } /* @@ -98,19 +99,14 @@ __owur static int ctr_BCC_blocks(RAND_DRBG_CTR *ctr, const unsigned char *in) */ __owur static int ctr_BCC_init(RAND_DRBG_CTR *ctr) { + unsigned char bltmp[48] = {0}; + unsigned char num_of_blk; + memset(ctr->KX, 0, 48); - memset(ctr->bltmp, 0, 16); - if (!ctr_BCC_block(ctr, ctr->KX, ctr->bltmp)) - return 0; - ctr->bltmp[3] = 1; - if (!ctr_BCC_block(ctr, ctr->KX + 16, ctr->bltmp)) - return 0; - if (ctr->keylen != 16) { - ctr->bltmp[3] = 2; - if (!ctr_BCC_block(ctr, ctr->KX + 32, ctr->bltmp)) - return 0; - } - return 1; + num_of_blk = ctr->keylen == 16 ? 2 : 3; + bltmp[(AES_BLOCK_SIZE * 1) + 3] = 1; + bltmp[(AES_BLOCK_SIZE * 2) + 3] = 2; + return ctr_BCC_block(ctr, ctr->KX, bltmp, num_of_blk * AES_BLOCK_SIZE); } /* @@ -199,20 +195,20 @@ __owur static int ctr_df(RAND_DRBG_CTR *ctr, || !ctr_BCC_final(ctr)) return 0; /* Set up key K */ - if (!EVP_CipherInit_ex(ctr->ctx, ctr->cipher, NULL, ctr->KX, NULL, 1)) + if (!EVP_CipherInit_ex(ctr->ctx_ecb, NULL, NULL, ctr->KX, NULL, -1)) return 0; /* X follows key K */ - if (!EVP_CipherUpdate(ctr->ctx, ctr->KX, &outlen, ctr->KX + ctr->keylen, + if (!EVP_CipherUpdate(ctr->ctx_ecb, ctr->KX, &outlen, ctr->KX + ctr->keylen, AES_BLOCK_SIZE) || outlen != AES_BLOCK_SIZE) return 0; - if (!EVP_CipherUpdate(ctr->ctx, ctr->KX + 16, &outlen, ctr->KX, + if (!EVP_CipherUpdate(ctr->ctx_ecb, ctr->KX + 16, &outlen, ctr->KX, AES_BLOCK_SIZE) || outlen != AES_BLOCK_SIZE) return 0; if (ctr->keylen != 16) - if (!EVP_CipherUpdate(ctr->ctx, ctr->KX + 32, &outlen, ctr->KX + 16, - AES_BLOCK_SIZE) + if (!EVP_CipherUpdate(ctr->ctx_ecb, ctr->KX + 32, &outlen, + ctr->KX + 16, AES_BLOCK_SIZE) || outlen != AES_BLOCK_SIZE) return 0; return 1; @@ -231,31 +227,25 @@ __owur static int ctr_update(RAND_DRBG *drbg, { RAND_DRBG_CTR *ctr = &drbg->data.ctr; int outlen = AES_BLOCK_SIZE; + unsigned char V_tmp[48], out[48]; + unsigned char len; /* correct key is already set up. */ + memcpy(V_tmp, ctr->V, 16); inc_128(ctr); - if (!EVP_CipherUpdate(ctr->ctx, ctr->K, &outlen, ctr->V, AES_BLOCK_SIZE) - || outlen != AES_BLOCK_SIZE) - return 0; - - /* If keylen longer than 128 bits need extra encrypt */ - if (ctr->keylen != 16) { + memcpy(V_tmp + 16, ctr->V, 16); + if (ctr->keylen == 16) { + len = 32; + } else { inc_128(ctr); - if (!EVP_CipherUpdate(ctr->ctx, ctr->K+16, &outlen, ctr->V, - AES_BLOCK_SIZE) - || outlen != AES_BLOCK_SIZE) - return 0; + memcpy(V_tmp + 32, ctr->V, 16); + len = 48; } - inc_128(ctr); - if (!EVP_CipherUpdate(ctr->ctx, ctr->V, &outlen, ctr->V, AES_BLOCK_SIZE) - || outlen != AES_BLOCK_SIZE) + if (!EVP_CipherUpdate(ctr->ctx_ecb, out, &outlen, V_tmp, len) + || outlen != len) return 0; - - /* If 192 bit key part of V is on end of K */ - if (ctr->keylen == 24) { - memcpy(ctr->V + 8, ctr->V, 8); - memcpy(ctr->V, ctr->K + 24, 8); - } + memcpy(ctr->K, out, ctr->keylen); + memcpy(ctr->V, out + ctr->keylen, 16); if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) { /* If no input reuse existing derived value */ @@ -270,7 +260,8 @@ __owur static int ctr_update(RAND_DRBG *drbg, ctr_XOR(ctr, in2, in2len); } - if (!EVP_CipherInit_ex(ctr->ctx, ctr->cipher, NULL, ctr->K, NULL, 1)) + if (!EVP_CipherInit_ex(ctr->ctx_ecb, NULL, NULL, ctr->K, NULL, -1) + || !EVP_CipherInit_ex(ctr->ctx_ctr, NULL, NULL, ctr->K, NULL, -1)) return 0; return 1; } @@ -287,8 +278,10 @@ __owur static int drbg_ctr_instantiate(RAND_DRBG *drbg, memset(ctr->K, 0, sizeof(ctr->K)); memset(ctr->V, 0, sizeof(ctr->V)); - if (!EVP_CipherInit_ex(ctr->ctx, ctr->cipher, NULL, ctr->K, NULL, 1)) + if (!EVP_CipherInit_ex(ctr->ctx_ecb, NULL, NULL, ctr->K, NULL, -1)) return 0; + + inc_128(ctr); if (!ctr_update(drbg, entropy, entropylen, pers, perslen, nonce, noncelen)) return 0; return 1; @@ -298,20 +291,40 @@ __owur static int drbg_ctr_reseed(RAND_DRBG *drbg, const unsigned char *entropy, size_t entropylen, const unsigned char *adin, size_t adinlen) { + RAND_DRBG_CTR *ctr = &drbg->data.ctr; + if (entropy == NULL) return 0; + + inc_128(ctr); if (!ctr_update(drbg, entropy, entropylen, adin, adinlen, NULL, 0)) return 0; return 1; } +static void ctr96_inc(unsigned char *counter) +{ + u32 n = 12, c = 1; + + do { + --n; + c += counter[n]; + counter[n] = (u8)c; + c >>= 8; + } while (n); +} + __owur static int drbg_ctr_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen, const unsigned char *adin, size_t adinlen) { RAND_DRBG_CTR *ctr = &drbg->data.ctr; + unsigned int ctr32, blocks; + int outl, buflen; if (adin != NULL && adinlen != 0) { + inc_128(ctr); + if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0)) return 0; /* This means we reuse derived value */ @@ -323,28 +336,51 @@ __owur static int drbg_ctr_generate(RAND_DRBG *drbg, adinlen = 0; } - for ( ; ; ) { - int outl = AES_BLOCK_SIZE; + inc_128(ctr); + if (outlen == 0) { inc_128(ctr); - if (outlen < 16) { - /* Use K as temp space as it will be updated */ - if (!EVP_CipherUpdate(ctr->ctx, ctr->K, &outl, ctr->V, - AES_BLOCK_SIZE) - || outl != AES_BLOCK_SIZE) - return 0; - memcpy(out, ctr->K, outlen); - break; - } - if (!EVP_CipherUpdate(ctr->ctx, out, &outl, ctr->V, AES_BLOCK_SIZE) - || outl != AES_BLOCK_SIZE) + + if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0)) return 0; - out += 16; - outlen -= 16; - if (outlen == 0) - break; + return 1; } + memset(out, 0, outlen); + + do { + if (!EVP_CipherInit_ex(ctr->ctx_ctr, + NULL, NULL, NULL, ctr->V, -1)) + return 0; + + /*- + * outlen has type size_t while EVP_CipherUpdate takes an + * int argument and thus cannot be guaranteed to process more + * than 2^31-1 bytes at a time. We process such huge generate + * requests in 2^30 byte chunks, which is the greatest multiple + * of AES block size lower than or equal to 2^31-1. + */ + buflen = outlen > (1U << 30) ? (1U << 30) : outlen; + blocks = (buflen + 15) / 16; + + ctr32 = GETU32(ctr->V + 12) + blocks; + if (ctr32 < blocks) { + /* 32-bit counter overflow into V. */ + blocks -= ctr32; + buflen = blocks * 16; + ctr32 = 0; + ctr96_inc(ctr->V); + } + PUTU32(ctr->V + 12, ctr32); + + if (!EVP_CipherUpdate(ctr->ctx_ctr, out, &outl, out, buflen) + || outl != buflen) + return 0; + + out += buflen; + outlen -= buflen; + } while (outlen); + if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0)) return 0; return 1; @@ -352,9 +388,11 @@ __owur static int drbg_ctr_generate(RAND_DRBG *drbg, static int drbg_ctr_uninstantiate(RAND_DRBG *drbg) { - EVP_CIPHER_CTX_free(drbg->data.ctr.ctx); + EVP_CIPHER_CTX_free(drbg->data.ctr.ctx_ecb); + EVP_CIPHER_CTX_free(drbg->data.ctr.ctx_ctr); EVP_CIPHER_CTX_free(drbg->data.ctr.ctx_df); - EVP_CIPHER_free(drbg->data.ctr.cipher); + EVP_CIPHER_free(drbg->data.ctr.cipher_ecb); + EVP_CIPHER_free(drbg->data.ctr.cipher_ctr); OPENSSL_cleanse(&drbg->data.ctr, sizeof(drbg->data.ctr)); return 1; } @@ -370,7 +408,8 @@ int drbg_ctr_init(RAND_DRBG *drbg) { RAND_DRBG_CTR *ctr = &drbg->data.ctr; size_t keylen; - EVP_CIPHER *cipher = NULL; + EVP_CIPHER *cipher_ecb = NULL; + EVP_CIPHER *cipher_ctr = NULL; switch (drbg->type) { default: @@ -378,30 +417,41 @@ int drbg_ctr_init(RAND_DRBG *drbg) return 0; case NID_aes_128_ctr: keylen = 16; - cipher = EVP_CIPHER_fetch(drbg->libctx, "AES-128-ECB", ""); + cipher_ecb = EVP_CIPHER_fetch(drbg->libctx, "AES-128-ECB", ""); + cipher_ctr = EVP_CIPHER_fetch(drbg->libctx, "AES-128-CTR", ""); break; case NID_aes_192_ctr: keylen = 24; - cipher = EVP_CIPHER_fetch(drbg->libctx, "AES-192-ECB", ""); + cipher_ecb = EVP_CIPHER_fetch(drbg->libctx, "AES-192-ECB", ""); + cipher_ctr = EVP_CIPHER_fetch(drbg->libctx, "AES-192-CTR", ""); break; case NID_aes_256_ctr: keylen = 32; - cipher = EVP_CIPHER_fetch(drbg->libctx, "AES-256-ECB", ""); + cipher_ecb = EVP_CIPHER_fetch(drbg->libctx, "AES-256-ECB", ""); + cipher_ctr = EVP_CIPHER_fetch(drbg->libctx, "AES-256-CTR", ""); break; } - if (cipher == NULL) + if (cipher_ecb == NULL || cipher_ctr == NULL) return 0; - EVP_CIPHER_free(ctr->cipher); - ctr->cipher = cipher; - - drbg->meth = &drbg_ctr_meth; + EVP_CIPHER_free(ctr->cipher_ecb); + ctr->cipher_ecb = cipher_ecb; + EVP_CIPHER_free(ctr->cipher_ctr); + ctr->cipher_ctr = cipher_ctr; ctr->keylen = keylen; - if (ctr->ctx == NULL) - ctr->ctx = EVP_CIPHER_CTX_new(); - if (ctr->ctx == NULL) + if (ctr->ctx_ecb == NULL) + ctr->ctx_ecb = EVP_CIPHER_CTX_new(); + if (ctr->ctx_ctr == NULL) + ctr->ctx_ctr = EVP_CIPHER_CTX_new(); + if (ctr->ctx_ecb == NULL || ctr->ctx_ctr == NULL + || !EVP_CipherInit_ex(ctr->ctx_ecb, + ctr->cipher_ecb, NULL, NULL, NULL, 1) + || !EVP_CipherInit_ex(ctr->ctx_ctr, + ctr->cipher_ctr, NULL, NULL, NULL, 1)) return 0; + + drbg->meth = &drbg_ctr_meth; drbg->strength = keylen * 8; drbg->seedlen = keylen + 16; @@ -419,7 +469,8 @@ int drbg_ctr_init(RAND_DRBG *drbg) if (ctr->ctx_df == NULL) return 0; /* Set key schedule for df_key */ - if (!EVP_CipherInit_ex(ctr->ctx_df, ctr->cipher, NULL, df_key, NULL, 1)) + if (!EVP_CipherInit_ex(ctr->ctx_df, + ctr->cipher_ecb, NULL, df_key, NULL, 1)) return 0; drbg->min_entropylen = ctr->keylen; diff --git a/crypto/rand/rand_local.h b/crypto/rand/rand_local.h index ce168925..646c0c33 100644 --- a/crypto/rand/rand_local.h +++ b/crypto/rand/rand_local.h @@ -175,9 +175,11 @@ typedef struct rand_drbg_hmac_st { * The state of a DRBG AES-CTR. */ typedef struct rand_drbg_ctr_st { - EVP_CIPHER_CTX *ctx; + EVP_CIPHER_CTX *ctx_ecb; + EVP_CIPHER_CTX *ctx_ctr; EVP_CIPHER_CTX *ctx_df; - EVP_CIPHER *cipher; + EVP_CIPHER *cipher_ecb; + EVP_CIPHER *cipher_ctr; size_t keylen; unsigned char K[32]; unsigned char V[16]; diff --git a/crypto/rc2/build.info b/crypto/rc2/build.info index 47a3fd0d..b6d60d6e 100644 --- a/crypto/rc2/build.info +++ b/crypto/rc2/build.info @@ -1,3 +1,11 @@ LIBS=../../libcrypto -SOURCE[../../libcrypto]=\ - rc2_ecb.c rc2_skey.c rc2_cbc.c rc2cfb64.c rc2ofb64.c + +$ALL=rc2_ecb.c rc2_skey.c rc2_cbc.c rc2cfb64.c rc2ofb64.c + +SOURCE[../../libcrypto]=$ALL + +# When all deprecated symbols are removed, libcrypto doesn't export the +# rc2 functions, so we must include them directly in liblegacy.a +IF[{- $disabled{'deprecated-3.0'} -}] + SOURCE[../../providers/liblegacy.a]=$ALL +ENDIF diff --git a/crypto/rc4/build.info b/crypto/rc4/build.info index abc0c52d..c7f17ca5 100644 --- a/crypto/rc4/build.info +++ b/crypto/rc4/build.info @@ -19,6 +19,12 @@ ENDIF SOURCE[../../libcrypto]=$RC4ASM +# When all deprecated symbols are removed, libcrypto doesn't export the +# rc4 functions, so we must include them directly in liblegacy.a +IF[{- $disabled{'deprecated-3.0'} -}] + SOURCE[../../providers/liblegacy.a]=$RC4ASM +ENDIF + GENERATE[rc4-586.s]=asm/rc4-586.pl DEPEND[rc4-586.s]=../perlasm/x86asm.pl diff --git a/crypto/rc5/build.info b/crypto/rc5/build.info index c684d1ee..3e2def8a 100644 --- a/crypto/rc5/build.info +++ b/crypto/rc5/build.info @@ -12,8 +12,15 @@ IF[{- !$disabled{asm} -}] ENDIF ENDIF -SOURCE[../../libcrypto]=\ - rc5_skey.c rc5_ecb.c $RC5ASM rc5cfb64.c rc5ofb64.c +$ALL=rc5_skey.c rc5_ecb.c $RC5ASM rc5cfb64.c rc5ofb64.c + +SOURCE[../../libcrypto]=$ALL + +# When all deprecated symbols are removed, libcrypto doesn't export the +# rc5 functions, so we must include them directly in liblegacy.a +IF[{- $disabled{'deprecated-3.0'} -}] + SOURCE[../../providers/liblegacy.a]=$ALL +ENDIF GENERATE[rc5-586.s]=asm/rc5-586.pl DEPEND[rc5-586.s]=../perlasm/x86asm.pl ../perlasm/cbc.pl diff --git a/crypto/rsa/build.info b/crypto/rsa/build.info index ddb4e6fc..0c9e4668 100644 --- a/crypto/rsa/build.info +++ b/crypto/rsa/build.info @@ -1,8 +1,9 @@ LIBS=../../libcrypto -$COMMON=rsa_ossl.c rsa_gen.c rsa_lib.c rsa_sign.c rsa_aid.c rsa_pk1.c \ +$COMMON=rsa_ossl.c rsa_gen.c rsa_lib.c rsa_sign.c rsa_pk1.c \ rsa_none.c rsa_oaep.c rsa_chk.c rsa_pss.c rsa_x931.c rsa_crpt.c \ - rsa_x931g.c rsa_sp800_56b_gen.c rsa_sp800_56b_check.c + rsa_x931g.c rsa_sp800_56b_gen.c rsa_sp800_56b_check.c rsa_backend.c \ + rsa_mp_names.c SOURCE[../../libcrypto]=$COMMON\ rsa_saos.c rsa_err.c rsa_asn1.c rsa_depr.c rsa_ameth.c rsa_prn.c \ diff --git a/crypto/rsa/rsa_aid.c b/crypto/rsa/rsa_aid.c deleted file mode 100644 index 4b4d3a62..00000000 --- a/crypto/rsa/rsa_aid.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include - -#include -#include "crypto/rsa.h" - -#define ASN1_SEQUENCE 0x30 -#define ASN1_OID 0x06 - -/* - * -- RFC 2313 - * pkcs-1 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) US(840) rsadsi(113549) pkcs(1) 1 - * } - */ - -/* - * -- RFC 3279 - * md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 } - * md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 } - * sha1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 } - */ -#define ENCODE_ALGORITHMIDENTIFIER_PKCS1(name, n) \ - static const unsigned char algorithmidentifier_##name##_der[] = { \ - ASN1_SEQUENCE, 0x0b, \ - ASN1_OID, 0x09, 1 * 40 + 2, 134, 72, 134, 247, 13, 1, 1, n \ -} -#ifndef FIPS_MODE -ENCODE_ALGORITHMIDENTIFIER_PKCS1(md2, 2); -ENCODE_ALGORITHMIDENTIFIER_PKCS1(md5, 4); -#endif -ENCODE_ALGORITHMIDENTIFIER_PKCS1(sha1, 5); - -/* - * -- RFC 4055 - * sha224WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 14 } - * sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 } - * sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 } - * sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 } - */ -ENCODE_ALGORITHMIDENTIFIER_PKCS1(sha224, 14); -ENCODE_ALGORITHMIDENTIFIER_PKCS1(sha256, 11); -ENCODE_ALGORITHMIDENTIFIER_PKCS1(sha384, 12); -ENCODE_ALGORITHMIDENTIFIER_PKCS1(sha512, 13); - -/* - * -- https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration - * - * sigAlgs OBJECT IDENTIFIER ::= { 2 16 840 1 101 3 4 3 } - * - * id-rsassa-pkcs1-v1_5-with-sha3-224 ::= { sigAlgs 13 } - * id-rsassa-pkcs1-v1_5-with-sha3-256 ::= { sigAlgs 14 } - * id-rsassa-pkcs1-v1_5-with-sha3-384 ::= { sigAlgs 15 } - * id-rsassa-pkcs1-v1_5-with-sha3-512 ::= { sigAlgs 16 } - */ -#define ENCODE_ALGORITHMIDENTIFIER_SIGALGS(name, n) \ - static const unsigned char algorithmidentifier_##name##_der[] = { \ - ASN1_SEQUENCE, 0x0c, \ - ASN1_OID, 0x0a, 1 * 40 + 2, 16, 134, 72, 1, 101, 3, 4, 3, n \ -} -ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_224, 13); -ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_256, 14); -ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_384, 15); -ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_512, 16); - -#define MD_CASE(name) \ - case NID_##name: \ - *len = sizeof(algorithmidentifier_##name##_der); \ - return algorithmidentifier_##name##_der - -const unsigned char *rsa_algorithmidentifier_encoding(int md_nid, size_t *len) -{ - switch (md_nid) { -#ifndef FIPS_MODE - MD_CASE(md2); - MD_CASE(md5); -#endif - MD_CASE(sha1); - MD_CASE(sha224); - MD_CASE(sha256); - MD_CASE(sha384); - MD_CASE(sha512); - MD_CASE(sha3_224); - MD_CASE(sha3_256); - MD_CASE(sha3_384); - MD_CASE(sha3_512); - default: - return NULL; - } -} diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c index 8a94a846..291c3a22 100644 --- a/crypto/rsa/rsa_ameth.c +++ b/crypto/rsa/rsa_ameth.c @@ -14,7 +14,7 @@ #include #include #include -#include "internal/param_build.h" +#include #include "crypto/asn1.h" #include "crypto/evp.h" #include "crypto/rsa.h" @@ -1075,28 +1075,38 @@ static size_t rsa_pkey_dirty_cnt(const EVP_PKEY *pkey) DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM) static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata, - EVP_KEYMGMT *to_keymgmt) + EVP_KEYMGMT *to_keymgmt, OPENSSL_CTX *libctx, + const char *propq) { RSA *rsa = from->pkey.rsa; - OSSL_PARAM_BLD tmpl; + OSSL_PARAM_BLD *tmpl = OSSL_PARAM_BLD_new(); const BIGNUM *n = RSA_get0_n(rsa), *e = RSA_get0_e(rsa); const BIGNUM *d = RSA_get0_d(rsa); STACK_OF(BIGNUM_const) *primes = NULL, *exps = NULL, *coeffs = NULL; int numprimes = 0, numexps = 0, numcoeffs = 0; OSSL_PARAM *params = NULL; + int selection = 0; int rv = 0; + if (tmpl == NULL) + return 0; + /* + * If the RSA method is foreign, then we can't be sure of anything, and + * can therefore not export or pretend to export. + */ + if (RSA_get_method(rsa) != RSA_PKCS1_OpenSSL()) + goto err; + /* Public parameters must always be present */ if (n == NULL || e == NULL) goto err; - ossl_param_bld_init(&tmpl); - /* |e| and |n| are always present */ - if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_E, e)) + if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_E, e)) goto err; - if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_N, n)) + if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_N, n)) goto err; + selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY; if (d != NULL) { int i; @@ -1123,55 +1133,65 @@ static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata, && (numprimes < 2 || numexps < 2 || numcoeffs < 1)) goto err; - /* assert that an OSSL_PARAM_BLD has enough space. */ - if (!ossl_assert(/* n, e */ 2 + /* d */ 1 + /* numprimes */ 1 - + numprimes + numexps + numcoeffs - <= OSSL_PARAM_BLD_MAX)) + if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_D, d)) goto err; + selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY; - if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_D, d)) - goto err; - - for (i = 0; i < numprimes; i++) { + for (i = 0; i < numprimes && rsa_mp_factor_names[i] != NULL; i++) { const BIGNUM *num = sk_BIGNUM_const_value(primes, i); - if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_FACTOR, - num)) + if (!OSSL_PARAM_BLD_push_BN(tmpl, rsa_mp_factor_names[i], num)) goto err; } - for (i = 0; i < numexps; i++) { + for (i = 0; i < numexps && rsa_mp_exp_names[i] != NULL; i++) { const BIGNUM *num = sk_BIGNUM_const_value(exps, i); - if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_EXPONENT, - num)) + if (!OSSL_PARAM_BLD_push_BN(tmpl, rsa_mp_exp_names[i], num)) goto err; } - for (i = 0; i < numcoeffs; i++) { + for (i = 0; i < numcoeffs && rsa_mp_coeff_names[i] != NULL; i++) { const BIGNUM *num = sk_BIGNUM_const_value(coeffs, i); - if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_COEFFICIENT, - num)) + if (!OSSL_PARAM_BLD_push_BN(tmpl, rsa_mp_coeff_names[i], num)) goto err; } } - if ((params = ossl_param_bld_to_param(&tmpl)) == NULL) + if ((params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) goto err; /* We export, the provider imports */ - rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL, - params); + rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params); err: sk_BIGNUM_const_free(primes); sk_BIGNUM_const_free(exps); sk_BIGNUM_const_free(coeffs); - ossl_param_bld_free(params); + OSSL_PARAM_BLD_free_params(params); + OSSL_PARAM_BLD_free(tmpl); return rv; } +static int rsa_pkey_import_from(const OSSL_PARAM params[], void *key) +{ + EVP_PKEY *pkey = key; + RSA *rsa = RSA_new(); + + if (rsa == NULL) { + ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!rsa_fromdata(rsa, params) + || !EVP_PKEY_assign_RSA(pkey, rsa)) { + RSA_free(rsa); + return 0; + } + return 1; +} + const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = { { EVP_PKEY_RSA, @@ -1210,7 +1230,8 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = { 0, 0, 0, 0, rsa_pkey_dirty_cnt, - rsa_pkey_export_to + rsa_pkey_export_to, + rsa_pkey_import_from }, { @@ -1255,5 +1276,6 @@ const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth = { 0, 0, 0, 0, rsa_pkey_dirty_cnt, - rsa_pkey_export_to + rsa_pkey_export_to, + rsa_pkey_import_from }; diff --git a/crypto/rsa/rsa_backend.c b/crypto/rsa/rsa_backend.c new file mode 100644 index 00000000..57a539c0 --- /dev/null +++ b/crypto/rsa/rsa_backend.c @@ -0,0 +1,99 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "crypto/rsa.h" + +/* + * The intention with the "backend" source file is to offer backend support + * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider + * implementations alike. + */ + +DEFINE_STACK_OF(BIGNUM) + +static int collect_numbers(STACK_OF(BIGNUM) *numbers, + const OSSL_PARAM params[], const char *names[]) +{ + const OSSL_PARAM *p = NULL; + int i; + + if (numbers == NULL) + return 0; + + for (i = 0; names[i] != NULL; i++){ + p = OSSL_PARAM_locate_const(params, names[i]); + if (p != NULL) { + BIGNUM *tmp = NULL; + + if (!OSSL_PARAM_get_BN(p, &tmp) + || sk_BIGNUM_push(numbers, tmp) == 0) + return 0; + } + } + + return 1; +} + +int rsa_fromdata(RSA *rsa, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *param_n, *param_e, *param_d; + BIGNUM *n = NULL, *e = NULL, *d = NULL; + STACK_OF(BIGNUM) *factors = NULL, *exps = NULL, *coeffs = NULL; + int is_private = 0; + + if (rsa == NULL) + return 0; + + param_n = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_N); + param_e = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E); + param_d = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D); + + if ((param_n != NULL && !OSSL_PARAM_get_BN(param_n, &n)) + || (param_e != NULL && !OSSL_PARAM_get_BN(param_e, &e)) + || (param_d != NULL && !OSSL_PARAM_get_BN(param_d, &d))) + goto err; + + is_private = (d != NULL); + + if (!RSA_set0_key(rsa, n, e, d)) + goto err; + n = e = d = NULL; + + if (is_private) { + if (!collect_numbers(factors = sk_BIGNUM_new_null(), params, + rsa_mp_factor_names) + || !collect_numbers(exps = sk_BIGNUM_new_null(), params, + rsa_mp_exp_names) + || !collect_numbers(coeffs = sk_BIGNUM_new_null(), params, + rsa_mp_coeff_names)) + goto err; + + /* It's ok if this private key just has n, e and d */ + if (sk_BIGNUM_num(factors) != 0 + && !rsa_set0_all_params(rsa, factors, exps, coeffs)) + goto err; + } + + sk_BIGNUM_free(factors); + sk_BIGNUM_free(exps); + sk_BIGNUM_free(coeffs); + return 1; + + err: + BN_free(n); + BN_free(e); + BN_free(d); + sk_BIGNUM_pop_free(factors, BN_free); + sk_BIGNUM_pop_free(exps, BN_free); + sk_BIGNUM_pop_free(coeffs, BN_free); + return 0; +} + diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c index b5003d3b..51fd3c5c 100644 --- a/crypto/rsa/rsa_lib.c +++ b/crypto/rsa/rsa_lib.c @@ -14,6 +14,7 @@ #include #include "internal/cryptlib.h" #include "internal/refcount.h" +#include "openssl/param_build.h" #include "crypto/bn.h" #include "crypto/evp.h" #include "crypto/rsa.h" @@ -628,13 +629,10 @@ const BIGNUM *RSA_get0_iqmp(const RSA *r) return r->iqmp; } -/* TODO(3.0): Temporary until we move PSS support into the FIPS module */ -#ifndef FIPS_MODE const RSA_PSS_PARAMS *RSA_get0_pss_params(const RSA *r) { return r->pss; } -#endif void RSA_clear_flags(RSA *r, int flags) { @@ -1260,4 +1258,98 @@ int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *saltlen) return 1; } + +int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int bits) +{ + OSSL_PARAM params[2], *p = params; + size_t bits2 = bits; + + if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) { + ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); + /* Uses the same return values as EVP_PKEY_CTX_ctrl */ + return -2; + } + + /* If key type not RSA return error */ + if (ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_RSA) + return -1; + + /* TODO(3.0): Remove this eventually when no more legacy */ + if (ctx->op.keymgmt.genctx == NULL) + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN, + EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL); + + *p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_RSA_BITS, &bits2); + *p++ = OSSL_PARAM_construct_end(); + + if (!EVP_PKEY_CTX_set_params(ctx, params)) + return 0; + + return 1; +} + +int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp) +{ + OSSL_PARAM_BLD *tmpl; + OSSL_PARAM *params; + int ret; + + if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) { + ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); + /* Uses the same return values as EVP_PKEY_CTX_ctrl */ + return -2; + } + + /* If key type not RSA return error */ + if (ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_RSA) + return -1; + + /* TODO(3.0): Remove this eventually when no more legacy */ + if (ctx->op.keymgmt.genctx == NULL) + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN, + EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, pubexp); + + if ((tmpl = OSSL_PARAM_BLD_new()) == NULL) + return 0; + if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_E, pubexp) + || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) { + OSSL_PARAM_BLD_free(tmpl); + return 0; + } + OSSL_PARAM_BLD_free(tmpl); + + ret = EVP_PKEY_CTX_set_params(ctx, params); + OSSL_PARAM_BLD_free_params(params); + return ret; +} + +int EVP_PKEY_CTX_set_rsa_keygen_primes(EVP_PKEY_CTX *ctx, int primes) +{ + OSSL_PARAM params[2], *p = params; + size_t primes2 = primes; + + if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) { + ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); + /* Uses the same return values as EVP_PKEY_CTX_ctrl */ + return -2; + } + + /* If key type not RSA return error */ + if (ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_RSA) + return -1; + + /* TODO(3.0): Remove this eventually when no more legacy */ + if (ctx->op.keymgmt.genctx == NULL) + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN, + EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES, primes, + NULL); + + *p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_RSA_PRIMES, &primes2); + *p++ = OSSL_PARAM_construct_end(); + + if (!EVP_PKEY_CTX_set_params(ctx, params)) + return 0; + + return 1; +} #endif diff --git a/crypto/rsa/rsa_local.h b/crypto/rsa/rsa_local.h index ac885620..423492b9 100644 --- a/crypto/rsa/rsa_local.h +++ b/crypto/rsa/rsa_local.h @@ -29,13 +29,15 @@ DECLARE_ASN1_ITEM(RSA_PRIME_INFO) DEFINE_STACK_OF(RSA_PRIME_INFO) struct rsa_st { - OPENSSL_CTX *libctx; - /* - * The first parameter is used to pickup errors where this is passed - * instead of an EVP_PKEY, it is set to 0 + * #legacy + * The first field is used to pickup errors where this is passed + * instead of an EVP_PKEY. It is always zero. + * THIS MUST REMAIN THE FIRST FIELD. */ - int pad; + int dummy_zero; + + OPENSSL_CTX *libctx; int32_t version; const RSA_METHOD *meth; /* functional reference if 'meth' is ENGINE-provided */ @@ -48,13 +50,12 @@ struct rsa_st { BIGNUM *dmp1; BIGNUM *dmq1; BIGNUM *iqmp; - /* TODO(3.0): Support PSS in FIPS_MODE */ + /* If a PSS only key this contains the parameter restrictions */ + RSA_PSS_PARAMS *pss; #ifndef FIPS_MODE /* for multi-prime RSA, defined in RFC 8017 */ STACK_OF(RSA_PRIME_INFO) *prime_infos; - /* If a PSS only key this contains the parameter restrictions */ - RSA_PSS_PARAMS *pss; - /* be careful using this if the RSA structure is shared */ + /* Be careful using this if the RSA structure is shared */ CRYPTO_EX_DATA ex_data; #endif CRYPTO_REF_COUNT references; @@ -168,4 +169,19 @@ int rsa_fips186_4_gen_prob_primes(RSA *rsa, BIGNUM *p1, BIGNUM *p2, const BIGNUM *Xq2, int nbits, const BIGNUM *e, BN_CTX *ctx, BN_GENCB *cb); +int rsa_padding_add_SSLv23_with_libctx(OPENSSL_CTX *libctx, unsigned char *to, + int tlen, const unsigned char *from, + int flen); +int rsa_padding_add_PKCS1_type_2_with_libctx(OPENSSL_CTX *libctx, + unsigned char *to, int tlen, + const unsigned char *from, + int flen); +int rsa_padding_add_PKCS1_OAEP_mgf1_with_libctx(OPENSSL_CTX *libctx, + unsigned char *to, int tlen, + const unsigned char *from, + int flen, + const unsigned char *param, + int plen, const EVP_MD *md, + const EVP_MD *mgf1md); + #endif /* OSSL_CRYPTO_RSA_LOCAL_H */ diff --git a/crypto/rsa/rsa_mp_names.c b/crypto/rsa/rsa_mp_names.c new file mode 100644 index 00000000..e69321a4 --- /dev/null +++ b/crypto/rsa/rsa_mp_names.c @@ -0,0 +1,76 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "crypto/rsa.h" + +/* + * The following tables are constants used during RSA parameter building + * operations. It is easier to point to one of these fixed strings than have + * to dynamically add and generate the names on the fly. + */ + +/* + * A fixed table of names for the RSA prime factors starting with + * P,Q and up to 8 additional primes. + */ +const char *rsa_mp_factor_names[] = { + OSSL_PKEY_PARAM_RSA_FACTOR1, + OSSL_PKEY_PARAM_RSA_FACTOR2, +#ifndef FIPS_MODE + OSSL_PKEY_PARAM_RSA_FACTOR3, + OSSL_PKEY_PARAM_RSA_FACTOR4, + OSSL_PKEY_PARAM_RSA_FACTOR5, + OSSL_PKEY_PARAM_RSA_FACTOR6, + OSSL_PKEY_PARAM_RSA_FACTOR7, + OSSL_PKEY_PARAM_RSA_FACTOR8, + OSSL_PKEY_PARAM_RSA_FACTOR9, + OSSL_PKEY_PARAM_RSA_FACTOR10, +#endif + NULL +}; + +/* + * A fixed table of names for the RSA exponents starting with + * DP,DQ and up to 8 additional exponents. + */ +const char *rsa_mp_exp_names[] = { + OSSL_PKEY_PARAM_RSA_EXPONENT1, + OSSL_PKEY_PARAM_RSA_EXPONENT2, +#ifndef FIPS_MODE + OSSL_PKEY_PARAM_RSA_EXPONENT3, + OSSL_PKEY_PARAM_RSA_EXPONENT4, + OSSL_PKEY_PARAM_RSA_EXPONENT5, + OSSL_PKEY_PARAM_RSA_EXPONENT6, + OSSL_PKEY_PARAM_RSA_EXPONENT7, + OSSL_PKEY_PARAM_RSA_EXPONENT8, + OSSL_PKEY_PARAM_RSA_EXPONENT9, + OSSL_PKEY_PARAM_RSA_EXPONENT10, +#endif + NULL +}; + +/* + * A fixed table of names for the RSA coefficients starting with + * QINV and up to 8 additional exponents. + */ +const char *rsa_mp_coeff_names[] = { + OSSL_PKEY_PARAM_RSA_COEFFICIENT1, + OSSL_PKEY_PARAM_RSA_COEFFICIENT2, +#ifndef FIPS_MODE + OSSL_PKEY_PARAM_RSA_COEFFICIENT3, + OSSL_PKEY_PARAM_RSA_COEFFICIENT4, + OSSL_PKEY_PARAM_RSA_COEFFICIENT5, + OSSL_PKEY_PARAM_RSA_COEFFICIENT6, + OSSL_PKEY_PARAM_RSA_COEFFICIENT7, + OSSL_PKEY_PARAM_RSA_COEFFICIENT8, + OSSL_PKEY_PARAM_RSA_COEFFICIENT9, +#endif + NULL +}; diff --git a/crypto/rsa/rsa_oaep.c b/crypto/rsa/rsa_oaep.c index d1150f09..a0af7411 100644 --- a/crypto/rsa/rsa_oaep.c +++ b/crypto/rsa/rsa_oaep.c @@ -34,8 +34,9 @@ int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen, const unsigned char *from, int flen, const unsigned char *param, int plen) { - return RSA_padding_add_PKCS1_OAEP_mgf1(to, tlen, from, flen, - param, plen, NULL, NULL); + return rsa_padding_add_PKCS1_OAEP_mgf1_with_libctx(NULL, to, tlen, from, + flen, param, plen, NULL, + NULL); } /* @@ -45,10 +46,13 @@ int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen, * Step numbers are included here but not in the constant time inverse below * to avoid complicating an already difficult enough function. */ -int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, - const unsigned char *from, int flen, - const unsigned char *param, int plen, - const EVP_MD *md, const EVP_MD *mgf1md) +int rsa_padding_add_PKCS1_OAEP_mgf1_with_libctx(OPENSSL_CTX *libctx, + unsigned char *to, int tlen, + const unsigned char *from, + int flen, + const unsigned char *param, + int plen, const EVP_MD *md, + const EVP_MD *mgf1md) { int rv = 0; int i, emlen = tlen - 1; @@ -61,8 +65,7 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, if (md == NULL) md = EVP_sha1(); #else - RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, - ERR_R_PASSED_NULL_PARAMETER); + RSAerr(0, ERR_R_PASSED_NULL_PARAMETER); return 0; #endif if (mgf1md == NULL) @@ -72,14 +75,12 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, /* step 2b: check KLen > nLen - 2 HLen - 2 */ if (flen > emlen - 2 * mdlen - 1) { - RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, - RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + RSAerr(0, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); return 0; } if (emlen < 2 * mdlen + 1) { - RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, - RSA_R_KEY_SIZE_TOO_SMALL); + RSAerr(0, RSA_R_KEY_SIZE_TOO_SMALL); return 0; } @@ -97,13 +98,13 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, db[emlen - flen - mdlen - 1] = 0x01; memcpy(db + emlen - flen - mdlen, from, (unsigned int)flen); /* step 3d: generate random byte string */ - if (RAND_bytes(seed, mdlen) <= 0) + if (RAND_bytes_ex(libctx, seed, mdlen) <= 0) goto err; dbmask_len = emlen - mdlen; dbmask = OPENSSL_malloc(dbmask_len); if (dbmask == NULL) { - RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE); + RSAerr(0, ERR_R_MALLOC_FAILURE); goto err; } @@ -128,6 +129,16 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, return rv; } +int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, + const unsigned char *from, int flen, + const unsigned char *param, int plen, + const EVP_MD *md, const EVP_MD *mgf1md) +{ + return rsa_padding_add_PKCS1_OAEP_mgf1_with_libctx(NULL, to, tlen, from, + flen, param, plen, md, + mgf1md); +} + int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, const unsigned char *from, int flen, int num, const unsigned char *param, int plen) diff --git a/crypto/rsa/rsa_ossl.c b/crypto/rsa/rsa_ossl.c index 6332a5a4..7746f6d9 100644 --- a/crypto/rsa/rsa_ossl.c +++ b/crypto/rsa/rsa_ossl.c @@ -105,14 +105,18 @@ static int rsa_ossl_public_encrypt(int flen, const unsigned char *from, switch (padding) { case RSA_PKCS1_PADDING: - i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen); + i = rsa_padding_add_PKCS1_type_2_with_libctx(rsa->libctx, buf, num, + from, flen); break; case RSA_PKCS1_OAEP_PADDING: - i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0); + i = rsa_padding_add_PKCS1_OAEP_mgf1_with_libctx(rsa->libctx, buf, num, + from, flen, NULL, 0, + NULL, NULL); break; #ifndef FIPS_MODE case RSA_SSLV23_PADDING: - i = RSA_padding_add_SSLv23(buf, num, from, flen); + i = rsa_padding_add_SSLv23_with_libctx(rsa->libctx, buf, num, from, + flen); break; #endif case RSA_NO_PADDING: diff --git a/crypto/rsa/rsa_pk1.c b/crypto/rsa/rsa_pk1.c index eedc558e..c6bbf2dc 100644 --- a/crypto/rsa/rsa_pk1.c +++ b/crypto/rsa/rsa_pk1.c @@ -17,6 +17,7 @@ #include #include "internal/cryptlib.h" #include "crypto/rsa.h" +#include "rsa_local.h" int RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen, const unsigned char *from, int flen) @@ -117,15 +118,16 @@ int RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen, return j; } -int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen, - const unsigned char *from, int flen) +int rsa_padding_add_PKCS1_type_2_with_libctx(OPENSSL_CTX *libctx, + unsigned char *to, int tlen, + const unsigned char *from, + int flen) { int i, j; unsigned char *p; if (flen > (tlen - RSA_PKCS1_PADDING_SIZE)) { - RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2, - RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + RSAerr(0, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); return 0; } @@ -137,12 +139,12 @@ int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen, /* pad out with non-zero random data */ j = tlen - 3 - flen; - if (RAND_bytes(p, j) <= 0) + if (RAND_bytes_ex(libctx, p, j) <= 0) return 0; for (i = 0; i < j; i++) { if (*p == '\0') do { - if (RAND_bytes(p, 1) <= 0) + if (RAND_bytes_ex(libctx, p, 1) <= 0) return 0; } while (*p == '\0'); p++; @@ -154,6 +156,12 @@ int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen, return 1; } +int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen, + const unsigned char *from, int flen) +{ + return rsa_padding_add_PKCS1_type_2_with_libctx(NULL, to, tlen, from, flen); +} + int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen, const unsigned char *from, int flen, int num) @@ -285,9 +293,10 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen, * decrypted data will be randomly generated (as per * https://tools.ietf.org/html/rfc5246#section-7.4.7.1). */ -int rsa_padding_check_PKCS1_type_2_TLS(unsigned char *to, size_t tlen, - const unsigned char *from, size_t flen, - int client_version, int alt_version) +int rsa_padding_check_PKCS1_type_2_TLS(OPENSSL_CTX *libctx, unsigned char *to, + size_t tlen, const unsigned char *from, + size_t flen, int client_version, + int alt_version) { unsigned int i, good, version_good; unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH]; @@ -306,8 +315,8 @@ int rsa_padding_check_PKCS1_type_2_TLS(unsigned char *to, size_t tlen, * Generate a random premaster secret to use in the event that we fail * to decrypt. */ - if (RAND_priv_bytes(rand_premaster_secret, - sizeof(rand_premaster_secret)) <= 0) { + if (RAND_priv_bytes_ex(libctx, rand_premaster_secret, + sizeof(rand_premaster_secret)) <= 0) { ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); return -1; } diff --git a/crypto/rsa/rsa_pss.c b/crypto/rsa/rsa_pss.c index 15014ef4..bd82faf5 100644 --- a/crypto/rsa/rsa_pss.c +++ b/crypto/rsa/rsa_pss.c @@ -200,7 +200,7 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM, ERR_R_MALLOC_FAILURE); goto err; } - if (RAND_bytes(salt, sLen) <= 0) + if (RAND_bytes_ex(rsa->libctx, salt, sLen) <= 0) goto err; } maskedDBLen = emLen - hLen - 1; diff --git a/crypto/rsa/rsa_sign.c b/crypto/rsa/rsa_sign.c index 5e2fe633..3d89a8db 100644 --- a/crypto/rsa/rsa_sign.c +++ b/crypto/rsa/rsa_sign.c @@ -180,6 +180,47 @@ const unsigned char *rsa_digestinfo_encoding(int md_nid, size_t *len) } } +#define MD_NID_CASE(name, sz) \ + case NID_##name: \ + return sz; + +static int digest_sz_from_nid(int nid) +{ + switch (nid) { +#ifndef FIPS_MODE +# ifndef OPENSSL_NO_MDC2 + MD_NID_CASE(mdc2, MDC2_DIGEST_LENGTH) +# endif +# ifndef OPENSSL_NO_MD2 + MD_NID_CASE(md2, MD2_DIGEST_LENGTH) +# endif +# ifndef OPENSSL_NO_MD4 + MD_NID_CASE(md4, MD4_DIGEST_LENGTH) +# endif +# ifndef OPENSSL_NO_MD5 + MD_NID_CASE(md5, MD5_DIGEST_LENGTH) +# endif +# ifndef OPENSSL_NO_RMD160 + MD_NID_CASE(ripemd160, RIPEMD160_DIGEST_LENGTH) +# endif +#endif /* FIPS_MODE */ + MD_NID_CASE(sha1, SHA_DIGEST_LENGTH) + MD_NID_CASE(sha224, SHA224_DIGEST_LENGTH) + MD_NID_CASE(sha256, SHA256_DIGEST_LENGTH) + MD_NID_CASE(sha384, SHA384_DIGEST_LENGTH) + MD_NID_CASE(sha512, SHA512_DIGEST_LENGTH) + MD_NID_CASE(sha512_224, SHA224_DIGEST_LENGTH) + MD_NID_CASE(sha512_256, SHA256_DIGEST_LENGTH) + MD_NID_CASE(sha3_224, SHA224_DIGEST_LENGTH) + MD_NID_CASE(sha3_256, SHA256_DIGEST_LENGTH) + MD_NID_CASE(sha3_384, SHA384_DIGEST_LENGTH) + MD_NID_CASE(sha3_512, SHA512_DIGEST_LENGTH) + default: + return 0; + } +} + + /* Size of an SSL signature: MD5+SHA1 */ #define SSL_SIG_LENGTH 36 @@ -231,8 +272,10 @@ int RSA_sign(int type, const unsigned char *m, unsigned int m_len, unsigned char *tmps = NULL; const unsigned char *encoded = NULL; +#ifndef FIPS_MODE if (rsa->meth->rsa_sign != NULL) return rsa->meth->rsa_sign(type, m, m_len, sigret, siglen, rsa); +#endif /* FIPS_MODE */ /* Compute the encoded digest. */ if (type == NID_md5_sha1) { @@ -305,6 +348,7 @@ int int_rsa_verify(int type, const unsigned char *m, unsigned int m_len, goto err; decrypt_len = len; +#ifndef FIPS_MODE if (type == NID_md5_sha1) { /* * NID_md5_sha1 corresponds to the MD5/SHA1 combination in TLS 1.1 and @@ -350,20 +394,17 @@ int int_rsa_verify(int type, const unsigned char *m, unsigned int m_len, goto err; } } - } else { + } else +#endif /* FIPS_MODE */ + { /* * If recovering the digest, extract a digest-sized output from the end * of |decrypt_buf| for |encode_pkcs1|, then compare the decryption * output as in a standard verification. */ if (rm != NULL) { - const EVP_MD *md = EVP_get_digestbynid(type); - if (md == NULL) { - RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_UNKNOWN_ALGORITHM_TYPE); - goto err; - } + len = digest_sz_from_nid(type); - len = EVP_MD_size(md); if (len <= 0) goto err; m_len = (unsigned int)len; diff --git a/crypto/rsa/rsa_ssl.c b/crypto/rsa/rsa_ssl.c index 99e54188..49005a54 100644 --- a/crypto/rsa/rsa_ssl.c +++ b/crypto/rsa/rsa_ssl.c @@ -13,16 +13,17 @@ #include #include #include "internal/constant_time.h" +#include "rsa_local.h" -int RSA_padding_add_SSLv23(unsigned char *to, int tlen, - const unsigned char *from, int flen) +int rsa_padding_add_SSLv23_with_libctx(OPENSSL_CTX *libctx, unsigned char *to, + int tlen, const unsigned char *from, + int flen) { int i, j; unsigned char *p; if (flen > (tlen - RSA_PKCS1_PADDING_SIZE)) { - RSAerr(RSA_F_RSA_PADDING_ADD_SSLV23, - RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + RSAerr(0, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); return 0; } @@ -34,12 +35,12 @@ int RSA_padding_add_SSLv23(unsigned char *to, int tlen, /* pad out with non-zero random data */ j = tlen - 3 - 8 - flen; - if (RAND_bytes(p, j) <= 0) + if (RAND_bytes_ex(libctx, p, j) <= 0) return 0; for (i = 0; i < j; i++) { if (*p == '\0') do { - if (RAND_bytes(p, 1) <= 0) + if (RAND_bytes_ex(libctx, p, 1) <= 0) return 0; } while (*p == '\0'); p++; @@ -53,6 +54,12 @@ int RSA_padding_add_SSLv23(unsigned char *to, int tlen, return 1; } +int RSA_padding_add_SSLv23(unsigned char *to, int tlen, + const unsigned char *from, int flen) +{ + return rsa_padding_add_SSLv23_with_libctx(NULL, to, tlen, from, flen); +} + /* * Copy of RSA_padding_check_PKCS1_type_2 with a twist that rejects padding * if nul delimiter is not preceded by 8 consecutive 0x03 bytes. It also diff --git a/crypto/seed/build.info b/crypto/seed/build.info index abdcbcaa..5336f039 100644 --- a/crypto/seed/build.info +++ b/crypto/seed/build.info @@ -1,2 +1,10 @@ LIBS=../../libcrypto -SOURCE[../../libcrypto]=seed.c seed_ecb.c seed_cbc.c seed_cfb.c seed_ofb.c +$ALL=seed.c seed_ecb.c seed_cbc.c seed_cfb.c seed_ofb.c + +SOURCE[../../libcrypto]=$ALL + +# When all deprecated symbols are removed, libcrypto doesn't export the +# seed functions, so we must include them directly in liblegacy.a +IF[{- $disabled{'deprecated-3.0'} -}] + SOURCE[../../providers/liblegacy.a]=$ALL +ENDIF diff --git a/crypto/serializer/serializer_pkey.c b/crypto/serializer/serializer_pkey.c index 1b6df1da..4b1bf5c3 100644 --- a/crypto/serializer/serializer_pkey.c +++ b/crypto/serializer/serializer_pkey.c @@ -121,13 +121,13 @@ static void select_serializer(const char *name, void *data) return; if ((s = OSSL_SERIALIZER_fetch(d->libctx, name, d->propquery)) != NULL) { - if (d->first == NULL && s->serialize_data != NULL) { - d->first = s; - } else if (OSSL_SERIALIZER_provider(s) == d->desired_provider - && s->serialize_object != NULL) { + if (OSSL_SERIALIZER_provider(s) == d->desired_provider + && s->serialize_object != NULL) { OSSL_SERIALIZER_free(d->first); d->first = NULL; d->desired = s; + } else if (d->first == NULL && s->serialize_data != NULL) { + d->first = s; } else { OSSL_SERIALIZER_free(s); } @@ -338,12 +338,14 @@ OSSL_SERIALIZER_CTX *OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(const EVP_PKEY *pkey, OSSL_SERIALIZER_free(sel_data.first); OSSL_SERIALIZER_free(sel_data.desired); - current_props = - ossl_parse_property(libctx, OSSL_SERIALIZER_properties(ser)); - if (ossl_property_match_count(check, current_props) > 0) - selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS; + if (ser != NULL) { + current_props = + ossl_parse_property(libctx, OSSL_SERIALIZER_properties(ser)); + if (ossl_property_match_count(check, current_props) > 0) + selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS; + ossl_property_free(current_props); + } - ossl_property_free(current_props); ossl_property_free(check); } diff --git a/crypto/sm2/sm2_pmeth.c b/crypto/sm2/sm2_pmeth.c index c3ba9280..9830fb82 100644 --- a/crypto/sm2/sm2_pmeth.c +++ b/crypto/sm2/sm2_pmeth.c @@ -26,7 +26,7 @@ typedef struct { /* message digest */ const EVP_MD *md; - /* Distinguishing Identifier, ISO/IEC 15946-3 */ + /* Distinguishing Identifier, ISO/IEC 15946-3, FIPS 196 */ uint8_t *id; size_t id_len; /* id_set indicates if the 'id' field is set (1) or not (0) */ @@ -247,14 +247,10 @@ static int pkey_sm2_ctrl_str(EVP_PKEY_CTX *ctx, else return -2; return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc); - } else if (strcmp(type, "sm2_id") == 0) { + } else if (strcmp(type, "distid") == 0) { return pkey_sm2_ctrl(ctx, EVP_PKEY_CTRL_SET1_ID, (int)strlen(value), (void *)value); - } else if (strcmp(type, "sm2_hex_id") == 0) { - /* - * TODO(3.0): reconsider the name "sm2_hex_id", OR change - * OSSL_PARAM_allocate_from_text() to handle infix "_hex_" - */ + } else if (strcmp(type, "hexdistid") == 0) { hex_id = OPENSSL_hexstr2buf((const char *)value, &hex_len); if (hex_id == NULL) { SM2err(SM2_F_PKEY_SM2_CTRL_STR, ERR_R_PASSED_INVALID_ARGUMENT); diff --git a/crypto/srp/srp_lib.c b/crypto/srp/srp_lib.c index 99511954..063f966f 100644 --- a/crypto/srp/srp_lib.c +++ b/crypto/srp/srp_lib.c @@ -20,39 +20,53 @@ /* calculate = SHA1(PAD(x) || PAD(y)) */ -static BIGNUM *srp_Calc_xy(const BIGNUM *x, const BIGNUM *y, const BIGNUM *N) +static BIGNUM *srp_Calc_xy(const BIGNUM *x, const BIGNUM *y, const BIGNUM *N, + OPENSSL_CTX *libctx, const char *propq) { unsigned char digest[SHA_DIGEST_LENGTH]; unsigned char *tmp = NULL; int numN = BN_num_bytes(N); BIGNUM *res = NULL; + EVP_MD *sha1 = EVP_MD_fetch(libctx, "SHA1", propq); + + if (sha1 == NULL) + return NULL; if (x != N && BN_ucmp(x, N) >= 0) - return NULL; + goto err; if (y != N && BN_ucmp(y, N) >= 0) - return NULL; + goto err; if ((tmp = OPENSSL_malloc(numN * 2)) == NULL) goto err; if (BN_bn2binpad(x, tmp, numN) < 0 || BN_bn2binpad(y, tmp + numN, numN) < 0 - || !EVP_Digest(tmp, numN * 2, digest, NULL, EVP_sha1(), NULL)) + || !EVP_Digest(tmp, numN * 2, digest, NULL, sha1, NULL)) goto err; res = BN_bin2bn(digest, sizeof(digest), NULL); err: + EVP_MD_free(sha1); OPENSSL_free(tmp); return res; } -static BIGNUM *srp_Calc_k(const BIGNUM *N, const BIGNUM *g) +static BIGNUM *srp_Calc_k(const BIGNUM *N, const BIGNUM *g, OPENSSL_CTX *libctx, + const char *propq) { /* k = SHA1(N | PAD(g)) -- tls-srp RFC 5054 */ - return srp_Calc_xy(N, g, N); + return srp_Calc_xy(N, g, N, libctx, propq); +} + +BIGNUM *SRP_Calc_u_ex(const BIGNUM *A, const BIGNUM *B, const BIGNUM *N, + OPENSSL_CTX *libctx, const char *propq) +{ + /* u = SHA1(PAD(A) || PAD(B) ) -- tls-srp RFC 5054 */ + return srp_Calc_xy(A, B, N, libctx, propq); } BIGNUM *SRP_Calc_u(const BIGNUM *A, const BIGNUM *B, const BIGNUM *N) { /* u = SHA1(PAD(A) || PAD(B) ) -- tls-srp RFC 5054 */ - return srp_Calc_xy(A, B, N); + return srp_Calc_xy(A, B, N, NULL, NULL); } BIGNUM *SRP_Calc_server_key(const BIGNUM *A, const BIGNUM *v, const BIGNUM *u, @@ -85,15 +99,15 @@ BIGNUM *SRP_Calc_server_key(const BIGNUM *A, const BIGNUM *v, const BIGNUM *u, return S; } -BIGNUM *SRP_Calc_B(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g, - const BIGNUM *v) +BIGNUM *SRP_Calc_B_ex(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g, + const BIGNUM *v, OPENSSL_CTX *libctx, const char *propq) { BIGNUM *kv = NULL, *gb = NULL; BIGNUM *B = NULL, *k = NULL; BN_CTX *bn_ctx; if (b == NULL || N == NULL || g == NULL || v == NULL || - (bn_ctx = BN_CTX_new()) == NULL) + (bn_ctx = BN_CTX_new_ex(libctx)) == NULL) return NULL; if ((kv = BN_new()) == NULL || @@ -103,7 +117,7 @@ BIGNUM *SRP_Calc_B(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g, /* B = g**b + k*v */ if (!BN_mod_exp(gb, g, b, N, bn_ctx) - || (k = srp_Calc_k(N, g)) == NULL + || (k = srp_Calc_k(N, g, libctx, propq)) == NULL || !BN_mod_mul(kv, v, k, N, bn_ctx) || !BN_mod_add(B, gb, kv, N, bn_ctx)) { BN_free(B); @@ -117,12 +131,20 @@ BIGNUM *SRP_Calc_B(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g, return B; } -BIGNUM *SRP_Calc_x(const BIGNUM *s, const char *user, const char *pass) +BIGNUM *SRP_Calc_B(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g, + const BIGNUM *v) +{ + return SRP_Calc_B_ex(b, N, g, v, NULL, NULL); +} + +BIGNUM *SRP_Calc_x_ex(const BIGNUM *s, const char *user, const char *pass, + OPENSSL_CTX *libctx, const char *propq) { unsigned char dig[SHA_DIGEST_LENGTH]; EVP_MD_CTX *ctxt; unsigned char *cs = NULL; BIGNUM *res = NULL; + EVP_MD *sha1 = NULL; if ((s == NULL) || (user == NULL) || (pass == NULL)) return NULL; @@ -133,12 +155,16 @@ BIGNUM *SRP_Calc_x(const BIGNUM *s, const char *user, const char *pass) if ((cs = OPENSSL_malloc(BN_num_bytes(s))) == NULL) goto err; - if (!EVP_DigestInit_ex(ctxt, EVP_sha1(), NULL) + sha1 = EVP_MD_fetch(libctx, "SHA1", propq); + if (sha1 == NULL) + goto err; + + if (!EVP_DigestInit_ex(ctxt, sha1, NULL) || !EVP_DigestUpdate(ctxt, user, strlen(user)) || !EVP_DigestUpdate(ctxt, ":", 1) || !EVP_DigestUpdate(ctxt, pass, strlen(pass)) || !EVP_DigestFinal_ex(ctxt, dig, NULL) - || !EVP_DigestInit_ex(ctxt, EVP_sha1(), NULL)) + || !EVP_DigestInit_ex(ctxt, sha1, NULL)) goto err; if (BN_bn2bin(s, cs) < 0) goto err; @@ -152,11 +178,17 @@ BIGNUM *SRP_Calc_x(const BIGNUM *s, const char *user, const char *pass) res = BN_bin2bn(dig, sizeof(dig), NULL); err: + EVP_MD_free(sha1); OPENSSL_free(cs); EVP_MD_CTX_free(ctxt); return res; } +BIGNUM *SRP_Calc_x(const BIGNUM *s, const char *user, const char *pass) +{ + return SRP_Calc_x_ex(s, user, pass, NULL, NULL); +} + BIGNUM *SRP_Calc_A(const BIGNUM *a, const BIGNUM *N, const BIGNUM *g) { BN_CTX *bn_ctx; @@ -173,14 +205,15 @@ BIGNUM *SRP_Calc_A(const BIGNUM *a, const BIGNUM *N, const BIGNUM *g) return A; } -BIGNUM *SRP_Calc_client_key(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g, - const BIGNUM *x, const BIGNUM *a, const BIGNUM *u) +BIGNUM *SRP_Calc_client_key_ex(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g, + const BIGNUM *x, const BIGNUM *a, const BIGNUM *u, + OPENSSL_CTX *libctx, const char *propq) { BIGNUM *tmp = NULL, *tmp2 = NULL, *tmp3 = NULL, *k = NULL, *K = NULL; BN_CTX *bn_ctx; if (u == NULL || B == NULL || N == NULL || g == NULL || x == NULL - || a == NULL || (bn_ctx = BN_CTX_new()) == NULL) + || a == NULL || (bn_ctx = BN_CTX_new_ex(libctx)) == NULL) return NULL; if ((tmp = BN_new()) == NULL || @@ -190,7 +223,7 @@ BIGNUM *SRP_Calc_client_key(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g, if (!BN_mod_exp(tmp, g, x, N, bn_ctx)) goto err; - if ((k = srp_Calc_k(N, g)) == NULL) + if ((k = srp_Calc_k(N, g, libctx, propq)) == NULL) goto err; if (!BN_mod_mul(tmp2, tmp, k, N, bn_ctx)) goto err; @@ -215,6 +248,12 @@ BIGNUM *SRP_Calc_client_key(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g, return K; } +BIGNUM *SRP_Calc_client_key(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g, + const BIGNUM *x, const BIGNUM *a, const BIGNUM *u) +{ + return SRP_Calc_client_key_ex(N, B, g, x, a, u, NULL, NULL); +} + int SRP_Verify_B_mod_N(const BIGNUM *B, const BIGNUM *N) { BIGNUM *r; diff --git a/crypto/srp/srp_vfy.c b/crypto/srp/srp_vfy.c index 9505d426..42608984 100644 --- a/crypto/srp/srp_vfy.c +++ b/crypto/srp/srp_vfy.c @@ -594,8 +594,9 @@ SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username) /* * create a verifier (*salt,*verifier,g and N are in base64) */ -char *SRP_create_verifier(const char *user, const char *pass, char **salt, - char **verifier, const char *N, const char *g) +char *SRP_create_verifier_ex(const char *user, const char *pass, char **salt, + char **verifier, const char *N, const char *g, + OPENSSL_CTX *libctx, const char *propq) { int len; char *result = NULL, *vf = NULL; @@ -634,7 +635,7 @@ char *SRP_create_verifier(const char *user, const char *pass, char **salt, } if (*salt == NULL) { - if (RAND_bytes(tmp2, SRP_RANDOM_SALT_LEN) <= 0) + if (RAND_bytes_ex(libctx, tmp2, SRP_RANDOM_SALT_LEN) <= 0) goto err; s = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL); @@ -646,7 +647,8 @@ char *SRP_create_verifier(const char *user, const char *pass, char **salt, if (s == NULL) goto err; - if (!SRP_create_verifier_BN(user, pass, &s, &v, N_bn, g_bn)) + if (!SRP_create_verifier_BN_ex(user, pass, &s, &v, N_bn, g_bn, libctx, + propq)) goto err; if (BN_bn2bin(v, tmp) < 0) @@ -683,6 +685,12 @@ char *SRP_create_verifier(const char *user, const char *pass, char **salt, return result; } +char *SRP_create_verifier(const char *user, const char *pass, char **salt, + char **verifier, const char *N, const char *g) +{ + return SRP_create_verifier_ex(user, pass, salt, verifier, N, g, NULL, NULL); +} + /* * create a verifier (*salt,*verifier,g and N are BIGNUMs). If *salt != NULL * then the provided salt will be used. On successful exit *verifier will point @@ -692,13 +700,14 @@ char *SRP_create_verifier(const char *user, const char *pass, char **salt, * The caller is responsible for freeing the allocated *salt and *verifier * BIGNUMS. */ -int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, - BIGNUM **verifier, const BIGNUM *N, - const BIGNUM *g) +int SRP_create_verifier_BN_ex(const char *user, const char *pass, BIGNUM **salt, + BIGNUM **verifier, const BIGNUM *N, + const BIGNUM *g, OPENSSL_CTX *libctx, + const char *propq) { int result = 0; BIGNUM *x = NULL; - BN_CTX *bn_ctx = BN_CTX_new(); + BN_CTX *bn_ctx = BN_CTX_new_ex(libctx); unsigned char tmp2[MAX_LEN]; BIGNUM *salttmp = NULL; @@ -709,7 +718,7 @@ int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, goto err; if (*salt == NULL) { - if (RAND_bytes(tmp2, SRP_RANDOM_SALT_LEN) <= 0) + if (RAND_bytes_ex(libctx, tmp2, SRP_RANDOM_SALT_LEN) <= 0) goto err; salttmp = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL); @@ -719,7 +728,7 @@ int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, salttmp = *salt; } - x = SRP_Calc_x(salttmp, user, pass); + x = SRP_Calc_x_ex(salttmp, user, pass, libctx, propq); if (x == NULL) goto err; @@ -743,4 +752,11 @@ int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, return result; } +int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, + BIGNUM **verifier, const BIGNUM *N, + const BIGNUM *g) +{ + return SRP_create_verifier_BN_ex(user, pass, salt, verifier, N, g, NULL, + NULL); +} #endif diff --git a/crypto/store/store_lib.c b/crypto/store/store_lib.c index d39967cc..eaf666a8 100644 --- a/crypto/store/store_lib.c +++ b/crypto/store/store_lib.c @@ -509,7 +509,7 @@ OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_name(X509_NAME *name) } OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_issuer_serial(X509_NAME *name, - const ASN1_INTEGER *serial) + const ASN1_INTEGER *serial) { OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search)); @@ -589,7 +589,7 @@ X509_NAME *OSSL_STORE_SEARCH_get0_name(const OSSL_STORE_SEARCH *criterion) } const ASN1_INTEGER *OSSL_STORE_SEARCH_get0_serial(const OSSL_STORE_SEARCH - *criterion) + *criterion) { return criterion->serial; } diff --git a/crypto/store/store_local.h b/crypto/store/store_local.h index c53d4514..7c4d65b9 100644 --- a/crypto/store/store_local.h +++ b/crypto/store/store_local.h @@ -73,7 +73,7 @@ struct ossl_store_search_st { * Used by OSSL_STORE_SEARCH_BY_NAME and * OSSL_STORE_SEARCH_BY_ISSUER_SERIAL */ - X509_NAME *name; + X509_NAME *name; /* TODO constify this; leads to API incompatibility */ /* Used by OSSL_STORE_SEARCH_BY_ISSUER_SERIAL */ const ASN1_INTEGER *serial; diff --git a/crypto/ts/ts_rsp_verify.c b/crypto/ts/ts_rsp_verify.c index 7d2161f2..1f20fb9c 100644 --- a/crypto/ts/ts_rsp_verify.c +++ b/crypto/ts/ts_rsp_verify.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -265,11 +265,12 @@ static int ts_find_cert(STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert) if (!cert_ids || !cert) return -1; - X509_digest(cert, EVP_sha1(), cert_sha1, NULL); - /* Recompute SHA1 hash of certificate if necessary (side effect). */ X509_check_purpose(cert, -1, 0); + if (!X509_digest(cert, EVP_sha1(), cert_sha1, NULL)) + return -1; + /* Look for cert in the cert_ids vector. */ for (i = 0; i < sk_ESS_CERT_ID_num(cert_ids); ++i) { ESS_CERT_ID *cid = sk_ESS_CERT_ID_value(cert_ids, i); @@ -302,7 +303,8 @@ static int ts_find_cert_v2(STACK_OF(ESS_CERT_ID_V2) *cert_ids, X509 *cert) else md = EVP_sha256(); - X509_digest(cert, md, cert_digest, &len); + if (!X509_digest(cert, md, cert_digest, &len)) + return -1; if (cid->hash->length != (int)len) return -1; @@ -495,34 +497,7 @@ static int ts_check_status_info(TS_RESP *response) static char *ts_get_status_text(STACK_OF(ASN1_UTF8STRING) *text) { - int i; - int length = 0; - char *result = NULL; - char *p; - - for (i = 0; i < sk_ASN1_UTF8STRING_num(text); ++i) { - ASN1_UTF8STRING *current = sk_ASN1_UTF8STRING_value(text, i); - if (ASN1_STRING_length(current) > TS_MAX_STATUS_LENGTH - length - 1) - return NULL; - length += ASN1_STRING_length(current); - length += 1; /* separator character */ - } - if ((result = OPENSSL_malloc(length)) == NULL) { - TSerr(TS_F_TS_GET_STATUS_TEXT, ERR_R_MALLOC_FAILURE); - return NULL; - } - - for (i = 0, p = result; i < sk_ASN1_UTF8STRING_num(text); ++i) { - ASN1_UTF8STRING *current = sk_ASN1_UTF8STRING_value(text, i); - length = ASN1_STRING_length(current); - if (i > 0) - *p++ = '/'; - strncpy(p, (const char *)ASN1_STRING_get0_data(current), length); - p += length; - } - *p = '\0'; - - return result; + return sk_ASN1_UTF8STRING2text(text, "/", TS_MAX_STATUS_LENGTH); } static int ts_check_policy(const ASN1_OBJECT *req_oid, diff --git a/crypto/ui/ui_lib.c b/crypto/ui/ui_lib.c index ab51a24a..f8021475 100644 --- a/crypto/ui/ui_lib.c +++ b/crypto/ui/ui_lib.c @@ -578,7 +578,7 @@ int UI_set_ex_data(UI *r, int idx, void *arg) return CRYPTO_set_ex_data(&r->ex_data, idx, arg); } -void *UI_get_ex_data(UI *r, int idx) +void *UI_get_ex_data(const UI *r, int idx) { return CRYPTO_get_ex_data(&r->ex_data, idx); } diff --git a/crypto/x509/build.info b/crypto/x509/build.info index c836ef1c..04b63d0b 100644 --- a/crypto/x509/build.info +++ b/crypto/x509/build.info @@ -12,6 +12,6 @@ SOURCE[../../libcrypto]=\ v3_prn.c v3_utl.c v3err.c v3_genn.c v3_alt.c v3_skey.c v3_akey.c \ v3_pku.c v3_int.c v3_enum.c v3_sxnet.c v3_cpols.c v3_crld.c v3_purp.c \ v3_info.c v3_akeya.c v3_pmaps.c v3_pcons.c v3_ncons.c \ - v3_pcia.c v3_pci.c \ + v3_pcia.c v3_pci.c v3_ist.c \ pcy_cache.c pcy_node.c pcy_data.c pcy_map.c pcy_tree.c pcy_lib.c \ v3_asid.c v3_addr.c v3_tlsf.c v3_admis.c diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c index 69950b7d..006f2e64 100644 --- a/crypto/x509/by_dir.c +++ b/crypto/x509/by_dir.c @@ -45,7 +45,7 @@ static int new_dir(X509_LOOKUP *lu); static void free_dir(X509_LOOKUP *lu); static int add_cert_dir(BY_DIR *ctx, const char *dir, int type); static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type, - X509_NAME *name, X509_OBJECT *ret); + const X509_NAME *name, X509_OBJECT *ret); static X509_LOOKUP_METHOD x509_dir_lookup = { "Load certs from files in a directory", new_dir, /* new_item */ @@ -209,7 +209,7 @@ static int add_cert_dir(BY_DIR *ctx, const char *dir, int type) } static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type, - X509_NAME *name, X509_OBJECT *ret) + const X509_NAME *name, X509_OBJECT *ret) { BY_DIR *ctx; union { @@ -228,11 +228,11 @@ static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type, stmp.type = type; if (type == X509_LU_X509) { - data.st_x509.cert_info.subject = name; + data.st_x509.cert_info.subject = (X509_NAME *)name; /* won't modify it */ stmp.data.x509 = &data.st_x509; postfix = ""; } else if (type == X509_LU_CRL) { - data.crl.crl.issuer = name; + data.crl.crl.issuer = (X509_NAME *)name; /* won't modify it */ stmp.data.crl = &data.crl; postfix = "r"; } else { diff --git a/crypto/x509/by_store.c b/crypto/x509/by_store.c index b2264d71..ecc9be4a 100644 --- a/crypto/x509/by_store.c +++ b/crypto/x509/by_store.c @@ -151,9 +151,10 @@ static int by_store(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, } static int by_store_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, - X509_NAME *name, X509_OBJECT *ret) + const X509_NAME *name, X509_OBJECT *ret) { - OSSL_STORE_SEARCH *criterion = OSSL_STORE_SEARCH_by_name(name); + OSSL_STORE_SEARCH *criterion = + OSSL_STORE_SEARCH_by_name((X509_NAME *)name); /* won't modify it */ int ok = by_store(ctx, type, criterion, ret); STACK_OF(X509_OBJECT) *store_objects = X509_STORE_get0_objects(X509_LOOKUP_get_store(ctx)); diff --git a/crypto/x509/ext_dat.h b/crypto/x509/ext_dat.h index 4329c440..b2fecaa1 100644 --- a/crypto/x509/ext_dat.h +++ b/crypto/x509/ext_dat.h @@ -24,3 +24,4 @@ extern const X509V3_EXT_METHOD v3_ct_scts[3]; extern const X509V3_EXT_METHOD v3_tls_feature; extern const X509V3_EXT_METHOD v3_ext_admission; extern const X509V3_EXT_METHOD v3_utf8_list[1]; +extern const X509V3_EXT_METHOD v3_issuer_sign_tool; diff --git a/crypto/x509/pcy_lib.c b/crypto/x509/pcy_lib.c index b392f13b..fbec0bd4 100644 --- a/crypto/x509/pcy_lib.c +++ b/crypto/x509/pcy_lib.c @@ -69,7 +69,7 @@ int X509_policy_level_node_count(X509_POLICY_LEVEL *level) return n; } -X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, int i) +X509_POLICY_NODE *X509_policy_level_get0_node(const X509_POLICY_LEVEL *level, int i) { if (!level) return NULL; diff --git a/crypto/x509/standard_exts.h b/crypto/x509/standard_exts.h index d66b6554..18f2c324 100644 --- a/crypto/x509/standard_exts.h +++ b/crypto/x509/standard_exts.h @@ -69,6 +69,7 @@ static const X509V3_EXT_METHOD *standard_exts[] = { &v3_ct_scts[2], #endif &v3_utf8_list[0], + &v3_issuer_sign_tool, &v3_tls_feature, &v3_ext_admission }; diff --git a/crypto/x509/t_x509.c b/crypto/x509/t_x509.c index eac299c0..16dc6eaa 100644 --- a/crypto/x509/t_x509.c +++ b/crypto/x509/t_x509.c @@ -227,7 +227,7 @@ int X509_ocspid_print(BIO *bp, X509 *x) int i; unsigned char SHA1md[SHA_DIGEST_LENGTH]; ASN1_BIT_STRING *keybstr; - X509_NAME *subj; + const X509_NAME *subj; /* * display the hash of the subject as it would appear in OCSP requests @@ -472,7 +472,7 @@ int X509_STORE_CTX_print_verify_cb(int ok, X509_STORE_CTX *ctx) BIO_printf(bio, "certs in trust store:\n"); print_store_certs(bio, X509_STORE_CTX_get0_store(ctx)); } - CMPerr(0, X509_R_CERTIFICATE_VERIFICATION_FAILED); + X509err(0, X509_R_CERTIFICATE_VERIFICATION_FAILED); ERR_add_error_mem_bio("\n", bio); BIO_free(bio); } diff --git a/crypto/x509/v3_crld.c b/crypto/x509/v3_crld.c index 4b60752a..24f44e4a 100644 --- a/crypto/x509/v3_crld.c +++ b/crypto/x509/v3_crld.c @@ -479,7 +479,7 @@ static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out, return 1; } -int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname) +int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, const X509_NAME *iname) { int i; STACK_OF(X509_NAME_ENTRY) *frag; diff --git a/crypto/x509/v3_ist.c b/crypto/x509/v3_ist.c new file mode 100644 index 00000000..6db4f199 --- /dev/null +++ b/crypto/x509/v3_ist.c @@ -0,0 +1,149 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "ext_dat.h" + +/* + * Issuer Sign Tool (1.2.643.100.112) The name of the tool used to signs the subject (ASN1_SEQUENCE) + * This extention is required to obtain the status of a qualified certificate at Russian Federation. + * RFC-style description is available here: https://tools.ietf.org/html/draft-deremin-rfc4491-bis-04#section-5 + * Russian Federal Law 63 "Digital Sign" is available here: http://www.consultant.ru/document/cons_doc_LAW_112701/ + */ + +ASN1_SEQUENCE(ISSUER_SIGN_TOOL) = { + ASN1_SIMPLE(ISSUER_SIGN_TOOL, signTool, ASN1_UTF8STRING), + ASN1_SIMPLE(ISSUER_SIGN_TOOL, cATool, ASN1_UTF8STRING), + ASN1_SIMPLE(ISSUER_SIGN_TOOL, signToolCert, ASN1_UTF8STRING), + ASN1_SIMPLE(ISSUER_SIGN_TOOL, cAToolCert, ASN1_UTF8STRING) +} ASN1_SEQUENCE_END(ISSUER_SIGN_TOOL) + +IMPLEMENT_ASN1_FUNCTIONS(ISSUER_SIGN_TOOL) + + +static ISSUER_SIGN_TOOL *v2i_issuer_sign_tool(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + ISSUER_SIGN_TOOL *ist = ISSUER_SIGN_TOOL_new(); + int i; + + if (ist == NULL) { + X509V3err(X509V3_F_V2I_ISSUER_SIGN_TOOL, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); ++i) { + CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i); + + if (cnf == NULL) { + continue; + } + if (strcmp(cnf->name, "signTool") == 0) { + ist->signTool = ASN1_UTF8STRING_new(); + if (ist->signTool == NULL) { + X509V3err(X509V3_F_V2I_ISSUER_SIGN_TOOL, ERR_R_MALLOC_FAILURE); + ISSUER_SIGN_TOOL_free(ist); + return NULL; + } + ASN1_STRING_set(ist->signTool, cnf->value, strlen(cnf->value)); + } else if (strcmp(cnf->name, "cATool") == 0) { + ist->cATool = ASN1_UTF8STRING_new(); + if (ist->cATool == NULL) { + X509V3err(X509V3_F_V2I_ISSUER_SIGN_TOOL, ERR_R_MALLOC_FAILURE); + ISSUER_SIGN_TOOL_free(ist); + return NULL; + } + ASN1_STRING_set(ist->cATool, cnf->value, strlen(cnf->value)); + } else if (strcmp(cnf->name, "signToolCert") == 0) { + ist->signToolCert = ASN1_UTF8STRING_new(); + if (ist->signToolCert == NULL) { + X509V3err(X509V3_F_V2I_ISSUER_SIGN_TOOL, ERR_R_MALLOC_FAILURE); + ISSUER_SIGN_TOOL_free(ist); + return NULL; + } + ASN1_STRING_set(ist->signToolCert, cnf->value, strlen(cnf->value)); + } else if (strcmp(cnf->name, "cAToolCert") == 0) { + ist->cAToolCert = ASN1_UTF8STRING_new(); + if (ist->cAToolCert == NULL) { + X509V3err(X509V3_F_V2I_ISSUER_SIGN_TOOL, ERR_R_MALLOC_FAILURE); + ISSUER_SIGN_TOOL_free(ist); + return NULL; + } + ASN1_STRING_set(ist->cAToolCert, cnf->value, strlen(cnf->value)); + } else { + X509V3err(X509V3_F_V2I_ISSUER_SIGN_TOOL, ERR_R_PASSED_INVALID_ARGUMENT); + ISSUER_SIGN_TOOL_free(ist); + return NULL; + } + } + return ist; +} + +static int i2r_issuer_sign_tool(X509V3_EXT_METHOD *method, + ISSUER_SIGN_TOOL *ist, BIO *out, + int indent) +{ + int new_line = 0; + + if (ist == NULL) { + X509V3err(X509V3_F_I2R_ISSUER_SIGN_TOOL, ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + if (ist->signTool != NULL) { + if (new_line == 1) { + BIO_write(out, "\n", 1); + } + BIO_printf(out, "%*ssignTool : ", indent, ""); + BIO_write(out, ist->signTool->data, ist->signTool->length); + new_line = 1; + } + if (ist->cATool != NULL) { + if (new_line == 1) { + BIO_write(out, "\n", 1); + } + BIO_printf(out, "%*scATool : ", indent, ""); + BIO_write(out, ist->cATool->data, ist->cATool->length); + new_line = 1; + } + if (ist->signToolCert != NULL) { + if (new_line == 1) { + BIO_write(out, "\n", 1); + } + BIO_printf(out, "%*ssignToolCert: ", indent, ""); + BIO_write(out, ist->signToolCert->data, ist->signToolCert->length); + new_line = 1; + } + if (ist->cAToolCert != NULL) { + if (new_line == 1) { + BIO_write(out, "\n", 1); + } + BIO_printf(out, "%*scAToolCert : ", indent, ""); + BIO_write(out, ist->cAToolCert->data, ist->cAToolCert->length); + new_line = 1; + } + return 1; +} + +const X509V3_EXT_METHOD v3_issuer_sign_tool = { + NID_issuerSignTool, /* nid */ + X509V3_EXT_MULTILINE, /* flags */ + ASN1_ITEM_ref(ISSUER_SIGN_TOOL), /* template */ + 0, 0, 0, 0, /* old functions, ignored */ + 0, /* i2s */ + 0, /* s2i */ + 0, /* i2v */ + (X509V3_EXT_V2I)v2i_issuer_sign_tool, /* v2i */ + (X509V3_EXT_I2R)i2r_issuer_sign_tool, /* i2r */ + 0, /* r2i */ + NULL /* extension-specific data */ +}; diff --git a/crypto/x509/v3_ncons.c b/crypto/x509/v3_ncons.c index 927aa8f9..fab9836d 100644 --- a/crypto/x509/v3_ncons.c +++ b/crypto/x509/v3_ncons.c @@ -31,7 +31,7 @@ static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip); static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc); static int nc_match_single(GENERAL_NAME *sub, GENERAL_NAME *gen); -static int nc_dn(X509_NAME *sub, X509_NAME *nm); +static int nc_dn(const X509_NAME *sub, const X509_NAME *nm); static int nc_dns(ASN1_IA5STRING *sub, ASN1_IA5STRING *dns); static int nc_email(ASN1_IA5STRING *sub, ASN1_IA5STRING *eml); static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base); @@ -400,7 +400,7 @@ static int cn2dnsid(ASN1_STRING *cn, unsigned char **dnsid, size_t *idlen) int NAME_CONSTRAINTS_check_CN(X509 *x, NAME_CONSTRAINTS *nc) { int r, i; - X509_NAME *nm = X509_get_subject_name(x); + const X509_NAME *nm = X509_get_subject_name(x); ASN1_STRING stmp; GENERAL_NAME gntmp; @@ -543,7 +543,7 @@ static int nc_match_single(GENERAL_NAME *gen, GENERAL_NAME *base) * subset of the name. */ -static int nc_dn(X509_NAME *nm, X509_NAME *base) +static int nc_dn(const X509_NAME *nm, const X509_NAME *base) { /* Ensure canonical encodings are up to date. */ if (nm->modified && i2d_X509_NAME(nm, NULL) < 0) diff --git a/crypto/x509/v3_purp.c b/crypto/x509/v3_purp.c index 10fd0f73..bee8210b 100644 --- a/crypto/x509/v3_purp.c +++ b/crypto/x509/v3_purp.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -15,8 +15,6 @@ #include "crypto/x509.h" #include "internal/tsan_assist.h" -static void x509v3_cache_extensions(X509 *x); - static int check_ssl_ca(const X509 *x); static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, int ca); @@ -80,7 +78,8 @@ int X509_check_purpose(X509 *x, int id, int ca) int idx; const X509_PURPOSE *pt; - x509v3_cache_extensions(x); + if (!X509v3_cache_extensions(x, NULL, NULL)) + return -1; /* Return if side-effect only call */ if (id == -1) @@ -300,10 +299,11 @@ int X509_supported_extension(X509_EXTENSION *ex) return 0; } -static void setup_dp(X509 *x, DIST_POINT *dp) +static int setup_dp(X509 *x, DIST_POINT *dp) { - X509_NAME *iname = NULL; + const X509_NAME *iname = NULL; int i; + if (dp->reasons) { if (dp->reasons->length > 0) dp->dp_reasons = dp->reasons->data[0]; @@ -313,7 +313,7 @@ static void setup_dp(X509 *x, DIST_POINT *dp) } else dp->dp_reasons = CRLDP_ALL_REASONS; if (!dp->distpoint || (dp->distpoint->type != 1)) - return; + return 1; for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) { GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i); if (gen->type == GEN_DIRNAME) { @@ -324,16 +324,21 @@ static void setup_dp(X509 *x, DIST_POINT *dp) if (!iname) iname = X509_get_issuer_name(x); - DIST_POINT_set_dpname(dp->distpoint, iname); - + return DIST_POINT_set_dpname(dp->distpoint, iname); } -static void setup_crldp(X509 *x) +static int setup_crldp(X509 *x) { int i; - x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL); - for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++) - setup_dp(x, sk_DIST_POINT_value(x->crldp, i)); + + x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, &i, NULL); + if (x->crldp == NULL && i != -1) + return 0; + for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++) { + if (!setup_dp(x, sk_DIST_POINT_value(x->crldp, i))) + return 0; + } + return 1; } #define V1_ROOT (EXFLAG_V1|EXFLAG_SS) @@ -344,7 +349,7 @@ static void setup_crldp(X509 *x) #define ns_reject(x, usage) \ (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage))) -static void x509v3_cache_extensions(X509 *x) +int X509v3_cache_extensions(X509 *x, OPENSSL_CTX *libctx, const char *propq) { BASIC_CONSTRAINTS *bs; PROXY_CERT_INFO_EXTENSION *pci; @@ -353,41 +358,52 @@ static void x509v3_cache_extensions(X509 *x) EXTENDED_KEY_USAGE *extusage; X509_EXTENSION *ex; int i; + EVP_MD *sha1; #ifdef tsan_ld_acq /* fast lock-free check, see end of the function for details. */ if (tsan_ld_acq((TSAN_QUALIFIER int *)&x->ex_cached)) - return; + return (x->ex_flags & EXFLAG_INVALID) == 0; #endif CRYPTO_THREAD_write_lock(x->lock); if (x->ex_flags & EXFLAG_SET) { CRYPTO_THREAD_unlock(x->lock); - return; + return (x->ex_flags & EXFLAG_INVALID) == 0; } - X509_digest(x, EVP_sha1(), x->sha1_hash, NULL); + sha1 = EVP_MD_fetch(libctx, "SHA1", propq); + if (sha1 == NULL || !X509_digest(x, sha1, x->sha1_hash, NULL)) + x->ex_flags |= EXFLAG_INVALID; + EVP_MD_free(sha1); + /* V1 should mean no extensions ... */ if (!X509_get_version(x)) x->ex_flags |= EXFLAG_V1; /* Handle basic constraints */ - if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, NULL, NULL))) { + if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, &i, NULL))) { if (bs->ca) x->ex_flags |= EXFLAG_CA; if (bs->pathlen) { - if ((bs->pathlen->type == V_ASN1_NEG_INTEGER) - || !bs->ca) { + if (bs->pathlen->type == V_ASN1_NEG_INTEGER) { x->ex_flags |= EXFLAG_INVALID; x->ex_pathlen = 0; - } else + } else { x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen); + if (!bs->ca && x->ex_pathlen != 0) { + x->ex_flags |= EXFLAG_INVALID; + x->ex_pathlen = 0; + } + } } else x->ex_pathlen = -1; BASIC_CONSTRAINTS_free(bs); x->ex_flags |= EXFLAG_BCONS; + } else if (i != -1) { + x->ex_flags |= EXFLAG_INVALID; } /* Handle proxy certificates */ - if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL))) { + if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, &i, NULL))) { if (x->ex_flags & EXFLAG_CA || X509_get_ext_by_NID(x, NID_subject_alt_name, -1) >= 0 || X509_get_ext_by_NID(x, NID_issuer_alt_name, -1) >= 0) { @@ -399,9 +415,11 @@ static void x509v3_cache_extensions(X509 *x) x->ex_pcpathlen = -1; PROXY_CERT_INFO_EXTENSION_free(pci); x->ex_flags |= EXFLAG_PROXY; + } else if (i != -1) { + x->ex_flags |= EXFLAG_INVALID; } /* Handle key usage */ - if ((usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) { + if ((usage = X509_get_ext_d2i(x, NID_key_usage, &i, NULL))) { if (usage->length > 0) { x->ex_kusage = usage->data[0]; if (usage->length > 1) @@ -410,9 +428,11 @@ static void x509v3_cache_extensions(X509 *x) x->ex_kusage = 0; x->ex_flags |= EXFLAG_KUSAGE; ASN1_BIT_STRING_free(usage); + } else if (i != -1) { + x->ex_flags |= EXFLAG_INVALID; } x->ex_xkusage = 0; - if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL))) { + if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, &i, NULL))) { x->ex_flags |= EXFLAG_XKUSAGE; for (i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) { switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage, i))) { @@ -455,18 +475,26 @@ static void x509v3_cache_extensions(X509 *x) } } sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free); + } else if (i != -1) { + x->ex_flags |= EXFLAG_INVALID; } - if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, NULL, NULL))) { + if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, &i, NULL))) { if (ns->length > 0) x->ex_nscert = ns->data[0]; else x->ex_nscert = 0; x->ex_flags |= EXFLAG_NSCERT; ASN1_BIT_STRING_free(ns); + } else if (i != -1) { + x->ex_flags |= EXFLAG_INVALID; } - x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL); - x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL); + x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, &i, NULL); + if (x->skid == NULL && i != -1) + x->ex_flags |= EXFLAG_INVALID; + x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, &i, NULL); + if (x->akid == NULL && i != -1) + x->ex_flags |= EXFLAG_INVALID; /* Does subject name match issuer ? */ if (!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) { x->ex_flags |= EXFLAG_SI; @@ -475,16 +503,22 @@ static void x509v3_cache_extensions(X509 *x) !ku_reject(x, KU_KEY_CERT_SIGN)) x->ex_flags |= EXFLAG_SS; } - x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); - x->nc = X509_get_ext_d2i(x, NID_name_constraints, &i, NULL); - if (!x->nc && (i != -1)) + x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, &i, NULL); + if (x->altname == NULL && i != -1) + x->ex_flags |= EXFLAG_INVALID; + x->nc = X509_get_ext_d2i(x, NID_name_constraints, &i, NULL); + if (x->nc == NULL && i != -1) + x->ex_flags |= EXFLAG_INVALID; + if (!setup_crldp(x)) x->ex_flags |= EXFLAG_INVALID; - setup_crldp(x); #ifndef OPENSSL_NO_RFC3779 - x->rfc3779_addr = X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, NULL, NULL); - x->rfc3779_asid = X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum, - NULL, NULL); + x->rfc3779_addr = X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, &i, NULL); + if (x->rfc3779_addr == NULL && i != -1) + x->ex_flags |= EXFLAG_INVALID; + x->rfc3779_asid = X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum, &i, NULL); + if (x->rfc3779_asid == NULL && i != -1) + x->ex_flags |= EXFLAG_INVALID; #endif for (i = 0; i < X509_get_ext_count(x); i++) { ex = X509_get_ext(x, i); @@ -509,6 +543,8 @@ static void x509v3_cache_extensions(X509 *x) */ #endif CRYPTO_THREAD_unlock(x->lock); + + return (x->ex_flags & EXFLAG_INVALID) == 0; } /*- @@ -516,9 +552,11 @@ static void x509v3_cache_extensions(X509 *x) * return codes: * 0 not a CA * 1 is a CA - * 2 basicConstraints absent so "maybe" a CA + * 2 Only possible in older versions of openSSL when basicConstraints are absent + * new versions will not return this value. May be a CA * 3 basicConstraints absent but self signed V1. * 4 basicConstraints absent but keyUsage present and keyCertSign asserted. + * 5 Netscape specific CA Flags present */ static int check_ca(const X509 *x) @@ -561,7 +599,9 @@ void X509_set_proxy_pathlen(X509 *x, long l) int X509_check_ca(X509 *x) { - x509v3_cache_extensions(x); + /* Note 0 normally means "not a CA" - but in this case means error. */ + if (!X509v3_cache_extensions(x, NULL, NULL)) + return 0; return check_ca(x); } @@ -777,8 +817,9 @@ int X509_check_issued(X509 *issuer, X509 *subject) X509_get_issuer_name(subject))) return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; - x509v3_cache_extensions(issuer); - x509v3_cache_extensions(subject); + if (!X509v3_cache_extensions(issuer, NULL, NULL) + || !X509v3_cache_extensions(subject, NULL, NULL)) + return X509_V_ERR_UNSPECIFIED; if (subject->akid) { int ret = X509_check_akid(issuer, subject->akid); @@ -861,7 +902,8 @@ uint32_t X509_get_extension_flags(X509 *x) uint32_t X509_get_key_usage(X509 *x) { /* Call for side-effect of computing hash and caching extensions */ - X509_check_purpose(x, -1, -1); + if (X509_check_purpose(x, -1, -1) != 1) + return 0; if (x->ex_flags & EXFLAG_KUSAGE) return x->ex_kusage; return UINT32_MAX; @@ -870,7 +912,8 @@ uint32_t X509_get_key_usage(X509 *x) uint32_t X509_get_extended_key_usage(X509 *x) { /* Call for side-effect of computing hash and caching extensions */ - X509_check_purpose(x, -1, -1); + if (X509_check_purpose(x, -1, -1) != 1) + return 0; if (x->ex_flags & EXFLAG_XKUSAGE) return x->ex_xkusage; return UINT32_MAX; @@ -879,28 +922,32 @@ uint32_t X509_get_extended_key_usage(X509 *x) const ASN1_OCTET_STRING *X509_get0_subject_key_id(X509 *x) { /* Call for side-effect of computing hash and caching extensions */ - X509_check_purpose(x, -1, -1); + if (X509_check_purpose(x, -1, -1) != 1) + return NULL; return x->skid; } const ASN1_OCTET_STRING *X509_get0_authority_key_id(X509 *x) { /* Call for side-effect of computing hash and caching extensions */ - X509_check_purpose(x, -1, -1); + if (X509_check_purpose(x, -1, -1) != 1) + return NULL; return (x->akid != NULL ? x->akid->keyid : NULL); } const GENERAL_NAMES *X509_get0_authority_issuer(X509 *x) { /* Call for side-effect of computing hash and caching extensions */ - X509_check_purpose(x, -1, -1); + if (X509_check_purpose(x, -1, -1) != 1) + return NULL; return (x->akid != NULL ? x->akid->issuer : NULL); } const ASN1_INTEGER *X509_get0_authority_serial(X509 *x) { /* Call for side-effect of computing hash and caching extensions */ - X509_check_purpose(x, -1, -1); + if (X509_check_purpose(x, -1, -1) != 1) + return NULL; return (x->akid != NULL ? x->akid->serial : NULL); } diff --git a/crypto/x509/v3_utl.c b/crypto/x509/v3_utl.c index 19b552c3..d8abb6da 100644 --- a/crypto/x509/v3_utl.c +++ b/crypto/x509/v3_utl.c @@ -22,7 +22,7 @@ static char *strip_spaces(char *name); static int sk_strcmp(const char *const *a, const char *const *b); -static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, +static STACK_OF(OPENSSL_STRING) *get_email(const X509_NAME *name, GENERAL_NAMES *gens); static void str_free(OPENSSL_STRING str); static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, const ASN1_IA5STRING *email); @@ -463,7 +463,7 @@ STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x) return ret; } -static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, +static STACK_OF(OPENSSL_STRING) *get_email(const X509_NAME *name, GENERAL_NAMES *gens) { STACK_OF(OPENSSL_STRING) *ret = NULL; @@ -819,7 +819,7 @@ static int do_x509_check(X509 *x, const char *chk, size_t chklen, unsigned int flags, int check_type, char **peername) { GENERAL_NAMES *gens = NULL; - X509_NAME *name = NULL; + const X509_NAME *name = NULL; int i; int cnid = NID_undef; int alt_type; diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c index b8a61ffe..5b000386 100644 --- a/crypto/x509/x509_cmp.c +++ b/crypto/x509/x509_cmp.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -135,9 +135,12 @@ unsigned long X509_subject_name_hash_old(X509 *x) int X509_cmp(const X509 *a, const X509 *b) { int rv; + /* ensure hash is valid */ - X509_check_purpose((X509 *)a, -1, 0); - X509_check_purpose((X509 *)b, -1, 0); + if (X509_check_purpose((X509 *)a, -1, 0) != 1) + return -2; + if (X509_check_purpose((X509 *)b, -1, 0) != 1) + return -2; rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH); if (rv) @@ -181,7 +184,7 @@ int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) } -unsigned long X509_NAME_hash(X509_NAME *x) +unsigned long X509_NAME_hash(const X509_NAME *x) { unsigned long ret = 0; unsigned char md[SHA_DIGEST_LENGTH]; @@ -204,7 +207,7 @@ unsigned long X509_NAME_hash(X509_NAME *x) * this is reasonably efficient. */ -unsigned long X509_NAME_hash_old(X509_NAME *x) +unsigned long X509_NAME_hash_old(const X509_NAME *x) { EVP_MD *md5 = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_MD5, "-fips"); EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); @@ -232,8 +235,8 @@ unsigned long X509_NAME_hash_old(X509_NAME *x) #endif /* Search a stack of X509 for a match */ -X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name, - ASN1_INTEGER *serial) +X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, const X509_NAME *name, + const ASN1_INTEGER *serial) { int i; X509 x, *x509 = NULL; @@ -242,7 +245,7 @@ X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name, return NULL; x.cert_info.serialNumber = *serial; - x.cert_info.issuer = name; + x.cert_info.issuer = (X509_NAME *)name; /* won't modify it */ for (i = 0; i < sk_X509_num(sk); i++) { x509 = sk_X509_value(sk, i); @@ -252,7 +255,7 @@ X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name, return NULL; } -X509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name) +X509 *X509_find_by_subject(STACK_OF(X509) *sk, const X509_NAME *name) { X509 *x509; int i; diff --git a/crypto/x509/x509_local.h b/crypto/x509/x509_local.h index a8d8bafe..1f79a0f5 100644 --- a/crypto/x509/x509_local.h +++ b/crypto/x509/x509_local.h @@ -64,7 +64,7 @@ struct x509_crl_method_st { int (*crl_init) (X509_CRL *crl); int (*crl_free) (X509_CRL *crl); int (*crl_lookup) (X509_CRL *crl, X509_REVOKED **ret, - ASN1_INTEGER *ser, X509_NAME *issuer); + const ASN1_INTEGER *ser, const X509_NAME *issuer); int (*crl_verify) (X509_CRL *crl, EVP_PKEY *pk); }; @@ -77,9 +77,10 @@ struct x509_lookup_method_st { int (*ctrl) (X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **ret); int (*get_by_subject) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, - X509_NAME *name, X509_OBJECT *ret); + const X509_NAME *name, X509_OBJECT *ret); int (*get_by_issuer_serial) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, - X509_NAME *name, ASN1_INTEGER *serial, + const X509_NAME *name, + const ASN1_INTEGER *serial, X509_OBJECT *ret); int (*get_by_fingerprint) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, const unsigned char *bytes, int len, @@ -128,8 +129,11 @@ struct x509_store_st { int (*cert_crl) (X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check policy status of the chain */ 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); + STACK_OF(X509) *(*lookup_certs) (X509_STORE_CTX *ctx, + const X509_NAME *nm); + /* cannot constify 'ctx' param due to lookup_certs_sk() in x509_vfy.c */ + STACK_OF(X509_CRL) *(*lookup_crls) (const X509_STORE_CTX *ctx, + const X509_NAME *nm); int (*cleanup) (X509_STORE_CTX *ctx); CRYPTO_EX_DATA ex_data; CRYPTO_REF_COUNT references; diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c index 9018d6e1..39814104 100644 --- a/crypto/x509/x509_lu.c +++ b/crypto/x509/x509_lu.c @@ -83,7 +83,7 @@ int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, } int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, - X509_NAME *name, X509_OBJECT *ret) + const X509_NAME *name, X509_OBJECT *ret) { if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL)) return 0; @@ -93,7 +93,8 @@ int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, } int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, - X509_NAME *name, ASN1_INTEGER *serial, + const X509_NAME *name, + const ASN1_INTEGER *serial, X509_OBJECT *ret) { if ((ctx->method == NULL) || (ctx->method->get_by_issuer_serial == NULL)) @@ -273,7 +274,7 @@ X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m) X509_OBJECT *X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type, - X509_NAME *name) + const X509_NAME *name) { X509_OBJECT *ret = X509_OBJECT_new(); @@ -286,8 +287,9 @@ X509_OBJECT *X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs, return ret; } -int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type, - X509_NAME *name, X509_OBJECT *ret) +int X509_STORE_CTX_get_by_subject(const X509_STORE_CTX *vs, + X509_LOOKUP_TYPE type, + const X509_NAME *name, X509_OBJECT *ret) { X509_STORE *store = vs->store; X509_LOOKUP *lu; @@ -403,7 +405,7 @@ X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a) return a->data.x509; } -X509_CRL *X509_OBJECT_get0_X509_CRL(X509_OBJECT *a) +X509_CRL *X509_OBJECT_get0_X509_CRL(const X509_OBJECT *a) { if (a == NULL || a->type != X509_LU_CRL) return NULL; @@ -472,7 +474,7 @@ void X509_OBJECT_free(X509_OBJECT *a) } static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, - X509_NAME *name, int *pnmatch) + const X509_NAME *name, int *pnmatch) { X509_OBJECT stmp; X509 x509_s; @@ -483,11 +485,11 @@ static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, switch (type) { case X509_LU_X509: stmp.data.x509 = &x509_s; - x509_s.cert_info.subject = name; + x509_s.cert_info.subject = (X509_NAME *)name; /* won't modify it */ break; case X509_LU_CRL: stmp.data.crl = &crl_s; - crl_s.crl.issuer = name; + crl_s.crl.issuer = (X509_NAME *)name; /* won't modify it */ break; case X509_LU_NONE: /* abort(); */ @@ -511,14 +513,14 @@ static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, } int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, - X509_NAME *name) + const X509_NAME *name) { return x509_object_idx_cnt(h, type, name, NULL); } X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, - X509_NAME *name) + const X509_NAME *name) { int idx; idx = X509_OBJECT_idx_by_subject(h, type, name); @@ -527,11 +529,12 @@ X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, return sk_X509_OBJECT_value(h, idx); } -STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *v) +STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(const X509_STORE *v) { return v->objs; } +/* TODO param type could be constified as change to lock is intermittent */ STACK_OF(X509) *X509_STORE_get1_all_certs(X509_STORE *store) { STACK_OF(X509) *sk; @@ -567,7 +570,8 @@ STACK_OF(X509) *X509_STORE_get1_all_certs(X509_STORE *store) return NULL; } -STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm) +STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx, + const X509_NAME *nm) { int i, idx, cnt; STACK_OF(X509) *sk = NULL; @@ -624,7 +628,8 @@ STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm) return sk; } -STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm) +STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(const X509_STORE_CTX *ctx, + const X509_NAME *nm) { int i, idx, cnt; STACK_OF(X509_CRL) *sk = sk_X509_CRL_new_null(); @@ -711,7 +716,7 @@ X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, */ int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) { - X509_NAME *xn; + const X509_NAME *xn; X509_OBJECT *obj = X509_OBJECT_new(), *pobj = NULL; X509_STORE *store = ctx->store; int i, ok, idx, ret; @@ -800,12 +805,12 @@ int X509_STORE_set_trust(X509_STORE *ctx, int trust) return X509_VERIFY_PARAM_set_trust(ctx->param, trust); } -int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param) +int X509_STORE_set1_param(X509_STORE *ctx, const X509_VERIFY_PARAM *param) { return X509_VERIFY_PARAM_set1(ctx->param, param); } -X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx) +X509_VERIFY_PARAM *X509_STORE_get0_param(const X509_STORE *ctx) { return ctx->param; } @@ -815,7 +820,7 @@ void X509_STORE_set_verify(X509_STORE *ctx, X509_STORE_CTX_verify_fn verify) ctx->verify = verify; } -X509_STORE_CTX_verify_fn X509_STORE_get_verify(X509_STORE *ctx) +X509_STORE_CTX_verify_fn X509_STORE_get_verify(const X509_STORE *ctx) { return ctx->verify; } @@ -826,7 +831,7 @@ void X509_STORE_set_verify_cb(X509_STORE *ctx, ctx->verify_cb = verify_cb; } -X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(X509_STORE *ctx) +X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(const X509_STORE *ctx) { return ctx->verify_cb; } @@ -837,7 +842,7 @@ void X509_STORE_set_get_issuer(X509_STORE *ctx, ctx->get_issuer = get_issuer; } -X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(X509_STORE *ctx) +X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(const X509_STORE *ctx) { return ctx->get_issuer; } @@ -848,7 +853,7 @@ void X509_STORE_set_check_issued(X509_STORE *ctx, ctx->check_issued = check_issued; } -X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(X509_STORE *ctx) +X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(const X509_STORE *ctx) { return ctx->check_issued; } @@ -859,7 +864,7 @@ void X509_STORE_set_check_revocation(X509_STORE *ctx, ctx->check_revocation = check_revocation; } -X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation(X509_STORE *ctx) +X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation(const X509_STORE *ctx) { return ctx->check_revocation; } @@ -870,7 +875,7 @@ void X509_STORE_set_get_crl(X509_STORE *ctx, ctx->get_crl = get_crl; } -X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(X509_STORE *ctx) +X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(const X509_STORE *ctx) { return ctx->get_crl; } @@ -881,7 +886,7 @@ void X509_STORE_set_check_crl(X509_STORE *ctx, ctx->check_crl = check_crl; } -X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(X509_STORE *ctx) +X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(const X509_STORE *ctx) { return ctx->check_crl; } @@ -892,7 +897,7 @@ void X509_STORE_set_cert_crl(X509_STORE *ctx, ctx->cert_crl = cert_crl; } -X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(X509_STORE *ctx) +X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(const X509_STORE *ctx) { return ctx->cert_crl; } @@ -903,7 +908,7 @@ void X509_STORE_set_check_policy(X509_STORE *ctx, ctx->check_policy = check_policy; } -X509_STORE_CTX_check_policy_fn X509_STORE_get_check_policy(X509_STORE *ctx) +X509_STORE_CTX_check_policy_fn X509_STORE_get_check_policy(const X509_STORE *ctx) { return ctx->check_policy; } @@ -914,7 +919,7 @@ void X509_STORE_set_lookup_certs(X509_STORE *ctx, ctx->lookup_certs = lookup_certs; } -X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(X509_STORE *ctx) +X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(const X509_STORE *ctx) { return ctx->lookup_certs; } @@ -925,7 +930,7 @@ void X509_STORE_set_lookup_crls(X509_STORE *ctx, ctx->lookup_crls = lookup_crls; } -X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(X509_STORE *ctx) +X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(const X509_STORE *ctx) { return ctx->lookup_crls; } @@ -936,7 +941,7 @@ void X509_STORE_set_cleanup(X509_STORE *ctx, ctx->cleanup = ctx_cleanup; } -X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(X509_STORE *ctx) +X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(const X509_STORE *ctx) { return ctx->cleanup; } @@ -946,12 +951,12 @@ int X509_STORE_set_ex_data(X509_STORE *ctx, int idx, void *data) return CRYPTO_set_ex_data(&ctx->ex_data, idx, data); } -void *X509_STORE_get_ex_data(X509_STORE *ctx, int idx) +void *X509_STORE_get_ex_data(const X509_STORE *ctx, int idx) { return CRYPTO_get_ex_data(&ctx->ex_data, idx); } -X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx) +X509_STORE *X509_STORE_CTX_get0_store(const X509_STORE_CTX *ctx) { return ctx->store; } diff --git a/crypto/x509/x509_r2x.c b/crypto/x509/x509_r2x.c index d7dd3754..310d28bb 100644 --- a/crypto/x509/x509_r2x.c +++ b/crypto/x509/x509_r2x.c @@ -21,7 +21,7 @@ X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey) { X509 *ret = NULL; X509_CINF *xi = NULL; - X509_NAME *xn; + const X509_NAME *xn; EVP_PKEY *pubkey = NULL; if ((ret = X509_new()) == NULL) { diff --git a/crypto/x509/x509_set.c b/crypto/x509/x509_set.c index 97676c2e..df45d9f1 100644 --- a/crypto/x509/x509_set.c +++ b/crypto/x509/x509_set.c @@ -47,14 +47,14 @@ int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial) return 1; } -int X509_set_issuer_name(X509 *x, X509_NAME *name) +int X509_set_issuer_name(X509 *x, const X509_NAME *name) { if (x == NULL) return 0; return X509_NAME_set(&x->cert_info.issuer, name); } -int X509_set_subject_name(X509 *x, X509_NAME *name) +int X509_set_subject_name(X509 *x, const X509_NAME *name) { if (x == NULL) return 0; diff --git a/crypto/x509/x509_trs.c b/crypto/x509/x509_trs.c index b077ba58..10718c34 100644 --- a/crypto/x509/x509_trs.c +++ b/crypto/x509/x509_trs.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -240,8 +240,9 @@ static int trust_1oid(X509_TRUST *trust, X509 *x, int flags) static int trust_compat(X509_TRUST *trust, X509 *x, int flags) { /* Call for side-effect of computing hash and caching extensions */ - X509_check_purpose(x, -1, 0); - if ((flags & X509_TRUST_NO_SS_COMPAT) == 0 && x->ex_flags & EXFLAG_SS) + if (X509_check_purpose(x, -1, 0) != 1) + return X509_TRUST_UNTRUSTED; + if ((flags & X509_TRUST_NO_SS_COMPAT) == 0 && (x->ex_flags & EXFLAG_SS)) return X509_TRUST_TRUSTED; else return X509_TRUST_UNTRUSTED; diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index c8d12588..84a4bb2c 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -104,15 +104,12 @@ static int null_callback(int ok, X509_STORE_CTX *e) return ok; } -/* Return 1 is a certificate is self signed */ -static int cert_self_signed(X509 *x) +/* Return 1 is a certificate is self signed, 0 if not, or -1 on error */ +static int cert_self_signed(X509_STORE_CTX *ctx, X509 *x) { - /* - * FIXME: x509v3_cache_extensions() needs to detect more failures and not - * set EXFLAG_SET when that happens. Especially, if the failures are - * parse errors, rather than memory pressure! - */ - X509_check_purpose(x, -1, 0); + if (!X509v3_cache_extensions(x, ctx->libctx, ctx->propq)) + return -1; + if (x->ex_flags & EXFLAG_SS) return 1; else @@ -328,14 +325,26 @@ static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x) static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer) { int ret; - if (x == issuer) - return cert_self_signed(x); + int ss; + + if (x == issuer) { + ss = cert_self_signed(ctx, x); + if (ss < 0) + return 0; + return ss; + } + ret = X509_check_issued(issuer, x); if (ret == X509_V_OK) { int i; X509 *ch; + + ss = cert_self_signed(ctx, x); + if (ss < 0) + return 0; + /* Special case: single self signed certificate */ - if (cert_self_signed(x) && sk_X509_num(ctx->chain) == 1) + if (ss > 0 && sk_X509_num(ctx->chain) == 1) return 1; for (i = 0; i < sk_X509_num(ctx->chain); i++) { ch = sk_X509_value(ctx->chain, i); @@ -361,7 +370,8 @@ static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) return 0; } -static STACK_OF(X509) *lookup_certs_sk(X509_STORE_CTX *ctx, X509_NAME *nm) +static STACK_OF(X509) *lookup_certs_sk(X509_STORE_CTX *ctx, + const X509_NAME *nm) { STACK_OF(X509) *sk = NULL; X509 *x; @@ -512,6 +522,12 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) ret = 1; break; } + if ((x->ex_flags & EXFLAG_CA) == 0 + && x->ex_pathlen != -1 + && (ctx->param->flags & X509_V_FLAG_X509_STRICT)) { + ctx->error = X509_V_ERR_INVALID_EXTENSION; + ret = 0; + } if (ret == 0 && !verify_cb_cert(ctx, x, i, X509_V_OK)) return 0; /* check_purpose() makes the callback as needed */ @@ -1212,7 +1228,7 @@ static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, X509 **pissuer, int *pcrl_score) { X509 *crl_issuer = NULL; - X509_NAME *cnm = X509_CRL_get_issuer(crl); + const X509_NAME *cnm = X509_CRL_get_issuer(crl); int cidx = ctx->error_depth; int i; @@ -1388,7 +1404,7 @@ static int idp_check_dp(DIST_POINT_NAME *a, DIST_POINT_NAME *b) static int crldp_check_crlissuer(DIST_POINT *dp, X509_CRL *crl, int crl_score) { int i; - X509_NAME *nm = X509_CRL_get_issuer(crl); + const X509_NAME *nm = X509_CRL_get_issuer(crl); /* If no CRLissuer return is successful iff don't need a match */ if (!dp->CRLissuer) return ! !(crl_score & CRL_SCORE_ISSUER_NAME); @@ -1447,7 +1463,7 @@ static int get_crl_delta(X509_STORE_CTX *ctx, unsigned int reasons; X509_CRL *crl = NULL, *dcrl = NULL; STACK_OF(X509_CRL) *skcrl; - X509_NAME *nm = X509_get_issuer_name(x); + const X509_NAME *nm = X509_get_issuer_name(x); reasons = ctx->current_reasons; ok = get_crl_sk(ctx, &crl, &dcrl, @@ -2052,12 +2068,12 @@ int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data) return CRYPTO_set_ex_data(&ctx->ex_data, idx, data); } -void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx) +void *X509_STORE_CTX_get_ex_data(const X509_STORE_CTX *ctx, int idx) { return CRYPTO_get_ex_data(&ctx->ex_data, idx); } -int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx) +int X509_STORE_CTX_get_error(const X509_STORE_CTX *ctx) { return ctx->error; } @@ -2067,7 +2083,7 @@ void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err) ctx->error = err; } -int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx) +int X509_STORE_CTX_get_error_depth(const X509_STORE_CTX *ctx) { return ctx->error_depth; } @@ -2077,7 +2093,7 @@ 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) +X509 *X509_STORE_CTX_get_current_cert(const X509_STORE_CTX *ctx) { return ctx->current_cert; } @@ -2087,29 +2103,29 @@ void X509_STORE_CTX_set_current_cert(X509_STORE_CTX *ctx, X509 *x) ctx->current_cert = x; } -STACK_OF(X509) *X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx) +STACK_OF(X509) *X509_STORE_CTX_get0_chain(const X509_STORE_CTX *ctx) { return ctx->chain; } -STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx) +STACK_OF(X509) *X509_STORE_CTX_get1_chain(const X509_STORE_CTX *ctx) { if (!ctx->chain) return NULL; return X509_chain_up_ref(ctx->chain); } -X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx) +X509 *X509_STORE_CTX_get0_current_issuer(const X509_STORE_CTX *ctx) { return ctx->current_issuer; } -X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx) +X509_CRL *X509_STORE_CTX_get0_current_crl(const X509_STORE_CTX *ctx) { return ctx->current_crl; } -X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx) +X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(const X509_STORE_CTX *ctx) { return ctx->parent; } @@ -2205,23 +2221,45 @@ int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, return 1; } -X509_STORE_CTX *X509_STORE_CTX_new(void) +X509_STORE_CTX *X509_STORE_CTX_new_with_libctx(OPENSSL_CTX *libctx, + const char *propq) { X509_STORE_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); if (ctx == NULL) { - X509err(X509_F_X509_STORE_CTX_NEW, ERR_R_MALLOC_FAILURE); + X509err(0, ERR_R_MALLOC_FAILURE); return NULL; } + + ctx->libctx = libctx; + if (propq != NULL) { + ctx->propq = OPENSSL_strdup(propq); + if (ctx->propq == NULL) { + OPENSSL_free(ctx); + X509err(0, ERR_R_MALLOC_FAILURE); + return NULL; + } + } + return ctx; } +X509_STORE_CTX *X509_STORE_CTX_new(void) +{ + return X509_STORE_CTX_new_with_libctx(NULL, NULL); +} + + void X509_STORE_CTX_free(X509_STORE_CTX *ctx) { if (ctx == NULL) return; X509_STORE_CTX_cleanup(ctx); + + /* libctx and propq survive X509_STORE_CTX_cleanup() */ + OPENSSL_free(ctx->propq); + OPENSSL_free(ctx); } @@ -2416,12 +2454,12 @@ void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, X509_VERIFY_PARAM_set_time(ctx->param, t); } -X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx) +X509 *X509_STORE_CTX_get0_cert(const X509_STORE_CTX *ctx) { return ctx->cert; } -STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx) +STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(const X509_STORE_CTX *ctx) { return ctx->untrusted; } @@ -2443,7 +2481,7 @@ void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, ctx->verify_cb = verify_cb; } -X509_STORE_CTX_verify_cb X509_STORE_CTX_get_verify_cb(X509_STORE_CTX *ctx) +X509_STORE_CTX_verify_cb X509_STORE_CTX_get_verify_cb(const X509_STORE_CTX *ctx) { return ctx->verify_cb; } @@ -2454,72 +2492,77 @@ void X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx, ctx->verify = verify; } -X509_STORE_CTX_verify_fn X509_STORE_CTX_get_verify(X509_STORE_CTX *ctx) +X509_STORE_CTX_verify_fn X509_STORE_CTX_get_verify(const X509_STORE_CTX *ctx) { return ctx->verify; } -X509_STORE_CTX_get_issuer_fn X509_STORE_CTX_get_get_issuer(X509_STORE_CTX *ctx) +X509_STORE_CTX_get_issuer_fn X509_STORE_CTX_get_get_issuer(const X509_STORE_CTX *ctx) { return ctx->get_issuer; } -X509_STORE_CTX_check_issued_fn X509_STORE_CTX_get_check_issued(X509_STORE_CTX *ctx) +X509_STORE_CTX_check_issued_fn + X509_STORE_CTX_get_check_issued(const X509_STORE_CTX *ctx) { return ctx->check_issued; } -X509_STORE_CTX_check_revocation_fn X509_STORE_CTX_get_check_revocation(X509_STORE_CTX *ctx) +X509_STORE_CTX_check_revocation_fn + X509_STORE_CTX_get_check_revocation(const X509_STORE_CTX *ctx) { return ctx->check_revocation; } -X509_STORE_CTX_get_crl_fn X509_STORE_CTX_get_get_crl(X509_STORE_CTX *ctx) +X509_STORE_CTX_get_crl_fn X509_STORE_CTX_get_get_crl(const X509_STORE_CTX *ctx) { return ctx->get_crl; } -X509_STORE_CTX_check_crl_fn X509_STORE_CTX_get_check_crl(X509_STORE_CTX *ctx) +X509_STORE_CTX_check_crl_fn X509_STORE_CTX_get_check_crl(const X509_STORE_CTX *ctx) { return ctx->check_crl; } -X509_STORE_CTX_cert_crl_fn X509_STORE_CTX_get_cert_crl(X509_STORE_CTX *ctx) +X509_STORE_CTX_cert_crl_fn X509_STORE_CTX_get_cert_crl(const X509_STORE_CTX *ctx) { return ctx->cert_crl; } -X509_STORE_CTX_check_policy_fn X509_STORE_CTX_get_check_policy(X509_STORE_CTX *ctx) +X509_STORE_CTX_check_policy_fn + X509_STORE_CTX_get_check_policy(const X509_STORE_CTX *ctx) { return ctx->check_policy; } -X509_STORE_CTX_lookup_certs_fn X509_STORE_CTX_get_lookup_certs(X509_STORE_CTX *ctx) +X509_STORE_CTX_lookup_certs_fn + X509_STORE_CTX_get_lookup_certs(const X509_STORE_CTX *ctx) { return ctx->lookup_certs; } -X509_STORE_CTX_lookup_crls_fn X509_STORE_CTX_get_lookup_crls(X509_STORE_CTX *ctx) +X509_STORE_CTX_lookup_crls_fn + X509_STORE_CTX_get_lookup_crls(const X509_STORE_CTX *ctx) { return ctx->lookup_crls; } -X509_STORE_CTX_cleanup_fn X509_STORE_CTX_get_cleanup(X509_STORE_CTX *ctx) +X509_STORE_CTX_cleanup_fn X509_STORE_CTX_get_cleanup(const X509_STORE_CTX *ctx) { return ctx->cleanup; } -X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx) +X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(const X509_STORE_CTX *ctx) { return ctx->tree; } -int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx) +int X509_STORE_CTX_get_explicit_policy(const X509_STORE_CTX *ctx) { return ctx->explicit_policy; } -int X509_STORE_CTX_get_num_untrusted(X509_STORE_CTX *ctx) +int X509_STORE_CTX_get_num_untrusted(const X509_STORE_CTX *ctx) { return ctx->num_untrusted; } @@ -2534,7 +2577,7 @@ int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name) return X509_VERIFY_PARAM_inherit(ctx->param, param); } -X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx) +X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(const X509_STORE_CTX *ctx) { return ctx->param; } @@ -2890,7 +2933,7 @@ static int build_chain(X509_STORE_CTX *ctx) SSL_DANE *dane = ctx->dane; int num = sk_X509_num(ctx->chain); X509 *cert = sk_X509_value(ctx->chain, num - 1); - int ss = cert_self_signed(cert); + int ss; STACK_OF(X509) *sktmp = NULL; unsigned int search; int may_trusted = 0; @@ -2908,6 +2951,13 @@ static int build_chain(X509_STORE_CTX *ctx) return 0; } + ss = cert_self_signed(ctx, cert); + if (ss < 0) { + X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR); + ctx->error = X509_V_ERR_UNSPECIFIED; + return 0; + } + #define S_DOUNTRUSTED (1 << 0) /* Search untrusted chain */ #define S_DOTRUSTED (1 << 1) /* Search trusted store */ #define S_DOALTERNATE (1 << 2) /* Retry with pruned alternate chain */ @@ -3080,7 +3130,12 @@ static int build_chain(X509_STORE_CTX *ctx) search = 0; continue; } - ss = cert_self_signed(x); + ss = cert_self_signed(ctx, x); + if (ss < 0) { + X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR); + ctx->error = X509_V_ERR_UNSPECIFIED; + return 0; + } } else if (num == ctx->num_untrusted) { /* * We have a self-signed certificate that has the same @@ -3192,7 +3247,12 @@ static int build_chain(X509_STORE_CTX *ctx) X509_up_ref(x = xtmp); ++ctx->num_untrusted; - ss = cert_self_signed(xtmp); + ss = cert_self_signed(ctx, xtmp); + if (ss < 0) { + X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR); + ctx->error = X509_V_ERR_UNSPECIFIED; + return 0; + } /* * Check for DANE-TA trust of the topmost untrusted certificate. diff --git a/crypto/x509/x509_vpm.c b/crypto/x509/x509_vpm.c index 27156b9b..b2b34d98 100644 --- a/crypto/x509/x509_vpm.c +++ b/crypto/x509/x509_vpm.c @@ -398,7 +398,7 @@ unsigned int X509_VERIFY_PARAM_get_hostflags(const X509_VERIFY_PARAM *param) return param->hostflags; } -char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param) +char *X509_VERIFY_PARAM_get0_peername(const X509_VERIFY_PARAM *param) { return param->peername; } diff --git a/crypto/x509/x509cset.c b/crypto/x509/x509cset.c index 23509952..28b3aba0 100644 --- a/crypto/x509/x509cset.c +++ b/crypto/x509/x509cset.c @@ -27,7 +27,7 @@ int X509_CRL_set_version(X509_CRL *x, long version) return ASN1_INTEGER_set(x->crl.version, version); } -int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name) +int X509_CRL_set_issuer_name(X509_CRL *x, const X509_NAME *name) { if (x == NULL) return 0; diff --git a/crypto/x509/x509name.c b/crypto/x509/x509name.c index 443ab42b..e674d6be 100644 --- a/crypto/x509/x509name.c +++ b/crypto/x509/x509name.c @@ -16,7 +16,8 @@ #include #include "crypto/x509.h" -int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len) +int X509_NAME_get_text_by_NID(const X509_NAME *name, int nid, + char *buf, int len) { ASN1_OBJECT *obj; @@ -26,7 +27,7 @@ int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len) return X509_NAME_get_text_by_OBJ(name, obj, buf, len); } -int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, +int X509_NAME_get_text_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj, char *buf, int len) { int i; @@ -53,7 +54,7 @@ int X509_NAME_entry_count(const X509_NAME *name) return sk_X509_NAME_ENTRY_num(name->entries); } -int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos) +int X509_NAME_get_index_by_NID(const X509_NAME *name, int nid, int lastpos) { ASN1_OBJECT *obj; @@ -64,7 +65,8 @@ int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos) } /* NOTE: you should be passing -1, not 0 as lastpos */ -int X509_NAME_get_index_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int lastpos) +int X509_NAME_get_index_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj, + int lastpos) { int n; X509_NAME_ENTRY *ne; @@ -216,11 +218,7 @@ int X509_NAME_add_entry(X509_NAME *name, const X509_NAME_ENTRY *ne, int loc, set = sk_X509_NAME_ENTRY_value(sk, loc)->set; } - /* - * X509_NAME_ENTRY_dup is ASN1 generated code, that can't be easily - * const'ified; harmless cast since dup() don't modify its input. - */ - if ((new_name = X509_NAME_ENTRY_dup((X509_NAME_ENTRY *)ne)) == NULL) + if ((new_name = X509_NAME_ENTRY_dup(ne)) == NULL) goto err; new_name->set = set; if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) { diff --git a/crypto/x509/x509rset.c b/crypto/x509/x509rset.c index 3256ec23..aeb5a556 100644 --- a/crypto/x509/x509rset.c +++ b/crypto/x509/x509rset.c @@ -23,7 +23,7 @@ int X509_REQ_set_version(X509_REQ *x, long version) return ASN1_INTEGER_set(x->req_info.version, version); } -int X509_REQ_set_subject_name(X509_REQ *x, X509_NAME *name) +int X509_REQ_set_subject_name(X509_REQ *x, const X509_NAME *name) { if (x == NULL) return 0; diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c index 6a6748ba..ce8c23b6 100644 --- a/crypto/x509/x_all.c +++ b/crypto/x509/x_all.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -71,10 +71,7 @@ int X509_verify(X509 *a, EVP_PKEY *r) if (X509_ALGOR_cmp(&a->sig_alg, &a->cert_info.signature)) return 0; -#ifndef OPENSSL_NO_SM2 - id = a->sm2_id; -#endif - + id = a->distinguishing_id; if ((ctx = make_id_ctx(r, id)) != NULL) { rv = ASN1_item_verify_ctx(ASN1_ITEM_rptr(X509_CINF), &a->sig_alg, &a->signature, &a->cert_info, ctx); @@ -89,10 +86,7 @@ int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r) EVP_MD_CTX *ctx = NULL; ASN1_OCTET_STRING *id = NULL; -#ifndef OPENSSL_NO_SM2 - id = a->sm2_id; -#endif - + id = a->distinguishing_id; if ((ctx = make_id_ctx(r, id)) != NULL) { rv = ASN1_item_verify_ctx(ASN1_ITEM_rptr(X509_REQ_INFO), &a->sig_alg, a->signature, &a->req_info, ctx); @@ -127,7 +121,7 @@ int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx) static ASN1_VALUE *simple_get_asn1(const char *url, BIO *bio, BIO *rbio, int timeout, const ASN1_ITEM *it) { - return OSSL_HTTP_get_asn1(url, NULL, NULL /* no proxy and port */, bio, + return OSSL_HTTP_get_asn1(url, NULL, NULL /* no proxy used */, bio, rbio, NULL /* no callback for SSL/TLS */, NULL, NULL /* headers */, 1024 /* maxline */, 0 /* max_resp_len */, timeout, @@ -439,7 +433,8 @@ int X509_pubkey_digest(const X509 *data, const EVP_MD *type, int X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md, unsigned int *len) { - if (type == EVP_sha1() && (data->ex_flags & EXFLAG_SET) != 0) { + if (type == EVP_sha1() && (data->ex_flags & EXFLAG_SET) != 0 + && (data->ex_flags & EXFLAG_INVALID) == 0) { /* Asking for SHA1 and we already computed it. */ if (len != NULL) *len = sizeof(data->sha1_hash); @@ -450,10 +445,40 @@ int X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md, (ASN1_ITEM_rptr(X509), type, (char *)data, md, len)); } +/* calculate cert digest using the same hash algorithm as in its signature */ +ASN1_OCTET_STRING *X509_digest_sig(const X509 *cert) +{ + unsigned int len; + unsigned char hash[EVP_MAX_MD_SIZE]; + int md_NID; + const EVP_MD *md = NULL; + ASN1_OCTET_STRING *new = NULL; + + if (cert == NULL) { + X509err(0, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if (!OBJ_find_sigid_algs(X509_get_signature_nid(cert), &md_NID, NULL) + || (md = EVP_get_digestbynid(md_NID)) == NULL) { + CMPerr(0, X509_R_UNSUPPORTED_ALGORITHM); + return NULL; + } + if (!X509_digest(cert, md, hash, &len) + || (new = ASN1_OCTET_STRING_new()) == NULL) + return NULL; + if (!(ASN1_OCTET_STRING_set(new, hash, len))) { + ASN1_OCTET_STRING_free(new); + return NULL; + } + return new; +} + int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type, unsigned char *md, unsigned int *len) { - if (type == EVP_sha1() && (data->flags & EXFLAG_SET) != 0) { + if (type == EVP_sha1() && (data->flags & EXFLAG_SET) != 0 + && (data->flags & EXFLAG_INVALID) == 0) { /* Asking for SHA1; always computed in CRL d2i. */ if (len != NULL) *len = sizeof(data->sha1_hash); diff --git a/crypto/x509/x_crl.c b/crypto/x509/x_crl.c index fdc05912..0f53be71 100644 --- a/crypto/x509/x_crl.c +++ b/crypto/x509/x_crl.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -17,7 +17,7 @@ static int X509_REVOKED_cmp(const X509_REVOKED *const *a, const X509_REVOKED *const *b); -static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp); +static int setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp); ASN1_SEQUENCE(X509_REVOKED) = { ASN1_EMBED(X509_REVOKED,serialNumber, ASN1_INTEGER), @@ -27,8 +27,8 @@ ASN1_SEQUENCE(X509_REVOKED) = { static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r); static int def_crl_lookup(X509_CRL *crl, - X509_REVOKED **ret, ASN1_INTEGER *serial, - X509_NAME *issuer); + X509_REVOKED **ret, const ASN1_INTEGER *serial, + const X509_NAME *issuer); static X509_CRL_METHOD int_crl_meth = { 0, @@ -155,7 +155,7 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, X509_CRL *crl = (X509_CRL *)*pval; STACK_OF(X509_EXTENSION) *exts; X509_EXTENSION *ext; - int idx; + int idx, i; switch (operation) { case ASN1_OP_D2I_PRE: @@ -184,23 +184,35 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, break; case ASN1_OP_D2I_POST: - X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL); + if (!X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL)) + crl->flags |= EXFLAG_INVALID; crl->idp = X509_CRL_get_ext_d2i(crl, - NID_issuing_distribution_point, NULL, + NID_issuing_distribution_point, &i, NULL); - if (crl->idp) - setup_idp(crl, crl->idp); + if (crl->idp != NULL) { + if (!setup_idp(crl, crl->idp)) + crl->flags |= EXFLAG_INVALID; + } + else if (i != -1) { + crl->flags |= EXFLAG_INVALID; + } crl->akid = X509_CRL_get_ext_d2i(crl, - NID_authority_key_identifier, NULL, + NID_authority_key_identifier, &i, NULL); + if (crl->akid == NULL && i != -1) + crl->flags |= EXFLAG_INVALID; crl->crl_number = X509_CRL_get_ext_d2i(crl, - NID_crl_number, NULL, NULL); + NID_crl_number, &i, NULL); + if (crl->crl_number == NULL && i != -1) + crl->flags |= EXFLAG_INVALID; crl->base_crl_number = X509_CRL_get_ext_d2i(crl, - NID_delta_crl, NULL, + NID_delta_crl, &i, NULL); + if (crl->base_crl_number == NULL && i != -1) + crl->flags |= EXFLAG_INVALID; /* Delta CRLs must have CRL number */ if (crl->base_crl_number && !crl->crl_number) crl->flags |= EXFLAG_INVALID; @@ -259,9 +271,10 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, /* Convert IDP into a more convenient form */ -static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp) +static int setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp) { int idp_only = 0; + /* Set various flags according to IDP */ crl->idp_flags |= IDP_PRESENT; if (idp->onlyuser > 0) { @@ -292,7 +305,7 @@ static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp) crl->idp_reasons &= CRLDP_ALL_REASONS; } - DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl)); + return DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl)); } ASN1_SEQUENCE_ref(X509_CRL, crl_cb) = { @@ -341,7 +354,7 @@ int X509_CRL_verify(X509_CRL *crl, EVP_PKEY *r) } int X509_CRL_get0_by_serial(X509_CRL *crl, - X509_REVOKED **ret, ASN1_INTEGER *serial) + X509_REVOKED **ret, const ASN1_INTEGER *serial) { if (crl->meth->crl_lookup) return crl->meth->crl_lookup(crl, ret, serial, NULL); @@ -363,7 +376,7 @@ static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r) &crl->sig_alg, &crl->signature, &crl->crl, r)); } -static int crl_revoked_issuer_match(X509_CRL *crl, X509_NAME *nm, +static int crl_revoked_issuer_match(X509_CRL *crl, const X509_NAME *nm, X509_REVOKED *rev) { int i; @@ -391,8 +404,8 @@ static int crl_revoked_issuer_match(X509_CRL *crl, X509_NAME *nm, } static int def_crl_lookup(X509_CRL *crl, - X509_REVOKED **ret, ASN1_INTEGER *serial, - X509_NAME *issuer) + X509_REVOKED **ret, const ASN1_INTEGER *serial, + const X509_NAME *issuer) { X509_REVOKED rtmp, *rev; int idx, num; @@ -441,8 +454,8 @@ X509_CRL_METHOD *X509_CRL_METHOD_new(int (*crl_init) (X509_CRL *crl), int (*crl_free) (X509_CRL *crl), int (*crl_lookup) (X509_CRL *crl, X509_REVOKED **ret, - ASN1_INTEGER *ser, - X509_NAME *issuer), + const ASN1_INTEGER *ser, + const X509_NAME *issuer), int (*crl_verify) (X509_CRL *crl, EVP_PKEY *pk)) { diff --git a/crypto/x509/x_name.c b/crypto/x509/x_name.c index 59d6531b..b820171b 100644 --- a/crypto/x509/x_name.c +++ b/crypto/x509/x_name.c @@ -542,7 +542,7 @@ int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase) return 0; } -int X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder, +int X509_NAME_get0_der(const X509_NAME *nm, const unsigned char **pder, size_t *pderlen) { /* Make sure encoding is valid */ diff --git a/crypto/x509/x_req.c b/crypto/x509/x_req.c index e9cc9ba4..d8a89011 100644 --- a/crypto/x509/x_req.c +++ b/crypto/x509/x_req.c @@ -53,14 +53,14 @@ static int req_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, switch (operation) { case ASN1_OP_D2I_PRE: - ASN1_OCTET_STRING_free(ret->sm2_id); + ASN1_OCTET_STRING_free(ret->distinguishing_id); /* fall thru */ case ASN1_OP_NEW_POST: - ret->sm2_id = NULL; + ret->distinguishing_id = NULL; break; case ASN1_OP_FREE_POST: - ASN1_OCTET_STRING_free(ret->sm2_id); + ASN1_OCTET_STRING_free(ret->distinguishing_id); break; } #endif @@ -90,15 +90,13 @@ IMPLEMENT_ASN1_FUNCTIONS(X509_REQ) IMPLEMENT_ASN1_DUP_FUNCTION(X509_REQ) -#ifndef OPENSSL_NO_SM2 -void X509_REQ_set0_sm2_id(X509_REQ *x, ASN1_OCTET_STRING *sm2_id) +void X509_REQ_set0_distinguishing_id(X509_REQ *x, ASN1_OCTET_STRING *d_id) { - ASN1_OCTET_STRING_free(x->sm2_id); - x->sm2_id = sm2_id; + ASN1_OCTET_STRING_free(x->distinguishing_id); + x->distinguishing_id = d_id; } -ASN1_OCTET_STRING *X509_REQ_get0_sm2_id(X509_REQ *x) +ASN1_OCTET_STRING *X509_REQ_get0_distinguishing_id(X509_REQ *x) { - return x->sm2_id; + return x->distinguishing_id; } -#endif diff --git a/crypto/x509/x_x509.c b/crypto/x509/x_x509.c index 7b41ce07..75b17101 100644 --- a/crypto/x509/x_x509.c +++ b/crypto/x509/x_x509.c @@ -53,9 +53,7 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free); ASIdentifiers_free(ret->rfc3779_asid); #endif -#ifndef OPENSSL_NO_SM2 - ASN1_OCTET_STRING_free(ret->sm2_id); -#endif + ASN1_OCTET_STRING_free(ret->distinguishing_id); /* fall thru */ @@ -76,9 +74,7 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, ret->rfc3779_addr = NULL; ret->rfc3779_asid = NULL; #endif -#ifndef OPENSSL_NO_SM2 - ret->sm2_id = NULL; -#endif + ret->distinguishing_id = NULL; ret->aux = NULL; ret->crldp = NULL; if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data)) @@ -98,9 +94,7 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free); ASIdentifiers_free(ret->rfc3779_asid); #endif -#ifndef OPENSSL_NO_SM2 - ASN1_OCTET_STRING_free(ret->sm2_id); -#endif + ASN1_OCTET_STRING_free(ret->distinguishing_id); break; } @@ -123,7 +117,7 @@ int X509_set_ex_data(X509 *r, int idx, void *arg) return CRYPTO_set_ex_data(&r->ex_data, idx, arg); } -void *X509_get_ex_data(X509 *r, int idx) +void *X509_get_ex_data(const X509 *r, int idx) { return CRYPTO_get_ex_data(&r->ex_data, idx); } @@ -254,15 +248,13 @@ int X509_get_signature_nid(const X509 *x) return OBJ_obj2nid(x->sig_alg.algorithm); } -#ifndef OPENSSL_NO_SM2 -void X509_set0_sm2_id(X509 *x, ASN1_OCTET_STRING *sm2_id) +void X509_set0_distinguishing_id(X509 *x, ASN1_OCTET_STRING *d_id) { - ASN1_OCTET_STRING_free(x->sm2_id); - x->sm2_id = sm2_id; + ASN1_OCTET_STRING_free(x->distinguishing_id); + x->distinguishing_id = d_id; } -ASN1_OCTET_STRING *X509_get0_sm2_id(X509 *x) +ASN1_OCTET_STRING *X509_get0_distinguishing_id(X509 *x) { - return x->sm2_id; + return x->distinguishing_id; } -#endif diff --git a/demos/pkcs12/pkread.c b/demos/pkcs12/pkread.c index 33fba5d2..d29ab98a 100644 --- a/demos/pkcs12/pkread.c +++ b/demos/pkcs12/pkread.c @@ -79,7 +79,7 @@ int main(int argc, char **argv) name = find_friendly_name(p12); PKCS12_free(p12); if ((fp = fopen(argv[3], "w")) == NULL) { - fprintf(stderr, "Error opening file %s\n", argv[1]); + fprintf(stderr, "Error opening file %s\n", argv[3]); goto err; } if (name != NULL) diff --git a/demos/pkcs12/pkwrite.c b/demos/pkcs12/pkwrite.c index e9ad8cde..262b49dc 100644 --- a/demos/pkcs12/pkwrite.c +++ b/demos/pkcs12/pkwrite.c @@ -42,7 +42,7 @@ int main(int argc, char **argv) exit(1); } if ((fp = fopen(argv[4], "wb")) == NULL) { - fprintf(stderr, "Error opening file %s\n", argv[1]); + fprintf(stderr, "Error opening file %s\n", argv[4]); ERR_print_errors_fp(stderr); exit(1); } diff --git a/doc/internal/man3/DER_w_begin_sequence.pod b/doc/internal/man3/DER_w_begin_sequence.pod new file mode 100644 index 00000000..3d221a94 --- /dev/null +++ b/doc/internal/man3/DER_w_begin_sequence.pod @@ -0,0 +1,48 @@ +=pod + +=head1 NAME + +DER_w_begin_sequence, DER_w_end_sequence +- internal DER writers for DER constructed elements + +=head1 SYNOPSIS + + #include "internal/der.h" + + int DER_w_begin_sequence(WPACKET *pkt, int tag); + int DER_w_end_sequence(WPACKET *pkt, int tag); + +=head1 DESCRIPTION + +All functions described here are wrappers for constructed structures, +i.e. the ASN.1 SEQUENCE, SET and CHOICE specifications. They all come +in pairs, as noted by the function names containing the words C +and B. + +When using these, special care must be taken to ensure that the ASN.1 tag +value I is the same in the matching C and C function calls. + +DER_w_begin_sequence() and DER_w_end_sequence() begins and ends a +SEQUENCE. + +=head1 RETURN VALUES + +All the functions return 1 on success and 0 on failure. Failure may +mean that the buffer held by the I is too small, but may also +mean that the values given to the functions are invalid, such as the provided +I value being too large for the implementation. + +=head1 SEE ALSO + +L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/internal/man3/DER_w_bn.pod b/doc/internal/man3/DER_w_bn.pod new file mode 100644 index 00000000..c51223f7 --- /dev/null +++ b/doc/internal/man3/DER_w_bn.pod @@ -0,0 +1,56 @@ +=pod + +=head1 NAME + +DER_w_boolean, DER_w_ulong, DER_w_bn, DER_w_null +- internal DER writers for DER primitives + +=head1 SYNOPSIS + + #include "internal/der.h" + + int DER_w_boolean(WPACKET *pkt, int tag, int b); + int DER_w_ulong(WPACKET *pkt, int tag, unsigned long v); + int DER_w_bn(WPACKET *pkt, int tag, const BIGNUM *v); + int DER_w_null(WPACKET *pkt, int tag); + +=head1 DESCRIPTION + +All functions described here behave the same way, they prepend +(remember that DER writers are used backwards) the DER encoding of +their respective value to the already written output buffer held by +I. + +DER_w_boolean() writes the primitive BOOLEAN using the value I. +Any value that evaluates as true will render a B BOOLEAN, +otherwise a B BOOLEAN. + +DER_w_ulong() and DER_w_bn() both write the primitive INTEGER using +the value I. + +=for comment Other similar functions for diverse C integers should be +added. + +DER_w_null() writes the primitive NULL. + +=head1 RETURN VALUES + +All the functions return 1 on success and 0 on failure. Failure may +mean that the buffer held by the I is too small, but may also +mean that the values given to the functions are invalid, such as the provided +I value being too large for the implementation. + +=head1 SEE ALSO + +L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/internal/man3/DER_w_precompiled.pod b/doc/internal/man3/DER_w_precompiled.pod new file mode 100644 index 00000000..81a92526 --- /dev/null +++ b/doc/internal/man3/DER_w_precompiled.pod @@ -0,0 +1,48 @@ +=pod + +=head1 NAME + +DER_w_precompiled +- internal DER writers for precompiled DER blobs + +=head1 SYNOPSIS + + #include "internal/der.h" + + int DER_w_precompiled(WPACKET *pkt, int tag, + const unsigned char *precompiled, + size_t precompiled_n); + +=head1 DESCRIPTION + +There may be already existing DER blobs that can simply be copied to +the buffer held by I. For example, precompiled values, such as +OIDs (for example, C) or complete AlgorithmIdentifiers +(for example, C). To add those as an element in a +structure being DER encoded, use DER_w_precompiled(). + +DER_w_precompiled() will simply take the DER encoded blob given as +I with length I and add it to the buffer +held by I. + +=head1 RETURN VALUES + +DER_w_precompiled() returns 1 on success and 0 on failure. Failure +may mean that the buffer held by the I is too small, but may also +mean that the values given to the functions are invalid, such as the provided +I value being too large for the implementation. + +=head1 SEE ALSO + +L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/internal/man3/DEFINE_SPARSE_ARRAY_OF.pod b/doc/internal/man3/OPENSSL_SA.pod similarity index 98% rename from doc/internal/man3/DEFINE_SPARSE_ARRAY_OF.pod rename to doc/internal/man3/OPENSSL_SA.pod index a78193c2..77f1a7b1 100644 --- a/doc/internal/man3/DEFINE_SPARSE_ARRAY_OF.pod +++ b/doc/internal/man3/OPENSSL_SA.pod @@ -2,15 +2,13 @@ =head1 NAME -DEFINE_SPARSE_ARRAY_OF, ossl_sa_TYPE_new, ossl_sa_TYPE_free, +OPENSSL_SA, ossl_sa_TYPE_new, ossl_sa_TYPE_free, ossl_sa_TYPE_free_leaves, ossl_sa_TYPE_num, ossl_sa_TYPE_doall, ossl_sa_TYPE_doall_arg, ossl_sa_TYPE_get, ossl_sa_TYPE_set - sparse array container =head1 SYNOPSIS -=for openssl generic - #include "crypto/sparse_array.h" typedef struct sparse_array_st OPENSSL_SA; diff --git a/doc/internal/man3/ossl_cmp_hdr_init.pod b/doc/internal/man3/ossl_cmp_hdr_init.pod index a7a4d87f..5df7486c 100644 --- a/doc/internal/man3/ossl_cmp_hdr_init.pod +++ b/doc/internal/man3/ossl_cmp_hdr_init.pod @@ -5,6 +5,7 @@ ossl_cmp_hdr_set_pvno, ossl_cmp_hdr_get_pvno, ossl_cmp_hdr_get0_sendernonce, +ossl_cmp_general_name_is_NULL_DN, ossl_cmp_hdr_set1_sender, ossl_cmp_hdr_set1_recipient, ossl_cmp_hdr_update_messagetime, @@ -14,7 +15,7 @@ ossl_cmp_hdr_push1_freeText, ossl_cmp_hdr_generalinfo_item_push0, ossl_cmp_hdr_generalinfo_items_push1, ossl_cmp_hdr_set_implicitConfirm, -ossl_cmp_hdr_check_implicitConfirm, +ossl_cmp_hdr_has_implicitConfirm, ossl_cmp_hdr_init - functions manipulating CMP message headers @@ -26,6 +27,7 @@ ossl_cmp_hdr_init int ossl_cmp_hdr_get_pvno(const OSSL_CMP_PKIHEADER *hdr); ASN1_OCTET_STRING *ossl_cmp_hdr_get0_sendernonce(const OSSL_CMP_PKIHEADER *hdr); + int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name); int ossl_cmp_hdr_set1_sender(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm); int ossl_cmp_hdr_set1_recipient(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm); @@ -41,7 +43,7 @@ ossl_cmp_hdr_init int ossl_cmp_hdr_push1_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text); int ossl_cmp_hdr_set_implicitConfirm(OSSL_CMP_PKIHEADER *hdr); - int ossl_cmp_hdr_check_implicitConfirm(OSSL_CMP_PKIHEADER *hdr); + int ossl_cmp_hdr_has_implicitConfirm(OSSL_CMP_PKIHEADER *hdr); int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr); =head1 DESCRIPTION @@ -52,6 +54,9 @@ ossl_cmp_hdr_get_pvno() returns the pvno of the given B or -1 on error. ossl_cmp_hdr_get0_sendernonce() returns the sender nonce of the given PKIHeader. +ossl_cmp_general_name_is_NULL_DN() determines if the given GENERAL_NAME +is the NULL-DN. + ossl_cmp_hdr_set1_sender() sets the sender field in the given PKIHeader to the given X509 Name value, without consuming the pointer. @@ -85,7 +90,7 @@ pointer. ossl_cmp_hdr_set_implicitConfirm() sets implicitConfirm in the generalInfo field of the PKIMessage header. -ossl_cmp_hdr_check_implicitConfirm() returns 1 if implicitConfirm is +ossl_cmp_hdr_has_implicitConfirm() returns 1 if implicitConfirm is set int generalInfo field of the given PKIMessage header, 0 if not. ossl_cmp_hdr_init() initializes a PKIHeader structure based on the @@ -107,6 +112,8 @@ ossl_cmp_hdr_get_pvno() returns the pvno of the given B or -1 on error. ossl_cmp_hdr_get0_sendernonce() returns the respective nonce. +ossl_cmp_general_name_is_NULL_DN() returns 1 given a NULL-DN, else 0. + All other functions return 1 on success, 0 on error. See the individual functions above. diff --git a/doc/internal/man3/ossl_cmp_mock_srv_new.pod b/doc/internal/man3/ossl_cmp_mock_srv_new.pod new file mode 100644 index 00000000..da1f44b3 --- /dev/null +++ b/doc/internal/man3/ossl_cmp_mock_srv_new.pod @@ -0,0 +1,85 @@ +=pod + +=head1 NAME + +ossl_cmp_mock_srv_new, +ossl_cmp_mock_srv_free, +ossl_cmp_mock_srv_set1_certOut, +ossl_cmp_mock_srv_set1_chainOut, +ossl_cmp_mock_srv_set1_caPubsOut, +ossl_cmp_mock_srv_set_statusInfo, +ossl_cmp_mock_srv_set_send_error, +ossl_cmp_mock_srv_set_pollCount, +ossl_cmp_mock_srv_set_checkAfterTime +- functions used for testing with CMP mock server + +=head1 SYNOPSIS + + #include + + OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(void); + void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX *srv_ctx); + + int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert); + int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx, + STACK_OF(X509) *chain); + int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx, + STACK_OF(X509) *caPubs); + int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status, + int fail_info, const char *text); + int ossl_cmp_mock_srv_set_send_error(OSSL_CMP_SRV_CTX *srv_ctx, int val); + int ossl_cmp_mock_srv_set_pollCount(OSSL_CMP_SRV_CTX *srv_ctx, int count); + int ossl_cmp_mock_srv_set_checkAfterTime(OSSL_CMP_SRV_CTX *srv_ctx, int sec); + +=head1 DESCRIPTION + +ossl_cmp_mock_srv_new() allocates the contexts for the CMP mock server. + +ossl_cmp_mock_srv_free() deallocates the contexts for the CMP mock server. + +OSSL_CMP_SRV_CTX_set1_certOut() sets the certificate to be returned in +cp/ip/kup. + +OSSL_CMP_SRV_CTX_set1_chainOut() sets the certificate chain to be added to +the extraCerts in a cp/ip/kup. +It should to useful to validate B. + +OSSL_CMP_SRV_CTX_set1_caPubsOut() sets the caPubs to be returned in an ip. + +OSSL_CMP_SRV_CTX_set_statusInfo() sets the status info to be returned. + +OSSL_CMP_SRV_CTX_set_send_error() enables enforcement of error responses. + +OSSL_CMP_SRV_CTX_set_pollCount() sets the number of polls before cert response. + +OSSL_CMP_SRV_CTX_set_checkAfterTime() sets the number of seconds +the client should wait for the next poll. + + +=head1 NOTES + +CMP is defined in RFC 4210 (and CRMF in RFC 4211). + +=head1 RETURN VALUES + +ossl_cmp_mock_srv() returns a B structure on success, +NULL on error. + +ossl_cmp_mock_srv_free() does not return a value. + +All other functions return 1 on success, 0 on error. + +=head1 HISTORY + +The OpenSSL CMP support was added in OpenSSL 3.0. + +=head1 COPYRIGHT + +Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/internal/man3/ossl_cmp_msg_check_received.pod b/doc/internal/man3/ossl_cmp_msg_check_received.pod new file mode 100644 index 00000000..3fc7882c --- /dev/null +++ b/doc/internal/man3/ossl_cmp_msg_check_received.pod @@ -0,0 +1,86 @@ +=pod + +=head1 NAME + +ossl_cmp_allow_unprotected_cb_t, +ossl_cmp_msg_check_received +- does all checks on a received CMP message that can be done generically + +=head1 SYNOPSIS + + #include "cmp_local.h" + + typedef int (*ossl_cmp_allow_unprotected_cb_t)(const OSSL_CMP_CTX *ctx, + const OSSL_CMP_MSG *msg, + int invalid_protection, int arg); + + int ossl_cmp_msg_check_received(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, + ossl_cmp_allow_unprotected_cb_t cb, int cb_arg); + +=head1 DESCRIPTION + +ossl_cmp_msg_check_received() checks the given message B, +which may be a server response or a request by some client. + +It is ensured for the B that + +=over 4 + +=item it has a valid body type, + +=item its protection is present and valid (or a callback function B +is present and indicates that a missing or invalid protection is acceptable), + +=item its recipNonce matches any previous senderNonce stored in B, and + +=item its transaction ID matches any previous transaction ID stored in B. + +=back + +In case no protection is present and B is not NULL then this callback +function is called with its B parameter being 0, while in +case an invalid protection is present the B parameter is 1. +The callback is passed also the arguments B, B, and +(which typically contains the expected message type). +The callback should return 1 on acceptance, 0 on rejection, or -1 on error. +It should not put and error on the error stack since this could be misleading. + +If all checks pass then ossl_cmp_msg_check_received() + +=over 4 + +=item learns the senderNonce from the received message, + +=item learns the transaction ID if it is not yet in B, and + +=item adds any extraCerts contained in the to the list of untrusted +certificates in B for future use, such that +they are available already to the certificate confirmation callback and the +peer does not need to send them again (at least not in the same transaction). +For efficiency, the extraCerts are prepended to the list so they get used first. + +=back + +=head1 RETURN VALUES + +ossl_cmp_msg_check_received() returns the message body type (which is >= 0) +on success, -1 on error. + +=head1 SEE ALSO + +L + +=head1 HISTORY + +The OpenSSL CMP support was added in OpenSSL 3.0. + +=head1 COPYRIGHT + +Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/internal/man3/ossl_cmp_msg_create.pod b/doc/internal/man3/ossl_cmp_msg_create.pod index 7498a1d6..ebc08f7e 100644 --- a/doc/internal/man3/ossl_cmp_msg_create.pod +++ b/doc/internal/man3/ossl_cmp_msg_create.pod @@ -62,8 +62,7 @@ See the individual functions above. =head1 SEE ALSO -L, L, -L +L, L =head1 HISTORY diff --git a/doc/internal/man3/ossl_cmp_statusinfo_new.pod b/doc/internal/man3/ossl_cmp_pkisi_get_status.pod similarity index 58% rename from doc/internal/man3/ossl_cmp_statusinfo_new.pod rename to doc/internal/man3/ossl_cmp_pkisi_get_status.pod index ee7dd35c..deca1aa2 100644 --- a/doc/internal/man3/ossl_cmp_statusinfo_new.pod +++ b/doc/internal/man3/ossl_cmp_pkisi_get_status.pod @@ -2,13 +2,11 @@ =head1 NAME -ossl_cmp_statusinfo_new, -ossl_cmp_pkisi_pkistatus_get, -ossl_cmp_pkisi_pkifailureinfo_get, -ossl_cmp_pkisi_pkifailureinfo_check, -ossl_cmp_pkisi_failinfo_get0, -ossl_cmp_pkisi_statusstring_get0, -ossl_pkisi_snprint +ossl_cmp_pkisi_get_status, +ossl_cmp_PKIStatus_to_string, +ossl_cmp_pkisi_get0_statusString, +ossl_cmp_pkisi_get_pkifailureinfo, +ossl_cmp_pkisi_check_pkifailureinfo - functions for managing PKI status information =head1 SYNOPSIS @@ -44,40 +42,27 @@ ossl_pkisi_snprint # define OSSL_CMP_PKIFAILUREINFO_duplicateCertReq 26 # define OSSL_CMP_PKIFAILUREINFO_MAX 26 - OSSL_CMP_PKISI *ossl_cmp_statusinfo_new(int status, int fail_info, - const char *text); - int ossl_cmp_pkisi_pkistatus_get(OSSL_CMP_PKISI *si); - int ossl_cmp_pkisi_pkifailureinfo_get(OSSL_CMP_PKISI *si); - int ossl_cmp_pkisi_pkifailureinfo_check(OSSL_CMP_PKISI *si, int bit_index); - OSSL_CMP_PKIFAILUREINFO *ossl_cmp_pkisi_failinfo_get0(const OSSL_CMP_PKISI *si); - OSSL_CMP_PKIFREETEXT *ossl_cmp_pkisi_statusstring_get0(const OSSL_CMP_PKISI *si); - char *ossl_pkisi_snprint(OSSL_CMP_PKISI *si, char *buf, int bufsize); + int ossl_cmp_pkisi_get_status(const OSSL_CMP_PKISI *si); + const char *ossl_cmp_PKIStatus_to_string(int status); + OSSL_CMP_PKIFREETEXT *ossl_cmp_pkisi_get0_statusString(const OSSL_CMP_PKISI *si); + int ossl_cmp_pkisi_get_pkifailureinfo(const OSSL_CMP_PKISI *si); + int ossl_cmp_pkisi_check_pkifailureinfo(const OSSL_CMP_PKISI *si, int index); =head1 DESCRIPTION -ossl_cmp_statusinfo_new() creates a new PKIStatusInfo structure and fills it -with the given values. It sets the status field to B. -If B is not NULL, it is copied to statusString. -B is is interpreted as bit pattern for the failInfo field. -Returns a pointer to the structure on success, or NULL on error. +ossl_cmp_pkisi_get_status() returns the PKIStatus of B, or -1 on error. -ossl_cmp_pkisi_pkistatus_get() returns the PKIStatus of B, or -1 on error. +ossl_cmp_PKIStatus_to_string() returns a human-readable string representing +the PKIStatus values as specified in RFC 4210, Appendix F. -ossl_cmp_pkisi_pkifailureinfo_get() returns the PKIFailureInfo bits -of B, encoded as integer, or -1 on error. - -ossl_cmp_pkisi_pkifailureinfo_check() returns the state of the bit (0 or 1) -with index B in the PKIFailureInfo of the B, or -1 on error. - -ossl_cmp_pkisi_failinfo_get0() returns a direct pointer to the failInfo -field contained in B, or NULL on error. - -ossl_cmp_pkisi_statusstring_get0() returns a direct pointer to the statusString +ossl_cmp_pkisi_get0_statusString() returns a direct pointer to the statusString field contained in B. -ossl_pkisi_snprint() places at max B characters of human-readable -error string of B in pre-allocated B. Returns pointer to the same -B containing the string, or NULL on error. +ossl_cmp_pkisi_get_pkifailureinfo() returns the PKIFailureInfo bits +of B, encoded as integer, or -1 on error. + +ossl_cmp_pkisi_check_pkifailureinfo() returns the state of the bit (0 or 1) +with index B in the PKIFailureInfo of the B, or -1 on error. =head1 NOTES diff --git a/doc/internal/man3/s2i_ASN1_UTF8STRING.pod b/doc/internal/man3/s2i_ASN1_UTF8STRING.pod index c5b434a5..9b806eb8 100644 --- a/doc/internal/man3/s2i_ASN1_UTF8STRING.pod +++ b/doc/internal/man3/s2i_ASN1_UTF8STRING.pod @@ -3,12 +3,12 @@ =head1 NAME i2s_ASN1_UTF8STRING, -s2i_ASN1_UTF8STRING, +s2i_ASN1_UTF8STRING - convert objects from/to ASN.1/string representation =head1 SYNOPSIS -=for openssl generic + #include "crypto/x509v3.h" char *i2s_ASN1_UTF8STRING(X509V3_EXT_METHOD *method, ASN1_UTF8STRING *utf8); @@ -22,7 +22,7 @@ representation. This function is used for B extentions. =head1 NOTES -The letters B and B in B() stand for +The letters B and B in i2s_ASN1_UTF8STRING() stand for "internal" (that is, an internal C structure) and string respectively. So B() converts from internal to string. diff --git a/doc/internal/man7/DERlib.pod b/doc/internal/man7/DERlib.pod new file mode 100644 index 00000000..7b0e7225 --- /dev/null +++ b/doc/internal/man7/DERlib.pod @@ -0,0 +1,148 @@ +=pod + +=head1 NAME + +DERlib - internal OpenSSL DER library + +=head1 DESCRIPTION + +OpenSSL contains an internal small DER reading and writing library, +as an alternative to the publically known i2d and d2i functions. It's +solely constituted of functions that work as building blocks to create +more similar functions to encode and decode larger structures. + +All these functions have similar function signatures (C +will vary depending on what the function will encode): + + int DER_w_something(WPACKET *pkt, int tag, ...); + +=begin comment + +When readers are added, add this: + + int DER_r_something(PACKET *pkt, int tag, ...); + +=end comment + +I is the packet context used, and I should be the +context-specific tag value of the element being handled, or -1 if there +is no tag number for that element (you may use the convenience macro +B instead of -1). Any argument following is the C +variable that's being encoded or decoded. + +=head2 DER writers / encoders + +DER writers are based in L, a generic packet writing +library, so before using any of them, I must be initialized +using L or L + +DER writers must be used in reverse order, except for the wrapping +functions that implement a constructed element. The latter are easily +recognised by their function name including the words C and +C. As an example, we can look at the DSA signature structure, +which is defined like this in ASN.1 terms: + + -- Copied from RFC 3279, section 2.2.2 + Dss-Sig-Value ::= SEQUENCE { + r INTEGER, + s INTEGER } + +With the DER library, this is the correspoding code, given two OpenSSL +Bs I and I: + + int ok = DER_w_begin_sequence(pkt, -1) + && DER_w_bn(pkg, -1, s) + && DER_w_bn(pkg, -1, r) + && DER_w_end_sequence(pkt, -1); + +As an example of the use of I, an ASN.1 element like this: + + v [1] INTEGER OPTIONAL + +Would be encoded like this: + + DER_w_bn(pkt, 1, v) + +=begin comment + +=head2 DER readers / decoders + +TBA + +=end comment + +=head1 EXAMPLES + +A more complex example, encoding the AlgorithmIdentifier with +RSASSA-PSS values. + +As a reminder, the AlgorithmIdentifier is specified like this: + + -- From RFC 3280, section 4.1.1.2 + AlgorithmIdentifier ::= SEQUENCE { + algorithm OBJECT IDENTIFIER, + parameters ANY DEFINED BY algorithm OPTIONAL } + +And the RSASSA-PSS OID and parameters are specified like this: + + -- From RFC 3279, section 3.1 + id-RSASSA-PSS OBJECT IDENTIFIER ::= { pkcs-1 10 } + + RSASSA-PSS-params ::= SEQUENCE { + hashAlgorithm [0] HashAlgorithm DEFAULT + sha1Identifier, + maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT + mgf1SHA1Identifier, + saltLength [2] INTEGER DEFAULT 20, + trailerField [3] INTEGER DEFAULT 1 } + +The value we want to encode, written in ASN.1 syntax: + + { + algorithm id-RSASSA-PSS, + parameters { + hashAlgorithm sha256Identifier, + maskGenAlgorithm mgf1SHA256Identifier, + saltLength 20 -- unnecessarily explicit + } + } + +Assuming that we have precompiled constants for C, +C and C, the DER writing code +looks as follows. This is a complete function to write that specific +value: + + int DER_w_AlgorithmIdentifier_RSASSA_PSS_special(WPACKET *pkt, + int tag, + RSA *rsa) + { + return DER_w_begin_sequence(pkt, tag) + && (DER_w_begin_sequence(pkt, DER_NO_CONTEXT) + && DER_w_ulong(pkt, 2, 20) + && DER_w_precompiled(pkt, 1, + der_mgf1SHA256Identifier, + sizeof(der_mgf1SHA256Identifier)) + && DER_w_precompiled(pkt, 0, + der_sha256Identifier, + sizeof(der_sha256Identifier)) + && DER_w_end_sequence(pkt, DER_NO_CONTEXT)) + && DER_w_precompiled(pkt, DER_NO_CONTEXT, + der_id_RSASSA_PSS, + sizeof(der_id_RSASSA_PSS)) + && DER_w_end_sequence(pkt, tag); + } + +=head1 SEE ALSO + +L, L, L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man1/CA.pl.pod b/doc/man1/CA.pl.pod index 4c539708..fa07c892 100644 --- a/doc/man1/CA.pl.pod +++ b/doc/man1/CA.pl.pod @@ -21,13 +21,13 @@ B<-signCA> | B<-signcert> | B<-crl> | B<-newca> -[B<-extra-cmd> I] +[B<-extra-I> I] -B B<-pkcs12> [B<-extra-pkcs12> I] [I] +B B<-pkcs12> [B<-extra-pkcs12> I] [I] -B B<-verify> [B<-extra-verify> I] I ... +B B<-verify> [B<-extra-verify> I] I ... -B B<-revoke> [B<-extra-ca> I] I [I] +B B<-revoke> [B<-extra-ca> I] I [I] =head1 DESCRIPTION @@ -36,6 +36,23 @@ arguments to the L command for some common certificate operations. It is intended to simplify the process of certificate creation and management by the use of some simple options. +The script is intended as a simple front end for the L program for +use by a beginner. Its behaviour isn't always what is wanted. For more control +over the behaviour of the certificate commands call the L command +directly. + +Most of the filenames mentioned below can be modified by editing the +B script. + +Under some environments it may not be possible to run the B script +directly (for example Win32) and the default configuration file location may +be wrong. In this case the command: + + perl -S CA.pl + +can be used and the B environment variable can be set to point to +the correct path of the configuration file. + =head1 OPTIONS =over 4 @@ -70,6 +87,11 @@ details of the CA will be prompted for. The relevant files and directories are created in a directory called F in the current directory. Uses L and L. +If the F directory already exists then the B<-newca> command will not +overwrite it and will do nothing. This can happen if a previous call using +the B<-newca> option terminated abnormally. To get the correct behaviour +delete the directory if it already exists. + =item B<-pkcs12> Create a PKCS#12 file containing the user certificate, private key and CA @@ -120,13 +142,15 @@ Verifies certificates against the CA certificate for F. If no certificates are specified on the command line it tries to verify the file F. Invokes L. -=item B<-extra-req> | B<-extra-ca> | B<-extra-pkcs12> | B<-extra-x509> | B<-extra-verify> I +=item B<-extra-I> I -For each option B>, pass I to the L +For each option B>, pass I to the L sub-command with the same name as I, if that sub-command is invoked. -For example, if L is invoked, the I given with +For example, if L is invoked, the I given with B<-extra-req> will be passed to it. -Users should consult L command documentation for more information. +For multi-word parameters, either repeat the option or quote the I +so it looks like one word to your shell. +See the individual command documentation for more information. =back @@ -144,66 +168,16 @@ the request and finally create a PKCS#12 file containing it. CA.pl -signreq CA.pl -pkcs12 "My Test Certificate" -=head1 DSA CERTIFICATES - -Although the B creates RSA CAs and requests it is still possible to -use it with DSA certificates and requests using the L command -directly. The following example shows the steps that would typically be taken. - -Create some DSA parameters: - - openssl dsaparam -out dsap.pem 1024 - -Create a DSA CA certificate and private key: - - openssl req -x509 -newkey dsa:dsap.pem -keyout cacert.pem -out cacert.pem - -Create the CA directories and files: - - CA.pl -newca - -enter a filename (for example, F) when prompted for the CA file -name. - -Create a DSA certificate request and private key (a different set of parameters -can optionally be created first): - - openssl req -out newreq.pem -newkey dsa:dsap.pem - -Sign the request: - - CA.pl -signreq - =head1 ENVIRONMENT +The environment variable B may be used to specify the name of +the OpenSSL program. It can be a full pathname, or a relative one. + The environment variable B may be used to specify a configuration option and value to the B and B commands invoked by this script. It's value should be the option and pathname, as in C<-config /path/to/conf-file>. -=head1 NOTES - -Most of the filenames mentioned can be modified by editing the B script. - -If the F directory already exists then the B<-newca> command will not -overwrite it and will do nothing. This can happen if a previous call using -the B<-newca> option terminated abnormally. To get the correct behaviour -delete the demoCA directory if it already exists. - -Under some environments it may not be possible to run the B script -directly (for example Win32) and the default configuration file location may -be wrong. In this case the command: - - perl -S CA.pl - -can be used and the B environment variable changed to point to -the correct path of the configuration file. - -The script is intended as a simple front end for the L program for -use by a beginner. Its behaviour isn't always what is wanted. For more control -over the behaviour of the certificate commands call the L command -directly. - =head1 SEE ALSO L, diff --git a/doc/man1/openssl-asn1parse.pod.in b/doc/man1/openssl-asn1parse.pod.in index 9b959664..e1c7f261 100644 --- a/doc/man1/openssl-asn1parse.pod.in +++ b/doc/man1/openssl-asn1parse.pod.in @@ -3,7 +3,7 @@ =head1 NAME -openssl-asn1parse - ASN.1 parsing tool +openssl-asn1parse - ASN.1 parsing command =head1 SYNOPSIS diff --git a/doc/man1/openssl-ca.pod.in b/doc/man1/openssl-ca.pod.in index a3c83d80..e07295cf 100644 --- a/doc/man1/openssl-ca.pod.in +++ b/doc/man1/openssl-ca.pod.in @@ -53,17 +53,16 @@ B B [B<-subj> I] [B<-utf8>] [B<-sigopt> I:I] +[B<-vfyopt> I:I] [B<-create_serial>] [B<-rand_serial>] [B<-multivalue-rdn>] -[B<-sm2-id> I] -[B<-sm2-hex-id> I] {- $OpenSSL::safe::opt_r_synopsis -} {- $OpenSSL::safe::opt_engine_synopsis -} {- $OpenSSL::safe::opt_provider_synopsis -} [I...] -=for openssl ifdef engine sm2-id sm2-hex-id +=for openssl ifdef engine =head1 DESCRIPTION @@ -147,16 +146,26 @@ See L for details. =item B<-sigopt> I:I -Pass options to the signature algorithm during sign or verify operations. +Pass options to the signature algorithm during sign operations. Names and values of these options are algorithm-specific. +=item B<-vfyopt> I:I + +Pass options to the signature algorithm during verify operations. +Names and values of these options are algorithm-specific. + +This often needs to be given while signing too, because the input +certificate signature request is verified against its own public key, +and that verification may need its own set of options. + =item B<-key> I =for openssl foreign manual ps(1) The password used to encrypt the private key. Since on some -systems the command line arguments are visible (e.g. Unix with -the L utility) this option should be used with caution. +systems the command line arguments are visible (e.g., when using +L on Unix), +this option should be used with caution. =item B<-selfsign> @@ -296,16 +305,6 @@ C If B<-multi-rdn> is not used then the UID value is C<123456+CN=John Doe>. -=item B<-sm2-id> I - -Specify the ID string to use when verifying an SM2 certificate. The ID string is -required by the SM2 signature algorithm for signing and verification. - -=item B<-sm2-hex-id> I - -Specify a binary ID string to use when signing or verifying using an SM2 -certificate. The argument for this option is string of hexadecimal digits. - {- $OpenSSL::safe::opt_r_item -} {- $OpenSSL::safe::opt_engine_item -} @@ -616,7 +615,9 @@ Sign a certificate request: Sign an SM2 certificate request: - openssl ca -in sm2.csr -out sm2.crt -md sm3 -sigopt "sm2_id:1234567812345678" -sm2-id "1234567812345678" + openssl ca -in sm2.csr -out sm2.crt -md sm3 \ + -sigopt "distid:1234567812345678" \ + -vfyopt "distid:1234567812345678" Sign a certificate request, using CA extensions: @@ -712,8 +713,8 @@ numbers of certificates are present because, as the name implies the database has to be kept in memory. This command really needs rewriting or the required functionality -exposed at either a command or interface level so a more friendly utility -(perl script or GUI) can handle things properly. The script +exposed at either a command or interface level so that a more user-friendly +replacement could handle things properly. The script B helps a little but not very much. Any fields in a request that are not present in a policy are silently diff --git a/doc/man1/openssl-ciphers.pod.in b/doc/man1/openssl-ciphers.pod.in index 78e97a0a..020bdcbc 100644 --- a/doc/man1/openssl-ciphers.pod.in +++ b/doc/man1/openssl-ciphers.pod.in @@ -3,7 +3,7 @@ =head1 NAME -openssl-ciphers - SSL cipher display and cipher list tool +openssl-ciphers - SSL cipher display and cipher list command =head1 SYNOPSIS @@ -31,7 +31,7 @@ B B =head1 DESCRIPTION This command converts textual OpenSSL cipher lists into -ordered SSL cipher preference lists. It can be used as a test tool to +ordered SSL cipher preference lists. It can be used to determine the appropriate cipherlist. =head1 OPTIONS @@ -524,6 +524,19 @@ distribution. TLS_GOSTR341094_WITH_NULL_GOSTR3411 GOST94-NULL-GOST94 TLS_GOSTR341001_WITH_NULL_GOSTR3411 GOST2001-NULL-GOST94 +=head2 GOST cipher suites, extending TLS v1.2 + +Note: these ciphers require an engine which including GOST cryptographic +algorithms, such as the B engine, which isn't part of the OpenSSL +distribution. + + TLS_GOSTR341112_256_WITH_28147_CNT_IMIT GOST2012-GOST8912-GOST8912 + TLS_GOSTR341112_256_WITH_NULL_GOSTR3411 GOST2012-NULL-GOST12 + +Note: GOST2012-GOST8912-GOST8912 is an alias for two ciphers ID +old LEGACY-GOST2012-GOST8912-GOST8912 and new IANA-GOST2012-GOST8912-GOST8912 + + =head2 Additional Export 1024 and other cipher suites Note: these ciphers can also be used in SSL v3. diff --git a/doc/man1/openssl-cms.pod.in b/doc/man1/openssl-cms.pod.in index 944135bb..5cf8172f 100644 --- a/doc/man1/openssl-cms.pod.in +++ b/doc/man1/openssl-cms.pod.in @@ -3,7 +3,7 @@ =head1 NAME -openssl-cms - CMS utility +openssl-cms - CMS command =head1 SYNOPSIS diff --git a/doc/man1/openssl-crl.pod.in b/doc/man1/openssl-crl.pod.in index c1bd31a4..fd50602b 100644 --- a/doc/man1/openssl-crl.pod.in +++ b/doc/man1/openssl-crl.pod.in @@ -3,7 +3,7 @@ =head1 NAME -openssl-crl - CRL utility +openssl-crl - CRL command =head1 SYNOPSIS diff --git a/doc/man1/openssl-ocsp.pod.in b/doc/man1/openssl-ocsp.pod.in index efa627b8..2edbfc88 100644 --- a/doc/man1/openssl-ocsp.pod.in +++ b/doc/man1/openssl-ocsp.pod.in @@ -3,7 +3,7 @@ =head1 NAME -openssl-ocsp - Online Certificate Status Protocol utility +openssl-ocsp - Online Certificate Status Protocol command =head1 SYNOPSIS diff --git a/doc/man1/openssl-pkcs12.pod.in b/doc/man1/openssl-pkcs12.pod.in index 631eec72..655f7180 100644 --- a/doc/man1/openssl-pkcs12.pod.in +++ b/doc/man1/openssl-pkcs12.pod.in @@ -3,7 +3,7 @@ =head1 NAME -openssl-pkcs12 - PKCS#12 file utility +openssl-pkcs12 - PKCS#12 file command =head1 SYNOPSIS diff --git a/doc/man1/openssl-pkcs7.pod.in b/doc/man1/openssl-pkcs7.pod.in index 0a12d237..d31ae2a0 100644 --- a/doc/man1/openssl-pkcs7.pod.in +++ b/doc/man1/openssl-pkcs7.pod.in @@ -7,7 +7,7 @@ =head1 NAME -openssl-pkcs7 - PKCS#7 utility +openssl-pkcs7 - PKCS#7 command =head1 SYNOPSIS diff --git a/doc/man1/openssl-pkcs8.pod.in b/doc/man1/openssl-pkcs8.pod.in index f9e5fb1d..38b50a6d 100644 --- a/doc/man1/openssl-pkcs8.pod.in +++ b/doc/man1/openssl-pkcs8.pod.in @@ -3,7 +3,7 @@ =head1 NAME -openssl-pkcs8 - PKCS#8 format private key conversion tool +openssl-pkcs8 - PKCS#8 format private key conversion command =head1 SYNOPSIS diff --git a/doc/man1/openssl-pkey.pod.in b/doc/man1/openssl-pkey.pod.in index 8460aed1..2785f298 100644 --- a/doc/man1/openssl-pkey.pod.in +++ b/doc/man1/openssl-pkey.pod.in @@ -7,7 +7,7 @@ =head1 NAME -openssl-pkey - public or private key processing tool +openssl-pkey - public or private key processing command =head1 SYNOPSIS diff --git a/doc/man1/openssl-pkeyparam.pod.in b/doc/man1/openssl-pkeyparam.pod.in index 7f9d351a..d5ea4012 100644 --- a/doc/man1/openssl-pkeyparam.pod.in +++ b/doc/man1/openssl-pkeyparam.pod.in @@ -7,7 +7,7 @@ =head1 NAME -openssl-pkeyparam - public key algorithm parameter processing tool +openssl-pkeyparam - public key algorithm parameter processing command =head1 SYNOPSIS diff --git a/doc/man1/openssl-pkeyutl.pod.in b/doc/man1/openssl-pkeyutl.pod.in index 0bca4838..8f9060a2 100644 --- a/doc/man1/openssl-pkeyutl.pod.in +++ b/doc/man1/openssl-pkeyutl.pod.in @@ -3,7 +3,7 @@ =head1 NAME -openssl-pkeyutl - public key algorithm utility +openssl-pkeyutl - public key algorithm command =head1 SYNOPSIS @@ -321,18 +321,18 @@ must be known for this to work. If the size of the file cannot be determined =head1 SM2 The SM2 algorithm supports sign, verify, encrypt and decrypt operations. For -the sign and verify operations, SM2 requires an ID string to be passed in. The -following B<-pkeyopt> value is supported: +the sign and verify operations, SM2 requires an Distinguishing ID string to +be passed in. The following B<-pkeyopt> value is supported: =over 4 -=item BI +=item BI This sets the ID string used in SM2 sign or verify operations. While verifying an SM2 signature, the ID string must be the same one used when signing the data. Otherwise the verification will fail. -=item BI +=item BI This sets the ID string used in SM2 sign or verify operations. While verifying an SM2 signature, the ID string must be the same one used when signing the data. @@ -382,12 +382,12 @@ Derive using the same algorithm, but read key from environment variable MYPASS: Sign some data using an L private key and a specific ID: openssl pkeyutl -sign -in file -inkey sm2.key -out sig -rawin -digest sm3 \ - -pkeyopt sm2_id:someid + -pkeyopt distid:someid Verify some data using an L certificate and a specific ID: openssl pkeyutl -verify -certin -in file -inkey sm2.cert -sigfile sig \ - -rawin -digest sm3 -pkeyopt sm2_id:someid + -rawin -digest sm3 -pkeyopt distid:someid =head1 SEE ALSO diff --git a/doc/man1/openssl-req.pod.in b/doc/man1/openssl-req.pod.in index 7587cb5a..c8abeb36 100644 --- a/doc/man1/openssl-req.pod.in +++ b/doc/man1/openssl-req.pod.in @@ -3,7 +3,7 @@ =head1 NAME -openssl-req - PKCS#10 certificate request and certificate generating utility +openssl-req - PKCS#10 certificate request and certificate generating command =head1 SYNOPSIS @@ -45,16 +45,15 @@ B B [B<-subject>] [B<-subj> I] [B<-sigopt> I:I] +[B<-vfyopt> I:I] [B<-batch>] [B<-verbose>] -[B<-sm2-id> I] -[B<-sm2-hex-id> I] {- $OpenSSL::safe::opt_name_synopsis -} {- $OpenSSL::safe::opt_r_synopsis -} {- $OpenSSL::safe::opt_engine_synopsis -} {- $OpenSSL::safe::opt_provider_synopsis -} -=for openssl ifdef engine keygen_engine sm2-id sm2-hex-id +=for openssl ifdef engine keygen_engine =head1 DESCRIPTION @@ -85,9 +84,22 @@ options (B<-new> and B<-newkey>) are not specified. =item B<-sigopt> I:I -Pass options to the signature algorithm during sign or verify operations. +Pass options to the signature algorithm during sign operations. Names and values of these options are algorithm-specific. +=item B<-vfyopt> I:I + +Pass options to the signature algorithm during verify operations. +Names and values of these options are algorithm-specific. + +=begin comment + +Maybe it would be preferable to only have -opts instead of -sigopt and +-vfyopt? They are both present here to be compatible with L, +which supports both options for good reasons. + +=end comment + =item B<-passin> I, B<-passout> I The password source for the input and output file. @@ -313,16 +325,6 @@ Print extra details about the operations being performed. Specifies an engine (by its unique I string) which would be used for key generation operations. -=item B<-sm2-id> - -Specify the ID string to use when verifying an SM2 certificate request. The ID -string is required by the SM2 signature algorithm for signing and verification. - -=item B<-sm2-hex-id> - -Specify a binary ID string to use when verifying an SM2 certificate request. The -argument for this option is string of hexadecimal digits. - {- $OpenSSL::safe::opt_name_item -} {- $OpenSSL::safe::opt_r_item -} @@ -531,11 +533,11 @@ Generate a self signed root certificate: Create an SM2 private key and then generate a certificate request from it: openssl ecparam -genkey -name SM2 -out sm2.key - openssl req -new -key sm2.key -out sm2.csr -sm3 -sigopt "sm2_id:1234567812345678" + openssl req -new -key sm2.key -out sm2.csr -sm3 -sigopt "distid:1234567812345678" Examine and verify an SM2 certificate request: - openssl req -verify -in sm2.csr -sm3 -sm2-id 1234567812345678 + openssl req -verify -in sm2.csr -sm3 -vfyopt "distid:1234567812345678" Example of a file pointed to by the B option: diff --git a/doc/man1/openssl-rsa.pod.in b/doc/man1/openssl-rsa.pod.in index e2c0b24a..fa1a20ea 100644 --- a/doc/man1/openssl-rsa.pod.in +++ b/doc/man1/openssl-rsa.pod.in @@ -7,7 +7,7 @@ =head1 NAME -openssl-rsa - RSA key processing tool +openssl-rsa - RSA key processing command =head1 SYNOPSIS diff --git a/doc/man1/openssl-rsautl.pod.in b/doc/man1/openssl-rsautl.pod.in index d28e6728..0bb0a136 100644 --- a/doc/man1/openssl-rsautl.pod.in +++ b/doc/man1/openssl-rsautl.pod.in @@ -3,7 +3,7 @@ =head1 NAME -openssl-rsautl - RSA utility +openssl-rsautl - RSA command =head1 SYNOPSIS @@ -167,7 +167,7 @@ encrypt and decrypt the block would have been of type 2 (the second byte) and random padding data visible instead of the 0xff bytes. It is possible to analyse the signature of certificates using this -utility in conjunction with L. Consider the self signed +command in conjunction with L. Consider the self signed example in F. Running L as follows yields: diff --git a/doc/man1/openssl-s_server.pod.in b/doc/man1/openssl-s_server.pod.in index 9a5ef10d..0fd22d46 100644 --- a/doc/man1/openssl-s_server.pod.in +++ b/doc/man1/openssl-s_server.pod.in @@ -124,6 +124,7 @@ B B [B<-nextprotoneg> I] [B<-use_srtp> I] [B<-alpn> I] +[B<-sendfile>] [B<-keylogfile> I] [B<-recv_max_early_data> I] [B<-max_early_data> I] @@ -152,6 +153,8 @@ B B =for openssl ifdef ssl3 tls1 tls1_1 tls1_2 tls1_3 dtls mtu dtls1 dtls1_2 +=for openssl ifdef sendfile + =head1 DESCRIPTION This command implements a generic SSL/TLS server which @@ -613,6 +616,12 @@ Protocol names are printable ASCII strings, for example "http/1.1" or "spdy/3". The flag B<-nextprotoneg> cannot be specified if B<-tls1_3> is used. +=item B<-sendfile> + +If this option is set and KTLS is enabled, SSL_sendfile() will be used +instead of BIO_write() to send the HTTP response requested by a client. +This option is only valid if B<-WWW> or B<-HTTP> is specified. + =item B<-keylogfile> I Appends TLS secrets to the specified keylog file such that external programs diff --git a/doc/man1/openssl-sess_id.pod.in b/doc/man1/openssl-sess_id.pod.in index f68f1807..e18ef6f9 100644 --- a/doc/man1/openssl-sess_id.pod.in +++ b/doc/man1/openssl-sess_id.pod.in @@ -3,7 +3,7 @@ =head1 NAME -openssl-sess_id - SSL/TLS session handling utility +openssl-sess_id - SSL/TLS session handling command =head1 SYNOPSIS diff --git a/doc/man1/openssl-smime.pod.in b/doc/man1/openssl-smime.pod.in index c6775505..69bf9187 100644 --- a/doc/man1/openssl-smime.pod.in +++ b/doc/man1/openssl-smime.pod.in @@ -3,7 +3,7 @@ =head1 NAME -openssl-smime - S/MIME utility +openssl-smime - S/MIME command =head1 SYNOPSIS diff --git a/doc/man1/openssl-spkac.pod.in b/doc/man1/openssl-spkac.pod.in index 4ea15fa5..77e4d7ce 100644 --- a/doc/man1/openssl-spkac.pod.in +++ b/doc/man1/openssl-spkac.pod.in @@ -7,7 +7,7 @@ =head1 NAME -openssl-spkac - SPKAC printing and generating utility +openssl-spkac - SPKAC printing and generating command =head1 SYNOPSIS diff --git a/doc/man1/openssl-storeutl.pod.in b/doc/man1/openssl-storeutl.pod.in index 75c30651..3de2059e 100644 --- a/doc/man1/openssl-storeutl.pod.in +++ b/doc/man1/openssl-storeutl.pod.in @@ -7,7 +7,7 @@ =head1 NAME -openssl-storeutl - STORE utility +openssl-storeutl - STORE command =head1 SYNOPSIS diff --git a/doc/man1/openssl-ts.pod.in b/doc/man1/openssl-ts.pod.in index 8d5e66e6..38fcf530 100644 --- a/doc/man1/openssl-ts.pod.in +++ b/doc/man1/openssl-ts.pod.in @@ -3,7 +3,7 @@ =head1 NAME -openssl-ts - Time Stamping Authority tool (client/server) +openssl-ts - Time Stamping Authority command =head1 SYNOPSIS diff --git a/doc/man1/openssl-verify.pod.in b/doc/man1/openssl-verify.pod.in index fd41bbeb..821f88da 100644 --- a/doc/man1/openssl-verify.pod.in +++ b/doc/man1/openssl-verify.pod.in @@ -3,7 +3,7 @@ =head1 NAME -openssl-verify - Utility to verify certificates +openssl-verify - certificate verification command =head1 SYNOPSIS @@ -12,11 +12,10 @@ B B [B<-CRLfile> I] [B<-crl_download>] [B<-show_chain>] -[B<-sm2-id> I] -[B<-sm2-hex-id> I] [B<-verbose>] [B<-trusted> I] [B<-untrusted> I] +[B<-vfyopt> I:I] {- $OpenSSL::safe::opt_name_synopsis -} {- $OpenSSL::safe::opt_trust_synopsis -} {- $OpenSSL::safe::opt_engine_synopsis -} @@ -25,7 +24,7 @@ B B [B<-->] [I ...] -=for openssl ifdef engine sm2-id sm2-hex-id +=for openssl ifdef engine =head1 DESCRIPTION @@ -59,16 +58,6 @@ Display information about the certificate chain that has been built (if successful). Certificates in the chain that came from the untrusted list will be flagged as "untrusted". -=item B<-sm2-id> I - -Specify the ID string to use when verifying an SM2 certificate. The ID string is -required by the SM2 signature algorithm for signing and verification. - -=item B<-sm2-hex-id> I - -Specify a binary ID string to use when signing or verifying using an SM2 -certificate. The argument for this option is string of hexadecimal digits. - =item B<-verbose> Print extra information about the operations being performed. @@ -81,6 +70,11 @@ A file of trusted certificates. A file of untrusted certificates. +=item B<-vfyopt> I:I + +Pass options to the signature algorithm during verify operations. +Names and values of these options are algorithm-specific. + {- $OpenSSL::safe::opt_name_item -} {- $OpenSSL::safe::opt_engine_item -} @@ -159,8 +153,6 @@ L The B<-show_chain> option was added in OpenSSL 1.1.0. -The B<-sm2-id> and B<-sm2-hex-id> options were added in OpenSSL 3.0. - =head1 COPYRIGHT Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man1/openssl-x509.pod.in b/doc/man1/openssl-x509.pod.in index 8cf03d93..568a2053 100644 --- a/doc/man1/openssl-x509.pod.in +++ b/doc/man1/openssl-x509.pod.in @@ -3,7 +3,7 @@ =head1 NAME -openssl-x509 - Certificate display and signing utility +openssl-x509 - Certificate display and signing command =head1 SYNOPSIS @@ -71,6 +71,7 @@ B B [B<-extfile> I] [B<-extensions> I
] [B<-sigopt> I:I] +[B<-vfyopt> I:I] [B<-preserve_dates>] {- $OpenSSL::safe::opt_name_synopsis -} {- $OpenSSL::safe::opt_r_synopsis -} @@ -81,7 +82,7 @@ B B =head1 DESCRIPTION -This command is a multi purpose certificate utility. It can +This command is a multi-purposes certificate command. It can be used to display certificate information, convert certificates to various forms, sign certificate requests like a "mini CA" or edit certificate trust settings. @@ -371,7 +372,12 @@ for testing. =item B<-sigopt> I:I -Pass options to the signature algorithm during sign or verify operations. +Pass options to the signature algorithm during sign operations. +Names and values of these options are algorithm-specific. + +=item B<-vfyopt> I:I + +Pass options to the signature algorithm during verify operations. Names and values of these options are algorithm-specific. =item B<-passin> I diff --git a/doc/man1/openssl.pod b/doc/man1/openssl.pod index 2f56ab75..c05fc29f 100644 --- a/doc/man1/openssl.pod +++ b/doc/man1/openssl.pod @@ -2,7 +2,7 @@ =head1 NAME -openssl - OpenSSL command line tool +openssl - OpenSSL command line program =head1 SYNOPSIS @@ -29,7 +29,7 @@ OpenSSL is a cryptography toolkit implementing the Secure Sockets Layer (SSL v2/v3) and Transport Layer Security (TLS v1) network protocols and related cryptography standards required by them. -The B program is a command line tool for using the various +The B program is a command line program for using the various cryptography functions of OpenSSL's B library from the shell. It can be used for @@ -104,7 +104,7 @@ Cipher Suite Description Determination. =item B -CMS (Cryptographic Message Syntax) utility. +CMS (Cryptographic Message Syntax) command. =item B @@ -196,7 +196,7 @@ Create or examine a Netscape certificate sequence. =item B -Online Certificate Status Protocol utility. +Online Certificate Status Protocol command. =item B @@ -212,7 +212,7 @@ PKCS#7 Data Management. =item B -PKCS#8 format private key conversion tool. +PKCS#8 format private key conversion command. =item B @@ -224,7 +224,7 @@ Public key algorithm parameter management. =item B -Public key algorithm cryptographic operation utility. +Public key algorithm cryptographic operation command. =item B @@ -252,7 +252,7 @@ RSA key management. =item B -RSA utility for signing, verification, encryption, and decryption. Superseded +RSA command for signing, verification, encryption, and decryption. Superseded by L. =item B @@ -289,7 +289,7 @@ Algorithm Speed Measurement. =item B -SPKAC printing and generating utility. +SPKAC printing and generating command. =item B @@ -297,11 +297,11 @@ Maintain SRP password file. =item B -Utility to list and display certificates, keys, CRLs, etc. +Command to list and display certificates, keys, CRLs, etc. =item B -Time Stamping Authority tool (client/server). +Time Stamping Authority command. =item B @@ -727,11 +727,11 @@ Do not use the default store. =head2 Random State Options -Prior to OpenSSL 3.0, it was common for applications to store information +Prior to OpenSSL 1.1.1, it was common for applications to store information about the state of the random-number generator in a file that was loaded at startup and rewritten upon exit. On modern operating systems, this is -generally no longer necessary as OpenSSL will seed itself from the -appropriate CPU flags, device files, and so on. These flags are still +generally no longer necessary as OpenSSL will seed itself from a trusted +entropy source provided by the operating system. These flags are still supported for special platforms or circumstances that might require them. It is generally an error to use the same seed file more than once and diff --git a/doc/man3/BIO_get_ex_new_index.pod b/doc/man3/BIO_get_ex_new_index.pod index 0bacb2e0..365c0840 100644 --- a/doc/man3/BIO_get_ex_new_index.pod +++ b/doc/man3/BIO_get_ex_new_index.pod @@ -9,6 +9,7 @@ DSA_get_ex_new_index, DSA_set_ex_data, DSA_get_ex_data, ECDH_get_ex_new_index, ECDH_set_ex_data, ECDH_get_ex_data, EC_KEY_get_ex_new_index, EC_KEY_set_ex_data, EC_KEY_get_ex_data, ENGINE_get_ex_new_index, ENGINE_set_ex_data, ENGINE_get_ex_data, +EVP_PKEY_get_ex_new_index, EVP_PKEY_set_ex_data, EVP_PKEY_get_ex_data, RAND_DRBG_set_ex_data, RAND_DRBG_get_ex_data, RAND_DRBG_get_ex_new_index, RSA_get_ex_new_index, RSA_set_ex_data, RSA_get_ex_data, RSA_set_app_data, RSA_get_app_data, @@ -39,7 +40,7 @@ X509_get_ex_new_index, X509_set_ex_data, X509_get_ex_data int TYPE_set_ex_data(TYPE *d, int idx, void *arg); - void *TYPE_get_ex_data(TYPE *d, int idx); + void *TYPE_get_ex_data(const TYPE *d, int idx); #define TYPE_set_app_data(TYPE *d, void *arg) #define TYPE_get_app_data(TYPE *d) @@ -53,7 +54,7 @@ L. These functions handle application-specific data for OpenSSL data structures. -TYPE_get_new_ex_index() is a macro that calls CRYPTO_get_ex_new_index() +TYPE_get_ex_new_index() is a macro that calls CRYPTO_get_ex_new_index() with the correct B value. TYPE_set_ex_data() is a function that calls CRYPTO_set_ex_data() with @@ -74,7 +75,7 @@ there are no backward compatibility concerns. =head1 RETURN VALUES -TYPE_get_new_ex_index() returns a new index on success or -1 on error. +TYPE_get_ex_new_index() returns a new index on success or -1 on error. TYPE_set_ex_data() returns 1 on success or 0 on error. diff --git a/doc/man3/CONF_modules_free.pod b/doc/man3/CONF_modules_free.pod index 592189d6..1174bfec 100644 --- a/doc/man3/CONF_modules_free.pod +++ b/doc/man3/CONF_modules_free.pod @@ -39,7 +39,7 @@ None of the functions return a value. =head1 SEE ALSO L, L, -L +L =head1 HISTORY diff --git a/doc/man3/CONF_modules_load_file.pod b/doc/man3/CONF_modules_load_file.pod index c0623eb7..ba2c8b68 100644 --- a/doc/man3/CONF_modules_load_file.pod +++ b/doc/man3/CONF_modules_load_file.pod @@ -2,12 +2,16 @@ =head1 NAME -CONF_modules_load_file, CONF_modules_load - OpenSSL configuration functions +CONF_modules_load_file_with_libctx, CONF_modules_load_file, CONF_modules_load +- OpenSSL configuration functions =head1 SYNOPSIS #include + int CONF_modules_load_file_with_libctx(OPENSSL_CTX *libctx, + const char *filename, + const char *appname, unsigned long flags); int CONF_modules_load_file(const char *filename, const char *appname, unsigned long flags); int CONF_modules_load(const CONF *cnf, const char *appname, @@ -15,12 +19,16 @@ CONF_modules_load_file, CONF_modules_load - OpenSSL configuration functions =head1 DESCRIPTION -The function CONF_modules_load_file() configures OpenSSL using file -B and application name B. If B is NULL -the standard OpenSSL configuration file is used. If B is -NULL the standard OpenSSL application name B is used. +The function CONF_modules_load_file_with_libctx() configures OpenSSL using +library context B file B and application name B. +If B is NULL the standard OpenSSL configuration file is used. +If B is NULL the standard OpenSSL application name B is +used. The behaviour can be customized using B. +CONF_modules_load_file() is the same as CONF_modules_load_file_with_libctx() but +has a NULL library context. + CONF_modules_load() is identical to CONF_modules_load_file() except it reads configuration information from B. @@ -40,8 +48,8 @@ returns success. This is used by default in L to ignore any errors in the default system-wide configuration file, as having all OpenSSL applications fail to start when there are potentially minor issues in the file is too risky. -Applications calling B explicitly should not generally -set this flag. +Applications calling B explicitly should not +generally set this flag. If B is set configuration module loading from DSOs is disabled. @@ -53,10 +61,10 @@ return an error. B if set and B is not NULL will use the default section pointed to by B if B does not exist. -By using CONF_modules_load_file() with appropriate flags an application can -customise application configuration to best suit its needs. In some cases the -use of a configuration file is optional and its absence is not an error: in -this case B would be set. +By using CONF_modules_load_file_with_libctx() with appropriate flags an +application can customise application configuration to best suit its needs. +In some cases the use of a configuration file is optional and its absence is not +an error: in this case B would be set. Errors during configuration may also be handled differently by different applications. For example in some cases an error may simply print out a warning @@ -78,7 +86,7 @@ return value of the failing module (this will always be zero or negative). Load a configuration file and print out any errors and exit (missing file considered fatal): - if (CONF_modules_load_file(NULL, NULL, 0) <= 0) { + if (CONF_modules_load_file_with_libctx(libctx, NULL, NULL, 0) <= 0) { fprintf(stderr, "FATAL: error loading configuration file\n"); ERR_print_errors_fp(stderr); exit(1); @@ -87,8 +95,8 @@ considered fatal): Load default configuration file using the section indicated by "myapp", tolerate missing files, but exit on other errors: - if (CONF_modules_load_file(NULL, "myapp", - CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) { + if (CONF_modules_load_file_with_libctx(NULL, NULL, "myapp", + CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) { fprintf(stderr, "FATAL: error loading configuration file\n"); ERR_print_errors_fp(stderr); exit(1); @@ -97,8 +105,8 @@ tolerate missing files, but exit on other errors: Load custom configuration file and section, only print warnings on error, missing configuration file ignored: - if (CONF_modules_load_file("/something/app.cnf", "myapp", - CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) { + if (CONF_modules_load_file_with_libctx(NULL, "/something/app.cnf", "myapp", + CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) { fprintf(stderr, "WARNING: error loading configuration file\n"); ERR_print_errors_fp(stderr); } @@ -114,7 +122,7 @@ Load and parse configuration file manually, custom error handling: fprintf(stderr, "Error opening configuration file\n"); /* Other missing configuration file behaviour */ } else { - cnf = NCONF_new(NULL); + cnf = NCONF_new_with_libctx(libctx, NULL); if (NCONF_load_fp(cnf, fp, &eline) == 0) { fprintf(stderr, "Error on line %ld of configuration file\n", eline); ERR_print_errors_fp(stderr); @@ -130,11 +138,13 @@ Load and parse configuration file manually, custom error handling: =head1 SEE ALSO -L, L +L, +L, +L =head1 COPYRIGHT -Copyright 2004-2017 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/CRYPTO_get_ex_new_index.pod b/doc/man3/CRYPTO_get_ex_new_index.pod index d8cecccd..10f7feb5 100644 --- a/doc/man3/CRYPTO_get_ex_new_index.pod +++ b/doc/man3/CRYPTO_get_ex_new_index.pod @@ -49,6 +49,7 @@ The specific structures are: DSA EC_KEY ENGINE + EVP_PKEY RAND_DRBG RSA SSL diff --git a/doc/man3/CTLOG_STORE_new.pod b/doc/man3/CTLOG_STORE_new.pod index f4a21e4b..196a3278 100644 --- a/doc/man3/CTLOG_STORE_new.pod +++ b/doc/man3/CTLOG_STORE_new.pod @@ -2,6 +2,7 @@ =head1 NAME +CTLOG_STORE_new_with_libctx, CTLOG_STORE_new, CTLOG_STORE_free, CTLOG_STORE_load_default_file, CTLOG_STORE_load_file - Create and populate a Certificate Transparency log list @@ -10,6 +11,8 @@ Create and populate a Certificate Transparency log list #include + CTLOG_STORE *CTLOG_STORE_new_with_libctx(OPENSSL_CTX *libctx, + const char *propq); CTLOG_STORE *CTLOG_STORE_new(void); void CTLOG_STORE_free(CTLOG_STORE *store); @@ -22,13 +25,19 @@ A CTLOG_STORE is a container for a list of CTLOGs (Certificate Transparency logs). The list can be loaded from one or more files and then searched by LogID (see RFC 6962, Section 3.2, for the definition of a LogID). -CTLOG_STORE_new() creates an empty list of CT logs. This is then populated -by CTLOG_STORE_load_default_file() or CTLOG_STORE_load_file(). -CTLOG_STORE_load_default_file() loads from the default file, which is named -F in OPENSSLDIR (see the output of L). -This can be overridden using an environment variable named B. -CTLOG_STORE_load_file() loads from a caller-specified file path instead. -Both of these functions append any loaded CT logs to the CTLOG_STORE. +CTLOG_STORE_new_with_libctx() creates an empty list of CT logs associated with +the library context I and the property query string I. + +CTLOG_STORE_new() does the same thing as CTLOG_STORE_new_with_libctx() but with +the default library context and property query string. + +The CTLOG_STORE is then populated by CTLOG_STORE_load_default_file() or +CTLOG_STORE_load_file(). CTLOG_STORE_load_default_file() loads from the default +file, which is named F in OPENSSLDIR (see the output of +L). This can be overridden using an environment variable +named B. CTLOG_STORE_load_file() loads from a caller-specified file +path instead. Both of these functions append any loaded CT logs to the +CTLOG_STORE. The expected format of the file is: @@ -65,7 +74,8 @@ L =head1 HISTORY -These functions were added in OpenSSL 1.1.0. +CTLOG_STORE_new_with_libctx was added in OpenSSL 3.0. All other functions were +added in OpenSSL 1.1.0. =head1 COPYRIGHT diff --git a/doc/man3/CTLOG_new.pod b/doc/man3/CTLOG_new.pod index 1c31f337..aa5ec0a7 100644 --- a/doc/man3/CTLOG_new.pod +++ b/doc/man3/CTLOG_new.pod @@ -2,7 +2,8 @@ =head1 NAME -CTLOG_new, CTLOG_new_from_base64, CTLOG_free, +CTLOG_new_with_libctx, CTLOG_new, CTLOG_new_from_base64, +CTLOG_new_from_base64_with_libctx, CTLOG_free, CTLOG_get0_name, CTLOG_get0_log_id, CTLOG_get0_public_key - encapsulates information about a Certificate Transparency log @@ -10,7 +11,13 @@ encapsulates information about a Certificate Transparency log #include + CTLOG *CTLOG_new_with_libctx(EVP_PKEY *public_key, const char *name, + OPENSSL_CTX *libctx, const char *propq); CTLOG *CTLOG_new(EVP_PKEY *public_key, const char *name); + + int CTLOG_new_from_base64_with_libctx(CTLOG **ct_log, const char *pkey_base64, + const char *name, OPENSSL_CTX *libctx, + const char *propq); int CTLOG_new_from_base64(CTLOG ** ct_log, const char *pkey_base64, const char *name); void CTLOG_free(CTLOG *log); @@ -21,14 +28,24 @@ encapsulates information about a Certificate Transparency log =head1 DESCRIPTION -CTLOG_new() returns a new CTLOG that represents the Certificate Transparency -(CT) log with the given public key. A name must also be provided that can be -used to help users identify this log. Ownership of the public key is -transferred. +CTLOG_new_with_libctx() returns a new CTLOG that represents the Certificate +Transparency (CT) log with the given public key and associates it with the +library context I and property query string I. A name must also +be provided that can be used to help users identify this log. Ownership of the +public key is transferred. -CTLOG_new_from_base64() also creates a new CTLOG, but takes the public key in -base64-encoded DER form and sets the ct_log pointer to point to the new CTLOG. -The base64 will be decoded and the public key parsed. +CTLOG_new() does the same thing as CTLOG_new_with_libctx() but with the default +library context and the default property query string. + +CTLOG_new_from_base64_with_libctx() also creates a new CTLOG, but takes the +public key in base64-encoded DER form and sets the ct_log pointer to point to +the new CTLOG. The base64 will be decoded and the public key parsed. The CTLOG +will be associated with the given library context I and property query +string I. + +CTLOG_new_from_base64() does the same thing as +CTLOG_new_from_base64_with_libctx() except that the default library context and +property query string are used. Regardless of whether CTLOG_new() or CTLOG_new_from_base64() is used, it is the caller's responsibility to pass the CTLOG to CTLOG_free() once it is no longer @@ -58,7 +75,8 @@ L =head1 HISTORY -These functions were added in OpenSSL 1.1.0. +The functions CTLOG_new_with_libctx() and CTLOG_new_from_base64_with_libctx() +were added in OpenSSL 3.0. All other functions were added in OpenSSL 1.1.0. =head1 COPYRIGHT diff --git a/doc/man3/CT_POLICY_EVAL_CTX_new.pod b/doc/man3/CT_POLICY_EVAL_CTX_new.pod index 27c04e19..38076352 100644 --- a/doc/man3/CT_POLICY_EVAL_CTX_new.pod +++ b/doc/man3/CT_POLICY_EVAL_CTX_new.pod @@ -2,6 +2,7 @@ =head1 NAME +CT_POLICY_EVAL_CTX_new_with_libctx, CT_POLICY_EVAL_CTX_new, CT_POLICY_EVAL_CTX_free, CT_POLICY_EVAL_CTX_get0_cert, CT_POLICY_EVAL_CTX_set1_cert, CT_POLICY_EVAL_CTX_get0_issuer, CT_POLICY_EVAL_CTX_set1_issuer, @@ -13,6 +14,8 @@ Encapsulates the data required to evaluate whether SCTs meet a Certificate Trans #include + CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new_with_libctx(OPENSSL_CTX *libctx, + const char *propq); CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void); void CT_POLICY_EVAL_CTX_free(CT_POLICY_EVAL_CTX *ctx); X509* CT_POLICY_EVAL_CTX_get0_cert(const CT_POLICY_EVAL_CTX *ctx); @@ -55,8 +58,15 @@ the current time The above requirements are met using the setters described below. -CT_POLICY_EVAL_CTX_new() creates an empty policy evaluation context. This -should then be populated using: +CT_POLICY_EVAL_CTX_new_with_libctx() creates an empty policy evaluation context +and associates it with the given library context I and property query +string I. + +CT_POLICY_EVAL_CTX_new() does the same thing as +CT_POLICY_EVAL_CTX_new_with_libctx() except that it uses the default library +context and property query string. + +The CT_POLICY_EVAL_CTX should then be populated using: =over 2 @@ -106,7 +116,8 @@ found in the TLS SCT extension or OCSP response. =head1 RETURN VALUES -CT_POLICY_EVAL_CTX_new() will return NULL if malloc fails. +CT_POLICY_EVAL_CTX_new_with_libctx() and CT_POLICY_EVAL_CTX_new() will return +NULL if malloc fails. =head1 SEE ALSO @@ -114,7 +125,8 @@ L =head1 HISTORY -These functions were added in OpenSSL 1.1.0. +CT_POLICY_EVAL_CTX_new_with_libctx was added in OpenSSL 3.0. All other +functions were added in OpenSSL 1.1.0. =head1 COPYRIGHT diff --git a/doc/man3/EVP_DigestInit.pod b/doc/man3/EVP_DigestInit.pod index ef40ae49..628e7c23 100644 --- a/doc/man3/EVP_DigestInit.pod +++ b/doc/man3/EVP_DigestInit.pod @@ -110,8 +110,8 @@ The B type is a structure for digest method implementation. =item EVP_MD_fetch() -Fetches the digest implementation for the given B from any -provider offering it, within the criteria given by the B. +Fetches the digest implementation for the given I from any +provider offering it, within the criteria given by the I. See L for further information. The returned value must eventually be freed with EVP_MD_free(). @@ -133,37 +133,45 @@ Allocates and returns a digest context. =item EVP_MD_CTX_reset() -Resets the digest context B. This can be used to reuse an already +Resets the digest context I. This can be used to reuse an already existing context. =item EVP_MD_CTX_free() -Cleans up digest context B and frees up the space allocated to it. +Cleans up digest context I and frees up the space allocated to it. =item EVP_MD_CTX_ctrl() -This is a legacy method. EVP_MD_CTX_set_params() and EVP_MD_CTX_get_params() +I. The control command -is indicated in B and any additional arguments in B and B. +providers.> + +Performs digest-specific control actions on context I. The control command +is indicated in I and any additional arguments in I and I. EVP_MD_CTX_ctrl() must be called after EVP_DigestInit_ex(). Other restrictions may apply depending on the control type and digest implementation. -See L below for more information. + +If this function happens to be used with a fetched B, it will +translate the controls that are known to OpenSSL into L +parameters with keys defined by OpenSSL and call EVP_MD_CTX_get_params() or +EVP_MD_CTX_set_params() as is appropriate for each control command. + +See L below for more information, including what translations are +being done. =item EVP_MD_get_params() -Retrieves the requested list of B from a MD B. +Retrieves the requested list of I from a MD I. See L below for more information. =item EVP_MD_CTX_get_params() -Retrieves the requested list of B from a MD context B. +Retrieves the requested list of I from a MD context I. See L below for more information. =item EVP_MD_CTX_set_params() -Sets the list of B into a MD context B. +Sets the list of I into a MD context I. See L below for more information. =item EVP_MD_gettable_params(), EVP_MD_gettable_ctx_params(), @@ -181,36 +189,36 @@ See L for the use of B as parameter descriptor. =item EVP_MD_CTX_set_flags(), EVP_MD_CTX_clear_flags(), EVP_MD_CTX_test_flags() -Sets, clears and tests B flags. See L below for more information. +Sets, clears and tests I flags. See L below for more information. =item EVP_Digest() A wrapper around the Digest Init_ex, Update and Final_ex functions. -Hashes B bytes of data at B using a digest B from ENGINE -B. The digest value is placed in B and its length is written at B +Hashes I bytes of data at I using a digest I from ENGINE +I. The digest value is placed in I and its length is written at I if the pointer is not NULL. At most B bytes will be written. -If B is NULL the default implementation of digest B is used. +If I is NULL the default implementation of digest I is used. =item EVP_DigestInit_ex() -Sets up digest context B to use a digest B. -B is typically supplied by a function such as EVP_sha1(), or a +Sets up digest context I to use a digest I. +I is typically supplied by a function such as EVP_sha1(), or a value explicitly fetched with EVP_MD_fetch(). -If B is non-NULL, its implementation of the digest B is used if +If I is non-NULL, its implementation of the digest I is used if there is one, and if not, the default implementation is used. =item EVP_DigestUpdate() -Hashes B bytes of data at B into the digest context B. This -function can be called several times on the same B to hash additional +Hashes I bytes of data at I into the digest context I. This +function can be called several times on the same I to hash additional data. =item EVP_DigestFinal_ex() -Retrieves the digest value from B and places it in B. If the B +Retrieves the digest value from I and places it in I. If the I parameter is not NULL then the number of bytes of data written (i.e. the -length of the digest) will be written to the integer at B, at most +length of the digest) will be written to the integer at I, at most B bytes will be written. After calling EVP_DigestFinal_ex() no additional calls to EVP_DigestUpdate() can be made, but EVP_DigestInit_ex() can be called to initialize a new digest operation. @@ -218,13 +226,13 @@ EVP_DigestInit_ex() can be called to initialize a new digest operation. =item EVP_DigestFinalXOF() Interfaces to extendable-output functions, XOFs, such as SHAKE128 and SHAKE256. -It retrieves the digest value from B and places it in B-sized md. +It retrieves the digest value from I and places it in I-sized md. After calling this function no additional calls to EVP_DigestUpdate() can be made, but EVP_DigestInit_ex() can be called to initialize a new operation. =item EVP_MD_CTX_copy_ex() -Can be used to copy the message digest state from B to B. This is +Can be used to copy the message digest state from I to I. This is useful if large amounts of data are to be hashed which only differ in the last few bytes. @@ -235,12 +243,12 @@ default digest implementation and calls EVP_MD_CTX_reset(). =item EVP_DigestFinal() -Similar to EVP_DigestFinal_ex() except the digest context B is +Similar to EVP_DigestFinal_ex() except the digest context I is automatically cleaned up. =item EVP_MD_CTX_copy() -Similar to EVP_MD_CTX_copy_ex() except the destination B does not have to +Similar to EVP_MD_CTX_copy_ex() except the destination I does not have to be initialized. =item EVP_MD_is_a() @@ -311,17 +319,17 @@ should not be used after the EVP_MD_CTX is freed. =item EVP_MD_CTX_set_update_fn() -Sets the update function for B to B. +Sets the update function for I to I. This is the function that is called by EVP_DigestUpdate. If not set, the update function from the B type specified at initialization is used. =item EVP_MD_CTX_update_fn() -Returns the update function for B. +Returns the update function for I. =item EVP_MD_flags() -Returns the B flags. Note that these are different from the B +Returns the I flags. Note that these are different from the B ones. See L for more information. =item EVP_MD_pkey_type() @@ -345,16 +353,16 @@ B structure respectively. =item EVP_MD_CTX_pkey_ctx() -Returns the B assigned to B. The returned pointer should not +Returns the B assigned to I. The returned pointer should not be freed by the caller. =item EVP_MD_CTX_set_pkey_ctx() Assigns an B to B. This is usually used to provide a customized B to L or -L. The B passed to this function should be freed -by the caller. A NULL B pointer is also allowed to clear the B -assigned to B. In such case, freeing the cleared B or not +L. The I passed to this function should be freed +by the caller. A NULL I pointer is also allowed to clear the B +assigned to I. In such case, freeing the cleared B or not depends on how the B is created. =item EVP_MD_do_all_provided() @@ -382,7 +390,7 @@ using a B. =item "pad_type" (B) -Sets the pad type. +Sets the padding type. It is used by the MDC2 algorithm. =back @@ -409,15 +417,21 @@ EVP_MD_CTX_ctrl() can be used to send the following standard controls: Gets the digest Message Integrity Check algorithm string. This is used when creating S/MIME multipart/signed messages, as specified in RFC 3851. -The string value is written to B. +The string value is written to I. + +When used with a fetched B, EVP_MD_CTX_get_params() gets called with +an L item with the key "micalg" (B). =item EVP_MD_CTRL_XOF_LEN -This control sets the digest length for extendable output functions to B. +This control sets the digest length for extendable output functions to I. Sending this control directly should not be necessary, the use of -C is preferred. +EVP_DigestFinalXOF() is preferred. Currently used by SHAKE. +When used with a fetched B, EVP_MD_CTX_get_params() gets called with +an L item with the key "xoflen" (B). + =back =head1 FLAGS @@ -529,7 +543,7 @@ New applications should use the SHA-2 (such as L) or the SHA-3 digest algorithms (such as L). The other digest algorithms are still in common use. -For most applications the B parameter to EVP_DigestInit_ex() will be +For most applications the I parameter to EVP_DigestInit_ex() will be set to NULL to use the default digest implementation. The functions EVP_DigestInit(), EVP_DigestFinal() and EVP_MD_CTX_copy() are diff --git a/doc/man3/EVP_DigestSignInit.pod b/doc/man3/EVP_DigestSignInit.pod index b5bd7bc3..d0c13bbc 100644 --- a/doc/man3/EVP_DigestSignInit.pod +++ b/doc/man3/EVP_DigestSignInit.pod @@ -11,7 +11,7 @@ EVP_DigestSignFinal, EVP_DigestSign - EVP signing functions int EVP_DigestSignInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const char *mdname, const char *props, - EVP_PKEY *pkey); + EVP_PKEY *pkey, OPENSSL_CTX *libctx); int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey); int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt); @@ -51,7 +51,9 @@ existing value in I<*pctx> is overwritten. The EVP_PKEY_CTX value returned must not be freed directly by the application if I is not assigned an EVP_PKEY_CTX value before being passed to EVP_DigestSignInit_ex() (which means the EVP_PKEY_CTX is created inside EVP_DigestSignInit_ex() and it will be freed -automatically when the EVP_MD_CTX is freed). +automatically when the EVP_MD_CTX is freed). If the EVP_PKEY_CTX to be used is +created by EVP_DigestSignInit_ex then it will use the B specified +in I and the property query string specified in I. The digest I may be NULL if the signing algorithm supports it. The I argument can always be NULL. diff --git a/doc/man3/EVP_DigestVerifyInit.pod b/doc/man3/EVP_DigestVerifyInit.pod index 5173abde..9b5de646 100644 --- a/doc/man3/EVP_DigestVerifyInit.pod +++ b/doc/man3/EVP_DigestVerifyInit.pod @@ -11,7 +11,7 @@ EVP_DigestVerifyFinal, EVP_DigestVerify - EVP signature verification functions int EVP_DigestVerifyInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const char *mdname, const char *props, - EVP_PKEY *pkey, EVP_SIGNATURE *signature); + EVP_PKEY *pkey, OPENSSL_CTX *libctx); int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey); int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt); @@ -26,20 +26,17 @@ The EVP signature routines are a high level interface to digital signatures. Input data is digested first before the signature verification takes place. EVP_DigestVerifyInit_ex() sets up verification context B to use a digest -with the name B and public key B. The signature algorithm -B will be used for the actual signature verification which must be -compatible with the public key. The name of the digest to be used is passed to -the provider of the signature algorithm in use. How that provider interprets the -digest name is provider specific. The provider may implement that digest -directly itself or it may (optionally) choose to fetch it (which could result in -a digest from a different provider being selected). If the provider supports -fetching the digest then it may use the B argument for the properties to -be used during the fetch. +with the name B and public key B. The name of the digest to be +used is passed to the provider of the signature algorithm in use. How that +provider interprets the digest name is provider specific. The provider may +implement that digest directly itself or it may (optionally) choose to fetch it +(which could result in a digest from a different provider being selected). If +the provider supports fetching the digest then it may use the B argument +for the properties to be used during the fetch. -The B parameter may be NULL in which case a suitable signature -algorithm implementation will be implicitly fetched based on the type of key in -use. See L for further information about providers and fetching -algorithms. +The I algorithm is used to fetch a B method implicitly, to +be used for the actual signing. See L for +more information about implict fetches. The OpenSSL default and legacy providers support fetching digests and can fetch those digests from any available provider. The OpenSSL fips provider also @@ -53,7 +50,9 @@ Note that any existing value in B<*pctx> is overwritten. The EVP_PKEY_CTX value returned must not be freed directly by the application if B is not assigned an EVP_PKEY_CTX value before being passed to EVP_DigestVerifyInit_ex() (which means the EVP_PKEY_CTX is created inside EVP_DigestVerifyInit_ex() and it will -be freed automatically when the EVP_MD_CTX is freed). +be freed automatically when the EVP_MD_CTX is freed). If the EVP_PKEY_CTX to be +used is created by EVP_DigestVerifyInit_ex then it will use the B +specified in I and the property query string specified in I. No B will be created by EVP_DigestSignInit_ex() if the passed B has already been assigned one via L. See also diff --git a/doc/man3/EVP_PKEY_CTX_ctrl.pod b/doc/man3/EVP_PKEY_CTX_ctrl.pod index ca1b1fa8..829bdb9e 100644 --- a/doc/man3/EVP_PKEY_CTX_ctrl.pod +++ b/doc/man3/EVP_PKEY_CTX_ctrl.pod @@ -51,6 +51,8 @@ EVP_PKEY_CTX_set_dh_kdf_outlen, EVP_PKEY_CTX_get_dh_kdf_outlen, EVP_PKEY_CTX_set0_dh_kdf_ukm, EVP_PKEY_CTX_get0_dh_kdf_ukm, +EVP_PKEY_CTX_set_ec_paramgen_curve_name, +EVP_PKEY_CTX_get_ec_paramgen_curve_name, EVP_PKEY_CTX_set_ec_paramgen_curve_nid, EVP_PKEY_CTX_set_ec_param_enc, EVP_PKEY_CTX_set_ecdh_cofactor_mode, @@ -143,6 +145,10 @@ EVP_PKEY_CTX_set1_id, EVP_PKEY_CTX_get1_id, EVP_PKEY_CTX_get1_id_len #include + int EVP_PKEY_CTX_set_ec_paramgen_curve_name(EVP_PKEY_CTX *ctx, + const char *name); + int EVP_PKEY_CTX_get_ec_paramgen_curve_name(EVP_PKEY_CTX *ctx, + char *name, size_t namelen); int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid); int EVP_PKEY_CTX_set_ec_param_enc(EVP_PKEY_CTX *ctx, int param_enc); int EVP_PKEY_CTX_set_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx, int cofactor_mode); @@ -513,12 +519,24 @@ by the library and should not be freed by the caller. =head2 EC parameters -The EVP_PKEY_CTX_set_ec_paramgen_curve_nid() sets the EC curve for EC parameter -generation to I. For EC parameter generation this macro must be called -or an error occurs because there is no default curve. -This function can also be called to set the curve explicitly when +EVP_PKEY_CTX_set_ec_paramgen_curve_name() sets the EC curve to I for EC +parameter generation. + +EVP_PKEY_CTX_set_ec_paramgen_curve_nid() does the same as +EVP_PKEY_CTX_set_ec_paramgen_curve_name(), but uses a I rather than a +name string. + +For EC parameter generation, one of EVP_PKEY_CTX_set_ec_paramgen_curve_name() +or EVP_PKEY_CTX_set_ec_paramgen_curve_nid() must be called or an error occurs +because there is no default curve. +These function can also be called to set the curve explicitly when generating an EC key. +EVP_PKEY_CTX_get_ec_paramgen_curve_name() finds the curve name that's currently +set with I, and writes it to the location that I points at, as long +as its size I is large enough to store that name, including a +terminating NUL byte. + The EVP_PKEY_CTX_set_ec_param_enc() macro sets the EC parameter encoding to I when generating EC parameters or an EC key. The encoding can be B for explicit parameters (the default in versions diff --git a/doc/man3/EVP_PKEY_fromdata.pod b/doc/man3/EVP_PKEY_fromdata.pod index 2d0059d3..e3ddf680 100644 --- a/doc/man3/EVP_PKEY_fromdata.pod +++ b/doc/man3/EVP_PKEY_fromdata.pod @@ -52,7 +52,7 @@ not supported by the public key algorithm. =head1 SEE ALSO -L, L +L, L, L =head1 HISTORY diff --git a/doc/man3/EVP_PKEY_keygen.pod b/doc/man3/EVP_PKEY_gen.pod similarity index 65% rename from doc/man3/EVP_PKEY_keygen.pod rename to doc/man3/EVP_PKEY_gen.pod index e326b82f..212ea2a7 100644 --- a/doc/man3/EVP_PKEY_keygen.pod +++ b/doc/man3/EVP_PKEY_gen.pod @@ -2,11 +2,12 @@ =head1 NAME -EVP_PKEY_keygen_init, EVP_PKEY_keygen, EVP_PKEY_paramgen_init, -EVP_PKEY_paramgen, EVP_PKEY_CTX_set_cb, EVP_PKEY_CTX_get_cb, +EVP_PKEY_keygen_init, EVP_PKEY_paramgen_init, EVP_PKEY_gen, +EVP_PKEY_CTX_set_cb, EVP_PKEY_CTX_get_cb, EVP_PKEY_CTX_get_keygen_info, EVP_PKEY_CTX_set_app_data, EVP_PKEY_CTX_get_app_data, -EVP_PKEY_gen_cb +EVP_PKEY_gen_cb, +EVP_PKEY_paramgen, EVP_PKEY_keygen - key and parameter generation and check functions =head1 SYNOPSIS @@ -14,9 +15,10 @@ EVP_PKEY_gen_cb #include int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx); - int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx); + int EVP_PKEY_gen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); + int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); typedef int EVP_PKEY_gen_cb(EVP_PKEY_CTX *ctx); @@ -30,24 +32,51 @@ EVP_PKEY_gen_cb =head1 DESCRIPTION -The EVP_PKEY_keygen_init() function initializes a public key algorithm -context using key B for a key generation operation. +Generating keys is sometimes straight forward, just generate the key's +numbers and be done with it. However, there are certain key types that need +key parameters, often called domain parameters but not necessarily limited +to that, that also need to be generated. In addition to this, the caller +may want to set user provided generation parameters that further affect key +parameter or key generation, such as the desired key size. -The EVP_PKEY_keygen() function performs a key generation operation, the -generated key is written to B. +To flexibly allow all that's just been described, key parameter and key +generation is divided into an initialization of a key algorithm context, +functions to set user provided parameters, and finally the key parameter or +key generation function itself. -The functions EVP_PKEY_paramgen_init() and EVP_PKEY_paramgen() are similar -except parameters are generated. +The key algorithm context must be created using L or +variants thereof, see that manual for details. + +EVP_PKEY_keygen_init() initializes a public key algorithm context using key +I for a key generation operation. + +EVP_PKEY_paramgen_init() is similar to EVP_PKEY_keygen_init() except key +parameters are generated. + +After initialization, generation parameters may be provided with +L or L, or any other +function described in those manuals. + +EVP_PKEY_gen() performs the generation operation, the resulting key +parameters or key are written to I<*ppkey>. If I<*ppkey> is NULL when this +function is called, it will be allocated, and should be freed by the caller +when no longer useful, using L. + +EVP_PKEY_paramgen() and EVP_PKEY_keygen() do exactly the same thing as +EVP_PKEY_gen(), after checking that the corresponding EVP_PKEY_paramgen_init() +or EVP_PKEY_keygen_init() was used to initialize I. +These are older functions that are kept for backward compatibility. +It is safe to use EVP_PKEY_gen() instead. The function EVP_PKEY_set_cb() sets the key or parameter generation callback -to B. The function EVP_PKEY_CTX_get_cb() returns the key or parameter +to I. The function EVP_PKEY_CTX_get_cb() returns the key or parameter generation callback. The function EVP_PKEY_CTX_get_keygen_info() returns parameters associated -with the generation operation. If B is -1 the total number of +with the generation operation. If I is -1 the total number of parameters available is returned. Any non negative value returns the value of that parameter. EVP_PKEY_CTX_gen_keygen_info() with a non-negative value for -B should only be called within the generation callback. +I should only be called within the generation callback. If the callback returns 0 then the key generation operation is aborted and an error occurs. This might occur during a time consuming operation where @@ -58,6 +87,13 @@ and retrieve an opaque pointer. This can be used to set some application defined value which can be retrieved in the callback: for example a handle which is used to update a "progress dialog". +=head1 RETURN VALUES + +EVP_PKEY_keygen_init(), EVP_PKEY_paramgen_init(), EVP_PKEY_keygen() and +EVP_PKEY_paramgen() return 1 for success and 0 or a negative value for failure. +In particular a return value of -2 indicates the operation is not supported by +the public key algorithm. + =head1 NOTES After the call to EVP_PKEY_keygen_init() or EVP_PKEY_paramgen_init() algorithm @@ -82,13 +118,6 @@ public key components and parameters (if any). An OpenSSL private key is equivalent to what some libraries call a "key pair". A private key can be used in functions which require the use of a public key or parameters. -=head1 RETURN VALUES - -EVP_PKEY_keygen_init(), EVP_PKEY_paramgen_init(), EVP_PKEY_keygen() and -EVP_PKEY_paramgen() return 1 for success and 0 or a negative value for failure. -In particular a return value of -2 indicates the operation is not supported by -the public key algorithm. - =head1 EXAMPLES Generate a 2048 bit RSA key: @@ -168,11 +197,17 @@ L =head1 HISTORY -These functions were added in OpenSSL 1.0.0. +EVP_PKEY_keygen_init(), int EVP_PKEY_paramgen_init(), EVP_PKEY_keygen(), +EVP_PKEY_paramgen(), EVP_PKEY_gen_cb(), EVP_PKEY_CTX_set_cb(), +EVP_PKEY_CTX_get_cb(), EVP_PKEY_CTX_get_keygen_info(), +EVP_PKEY_CTX_set_app_data() and EVP_PKEY_CTX_get_app_data() were added in +OpenSSL 1.0.0. + +EVP_PKEY_gen() was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_gettable_params.pod b/doc/man3/EVP_PKEY_gettable_params.pod new file mode 100644 index 00000000..87d25c7b --- /dev/null +++ b/doc/man3/EVP_PKEY_gettable_params.pod @@ -0,0 +1,108 @@ +=pod + +=head1 NAME + +EVP_PKEY_gettable_params, EVP_PKEY_get_int_param, EVP_PKEY_get_size_t_param, +EVP_PKEY_get_bn_param, EVP_PKEY_get_utf8_string_param, +EVP_PKEY_get_octet_string_param +- retrieve key parameters from a key + +=head1 SYNOPSIS + + #include + + const OSSL_PARAM *EVP_PKEY_gettable_params(EVP_PKEY *pkey); + int EVP_PKEY_get_int_param(EVP_PKEY *pkey, const char *key_name, int *out); + int EVP_PKEY_get_size_t_param(EVP_PKEY *pkey, const char *key_name, size_t *out); + int EVP_PKEY_get_bn_param(EVP_PKEY *pkey, const char *key_name, BIGNUM **bn); + int EVP_PKEY_get_utf8_string_param(EVP_PKEY *pkey, const char *key_name, + char *str, size_t max_buf_sz, size_t *out_sz); + int EVP_PKEY_get_octet_string_param(EVP_PKEY *pkey, const char *key_name, + unsigned char *buf, size_t max_buf_sz, + size_t *out_sz); + +=head1 DESCRIPTION + +EVP_PKEY_gettable_params() returns a constant list of I indicating +the names and types of key parameters that can be retrieved. +See L for information about parameters. + +EVP_PKEY_get_int_param() retrieves a key I integer value I<*out> +associated with a name of I. + +EVP_PKEY_get_size_t_param() retrieves a key I size_t value I<*out> +associated with a name of I. + +EVP_PKEY_get_bn_param() retrieves a key I BIGNUM value I<**bn> +associated with a name of I. If I<*bn> is NULL then the BIGNUM +is allocated by the method. + +EVP_PKEY_get_utf8_string_param() get a key I UTF8 string value int a buffer +I of maximum size I associated with a name of I. +I<*out_sz> is the returned size of the string if it is not NULL. + +EVP_PKEY_get_octet_string_param() copy a I's octet string value into a buffer +I of maximum size I associated with a name of I. +I<*out_sz> is the returned size of the buffer if it is not NULL. + +=head1 NOTES + +These functions only work for Bs that contain a provider side key. + +=head1 RETURN VALUES + +EVP_PKEY_gettable_params() returns NULL on error or if it is not supported, + +All other methods return 1 if a value associated with the key's I was +successfully returned, or 0 if there was an error. +An error may be returned by methods EVP_PKEY_get_utf8_string_param() and +EVP_PKEY_get_octet_string_param() if I is not big enough to hold the +value. + +=head1 EXAMPLES + + #include + + char *curve_name[64]; + unsigned char pub[256]; + BIGNUM *bn_priv = NULL; + + /* + * NB: assumes 'key' is set up before the next step. In this example the key + * is an EC key. + */ + + if (!EVP_PKEY_get_utf8_string_param(key, OSSL_PKEY_PARAM_EC_NAME, + curve_name, sizeof(curve_name), &len)) { + /* Error */ + } + if (!EVP_PKEY_get_octet_string_param(key, OSSL_PKEY_PARAM_PUB_KEY, + pub, sizeof(pub), &len)) { + /* Error */ + } + if (!EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_PRIV_KEY, &bn_priv)) { + /* Error */ + } + + + BN_clear_free(bn_priv); + +=head1 SEE ALSO + +L, L, L + +=head1 HISTORY + +These functions were added in OpenSSL 3.0. + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut + diff --git a/doc/man3/EVP_PKEY_is_a.pod b/doc/man3/EVP_PKEY_is_a.pod new file mode 100644 index 00000000..cfce3de5 --- /dev/null +++ b/doc/man3/EVP_PKEY_is_a.pod @@ -0,0 +1,72 @@ +=pod + +=head1 NAME + +EVP_PKEY_is_a, EVP_PKEY_can_sign +- key type and capabilities functions + +=head1 SYNOPSIS + + #include + + int EVP_PKEY_is_a(const EVP_PKEY *pkey, const char *name); + int EVP_PKEY_can_sign(const EVP_PKEY *pkey); + +=head1 DESCRIPTION + +EVP_PKEY_is_a() checks if the key type of I is I. + +EVP_PKEY_can_sign() checks if the functionality for the key type of +I supports signing. No other check is done, such as whether +I contains a private key. + +=head1 RETURN VALUES + +EVP_PKEY_is_a() returns 1 if I has the key type I, +otherwise 0. + +EVP_PKEY_can_sign() returns 1 if the I key type functionality +supports signing, otherwise 0. + +=head1 EXAMPLES + +=head2 EVP_PKEY_is_a() + +The loaded providers and what key types they support will ultimately +determine what I is possible to use with EVP_PKEY_is_a(). We do know +that the default provider supports RSA, DH, DSA and EC keys, so we can use +this as an crude example: + + #include + + ... + /* |pkey| is an EVP_PKEY* */ + if (EVP_PKEY_is_a(pkey, "RSA")) { + BIGNUM *modulus = NULL; + if (EVP_PKEY_get_bn_param(pkey, "n", &modulus)) + /* do whatever with the modulus */ + BN_free(modulus); + } + +=head2 EVP_PKEY_can_sign() + + #include + + ... + /* |pkey| is an EVP_PKEY* */ + if (!EVP_PKEY_can_sign(pkey)) { + fprintf(stderr, "Not a signing key!"); + exit(1); + } + /* Sign something... */ + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man3/EVP_PKEY_set1_RSA.pod b/doc/man3/EVP_PKEY_set1_RSA.pod index 8423a0a3..598cda42 100644 --- a/doc/man3/EVP_PKEY_set1_RSA.pod +++ b/doc/man3/EVP_PKEY_set1_RSA.pod @@ -51,52 +51,61 @@ EVP_PKEY_set1_engine, EVP_PKEY_get0_engine - EVP_PKEY assignment functions =head1 DESCRIPTION EVP_PKEY_set1_RSA(), EVP_PKEY_set1_DSA(), EVP_PKEY_set1_DH() and -EVP_PKEY_set1_EC_KEY() set the key referenced by B to B. +EVP_PKEY_set1_EC_KEY() set the key referenced by I to I. EVP_PKEY_get1_RSA(), EVP_PKEY_get1_DSA(), EVP_PKEY_get1_DH() and -EVP_PKEY_get1_EC_KEY() return the referenced key in B or -B if the key is not of the correct type. +EVP_PKEY_get1_EC_KEY() return the referenced key in I or +NULL if the key is not of the correct type. EVP_PKEY_get0_hmac(), EVP_PKEY_get0_poly1305(), EVP_PKEY_get0_siphash(), EVP_PKEY_get0_RSA(), EVP_PKEY_get0_DSA(), EVP_PKEY_get0_DH() -and EVP_PKEY_get0_EC_KEY() also return the referenced key in B or B +and EVP_PKEY_get0_EC_KEY() also return the referenced key in I or NULL if the key is not of the correct type but the reference count of the returned key is B incremented and so must not be freed up after use. EVP_PKEY_assign_RSA(), EVP_PKEY_assign_DSA(), EVP_PKEY_assign_DH(), EVP_PKEY_assign_EC_KEY(), EVP_PKEY_assign_POLY1305() and -EVP_PKEY_assign_SIPHASH() also set the referenced key to B -however these use the supplied B internally and so B -will be freed when the parent B is freed. +EVP_PKEY_assign_SIPHASH() also set the referenced key to I +however these use the supplied I internally and so I +will be freed when the parent I is freed. -EVP_PKEY_base_id() returns the type of B. For example +EVP_PKEY_base_id() returns the type of I. For example an RSA key will return B. -EVP_PKEY_id() returns the actual OID associated with B. Historically keys +EVP_PKEY_id() returns the actual OID associated with I. Historically keys using the same algorithm could use different OIDs. For example an RSA key could use the OIDs corresponding to the NIDs B (equivalent to B) or B (equivalent to B). The use of alternative non-standard OIDs is now rare so B et al are not often seen in practice. -EVP_PKEY_type() returns the underlying type of the NID B. For example +EVP_PKEY_type() returns the underlying type of the NID I. For example EVP_PKEY_type(EVP_PKEY_RSA2) will return B. -EVP_PKEY_get0_engine() returns a reference to the ENGINE handling B. +EVP_PKEY_get0_engine() returns a reference to the ENGINE handling I. -EVP_PKEY_set1_engine() sets the ENGINE handling B to B. It +EVP_PKEY_set1_engine() sets the ENGINE handling I to I. It must be called after the key algorithm and components are set up. -If B does not include an B for B an +If I does not include an B for I an error occurs. EVP_PKEY_set_alias_type() allows modifying a EVP_PKEY to use a different set of algorithms than the default. +=head1 WARNINGS + +The following functions are only reliable with Bs that have +been assigned an internal key with EVP_PKEY_assign_*(): + +EVP_PKEY_id(), EVP_PKEY_base_id(), EVP_PKEY_type(), EVP_PKEY_set_alias_type() + +For EVP_PKEY key type checking purposes, L is more generic. + =head1 NOTES In accordance with the OpenSSL naming convention the key obtained -from or assigned to the B using the B<1> functions must be -freed as well as B. +from or assigned to the I using the B<1> functions must be +freed as well as I. EVP_PKEY_assign_RSA(), EVP_PKEY_assign_DSA(), EVP_PKEY_assign_DH(), EVP_PKEY_assign_EC_KEY(), EVP_PKEY_assign_POLY1305() @@ -129,7 +138,7 @@ EVP_PKEY_set1_RSA(), EVP_PKEY_set1_DSA(), EVP_PKEY_set1_DH() and EVP_PKEY_set1_EC_KEY() return 1 for success or 0 for failure. EVP_PKEY_get1_RSA(), EVP_PKEY_get1_DSA(), EVP_PKEY_get1_DH() and -EVP_PKEY_get1_EC_KEY() return the referenced key or B if +EVP_PKEY_get1_EC_KEY() return the referenced key or NULL if an error occurred. EVP_PKEY_assign_RSA(), EVP_PKEY_assign_DSA(), EVP_PKEY_assign_DH(), diff --git a/doc/man3/EVP_PKEY_set_type.pod b/doc/man3/EVP_PKEY_set_type.pod new file mode 100644 index 00000000..e5111a55 --- /dev/null +++ b/doc/man3/EVP_PKEY_set_type.pod @@ -0,0 +1,68 @@ +=pod + +=head1 NAME + +EVP_PKEY_set_type, EVP_PKEY_set_type_str, EVP_PKEY_set_type_by_keymgmt +- functions to change the EVP_PKEY type + +=head1 SYNOPSIS + + #include + + int EVP_PKEY_set_type(EVP_PKEY *pkey, int type); + int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len); + int EVP_PKEY_set_type_by_keymgmt(EVP_PKEY *pkey, EVP_KEYMGMT *keymgmt); + +=head1 DESCRIPTION + +All the functions described here behave the same in so far that they +clear all the previous key data and methods from I, and reset it +to be of the type of key given by the different arguments. If +I is NULL, these functions will still return the same return +values as if it wasn't. + +EVP_PKEY_set_type() initialises I to contain an internal legacy +key. When doing this, it finds a L +corresponding to I, and associates I with the findings. +It is an error if no L could be found for +I. + +EVP_PKEY_set_type_str() initialises I to contain an internal legacy +key. When doing this, it finds a L +corresponding to I that has then length I, and associates +I with the findings. +It is an error if no L could be found for +I. + +For both EVP_PKEY_set_type() and EVP_PKEY_set_type_str(), I gets +a numeric type, which can be retrieved with L. This +numeric type is taken from the L that was +found, and is equal to or closely related to I in the case of +EVP_PKEY_set_type(), or related to I in the case of +EVP_PKEY_set_type_str(). + +EVP_PKEY_set_type_by_keymgmt() initialises I to contain an +internal provider side key. When doing this, it associates I +with I. For keys initialised like this, the numeric type +retrieved with L will always be B. + +=head1 RETURN VALUES + +All functions described here return 1 if successful, or 0 on error. + +=head1 SEE ALSO + +L, L, L, +L, L, +L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man3/EVP_aes_128_gcm.pod b/doc/man3/EVP_aes_128_gcm.pod index 1ca893a7..56ae7404 100644 --- a/doc/man3/EVP_aes_128_gcm.pod +++ b/doc/man3/EVP_aes_128_gcm.pod @@ -160,6 +160,13 @@ In particular, XTS-AES-128 (B) takes input of a 256-bit key to achieve AES 128-bit security, and XTS-AES-256 (B) takes input of a 512-bit key to achieve AES 256-bit security. +The XTS implementation in OpenSSL does not support streaming. That is there must +only be one L call per L call (and +similarly with the "Decrypt" functions). + +The I parameter to L or L is +the XTS "tweak" value. + =back =head1 RETURN VALUES diff --git a/doc/man3/ISSUER_SIGN_TOOL_new.pod b/doc/man3/ISSUER_SIGN_TOOL_new.pod new file mode 100644 index 00000000..4fb1f70f --- /dev/null +++ b/doc/man3/ISSUER_SIGN_TOOL_new.pod @@ -0,0 +1,51 @@ +=pod + +=head1 NAME + +ISSUER_SIGN_TOOL_new, ISSUER_SIGN_TOOL_free,ISSUER_SIGN_TOOL_it, +d2i_ISSUER_SIGN_TOOL, i2d_ISSUER_SIGN_TOOL + +=head1 SYNOPSIS + +=for openssl generic + + #include + + extern const ISSUER_SIGN_TOOL_it; + + ISSUER_SIGN_TOOL *ISSUER_SIGN_TOOL_new(void); + void ISSUER_SIGN_TOOL_free(ISSUER_SIGN_TOOL *v); + + ISSUER_SIGN_TOOL *d2i_ISSUER_SIGN_TOOL(ISSUER_SIGN_TOOL **a, const unsigned char **pp, long length); + int i2d_ISSUER_SIGN_TOOL(const ISSUER_SIGN_TOOL *a, unsigned char **pp); + +=head1 DESCRIPTION + +The ISSUER_SIGN_TOOL_new() function returns a new ISSUER_SIGN_TOOL. + +ISSUER_SIGN_TOOL_free() frees up a single ISSUER_SIGN_TOOL object. + +=head1 RETURN VALUES + +ISSUER_SIGN_TOOL_new() returns a newly created ISSUER_SIGN_TOOL or NULL if the call fails. + +ISSUER_SIGN_TOOL_free() does not return values. + +d2i_ISSUER_SIGN_TOOL() and i2d_ISSUER_SIGN_TOOL() decode and encode an B +structure. They otherwise follow the conventions of other ASN.1 functions such as d2i_X509(). + +=head1 HISTORY + +The ISSUER_SIGN_TOOL_up_ref(), ISSUER_SIGN_TOOL_lock() and ISSUER_SIGN_TOOL_unlock() +functions were added in OpenSSL 3.0. + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man3/NCONF_new_with_libctx.pod b/doc/man3/NCONF_new_with_libctx.pod new file mode 100644 index 00000000..b976d7f7 --- /dev/null +++ b/doc/man3/NCONF_new_with_libctx.pod @@ -0,0 +1,59 @@ +=pod + +=head1 NAME + +NCONF_new_with_libctx, NCONF_new, NCONF_free, NCONF_default, NCONF_load +- functionality to Load and parse configuration files manually + +=head1 SYNOPSIS + + #include + + CONF *NCONF_new_with_libctx(OPENSSL_CTX *libctx, CONF_METHOD *meth); + CONF *NCONF_new(CONF_METHOD *meth); + void NCONF_free(CONF *conf); + CONF_METHOD *NCONF_default(void); + int NCONF_load(CONF *conf, const char *file, long *eline); + +=head1 DESCRIPTION + +NCONF_new_with_libctx() creates a new CONF object in heap memory and assigns to +it a context I that can be used during loading. If the method table +I is set to NULL then the default value of NCONF_default() is used. + +NCONF_new() is similar to NCONF_new_with_libctx() but sets the I to NULL. + +NCONF_free() frees the data associated with I and then frees the I +object. + +NCONF_load() parses the file named I and adds the values found to +I. If an error occurs I and I list the file and line that +the load failed on if they are not NULL. + +NCONF_default() gets the default method table for processing a configuration file. + +=head1 RETURN VALUES + +NCONF_load() returns 1 on success or 0 on error. + +NCONF_new_with_libctx() and NCONF_new() return a newly created I object +or NULL if an error occurs. + +=head1 SEE ALSO + +L, + +=head1 HISTORY + +NCONF_new_with_libctx() was added in OpenSSL 3.0. + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man3/OCSP_response_status.pod b/doc/man3/OCSP_response_status.pod index c1de86b1..6c02b55f 100644 --- a/doc/man3/OCSP_response_status.pod +++ b/doc/man3/OCSP_response_status.pod @@ -4,8 +4,9 @@ OCSP_response_status, OCSP_response_get1_basic, OCSP_response_create, OCSP_RESPONSE_free, OCSP_RESPID_set_by_name, -OCSP_RESPID_set_by_key, OCSP_RESPID_match, -OCSP_basic_sign, OCSP_basic_sign_ctx - OCSP response functions +OCSP_RESPID_set_by_key_ex, OCSP_RESPID_set_by_key, OCSP_RESPID_match_ex, +OCSP_RESPID_match, OCSP_basic_sign, OCSP_basic_sign_ctx +- OCSP response functions =head1 SYNOPSIS @@ -17,7 +18,11 @@ OCSP_basic_sign, OCSP_basic_sign_ctx - OCSP response functions void OCSP_RESPONSE_free(OCSP_RESPONSE *resp); int OCSP_RESPID_set_by_name(OCSP_RESPID *respid, X509 *cert); + int OCSP_RESPID_set_by_key_ex(OCSP_RESPID *respid, X509 *cert, + OPENSSL_CTX *libctx, const char *propq); int OCSP_RESPID_set_by_key(OCSP_RESPID *respid, X509 *cert); + int OCSP_RESPID_match_ex(OCSP_RESPID *respid, X509 *cert, OPENSSL_CTX *libctx, + const char *propq); int OCSP_RESPID_match(OCSP_RESPID *respid, X509 *cert); int OCSP_basic_sign(OCSP_BASICRESP *brsp, X509 *signer, EVP_PKEY *key, @@ -28,49 +33,60 @@ OCSP_basic_sign, OCSP_basic_sign_ctx - OCSP response functions =head1 DESCRIPTION -OCSP_response_status() returns the OCSP response status of B. It returns -one of the values: B, -B, -B, B -B, or B. +OCSP_response_status() returns the OCSP response status of I. It returns +one of the values: I, +I, +I, I +I, or I. -OCSP_response_get1_basic() decodes and returns the B structure -contained in B. +OCSP_response_get1_basic() decodes and returns the I structure +contained in I. -OCSP_response_create() creates and returns an B structure for -B and optionally including basic response B. +OCSP_response_create() creates and returns an I structure for +I and optionally including basic response I. -OCSP_RESPONSE_free() frees up OCSP response B. +OCSP_RESPONSE_free() frees up OCSP response I. OCSP_RESPID_set_by_name() sets the name of the OCSP_RESPID to be the same as the -subject name in the supplied X509 certificate B for the OCSP responder. +subject name in the supplied X509 certificate I for the OCSP responder. -OCSP_RESPID_set_by_key() sets the key of the OCSP_RESPID to be the same as the -key in the supplied X509 certificate B for the OCSP responder. The key is -stored as a SHA1 hash. +OCSP_RESPID_set_by_key_ex() sets the key of the OCSP_RESPID to be the same as the +key in the supplied X509 certificate I for the OCSP responder. The key is +stored as a SHA1 hash. To calculate the hash the SHA1 algorithm is fetched using +the library ctx I and the property query string I (see +L for further information). + +OCSP_RESPID_set_by_key() does the same as OCSP_RESPID_set_by_key_ex() except +that the default library context is used with an empty property query string. Note that an OCSP_RESPID can only have one of the name, or the key set. Calling OCSP_RESPID_set_by_name() or OCSP_RESPID_set_by_key() will clear any existing setting. -OCSP_RESPID_match() tests whether the OCSP_RESPID given in B matches -with the X509 certificate B. +OCSP_RESPID_match_ex() tests whether the OCSP_RESPID given in I matches +with the X509 certificate I based on the SHA1 hash. To calculate the hash +the SHA1 algorithm is fetched using the library ctx I and the property +query string I (see L for further +information). -OCSP_basic_sign() signs OCSP response B using certificate B, private key -B, digest B and additional certificates B. If the B option -B is set then no certificates will be included in the response. If the -B option B is set then the responder is identified by key ID -rather than by name. OCSP_basic_sign_ctx() also signs OCSP response B but -uses the parameters contained in digest context B. +OCSP_RESPID_match() does the same as OCSP_RESPID_match_ex() except that the +default library context is used with an empty property query string. + +OCSP_basic_sign() signs OCSP response I using certificate I, private key +I, digest I and additional certificates I. If the I option +I is set then no certificates will be included in the response. If the +I option I is set then the responder is identified by key ID +rather than by name. OCSP_basic_sign_ctx() also signs OCSP response I but +uses the parameters contained in digest context I. =head1 RETURN VALUES OCSP_RESPONSE_status() returns a status value. -OCSP_response_get1_basic() returns an B structure pointer or -B if an error occurred. +OCSP_response_get1_basic() returns an I structure pointer or +I if an error occurred. -OCSP_response_create() returns an B structure pointer or B +OCSP_response_create() returns an I structure pointer or I if an error occurred. OCSP_RESPONSE_free() does not return a value. @@ -85,7 +101,7 @@ or 0 otherwise. =head1 NOTES OCSP_response_get1_basic() is only called if the status of a response is -B. +I. =head1 SEE ALSO diff --git a/doc/man3/OPENSSL_CTX.pod b/doc/man3/OPENSSL_CTX.pod index d574a374..33012507 100644 --- a/doc/man3/OPENSSL_CTX.pod +++ b/doc/man3/OPENSSL_CTX.pod @@ -2,7 +2,8 @@ =head1 NAME -OPENSSL_CTX, OPENSSL_CTX_new, OPENSSL_CTX_free - OpenSSL library context +OPENSSL_CTX, OPENSSL_CTX_new, OPENSSL_CTX_free, OPENSSL_CTX_load_config +- OpenSSL library context =head1 SYNOPSIS @@ -11,6 +12,7 @@ OPENSSL_CTX, OPENSSL_CTX_new, OPENSSL_CTX_free - OpenSSL library context typedef struct openssl_ctx_st OPENSSL_CTX; OPENSSL_CTX *OPENSSL_CTX_new(void); + int OPENSSL_CTX_load_config(OPENSSL_CTX *ctx, const char *config_file); void OPENSSL_CTX_free(OPENSSL_CTX *ctx); =head1 DESCRIPTION @@ -26,6 +28,10 @@ multi-threaded applications to properly clean up thread local resources before the OPENSSL_CTX is freed. See L for more information. +OPENSSL_CTX_load_config() loads a configuration file using the given C. +This can be used to associate a libctx with providers that are loaded from +a configuration. + OPENSSL_CTX_free() frees the given C. =head1 RETURN VALUES @@ -37,12 +43,12 @@ OPENSSL_CTX_free() doesn't return any value. =head1 HISTORY -OPENSSL_CTX, OPENSSL_CTX_new() and OPENSSL_CTX_free() +OPENSSL_CTX, OPENSSL_CTX_new(), OPENSSL_CTX_load_config() and OPENSSL_CTX_free() were added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OSSL_CMP_CTX_new.pod b/doc/man3/OSSL_CMP_CTX_new.pod index b10cfc48..d070a59b 100644 --- a/doc/man3/OSSL_CMP_CTX_new.pod +++ b/doc/man3/OSSL_CMP_CTX_new.pod @@ -11,15 +11,14 @@ OSSL_CMP_CTX_set_log_cb, OSSL_CMP_CTX_set_log_verbosity, OSSL_CMP_CTX_print_errors, OSSL_CMP_CTX_set1_serverPath, -OSSL_CMP_CTX_set1_serverName, +OSSL_CMP_CTX_set1_server, OSSL_CMP_CTX_set_serverPort, -OSSL_CMP_CTX_set1_proxyName, -OSSL_CMP_CTX_set_proxyPort, -OSSL_CMP_DEFAULT_PORT, +OSSL_CMP_CTX_set1_proxy, +OSSL_CMP_CTX_set1_no_proxy, OSSL_CMP_CTX_set_http_cb, OSSL_CMP_CTX_set_http_cb_arg, OSSL_CMP_CTX_get_http_cb_arg, -OSSL_cmp_transfer_cb_t, +OSSL_CMP_transfer_cb_t, OSSL_CMP_CTX_set_transfer_cb, OSSL_CMP_CTX_set_transfer_cb_arg, OSSL_CMP_CTX_get_transfer_cb_arg, @@ -47,7 +46,7 @@ OSSL_CMP_CTX_push0_policy, OSSL_CMP_CTX_set1_oldCert, OSSL_CMP_CTX_set1_p10CSR, OSSL_CMP_CTX_push0_genm_ITAV, -OSSL_cmp_certConf_cb_t, +OSSL_CMP_certConf_cb_t, OSSL_CMP_CTX_set_certConf_cb, OSSL_CMP_CTX_set_certConf_cb_arg, OSSL_CMP_CTX_get_certConf_cb_arg, @@ -72,24 +71,23 @@ OSSL_CMP_CTX_set1_senderNonce int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt); /* logging and error reporting: */ - int OSSL_CMP_CTX_set_log_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_log_cb_t cb); + int OSSL_CMP_CTX_set_log_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_log_cb_t cb); #define OSSL_CMP_CTX_set_log_verbosity(ctx, level) void OSSL_CMP_CTX_print_errors(OSSL_CMP_CTX *ctx); /* message transfer: */ int OSSL_CMP_CTX_set1_serverPath(OSSL_CMP_CTX *ctx, const char *path); - int OSSL_CMP_CTX_set1_serverName(OSSL_CMP_CTX *ctx, const char *name); + int OSSL_CMP_CTX_set1_server(OSSL_CMP_CTX *ctx, const char *address); int OSSL_CMP_CTX_set_serverPort(OSSL_CMP_CTX *ctx, int port); - int OSSL_CMP_CTX_set1_proxyName(OSSL_CMP_CTX *ctx, const char *name); - int OSSL_CMP_CTX_set_proxyPort(OSSL_CMP_CTX *ctx, int port); - #define OSSL_CMP_DEFAULT_PORT 80 + int OSSL_CMP_CTX_set1_proxy(OSSL_CMP_CTX *ctx, const char *name); + int OSSL_CMP_CTX_set1_no_proxy(OSSL_CMP_CTX *ctx, const char *names); int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, HTTP_bio_cb_t cb); int OSSL_CMP_CTX_set_http_cb_arg(OSSL_CMP_CTX *ctx, void *arg); void *OSSL_CMP_CTX_get_http_cb_arg(const OSSL_CMP_CTX *ctx); - typedef OSSL_CMP_MSG *(*OSSL_cmp_transfer_cb_t)(OSSL_CMP_CTX *ctx, + typedef OSSL_CMP_MSG *(*OSSL_CMP_transfer_cb_t)(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req); int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx, - OSSL_cmp_transfer_cb_t cb); + OSSL_CMP_transfer_cb_t cb); int OSSL_CMP_CTX_set_transfer_cb_arg(OSSL_CMP_CTX *ctx, void *arg); void *OSSL_CMP_CTX_get_transfer_cb_arg(const OSSL_CMP_CTX *ctx); @@ -134,9 +132,9 @@ OSSL_CMP_CTX_set1_senderNonce int OSSL_CMP_CTX_push0_genm_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav); /* certificate confirmation: */ - typedef int (*OSSL_cmp_certConf_cb_t)(OSSL_CMP_CTX *ctx, X509 *cert, + typedef int (*OSSL_CMP_certConf_cb_t)(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info, const char **txt); - int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_certConf_cb_t cb); + int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_certConf_cb_t cb); int OSSL_CMP_CTX_set_certConf_cb_arg(OSSL_CMP_CTX *ctx, void *arg); void *OSSL_CMP_CTX_get_certConf_cb_arg(const OSSL_CMP_CTX *ctx); @@ -149,7 +147,7 @@ OSSL_CMP_CTX_set1_senderNonce STACK_OF(X509) *OSSL_CMP_CTX_get1_caPubs(const OSSL_CMP_CTX *ctx); STACK_OF(X509) *OSSL_CMP_CTX_get1_extraCertsIn(const OSSL_CMP_CTX *ctx); - /* for test purposes only: */ + /* for testing and debugging purposes: */ int OSSL_CMP_CTX_set1_transactionID(OSSL_CMP_CTX *ctx, const ASN1_OCTET_STRING *id); int OSSL_CMP_CTX_set1_senderNonce(OSSL_CMP_CTX *ctx, @@ -172,7 +170,7 @@ from the last executed transaction. All other field values (i.e., CMP options) are retained for potential re-use. OSSL_CMP_CTX_set_option() sets the given value for the given option -(e.g., OSSL_CMP_OPT_IMPLICITCONFIRM) in the given OSSL_CMP_CTX structure. +(e.g., OSSL_CMP_OPT_IMPLICIT_CONFIRM) in the given OSSL_CMP_CTX structure. The following options can be set: @@ -184,17 +182,17 @@ The following options can be set: due to errors, warnings, general info, debugging, etc. Default is OSSL_CMP_LOG_INFO. See also L. -=item B +=item B Number of seconds (or 0 for infinite) a CMP message round trip is allowed to take before a timeout error is returned. Default is 120. -=item B +=item B Maximum total number of seconds an enrollment (including polling) may take. Default is 0 (infinite). -=item B +=item B Number of days new certificates are asked to be valid for. @@ -211,7 +209,7 @@ The following options can be set: Demand that the given policies are flagged as critical. -=item B +=item B Select the proof of possession method to use. Possible values are: @@ -239,7 +237,7 @@ The following options can be set: OSSL_CMP_OPT_MAC_ALGNID The MAC algorithm NID to be used in RFC 4210's MSG_MAC_ALG, - if applicable used for message protection. + if applicable used for message protection. Default is HMAC-SHA1 as per RFC 4210. =item B @@ -247,14 +245,14 @@ The following options can be set: The reason code to be included in a Revocation Request (RR); values: 0..10 (RFC 5210, 5.3.1) or -1 for none, which is the default. -=item B +=item B Request server to enable implicit confirm mode, where the client does not need to send confirmation upon receiving the certificate. If the server does not enable implicit confirmation in the return message, then confirmation is sent anyway. -=item B +=item B Do not confirm enrolled certificates, to cope with broken servers not supporting implicit confirmation correctly. @@ -290,7 +288,7 @@ RFC 4210. =back OSSL_CMP_CTX_get_option() reads the current value of the given option -(e.g., OSSL_CMP_OPT_IMPLICITCONFIRM) from the given OSSL_CMP_CTX structure. +(e.g., OSSL_CMP_OPT_IMPLICIT_CONFIRM) from the given OSSL_CMP_CTX structure. OSSL_CMP_CTX_set_log_cb() sets in B the callback function C for handling error queue entries and logging messages. @@ -306,19 +304,30 @@ It is similar to B but uses the CMP log callback function if set in the C for uniformity with CMP logging if given. Otherwise it uses B to print to STDERR (unless OPENSSL_NO_STDIO is defined). -OSSL_CMP_CTX_set1_serverPath() sets the HTTP path of the CMP server on the host. +OSSL_CMP_CTX_set1_serverPath() sets the HTTP path of the CMP server on the host, +also known as "CMP alias". +The default is "/". -OSSL_CMP_CTX_set1_serverName() sets the given server Address (as IP or name) -in the given OSSL_CMP_CTX structure. +OSSL_CMP_CTX_set1_server() sets the given server B
+(which may be a hostname or IP address or NULL) in the given B. OSSL_CMP_CTX_set_serverPort() sets the port of the CMP server to connect to. -Port defaults to OSSL_CMP_DEFAULT_PORT = 80 if not set explicitly. +If not used or the B argument is 0 +the default port applies, which is 80 for HTTP and 443 for HTTPS. -OSSL_CMP_CTX_set1_proxyName() sets the hostname of the HTTP proxy to be used -for connecting to the CA server. +OSSL_CMP_CTX_set1_proxy() sets the HTTP proxy to be used for connecting to +the given CMP server unless overruled by any "no_proxy" settings (see below). +If TLS is not used this defaults to the value of +the environment variable B if set, else B. +Otherwise defaults to the value of B if set, else B. +An empty proxy string specifies not to use a proxy. +Else the format is I<[http[s]://]address[:port][/path]>, +where any path given is ignored. +The default port number is 80, or 443 in case "https:" is given. -OSSL_CMP_CTX_set_proxyPort() sets the port of the HTTP proxy. -Port defaults to OSSL_CMP_DEFAULT_PORT = 80 if not set explicitly. +OSSL_CMP_CTX_set1_no_proxy() sets the list of server hostnames not to use +an HTTP proxy for. The names may be separated by commas and/or whitespace. +Defaults to the environment variable B if set, else B. OSSL_CMP_CTX_set_http_cb() sets the optional BIO connect/disconnect callback function, which has the prototype @@ -350,19 +359,18 @@ OSSL_CMP_CTX_set_http_cb_arg() or NULL if unset. OSSL_CMP_CTX_set_transfer_cb() sets the message transfer callback function, which has the type - typedef OSSL_CMP_MSG *(*OSSL_cmp_transfer_cb_t) (OSSL_CMP_CTX *ctx, + typedef OSSL_CMP_MSG *(*OSSL_CMP_transfer_cb_t) (OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req); Returns 1 on success, 0 on error. Default is NULL, which implies the use of L. The callback should send the CMP request message it obtains via the B -parameter and on success return the response. +parameter and on success return the response, else it must return NULL. The transfer callback may make use of a custom defined argument stored in the ctx by means of OSSL_CMP_CTX_set_transfer_cb_arg(), which may be retrieved again through OSSL_CMP_CTX_get_transfer_cb_arg(). - OSSL_CMP_CTX_set_transfer_cb_arg() sets an argument, respectively a pointer to a structure containing arguments, optionally to be used by the transfer callback. B is not consumed, and it must therefore explicitly be freed when not @@ -372,9 +380,9 @@ OSSL_CMP_CTX_get_transfer_cb_arg() gets the argument, respectively the pointer to a structure containing arguments, previously set by OSSL_CMP_CTX_set_transfer_cb_arg() or NULL if unset. -OSSL_CMP_CTX_set1_srvCert() pins the server certificate to be directly trusted -(even if it is expired) for verifying response messages. -The cert pointer is not consumed. It may be NULL to clear the entry. +OSSL_CMP_CTX_set1_srvCert() pins the given server certificate B +directly trusts it (even if it is expired) for verifying response messages. +The B argument may be NULL to clear the entry. OSSL_CMP_CTX_set1_expected_sender() sets the Distinguished Name (DN) expected to be given in the sender response for messages protected with MSG_SIG_ALG. This @@ -384,8 +392,7 @@ identify the server certificate. This can be used to ensure that only a particular entity is accepted to act as CMP server, and attackers are not able to use arbitrary certificates of a trusted PKI hierarchy to fraudulently pose as server. -This defaults to the subject DN of the certificate set via -OSSL_CMP_CTX_set1_srvCert(), if any. +This defaults to the subject of the B, if any. OSSL_CMP_CTX_set0_trustedStore() sets the X509_STORE type certificate store containing trusted (root) CA certificates. The certificate store may also hold @@ -404,32 +411,52 @@ The reference counts of those certificates handled successfully are increased. OSSL_CMP_CTX_get0_untrusted_certs(OSSL_CMP_CTX *ctx) returns a pointer to the list of untrusted certs, which my be empty if unset. -OSSL_CMP_CTX_set1_clCert() sets the client certificate in the given -OSSL_CMP_CTX structure. The client certificate will then be used by the -functions to set the "sender" field for outgoing messages and it will be -included in the extraCerts field. +OSSL_CMP_CTX_set1_clCert() sets the client certificate in the given B. +The public key of this B must correspond to +the private key set via B. +When using signature-based protection of CMP request messages +this "protection certificate" will be included first in the extraCerts field. +The subject of this B will be used as the "sender" field +of outgoing CMP messages, with the fallback being +the B set via B. +The B argument may be NULL to clear the entry. -OSSL_CMP_CTX_set1_pkey() sets the private key corresponding to the client -certificate set with B in the given CMP context. -Used to create the protection in case of MSG_SIG_ALG. +OSSL_CMP_CTX_set1_pkey() sets the private key corresponding to +the client certificate B set via B. +This key is used create signature-based protection (protectionAlg = MSG_SIG_ALG) +of outgoing messages +unless a PBM secret has been set via B. +The B argument may be NULL to clear the entry. -OSSL_CMP_CTX_set1_referenceValue() sets the given referenceValue in the given -B or clears it if the B argument is NULL. +OSSL_CMP_CTX_set1_secretValue() sets the byte string B with length B +as PBM secret in the given B or clears it if the B argument is NULL. +If present, this secret is used to create PBM-based protection of outgoing +messages and to verify any PBM-based protection of incoming messages +(protectionAlg = MSG_MAC_ALG). PBM stands for Password-Based MAC. +PBM-based protection takes precedence over signature-based protection. -OSSL_CMP_CTX_set1_secretValue() sets the B with the length B in the -given B or clears it if the B argument is NULL. +OSSL_CMP_CTX_set1_referenceValue() sets the given referenceValue B with +length B in the given B or clears it if the B argument is NULL. +According to RFC 4210 section 5.1.1, if no value for the "sender" field in +CMP message headers can be determined (i.e., no B and no B +is given) then the "sender" field will contain the NULL-DN +and the senderKID field of the CMP message header must be set. +When signature-based protection is used the senderKID will be set to +the subjectKeyIdentifier of the as far as present. +If not present or when PBM-based protection is used +the B value is taken as the fallback value for the senderKID. OSSL_CMP_CTX_set1_recipient() sets the recipient name that will be used in the PKIHeader of a request message, i.e. the X509 name of the (CA) server. -Setting is overruled by subject of srvCert if set. -If neither srvCert nor recipient are set, the recipient of the PKI message is +Setting is overruled by subject of B if set. +If neither B nor recipient are set, the recipient of the PKI message is determined in the following order: issuer, issuer of old cert (oldCert), -issuer of client cert (clCert), else NULL-DN. +issuer of client cert (B), else NULL-DN. When a response is received, its sender must match the recipient of the request. OSSL_CMP_CTX_push0_geninfo_ITAV() adds B to the stack in the B to be added to the GeneralInfo field of the CMP PKIMessage header of a request -message sent with this context. Consumes the pointer to B. +message sent with this context. OSSL_CMP_CTX_set1_extraCertsOut() sets the stack of extraCerts that will be sent to remote. @@ -450,24 +477,22 @@ will be set in the CertTemplate, i.e., the X509 name of the CA server. OSSL_CMP_CTX_set1_subjectName() sets the subject DN that will be used in the CertTemplate structure when requesting a new cert. For Key Update Requests -(KUR), it defaults to the subject DN of the reference certificate, +(KUR), it defaults to the subject DN of the B, see B. This default is used for Initialization Requests (IR) and Certification Requests (CR) only if no SANs are set. - -If clCert is not set (e.g. in case of IR with MSG_MAC_ALG), the subject DN -is also used as sender of the PKI message. +The B is also used as the "sender" field for outgoing CMP messages +if no B has been set (e.g., in case requests are protected using PBM). OSSL_CMP_CTX_push1_subjectAltName() adds the given X509 name to the list of alternate names on the certificate template request. This cannot be used if any Subject Alternative Name extension is set via OSSL_CMP_CTX_set0_reqExtensions(). By default, unless OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT has been set, -the Subject Alternative Names are copied from the reference certificate, -see OSSL_CMP_CTX_set1_oldCert(). - +the Subject Alternative Names are copied from the B, +see B. If set and the subject DN is not set with OSSL_CMP_CTX_set1_subjectName(), then the certificate template of an IR and CR will not be filled with the default -subject DN from the reference certificate (see OSSL_CMP_CTX_set1_oldCert(). +subject DN from the B. If a subject DN is desired it needs to be set explicitly with OSSL_CMP_CTX_set1_subjectName(). @@ -483,7 +508,7 @@ to the X509_EXTENSIONS of the requested certificate template. OSSL_CMP_CTX_set1_oldCert() sets the old certificate to be updated in Key Update Requests (KUR) or to be revoked in Revocation Requests (RR). It must be given for RR, else it defaults to B. -The reference certificate determined in this way, if any, is also used for +The B determined in this way, if any, is also used for deriving default subject DN and Subject Alternative Names for IR, CR, and KUR. Its issuer, if any, is used as default recipient in the CMP message header. @@ -491,13 +516,12 @@ OSSL_CMP_CTX_set1_p10CSR() sets the PKCS#10 CSR to be used in P10CR. OSSL_CMP_CTX_push0_genm_ITAV() adds B to the stack in the B which will be the body of a General Message sent with this context. -Consumes the pointer to B. OSSL_CMP_CTX_set_certConf_cb() sets the callback used for evaluating the newly enrolled certificate before the library sends, depending on its result, a positive or negative certConf message to the server. The callback has type - typedef int (*OSSL_cmp_certConf_cb_t) (OSSL_CMP_CTX *ctx, X509 *cert, + typedef int (*OSSL_CMP_certConf_cb_t) (OSSL_CMP_CTX *ctx, X509 *cert, int fail_info, const char **txt); and should inspect the certificate it obtains via the B parameter and may @@ -587,7 +611,7 @@ All other functions return 1 on success, 0 on error. The following code does an Initialization Request: cmp_ctx = OSSL_CMP_CTX_new(); - OSSL_CMP_CTX_set1_serverName(cmp_ctx, opt_serverName); + OSSL_CMP_CTX_set1_server(cmp_ctx, address); OSSL_CMP_CTX_set1_referenceValue(cmp_ctx, ref, ref_len); OSSL_CMP_CTX_set1_secretValue(cmp_ctx, sec, sec_len); OSSL_CMP_CTX_set0_newPkey(cmp_ctx, new_pkey, 1); @@ -599,7 +623,7 @@ The following code does an Initialization Request using an external identity certificate (RFC 4210, Appendix E.7): cmp_ctx = OSSL_CMP_CTX_new(); - OSSL_CMP_CTX_set1_serverName(cmp_ctx, sname); + OSSL_CMP_CTX_set1_server(cmp_ctx, sname); OSSL_CMP_CTX_set1_clCert(cmp_ctx, cl_cert); OSSL_CMP_CTX_set1_pkey(cmp_ctx, pkey); OSSL_CMP_CTX_set0_newPkey(cmp_ctx, new_pkey, 1); @@ -614,7 +638,7 @@ which is trusted by the current CA the code will connect to. The following code does a Key Update Request: cmp_ctx = OSSL_CMP_CTX_new(); - OSSL_CMP_CTX_set1_serverName(cmp_ctx, sname); + OSSL_CMP_CTX_set1_server(cmp_ctx, url); OSSL_CMP_CTX_set1_pkey(cmp_ctx, pkey); OSSL_CMP_CTX_set0_newPkey(cmp_ctx, new_pkey, 1); OSSL_CMP_CTX_set1_clCert(cmp_ctx, cl_cert); @@ -627,7 +651,7 @@ including, as an example, the id-it-signKeyPairTypes OID and prints info on the General Response contents. cmp_ctx = OSSL_CMP_CTX_new(); - OSSL_CMP_CTX_set1_serverName(cmp_ctx, sname); + OSSL_CMP_CTX_set1_server(cmp_ctx, sname); OSSL_CMP_CTX_set1_referenceValue(cmp_ctx, ref, ref_len); OSSL_CMP_CTX_set1_secretValue(cmp_ctx, sec, sec_len); diff --git a/doc/man3/OSSL_CMP_CTX_snprint_PKIStatus.pod b/doc/man3/OSSL_CMP_CTX_snprint_PKIStatus.pod deleted file mode 100644 index 3ae6831e..00000000 --- a/doc/man3/OSSL_CMP_CTX_snprint_PKIStatus.pod +++ /dev/null @@ -1,46 +0,0 @@ -=pod - -=head1 NAME - -OSSL_CMP_CTX_snprint_PKIStatus -- function(s) for managing the CMP PKIStatus - -=head1 SYNOPSIS - - #include - - char *OSSL_CMP_CTX_snprint_PKIStatus(OSSL_CMP_CTX *ctx, char *buf, int bufsize); - -=head1 DESCRIPTION - -This is the PKIStatus API for using CMP (Certificate Management Protocol) with -OpenSSL. - -OSSL_CMP_CTX_snprint_PKIStatus() takes the PKIStatusInfo components contained -in the given CMP context and places a human-readable string created from them -in the given buffer, with the given maximal length. -On success it returns a copy of the buffer pointer containing the string. - -=head1 NOTES - -CMP is defined in RFC 4210 (and CRMF in RFC 4211). - -=head1 RETURN VALUES - -OSSL_CMP_CTX_snprint_PKIStatus() -returns the intended pointer value as described above or NULL on error. - -=head1 HISTORY - -The OpenSSL CMP support was added in OpenSSL 3.0. - -=head1 COPYRIGHT - -Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved. - -Licensed under the Apache License 2.0 (the "License"). You may not use -this file except in compliance with the License. You can obtain a copy -in the file LICENSE in the source distribution or at -L. - -=cut diff --git a/doc/man3/OSSL_CMP_MSG_get0_header.pod b/doc/man3/OSSL_CMP_MSG_get0_header.pod index 3ed11400..f42b8eaa 100644 --- a/doc/man3/OSSL_CMP_MSG_get0_header.pod +++ b/doc/man3/OSSL_CMP_MSG_get0_header.pod @@ -2,7 +2,9 @@ =head1 NAME -OSSL_CMP_MSG_get0_header +OSSL_CMP_MSG_get0_header, +d2i_OSSL_CMP_MSG_bio, +i2d_OSSL_CMP_MSG_bio - function(s) manipulating CMP messages =head1 SYNOPSIS @@ -10,20 +12,32 @@ OSSL_CMP_MSG_get0_header #include OSSL_CMP_PKIHEADER *OSSL_CMP_MSG_get0_header(const OSSL_CMP_MSG *msg); + OSSL_CMP_MSG *d2i_OSSL_CMP_MSG_bio(BIO *bio, OSSL_CMP_MSG **msg); + int i2d_OSSL_CMP_MSG_bio(BIO *bio, const OSSL_CMP_MSG *msg); =head1 DESCRIPTION OSSL_CMP_MSG_get0_header returns the header of the given CMP message. +d2i_OSSL_CMP_MSG_bio parses an ASN.1-encoded OSSL_CMP_MSG from the BIO I. +It assigns a pointer to the new structure to I<*msg> if I is not NULL. + +i2d_OSSL_CMP_MSG_bio writes the OSSL_CMP_MSG I in ASN.1 encoding +to BIO I. + =head1 NOTES CMP is defined in RFC 4210. =head1 RETURN VALUES -CMP_MSG_get0_header() returns the intended pointer value as described above +OSSL_CMP_MSG_get0_header() returns the intended pointer value as described above or NULL if the respective entry does not exist and on error. +d2i_OSSL_CMP_MSG_bio() returns the parsed message or NULL on error. + +i2d_OSSL_CMP_MSG_bio() returns 1 on success or 0 on error. + =head1 HISTORY The OpenSSL CMP support was added in OpenSSL 3.0. diff --git a/doc/man3/OSSL_CMP_MSG_http_perform.pod b/doc/man3/OSSL_CMP_MSG_http_perform.pod new file mode 100644 index 00000000..6582d441 --- /dev/null +++ b/doc/man3/OSSL_CMP_MSG_http_perform.pod @@ -0,0 +1,60 @@ +=pod + +=head1 NAME + +OSSL_CMP_MSG_http_perform +- client-side HTTP(S) transfer of a CMP request-response pair + +=head1 SYNOPSIS + + #include + + OSSL_CMP_MSG *OSSL_CMP_MSG_http_perform(OSSL_CMP_CTX *ctx, + const OSSL_CMP_MSG *req); + +=head1 DESCRIPTION + +OSSL_CMP_MSG_http_perform() sends the given PKIMessage B +to the CMP server specified in B via L +and optionally L, using +any "CMP alias" optionally specified via L. +The default port is 80 for HTTP and 443 for HTTPS; the default path is "/". +On success the function returns the server's response PKIMessage. + +The function makes use of any HTTP callback function +set via L. +It respects any timeout value set via L +with an B argument. +It also respects any HTTP(S) proxy options set via L +and L and the respective environment variables. +Proxying plain HTTP is supported directly, +while using a proxy for HTTPS connections requires a suitable callback function +such as L. + +=head1 NOTES + +CMP is defined in RFC 4210. +HTTP transfer for CMP is defined in RFC 6712. + +=head1 RETURN VALUES + +OSSL_CMP_MSG_http_perform() returns a CMP message on success, else NULL. + +=head1 SEE ALSO + +L, L. + +=head1 HISTORY + +The OpenSSL CMP support was added in OpenSSL 3.0. + +=head1 COPYRIGHT + +Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man3/OSSL_CMP_SRV_CTX_new.pod b/doc/man3/OSSL_CMP_SRV_CTX_new.pod new file mode 100644 index 00000000..2b7ce7fa --- /dev/null +++ b/doc/man3/OSSL_CMP_SRV_CTX_new.pod @@ -0,0 +1,162 @@ +=pod + +=head1 NAME + +OSSL_CMP_SRV_process_request, +OSSL_CMP_CTX_server_perform, +OSSL_CMP_SRV_CTX_new, +OSSL_CMP_SRV_CTX_free, +OSSL_CMP_SRV_cert_request_cb_t, +OSSL_CMP_SRV_rr_cb_t, +OSSL_CMP_SRV_certConf_cb_t, +OSSL_CMP_SRV_genm_cb_t, +OSSL_CMP_SRV_error_cb_t, +OSSL_CMP_SRV_pollReq_cb_t, +OSSL_CMP_SRV_CTX_init, +OSSL_CMP_SRV_CTX_get0_cmp_ctx, +OSSL_CMP_SRV_CTX_get0_custom_ctx, +OSSL_CMP_SRV_CTX_set_send_unprotected_errors, +OSSL_CMP_SRV_CTX_set_accept_unprotected, +OSSL_CMP_SRV_CTX_set_accept_raverified, +OSSL_CMP_SRV_CTX_set_grant_implicit_confirm +- generic functions to set up and control a CMP server + +=head1 SYNOPSIS + + #include + + OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req); + OSSL_CMP_MSG *OSSL_CMP_CTX_server_perform(OSSL_CMP_CTX *client_ctx, + const OSSL_CMP_MSG *req); + OSSL_CMP_SRV_CTX *OSSL_CMP_SRV_CTX_new(void); + void OSSL_CMP_SRV_CTX_free(OSSL_CMP_SRV_CTX *srv_ctx); + + typedef OSSL_CMP_PKISI *(*OSSL_CMP_SRV_cert_request_cb_t)( + OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req, + int certReqId, + const OSSL_CRMF_MSG *crm, + const X509_REQ *p10cr, + X509 **certOut, + STACK_OF(X509) **chainOut, + STACK_OF(X509) **caPubs); + typedef OSSL_CMP_PKISI *(*OSSL_CMP_SRV_rr_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req, + const X509_NAME *issuer, + const ASN1_INTEGER *serial); + typedef int (*OSSL_CMP_SRV_genm_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req, + STACK_OF(OSSL_CMP_ITAV) *in, + STACK_OF(OSSL_CMP_ITAV) **out); + typedef void (*OSSL_CMP_SRV_error_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req, + const OSSL_CMP_PKISI *statusInfo, + const ASN1_INTEGER *errorCode, + const OSSL_CMP_PKIFREETEXT *errorDetails); + typedef int (*OSSL_CMP_SRV_certConf_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req, + int certReqId, + const ASN1_OCTET_STRING *certHash, + const OSSL_CMP_PKISI *si); + typedef int (*OSSL_CMP_SRV_pollReq_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req, + int certReqId, + OSSL_CMP_MSG **certReq, + int64_t *check_after); + int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx, + OSSL_CMP_SRV_cert_request_cb_t process_cert_request, + OSSL_CMP_SRV_rr_cb_t process_rr, + OSSL_CMP_SRV_genm_cb_t process_genm, + OSSL_CMP_SRV_error_cb_t process_error, + OSSL_CMP_SRV_certConf_cb_t process_certConf, + OSSL_CMP_SRV_pollReq_cb_t process_pollReq); + + OSSL_CMP_CTX *OSSL_CMP_SRV_CTX_get0_cmp_ctx(const OSSL_CMP_SRV_CTX *srv_ctx); + void *OSSL_CMP_SRV_CTX_get0_custom_ctx(const OSSL_CMP_SRV_CTX *srv_ctx); + + int OSSL_CMP_SRV_CTX_set_send_unprotected_errors(OSSL_CMP_SRV_CTX *srv_ctx, + int val); + int OSSL_CMP_SRV_CTX_set_accept_unprotected(OSSL_CMP_SRV_CTX *srv_ctx, int val); + int OSSL_CMP_SRV_CTX_set_accept_raverified(OSSL_CMP_SRV_CTX *srv_ctx, int val); + int OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(OSSL_CMP_SRV_CTX *srv_ctx, + int val); + +=head1 DESCRIPTION + +OSSL_CMP_SRV_process_request() implements the generic aspects of a CMP server. +It does the typical generic checks on the given request message, calls +the respective callback function (if present) for more specific processing, +and then assembles a result message, which may be a CMP error message. + +OSSL_CMP_CTX_server_perform() is an interface to +B that can be used by a CMP client +in the same way as B. +The B must be set as B of B. + +OSSL_CMP_SRV_CTX_new() creates and initializes an OSSL_CMP_SRV_CTX structure +and returns a pointer to it on success, NULL on error. + +OSSL_CMP_SRV_CTX_free() deletes the given B. + +OSSL_CMP_SRV_CTX_init() sets in the given B a custom server context +pointer as well as callback functions performing the specific processing of CMP +certificate requests, revocation requests, certificate confirmation requests, +general messages, error messages, and poll requests. +All arguments except B may be NULL. +If a callback for some message type is not given this means that the respective +type of CMP message is not supported by the server. + +OSSL_CMP_SRV_CTX_get0_cmp_ctx() returns the B from the B. + +OSSL_CMP_SRV_CTX_get0_custom_ctx() returns the custom server context from +B that has been set using B. + +OSSL_CMP_SRV_CTX_set_send_unprotected_errors() enables sending error messages +and other forms of negative responses unprotected. + +OSSL_CMP_SRV_CTX_set_accept_unprotected() enables acceptance of requests +without protection of with invalid protection. + +OSSL_CMP_SRV_CTX_set_accept_raverified() enables acceptance of ir/cr/kur +messages with POPO 'RAVerified'. + +OSSL_CMP_SRV_CTX_set_grant_implicit_confirm() enables granting implicit +confirmation of newly enrolled certificates if requested. + +=head1 NOTES + +CMP is defined in RFC 4210 (and CRMF in RFC 4211). + +So far the CMP server implementation is limited to one request per CMP message +(and consequently to at most one response component per CMP message). + +=head1 RETURN VALUES + +OSSL_CMP_SRV_CTX_new() returns a B structure on success, +NULL on error. + +OSSL_CMP_SRV_CTX_free() does not return a value. + +OSSL_CMP_SRV_CTX_get0_cmp_ctx() returns a B structure on success, +NULL on error. + +OSSL_CMP_SRV_CTX_get0_custom_ctx() returns the custom server context +that has been set using B. + +All other functions return 1 on success, 0 on error. + +=head1 HISTORY + +The OpenSSL CMP support was added in OpenSSL 3.0. + +=head1 COPYRIGHT + +Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man3/OSSL_CMP_STATUSINFO_new.pod b/doc/man3/OSSL_CMP_STATUSINFO_new.pod new file mode 100644 index 00000000..520a104d --- /dev/null +++ b/doc/man3/OSSL_CMP_STATUSINFO_new.pod @@ -0,0 +1,66 @@ +=pod + +=head1 NAME + +OSSL_CMP_STATUSINFO_new, +OSSL_CMP_snprint_PKIStatusInfo, +OSSL_CMP_CTX_snprint_PKIStatus +- function(s) for managing the CMP PKIStatus + +=head1 SYNOPSIS + + #include + + OSSL_CMP_PKISI *OSSL_CMP_STATUSINFO_new(int status, int fail_info, + const char *text); + char *OSSL_CMP_snprint_PKIStatusInfo(const OSSL_CMP_PKISI *statusInfo, + char *buf, size_t bufsize); + char *OSSL_CMP_CTX_snprint_PKIStatus(const OSSL_CMP_CTX *ctx, char *buf, + size_t bufsize); + +=head1 DESCRIPTION + +This is the PKIStatus API for using CMP (Certificate Management Protocol) with +OpenSSL. + +OSSL_CMP_STATUSINFO_new() creates a new PKIStatusInfo structure +and fills in the given values. +It sets the status field to B, +copies B (unless it is NULL) to statusString, +and interprets B as bit pattern for the failInfo field. + +OSSL_CMP_snprint_PKIStatusInfo() places a human-readable string +representing the given statusInfo +in the given buffer, with the given maximal length. + +OSSL_CMP_CTX_snprint_PKIStatus() places a human-readable string +representing the PKIStatusInfo components of the CMP context B +in the given buffer, with the given maximal length. + +=head1 NOTES + +CMP is defined in RFC 4210 (and CRMF in RFC 4211). + +=head1 RETURN VALUES + +OSSL_CMP_STATUSINFO_new() +returns a pointer to the structure on success, or NULL on error. + +OSSL_CMP_snprint_PKIStatusInfo() and +OSSL_CMP_CTX_snprint_PKIStatus() +return a copy of the buffer pointer containing the string or NULL on error. + +=head1 HISTORY + +The OpenSSL CMP support was added in OpenSSL 3.0. + +=head1 COPYRIGHT + +Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man3/OSSL_CMP_exec_IR_ses.pod b/doc/man3/OSSL_CMP_exec_IR_ses.pod new file mode 100644 index 00000000..24913d5b --- /dev/null +++ b/doc/man3/OSSL_CMP_exec_IR_ses.pod @@ -0,0 +1,172 @@ +=pod + +=head1 NAME + +OSSL_CMP_exec_IR_ses, +OSSL_CMP_exec_CR_ses, +OSSL_CMP_exec_P10CR_ses, +OSSL_CMP_exec_KUR_ses, +OSSL_CMP_IR, +OSSL_CMP_CR, +OSSL_CMP_P10CR, +OSSL_CMP_KUR, +OSSL_CMP_try_certreq, +OSSL_CMP_exec_RR_ses, +OSSL_CMP_exec_GENM_ses, +OSSL_CMP_certConf_cb +- functions implementing CMP client transactions + +=head1 SYNOPSIS + + #include + + X509 *OSSL_CMP_exec_IR_ses(OSSL_CMP_CTX *ctx); + X509 *OSSL_CMP_exec_CR_ses(OSSL_CMP_CTX *ctx); + X509 *OSSL_CMP_exec_P10CR_ses(OSSL_CMP_CTX *ctx); + X509 *OSSL_CMP_exec_KUR_ses(OSSL_CMP_CTX *ctx); + #define OSSL_CMP_IR + #define OSSL_CMP_CR + #define OSSL_CMP_P10CR + #define OSSL_CMP_KUR + int OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type, int *checkAfter); + int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info, + const char **text); + X509 *OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx); + STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx); + +=head1 DESCRIPTION + +This is the OpenSSL API for doing CMP (Certificate Management Protocol) +client-server transactions, i.e., sequences of CMP requests and responses. + +All functions take a populated OSSL_CMP_CTX structure as their first argument. +Usually the server name, port, and path ("CMP alias") need to be set, as well as +credentials the client can use for authenticating itself to the client. +In order to authenticate the server the client typically needs a trust store. +For performing certificate enrollment requests the certificate template needs +to be sufficiently filled in, giving at least the subject name and key. +The functions return their respective main results directly, while there are +also accessor functions for retrieving various results and status information +from the B. See L etc. for details. + +The default conveying protocol is HTTP. +Timeout values may be given per request-response pair and per transaction. +See L for details. + +OSSL_CMP_exec_IR_ses() requests an initial certificate from the given PKI. + +OSSL_CMP_exec_CR_ses() requests an additional certificate. + +OSSL_CMP_exec_P10CR_ses() conveys a legacy PKCS#10 CSR requesting a certificate. + +OSSL_CMP_exec_KUR_ses() obtains an updated certificate. + +All these four types of certificate enrollment may be blocked by sleeping until the +CAs or an intermedate PKI component can fully process and answer the request. + +OSSL_CMP_try_certreq() is an alternative to these four functions that is +more uniform regarding the type of the certificate request to use and +more flexible regarding what to do after receiving a checkAfter value. +When called for the first time (with no certificate request in progress for +the given B) it starts a new transaction by sending a certificate request +of the given type, +which may be IR, CR, P10CR, or KUR as specified by the B parameter. +Otherwise (when according to B a 'waiting' status has been received before) +it continues polling for the pending request +unless the B argument is < 0, which aborts the request. +If the requested certificate is available the function returns 1 and the +caller can use B to retrieve the new certificate. +If no error occurred but no certificate is available yet then +OSSL_CMP_try_certreq() remembers in the CMP context that it should be retried +and returns -1 after assigning the received checkAfter value +via the output pointer argument (unless it is NULL). +The checkAfter value indicates the number of seconds the caller should let pass +before trying again. The caller is free to sleep for the given number of seconds +or for some other time and/or to do anything else before retrying by calling +OSSL_CMP_try_certreq() again with the same parameter values as before. +OSSL_CMP_try_certreq() then polls +to see whether meanwhile the requested certificate is available. +If the caller decides to abort the pending certificate request and provides +a negative value as the B argument then OSSL_CMP_try_certreq() +aborts the CMP transaction by sending an error message to the server. + +OSSL_CMP_certConf_cb() is a basic certificate confirmation callback validating +that the new certificate can be verified with the trusted/untrusted certificates +in B. +As there is no requirement in RFC 4210 that the certificate can be +validated by the client, this callback is not set by default in the context. + +OSSL_CMP_exec_RR_ses() requests the revocation of the certificate +specified in the B using L. +RFC 4210 is vague in which PKIStatus should be returned by the server. +We take "accepted" and "grantedWithMods" as clear success and handle +"revocationWarning" and "revocationNotification" just as warnings because CAs +typically return them as an indication that the certificate was already revoked. +"rejection" is a clear error. The values "waiting" and "keyUpdateWarning" +make no sense for revocation and thus are treated as an error as well. + +OSSL_CMP_exec_GENM_ses() sends a general message containing the sequence of +infoType and infoValue pairs (InfoTypeAndValue; short: B) +provided in the B using L. +It returns the list of Bs received in the GenRep. +This can be used, for instance, to poll for CRLs or CA Key Updates. +See RFC 4210 section 5.3.19 and appendix E.5 for details. + +=head1 NOTES + +CMP is defined in RFC 4210 (and CRMF in RFC 4211). + +So far the CMP client implementation is limited to one request per CMP message +(and consequently to at most one response component per CMP message). + +=head1 RETURN VALUES + +OSSL_CMP_exec_IR_ses(), OSSL_CMP_exec_CR_ses(), +OSSL_CMP_exec_P10CR_ses(), and OSSL_CMP_exec_KUR_ses() return a +pointer to the newly obtained X509 certificate on success, B on error. +This pointer will be freed implicitly by OSSL_CMP_CTX_free() or +CSSL_CMP_CTX_reinit(). + +OSSL_CMP_try_certreq() returns 1 if the requested certificate is available +via B +or on successfully aborting a pending certificate request, 0 on error, and -1 +in case a 'waiting' status has been received and checkAfter value is available. +In the latter case B yields NULL +and the output parameter B has been used to +assign the received value unless B is NULL. + +OSSL_CMP_certConf_cb() returns B if it is not equal to B<0>, +else B<0> on successful validation, +or else a bit field with the B bit set. + +OSSL_CMP_exec_RR_ses() returns the +pointer to the revoked certificate on success, B on error. +This pointer will be freed implicitly by OSSL_CMP_CTX_free(). + +OSSL_CMP_exec_GENM_ses() returns a +pointer to the received B sequence on success, B on error. +This pointer must be freed by the caller. + +=head1 EXAMPLES + +See OSSL_CMP_CTX for examples on how to prepare the context for these +functions. + +=head1 SEE ALSO + +L, L + +=head1 HISTORY + +The OpenSSL CMP support was added in OpenSSL 3.0. + +=head1 COPYRIGHT + +Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man3/OSSL_CMP_log_open.pod b/doc/man3/OSSL_CMP_log_open.pod index 9f204d6e..78d51ee7 100644 --- a/doc/man3/OSSL_CMP_log_open.pod +++ b/doc/man3/OSSL_CMP_log_open.pod @@ -13,7 +13,7 @@ OSSL_CMP_LOG_WARNING, OSSL_CMP_LOG_NOTICE, OSSL_CMP_LOG_INFO, OSSL_CMP_LOG_DEBUG, -OSSL_cmp_log_cb_t, +OSSL_CMP_log_cb_t, OSSL_CMP_print_to_bio, OSSL_CMP_print_errors_cb - functions for logging and error reporting @@ -36,12 +36,12 @@ OSSL_CMP_print_errors_cb #define OSSL_CMP_LOG_INFO 6 #define OSSL_CMP_LOG_DEBUG 7 - typedef int (*OSSL_cmp_log_cb_t)(const char *component, + typedef int (*OSSL_CMP_log_cb_t)(const char *component, const char *file, int line, OSSL_CMP_severity level, const char *msg); int OSSL_CMP_print_to_bio(BIO *bio, const char *component, const char *file, int line, OSSL_CMP_severity level, const char *msg); - void OSSL_CMP_print_errors_cb(OSSL_cmp_log_cb_t log_fn); + void OSSL_CMP_print_errors_cb(OSSL_CMP_log_cb_t log_fn); =head1 DESCRIPTION @@ -56,7 +56,7 @@ should be provided for user information, debugging, and auditing purposes. A CMP application can obtain this information by providing a callback function with the following type: - typedef int (*OSSL_cmp_log_cb_t)(const char *component, + typedef int (*OSSL_CMP_log_cb_t)(const char *component, const char *file, int line, OSSL_CMP_severity level, const char *msg); diff --git a/doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod b/doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod index 8a85f30c..eaebce88 100644 --- a/doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod +++ b/doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod @@ -21,7 +21,7 @@ OSSL_CRMF_MSG_get_certReqId X509_NAME *OSSL_CRMF_CERTTEMPLATE_get0_issuer(OSSL_CRMF_CERTTEMPLATE *tmpl); ASN1_INTEGER *OSSL_CRMF_CERTID_get0_serialNumber(const OSSL_CRMF_CERTID *cid); - X509_NAME *OSSL_CRMF_CERTID_get0_issuer(const OSSL_CRMF_CERTID *cid); + const X509_NAME *OSSL_CRMF_CERTID_get0_issuer(const OSSL_CRMF_CERTID *cid); X509 *OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(OSSL_CRMF_ENCRYPTEDVALUE *ecert, EVP_PKEY *pkey); diff --git a/doc/man3/OSSL_HTTP_transfer.pod b/doc/man3/OSSL_HTTP_transfer.pod index 68010cb6..632f48db 100644 --- a/doc/man3/OSSL_HTTP_transfer.pod +++ b/doc/man3/OSSL_HTTP_transfer.pod @@ -17,14 +17,14 @@ OSSL_HTTP_parse_url typedef BIO *(*OSSL_HTTP_bio_cb_t)(BIO *bio, void *arg, int connect, int detail); - BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *proxy_port, + BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *no_proxy, BIO *bio, BIO *rbio, OSSL_HTTP_bio_cb_t bio_update_fn, void *arg, const STACK_OF(CONF_VALUE) *headers, int maxline, unsigned long max_resp_len, int timeout, const char *expected_content_type, int expect_asn1); ASN1_VALUE *OSSL_HTTP_get_asn1(const char *url, - const char *proxy, const char *proxy_port, + const char *proxy, const char *no_proxy, BIO *bio, BIO *rbio, OSSL_HTTP_bio_cb_t bio_update_fn, void *arg, const STACK_OF(CONF_VALUE) *headers, @@ -33,7 +33,7 @@ OSSL_HTTP_parse_url const ASN1_ITEM *it); ASN1_VALUE *OSSL_HTTP_post_asn1(const char *server, const char *port, const char *path, int use_ssl, - const char *proxy, const char *proxy_port, + const char *proxy, const char *no_proxy, BIO *bio, BIO *rbio, OSSL_HTTP_bio_cb_t bio_update_fn, void *arg, const STACK_OF(CONF_VALUE) *headers, @@ -43,7 +43,7 @@ OSSL_HTTP_parse_url int timeout, const char *expected_ct, const ASN1_ITEM *rsp_it); BIO *OSSL_HTTP_transfer(const char *server, const char *port, const char *path, - int use_ssl, const char *proxy, const char *proxy_port, + int use_ssl, const char *proxy, const char *no_proxy, BIO *bio, BIO *rbio, OSSL_HTTP_bio_cb_t bio_update_fn, void *arg, const STACK_OF(CONF_VALUE) *headers, @@ -69,17 +69,18 @@ and returns it on success as a pointer to I. OSSL_HTTP_post_asn1() uses the HTTP POST method to send a request B with the ASN.1 structure defined in B and the given B to -the given B and optional B and B, which defaults to "/". +the given B and optional B and B. If B is nonzero a TLS connection is requested and the B parameter, described below, must be provided. The optional list B may contain additional custom HTTP header lines. The expected structure of the response is specified by B. On success it returns the response as a pointer to B. -OSSL_HTTP_transfer() exchanges an HTTP request and response with -the given B and optional B and B, which defaults to "/". -If B is nonzero a TLS connection is requested and the B -parameter, described below, must be provided. +OSSL_HTTP_transfer() exchanges any form of HTTP request and response. +It implements the core of the functions described above. +If B parameter is NULL it defaults to "/". +If B is nonzero a TLS connection is requested +and the B parameter, described below, must be provided. If B is NULL it uses the HTTP GET method, else it uses HTTP POST to send a request with the contents of the memory BIO and optional B. The optional list B may contain additional custom HTTP header lines. @@ -91,22 +92,36 @@ L. The above functions have the following parameters in common. -If the B parameter is not NULL the HTTP client functions connect -via the given proxy and the optionally given B. -Proxying plain HTTP is supported directly, -while using a proxy for HTTPS connections requires a suitable callback function -such as OSSL_HTTP_proxy_connect(), described below. - -Typically the B and B parameters are NULL and the client creates a -network BIO internally for connecting to the given server and port (optionally -via a proxy and its port), and uses it for exchanging the request and response. -If B is given and B is NULL then the client uses this BIO instead. +Typically the OpenSSL build supports sockets +and the B and B parameters are both NULL. +In this case the client creates a network BIO internally +for connecting to the given B +at the specified B (if any, defaulting to 80 for HTTP or 443 for HTTPS), +optionally via a B (respecting B) as described below. +Then the client uses this internal BIO for exchanging the request and response. +If B is given and B is NULL then the client uses this B instead. If both B and B are given (which may be memory BIOs for instance) then no explicit connection is attempted, B is used for writing the request, and B for reading the response. As soon as the client has flushed B the server must be ready to provide a response or indicate a waiting condition via B. +The optional B parameter can be used to set the address of the an +HTTP(S) proxy to use (unless overridden by "no_proxy" settings). +If TLS is not used this defaults to the environment variable B +if set, else B. +If B != 0 it defaults to B if set, else B. +An empty proxy string specifies not to use a proxy. +Else the format is I<[http[s]://]address[:port][/path]>, +where any path given is ignored. +The default proxy port number is 80, or 443 in case "https:" is given. +The HTTP client functions connect via the given proxy unless the B +is found in the optional list B of proxy hostnames (if not NULL; +default is the environment variable B if set, else B). +Proxying plain HTTP is supported directly, +while using a proxy for HTTPS connections requires a suitable callback function +such as B, described below. + The B parameter specifies the response header maximum line length, where 0 indicates the default value, which currently is 4k. The B parameter specifies the maximum response length, @@ -115,7 +130,7 @@ where 0 indicates the default value, which currently is 100k. An ASN.1-encoded response is expected by OSSL_HTTP_get_asn1() and OSSL_HTTP_post_asn1(), while for OSSL_HTTP_get() or OSSL_HTTP_transfer() this is only the case if the B parameter is nonzero. -If the response header contains one or more Content-Length header lines and/or +If the response header contains one or more "Content-Length" header lines and/or an ASN.1-encoded response is expected, which should include a total length, the length indications received are checked for consistency and for not exceeding the maximum response length. @@ -164,11 +179,12 @@ Here is a simple example that supports TLS connections (but not via a proxy): After disconnect the modified BIO will be deallocated using BIO_free_all(). OSSL_HTTP_proxy_connect() may be used by an above BIO connect callback function -to set up an SSL/TLS connection via an HTTP proxy. +to set up an SSL/TLS connection via an HTTPS proxy. It promotes the given BIO B representing a connection pre-established with a TLS proxy using the HTTP CONNECT method, optionally using proxy client credentials B and B, to connect with TLS protection ultimately to B and B. +If the B argument is NULL or the empty string it defaults to "443". The B parameter is used as described above. Since this function is typically called by appplications such as L it uses the B and B parameters (unless @@ -184,6 +200,13 @@ them copies of the respective string components. The strings returned this way must be deallocated by the caller using L unless they are NULL, which is their default value on error. +=head1 NOTES + +The names of the environment variables used by this implementation: +B, B, B, B, B, and +B, have been chosen for maximal compatibility with +other HTTP client implementations such as wget, curl, and git. + =head1 RETURN VALUES OSSL_HTTP_get(), OSSL_HTTP_get_asn1(), OSSL_HTTP_post_asn1(), and diff --git a/doc/man3/OSSL_PARAM.pod b/doc/man3/OSSL_PARAM.pod index cd7d4100..a2392a96 100644 --- a/doc/man3/OSSL_PARAM.pod +++ b/doc/man3/OSSL_PARAM.pod @@ -159,6 +159,9 @@ The parameter data is a pointer to a printable string. The difference between this and B is that I doesn't point directly at the data, but to a pointer that points to the data. +If there is any uncertainty about which to use, B is +almost certainly the correct choice. + This is used to indicate that constant data is or will be passed, and there is therefore no need to copy the data that is passed, just the pointer to it. @@ -182,6 +185,9 @@ The difference between this and B is that I doesn't point directly at the data, but to a pointer that points to the data. +If there is any uncertainty about which to use, B is +almost certainly the correct choice. + This is used to indicate that constant data is or will be passed, and there is therefore no need to copy the data that is passed, just the pointer to it. diff --git a/doc/internal/man3/ossl_param_bld_init.pod b/doc/man3/OSSL_PARAM_BLD.pod similarity index 52% rename from doc/internal/man3/ossl_param_bld_init.pod rename to doc/man3/OSSL_PARAM_BLD.pod index 8ae0dccb..ed82e320 100644 --- a/doc/internal/man3/ossl_param_bld_init.pod +++ b/doc/man3/OSSL_PARAM_BLD.pod @@ -2,44 +2,45 @@ =head1 NAME -ossl_param_bld_init, ossl_param_bld_to_param, -ossl_param_bld_free, ossl_param_bld_push_int, ossl_param_bld_push_uint, -ossl_param_bld_push_long, ossl_param_bld_push_ulong, -ossl_param_bld_push_int32, ossl_param_bld_push_uint32, -ossl_param_bld_push_int64, ossl_param_bld_push_uint64, -ossl_param_bld_push_size_t, ossl_param_bld_push_double, -ossl_param_bld_push_BN, ossl_param_bld_push_BN_pad, -ossl_param_bld_push_utf8_string, ossl_param_bld_push_utf8_ptr, -ossl_param_bld_push_octet_string, ossl_param_bld_push_octet_ptr +OSSL_PARAM_BLD, OSSL_PARAM_BLD_new, OSSL_PARAM_BLD_to_param, +OSSL_PARAM_BLD_free_params, OSSL_PARAM_BLD_free, OSSL_PARAM_BLD_push_int, +OSSL_PARAM_BLD_push_uint, OSSL_PARAM_BLD_push_long, +OSSL_PARAM_BLD_push_ulong, OSSL_PARAM_BLD_push_int32, +OSSL_PARAM_BLD_push_uint32, OSSL_PARAM_BLD_push_int64, +OSSL_PARAM_BLD_push_uint64, OSSL_PARAM_BLD_push_size_t, +OSSL_PARAM_BLD_push_double, OSSL_PARAM_BLD_push_BN, +OSSL_PARAM_BLD_push_BN_pad, OSSL_PARAM_BLD_push_utf8_string, +OSSL_PARAM_BLD_push_utf8_ptr, OSSL_PARAM_BLD_push_octet_string, +OSSL_PARAM_BLD_push_octet_ptr - functions to assist in the creation of OSSL_PARAM arrays =head1 SYNOPSIS =for openssl generic - #include "internal/params_build.h" + #include "openssl/param_build.h" - #define OSSL_PARAM_BLD_MAX 10 - typedef struct { ... } OSSL_PARAM_BLD; + typedef struct OSSL_PARAM_BLD; - void ossl_param_bld_init(OSSL_PARAM_BLD *bld); - OSSL_PARAM *ossl_param_bld_to_param(OSSL_PARAM_BLD *bld); - void ossl_param_bld_free(OSSL_PARAM *params); + OSSL_PARAM_BLD *OSSL_PARAM_BLD_new(void); + OSSL_PARAM *OSSL_PARAM_BLD_to_param(OSSL_PARAM_BLD *bld); + void OSSL_PARAM_BLD_free_params(OSSL_PARAM *params); + void OSSL_PARAM_BLD_free(OSSL_PARAM_BLD *bld); - int ossl_param_bld_push_TYPE(OSSL_PARAM_BLD *bld, const char *key, TYPE val); + int OSSL_PARAM_BLD_push_TYPE(OSSL_PARAM_BLD *bld, const char *key, TYPE val); - int ossl_param_bld_push_BN(OSSL_PARAM_BLD *bld, const char *key, + int OSSL_PARAM_BLD_push_BN(OSSL_PARAM_BLD *bld, const char *key, const BIGNUM *bn); - int ossl_param_bld_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key, + int OSSL_PARAM_BLD_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key, const BIGNUM *bn, size_t sz); - int ossl_param_bld_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key, + int OSSL_PARAM_BLD_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key, const char *buf, size_t bsize); - int ossl_param_bld_push_utf8_ptr(OSSL_PARAM_BLD *bld, const char *key, + int OSSL_PARAM_BLD_push_utf8_ptr(OSSL_PARAM_BLD *bld, const char *key, char *buf, size_t bsize); - int ossl_param_bld_push_octet_string(OSSL_PARAM_BLD *bld, const char *key, + int OSSL_PARAM_BLD_push_octet_string(OSSL_PARAM_BLD *bld, const char *key, const void *buf, size_t bsize); - int ossl_param_bld_push_octet_ptr(OSSL_PARAM_BLD *bld, const char *key, + int OSSL_PARAM_BLD_push_octet_ptr(OSSL_PARAM_BLD *bld, const char *key, void *buf, size_t bsize); @@ -48,17 +49,20 @@ ossl_param_bld_push_octet_string, ossl_param_bld_push_octet_ptr A collection of utility functions that simplify the creation of OSSL_PARAM arrays. The B> names are as per L. -ossl_param_bld_init() initialises the OSSL_PARAM_BLD structure so that values -can be added. +OSSL_PARAM_BLD_new() allocates and initialises a new OSSL_PARAM_BLD structure +so that values can be added. Any existing values are cleared. -ossl_param_bld_to_param() converts a built up OSSL_PARAM_BLD structure +OSSL_PARAM_BLD_free() deallocates the memory allocates by OSSL_PARAM_BLD_new(). + +OSSL_PARAM_BLD_to_param() converts a built up OSSL_PARAM_BLD structure I into an allocated OSSL_PARAM array. The OSSL_PARAM array and all associated storage must be freed by calling -ossl_param_bld_free() with the functions return value. +OSSL_PARAM_BLD_free_params() with the functions return value. +OSSL_PARAM_BLD_free() can safely be called any time after this function is. -ossl_param_bld_free() deallocates the memory allocated by -ossl_param_bld_to_param(). +OSSL_PARAM_BLD_free_params() deallocates the memory allocated by +OSSL_PARAM_BLD_to_param(). =begin comment @@ -68,65 +72,59 @@ the processor along =end comment -B>() are a series of functions which will create +B>() are a series of functions which will create OSSL_PARAM objects of the specified size and correct type for the I argument. I is stored by value and an expression or auto variable can be used. -ossl_param_bld_push_BN() is a function that will create an OSSL_PARAM object +OSSL_PARAM_BLD_push_BN() is a function that will create an OSSL_PARAM object that holds the specified BIGNUM I. If I is marked as being securely allocated, its OSSL_PARAM representation will also be securely allocated. The I argument is stored by reference and the underlying BIGNUM object -must exist until after ossl_param_bld_to_param() has been called. +must exist until after OSSL_PARAM_BLD_to_param() has been called. -ossl_param_bld_push_BN_pad() is a function that will create an OSSL_PARAM object +OSSL_PARAM_BLD_push_BN_pad() is a function that will create an OSSL_PARAM object that holds the specified BIGNUM I. The object will be padded to occupy exactly I bytes, if insufficient space is specified an error results. If I is marked as being securely allocated, its OSSL_PARAM representation will also be securely allocated. The I argument is stored by reference and the underlying BIGNUM object -must exist until after ossl_param_bld_to_param() has been called. +must exist until after OSSL_PARAM_BLD_to_param() has been called. -ossl_param_bld_push_utf8_string() is a function that will create an OSSL_PARAM +OSSL_PARAM_BLD_push_utf8_string() is a function that will create an OSSL_PARAM object that references the UTF8 string specified by I. If the length of the string, I, is zero then it will be calculated. The string that I points to is stored by reference and must remain in -scope until after ossl_param_bld_to_param() has been called. +scope until after OSSL_PARAM_BLD_to_param() has been called. -ossl_param_bld_push_octet_string() is a function that will create an OSSL_PARAM +OSSL_PARAM_BLD_push_octet_string() is a function that will create an OSSL_PARAM object that references the octet string specified by I and . The memory that I points to is stored by reference and must remain in -scope until after ossl_param_bld_to_param() has been called. +scope until after OSSL_PARAM_BLD_to_param() has been called. -ossl_param_bld_push_utf8_ptr() is a function that will create an OSSL_PARAM +OSSL_PARAM_BLD_push_utf8_ptr() is a function that will create an OSSL_PARAM object that references the UTF8 string specified by I. If the length of the string, I, is zero then it will be calculated. The string I points to is stored by reference and must remain in scope until the OSSL_PARAM array is freed. -ossl_param_bld_push_octet_ptr() is a function that will create an OSSL_PARAM +OSSL_PARAM_BLD_push_octet_ptr() is a function that will create an OSSL_PARAM object that references the octet string specified by I. The memory I points to is stored by reference and must remain in scope until the OSSL_PARAM array is freed. =head1 RETURN VALUES -ossl_param_bld_to_param() returns the allocated OSSL_PARAM array, or NULL +OSSL_PARAM_BLD_new() returns the allocated OSSL_PARAM_BLD structure, or NULL on error. -All of the ossl_param_bld_push_TYPE functions return 1 on success and 0 +OSSL_PARAM_BLD_to_param() returns the allocated OSSL_PARAM array, or NULL on error. -=head1 NOTES - -The constant B specifies the maximum number of parameters -that can be added. -Exceeding this will result in the push functions returning errors. - -The structure B should be considered opaque and subject to -change between versions. +All of the OSSL_PARAM_BLD_push_TYPE functions return 1 on success and 0 +on error. =head1 EXAMPLES @@ -143,37 +141,39 @@ For both, the predefined key variables are: This example shows how to create an OSSL_PARAM array that contains an RSA private key. - OSSL_PARAM_BLD bld; + OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new(); OSSL_PARAM *params; - ossl_param_bld_init(&bld, &secure); - if (!ossl_param_bld_push_BN(&bld, "p", p) - || !ossl_param_bld_push_BN(&bld, "q", q) - || !ossl_param_bld_push_uint(&bld, "e", e) - || !ossl_param_bld_push_BN(&bld, "n", n) - || !ossl_param_bld_push_BN(&bld, "d", d) - || (params = ossl_param_bld_to_param(&bld)) == NULL) + if (bld == NULL + || !OSSL_PARAM_BLD_push_BN(&bld, "p", p) + || !OSSL_PARAM_BLD_push_BN(&bld, "q", q) + || !OSSL_PARAM_BLD_push_uint(&bld, "e", e) + || !OSSL_PARAM_BLD_push_BN(&bld, "n", n) + || !OSSL_PARAM_BLD_push_BN(&bld, "d", d) + || (params = OSSL_PARAM_BLD_to_param(&bld)) == NULL) goto err; + OSSL_PARAM_BLD_free(bld); /* Use params */ ... - ossl_param_bld_free(params); + OSSL_PARAM_BLD_free_params(params); =head2 Example 2 This example shows how to create an OSSL_PARAM array that contains an RSA public key. - OSSL_PARAM_BLD bld; + OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new(); OSSL_PARAM *params; - ossl_param_bld_init(&bld, &secure); - if (!ossl_param_bld_push_BN(&bld, "n", n) - || !ossl_param_bld_push_BN(&bld, "d", d) - || (params = ossl_param_bld_to_param(&bld)) == NULL) + if (nld == NULL + || !OSSL_PARAM_BLD_push_BN(bld, "n", n) + || !OSSL_PARAM_BLD_push_BN(bld, "d", d) + || (params = OSSL_PARAM_BLD_to_param(bld)) == NULL) goto err; + OSSL_PARAM_BLD_free(bld); /* Use params */ ... - ossl_param_bld_free(params); + OSSL_PARAM_BLD_free_params(params); =head1 SEE ALSO @@ -185,7 +185,7 @@ The functions described here were all added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OSSL_PARAM_allocate_from_text.pod b/doc/man3/OSSL_PARAM_allocate_from_text.pod index 48dbfc75..5b92fdd2 100644 --- a/doc/man3/OSSL_PARAM_allocate_from_text.pod +++ b/doc/man3/OSSL_PARAM_allocate_from_text.pod @@ -26,34 +26,74 @@ OpenSSL 3.0 introduces a new mechanism to do the same thing with an array of parameters that contain name, value, value type and value size (see L for more information). -OSSL_PARAM_allocate_from_text() takes a control I, I and -value size I, and given a parameter descriptor array -I, it converts the value to something suitable for -L and stores that in the buffer I, and modifies -the parameter I to match. -I, if not NULL, will be assigned the number of bytes used in -I. -If I is NULL, only I will be modified, everything else is -left untouched, allowing a caller to find out how large the buffer -should be. -I needs to be correctly aligned for the type of the B -I. -If is not NULL, it is set to 1 if the parameter can be located and -to 0 otherwise. +OSSL_PARAM_allocate_from_text() uses I to look up an item in +I. If an item was found, it converts I to something +suitable for that item's I, and stores the result in +I<< to->data >> as well as its size in I<< to->data_size >>. +I<< to->key >> and I<< to->data_type >> are assigned the corresponding +values from the item that was found, and I<< to->return_size >> is set +to zero. -The caller must remember to free the data of I when it's not -useful any more. +I<< to->data >> is always allocated using L and +needs to be freed by the caller when it's not useful any more, using +L. -For parameters having the type B, -B, or B, both -functions will interpret the I differently if the key starts -with "hex". -In that case, the value is decoded first, and the result will be used -as parameter value. +If I is not NULL, I<*found> is set to 1 if I could be +located in I, and to 0 otherwise. + +=head2 The use of I and I in detail + +OSSL_PARAM_allocate_from_text() takes note if I starts with +"hex", and will only use the rest of I to look up an item in +I in that case. As an example, if I is "hexid", "id" +will be looked up in I. + +When an item in I has been found, I is converted +depending on that item's I, as follows: + +=over 4 + +=item B and B + +If I started with "hex", I is assumed to contain +I hexadecimal characters, which are decoded, and the +resulting bytes become the number stored in the I<< to->data >> +storage. + +If I didn't start with "hex", I is assumed to contain +I decimal characters, which are decoded, and the resulting +bytes become the number stored in the I<< to->data >> storage. + +If I contains characters that couldn't be decoded as +hexadecimal or decimal characters, OSSL_PARAM_allocate_from_text() +considers that an error. + +=item B + +If I started with "hex", OSSL_PARAM_allocate_from_text() +considers that an error. + +Otherwise, I is considered a C string and is copied with no +further checks to the I<< to->data >> storage. + +=item B + +If I started with "hex", I is assumed to contain +I hexadecimal characters, which are decoded, and the +resulting bytes are stored in the I<< to->data >> storage. +If I contains characters that couldn't be decoded as +hexadecimal or decimal characters, OSSL_PARAM_allocate_from_text() +considers that an error. + +If I didn't start with "hex", I bytes from I are +copied to the I<< to->data >> storage. + +=back =head1 RETURN VALUES -OSSL_PARAM_allocate_from_text() returns 1 on success, and 0 on error. +OSSL_PARAM_allocate_from_text() returns 1 if I was found in +I and there was no other failure, otherwise 0. =head1 NOTES @@ -65,7 +105,7 @@ The following B attributes are used: =item I -=item I +=item I =item I diff --git a/doc/man3/OSSL_SELF_TEST_new.pod b/doc/man3/OSSL_SELF_TEST_new.pod index 32155e1c..b2c4f5cc 100644 --- a/doc/man3/OSSL_SELF_TEST_new.pod +++ b/doc/man3/OSSL_SELF_TEST_new.pod @@ -133,7 +133,7 @@ A single self test could be set up in the following way: || !EVP_DigestUpdate(ctx, pt, pt_len) || !EVP_DigestFinal(ctx, out, &out_len)) goto err; - + /* Optional corruption - If the application callback returns 0 */ OSSL_SELF_TEST_oncorrupt_byte(st, out); diff --git a/doc/man3/RAND_set_rand_method.pod b/doc/man3/RAND_set_rand_method.pod index 0966b091..d9e21325 100644 --- a/doc/man3/RAND_set_rand_method.pod +++ b/doc/man3/RAND_set_rand_method.pod @@ -33,10 +33,10 @@ RAND_get_rand_method() returns a pointer to the current B. =head1 THE RAND_METHOD STRUCTURE typedef struct rand_meth_st { - void (*seed)(const void *buf, int num); + int (*seed)(const void *buf, int num); int (*bytes)(unsigned char *buf, int num); void (*cleanup)(void); - void (*add)(const void *buf, int num, int randomness); + int (*add)(const void *buf, int num, double entropy); int (*pseudorand)(unsigned char *buf, int num); int (*status)(void); } RAND_METHOD; diff --git a/doc/man3/SRP_Calc_B.pod b/doc/man3/SRP_Calc_B.pod new file mode 100644 index 00000000..1353311f --- /dev/null +++ b/doc/man3/SRP_Calc_B.pod @@ -0,0 +1,88 @@ +=pod + +=head1 NAME + +SRP_Calc_server_key, +SRP_Calc_A, +SRP_Calc_B_ex, +SRP_Calc_B, +SRP_Calc_u_ex, +SRP_Calc_u, +SRP_Calc_x_ex, +SRP_Calc_x, +SRP_Calc_client_key_ex, +SRP_Calc_client_key +- SRP authentication primitives + +=head1 SYNOPSIS + + #include + + /* server side .... */ + BIGNUM *SRP_Calc_server_key(const BIGNUM *A, const BIGNUM *v, const BIGNUM *u, + const BIGNUM *b, const BIGNUM *N); + BIGNUM *SRP_Calc_B_ex(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g, + const BIGNUM *v, OPENSSL_CTX *libctx, const char *propq); + BIGNUM *SRP_Calc_B(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g, + const BIGNUM *v); + + BIGNUM *SRP_Calc_u_ex(const BIGNUM *A, const BIGNUM *B, const BIGNUM *N, + OPENSSL_CTX *libctx, const char *propq); + BIGNUM *SRP_Calc_u(const BIGNUM *A, const BIGNUM *B, const BIGNUM *N); + + /* client side .... */ + BIGNUM *SRP_Calc_client_key_ex(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g, + const BIGNUM *x, const BIGNUM *a, const BIGNUM *u, + OPENSSL_CTX *libctx, const char *propq); + BIGNUM *SRP_Calc_client_key(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g, + const BIGNUM *x, const BIGNUM *a, const BIGNUM *u); + BIGNUM *SRP_Calc_x_ex(const BIGNUM *s, const char *user, const char *pass, + OPENSSL_CTX *libctx, const char *propq); + BIGNUM *SRP_Calc_x(const BIGNUM *s, const char *user, const char *pass); + BIGNUM *SRP_Calc_A(const BIGNUM *a, const BIGNUM *N, const BIGNUM *g); + +=head1 DESCRIPTION + +The SRP functions described on this page are used to calculate various +parameters and keys used by SRP as defined in RFC2945. The server key and I +and I parameters are used on the server side and are calculated via +SRP_Calc_server_key(), SRP_Calc_B_ex(), SRP_Calc_B(), SRP_Calc_u_ex() and +SRP_Calc_u(). The client key and B and B parameters are used on the +client side and are calculated via the functions SRP_Calc_client_key_ex(), +SRP_Calc_client_key(), SRP_Calc_x_ex(), SRP_Calc_x() and SRP_Calc_A(). See +RFC2945 for a detailed description of their usage and the meaning of the various +BIGNUM parameters to these functions. + +Most of these functions come in two forms. Those that take a I and +I parameter, and those that don't. Any cryptogrpahic functions that +are fetched and used during the calculation use the provided I and +I. See L for more details. The variants +that do not take a I and I parameter use the default library +context and property query string. The SRP_Calc_server_key() and SRP_Calc_A() +functions do not have a form that takes I or I parameters because +they do not need to fetch any cryptographic algorithms. + +=head1 RETURN VALUES + +All these functions return the calculated key or parameter, or NULL on error. + +=head1 SEE ALSO + +L, +L, +L + +=head1 HISTORY + +These functions were added in OpenSSL 1.0.1. + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man3/SRP_create_verifier.pod b/doc/man3/SRP_create_verifier.pod index fb77bba7..98f31d14 100644 --- a/doc/man3/SRP_create_verifier.pod +++ b/doc/man3/SRP_create_verifier.pod @@ -2,7 +2,9 @@ =head1 NAME +SRP_create_verifier_ex, SRP_create_verifier, +SRP_create_verifier_BN_ex, SRP_create_verifier_BN, SRP_check_known_gN_param, SRP_get_default_gN @@ -12,8 +14,15 @@ SRP_get_default_gN #include + int SRP_create_verifier_BN_ex(const char *user, const char *pass, BIGNUM **salt, + BIGNUM **verifier, const BIGNUM *N, + const BIGNUM *g, OPENSSL_CTX *libctx, + const char *propq); char *SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, BIGNUM **verifier, const BIGNUM *N, const BIGNUM *g); + char *SRP_create_verifier_ex(const char *user, const char *pass, char **salt, + char **verifier, const char *N, const char *g, + OPENSSL_CTX *libctx, const char *propq); char *SRP_create_verifier(const char *user, const char *pass, char **salt, char **verifier, const char *N, const char *g); @@ -22,46 +31,55 @@ SRP_get_default_gN =head1 DESCRIPTION -The SRP_create_verifier_BN() function creates an SRP password verifier from -the supplied parameters as defined in section 2.4 of RFC 5054. -On successful exit B<*verifier> will point to a newly allocated BIGNUM containing -the verifier and (if a salt was not provided) B<*salt> will be populated with a -newly allocated BIGNUM containing a random salt. If B<*salt> is not NULL then +The SRP_create_verifier_BN_ex() function creates an SRP password verifier from +the supplied parameters as defined in section 2.4 of RFC 5054 using the library +context I and property query string I. Any cryptographic +algorithms that need to be fetched will use the I and I. See +L. + +SRP_create_verifier_BN() is the same as SRP_create_verifier_BN_ex() except the +default library context and property query string is used. + +On successful exit I<*verifier> will point to a newly allocated BIGNUM containing +the verifier and (if a salt was not provided) I<*salt> will be populated with a +newly allocated BIGNUM containing a random salt. If I<*salt> is not NULL then the provided salt is used instead. -The caller is responsible for freeing the allocated B<*salt> and B<*verifier> +The caller is responsible for freeing the allocated I<*salt> and I<*verifier> BIGNUMS (use L). The SRP_create_verifier() function is similar to SRP_create_verifier_BN() but all numeric parameters are in a non-standard base64 encoding originally designed for compatibility with libsrp. This is mainly present for historical compatibility and its use is discouraged. -It is possible to pass NULL as B and an SRP group id as B instead to +It is possible to pass NULL as I and an SRP group id as I instead to load the appropriate gN values (see SRP_get_default_gN()). -If both B and B are NULL the 8192-bit SRP group parameters are used. -The caller is responsible for freeing the allocated B<*salt> and B<*verifier> +If both I and I are NULL the 8192-bit SRP group parameters are used. +The caller is responsible for freeing the allocated I<*salt> and I<*verifier> (use L). -The SRP_check_known_gN_param() function checks that B and B are valid +The SRP_check_known_gN_param() function checks that I and I are valid SRP group parameters from RFC 5054 appendix A. -The SRP_get_default_gN() function returns the gN parameters for the RFC 5054 B +The SRP_get_default_gN() function returns the gN parameters for the RFC 5054 I SRP group size. The known ids are "1024", "1536", "2048", "3072", "4096", "6144" and "8192". =head1 RETURN VALUES -SRP_create_verifier_BN() returns 1 on success and 0 on failure. +SRP_create_verifier_BN_ex() and SRP_create_verifier_BN() return 1 on success and +0 on failure. -SRP_create_verifier() returns NULL on failure and a non-NULL value on success: -"*" if B is not NULL, the selected group id otherwise. This value should +SRP_create_verifier_ex() and SRP_create_verifier() return NULL on failure and a +non-NULL value on success: +"*" if I is not NULL, the selected group id otherwise. This value should not be freed. SRP_check_known_gN_param() returns the text representation of the group id (ie. the prime bit size) or NULL if the arguments are not valid SRP group parameters. This value should not be freed. -SRP_get_default_gN() returns NULL if B is not a valid group size, -or the 8192-bit group parameters if B is NULL. +SRP_get_default_gN() returns NULL if I is not a valid group size, +or the 8192-bit group parameters if I is NULL. =head1 EXAMPLES @@ -79,7 +97,8 @@ omitted for clarity): SRP_gN *gN = SRP_get_default_gN("8192"); BIGNUM *salt = NULL, *verifier = NULL; - SRP_create_verifier_BN(username, password, &salt, &verifier, gN->N, gN->g); + SRP_create_verifier_BN_ex(username, password, &salt, &verifier, gN->N, gN->g, + NULL, NULL); SRP_user_pwd *pwd = SRP_user_pwd_new(); SRP_user_pwd_set1_ids(pwd, username, NULL); diff --git a/doc/man3/SSL_CTX_sess_set_get_cb.pod b/doc/man3/SSL_CTX_sess_set_get_cb.pod index 98fbfb57..3804e508 100644 --- a/doc/man3/SSL_CTX_sess_set_get_cb.pod +++ b/doc/man3/SSL_CTX_sess_set_get_cb.pod @@ -28,19 +28,19 @@ SSL_CTX_sess_set_new_cb, SSL_CTX_sess_set_remove_cb, SSL_CTX_sess_set_get_cb, SS =head1 DESCRIPTION -SSL_CTX_sess_set_new_cb() sets the callback function, which is automatically +SSL_CTX_sess_set_new_cb() sets the callback function that is called whenever a new session was negotiated. -SSL_CTX_sess_set_remove_cb() sets the callback function, which is -automatically called whenever a session is removed by the SSL engine, -because it is considered faulty or the session has become obsolete because -of exceeding the timeout value. +SSL_CTX_sess_set_remove_cb() sets the callback function that is +called whenever a session is removed by the SSL engine. For example, +this can occur because a session is considered faulty or has become obsolete +because of exceeding the timeout value. -SSL_CTX_sess_set_get_cb() sets the callback function which is called, -whenever a SSL/TLS client proposed to resume a session but the session +SSL_CTX_sess_set_get_cb() sets the callback function that is called +whenever a TLS client proposed to resume a session but the session could not be found in the internal session cache (see L). -(SSL/TLS server only.) +(TLS server only.) SSL_CTX_sess_get_new_cb(), SSL_CTX_sess_get_remove_cb(), and SSL_CTX_sess_get_get_cb() retrieve the function pointers set by the @@ -56,7 +56,8 @@ L interface. The new_session_cb() is called whenever a new session has been negotiated and session caching is enabled (see L). The -new_session_cb() is passed the B connection and the ssl session B. +new_session_cb() is passed the B connection and the nascent +ssl session B. Since sessions are reference-counted objects, the reference count on the session is incremented before the callback, on behalf of the application. If the callback returns B<0>, the session will be immediately removed from the @@ -78,21 +79,23 @@ In TLSv1.3 it is recommended that each SSL_SESSION object is only used for resumption once. One way of enforcing that is for applications to call L after a session has been used. -The remove_session_cb() is called, whenever the SSL engine removes a session -from the internal cache. This happens when the session is removed because +The remove_session_cb() is called whenever the SSL engine removes a session +from the internal cache. This can happen when the session is removed because it is expired or when a connection was not shutdown cleanly. It also happens for all sessions in the internal session cache when L is called. The remove_session_cb() is passed the B and the ssl session B. It does not provide any feedback. -The get_session_cb() is only called on SSL/TLS servers with the session id -proposed by the client. The get_session_cb() is always called, also when +The get_session_cb() is only called on SSL/TLS servers, and is given +the session id +proposed by the client. The get_session_cb() is always called, even when session caching was disabled. The get_session_cb() is passed the -B connection, the session id of length B at the memory location -B. With the parameter B the callback can require the -SSL engine to increment the reference count of the SSL_SESSION object, -Normally the reference count is not incremented and therefore the -session must not be explicitly freed with +B connection and the session id of length B at the memory location +B. By setting the parameter B to B<1>, the callback can require the +SSL engine to increment the reference count of the SSL_SESSION object; +setting B to B<0> causes the reference count to remain unchanged. +If the get_session_cb() does not write to B, the reference count +is incremented and the session must be explicitly freed with L. =head1 RETURN VALUES diff --git a/doc/man3/SSL_CTX_set_tmp_dh_callback.pod b/doc/man3/SSL_CTX_set_tmp_dh_callback.pod index 0e9108d0..9b577bdd 100644 --- a/doc/man3/SSL_CTX_set_tmp_dh_callback.pod +++ b/doc/man3/SSL_CTX_set_tmp_dh_callback.pod @@ -62,15 +62,6 @@ generate their own DH parameters during the installation process using the openssl L application. This application guarantees that "strong" primes are used. -Files dh2048.pem, and dh4096.pem in the 'apps' directory of the current -version of the OpenSSL distribution contain the 'SKIP' DH parameters, -which use safe primes and were generated verifiably pseudo-randomly. -These files can be converted into C code using the B<-C> option of the -L application. Generation of custom DH -parameters during installation should still be preferred to stop an -attacker from specializing on a commonly used group. File dh1024.pem -contains old parameters that must not be used by applications. - An application may either directly specify the DH parameters or can supply the DH parameters via a callback function. diff --git a/doc/man3/SSL_accept.pod b/doc/man3/SSL_accept.pod index a8d84ac8..eda0a35b 100644 --- a/doc/man3/SSL_accept.pod +++ b/doc/man3/SSL_accept.pod @@ -56,7 +56,7 @@ established. The TLS/SSL handshake was not successful because a fatal error occurred either at the protocol level or a connection failure occurred. The shutdown was -not clean. It can also occur of action is need to continue the operation +not clean. It can also occur if action is needed to continue the operation for non-blocking BIOs. Call SSL_get_error() with the return value B to find out the reason. @@ -72,7 +72,7 @@ L =head1 COPYRIGHT -Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_connect.pod b/doc/man3/SSL_connect.pod index 5777f4ff..b74aa1d2 100644 --- a/doc/man3/SSL_connect.pod +++ b/doc/man3/SSL_connect.pod @@ -71,7 +71,7 @@ established. The TLS/SSL handshake was not successful, because a fatal error occurred either at the protocol level or a connection failure occurred. The shutdown was -not clean. It can also occur of action is need to continue the operation +not clean. It can also occur if action is needed to continue the operation for non-blocking BIOs. Call SSL_get_error() with the return value B to find out the reason. @@ -87,7 +87,7 @@ L =head1 COPYRIGHT -Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_do_handshake.pod b/doc/man3/SSL_do_handshake.pod index b110cb55..55a11ccd 100644 --- a/doc/man3/SSL_do_handshake.pod +++ b/doc/man3/SSL_do_handshake.pod @@ -57,7 +57,7 @@ established. The TLS/SSL handshake was not successful because a fatal error occurred either at the protocol level or a connection failure occurred. The shutdown was -not clean. It can also occur of action is need to continue the operation +not clean. It can also occur if action is needed to continue the operation for non-blocking BIOs. Call SSL_get_error() with the return value B to find out the reason. @@ -71,7 +71,7 @@ L =head1 COPYRIGHT -Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_CRL_get0_by_serial.pod b/doc/man3/X509_CRL_get0_by_serial.pod index 3294a32a..5deace4f 100644 --- a/doc/man3/X509_CRL_get0_by_serial.pod +++ b/doc/man3/X509_CRL_get0_by_serial.pod @@ -13,7 +13,7 @@ functions #include int X509_CRL_get0_by_serial(X509_CRL *crl, - X509_REVOKED **ret, ASN1_INTEGER *serial); + X509_REVOKED **ret, const ASN1_INTEGER *serial); int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x); STACK_OF(X509_REVOKED) *X509_CRL_get_REVOKED(X509_CRL *crl); diff --git a/doc/man3/X509_LOOKUP.pod b/doc/man3/X509_LOOKUP.pod index f29aceb0..bd7470d2 100644 --- a/doc/man3/X509_LOOKUP.pod +++ b/doc/man3/X509_LOOKUP.pod @@ -40,10 +40,10 @@ X509_LOOKUP_by_alias X509_STORE *X509_LOOKUP_get_store(const X509_LOOKUP *ctx); int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, - X509_NAME *name, X509_OBJECT *ret); + const 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); + const X509_NAME *name, + const 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); diff --git a/doc/man3/X509_LOOKUP_meth_new.pod b/doc/man3/X509_LOOKUP_meth_new.pod index 7a0dab7e..ccf352f3 100644 --- a/doc/man3/X509_LOOKUP_meth_new.pod +++ b/doc/man3/X509_LOOKUP_meth_new.pod @@ -57,7 +57,7 @@ X509_OBJECT_set1_X509, X509_OBJECT_set1_X509_CRL typedef int (*X509_LOOKUP_get_by_subject_fn)(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, - X509_NAME *name, + const X509_NAME *name, X509_OBJECT *ret); int X509_LOOKUP_meth_set_get_by_subject(X509_LOOKUP_METHOD *method, X509_LOOKUP_get_by_subject_fn fn); @@ -66,8 +66,8 @@ X509_OBJECT_set1_X509, X509_OBJECT_set1_X509_CRL typedef int (*X509_LOOKUP_get_by_issuer_serial_fn)(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, - X509_NAME *name, - ASN1_INTEGER *serial, + const X509_NAME *name, + const ASN1_INTEGER *serial, X509_OBJECT *ret); int X509_LOOKUP_meth_set_get_by_issuer_serial( X509_LOOKUP_METHOD *method, X509_LOOKUP_get_by_issuer_serial_fn fn); diff --git a/doc/man3/X509_NAME_get0_der.pod b/doc/man3/X509_NAME_get0_der.pod index 2bab4378..dd28b443 100644 --- a/doc/man3/X509_NAME_get0_der.pod +++ b/doc/man3/X509_NAME_get0_der.pod @@ -8,7 +8,7 @@ X509_NAME_get0_der - get X509_NAME DER encoding #include - int X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder, + int X509_NAME_get0_der(const X509_NAME *nm, const unsigned char **pder, size_t *pderlen) diff --git a/doc/man3/X509_NAME_get_index_by_NID.pod b/doc/man3/X509_NAME_get_index_by_NID.pod index f287849c..b8cbdf01 100644 --- a/doc/man3/X509_NAME_get_index_by_NID.pod +++ b/doc/man3/X509_NAME_get_index_by_NID.pod @@ -10,14 +10,17 @@ X509_NAME lookup and enumeration functions #include - int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos); - int X509_NAME_get_index_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int lastpos); + int X509_NAME_get_index_by_NID(const X509_NAME *name, int nid, int lastpos); + int X509_NAME_get_index_by_OBJ(const X509_NAME *name, + const ASN1_OBJECT *obj, int lastpos); int X509_NAME_entry_count(const X509_NAME *name); X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, int loc); - int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len); - int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, char *buf, int len); + int X509_NAME_get_text_by_NID(const X509_NAME *name, int nid, + char *buf, int len); + int X509_NAME_get_text_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj, + char *buf, int len); =head1 DESCRIPTION diff --git a/doc/man3/X509_STORE_CTX_get_error.pod b/doc/man3/X509_STORE_CTX_get_error.pod index 4e51ef28..b4d0cf4d 100644 --- a/doc/man3/X509_STORE_CTX_get_error.pod +++ b/doc/man3/X509_STORE_CTX_get_error.pod @@ -13,15 +13,15 @@ information #include - int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx); + int X509_STORE_CTX_get_error(const 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); + int X509_STORE_CTX_get_error_depth(const 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); + X509 *X509_STORE_CTX_get_current_cert(const X509_STORE_CTX *ctx); void X509_STORE_CTX_set_current_cert(X509_STORE_CTX *ctx, X509 *x); - X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx); + X509 *X509_STORE_CTX_get0_cert(const X509_STORE_CTX *ctx); - STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx); + STACK_OF(X509) *X509_STORE_CTX_get1_chain(const X509_STORE_CTX *ctx); const char *X509_verify_cert_error_string(long n); diff --git a/doc/man3/X509_STORE_CTX_new.pod b/doc/man3/X509_STORE_CTX_new.pod index db8416fa..5217a67d 100644 --- a/doc/man3/X509_STORE_CTX_new.pod +++ b/doc/man3/X509_STORE_CTX_new.pod @@ -2,9 +2,9 @@ =head1 NAME -X509_STORE_CTX_new, X509_STORE_CTX_cleanup, X509_STORE_CTX_free, -X509_STORE_CTX_init, X509_STORE_CTX_set0_trusted_stack, X509_STORE_CTX_set_cert, -X509_STORE_CTX_set0_crls, +X509_STORE_CTX_new_with_libctx, X509_STORE_CTX_new, X509_STORE_CTX_cleanup, +X509_STORE_CTX_free, X509_STORE_CTX_init, X509_STORE_CTX_set0_trusted_stack, +X509_STORE_CTX_set_cert, X509_STORE_CTX_set0_crls, X509_STORE_CTX_get0_chain, X509_STORE_CTX_set0_verified_chain, X509_STORE_CTX_get0_param, X509_STORE_CTX_set0_param, X509_STORE_CTX_get0_untrusted, X509_STORE_CTX_set0_untrusted, @@ -18,6 +18,8 @@ X509_STORE_CTX_verify_fn #include + X509_STORE_CTX *X509_STORE_CTX_new_with_libctx(OPENSSL_CTX *libctx, + const char *propq); X509_STORE_CTX *X509_STORE_CTX_new(void); void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx); void X509_STORE_CTX_free(X509_STORE_CTX *ctx); @@ -28,18 +30,18 @@ X509_STORE_CTX_verify_fn void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk); void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x); - STACK_OF(X509) *X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx); + STACK_OF(X509) *X509_STORE_CTX_get0_chain(const X509_STORE_CTX *ctx); void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *chain); void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk); - X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx); + X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(const X509_STORE_CTX *ctx); void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param); int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name); - STACK_OF(X509)* X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx); + STACK_OF(X509)* X509_STORE_CTX_get0_untrusted(const X509_STORE_CTX *ctx); void X509_STORE_CTX_set0_untrusted(X509_STORE_CTX *ctx, STACK_OF(X509) *sk); - int X509_STORE_CTX_get_num_untrusted(X509_STORE_CTX *ctx); + int X509_STORE_CTX_get_num_untrusted(const X509_STORE_CTX *ctx); typedef int (*X509_STORE_CTX_verify_fn)(X509_STORE_CTX *); void X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx, X509_STORE_CTX_verify_fn verify); @@ -49,61 +51,68 @@ X509_STORE_CTX_verify_fn These functions initialise an B structure for subsequent use by X509_verify_cert(). -X509_STORE_CTX_new() returns a newly initialised B structure. +X509_STORE_CTX_new_with_libctx() returns a newly initialised B +structure associated with the specified library context I and property +query string I. Any cryptographic algorithms fetched while performing +processing with the X509_STORE_CTX will use that library context and property +query string. + +X509_STORE_CTX_new() is the same as X509_STORE_CTX_new_with_libctx() except that +the default library context and a NULL property query string are used. X509_STORE_CTX_cleanup() internally cleans up an B structure. The context can then be reused with an new call to X509_STORE_CTX_init(). -X509_STORE_CTX_free() completely frees up B. After this call B +X509_STORE_CTX_free() completely frees up I. After this call I is no longer valid. -If B is NULL nothing is done. +If I is NULL nothing is done. -X509_STORE_CTX_init() sets up B for a subsequent verification operation. -It must be called before each call to X509_verify_cert(), i.e. a B is only +X509_STORE_CTX_init() sets up I for a subsequent verification operation. +It must be called before each call to X509_verify_cert(), i.e. a I is only good for one call to X509_verify_cert(); if you want to verify a second -certificate with the same B then you must call X509_STORE_CTX_cleanup() +certificate with the same I then you must call X509_STORE_CTX_cleanup() and then X509_STORE_CTX_init() again before the second call to -X509_verify_cert(). The trusted certificate store is set to B, the end -entity certificate to be verified is set to B and a set of additional +X509_verify_cert(). The trusted certificate store is set to I, the end +entity certificate to be verified is set to I and a set of additional certificates (which will be untrusted but may be used to build the chain) in -B. Any or all of the B, B and B parameters can be +I. Any or all of the I, I and I parameters can be B. X509_STORE_CTX_set0_trusted_stack() sets the set of trusted certificates of -B to B. This is an alternative way of specifying trusted certificates +I to I. This is an alternative way of specifying trusted certificates instead of using an B. -X509_STORE_CTX_set_cert() sets the certificate to be verified in B to -B. +X509_STORE_CTX_set_cert() sets the certificate to be verified in I to +I. X509_STORE_CTX_set0_verified_chain() sets the validated chain used -by B to be B. -Ownership of the chain is transferred to B and should not be +by I to be I. +Ownership of the chain is transferred to I and should not be free'd by the caller. X509_STORE_CTX_get0_chain() returns a the internal pointer used by the -B that contains the validated chain. +I that contains the validated chain. X509_STORE_CTX_set0_crls() sets a set of CRLs to use to aid certificate -verification to B. These CRLs will only be used if CRL verification is +verification to I. These CRLs will only be used if CRL verification is enabled in the associated B structure. This might be used where additional "useful" CRLs are supplied as part of a protocol, for example in a PKCS#7 structure. X509_STORE_CTX_get0_param() retrieves an internal pointer -to the verification parameters associated with B. +to the verification parameters associated with I. X509_STORE_CTX_get0_untrusted() retrieves an internal pointer to the -stack of untrusted certificates associated with B. +stack of untrusted certificates associated with I. X509_STORE_CTX_set0_untrusted() sets the internal point to the stack -of untrusted certificates associated with B to B. +of untrusted certificates associated with I to I. X509_STORE_CTX_set0_param() sets the internal verification parameter pointer -to B. After this call B should not be used. +to I. After this call B should not be used. X509_STORE_CTX_set_default() looks up and sets the default verification -method to B. This uses the function X509_VERIFY_PARAM_lookup() to -find an appropriate set of parameters from B. +method to I. This uses the function X509_VERIFY_PARAM_lookup() to +find an appropriate set of parameters from I. X509_STORE_CTX_get_num_untrusted() returns the number of untrusted certificates that were used in building the chain following a call to X509_verify_cert(). @@ -161,6 +170,7 @@ L The X509_STORE_CTX_set0_crls() function was added in OpenSSL 1.0.0. The X509_STORE_CTX_get_num_untrusted() function was added in OpenSSL 1.1.0. +The X509_STORE_CTX_new_with_libctx() function was added in OpenSSL 3.0. =head1 COPYRIGHT diff --git a/doc/man3/X509_STORE_get0_param.pod b/doc/man3/X509_STORE_get0_param.pod index 6db760ea..c458afa1 100644 --- a/doc/man3/X509_STORE_get0_param.pod +++ b/doc/man3/X509_STORE_get0_param.pod @@ -10,9 +10,9 @@ X509_STORE_get0_objects, X509_STORE_get1_all_certs #include - X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx); - int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *pm); - STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *ctx); + X509_VERIFY_PARAM *X509_STORE_get0_param(const X509_STORE *ctx); + int X509_STORE_set1_param(X509_STORE *ctx, const X509_VERIFY_PARAM *pm); + STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(const X509_STORE *ctx); STACK_OF(X509) *X509_STORE_get1_all_certs(X509_STORE *st); =head1 DESCRIPTION diff --git a/doc/man3/X509_STORE_set_verify_cb_func.pod b/doc/man3/X509_STORE_set_verify_cb_func.pod index b6069a3b..5a2a52fe 100644 --- a/doc/man3/X509_STORE_set_verify_cb_func.pod +++ b/doc/man3/X509_STORE_set_verify_cb_func.pod @@ -51,57 +51,65 @@ X509_STORE_CTX_lookup_certs_fn, X509_STORE_CTX_lookup_crls_fn X509_CRL *crl, X509 *x); typedef int (*X509_STORE_CTX_check_policy_fn)(X509_STORE_CTX *ctx); typedef STACK_OF(X509) *(*X509_STORE_CTX_lookup_certs_fn)(X509_STORE_CTX *ctx, - X509_NAME *nm); - typedef STACK_OF(X509_CRL) *(*X509_STORE_CTX_lookup_crls_fn)(X509_STORE_CTX *ctx, - X509_NAME *nm); + const X509_NAME *nm); + typedef STACK_OF(X509_CRL) *(*X509_STORE_CTX_lookup_crls_fn)(const + X509_STORE_CTX *ctx, + const X509_NAME *nm); typedef int (*X509_STORE_CTX_cleanup_fn)(X509_STORE_CTX *ctx); void X509_STORE_set_verify_cb(X509_STORE *ctx, X509_STORE_CTX_verify_cb verify_cb); - X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(X509_STORE_CTX *ctx); + X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(const X509_STORE_CTX *ctx); void X509_STORE_set_verify(X509_STORE *ctx, X509_STORE_CTX_verify_fn verify); - X509_STORE_CTX_verify_fn X509_STORE_CTX_get_verify(X509_STORE_CTX *ctx); + X509_STORE_CTX_verify_fn X509_STORE_CTX_get_verify(const X509_STORE_CTX *ctx); void X509_STORE_set_get_issuer(X509_STORE *ctx, X509_STORE_CTX_get_issuer_fn get_issuer); - X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(X509_STORE_CTX *ctx); + X509_STORE_CTX_get_issuer_fn + X509_STORE_get_get_issuer(const X509_STORE_CTX *ctx); void X509_STORE_set_check_issued(X509_STORE *ctx, X509_STORE_CTX_check_issued_fn check_issued); - X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(X509_STORE_CTX *ctx); + X509_STORE_CTX_check_issued_fn + X509_STORE_get_check_issued(const X509_STORE_CTX *ctx); void X509_STORE_set_check_revocation(X509_STORE *ctx, X509_STORE_CTX_check_revocation_fn check_revocation); - X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation(X509_STORE_CTX *ctx); + X509_STORE_CTX_check_revocation_fn + X509_STORE_get_check_revocation(const X509_STORE_CTX *ctx); void X509_STORE_set_get_crl(X509_STORE *ctx, X509_STORE_CTX_get_crl_fn get_crl); - X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(X509_STORE_CTX *ctx); + X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(const X509_STORE_CTX *ctx); void X509_STORE_set_check_crl(X509_STORE *ctx, X509_STORE_CTX_check_crl_fn check_crl); - X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(X509_STORE_CTX *ctx); + X509_STORE_CTX_check_crl_fn + X509_STORE_get_check_crl(const X509_STORE_CTX *ctx); void X509_STORE_set_cert_crl(X509_STORE *ctx, X509_STORE_CTX_cert_crl_fn cert_crl); - X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(X509_STORE_CTX *ctx); + X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(const X509_STORE_CTX *ctx); void X509_STORE_set_check_policy(X509_STORE *ctx, X509_STORE_CTX_check_policy_fn check_policy); - X509_STORE_CTX_check_policy_fn X509_STORE_get_check_policy(X509_STORE_CTX *ctx); + X509_STORE_CTX_check_policy_fn + X509_STORE_get_check_policy(const X509_STORE_CTX *ctx); void X509_STORE_set_lookup_certs(X509_STORE *ctx, X509_STORE_CTX_lookup_certs_fn lookup_certs); - X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(X509_STORE_CTX *ctx); + X509_STORE_CTX_lookup_certs_fn + X509_STORE_get_lookup_certs(const X509_STORE_CTX *ctx); void X509_STORE_set_lookup_crls(X509_STORE *ctx, X509_STORE_CTX_lookup_crls_fn lookup_crls); - X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(X509_STORE_CTX *ctx); + X509_STORE_CTX_lookup_crls_fn + X509_STORE_get_lookup_crls(const X509_STORE_CTX *ctx); void X509_STORE_set_cleanup(X509_STORE *ctx, X509_STORE_CTX_cleanup_fn cleanup); - X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(X509_STORE_CTX *ctx); + X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(const X509_STORE_CTX *ctx); /* Aliases */ void X509_STORE_set_verify_cb_func(X509_STORE *st, diff --git a/doc/man3/X509_VERIFY_PARAM_set_flags.pod b/doc/man3/X509_VERIFY_PARAM_set_flags.pod index 8352a39b..b458c282 100644 --- a/doc/man3/X509_VERIFY_PARAM_set_flags.pod +++ b/doc/man3/X509_VERIFY_PARAM_set_flags.pod @@ -57,7 +57,7 @@ X509_VERIFY_PARAM_set1_ip_asc void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, unsigned int flags); unsigned int X509_VERIFY_PARAM_get_hostflags(const X509_VERIFY_PARAM *param); - char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param); + char *X509_VERIFY_PARAM_get0_peername(const X509_VERIFY_PARAM *param); int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, const char *email, size_t emaillen); int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, diff --git a/doc/man3/X509_check_ca.pod b/doc/man3/X509_check_ca.pod index 9fe01d19..89adb2e3 100644 --- a/doc/man3/X509_check_ca.pod +++ b/doc/man3/X509_check_ca.pod @@ -24,6 +24,8 @@ B extension with bit B set, but without B, and 5 if it has outdated Netscape Certificate Type extension telling that it is CA certificate. +This function will also return 0 on error. + Actually, any nonzero value means that this certificate could have been used to sign other certificates. diff --git a/doc/man3/X509_check_purpose.pod b/doc/man3/X509_check_purpose.pod new file mode 100644 index 00000000..e44a9ea1 --- /dev/null +++ b/doc/man3/X509_check_purpose.pod @@ -0,0 +1,74 @@ +=pod + +=head1 NAME + +X509_check_purpose - Check the purpose of a certificate + +=head1 SYNOPSIS + + #include + + int X509_check_purpose(X509 *x, int id, int ca) + +=head1 DESCRIPTION + +This function checks if certificate I was created with the purpose +represented by I. If I is nonzero, then certificate I is +checked to determine if it's a possible CA with various levels of certainty +possibly returned. + +Below are the potential ID's that can be checked: + + # define X509_PURPOSE_SSL_CLIENT 1 + # define X509_PURPOSE_SSL_SERVER 2 + # define X509_PURPOSE_NS_SSL_SERVER 3 + # define X509_PURPOSE_SMIME_SIGN 4 + # define X509_PURPOSE_SMIME_ENCRYPT 5 + # define X509_PURPOSE_CRL_SIGN 6 + # define X509_PURPOSE_ANY 7 + # define X509_PURPOSE_OCSP_HELPER 8 + # define X509_PURPOSE_TIMESTAMP_SIGN 9 + +=head1 RETURN VALUES + +For non-CA checks + +=over 4 + +=item -1 an error condition has occured + +=item E<32>1 if the certificate was created to perform the purpose represented by I + +=item E<32>0 if the certificate was not created to perform the purpose represented by I + +=back + +For CA checks the below integers could be returned with the following meanings: + +=over 4 + +=item -1 an error condition has occured + +=item E<32>0 not a CA or does not have the purpose represented by I + +=item E<32>1 is a CA. + +=item E<32>2 Only possible in old versions of openSSL when basicConstraints are absent. + New versions will not return this value. May be a CA + +=item E<32>3 basicConstraints absent but self signed V1. + +=item E<32>4 basicConstraints absent but keyUsage present and keyCertSign asserted. + +=item E<32>5 legacy Netscape specific CA Flags present + +=back + +=head1 COPYRIGHT + +Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. +Licensed under the Apache License 2.0 (the "License"). You may not use this +file except in compliance with the License. You can obtain a copy in the file +LICENSE in the source distribution or at L. + +=cut diff --git a/doc/man3/X509_digest.pod b/doc/man3/X509_digest.pod index 52eb522b..dfddd12e 100644 --- a/doc/man3/X509_digest.pod +++ b/doc/man3/X509_digest.pod @@ -2,7 +2,9 @@ =head1 NAME -X509_digest, X509_CRL_digest, +X509_digest, +X509_digest_sig, +X509_CRL_digest, X509_pubkey_digest, X509_NAME_digest, X509_REQ_digest, @@ -15,6 +17,7 @@ PKCS7_ISSUER_AND_SERIAL_digest int X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md, unsigned int *len); + ASN1_OCTET_STRING *X509_digest_sig(const X509 *cert); int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type, unsigned char *md, unsigned int *len); @@ -36,8 +39,12 @@ PKCS7_ISSUER_AND_SERIAL_digest =head1 DESCRIPTION +X509_digest_sig() calculates a digest of the given certificate +using the same hash algorithm as in its signature. + X509_pubkey_digest() returns a digest of the DER representation of the public key in the specified X509 B object. + All other functions described here return a digest of the DER representation of their entire B objects. @@ -49,12 +56,18 @@ to a place where the digest size will be stored. =head1 RETURN VALUES -All functions described here return 1 for success and 0 for failure. +X509_digest_sig() returns an ASN1_OCTET_STRING on success, else NULL. + +All other functions described here return 1 for success and 0 for failure. =head1 SEE ALSO L +=head1 HISTORY + +The X509_digest_sig() function was added in OpenSSL 3.0. + =head1 COPYRIGHT Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/X509_dup.pod b/doc/man3/X509_dup.pod index d7d84778..cb1e9edf 100644 --- a/doc/man3/X509_dup.pod +++ b/doc/man3/X509_dup.pod @@ -122,13 +122,17 @@ OCSP_SIGNATURE_free, OCSP_SIGNATURE_new, OCSP_SINGLERESP_free, OCSP_SINGLERESP_new, +OSSL_CMP_ITAV_dup, OSSL_CMP_ITAV_free, +OSSL_CMP_MSG_dup, OSSL_CMP_MSG_it, OSSL_CMP_MSG_free, OSSL_CMP_PKIHEADER_free, OSSL_CMP_PKIHEADER_it, OSSL_CMP_PKIHEADER_new, +OSSL_CMP_PKISI_dup, OSSL_CMP_PKISI_free, +OSSL_CMP_PKISI_it, OSSL_CMP_PKISI_new, OSSL_CMP_PKISTATUS_it, OSSL_CRMF_CERTID_free, diff --git a/doc/man3/X509_get0_distinguishing_id.pod b/doc/man3/X509_get0_distinguishing_id.pod new file mode 100644 index 00000000..2dd06e71 --- /dev/null +++ b/doc/man3/X509_get0_distinguishing_id.pod @@ -0,0 +1,71 @@ +=pod + +=head1 NAME + +X509_get0_distinguishing_id, X509_set0_distinguishing_id, +X509_REQ_get0_distinguishing_id, X509_REQ_set0_distinguishing_id +- get or set the Distinguishing ID for certificate operations + +=head1 SYNOPSIS + + #include + + ASN1_OCTET_STRING *X509_get0_distinguishing_id(X509 *x); + void X509_set0_distinguishing_id(X509 *x, ASN1_OCTET_STRING *distid); + ASN1_OCTET_STRING *X509_REQ_get0_distinguishing_id(X509_REQ *x); + void X509_REQ_set0_distinguishing_id(X509_REQ *x, ASN1_OCTET_STRING *distid); + +=head1 DESCRIPTION + +The Distinguishing ID is defined in FIPS 196 as follows: + +=over 4 + +I: information which unambiguously distinguishes +an entity in the authentication process. + +=back + +The SM2 signature algorithm requires a Distinguishing ID value when generating +and verifying a signature, but the Ddistinguishing ID may also find other uses. +In the context of SM2, the Distinguishing ID is often referred to as the "SM2 +ID". + +For the purpose off verifying a certificate or a certification request, a +Distinguishing ID may be attached to it, so functions like L +or L have easy access to that identity for signature +verification. + +X509_get0_distinguishing_id() gets the Distinguishing ID value of a certificate +B by returning an B object which should not be freed by +the caller. + +X509_set0_distinguishing_id() assigns B to the certificate B. +Calling this function transfers the memory management of the value to the X509 +object, and therefore the value that has been passed in should not be freed by +the caller after this function has been called. + +X509_REQ_get0_distinguishing_id() and X509_REQ_set0_distinguishing_id() +have the same functionality as X509_get0_distinguishing_id() and +X509_set0_distinguishing_id() except that they deal with B +objects instead of B. + +=head1 RETURN VALUES + +X509_set0_distinguishing_id() and X509_REQ_set0_distinguishing_id() do not +return a value. + +=head1 SEE ALSO + +L, L + +=head1 COPYRIGHT + +Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man3/X509_get0_sm2_id.pod b/doc/man3/X509_get0_sm2_id.pod deleted file mode 100644 index d8a85d7f..00000000 --- a/doc/man3/X509_get0_sm2_id.pod +++ /dev/null @@ -1,55 +0,0 @@ -=pod - -=head1 NAME - -X509_get0_sm2_id, X509_set0_sm2_id, -X509_REQ_get0_sm2_id, X509_REQ_set0_sm2_id -- get or set SM2 ID for certificate operations - -=head1 SYNOPSIS - - #include - - ASN1_OCTET_STRING *X509_get0_sm2_id(X509 *x); - void X509_set0_sm2_id(X509 *x, ASN1_OCTET_STRING *sm2_id); - ASN1_OCTET_STRING *X509_REQ_get0_sm2_id(X509_REQ *x); - void X509_REQ_set0_sm2_id(X509_REQ *x, ASN1_OCTET_STRING *sm2_id); - -=head1 DESCRIPTION - -X509_get0_sm2_id() gets the ID value of an SM2 certificate B by returning an -B object which should not be freed by the caller. - -X509_set0_sm2_id() sets the B value to an SM2 certificate B. Calling -this function transfers the memory management of the value to the X509 object, -and therefore the value that has been passed in should not be freed by the -caller after this function has been called. - -X509_REQ_get0_sm2_id() and X509_REQ_set0_sm2_id() have the same functionality -as X509_get0_sm2_id() and X509_set0_sm2_id() except that they deal with -B objects instead of B. - -=head1 NOTES - -SM2 signature algorithm requires an ID value when generating and verifying a -signature. The functions described in this manual provide the user with the -ability to set and retrieve the SM2 ID value. - -=head1 RETURN VALUES - -X509_set0_sm2_id() and X509_REQ_set0_sm2_id() do not return a value. - -=head1 SEE ALSO - -L, L - -=head1 COPYRIGHT - -Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. - -Licensed under the Apache License 2.0 (the "License"). You may not use -this file except in compliance with the License. You can obtain a copy -in the file LICENSE in the source distribution or at -L. - -=cut diff --git a/doc/man3/X509_get_extension_flags.pod b/doc/man3/X509_get_extension_flags.pod index 34f811c7..3f09939e 100644 --- a/doc/man3/X509_get_extension_flags.pod +++ b/doc/man3/X509_get_extension_flags.pod @@ -80,6 +80,17 @@ The certificate contains an unhandled critical extension. Some certificate extension values are invalid or inconsistent. The certificate should be rejected. +This bit may also be raised after an out-of-memory error while +processing the X509 object, so it may not be related to the processed +ASN1 object itself. + +=item B + +The NID_certificate_policies certificate extension is invalid or +inconsistent. The certificate should be rejected. +This bit may also be raised after an out-of-memory error while +processing the X509 object, so it may not be related to the processed +ASN1 object itself. =item B @@ -183,7 +194,7 @@ X509_get_proxy_pathlen() were added in OpenSSL 1.1.0. =head1 COPYRIGHT -Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_get_subject_name.pod b/doc/man3/X509_get_subject_name.pod index 8c9d854b..3b52d370 100644 --- a/doc/man3/X509_get_subject_name.pod +++ b/doc/man3/X509_get_subject_name.pod @@ -12,16 +12,16 @@ subject names #include X509_NAME *X509_get_subject_name(const X509 *x); - int X509_set_subject_name(X509 *x, X509_NAME *name); + int X509_set_subject_name(X509 *x, const X509_NAME *name); X509_NAME *X509_get_issuer_name(const X509 *x); - int X509_set_issuer_name(X509 *x, X509_NAME *name); + int X509_set_issuer_name(X509 *x, const X509_NAME *name); X509_NAME *X509_REQ_get_subject_name(const X509_REQ *req); - int X509_REQ_set_subject_name(X509_REQ *req, X509_NAME *name); + int X509_REQ_set_subject_name(X509_REQ *req, const X509_NAME *name); X509_NAME *X509_CRL_get_issuer(const X509_CRL *crl); - int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name); + int X509_CRL_set_issuer_name(X509_CRL *x, const X509_NAME *name); =head1 DESCRIPTION diff --git a/doc/man3/X509v3_cache_extensions.pod b/doc/man3/X509v3_cache_extensions.pod new file mode 100644 index 00000000..952a8c2e --- /dev/null +++ b/doc/man3/X509v3_cache_extensions.pod @@ -0,0 +1,43 @@ +=pod + +=head1 NAME + +X509v3_cache_extensions +- process any extensions in an X509 object + +=head1 SYNOPSIS + + #include + + int X509v3_cache_extensions(X509 *x, OPENSSL_CTX *libctx, const char *propq); + +=head1 DESCRIPTION + +This function processes any X509v3 extensions that might be present in an X509 +object and caches the result of that processing. Many OpenSSL functions that use +an X509 object will cause extensions to be processed and cached implicitly. If +this is done implicitly then the default library context and property query +string will be used. In some cases it may be desirable to use some other library +context and property query string. If so then an application can call +X509v3_cache_extensions() explicitly. This should be done before any function +that needs to use those extensions is called - otherwise calling +X509v3_cache_extensions() will have no effect. Typically this means calling this +soon after creation of the X509 object. The X509 object to be processed is +given in I and the library context and property query string to use are given +in I and I. + +=head1 RETURN VALUES + +This function returns 0 if the extensions are invalid or an error occurred. +Otherwise it returns 1. + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man3/d2i_X509.pod b/doc/man3/d2i_X509.pod index d41d2e0c..35475738 100644 --- a/doc/man3/d2i_X509.pod +++ b/doc/man3/d2i_X509.pod @@ -98,6 +98,7 @@ d2i_OCSP_SIGNATURE, d2i_OCSP_SINGLERESP, d2i_OSSL_CMP_MSG, d2i_OSSL_CMP_PKIHEADER, +d2i_OSSL_CMP_PKISI, d2i_OSSL_CRMF_CERTID, d2i_OSSL_CRMF_CERTTEMPLATE, d2i_OSSL_CRMF_ENCRYPTEDVALUE, @@ -289,6 +290,7 @@ i2d_OCSP_SIGNATURE, i2d_OCSP_SINGLERESP, i2d_OSSL_CMP_MSG, i2d_OSSL_CMP_PKIHEADER, +i2d_OSSL_CMP_PKISI, i2d_OSSL_CRMF_CERTID, i2d_OSSL_CRMF_CERTTEMPLATE, i2d_OSSL_CRMF_ENCRYPTEDVALUE, diff --git a/doc/man5/config.pod b/doc/man5/config.pod index b9ad06b1..98b8cd33 100644 --- a/doc/man5/config.pod +++ b/doc/man5/config.pod @@ -455,7 +455,7 @@ priority and B used if neither is defined: Simple OpenSSL library configuration example to enter FIPS mode: # Default appname: should match "appname" parameter (if any) - # supplied to CONF_modules_load_file et al. + # supplied to CONF_modules_load_file_with_libctx et al. openssl_conf = openssl_conf_section [openssl_conf_section] @@ -488,7 +488,7 @@ minimum TLS version: More complex OpenSSL library configuration. Add OID and don't enter FIPS mode: # Default appname: should match "appname" parameter (if any) - # supplied to CONF_modules_load_file et al. + # supplied to CONF_modules_load_file_with_libctx et al. openssl_conf = openssl_conf_section [openssl_conf_section] @@ -576,7 +576,7 @@ L, L, L, L =head1 COPYRIGHT -Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_MD-BLAKE2.pod b/doc/man7/EVP_MD-BLAKE2.pod new file mode 100644 index 00000000..be3b0b92 --- /dev/null +++ b/doc/man7/EVP_MD-BLAKE2.pod @@ -0,0 +1,46 @@ +=pod + +=head1 NAME + +EVP_MD-BLAKE2 - The BLAKE2 EVP_MD implementation + +=head1 DESCRIPTION + +Support for computing SHA2 digests through the B API. + +=head2 Identities + +This implementation is only available with the default provider, and +includes the following varieties: + +=over 4 + +=item BLAKE2S-256 + +Known names are "BLAKE2S-256" and "BLAKE2s256". + +=item BLAKE2B-512 + +Known names are "BLAKE2B-512" and "BLAKE2b512". + +=back + +=head2 Gettable Parameters + +This implementation supports the common gettable parameters described +in L. + +=head1 SEE ALSO + +L, L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man7/EVP_MD-MD2.pod b/doc/man7/EVP_MD-MD2.pod new file mode 100644 index 00000000..61fc42fc --- /dev/null +++ b/doc/man7/EVP_MD-MD2.pod @@ -0,0 +1,34 @@ +=pod + +=head1 NAME + +EVP_MD-MD2 - The MD2 EVP_MD implementation + +=head1 DESCRIPTION + +Support for computing MD2 digests through the B API. + +=head2 Identity + +This implementation is only available with the legacy provider, and is +identified with the name "MD2". + +=head2 Gettable Parameters + +This implementation supports the common gettable parameters described +in L. + +=head1 SEE ALSO + +L, L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man7/EVP_MD-MD4.pod b/doc/man7/EVP_MD-MD4.pod new file mode 100644 index 00000000..0a3f97c4 --- /dev/null +++ b/doc/man7/EVP_MD-MD4.pod @@ -0,0 +1,34 @@ +=pod + +=head1 NAME + +EVP_MD-MD4 - The MD4 EVP_MD implementation + +=head1 DESCRIPTION + +Support for computing MD4 digests through the B API. + +=head2 Identity + +This implementation is only available with the legacy provider, and is +identified with the name "MD4". + +=head2 Gettable Parameters + +This implementation supports the common gettable parameters described +in L. + +=head1 SEE ALSO + +L, L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man7/EVP_MD-MD5-SHA1.pod b/doc/man7/EVP_MD-MD5-SHA1.pod new file mode 100644 index 00000000..61652ad5 --- /dev/null +++ b/doc/man7/EVP_MD-MD5-SHA1.pod @@ -0,0 +1,56 @@ +=pod + +=head1 NAME + +EVP_MD-MD5-SHA1 - The MD5-SHA1 EVP_MD implementation + +=head1 DESCRIPTION + +Support for computing MD5-SHA1 digests through the B API. + +MD5-SHA1 is a rather special digest that's used with SSLv3. + +=head2 Identity + +This implementation is only available with the default provider, and is +identified with the name "MD5-SHA1". + +=head2 Gettable Parameters + +This implementation supports the common gettable parameters described +in L. + +=head2 Settable Context Parameters + +This implementation supports the following L entries, +settable for an B with L: + +=over 4 + +=item "ssl3-ms" (B) + +This parameter is set by libssl in order to calculate a signature hash for an +SSLv3 CertificateVerify message as per RFC6101. +It is only set after all handshake messages have already been digested via +OP_digest_update() calls. +The parameter provides the master secret value to be added to the digest. +The digest implementation should calculate the complete digest as per RFC6101 +section 5.6.8. +The next call after setting this parameter should be OP_digest_final(). + +=back + +=head1 SEE ALSO + +L, L, L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man7/EVP_MD-MD5.pod b/doc/man7/EVP_MD-MD5.pod new file mode 100644 index 00000000..98ae2c5b --- /dev/null +++ b/doc/man7/EVP_MD-MD5.pod @@ -0,0 +1,34 @@ +=pod + +=head1 NAME + +EVP_MD-MD5 - The MD5 EVP_MD implementation + +=head1 DESCRIPTION + +Support for computing MD5 digests through the B API. + +=head2 Identity + +This implementation is only available with the default provider, and is +identified with the name "MD5". + +=head2 Gettable Parameters + +This implementation supports the common gettable parameters described +in L. + +=head1 SEE ALSO + +L, L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man7/EVP_MD-MDC2.pod b/doc/man7/EVP_MD-MDC2.pod new file mode 100644 index 00000000..516e19da --- /dev/null +++ b/doc/man7/EVP_MD-MDC2.pod @@ -0,0 +1,50 @@ +=pod + +=head1 NAME + +EVP_MD-MDC2 - The MDC2 EVP_MD implementation + +=head1 DESCRIPTION + +Support for computing MDC2 digests through the B API. + +=head2 Identity + +This implementation is only available with the legacy provider, and is +identified with the name "MDC2". + +=head2 Gettable Parameters + +This implementation supports the common gettable parameters described +in L. + +=head2 Settable Context Parameters + +This implementation supports the following L entries, +settable for an B with L: + +=over 4 + +=item "pad_type" (B) + +Sets the padding type to be used. +Normally the final MDC2 block is padded with zeros. +If the pad type is set to 2 then the final block is padded with 0x80 followed by +zeros. + +=back + +=head1 SEE ALSO + +L, L, L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man7/EVP_MD-RIPEMD160.pod b/doc/man7/EVP_MD-RIPEMD160.pod new file mode 100644 index 00000000..0504e9b3 --- /dev/null +++ b/doc/man7/EVP_MD-RIPEMD160.pod @@ -0,0 +1,35 @@ +=pod + +=head1 NAME + +EVP_MD-RIPEMD160 - The RIPEMD160 EVP_MD implementation + +=head1 DESCRIPTION + +Support for computing RIPEMD160 digests through the B API. + +=head2 Identities + +This implementation is only available with the legacy provider, and is +identified with any of the names "RIPEMD-160", "RIPEMD160", "RIPEMD" and +"RMD160". + +=head2 Gettable Parameters + +This implementation supports the common gettable parameters described +in L. + +=head1 SEE ALSO + +L, L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man7/EVP_MD-SHA1.pod b/doc/man7/EVP_MD-SHA1.pod new file mode 100644 index 00000000..5fd94df4 --- /dev/null +++ b/doc/man7/EVP_MD-SHA1.pod @@ -0,0 +1,55 @@ +=pod + +=head1 NAME + +EVP_MD-SHA1 - The SHA1 EVP_MD implementation + +=head1 DESCRIPTION + +Support for computing SHA1 digests through the B API. + +=head2 Identities + +This implementation is available with the FIPS provider as well as the +default provider, and is identified with the names "SHA1" and "SHA-1". + +=head2 Gettable Parameters + +This implementation supports the common gettable parameters described +in L. + +=head2 Settable Context Parameters + +This implementation supports the following L entries, +settable for an B with L: + +=over 4 + +=item "ssl3-ms" (B) + +This parameter is set by libssl in order to calculate a signature hash for an +SSLv3 CertificateVerify message as per RFC6101. +It is only set after all handshake messages have already been digested via +OP_digest_update() calls. +The parameter provides the master secret value to be added to the digest. +The digest implementation should calculate the complete digest as per RFC6101 +section 5.6.8. +The next call after setting this parameter should be OP_digest_final(). + +=back + +=head1 SEE ALSO + +L, L, +L, L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man7/EVP_MD-SHA2.pod b/doc/man7/EVP_MD-SHA2.pod new file mode 100644 index 00000000..2a2e799d --- /dev/null +++ b/doc/man7/EVP_MD-SHA2.pod @@ -0,0 +1,77 @@ +=pod + +=head1 NAME + +EVP_MD-SHA2 - The SHA2 EVP_MD implementation + +=head1 DESCRIPTION + +Support for computing SHA2 digests through the B API. + +=head2 Identities + +This implementation includes the following varieties: + +=over 4 + +=item * + +Available with the FIPS provider as well as the default provider: + +=over 4 + +=item SHA2-224 + +Known names are "SHA2-224", "SHA-224" and "SHA224". + +=item SHA2-256 + +Known names are "SHA2-256", "SHA-256" and "SHA256". + +=item SHA2-384 + +Known names are "SHA2-384", "SHA-384" and "SHA384". + +=item SHA2-512 + +Known names are "SHA2-512", "SHA-512" and "SHA512". + +=back + +=item * + +Available with the default provider: + +=over 4 + +=item SHA2-512/224 + +Known names are "SHA2-512/224", "SHA-512/224" and "SHA512-224". + +=item SHA2-512/256 + +Known names are "SHA2-512/256", "SHA-512/256" and "SHA512-256". + +=back + +=back + +=head2 Gettable Parameters + +This implementation supports the common gettable parameters described +in L. + +=head1 SEE ALSO + +L, L, L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man7/EVP_MD-SHA3.pod b/doc/man7/EVP_MD-SHA3.pod new file mode 100644 index 00000000..bc5c3508 --- /dev/null +++ b/doc/man7/EVP_MD-SHA3.pod @@ -0,0 +1,46 @@ +=pod + +=head1 NAME + +EVP_MD-SHA3 - The SHA3 EVP_MD implementations + +=head1 DESCRIPTION + +Support for computing SHA3 digests through the B API. + +=head2 Identities + +This implementation is available with the FIPS provider as well as the +default provider, and includes the following varieties: + +=over 4 + +=item "SHA3-224" + +=item "SHA3-256" + +=item "SHA3-384" + +=item "SHA3-512" + +=back + +=head2 Gettable Parameters + +This implementation supports the common gettable parameters described +in L. + +=head1 SEE ALSO + +L, L, L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man7/EVP_MD-SHAKE.pod b/doc/man7/EVP_MD-SHAKE.pod new file mode 100644 index 00000000..2426d5a4 --- /dev/null +++ b/doc/man7/EVP_MD-SHAKE.pod @@ -0,0 +1,73 @@ +=pod + +=head1 NAME + +EVP_MD-SHAKE, EVP_MD-KECCAK-KMAC +- The SHAKE / KECCAK family EVP_MD implementations + +=head1 DESCRIPTION + +Support for computing SHAKE or KECCAK-KMAC digests through the +B API. + +KECCAK-KMAC is a special digest that's used by the KMAC EVP_MAC +implementation (see L). + +=head2 Identities + +This implementation is only available with the default provider, and +includes the following varieties: + +=over 4 + +=item KECCAK-KMAC-128 + +Known names are "KECCAK-KMAC-128" and "KECCAK-KMAC128" + +=item KECCAK-KMAC-256 + +Known names are "KECCAK-KMAC-256" and "KECCAK-KMAC256" + +=item SHAKE-128 + +Known names are "SHAKE-128" and "SHAKE128" + +=item SHAKE-256 + +Known names are "SHAKE-256" and "SHAKE256" + +=back + +=head2 Gettable Parameters + +This implementation supports the common gettable parameters described +in L. + +=head2 Settable Context Parameters + +These implementations support the following L entries, +settable for an B with L: + +=over 4 + +=item "xoflen" (B) + +Sets the digest length for extendable output functions. +The length of the "xoflen" parameter should not exceed that of a B. + +=back + +=head1 SEE ALSO + +L, L, L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man7/EVP_MD-SM3.pod b/doc/man7/EVP_MD-SM3.pod new file mode 100644 index 00000000..355c52ec --- /dev/null +++ b/doc/man7/EVP_MD-SM3.pod @@ -0,0 +1,34 @@ +=pod + +=head1 NAME + +EVP_MD-SM3 - The SM3 EVP_MD implementations + +=head1 DESCRIPTION + +Support for computing SM3 digests through the B API. + +=head2 Identity + +This implementation is only available with the default provider, and is +identified with the name "SM3". + +=head2 Gettable Parameters + +This implementation supports the common gettable parameters described +in L. + +=head1 SEE ALSO + +L, L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man7/EVP_MD-WHIRLPOOL.pod b/doc/man7/EVP_MD-WHIRLPOOL.pod new file mode 100644 index 00000000..2252ab2d --- /dev/null +++ b/doc/man7/EVP_MD-WHIRLPOOL.pod @@ -0,0 +1,34 @@ +=pod + +=head1 NAME + +EVP_MD-WHIRLPOOL - The WHIRLPOOL EVP_MD implementation + +=head1 DESCRIPTION + +Support for computing WHIRLPOOL digests through the B API. + +=head2 Identity + +This implementation is only available with the legacy provider, and is +identified with the name "WHIRLPOOL". + +=head2 Gettable Parameters + +This implementation supports the common gettable parameters described +in L. + +=head1 SEE ALSO + +L, L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man7/EVP_MD-common.pod b/doc/man7/EVP_MD-common.pod new file mode 100644 index 00000000..78384498 --- /dev/null +++ b/doc/man7/EVP_MD-common.pod @@ -0,0 +1,67 @@ +=pod + +=head1 NAME + +EVP_MD-common - The OpenSSL EVP_MD implementations, common things + +=head1 DESCRIPTION + +All the OpenSSL EVP_MD implementations understand the following +L entries: + +=over 4 + +Gettable with L: + +=over 4 + +=item "blocksize" (B) + +The digest block size. +The length of the "blocksize" parameter should not exceed that of a +B. + +This value can also be retrieved with L. + +=item "size" (B) + +The digest output size. +The length of the "size" parameter should not exceed that of a B. + +This value can also be retrieved with L. + +=item "flags" (B) + +Diverse flags that describe exceptional behaviour for the digest. +These flags are described in L. + +The length of the "flags" parameter should equal that of an +B. + +=begin comment + +The description of these flags should probably be moved. Also, +EVP_MD_FLAG_FIPS isn't relevant any more. + +=end comment + +This value can also be retrieved with L. + +=back + +=back + +=head1 SEE ALSO + +L, L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man7/Ed25519.pod b/doc/man7/Ed25519.pod index 242d5611..3d82f5ea 100644 --- a/doc/man7/Ed25519.pod +++ b/doc/man7/Ed25519.pod @@ -11,7 +11,7 @@ Ed448 The B and B EVP_PKEY implementation supports key generation, one-shot digest sign and digest verify using PureEdDSA and B or B (see RFC8032). It has associated private and public key formats compatible with -draft-ietf-curdle-pkix-04. +RFC 8410. No additional parameters can be set during key generation, one-shot signing or verification. In particular, because PureEdDSA is used, a digest must B be diff --git a/doc/man7/OSSL_PROVIDER-FIPS.pod b/doc/man7/OSSL_PROVIDER-FIPS.pod index 1cb75e7c..92dab0e8 100644 --- a/doc/man7/OSSL_PROVIDER-FIPS.pod +++ b/doc/man7/OSSL_PROVIDER-FIPS.pod @@ -2,15 +2,136 @@ =head1 NAME -OSSL_PROVIDER-FIPS - OPENSSL FIPS provider +OSSL_PROVIDER-FIPS - OpenSSL FIPS provider =head1 DESCRIPTION -The OPENSSL FIPS provider is a special provider that conforms to the Federal +The OpenSSL FIPS provider is a special provider that conforms to the Federal Information Processing Standards (FIPS) specified in FIPS 140-2. This 'module' contains an approved set of cryptographic algorithms that is validated by an accredited testing laboratory. +=head2 Properties + +The implementations in this provider specifically have these properties +defined: + +=over 4 + +"provider=default" + +"fips=yes" + +=back + +It may be used in a property query string with fetching functions such as +L or L, as well as with other +functions that take a property query string, such as +L. + +It isn't mandatory to query for any of these properties, except to +make sure to get implementations of this provider and none other. + +The "fips=yes" property can be use to make sure only FIPS approved +implementations are used for crypto operations. This may also include +other non-crypto support operations that are not in the fips provider, +such as asymmetric key serializers, +see L. + +=head1 OPERATIONS AND ALGORITHMS + +The OpenSSL FIPS provider supports these operations and algorithms: + +=head2 Hashing Algorithms / Message Digests + +=over 4 + +=item SHA1, see L + +=item SHA2, see L + +=item SHA3, see L + +=item KECCAK-KMAC, see L + +=back + +=head2 Symmetric Ciphers + +=over 4 + +=item AES, see L + +=item DES-EDE3 (TrippleDES), see L + +=back + +=head2 Message Authentication Code (MAC) + +=over 4 + +=item CMAC, see L + +=item GMAC, see L + +=item HMAC, see L + +=item KMAC, see L + +=back + +=head2 Key Derivation Function (KDF) + +=over 4 + +=item HKDF, see L + +=item SSKDF, see L + +=item PBKDF2, see L + +=item TLS1-PRF, see L + +=item KBKDF, see L + +=back + +=head2 Key Exchange + +=over 4 + +=item DH, see L + +=back + +=head2 Asymmetric Signature + +=over 4 + +=item DSA, see L + +=back + +=head2 Asymmetric Cipher + +=over 4 + +=item RSA, see L + +=back + +=head2 Asymmetric Key Management + +=over 4 + +=item DH, see L + +=item DSA, see L + +=item RSA, see L + +=back + =head1 SELF TESTING One of the requirements for the FIPS module is self testing. An optional callback @@ -19,7 +140,7 @@ L. The parameters passed to the callback are described in L -The OPENSSL FIPS module uses the following mechanism to provide information +The OpenSSL FIPS module uses the following mechanism to provide information about the self tests as they run. This is useful for debugging if a self test is failing. The callback also allows forcing any self test to fail, in order to check that @@ -124,12 +245,14 @@ Signature tests used with the "KAT_Signature" type. =item "ECDH" (B) -=item "ECDSA" (B) +=item "DH" (B) Key agreement tests used with the "KAT_KA" type. =item "HKDF" (B) +=item "SSKDF" (B) + Key Derivation Function tests used with the "KAT_KDF" type. =item "CTR" (B) @@ -196,7 +319,9 @@ L, L, L, L, -L +L, +L, +L =head1 HISTORY diff --git a/doc/man7/OSSL_PROVIDER-default.pod b/doc/man7/OSSL_PROVIDER-default.pod new file mode 100644 index 00000000..acfd4d0e --- /dev/null +++ b/doc/man7/OSSL_PROVIDER-default.pod @@ -0,0 +1,226 @@ +=pod + +=head1 NAME + +OSSL_PROVIDER-default - OpenSSL default provider + +=head1 DESCRIPTION + +The OpenSSL default provider supplies the majority of OpenSSL's diverse +algorithm implementations. It also acts as a fallback when no other +provider has been loaded. + +=head2 Properties + +The implementations in this provider specifically have this property +defined: + +=over 4 + +"provider=default" + +=back + +It may be used in a property query string with fetching functions such as +L or L, as well as with other +functions that take a property query string, such as +L. + +It isn't mandatory to query for this property, except to make sure to get +implementations of this provider and none other. + +Some implementations may define additional properties. Exact information is +listed below + +=head1 OPERATIONS AND ALGORITHMS + +The OpenSSL default provider supports these operations and algorithms: + +=head2 Hashing Algorithms / Message Digests + +=over 4 + +=item SHA1, see L + +=item SHA2, see L + +=item SHA3, see L + +=item KECCAK-KMAC, see L + +=item SHAKE, see L + +=item BLAKE2, see L + +=item SM3, see L + +=item MD5, see L + +=item MD5-SHA1, see L + +=back + +=head2 Symmetric Ciphers + +=over 4 + +=item AES, see L + +=item ARIA, see L + +=item CAMELLIA, see L + +=item DES, see L + +=item BF, see L + +=item IDEA, see L + +=item CAST5, see L + +=item SEED, see L + +=item SM4, see L + +=item RC2, see L + +=item RC4, see L + +=item RC5, see L + +=item ChaCha20, see L + +=item ChaCha20-Poly1305, see L + +=back + +=head2 Message Authentication Code (MAC) + +=over 4 + +=item BLAKE2, see L + +=item CMAC, see L + +=item GMAC, see L + +=item HMAC, see L + +=item KMAC, see L + +=item SIPHASH, see L + +=item POLY1305, see L + +=back + +=head2 Key Derivation Function (KDF) + +=over 4 + +=item HKDF, see L + +=item SSKDF, see L + +=item PBKDF2, see L + +=item SSHKDF, see L + +=item TLS1-PRF, see L + +=item KBKDF, see L + +=item X942KDF, see L + +=item SCRYPT, see L + +=item KRB5KDF, see L + +=back + +=head2 Key Exchange + +=over 4 + +=item DH, see L + +=item ECDH, see L + +=item X25519, see L + +=item X448, see L + +=back + +=head2 Asymmetric Signature + +=over 4 + +=item DSA, see L + +=item RSA, see L + +=back + +=head2 Asymmetric Cipher + +=over 4 + +=item RSA, see L + +=back + +=head2 Asymmetric Key Management + +=over 4 + +=item DH, see L + +=item DSA, see L + +=item RSA, see L + +=item EC, see L + +=item X25519, see L + +=item X448, see L + +=back + +=head2 Asymmetric Key Serializer + +In addition to "provider=default", this set of implementations define the +property "fips=yes", to allow them to be used together with the FIPS +provider. + +=over 4 + +=item RSA, see L + +=item DH, see L + +=item DSA, see L + +=item EC, see L + +=item X25519, see L + +=item X448, see L + +=back + +=head1 SEE ALSO + +L, L, L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man7/OSSL_PROVIDER-legacy.pod b/doc/man7/OSSL_PROVIDER-legacy.pod new file mode 100644 index 00000000..27ed3080 --- /dev/null +++ b/doc/man7/OSSL_PROVIDER-legacy.pod @@ -0,0 +1,92 @@ +=pod + +=head1 NAME + +OSSL_PROVIDER-legacy - OpenSSL legacy provider + +=head1 DESCRIPTION + +The OpenSSL legacy provider supplies OpenSSL implementations of algorithms +that have been deemed legacy. Such algorithms have commonly fallen out of +use, have been deemed insecure by the cryptography community, or something +similar. + +We can consider this the retirement home of cryptographic algorithms. + +=head2 Properties + +The implementations in this provider specifically have these property +defined: + +=over 4 + +"provider=legacy" + +=back + +It may be used in a property query string with fetching functions such as +L or L, as well as with other +functions that take a property query string, such as +L. + +It isn't mandatory to query for any of these properties, except to +make sure to get implementations of this provider and none other. + +=head1 OPERATIONS AND ALGORITHMS + +The OpenSSL legacy provider supports these operations and algorithms: + +=head2 Hashing Algorithms / Message Digests + +=over 4 + +=item MD2, see L + +=item MD4, see L + +=item MDC2, see L + +=item WHIRLPOOL, see L + +=item RIPEMD160, see L + +=back + +=begin comment + +When algorithms for other operations start appearing, the +following =head2 titles are appropriate to use: + +- Symmetric Ciphers + +- Message Authentication Code (MAC) + +- Key Derivation Function (KDF) + +- Key Exchange + +- Signature + +- Asymmetric Cipher + +- Asymmetric Key Management + +=end comment + +=head1 SEE ALSO + +L, +L, +L, +L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man7/OSSL_PROVIDER-null.pod b/doc/man7/OSSL_PROVIDER-null.pod new file mode 100644 index 00000000..10ce5844 --- /dev/null +++ b/doc/man7/OSSL_PROVIDER-null.pod @@ -0,0 +1,35 @@ +=pod + +=head1 NAME + +OSSL_PROVIDER-null - OpenSSL null provider + +=head1 DESCRIPTION + +The OpenSSL null provider supplies no algorithms. + +It can used to guarantee that the default library context and a fallback +provider will not be accidentally accessed. + +=head2 Properties + +The null provider defines no properties. + +=head1 OPERATIONS AND ALGORITHMS + +The OpenSSL null provider supports no operations and algorithms. + +=head1 SEE ALSO + +L + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man7/X25519.pod b/doc/man7/X25519.pod index 6af40c6a..0cfe2b53 100644 --- a/doc/man7/X25519.pod +++ b/doc/man7/X25519.pod @@ -10,7 +10,7 @@ X448 The B and B EVP_PKEY implementation supports key generation and key derivation using B and B. It has associated private and public -key formats compatible with draft-ietf-curdle-pkix-03. +key formats compatible with RFC 8410. No additional parameters can be set during key generation. diff --git a/doc/man7/provider-digest.pod b/doc/man7/provider-digest.pod index 576ea581..1cac58b4 100644 --- a/doc/man7/provider-digest.pod +++ b/doc/man7/provider-digest.pod @@ -227,44 +227,6 @@ values associated with the give provider side digest context I and stores them in I. See L for further details on the parameters structure. -Parameters currently recognised by built-in digests are as follows. Not all -parameters are relevant to, or are understood by all digests: - -=over 4 - -=item "xoflen" (B) - -Sets the digest length for extendable output functions. -The length of the "xoflen" parameter should not exceed that of a B. - -=item "ssl3-ms" (B) - -This parameter is set by libssl in order to calculate a signature hash for an -SSLv3 CertificateVerify message as per RFC6101. -It is only set after all handshake messages have already been digested via -OP_digest_update() calls. -The parameter provides the master secret value to be added to the digest. -The digest implementation should calculate the complete digest as per RFC6101 -section 5.6.8. -The next call after setting this parameter will be OP_digest_final(). -This is only relevant for implementations of SHA1 or MD5_SHA1. - -=item "pad_type" (B) - -Sets the pad type to be used. -The only built-in digest that uses this is MDC2. -Normally the final MDC2 block is padded with 0s. -If the pad type is set to 2 then the final block is padded with 0x80 followed by -0s. - -=item "micalg" (B) - -Gets the digest Message Integrity Check algorithm string. -This is used when creating S/MIME multipart/signed messages, as specified in -RFC 5751. - -=back - =head1 RETURN VALUES OP_digest_newctx() and OP_digest_dupctx() should return the newly created @@ -281,7 +243,8 @@ algorithm. =head1 SEE ALSO -L +L, L, L, +L =head1 HISTORY diff --git a/doc/man7/provider-keymgmt.pod b/doc/man7/provider-keymgmt.pod index 0f765f77..52cb977c 100644 --- a/doc/man7/provider-keymgmt.pod +++ b/doc/man7/provider-keymgmt.pod @@ -18,6 +18,15 @@ provider-keymgmt - The KEYMGMT library E-E provider functions void *OP_keymgmt_new(void *provctx); void OP_keymgmt_free(void *keydata); + void *OP_keymgmt_gen_init(void *provctx, int selection); + int OP_keymgmt_gen_set_template(void *genctx, void *template); + int OP_keymgmt_gen_set_params(void *genctx, const OSSL_PARAM params[]); + const OSSL_PARAM *OP_keymgmt_gen_settable_params(void *provctx); + int OP_keymgmt_gen_get_params(void *genctx, const OSSL_PARAM params[]); + const OSSL_PARAM *OP_keymgmt_gen_gettable_params(void *provctx); + void *OP_keymgmt_gen(void *genctx, OSSL_CALLBACK *cb, void *cbarg); + void OP_keymgmt_gen_cleanup(void *genctx); + /* Key object information */ int OP_keymgmt_get_params(void *keydata, OSSL_PARAM params[]); const OSSL_PARAM *OP_keymgmt_gettable_params(void); @@ -80,6 +89,15 @@ macros in L, as follows: OP_keymgmt_new OSSL_FUNC_KEYMGMT_NEW OP_keymgmt_free OSSL_FUNC_KEYMGMT_FREE + OP_keymgmt_gen_init OSSL_FUNC_KEYMGMT_GEN_INIT + OP_keymgmt_gen_set_template OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE + OP_keymgmt_gen_set_params OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS + OP_keymgmt_gen_settable_params OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS + OP_keymgmt_gen_get_params OSSL_FUNC_KEYMGMT_GEN_GET_PARAMS + OP_keymgmt_gen_gettable_params OSSL_FUNC_KEYMGMT_GEN_GETTABLE_PARAMS + OP_keymgmt_gen OSSL_FUNC_KEYMGMT_GEN + OP_keymgmt_gen_cleanup OSSL_FUNC_KEYMGMT_GEN_CLEANUP + OP_keymgmt_get_params OSSL_FUNC_KEYMGMT_GET_PARAMS OP_keymgmt_gettable_params OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS OP_keymgmt_set_params OSSL_FUNC_KEYMGMT_SET_PARAMS @@ -193,12 +211,49 @@ key object, but that is not mandatory. OP_keymgmt_free() should free the passed I. -The constructor and destructor are mandatory, a KEYMGMT implementation -without them will not be accepted. +OP_keymgmt_gen_init(), OP_keymgmt_gen_set_template(), +OP_keymgmt_gen_set_params(), OP_keymgmt_gen_settable_params(), +OP_keymgmt_gen_get_params(), OP_keymgmt_gen_gettable_params(), +OP_keymgmt_gen() and OP_keymgmt_gen_cleanup() work together as a more +elaborate context based key object constructor. -=for comment when new constructors appear, it's sufficient if only one -of them is present. The remark above will have to change to reflect -that. +OP_keymgmt_gen_init() should create the key object generation context +and initialize it with I, which will determine what kind +of contents the key object to be generated should get. + +OP_keymgmt_gen_set_template() should add I