mirror of https://github.com/openssl/openssl.git
Compare commits
59 Commits
55ae352927
...
0d6cb5d069
Author | SHA1 | Date |
---|---|---|
|
0d6cb5d069 | |
|
296f1f6dd8 | |
|
fd7fc90346 | |
|
fcb5e20ac7 | |
|
b9ff440dd6 | |
|
f77fafd16e | |
|
f12f8cc035 | |
|
d0899abb1b | |
|
daa004d484 | |
|
3c4f009959 | |
|
bd1a14bcaf | |
|
8ceae5a622 | |
|
88a1fbb8d1 | |
|
cff8031163 | |
|
758ca8acf0 | |
|
ead653be8b | |
|
dcf009cd89 | |
|
3f633775e4 | |
|
2f41923d2d | |
|
1df3a8a80e | |
|
30740298b6 | |
|
10e26ab122 | |
|
9ccd388664 | |
|
62c4633851 | |
|
707f612416 | |
|
f5fdbb8fff | |
|
6de54753c2 | |
|
133889218e | |
|
2f531a742d | |
|
63e526a4d8 | |
|
1109bc1237 | |
|
e914d23642 | |
|
0afaa27df7 | |
|
deed2379a7 | |
|
09fa39899b | |
|
5e34e6a573 | |
|
082a81404c | |
|
70c05fcde5 | |
|
e08b83cbb3 | |
|
9c09d2076a | |
|
1a1c10f5d7 | |
|
981d6776a3 | |
|
44ef69cffb | |
|
d777deffba | |
|
92330c8f80 | |
|
a43b926fd2 | |
|
b083613476 | |
|
4a3c954a0c | |
|
cdbfacead0 | |
|
49f8db5327 | |
|
1f3af48c31 | |
|
9665baf0f9 | |
|
b1b4b154fd | |
|
c108ead284 | |
|
bd172dd0e1 | |
|
e7d5398aa1 | |
|
d3e781b764 | |
|
b1d75d2df8 | |
|
11348dc644 |
|
@ -1,4 +1,4 @@
|
|||
name: "Build openssl interop container from master"
|
||||
name: "Build openssl interop containers"
|
||||
|
||||
on:
|
||||
schedule:
|
||||
|
@ -24,3 +24,24 @@ jobs:
|
|||
run: |
|
||||
docker push quay.io/openssl-ci/openssl-quic-interop:latest
|
||||
|
||||
update_msquic_quay_container:
|
||||
if: github.repository == 'openssl/openssl'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: microsoft/msquic
|
||||
ref: main
|
||||
submodules: recursive
|
||||
- name: "log in to quay.io"
|
||||
run: |
|
||||
docker login -u openssl-ci+machine -p ${{ secrets.QUAY_IO_PASSWORD }} quay.io
|
||||
- name: Patch qns.Dockerfile
|
||||
run: |
|
||||
sed 's/RUN cmake -DQUIC_BUILD_TOOLS=on -DQUIC_ENABLE_LOGGING=on ../RUN cmake -DQUIC_BUILD_TOOLS=on -DQUIC_ENABLE_LOGGING=on -DQUIC_TLS_LIB=openssl ../' ./scripts/qns.Dockerfile
|
||||
- name: "Build container"
|
||||
run: |
|
||||
docker build -f ./scripts/qns.Dockerfile -t quay.io/openssl-ci/msquic-openssl:latest .
|
||||
- name: "Push to quay"
|
||||
run: |
|
||||
docker push quay.io/openssl-ci/msquic-openssl:latest
|
||||
|
|
|
@ -32,7 +32,7 @@ jobs:
|
|||
no-http,
|
||||
no-legacy,
|
||||
no-sock,
|
||||
no-ssl-trace,
|
||||
no-sm2,
|
||||
no-stdio,
|
||||
no-threads,
|
||||
no-thread-pool,
|
||||
|
|
|
@ -102,13 +102,13 @@ jobs:
|
|||
no-shared,
|
||||
no-siphash,
|
||||
no-siv,
|
||||
no-sm2,
|
||||
no-sm2-precomp,
|
||||
no-sm3,
|
||||
no-sm4,
|
||||
no-sock,
|
||||
no-sse2,
|
||||
no-ssl,
|
||||
no-ssl-trace,
|
||||
enable-ssl3,
|
||||
enable-ssl3-method,
|
||||
enable-sslkeylog,
|
||||
|
|
|
@ -2,7 +2,7 @@ name: "Run openssl quic interop testing"
|
|||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Build openssl interop container from master"]
|
||||
workflows: ["Build openssl interop containers"]
|
||||
types: [completed]
|
||||
workflow_dispatch:
|
||||
|
||||
|
@ -11,10 +11,12 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
tests: [http3, transfer, handshake, retry, chacha20, resumption, multiplexing, ipv6]
|
||||
servers: [quic-go, ngtcp2, mvfst, quiche, nginx, msquic, haproxy]
|
||||
servers: [quic-go, ngtcp2, mvfst, quiche, nginx, msquic, haproxy, msquic-openssl]
|
||||
exclude:
|
||||
- servers: msquic
|
||||
tests: retry
|
||||
- servers: msquic-openssl
|
||||
tests: retry
|
||||
fail-fast: false
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
@ -36,10 +38,15 @@ jobs:
|
|||
for i in {1..3}; do sudo apt-get install -y tshark && break; sleep 10; done
|
||||
- name: Patch implementations file
|
||||
run: |
|
||||
jq '.openssl = { image: "quay.io/openssl-ci/openssl-quic-interop"
|
||||
, url: "https://github.com/openssl/openssl"
|
||||
, role: "both"
|
||||
}' ./implementations.json > ./implementations.tmp
|
||||
jq '. + {
|
||||
"openssl": { image: "quay.io/openssl-ci/openssl-quic-interop"
|
||||
, url: "https://github.com/openssl/openssl"
|
||||
, role: "both"
|
||||
},
|
||||
"msquic-openssl": { image: "quay.io/openssl-ci/msquic-openssl"
|
||||
, url: "https://github.com/microsoft/msquic"
|
||||
, role: "both"
|
||||
}}' ./implementations.json > ./implementations.tmp
|
||||
mv ./implementations.tmp implementations.json
|
||||
- name: "Update to docker-compose 2.36 and docker engine 28.1.1"
|
||||
run: |
|
||||
|
@ -69,7 +76,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
tests: [http3, transfer, handshake, retry, chacha20, resumption, amplificationlimit, ipv6]
|
||||
clients: [quic-go, ngtcp2, mvfst, quiche, msquic, openssl, chrome]
|
||||
clients: [quic-go, ngtcp2, mvfst, quiche, msquic, openssl, chrome, msquic-openssl]
|
||||
exclude:
|
||||
- clients: mvfst
|
||||
tests: amplificationlimit
|
||||
|
@ -94,10 +101,15 @@ jobs:
|
|||
for i in {1..3}; do sudo apt-get install -y tshark && break; done
|
||||
- name: Patch implementations file
|
||||
run: |
|
||||
jq '.openssl = { image: "quay.io/openssl-ci/openssl-quic-interop"
|
||||
, url: "https://github.com/openssl/openssl"
|
||||
, role: "both"
|
||||
}' ./implementations.json > ./implementations.tmp
|
||||
jq '. + {
|
||||
"openssl": { image: "quay.io/openssl-ci/openssl-quic-interop"
|
||||
, url: "https://github.com/openssl/openssl"
|
||||
, role: "both"
|
||||
},
|
||||
"msquic-openssl": { image: "quay.io/openssl-ci/msquic-openssl"
|
||||
, url: "https://github.com/microsoft/msquic"
|
||||
, role: "both"
|
||||
}}' ./implementations.json > ./implementations.tmp
|
||||
mv ./implementations.tmp implementations.json
|
||||
- name: "Update to docker-compose 2.36 and docker engine 28.1.1"
|
||||
run: |
|
||||
|
|
|
@ -75,6 +75,7 @@ providers/common/der/der_rsa_gen.c
|
|||
providers/common/der/der_wrap_gen.c
|
||||
providers/common/der/der_sm2_gen.c
|
||||
providers/common/der/der_ml_dsa_gen.c
|
||||
providers/common/der/der_hkdf_gen.c
|
||||
providers/common/include/prov/der_slh_dsa.h
|
||||
providers/common/include/prov/der_dsa.h
|
||||
providers/common/include/prov/der_ec.h
|
||||
|
@ -84,6 +85,7 @@ providers/common/include/prov/der_digests.h
|
|||
providers/common/include/prov/der_wrap.h
|
||||
providers/common/include/prov/der_sm2.h
|
||||
providers/common/include/prov/der_ml_dsa.h
|
||||
providers/common/include/prov/der_hkdf.h
|
||||
providers/implementations/keymgmt/ml_dsa_kmgmt.c
|
||||
providers/implementations/keymgmt/ml_kem_kmgmt.c
|
||||
providers/implementations/keymgmt/mlx_kmgmt.c
|
||||
|
|
17
CHANGES.md
17
CHANGES.md
|
@ -133,6 +133,23 @@ OpenSSL 3.6
|
|||
|
||||
*Adrian Stanciu*
|
||||
|
||||
* Added support for TLS 1.3 OCSP multi-stapling for server certs.
|
||||
* new `s_client` options:
|
||||
* `-ocsp_check_leaf`: Checks the status of the leaf (server) certificate.
|
||||
* `-ocsp_check_all`: Checks the status of all certificates in the server chain.
|
||||
* new `s_server` option:
|
||||
* `-status_all` Provides OCSP status information for the entire server certificate chain (multi-stapling) for TLS 1.3 and later.
|
||||
|
||||
* Improved `-status_file` option can now be given multiple times to provide
|
||||
multiple files containing OCSP responses.
|
||||
|
||||
*Michael Krueger, Martin Rauch*
|
||||
|
||||
* Added KEMRecipientInfo (RFC 9629) and ML-KEM (draft-ietf-lamps-cms-kyber)
|
||||
support to CMS.
|
||||
|
||||
*Daniel Van Geest (CryptoNext Security)*
|
||||
|
||||
OpenSSL 3.5
|
||||
-----------
|
||||
|
||||
|
|
|
@ -1180,7 +1180,7 @@ generate_buildinfo: generate_doc_buildinfo
|
|||
|
||||
.PHONY: doc-nits md-nits
|
||||
doc-nits: build_generated_pods ## Evaluate OpenSSL documentation
|
||||
$(PERL) $(SRCDIR)/util/find-doc-nits -c -n -l -e -i
|
||||
$(PERL) $(SRCDIR)/util/find-doc-nits -c -n -l -e -i -a
|
||||
|
||||
# This uses "mdl", the markdownlint application, which is written in ruby.
|
||||
# The source is at https://github.com/markdownlint/markdownlint
|
||||
|
|
132
apps/cms.c
132
apps/cms.c
|
@ -53,6 +53,7 @@ static int cms_set_pkey_param(EVP_PKEY_CTX *pctx,
|
|||
static int verify_err = 0;
|
||||
|
||||
typedef struct cms_key_param_st cms_key_param;
|
||||
typedef struct cms_recip_opt_st cms_recip_opt;
|
||||
|
||||
struct cms_key_param_st {
|
||||
int idx;
|
||||
|
@ -60,6 +61,14 @@ struct cms_key_param_st {
|
|||
cms_key_param *next;
|
||||
};
|
||||
|
||||
struct cms_recip_opt_st {
|
||||
int idx;
|
||||
const char *kdf;
|
||||
unsigned char *ukm_data;
|
||||
long ukm_data_length;
|
||||
cms_recip_opt *next;
|
||||
};
|
||||
|
||||
typedef enum OPTION_choice {
|
||||
OPT_COMMON,
|
||||
OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_ENCRYPT,
|
||||
|
@ -85,7 +94,8 @@ typedef enum OPTION_choice {
|
|||
OPT_PROV_ENUM, OPT_CONFIG,
|
||||
OPT_V_ENUM,
|
||||
OPT_CIPHER, OPT_KEKCIPHER,
|
||||
OPT_ORIGINATOR
|
||||
OPT_ORIGINATOR,
|
||||
OPT_RECIP_UKM, OPT_RECIP_KDF
|
||||
} OPTION_CHOICE;
|
||||
|
||||
const OPTIONS cms_options[] = {
|
||||
|
@ -167,13 +177,15 @@ const OPTIONS cms_options[] = {
|
|||
{"kekcipher", OPT_KEKCIPHER, 's',
|
||||
"The key encryption algorithm to use"},
|
||||
{"wrap", OPT_WRAP, 's',
|
||||
"Key wrap algorithm to use when encrypting with key agreement"},
|
||||
"Key wrap algorithm to use when encrypting with key agreement or key encapsulation"},
|
||||
{"aes128-wrap", OPT_AES128_WRAP, '-', "Use AES128 to wrap key"},
|
||||
{"aes192-wrap", OPT_AES192_WRAP, '-', "Use AES192 to wrap key"},
|
||||
{"aes256-wrap", OPT_AES256_WRAP, '-', "Use AES256 to wrap key"},
|
||||
{"des3-wrap", OPT_3DES_WRAP, '-', "Use 3DES-EDE to wrap key"},
|
||||
{"debug_decrypt", OPT_DEBUG_DECRYPT, '-',
|
||||
"Disable MMA protection, return error if no recipient found (see doc)"},
|
||||
{"recip_kdf", OPT_RECIP_KDF, 's', "Set KEMRecipientInfo KDF for current recipient"},
|
||||
{"recip_ukm", OPT_RECIP_UKM, 's', "KEMRecipientInfo user keying material for current recipient, in hex notation"},
|
||||
|
||||
OPT_SECTION("Signing"),
|
||||
{"md", OPT_MD, 's', "Digest algorithm to use"},
|
||||
|
@ -281,6 +293,19 @@ static CMS_ContentInfo *load_content_info(int informat, BIO *in, int flags,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static cms_recip_opt *alloc_recip_opt(int recipidx)
|
||||
{
|
||||
cms_recip_opt *opt;
|
||||
|
||||
opt = app_malloc(sizeof(*opt), "recipient options buffer");
|
||||
opt->idx = recipidx;
|
||||
opt->next = NULL;
|
||||
opt->kdf = NULL;
|
||||
opt->ukm_data = NULL;
|
||||
opt->ukm_data_length = 0;
|
||||
return opt;
|
||||
}
|
||||
|
||||
int cms_main(int argc, char **argv)
|
||||
{
|
||||
CONF *conf = NULL;
|
||||
|
@ -319,6 +344,8 @@ int cms_main(int argc, char **argv)
|
|||
size_t secret_keylen = 0, secret_keyidlen = 0;
|
||||
unsigned char *pwri_pass = NULL, *pwri_tmp = NULL;
|
||||
unsigned char *secret_key = NULL, *secret_keyid = NULL;
|
||||
cms_recip_opt *recip_first = NULL, *recip_opt = NULL;
|
||||
int recipidx = -1;
|
||||
long ltmp;
|
||||
const char *mime_eol = "\n";
|
||||
OPTION_CHOICE o;
|
||||
|
@ -653,6 +680,46 @@ int cms_main(int argc, char **argv)
|
|||
recipfile = opt_arg();
|
||||
}
|
||||
break;
|
||||
case OPT_RECIP_KDF:
|
||||
case OPT_RECIP_UKM:
|
||||
recipidx = -1;
|
||||
if (operation == SMIME_ENCRYPT) {
|
||||
if (sk_X509_num(encerts) > 0)
|
||||
recipidx += sk_X509_num(encerts);
|
||||
}
|
||||
if (recipidx < 0) {
|
||||
BIO_printf(bio_err, "No recipient specified\n");
|
||||
goto opthelp;
|
||||
}
|
||||
if (recip_opt == NULL || recip_opt->idx != recipidx) {
|
||||
cms_recip_opt *nopt;
|
||||
|
||||
nopt = alloc_recip_opt(recipidx);
|
||||
if (recip_first == NULL)
|
||||
recip_first = nopt;
|
||||
else
|
||||
recip_opt->next = nopt;
|
||||
recip_opt = nopt;
|
||||
}
|
||||
if (o == OPT_RECIP_KDF) {
|
||||
if (recip_opt->kdf != NULL) {
|
||||
BIO_puts(bio_err, "Illegal multiple -recip_kdf for one -recip\n");
|
||||
goto end;
|
||||
}
|
||||
recip_opt->kdf = opt_arg();
|
||||
} else {
|
||||
if (recip_opt->ukm_data != NULL) {
|
||||
BIO_puts(bio_err, "Illegal multiple -recip_ukm for one -recip\n");
|
||||
goto end;
|
||||
}
|
||||
recip_opt->ukm_data = OPENSSL_hexstr2buf(opt_arg(),
|
||||
&recip_opt->ukm_data_length);
|
||||
if (recip_opt->ukm_data == NULL) {
|
||||
BIO_printf(bio_err, "Invalid hex value after -recip_ukm\n");
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OPT_CIPHER:
|
||||
ciphername = opt_unknown();
|
||||
break;
|
||||
|
@ -831,6 +898,9 @@ int cms_main(int argc, char **argv)
|
|||
if (operation != SMIME_ENCRYPT && *argv != NULL)
|
||||
BIO_printf(bio_err,
|
||||
"Warning: recipient certificate file parameters ignored for operation other than -encrypt\n");
|
||||
if (operation != SMIME_ENCRYPT && recip_first != NULL)
|
||||
BIO_printf(bio_err,
|
||||
"Warning: -recip_kdf and -recip_ukm parameters ignored for operation other than -encrypt\n");
|
||||
|
||||
if ((flags & CMS_BINARY) != 0) {
|
||||
if (!(operation & SMIME_OP))
|
||||
|
@ -990,7 +1060,9 @@ int cms_main(int argc, char **argv)
|
|||
goto end;
|
||||
for (i = 0; i < sk_X509_num(encerts); i++) {
|
||||
CMS_RecipientInfo *ri;
|
||||
int ri_type;
|
||||
cms_key_param *kparam;
|
||||
cms_recip_opt *ropt;
|
||||
int tflags = flags | CMS_KEY_PARAM;
|
||||
/* This flag enforces allocating the EVP_PKEY_CTX for the recipient here */
|
||||
EVP_PKEY_CTX *pctx;
|
||||
|
@ -998,14 +1070,19 @@ int cms_main(int argc, char **argv)
|
|||
int res;
|
||||
|
||||
for (kparam = key_first; kparam; kparam = kparam->next) {
|
||||
if (kparam->idx == i) {
|
||||
if (kparam->idx == i)
|
||||
break;
|
||||
}
|
||||
for (ropt = recip_first; ropt; ropt = ropt->next) {
|
||||
if (ropt->idx == i)
|
||||
break;
|
||||
}
|
||||
}
|
||||
ri = CMS_add1_recipient(cms, x, key, originator, tflags);
|
||||
if (ri == NULL)
|
||||
goto end;
|
||||
|
||||
ri_type = CMS_RecipientInfo_type(ri);
|
||||
|
||||
pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
|
||||
if (pctx != NULL && kparam != NULL) {
|
||||
if (!cms_set_pkey_param(pctx, kparam->param))
|
||||
|
@ -1018,12 +1095,39 @@ int cms_main(int argc, char **argv)
|
|||
if (res <= 0 && res != -2)
|
||||
goto end;
|
||||
|
||||
if (CMS_RecipientInfo_type(ri) == CMS_RECIPINFO_AGREE
|
||||
&& wrap_cipher != NULL) {
|
||||
EVP_CIPHER_CTX *wctx;
|
||||
wctx = CMS_RecipientInfo_kari_get0_ctx(ri);
|
||||
if (EVP_EncryptInit_ex(wctx, wrap_cipher, NULL, NULL, NULL) != 1)
|
||||
goto end;
|
||||
if (wrap_cipher != NULL) {
|
||||
EVP_CIPHER_CTX *wctx = NULL;
|
||||
|
||||
if (ri_type == CMS_RECIPINFO_AGREE)
|
||||
wctx = CMS_RecipientInfo_kari_get0_ctx(ri);
|
||||
else if (ri_type == CMS_RECIPINFO_KEM)
|
||||
wctx = CMS_RecipientInfo_kemri_get0_ctx(ri);
|
||||
if (wctx != NULL) {
|
||||
if (EVP_EncryptInit_ex(wctx, wrap_cipher, NULL, NULL, NULL) != 1)
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (ropt != NULL && ri_type == CMS_RECIPINFO_KEM) {
|
||||
if (ropt->ukm_data != NULL) {
|
||||
if (!CMS_RecipientInfo_kemri_set_ukm(ri, ropt->ukm_data,
|
||||
(int)ropt->ukm_data_length))
|
||||
goto end;
|
||||
}
|
||||
if (ropt->kdf != NULL) {
|
||||
X509_ALGOR *kdf_algo;
|
||||
ASN1_OBJECT *kdf_obj;
|
||||
|
||||
kdf_algo = CMS_RecipientInfo_kemri_get0_kdf_alg(ri);
|
||||
kdf_obj = OBJ_txt2obj(ropt->kdf, 0);
|
||||
if (kdf_obj == NULL) {
|
||||
BIO_printf(bio_err, "Unknown KDF %s\n", ropt->kdf);
|
||||
goto end;
|
||||
}
|
||||
/* Only works for OIDs without params */
|
||||
if (!X509_ALGOR_set0(kdf_algo, kdf_obj, V_ASN1_UNDEF, NULL))
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1315,6 +1419,14 @@ int cms_main(int argc, char **argv)
|
|||
OPENSSL_free(key_param);
|
||||
key_param = tparam;
|
||||
}
|
||||
for (recip_opt = recip_first; recip_opt != NULL;) {
|
||||
cms_recip_opt *topt;
|
||||
|
||||
OPENSSL_free(recip_opt->ukm_data);
|
||||
topt = recip_opt->next;
|
||||
OPENSSL_free(recip_opt);
|
||||
recip_opt = topt;
|
||||
}
|
||||
X509_STORE_free(store);
|
||||
X509_free(cert);
|
||||
X509_free(recip);
|
||||
|
|
|
@ -3047,15 +3047,11 @@ BIO *dup_bio_out(int format)
|
|||
{
|
||||
BIO *b = BIO_new_fp(stdout,
|
||||
BIO_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0));
|
||||
void *prefix = NULL;
|
||||
BIO *btmp;
|
||||
|
||||
if (b == NULL)
|
||||
return NULL;
|
||||
|
||||
#ifdef OPENSSL_SYS_VMS
|
||||
if (FMT_istext(format)) {
|
||||
btmp = BIO_new(BIO_f_linebuffer());
|
||||
if (b != NULL && FMT_istext(format)) {
|
||||
BIO *btmp = BIO_new(BIO_f_linebuffer());
|
||||
|
||||
if (btmp == NULL) {
|
||||
BIO_free(b);
|
||||
return NULL;
|
||||
|
@ -3064,17 +3060,6 @@ BIO *dup_bio_out(int format)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (FMT_istext(format)
|
||||
&& (prefix = getenv("HARNESS_OSSL_PREFIX")) != NULL) {
|
||||
btmp = BIO_new(BIO_f_prefix());
|
||||
if (btmp == NULL) {
|
||||
BIO_free_all(b);
|
||||
return NULL;
|
||||
}
|
||||
b = BIO_push(btmp, b);
|
||||
BIO_set_prefix(b, prefix);
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
|
|
|
@ -106,6 +106,10 @@ int verify_callback(int ok, X509_STORE_CTX *ctx)
|
|||
if (!verify_args.quiet)
|
||||
policies_print(ctx);
|
||||
break;
|
||||
case X509_V_ERR_OCSP_NO_RESPONSE:
|
||||
if (!verify_args.quiet)
|
||||
BIO_printf(bio_err, "no OCSP response(s) for certificate(s) found.\n");
|
||||
break;
|
||||
}
|
||||
if (err == X509_V_OK && ok == 2 && !verify_args.quiet)
|
||||
policies_print(ctx);
|
||||
|
|
|
@ -93,7 +93,6 @@ EOF
|
|||
|
||||
my %cmd_disabler = (
|
||||
ciphers => "sock",
|
||||
genrsa => "rsa",
|
||||
gendsa => "dsa",
|
||||
dsaparam => "dsa",
|
||||
gendh => "dh",
|
||||
|
@ -107,7 +106,7 @@ EOF
|
|||
# [2] = preprocessor conditional for excluding irrespective of deprecation
|
||||
# rsa => [ "pkey", "3_0", "rsa" ],
|
||||
# genrsa => [ "genpkey", "3_0", "rsa" ],
|
||||
rsautl => [ "pkeyutl", "3_0", "rsa" ],
|
||||
rsautl => [ "pkeyutl", "3_0", "" ],
|
||||
# dhparam => [ "pkeyparam", "3_0", "dh" ],
|
||||
# dsaparam => [ "pkeyparam", "3_0", "dsa" ],
|
||||
# dsa => [ "pkey", "3_0", "dsa" ],
|
||||
|
|
|
@ -199,7 +199,7 @@ int rand_main(int argc, char **argv)
|
|||
int chunk;
|
||||
|
||||
chunk = scaled_num > buflen ? (int)buflen : (int)scaled_num;
|
||||
r = RAND_bytes(buf, chunk);
|
||||
r = RAND_bytes_ex(app_get0_libctx(), buf, chunk, 0);
|
||||
if (r <= 0)
|
||||
goto end;
|
||||
if (format != FORMAT_TEXT) {
|
||||
|
|
105
apps/s_client.c
105
apps/s_client.c
|
@ -110,9 +110,10 @@ static char *sess_out = NULL;
|
|||
static SSL_SESSION *psksess = NULL;
|
||||
|
||||
static void print_stuff(BIO *berr, SSL *con, int full);
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
static int ocsp_resp_cb(SSL *s, void *arg);
|
||||
#endif
|
||||
static void print_ocsp_response(BIO *bp, OCSP_RESPONSE *rsp);
|
||||
# endif
|
||||
static int ldap_ExtendedResponse_parse(const char *buf, long rem);
|
||||
static int is_dNS_name(const char *host);
|
||||
|
||||
|
@ -483,7 +484,10 @@ typedef enum OPTION_choice {
|
|||
OPT_CERTFORM, OPT_CRLFORM, OPT_VERIFY_RET_ERROR, OPT_VERIFY_QUIET,
|
||||
OPT_BRIEF, OPT_PREXIT, OPT_NO_INTERACTIVE, OPT_CRLF, OPT_QUIET, OPT_NBIO,
|
||||
OPT_SSL_CLIENT_ENGINE, OPT_IGN_EOF, OPT_NO_IGN_EOF,
|
||||
OPT_DEBUG, OPT_TLSEXTDEBUG, OPT_STATUS, OPT_WDEBUG,
|
||||
OPT_DEBUG, OPT_TLSEXTDEBUG, OPT_WDEBUG,
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
OPT_STATUS, OPT_STATUS_OCSP_CHECK_LEAF, OPT_STATUS_OCSP_CHECK_ALL,
|
||||
# endif
|
||||
OPT_MSG, OPT_MSGFILE, OPT_ENGINE, OPT_TRACE, OPT_SECURITY_DEBUG,
|
||||
OPT_SECURITY_DEBUG_VERBOSE, OPT_SHOWCERTS, OPT_NBIO_TEST, OPT_STATE,
|
||||
OPT_PSK_IDENTITY, OPT_PSK, OPT_PSK_SESS,
|
||||
|
@ -625,6 +629,17 @@ const OPTIONS s_client_options[] = {
|
|||
{"no-interactive", OPT_NO_INTERACTIVE, '-',
|
||||
"Don't run the client in the interactive mode"},
|
||||
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
OPT_SECTION("OCSP stapling"),
|
||||
{"status", OPT_STATUS, '-',
|
||||
"Sends a certificate status request to the server (OCSP stapling) " \
|
||||
"The server response (if any) will be printed out."},
|
||||
{"ocsp_check_leaf", OPT_STATUS_OCSP_CHECK_LEAF, '-',
|
||||
"Require checking leaf certificate status, attempting to use OCSP stapling first"},
|
||||
{"ocsp_check_all", OPT_STATUS_OCSP_CHECK_ALL, '-',
|
||||
"Require checking status of full chain, attempting to use OCSP stapling first"},
|
||||
# endif
|
||||
|
||||
OPT_SECTION("Debug"),
|
||||
{"showcerts", OPT_SHOWCERTS, '-',
|
||||
"Show all certificates sent by the server"},
|
||||
|
@ -659,9 +674,6 @@ const OPTIONS s_client_options[] = {
|
|||
"Hex dump of all TLS extensions received"},
|
||||
{"ignore_unexpected_eof", OPT_IGNORE_UNEXPECTED_EOF, '-',
|
||||
"Do not treat lack of close_notify from a peer as an error"},
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
{"status", OPT_STATUS, '-', "Request certificate status from server"},
|
||||
#endif
|
||||
{"serverinfo", OPT_SERVERINFO, 's',
|
||||
"types Send empty ClientHello extensions (comma-separated numbers)"},
|
||||
{"alpn", OPT_ALPN, 's',
|
||||
|
@ -1195,11 +1207,23 @@ int s_client_main(int argc, char **argv)
|
|||
case OPT_TLSEXTDEBUG:
|
||||
c_tlsextdebug = 1;
|
||||
break;
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
case OPT_STATUS:
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
c_status_req = 1;
|
||||
#endif
|
||||
break;
|
||||
case OPT_STATUS_OCSP_CHECK_LEAF:
|
||||
c_status_req = 1;
|
||||
X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_OCSP_RESP_CHECK);
|
||||
vpmtouched++;
|
||||
break;
|
||||
case OPT_STATUS_OCSP_CHECK_ALL:
|
||||
c_status_req = 1;
|
||||
X509_VERIFY_PARAM_set_flags(vpm,
|
||||
X509_V_FLAG_OCSP_RESP_CHECK |
|
||||
X509_V_FLAG_OCSP_RESP_CHECK_ALL);
|
||||
vpmtouched++;
|
||||
break;
|
||||
# endif
|
||||
case OPT_WDEBUG:
|
||||
#ifdef WATT32
|
||||
dbug_init();
|
||||
|
@ -3626,27 +3650,58 @@ static void print_stuff(BIO *bio, SSL *s, int full)
|
|||
# ifndef OPENSSL_NO_OCSP
|
||||
static int ocsp_resp_cb(SSL *s, void *arg)
|
||||
{
|
||||
const unsigned char *p;
|
||||
int len;
|
||||
int num, i;
|
||||
STACK_OF(OCSP_RESPONSE) *sk_resp = NULL;
|
||||
OCSP_RESPONSE *rsp;
|
||||
len = SSL_get_tlsext_status_ocsp_resp(s, &p);
|
||||
BIO_puts(arg, "OCSP response: ");
|
||||
if (p == NULL) {
|
||||
BIO_puts(arg, "no response sent\n");
|
||||
return 1;
|
||||
|
||||
if (SSL_version(s) >= TLS1_3_VERSION) {
|
||||
(void)SSL_get0_tlsext_status_ocsp_resp_ex(s, &sk_resp);
|
||||
|
||||
BIO_puts(arg, "OCSP responses: ");
|
||||
|
||||
if (sk_resp == NULL) {
|
||||
BIO_puts(arg, "no responses sent\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
num = sk_OCSP_RESPONSE_num(sk_resp);
|
||||
|
||||
BIO_printf(arg, "number of responses: %d", num);
|
||||
for (i = 0; i < num; i++)
|
||||
print_ocsp_response(arg, sk_OCSP_RESPONSE_value(sk_resp, i));
|
||||
} else {
|
||||
const unsigned char *p;
|
||||
int len = SSL_get_tlsext_status_ocsp_resp(s, &p);
|
||||
|
||||
BIO_puts(arg, "OCSP response: ");
|
||||
if (p == NULL) {
|
||||
BIO_puts(arg, "no OCSP response received\n");
|
||||
return 1;
|
||||
}
|
||||
rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
|
||||
if (rsp == NULL) {
|
||||
BIO_puts(arg, "OCSP response parse error\n");
|
||||
BIO_dump_indent(arg, (char *)p, len, 4);
|
||||
return 0;
|
||||
}
|
||||
print_ocsp_response(arg, rsp);
|
||||
OCSP_RESPONSE_free(rsp);
|
||||
}
|
||||
rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
|
||||
if (rsp == NULL) {
|
||||
BIO_puts(arg, "response parse error\n");
|
||||
BIO_dump_indent(arg, (char *)p, len, 4);
|
||||
return 0;
|
||||
}
|
||||
BIO_puts(arg, "\n======================================\n");
|
||||
OCSP_RESPONSE_print(arg, rsp, 0);
|
||||
BIO_puts(arg, "======================================\n");
|
||||
OCSP_RESPONSE_free(rsp);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void print_ocsp_response(BIO *bp, OCSP_RESPONSE *rsp)
|
||||
{
|
||||
if (rsp == NULL) {
|
||||
BIO_puts(bp, "no OCSP response to print\n");
|
||||
return;
|
||||
}
|
||||
|
||||
BIO_puts(bp, "\n======================================\n");
|
||||
OCSP_RESPONSE_print(bp, rsp, 0);
|
||||
BIO_puts(bp, "\n======================================\n");
|
||||
}
|
||||
# endif
|
||||
|
||||
static int ldap_ExtendedResponse_parse(const char *buf, long rem)
|
||||
|
|
348
apps/s_server.c
348
apps/s_server.c
|
@ -54,9 +54,10 @@ typedef unsigned int u_int;
|
|||
#include "s_apps.h"
|
||||
#include "timeouts.h"
|
||||
#ifdef CHARSET_EBCDIC
|
||||
#include <openssl/ebcdic.h>
|
||||
# include <openssl/ebcdic.h>
|
||||
#endif
|
||||
#include "internal/sockets.h"
|
||||
#include "internal/statem.h"
|
||||
|
||||
static int not_resumable_sess_cb(SSL *s, int is_forward_secure);
|
||||
static int sv_body(int s, int stype, int prot, unsigned char *context);
|
||||
|
@ -454,16 +455,20 @@ static int ssl_servername_cb(SSL *s, int *ad, void *arg)
|
|||
/* Structure passed to cert status callback */
|
||||
typedef struct tlsextstatusctx_st {
|
||||
int timeout;
|
||||
/* File to load OCSP Response from (or NULL if no file) */
|
||||
char *respin;
|
||||
/*
|
||||
* List of filenames, from which we are loading each OCSP Response to
|
||||
* staple during handshake (or NULL if no file)
|
||||
*/
|
||||
STACK_OF(OPENSSL_STRING) *sk_resp_in;
|
||||
/* Default responder to use */
|
||||
char *host, *path, *port;
|
||||
char *proxy, *no_proxy;
|
||||
int use_ssl;
|
||||
int verbose;
|
||||
int status_all;
|
||||
} tlsextstatusctx;
|
||||
|
||||
static tlsextstatusctx tlscstatp = { -1 };
|
||||
static tlsextstatusctx tlscstatp = { -1, NULL };
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
|
||||
|
@ -474,14 +479,15 @@ static tlsextstatusctx tlscstatp = { -1 };
|
|||
* the OCSP certificate IDs and minimise the number of OCSP responses by caching
|
||||
* them until they were considered "expired".
|
||||
*/
|
||||
static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
|
||||
OCSP_RESPONSE **resp)
|
||||
static int get_ocsp_resp_from_responder_single(SSL *s, X509 *x,
|
||||
tlsextstatusctx *srctx,
|
||||
OCSP_RESPONSE **resp)
|
||||
{
|
||||
char *host = NULL, *port = NULL, *path = NULL;
|
||||
char *proxy = NULL, *no_proxy = NULL;
|
||||
int use_ssl;
|
||||
STACK_OF(OPENSSL_STRING) *aia = NULL;
|
||||
X509 *x = NULL, *cert;
|
||||
X509 *cert;
|
||||
X509_NAME *iname;
|
||||
STACK_OF(X509) *chain = NULL;
|
||||
SSL_CTX *ssl_ctx;
|
||||
|
@ -494,7 +500,6 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
|
|||
int i;
|
||||
|
||||
/* Build up OCSP query from server certificate */
|
||||
x = SSL_get_certificate(s);
|
||||
iname = X509_get_issuer_name(x);
|
||||
aia = X509_get1_ocsp(x);
|
||||
if (aia != NULL) {
|
||||
|
@ -559,6 +564,7 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
|
|||
SSL_get_tlsext_status_exts(s, &exts);
|
||||
for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
|
||||
X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
|
||||
|
||||
if (!OCSP_REQUEST_add_ext(req, ext, -1))
|
||||
goto err;
|
||||
}
|
||||
|
@ -591,6 +597,214 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int bring_ocsp_resp_in_correct_order(SSL *s, tlsextstatusctx *srctx,
|
||||
STACK_OF(OCSP_RESPONSE) *sk_resp_unordered,
|
||||
STACK_OF(OCSP_RESPONSE) **sk_resp)
|
||||
{
|
||||
STACK_OF(X509) *server_certs = NULL;
|
||||
X509 *ssl_cert = NULL;
|
||||
X509 *issuer = NULL;
|
||||
OCSP_RESPONSE *resp = NULL;
|
||||
OCSP_BASICRESP *bs = NULL;
|
||||
OCSP_CERTID *cert_id = NULL;
|
||||
int found = -1;
|
||||
int i, j, num = 1;
|
||||
|
||||
if (*sk_resp != NULL)
|
||||
sk_OCSP_RESPONSE_pop_free(*sk_resp, OCSP_RESPONSE_free);
|
||||
|
||||
SSL_get0_chain_certs(s, &server_certs);
|
||||
/*
|
||||
* TODO(DTLS-1.3): in future DTLS should also be considered
|
||||
*/
|
||||
if (server_certs != NULL && srctx->status_all &&
|
||||
!SSL_is_dtls(s) && SSL_version(s) >= TLS1_3_VERSION) {
|
||||
/* certificate chain is available */
|
||||
num = sk_X509_num(server_certs) + 1;
|
||||
}
|
||||
|
||||
/* get OCSP response for server certificate first */
|
||||
ssl_cert = SSL_get_certificate(s);
|
||||
|
||||
/*
|
||||
* OpenSSL servers with TLS < 1.3 can be configured with no certificate
|
||||
*/
|
||||
if (ssl_cert == NULL)
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
|
||||
/* reserve enough space so the pushes to the stack would not fail */
|
||||
*sk_resp = sk_OCSP_RESPONSE_new_reserve(NULL, num);
|
||||
|
||||
if (*sk_resp == NULL)
|
||||
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
if (i != 0) /* for each certificate in chain (except root) get the OCSP response */
|
||||
ssl_cert = sk_X509_value(server_certs, i - 1);
|
||||
|
||||
/* issuer certificate is next in chain */
|
||||
issuer = sk_X509_value(server_certs, i);
|
||||
|
||||
if (issuer == NULL
|
||||
|| (cert_id = OCSP_cert_to_id(NULL, ssl_cert, issuer)) == NULL) {
|
||||
sk_OCSP_RESPONSE_push(*sk_resp, NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* find the correct OCSP response for the requested certificate */
|
||||
found = -1;
|
||||
for (j = 0; j < sk_OCSP_RESPONSE_num(sk_resp_unordered); j++) {
|
||||
if ((resp = sk_OCSP_RESPONSE_value(sk_resp_unordered, j)) == NULL)
|
||||
continue;
|
||||
if ((bs = OCSP_response_get1_basic(resp)) == NULL)
|
||||
continue;
|
||||
found = OCSP_resp_find(bs, cert_id, -1);
|
||||
OCSP_BASICRESP_free(bs);
|
||||
if (found > -1) {
|
||||
/* remove the found OCSP response to prevent freeing it with the remaining list */
|
||||
sk_OCSP_RESPONSE_delete(sk_resp_unordered, j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found < 0)
|
||||
resp = NULL;
|
||||
|
||||
OCSP_CERTID_free(cert_id);
|
||||
|
||||
/* add response to stack; also insert null response */
|
||||
(void)sk_OCSP_RESPONSE_push(*sk_resp, resp);
|
||||
}
|
||||
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to get a list OCSP_RESPONSE from the files specified using
|
||||
* -status_file options for the server certificate and the chain certificates,
|
||||
* in the same order as the list of certs returned by SSL_get0_chain_certs().
|
||||
* In case of a missing entry, the respective list element will be NULL.
|
||||
*/
|
||||
static int get_ocsp_resp_from_files(SSL *s, tlsextstatusctx *srctx,
|
||||
STACK_OF(OCSP_RESPONSE) **sk_resp)
|
||||
{
|
||||
STACK_OF(OCSP_RESPONSE) *sk_resp_unordered = NULL;
|
||||
char *respfile = NULL;
|
||||
OCSP_RESPONSE *resp = NULL;
|
||||
BIO *derbio;
|
||||
int i;
|
||||
int num = sk_OPENSSL_STRING_num(srctx->sk_resp_in);
|
||||
int ret = SSL_TLSEXT_ERR_OK;
|
||||
|
||||
sk_resp_unordered = sk_OCSP_RESPONSE_new_reserve(NULL, num);
|
||||
|
||||
if (sk_resp_unordered == NULL) {
|
||||
BIO_puts(bio_err, "cert_status: Cannot reserve memory for OCSP responses\n");
|
||||
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||
}
|
||||
|
||||
/* reading as many responses as files given */
|
||||
for (i = 0; i < num; i++) {
|
||||
respfile = sk_OPENSSL_STRING_value(srctx->sk_resp_in, i);
|
||||
|
||||
derbio = bio_open_default(respfile, 'r', FORMAT_ASN1);
|
||||
|
||||
if (derbio == NULL) {
|
||||
BIO_printf(bio_err, "cert_status: Cannot open OCSP response file %s\n", respfile);
|
||||
ret = SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
|
||||
BIO_free(derbio);
|
||||
if (resp == NULL) {
|
||||
BIO_printf(bio_err, "cert_status: Error reading OCSP response from file %s\n",
|
||||
respfile);
|
||||
ret = SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
sk_OCSP_RESPONSE_push(sk_resp_unordered, resp);
|
||||
}
|
||||
|
||||
ret = bring_ocsp_resp_in_correct_order(s, srctx, sk_resp_unordered, sk_resp);
|
||||
|
||||
err:
|
||||
/* free the unordered list, including all remaining OCSP responses */
|
||||
sk_OCSP_RESPONSE_pop_free(sk_resp_unordered, OCSP_RESPONSE_free);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to get a list of OCSP_RESPONSE from a responder
|
||||
* for the server certificate and the chain certificates
|
||||
* in the same order as the list of certs returned by SSL_get0_chain_certs().
|
||||
* The function get_ocsp_resp_from_responder_single is called for each
|
||||
* certificate.
|
||||
* In case of a missing response, the respective list element will be NULL.
|
||||
* This is a simplified version. It examines certificates each time and
|
||||
* makes one OCSP responder query for each request. A full version would
|
||||
* store details such as the OCSP certificate IDs and minimise the number of
|
||||
* OCSP queries by caching responses until they were considered "expired".
|
||||
*/
|
||||
static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
|
||||
STACK_OF(OCSP_RESPONSE) **sk_resp)
|
||||
{
|
||||
X509 *ssl_cert = NULL;
|
||||
int i, num = 0;
|
||||
STACK_OF(X509) *server_certs = NULL;
|
||||
OCSP_RESPONSE *resp = NULL;
|
||||
|
||||
if (*sk_resp != NULL) {
|
||||
sk_OCSP_RESPONSE_pop_free(*sk_resp, OCSP_RESPONSE_free);
|
||||
*sk_resp = NULL;
|
||||
}
|
||||
|
||||
SSL_get0_chain_certs(s, &server_certs);
|
||||
/*
|
||||
* TODO(DTLS-1.3): in future DTLS should also be considered
|
||||
*/
|
||||
if (server_certs != NULL && srctx->status_all &&
|
||||
!SSL_is_dtls(s) && SSL_version(s) >= TLS1_3_VERSION) {
|
||||
/* certificate chain is available */
|
||||
num = sk_X509_num(server_certs) + 1;
|
||||
} else {
|
||||
/*
|
||||
* certificate chain is not available,
|
||||
* set num to 1 for server certificate
|
||||
*/
|
||||
num = 1;
|
||||
}
|
||||
|
||||
ssl_cert = SSL_get_certificate(s);
|
||||
|
||||
/*
|
||||
* OpenSSL servers with TLS < 1.3 can be configured with no certificate
|
||||
*/
|
||||
if (ssl_cert == NULL)
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
|
||||
*sk_resp = sk_OCSP_RESPONSE_new_reserve(NULL, num);
|
||||
|
||||
if (*sk_resp == NULL)
|
||||
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||
|
||||
/* for each certificate in chain (except root) get the OCSP response */
|
||||
for (i = 0; i < num; i++) {
|
||||
if (i != 0) /* get OCSP response for server certificate first */
|
||||
ssl_cert = sk_X509_value(server_certs, i - 1);
|
||||
|
||||
resp = NULL;
|
||||
if (get_ocsp_resp_from_responder_single(s, ssl_cert, srctx, &resp) != SSL_TLSEXT_ERR_OK)
|
||||
resp = NULL;
|
||||
|
||||
/* add response to stack; also insert null response */
|
||||
sk_OCSP_RESPONSE_push(*sk_resp, resp);
|
||||
}
|
||||
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Certificate Status callback. This is called when a client includes a
|
||||
* certificate status request extension. The response is either obtained from a
|
||||
|
@ -600,48 +814,48 @@ static int cert_status_cb(SSL *s, void *arg)
|
|||
{
|
||||
tlsextstatusctx *srctx = arg;
|
||||
OCSP_RESPONSE *resp = NULL;
|
||||
unsigned char *rspder = NULL;
|
||||
int rspderlen;
|
||||
STACK_OF(OCSP_RESPONSE) *sk_resp = NULL;
|
||||
int ret = SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||
int i;
|
||||
|
||||
if (srctx->verbose)
|
||||
BIO_puts(bio_err, "cert_status: callback called\n");
|
||||
|
||||
if (srctx->respin != NULL) {
|
||||
BIO *derbio = bio_open_default(srctx->respin, 'r', FORMAT_ASN1);
|
||||
if (derbio == NULL) {
|
||||
BIO_puts(bio_err, "cert_status: Cannot open OCSP response file\n");
|
||||
goto err;
|
||||
SSL_get0_tlsext_status_ocsp_resp_ex(s, &sk_resp);
|
||||
|
||||
if (sk_resp == NULL || sk_OCSP_RESPONSE_num(sk_resp) <= 0) {
|
||||
if (srctx->sk_resp_in != NULL) {
|
||||
get_ocsp_resp_from_files(s, srctx, &sk_resp);
|
||||
} else {
|
||||
ret = get_ocsp_resp_from_responder(s, srctx, &sk_resp);
|
||||
if (ret != SSL_TLSEXT_ERR_OK)
|
||||
goto err;
|
||||
}
|
||||
resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
|
||||
BIO_free(derbio);
|
||||
if (resp == NULL) {
|
||||
BIO_puts(bio_err, "cert_status: Error reading OCSP response\n");
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
ret = get_ocsp_resp_from_responder(s, srctx, &resp);
|
||||
if (ret != SSL_TLSEXT_ERR_OK)
|
||||
goto err;
|
||||
|
||||
(void)SSL_set0_tlsext_status_ocsp_resp_ex(s, sk_resp);
|
||||
}
|
||||
|
||||
rspderlen = i2d_OCSP_RESPONSE(resp, &rspder);
|
||||
if (rspderlen <= 0)
|
||||
goto err;
|
||||
|
||||
SSL_set_tlsext_status_ocsp_resp(s, rspder, rspderlen);
|
||||
if (srctx->verbose) {
|
||||
BIO_puts(bio_err, "cert_status: ocsp response sent:\n");
|
||||
OCSP_RESPONSE_print(bio_err, resp, 2);
|
||||
BIO_printf(bio_err, "cert_status: number of responses: %d\n",
|
||||
sk_OCSP_RESPONSE_num(sk_resp));
|
||||
for (i = 0; i < sk_OCSP_RESPONSE_num(sk_resp); i++) {
|
||||
resp = sk_OCSP_RESPONSE_value(sk_resp, i);
|
||||
if (resp != NULL)
|
||||
OCSP_RESPONSE_print(bio_err, resp, 2);
|
||||
else
|
||||
BIO_printf(bio_err,
|
||||
"cert_status: no ocsp response for certificate with index %d\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
ret = SSL_TLSEXT_ERR_OK;
|
||||
|
||||
err:
|
||||
if (ret != SSL_TLSEXT_ERR_OK)
|
||||
if (ret != SSL_TLSEXT_ERR_OK) {
|
||||
ERR_print_errors(bio_err);
|
||||
|
||||
OCSP_RESPONSE_free(resp);
|
||||
sk_OCSP_RESPONSE_pop_free(sk_resp, OCSP_RESPONSE_free);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -680,6 +894,7 @@ static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen,
|
|||
if (!s_quiet) {
|
||||
/* We can assume that |in| is syntactically valid. */
|
||||
unsigned int i;
|
||||
|
||||
BIO_printf(bio_s_out, "ALPN protocols advertised by the client: ");
|
||||
for (i = 0; i < inlen;) {
|
||||
if (i)
|
||||
|
@ -692,9 +907,8 @@ 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,
|
||||
(unsigned int)alpn_ctx->len, in, inlen) != OPENSSL_NPN_NEGOTIATED) {
|
||||
(unsigned int)alpn_ctx->len, in, inlen) != OPENSSL_NPN_NEGOTIATED)
|
||||
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||
}
|
||||
|
||||
if (!s_quiet) {
|
||||
BIO_printf(bio_s_out, "ALPN protocols selected: ");
|
||||
|
@ -725,9 +939,9 @@ typedef enum OPTION_choice {
|
|||
OPT_VERIFYCAFILE,
|
||||
OPT_CASTORE, OPT_NOCASTORE, OPT_CHAINCASTORE, OPT_VERIFYCASTORE,
|
||||
OPT_NBIO, OPT_NBIO_TEST, OPT_IGN_EOF, OPT_NO_IGN_EOF,
|
||||
OPT_DEBUG, OPT_TLSEXTDEBUG, OPT_STATUS, OPT_STATUS_VERBOSE,
|
||||
OPT_STATUS_TIMEOUT, OPT_PROXY, OPT_NO_PROXY, OPT_STATUS_URL,
|
||||
OPT_STATUS_FILE, OPT_MSG, OPT_MSGFILE,
|
||||
OPT_DEBUG, OPT_TLSEXTDEBUG, OPT_STATUS, OPT_STATUS_ALL,
|
||||
OPT_STATUS_VERBOSE, OPT_STATUS_TIMEOUT, OPT_PROXY, OPT_NO_PROXY,
|
||||
OPT_STATUS_URL, OPT_STATUS_FILE, OPT_MSG, OPT_MSGFILE,
|
||||
OPT_TRACE, OPT_SECURITY_DEBUG, OPT_SECURITY_DEBUG_VERBOSE, OPT_STATE,
|
||||
OPT_CRLF, OPT_QUIET, OPT_BRIEF, OPT_NO_DHE,
|
||||
OPT_NO_RESUME_EPHEMERAL, OPT_PSK_IDENTITY, OPT_PSK_HINT, OPT_PSK,
|
||||
|
@ -876,9 +1090,12 @@ const OPTIONS s_server_options[] = {
|
|||
{"cert_comp", OPT_CERT_COMP, '-', "Pre-compress server certificates"},
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
OPT_SECTION("OCSP"),
|
||||
{"status", OPT_STATUS, '-', "Request certificate status from server"},
|
||||
{"status", OPT_STATUS, '-',
|
||||
"Provide certificate status response if requested, for server cert only"},
|
||||
{"status_all", OPT_STATUS_ALL, '-',
|
||||
"Provide certificate status response(s) if requested, for the whole chain"},
|
||||
{"status_verbose", OPT_STATUS_VERBOSE, '-',
|
||||
"Print more output in certificate status callback"},
|
||||
{"status_timeout", OPT_STATUS_TIMEOUT, 'n',
|
||||
|
@ -891,8 +1108,8 @@ const OPTIONS s_server_options[] = {
|
|||
{OPT_MORE_STR, 0, 0,
|
||||
"Default from environment variable 'no_proxy', else 'NO_PROXY', else none"},
|
||||
{"status_file", OPT_STATUS_FILE, '<',
|
||||
"File containing DER encoded OCSP Response"},
|
||||
#endif
|
||||
"File containing DER encoded OCSP Response (can be specified multiple times)"},
|
||||
# endif
|
||||
|
||||
OPT_SECTION("Debug"),
|
||||
{"security_debug", OPT_SECURITY_DEBUG, '-',
|
||||
|
@ -1076,9 +1293,9 @@ int s_server_main(int argc, char *argv[])
|
|||
const char *s_cert_file = TEST_CERT, *s_key_file = NULL, *s_chain_file = NULL;
|
||||
const char *s_cert_file2 = TEST_CERT2, *s_key_file2 = NULL;
|
||||
char *s_dcert_file = NULL, *s_dkey_file = NULL, *s_dchain_file = NULL;
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
int s_tlsextstatus = 0;
|
||||
#endif
|
||||
# endif
|
||||
int no_resume_ephemeral = 0;
|
||||
unsigned int max_send_fragment = 0;
|
||||
unsigned int split_send_fragment = 0, max_pipelines = 0;
|
||||
|
@ -1390,33 +1607,40 @@ int s_server_main(int argc, char *argv[])
|
|||
s_tlsextdebug = 1;
|
||||
break;
|
||||
case OPT_STATUS:
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
s_tlsextstatus = 1;
|
||||
#endif
|
||||
tlscstatp.status_all = 0;
|
||||
# endif
|
||||
break;
|
||||
case OPT_STATUS_ALL:
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
s_tlsextstatus = tlscstatp.status_all = 1;
|
||||
# endif
|
||||
break;
|
||||
|
||||
case OPT_STATUS_VERBOSE:
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
s_tlsextstatus = tlscstatp.verbose = 1;
|
||||
#endif
|
||||
# endif
|
||||
break;
|
||||
case OPT_STATUS_TIMEOUT:
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
s_tlsextstatus = 1;
|
||||
tlscstatp.timeout = atoi(opt_arg());
|
||||
#endif
|
||||
# endif
|
||||
break;
|
||||
case OPT_PROXY:
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
tlscstatp.proxy = opt_arg();
|
||||
#endif
|
||||
# endif
|
||||
break;
|
||||
case OPT_NO_PROXY:
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
tlscstatp.no_proxy = opt_arg();
|
||||
#endif
|
||||
# endif
|
||||
break;
|
||||
case OPT_STATUS_URL:
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
s_tlsextstatus = 1;
|
||||
if (!OSSL_HTTP_parse_url(opt_arg(), &tlscstatp.use_ssl, NULL,
|
||||
&tlscstatp.host, &tlscstatp.port, NULL,
|
||||
|
@ -1424,13 +1648,16 @@ int s_server_main(int argc, char *argv[])
|
|||
BIO_printf(bio_err, "Error parsing -status_url argument\n");
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
# endif
|
||||
break;
|
||||
case OPT_STATUS_FILE:
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
s_tlsextstatus = 1;
|
||||
tlscstatp.respin = opt_arg();
|
||||
#endif
|
||||
if (tlscstatp.sk_resp_in == NULL
|
||||
&& (tlscstatp.sk_resp_in = sk_OPENSSL_STRING_new_null()) == NULL)
|
||||
goto end;
|
||||
sk_OPENSSL_STRING_push(tlscstatp.sk_resp_in, opt_arg());
|
||||
# endif
|
||||
break;
|
||||
case OPT_MSG:
|
||||
s_msg = 1;
|
||||
|
@ -2358,6 +2585,7 @@ int s_server_main(int argc, char *argv[])
|
|||
OPENSSL_free(port);
|
||||
X509_VERIFY_PARAM_free(vpm);
|
||||
free_sessions();
|
||||
sk_OPENSSL_STRING_free(tlscstatp.sk_resp_in);
|
||||
OPENSSL_free(tlscstatp.host);
|
||||
OPENSSL_free(tlscstatp.port);
|
||||
OPENSSL_free(tlscstatp.path);
|
||||
|
|
|
@ -2,4 +2,4 @@ LIBS=../../libcrypto
|
|||
SOURCE[../../libcrypto]= \
|
||||
cms_lib.c cms_asn1.c cms_att.c cms_io.c cms_smime.c cms_err.c \
|
||||
cms_sd.c cms_dd.c cms_cd.c cms_env.c cms_enc.c cms_ess.c \
|
||||
cms_pwri.c cms_kari.c cms_rsa.c cms_dh.c cms_ec.c
|
||||
cms_pwri.c cms_kari.c cms_rsa.c cms_dh.c cms_ec.c cms_kem.c cms_kemri.c
|
||||
|
|
|
@ -201,10 +201,52 @@ ASN1_SEQUENCE(CMS_PasswordRecipientInfo) = {
|
|||
ASN1_SIMPLE(CMS_PasswordRecipientInfo, encryptedKey, ASN1_OCTET_STRING)
|
||||
} ASN1_SEQUENCE_END(CMS_PasswordRecipientInfo)
|
||||
|
||||
static int cms_kemri_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
void *exarg)
|
||||
{
|
||||
CMS_KEMRecipientInfo *kemri = (CMS_KEMRecipientInfo *)*pval;
|
||||
|
||||
if (operation == ASN1_OP_NEW_POST) {
|
||||
kemri->ctx = EVP_CIPHER_CTX_new();
|
||||
if (kemri->ctx == NULL)
|
||||
return 0;
|
||||
EVP_CIPHER_CTX_set_flags(kemri->ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
|
||||
kemri->pctx = NULL;
|
||||
} else if (operation == ASN1_OP_FREE_POST) {
|
||||
EVP_PKEY_CTX_free(kemri->pctx);
|
||||
EVP_CIPHER_CTX_free(kemri->ctx);
|
||||
ASN1_OCTET_STRING_free(kemri->ukm);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
ASN1_SEQUENCE_cb(CMS_KEMRecipientInfo, cms_kemri_cb) = {
|
||||
ASN1_EMBED(CMS_KEMRecipientInfo, version, INT32),
|
||||
ASN1_SIMPLE(CMS_KEMRecipientInfo, rid, CMS_SignerIdentifier),
|
||||
ASN1_SIMPLE(CMS_KEMRecipientInfo, kem, X509_ALGOR),
|
||||
ASN1_SIMPLE(CMS_KEMRecipientInfo, kemct, ASN1_OCTET_STRING),
|
||||
ASN1_SIMPLE(CMS_KEMRecipientInfo, kdf, X509_ALGOR),
|
||||
ASN1_EMBED(CMS_KEMRecipientInfo, kekLength, INT32),
|
||||
ASN1_EXP_OPT(CMS_KEMRecipientInfo, ukm, ASN1_OCTET_STRING, 0),
|
||||
ASN1_SIMPLE(CMS_KEMRecipientInfo, wrap, X509_ALGOR),
|
||||
ASN1_SIMPLE(CMS_KEMRecipientInfo, encryptedKey, ASN1_OCTET_STRING)
|
||||
} ASN1_SEQUENCE_END_cb(CMS_KEMRecipientInfo, CMS_KEMRecipientInfo)
|
||||
|
||||
ASN1_ADB_TEMPLATE(ori_def) = ASN1_SIMPLE(CMS_OtherRecipientInfo, d.other, ASN1_ANY);
|
||||
|
||||
ASN1_ADB(CMS_OtherRecipientInfo) = {
|
||||
ADB_ENTRY(NID_id_smime_ori_kem, ASN1_SIMPLE(CMS_OtherRecipientInfo, d.kemri,
|
||||
CMS_KEMRecipientInfo))
|
||||
} ASN1_ADB_END(CMS_OtherRecipientInfo, 0, oriType, 0, &ori_def_tt, NULL);
|
||||
|
||||
DECLARE_ASN1_FUNCTIONS(CMS_OtherRecipientInfo)
|
||||
|
||||
ASN1_SEQUENCE(CMS_OtherRecipientInfo) = {
|
||||
ASN1_SIMPLE(CMS_OtherRecipientInfo, oriType, ASN1_OBJECT),
|
||||
ASN1_OPT(CMS_OtherRecipientInfo, oriValue, ASN1_ANY)
|
||||
} static_ASN1_SEQUENCE_END(CMS_OtherRecipientInfo)
|
||||
ASN1_ADB_OBJECT(CMS_OtherRecipientInfo)
|
||||
} ASN1_SEQUENCE_END(CMS_OtherRecipientInfo)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(CMS_OtherRecipientInfo)
|
||||
|
||||
/* Free up RecipientInfo additional data */
|
||||
static int cms_ri_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
|
@ -224,6 +266,23 @@ static int cms_ri_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
|||
CMS_PasswordRecipientInfo *pwri = ri->d.pwri;
|
||||
OPENSSL_clear_free(pwri->pass, pwri->passlen);
|
||||
}
|
||||
} else if (operation == ASN1_OP_D2I_POST) {
|
||||
CMS_RecipientInfo *ri = (CMS_RecipientInfo *)*pval;
|
||||
|
||||
ri->type = ri->encoded_type;
|
||||
if (ri->type == CMS_RECIPINFO_OTHER) {
|
||||
int nid;
|
||||
|
||||
nid = OBJ_obj2nid(ri->d.ori->oriType);
|
||||
/* For ORI, map NID to specific type */
|
||||
if (nid == NID_id_smime_ori_kem)
|
||||
ri->type = CMS_RECIPINFO_KEM;
|
||||
/* Otherwise stay with generic CMS_RECIPINFO_OTHER type */
|
||||
}
|
||||
} else if (operation == ASN1_OP_NEW_POST) {
|
||||
CMS_RecipientInfo *ri = (CMS_RecipientInfo *)*pval;
|
||||
|
||||
ri->type = ri->encoded_type;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -234,7 +293,7 @@ ASN1_CHOICE_cb(CMS_RecipientInfo, cms_ri_cb) = {
|
|||
ASN1_IMP(CMS_RecipientInfo, d.kekri, CMS_KEKRecipientInfo, 2),
|
||||
ASN1_IMP(CMS_RecipientInfo, d.pwri, CMS_PasswordRecipientInfo, 3),
|
||||
ASN1_IMP(CMS_RecipientInfo, d.ori, CMS_OtherRecipientInfo, 4)
|
||||
} ASN1_CHOICE_END_cb(CMS_RecipientInfo, CMS_RecipientInfo, type)
|
||||
} ASN1_CHOICE_END_cb(CMS_RecipientInfo, CMS_RecipientInfo, encoded_type)
|
||||
|
||||
ASN1_NDEF_SEQUENCE(CMS_EnvelopedData) = {
|
||||
ASN1_EMBED(CMS_EnvelopedData, version, INT32),
|
||||
|
@ -430,3 +489,33 @@ int CMS_SharedInfo_encode(unsigned char **pder, X509_ALGOR *kekalg,
|
|||
intsi.pecsi = &ecsi;
|
||||
return ASN1_item_i2d(intsi.a, pder, ASN1_ITEM_rptr(CMS_SharedInfo));
|
||||
}
|
||||
|
||||
/*
|
||||
* Utilities to encode the CMS_CMSORIforKEMOtherInfo structure used during key
|
||||
* derivation.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
X509_ALGOR *wrap;
|
||||
uint32_t kekLength;
|
||||
ASN1_OCTET_STRING *ukm;
|
||||
} CMS_CMSORIforKEMOtherInfo;
|
||||
|
||||
ASN1_SEQUENCE(CMS_CMSORIforKEMOtherInfo) = {
|
||||
ASN1_SIMPLE(CMS_CMSORIforKEMOtherInfo, wrap, X509_ALGOR),
|
||||
ASN1_EMBED(CMS_CMSORIforKEMOtherInfo, kekLength, INT32),
|
||||
ASN1_EXP_OPT(CMS_CMSORIforKEMOtherInfo, ukm, ASN1_OCTET_STRING, 0),
|
||||
} static_ASN1_SEQUENCE_END(CMS_CMSORIforKEMOtherInfo)
|
||||
|
||||
int CMS_CMSORIforKEMOtherInfo_encode(unsigned char **pder, X509_ALGOR *wrap,
|
||||
ASN1_OCTET_STRING *ukm, int keylen)
|
||||
{
|
||||
CMS_CMSORIforKEMOtherInfo kem_otherinfo;
|
||||
|
||||
kem_otherinfo.wrap = wrap;
|
||||
kem_otherinfo.kekLength = keylen;
|
||||
kem_otherinfo.ukm = ukm;
|
||||
|
||||
return ASN1_item_i2d((ASN1_VALUE *)&kem_otherinfo, pder,
|
||||
ASN1_ITEM_rptr(CMS_CMSORIforKEMOtherInfo));
|
||||
}
|
||||
|
|
|
@ -7,6 +7,12 @@
|
|||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* Low level key APIs (DH etc) are deprecated for public use, but still ok for
|
||||
* internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/pem.h>
|
||||
|
@ -14,6 +20,7 @@
|
|||
#include <openssl/err.h>
|
||||
#include <openssl/cms.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include "internal/sizes.h"
|
||||
#include "crypto/asn1.h"
|
||||
#include "crypto/evp.h"
|
||||
|
@ -111,9 +118,12 @@ int ossl_cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd)
|
|||
{
|
||||
EVP_PKEY *pkey;
|
||||
int i;
|
||||
if (ri->type == CMS_RECIPINFO_TRANS)
|
||||
|
||||
switch (ri->type) {
|
||||
case CMS_RECIPINFO_TRANS:
|
||||
pkey = ri->d.ktri->pkey;
|
||||
else if (ri->type == CMS_RECIPINFO_AGREE) {
|
||||
break;
|
||||
case CMS_RECIPINFO_AGREE: {
|
||||
EVP_PKEY_CTX *pctx = ri->d.kari->pctx;
|
||||
|
||||
if (pctx == NULL)
|
||||
|
@ -121,8 +131,13 @@ int ossl_cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd)
|
|||
pkey = EVP_PKEY_CTX_get0_pkey(pctx);
|
||||
if (pkey == NULL)
|
||||
return 0;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
case CMS_RECIPINFO_KEM:
|
||||
return ossl_cms_kem_envelope(ri, cmd);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_is_a(pkey, "DHX") || EVP_PKEY_is_a(pkey, "DH"))
|
||||
return ossl_cms_dh_envelope(ri, cmd);
|
||||
|
@ -202,6 +217,9 @@ void ossl_cms_RecipientInfos_set_cmsctx(CMS_ContentInfo *cms)
|
|||
case CMS_RECIPINFO_PASS:
|
||||
ri->d.pwri->cms_ctx = ctx;
|
||||
break;
|
||||
case CMS_RECIPINFO_KEM:
|
||||
ri->d.ori->d.kemri->cms_ctx = ctx;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -220,6 +238,8 @@ EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri)
|
|||
return ri->d.ktri->pctx;
|
||||
else if (ri->type == CMS_RECIPINFO_AGREE)
|
||||
return ri->d.kari->pctx;
|
||||
else if (ri->type == CMS_RECIPINFO_KEM)
|
||||
return ri->d.ori->d.kemri->pctx;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -336,7 +356,7 @@ static int cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip,
|
|||
ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo);
|
||||
if (!ri->d.ktri)
|
||||
return 0;
|
||||
ri->type = CMS_RECIPINFO_TRANS;
|
||||
ri->encoded_type = ri->type = CMS_RECIPINFO_TRANS;
|
||||
|
||||
ktri = ri->d.ktri;
|
||||
ktri->cms_ctx = ctx;
|
||||
|
@ -423,6 +443,11 @@ CMS_RecipientInfo *CMS_add1_recipient(CMS_ContentInfo *cms, X509 *recip,
|
|||
goto err;
|
||||
break;
|
||||
|
||||
case CMS_RECIPINFO_KEM:
|
||||
if (!ossl_cms_RecipientInfo_kemri_init(ri, recip, pk, flags, ctx))
|
||||
goto err;
|
||||
break;
|
||||
|
||||
default:
|
||||
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
|
||||
goto err;
|
||||
|
@ -750,7 +775,7 @@ CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
|
|||
ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB);
|
||||
goto err;
|
||||
}
|
||||
ri->type = CMS_RECIPINFO_KEK;
|
||||
ri->encoded_type = ri->type = CMS_RECIPINFO_KEK;
|
||||
|
||||
kekri = ri->d.kekri;
|
||||
|
||||
|
@ -1025,6 +1050,9 @@ int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
|
|||
case CMS_RECIPINFO_PASS:
|
||||
return ossl_cms_RecipientInfo_pwri_crypt(cms, ri, 0);
|
||||
|
||||
case CMS_RECIPINFO_KEM:
|
||||
return ossl_cms_RecipientInfo_kemri_decrypt(cms, ri);
|
||||
|
||||
default:
|
||||
ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE);
|
||||
return 0;
|
||||
|
@ -1046,6 +1074,9 @@ int CMS_RecipientInfo_encrypt(const CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
|
|||
case CMS_RECIPINFO_PASS:
|
||||
return ossl_cms_RecipientInfo_pwri_crypt(cms, ri, 1);
|
||||
|
||||
case CMS_RECIPINFO_KEM:
|
||||
return ossl_cms_RecipientInfo_kemri_encrypt(cms, ri);
|
||||
|
||||
default:
|
||||
ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_RECIPIENT_TYPE);
|
||||
return 0;
|
||||
|
@ -1100,7 +1131,8 @@ static void cms_env_set_version(CMS_EnvelopedData *env)
|
|||
|
||||
for (i = 0; i < sk_CMS_RecipientInfo_num(env->recipientInfos); i++) {
|
||||
ri = sk_CMS_RecipientInfo_value(env->recipientInfos, i);
|
||||
if (ri->type == CMS_RECIPINFO_PASS || ri->type == CMS_RECIPINFO_OTHER) {
|
||||
if (ri->type == CMS_RECIPINFO_PASS || ri->type == CMS_RECIPINFO_OTHER
|
||||
|| ri->type == CMS_RECIPINFO_KEM) {
|
||||
env->version = 3;
|
||||
return;
|
||||
} else if (ri->type != CMS_RECIPINFO_TRANS
|
||||
|
@ -1337,6 +1369,18 @@ err:
|
|||
*/
|
||||
int ossl_cms_pkey_get_ri_type(EVP_PKEY *pk)
|
||||
{
|
||||
int ri_type;
|
||||
EVP_PKEY_CTX *ctx = NULL;
|
||||
|
||||
/*
|
||||
* First check the provider for RecipientInfo support since a key may support
|
||||
* multiple types, e.g. an RSA key and provider may support RSA key transport
|
||||
* and/or RSA-KEM.
|
||||
*/
|
||||
if (evp_pkey_is_provided(pk)
|
||||
&& EVP_PKEY_get_int_param(pk, OSSL_PKEY_PARAM_CMS_RI_TYPE, &ri_type))
|
||||
return ri_type;
|
||||
|
||||
/* Check types that we know about */
|
||||
if (EVP_PKEY_is_a(pk, "DH"))
|
||||
return CMS_RECIPINFO_AGREE;
|
||||
|
@ -1350,7 +1394,7 @@ int ossl_cms_pkey_get_ri_type(EVP_PKEY *pk)
|
|||
return CMS_RECIPINFO_TRANS;
|
||||
|
||||
/*
|
||||
* Otherwise this might ben an engine implementation, so see if we can get
|
||||
* Otherwise this might be an engine implementation, so see if we can get
|
||||
* the type from the ameth.
|
||||
*/
|
||||
if (pk->ameth && pk->ameth->pkey_ctrl) {
|
||||
|
@ -1359,7 +1403,25 @@ int ossl_cms_pkey_get_ri_type(EVP_PKEY *pk)
|
|||
if (i > 0)
|
||||
return r;
|
||||
}
|
||||
return CMS_RECIPINFO_TRANS;
|
||||
|
||||
/*
|
||||
* Otherwise try very hard to figure out what RecipientInfo the key supports.
|
||||
*/
|
||||
ri_type = CMS_RECIPINFO_TRANS;
|
||||
ctx = EVP_PKEY_CTX_new(pk, NULL);
|
||||
if (ctx != NULL) {
|
||||
ERR_set_mark();
|
||||
if (EVP_PKEY_encrypt_init(ctx) > 0)
|
||||
ri_type = CMS_RECIPINFO_TRANS;
|
||||
else if (EVP_PKEY_derive_init(ctx) > 0)
|
||||
ri_type = CMS_RECIPINFO_AGREE;
|
||||
else if (EVP_PKEY_encapsulate_init(ctx, NULL) > 0)
|
||||
ri_type = CMS_RECIPINFO_KEM;
|
||||
ERR_pop_to_mark();
|
||||
}
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
|
||||
return ri_type;
|
||||
}
|
||||
|
||||
int ossl_cms_pkey_is_ri_type_supported(EVP_PKEY *pk, int ri_type)
|
||||
|
@ -1381,3 +1443,79 @@ int ossl_cms_pkey_is_ri_type_supported(EVP_PKEY *pk, int ri_type)
|
|||
|
||||
return (supportedRiType == ri_type);
|
||||
}
|
||||
|
||||
int ossl_cms_RecipientInfo_wrap_init(CMS_RecipientInfo *ri,
|
||||
const EVP_CIPHER *cipher)
|
||||
{
|
||||
const CMS_CTX *cms_ctx;
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
const EVP_CIPHER *kekcipher;
|
||||
EVP_CIPHER *fetched_kekcipher;
|
||||
const char *kekcipher_name;
|
||||
int keylen;
|
||||
int ret;
|
||||
|
||||
if (ri->type == CMS_RECIPINFO_AGREE) {
|
||||
cms_ctx = ri->d.kari->cms_ctx;
|
||||
ctx = ri->d.kari->ctx;
|
||||
} else if (ri->type == CMS_RECIPINFO_KEM) {
|
||||
cms_ctx = ri->d.ori->d.kemri->cms_ctx;
|
||||
ctx = ri->d.ori->d.kemri->ctx;
|
||||
} else {
|
||||
ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If a suitable wrap algorithm is already set nothing to do */
|
||||
kekcipher = EVP_CIPHER_CTX_get0_cipher(ctx);
|
||||
if (kekcipher != NULL) {
|
||||
if (EVP_CIPHER_CTX_get_mode(ctx) != EVP_CIPH_WRAP_MODE)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
if (cipher == NULL)
|
||||
return 0;
|
||||
keylen = EVP_CIPHER_get_key_length(cipher);
|
||||
if (keylen <= 0) {
|
||||
ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
if ((EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_GET_WRAP_CIPHER) != 0) {
|
||||
ret = EVP_CIPHER_meth_get_ctrl(cipher)(NULL, EVP_CTRL_GET_WRAP_CIPHER,
|
||||
0, &kekcipher);
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
|
||||
if (kekcipher != NULL) {
|
||||
if (EVP_CIPHER_get_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
|
||||
return 0;
|
||||
kekcipher_name = EVP_CIPHER_get0_name(kekcipher);
|
||||
goto enc;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pick a cipher based on content encryption cipher. If it is DES3 use
|
||||
* DES3 wrap otherwise use AES wrap similar to key size.
|
||||
*/
|
||||
#ifndef OPENSSL_NO_DES
|
||||
if (EVP_CIPHER_get_type(cipher) == NID_des_ede3_cbc)
|
||||
kekcipher_name = SN_id_smime_alg_CMS3DESwrap;
|
||||
else
|
||||
#endif
|
||||
if (keylen <= 16)
|
||||
kekcipher_name = SN_id_aes128_wrap;
|
||||
else if (keylen <= 24)
|
||||
kekcipher_name = SN_id_aes192_wrap;
|
||||
else
|
||||
kekcipher_name = SN_id_aes256_wrap;
|
||||
enc:
|
||||
fetched_kekcipher = EVP_CIPHER_fetch(ossl_cms_ctx_get0_libctx(cms_ctx),
|
||||
kekcipher_name,
|
||||
ossl_cms_ctx_get0_propq(cms_ctx));
|
||||
if (fetched_kekcipher == NULL)
|
||||
return 0;
|
||||
ret = EVP_EncryptInit_ex(ctx, fetched_kekcipher, NULL, NULL, NULL);
|
||||
EVP_CIPHER_free(fetched_kekcipher);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -88,6 +88,7 @@ static const ERR_STRING_DATA CMS_str_reasons[] = {
|
|||
"not a signed receipt"},
|
||||
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_ENCRYPTED_DATA), "not encrypted data"},
|
||||
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_KEK), "not kek"},
|
||||
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_KEM), "not kem"},
|
||||
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_KEY_AGREEMENT), "not key agreement"},
|
||||
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_KEY_TRANSPORT), "not key transport"},
|
||||
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_PWRI), "not pwri"},
|
||||
|
@ -140,6 +141,8 @@ static const ERR_STRING_DATA CMS_str_reasons[] = {
|
|||
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNKNOWN_DIGEST_ALGORITHM),
|
||||
"unknown digest algorithm"},
|
||||
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNKNOWN_ID), "unknown id"},
|
||||
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNKNOWN_KDF_ALGORITHM),
|
||||
"unknown kdf algorithm"},
|
||||
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM),
|
||||
"unsupported compression algorithm"},
|
||||
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM),
|
||||
|
@ -148,6 +151,8 @@ static const ERR_STRING_DATA CMS_str_reasons[] = {
|
|||
"unsupported content type"},
|
||||
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_ENCRYPTION_TYPE),
|
||||
"unsupported encryption type"},
|
||||
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_KDF_ALGORITHM),
|
||||
"unsupported kdf algorithm"},
|
||||
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_KEK_ALGORITHM),
|
||||
"unsupported kek algorithm"},
|
||||
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM),
|
||||
|
|
|
@ -7,12 +7,6 @@
|
|||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* Low level key APIs (DH etc) are deprecated for public use, but still ok for
|
||||
* internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/pem.h>
|
||||
|
@ -349,7 +343,7 @@ int ossl_cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip,
|
|||
ri->d.kari = M_ASN1_new_of(CMS_KeyAgreeRecipientInfo);
|
||||
if (ri->d.kari == NULL)
|
||||
return 0;
|
||||
ri->type = CMS_RECIPINFO_AGREE;
|
||||
ri->encoded_type = ri->type = CMS_RECIPINFO_AGREE;
|
||||
|
||||
kari = ri->d.kari;
|
||||
kari->version = 3;
|
||||
|
@ -412,67 +406,6 @@ int ossl_cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int cms_wrap_init(CMS_KeyAgreeRecipientInfo *kari,
|
||||
const EVP_CIPHER *cipher)
|
||||
{
|
||||
const CMS_CTX *cms_ctx = kari->cms_ctx;
|
||||
EVP_CIPHER_CTX *ctx = kari->ctx;
|
||||
const EVP_CIPHER *kekcipher;
|
||||
EVP_CIPHER *fetched_kekcipher;
|
||||
const char *kekcipher_name;
|
||||
int keylen;
|
||||
int ret;
|
||||
|
||||
/* If a suitable wrap algorithm is already set nothing to do */
|
||||
kekcipher = EVP_CIPHER_CTX_get0_cipher(ctx);
|
||||
if (kekcipher != NULL) {
|
||||
if (EVP_CIPHER_CTX_get_mode(ctx) != EVP_CIPH_WRAP_MODE)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
if (cipher == NULL)
|
||||
return 0;
|
||||
keylen = EVP_CIPHER_get_key_length(cipher);
|
||||
if ((EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_GET_WRAP_CIPHER) != 0) {
|
||||
ret = EVP_CIPHER_meth_get_ctrl(cipher)(NULL, EVP_CTRL_GET_WRAP_CIPHER,
|
||||
0, &kekcipher);
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
|
||||
if (kekcipher != NULL) {
|
||||
if (EVP_CIPHER_get_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
|
||||
return 0;
|
||||
kekcipher_name = EVP_CIPHER_get0_name(kekcipher);
|
||||
goto enc;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pick a cipher based on content encryption cipher. If it is DES3 use
|
||||
* DES3 wrap otherwise use AES wrap similar to key size.
|
||||
*/
|
||||
#ifndef OPENSSL_NO_DES
|
||||
if (EVP_CIPHER_get_type(cipher) == NID_des_ede3_cbc)
|
||||
kekcipher_name = SN_id_smime_alg_CMS3DESwrap;
|
||||
else
|
||||
#endif
|
||||
if (keylen <= 16)
|
||||
kekcipher_name = SN_id_aes128_wrap;
|
||||
else if (keylen <= 24)
|
||||
kekcipher_name = SN_id_aes192_wrap;
|
||||
else
|
||||
kekcipher_name = SN_id_aes256_wrap;
|
||||
enc:
|
||||
fetched_kekcipher = EVP_CIPHER_fetch(ossl_cms_ctx_get0_libctx(cms_ctx),
|
||||
kekcipher_name,
|
||||
ossl_cms_ctx_get0_propq(cms_ctx));
|
||||
if (fetched_kekcipher == NULL)
|
||||
return 0;
|
||||
ret = EVP_EncryptInit_ex(ctx, fetched_kekcipher, NULL, NULL, NULL);
|
||||
EVP_CIPHER_free(fetched_kekcipher);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Encrypt content key in key agreement recipient info */
|
||||
|
||||
int ossl_cms_RecipientInfo_kari_encrypt(const CMS_ContentInfo *cms,
|
||||
|
@ -492,7 +425,7 @@ int ossl_cms_RecipientInfo_kari_encrypt(const CMS_ContentInfo *cms,
|
|||
reks = kari->recipientEncryptedKeys;
|
||||
ec = ossl_cms_get0_env_enc_content(cms);
|
||||
/* Initialise wrap algorithm parameters */
|
||||
if (!cms_wrap_init(kari, ec->cipher))
|
||||
if (!ossl_cms_RecipientInfo_wrap_init(ri, ec->cipher))
|
||||
return 0;
|
||||
/*
|
||||
* If no originator key set up initialise for ephemeral key the public key
|
||||
|
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Copyright 2025 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 <assert.h>
|
||||
#include <limits.h>
|
||||
#include <openssl/cms.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/decoder.h>
|
||||
#include "internal/sizes.h"
|
||||
#include "crypto/asn1.h"
|
||||
#include "crypto/evp.h"
|
||||
#include "cms_local.h"
|
||||
|
||||
static int kem_cms_decrypt(CMS_RecipientInfo *ri)
|
||||
{
|
||||
uint32_t *kekLength;
|
||||
X509_ALGOR *wrap;
|
||||
EVP_PKEY_CTX *pctx;
|
||||
EVP_CIPHER_CTX *kekctx;
|
||||
uint32_t cipher_length;
|
||||
char name[OSSL_MAX_NAME_SIZE];
|
||||
EVP_CIPHER *kekcipher = NULL;
|
||||
int rv = 0;
|
||||
|
||||
if (!ossl_cms_RecipientInfo_kemri_get0_alg(ri, &kekLength, &wrap))
|
||||
goto err;
|
||||
|
||||
pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
|
||||
if (pctx == NULL)
|
||||
goto err;
|
||||
|
||||
kekctx = CMS_RecipientInfo_kemri_get0_ctx(ri);
|
||||
if (kekctx == NULL)
|
||||
goto err;
|
||||
|
||||
OBJ_obj2txt(name, sizeof(name), wrap->algorithm, 0);
|
||||
kekcipher = EVP_CIPHER_fetch(pctx->libctx, name, pctx->propquery);
|
||||
if (kekcipher == NULL || EVP_CIPHER_get_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
|
||||
goto err;
|
||||
if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
|
||||
goto err;
|
||||
if (EVP_CIPHER_asn1_to_param(kekctx, wrap->parameter) <= 0)
|
||||
goto err;
|
||||
|
||||
cipher_length = EVP_CIPHER_CTX_get_key_length(kekctx);
|
||||
if (cipher_length != *kekLength) {
|
||||
ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
rv = 1;
|
||||
err:
|
||||
EVP_CIPHER_free(kekcipher);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int kem_cms_encrypt(CMS_RecipientInfo *ri)
|
||||
{
|
||||
uint32_t *kekLength;
|
||||
X509_ALGOR *wrap;
|
||||
X509_ALGOR *kdf;
|
||||
EVP_PKEY_CTX *pctx;
|
||||
EVP_PKEY *pkey;
|
||||
int security_bits;
|
||||
const ASN1_OBJECT *kdf_obj = NULL;
|
||||
unsigned char kemri_x509_algor[OSSL_MAX_ALGORITHM_ID_SIZE];
|
||||
OSSL_PARAM params[2];
|
||||
X509_ALGOR *x509_algor = NULL;
|
||||
EVP_CIPHER_CTX *kekctx;
|
||||
int wrap_nid;
|
||||
int rv = 0;
|
||||
|
||||
if (!ossl_cms_RecipientInfo_kemri_get0_alg(ri, &kekLength, &wrap))
|
||||
goto err;
|
||||
|
||||
kdf = CMS_RecipientInfo_kemri_get0_kdf_alg(ri);
|
||||
if (kdf == NULL)
|
||||
goto err;
|
||||
|
||||
pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
|
||||
if (pctx == NULL)
|
||||
goto err;
|
||||
|
||||
pkey = EVP_PKEY_CTX_get0_pkey(pctx);
|
||||
if (pkey == NULL)
|
||||
goto err;
|
||||
|
||||
security_bits = EVP_PKEY_get_security_bits(pkey);
|
||||
if (security_bits == 0)
|
||||
goto err;
|
||||
|
||||
X509_ALGOR_get0(&kdf_obj, NULL, NULL, kdf);
|
||||
if (kdf_obj == NULL || OBJ_obj2nid(kdf_obj) == NID_undef) {
|
||||
/*
|
||||
* If the KDF OID hasn't already been set, then query the provider
|
||||
* for a default KDF.
|
||||
*/
|
||||
params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_CMS_KEMRI_KDF_ALGORITHM,
|
||||
kemri_x509_algor, sizeof(kemri_x509_algor));
|
||||
params[1] = OSSL_PARAM_construct_end();
|
||||
if (!EVP_PKEY_get_params(pkey, params))
|
||||
goto err;
|
||||
if (OSSL_PARAM_modified(¶ms[0])) {
|
||||
const unsigned char *p = kemri_x509_algor;
|
||||
|
||||
x509_algor = d2i_X509_ALGOR(NULL, &p, (long)params[0].return_size);
|
||||
if (x509_algor == NULL)
|
||||
goto err;
|
||||
if (!X509_ALGOR_copy(kdf, x509_algor))
|
||||
goto err;
|
||||
} else {
|
||||
if (!X509_ALGOR_set0(kdf, OBJ_nid2obj(NID_HKDF_SHA256), V_ASN1_UNDEF, NULL))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get wrap NID */
|
||||
kekctx = CMS_RecipientInfo_kemri_get0_ctx(ri);
|
||||
if (kekctx == NULL)
|
||||
goto err;
|
||||
*kekLength = EVP_CIPHER_CTX_get_key_length(kekctx);
|
||||
wrap_nid = EVP_CIPHER_CTX_get_type(kekctx);
|
||||
|
||||
/* Package wrap algorithm in an AlgorithmIdentifier */
|
||||
ASN1_OBJECT_free(wrap->algorithm);
|
||||
ASN1_TYPE_free(wrap->parameter);
|
||||
wrap->algorithm = OBJ_nid2obj(wrap_nid);
|
||||
wrap->parameter = ASN1_TYPE_new();
|
||||
if (wrap->parameter == NULL)
|
||||
goto err;
|
||||
if (EVP_CIPHER_param_to_asn1(kekctx, wrap->parameter) <= 0)
|
||||
goto err;
|
||||
if (ASN1_TYPE_get(wrap->parameter) == NID_undef) {
|
||||
ASN1_TYPE_free(wrap->parameter);
|
||||
wrap->parameter = NULL;
|
||||
}
|
||||
|
||||
rv = 1;
|
||||
err:
|
||||
X509_ALGOR_free(x509_algor);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int ossl_cms_kem_envelope(CMS_RecipientInfo *ri, int decrypt)
|
||||
{
|
||||
assert(decrypt == 0 || decrypt == 1);
|
||||
|
||||
if (decrypt == 1)
|
||||
return kem_cms_decrypt(ri);
|
||||
|
||||
if (decrypt == 0)
|
||||
return kem_cms_encrypt(ri);
|
||||
|
||||
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,409 @@
|
|||
/*
|
||||
* Copyright 2025 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 <openssl/cms.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/kdf.h>
|
||||
#include <openssl/x509.h>
|
||||
#include "cms_local.h"
|
||||
#include "crypto/evp.h"
|
||||
#include "internal/sizes.h"
|
||||
|
||||
/* KEM Recipient Info (KEMRI) routines */
|
||||
|
||||
int ossl_cms_RecipientInfo_kemri_get0_alg(CMS_RecipientInfo *ri,
|
||||
uint32_t **pkekLength,
|
||||
X509_ALGOR **pwrap)
|
||||
{
|
||||
if (ri->type != CMS_RECIPINFO_KEM) {
|
||||
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEM);
|
||||
return 0;
|
||||
}
|
||||
if (pkekLength)
|
||||
*pkekLength = &ri->d.ori->d.kemri->kekLength;
|
||||
if (pwrap)
|
||||
*pwrap = ri->d.ori->d.kemri->wrap;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CMS_RecipientInfo_kemri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert)
|
||||
{
|
||||
if (ri->type != CMS_RECIPINFO_KEM) {
|
||||
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEM);
|
||||
return -2;
|
||||
}
|
||||
return ossl_cms_SignerIdentifier_cert_cmp(ri->d.ori->d.kemri->rid, cert);
|
||||
}
|
||||
|
||||
int CMS_RecipientInfo_kemri_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk)
|
||||
{
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
CMS_KEMRecipientInfo *kemri;
|
||||
|
||||
if (ri->type != CMS_RECIPINFO_KEM) {
|
||||
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
kemri = ri->d.ori->d.kemri;
|
||||
|
||||
EVP_PKEY_CTX_free(kemri->pctx);
|
||||
kemri->pctx = NULL;
|
||||
|
||||
if (pk != NULL) {
|
||||
pctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(kemri->cms_ctx), pk,
|
||||
ossl_cms_ctx_get0_propq(kemri->cms_ctx));
|
||||
if (pctx == NULL || EVP_PKEY_decapsulate_init(pctx, NULL) <= 0)
|
||||
goto err;
|
||||
|
||||
kemri->pctx = pctx;
|
||||
}
|
||||
|
||||
return 1;
|
||||
err:
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initialise a kemri based on passed certificate and key */
|
||||
|
||||
int ossl_cms_RecipientInfo_kemri_init(CMS_RecipientInfo *ri, X509 *recip,
|
||||
EVP_PKEY *recipPubKey, unsigned int flags,
|
||||
const CMS_CTX *ctx)
|
||||
{
|
||||
CMS_OtherRecipientInfo *ori;
|
||||
CMS_KEMRecipientInfo *kemri;
|
||||
int idtype;
|
||||
X509_PUBKEY *x_pubkey;
|
||||
X509_ALGOR *x_alg;
|
||||
|
||||
ri->d.ori = M_ASN1_new_of(CMS_OtherRecipientInfo);
|
||||
if (ri->d.ori == NULL)
|
||||
return 0;
|
||||
ri->encoded_type = CMS_RECIPINFO_OTHER;
|
||||
ri->type = CMS_RECIPINFO_KEM;
|
||||
|
||||
ori = ri->d.ori;
|
||||
ori->oriType = OBJ_nid2obj(NID_id_smime_ori_kem);
|
||||
if (ori->oriType == NULL)
|
||||
return 0;
|
||||
ori->d.kemri = M_ASN1_new_of(CMS_KEMRecipientInfo);
|
||||
if (ori->d.kemri == NULL)
|
||||
return 0;
|
||||
|
||||
kemri = ori->d.kemri;
|
||||
kemri->version = 0;
|
||||
kemri->cms_ctx = ctx;
|
||||
|
||||
/*
|
||||
* Not a typo: RecipientIdentifier and SignerIdentifier are the same
|
||||
* structure.
|
||||
*/
|
||||
|
||||
idtype = (flags & CMS_USE_KEYID) ? CMS_RECIPINFO_KEYIDENTIFIER : CMS_RECIPINFO_ISSUER_SERIAL;
|
||||
if (!ossl_cms_set1_SignerIdentifier(kemri->rid, recip, idtype, ctx))
|
||||
return 0;
|
||||
|
||||
x_pubkey = X509_get_X509_PUBKEY(recip);
|
||||
if (x_pubkey == NULL)
|
||||
return 0;
|
||||
if (!X509_PUBKEY_get0_param(NULL, NULL, NULL, &x_alg, x_pubkey))
|
||||
return 0;
|
||||
if (!X509_ALGOR_copy(kemri->kem, x_alg))
|
||||
return 0;
|
||||
|
||||
kemri->pctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(ctx),
|
||||
recipPubKey,
|
||||
ossl_cms_ctx_get0_propq(ctx));
|
||||
if (kemri->pctx == NULL)
|
||||
return 0;
|
||||
if (EVP_PKEY_encapsulate_init(kemri->pctx, NULL) <= 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX *CMS_RecipientInfo_kemri_get0_ctx(CMS_RecipientInfo *ri)
|
||||
{
|
||||
if (ri->type == CMS_RECIPINFO_KEM)
|
||||
return ri->d.ori->d.kemri->ctx;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
X509_ALGOR *CMS_RecipientInfo_kemri_get0_kdf_alg(CMS_RecipientInfo *ri)
|
||||
{
|
||||
if (ri->type == CMS_RECIPINFO_KEM)
|
||||
return ri->d.ori->d.kemri->kdf;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int CMS_RecipientInfo_kemri_set_ukm(CMS_RecipientInfo *ri,
|
||||
const unsigned char *ukm,
|
||||
int ukmLength)
|
||||
{
|
||||
CMS_KEMRecipientInfo *kemri;
|
||||
|
||||
if (ri->type != CMS_RECIPINFO_KEM) {
|
||||
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ukm == NULL && ukmLength != 0) {
|
||||
ERR_raise(ERR_LIB_CMS, ERR_R_PASSED_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
kemri = ri->d.ori->d.kemri;
|
||||
|
||||
ASN1_OCTET_STRING_free(kemri->ukm);
|
||||
kemri->ukm = ASN1_OCTET_STRING_new();
|
||||
if (kemri->ukm == NULL)
|
||||
return 0;
|
||||
ASN1_OCTET_STRING_set(kemri->ukm, ukm, ukmLength);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static EVP_KDF_CTX *create_kdf_ctx(CMS_KEMRecipientInfo *kemri)
|
||||
{
|
||||
const ASN1_OBJECT *kdf_oid;
|
||||
int ptype;
|
||||
char kdf_alg[OSSL_MAX_NAME_SIZE];
|
||||
EVP_KDF *kdf = NULL;
|
||||
EVP_KDF_CTX *kctx = NULL;
|
||||
|
||||
/*
|
||||
* KDFs with algorithm identifier parameters are not supported yet. To
|
||||
* support this, EVP_KDF_CTX_set_algor_params from
|
||||
* `doc/designs/passing-algorithmidentifier-parameters.md` needs to be
|
||||
* implemented.
|
||||
*/
|
||||
X509_ALGOR_get0(&kdf_oid, &ptype, NULL, kemri->kdf);
|
||||
if (ptype != V_ASN1_UNDEF && ptype != V_ASN1_NULL) {
|
||||
ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_KDF_ALGORITHM);
|
||||
goto err;
|
||||
}
|
||||
if (OBJ_obj2txt(kdf_alg, sizeof(kdf_alg), kdf_oid, 1) < 0)
|
||||
goto err;
|
||||
|
||||
kdf = EVP_KDF_fetch(ossl_cms_ctx_get0_libctx(kemri->cms_ctx), kdf_alg,
|
||||
ossl_cms_ctx_get0_propq(kemri->cms_ctx));
|
||||
if (kdf == NULL)
|
||||
goto err;
|
||||
|
||||
kctx = EVP_KDF_CTX_new(kdf);
|
||||
err:
|
||||
EVP_KDF_free(kdf);
|
||||
return kctx;
|
||||
}
|
||||
|
||||
static int kdf_derive(unsigned char *kek, size_t keklen,
|
||||
const unsigned char *ss, size_t sslen,
|
||||
CMS_KEMRecipientInfo *kemri)
|
||||
{
|
||||
EVP_KDF_CTX *kctx = NULL;
|
||||
OSSL_PARAM params[3];
|
||||
unsigned char *infoder = NULL;
|
||||
int infolen = 0;
|
||||
int rv = 0;
|
||||
|
||||
infolen = CMS_CMSORIforKEMOtherInfo_encode(&infoder, kemri->wrap, kemri->ukm,
|
||||
kemri->kekLength);
|
||||
if (infolen <= 0)
|
||||
goto err;
|
||||
|
||||
kctx = create_kdf_ctx(kemri);
|
||||
if (kctx == NULL)
|
||||
goto err;
|
||||
|
||||
params[0] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
|
||||
(unsigned char *)ss, sslen);
|
||||
params[1] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
|
||||
(char *)infoder, infolen);
|
||||
params[2] = OSSL_PARAM_construct_end();
|
||||
|
||||
if (EVP_KDF_derive(kctx, kek, keklen, params) <= 0)
|
||||
goto err;
|
||||
|
||||
rv = 1;
|
||||
err:
|
||||
OPENSSL_free(infoder);
|
||||
EVP_KDF_CTX_free(kctx);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Derive KEK and decrypt/encrypt with it to produce either the original CEK
|
||||
* or the encrypted CEK.
|
||||
*/
|
||||
|
||||
static int cms_kek_cipher(unsigned char **pout, size_t *poutlen,
|
||||
const unsigned char *ss, size_t sslen,
|
||||
const unsigned char *in, size_t inlen,
|
||||
CMS_KEMRecipientInfo *kemri, int enc)
|
||||
{
|
||||
/* Key encryption key */
|
||||
unsigned char kek[EVP_MAX_KEY_LENGTH];
|
||||
size_t keklen = kemri->kekLength;
|
||||
unsigned char *out = NULL;
|
||||
int outlen = 0;
|
||||
int rv = 0;
|
||||
|
||||
if (keklen > sizeof(kek)) {
|
||||
ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!kdf_derive(kek, keklen, ss, sslen, kemri))
|
||||
goto err;
|
||||
|
||||
/* Set KEK in context */
|
||||
if (!EVP_CipherInit_ex(kemri->ctx, NULL, NULL, kek, NULL, enc))
|
||||
goto err;
|
||||
/* obtain output length of ciphered key */
|
||||
if (!EVP_CipherUpdate(kemri->ctx, NULL, &outlen, in, (int)inlen))
|
||||
goto err;
|
||||
out = OPENSSL_malloc(outlen);
|
||||
if (out == NULL)
|
||||
goto err;
|
||||
if (!EVP_CipherUpdate(kemri->ctx, out, &outlen, in, (int)inlen))
|
||||
goto err;
|
||||
*pout = out;
|
||||
out = NULL;
|
||||
*poutlen = (size_t)outlen;
|
||||
|
||||
rv = 1;
|
||||
err:
|
||||
OPENSSL_free(out);
|
||||
OPENSSL_cleanse(kek, keklen);
|
||||
EVP_CIPHER_CTX_reset(kemri->ctx);
|
||||
EVP_PKEY_CTX_free(kemri->pctx);
|
||||
kemri->pctx = NULL;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Encrypt content key in KEM recipient info */
|
||||
|
||||
int ossl_cms_RecipientInfo_kemri_encrypt(const CMS_ContentInfo *cms,
|
||||
CMS_RecipientInfo *ri)
|
||||
{
|
||||
CMS_KEMRecipientInfo *kemri;
|
||||
CMS_EncryptedContentInfo *ec;
|
||||
unsigned char *kem_ct = NULL;
|
||||
size_t kem_ct_len;
|
||||
unsigned char *kem_secret = NULL;
|
||||
size_t kem_secret_len = 0;
|
||||
unsigned char *enckey;
|
||||
size_t enckeylen;
|
||||
int rv = 0;
|
||||
|
||||
if (ri->type != CMS_RECIPINFO_KEM) {
|
||||
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
kemri = ri->d.ori->d.kemri;
|
||||
|
||||
ec = ossl_cms_get0_env_enc_content(cms);
|
||||
/* Initialise wrap algorithm parameters */
|
||||
if (!ossl_cms_RecipientInfo_wrap_init(ri, ec->cipher))
|
||||
return 0;
|
||||
|
||||
/* Initialise KDF algorithm */
|
||||
if (!ossl_cms_env_asn1_ctrl(ri, 0))
|
||||
return 0;
|
||||
|
||||
if (EVP_PKEY_encapsulate(kemri->pctx, NULL, &kem_ct_len, NULL, &kem_secret_len) <= 0)
|
||||
return 0;
|
||||
kem_ct = OPENSSL_malloc(kem_ct_len);
|
||||
kem_secret = OPENSSL_malloc(kem_secret_len);
|
||||
if (kem_ct == NULL || kem_secret == NULL)
|
||||
goto err;
|
||||
|
||||
if (EVP_PKEY_encapsulate(kemri->pctx, kem_ct, &kem_ct_len, kem_secret, &kem_secret_len) <= 0)
|
||||
goto err;
|
||||
|
||||
ASN1_STRING_set0(kemri->kemct, kem_ct, (int)kem_ct_len);
|
||||
kem_ct = NULL;
|
||||
|
||||
if (!cms_kek_cipher(&enckey, &enckeylen, kem_secret, kem_secret_len, ec->key, ec->keylen,
|
||||
kemri, 1))
|
||||
goto err;
|
||||
ASN1_STRING_set0(kemri->encryptedKey, enckey, (int)enckeylen);
|
||||
|
||||
rv = 1;
|
||||
err:
|
||||
OPENSSL_free(kem_ct);
|
||||
OPENSSL_clear_free(kem_secret, kem_secret_len);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int ossl_cms_RecipientInfo_kemri_decrypt(const CMS_ContentInfo *cms,
|
||||
CMS_RecipientInfo *ri)
|
||||
{
|
||||
CMS_KEMRecipientInfo *kemri;
|
||||
CMS_EncryptedContentInfo *ec;
|
||||
const unsigned char *kem_ct = NULL;
|
||||
size_t kem_ct_len;
|
||||
unsigned char *kem_secret = NULL;
|
||||
size_t kem_secret_len = 0;
|
||||
unsigned char *enckey = NULL;
|
||||
size_t enckeylen;
|
||||
unsigned char *cek = NULL;
|
||||
size_t ceklen;
|
||||
int ret = 0;
|
||||
|
||||
if (ri->type != CMS_RECIPINFO_KEM) {
|
||||
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
kemri = ri->d.ori->d.kemri;
|
||||
|
||||
ec = ossl_cms_get0_env_enc_content(cms);
|
||||
|
||||
if (kemri->pctx == NULL) {
|
||||
ERR_raise(ERR_LIB_CMS, CMS_R_NO_PRIVATE_KEY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Setup all parameters to derive KEK */
|
||||
if (!ossl_cms_env_asn1_ctrl(ri, 1))
|
||||
goto err;
|
||||
|
||||
kem_ct = ASN1_STRING_get0_data(kemri->kemct);
|
||||
kem_ct_len = ASN1_STRING_length(kemri->kemct);
|
||||
|
||||
if (EVP_PKEY_decapsulate(kemri->pctx, NULL, &kem_secret_len, kem_ct, kem_ct_len) <= 0)
|
||||
return 0;
|
||||
kem_secret = OPENSSL_malloc(kem_secret_len);
|
||||
if (kem_secret == NULL)
|
||||
goto err;
|
||||
|
||||
if (EVP_PKEY_decapsulate(kemri->pctx, kem_secret, &kem_secret_len, kem_ct, kem_ct_len) <= 0)
|
||||
goto err;
|
||||
|
||||
/* Attempt to decrypt CEK */
|
||||
enckeylen = kemri->encryptedKey->length;
|
||||
enckey = kemri->encryptedKey->data;
|
||||
if (!cms_kek_cipher(&cek, &ceklen, kem_secret, kem_secret_len, enckey, enckeylen, kemri, 0))
|
||||
goto err;
|
||||
ec = ossl_cms_get0_env_enc_content(cms);
|
||||
OPENSSL_clear_free(ec->key, ec->keylen);
|
||||
ec->key = cek;
|
||||
ec->keylen = ceklen;
|
||||
|
||||
ret = 1;
|
||||
err:
|
||||
OPENSSL_clear_free(kem_secret, kem_secret_len);
|
||||
return ret;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2008-2024 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2008-2025 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
|
||||
|
@ -41,6 +41,7 @@ typedef struct CMS_KEKIdentifier_st CMS_KEKIdentifier;
|
|||
typedef struct CMS_KEKRecipientInfo_st CMS_KEKRecipientInfo;
|
||||
typedef struct CMS_PasswordRecipientInfo_st CMS_PasswordRecipientInfo;
|
||||
typedef struct CMS_OtherRecipientInfo_st CMS_OtherRecipientInfo;
|
||||
typedef struct CMS_KEMRecipientInfo_st CMS_KEMRecipientInfo;
|
||||
typedef struct CMS_ReceiptsFrom_st CMS_ReceiptsFrom;
|
||||
typedef struct CMS_CTX_st CMS_CTX;
|
||||
|
||||
|
@ -142,7 +143,11 @@ struct CMS_EncryptedContentInfo_st {
|
|||
};
|
||||
|
||||
struct CMS_RecipientInfo_st {
|
||||
int type;
|
||||
/*
|
||||
* Type which the RecipientInfo is encoded with. OtherRecipientInfo
|
||||
* encompasses different types, specified by 'type' below.
|
||||
*/
|
||||
int encoded_type;
|
||||
union {
|
||||
CMS_KeyTransRecipientInfo *ktri;
|
||||
CMS_KeyAgreeRecipientInfo *kari;
|
||||
|
@ -150,6 +155,8 @@ struct CMS_RecipientInfo_st {
|
|||
CMS_PasswordRecipientInfo *pwri;
|
||||
CMS_OtherRecipientInfo *ori;
|
||||
} d;
|
||||
/* internal type, including ORI types */
|
||||
int type;
|
||||
};
|
||||
|
||||
typedef CMS_SignerIdentifier CMS_RecipientIdentifier;
|
||||
|
@ -245,7 +252,29 @@ struct CMS_PasswordRecipientInfo_st {
|
|||
|
||||
struct CMS_OtherRecipientInfo_st {
|
||||
ASN1_OBJECT *oriType;
|
||||
ASN1_TYPE *oriValue;
|
||||
union {
|
||||
/* NID_id_smime_ori_kem */
|
||||
CMS_KEMRecipientInfo *kemri;
|
||||
/* anything else */
|
||||
ASN1_TYPE *other;
|
||||
} d;
|
||||
};
|
||||
|
||||
struct CMS_KEMRecipientInfo_st {
|
||||
int32_t version;
|
||||
CMS_RecipientIdentifier *rid;
|
||||
X509_ALGOR *kem;
|
||||
ASN1_OCTET_STRING *kemct;
|
||||
X509_ALGOR *kdf;
|
||||
uint32_t kekLength;
|
||||
ASN1_OCTET_STRING *ukm;
|
||||
X509_ALGOR *wrap;
|
||||
ASN1_OCTET_STRING *encryptedKey;
|
||||
/* Public key context associated with current operation */
|
||||
EVP_PKEY_CTX *pctx;
|
||||
/* Cipher context for CEK wrapping */
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
const CMS_CTX *cms_ctx;
|
||||
};
|
||||
|
||||
struct CMS_DigestedData_st {
|
||||
|
@ -460,6 +489,7 @@ int ossl_cms_pkey_get_ri_type(EVP_PKEY *pk);
|
|||
int ossl_cms_pkey_is_ri_type_supported(EVP_PKEY *pk, int ri_type);
|
||||
|
||||
void ossl_cms_RecipientInfos_set_cmsctx(CMS_ContentInfo *cms);
|
||||
int ossl_cms_RecipientInfo_wrap_init(CMS_RecipientInfo *ri, const EVP_CIPHER *cipher);
|
||||
|
||||
/* KARI routines */
|
||||
int ossl_cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip,
|
||||
|
@ -470,6 +500,20 @@ int ossl_cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip,
|
|||
int ossl_cms_RecipientInfo_kari_encrypt(const CMS_ContentInfo *cms,
|
||||
CMS_RecipientInfo *ri);
|
||||
|
||||
/* KEMRI routines */
|
||||
int ossl_cms_RecipientInfo_kemri_get0_alg(CMS_RecipientInfo *ri,
|
||||
uint32_t **pkekLength,
|
||||
X509_ALGOR **pwrap);
|
||||
int ossl_cms_RecipientInfo_kemri_init(CMS_RecipientInfo *ri, X509 *recip,
|
||||
EVP_PKEY *recipPubKey, unsigned int flags,
|
||||
const CMS_CTX *ctx);
|
||||
int ossl_cms_RecipientInfo_kemri_encrypt(const CMS_ContentInfo *cms,
|
||||
CMS_RecipientInfo *ri);
|
||||
int ossl_cms_RecipientInfo_kemri_decrypt(const CMS_ContentInfo *cms,
|
||||
CMS_RecipientInfo *ri);
|
||||
int CMS_CMSORIforKEMOtherInfo_encode(unsigned char **pder, X509_ALGOR *wrap,
|
||||
ASN1_OCTET_STRING *ukm, int keylen);
|
||||
|
||||
/* PWRI routines */
|
||||
int ossl_cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms,
|
||||
CMS_RecipientInfo *ri, int en_de);
|
||||
|
@ -486,6 +530,7 @@ int ossl_cms_dh_envelope(CMS_RecipientInfo *ri, int decrypt);
|
|||
int ossl_cms_ecdh_envelope(CMS_RecipientInfo *ri, int decrypt);
|
||||
int ossl_cms_rsa_envelope(CMS_RecipientInfo *ri, int decrypt);
|
||||
int ossl_cms_rsa_sign(CMS_SignerInfo *si, int verify);
|
||||
int ossl_cms_kem_envelope(CMS_RecipientInfo *ri, int decrypt);
|
||||
|
||||
int ossl_cms_get1_certs_ex(CMS_ContentInfo *cms, STACK_OF(X509) **certs);
|
||||
int ossl_cms_get1_crls_ex(CMS_ContentInfo *cms, STACK_OF(X509_CRL) **crls);
|
||||
|
@ -496,10 +541,12 @@ DECLARE_ASN1_ITEM(CMS_EncryptedData)
|
|||
DECLARE_ASN1_ITEM(CMS_EnvelopedData)
|
||||
DECLARE_ASN1_ITEM(CMS_AuthEnvelopedData)
|
||||
DECLARE_ASN1_ITEM(CMS_KEKRecipientInfo)
|
||||
DECLARE_ASN1_ITEM(CMS_KEMRecipientInfo)
|
||||
DECLARE_ASN1_ITEM(CMS_KeyAgreeRecipientInfo)
|
||||
DECLARE_ASN1_ITEM(CMS_KeyTransRecipientInfo)
|
||||
DECLARE_ASN1_ITEM(CMS_OriginatorPublicKey)
|
||||
DECLARE_ASN1_ITEM(CMS_OtherKeyAttribute)
|
||||
DECLARE_ASN1_ITEM(CMS_OtherRecipientInfo)
|
||||
DECLARE_ASN1_ITEM(CMS_Receipt)
|
||||
DECLARE_ASN1_ITEM(CMS_ReceiptRequest)
|
||||
DECLARE_ASN1_ITEM(CMS_RecipientEncryptedKey)
|
||||
|
|
|
@ -138,7 +138,7 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
|
|||
ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB);
|
||||
goto err;
|
||||
}
|
||||
ri->type = CMS_RECIPINFO_PASS;
|
||||
ri->encoded_type = ri->type = CMS_RECIPINFO_PASS;
|
||||
|
||||
pwri = ri->d.pwri;
|
||||
pwri->cms_ctx = cms_ctx;
|
||||
|
|
|
@ -750,6 +750,14 @@ int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms, EVP_PKEY *pk,
|
|||
return 1;
|
||||
if (r < 0)
|
||||
return 0;
|
||||
} else if (ri_type == CMS_RECIPINFO_KEM) {
|
||||
if (cert == NULL || !CMS_RecipientInfo_kemri_cert_cmp(ri, cert)) {
|
||||
CMS_RecipientInfo_kemri_set0_pkey(ri, pk);
|
||||
r = CMS_RecipientInfo_decrypt(cms, ri);
|
||||
CMS_RecipientInfo_kemri_set0_pkey(ri, NULL);
|
||||
if (cert != NULL || r > 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
/* If we have a cert, try matching RecipientInfo, else try them all */
|
||||
else if (cert == NULL || !CMS_RecipientInfo_ktri_cert_cmp(ri, cert)) {
|
||||
|
|
|
@ -80,6 +80,12 @@ int ossl_dh_key_fromdata(DH *dh, const OSSL_PARAM params[], int include_private)
|
|||
if (!DH_set0_key(dh, pub_key, priv_key))
|
||||
goto err;
|
||||
|
||||
#ifdef FIPS_MODULE
|
||||
if (pub_key != NULL && priv_key != NULL)
|
||||
if (ossl_dh_check_pairwise(dh) == 0)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
|
||||
err:
|
||||
|
|
|
@ -354,6 +354,7 @@ CMS_R_NEED_ONE_SIGNER:164:need one signer
|
|||
CMS_R_NOT_A_SIGNED_RECEIPT:165:not a signed receipt
|
||||
CMS_R_NOT_ENCRYPTED_DATA:122:not encrypted data
|
||||
CMS_R_NOT_KEK:123:not kek
|
||||
CMS_R_NOT_KEM:197:not kem
|
||||
CMS_R_NOT_KEY_AGREEMENT:181:not key agreement
|
||||
CMS_R_NOT_KEY_TRANSPORT:124:not key transport
|
||||
CMS_R_NOT_PWRI:177:not pwri
|
||||
|
@ -394,11 +395,13 @@ CMS_R_UNABLE_TO_FINALIZE_CONTEXT:147:unable to finalize context
|
|||
CMS_R_UNKNOWN_CIPHER:148:unknown cipher
|
||||
CMS_R_UNKNOWN_DIGEST_ALGORITHM:149:unknown digest algorithm
|
||||
CMS_R_UNKNOWN_ID:150:unknown id
|
||||
CMS_R_UNKNOWN_KDF_ALGORITHM:198:unknown kdf algorithm
|
||||
CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM:151:unsupported compression algorithm
|
||||
CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM:194:\
|
||||
unsupported content encryption algorithm
|
||||
CMS_R_UNSUPPORTED_CONTENT_TYPE:152:unsupported content type
|
||||
CMS_R_UNSUPPORTED_ENCRYPTION_TYPE:192:unsupported encryption type
|
||||
CMS_R_UNSUPPORTED_KDF_ALGORITHM:199:unsupported kdf algorithm
|
||||
CMS_R_UNSUPPORTED_KEK_ALGORITHM:153:unsupported kek algorithm
|
||||
CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM:179:\
|
||||
unsupported key encryption algorithm
|
||||
|
|
|
@ -261,10 +261,12 @@ int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx,
|
|||
|
||||
cipher = ctx->op.ciph.cipher;
|
||||
desc = cipher->description != NULL ? cipher->description : "";
|
||||
ERR_set_mark();
|
||||
ret = cipher->encrypt(ctx->op.ciph.algctx, out, outlen, (out == NULL ? 0 : *outlen), in, inlen);
|
||||
if (ret <= 0)
|
||||
if (ret <= 0 && ERR_count_to_mark() == 0)
|
||||
ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_ASYM_CIPHER_FAILURE,
|
||||
"%s encrypt:%s", cipher->type_name, desc);
|
||||
ERR_clear_last_mark();
|
||||
return ret;
|
||||
|
||||
legacy:
|
||||
|
@ -309,10 +311,12 @@ int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
|
|||
|
||||
cipher = ctx->op.ciph.cipher;
|
||||
desc = cipher->description != NULL ? cipher->description : "";
|
||||
ERR_set_mark();
|
||||
ret = cipher->decrypt(ctx->op.ciph.algctx, out, outlen, (out == NULL ? 0 : *outlen), in, inlen);
|
||||
if (ret <= 0)
|
||||
if (ret <= 0 && ERR_count_to_mark() == 0)
|
||||
ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_ASYM_CIPHER_FAILURE,
|
||||
"%s decrypt:%s", cipher->type_name, desc);
|
||||
ERR_clear_last_mark();
|
||||
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -460,10 +460,12 @@ void *evp_keymgmt_gen(const EVP_KEYMGMT *keymgmt, void *genctx,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ERR_set_mark();
|
||||
ret = keymgmt->gen(genctx, cb, cbarg);
|
||||
if (ret == NULL)
|
||||
if (ret == NULL && ERR_count_to_mark() == 0)
|
||||
ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_KEYMGMT_FAILURE,
|
||||
"%s key generation:%s", keymgmt->type_name, desc);
|
||||
ERR_clear_last_mark();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -426,14 +426,20 @@ int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ERR_set_mark();
|
||||
ret = signature->digest_sign_update(pctx->op.sig.algctx, data, dsize);
|
||||
if (ret <= 0)
|
||||
if (ret <= 0 && ERR_count_to_mark() == 0)
|
||||
ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE,
|
||||
"%s digest_sign_update:%s", signature->type_name, desc);
|
||||
ERR_clear_last_mark();
|
||||
return ret;
|
||||
|
||||
legacy:
|
||||
if (pctx != NULL) {
|
||||
if (pctx->pmeth == NULL) {
|
||||
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
||||
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))
|
||||
|
@ -470,10 +476,12 @@ int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ERR_set_mark();
|
||||
ret = signature->digest_verify_update(pctx->op.sig.algctx, data, dsize);
|
||||
if (ret <= 0)
|
||||
if (ret <= 0 && ERR_count_to_mark() == 0)
|
||||
ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE,
|
||||
"%s digest_verify_update:%s", signature->type_name, desc);
|
||||
ERR_clear_last_mark();
|
||||
return ret;
|
||||
|
||||
legacy:
|
||||
|
@ -523,11 +531,13 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
|
|||
pctx = dctx;
|
||||
}
|
||||
|
||||
ERR_set_mark();
|
||||
r = signature->digest_sign_final(pctx->op.sig.algctx, sigret, siglen,
|
||||
sigret == NULL ? 0 : *siglen);
|
||||
if (!r)
|
||||
if (!r && ERR_count_to_mark() == 0)
|
||||
ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE,
|
||||
"%s digest_sign_final:%s", signature->type_name, desc);
|
||||
ERR_clear_last_mark();
|
||||
if (dctx == NULL && sigret != NULL)
|
||||
ctx->flags |= EVP_MD_CTX_FLAG_FINALISED;
|
||||
else
|
||||
|
@ -634,11 +644,13 @@ int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen,
|
|||
|
||||
if (sigret != NULL)
|
||||
ctx->flags |= EVP_MD_CTX_FLAG_FINALISED;
|
||||
ERR_set_mark();
|
||||
ret = signature->digest_sign(pctx->op.sig.algctx, sigret, siglen,
|
||||
sigret == NULL ? 0 : *siglen, tbs, tbslen);
|
||||
if (ret <= 0)
|
||||
if (ret <= 0 && ERR_count_to_mark() == 0)
|
||||
ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE,
|
||||
"%s digest_sign:%s", signature->type_name, desc);
|
||||
ERR_clear_last_mark();
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
|
@ -689,10 +701,12 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
|
|||
pctx = dctx;
|
||||
}
|
||||
|
||||
ERR_set_mark();
|
||||
r = signature->digest_verify_final(pctx->op.sig.algctx, sig, siglen);
|
||||
if (!r)
|
||||
if (!r && ERR_count_to_mark() == 0)
|
||||
ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE,
|
||||
"%s digest_verify_final:%s", signature->type_name, desc);
|
||||
ERR_clear_last_mark();
|
||||
if (dctx == NULL)
|
||||
ctx->flags |= EVP_MD_CTX_FLAG_FINALISED;
|
||||
else
|
||||
|
@ -765,10 +779,12 @@ int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret,
|
|||
int ret;
|
||||
|
||||
ctx->flags |= EVP_MD_CTX_FLAG_FINALISED;
|
||||
ERR_set_mark();
|
||||
ret = signature->digest_verify(pctx->op.sig.algctx, sigret, siglen, tbs, tbslen);
|
||||
if (ret <= 0)
|
||||
if (ret <= 0 && ERR_count_to_mark() == 0)
|
||||
ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE,
|
||||
"%s digest_verify:%s", signature->type_name, desc);
|
||||
ERR_clear_last_mark();
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -1024,12 +1024,19 @@ DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey)
|
|||
|
||||
int EVP_PKEY_get_id(const EVP_PKEY *pkey)
|
||||
{
|
||||
if (pkey->type == EVP_PKEY_KEYMGMT) {
|
||||
const char *name = EVP_KEYMGMT_get0_name(pkey->keymgmt);
|
||||
int type = evp_pkey_name2type(name);
|
||||
if (type != NID_undef)
|
||||
return type;
|
||||
}
|
||||
|
||||
return pkey->type;
|
||||
}
|
||||
|
||||
int EVP_PKEY_get_base_id(const EVP_PKEY *pkey)
|
||||
{
|
||||
return EVP_PKEY_type(pkey->type);
|
||||
return EVP_PKEY_type(EVP_PKEY_get_id(pkey));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -37,13 +37,16 @@ struct added_obj_st {
|
|||
ASN1_OBJECT *obj;
|
||||
};
|
||||
|
||||
static unsigned long added_obj_hash(const ADDED_OBJ *ca);
|
||||
static int added_obj_cmp(const ADDED_OBJ *ca, const ADDED_OBJ *cb);
|
||||
|
||||
static LHASH_OF(ADDED_OBJ) *added = NULL;
|
||||
static CRYPTO_RWLOCK *ossl_obj_lock = NULL;
|
||||
#ifdef TSAN_REQUIRES_LOCKING
|
||||
static CRYPTO_RWLOCK *ossl_obj_nid_lock = NULL;
|
||||
#endif
|
||||
|
||||
static CRYPTO_ONCE ossl_obj_lock_init = CRYPTO_ONCE_STATIC_INIT;
|
||||
static CRYPTO_ONCE ossl_obj_api_init = CRYPTO_ONCE_STATIC_INIT;
|
||||
|
||||
static ossl_inline void objs_free_locks(void)
|
||||
{
|
||||
|
@ -55,7 +58,7 @@ static ossl_inline void objs_free_locks(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
DEFINE_RUN_ONCE_STATIC(obj_lock_initialise)
|
||||
DEFINE_RUN_ONCE_STATIC(obj_api_initialise)
|
||||
{
|
||||
ossl_obj_lock = CRYPTO_THREAD_lock_new();
|
||||
if (ossl_obj_lock == NULL)
|
||||
|
@ -68,40 +71,41 @@ DEFINE_RUN_ONCE_STATIC(obj_lock_initialise)
|
|||
return 0;
|
||||
}
|
||||
#endif
|
||||
added = lh_ADDED_OBJ_new(added_obj_hash, added_obj_cmp);
|
||||
if (added == NULL) {
|
||||
objs_free_locks();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ossl_inline int ossl_init_added_lock(void)
|
||||
static ossl_inline int ossl_init_added_api(void)
|
||||
{
|
||||
#ifndef OPENSSL_NO_AUTOLOAD_CONFIG
|
||||
/* Make sure we've loaded config before checking for any "added" objects */
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
|
||||
#endif
|
||||
return RUN_ONCE(&ossl_obj_lock_init, obj_lock_initialise);
|
||||
return RUN_ONCE(&ossl_obj_api_init, obj_api_initialise);
|
||||
}
|
||||
|
||||
static ossl_inline int ossl_obj_write_lock(int lock)
|
||||
static ossl_inline int ossl_obj_write_lock(void)
|
||||
{
|
||||
if (!lock)
|
||||
return 1;
|
||||
if (!ossl_init_added_lock())
|
||||
if (!ossl_init_added_api())
|
||||
return 0;
|
||||
return CRYPTO_THREAD_write_lock(ossl_obj_lock);
|
||||
}
|
||||
|
||||
static ossl_inline int ossl_obj_read_lock(int lock)
|
||||
static ossl_inline int ossl_obj_read_lock(void)
|
||||
{
|
||||
if (!lock)
|
||||
return 1;
|
||||
if (!ossl_init_added_lock())
|
||||
if (!ossl_init_added_api())
|
||||
return 0;
|
||||
return CRYPTO_THREAD_read_lock(ossl_obj_lock);
|
||||
}
|
||||
|
||||
static ossl_inline void ossl_obj_unlock(int lock)
|
||||
static ossl_inline void ossl_obj_unlock(void)
|
||||
{
|
||||
if (lock)
|
||||
CRYPTO_THREAD_unlock(ossl_obj_lock);
|
||||
CRYPTO_THREAD_unlock(ossl_obj_lock);
|
||||
}
|
||||
|
||||
static int sn_cmp(const ASN1_OBJECT *const *a, const unsigned int *b)
|
||||
|
@ -221,112 +225,22 @@ void ossl_obj_cleanup_int(void)
|
|||
objs_free_locks();
|
||||
}
|
||||
|
||||
/*
|
||||
* Requires that the ossl_obj_lock be held
|
||||
* if TSAN_REQUIRES_LOCKING defined
|
||||
*/
|
||||
static int obj_new_nid_unlocked(int num)
|
||||
int OBJ_new_nid(int num)
|
||||
{
|
||||
static TSAN_QUALIFIER int new_nid = NUM_NID;
|
||||
#ifdef TSAN_REQUIRES_LOCKING
|
||||
int i;
|
||||
|
||||
ossl_obj_write_lock();
|
||||
i = new_nid;
|
||||
new_nid += num;
|
||||
|
||||
ossl_obj_unlock();
|
||||
return i;
|
||||
#else
|
||||
return tsan_add(&new_nid, num);
|
||||
#endif
|
||||
}
|
||||
|
||||
int OBJ_new_nid(int num)
|
||||
{
|
||||
#ifdef TSAN_REQUIRES_LOCKING
|
||||
int i;
|
||||
|
||||
if (!ossl_obj_write_lock(1)) {
|
||||
ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
|
||||
return NID_undef;
|
||||
}
|
||||
|
||||
i = obj_new_nid_unlocked(num);
|
||||
|
||||
ossl_obj_unlock(1);
|
||||
|
||||
return i;
|
||||
#else
|
||||
return obj_new_nid_unlocked(num);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int ossl_obj_add_object(const ASN1_OBJECT *obj, int lock)
|
||||
{
|
||||
ASN1_OBJECT *o = NULL;
|
||||
ADDED_OBJ *ao[4] = { NULL, NULL, NULL, NULL }, *aop[4];
|
||||
int i;
|
||||
|
||||
if ((o = OBJ_dup(obj)) == NULL)
|
||||
return NID_undef;
|
||||
if ((ao[ADDED_NID] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL
|
||||
|| (o->length != 0
|
||||
&& obj->data != NULL
|
||||
&& (ao[ADDED_DATA] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL)
|
||||
|| (o->sn != NULL
|
||||
&& (ao[ADDED_SNAME] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL)
|
||||
|| (o->ln != NULL
|
||||
&& (ao[ADDED_LNAME] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL))
|
||||
goto err2;
|
||||
|
||||
if (!ossl_obj_write_lock(lock)) {
|
||||
ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
|
||||
goto err2;
|
||||
}
|
||||
if (added == NULL) {
|
||||
added = lh_ADDED_OBJ_new(added_obj_hash, added_obj_cmp);
|
||||
if (added == NULL) {
|
||||
ERR_raise(ERR_LIB_OBJ, ERR_R_CRYPTO_LIB);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = ADDED_DATA; i <= ADDED_NID; i++) {
|
||||
if (ao[i] != NULL) {
|
||||
ao[i]->type = i;
|
||||
ao[i]->obj = o;
|
||||
aop[i] = lh_ADDED_OBJ_retrieve(added, ao[i]);
|
||||
if (aop[i] != NULL)
|
||||
aop[i]->type = -1;
|
||||
(void)lh_ADDED_OBJ_insert(added, ao[i]);
|
||||
if (lh_ADDED_OBJ_error(added)) {
|
||||
if (aop[i] != NULL)
|
||||
aop[i]->type = i;
|
||||
while (i-- > ADDED_DATA) {
|
||||
lh_ADDED_OBJ_delete(added, ao[i]);
|
||||
if (aop[i] != NULL)
|
||||
aop[i]->type = i;
|
||||
}
|
||||
ERR_raise(ERR_LIB_OBJ, ERR_R_CRYPTO_LIB);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
o->flags &=
|
||||
~(ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
|
||||
ASN1_OBJECT_FLAG_DYNAMIC_DATA);
|
||||
|
||||
ossl_obj_unlock(lock);
|
||||
return o->nid;
|
||||
|
||||
err:
|
||||
ossl_obj_unlock(lock);
|
||||
err2:
|
||||
for (i = ADDED_DATA; i <= ADDED_NID; i++)
|
||||
OPENSSL_free(ao[i]);
|
||||
ASN1_OBJECT_free(o);
|
||||
return NID_undef;
|
||||
}
|
||||
|
||||
ASN1_OBJECT *OBJ_nid2obj(int n)
|
||||
{
|
||||
ADDED_OBJ ad, *adp = NULL;
|
||||
|
@ -339,13 +253,12 @@ ASN1_OBJECT *OBJ_nid2obj(int n)
|
|||
ad.type = ADDED_NID;
|
||||
ad.obj = &ob;
|
||||
ob.nid = n;
|
||||
if (!ossl_obj_read_lock(1)) {
|
||||
if (!ossl_obj_read_lock()) {
|
||||
ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_READ_LOCK);
|
||||
return NULL;
|
||||
}
|
||||
if (added != NULL)
|
||||
adp = lh_ADDED_OBJ_retrieve(added, &ad);
|
||||
ossl_obj_unlock(1);
|
||||
adp = lh_ADDED_OBJ_retrieve(added, &ad);
|
||||
ossl_obj_unlock();
|
||||
if (adp != NULL)
|
||||
return adp->obj;
|
||||
|
||||
|
@ -383,7 +296,7 @@ static int obj_cmp(const ASN1_OBJECT *const *ap, const unsigned int *bp)
|
|||
|
||||
IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, obj);
|
||||
|
||||
static int ossl_obj_obj2nid(const ASN1_OBJECT *a, const int lock)
|
||||
static int ossl_obj_obj2nid(const ASN1_OBJECT *a)
|
||||
{
|
||||
int nid = NID_undef;
|
||||
const unsigned int *op;
|
||||
|
@ -399,18 +312,16 @@ static int ossl_obj_obj2nid(const ASN1_OBJECT *a, const int lock)
|
|||
op = OBJ_bsearch_obj(&a, obj_objs, NUM_OBJ);
|
||||
if (op != NULL)
|
||||
return nid_objs[*op].nid;
|
||||
if (!ossl_obj_read_lock(lock)) {
|
||||
if (!ossl_obj_read_lock()) {
|
||||
ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_READ_LOCK);
|
||||
return NID_undef;
|
||||
}
|
||||
if (added != NULL) {
|
||||
ad.type = ADDED_DATA;
|
||||
ad.obj = (ASN1_OBJECT *)a; /* casting away const is harmless here */
|
||||
adp = lh_ADDED_OBJ_retrieve(added, &ad);
|
||||
if (adp != NULL)
|
||||
nid = adp->obj->nid;
|
||||
}
|
||||
ossl_obj_unlock(lock);
|
||||
ad.type = ADDED_DATA;
|
||||
ad.obj = (ASN1_OBJECT *)a; /* casting away const is harmless here */
|
||||
adp = lh_ADDED_OBJ_retrieve(added, &ad);
|
||||
if (adp != NULL)
|
||||
nid = adp->obj->nid;
|
||||
ossl_obj_unlock();
|
||||
return nid;
|
||||
}
|
||||
|
||||
|
@ -645,18 +556,16 @@ int OBJ_ln2nid(const char *s)
|
|||
op = OBJ_bsearch_ln(&oo, ln_objs, NUM_LN);
|
||||
if (op != NULL)
|
||||
return nid_objs[*op].nid;
|
||||
if (!ossl_obj_read_lock(1)) {
|
||||
if (!ossl_obj_read_lock()) {
|
||||
ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_READ_LOCK);
|
||||
return NID_undef;
|
||||
}
|
||||
if (added != NULL) {
|
||||
ad.type = ADDED_LNAME;
|
||||
ad.obj = &o;
|
||||
adp = lh_ADDED_OBJ_retrieve(added, &ad);
|
||||
if (adp != NULL)
|
||||
nid = adp->obj->nid;
|
||||
}
|
||||
ossl_obj_unlock(1);
|
||||
ad.type = ADDED_LNAME;
|
||||
ad.obj = &o;
|
||||
adp = lh_ADDED_OBJ_retrieve(added, &ad);
|
||||
if (adp != NULL)
|
||||
nid = adp->obj->nid;
|
||||
ossl_obj_unlock();
|
||||
return nid;
|
||||
}
|
||||
|
||||
|
@ -672,18 +581,16 @@ int OBJ_sn2nid(const char *s)
|
|||
op = OBJ_bsearch_sn(&oo, sn_objs, NUM_SN);
|
||||
if (op != NULL)
|
||||
return nid_objs[*op].nid;
|
||||
if (!ossl_obj_read_lock(1)) {
|
||||
if (!ossl_obj_read_lock()) {
|
||||
ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_READ_LOCK);
|
||||
return NID_undef;
|
||||
}
|
||||
if (added != NULL) {
|
||||
ad.type = ADDED_SNAME;
|
||||
ad.obj = &o;
|
||||
adp = lh_ADDED_OBJ_retrieve(added, &ad);
|
||||
if (adp != NULL)
|
||||
nid = adp->obj->nid;
|
||||
}
|
||||
ossl_obj_unlock(1);
|
||||
ad.type = ADDED_SNAME;
|
||||
ad.obj = &o;
|
||||
adp = lh_ADDED_OBJ_retrieve(added, &ad);
|
||||
if (adp != NULL)
|
||||
nid = adp->obj->nid;
|
||||
ossl_obj_unlock();
|
||||
return nid;
|
||||
}
|
||||
|
||||
|
@ -808,20 +715,14 @@ int OBJ_create(const char *oid, const char *sn, const char *ln)
|
|||
}
|
||||
}
|
||||
|
||||
if (!ossl_obj_write_lock(1)) {
|
||||
ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
|
||||
ASN1_OBJECT_free(tmpoid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If NID is not NID_undef then object already exists */
|
||||
if (oid != NULL
|
||||
&& ossl_obj_obj2nid(tmpoid, 0) != NID_undef) {
|
||||
&& ossl_obj_obj2nid(tmpoid) != NID_undef) {
|
||||
ERR_raise(ERR_LIB_OBJ, OBJ_R_OID_EXISTS);
|
||||
goto err;
|
||||
}
|
||||
|
||||
tmpoid->nid = obj_new_nid_unlocked(1);
|
||||
tmpoid->nid = OBJ_new_nid(1);
|
||||
|
||||
if (tmpoid->nid == NID_undef)
|
||||
goto err;
|
||||
|
@ -829,13 +730,14 @@ int OBJ_create(const char *oid, const char *sn, const char *ln)
|
|||
tmpoid->sn = (char *)sn;
|
||||
tmpoid->ln = (char *)ln;
|
||||
|
||||
ok = ossl_obj_add_object(tmpoid, 0);
|
||||
if (OBJ_add_object(tmpoid) != NID_undef)
|
||||
ok = 1;
|
||||
|
||||
|
||||
tmpoid->sn = NULL;
|
||||
tmpoid->ln = NULL;
|
||||
|
||||
err:
|
||||
ossl_obj_unlock(1);
|
||||
ASN1_OBJECT_free(tmpoid);
|
||||
return ok;
|
||||
}
|
||||
|
@ -856,10 +758,65 @@ const unsigned char *OBJ_get0_data(const ASN1_OBJECT *obj)
|
|||
|
||||
int OBJ_add_object(const ASN1_OBJECT *obj)
|
||||
{
|
||||
return ossl_obj_add_object(obj, 1);
|
||||
ASN1_OBJECT *o = NULL;
|
||||
ADDED_OBJ *ao[4] = { NULL, NULL, NULL, NULL }, *aop[4];
|
||||
int i;
|
||||
|
||||
if ((o = OBJ_dup(obj)) == NULL)
|
||||
return NID_undef;
|
||||
if ((ao[ADDED_NID] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL
|
||||
|| (o->length != 0
|
||||
&& obj->data != NULL
|
||||
&& (ao[ADDED_DATA] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL)
|
||||
|| (o->sn != NULL
|
||||
&& (ao[ADDED_SNAME] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL)
|
||||
|| (o->ln != NULL
|
||||
&& (ao[ADDED_LNAME] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL))
|
||||
goto err2;
|
||||
|
||||
if (!ossl_obj_write_lock()) {
|
||||
ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
|
||||
goto err2;
|
||||
}
|
||||
|
||||
for (i = ADDED_DATA; i <= ADDED_NID; i++) {
|
||||
if (ao[i] != NULL) {
|
||||
ao[i]->type = i;
|
||||
ao[i]->obj = o;
|
||||
aop[i] = lh_ADDED_OBJ_retrieve(added, ao[i]);
|
||||
if (aop[i] != NULL)
|
||||
aop[i]->type = -1;
|
||||
(void)lh_ADDED_OBJ_insert(added, ao[i]);
|
||||
if (lh_ADDED_OBJ_error(added)) {
|
||||
if (aop[i] != NULL)
|
||||
aop[i]->type = i;
|
||||
while (i-- > ADDED_DATA) {
|
||||
lh_ADDED_OBJ_delete(added, ao[i]);
|
||||
if (aop[i] != NULL)
|
||||
aop[i]->type = i;
|
||||
}
|
||||
ERR_raise(ERR_LIB_OBJ, ERR_R_CRYPTO_LIB);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
o->flags &=
|
||||
~(ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
|
||||
ASN1_OBJECT_FLAG_DYNAMIC_DATA);
|
||||
|
||||
ossl_obj_unlock();
|
||||
return o->nid;
|
||||
|
||||
err:
|
||||
ossl_obj_unlock();
|
||||
err2:
|
||||
for (i = ADDED_DATA; i <= ADDED_NID; i++)
|
||||
OPENSSL_free(ao[i]);
|
||||
ASN1_OBJECT_free(o);
|
||||
return NID_undef;
|
||||
}
|
||||
|
||||
int OBJ_obj2nid(const ASN1_OBJECT *a)
|
||||
{
|
||||
return ossl_obj_obj2nid(a, 1);
|
||||
return ossl_obj_obj2nid(a);
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
*/
|
||||
|
||||
/* Serialized OID's */
|
||||
static const unsigned char so[9550] = {
|
||||
static const unsigned char so[9571] = {
|
||||
0x2A,0x86,0x48,0x86,0xF7,0x0D, /* [ 0] OBJ_rsadsi */
|
||||
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, /* [ 6] OBJ_pkcs */
|
||||
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x02, /* [ 13] OBJ_md2 */
|
||||
|
@ -1351,9 +1351,11 @@ static const unsigned char so[9550] = {
|
|||
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x1C, /* [ 9516] OBJ_HKDF_SHA256 */
|
||||
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x1D, /* [ 9527] OBJ_HKDF_SHA384 */
|
||||
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x1E, /* [ 9538] OBJ_HKDF_SHA512 */
|
||||
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x0D, /* [ 9549] OBJ_id_smime_ori */
|
||||
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x0D,0x03, /* [ 9559] OBJ_id_smime_ori_kem */
|
||||
};
|
||||
|
||||
#define NUM_NID 1499
|
||||
#define NUM_NID 1501
|
||||
static const ASN1_OBJECT nid_objs[NUM_NID] = {
|
||||
{"UNDEF", "undefined", NID_undef},
|
||||
{"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]},
|
||||
|
@ -2854,9 +2856,11 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = {
|
|||
{"id-alg-hkdf-with-sha256", "HKDF-SHA256", NID_HKDF_SHA256, 11, &so[9516]},
|
||||
{"id-alg-hkdf-with-sha384", "HKDF-SHA384", NID_HKDF_SHA384, 11, &so[9527]},
|
||||
{"id-alg-hkdf-with-sha512", "HKDF-SHA512", NID_HKDF_SHA512, 11, &so[9538]},
|
||||
{"id-smime-ori", "id-smime-ori", NID_id_smime_ori, 10, &so[9549]},
|
||||
{"id-smime-ori-kem", "id-smime-ori-kem", NID_id_smime_ori_kem, 11, &so[9559]},
|
||||
};
|
||||
|
||||
#define NUM_SN 1490
|
||||
#define NUM_SN 1492
|
||||
static const unsigned int sn_objs[NUM_SN] = {
|
||||
364, /* "AD_DVCS" */
|
||||
419, /* "AES-128-CBC" */
|
||||
|
@ -3744,6 +3748,8 @@ static const unsigned int sn_objs[NUM_SN] = {
|
|||
201, /* "id-smime-mod-ets-eSignature-97" */
|
||||
199, /* "id-smime-mod-msg-v3" */
|
||||
198, /* "id-smime-mod-oid" */
|
||||
1499, /* "id-smime-ori" */
|
||||
1500, /* "id-smime-ori-kem" */
|
||||
194, /* "id-smime-spq" */
|
||||
250, /* "id-smime-spq-ets-sqt-unotice" */
|
||||
249, /* "id-smime-spq-ets-sqt-uri" */
|
||||
|
@ -4350,7 +4356,7 @@ static const unsigned int sn_objs[NUM_SN] = {
|
|||
1289, /* "zstd" */
|
||||
};
|
||||
|
||||
#define NUM_LN 1490
|
||||
#define NUM_LN 1492
|
||||
static const unsigned int ln_objs[NUM_LN] = {
|
||||
363, /* "AD Time Stamping" */
|
||||
405, /* "ANSI X9.62" */
|
||||
|
@ -5367,6 +5373,8 @@ static const unsigned int ln_objs[NUM_LN] = {
|
|||
201, /* "id-smime-mod-ets-eSignature-97" */
|
||||
199, /* "id-smime-mod-msg-v3" */
|
||||
198, /* "id-smime-mod-oid" */
|
||||
1499, /* "id-smime-ori" */
|
||||
1500, /* "id-smime-ori-kem" */
|
||||
194, /* "id-smime-spq" */
|
||||
250, /* "id-smime-spq-ets-sqt-unotice" */
|
||||
249, /* "id-smime-spq-ets-sqt-uri" */
|
||||
|
@ -5844,7 +5852,7 @@ static const unsigned int ln_objs[NUM_LN] = {
|
|||
125, /* "zlib compression" */
|
||||
};
|
||||
|
||||
#define NUM_OBJ 1347
|
||||
#define NUM_OBJ 1349
|
||||
static const unsigned int obj_objs[NUM_OBJ] = {
|
||||
0, /* OBJ_undef 0 */
|
||||
181, /* OBJ_iso 1 */
|
||||
|
@ -7051,6 +7059,7 @@ static const unsigned int obj_objs[NUM_OBJ] = {
|
|||
193, /* OBJ_id_smime_cd 1 2 840 113549 1 9 16 4 */
|
||||
194, /* OBJ_id_smime_spq 1 2 840 113549 1 9 16 5 */
|
||||
195, /* OBJ_id_smime_cti 1 2 840 113549 1 9 16 6 */
|
||||
1499, /* OBJ_id_smime_ori 1 2 840 113549 1 9 16 13 */
|
||||
158, /* OBJ_x509Certificate 1 2 840 113549 1 9 22 1 */
|
||||
159, /* OBJ_sdsiCertificate 1 2 840 113549 1 9 22 2 */
|
||||
160, /* OBJ_x509Crl 1 2 840 113549 1 9 23 1 */
|
||||
|
@ -7169,6 +7178,7 @@ static const unsigned int obj_objs[NUM_OBJ] = {
|
|||
254, /* OBJ_id_smime_cti_ets_proofOfSender 1 2 840 113549 1 9 16 6 4 */
|
||||
255, /* OBJ_id_smime_cti_ets_proofOfApproval 1 2 840 113549 1 9 16 6 5 */
|
||||
256, /* OBJ_id_smime_cti_ets_proofOfCreation 1 2 840 113549 1 9 16 6 6 */
|
||||
1500, /* OBJ_id_smime_ori_kem 1 2 840 113549 1 9 16 13 3 */
|
||||
150, /* OBJ_keyBag 1 2 840 113549 1 12 10 1 1 */
|
||||
151, /* OBJ_pkcs8ShroudedKeyBag 1 2 840 113549 1 12 10 1 2 */
|
||||
152, /* OBJ_certBag 1 2 840 113549 1 12 10 1 3 */
|
||||
|
|
|
@ -1496,3 +1496,5 @@ aes_256_cbc_hmac_sha512_etm 1495
|
|||
HKDF_SHA256 1496
|
||||
HKDF_SHA384 1497
|
||||
HKDF_SHA512 1498
|
||||
id_smime_ori 1499
|
||||
id_smime_ori_kem 1500
|
||||
|
|
|
@ -251,6 +251,7 @@ SMIME 3 : id-smime-alg
|
|||
SMIME 4 : id-smime-cd
|
||||
SMIME 5 : id-smime-spq
|
||||
SMIME 6 : id-smime-cti
|
||||
SMIME 13 : id-smime-ori
|
||||
|
||||
# S/MIME Modules
|
||||
id-smime-mod 1 : id-smime-mod-cms
|
||||
|
@ -355,6 +356,9 @@ id-smime-cti 4 : id-smime-cti-ets-proofOfSender
|
|||
id-smime-cti 5 : id-smime-cti-ets-proofOfApproval
|
||||
id-smime-cti 6 : id-smime-cti-ets-proofOfCreation
|
||||
|
||||
# S/MIME OtherRecipientInfo Type Identifier
|
||||
id-smime-ori 3 : id-smime-ori-kem
|
||||
|
||||
pkcs9 20 : : friendlyName
|
||||
pkcs9 21 : : localKeyID
|
||||
!Alias ms-corp 1 3 6 1 4 1 311
|
||||
|
|
|
@ -375,7 +375,9 @@ int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey,
|
|||
V_ASN1_NULL, NULL))
|
||||
return 0;
|
||||
|
||||
if (EVP_PKEY_is_a(pkey, "EC") || EVP_PKEY_is_a(pkey, "DSA"))
|
||||
if (EVP_PKEY_is_a(pkey, "EC")
|
||||
|| EVP_PKEY_is_a(pkey, "DSA")
|
||||
|| EVP_PKEY_is_a(pkey, "SM2"))
|
||||
return pkcs7_ecdsa_or_dsa_sign_verify_setup(p7i, 0);
|
||||
if (EVP_PKEY_is_a(pkey, "RSA"))
|
||||
return pkcs7_rsa_sign_verify_setup(p7i, 0);
|
||||
|
|
|
@ -2419,6 +2419,11 @@ static int core_pop_error_to_mark(const OSSL_CORE_HANDLE *handle)
|
|||
return ERR_pop_to_mark();
|
||||
}
|
||||
|
||||
static int core_count_to_mark(const OSSL_CORE_HANDLE *handle)
|
||||
{
|
||||
return ERR_count_to_mark();
|
||||
}
|
||||
|
||||
static void core_indicator_get_callback(OPENSSL_CORE_CTX *libctx,
|
||||
OSSL_INDICATOR_CALLBACK **cb)
|
||||
{
|
||||
|
@ -2600,6 +2605,7 @@ static const OSSL_DISPATCH core_dispatch_[] = {
|
|||
{ 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_COUNT_TO_MARK, (void (*)(void))core_count_to_mark },
|
||||
{ OSSL_FUNC_BIO_NEW_FILE, (void (*)(void))ossl_core_bio_new_file },
|
||||
{ OSSL_FUNC_BIO_NEW_MEMBUF, (void (*)(void))ossl_core_bio_new_mem_buf },
|
||||
{ OSSL_FUNC_BIO_READ_EX, (void (*)(void))ossl_core_bio_read_ex },
|
||||
|
|
|
@ -220,6 +220,10 @@ static ECDSA_SIG *sm2_sig_gen(const EC_KEY *key, const BIGNUM *e)
|
|||
BIGNUM *tmp = NULL;
|
||||
OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key);
|
||||
|
||||
if (dA == NULL) {
|
||||
ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_PRIVATE_KEY);
|
||||
goto done;
|
||||
}
|
||||
kG = EC_POINT_new(group);
|
||||
if (kG == NULL) {
|
||||
ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB);
|
||||
|
|
|
@ -428,12 +428,6 @@ OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx)
|
|||
if (ctx->loader != NULL)
|
||||
OSSL_TRACE(STORE, "Loading next object\n");
|
||||
|
||||
if (ctx->cached_info != NULL
|
||||
&& sk_OSSL_STORE_INFO_num(ctx->cached_info) == 0) {
|
||||
sk_OSSL_STORE_INFO_free(ctx->cached_info);
|
||||
ctx->cached_info = NULL;
|
||||
}
|
||||
|
||||
if (ctx->cached_info != NULL) {
|
||||
v = sk_OSSL_STORE_INFO_shift(ctx->cached_info);
|
||||
} else {
|
||||
|
@ -556,14 +550,23 @@ int OSSL_STORE_error(OSSL_STORE_CTX *ctx)
|
|||
|
||||
int OSSL_STORE_eof(OSSL_STORE_CTX *ctx)
|
||||
{
|
||||
int ret = 1;
|
||||
int ret = 0;
|
||||
|
||||
if (ctx->fetched_loader != NULL)
|
||||
ret = ctx->loader->p_eof(ctx->loader_ctx);
|
||||
if (ctx->cached_info != NULL
|
||||
&& sk_OSSL_STORE_INFO_num(ctx->cached_info) == 0) {
|
||||
sk_OSSL_STORE_INFO_free(ctx->cached_info);
|
||||
ctx->cached_info = NULL;
|
||||
}
|
||||
|
||||
if (ctx->cached_info == NULL) {
|
||||
ret = 1;
|
||||
if (ctx->fetched_loader != NULL)
|
||||
ret = ctx->loader->p_eof(ctx->loader_ctx);
|
||||
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
||||
if (ctx->fetched_loader == NULL)
|
||||
ret = ctx->loader->eof(ctx->loader_ctx);
|
||||
if (ctx->fetched_loader == NULL)
|
||||
ret = ctx->loader->eof(ctx->loader_ctx);
|
||||
#endif
|
||||
}
|
||||
return ret != 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -174,6 +174,16 @@ const char *X509_verify_cert_error_string(long n)
|
|||
return "OCSP verification failed";
|
||||
case X509_V_ERR_OCSP_CERT_UNKNOWN:
|
||||
return "OCSP unknown cert";
|
||||
case X509_V_ERR_OCSP_RESP_INVALID:
|
||||
return "OCSP response(s) invalid";
|
||||
case X509_V_ERR_OCSP_SIGNATURE_FAILURE:
|
||||
return "OCSP response signature verification failure";
|
||||
case X509_V_ERR_OCSP_NOT_YET_VALID:
|
||||
return "OCSP response not yet valid (contains a date in the future)";
|
||||
case X509_V_ERR_OCSP_HAS_EXPIRED:
|
||||
return "OCSP response has expired";
|
||||
case X509_V_ERR_OCSP_NO_RESPONSE:
|
||||
return "no OCSP response available for certificate";
|
||||
case X509_V_ERR_UNSUPPORTED_SIGNATURE_ALGORITHM:
|
||||
return "Cannot find certificate signature algorithm";
|
||||
case X509_V_ERR_SIGNATURE_ALGORITHM_MISMATCH:
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <openssl/asn1.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/ocsp.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include "internal/dane.h"
|
||||
|
@ -55,7 +56,10 @@ static int check_name_constraints(X509_STORE_CTX *ctx);
|
|||
static int check_id(X509_STORE_CTX *ctx);
|
||||
static int check_trust(X509_STORE_CTX *ctx, int num_untrusted);
|
||||
static int check_revocation(X509_STORE_CTX *ctx);
|
||||
static int check_cert(X509_STORE_CTX *ctx);
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
static int check_cert_ocsp_resp(X509_STORE_CTX *ctx);
|
||||
#endif
|
||||
static int check_cert_crl(X509_STORE_CTX *ctx);
|
||||
static int check_policy(X509_STORE_CTX *ctx);
|
||||
static int check_dane_issuer(X509_STORE_CTX *ctx, int depth);
|
||||
static int check_cert_key_level(X509_STORE_CTX *ctx, X509 *cert);
|
||||
|
@ -184,6 +188,24 @@ static int verify_cb_crl(X509_STORE_CTX *ctx, int err)
|
|||
return ctx->verify_cb(0, ctx);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
/*
|
||||
* Inform the verify callback of an error, OCSP-specific variant.
|
||||
* It is called also on OCSP response errors, if the
|
||||
* X509_V_FLAG_OCSP_RESP_CHECK or X509_V_FLAG_OCSP_RESP_CHECK_ALL flag
|
||||
* is set.
|
||||
* Here, the error depth and certificate are already set, we just specify
|
||||
* the error number.
|
||||
*
|
||||
* Returns 0 to abort verification with an error, non-zero to continue.
|
||||
*/
|
||||
static int verify_cb_ocsp(X509_STORE_CTX *ctx, int err)
|
||||
{
|
||||
ctx->error = err;
|
||||
return ctx->verify_cb(0, ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Sadly, returns 0 also on internal error in ctx->verify_cb(). */
|
||||
static int check_auth_level(X509_STORE_CTX *ctx)
|
||||
{
|
||||
|
@ -225,7 +247,6 @@ static int verify_rpk(X509_STORE_CTX *ctx)
|
|||
return !!ctx->verify_cb(ctx->error == X509_V_OK, ctx);
|
||||
}
|
||||
|
||||
|
||||
/*-
|
||||
* Returns -1 on internal error.
|
||||
* Sadly, returns 0 also on internal error in ctx->verify_cb().
|
||||
|
@ -1037,28 +1058,209 @@ static int check_trust(X509_STORE_CTX *ctx, int num_untrusted)
|
|||
static int check_revocation(X509_STORE_CTX *ctx)
|
||||
{
|
||||
int i = 0, last = 0, ok = 0;
|
||||
int crl_check_enabled =
|
||||
(ctx->param->flags &
|
||||
(X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL)) != 0;
|
||||
int crl_check_all_enabled =
|
||||
(ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL) != 0;
|
||||
int ocsp_check_enabled =
|
||||
(ctx->param->flags &
|
||||
(X509_V_FLAG_OCSP_RESP_CHECK | X509_V_FLAG_OCSP_RESP_CHECK_ALL)) != 0;
|
||||
int ocsp_check_all_enabled =
|
||||
(ctx->param->flags & X509_V_FLAG_OCSP_RESP_CHECK_ALL) != 0;
|
||||
|
||||
if ((ctx->param->flags & X509_V_FLAG_CRL_CHECK) == 0)
|
||||
if (!crl_check_enabled && !ocsp_check_enabled)
|
||||
return 1;
|
||||
if ((ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL) != 0) {
|
||||
last = sk_X509_num(ctx->chain) - 1;
|
||||
} else {
|
||||
/* If checking CRL paths this isn't the EE certificate */
|
||||
if (ctx->parent != NULL)
|
||||
return 1;
|
||||
last = 0;
|
||||
|
||||
if (ocsp_check_enabled) {
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
/*
|
||||
* certificate status checking with OCSP
|
||||
*/
|
||||
if (ocsp_check_all_enabled)
|
||||
last = sk_X509_num(ctx->chain) - 1;
|
||||
else if (!crl_check_all_enabled && ctx->parent != NULL)
|
||||
return 1; /* If checking CRL paths this isn't the EE certificate */
|
||||
|
||||
for (i = 0; i <= last; i++) {
|
||||
ctx->error_depth = i;
|
||||
ctx->current_cert = sk_X509_value(ctx->chain, i);
|
||||
|
||||
/* skip if cert is apparently self-signed */
|
||||
if (ctx->current_cert->ex_flags & EXFLAG_SS)
|
||||
continue;
|
||||
|
||||
/* the issuer certificate is the next in the chain */
|
||||
ctx->current_issuer = sk_X509_value(ctx->chain, i + 1);
|
||||
|
||||
ok = check_cert_ocsp_resp(ctx);
|
||||
|
||||
/*
|
||||
* In the case the certificate status is REVOKED, the verification
|
||||
* can stop here.
|
||||
*/
|
||||
if (ok == V_OCSP_CERTSTATUS_REVOKED) {
|
||||
return verify_cb_ocsp(ctx, ctx->error != 0
|
||||
? ctx->error
|
||||
: X509_V_ERR_OCSP_VERIFY_FAILED);
|
||||
}
|
||||
|
||||
/*
|
||||
* In the case the certificate status is GOOD, continue with the next
|
||||
* certificate.
|
||||
*/
|
||||
if (ok == V_OCSP_CERTSTATUS_GOOD)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* As stated in RFC 6961 section 2.2:
|
||||
* If OCSP is not enabled or the client receives a "ocsp_response_list"
|
||||
* that does not contain a response for one or more of the certificates
|
||||
* in the completed certificate chain, the client SHOULD attempt to
|
||||
* validate the certificate using an alternative retrieval method,
|
||||
* such as downloading the relevant CRL;
|
||||
*/
|
||||
if (crl_check_all_enabled || (crl_check_enabled && i == 0)) {
|
||||
ok = check_cert_crl(ctx);
|
||||
if (!ok)
|
||||
return ok;
|
||||
} else {
|
||||
ok = verify_cb_ocsp(ctx, X509_V_ERR_OCSP_VERIFY_FAILED);
|
||||
if (!ok)
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
for (i = 0; i <= last; i++) {
|
||||
ctx->error_depth = i;
|
||||
ok = check_cert(ctx);
|
||||
if (!ok)
|
||||
return ok;
|
||||
|
||||
if (crl_check_enabled && !ocsp_check_all_enabled) {
|
||||
/* certificate status check with CRLs */
|
||||
if (crl_check_all_enabled) {
|
||||
last = sk_X509_num(ctx->chain) - 1;
|
||||
} else {
|
||||
/* If checking CRL paths this isn't the EE certificate */
|
||||
if (ctx->parent != NULL)
|
||||
return 1;
|
||||
last = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* in the case that OCSP is only enabled for the server certificate
|
||||
* and CRL for the complete chain, the rest of the chain has to be
|
||||
* checked here
|
||||
*/
|
||||
if (ocsp_check_enabled && crl_check_all_enabled)
|
||||
i = 1;
|
||||
else
|
||||
i = 0;
|
||||
for (; i <= last; i++) {
|
||||
ctx->error_depth = i;
|
||||
ok = check_cert_crl(ctx);
|
||||
if (!ok)
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
static int check_cert_ocsp_resp(X509_STORE_CTX *ctx)
|
||||
{
|
||||
int cert_status, crl_reason;
|
||||
int i;
|
||||
OCSP_RESPONSE *resp = NULL;
|
||||
OCSP_BASICRESP *bs = NULL;
|
||||
OCSP_SINGLERESP *sr = NULL;
|
||||
OCSP_CERTID *sr_cert_id = NULL;
|
||||
ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
|
||||
ASN1_OBJECT *cert_id_md_oid;
|
||||
EVP_MD *cert_id_md;
|
||||
OCSP_CERTID *cert_id = NULL;
|
||||
int ret = V_OCSP_CERTSTATUS_UNKNOWN;
|
||||
int num;
|
||||
|
||||
num = sk_OCSP_RESPONSE_num(ctx->ocsp_resp);
|
||||
|
||||
if (num < 0 || num <= ctx->error_depth)
|
||||
return X509_V_ERR_OCSP_NO_RESPONSE;
|
||||
|
||||
if ((resp = sk_OCSP_RESPONSE_value(ctx->ocsp_resp, ctx->error_depth)) == NULL
|
||||
|| (bs = OCSP_response_get1_basic(resp)) == NULL
|
||||
|| (num = OCSP_resp_count(bs)) < 1)
|
||||
return X509_V_ERR_OCSP_NO_RESPONSE;
|
||||
|
||||
if (OCSP_response_status(resp) != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
|
||||
OCSP_BASICRESP_free(bs);
|
||||
ret = X509_V_ERR_OCSP_RESP_INVALID;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (OCSP_basic_verify(bs, ctx->chain, ctx->store, OCSP_TRUSTOTHER) <= 0) {
|
||||
ret = X509_V_ERR_OCSP_SIGNATURE_FAILURE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* find the right single response in the OCSP response */
|
||||
for (i = 0; i < num; i++) {
|
||||
sr = OCSP_resp_get0(bs, i);
|
||||
|
||||
/* determine the md algorithm which was used to create cert id */
|
||||
sr_cert_id = (OCSP_CERTID *)OCSP_SINGLERESP_get0_id(sr);
|
||||
OCSP_id_get0_info(NULL, &cert_id_md_oid, NULL, NULL, sr_cert_id);
|
||||
if (cert_id_md_oid != NULL)
|
||||
cert_id_md = (EVP_MD *)EVP_get_digestbyobj(cert_id_md_oid);
|
||||
else
|
||||
cert_id_md = NULL;
|
||||
|
||||
/* search the stack for the requested OCSP response */
|
||||
cert_id = OCSP_cert_to_id(cert_id_md, ctx->current_cert, ctx->current_issuer);
|
||||
if (cert_id == NULL) {
|
||||
ret = X509_V_ERR_OCSP_RESP_INVALID;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!OCSP_id_cmp(cert_id, sr_cert_id))
|
||||
break;
|
||||
|
||||
OCSP_CERTID_free(cert_id);
|
||||
cert_id = NULL;
|
||||
}
|
||||
|
||||
if (cert_id == NULL) {
|
||||
ret = X509_V_ERR_OCSP_NO_RESPONSE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (OCSP_resp_find_status(bs, cert_id, &cert_status, &crl_reason, &rev,
|
||||
&thisupd, &nextupd) <= 0) {
|
||||
ret = X509_V_ERR_OCSP_RESP_INVALID;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (cert_status == V_OCSP_CERTSTATUS_GOOD) {
|
||||
/*
|
||||
* Note:
|
||||
* A OCSP stapling result will be accepted up to 5 minutes
|
||||
* after it expired!
|
||||
*/
|
||||
if (!OCSP_check_validity(thisupd, nextupd, 300L, -1L))
|
||||
ret = X509_V_ERR_OCSP_HAS_EXPIRED;
|
||||
else
|
||||
ret = V_OCSP_CERTSTATUS_GOOD;
|
||||
} else {
|
||||
ret = cert_status;
|
||||
}
|
||||
|
||||
end:
|
||||
OCSP_CERTID_free(cert_id);
|
||||
OCSP_BASICRESP_free(bs);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Sadly, returns 0 also on internal error. */
|
||||
static int check_cert(X509_STORE_CTX *ctx)
|
||||
static int check_cert_crl(X509_STORE_CTX *ctx)
|
||||
{
|
||||
X509_CRL *crl = NULL, *dcrl = NULL;
|
||||
int ok = 0;
|
||||
|
@ -1070,6 +1272,9 @@ static int check_cert(X509_STORE_CTX *ctx)
|
|||
ctx->current_crl_score = 0;
|
||||
ctx->current_reasons = 0;
|
||||
|
||||
/* skip if cert is apparently self-signed */
|
||||
if (ctx->current_cert->ex_flags & EXFLAG_SS)
|
||||
return 1;
|
||||
if ((x->ex_flags & EXFLAG_PROXY) != 0)
|
||||
return 1;
|
||||
|
||||
|
@ -1645,7 +1850,7 @@ static int get_crl_delta(X509_STORE_CTX *ctx,
|
|||
|
||||
sk_X509_CRL_pop_free(skcrl, X509_CRL_free);
|
||||
|
||||
done:
|
||||
done:
|
||||
/* If we got any kind of CRL use it and return success */
|
||||
if (crl != NULL) {
|
||||
ctx->current_issuer = issuer;
|
||||
|
@ -2374,6 +2579,13 @@ void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk)
|
|||
ctx->crls = sk;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
void X509_STORE_CTX_set_ocsp_resp(X509_STORE_CTX *ctx, STACK_OF(OCSP_RESPONSE) *sk)
|
||||
{
|
||||
ctx->ocsp_resp = sk;
|
||||
}
|
||||
#endif
|
||||
|
||||
int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose)
|
||||
{
|
||||
/*
|
||||
|
@ -2490,7 +2702,6 @@ void X509_STORE_CTX_free(X509_STORE_CTX *ctx)
|
|||
OPENSSL_free(ctx);
|
||||
}
|
||||
|
||||
|
||||
int X509_STORE_CTX_init_rpk(X509_STORE_CTX *ctx, X509_STORE *store, EVP_PKEY *rpk)
|
||||
{
|
||||
if (!X509_STORE_CTX_init(ctx, store, NULL, NULL))
|
||||
|
@ -2531,6 +2742,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
|
|||
ctx->rpk = NULL;
|
||||
/* Zero ex_data to make sure we're cleanup-safe */
|
||||
memset(&ctx->ex_data, 0, sizeof(ctx->ex_data));
|
||||
ctx->ocsp_resp = NULL;
|
||||
|
||||
/* store->cleanup is always 0 in OpenSSL, if set must be idempotent */
|
||||
if (store != NULL)
|
||||
|
@ -2690,7 +2902,7 @@ void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags,
|
|||
void X509_STORE_CTX_set_current_reasons(X509_STORE_CTX *ctx,
|
||||
unsigned int current_reasons)
|
||||
{
|
||||
ctx->current_reasons = current_reasons;
|
||||
ctx->current_reasons = current_reasons;
|
||||
}
|
||||
|
||||
X509 *X509_STORE_CTX_get0_cert(const X509_STORE_CTX *ctx)
|
||||
|
@ -2767,7 +2979,7 @@ X509_STORE_CTX_get_crl_fn X509_STORE_CTX_get_get_crl(const X509_STORE_CTX *ctx)
|
|||
void X509_STORE_CTX_set_get_crl(X509_STORE_CTX *ctx,
|
||||
X509_STORE_CTX_get_crl_fn get_crl)
|
||||
{
|
||||
ctx->get_crl = get_crl;
|
||||
ctx->get_crl = get_crl;
|
||||
}
|
||||
|
||||
X509_STORE_CTX_check_crl_fn
|
||||
|
|
|
@ -289,6 +289,7 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
|||
static int setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp)
|
||||
{
|
||||
int idp_only = 0;
|
||||
int ret = 0;
|
||||
|
||||
/* Set various flags according to IDP */
|
||||
crl->idp_flags |= IDP_PRESENT;
|
||||
|
@ -320,7 +321,17 @@ static int setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp)
|
|||
crl->idp_reasons &= CRLDP_ALL_REASONS;
|
||||
}
|
||||
|
||||
return DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl));
|
||||
ret = DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl));
|
||||
|
||||
/*
|
||||
* RFC5280 specifies that if onlyContainsUserCerts, onlyContainsCACerts,
|
||||
* indirectCRL, and OnlyContainsAttributeCerts are all FALSE, there must
|
||||
* be either a distributionPoint field or an onlySomeReasons field present.
|
||||
*/
|
||||
if (crl->idp_flags == IDP_PRESENT && idp->distpoint == NULL)
|
||||
crl->idp_flags |= IDP_INVALID;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ASN1_SEQUENCE_ref(X509_CRL, crl_cb) = {
|
||||
|
|
|
@ -75,6 +75,8 @@ Encryption options:
|
|||
[B<-aes256-wrap>]
|
||||
[B<-des3-wrap>]
|
||||
[B<-debug_decrypt>]
|
||||
[B<-recip_kdf> I<kdf>]
|
||||
[B<-recip_ukm> I<ukm>]
|
||||
|
||||
Signing options:
|
||||
|
||||
|
@ -450,6 +452,19 @@ Depending on the OpenSSL build options used, B<-des3-wrap> may not be supported.
|
|||
This option sets the B<CMS_DEBUG_DECRYPT> flag. This option should be used
|
||||
with caution: see the notes section below.
|
||||
|
||||
=item B<-recip_kdf>
|
||||
|
||||
This option sets the KDF used to generate the key encryption key in the
|
||||
B<KEMRecipientInfo> type. Any KDF that takes B<OSSL_KDF_PARAM_KEY> and
|
||||
B<OSSL_KDF_PARAM_INFO> parameters and is otherwise fully defined by its name or
|
||||
OID can be used, for example B<HKDF-SHA256>.
|
||||
|
||||
=item B<-recip_ukm>
|
||||
|
||||
This option sets the B<KEMRecipientInfo> type's optional user keying material (UKM)
|
||||
in hexadecimal form. The UKM will be encoded, along with other information, into the
|
||||
B<OSSL_KDF_PARAM_INFO> parameter of the B<KEMRecipientInfo> type's KDF.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Signing options
|
||||
|
@ -937,6 +952,8 @@ The B<-engine> option was deprecated in OpenSSL 3.0.
|
|||
|
||||
The B<-digest> option was added in OpenSSL 3.2.
|
||||
|
||||
The B<-recip_kdf> and B<-recip_ukm> options were added in OpenSSL 3.6.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2008-2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
|
|
|
@ -133,6 +133,13 @@ By default, this command only lists each directory as it is processed.
|
|||
The path to an executable to use to generate hashes and
|
||||
fingerprints (see above).
|
||||
|
||||
=item B<PATH>
|
||||
|
||||
List of paths, separated by colons (or semicolons, on Windows platforms),
|
||||
where the B<openssl> executable is searched in case the path to the hash
|
||||
generating executable is not provided in the B<OPENSSL> environment variable
|
||||
or it is not usable (that is, does not exist or is not executable).
|
||||
|
||||
=item B<SSL_CERT_DIR>
|
||||
|
||||
Colon separated list of directories to operate on.
|
||||
|
|
|
@ -94,6 +94,8 @@ B<openssl> B<s_client>
|
|||
[B<-sess_in> I<filename>]
|
||||
[B<-serverinfo> I<types>]
|
||||
[B<-status>]
|
||||
[B<-ocsp_check_leaf>]
|
||||
[B<-ocsp_check_all>]
|
||||
[B<-alpn> I<protocols>]
|
||||
[B<-nextprotoneg> I<protocols>]
|
||||
[B<-ct>]
|
||||
|
@ -671,6 +673,24 @@ file.
|
|||
Sends a certificate status request to the server (OCSP stapling). The server
|
||||
response (if any) is printed out.
|
||||
|
||||
=item B<-ocsp_check_leaf>
|
||||
|
||||
Require performing server (end-entity) certificate status checking, where any
|
||||
OCSP response provided in the TLS handshake (by so-called "OCSP stapling") is tried
|
||||
first.
|
||||
If no valid and conclusive OCSP response can be found, CRL-based checking
|
||||
is attempted as fallback if enabled, otherwise the status check fails.
|
||||
|
||||
This implies B<-status>.
|
||||
|
||||
=item B<-ocsp_check_all>
|
||||
|
||||
As the option before, but require performing certificate status checking also
|
||||
for the issuer chain of the server certificate (i.e., intermediate CA certificates,
|
||||
excluding the trust anchor).
|
||||
|
||||
This implies the B<-status> and B<-ocsp_check_leaf>.
|
||||
|
||||
=item B<-alpn> I<protocols>, B<-nextprotoneg> I<protocols>
|
||||
|
||||
These flags enable the Enable the Application-Layer Protocol Negotiation
|
||||
|
@ -1023,6 +1043,11 @@ B<-no_tx_cert_comp>,
|
|||
and B<-tfo>
|
||||
options were added in OpenSSL 3.2.
|
||||
|
||||
The
|
||||
<-ocsp_check_leaf>
|
||||
and B<-ocsp_check_all>
|
||||
options were added in OpenSSL 3.6.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
|
|
|
@ -74,6 +74,7 @@ B<openssl> B<s_server>
|
|||
[B<-no_ign_eof>]
|
||||
[B<-no_ems>]
|
||||
[B<-status>]
|
||||
[B<-status_all>]
|
||||
[B<-status_verbose>]
|
||||
[B<-status_timeout> I<int>]
|
||||
[B<-proxy> I<[http[s]://][userinfo@]host[:port][/path][?query][#fragment]>]
|
||||
|
@ -487,7 +488,15 @@ Disable Extended master secret negotiation.
|
|||
|
||||
=item B<-status>
|
||||
|
||||
Enables certificate status request support (aka OCSP stapling).
|
||||
Enables certificate status request support (aka OCSP stapling):
|
||||
an OCSP response is provided for the leaf (server) certificate
|
||||
if requested by the client side.
|
||||
|
||||
=item B<-status_all>
|
||||
|
||||
Like before, but for TLS v1.3 and beyond, status responses for all
|
||||
certificates in the chain (except the trust anchor) are provided
|
||||
if requested by the client side.
|
||||
|
||||
=item B<-status_verbose>
|
||||
|
||||
|
@ -530,6 +539,8 @@ Any given query component is handled as part of the path component.
|
|||
|
||||
Overrides any OCSP responder URLs from the certificate and always provides the
|
||||
OCSP Response stored in the file. The file must be in DER format.
|
||||
This option may be used multiple times to specify OCSP responses for all
|
||||
certificates in the server certificate chain.
|
||||
|
||||
=item B<-ssl_config> I<val>
|
||||
|
||||
|
@ -925,6 +936,8 @@ B<-no_tx_cert_comp>,
|
|||
and B<-tfo>
|
||||
options were added in OpenSSL 3.2.
|
||||
|
||||
The B<-status_all> option was added in OpenSSL 3.6.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
|
|
|
@ -134,6 +134,18 @@ See L<openssl(1)/TLS Version Options>.
|
|||
|
||||
=back
|
||||
|
||||
=head1 ENVIRONMENT
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<SSL_CIPHER>
|
||||
|
||||
If the B<-cipher> option is not specified, the contents of this environment
|
||||
variable are used to modify the TLSv1.2 and below cipher list sent
|
||||
by the client the same way the aforementioned option does.
|
||||
|
||||
=back
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
This command can be used to measure the performance of an SSL connection.
|
||||
|
|
|
@ -30,7 +30,8 @@ The originator-related fields are relevant only in case when the keyAgreement
|
|||
method of providing of the shared key is in use.
|
||||
|
||||
CMS_add1_recipient_cert() adds recipient B<recip> to CMS_ContentInfo enveloped
|
||||
data structure B<cms> as a KeyTransRecipientInfo structure.
|
||||
data structure B<cms> as a KeyTransRecipientInfo or KEMRecipientInfo structure,
|
||||
or as a KeyAgreeRecipientInfo structure with an ephemeral key.
|
||||
|
||||
CMS_add0_recipient_key() adds symmetric key B<key> of length B<keylen> using
|
||||
wrapping algorithm B<nid>, identifier B<id> of length B<idlen> and optional
|
||||
|
|
|
@ -78,10 +78,12 @@ BIO_new_CMS().
|
|||
|
||||
The recipients specified in B<certs> use a CMS KeyTransRecipientInfo info
|
||||
structure. KEKRecipientInfo is also supported using the flag B<CMS_PARTIAL>
|
||||
and CMS_add0_recipient_key().
|
||||
and CMS_add0_recipient_key(). KEMRecipientInfo is also supported using the
|
||||
flag B<CMS_PARTIAL> and CMS_add1_recipient().
|
||||
|
||||
The parameter B<certs> may be NULL if B<CMS_PARTIAL> is set and recipients
|
||||
added later using CMS_add1_recipient_cert() or CMS_add0_recipient_key().
|
||||
are added later using CMS_add1_recipient() or CMS_add1_recipient_cert() with
|
||||
CMS_add0_recipient_key().
|
||||
|
||||
CMS_encrypt() is similar to CMS_encrypt_ex() but uses default values
|
||||
of NULL for the library context I<libctx> and the property query I<propq>.
|
||||
|
@ -104,7 +106,7 @@ The B<CMS_STREAM> flag was first supported in OpenSSL 1.0.0.
|
|||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
Copyright 2008-2025 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
|
||||
|
|
|
@ -6,9 +6,12 @@ CMS_get0_RecipientInfos, CMS_RecipientInfo_type,
|
|||
CMS_RecipientInfo_ktri_get0_signer_id, CMS_RecipientInfo_ktri_cert_cmp,
|
||||
CMS_RecipientInfo_set0_pkey, CMS_RecipientInfo_kekri_get0_id,
|
||||
CMS_RecipientInfo_kari_set0_pkey_and_peer,
|
||||
CMS_RecipientInfo_kari_set0_pkey,
|
||||
CMS_RecipientInfo_kari_set0_pkey, CMS_RecipientInfo_kari_get0_ctx,
|
||||
CMS_RecipientInfo_kekri_id_cmp, CMS_RecipientInfo_set0_key,
|
||||
CMS_RecipientInfo_decrypt, CMS_RecipientInfo_encrypt
|
||||
CMS_RecipientInfo_kemri_cert_cmp, CMS_RecipientInfo_kemri_set0_pkey,
|
||||
CMS_RecipientInfo_kemri_get0_ctx, CMS_RecipientInfo_kemri_get0_kdf_alg,
|
||||
CMS_RecipientInfo_kemri_set_ukm, CMS_RecipientInfo_decrypt,
|
||||
CMS_RecipientInfo_encrypt
|
||||
- CMS envelopedData RecipientInfo routines
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
@ -27,6 +30,7 @@ CMS_RecipientInfo_decrypt, CMS_RecipientInfo_encrypt
|
|||
int CMS_RecipientInfo_kari_set0_pkey_and_peer(CMS_RecipientInfo *ri,
|
||||
EVP_PKEY *pk, X509 *peer);
|
||||
int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk);
|
||||
EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri);
|
||||
int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri, X509_ALGOR **palg,
|
||||
ASN1_OCTET_STRING **pid,
|
||||
ASN1_GENERALIZEDTIME **pdate,
|
||||
|
@ -36,6 +40,13 @@ CMS_RecipientInfo_decrypt, CMS_RecipientInfo_encrypt
|
|||
const unsigned char *id, size_t idlen);
|
||||
int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri,
|
||||
unsigned char *key, size_t keylen);
|
||||
int CMS_RecipientInfo_kemri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert);
|
||||
int CMS_RecipientInfo_kemri_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk);
|
||||
EVP_CIPHER_CTX *CMS_RecipientInfo_kemri_get0_ctx(CMS_RecipientInfo *ri);
|
||||
X509_ALGOR *CMS_RecipientInfo_kemri_get0_kdf_alg(CMS_RecipientInfo *ri);
|
||||
int CMS_RecipientInfo_kemri_set_ukm(CMS_RecipientInfo *ri,
|
||||
const unsigned char *ukm,
|
||||
int ukmLength);
|
||||
|
||||
int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri);
|
||||
int CMS_RecipientInfo_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri);
|
||||
|
@ -47,7 +58,8 @@ structures associated with a CMS EnvelopedData structure.
|
|||
|
||||
CMS_RecipientInfo_type() returns the type of CMS_RecipientInfo structure B<ri>.
|
||||
It will currently return CMS_RECIPINFO_TRANS, CMS_RECIPINFO_AGREE,
|
||||
CMS_RECIPINFO_KEK, CMS_RECIPINFO_PASS, or CMS_RECIPINFO_OTHER.
|
||||
CMS_RECIPINFO_KEK, CMS_RECIPINFO_PASS, CMS_RECIPINFO_KEM, or
|
||||
CMS_RECIPINFO_OTHER.
|
||||
|
||||
CMS_RecipientInfo_ktri_get0_signer_id() retrieves the certificate recipient
|
||||
identifier associated with a specific CMS_RecipientInfo structure B<ri>, which
|
||||
|
@ -69,6 +81,10 @@ must be of type CMS_RECIPINFO_AGREE.
|
|||
CMS_RecipientInfo_kari_set0_pkey() associates the private key B<pkey> with the
|
||||
CMS_RecipientInfo structure B<ri>, which must be of type CMS_RECIPINFO_AGREE.
|
||||
|
||||
CMS_RecipientInfo_kari_get0_ctx() returns the EVP_CIPHER_CTX for the key
|
||||
encryption key, allowing the caller to specify the key wrap cipher. The
|
||||
CMS_RecipientInfo structure B<ri> must be of type CMS_RECIPINFO_AGREE.
|
||||
|
||||
CMS_RecipientInfo_kekri_get0_id() retrieves the key information from the
|
||||
CMS_RecipientInfo structure B<ri> which must be of type CMS_RECIPINFO_KEK. Any
|
||||
of the remaining parameters can be NULL if the application is not interested in
|
||||
|
@ -88,6 +104,27 @@ CMS_RecipientInfo_set0_key() associates the symmetric key B<key> of length
|
|||
B<keylen> with the CMS_RecipientInfo structure B<ri>, which must be of type
|
||||
CMS_RECIPINFO_KEK.
|
||||
|
||||
CMS_RecipientInfo_kemri_cert_cmp() compares the certificate B<cert> against the
|
||||
CMS_RecipientInfo structure B<ri>, which must be of type CMS_RECIPINFO_KEM.
|
||||
It returns zero if the comparison is successful and non zero if not.
|
||||
|
||||
CMS_RecipientInfo_kemri_set0_pkey() associates the private key B<pkey> with the
|
||||
CMS_RecipientInfo structure B<ri>, which must be of type CMS_RECIPINFO_KEM.
|
||||
|
||||
CMS_RecipientInfo_kemri_get0_ctx() returns the EVP_CIPHER_CTX for the key
|
||||
encryption key, allowing the caller to specify the key wrap cipher. The
|
||||
CMS_RecipientInfo structure B<ri> must be of type CMS_RECIPINFO_KEM.
|
||||
|
||||
CMS_RecipientInfo_kemri_get0_kdf_alg() returns the X509_ALGOR for the
|
||||
RecipientInfo's KDF, allowing the caller to specify the KDF algorithm. The
|
||||
CMS_RecipientInfo structure B<ri> must be of type CMS_RECIPINFO_KEM. If the
|
||||
caller doesn't specify a KDF algorithm, B<HKDF-SHA256> will be used.
|
||||
|
||||
CMS_RecipientInfo_kemri_set_ukm() sets the RecipientInfo's optional user
|
||||
keying material (UKM). The UKM is encoded, along with other information, into
|
||||
the B<OSSL_KDF_PARAM_INFO> parameter of the RecipientInfo's KDF. The
|
||||
CMS_RecipientInfo structure B<ri> must be of type CMS_RECIPINFO_KEM.
|
||||
|
||||
CMS_RecipientInfo_decrypt() attempts to decrypt CMS_RecipientInfo structure
|
||||
B<ri> in structure B<cms>. A key must have been associated with the structure
|
||||
first.
|
||||
|
@ -125,12 +162,20 @@ CMS_get0_RecipientInfos() returns all CMS_RecipientInfo structures, or NULL if
|
|||
an error occurs.
|
||||
|
||||
CMS_RecipientInfo_ktri_get0_signer_id(), CMS_RecipientInfo_set0_pkey(),
|
||||
CMS_RecipientInfo_kekri_get0_id(), CMS_RecipientInfo_set0_key() and
|
||||
CMS_RecipientInfo_decrypt() return 1 for success or 0 if an error occurs.
|
||||
CMS_RecipientInfo_encrypt() return 1 for success or 0 if an error occurs.
|
||||
CMS_RecipientInfo_kekri_get0_id(), CMS_RecipientInfo_set0_key(),
|
||||
CMS_RecipientInfo_kemri_set0_pkey(), CMS_RecipientInfo_kemri_set_ukm(),
|
||||
CMS_RecipientInfo_decrypt() and CMS_RecipientInfo_encrypt() return 1 for
|
||||
success or 0 if an error occurs.
|
||||
|
||||
CMS_RecipientInfo_ktri_cert_cmp() and CMS_RecipientInfo_kekri_cmp() return 0
|
||||
for a successful comparison and non zero otherwise.
|
||||
CMS_RecipientInfo_ktri_cert_cmp(), CMS_RecipientInfo_kemri_cert_cmp() and
|
||||
CMS_RecipientInfo_kekri_cmp() return 0 for a successful comparison and non zero
|
||||
otherwise.
|
||||
|
||||
CMS_RecipientInfo_kemri_get0_ctx() and CMS_RecipientInfo_kari_get0_ctx return
|
||||
the RecipientInfo's EVP_CIPHER_CTX or NULL if an error occurred.
|
||||
|
||||
CMS_RecipientInfo_kemri_get0_kdf_alg() returns the RecipientInfo's KDF's
|
||||
X509_ALGOR or NULL if an error occurred.
|
||||
|
||||
Any error can be obtained from L<ERR_get_error(3)>.
|
||||
|
||||
|
@ -143,9 +188,13 @@ L<ERR_get_error(3)>, L<CMS_decrypt(3)>
|
|||
B<CMS_RecipientInfo_kari_set0_pkey_and_peer> and B<CMS_RecipientInfo_kari_set0_pkey>
|
||||
were added in OpenSSL 3.0.
|
||||
|
||||
B<CMS_RecipientInfo_kemri_cert_cmp>, B<CMS_RecipientInfo_kemri_set0_pkey>,
|
||||
B<CMS_RecipientInfo_kemri_get0_ctx>, B<CMS_RecipientInfo_kemri_get0_kdf_alg>
|
||||
and B<CMS_RecipientInfo_kemri_set_ukm> were added in OpenSSL 3.6.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
Copyright 2008-2025 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
|
||||
|
|
|
@ -18,7 +18,8 @@ CRYPTO_get_alloc_counts,
|
|||
CRYPTO_set_mem_debug, CRYPTO_mem_ctrl,
|
||||
CRYPTO_mem_leaks, CRYPTO_mem_leaks_fp, CRYPTO_mem_leaks_cb,
|
||||
OPENSSL_MALLOC_FAILURES,
|
||||
OPENSSL_MALLOC_FD
|
||||
OPENSSL_MALLOC_FD,
|
||||
OPENSSL_MALLOC_SEED
|
||||
- Memory allocation functions
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
@ -69,6 +70,7 @@ OPENSSL_MALLOC_FD
|
|||
|
||||
env OPENSSL_MALLOC_FAILURES=... <application>
|
||||
env OPENSSL_MALLOC_FD=... <application>
|
||||
env OPENSSL_MALLOC_SEED=... <application>
|
||||
|
||||
The following functions have been deprecated since OpenSSL 3.0, and can be
|
||||
hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value,
|
||||
|
@ -155,9 +157,9 @@ with CRYPTO_set_mem_functions(), it's recommended to swap them all out
|
|||
at once.
|
||||
|
||||
If the library is built with the C<crypto-mdebug> option, then one
|
||||
function, CRYPTO_get_alloc_counts(), and two additional environment
|
||||
variables, B<OPENSSL_MALLOC_FAILURES> and B<OPENSSL_MALLOC_FD>,
|
||||
are available.
|
||||
function, CRYPTO_get_alloc_counts(), and three additional environment
|
||||
variables, B<OPENSSL_MALLOC_FAILURES>, B<OPENSSL_MALLOC_FD>,
|
||||
and B<OPENSSL_MALLOC_SEED>, are available.
|
||||
|
||||
The function CRYPTO_get_alloc_counts() fills in the number of times
|
||||
each of CRYPTO_malloc(), CRYPTO_realloc(), and CRYPTO_free() have been
|
||||
|
@ -167,12 +169,14 @@ respectively. If a pointer is NULL, then the corresponding count is not stored.
|
|||
The variable
|
||||
B<OPENSSL_MALLOC_FAILURES> controls how often allocations should fail.
|
||||
It is a set of fields separated by semicolons, which each field is a count
|
||||
(defaulting to zero) and an optional atsign and percentage (defaulting
|
||||
to 100). If the count is zero, then it lasts forever. For example,
|
||||
C<100;@25> or C<100@0;0@25> means the first 100 allocations pass, then all
|
||||
other allocations (until the program exits or crashes) have a 25% chance of
|
||||
failing. The length of the value of B<OPENSSL_MALLOC_FAILURES> must be 256 or
|
||||
fewer characters.
|
||||
(defaulting to zero) and an optional atsign and percentage (interpreted
|
||||
as a floating point number that is rounded up to two decimal digits
|
||||
of precision, defaulting to 100). If the count is zero, then it lasts forever.
|
||||
For example, C<100;@0.258> or C<100@0;0@0.258> means the first 100 allocations
|
||||
pass, then all other allocations (until the program exits or crashes) have
|
||||
a 0.26% chance of failing, with random(3) used as a source of randomness.
|
||||
The length of the value of B<OPENSSL_MALLOC_FAILURES> must be 256 or fewer
|
||||
characters.
|
||||
|
||||
If the variable B<OPENSSL_MALLOC_FD> is parsed as a positive integer, then
|
||||
it is taken as an open file descriptor. This is used in conjunction with
|
||||
|
@ -188,6 +192,10 @@ work on all platforms):
|
|||
export OPENSSL_MALLOC_FD
|
||||
...app invocation... 3>/tmp/log$$
|
||||
|
||||
If the environment variable B<OPENSSL_MALLOC_SEED> is set, its value
|
||||
is interpreted as an integer using atoi(3) and supplied to the srandom(3)
|
||||
call for the random number generator initialisation.
|
||||
|
||||
=head1 RETURN VALUES
|
||||
|
||||
OPENSSL_malloc_init(), OPENSSL_free(), OPENSSL_clear_free()
|
||||
|
|
|
@ -67,6 +67,28 @@ given passphrase. See L<passphrase-encoding(7)> for more information.
|
|||
|
||||
All functions returning an integer return 1 on success and 0 if an error occurred.
|
||||
|
||||
=head1 ENVIRONMENT
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<LEGACY_GOST_PKCS12>
|
||||
|
||||
=for comment
|
||||
https://tc26.ru/standarts/metodicheskie-rekomendatsii/transportnyy-klyuchevoy-konteyner.html section 5.1
|
||||
https://tc26.ru/standard/rs/%D0%A0%2050.1.112-2016.pdf section 5
|
||||
https://meganorm.ru/mega_doc/norm/prikaz/25/r_1323565_1_041-2022_rekomendatsii_po_standartizatsii.html section 7.1
|
||||
|
||||
If this environment variable is set, MAC generation that utilises
|
||||
GOST R 34.11-94 or GOST 34.11-2012 hashing algorithms is performed the usual
|
||||
way and not in accordance with the specification provided in the methodical
|
||||
recommendation MP 26.2.002-2012 (or in its later versions, standartisation
|
||||
recommendation P 50.1.112-2016 or P 1323565.1.041-2022)
|
||||
of Technical Committee 26, that specifies that the key used for MAC
|
||||
generation should be the last 32 bytes of the 96-byte sequence generated
|
||||
by L<PKCS5_PBKDF2_HMAC(3)> and not the whole sequence.
|
||||
|
||||
=back
|
||||
|
||||
=head1 CONFORMING TO
|
||||
|
||||
IETF RFC 7292 (L<https://tools.ietf.org/html/rfc7292>)
|
||||
|
|
|
@ -11,7 +11,9 @@ SSL_CTX_get_tlsext_status_type,
|
|||
SSL_set_tlsext_status_type,
|
||||
SSL_get_tlsext_status_type,
|
||||
SSL_get_tlsext_status_ocsp_resp,
|
||||
SSL_set_tlsext_status_ocsp_resp
|
||||
SSL_set_tlsext_status_ocsp_resp,
|
||||
SSL_get0_tlsext_status_ocsp_resp_ex,
|
||||
SSL_set0_tlsext_status_ocsp_resp_ex
|
||||
- OCSP Certificate Status Request functions
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
@ -33,9 +35,12 @@ SSL_set_tlsext_status_ocsp_resp
|
|||
long SSL_get_tlsext_status_ocsp_resp(ssl, unsigned char **resp);
|
||||
long SSL_set_tlsext_status_ocsp_resp(ssl, unsigned char *resp, int len);
|
||||
|
||||
long SSL_get0_tlsext_status_ocsp_resp_ex(ssl, STACK_OF(OCSP_RESPONSE) **resp);
|
||||
long SSL_set0_tlsext_status_ocsp_resp_ex(ssl, STACK_OF(OCSP_RESPONSE) *resp);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A client application may request that a server send back an OCSP status response
|
||||
A client application may request that a server send back OCSP status response(s)
|
||||
(also known as OCSP stapling). To do so the client should call the
|
||||
SSL_CTX_set_tlsext_status_type() function prior to the creation of any SSL
|
||||
objects. Alternatively an application can call the SSL_set_tlsext_status_type()
|
||||
|
@ -45,9 +50,13 @@ should be passed in the B<type> argument. Calling
|
|||
SSL_CTX_get_tlsext_status_type() will return the type B<TLSEXT_STATUSTYPE_ocsp>
|
||||
previously set via SSL_CTX_set_tlsext_status_type() or -1 if not set.
|
||||
|
||||
For TLS versions before 1.3 only a single OCSP status response is sent back
|
||||
by the server. TLS 1.3 specifies that the server can send OCSP status responses
|
||||
for the whole chain (OCSP multi-stapling).
|
||||
|
||||
The client should additionally provide a callback function to decide what to do
|
||||
with the returned OCSP response by calling SSL_CTX_set_tlsext_status_cb(). The
|
||||
callback function should determine whether the returned OCSP response is
|
||||
callback function should determine whether the returned OCSP response(s) are
|
||||
acceptable or not. The callback will be passed as an argument the value
|
||||
previously set via a call to SSL_CTX_set_tlsext_status_arg(). Note that the
|
||||
callback will not be called in the event of a handshake where session resumption
|
||||
|
@ -63,22 +72,48 @@ side SSL_get_tlsext_status_type() can be used to determine whether the client
|
|||
requested OCSP stapling. If the client requested it then this function will
|
||||
return B<TLSEXT_STATUSTYPE_ocsp>, or -1 otherwise.
|
||||
|
||||
The response returned by the server can be obtained via a call to
|
||||
SSL_get_tlsext_status_ocsp_resp(). The value B<*resp> will be updated to point
|
||||
to the OCSP response data and the return value will be the length of that data.
|
||||
Typically a callback would obtain an OCSP_RESPONSE object from this data via a
|
||||
call to the d2i_OCSP_RESPONSE() function. If the server has not provided any
|
||||
response data then B<*resp> will be NULL and the return value from
|
||||
A single response returned by the server (TLS < 1.3) can be obtained via a call
|
||||
to SSL_get_tlsext_status_ocsp_resp(). The value B<*resp> will be updated to
|
||||
point to the OCSP response data and the return value will be the length of that
|
||||
data. Typically a callback would obtain an OCSP_RESPONSE object from this data
|
||||
via a call to the d2i_OCSP_RESPONSE() function. If the server has not provided
|
||||
any response data then B<*resp> will be NULL and the return value from
|
||||
SSL_get_tlsext_status_ocsp_resp() will be -1.
|
||||
|
||||
A server application must also call the SSL_CTX_set_tlsext_status_cb() function
|
||||
if it wants to be able to provide clients with (single) OCSP response for the
|
||||
server certificate. Typically the server callback would obtain the server
|
||||
certificate that is being sent back to the client via a call to
|
||||
SSL_get_certificate(); retrieve the related OCSP response to be sent back; and
|
||||
then set that response data by calling SSL_set_tlsext_status_ocsp_resp(). A
|
||||
pointer to the response data should be provided in the B<resp> argument, and
|
||||
the length of that data should be in the B<len> argument.
|
||||
|
||||
In the case of multi-stapling the responses to be returned by the server can be
|
||||
obtained via a call to SSL_get0_tlsext_status_ocsp_resp_ex(). The value B<*resp>
|
||||
will be updated to point to the OCSP response stack and the return value will
|
||||
be the number of responses on the stack.
|
||||
The OCSP responses on the stack are expected to be in the same order as the
|
||||
certificates in the chain. If no OCSP response is available for a certificate
|
||||
in the chain, a NULL element in the stack will represent this.
|
||||
Typically a callback would obtain an OCSP_RESPONSE object from the stack via a
|
||||
call to sk_OCSP_RESPONSE_pop. If the server has not provided any response data
|
||||
then B<*resp> will be NULL and the return value from
|
||||
SSL_get0_tlsext_status_ocsp_resp_ex() will be -1.
|
||||
|
||||
A server application must also call the SSL_CTX_set_tlsext_status_cb() function
|
||||
if it wants to be able to provide clients with OCSP Certificate Status
|
||||
responses. Typically the server callback would obtain the server certificate
|
||||
that is being sent back to the client via a call to SSL_get_certificate();
|
||||
obtain the OCSP response to be sent back; and then set that response data by
|
||||
calling SSL_set_tlsext_status_ocsp_resp(). A pointer to the response data should
|
||||
be provided in the B<resp> argument, and the length of that data should be in
|
||||
the B<len> argument.
|
||||
responses, where TLS 1.3 allows for multi-stapling, i.e., providing responses
|
||||
for all certificates in the chain of the server certificate (excluding the root
|
||||
CA certificate).
|
||||
The certificates sent back to the client and for which OCSP response(s)
|
||||
should be acquired could be obtained via call to SSL_get_certificate() resp.
|
||||
SSL_get0_chain_certs(). OCSP response(s) then set by calling
|
||||
SSL_set0_tlsext_status_ocsp_resp_ex(). A stack of OCSP responses should be
|
||||
provided in the B<resp> argument.
|
||||
The OCSP responses on the stack are expected to be in the same order as the
|
||||
certificate in the chain. If no OCSP response is available for a certificate in
|
||||
the chain, a NULL element in the stack will represent this.
|
||||
|
||||
=head1 RETURN VALUES
|
||||
|
||||
|
@ -93,8 +128,9 @@ returned) or SSL_TLSEXT_ERR_ALERT_FATAL (meaning that a fatal error has
|
|||
occurred).
|
||||
|
||||
SSL_CTX_set_tlsext_status_cb(), SSL_CTX_set_tlsext_status_arg(),
|
||||
SSL_CTX_set_tlsext_status_type(), SSL_set_tlsext_status_type() and
|
||||
SSL_CTX_set_tlsext_status_type(), SSL_set_tlsext_status_type(),
|
||||
SSL_set_tlsext_status_ocsp_resp() return 0 on error or 1 on success.
|
||||
SSL_set0_tlsext_status_ocsp_resp_ex() will return always 1.
|
||||
|
||||
SSL_CTX_get_tlsext_status_type() returns the value previously set by
|
||||
SSL_CTX_set_tlsext_status_type(), or -1 if not set.
|
||||
|
@ -102,6 +138,9 @@ SSL_CTX_set_tlsext_status_type(), or -1 if not set.
|
|||
SSL_get_tlsext_status_ocsp_resp() returns the length of the OCSP response data
|
||||
or -1 if there is no OCSP response data.
|
||||
|
||||
SSL_get0_tlsext_status_ocsp_resp_ex() returns the number of the OCSP responses
|
||||
on the stack or -1 if there is no OCSP response data.
|
||||
|
||||
SSL_get_tlsext_status_type() returns B<TLSEXT_STATUSTYPE_ocsp> on the client
|
||||
side if SSL_set_tlsext_status_type() was previously called, or on the server
|
||||
side if the client requested OCSP stapling. Otherwise -1 is returned.
|
||||
|
@ -115,6 +154,9 @@ L<ssl(7)>
|
|||
The SSL_get_tlsext_status_type(), SSL_CTX_get_tlsext_status_type()
|
||||
and SSL_CTX_set_tlsext_status_type() functions were added in OpenSSL 1.1.0.
|
||||
|
||||
The SSL_get0_tlsext_status_ocsp_resp_ex() and SSL_set0_tlsext_status_ocsp_resp_ex()
|
||||
macros were added in OpenSSL 3.6.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
|
|
|
@ -440,6 +440,32 @@ Returned by the verify callback to indicate OCSP verification failed.
|
|||
Returned by the verify callback to indicate that the certificate is not
|
||||
recognized by the OCSP responder.
|
||||
|
||||
=item B<X509_V_ERR_OCSP_RESP_INVALID: OCSP response(s) invalid>
|
||||
|
||||
Returned by the verify callback to indicate that one or more OCSP
|
||||
responses are invalid.
|
||||
|
||||
=item B<X509_V_ERR_OCSP_SIGNATURE_FAILURE: OCSP response signature failure>
|
||||
|
||||
Returned by the verify callback to indicate OCSP response signature
|
||||
verification failed.
|
||||
|
||||
=item B<X509_V_ERR_OCSP_NOT_YET_VALID: OCSP response not yet valid>
|
||||
OCSP response not yet valid (contains a date in the future)>
|
||||
|
||||
Returned by the verify callback to indicate that OCSP response has a
|
||||
I<thisUpdate> date in the future.
|
||||
|
||||
=item B<X509_V_ERR_OCSP_HAS_EXPIRED: OCSP response has expired>
|
||||
|
||||
Returned by the verify callback to indicate that the OCSP response has expired.
|
||||
|
||||
=item B<X509_V_ERR_OCSP_NO_RESPONSE:
|
||||
no OCSP response available for certificate>
|
||||
|
||||
Returned by the verify callback to indicate that no OCSP response is available
|
||||
for the certificate.
|
||||
|
||||
=item B<X509_V_ERR_UNSUPPORTED_SIGNATURE_ALGORITHM:
|
||||
unsupported signature algorithm>
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ X509_STORE_CTX_get0_rpk,
|
|||
X509_STORE_CTX_set_default,
|
||||
X509_STORE_CTX_set_verify,
|
||||
X509_STORE_CTX_verify_fn,
|
||||
X509_STORE_CTX_set_ocsp_resp,
|
||||
X509_STORE_CTX_set_purpose,
|
||||
X509_STORE_CTX_set_trust,
|
||||
X509_STORE_CTX_purpose_inherit
|
||||
|
@ -56,6 +57,7 @@ X509_STORE_CTX_purpose_inherit
|
|||
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);
|
||||
|
||||
void X509_STORE_CTX_set_ocsp_resp(X509_STORE_CTX *ctx, STACK_OF(OCSP_RESPONSE) *sk);
|
||||
int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
|
||||
int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust);
|
||||
int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
|
||||
|
@ -217,6 +219,12 @@ validate extended key usage information in certificates will need to define a
|
|||
custom "purpose" (see below) or supply a nondefault verification callback
|
||||
(L<X509_STORE_set_verify_cb_func(3)>).
|
||||
|
||||
X509_STORE_CTX_set_ocsp_resp() sets the OCSP response(s) for the verification
|
||||
of a certificate chain or for including in the TLS handshake, when the client
|
||||
requests OCSP stapling. The stack of OCSP responses I<sk> is not copied but
|
||||
just stored to the context.
|
||||
I<ctx> holds a pointer to the stack, so the stack must outlive the I<ctx>.
|
||||
|
||||
X509_STORE_CTX_set_purpose() sets the purpose for the target certificate being
|
||||
verified in the I<ctx>. Built-in available values for the I<purpose> argument
|
||||
are B<X509_PURPOSE_SSL_CLIENT>, B<X509_PURPOSE_SSL_SERVER>,
|
||||
|
@ -314,6 +322,7 @@ The X509_STORE_CTX_get_num_untrusted() function was added in OpenSSL 1.1.0.
|
|||
The X509_STORE_CTX_new_ex() function was added in OpenSSL 3.0.
|
||||
The X509_STORE_CTX_init_rpk(), X509_STORE_CTX_get0_rpk(), and
|
||||
X509_STORE_CTX_set0_rpk() functions were added in OpenSSL 3.2.
|
||||
X509_STORE_CTX_set_ocsp_resp() function was added in OpenSSL 3.6.
|
||||
|
||||
There is no need to call X509_STORE_CTX_cleanup() explicitly since OpenSSL 3.0.
|
||||
|
||||
|
|
|
@ -6,10 +6,11 @@ openssl-env - OpenSSL environment variables
|
|||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The OpenSSL libraries use environment variables to override the
|
||||
compiled-in default paths for various data.
|
||||
To avoid security risks, the environment is usually not consulted when
|
||||
the executable is set-user-ID or set-group-ID.
|
||||
The OpenSSL libraries and commands use environment variables to override
|
||||
compiled-in defaults for various aspects of their behaviour.
|
||||
To avoid security risks, the environment is not consulted
|
||||
for security-sensitive environment variables when the executable
|
||||
is set-user-ID or set-group-ID.
|
||||
|
||||
=over 4
|
||||
|
||||
|
@ -18,39 +19,85 @@ the executable is set-user-ID or set-group-ID.
|
|||
Specifies the path to a certificate transparency log list.
|
||||
See L<CTLOG_STORE_new(3)>.
|
||||
|
||||
This variable is considered a security-sensitive environment variable.
|
||||
|
||||
=item B<HOME>, B<SYSTEMROOT>, B<USERPROFILE>
|
||||
|
||||
Path which L<RAND_file_name(3)> uses as a directory for the random seed file
|
||||
name when the B<RANDFILE> environment variable is not set.
|
||||
B<HOME> is the only variable that is considered on Unix-like systems;
|
||||
B<USERPROFILE> and B<SYSTEMROOT> are used as fallbacks on Windows platforms.
|
||||
|
||||
B<HOME> variable is considered a security-sensitive environment variable.
|
||||
|
||||
=item B<HTTPS_PROXY>, B<HTTP_PROXY>, B<NO_PROXY>, B<https_proxy>, B<http_proxy>, B<no_proxy>
|
||||
|
||||
Specify a proxy hostname.
|
||||
See L<OSSL_HTTP_parse_url(3)>.
|
||||
|
||||
These variables are considered security-sensitive environment variables.
|
||||
|
||||
=item B<LEGACY_GOST_PKCS12>
|
||||
|
||||
Affects the way MAC is generated in PKCS#12 containers for GOST algorithms.
|
||||
See L<PKCS12_gen_mac(3)>.
|
||||
|
||||
This variable is considered a security-sensitive environment variable.
|
||||
|
||||
=item B<OPENSSL>
|
||||
|
||||
Specifies the path to the B<openssl> executable. Used by
|
||||
the B<rehash> script (see L<openssl-rehash(1)/Script Configuration>)
|
||||
and by the B<CA.pl> script (see L<CA.pl(1)/NOTES>
|
||||
|
||||
This variable is not considered security-sensitive.
|
||||
|
||||
=item B<OPENSSL_CONF>, B<OPENSSL_CONF_INCLUDE>
|
||||
|
||||
Specifies the path to a configuration file and the directory for
|
||||
included files.
|
||||
See L<config(5)>.
|
||||
|
||||
These variables are considered security-sensitive environment variables.
|
||||
|
||||
=item B<OPENSSL_CONFIG>
|
||||
|
||||
Specifies a configuration option and filename for the B<req> and B<ca>
|
||||
commands invoked by the B<CA.pl> script.
|
||||
See L<CA.pl(1)>.
|
||||
|
||||
This variable is not considered security-sensitive.
|
||||
|
||||
=item B<OPENSSL_DEBUG_DECC_INIT>
|
||||
|
||||
On VMS only: if this variable is set, enables verbose output of parsing
|
||||
of C<DECC$*> logical names, that contain C RTL features, during library
|
||||
initialisation (C<LIB$INITIALIZE>). If the value of the variable is more
|
||||
than 1, outputs information about every processed feature.
|
||||
|
||||
This variable is not considered security-sensitive.
|
||||
|
||||
=item B<OPENSSL_ENGINES>
|
||||
|
||||
Specifies the directory from which dynamic engines are loaded.
|
||||
See L<openssl-engine(1)>.
|
||||
|
||||
=item B<OPENSSL_MALLOC_FD>, B<OPENSSL_MALLOC_FAILURES>
|
||||
This variable is considered a security-sensitive environment variable.
|
||||
|
||||
=item B<OPENSSL_MALLOC_FAILURES>, B<OPENSSL_MALLOC_FD>, B<OPENSSL_MALLOC_SEED>
|
||||
|
||||
If built with debugging, this allows memory allocation to fail.
|
||||
See L<OPENSSL_malloc(3)>.
|
||||
|
||||
These variables are not considered security-sensitive.
|
||||
|
||||
=item B<OPENSSL_MODULES>
|
||||
|
||||
Specifies the directory from which cryptographic providers are loaded.
|
||||
Equivalently, the generic B<-provider-path> command-line option may be used.
|
||||
|
||||
This variable is considered a security-sensitive environment variable.
|
||||
|
||||
=item B<OPENSSL_SEC_MEM>
|
||||
|
||||
Initializes the secure memory at the beginning of the application which makes
|
||||
|
@ -59,12 +106,24 @@ indicates the B<size> parameter in bytes. The value can be expressed in
|
|||
binary, octal, decimal and hexadecimal. For formatting see B<strtol(3)>.
|
||||
For further restrictions see L<CRYPTO_secure_malloc_init(3)>.
|
||||
|
||||
This variable is not considered security-sensitive.
|
||||
|
||||
=item B<OPENSSL_SEC_MEM_MINSIZE>
|
||||
|
||||
An optional variable used with B<OPENSSL_SEC_MEM>. The value indicates
|
||||
B<minsize> parameter in bytes. The same formatting applies as above.
|
||||
Default is 0. For more info see L<CRYPTO_secure_malloc_init(3)>.
|
||||
|
||||
This variable is not considered security-sensitive.
|
||||
|
||||
=item B<OPENSSL_TEST_LIBCTX>
|
||||
|
||||
This test-only environment variable, that is recognised by the L<openssl(1)>
|
||||
command, when is set to "1", leads to creation of a nondefault library context
|
||||
by the command, for which the B<-config> option then takes effect.
|
||||
|
||||
This variable is not considered security-sensitive.
|
||||
|
||||
=item B<OPENSSL_TRACE>
|
||||
|
||||
By default the OpenSSL trace feature is disabled statically.
|
||||
|
@ -75,58 +134,14 @@ Unless OpenSSL tracing support is generally disabled,
|
|||
enable trace output of specific parts of OpenSSL libraries, by name.
|
||||
This output usually makes sense only if you know OpenSSL internals well.
|
||||
|
||||
The value of this environment varialble is a comma-separated list of names,
|
||||
The value of this environment variable is a comma-separated list of names,
|
||||
with the following available:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<TRACE>
|
||||
=item B<ALL>
|
||||
|
||||
Traces the OpenSSL trace API itself.
|
||||
|
||||
=item B<INIT>
|
||||
|
||||
Traces OpenSSL library initialization and cleanup.
|
||||
|
||||
=item B<TLS>
|
||||
|
||||
Traces the TLS/SSL protocol.
|
||||
|
||||
=item B<TLS_CIPHER>
|
||||
|
||||
Traces the ciphers used by the TLS/SSL protocol.
|
||||
|
||||
=item B<CONF>
|
||||
|
||||
Show details about provider and engine configuration.
|
||||
|
||||
=item B<ENGINE_TABLE>
|
||||
|
||||
The function that is used by RSA, DSA (etc) code to select registered
|
||||
ENGINEs, cache defaults and functional references (etc), will generate
|
||||
debugging summaries.
|
||||
|
||||
=item B<ENGINE_REF_COUNT>
|
||||
|
||||
Reference counts in the ENGINE structure will be monitored with a line
|
||||
of generated for each change.
|
||||
|
||||
=item B<PKCS5V2>
|
||||
|
||||
Traces PKCS#5 v2 key generation.
|
||||
|
||||
=item B<PKCS12_KEYGEN>
|
||||
|
||||
Traces PKCS#12 key generation.
|
||||
|
||||
=item B<PKCS12_DECRYPT>
|
||||
|
||||
Traces PKCS#12 decryption.
|
||||
|
||||
=item B<X509V3_POLICY>
|
||||
|
||||
Generates the complete policy tree at various points during X.509 v3
|
||||
policy evaluation.
|
||||
Traces everything.
|
||||
|
||||
=item B<BN_CTX>
|
||||
|
||||
|
@ -136,9 +151,9 @@ Traces BIGNUM context operations.
|
|||
|
||||
Traces CMP client and server activity.
|
||||
|
||||
=item B<STORE>
|
||||
=item B<CONF>
|
||||
|
||||
Traces STORE operations.
|
||||
Show details about provider and engine configuration.
|
||||
|
||||
=item B<DECODER>
|
||||
|
||||
|
@ -148,16 +163,81 @@ Traces decoder operations.
|
|||
|
||||
Traces encoder operations.
|
||||
|
||||
=item B<REF_COUNT>
|
||||
=item B<ENGINE_REF_COUNT>
|
||||
|
||||
Traces decrementing certain ASN.1 structure references.
|
||||
Reference counts in the ENGINE structure will be monitored with a line
|
||||
of generated for each change.
|
||||
|
||||
=item B<ENGINE_TABLE>
|
||||
|
||||
The function that is used by RSA, DSA (etc) code to select registered
|
||||
ENGINEs, cache defaults and functional references (etc), will generate
|
||||
debugging summaries.
|
||||
|
||||
=item B<HTTP>
|
||||
|
||||
Traces the HTTP client and server, such as messages being sent and received.
|
||||
|
||||
=item B<INIT>
|
||||
|
||||
Traces OpenSSL library initialization and cleanup.
|
||||
|
||||
=item B<PKCS12_DECRYPT>
|
||||
|
||||
Traces PKCS#12 decryption.
|
||||
|
||||
=item B<PKCS12_KEYGEN>
|
||||
|
||||
Traces PKCS#12 key generation.
|
||||
|
||||
=item B<PKCS5V2>
|
||||
|
||||
Traces PKCS#5 v2 key generation.
|
||||
|
||||
=item B<PROVIDER>
|
||||
|
||||
Traces various operations that are performed on OpenSSL providers during their
|
||||
handling by the library (see L<provider(7)>), such as initialisation, tear down,
|
||||
parameter and capability retrieval, self-test, and so on.
|
||||
|
||||
=item B<QUERY>
|
||||
|
||||
Traces operation related to addition, removal, and fetching of methods
|
||||
in the so-called method store, that holds pointers to functions provided
|
||||
by various providers.
|
||||
|
||||
=item B<REF_COUNT>
|
||||
|
||||
Traces reference count changes in various structures,
|
||||
including C<BIO>, C<DH>, C<DSA>, C<EC_KEY>, C<ECX_KEY>,
|
||||
C<EVP_PKEY>, C<EVP_SKEY>, C<RSA>, C<SSL>, C<SSL_CTX>, C<SSL_SESSION>,
|
||||
C<X509_CRL>, C<X509_STORE>, C<X509>, and some others.
|
||||
|
||||
=item B<STORE>
|
||||
|
||||
Traces STORE operations.
|
||||
|
||||
=item B<TLS>
|
||||
|
||||
Traces the TLS/SSL protocol.
|
||||
|
||||
=item B<TLS_CIPHER>
|
||||
|
||||
Traces the ciphers used by the TLS/SSL protocol.
|
||||
|
||||
=item B<TRACE>
|
||||
|
||||
Traces the OpenSSL trace API itself.
|
||||
|
||||
=item B<X509V3_POLICY>
|
||||
|
||||
Generates the complete policy tree at various points during X.509 v3
|
||||
policy evaluation.
|
||||
|
||||
=back
|
||||
|
||||
This variable is not considered security-sensitive.
|
||||
|
||||
=item B<OPENSSL_WIN32_UTF8>
|
||||
|
||||
If set, then L<UI_OpenSSL(3)> returns UTF-8 encoded strings, rather than
|
||||
|
@ -166,41 +246,35 @@ the L<openssl(1)> program also transcodes the command-line parameters
|
|||
from the current code page to UTF-8.
|
||||
This environment variable is only checked on Microsoft Windows platforms.
|
||||
|
||||
=item B<OPENSSL_armcap>, B<OPENSSL_ia32cap>, B<OPENSSL_ppccap>, B<OPENSSL_riscvcap>, B<OPENSSL_s390xcap>, B<OPENSSL_sparcv9cap>
|
||||
|
||||
OpenSSL supports a number of different algorithm implementations for
|
||||
various machines and, by default, it determines which to use based on the
|
||||
processor capabilities and run time feature enquiry. These environment
|
||||
variables can be used to exert more control over this selection process.
|
||||
See L<OPENSSL_ia32cap(3)>, L<OPENSSL_riscvcap(3)>, and L<OPENSSL_s390xcap(3)>.
|
||||
|
||||
These variables are not considered security-sensitive.
|
||||
|
||||
=item B<OSSL_QFILTER>
|
||||
|
||||
Used to set a QUIC qlog filter specification. See L<openssl-qlog(7)>.
|
||||
|
||||
This variable is considered a security-sensitive environment variable.
|
||||
|
||||
=item B<QLOGDIR>
|
||||
|
||||
Specifies a QUIC qlog output directory. See L<openssl-qlog(7)>.
|
||||
|
||||
This variable is considered a security-sensitive environment variable.
|
||||
|
||||
=item B<RANDFILE>
|
||||
|
||||
The state file for the random number generator.
|
||||
This should not be needed in normal use.
|
||||
See L<RAND_load_file(3)>.
|
||||
|
||||
=item B<SSL_CERT_DIR>, B<SSL_CERT_FILE>
|
||||
|
||||
Specify the default directory or file containing CA certificates.
|
||||
See L<SSL_CTX_load_verify_locations(3)>.
|
||||
|
||||
=item B<TSGET>
|
||||
|
||||
Additional arguments for the L<tsget(1)> command.
|
||||
|
||||
=item B<OPENSSL_ia32cap>, B<OPENSSL_sparcv9cap>, B<OPENSSL_ppccap>, B<OPENSSL_armcap>, B<OPENSSL_s390xcap>, B<OPENSSL_riscvcap>
|
||||
|
||||
OpenSSL supports a number of different algorithm implementations for
|
||||
various machines and, by default, it determines which to use based on the
|
||||
processor capabilities and run time feature enquiry. These environment
|
||||
variables can be used to exert more control over this selection process.
|
||||
See L<OPENSSL_ia32cap(3)>, L<OPENSSL_s390xcap(3)> and L<OPENSSL_riscvcap(3)>.
|
||||
|
||||
=item B<NO_PROXY>, B<HTTPS_PROXY>, B<HTTP_PROXY>
|
||||
|
||||
Specify a proxy hostname.
|
||||
See L<OSSL_HTTP_parse_url(3)>.
|
||||
|
||||
=item B<QLOGDIR>
|
||||
|
||||
Specifies a QUIC qlog output directory. See L<openssl-qlog(7)>.
|
||||
|
||||
=item B<OSSL_QFILTER>
|
||||
|
||||
Used to set a QUIC qlog filter specification. See L<openssl-qlog(7)>.
|
||||
This variable is considered a security-sensitive environment variable.
|
||||
|
||||
=item B<SSLKEYLOGFILE>
|
||||
|
||||
|
@ -214,6 +288,49 @@ the exchanged keys during an SSL session, it allows any available party with
|
|||
read access to the file to decrypt application traffic sent over that session.
|
||||
Use of this feature should be restricted to test and debug environments only.
|
||||
|
||||
This variable is considered a security-sensitive environment variable.
|
||||
|
||||
=item B<SSL_CERT_DIR>, B<SSL_CERT_FILE>
|
||||
|
||||
Specify the default directory or file containing CA certificates.
|
||||
See L<SSL_CTX_load_verify_locations(3)>.
|
||||
|
||||
These variables are considered security-sensitive environment variables,
|
||||
except in L<openssl-rehash(1)>, where B<SSL_CERT_DIR> is not considered
|
||||
security-sensitive.
|
||||
|
||||
=item B<SSL_CIPHER>
|
||||
|
||||
Used by L<openssl-s_time(1)> in case B<-cipher> option (that allows modifying
|
||||
TLSv1.2 and below cipher list sent by the client) is not provided,
|
||||
for specification of the aforementioned ciphers.
|
||||
|
||||
This variable is not considered security-sensitive.
|
||||
|
||||
=item B<TSGET>
|
||||
|
||||
Additional arguments for the L<tsget(1)> command.
|
||||
|
||||
This variable is not considered security-sensitive.
|
||||
|
||||
=back
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
This section contains environment variables that are no longer considered
|
||||
by the OpenSSL libraries and commands.
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<HARNESS_OSSL_PREFIX>
|
||||
|
||||
This environment variable, existed in OpenSSL versions from 1.1.1 up to 3.5,
|
||||
allowed specification of a prefix prepended to each line sent to the I<stdout>
|
||||
by L<openssl(1)>, used by the test harness to avoid commingling the command
|
||||
under test output with the output for the TAP consumer.
|
||||
|
||||
This variable was not considered security-sensitive.
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
|
|
@ -154,6 +154,10 @@ provider):
|
|||
core_new_error OSSL_FUNC_CORE_NEW_ERROR
|
||||
core_set_error_debug OSSL_FUNC_CORE_SET_ERROR_DEBUG
|
||||
core_vset_error OSSL_FUNC_CORE_VSET_ERROR
|
||||
core_set_error_mark OSSL_FUNC_CORE_SET_ERROR_MARK
|
||||
core_clear_last_error_mark OSSL_FUNC_CORE_CLEAR_LAST_ERROR_MARK
|
||||
core_pop_error_to_mark OSSL_FUNC_CORE_POP_ERROR_TO_MARK
|
||||
core_count_to_mark OSSL_FUNC_CORE_COUNT_TO_MARK
|
||||
core_obj_add_sigid OSSL_FUNC_CORE_OBJ_ADD_SIGID
|
||||
core_obj_create OSSL_FUNC_CORE_OBJ_CREATE
|
||||
CRYPTO_malloc OSSL_FUNC_CRYPTO_MALLOC
|
||||
|
@ -270,6 +274,33 @@ error occurred or was reported.
|
|||
|
||||
This corresponds to the OpenSSL function L<ERR_vset_error(3)>.
|
||||
|
||||
=item core_set_error_mark()
|
||||
|
||||
sets a mark on the current topmost error record if there is one.
|
||||
|
||||
This corresponds to the OpenSSL function L<ERR_set_mark(3)>.
|
||||
|
||||
=item core_clear_last_error_mark()
|
||||
|
||||
removes the last mark added if there is one.
|
||||
|
||||
This corresponds to the OpenSSL function L<ERR_clear_last_mark(3)>.
|
||||
|
||||
=item core_pop_error_to_mark()
|
||||
|
||||
pops the top of the error stack until a mark is found. The mark is then removed.
|
||||
If there is no mark, the whole stack is removed.
|
||||
|
||||
This corresponds to the OpenSSL function L<ERR_pop_to_mark(3)>.
|
||||
|
||||
=item core_count_to_mark()
|
||||
|
||||
returns the number of entries on the error stack above the most recently
|
||||
marked entry, not including that entry. If there is no mark in the error stack,
|
||||
the number of entries in the error stack is returned.
|
||||
|
||||
This corresponds to the OpenSSL function L<ERR_count_to_mark(3)>.
|
||||
|
||||
=back
|
||||
|
||||
The core_obj_create() function registers a new OID and associated short name
|
||||
|
|
|
@ -442,6 +442,30 @@ its argument I<mdname>. This signifies that no digest has to be specified
|
|||
with the corresponding signature operation, but may be specified as an
|
||||
option.
|
||||
|
||||
=item "ri-type" (B<OSSL_PKEY_PARAM_CMS_RI_TYPE>) <integer>
|
||||
|
||||
The value should be the CMS RecipientInfo type for the given key, for example
|
||||
B<CMS_RECIPINFO_KEM> or B<CMS_RECIPINFO_AGREE>.
|
||||
The value that can be given through this parameter is found in
|
||||
F<< <openssl/cms.h> >>, with the macros having names starting with
|
||||
C<CMS_RECIPINFO_>.
|
||||
|
||||
CMS will query this parameter first to determine the RecipientInfo type. If
|
||||
this parameter is not filled in, CMS will check for known key types and map
|
||||
them to the appropriate RecipientInfo type. Otherwise, CMS will default to
|
||||
using B<CMS_RECIPINFO_TRANS>.
|
||||
|
||||
=item "kemri-kdf-alg" (B<OSSL_PKEY_PARAM_CMS_KEMRI_KDF_ALGORITHM>) <UTF8 string>
|
||||
|
||||
The value should be the DER-encoded X509_ALGOR for the default KDF for this key
|
||||
if it supports the KEMRecipientInfo (B<CMS_RECIPINFO_KEM>) type.
|
||||
|
||||
Any KDF that takes B<OSSL_KDF_PARAM_KEY> and B<OSSL_KDF_PARAM_INFO> parameters
|
||||
and is otherwise fully defined by its OID can be used, for example B<HKDF-SHA256>.
|
||||
|
||||
If B<OSSL_PKEY_PARAM_CMS_KEMRI_KDF_ALGORITHM> is not implemented, B<HKDF-SHA256>
|
||||
will be used as the default KDF.
|
||||
|
||||
=back
|
||||
|
||||
The OpenSSL FIPS provider also supports the following parameters:
|
||||
|
|
|
@ -590,10 +590,7 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len)
|
|||
SSL *server;
|
||||
BIO *in;
|
||||
BIO *out;
|
||||
#if !defined(OPENSSL_NO_EC) \
|
||||
|| (!defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DEPRECATED_3_0))
|
||||
BIO *bio_buf;
|
||||
#endif
|
||||
SSL_CTX *ctx;
|
||||
int ret;
|
||||
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
||||
|
|
|
@ -1347,3 +1347,5 @@ OBJ_SLH_DSA_SHAKE_256f_WITH_SHAKE256="\x60\x86\x48\x01\x65\x03\x04\x03\x2E"
|
|||
OBJ_HKDF_SHA256="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x03\x1C"
|
||||
OBJ_HKDF_SHA384="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x03\x1D"
|
||||
OBJ_HKDF_SHA512="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x03\x1E"
|
||||
OBJ_id_smime_ori="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x0D"
|
||||
OBJ_id_smime_ori_kem="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x0D\x03"
|
||||
|
|
|
@ -221,6 +221,7 @@ struct x509_store_ctx_st { /* X509_STORE_CTX */
|
|||
STACK_OF(X509) *untrusted;
|
||||
/* set of CRLs passed in */
|
||||
STACK_OF(X509_CRL) *crls;
|
||||
STACK_OF(OCSP_RESPONSE) *ocsp_resp;
|
||||
X509_VERIFY_PARAM *param;
|
||||
/* Other info for use with get_issuer() */
|
||||
void *other_ctx;
|
||||
|
|
|
@ -23,7 +23,7 @@ OSSL_ACKM *ossl_ackm_new(OSSL_TIME (*now)(void *arg),
|
|||
void *now_arg,
|
||||
OSSL_STATM *statm,
|
||||
const OSSL_CC_METHOD *cc_method,
|
||||
OSSL_CC_DATA *cc_data);
|
||||
OSSL_CC_DATA *cc_data, int is_server);
|
||||
void ossl_ackm_free(OSSL_ACKM *ackm);
|
||||
|
||||
void ossl_ackm_set_loss_detection_deadline_callback(OSSL_ACKM *ackm,
|
||||
|
|
|
@ -70,6 +70,7 @@ CMS_ContentInfo *CMS_ContentInfo_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
|
|||
# define CMS_RECIPINFO_KEK 2
|
||||
# define CMS_RECIPINFO_PASS 3
|
||||
# define CMS_RECIPINFO_OTHER 4
|
||||
# define CMS_RECIPINFO_KEM 5
|
||||
|
||||
/* S/MIME related flags */
|
||||
|
||||
|
@ -401,6 +402,14 @@ int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms,
|
|||
int CMS_SharedInfo_encode(unsigned char **pder, X509_ALGOR *kekalg,
|
||||
ASN1_OCTET_STRING *ukm, int keylen);
|
||||
|
||||
int CMS_RecipientInfo_kemri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert);
|
||||
int CMS_RecipientInfo_kemri_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk);
|
||||
EVP_CIPHER_CTX *CMS_RecipientInfo_kemri_get0_ctx(CMS_RecipientInfo *ri);
|
||||
X509_ALGOR *CMS_RecipientInfo_kemri_get0_kdf_alg(CMS_RecipientInfo *ri);
|
||||
int CMS_RecipientInfo_kemri_set_ukm(CMS_RecipientInfo *ri,
|
||||
const unsigned char *ukm,
|
||||
int ukmLength);
|
||||
|
||||
/* Backward compatibility for spelling errors. */
|
||||
# define CMS_R_UNKNOWN_DIGEST_ALGORITM CMS_R_UNKNOWN_DIGEST_ALGORITHM
|
||||
# define CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE \
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
# define CMS_R_NOT_A_SIGNED_RECEIPT 165
|
||||
# define CMS_R_NOT_ENCRYPTED_DATA 122
|
||||
# define CMS_R_NOT_KEK 123
|
||||
# define CMS_R_NOT_KEM 197
|
||||
# define CMS_R_NOT_KEY_AGREEMENT 181
|
||||
# define CMS_R_NOT_KEY_TRANSPORT 124
|
||||
# define CMS_R_NOT_PWRI 177
|
||||
|
@ -106,10 +107,12 @@
|
|||
# define CMS_R_UNKNOWN_CIPHER 148
|
||||
# define CMS_R_UNKNOWN_DIGEST_ALGORITHM 149
|
||||
# define CMS_R_UNKNOWN_ID 150
|
||||
# define CMS_R_UNKNOWN_KDF_ALGORITHM 198
|
||||
# define CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM 151
|
||||
# define CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM 194
|
||||
# define CMS_R_UNSUPPORTED_CONTENT_TYPE 152
|
||||
# define CMS_R_UNSUPPORTED_ENCRYPTION_TYPE 192
|
||||
# define CMS_R_UNSUPPORTED_KDF_ALGORITHM 199
|
||||
# define CMS_R_UNSUPPORTED_KEK_ALGORITHM 153
|
||||
# define CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM 179
|
||||
# define CMS_R_UNSUPPORTED_LABEL_SOURCE 193
|
||||
|
|
|
@ -253,6 +253,10 @@ OSSL_CORE_MAKE_FUNC(int, provider_up_ref,
|
|||
OSSL_CORE_MAKE_FUNC(int, provider_free,
|
||||
(const OSSL_CORE_HANDLE *prov, int deactivate))
|
||||
|
||||
/* Additional error functions provided by the core */
|
||||
# define OSSL_FUNC_CORE_COUNT_TO_MARK 120
|
||||
OSSL_CORE_MAKE_FUNC(int, core_count_to_mark, (const OSSL_CORE_HANDLE *prov))
|
||||
|
||||
/* Functions provided by the provider to the Core, reserved numbers 1024-1535 */
|
||||
# define OSSL_FUNC_PROVIDER_TEARDOWN 1024
|
||||
OSSL_CORE_MAKE_FUNC(void, provider_teardown, (void *provctx))
|
||||
|
|
|
@ -778,6 +778,10 @@
|
|||
#define NID_id_smime_cti 195
|
||||
#define OBJ_id_smime_cti OBJ_SMIME,6L
|
||||
|
||||
#define SN_id_smime_ori "id-smime-ori"
|
||||
#define NID_id_smime_ori 1499
|
||||
#define OBJ_id_smime_ori OBJ_SMIME,13L
|
||||
|
||||
#define SN_id_smime_mod_cms "id-smime-mod-cms"
|
||||
#define NID_id_smime_mod_cms 196
|
||||
#define OBJ_id_smime_mod_cms OBJ_id_smime_mod,1L
|
||||
|
@ -1113,6 +1117,10 @@
|
|||
#define NID_id_smime_cti_ets_proofOfCreation 256
|
||||
#define OBJ_id_smime_cti_ets_proofOfCreation OBJ_id_smime_cti,6L
|
||||
|
||||
#define SN_id_smime_ori_kem "id-smime-ori-kem"
|
||||
#define NID_id_smime_ori_kem 1500
|
||||
#define OBJ_id_smime_ori_kem OBJ_id_smime_ori,3L
|
||||
|
||||
#define LN_friendlyName "friendlyName"
|
||||
#define NID_friendlyName 156
|
||||
#define OBJ_friendlyName OBJ_pkcs9,20L
|
||||
|
|
|
@ -57,6 +57,7 @@ extern "C" {
|
|||
# define PEM_STRING_ECPRIVATEKEY "EC PRIVATE KEY"
|
||||
# define PEM_STRING_PARAMETERS "PARAMETERS"
|
||||
# define PEM_STRING_CMS "CMS"
|
||||
# define PEM_STRING_SM2PRIVATEKEY "SM2 PRIVATE KEY"
|
||||
# define PEM_STRING_SM2PARAMETERS "SM2 PARAMETERS"
|
||||
# define PEM_STRING_ACERT "ATTRIBUTE CERTIFICATE"
|
||||
|
||||
|
|
|
@ -1342,6 +1342,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
|
|||
# define SSL_CTRL_GET0_IMPLEMENTED_GROUPS 139
|
||||
# define SSL_CTRL_GET_SIGNATURE_NAME 140
|
||||
# define SSL_CTRL_GET_PEER_SIGNATURE_NAME 141
|
||||
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP_EX 142
|
||||
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP_EX 143
|
||||
# define SSL_CERT_SET_FIRST 1
|
||||
# define SSL_CERT_SET_NEXT 2
|
||||
# define SSL_CERT_SET_SERVER 3
|
||||
|
|
|
@ -325,6 +325,12 @@ __owur int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain)
|
|||
# define SSL_set_tlsext_status_ocsp_resp(ssl, arg, arglen) \
|
||||
SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP,arglen,arg)
|
||||
|
||||
# define SSL_get0_tlsext_status_ocsp_resp_ex(ssl, arg) \
|
||||
SSL_ctrl(ssl, SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP_EX, 0, arg)
|
||||
|
||||
# define SSL_set0_tlsext_status_ocsp_resp_ex(ssl, arg) \
|
||||
SSL_ctrl(ssl, SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP_EX, 0, arg)
|
||||
|
||||
# define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \
|
||||
SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,\
|
||||
(void (*)(void))cb)
|
||||
|
|
|
@ -39,6 +39,8 @@ use OpenSSL::stackhash qw(generate_stack_macros);
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
DEFINE_STACK_OF(OCSP_RESPONSE)
|
||||
|
||||
/*-
|
||||
SSL_CTX -> X509_STORE
|
||||
-> X509_LOOKUP
|
||||
|
@ -316,6 +318,14 @@ X509_LOOKUP_ctrl_ex((x), X509_L_ADD_STORE, (name), 0, NULL, \
|
|||
# define X509_V_ERR_EC_KEY_EXPLICIT_PARAMS 94
|
||||
# define X509_V_ERR_RPK_UNTRUSTED 95
|
||||
|
||||
/* additional OCSP status errors */
|
||||
# define X509_V_ERR_OCSP_RESP_INVALID 96
|
||||
# define X509_V_ERR_OCSP_SIGNATURE_FAILURE 97
|
||||
# define X509_V_ERR_OCSP_NOT_YET_VALID 98
|
||||
# define X509_V_ERR_OCSP_HAS_EXPIRED 99
|
||||
# define X509_V_ERR_OCSP_NO_RESPONSE 100
|
||||
# define X509_V_ERR_CRL_VERIFY_FAILED 101
|
||||
|
||||
/* Certificate verify flags */
|
||||
# ifndef OPENSSL_NO_DEPRECATED_1_1_0
|
||||
# define X509_V_FLAG_CB_ISSUER_CHECK 0x0 /* Deprecated */
|
||||
|
@ -367,6 +377,11 @@ X509_LOOKUP_ctrl_ex((x), X509_L_ADD_STORE, (name), 0, NULL, \
|
|||
/* Do not check certificate/CRL validity against current time */
|
||||
# define X509_V_FLAG_NO_CHECK_TIME 0x200000
|
||||
|
||||
/* Verify OCSP stapling response for server certificate */
|
||||
# define X509_V_FLAG_OCSP_RESP_CHECK 0x400000
|
||||
/* Verify OCSP stapling responses for whole chain */
|
||||
# define X509_V_FLAG_OCSP_RESP_CHECK_ALL 0x800000
|
||||
|
||||
# define X509_VP_FLAG_DEFAULT 0x1
|
||||
# define X509_VP_FLAG_OVERWRITE 0x2
|
||||
# define X509_VP_FLAG_RESET_FLAGS 0x4
|
||||
|
@ -675,6 +690,9 @@ void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *target);
|
|||
void X509_STORE_CTX_set0_rpk(X509_STORE_CTX *ctx, EVP_PKEY *target);
|
||||
void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *c, STACK_OF(X509) *sk);
|
||||
void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk);
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
void X509_STORE_CTX_set_ocsp_resp(X509_STORE_CTX *ctx, STACK_OF(OCSP_RESPONSE) *sk);
|
||||
# endif
|
||||
int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
|
||||
int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust);
|
||||
int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
-- Copyright 2025 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
|
||||
|
||||
-- -------------------------------------------------------------------
|
||||
-- Taken from https://datatracker.ietf.org/doc/rfc8619/
|
||||
|
||||
id-smime OBJECT IDENTIFIER ::= { 1 2 840 113549 1 9 16 }
|
||||
id-alg OBJECT IDENTIFIER ::= { id-smime 3 }
|
||||
|
||||
id-alg-hkdf-with-sha256 OBJECT IDENTIFIER ::= { id-alg 28 }
|
||||
id-alg-hkdf-with-sha384 OBJECT IDENTIFIER ::= { id-alg 29 }
|
||||
id-alg-hkdf-with-sha512 OBJECT IDENTIFIER ::= { id-alg 30 }
|
|
@ -127,9 +127,20 @@ IF[{- !$disabled{'slh-dsa'} -}]
|
|||
DEPEND[$DER_SLH_DSA_H]=oids_to_c.pm SLH_DSA.asn1
|
||||
ENDIF
|
||||
|
||||
#----- HKDF
|
||||
$DER_HKDF_H=$INCDIR/der_hkdf.h
|
||||
$DER_HKDF_GEN=der_hkdf_gen.c
|
||||
|
||||
GENERATE[$DER_HKDF_GEN]=der_hkdf_gen.c.in
|
||||
DEPEND[$DER_HKDF_GEN]=oids_to_c.pm HKDF.asn1
|
||||
|
||||
DEPEND[${DER_HKDF_GEN/.c/.o}]=$DER_HKDF_H
|
||||
GENERATE[$DER_HKDF_H]=$INCDIR/der_hkdf.h.in
|
||||
DEPEND[$DER_HKDF_H]=oids_to_c.pm HKDF.asn1
|
||||
|
||||
#----- Conclusion
|
||||
|
||||
$COMMON= $DER_RSA_COMMON $DER_DIGESTS_GEN $DER_WRAP_GEN
|
||||
$COMMON= $DER_RSA_COMMON $DER_DIGESTS_GEN $DER_WRAP_GEN $DER_HKDF_GEN
|
||||
|
||||
IF[{- !$disabled{dsa} -}]
|
||||
$COMMON = $COMMON $DER_DSA_GEN $DER_DSA_AUX
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* {- join("\n * ", @autowarntext) -}
|
||||
*
|
||||
* Copyright 2025 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 "prov/der_hkdf.h"
|
||||
|
||||
/* Well known OIDs precompiled */
|
||||
{-
|
||||
$OUT = oids_to_c::process_leaves('providers/common/der/HKDF.asn1',
|
||||
{ dir => $config{sourcedir},
|
||||
filter => \&oids_to_c::filter_to_C });
|
||||
-}
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* {- join("\n * ", @autowarntext) -}
|
||||
*
|
||||
* Copyright 2025 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 "internal/der.h"
|
||||
|
||||
/* Well known OIDs precompiled */
|
||||
{-
|
||||
$OUT = oids_to_c::process_leaves('providers/common/der/HKDF.asn1',
|
||||
{ dir => $config{sourcedir},
|
||||
filter => \&oids_to_c::filter_to_H });
|
||||
-}
|
|
@ -65,6 +65,7 @@ static OSSL_FUNC_core_vset_error_fn *c_vset_error;
|
|||
static OSSL_FUNC_core_set_error_mark_fn *c_set_error_mark;
|
||||
static OSSL_FUNC_core_clear_last_error_mark_fn *c_clear_last_error_mark;
|
||||
static OSSL_FUNC_core_pop_error_to_mark_fn *c_pop_error_to_mark;
|
||||
static OSSL_FUNC_core_count_to_mark_fn *c_count_to_mark;
|
||||
static OSSL_FUNC_CRYPTO_malloc_fn *c_CRYPTO_malloc;
|
||||
static OSSL_FUNC_CRYPTO_zalloc_fn *c_CRYPTO_zalloc;
|
||||
static OSSL_FUNC_CRYPTO_free_fn *c_CRYPTO_free;
|
||||
|
@ -834,6 +835,9 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle,
|
|||
case OSSL_FUNC_CORE_POP_ERROR_TO_MARK:
|
||||
set_func(c_pop_error_to_mark, OSSL_FUNC_core_pop_error_to_mark(in));
|
||||
break;
|
||||
case OSSL_FUNC_CORE_COUNT_TO_MARK:
|
||||
set_func(c_count_to_mark, OSSL_FUNC_core_count_to_mark(in));
|
||||
break;
|
||||
case OSSL_FUNC_CRYPTO_MALLOC:
|
||||
set_func(c_CRYPTO_malloc, OSSL_FUNC_CRYPTO_malloc(in));
|
||||
break;
|
||||
|
@ -1072,6 +1076,11 @@ int ERR_pop_to_mark(void)
|
|||
return c_pop_error_to_mark(NULL);
|
||||
}
|
||||
|
||||
int ERR_count_to_mark(void)
|
||||
{
|
||||
return c_count_to_mark != NULL ? c_count_to_mark(NULL) : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This must take a library context, since it's called from the depths
|
||||
* of crypto/initthread.c code, where it's (correctly) assumed that the
|
||||
|
|
|
@ -1027,38 +1027,39 @@ static const unsigned char dh_priv[] = {
|
|||
0x40, 0xb8, 0xfc, 0xe6
|
||||
};
|
||||
static const unsigned char dh_pub[] = {
|
||||
0x95, 0xdd, 0x33, 0x8d, 0x29, 0xe5, 0x71, 0x04,
|
||||
0x92, 0xb9, 0x18, 0x31, 0x7b, 0x72, 0xa3, 0x69,
|
||||
0x36, 0xe1, 0x95, 0x1a, 0x2e, 0xe5, 0xa5, 0x59,
|
||||
0x16, 0x99, 0xc0, 0x48, 0x6d, 0x0d, 0x4f, 0x9b,
|
||||
0xdd, 0x6d, 0x5a, 0x3f, 0x6b, 0x98, 0x89, 0x0c,
|
||||
0x62, 0xb3, 0x76, 0x52, 0xd3, 0x6e, 0x71, 0x21,
|
||||
0x11, 0xe6, 0x8a, 0x73, 0x55, 0x37, 0x25, 0x06,
|
||||
0x99, 0xef, 0xe3, 0x30, 0x53, 0x73, 0x91, 0xfb,
|
||||
0xc2, 0xc5, 0x48, 0xbc, 0x5a, 0xc3, 0xe5, 0xb2,
|
||||
0x33, 0x86, 0xc3, 0xee, 0xf5, 0xeb, 0x43, 0xc0,
|
||||
0x99, 0xd7, 0x0a, 0x52, 0x02, 0x68, 0x7e, 0x83,
|
||||
0x96, 0x42, 0x48, 0xfc, 0xa9, 0x1f, 0x40, 0x90,
|
||||
0x8e, 0x8f, 0xb3, 0x31, 0x93, 0x15, 0xf6, 0xd2,
|
||||
0x60, 0x6d, 0x7f, 0x7c, 0xd5, 0x2c, 0xc6, 0xe7,
|
||||
0xc5, 0x84, 0x3a, 0xfb, 0x22, 0x51, 0x9c, 0xf0,
|
||||
0xf0, 0xf9, 0xd3, 0xa0, 0xa4, 0xe8, 0xc8, 0x88,
|
||||
0x99, 0xef, 0xed, 0xe7, 0x36, 0x43, 0x51, 0xfb,
|
||||
0x6a, 0x36, 0x3e, 0xe7, 0x17, 0xe5, 0x44, 0x5a,
|
||||
0xda, 0xb4, 0xc9, 0x31, 0xa6, 0x48, 0x39, 0x97,
|
||||
0xb8, 0x7d, 0xad, 0x83, 0x67, 0x7e, 0x4d, 0x1d,
|
||||
0x3a, 0x77, 0x75, 0xe0, 0xf6, 0xd0, 0x0f, 0xdf,
|
||||
0x73, 0xc7, 0xad, 0x80, 0x1e, 0x66, 0x5a, 0x0e,
|
||||
0x5a, 0x79, 0x6d, 0x0a, 0x03, 0x80, 0xa1, 0x9f,
|
||||
0xa1, 0x82, 0xef, 0xc8, 0xa0, 0x4f, 0x5e, 0x4d,
|
||||
0xb9, 0x0d, 0x1a, 0x86, 0x37, 0xf9, 0x5d, 0xb1,
|
||||
0x64, 0x36, 0xbd, 0xc8, 0xf3, 0xfc, 0x09, 0x6c,
|
||||
0x4f, 0xf7, 0xf2, 0x34, 0xbe, 0x8f, 0xef, 0x47,
|
||||
0x9a, 0xc4, 0xb0, 0xdc, 0x4b, 0x77, 0x26, 0x3e,
|
||||
0x07, 0xd9, 0x95, 0x9d, 0xe0, 0xf1, 0xbf, 0x3f,
|
||||
0x0a, 0xe3, 0xd9, 0xd5, 0x0e, 0x4b, 0x89, 0xc9,
|
||||
0x9e, 0x3e, 0xa1, 0x21, 0x73, 0x43, 0xdd, 0x8c,
|
||||
0x65, 0x81, 0xac, 0xc4, 0x95, 0x9c, 0x91, 0xd3
|
||||
0x00, 0x8f, 0x81, 0x67, 0x68, 0xce, 0x97, 0x99,
|
||||
0x7e, 0x11, 0x5c, 0xad, 0x5b, 0xe1, 0x0c, 0xd4,
|
||||
0x15, 0x44, 0xdf, 0xc2, 0x47, 0xe7, 0x06, 0x27,
|
||||
0x5e, 0xf3, 0x9d, 0x5c, 0x4b, 0x2e, 0x35, 0x05,
|
||||
0xfd, 0x3c, 0x8f, 0x35, 0x85, 0x1b, 0x82, 0xdd,
|
||||
0x49, 0xc9, 0xa8, 0x7e, 0x3a, 0x5f, 0x33, 0xdc,
|
||||
0x8f, 0x5e, 0x32, 0x76, 0xe1, 0x52, 0x1b, 0x88,
|
||||
0x85, 0xda, 0xa9, 0x1d, 0x5f, 0x1c, 0x05, 0x3a,
|
||||
0xd4, 0x8d, 0xbb, 0xe7, 0x46, 0x46, 0x1e, 0x29,
|
||||
0x4b, 0x5a, 0x02, 0x88, 0x46, 0x94, 0xd0, 0x68,
|
||||
0x7d, 0xb2, 0x9f, 0x3a, 0x3d, 0x82, 0x05, 0xe5,
|
||||
0xa7, 0xbe, 0x6c, 0x7e, 0x24, 0x35, 0x25, 0x14,
|
||||
0xf3, 0x45, 0x08, 0x90, 0xfc, 0x55, 0x2e, 0xa8,
|
||||
0xb8, 0xb1, 0x89, 0x15, 0x94, 0x51, 0x44, 0xa9,
|
||||
0x9f, 0x68, 0xcb, 0x90, 0xbc, 0xd3, 0xae, 0x02,
|
||||
0x37, 0x26, 0xe4, 0xe9, 0x1a, 0x90, 0x95, 0x7e,
|
||||
0x1d, 0xac, 0x0c, 0x91, 0x97, 0x83, 0x24, 0x83,
|
||||
0xb9, 0xa1, 0x40, 0x72, 0xac, 0xf0, 0x55, 0x32,
|
||||
0x18, 0xab, 0xb8, 0x90, 0xda, 0x13, 0x4a, 0xc8,
|
||||
0x4b, 0x7c, 0x18, 0xbc, 0x33, 0xbf, 0x99, 0x85,
|
||||
0x39, 0x3e, 0xc6, 0x95, 0x9b, 0x48, 0x8e, 0xbe,
|
||||
0x46, 0x59, 0x48, 0x41, 0x0d, 0x37, 0x25, 0x94,
|
||||
0xbe, 0x8d, 0xf5, 0x81, 0x52, 0xf6, 0xdc, 0xeb,
|
||||
0x98, 0xd7, 0x3b, 0x44, 0x61, 0x6f, 0xa3, 0xef,
|
||||
0x7b, 0xfe, 0xbb, 0xc2, 0x8e, 0x46, 0x63, 0xbc,
|
||||
0x52, 0x65, 0xf9, 0xf8, 0x85, 0x41, 0xdf, 0x82,
|
||||
0x4a, 0x10, 0x2a, 0xe3, 0x0c, 0xb7, 0xad, 0x84,
|
||||
0xa6, 0x6f, 0x4e, 0x8e, 0x96, 0x1e, 0x04, 0xf7,
|
||||
0x57, 0x39, 0xca, 0x58, 0xd4, 0xef, 0x5a, 0xf1,
|
||||
0xf5, 0x69, 0xc2, 0xb1, 0x5c, 0x0a, 0xce, 0xbe,
|
||||
0x38, 0x01, 0xb5, 0x3f, 0x07, 0x8a, 0x72, 0x90,
|
||||
0x10, 0xac, 0x51, 0x3a, 0x96, 0x43, 0xdf, 0x6f,
|
||||
0xea
|
||||
};
|
||||
static const unsigned char dh_peer_pub[] = {
|
||||
0x1f, 0xc1, 0xda, 0x34, 0x1d, 0x1a, 0x84, 0x6a,
|
||||
|
|
|
@ -151,6 +151,7 @@ static int pem2der_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
|
|||
{ PEM_STRING_DSAPARAMS, OSSL_OBJECT_PKEY, "DSA", "type-specific" },
|
||||
{ PEM_STRING_ECPRIVATEKEY, OSSL_OBJECT_PKEY, "EC", "type-specific" },
|
||||
{ PEM_STRING_ECPARAMETERS, OSSL_OBJECT_PKEY, "EC", "type-specific" },
|
||||
{ PEM_STRING_SM2PRIVATEKEY, OSSL_OBJECT_PKEY, "SM2", "type-specific" },
|
||||
{ PEM_STRING_SM2PARAMETERS, OSSL_OBJECT_PKEY, "SM2", "type-specific" },
|
||||
{ PEM_STRING_RSA, OSSL_OBJECT_PKEY, "RSA", "type-specific" },
|
||||
{ PEM_STRING_RSA_PUBLIC, OSSL_OBJECT_PKEY, "RSA", "type-specific" },
|
||||
|
|
|
@ -47,6 +47,7 @@ IF[{- !$disabled{'ml-kem'} -}]
|
|||
SOURCE[$TLS_ML_KEM_HYBRID_GOAL]=mlx_kmgmt.c
|
||||
ENDIF
|
||||
SOURCE[$ML_KEM_GOAL]=ml_kem_kmgmt.c
|
||||
DEPEND[ml_kem_kmgmt.o]=../../common/include/prov/der_hkdf.h
|
||||
ENDIF
|
||||
|
||||
SOURCE[$RSA_GOAL]=rsa_kmgmt.c
|
||||
|
|
|
@ -19,9 +19,13 @@ use OpenSSL::paramnames qw(produce_param_decoder);
|
|||
#include <openssl/rand.h>
|
||||
#include <openssl/self_test.h>
|
||||
#include <openssl/param_build.h>
|
||||
#include <openssl/cms.h>
|
||||
#include "crypto/ml_kem.h"
|
||||
#include "internal/fips.h"
|
||||
#include "internal/param_build_set.h"
|
||||
#include "internal/sizes.h"
|
||||
#include "prov/der_hkdf.h"
|
||||
#include "prov/der_wrap.h"
|
||||
#include "prov/implementations.h"
|
||||
#include "prov/providercommon.h"
|
||||
#include "prov/provider_ctx.h"
|
||||
|
@ -494,7 +498,9 @@ static int ml_kem_import(void *vkey, int selection, const OSSL_PARAM params[])
|
|||
['PKEY_PARAM_PRIV_KEY', 'privkey', 'octet_string'],
|
||||
['PKEY_PARAM_PUB_KEY', 'pubkey', 'octet_string'],
|
||||
['PKEY_PARAM_ENCODED_PUBLIC_KEY', 'encpubkey', 'octet_string'],
|
||||
)); -}
|
||||
['PKEY_PARAM_CMS_RI_TYPE', 'ri_type', 'int'],
|
||||
['PKEY_PARAM_CMS_KEMRI_KDF_ALGORITHM', 'kemri_kdf_alg', 'octet_string'],
|
||||
)); -}
|
||||
|
||||
static const OSSL_PARAM *ml_kem_gettable_params(void *provctx)
|
||||
{
|
||||
|
@ -612,6 +618,36 @@ static int ml_kem_get_params(void *vkey, OSSL_PARAM params[])
|
|||
&ossl_ml_kem_encode_seed))
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
if (p.ri_type != NULL && !OSSL_PARAM_set_int(p.ri_type, CMS_RECIPINFO_KEM))
|
||||
return 0;
|
||||
|
||||
if (p.kemri_kdf_alg != NULL) {
|
||||
uint8_t aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE];
|
||||
int ret;
|
||||
size_t aid_len = 0;
|
||||
WPACKET pkt;
|
||||
uint8_t *aid = NULL;
|
||||
|
||||
ret = WPACKET_init_der(&pkt, aid_buf, sizeof(aid_buf));
|
||||
ret &= ossl_DER_w_begin_sequence(&pkt, -1)
|
||||
&& ossl_DER_w_precompiled(&pkt, -1, ossl_der_oid_id_alg_hkdf_with_sha256,
|
||||
sizeof(ossl_der_oid_id_alg_hkdf_with_sha256))
|
||||
&& ossl_DER_w_end_sequence(&pkt, -1);
|
||||
if (ret && WPACKET_finish(&pkt)) {
|
||||
WPACKET_get_total_written(&pkt, &aid_len);
|
||||
aid = WPACKET_get_curr(&pkt);
|
||||
}
|
||||
WPACKET_cleanup(&pkt);
|
||||
if (!ret)
|
||||
return 0;
|
||||
if (aid != NULL && aid_len != 0 &&
|
||||
!OSSL_PARAM_set_octet_string(p.kemri_kdf_alg, aid, aid_len))
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ static OSSL_FUNC_core_vset_error_fn *c_vset_error;
|
|||
static OSSL_FUNC_core_set_error_mark_fn *c_set_error_mark;
|
||||
static OSSL_FUNC_core_clear_last_error_mark_fn *c_clear_last_error_mark;
|
||||
static OSSL_FUNC_core_pop_error_to_mark_fn *c_pop_error_to_mark;
|
||||
static OSSL_FUNC_core_count_to_mark_fn *c_count_to_mark;
|
||||
#endif
|
||||
|
||||
/* Parameters we provide to the core */
|
||||
|
@ -234,6 +235,9 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle,
|
|||
case OSSL_FUNC_CORE_POP_ERROR_TO_MARK:
|
||||
set_func(c_pop_error_to_mark, OSSL_FUNC_core_pop_error_to_mark(tmp));
|
||||
break;
|
||||
case OSSL_FUNC_CORE_COUNT_TO_MARK:
|
||||
set_func(c_count_to_mark, OSSL_FUNC_core_count_to_mark(in));
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -301,4 +305,9 @@ int ERR_pop_to_mark(void)
|
|||
{
|
||||
return c_pop_error_to_mark(NULL);
|
||||
}
|
||||
|
||||
int ERR_count_to_mark(void)
|
||||
{
|
||||
return c_count_to_mark != NULL ? c_count_to_mark(NULL) : 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -536,6 +536,9 @@ struct ossl_ackm_st {
|
|||
/* Set to 1 when the handshake is confirmed. */
|
||||
char handshake_confirmed;
|
||||
|
||||
/* Set to 1 when attached to server channel */
|
||||
char is_server;
|
||||
|
||||
/* Set to 1 when the peer has completed address validation. */
|
||||
char peer_completed_addr_validation;
|
||||
|
||||
|
@ -855,7 +858,13 @@ static OSSL_TIME ackm_get_pto_time_and_space(OSSL_ACKM *ackm, int *space)
|
|||
}
|
||||
|
||||
for (i = QUIC_PN_SPACE_INITIAL; i < QUIC_PN_SPACE_NUM; ++i) {
|
||||
if (ackm->ack_eliciting_bytes_in_flight[i] == 0)
|
||||
/*
|
||||
* RFC 9002 section 6.2.2.1 keep probe timeout armed until
|
||||
* handshake is confirmed (client sees HANDSHAKE_DONE message
|
||||
* from server).
|
||||
*/
|
||||
if (ackm->ack_eliciting_bytes_in_flight[i] == 0 &&
|
||||
(ackm->handshake_confirmed == 1 || ackm->is_server == 1))
|
||||
continue;
|
||||
|
||||
if (i == QUIC_PN_SPACE_APP) {
|
||||
|
@ -875,10 +884,18 @@ static OSSL_TIME ackm_get_pto_time_and_space(OSSL_ACKM *ackm, int *space)
|
|||
}
|
||||
}
|
||||
|
||||
t = ossl_time_add(ackm->time_of_last_ack_eliciting_pkt[i], duration);
|
||||
if (ossl_time_compare(t, pto_timeout) < 0) {
|
||||
pto_timeout = t;
|
||||
pto_space = i;
|
||||
/*
|
||||
* Only re-arm timer if stack has sent at least one ACK eliciting frame.
|
||||
* If stack has sent no ACK eliciting frame at given encryption level then
|
||||
* particular timer is zero and we must not attempt to set it. Timer keeps
|
||||
* time since epoch (Jan 1 1970) and we must not set timer to past.
|
||||
*/
|
||||
if (!ossl_time_is_zero(ackm->time_of_last_ack_eliciting_pkt[i])) {
|
||||
t = ossl_time_add(ackm->time_of_last_ack_eliciting_pkt[i], duration);
|
||||
if (ossl_time_compare(t, pto_timeout) < 0) {
|
||||
pto_timeout = t;
|
||||
pto_space = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1021,7 +1038,8 @@ OSSL_ACKM *ossl_ackm_new(OSSL_TIME (*now)(void *arg),
|
|||
void *now_arg,
|
||||
OSSL_STATM *statm,
|
||||
const OSSL_CC_METHOD *cc_method,
|
||||
OSSL_CC_DATA *cc_data)
|
||||
OSSL_CC_DATA *cc_data,
|
||||
int is_server)
|
||||
{
|
||||
OSSL_ACKM *ackm;
|
||||
int i;
|
||||
|
@ -1045,6 +1063,7 @@ OSSL_ACKM *ossl_ackm_new(OSSL_TIME (*now)(void *arg),
|
|||
ackm->statm = statm;
|
||||
ackm->cc_method = cc_method;
|
||||
ackm->cc_data = cc_data;
|
||||
ackm->is_server = (char)is_server;
|
||||
|
||||
ackm->rx_max_ack_delay = ossl_ms2time(QUIC_DEFAULT_MAX_ACK_DELAY);
|
||||
ackm->tx_max_ack_delay = DEFAULT_TX_MAX_ACK_DELAY;
|
||||
|
|
|
@ -242,7 +242,8 @@ static int ch_init(QUIC_CHANNEL *ch)
|
|||
goto err;
|
||||
|
||||
if ((ch->ackm = ossl_ackm_new(get_time, ch, &ch->statm,
|
||||
ch->cc_method, ch->cc_data)) == NULL)
|
||||
ch->cc_method, ch->cc_data,
|
||||
ch->is_server)) == NULL)
|
||||
goto err;
|
||||
|
||||
if (!ossl_quic_stream_map_init(&ch->qsm, get_stream_limit, ch,
|
||||
|
|
84
ssl/s3_lib.c
84
ssl/s3_lib.c
|
@ -22,6 +22,7 @@
|
|||
#include <openssl/core_names.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/ssl_unwrap.h"
|
||||
#include <openssl/ocsp.h>
|
||||
|
||||
#define TLS13_NUM_CIPHERS OSSL_NELEM(tls13_ciphers)
|
||||
#define SSL3_NUM_CIPHERS OSSL_NELEM(ssl3_ciphers)
|
||||
|
@ -3534,6 +3535,10 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
|
|||
{
|
||||
int ret = 0;
|
||||
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
unsigned char *p = NULL;
|
||||
OCSP_RESPONSE *resp = NULL;
|
||||
#endif
|
||||
|
||||
if (sc == NULL)
|
||||
return ret;
|
||||
|
@ -3666,16 +3671,79 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
|
|||
break;
|
||||
|
||||
case SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP:
|
||||
*(unsigned char **)parg = sc->ext.ocsp.resp;
|
||||
if (sc->ext.ocsp.resp_len == 0
|
||||
|| sc->ext.ocsp.resp_len > LONG_MAX)
|
||||
return -1;
|
||||
return (long)sc->ext.ocsp.resp_len;
|
||||
*(unsigned char **)parg = NULL;
|
||||
ret = -1;
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
resp = sk_OCSP_RESPONSE_value(sc->ext.ocsp.resp_ex, 0);
|
||||
|
||||
if (resp != NULL) {
|
||||
int resp_len = i2d_OCSP_RESPONSE(resp, &p);
|
||||
|
||||
if (resp_len > 0) {
|
||||
OPENSSL_free(sc->ext.ocsp.resp);
|
||||
*(unsigned char **)parg = sc->ext.ocsp.resp = p;
|
||||
sc->ext.ocsp.resp_len = (size_t)resp_len;
|
||||
ret = resp_len;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP:
|
||||
OPENSSL_free(sc->ext.ocsp.resp);
|
||||
sc->ext.ocsp.resp = parg;
|
||||
sc->ext.ocsp.resp_len = larg;
|
||||
ret = 1;
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
/*
|
||||
* cleanup single values, which might be set somewhere else
|
||||
* we only use the extended values
|
||||
*/
|
||||
if (sc->ext.ocsp.resp != NULL) {
|
||||
OPENSSL_free(sc->ext.ocsp.resp);
|
||||
sc->ext.ocsp.resp = NULL;
|
||||
sc->ext.ocsp.resp_len = 0;
|
||||
}
|
||||
|
||||
sk_OCSP_RESPONSE_pop_free(sc->ext.ocsp.resp_ex, OCSP_RESPONSE_free);
|
||||
sc->ext.ocsp.resp_ex = NULL;
|
||||
|
||||
if (parg != NULL) {
|
||||
sc->ext.ocsp.resp_ex = sk_OCSP_RESPONSE_new_reserve(NULL, 1);
|
||||
if (sc->ext.ocsp.resp_ex == NULL)
|
||||
return 0;
|
||||
|
||||
p = parg;
|
||||
resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p, larg);
|
||||
if (resp != NULL)
|
||||
sk_OCSP_RESPONSE_push(sc->ext.ocsp.resp_ex, resp);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP_EX:
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
*(STACK_OF(OCSP_RESPONSE) **)parg = sc->ext.ocsp.resp_ex;
|
||||
ret = sk_OCSP_RESPONSE_num(sc->ext.ocsp.resp_ex);
|
||||
#else
|
||||
*(unsigned char **)parg = NULL;
|
||||
ret = -1;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP_EX:
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
/*
|
||||
* cleanup single values, which might be set somewhere else
|
||||
* we only use the extended values
|
||||
*/
|
||||
if (sc->ext.ocsp.resp != NULL) {
|
||||
OPENSSL_free(sc->ext.ocsp.resp);
|
||||
sc->ext.ocsp.resp = NULL;
|
||||
sc->ext.ocsp.resp_len = 0;
|
||||
}
|
||||
|
||||
sk_OCSP_RESPONSE_pop_free(sc->ext.ocsp.resp_ex, OCSP_RESPONSE_free);
|
||||
sc->ext.ocsp.resp_ex = (STACK_OF(OCSP_RESPONSE) *)parg;
|
||||
#endif
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
|
|
|
@ -433,6 +433,9 @@ static int ssl_verify_internal(SSL_CONNECTION *s, STACK_OF(X509) *sk, EVP_PKEY *
|
|||
X509_STORE_CTX *ctx = NULL;
|
||||
X509_VERIFY_PARAM *param;
|
||||
SSL_CTX *sctx;
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
SSL *ssl;
|
||||
#endif
|
||||
|
||||
/* Something must be passed in */
|
||||
if ((sk == NULL || sk_X509_num(sk) == 0) && rpk == NULL)
|
||||
|
@ -486,6 +489,26 @@ static int ssl_verify_internal(SSL_CONNECTION *s, STACK_OF(X509) *sk, EVP_PKEY *
|
|||
if (DANETLS_ENABLED(&s->dane))
|
||||
X509_STORE_CTX_set0_dane(ctx, &s->dane);
|
||||
|
||||
/*
|
||||
* Set OCSP Responses for verification:
|
||||
* This function is called in the SERVER_CERTIFICATE message, in TLS 1.2
|
||||
* the OCSP responses are sent in the CERT_STATUS message after that.
|
||||
* Therefore the verification code currently only works in TLS 1.3.
|
||||
*/
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
ssl = SSL_CONNECTION_GET_SSL(s);
|
||||
/*
|
||||
* TODO(DTLS-1.3): in future DTLS should also be considered
|
||||
*/
|
||||
if (!SSL_is_dtls(ssl) && SSL_version(ssl) >= TLS1_3_VERSION) {
|
||||
/* ignore status_request_v2 if TLS version < 1.3 */
|
||||
int status = SSL_get_tlsext_status_type(ssl);
|
||||
|
||||
if (status == TLSEXT_STATUSTYPE_ocsp)
|
||||
X509_STORE_CTX_set_ocsp_resp(ctx, s->ext.ocsp.resp_ex);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We need to inherit the verify parameters. These can be determined by
|
||||
* the context: if its a server it will verify SSL client certificates or
|
||||
|
@ -555,7 +578,7 @@ int ssl_verify_cert_chain(SSL_CONNECTION *s, STACK_OF(X509) *sk)
|
|||
}
|
||||
|
||||
static void set0_CA_list(STACK_OF(X509_NAME) **ca_list,
|
||||
STACK_OF(X509_NAME) *name_list)
|
||||
STACK_OF(X509_NAME) *name_list)
|
||||
{
|
||||
sk_X509_NAME_pop_free(*ca_list, X509_NAME_free);
|
||||
*ca_list = name_list;
|
||||
|
|
|
@ -831,6 +831,7 @@ SSL *ossl_ssl_connection_new_int(SSL_CTX *ctx, SSL *user_ssl,
|
|||
s->ext.ocsp.exts = NULL;
|
||||
s->ext.ocsp.resp = NULL;
|
||||
s->ext.ocsp.resp_len = 0;
|
||||
s->ext.ocsp.resp_ex = NULL;
|
||||
|
||||
if (!SSL_CTX_up_ref(ctx))
|
||||
goto err;
|
||||
|
@ -1497,14 +1498,20 @@ void ossl_ssl_connection_free(SSL *ssl)
|
|||
OPENSSL_free(s->ext.tuples);
|
||||
OPENSSL_free(s->ext.peer_supportedgroups);
|
||||
sk_X509_EXTENSION_pop_free(s->ext.ocsp.exts, X509_EXTENSION_free);
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
OPENSSL_free(s->ext.ocsp.resp);
|
||||
s->ext.ocsp.resp = NULL;
|
||||
s->ext.ocsp.resp_len = 0;
|
||||
|
||||
sk_OCSP_RESPID_pop_free(s->ext.ocsp.ids, OCSP_RESPID_free);
|
||||
sk_OCSP_RESPONSE_pop_free(s->ext.ocsp.resp_ex, OCSP_RESPONSE_free);
|
||||
s->ext.ocsp.resp_ex = NULL;
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_CT
|
||||
SCT_LIST_free(s->scts);
|
||||
OPENSSL_free(s->ext.scts);
|
||||
#endif
|
||||
OPENSSL_free(s->ext.ocsp.resp);
|
||||
OPENSSL_free(s->ext.alpn);
|
||||
OPENSSL_free(s->ext.tls13_cookie);
|
||||
if (s->clienthello != NULL)
|
||||
|
@ -6428,41 +6435,59 @@ static int ct_extract_ocsp_response_scts(SSL_CONNECTION *s)
|
|||
{
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
int scts_extracted = 0;
|
||||
const unsigned char *p;
|
||||
OCSP_BASICRESP *br = NULL;
|
||||
OCSP_RESPONSE *rsp = NULL;
|
||||
STACK_OF(SCT) *scts = NULL;
|
||||
int i;
|
||||
int ret;
|
||||
int i, j;
|
||||
|
||||
if (s->ext.ocsp.resp == NULL || s->ext.ocsp.resp_len == 0)
|
||||
if (s->ext.ocsp.resp_ex == NULL)
|
||||
goto err;
|
||||
|
||||
p = s->ext.ocsp.resp;
|
||||
rsp = d2i_OCSP_RESPONSE(NULL, &p, (int)s->ext.ocsp.resp_len);
|
||||
if (rsp == NULL)
|
||||
goto err;
|
||||
|
||||
br = OCSP_response_get1_basic(rsp);
|
||||
if (br == NULL)
|
||||
goto err;
|
||||
|
||||
for (i = 0; i < OCSP_resp_count(br); ++i) {
|
||||
OCSP_SINGLERESP *single = OCSP_resp_get0(br, i);
|
||||
|
||||
if (single == NULL)
|
||||
continue;
|
||||
|
||||
scts =
|
||||
OCSP_SINGLERESP_get1_ext_d2i(single, NID_ct_cert_scts, NULL, NULL);
|
||||
scts_extracted =
|
||||
ct_move_scts(&s->scts, scts, SCT_SOURCE_OCSP_STAPLED_RESPONSE);
|
||||
if (scts_extracted < 0)
|
||||
for (j = 0; j < sk_OCSP_RESPONSE_num(s->ext.ocsp.resp_ex); j++) {
|
||||
rsp = sk_OCSP_RESPONSE_value(s->ext.ocsp.resp_ex, j);
|
||||
if (rsp == NULL)
|
||||
goto err;
|
||||
|
||||
br = OCSP_response_get1_basic(rsp);
|
||||
if (br == NULL)
|
||||
goto err;
|
||||
|
||||
for (i = 0; i < OCSP_resp_count(br); ++i) {
|
||||
OCSP_SINGLERESP *single = OCSP_resp_get0(br, i);
|
||||
|
||||
if (single == NULL)
|
||||
continue;
|
||||
|
||||
scts = OCSP_SINGLERESP_get1_ext_d2i(single,
|
||||
NID_ct_cert_scts, NULL, NULL);
|
||||
|
||||
OCSP_SINGLERESP_free(single);
|
||||
|
||||
if (scts == NULL) {
|
||||
scts_extracted = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = ct_move_scts(&s->scts, scts,
|
||||
SCT_SOURCE_OCSP_STAPLED_RESPONSE);
|
||||
|
||||
SCT_LIST_free(scts);
|
||||
|
||||
if (ret < 0) {
|
||||
scts_extracted = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
scts_extracted += ret;
|
||||
}
|
||||
|
||||
OCSP_BASICRESP_free(br);
|
||||
/* to assure that is not freed twice */
|
||||
br = NULL;
|
||||
}
|
||||
err:
|
||||
SCT_LIST_free(scts);
|
||||
OCSP_BASICRESP_free(br);
|
||||
OCSP_RESPONSE_free(rsp);
|
||||
return scts_extracted;
|
||||
# else
|
||||
/* Behave as if no OCSP response exists */
|
||||
|
|
|
@ -1639,6 +1639,7 @@ struct ssl_connection_st {
|
|||
/* OCSP response received or to be sent */
|
||||
unsigned char *resp;
|
||||
size_t resp_len;
|
||||
STACK_OF(OCSP_RESPONSE) *resp_ex;
|
||||
} ocsp;
|
||||
|
||||
/* RFC4507 session ticket expected to be received or sent */
|
||||
|
@ -2594,6 +2595,7 @@ void ssl_cert_set_cert_cb(CERT *c, int (*cb) (SSL *ssl, void *arg), void *arg);
|
|||
|
||||
__owur int ssl_verify_cert_chain(SSL_CONNECTION *s, STACK_OF(X509) *sk);
|
||||
__owur int ssl_verify_rpk(SSL_CONNECTION *s, EVP_PKEY *rpk);
|
||||
__owur int ssl_verify_ocsp(SSL *s, STACK_OF(X509) *sk);
|
||||
__owur int ssl_build_cert_chain(SSL_CONNECTION *s, SSL_CTX *ctx, int flags);
|
||||
__owur int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain,
|
||||
int ref);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "internal/ssl_unwrap.h"
|
||||
#include "../ssl_local.h"
|
||||
#include "statem_local.h"
|
||||
#include <openssl/ocsp.h>
|
||||
|
||||
static int final_renegotiate(SSL_CONNECTION *s, unsigned int context, int sent);
|
||||
static int init_server_name(SSL_CONNECTION *s, unsigned int context);
|
||||
|
@ -1148,6 +1149,9 @@ static int init_status_request(SSL_CONNECTION *s, unsigned int context)
|
|||
OPENSSL_free(s->ext.ocsp.resp);
|
||||
s->ext.ocsp.resp = NULL;
|
||||
s->ext.ocsp.resp_len = 0;
|
||||
|
||||
sk_OCSP_RESPONSE_pop_free(s->ext.ocsp.resp_ex, OCSP_RESPONSE_free);
|
||||
s->ext.ocsp.resp_ex = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -1510,14 +1510,8 @@ int tls_parse_stoc_status_request(SSL_CONNECTION *s, PACKET *pkt,
|
|||
}
|
||||
|
||||
if (SSL_CONNECTION_IS_TLS13(s)) {
|
||||
/* We only know how to handle this if it's for the first Certificate in
|
||||
* the chain. We ignore any other responses.
|
||||
*/
|
||||
if (chainidx != 0)
|
||||
return 1;
|
||||
|
||||
/* SSLfatal() already called */
|
||||
return tls_process_cert_status_body(s, pkt);
|
||||
return tls_process_cert_status_body(s, chainidx, pkt);
|
||||
}
|
||||
|
||||
/* Set flag to expect CertificateStatus message */
|
||||
|
|
|
@ -1751,9 +1751,6 @@ EXT_RETURN tls_construct_stoc_status_request(SSL_CONNECTION *s, WPACKET *pkt,
|
|||
if (!s->ext.status_expected)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (SSL_CONNECTION_IS_TLS13(s) && chainidx != 0)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||
|
@ -1765,9 +1762,10 @@ EXT_RETURN tls_construct_stoc_status_request(SSL_CONNECTION *s, WPACKET *pkt,
|
|||
* send back an empty extension, with the certificate status appearing as a
|
||||
* separate message
|
||||
*/
|
||||
if (SSL_CONNECTION_IS_TLS13(s) && !tls_construct_cert_status_body(s, pkt)) {
|
||||
/* SSLfatal() already called */
|
||||
return EXT_RETURN_FAIL;
|
||||
if (SSL_CONNECTION_IS_TLS13(s)
|
||||
&& !tls_construct_cert_status_body(s, chainidx, pkt)) {
|
||||
/* SSLfatal() already called */
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
if (!WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "internal/cryptlib.h"
|
||||
#include "internal/comp.h"
|
||||
#include "internal/ssl_unwrap.h"
|
||||
#include <openssl/ocsp.h>
|
||||
|
||||
static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL_CONNECTION *s,
|
||||
PACKET *pkt);
|
||||
|
@ -2900,40 +2901,77 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL_CONNECTION *s,
|
|||
* In TLSv1.3 this is called from the extensions code, otherwise it is used to
|
||||
* parse a separate message. Returns 1 on success or 0 on failure
|
||||
*/
|
||||
int tls_process_cert_status_body(SSL_CONNECTION *s, PACKET *pkt)
|
||||
int tls_process_cert_status_body(SSL_CONNECTION *s, size_t chainidx, PACKET *pkt)
|
||||
{
|
||||
size_t resplen;
|
||||
unsigned int type;
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
size_t resplen;
|
||||
unsigned char *respder;
|
||||
OCSP_RESPONSE *resp = NULL;
|
||||
const unsigned char *p;
|
||||
#endif
|
||||
|
||||
if (!PACKET_get_1(pkt, &type)
|
||||
|| type != TLSEXT_STATUSTYPE_ocsp) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_UNSUPPORTED_STATUS_TYPE);
|
||||
return 0;
|
||||
}
|
||||
if (!PACKET_get_net_3_len(pkt, &resplen)
|
||||
|| PACKET_remaining(pkt) != resplen) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
s->ext.ocsp.resp = OPENSSL_malloc(resplen);
|
||||
if (s->ext.ocsp.resp == NULL) {
|
||||
s->ext.ocsp.resp_len = 0;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
|
||||
return 0;
|
||||
}
|
||||
s->ext.ocsp.resp_len = resplen;
|
||||
if (!PACKET_copy_bytes(pkt, s->ext.ocsp.resp, resplen)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
OPENSSL_free(s->ext.ocsp.resp);
|
||||
s->ext.ocsp.resp = NULL;
|
||||
s->ext.ocsp.resp_len = 0;
|
||||
|
||||
if (s->ext.ocsp.resp_ex == NULL)
|
||||
s->ext.ocsp.resp_ex = sk_OCSP_RESPONSE_new_null();
|
||||
|
||||
/*
|
||||
* TODO(DTLS-1.3): in future DTLS should also be considered
|
||||
*/
|
||||
if (!SSL_CONNECTION_IS_TLS13(s) && type == TLSEXT_STATUSTYPE_ocsp) {
|
||||
sk_OCSP_RESPONSE_pop_free(s->ext.ocsp.resp_ex, OCSP_RESPONSE_free);
|
||||
s->ext.ocsp.resp_ex = sk_OCSP_RESPONSE_new_null();
|
||||
}
|
||||
|
||||
if (PACKET_remaining(pkt) > 0) {
|
||||
if (!PACKET_get_net_3_len(pkt, &resplen)
|
||||
|| PACKET_remaining(pkt) != resplen) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (resplen > 0) {
|
||||
respder = OPENSSL_malloc(resplen);
|
||||
|
||||
if (respder == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!PACKET_copy_bytes(pkt, respder, resplen)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
|
||||
OPENSSL_free(respder);
|
||||
return 0;
|
||||
}
|
||||
p = respder;
|
||||
resp = d2i_OCSP_RESPONSE(NULL, &p, (long)resplen);
|
||||
OPENSSL_free(respder);
|
||||
if (resp == NULL) {
|
||||
SSLfatal(s, TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE,
|
||||
SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE);
|
||||
return 0;
|
||||
}
|
||||
sk_OCSP_RESPONSE_insert(s->ext.ocsp.resp_ex, resp, (int)chainidx);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_cert_status(SSL_CONNECTION *s, PACKET *pkt)
|
||||
{
|
||||
if (!tls_process_cert_status_body(s, pkt)) {
|
||||
if (!tls_process_cert_status_body(s, 0, pkt)) {
|
||||
/* SSLfatal() already called */
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
|
|
@ -148,7 +148,7 @@ __owur MSG_PROCESS_RETURN tls_process_certificate_request(SSL_CONNECTION *s,
|
|||
PACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL_CONNECTION *s,
|
||||
PACKET *pkt);
|
||||
__owur int tls_process_cert_status_body(SSL_CONNECTION *s, PACKET *pkt);
|
||||
__owur int tls_process_cert_status_body(SSL_CONNECTION *s, size_t chainidx, PACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_cert_status(SSL_CONNECTION *s,
|
||||
PACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_server_done(SSL_CONNECTION *s,
|
||||
|
@ -168,7 +168,7 @@ __owur int ssl_do_client_cert_cb(SSL_CONNECTION *s, X509 **px509,
|
|||
__owur CON_FUNC_RETURN tls_construct_client_key_exchange(SSL_CONNECTION *s,
|
||||
WPACKET *pkt);
|
||||
__owur int tls_client_key_exchange_post_work(SSL_CONNECTION *s);
|
||||
__owur int tls_construct_cert_status_body(SSL_CONNECTION *s, WPACKET *pkt);
|
||||
__owur int tls_construct_cert_status_body(SSL_CONNECTION *s, size_t chainidx, WPACKET *pkt);
|
||||
__owur CON_FUNC_RETURN tls_construct_cert_status(SSL_CONNECTION *s,
|
||||
WPACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_key_exchange(SSL_CONNECTION *s,
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <openssl/asn1t.h>
|
||||
#include <openssl/comp.h>
|
||||
#include "internal/comp.h"
|
||||
#include <openssl/ocsp.h>
|
||||
|
||||
#define TICKET_NONCE_SIZE 8
|
||||
|
||||
|
@ -2193,8 +2194,11 @@ static int tls_handle_status_request(SSL_CONNECTION *s)
|
|||
break;
|
||||
/* status request response should be sent */
|
||||
case SSL_TLSEXT_ERR_OK:
|
||||
if (s->ext.ocsp.resp)
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
if (s->ext.ocsp.resp_ex != NULL
|
||||
&& sk_OCSP_RESPONSE_num(s->ext.ocsp.resp_ex) > 0)
|
||||
s->ext.status_expected = 1;
|
||||
#endif
|
||||
break;
|
||||
/* something bad happened */
|
||||
case SSL_TLSEXT_ERR_ALERT_FATAL:
|
||||
|
@ -2298,6 +2302,7 @@ WORK_STATE tls_post_process_client_hello(SSL_CONNECTION *s, WORK_STATE wst)
|
|||
|
||||
if (wst == WORK_MORE_A) {
|
||||
int rv = tls_early_post_process_client_hello(s);
|
||||
|
||||
if (rv == 0) {
|
||||
/* SSLfatal() was already called */
|
||||
goto err;
|
||||
|
@ -4327,21 +4332,149 @@ CON_FUNC_RETURN tls_construct_new_session_ticket(SSL_CONNECTION *s, WPACKET *pkt
|
|||
* In TLSv1.3 this is called from the extensions code, otherwise it is used to
|
||||
* create a separate message. Returns 1 on success or 0 on failure.
|
||||
*/
|
||||
int tls_construct_cert_status_body(SSL_CONNECTION *s, WPACKET *pkt)
|
||||
int tls_construct_cert_status_body(SSL_CONNECTION *s, size_t chainidx, WPACKET *pkt)
|
||||
{
|
||||
if (!WPACKET_put_bytes_u8(pkt, s->ext.status_type)
|
||||
|| !WPACKET_sub_memcpy_u24(pkt, s->ext.ocsp.resp,
|
||||
s->ext.ocsp.resp_len)) {
|
||||
unsigned char *respder = NULL;
|
||||
int resplen = 0;
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
int i = 0, num = 0;
|
||||
unsigned int len;
|
||||
X509 *x = NULL;
|
||||
STACK_OF(X509) *chain_certs = NULL;
|
||||
SSL *ssl = SSL_CONNECTION_GET_SSL(s);
|
||||
OCSP_RESPONSE *resp = NULL;
|
||||
OCSP_BASICRESP *bs = NULL;
|
||||
OCSP_SINGLERESP *sr = NULL;
|
||||
OCSP_CERTID *cid = NULL;
|
||||
OCSP_CERTID *sr_cert_id = NULL;
|
||||
ASN1_OBJECT *cert_id_md_oid;
|
||||
const EVP_MD *cert_id_md;
|
||||
ASN1_INTEGER *respSerial;
|
||||
ASN1_OCTET_STRING *respIssuerNameHash;
|
||||
ASN1_OCTET_STRING *certIssuerNameHash;
|
||||
const X509_NAME *certIssuerName;
|
||||
unsigned char md[EVP_MAX_MD_SIZE];
|
||||
const ASN1_INTEGER *certSerial;
|
||||
#endif
|
||||
|
||||
if (!WPACKET_put_bytes_u8(pkt, s->ext.status_type)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
/*
|
||||
* In TLSv1.3 the caller gives the index of the certificate for which the
|
||||
* status message should be created.
|
||||
* Prior to TLSv1.3 the chain index is 0 and the body should contain only
|
||||
* the status of the server certificate itself.
|
||||
*/
|
||||
SSL_get0_chain_certs(ssl, &chain_certs);
|
||||
|
||||
/*
|
||||
* if the certificate chain was built, get the status message for the
|
||||
* requested certificate specified by chainidx SSL_get0_chain_certs
|
||||
* contains certificate chain except the server cert
|
||||
*
|
||||
* if chainidx = 0 the server certificate is requested
|
||||
* if chainidx > 0 an intermediate certificate is requested
|
||||
*/
|
||||
if (chain_certs != NULL && (int)chainidx <= sk_X509_num(chain_certs) && chainidx > 0)
|
||||
x = sk_X509_value(chain_certs, (int)chainidx - 1);
|
||||
else
|
||||
x = SSL_get_certificate(ssl);
|
||||
if (x == NULL)
|
||||
return 0;
|
||||
|
||||
/* for a selfsigned certificate there will be no OCSP response */
|
||||
if (X509_self_signed(x, 0))
|
||||
return 1;
|
||||
|
||||
if ((resp = sk_OCSP_RESPONSE_value(s->ext.ocsp.resp_ex, (int)chainidx)) != NULL) {
|
||||
/*
|
||||
* check if its the right response in the case it is a successful response
|
||||
* as not every time the issuer certificate is available the check just
|
||||
* uses the issuer name and the serial number from the current certificate
|
||||
*/
|
||||
if (OCSP_response_status(resp) == OCSP_RESPONSE_STATUS_SUCCESSFUL) {
|
||||
/*
|
||||
* set a mark for the error queue her to be able to ignore errors
|
||||
* happening because of test cases
|
||||
*/
|
||||
ERR_set_mark();
|
||||
if (((bs = OCSP_response_get1_basic(resp)) != NULL)
|
||||
&& ((sr = OCSP_resp_get0(bs, 0)) != NULL)) {
|
||||
/* use the first single response to get the algorithm used */
|
||||
cid = (OCSP_CERTID *)OCSP_SINGLERESP_get0_id(sr);
|
||||
|
||||
OCSP_id_get0_info(&respIssuerNameHash, &cert_id_md_oid, NULL, &respSerial, cid);
|
||||
if (cert_id_md_oid != NULL)
|
||||
cert_id_md = EVP_get_digestbyobj(cert_id_md_oid);
|
||||
else
|
||||
cert_id_md = EVP_sha1();
|
||||
|
||||
/* get serial number and issuer name hash of the certificate from the chain */
|
||||
certSerial = X509_get0_serialNumber(x);
|
||||
certIssuerName = X509_get_issuer_name(x);
|
||||
certIssuerNameHash = ASN1_OCTET_STRING_new();
|
||||
if (!X509_NAME_digest(certIssuerName, cert_id_md, md, &len) ||
|
||||
!(ASN1_OCTET_STRING_set(certIssuerNameHash, md, len))) {
|
||||
ASN1_OCTET_STRING_free(certIssuerNameHash);
|
||||
OCSP_BASICRESP_free(bs);
|
||||
ERR_clear_last_mark();
|
||||
return 0;
|
||||
}
|
||||
|
||||
num = OCSP_resp_count(bs);
|
||||
for (i = 0; i < num; i++) {
|
||||
sr = OCSP_resp_get0(bs, i);
|
||||
|
||||
/* determine the md algorithm which was used to create cert id */
|
||||
sr_cert_id = (OCSP_CERTID *)OCSP_SINGLERESP_get0_id(sr);
|
||||
|
||||
OCSP_id_get0_info(&respIssuerNameHash, NULL, NULL, &respSerial, sr_cert_id);
|
||||
|
||||
if (!ASN1_INTEGER_cmp(certSerial, respSerial) &&
|
||||
!ASN1_OCTET_STRING_cmp(certIssuerNameHash, respIssuerNameHash))
|
||||
break;
|
||||
}
|
||||
|
||||
ASN1_OCTET_STRING_free(certIssuerNameHash);
|
||||
OCSP_BASICRESP_free(bs);
|
||||
|
||||
/*
|
||||
* if we did not find the right single response in the OCSP response we
|
||||
* construct an empty message
|
||||
*/
|
||||
if (i == num)
|
||||
resp = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* in a test case a response without a basic response is used the error set
|
||||
* could be ignored here
|
||||
*/
|
||||
ERR_pop_to_mark();
|
||||
}
|
||||
}
|
||||
|
||||
if (resp != NULL)
|
||||
resplen = i2d_OCSP_RESPONSE(resp, &respder);
|
||||
#endif
|
||||
|
||||
if (!WPACKET_sub_memcpy_u24(pkt, respder, resplen)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||
OPENSSL_free(respder);
|
||||
return 0;
|
||||
}
|
||||
|
||||
OPENSSL_free(respder);
|
||||
return 1;
|
||||
}
|
||||
|
||||
CON_FUNC_RETURN tls_construct_cert_status(SSL_CONNECTION *s, WPACKET *pkt)
|
||||
{
|
||||
if (!tls_construct_cert_status_body(s, pkt)) {
|
||||
if (!tls_construct_cert_status_body(s, 0, pkt)) {
|
||||
/* SSLfatal() already called */
|
||||
return CON_FUNC_ERROR;
|
||||
}
|
||||
|
|
126
test/crltest.c
126
test/crltest.c
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "internal/nelem.h"
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
|
@ -17,7 +18,16 @@
|
|||
|
||||
#include "testutil.h"
|
||||
|
||||
/*
|
||||
* We cannot use old certificates for new tests because the private key
|
||||
* associated with them is no longer available. Therefore, we add kCRLTestLeaf,
|
||||
* kCRLTestLeaf2 and PARAM_TIME2, as well as pass the verification time to the
|
||||
* verify function as a parameter. Certificates and CRL from
|
||||
* https://github.com/openssl/openssl/issues/27506 are used.
|
||||
*/
|
||||
|
||||
#define PARAM_TIME 1474934400 /* Sep 27th, 2016 */
|
||||
#define PARAM_TIME2 1753284700 /* July 23th, 2025 */
|
||||
|
||||
static const char *kCRLTestRoot[] = {
|
||||
"-----BEGIN CERTIFICATE-----\n",
|
||||
|
@ -70,6 +80,61 @@ static const char *kCRLTestLeaf[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static const char *kCRLTestRoot2[] = {
|
||||
"-----BEGIN CERTIFICATE-----\n",
|
||||
"MIID4zCCAsugAwIBAgIUGTcyNat9hTOo8nnGdzF7MTzL9WAwDQYJKoZIhvcNAQEL\n",
|
||||
"BQAweTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM\n",
|
||||
"DVNhbiBGcmFuY2lzY28xEzARBgNVBAoMCk15IENvbXBhbnkxEzARBgNVBAMMCk15\n",
|
||||
"IFJvb3QgQ0ExEzARBgNVBAsMCk15IFJvb3QgQ0EwHhcNMjUwMzAzMDcxNDA0WhcN\n",
|
||||
"MzUwMzAxMDcxNDA0WjB5MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5p\n",
|
||||
"YTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzETMBEGA1UECgwKTXkgQ29tcGFueTET\n",
|
||||
"MBEGA1UEAwwKTXkgUm9vdCBDQTETMBEGA1UECwwKTXkgUm9vdCBDQTCCASIwDQYJ\n",
|
||||
"KoZIhvcNAQEBBQADggEPADCCAQoCggEBAN6jjwkmV+pse430MQfyaWv+JtAd2r6K\n",
|
||||
"qzEquBcoofzuf/yvdEhQPjK3bcotgfEcFq3QMo1MJ7vqRHEIu0hJ+5ZnEQtIRcrg\n",
|
||||
"Vm7/EoVCBpDc9BDtW40TDp69z9kaKyyKYy6rxmSKgJydGBeGGMwBxgTK/o0xAriC\n",
|
||||
"C3lLXHT8G8YMamKUpToPL5iCRX+GJPnnizB2ODvpQGMWkbp9+1xEc4dD7Db2wfUb\n",
|
||||
"gatDYUoGndQKWD49UhURavQZeLpDxlz93YutRRkZTWc4IB7WebiEb39BDjSP3QYm\n",
|
||||
"2h+rZYyjp3Gxy8pBNTPzE9Dk4yjiqS7o3WGvi/S6zKTLDvWl9t6pMOMCAwEAAaNj\n",
|
||||
"MGEwHQYDVR0OBBYEFNdhiR+Tlot2VBbp5XfcfLdlG4AkMA4GA1UdDwEB/wQEAwIB\n",
|
||||
"hjAfBgNVHSMEGDAWgBTXYYkfk5aLdlQW6eV33Hy3ZRuAJDAPBgNVHRMBAf8EBTAD\n",
|
||||
"AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCvwutY0WMcKoqulifnYfhxGLtXSSvD2GET\n",
|
||||
"uNRv+S1KI5JKcAdfvnbNDpUwlujMDIpe3ewmv9i6kcitpHwZXdVAw6KWagJ0kDSt\n",
|
||||
"jbArJxuuuFmSFDS7kj8x7FZok5quAWDSSg+ubV2tCVxmDuTs1WXJXD3l9g+3J9GU\n",
|
||||
"kyeFMKqwRp8w22vm9ilgXrzeesAmmAg/pEb56ljTPeaONQxVe7KJhv2q8J17sML8\n",
|
||||
"BE7TdVx7UFQbO/t9XqdT5O9eF8JUx4Vn4QSr+jdjJ/ns4T3/IC9dJq9k7tjD48iA\n",
|
||||
"TNc+7x+uj8P39VA96HpjujVakj8/qn5SQMPJgDds+MSXrX+6JBWm\n",
|
||||
"-----END CERTIFICATE-----\n",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *kCRLTestLeaf2[] = {
|
||||
"-----BEGIN CERTIFICATE-----\n",
|
||||
"MIIECjCCAvKgAwIBAgIUPxuMqMtuN1j3XZVRVrNmaTCIP04wDQYJKoZIhvcNAQEL\n",
|
||||
"BQAweTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM\n",
|
||||
"DVNhbiBGcmFuY2lzY28xEzARBgNVBAoMCk15IENvbXBhbnkxEzARBgNVBAMMCk15\n",
|
||||
"IFJvb3QgQ0ExEzARBgNVBAsMCk15IFJvb3QgQ0EwHhcNMjUwNDE3MTAxNjQ5WhcN\n",
|
||||
"MjYwNDE3MTAxNjQ5WjBoMQswCQYDVQQGEwJDTjEQMA4GA1UECAwHQmVpamluZzEQ\n",
|
||||
"MA4GA1UEBwwHQmVpamluZzEYMBYGA1UECgwPTXkgT3JnYW5pemF0aW9uMRswGQYD\n",
|
||||
"VQQDDBJNeSBJbnRlcm1lZGlhdGUgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw\n",
|
||||
"ggEKAoIBAQDIxRxZQokflDaLYoD21HT2U4EshqtKpSf9zPS5unBMCfnQkU4IJjBF\n",
|
||||
"3qQmfgz5ZOpZv3x0w48fDjiysk0eOVCFAo+uixEjMeuln6Wj3taetch2Sk0YNm5J\n",
|
||||
"SJCNF2olHZXn5R8ngEmho2j1wbwNnpcccZyRNzUSjR9oAgObkP3O7fyQKJRxwNU0\n",
|
||||
"sN7mfoyEOczKtUaYbqi2gPx6OOqNLjXlLmfZ8PJagKCN/oYkGU5PoRNXp65Znhu6\n",
|
||||
"s8FuSmvTodu8Qhs9Uizo+SycaBXn5Fbqt32S+9vPfhH9FfELDfQIaBp+iQAxcKPX\n",
|
||||
"tUglXEjiEVrbNf722PuWIWN9EIBolULVAgMBAAGjgZowgZcwEgYDVR0TAQH/BAgw\n",
|
||||
"BgEB/wIBATAxBgNVHR8EKjAoMCagJKAihiBodHRwOi8vbG9jYWxob3N0OjgwMDAv\n",
|
||||
"Y2FfY3JsLmRlcjAdBgNVHQ4EFgQUh40vFgoopz5GUggPEEk2+bKgbwQwHwYDVR0j\n",
|
||||
"BBgwFoAU12GJH5OWi3ZUFunld9x8t2UbgCQwDgYDVR0PAQH/BAQDAgGGMA0GCSqG\n",
|
||||
"SIb3DQEBCwUAA4IBAQDANfJuTgo0vRaMPYqOeW8R4jLHdVazdGLeQQ/85vXr/Gl1\n",
|
||||
"aL40tLp4yZbThxuxTzPzfY1OGkG69YQ/8Vo0gCEi5KjBMYPKmZISKy1MwROQ1Jfp\n",
|
||||
"HkmyZk1TfuzG/4fN/bun2gjpDYcihf4xA4NhSVzQyvqm1N6VkTgK+bEWTOGzqw66\n",
|
||||
"6IYPN6oVDmLbwU1EvV3rggB7HUJCJP4qW9DbAQRAijUurPUGoU2vEbrSyYkfQXCf\n",
|
||||
"p4ouOTMl6O7bJ110SKzxbCfWqom+iAwHlU2tOPVmOp1CLDCClMRNHIFMDGAoBomH\n",
|
||||
"s01wD+IcIi9OkQEbqVb/XDKes8fqzQgTtSM9C9Ot\n",
|
||||
"-----END CERTIFICATE-----\n",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *kBasicCRL[] = {
|
||||
"-----BEGIN X509 CRL-----\n",
|
||||
"MIIBpzCBkAIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE\n",
|
||||
|
@ -124,6 +189,24 @@ static const char *kBadIssuerCRL[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static const char *kEmptyIdpCRL[] = {
|
||||
"-----BEGIN X509 CRL-----\n",
|
||||
"MIICOTCCASECAQEwDQYJKoZIhvcNAQELBQAweTELMAkGA1UEBhMCVVMxEzARBgNV\n",
|
||||
"BAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xEzARBgNVBAoM\n",
|
||||
"Ck15IENvbXBhbnkxEzARBgNVBAMMCk15IFJvb3QgQ0ExEzARBgNVBAsMCk15IFJv\n",
|
||||
"b3QgQ0EXDTI1MDEwMTAwMDAwMFoXDTI1MTIwMTAwMDAwMFowJzAlAhQcgAIu+B8k\n",
|
||||
"Be6WphLcth/grHAeXhcNMjUwNDE3MTAxNjUxWqBLMEkwGAYDVR0UBBECDxnP/97a\n",
|
||||
"dO3y9qRGDM7hQDAfBgNVHSMEGDAWgBTXYYkfk5aLdlQW6eV33Hy3ZRuAJDAMBgNV\n",
|
||||
"HRwBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQAf+mtlDi9IftsYwTcxYYKxE203\n",
|
||||
"+prttFB00om29jjtkGYRxcs3vZQRTvera21YFn3mrS/lxvhBq6GMx0I61AQ48Pr4\n",
|
||||
"63bDvZgf+/P6T2+MLgLds23o3TOfy2SBSdnFEcN0bFUgF5U0bFpQqlQWx+FYhrAf\n",
|
||||
"ZX3RAhURiKKfGKGeVOVKS0u+x666FoDQ7pbhbHM3+jnuzdtv8RQMkj1AZMw0FMl8\n",
|
||||
"m2dFQhZqT9WdJqZAc8ldc6V3a0rUeOV8BUPACf1k4B0CKhn4draIqltZkWgl3cmU\n",
|
||||
"SX2V/a51lS12orfNYSEx+vtJ9gpx4LDxyOnai18vueVyljrXuQSrcYuxS2Cd\n",
|
||||
"-----END X509 CRL-----\n",
|
||||
NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* This is kBasicCRL but with a critical issuing distribution point
|
||||
* extension.
|
||||
|
@ -189,6 +272,8 @@ static const char **unknown_critical_crls[] = {
|
|||
|
||||
static X509 *test_root = NULL;
|
||||
static X509 *test_leaf = NULL;
|
||||
static X509 *test_root2 = NULL;
|
||||
static X509 *test_leaf2 = NULL;
|
||||
|
||||
/*
|
||||
* Glue an array of strings together. Return a BIO and put the string
|
||||
|
@ -251,7 +336,7 @@ static X509 *X509_from_strings(const char **pem)
|
|||
* Returns a value from X509_V_ERR_xxx or X509_V_OK.
|
||||
*/
|
||||
static int verify(X509 *leaf, X509 *root, STACK_OF(X509_CRL) *crls,
|
||||
unsigned long flags)
|
||||
unsigned long flags, time_t verification_time)
|
||||
{
|
||||
X509_STORE_CTX *ctx = X509_STORE_CTX_new();
|
||||
X509_STORE *store = X509_STORE_new();
|
||||
|
@ -276,8 +361,8 @@ static int verify(X509 *leaf, X509 *root, STACK_OF(X509_CRL) *crls,
|
|||
goto err;
|
||||
X509_STORE_CTX_set0_trusted_stack(ctx, roots);
|
||||
X509_STORE_CTX_set0_crls(ctx, crls);
|
||||
X509_VERIFY_PARAM_set_time(param, PARAM_TIME);
|
||||
if (!TEST_long_eq((long)X509_VERIFY_PARAM_get_time(param), PARAM_TIME))
|
||||
X509_VERIFY_PARAM_set_time(param, verification_time);
|
||||
if (!TEST_long_eq((long)X509_VERIFY_PARAM_get_time(param), (long)verification_time))
|
||||
goto err;
|
||||
X509_VERIFY_PARAM_set_depth(param, 16);
|
||||
if (flags)
|
||||
|
@ -342,10 +427,10 @@ static int test_basic_crl(void)
|
|||
&& TEST_ptr(revoked_crl)
|
||||
&& TEST_int_eq(verify(test_leaf, test_root,
|
||||
make_CRL_stack(basic_crl, NULL),
|
||||
X509_V_FLAG_CRL_CHECK), X509_V_OK)
|
||||
X509_V_FLAG_CRL_CHECK, PARAM_TIME), X509_V_OK)
|
||||
&& TEST_int_eq(verify(test_leaf, test_root,
|
||||
make_CRL_stack(basic_crl, revoked_crl),
|
||||
X509_V_FLAG_CRL_CHECK), X509_V_ERR_CERT_REVOKED);
|
||||
X509_V_FLAG_CRL_CHECK, PARAM_TIME), X509_V_ERR_CERT_REVOKED);
|
||||
if (r) {
|
||||
X509_CRL_get0_signature(basic_crl, NULL, &alg);
|
||||
tbsalg = X509_CRL_get0_tbs_sigalg(basic_crl);
|
||||
|
@ -362,7 +447,7 @@ static int test_basic_crl(void)
|
|||
static int test_no_crl(void)
|
||||
{
|
||||
return TEST_int_eq(verify(test_leaf, test_root, NULL,
|
||||
X509_V_FLAG_CRL_CHECK),
|
||||
X509_V_FLAG_CRL_CHECK, PARAM_TIME),
|
||||
X509_V_ERR_UNABLE_TO_GET_CRL);
|
||||
}
|
||||
|
||||
|
@ -374,12 +459,26 @@ static int test_bad_issuer_crl(void)
|
|||
r = TEST_ptr(bad_issuer_crl)
|
||||
&& TEST_int_eq(verify(test_leaf, test_root,
|
||||
make_CRL_stack(bad_issuer_crl, NULL),
|
||||
X509_V_FLAG_CRL_CHECK),
|
||||
X509_V_FLAG_CRL_CHECK, PARAM_TIME),
|
||||
X509_V_ERR_UNABLE_TO_GET_CRL);
|
||||
X509_CRL_free(bad_issuer_crl);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int test_crl_empty_idp(void)
|
||||
{
|
||||
X509_CRL *empty_idp_crl = CRL_from_strings(kEmptyIdpCRL);
|
||||
int r;
|
||||
|
||||
r = TEST_ptr(empty_idp_crl)
|
||||
&& TEST_int_eq(verify(test_leaf2, test_root2,
|
||||
make_CRL_stack(empty_idp_crl, NULL),
|
||||
X509_V_FLAG_CRL_CHECK, PARAM_TIME2),
|
||||
X509_V_ERR_UNABLE_TO_GET_CRL);
|
||||
X509_CRL_free(empty_idp_crl);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int test_known_critical_crl(void)
|
||||
{
|
||||
X509_CRL *known_critical_crl = CRL_from_strings(kKnownCriticalCRL);
|
||||
|
@ -388,7 +487,7 @@ static int test_known_critical_crl(void)
|
|||
r = TEST_ptr(known_critical_crl)
|
||||
&& TEST_int_eq(verify(test_leaf, test_root,
|
||||
make_CRL_stack(known_critical_crl, NULL),
|
||||
X509_V_FLAG_CRL_CHECK), X509_V_OK);
|
||||
X509_V_FLAG_CRL_CHECK, PARAM_TIME), X509_V_OK);
|
||||
X509_CRL_free(known_critical_crl);
|
||||
return r;
|
||||
}
|
||||
|
@ -401,7 +500,7 @@ static int test_unknown_critical_crl(int n)
|
|||
r = TEST_ptr(unknown_critical_crl)
|
||||
&& TEST_int_eq(verify(test_leaf, test_root,
|
||||
make_CRL_stack(unknown_critical_crl, NULL),
|
||||
X509_V_FLAG_CRL_CHECK),
|
||||
X509_V_FLAG_CRL_CHECK, PARAM_TIME),
|
||||
X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION);
|
||||
X509_CRL_free(unknown_critical_crl);
|
||||
return r;
|
||||
|
@ -421,7 +520,7 @@ static int test_reuse_crl(int idx)
|
|||
if (idx & 1) {
|
||||
if (!TEST_true(X509_CRL_up_ref(reused_crl)))
|
||||
goto err;
|
||||
addref_crl = reused_crl;
|
||||
addref_crl = reused_crl;
|
||||
}
|
||||
|
||||
idx >>= 1;
|
||||
|
@ -464,12 +563,15 @@ static int test_reuse_crl(int idx)
|
|||
int setup_tests(void)
|
||||
{
|
||||
if (!TEST_ptr(test_root = X509_from_strings(kCRLTestRoot))
|
||||
|| !TEST_ptr(test_leaf = X509_from_strings(kCRLTestLeaf)))
|
||||
|| !TEST_ptr(test_leaf = X509_from_strings(kCRLTestLeaf))
|
||||
|| !TEST_ptr(test_root2 = X509_from_strings(kCRLTestRoot2))
|
||||
|| !TEST_ptr(test_leaf2 = X509_from_strings(kCRLTestLeaf2)))
|
||||
return 0;
|
||||
|
||||
ADD_TEST(test_no_crl);
|
||||
ADD_TEST(test_basic_crl);
|
||||
ADD_TEST(test_bad_issuer_crl);
|
||||
ADD_TEST(test_crl_empty_idp);
|
||||
ADD_TEST(test_known_critical_crl);
|
||||
ADD_ALL_TESTS(test_unknown_critical_crl, OSSL_NELEM(unknown_critical_crls));
|
||||
ADD_ALL_TESTS(test_reuse_crl, 6);
|
||||
|
@ -480,4 +582,6 @@ void cleanup_tests(void)
|
|||
{
|
||||
X509_free(test_root);
|
||||
X509_free(test_leaf);
|
||||
X509_free(test_root2);
|
||||
X509_free(test_leaf2);
|
||||
}
|
||||
|
|
|
@ -23,9 +23,19 @@ print <<"_____";
|
|||
#ifndef OPENSSL_NO_STDIO
|
||||
# include <stdio.h>
|
||||
#endif
|
||||
_____
|
||||
|
||||
if (${name_uc} eq "RSA") {
|
||||
print("#include <openssl/rsa.h>");
|
||||
}
|
||||
else {
|
||||
print <<"_____";
|
||||
#ifndef OPENSSL_NO_${name_uc}
|
||||
# include <openssl/$name.h>
|
||||
#endif
|
||||
_____
|
||||
}
|
||||
print <<"_____";
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <openssl/x509_vfy.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/ocsp.h>
|
||||
|
||||
#include "../../ssl/ssl_local.h"
|
||||
#include "internal/ssl_unwrap.h"
|
||||
|
@ -265,47 +266,100 @@ static int client_hello_nov12_cb(SSL *s, int *al, void *arg)
|
|||
return SSL_CLIENT_HELLO_SUCCESS;
|
||||
}
|
||||
|
||||
static unsigned char dummy_ocsp_resp_good_val = 0xff;
|
||||
static unsigned char dummy_ocsp_resp_bad_val = 0xfe;
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
static OCSP_RESPONSE *dummy_ocsp_resp = NULL;
|
||||
static STACK_OF(OCSP_RESPONSE) *dummy_sk_resp = NULL;
|
||||
|
||||
static int server_ocsp_cb(SSL *s, void *arg)
|
||||
{
|
||||
unsigned char *resp;
|
||||
unsigned char *respder = NULL;
|
||||
int resplen = 0;
|
||||
|
||||
resplen = i2d_OCSP_RESPONSE(arg, &respder);
|
||||
|
||||
resp = OPENSSL_malloc(1);
|
||||
if (resp == NULL)
|
||||
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||
/*
|
||||
* For the purposes of testing we just send back a dummy OCSP response
|
||||
*/
|
||||
*resp = *(unsigned char *)arg;
|
||||
if (!SSL_set_tlsext_status_ocsp_resp(s, resp, 1)) {
|
||||
OPENSSL_free(resp);
|
||||
if (!SSL_set_tlsext_status_ocsp_resp(s, respder, resplen)) {
|
||||
OPENSSL_free(respder);
|
||||
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||
}
|
||||
|
||||
OPENSSL_free(respder);
|
||||
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
|
||||
static int server_ocsp_cb_ext(SSL *s, void *arg)
|
||||
{
|
||||
STACK_OF(OCSP_RESPONSE) *sk_resp = NULL;
|
||||
|
||||
/*
|
||||
* For the purposes of testing we just send back a dummy OCSP response
|
||||
*/
|
||||
sk_resp = (STACK_OF(OCSP_RESPONSE) *)arg;
|
||||
if (!SSL_set0_tlsext_status_ocsp_resp_ex(s, sk_resp))
|
||||
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
|
||||
static int client_ocsp_cb(SSL *s, void *arg)
|
||||
{
|
||||
const unsigned char *resp;
|
||||
int len;
|
||||
const unsigned char *resp, *p;
|
||||
OCSP_RESPONSE *rsp;
|
||||
int len, status;
|
||||
|
||||
len = SSL_get_tlsext_status_ocsp_resp(s, &resp);
|
||||
if (len != 1 || *resp != dummy_ocsp_resp_good_val)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
p = resp;
|
||||
rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
|
||||
|
||||
status = OCSP_response_status(rsp);
|
||||
|
||||
OCSP_RESPONSE_free(rsp);
|
||||
SSL_set_tlsext_status_ocsp_resp(s, NULL, 0);
|
||||
|
||||
OCSP_RESPONSE_free(dummy_ocsp_resp);
|
||||
|
||||
return status == OCSP_RESPONSE_STATUS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static int verify_reject_cb(X509_STORE_CTX *ctx, void *arg) {
|
||||
static int client_ocsp_cb_ext(SSL *s, void *arg)
|
||||
{
|
||||
int len, status;
|
||||
STACK_OF(OCSP_RESPONSE) *sk_resp = NULL;
|
||||
OCSP_RESPONSE *rsp;
|
||||
|
||||
SSL_get0_tlsext_status_ocsp_resp_ex(s, &sk_resp);
|
||||
|
||||
if (sk_resp == NULL)
|
||||
return 0;
|
||||
|
||||
len = sk_OCSP_RESPONSE_num(sk_resp);
|
||||
|
||||
if (len != 1)
|
||||
return 0;
|
||||
|
||||
rsp = sk_OCSP_RESPONSE_value(sk_resp, 0);
|
||||
|
||||
status = OCSP_response_status(rsp);
|
||||
|
||||
SSL_set0_tlsext_status_ocsp_resp_ex(s, NULL);
|
||||
|
||||
return status == OCSP_RESPONSE_STATUS_SUCCESSFUL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int verify_reject_cb(X509_STORE_CTX *ctx, void *arg)
|
||||
{
|
||||
X509_STORE_CTX_set_error(ctx, X509_V_ERR_APPLICATION_VERIFICATION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int n_retries = 0;
|
||||
static int verify_retry_cb(X509_STORE_CTX *ctx, void *arg) {
|
||||
static int verify_retry_cb(X509_STORE_CTX *ctx, void *arg)
|
||||
{
|
||||
int idx = SSL_get_ex_data_X509_STORE_CTX_idx();
|
||||
SSL *ssl;
|
||||
|
||||
|
@ -320,7 +374,8 @@ static int verify_retry_cb(X509_STORE_CTX *ctx, void *arg) {
|
|||
return SSL_set_retry_verify(ssl);
|
||||
}
|
||||
|
||||
static int verify_accept_cb(X509_STORE_CTX *ctx, void *arg) {
|
||||
static int verify_accept_cb(X509_STORE_CTX *ctx, void *arg)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -566,13 +621,67 @@ static int configure_handshake_ctx(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
|
|||
}
|
||||
|
||||
if (extra->server.cert_status != SSL_TEST_CERT_STATUS_NONE) {
|
||||
|
||||
SSL_CTX_set_tlsext_status_type(client_ctx, TLSEXT_STATUSTYPE_ocsp);
|
||||
SSL_CTX_set_tlsext_status_cb(client_ctx, client_ocsp_cb);
|
||||
SSL_CTX_set_tlsext_status_arg(client_ctx, NULL);
|
||||
SSL_CTX_set_tlsext_status_cb(server_ctx, server_ocsp_cb);
|
||||
SSL_CTX_set_tlsext_status_arg(server_ctx,
|
||||
((extra->server.cert_status == SSL_TEST_CERT_STATUS_GOOD_RESPONSE)
|
||||
? &dummy_ocsp_resp_good_val : &dummy_ocsp_resp_bad_val));
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
switch (extra->server.cert_status) {
|
||||
case SSL_TEST_CERT_STATUS_GOOD_RESPONSE:
|
||||
|
||||
dummy_ocsp_resp = OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL, NULL);
|
||||
|
||||
SSL_CTX_set_tlsext_status_cb(client_ctx, client_ocsp_cb);
|
||||
SSL_CTX_set_tlsext_status_cb(server_ctx, server_ocsp_cb);
|
||||
SSL_CTX_set_tlsext_status_arg(server_ctx, dummy_ocsp_resp);
|
||||
|
||||
break;
|
||||
|
||||
case SSL_TEST_CERT_STATUS_BAD_RESPONSE:
|
||||
|
||||
dummy_ocsp_resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, NULL);
|
||||
|
||||
SSL_CTX_set_tlsext_status_cb(client_ctx, client_ocsp_cb);
|
||||
SSL_CTX_set_tlsext_status_cb(server_ctx, server_ocsp_cb);
|
||||
SSL_CTX_set_tlsext_status_arg(server_ctx, dummy_ocsp_resp);
|
||||
|
||||
break;
|
||||
|
||||
case SSL_TEST_CERT_STATUS_GOOD_RESPONSE_EXT:
|
||||
|
||||
dummy_sk_resp = sk_OCSP_RESPONSE_new_null();
|
||||
dummy_ocsp_resp = OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL, NULL);
|
||||
sk_OCSP_RESPONSE_push(dummy_sk_resp, dummy_ocsp_resp);
|
||||
|
||||
SSL_CTX_set_tlsext_status_cb(client_ctx, client_ocsp_cb_ext);
|
||||
SSL_CTX_set_tlsext_status_cb(server_ctx, server_ocsp_cb_ext);
|
||||
SSL_CTX_set_tlsext_status_arg(server_ctx, dummy_sk_resp);
|
||||
|
||||
break;
|
||||
|
||||
case SSL_TEST_CERT_STATUS_BAD_RESPONSE_EXT:
|
||||
|
||||
dummy_sk_resp = sk_OCSP_RESPONSE_new_null();
|
||||
dummy_ocsp_resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, NULL);
|
||||
sk_OCSP_RESPONSE_push(dummy_sk_resp, dummy_ocsp_resp);
|
||||
|
||||
SSL_CTX_set_tlsext_status_cb(client_ctx, client_ocsp_cb_ext);
|
||||
SSL_CTX_set_tlsext_status_cb(server_ctx, server_ocsp_cb_ext);
|
||||
SSL_CTX_set_tlsext_status_arg(server_ctx, dummy_sk_resp);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
dummy_ocsp_resp = OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL, NULL);
|
||||
|
||||
SSL_CTX_set_tlsext_status_cb(client_ctx, client_ocsp_cb);
|
||||
SSL_CTX_set_tlsext_status_cb(server_ctx, server_ocsp_cb);
|
||||
SSL_CTX_set_tlsext_status_arg(server_ctx, &dummy_ocsp_resp);
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -460,7 +460,9 @@ IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_CTX, test, enable_server_sctp_label_bug)
|
|||
static const test_enum ssl_certstatus[] = {
|
||||
{"None", SSL_TEST_CERT_STATUS_NONE},
|
||||
{"GoodResponse", SSL_TEST_CERT_STATUS_GOOD_RESPONSE},
|
||||
{"BadResponse", SSL_TEST_CERT_STATUS_BAD_RESPONSE}
|
||||
{"BadResponse", SSL_TEST_CERT_STATUS_BAD_RESPONSE},
|
||||
{"GoodResponseExt", SSL_TEST_CERT_STATUS_GOOD_RESPONSE_EXT},
|
||||
{"BadResponseExt", SSL_TEST_CERT_STATUS_BAD_RESPONSE_EXT}
|
||||
};
|
||||
|
||||
__owur static int parse_certstatus(SSL_TEST_SERVER_CONF *server_conf,
|
||||
|
|
|
@ -88,7 +88,9 @@ typedef enum {
|
|||
typedef enum {
|
||||
SSL_TEST_CERT_STATUS_NONE = 0, /* Default */
|
||||
SSL_TEST_CERT_STATUS_GOOD_RESPONSE,
|
||||
SSL_TEST_CERT_STATUS_BAD_RESPONSE
|
||||
SSL_TEST_CERT_STATUS_BAD_RESPONSE,
|
||||
SSL_TEST_CERT_STATUS_GOOD_RESPONSE_EXT,
|
||||
SSL_TEST_CERT_STATUS_BAD_RESPONSE_EXT
|
||||
} ssl_cert_status_t;
|
||||
|
||||
/*
|
||||
|
|
|
@ -104,7 +104,8 @@ static int helper_init(struct helper *h, size_t num_pkts)
|
|||
|
||||
/* Initialise ACK manager. */
|
||||
h->ackm = ossl_ackm_new(fake_now, NULL, &h->statm,
|
||||
&ossl_cc_dummy_method, h->ccdata);
|
||||
&ossl_cc_dummy_method, h->ccdata,
|
||||
/* is_server */0);
|
||||
if (!TEST_ptr(h->ackm))
|
||||
goto err;
|
||||
|
||||
|
|
|
@ -329,7 +329,8 @@ static int test_fifd(int idx)
|
|||
|| !TEST_ptr(info.ackm = ossl_ackm_new(fake_now, NULL,
|
||||
&info.statm,
|
||||
&ossl_cc_dummy_method,
|
||||
info.ccdata))
|
||||
info.ccdata,
|
||||
/* is_server */0))
|
||||
|| !TEST_true(ossl_ackm_on_handshake_confirmed(info.ackm))
|
||||
|| !TEST_ptr(info.cfq = ossl_quic_cfq_new())
|
||||
|| !TEST_ptr(info.txpim = ossl_quic_txpim_new())
|
||||
|
|
|
@ -182,7 +182,8 @@ static int helper_init(struct helper *h)
|
|||
if (!TEST_ptr(h->args.ackm = ossl_ackm_new(fake_now, NULL,
|
||||
&h->statm,
|
||||
h->cc_method,
|
||||
h->cc_data)))
|
||||
h->cc_data,
|
||||
/* is_server */0)))
|
||||
goto err;
|
||||
|
||||
if (!TEST_true(ossl_quic_stream_map_init(&h->qsm, NULL, NULL,
|
||||
|
|
|
@ -18,7 +18,7 @@ setup("test_ec");
|
|||
|
||||
plan skip_all => 'EC is not supported in this build' if disabled('ec');
|
||||
|
||||
plan tests => 15;
|
||||
plan tests => 16;
|
||||
|
||||
my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0);
|
||||
|
||||
|
@ -33,6 +33,16 @@ subtest 'EC conversions -- private key' => sub {
|
|||
tconversion( -type => 'ec', -prefix => 'ec-priv',
|
||||
-in => srctop_file("test","testec-p256.pem") );
|
||||
};
|
||||
|
||||
SKIP: {
|
||||
skip "SM2 is not supported by this OpenSSL build", 1
|
||||
if disabled("sm2");
|
||||
subtest 'EC conversions -- private key' => sub {
|
||||
tconversion( -type => 'ec', -prefix => 'sm2-priv',
|
||||
-in => srctop_file("test","testec-sm2.pem") );
|
||||
};
|
||||
}
|
||||
|
||||
subtest 'EC conversions -- private key PKCS#8' => sub {
|
||||
tconversion( -type => 'ec', -prefix => 'ec-pkcs8',
|
||||
-in => srctop_file("test","testec-p256.pem"),
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue