Latest update (add quic)

This commit is contained in:
2020-07-12 19:52:18 +09:00
parent 3a6d64bb68
commit e85ee33eee
501 changed files with 19166 additions and 10232 deletions
+5 -2
View File
@@ -14,8 +14,8 @@ $OPENSSLSRC=\
openssl.c progs.c \
asn1pars.c ca.c ciphers.c cms.c crl.c crl2p7.c dgst.c \
enc.c errstr.c \
genpkey.c genrsa.c kdf.c mac.c nseq.c ocsp.c passwd.c pkcs12.c pkcs7.c \
pkcs8.c pkey.c pkeyparam.c pkeyutl.c prime.c rand.c req.c rsa.c \
genpkey.c kdf.c mac.c nseq.c passwd.c pkcs7.c \
pkcs8.c pkey.c pkeyparam.c pkeyutl.c prime.c rand.c req.c \
rsautl.c s_client.c s_server.c s_time.c sess_id.c smime.c speed.c \
spkac.c verify.c version.c x509.c rehash.c storeutl.c \
list.c info.c provider.c fipsinstall.c
@@ -43,6 +43,9 @@ ENDIF
IF[{- !$disabled{'engine'} -}]
$OPENSSLSRC=$OPENSSLSRC engine.c
ENDIF
IF[{- !$disabled{'rsa'} -}]
$OPENSSLSRC=$OPENSSLSRC rsa.c genrsa.c
ENDIF
IF[{- !$disabled{'cmp'} -}]
$OPENSSLSRC=$OPENSSLSRC cmp.c cmp_mock_srv.c
ENDIF
+29 -11
View File
@@ -347,16 +347,16 @@ const OPTIONS cmp_options[] = {
OPT_SECTION("Server authentication"),
{"trusted", OPT_TRUSTED, 's',
"Trusted certs used for CMP server authentication when verifying responses"},
"Certificates to trust as chain roots when verifying signed CMP responses"},
{OPT_MORE_STR, 0, 0, "unless -srvcert is given"},
{"untrusted", OPT_UNTRUSTED, 's',
"Intermediate certs for chain construction verifying CMP/TLS/enrolled certs"},
"Intermediate CA certs for chain construction for CMP/TLS/enrolled certs"},
{"srvcert", OPT_SRVCERT, 's',
"Specific CMP server cert to use and trust directly when verifying responses"},
"Server cert to pin and trust directly when verifying signed CMP responses"},
{"recipient", OPT_RECIPIENT, 's',
"Distinguished Name (DN) of the recipient to use unless -srvcert is given"},
"Distinguished Name (DN) to use as msg recipient; see man page for defaults"},
{"expect_sender", OPT_EXPECT_SENDER, 's',
"DN of expected response sender. Defaults to DN of -srvcert, if provided"},
"DN of expected sender of responses. Defaults to subject of -srvcert, if any"},
{"ignore_keyusage", OPT_IGNORE_KEYUSAGE, '-',
"Ignore CMP signer cert key usage, else 'digitalSignature' must be allowed"},
{"unprotected_errors", OPT_UNPROTECTED_ERRORS, '-',
@@ -1637,8 +1637,7 @@ static SSL_CTX *setup_ssl_ctx(OSSL_CMP_CTX *ctx, ENGINE *e)
/*
* Any further certs and any untrusted certs are used for constructing
* the client cert chain to be provided along with the TLS client cert
* to the TLS server.
* the chain to be provided with the TLS client cert to the TLS server.
*/
if (!SSL_CTX_set0_chain(ssl_ctx, certs)) {
CMP_err("could not set TLS client cert chain");
@@ -2097,9 +2096,12 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *e)
goto oom;
if (opt_proxy != NULL && !OSSL_CMP_CTX_set1_proxy(ctx, opt_proxy))
goto oom;
if (opt_no_proxy != NULL && !OSSL_CMP_CTX_set1_no_proxy(ctx, opt_no_proxy))
goto oom;
(void)BIO_snprintf(server_buf, sizeof(server_buf), "http%s://%s%s%s/%s",
opt_tls_used ? "s" : "", opt_server,
server_port == 0 ? "" : ":", server_port_s,
opt_path == NULL ? "" :
opt_path[0] == '/' ? opt_path + 1 : opt_path);
if (opt_proxy != NULL)
@@ -2221,7 +2223,7 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *e)
if (!set_name(opt_recipient, OSSL_CMP_CTX_set1_recipient, ctx, "recipient")
|| !set_name(opt_expect_sender, OSSL_CMP_CTX_set1_expected_sender,
ctx, "expected sender"))
goto oom;
goto err;
if (opt_geninfo != NULL && !handle_opt_geninfo(ctx))
goto err;
@@ -2977,12 +2979,13 @@ int cmp_main(int argc, char **argv)
if ((acbio = http_server_init_bio(prog, opt_port)) == NULL)
goto err;
while (opt_max_msgs <= 0 || msgs < opt_max_msgs) {
char *path = NULL;
OSSL_CMP_MSG *req = NULL;
OSSL_CMP_MSG *resp = NULL;
ret = http_server_get_asn1_req(ASN1_ITEM_rptr(OSSL_CMP_MSG),
(ASN1_VALUE **)&req, &cbio, acbio,
prog, 0, 0);
(ASN1_VALUE **)&req, &path,
&cbio, acbio, prog, 0, 0);
if (ret == 0)
continue;
if (ret++ == -1)
@@ -2991,17 +2994,32 @@ int cmp_main(int argc, char **argv)
ret = 0;
msgs++;
if (req != NULL) {
if (strcmp(path, "") != 0 && strcmp(path, "pkix/") != 0) {
(void)http_server_send_status(cbio, 404, "Not Found");
CMP_err1("Expecting empty path or 'pkix/' but got '%s'",
path);
OPENSSL_free(path);
OSSL_CMP_MSG_free(req);
goto cont;
}
OPENSSL_free(path);
resp = OSSL_CMP_CTX_server_perform(cmp_ctx, req);
OSSL_CMP_MSG_free(req);
if (resp == NULL)
if (resp == NULL) {
(void)http_server_send_status(cbio,
500, "Internal Server Error");
break; /* treated as fatal error */
}
ret = http_server_send_asn1_resp(cbio, "application/pkixcmp",
ASN1_ITEM_rptr(OSSL_CMP_MSG),
(const ASN1_VALUE *)resp);
OSSL_CMP_MSG_free(resp);
if (!ret)
break; /* treated as fatal error */
} else {
(void)http_server_send_status(cbio, 400, "Bad Request");
}
cont:
BIO_free_all(cbio);
cbio = NULL;
}
+1
View File
@@ -208,6 +208,7 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
}
if (ctx->certOut != NULL
&& (*certOut = X509_dup(ctx->certOut)) == NULL)
/* TODO better return a cert produced from data in request template */
goto err;
if (ctx->chainOut != NULL
&& (*chainOut = X509_chain_up_ref(ctx->chainOut)) == NULL)
+10 -3
View File
@@ -670,12 +670,18 @@ int cms_main(int argc, char **argv)
goto opthelp;
}
if (flags & CMS_CADES) {
if (flags & CMS_NOATTR) {
if ((flags & CMS_CADES) != 0) {
if ((flags & CMS_NOATTR) != 0) {
BIO_puts(bio_err, "Incompatible options: "
"CAdES required signed attributes\n");
goto opthelp;
}
if (operation == SMIME_VERIFY
&& (flags & (CMS_NO_SIGNER_CERT_VERIFY | CMS_NO_ATTR_VERIFY)) != 0) {
BIO_puts(bio_err, "Incompatible options: CAdES validation require"
" certs and signed attributes validations\n");
goto opthelp;
}
}
if (operation & SMIME_SIGNERS) {
@@ -1115,7 +1121,8 @@ int cms_main(int argc, char **argv)
goto end;
} else if (operation == SMIME_VERIFY) {
if (CMS_verify(cms, other, store, indata, out, flags) > 0) {
BIO_printf(bio_err, "Verification successful\n");
BIO_printf(bio_err, "%s Verification successful\n",
(flags & CMS_CADES) ? "CAdES" : "CMS");
} else {
BIO_printf(bio_err, "Verification failure\n");
if (verify_retcode)
+20 -30
View File
@@ -84,7 +84,7 @@ const OPTIONS dhparam_options[] = {
int dhparam_main(int argc, char **argv)
{
BIO *in = NULL, *out = NULL;
DH *dh = NULL;
DH *dh = NULL, *alloc_dh = NULL;
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx = NULL;
char *infile = NULL, *outfile = NULL, *prog;
@@ -177,7 +177,7 @@ int dhparam_main(int argc, char **argv)
#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DEPRECATED_3_0)
if (dsaparam && g) {
BIO_printf(bio_err,
"generator may not be chosen for DSA parameters\n");
"Error, generator may not be chosen for DSA parameters\n");
goto end;
}
#endif
@@ -198,10 +198,8 @@ int dhparam_main(int argc, char **argv)
DSA *dsa = DSA_new();
BN_GENCB *cb = BN_GENCB_new();
if (cb == NULL) {
ERR_print_errors(bio_err);
if (cb == NULL)
goto end;
}
BN_GENCB_set(cb, dh_cb, bio_err);
@@ -212,23 +210,20 @@ int dhparam_main(int argc, char **argv)
cb)) {
DSA_free(dsa);
BN_GENCB_free(cb);
ERR_print_errors(bio_err);
BIO_printf(bio_err, "Error, unable to generate DSA parameters\n");
goto end;
}
dh = DSA_dup_DH(dsa);
dh = alloc_dh = DSA_dup_DH(dsa);
DSA_free(dsa);
BN_GENCB_free(cb);
if (dh == NULL) {
ERR_print_errors(bio_err);
if (dh == NULL)
goto end;
}
} else
#endif
{
ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL);
if (ctx == NULL) {
ERR_print_errors(bio_err);
BIO_printf(bio_err,
"Error, DH key generation context allocation failed\n");
goto end;
@@ -242,20 +237,18 @@ int dhparam_main(int argc, char **argv)
if (!EVP_PKEY_paramgen_init(ctx)) {
BIO_printf(bio_err,
"Error, unable to initialise DH param generation\n");
ERR_print_errors(bio_err);
goto end;
}
if (!EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, num)) {
BIO_printf(bio_err, "Error, unable to set DH prime length\n");
ERR_print_errors(bio_err);
goto end;
}
if (!EVP_PKEY_paramgen(ctx, &pkey)) {
BIO_printf(bio_err, "Error, DH generation failed\n");
ERR_print_errors(bio_err);
goto end;
}
dh = EVP_PKEY_get0_DH(pkey);
}
} else {
in = bio_open_default(infile, 'r', informat);
@@ -272,17 +265,14 @@ int dhparam_main(int argc, char **argv)
dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL);
if (dsa == NULL) {
BIO_printf(bio_err, "unable to load DSA parameters\n");
ERR_print_errors(bio_err);
BIO_printf(bio_err, "Error, unable to load DSA parameters\n");
goto end;
}
dh = DSA_dup_DH(dsa);
dh = alloc_dh = DSA_dup_DH(dsa);
DSA_free(dsa);
if (dh == NULL) {
ERR_print_errors(bio_err);
if (dh == NULL)
goto end;
}
} else
#endif
{
@@ -291,18 +281,17 @@ int dhparam_main(int argc, char **argv)
* We have no PEM header to determine what type of DH params it
* is. We'll just try both.
*/
dh = ASN1_d2i_bio_of(DH, DH_new, d2i_DHparams, in, NULL);
dh = alloc_dh = ASN1_d2i_bio_of(DH, DH_new, d2i_DHparams, in, NULL);
/* BIO_reset() returns 0 for success for file BIOs only!!! */
if (dh == NULL && BIO_reset(in) == 0)
dh = ASN1_d2i_bio_of(DH, DH_new, d2i_DHxparams, in, NULL);
dh = alloc_dh = ASN1_d2i_bio_of(DH, DH_new, d2i_DHxparams, in, NULL);
} else {
/* informat == FORMAT_PEM */
dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
dh = alloc_dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
}
if (dh == NULL) {
BIO_printf(bio_err, "unable to load DH parameters\n");
ERR_print_errors(bio_err);
BIO_printf(bio_err, "Error, unable to load DH parameters\n");
goto end;
}
}
@@ -314,8 +303,7 @@ int dhparam_main(int argc, char **argv)
if (check) {
if (!EVP_PKEY_param_check(ctx) /* DH_check(dh, &i) */) {
ERR_print_errors(bio_err);
BIO_printf(bio_err, "ERROR: Invalid parameters generated\n");
BIO_printf(bio_err, "Error, invalid parameters generated\n");
goto end;
}
BIO_printf(bio_err, "DH parameters appear to be ok.\n");
@@ -324,7 +312,7 @@ int dhparam_main(int argc, char **argv)
* We have generated parameters but DH_check() indicates they are
* invalid! This should never happen!
*/
BIO_printf(bio_err, "ERROR: Invalid parameters generated\n");
BIO_printf(bio_err, "Error, invalid parameters generated\n");
goto end;
}
}
@@ -382,13 +370,15 @@ int dhparam_main(int argc, char **argv)
i = PEM_write_bio_DHparams(out, dh);
}
if (!i) {
BIO_printf(bio_err, "unable to write DH parameters\n");
ERR_print_errors(bio_err);
BIO_printf(bio_err, "Error, unable to write DH parameters\n");
goto end;
}
}
ret = 0;
end:
if (ret != 0)
ERR_print_errors(bio_err);
DH_free(alloc_dh);
BIO_free(in);
BIO_free_all(out);
EVP_PKEY_free(pkey);
+23 -56
View File
@@ -66,9 +66,8 @@ const OPTIONS dsaparam_options[] = {
int dsaparam_main(int argc, char **argv)
{
ENGINE *e = NULL;
DSA *dsa = NULL;
BIO *in = NULL, *out = NULL;
EVP_PKEY *pkey = NULL;
EVP_PKEY *params = NULL, *pkey = NULL;
EVP_PKEY_CTX *ctx = NULL;
int numbits = -1, num = 0, genkey = 0;
int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0, C = 0;
@@ -150,7 +149,6 @@ int dsaparam_main(int argc, char **argv)
ctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL);
if (ctx == NULL) {
ERR_print_errors(bio_err);
BIO_printf(bio_err,
"Error, DSA parameter generation context allocation failed\n");
goto end;
@@ -170,62 +168,41 @@ int dsaparam_main(int argc, char **argv)
BIO_printf(bio_err, "This could take some time\n");
}
if (EVP_PKEY_paramgen_init(ctx) <= 0) {
ERR_print_errors(bio_err);
BIO_printf(bio_err,
"Error, DSA key generation paramgen init failed\n");
goto end;
}
if (!EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, num)) {
ERR_print_errors(bio_err);
BIO_printf(bio_err,
"Error, DSA key generation setting bit length failed\n");
goto end;
}
if (EVP_PKEY_paramgen(ctx, &pkey) <= 0) {
ERR_print_errors(bio_err);
if (EVP_PKEY_paramgen(ctx, &params) <= 0) {
BIO_printf(bio_err, "Error, DSA key generation failed\n");
goto end;
}
dsa = EVP_PKEY_get1_DSA(pkey);
if (dsa == NULL) {
ERR_print_errors(bio_err);
BIO_printf(bio_err, "Error, DSA key extraction failed\n");
goto end;
}
} else if (informat == FORMAT_ASN1) {
dsa = d2i_DSAparams_bio(in, NULL);
params = d2i_KeyParams_bio(EVP_PKEY_DSA, NULL, in);
} else {
dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL);
params = PEM_read_bio_Parameters(in, NULL);
}
if (dsa == NULL) {
BIO_printf(bio_err, "unable to load DSA parameters\n");
ERR_print_errors(bio_err);
if (params == NULL) {
BIO_printf(bio_err, "Error, unable to load DSA parameters\n");
goto end;
}
if (pkey == NULL) {
pkey = EVP_PKEY_new();
if (pkey == NULL) {
BIO_printf(bio_err, "Error, unable to allocate PKEY object\n");
ERR_print_errors(bio_err);
goto end;
}
if (!EVP_PKEY_set1_DSA(pkey, dsa)) {
BIO_printf(bio_err, "Error, unable to set DSA parameters\n");
ERR_print_errors(bio_err);
goto end;
}
}
if (text) {
EVP_PKEY_print_params(out, pkey, 0, NULL);
EVP_PKEY_print_params(out, params, 0, NULL);
}
if (C) {
const BIGNUM *p = NULL, *q = NULL, *g = NULL;
BIGNUM *p = NULL, *q = NULL, *g = NULL;
unsigned char *data;
int len, bits_p;
DSA_get0_pqg(dsa, &p, &q, &g);
EVP_PKEY_get_bn_param(params, "p", &p);
EVP_PKEY_get_bn_param(params, "q", &q);
EVP_PKEY_get_bn_param(params, "g", &g);
len = BN_num_bytes(p);
bits_p = BN_num_bits(p);
@@ -261,56 +238,46 @@ int dsaparam_main(int argc, char **argv)
if (!noout) {
if (outformat == FORMAT_ASN1)
i = i2d_DSAparams_bio(out, dsa);
i = i2d_KeyParams_bio(out, params);
else
i = PEM_write_bio_DSAparams(out, dsa);
i = PEM_write_bio_Parameters(out, params);
if (!i) {
BIO_printf(bio_err, "unable to write DSA parameters\n");
ERR_print_errors(bio_err);
BIO_printf(bio_err, "Error, unable to write DSA parameters\n");
goto end;
}
}
if (genkey) {
DSA *dsakey;
EVP_PKEY_CTX_free(ctx);
ctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL);
ctx = EVP_PKEY_CTX_new(params, NULL);
if (ctx == NULL) {
ERR_print_errors(bio_err);
BIO_printf(bio_err,
"Error, DSA key generation context allocation failed\n");
goto end;
}
if (!EVP_PKEY_keygen_init(ctx)) {
BIO_printf(bio_err, "unable to initialise for key generation\n");
ERR_print_errors(bio_err);
BIO_printf(bio_err,
"Error, unable to initialise for key generation\n");
goto end;
}
if (!EVP_PKEY_keygen(ctx, &pkey)) {
BIO_printf(bio_err, "unable to generate key\n");
ERR_print_errors(bio_err);
goto end;
}
dsakey = EVP_PKEY_get0_DSA(pkey);
if (dsakey == NULL) {
BIO_printf(bio_err, "unable to extract generated key\n");
ERR_print_errors(bio_err);
BIO_printf(bio_err, "Error, unable to generate key\n");
goto end;
}
assert(private);
if (outformat == FORMAT_ASN1)
i = i2d_DSAPrivateKey_bio(out, dsakey);
i = i2d_PrivateKey_bio(out, pkey);
else
i = PEM_write_bio_DSAPrivateKey(out, dsakey, NULL, NULL, 0, NULL,
NULL);
i = PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, NULL);
}
ret = 0;
end:
if (ret != 0)
ERR_print_errors(bio_err);
BIO_free(in);
BIO_free_all(out);
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
DSA_free(dsa);
EVP_PKEY_free(params);
release_engine(e);
return ret;
}
+1 -2
View File
@@ -305,7 +305,6 @@ int ecparam_main(int argc, char **argv)
size_t buf_len = 0, tmp_len = 0;
const EC_POINT *point;
int is_prime, len = 0;
const EC_METHOD *meth = EC_GROUP_method_of(group);
if ((ec_p = BN_new()) == NULL
|| (ec_a = BN_new()) == NULL
@@ -317,7 +316,7 @@ int ecparam_main(int argc, char **argv)
goto end;
}
is_prime = (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field);
is_prime = (EC_GROUP_get_field_type(group) == NID_X9_62_prime_field);
if (!is_prime) {
BIO_printf(bio_err, "Can only handle X9.62 prime fields\n");
goto end;
+5 -5
View File
@@ -366,7 +366,7 @@ opthelp:
goto end;
}
ctx = EVP_MAC_CTX_new(mac);
ctx = EVP_MAC_new_ctx(mac);
if (ctx == NULL) {
BIO_printf(bio_err, "Unable to create MAC CTX for module check\n");
goto end;
@@ -380,7 +380,7 @@ opthelp:
if (params == NULL)
goto end;
if (!EVP_MAC_CTX_set_params(ctx, params)) {
if (!EVP_MAC_set_ctx_params(ctx, params)) {
BIO_printf(bio_err, "MAC parameter error\n");
ERR_print_errors(bio_err);
ok = 0;
@@ -390,7 +390,7 @@ opthelp:
goto end;
}
ctx2 = EVP_MAC_CTX_dup(ctx);
ctx2 = EVP_MAC_dup_ctx(ctx);
if (ctx2 == NULL) {
BIO_printf(bio_err, "Unable to create MAC CTX for install indicator\n");
goto end;
@@ -450,8 +450,8 @@ cleanup:
BIO_free(module_bio);
sk_OPENSSL_STRING_free(opts);
EVP_MAC_free(mac);
EVP_MAC_CTX_free(ctx2);
EVP_MAC_CTX_free(ctx);
EVP_MAC_free_ctx(ctx2);
EVP_MAC_free_ctx(ctx);
OPENSSL_free(read_buffer);
free_config_and_unload(conf);
return ret;
+40 -58
View File
@@ -29,11 +29,14 @@
static int verbose = 0;
static int genrsa_cb(EVP_PKEY_CTX *ctx);
static int genrsa_cb(int p, int n, BN_GENCB *cb);
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
OPT_3, OPT_F4, OPT_ENGINE,
#ifndef OPENSSL_NO_DEPRECATED_3_0
OPT_3,
#endif
OPT_F4, OPT_ENGINE,
OPT_OUT, OPT_PASSOUT, OPT_CIPHER, OPT_PRIMES, OPT_VERBOSE,
OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
@@ -48,9 +51,11 @@ const OPTIONS genrsa_options[] = {
#endif
OPT_SECTION("Input"),
{"3", OPT_3, '-', "Use 3 for the E value"},
{"F4", OPT_F4, '-', "Use F4 (0x10001) for the E value"},
{"f4", OPT_F4, '-', "Use F4 (0x10001) for the E value"},
#ifndef OPENSSL_NO_DEPRECATED_3_0
{"3", OPT_3, '-', "(deprecated) Use 3 for the E value"},
#endif
{"F4", OPT_F4, '-', "Use the Fermat number F4 (0x10001) for the E value"},
{"f4", OPT_F4, '-', "Use the Fermat number F4 (0x10001) for the E value"},
OPT_SECTION("Output"),
{"out", OPT_OUT, '>', "Output the key to specified file"},
@@ -70,24 +75,24 @@ const OPTIONS genrsa_options[] = {
int genrsa_main(int argc, char **argv)
{
BN_GENCB *cb = BN_GENCB_new();
PW_CB_DATA cb_data;
ENGINE *eng = NULL;
BIGNUM *bn = BN_new();
RSA *rsa;
BIO *out = NULL;
const BIGNUM *e;
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx = NULL;
RSA *rsa = NULL;
const EVP_CIPHER *enc = NULL;
int ret = 1, num = DEFBITS, private = 0, primes = DEFPRIMES;
unsigned long f4 = RSA_F4;
char *outfile = NULL, *passoutarg = NULL, *passout = NULL;
char *prog, *hexe, *dece;
OPTION_CHOICE o;
unsigned char *ebuf = NULL;
if (bn == NULL || cb == NULL)
goto end;
BN_GENCB_set(cb, genrsa_cb, bio_err);
prog = opt_init(argc, argv, genrsa_options);
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
@@ -100,9 +105,11 @@ opthelp:
ret = 0;
opt_help(genrsa_options);
goto end;
#ifndef OPENSSL_NO_DEPRECATED_3_0
case OPT_3:
f4 = RSA_3;
f4 = 3;
break;
#endif
case OPT_F4:
f4 = RSA_F4;
break;
@@ -162,74 +169,49 @@ opthelp:
if (out == NULL)
goto end;
if (!init_gen_str(&ctx, "RSA", eng, 0))
goto end;
EVP_PKEY_CTX_set_cb(ctx, genrsa_cb);
EVP_PKEY_CTX_set_app_data(ctx, bio_err);
if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, num) <= 0) {
BIO_printf(bio_err, "Error setting RSA length\n");
goto end;
}
if (!BN_set_word(bn, f4)) {
BIO_printf(bio_err, "Error allocating RSA public exponent\n");
goto end;
}
if (EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, bn) <= 0) {
BIO_printf(bio_err, "Error setting RSA public exponent\n");
goto end;
}
if (EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, primes) <= 0) {
BIO_printf(bio_err, "Error setting number of primes\n");
goto end;
}
if (verbose)
BIO_printf(bio_err, "Generating RSA private key, %d bit long modulus (%d primes)\n",
num, primes);
if (!EVP_PKEY_keygen(ctx, &pkey)) {
BIO_printf(bio_err, "Error generating RSA key\n");
rsa = eng ? RSA_new_method(eng) : RSA_new();
if (rsa == NULL)
goto end;
}
if (verbose) {
if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
RSA_get0_key(rsa, NULL, &e, NULL);
} else {
BIO_printf(bio_err, "Error cannot access RSA e\n");
goto end;
}
hexe = BN_bn2hex(e);
dece = BN_bn2dec(e);
if (hexe && dece) {
BIO_printf(bio_err, "e is %s (0x%s)\n", dece, hexe);
}
OPENSSL_free(hexe);
OPENSSL_free(dece);
if (!BN_set_word(bn, f4)
|| !RSA_generate_multi_prime_key(rsa, num, primes, bn, cb))
goto end;
RSA_get0_key(rsa, NULL, &e, NULL);
hexe = BN_bn2hex(e);
dece = BN_bn2dec(e);
if (hexe && dece && verbose) {
BIO_printf(bio_err, "e is %s (0x%s)\n", dece, hexe);
}
if (!PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, passout))
OPENSSL_free(hexe);
OPENSSL_free(dece);
cb_data.password = passout;
cb_data.prompt_info = outfile;
assert(private);
if (!PEM_write_bio_RSAPrivateKey(out, rsa, enc, NULL, 0,
(pem_password_cb *)password_callback,
&cb_data))
goto end;
ret = 0;
end:
BN_free(bn);
BN_GENCB_free(cb);
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
RSA_free(rsa);
BIO_free_all(out);
release_engine(eng);
OPENSSL_free(passout);
OPENSSL_free(ebuf);
if (ret != 0)
ERR_print_errors(bio_err);
return ret;
}
static int genrsa_cb(EVP_PKEY_CTX *ctx)
static int genrsa_cb(int p, int n, BN_GENCB *cb)
{
char c = '*';
BIO *b = EVP_PKEY_CTX_get_app_data(ctx);
int p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
if (!verbose)
return 1;
@@ -242,7 +224,7 @@ static int genrsa_cb(EVP_PKEY_CTX *ctx)
c = '*';
if (p == 3)
c = '\n';
BIO_write(b, &c, 1);
(void)BIO_flush(b);
BIO_write(BN_GENCB_get_arg(cb), &c, 1);
(void)BIO_flush(BN_GENCB_get_arg(cb));
return 1;
}
+2 -25
View File
@@ -15,6 +15,7 @@
# include "internal/sockets.h" /* for openssl_fdset() */
# include <assert.h>
# include <stdarg.h>
# include <sys/types.h>
# ifndef OPENSSL_NO_POSIX_IO
# include <sys/stat.h>
@@ -29,7 +30,6 @@
# include <openssl/txt_db.h>
# include <openssl/engine.h>
# include <openssl/ocsp.h>
# include <openssl/http.h>
# include <signal.h>
# include "apps_ui.h"
# include "opt.h"
@@ -179,6 +179,7 @@ typedef struct ca_db_st {
# endif
} CA_DB;
void app_bail_out(char *fmt, ...);
void* app_malloc(int sz, const char *what);
BIGNUM *load_serial(const char *serialfile, int create, ASN1_INTEGER **retai);
int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial,
@@ -227,30 +228,6 @@ void print_cert_checks(BIO *bio, X509 *x,
void store_setup_crl_download(X509_STORE *st);
typedef struct app_http_tls_info_st {
const char *server;
const char *port;
int use_proxy;
long timeout;
SSL_CTX *ssl_ctx;
} APP_HTTP_TLS_INFO;
BIO *app_http_tls_cb(BIO *hbio, /* APP_HTTP_TLS_INFO */ void *arg,
int connect, int detail);
# ifndef OPENSSL_NO_SOCK
ASN1_VALUE *app_http_get_asn1(const char *url, const char *proxy,
const char *no_proxy, SSL_CTX *ssl_ctx,
const STACK_OF(CONF_VALUE) *headers,
long timeout, const char *expected_content_type,
const ASN1_ITEM *it);
ASN1_VALUE *app_http_post_asn1(const char *host, const char *port,
const char *path, const char *proxy,
const char *no_proxy, SSL_CTX *ctx,
const STACK_OF(CONF_VALUE) *headers,
const char *content_type,
ASN1_VALUE *req, const ASN1_ITEM *req_it,
long timeout, const ASN1_ITEM *rsp_it);
# endif
# define EXT_COPY_NONE 0
# define EXT_COPY_ADD 1
# define EXT_COPY_ALL 2
+23 -7
View File
@@ -60,23 +60,29 @@ void log_message(const char *prog, int level, const char *fmt, ...);
* returns a BIO for accepting requests, NULL on error
*/
BIO *http_server_init_bio(const char *prog, const char *port);
/*-
* Accept an ASN.1-formatted HTTP request
* it: the expected request ASN.1 type
* preq: pointer to variable where to place the parsed request
* pcbio: pointer to variable where to place the BIO for sending the response to
* ppath: pointer to variable where to place the request path, or NULL
* acbio: the listening bio (typically as returned by http_server_init_bio())
* prog: the name of the current app
* accept_get: wheter to accept GET requests (in addition to POST requests)
* accept_get: whether to accept GET requests (in addition to POST requests)
* timeout: connection timeout (in seconds), or 0 for none/infinite
* returns 0 in case caller should retry, then *preq == *pcbio == NULL
* returns -1 on fatal error; also in this case *preq == *pcbio == NULL
* returns 1 otherwise. In this case it is guaranteed that *pcbio != NULL
* while *preq == NULL if and only if request is invalid
* returns 0 in case caller should retry, then *preq == *ppath == *pcbio == NULL
* returns -1 on fatal error; also then holds *preq == *ppath == *pcbio == NULL
* returns 1 otherwise. In this case it is guaranteed that *pcbio != NULL while
* *ppath == NULL and *preq == NULL if and only if the request is invalid,
* On return value 1 the caller is responsible for sending an HTTP response,
* using http_server_send_asn1_resp() or http_server_send_status().
* The caller must free any non-NULL *preq, *ppath, and *pcbio pointers.
*/
int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq,
BIO **pcbio, BIO *acbio,
const char *prog, int accept_get, int timeout);
char **ppath, BIO **pcbio, BIO *acbio,
const char *prog, int accept_get, int timeout);
/*-
* Send an ASN.1-formatted HTTP response
* cbio: destination BIO (typically as returned by http_server_get_asn1_req())
@@ -89,6 +95,16 @@ int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq,
*/
int http_server_send_asn1_resp(BIO *cbio, const char *content_type,
const ASN1_ITEM *it, const ASN1_VALUE *resp);
/*-
* Send a trivial HTTP response, typically to report an error or OK
* cbio: destination BIO (typically as returned by http_server_get_asn1_req())
* status: the status code to send
* reason: the corresponding human-readable string
* returns 1 on success, 0 on failure
*/
int http_server_send_status(BIO *cbio, int status, const char *reason);
# endif
# ifdef HTTP_DAEMON
+3 -3
View File
@@ -104,7 +104,7 @@ opthelp:
goto opthelp;
}
ctx = EVP_KDF_CTX_new(kdf);
ctx = EVP_KDF_new_ctx(kdf);
if (ctx == NULL)
goto err;
@@ -116,7 +116,7 @@ opthelp:
if (params == NULL)
goto err;
if (!EVP_KDF_CTX_set_params(ctx, params)) {
if (!EVP_KDF_set_ctx_params(ctx, params)) {
BIO_printf(bio_err, "KDF parameter error\n");
ERR_print_errors(bio_err);
ok = 0;
@@ -161,7 +161,7 @@ err:
OPENSSL_clear_free(dkm_bytes, dkm_len);
sk_OPENSSL_STRING_free(opts);
EVP_KDF_free(kdf);
EVP_KDF_CTX_free(ctx);
EVP_KDF_free_ctx(ctx);
BIO_free(out);
OPENSSL_free(hexout);
return ret;
+25 -198
View File
@@ -438,10 +438,6 @@ X509 *load_cert_pass(const char *uri, int maybe_stdin,
if (desc == NULL)
desc = "certificate";
if (uri == NULL) {
unbuffer(stdin);
uri = "";
}
(void)load_key_cert_crl(uri, maybe_stdin, pass, desc, NULL, &cert, NULL);
if (cert == NULL) {
BIO_printf(bio_err, "Unable to load %s\n", desc);
@@ -453,7 +449,7 @@ X509 *load_cert_pass(const char *uri, int maybe_stdin,
/* the format parameter is meanwhile not needed anymore and thus ignored */
X509 *load_cert(const char *uri, int format, const char *desc)
{
return load_cert_pass(uri, 0, NULL, desc);
return load_cert_pass(uri, 1, NULL, desc);
}
/* the format parameter is meanwhile not needed anymore and thus ignored */
@@ -671,16 +667,24 @@ static int load_certs_crls(const char *file, int format,
return rv;
}
void app_bail_out(char *fmt, ...)
{
va_list args;
va_start(args, fmt);
BIO_vprintf(bio_err, fmt, args);
va_end(args);
ERR_print_errors(bio_err);
exit(1);
}
void* app_malloc(int sz, const char *what)
{
void *vp = OPENSSL_malloc(sz);
if (vp == NULL) {
BIO_printf(bio_err, "%s: Could not allocate %d bytes for %s\n",
opt_getprog(), sz, what);
ERR_print_errors(bio_err);
exit(1);
}
if (vp == NULL)
app_bail_out("%s: Could not allocate %d bytes for %s\n",
opt_getprog(), sz, what);
return vp;
}
@@ -1627,7 +1631,7 @@ X509_NAME *parse_name(const char *cp, long chtype, int canmulti)
goto err;
}
while (*cp) {
while (*cp != '\0') {
char *bp = work;
char *typestr = bp;
unsigned char *valstr;
@@ -1636,12 +1640,12 @@ X509_NAME *parse_name(const char *cp, long chtype, int canmulti)
nextismulti = 0;
/* Collect the type */
while (*cp && *cp != '=')
while (*cp != '\0' && *cp != '=')
*bp++ = *cp++;
if (*cp == '\0') {
BIO_printf(bio_err,
"%s: Hit end of string before finding the '='\n",
opt_getprog());
"%s: Hit end of string before finding the '='\n",
opt_getprog());
goto err;
}
*bp++ = '\0';
@@ -1649,7 +1653,7 @@ X509_NAME *parse_name(const char *cp, long chtype, int canmulti)
/* Collect the value. */
valstr = (unsigned char *)bp;
for (; *cp && *cp != '/'; *bp++ = *cp++) {
for (; *cp != '\0' && *cp != '/'; *bp++ = *cp++) {
if (canmulti && *cp == '+') {
nextismulti = 1;
break;
@@ -1664,7 +1668,7 @@ X509_NAME *parse_name(const char *cp, long chtype, int canmulti)
*bp++ = '\0';
/* If not at EOS (must be + or /), move forward. */
if (*cp)
if (*cp != '\0')
++cp;
/* Parse */
@@ -1683,6 +1687,7 @@ X509_NAME *parse_name(const char *cp, long chtype, int canmulti)
if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
valstr, strlen((char *)valstr),
-1, ismulti ? -1 : 0)) {
ERR_print_errors(bio_err);
BIO_printf(bio_err, "%s: Error adding name attribute \"/%s=%s\"\n",
opt_getprog(), typestr ,valstr);
goto err;
@@ -1949,137 +1954,6 @@ void store_setup_crl_download(X509_STORE *st)
X509_STORE_set_lookup_crls_cb(st, crls_http_cb);
}
#ifndef OPENSSL_NO_SOCK
static const char *tls_error_hint(void)
{
unsigned long err = ERR_peek_error();
if (ERR_GET_LIB(err) != ERR_LIB_SSL)
err = ERR_peek_last_error();
if (ERR_GET_LIB(err) != ERR_LIB_SSL)
return NULL;
switch (ERR_GET_REASON(err)) {
case SSL_R_WRONG_VERSION_NUMBER:
return "The server does not support (a suitable version of) TLS";
case SSL_R_UNKNOWN_PROTOCOL:
return "The server does not support HTTPS";
case SSL_R_CERTIFICATE_VERIFY_FAILED:
return "Cannot authenticate server via its TLS certificate, likely due to mismatch with our trusted TLS certs or missing revocation status";
case SSL_AD_REASON_OFFSET + TLS1_AD_UNKNOWN_CA:
return "Server did not accept our TLS certificate, likely due to mismatch with server's trust anchor or missing revocation status";
case SSL_AD_REASON_OFFSET + SSL3_AD_HANDSHAKE_FAILURE:
return "TLS handshake failure. Possibly the server requires our TLS certificate but did not receive it";
default: /* no error or no hint available for error */
return NULL;
}
}
/* HTTP callback function that supports TLS connection also via HTTPS proxy */
BIO *app_http_tls_cb(BIO *hbio, void *arg, int connect, int detail)
{
APP_HTTP_TLS_INFO *info = (APP_HTTP_TLS_INFO *)arg;
SSL_CTX *ssl_ctx = info->ssl_ctx;
SSL *ssl;
BIO *sbio = NULL;
if (connect && detail) { /* connecting with TLS */
if ((info->use_proxy
&& !OSSL_HTTP_proxy_connect(hbio, info->server, info->port,
NULL, NULL, /* no proxy credentials */
info->timeout, bio_err, opt_getprog()))
|| (sbio = BIO_new(BIO_f_ssl())) == NULL) {
return NULL;
}
if (ssl_ctx == NULL || (ssl = SSL_new(ssl_ctx)) == NULL) {
BIO_free(sbio);
return NULL;
}
SSL_set_tlsext_host_name(ssl, info->server);
SSL_set_connect_state(ssl);
BIO_set_ssl(sbio, ssl, BIO_CLOSE);
hbio = BIO_push(sbio, hbio);
} else if (!connect && !detail) { /* disconnecting after error */
const char *hint = tls_error_hint();
if (hint != NULL)
ERR_add_error_data(2, " : ", hint);
/*
* If we pop sbio and BIO_free() it this may lead to libssl double free.
* Rely on BIO_free_all() done by OSSL_HTTP_transfer() in http_client.c
*/
}
return hbio;
}
ASN1_VALUE *app_http_get_asn1(const char *url, const char *proxy,
const char *no_proxy, SSL_CTX *ssl_ctx,
const STACK_OF(CONF_VALUE) *headers,
long timeout, const char *expected_content_type,
const ASN1_ITEM *it)
{
APP_HTTP_TLS_INFO info;
char *server;
char *port;
int use_ssl;
ASN1_VALUE *resp = NULL;
if (url == NULL || it == NULL) {
HTTPerr(0, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (!OSSL_HTTP_parse_url(url, &server, &port, NULL /* ppath */, &use_ssl))
return NULL;
if (use_ssl && ssl_ctx == NULL) {
HTTPerr(0, ERR_R_PASSED_NULL_PARAMETER);
ERR_add_error_data(1, "missing SSL_CTX");
goto end;
}
info.server = server;
info.port = port;
info.use_proxy = proxy != NULL;
info.timeout = timeout;
info.ssl_ctx = ssl_ctx;
resp = OSSL_HTTP_get_asn1(url, proxy, no_proxy,
NULL, NULL, app_http_tls_cb, &info,
headers, 0 /* maxline */, 0 /* max_resp_len */,
timeout, expected_content_type, it);
end:
OPENSSL_free(server);
OPENSSL_free(port);
return resp;
}
ASN1_VALUE *app_http_post_asn1(const char *host, const char *port,
const char *path, const char *proxy,
const char *no_proxy, SSL_CTX *ssl_ctx,
const STACK_OF(CONF_VALUE) *headers,
const char *content_type,
ASN1_VALUE *req, const ASN1_ITEM *req_it,
long timeout, const ASN1_ITEM *rsp_it)
{
APP_HTTP_TLS_INFO info;
info.server = host;
info.port = port;
info.use_proxy = proxy != NULL;
info.timeout = timeout;
info.ssl_ctx = ssl_ctx;
return OSSL_HTTP_post_asn1(host, port, path, ssl_ctx != NULL,
proxy, no_proxy,
NULL, NULL, app_http_tls_cb, &info,
headers, content_type, req, req_it,
0 /* maxline */,
0 /* max_resp_len */, timeout, NULL, rsp_it);
}
#endif
/*
* Platform-specific sections
*/
@@ -2230,70 +2104,23 @@ double app_tminterval(int stop, int usertime)
return ret;
}
#elif defined(OPENSSL_SYSTEM_VMS)
# include <time.h>
# include <times.h>
double app_tminterval(int stop, int usertime)
{
static clock_t tmstart;
double ret = 0;
clock_t now;
# ifdef __TMS
struct tms rus;
now = times(&rus);
if (usertime)
now = rus.tms_utime;
# else
if (usertime)
now = clock(); /* sum of user and kernel times */
else {
struct timeval tv;
gettimeofday(&tv, NULL);
now = (clock_t)((unsigned long long)tv.tv_sec * CLK_TCK +
(unsigned long long)tv.tv_usec * (1000000 / CLK_TCK)
);
}
# endif
if (stop == TM_START)
tmstart = now;
else
ret = (now - tmstart) / (double)(CLK_TCK);
return ret;
}
#elif defined(_SC_CLK_TCK) /* by means of unistd.h */
# include <sys/times.h>
double app_tminterval(int stop, int usertime)
{
double ret = 0;
clock_t now;
static clock_t tmstart;
long int tck = sysconf(_SC_CLK_TCK);
# ifdef __TMS
struct tms rus;
clock_t now = times(&rus);
static clock_t tmstart;
now = times(&rus);
if (usertime)
now = rus.tms_utime;
# else
if (usertime)
now = clock(); /* sum of user and kernel times */
else {
struct timeval tv;
gettimeofday(&tv, NULL);
now = (clock_t)((unsigned long long)tv.tv_sec * tck +
(unsigned long long)tv.tv_usec * (1000000 / tck)
);
}
# endif
if (stop == TM_START) {
tmstart = now;
} else {
long int tck = sysconf(_SC_CLK_TCK);
ret = (now - tmstart) / (double)tck;
}
+77 -24
View File
@@ -255,17 +255,19 @@ static int urldecode(char *p)
}
int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq,
BIO **pcbio, BIO *acbio,
char **ppath, BIO **pcbio, BIO *acbio,
const char *prog, int accept_get, int timeout)
{
BIO *cbio = NULL, *getbio = NULL, *b64 = NULL;
int len;
char reqbuf[2048], inbuf[2048];
char *url, *end;
char *meth, *url, *end;
ASN1_VALUE *req;
int ret = 1;
*preq = NULL;
if (ppath != NULL)
*ppath = NULL;
*pcbio = NULL;
/* Connection loss before accept() is routine, ignore silently */
@@ -275,6 +277,7 @@ int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq,
cbio = BIO_pop(acbio);
*pcbio = cbio;
if (cbio == NULL) {
/* Cannot call http_server_send_status(cbio, ...) */
ret = -1;
goto out;
}
@@ -288,16 +291,26 @@ int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq,
/* Read the request line. */
len = BIO_gets(cbio, reqbuf, sizeof(reqbuf));
if (len <= 0)
if (len <= 0) {
log_message(prog, LOG_INFO,
"Request line read error or empty request");
(void)http_server_send_status(cbio, 400, "Bad Request");
goto out;
}
if (accept_get && strncmp(reqbuf, "GET ", 4) == 0) {
/* Expecting GET {sp} /URL {sp} HTTP/1.x */
for (url = reqbuf + 4; *url == ' '; ++url)
continue;
meth = reqbuf;
url = meth + 3;
if ((accept_get && strncmp(meth, "GET ", 4) == 0)
|| (url++, strncmp(meth, "POST ", 5) == 0)) {
/* Expecting (GET|POST) {sp} /URL {sp} HTTP/1.x */
*(url++) = '\0';
while (*url == ' ')
url++;
if (*url != '/') {
log_message(prog, LOG_INFO,
"Invalid GET -- URL does not begin with '/': %s", url);
"Invalid %s -- URL does not begin with '/': %s",
meth, url);
(void)http_server_send_status(cbio, 400, "Bad Request");
goto out;
}
url++;
@@ -308,7 +321,9 @@ int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq,
break;
if (strncmp(end, " HTTP/1.", 7) != 0) {
log_message(prog, LOG_INFO,
"Invalid GET -- bad HTTP/version string: %s", end + 1);
"Invalid %s -- bad HTTP/version string: %s",
meth, end + 1);
(void)http_server_send_status(cbio, 400, "Bad Request");
goto out;
}
*end = '\0';
@@ -318,39 +333,52 @@ int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq,
* 'url' was incremented above to point to the first byte *after*
* the leading slash, so in case 'GET / ' it is now an empty string.
*/
if (url[0] == '\0')
if (strlen(meth) == 3 && url[0] == '\0') {
(void)http_server_send_status(cbio, 200, "OK");
goto out;
}
len = urldecode(url);
if (len <= 0) {
if (len < 0) {
log_message(prog, LOG_INFO,
"Invalid GET request -- bad URL encoding: %s", url);
"Invalid %s request -- bad URL encoding: %s",
meth, url);
(void)http_server_send_status(cbio, 400, "Bad Request");
goto out;
}
if ((getbio = BIO_new_mem_buf(url, len)) == NULL
|| (b64 = BIO_new(BIO_f_base64())) == NULL) {
log_message(prog, LOG_ERR,
"Could not allocate base64 bio with size = %d", len);
BIO_free_all(cbio);
*pcbio = NULL;
ret = -1;
goto out;
if (strlen(meth) == 3) { /* GET */
if ((getbio = BIO_new_mem_buf(url, len)) == NULL
|| (b64 = BIO_new(BIO_f_base64())) == NULL) {
log_message(prog, LOG_ERR,
"Could not allocate base64 bio with size = %d",
len);
goto fatal;
}
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
getbio = BIO_push(b64, getbio);
}
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
getbio = BIO_push(b64, getbio);
} else if (strncmp(reqbuf, "POST ", 5) != 0) {
} else {
log_message(prog, LOG_INFO,
"HTTP request does not start with GET/POST: %s", reqbuf);
/* TODO provide better diagnosis in case client tries TLS */
(void)http_server_send_status(cbio, 400, "Bad Request");
goto out;
}
/* chop any further/duplicate leading or trailing '/' */
while (*url == '/')
url++;
while (end >= url + 2 && end[-2] == '/' && end[-1] == '/')
end--;
*end = '\0';
/* Read and skip past the headers. */
for (;;) {
len = BIO_gets(cbio, inbuf, sizeof(inbuf));
if (len <= 0) {
log_message(prog, LOG_ERR,
"Error skipping remaining HTTP headers");
(void)http_server_send_status(cbio, 400, "Bad Request");
goto out;
}
if ((inbuf[0] == '\r') || (inbuf[0] == '\n'))
@@ -365,8 +393,14 @@ int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq,
/* Try to read and parse request */
req = ASN1_item_d2i_bio(it, getbio != NULL ? getbio : cbio, NULL);
if (req == NULL)
if (req == NULL) {
log_message(prog, LOG_ERR, "Error parsing request");
} else if (ppath != NULL && (*ppath = OPENSSL_strdup(url)) == NULL) {
log_message(prog, LOG_ERR,
"Out of memory allocating %d bytes", strlen(url) + 1);
ASN1_item_free(req, it);
goto fatal;
}
*preq = req;
@@ -378,6 +412,17 @@ int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq,
acfd = (int)INVALID_SOCKET;
# endif
return ret;
fatal:
(void)http_server_send_status(cbio, 500, "Internal Server Error");
if (ppath != NULL) {
OPENSSL_free(*ppath);
*ppath = NULL;
}
BIO_free_all(cbio);
*pcbio = NULL;
ret = -1;
goto out;
}
/* assumes that cbio does not do an encoding that changes the output length */
@@ -392,4 +437,12 @@ int http_server_send_asn1_resp(BIO *cbio, const char *content_type,
(void)BIO_flush(cbio);
return ret;
}
int http_server_send_status(BIO *cbio, int status, const char *reason)
{
int ret = BIO_printf(cbio, "HTTP/1.0 %d %s\r\n\r\n", status, reason) > 0;
(void)BIO_flush(cbio);
return ret;
}
#endif
+9 -18
View File
@@ -209,6 +209,7 @@ int opt_format(const char *s, unsigned long flags, int *result)
{
switch (*s) {
default:
opt_printf_stderr("%s: Bad format \"%s\"\n", prog, s);
return 0;
case 'D':
case 'd':
@@ -275,6 +276,7 @@ int opt_format(const char *s, unsigned long flags, int *result)
return opt_format_error(s, flags);
*result = FORMAT_PKCS12;
} else {
opt_printf_stderr("%s: Bad format \"%s\"\n", prog, s);
return 0;
}
break;
@@ -740,40 +742,29 @@ int opt_next(void)
break;
case 'p':
case 'n':
if (!opt_int(arg, &ival)
|| (o->valtype == 'p' && ival <= 0)) {
if (!opt_int(arg, &ival))
return -1;
if (o->valtype == 'p' && ival <= 0) {
opt_printf_stderr("%s: Non-positive number \"%s\" for -%s\n",
prog, arg, o->name);
return -1;
}
break;
case 'M':
if (!opt_imax(arg, &imval)) {
opt_printf_stderr("%s: Invalid number \"%s\" for -%s\n",
prog, arg, o->name);
if (!opt_imax(arg, &imval))
return -1;
}
break;
case 'U':
if (!opt_umax(arg, &umval)) {
opt_printf_stderr("%s: Invalid number \"%s\" for -%s\n",
prog, arg, o->name);
if (!opt_umax(arg, &umval))
return -1;
}
break;
case 'l':
if (!opt_long(arg, &lval)) {
opt_printf_stderr("%s: Invalid number \"%s\" for -%s\n",
prog, arg, o->name);
if (!opt_long(arg, &lval))
return -1;
}
break;
case 'u':
if (!opt_ulong(arg, &ulval)) {
opt_printf_stderr("%s: Invalid number \"%s\" for -%s\n",
prog, arg, o->name);
if (!opt_ulong(arg, &ulval))
return -1;
}
break;
case 'c':
case 'E':
+2 -2
View File
@@ -787,7 +787,7 @@ int generate_cookie_callback(SSL *ssl, unsigned char *cookie,
BIO_printf(bio_err, "HMAC not found\n");
goto end;
}
ctx = EVP_MAC_CTX_new(hmac);
ctx = EVP_MAC_new_ctx(hmac);
if (ctx == NULL) {
BIO_printf(bio_err, "HMAC context allocation failed\n");
goto end;
@@ -796,7 +796,7 @@ int generate_cookie_callback(SSL *ssl, unsigned char *cookie,
*p++ = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, cookie_secret,
COOKIE_SECRET_LENGTH);
*p = OSSL_PARAM_construct_end();
if (!EVP_MAC_CTX_set_params(ctx, params)) {
if (!EVP_MAC_set_ctx_params(ctx, params)) {
BIO_printf(bio_err, "HMAC context parameter setting failed\n");
goto end;
}
+3 -3
View File
@@ -114,7 +114,7 @@ opthelp:
goto opthelp;
}
ctx = EVP_MAC_CTX_new(mac);
ctx = EVP_MAC_new_ctx(mac);
if (ctx == NULL)
goto err;
@@ -126,7 +126,7 @@ opthelp:
if (params == NULL)
goto err;
if (!EVP_MAC_CTX_set_params(ctx, params)) {
if (!EVP_MAC_set_ctx_params(ctx, params)) {
BIO_printf(bio_err, "MAC parameter error\n");
ERR_print_errors(bio_err);
ok = 0;
@@ -199,7 +199,7 @@ err:
sk_OPENSSL_STRING_free(opts);
BIO_free(in);
BIO_free(out);
EVP_MAC_CTX_free(ctx);
EVP_MAC_free_ctx(ctx);
EVP_MAC_free(mac);
return ret;
}
+124 -15
View File
@@ -83,6 +83,13 @@ static char *prog;
static int index_changed(CA_DB *);
#endif
#ifndef OPENSSL_NO_SOCK
static OCSP_RESPONSE *query_responder(BIO *cbio, const char *host,
const char *path,
const STACK_OF(CONF_VALUE) *headers,
OCSP_REQUEST *req, int req_timeout);
#endif
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
OPT_OUTFILE, OPT_TIMEOUT, OPT_URL, OPT_HOST, OPT_PORT,
@@ -234,7 +241,7 @@ int ocsp_main(int argc, char **argv)
int noCAfile = 0, noCApath = 0, noCAstore = 0;
int accept_count = -1, add_nonce = 1, noverify = 0, use_ssl = -1;
int vpmtouched = 0, badsig = 0, i, ignore_err = 0, nmin = 0, ndays = -1;
int req_text = 0, resp_text = 0, ret = 1;
int req_text = 0, resp_text = 0, res, ret = 1;
int req_timeout = -1;
long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
unsigned long sign_flags = 0, verify_flags = 0, rflags = 0;
@@ -274,8 +281,7 @@ int ocsp_main(int argc, char **argv)
OPENSSL_free(tport);
OPENSSL_free(tpath);
thost = tport = tpath = NULL;
if (!OSSL_HTTP_parse_url(opt_arg(),
&host, &port, &path, &use_ssl)) {
if (!OCSP_parse_url(opt_arg(), &host, &port, &path, &use_ssl)) {
BIO_printf(bio_err, "%s Error parsing URL\n", prog);
goto end;
}
@@ -629,13 +635,17 @@ redo_accept:
#endif
req = NULL;
if (!do_responder(&req, &cbio, acbio, req_timeout))
res = do_responder(&req, &cbio, acbio, req_timeout);
if (res == 0)
goto redo_accept;
if (req == NULL) {
resp = OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST,
NULL);
send_ocsp_response(cbio, resp);
if (res == 1) {
resp =
OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST,
NULL);
send_ocsp_response(cbio, resp);
}
goto done_resp;
}
}
@@ -1151,7 +1161,7 @@ static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio,
{
#ifndef OPENSSL_NO_SOCK
return http_server_get_asn1_req(ASN1_ITEM_rptr(OCSP_RESPONSE),
(ASN1_VALUE **)preq, pcbio, acbio,
(ASN1_VALUE **)preq, NULL, pcbio, acbio,
prog, 1 /* accept_get */, timeout);
#else
BIO_printf(bio_err,
@@ -1175,34 +1185,133 @@ static int send_ocsp_response(BIO *cbio, const OCSP_RESPONSE *resp)
}
#ifndef OPENSSL_NO_SOCK
static OCSP_RESPONSE *query_responder(BIO *cbio, const char *host,
const char *path,
const STACK_OF(CONF_VALUE) *headers,
OCSP_REQUEST *req, int req_timeout)
{
int fd;
int rv;
int i;
int add_host = 1;
OCSP_REQ_CTX *ctx = NULL;
OCSP_RESPONSE *rsp = NULL;
fd_set confds;
struct timeval tv;
if (req_timeout != -1)
BIO_set_nbio(cbio, 1);
rv = BIO_do_connect(cbio);
if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio))) {
BIO_puts(bio_err, "Error connecting BIO\n");
return NULL;
}
if (BIO_get_fd(cbio, &fd) < 0) {
BIO_puts(bio_err, "Can't get connection fd\n");
goto err;
}
if (req_timeout != -1 && rv <= 0) {
FD_ZERO(&confds);
openssl_fdset(fd, &confds);
tv.tv_usec = 0;
tv.tv_sec = req_timeout;
rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
if (rv == 0) {
BIO_puts(bio_err, "Timeout on connect\n");
return NULL;
}
}
ctx = OCSP_sendreq_new(cbio, path, NULL, -1);
if (ctx == NULL)
return NULL;
for (i = 0; i < sk_CONF_VALUE_num(headers); i++) {
CONF_VALUE *hdr = sk_CONF_VALUE_value(headers, i);
if (add_host == 1 && strcasecmp("host", hdr->name) == 0)
add_host = 0;
if (!OCSP_REQ_CTX_add1_header(ctx, hdr->name, hdr->value))
goto err;
}
if (add_host == 1 && OCSP_REQ_CTX_add1_header(ctx, "Host", host) == 0)
goto err;
if (!OCSP_REQ_CTX_set1_req(ctx, req))
goto err;
for (;;) {
rv = OCSP_sendreq_nbio(&rsp, ctx);
if (rv != -1)
break;
if (req_timeout == -1)
continue;
FD_ZERO(&confds);
openssl_fdset(fd, &confds);
tv.tv_usec = 0;
tv.tv_sec = req_timeout;
if (BIO_should_read(cbio)) {
rv = select(fd + 1, (void *)&confds, NULL, NULL, &tv);
} else if (BIO_should_write(cbio)) {
rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
} else {
BIO_puts(bio_err, "Unexpected retry condition\n");
goto err;
}
if (rv == 0) {
BIO_puts(bio_err, "Timeout on request\n");
break;
}
if (rv == -1) {
BIO_puts(bio_err, "Select error\n");
break;
}
}
err:
OCSP_REQ_CTX_free(ctx);
return rsp;
}
OCSP_RESPONSE *process_responder(OCSP_REQUEST *req,
const char *host, const char *path,
const char *port, int use_ssl,
STACK_OF(CONF_VALUE) *headers,
int req_timeout)
{
BIO *cbio = NULL;
SSL_CTX *ctx = NULL;
OCSP_RESPONSE *resp = NULL;
cbio = BIO_new_connect(host);
if (cbio == NULL) {
BIO_printf(bio_err, "Error creating connect BIO\n");
goto end;
}
if (port != NULL)
BIO_set_conn_port(cbio, port);
if (use_ssl == 1) {
BIO *sbio;
ctx = SSL_CTX_new(TLS_client_method());
if (ctx == NULL) {
BIO_printf(bio_err, "Error creating SSL context.\n");
goto end;
}
SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
sbio = BIO_new_ssl(ctx, 1);
cbio = BIO_push(sbio, cbio);
}
resp = (OCSP_RESPONSE *)
app_http_post_asn1(host, port, path, NULL, NULL /* no proxy used */,
ctx, headers, "application/ocsp-request",
(ASN1_VALUE *)req, ASN1_ITEM_rptr(OCSP_REQUEST),
req_timeout, ASN1_ITEM_rptr(OCSP_RESPONSE));
resp = query_responder(cbio, host, path, headers, req, req_timeout);
if (resp == NULL)
BIO_printf(bio_err, "Error querying OCSP responder\n");
end:
BIO_free_all(cbio);
SSL_CTX_free(ctx);
return resp;
}
-53
View File
@@ -171,27 +171,9 @@ unstructuredName = An optional company name
basicConstraints=CA:FALSE
# Here are some examples of the usage of nsCertType. If it is omitted
# the certificate can be used for anything *except* object signing.
# This is OK for an SSL server.
# nsCertType = server
# For an object signing certificate this would be used.
# nsCertType = objsign
# For normal client use this is typical
# nsCertType = client, email
# and for everything including object signing:
# nsCertType = client, email, objsign
# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
# This will be displayed in Netscape's comment listbox.
nsComment = "OpenSSL Generated Certificate"
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
@@ -206,13 +188,6 @@ authorityKeyIdentifier=keyid,issuer
# Copy subject details
# issuerAltName=issuer:copy
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
#nsBaseUrl
#nsRevocationUrl
#nsRenewalUrl
#nsCaPolicyUrl
#nsSslServerName
# This is required for TSA certificates.
# extendedKeyUsage = critical,timeStamping
@@ -242,9 +217,6 @@ basicConstraints = critical,CA:true
# left out by default.
# keyUsage = cRLSign, keyCertSign
# Some might want this also
# nsCertType = sslCA, emailCA
# Include email address in subject alt name: another PKIX recommendation
# subjectAltName=email:copy
# Copy issuer details
@@ -272,27 +244,9 @@ authorityKeyIdentifier=keyid:always
basicConstraints=CA:FALSE
# Here are some examples of the usage of nsCertType. If it is omitted
# the certificate can be used for anything *except* object signing.
# This is OK for an SSL server.
# nsCertType = server
# For an object signing certificate this would be used.
# nsCertType = objsign
# For normal client use this is typical
# nsCertType = client, email
# and for everything including object signing:
# nsCertType = client, email, objsign
# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
# This will be displayed in Netscape's comment listbox.
nsComment = "OpenSSL Generated Certificate"
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
@@ -307,13 +261,6 @@ authorityKeyIdentifier=keyid,issuer
# Copy subject details
# issuerAltName=issuer:copy
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
#nsBaseUrl
#nsRevocationUrl
#nsRenewalUrl
#nsCaPolicyUrl
#nsSslServerName
# This really needs to be in place for it to be a proxy certificate.
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
+12 -116
View File
@@ -30,9 +30,6 @@
#include "apps.h"
#include "progs.h"
/* Special sentinel to exit the program. */
#define EXIT_THE_PROGRAM (-1)
/*
* The LHASH callbacks ("hash" & "cmp") have been replaced by functions with
* the base prototypes (we cast each variable inside the function to the
@@ -80,27 +77,6 @@ static void apps_shutdown(void)
destroy_ui_method();
}
static char *make_config_name(void)
{
const char *t;
size_t len;
char *p;
if ((t = getenv("OPENSSL_CONF")) != NULL)
return OPENSSL_strdup(t);
t = X509_get_default_cert_area();
len = strlen(t) + 1 + strlen(OPENSSL_CONF) + 1;
p = app_malloc(len, "config filename buffer");
strcpy(p, t);
#ifndef OPENSSL_SYS_VMS
strcat(p, "/");
#endif
strcat(p, OPENSSL_CONF);
return p;
}
#ifndef OPENSSL_NO_TRACE
typedef struct tracedata_st {
@@ -233,17 +209,14 @@ int main(int argc, char *argv[])
{
FUNCTION f, *fp;
LHASH_OF(FUNCTION) *prog = NULL;
char *p, *pname;
char buf[1024];
const char *prompt;
char *pname;
ARGS arg;
int first, n, i, ret = 0;
int ret = 0;
arg.argv = NULL;
arg.size = 0;
/* Set up some of the environment. */
default_config_file = make_config_name();
bio_in = dup_bio_in(FORMAT_TEXT);
bio_out = dup_bio_out(FORMAT_TEXT);
bio_err = dup_bio_err(FORMAT_TEXT);
@@ -261,11 +234,6 @@ int main(int argc, char *argv[])
setup_trace(getenv("OPENSSL_TRACE"));
#endif
if (getenv("OPENSSL_FIPS")) {
BIO_printf(bio_err, "FIPS mode not supported.\n");
return 1;
}
if (!apps_startup()) {
BIO_printf(bio_err,
"FATAL: Startup failure (dev note: apps_startup() failed)\n");
@@ -284,92 +252,24 @@ int main(int argc, char *argv[])
}
pname = opt_progname(argv[0]);
default_config_file = CONF_get1_default_config_file();
if (default_config_file == NULL)
app_bail_out("%s: could not get default config file\n", pname);
/* first check the program name */
f.name = pname;
fp = lh_FUNCTION_retrieve(prog, &f);
if (fp != NULL) {
argv[0] = pname;
if (fp->deprecated_alternative != NULL)
warn_deprecated(fp);
ret = fp->func(argc, argv);
goto end;
}
/* If there is stuff on the command line, run with that. */
if (argc != 1) {
if (fp == NULL) {
/* We assume we've been called as 'openssl cmd' */
argc--;
argv++;
ret = do_cmd(prog, argc, argv);
if (ret < 0)
ret = 0;
goto end;
}
/* ok, lets enter interactive mode */
for (;;) {
ret = 0;
/* Read a line, continue reading if line ends with \ */
for (p = buf, n = sizeof(buf), i = 0, first = 1; n > 0; first = 0) {
prompt = first ? "OpenSSL> " : "> ";
p[0] = '\0';
#ifndef READLINE
fputs(prompt, stdout);
fflush(stdout);
if (!fgets(p, n, stdin))
goto end;
if (p[0] == '\0')
goto end;
i = strlen(p);
if (i <= 1)
break;
if (p[i - 2] != '\\')
break;
i -= 2;
p += i;
n -= i;
#else
{
extern char *readline(const char *);
extern void add_history(const char *cp);
char *text;
/* If there's a command, run with that, otherwise "help". */
ret = argc > 0
? do_cmd(prog, argc, argv)
: help_main(argc, argv);
text = readline(prompt);
if (text == NULL)
goto end;
i = strlen(text);
if (i == 0 || i > n)
break;
if (text[i - 1] != '\\') {
p += strlen(strcpy(p, text));
free(text);
add_history(buf);
break;
}
text[i - 1] = '\0';
p += strlen(strcpy(p, text));
free(text);
n -= i;
}
#endif
}
if (!chopup_args(&arg, buf)) {
BIO_printf(bio_err, "Can't parse (no memory?)\n");
break;
}
ret = do_cmd(prog, arg.argc, arg.argv);
if (ret == EXIT_THE_PROGRAM) {
ret = 0;
goto end;
}
if (ret != 0)
BIO_printf(bio_err, "error in %s\n", arg.argv[0]);
(void)BIO_flush(bio_out);
(void)BIO_flush(bio_err);
}
ret = 1;
end:
app_providers_cleanup();
OPENSSL_free(default_config_file);
@@ -502,10 +402,6 @@ static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[])
BIO_printf(bio_out, "%s\n", argv[0] + 3);
return 1;
}
if (strcmp(argv[0], "quit") == 0 || strcmp(argv[0], "q") == 0 ||
strcmp(argv[0], "exit") == 0 || strcmp(argv[0], "bye") == 0)
/* Special value to mean "exit the program. */
return EXIT_THE_PROGRAM;
BIO_printf(bio_err, "Invalid command '%s'; type \"help\" for a list.\n",
argv[0]);
-53
View File
@@ -171,27 +171,9 @@ unstructuredName = An optional company name
basicConstraints=CA:FALSE
# Here are some examples of the usage of nsCertType. If it is omitted
# the certificate can be used for anything *except* object signing.
# This is OK for an SSL server.
# nsCertType = server
# For an object signing certificate this would be used.
# nsCertType = objsign
# For normal client use this is typical
# nsCertType = client, email
# and for everything including object signing:
# nsCertType = client, email, objsign
# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
# This will be displayed in Netscape's comment listbox.
nsComment = "OpenSSL Generated Certificate"
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
@@ -206,13 +188,6 @@ authorityKeyIdentifier=keyid,issuer
# Copy subject details
# issuerAltName=issuer:copy
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
#nsBaseUrl
#nsRevocationUrl
#nsRenewalUrl
#nsCaPolicyUrl
#nsSslServerName
# This is required for TSA certificates.
# extendedKeyUsage = critical,timeStamping
@@ -242,9 +217,6 @@ basicConstraints = critical,CA:true
# left out by default.
# keyUsage = cRLSign, keyCertSign
# Some might want this also
# nsCertType = sslCA, emailCA
# Include email address in subject alt name: another PKIX recommendation
# subjectAltName=email:copy
# Copy issuer details
@@ -272,27 +244,9 @@ authorityKeyIdentifier=keyid:always
basicConstraints=CA:FALSE
# Here are some examples of the usage of nsCertType. If it is omitted
# the certificate can be used for anything *except* object signing.
# This is OK for an SSL server.
# nsCertType = server
# For an object signing certificate this would be used.
# nsCertType = objsign
# For normal client use this is typical
# nsCertType = client, email
# and for everything including object signing:
# nsCertType = client, email, objsign
# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
# This will be displayed in Netscape's comment listbox.
nsComment = "OpenSSL Generated Certificate"
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
@@ -307,13 +261,6 @@ authorityKeyIdentifier=keyid,issuer
# Copy subject details
# issuerAltName=issuer:copy
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
#nsBaseUrl
#nsRevocationUrl
#nsRenewalUrl
#nsCaPolicyUrl
#nsSslServerName
# This really needs to be in place for it to be a proxy certificate.
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
+1 -1
View File
@@ -65,9 +65,9 @@ const OPTIONS rsa_options[] = {
{"pvk-strong", OPT_PVK_STRONG, '-', "Enable 'Strong' PVK encoding level (default)"},
{"pvk-weak", OPT_PVK_WEAK, '-', "Enable 'Weak' PVK encoding level"},
{"pvk-none", OPT_PVK_NONE, '-', "Don't enforce PVK encoding"},
#endif
OPT_PROV_OPTIONS,
#endif
{NULL}
};
+174 -38
View File
@@ -81,6 +81,7 @@ static void print_stuff(BIO *berr, SSL *con, int full);
static int ocsp_resp_cb(SSL *s, void *arg);
#endif
static int ldap_ExtendedResponse_parse(const char *buf, long rem);
static char *base64encode (const void *buf, size_t len);
static int is_dNS_name(const char *host);
static int saved_errno;
@@ -576,7 +577,7 @@ typedef enum OPTION_choice {
OPT_READ_BUF, OPT_KEYLOG_FILE, OPT_EARLY_DATA, OPT_REQCAFILE,
OPT_V_ENUM,
OPT_X_ENUM,
OPT_S_ENUM,
OPT_S_ENUM, OPT_IGNORE_UNEXPECTED_EOF,
OPT_FALLBACKSCSV, OPT_NOCMDS, OPT_PROXY, OPT_PROXY_USER, OPT_PROXY_PASS,
OPT_DANE_TLSA_DOMAIN,
#ifndef OPENSSL_NO_CT
@@ -718,6 +719,8 @@ const OPTIONS s_client_options[] = {
"Do not send the server name (SNI) extension in the ClientHello"},
{"tlsextdebug", OPT_TLSEXTDEBUG, '-',
"Hex dump of all TLS extensions received"},
{"ignore_unexpected_eof", OPT_IGNORE_UNEXPECTED_EOF, '-',
"Do not treat lack of close_notify from a peer as an error"},
#ifndef OPENSSL_NO_OCSP
{"status", OPT_STATUS, '-', "Request certificate status from server"},
#endif
@@ -919,6 +922,7 @@ int s_client_main(int argc, char **argv)
char *connectstr = NULL, *bindstr = NULL;
char *cert_file = NULL, *key_file = NULL, *chain_file = NULL;
char *chCApath = NULL, *chCAfile = NULL, *chCAstore = NULL, *host = NULL;
char *thost = NULL, *tport = NULL;
char *port = OPENSSL_strdup(PORT);
char *bindhost = NULL, *bindport = NULL;
char *passarg = NULL, *pass = NULL;
@@ -934,7 +938,7 @@ int s_client_main(int argc, char **argv)
int prexit = 0;
int sdebug = 0;
int reconnect = 0, verify = SSL_VERIFY_NONE, vpmtouched = 0;
int ret = 1, in_init = 1, i, nbio_test = 0, sock = -1, k, width, state = 0;
int ret = 1, in_init = 1, i, nbio_test = 0, s = -1, k, width, state = 0;
int sbuf_len, sbuf_off, cmdletters = 1;
int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM, protocol = 0;
int starttls_proto = PROTO_OFF, crl_format = FORMAT_PEM, crl_download = 0;
@@ -1001,6 +1005,7 @@ int s_client_main(int argc, char **argv)
#ifndef OPENSSL_NO_SCTP
int sctp_label_bug = 0;
#endif
int ignore_unexpected_eof = 0;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
@@ -1180,6 +1185,9 @@ int s_client_main(int argc, char **argv)
if (!args_excert(o, &exc))
goto end;
break;
case OPT_IGNORE_UNEXPECTED_EOF:
ignore_unexpected_eof = 1;
break;
case OPT_PREXIT:
prexit = 1;
break;
@@ -1593,29 +1601,12 @@ int s_client_main(int argc, char **argv)
goto opthelp;
}
#endif
if (proxystr != NULL) {
if (connectstr != NULL) {
int res;
char *tmp_host = host, *tmp_port = port;
if (connectstr == NULL) {
BIO_printf(bio_err, "%s: -proxy requires use of -connect or target parameter\n", prog);
goto opthelp;
}
res = BIO_parse_hostserv(proxystr, &host, &port, BIO_PARSE_PRIO_HOST);
if (tmp_host != host)
OPENSSL_free(tmp_host);
if (tmp_port != port)
OPENSSL_free(tmp_port);
if (!res) {
BIO_printf(bio_err,
"%s: -proxy argument malformed or ambiguous\n", prog);
goto end;
}
} else {
int res = 1;
char *tmp_host = host, *tmp_port = port;
if (connectstr != NULL)
res = BIO_parse_hostserv(connectstr, &host, &port,
BIO_PARSE_PRIO_HOST);
res = BIO_parse_hostserv(connectstr, &host, &port, BIO_PARSE_PRIO_HOST);
if (tmp_host != host)
OPENSSL_free(tmp_host);
if (tmp_port != port)
@@ -1628,6 +1619,35 @@ int s_client_main(int argc, char **argv)
}
}
if (proxystr != NULL) {
int res;
char *tmp_host = host, *tmp_port = port;
if (host == NULL || port == NULL) {
BIO_printf(bio_err, "%s: -proxy requires use of -connect or target parameter\n", prog);
goto opthelp;
}
/* Retain the original target host:port for use in the HTTP proxy connect string */
thost = OPENSSL_strdup(host);
tport = OPENSSL_strdup(port);
if (thost == NULL || tport == NULL) {
BIO_printf(bio_err, "%s: out of memory\n", prog);
goto end;
}
res = BIO_parse_hostserv(proxystr, &host, &port, BIO_PARSE_PRIO_HOST);
if (tmp_host != host)
OPENSSL_free(tmp_host);
if (tmp_port != port)
OPENSSL_free(tmp_port);
if (!res) {
BIO_printf(bio_err,
"%s: -proxy argument malformed or ambiguous\n", prog);
goto end;
}
}
if (bindstr != NULL) {
int res;
res = BIO_parse_hostserv(bindstr, &bindhost, &bindport,
@@ -1776,6 +1796,9 @@ int s_client_main(int argc, char **argv)
&& SSL_CTX_set_max_proto_version(ctx, max_version) == 0)
goto end;
if (ignore_unexpected_eof)
SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
if (vpmtouched && !SSL_CTX_set1_param(ctx, vpm)) {
BIO_printf(bio_err, "Error setting verify params\n");
ERR_print_errors(bio_err);
@@ -2077,16 +2100,16 @@ int s_client_main(int argc, char **argv)
}
re_start:
if (init_client(&sock, host, port, bindhost, bindport, socket_family,
if (init_client(&s, host, port, bindhost, bindport, socket_family,
socket_type, protocol) == 0) {
BIO_printf(bio_err, "connect:errno=%d\n", get_last_socket_error());
BIO_closesocket(sock);
BIO_closesocket(s);
goto end;
}
BIO_printf(bio_c_out, "CONNECTED(%08X)\n", sock);
BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s);
if (c_nbio) {
if (!BIO_socket_nbio(sock, 1)) {
if (!BIO_socket_nbio(s, 1)) {
ERR_print_errors(bio_err);
goto end;
}
@@ -2098,21 +2121,21 @@ int s_client_main(int argc, char **argv)
#ifndef OPENSSL_NO_SCTP
if (protocol == IPPROTO_SCTP)
sbio = BIO_new_dgram_sctp(sock, BIO_NOCLOSE);
sbio = BIO_new_dgram_sctp(s, BIO_NOCLOSE);
else
#endif
sbio = BIO_new_dgram(sock, BIO_NOCLOSE);
sbio = BIO_new_dgram(s, BIO_NOCLOSE);
if ((peer_info.addr = BIO_ADDR_new()) == NULL) {
BIO_printf(bio_err, "memory allocation failure\n");
BIO_closesocket(sock);
BIO_closesocket(s);
goto end;
}
if (!BIO_sock_info(sock, BIO_SOCK_INFO_ADDRESS, &peer_info)) {
if (!BIO_sock_info(s, BIO_SOCK_INFO_ADDRESS, &peer_info)) {
BIO_printf(bio_err, "getsockname:errno=%d\n",
get_last_socket_error());
BIO_ADDR_free(peer_info.addr);
BIO_closesocket(sock);
BIO_closesocket(s);
goto end;
}
@@ -2149,7 +2172,7 @@ int s_client_main(int argc, char **argv)
}
} else
#endif /* OPENSSL_NO_DTLS */
sbio = BIO_new_socket(sock, BIO_NOCLOSE);
sbio = BIO_new_socket(s, BIO_NOCLOSE);
if (nbio_test) {
BIO *test;
@@ -2380,9 +2403,83 @@ int s_client_main(int argc, char **argv)
}
break;
case PROTO_CONNECT:
if (!OSSL_HTTP_proxy_connect(sbio, host, port, proxyuser, proxypass,
0 /* no timeout */, bio_err, prog))
goto shut;
{
enum {
error_proto, /* Wrong protocol, not even HTTP */
error_connect, /* CONNECT failed */
success
} foundit = error_connect;
BIO *fbio = BIO_new(BIO_f_buffer());
BIO_push(fbio, sbio);
BIO_printf(fbio, "CONNECT %s HTTP/1.0\r\n", connectstr);
/*
* Workaround for broken proxies which would otherwise close
* the connection when entering tunnel mode (eg Squid 2.6)
*/
BIO_printf(fbio, "Proxy-Connection: Keep-Alive\r\n");
/* Support for basic (base64) proxy authentication */
if (proxyuser != NULL) {
size_t l;
char *proxyauth, *proxyauthenc;
l = strlen(proxyuser);
if (proxypass != NULL)
l += strlen(proxypass);
proxyauth = app_malloc(l + 2, "Proxy auth string");
BIO_snprintf(proxyauth, l + 2, "%s:%s", proxyuser,
(proxypass != NULL) ? proxypass : "");
proxyauthenc = base64encode(proxyauth, strlen(proxyauth));
BIO_printf(fbio, "Proxy-Authorization: Basic %s\r\n",
proxyauthenc);
OPENSSL_clear_free(proxyauth, strlen(proxyauth));
OPENSSL_clear_free(proxyauthenc, strlen(proxyauthenc));
}
/* Terminate the HTTP CONNECT request */
BIO_printf(fbio, "\r\n");
(void)BIO_flush(fbio);
/*
* The first line is the HTTP response. According to RFC 7230,
* it's formatted exactly like this:
*
* HTTP/d.d ddd Reason text\r\n
*/
mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
if (mbuf_len < (int)strlen("HTTP/1.0 200")) {
BIO_printf(bio_err,
"%s: HTTP CONNECT failed, insufficient response "
"from proxy (got %d octets)\n", prog, mbuf_len);
(void)BIO_flush(fbio);
BIO_pop(fbio);
BIO_free(fbio);
goto shut;
}
if (mbuf[8] != ' ') {
BIO_printf(bio_err,
"%s: HTTP CONNECT failed, incorrect response "
"from proxy\n", prog);
foundit = error_proto;
} else if (mbuf[9] != '2') {
BIO_printf(bio_err, "%s: HTTP CONNECT failed: %s ", prog,
&mbuf[9]);
} else {
foundit = success;
}
if (foundit != error_proto) {
/* Read past all following headers */
do {
mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
} while (mbuf_len > 2);
}
(void)BIO_flush(fbio);
BIO_pop(fbio);
BIO_free(fbio);
if (foundit != success) {
goto shut;
}
}
break;
case PROTO_IRC:
{
@@ -3100,8 +3197,8 @@ int s_client_main(int argc, char **argv)
timeout.tv_usec = 500000; /* some extreme round-trip */
do {
FD_ZERO(&readfds);
openssl_fdset(sock, &readfds);
} while (select(sock + 1, &readfds, NULL, NULL, &timeout) > 0
openssl_fdset(s, &readfds);
} while (select(s + 1, &readfds, NULL, NULL, &timeout) > 0
&& BIO_read(sbio, sbuf, BUFSIZZ) > 0);
BIO_closesocket(SSL_get_fd(con));
@@ -3129,6 +3226,8 @@ int s_client_main(int argc, char **argv)
OPENSSL_free(bindstr);
OPENSSL_free(host);
OPENSSL_free(port);
OPENSSL_free(thost);
OPENSSL_free(tport);
X509_VERIFY_PARAM_free(vpm);
ssl_excert_free(exc);
sk_OPENSSL_STRING_free(ssl_args);
@@ -3151,6 +3250,7 @@ static void print_stuff(BIO *bio, SSL *s, int full)
X509 *peer = NULL;
STACK_OF(X509) *sk;
const SSL_CIPHER *c;
EVP_PKEY *public_key;
int i, istls13 = (SSL_version(s) == TLS1_3_VERSION);
long verify_result;
#ifndef OPENSSL_NO_COMP
@@ -3176,6 +3276,19 @@ static void print_stuff(BIO *bio, SSL *s, int full)
BIO_printf(bio, " i:");
X509_NAME_print_ex(bio, X509_get_issuer_name(sk_X509_value(sk, i)), 0, get_nameopt());
BIO_puts(bio, "\n");
public_key = X509_get_pubkey(sk_X509_value(sk, i));
if (public_key != NULL) {
BIO_printf(bio, " a:PKEY: %s, %d (bit); sigalg: %s\n",
OBJ_nid2sn(EVP_PKEY_base_id(public_key)),
EVP_PKEY_bits(public_key),
OBJ_nid2sn(X509_get_signature_nid(sk_X509_value(sk, i))));
EVP_PKEY_free(public_key);
}
BIO_printf(bio, " v:NotBefore: ");
ASN1_TIME_print(bio, X509_get0_notBefore(sk_X509_value(sk, i)));
BIO_printf(bio, "; NotAfter: ");
ASN1_TIME_print(bio, X509_get0_notAfter(sk_X509_value(sk, i)));
BIO_puts(bio, "\n");
if (c_showcerts)
PEM_write_bio_X509(bio, sk_X509_value(sk, i));
}
@@ -3477,6 +3590,29 @@ static int ldap_ExtendedResponse_parse(const char *buf, long rem)
return ret;
}
/*
* BASE64 encoder: used only for encoding basic proxy authentication credentials
*/
static char *base64encode (const void *buf, size_t len)
{
int i;
size_t outl;
char *out;
/* Calculate size of encoded data */
outl = (len / 3);
if (len % 3 > 0)
outl++;
outl <<= 2;
out = app_malloc(outl + 1, "base64 encode buffer");
i = EVP_EncodeBlock((unsigned char *)out, buf, len);
assert(i <= (int)outl);
if (i < 0)
*out = '\0';
return out;
}
/*
* Host dNS Name verifier: used for checking that the hostname is in dNS format
* before setting it as SNI
+17 -8
View File
@@ -534,8 +534,8 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
x = SSL_get_certificate(s);
aia = X509_get1_ocsp(x);
if (aia != NULL) {
if (!OSSL_HTTP_parse_url(sk_OPENSSL_STRING_value(aia, 0),
&host, &port, &path, &use_ssl)) {
if (!OCSP_parse_url(sk_OPENSSL_STRING_value(aia, 0),
&host, &port, &path, &use_ssl)) {
BIO_puts(bio_err, "cert_status: can't parse AIA URL\n");
goto err;
}
@@ -761,7 +761,7 @@ typedef enum OPTION_choice {
OPT_SRTP_PROFILES, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN,
OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_RECV_MAX_EARLY, OPT_EARLY_DATA,
OPT_S_NUM_TICKETS, OPT_ANTI_REPLAY, OPT_NO_ANTI_REPLAY, OPT_SCTP_LABEL_BUG,
OPT_HTTP_SERVER_BINMODE, OPT_NOCANAMES,
OPT_HTTP_SERVER_BINMODE, OPT_NOCANAMES, OPT_IGNORE_UNEXPECTED_EOF,
OPT_R_ENUM,
OPT_S_ENUM,
OPT_V_ENUM,
@@ -850,6 +850,8 @@ const OPTIONS s_server_options[] = {
"Disable caching and tickets if ephemeral (EC)DH is used"},
{"www", OPT_WWW, '-', "Respond to a 'GET /' with a status page"},
{"WWW", OPT_UPPER_WWW, '-', "Respond to a 'GET with the file ./path"},
{"ignore_unexpected_eof", OPT_IGNORE_UNEXPECTED_EOF, '-',
"Do not treat lack of close_notify from a peer as an error"},
{"tlsextdebug", OPT_TLSEXTDEBUG, '-',
"Hex dump of all TLS extensions received"},
{"HTTP", OPT_HTTP, '-', "Like -WWW but ./path includes HTTP headers"},
@@ -1094,6 +1096,7 @@ int s_server_main(int argc, char *argv[])
#ifndef OPENSSL_NO_SCTP
int sctp_label_bug = 0;
#endif
int ignore_unexpected_eof = 0;
/* Init of few remaining global variables */
local_argc = argc;
@@ -1403,9 +1406,10 @@ int s_server_main(int argc, char *argv[])
case OPT_STATUS_URL:
#ifndef OPENSSL_NO_OCSP
s_tlsextstatus = 1;
if (!OSSL_HTTP_parse_url(opt_arg(),
&tlscstatp.host, &tlscstatp.port,
&tlscstatp.path, &tlscstatp.use_ssl)) {
if (!OCSP_parse_url(opt_arg(),
&tlscstatp.host,
&tlscstatp.port,
&tlscstatp.path, &tlscstatp.use_ssl)) {
BIO_printf(bio_err, "Error parsing URL\n");
goto end;
}
@@ -1667,6 +1671,9 @@ int s_server_main(int argc, char *argv[])
use_sendfile = 1;
#endif
break;
case OPT_IGNORE_UNEXPECTED_EOF:
ignore_unexpected_eof = 1;
break;
}
}
argc = opt_num_rest();
@@ -1867,7 +1874,6 @@ int s_server_main(int argc, char *argv[])
goto end;
}
}
#ifndef OPENSSL_NO_SCTP
if (protocol == IPPROTO_SCTP && sctp_label_bug == 1)
SSL_CTX_set_mode(ctx, SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG);
@@ -1911,6 +1917,9 @@ int s_server_main(int argc, char *argv[])
SSL_CTX_set_options(ctx, SSL_OP_DISABLE_TLSEXT_CA_NAMES);
}
if (ignore_unexpected_eof)
SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
if (max_send_fragment > 0
&& !SSL_CTX_set_max_send_fragment(ctx, max_send_fragment)) {
BIO_printf(bio_err, "%s: Max send fragment size %u is out of permitted range\n",
@@ -3617,7 +3626,7 @@ static int generate_session_id(SSL *ssl, unsigned char *id,
{
unsigned int count = 0;
unsigned int session_id_prefix_len = strlen(session_id_prefix);
do {
if (RAND_bytes(id, *id_len) <= 0)
return 0;
+347 -10
View File
@@ -16,6 +16,7 @@
#define ECDH_SECONDS 10
#define EdDSA_SECONDS 10
#define SM2_SECONDS 10
#define FFDH_SECONDS 10
/* We need to use some deprecated APIs */
#define OPENSSL_SUPPRESS_DEPRECATED
@@ -98,6 +99,9 @@
# include <openssl/rsa.h>
# include "./testrsa.h"
#endif
#ifndef OPENSSL_NO_DH
# include <openssl/dh.h>
#endif
#include <openssl/x509.h>
#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DEPRECATED_3_0)
# include <openssl/dsa.h>
@@ -125,6 +129,7 @@
#define MAX_MISALIGNMENT 63
#define MAX_ECDH_SIZE 256
#define MISALIGN 64
#define MAX_FFDH_SIZE 1024
typedef struct openssl_speed_sec_st {
int sym;
@@ -134,6 +139,7 @@ typedef struct openssl_speed_sec_st {
int ecdh;
int eddsa;
int sm2;
int ffdh;
} openssl_speed_sec_t;
static volatile int run = 0;
@@ -435,6 +441,22 @@ static const OPT_PAIR rsa_choices[RSA_NUM] = {
static double rsa_results[RSA_NUM][2]; /* 2 ops: sign then verify */
#endif /* OPENSSL_NO_RSA */
#ifndef OPENSSL_NO_DH
enum ff_params_t {
R_FFDH_2048, R_FFDH_3072, R_FFDH_4096, R_FFDH_6144, R_FFDH_8192, FFDH_NUM
};
static const OPT_PAIR ffdh_choices[FFDH_NUM] = {
{"ffdh2048", R_FFDH_2048},
{"ffdh3072", R_FFDH_3072},
{"ffdh4096", R_FFDH_4096},
{"ffdh6144", R_FFDH_6144},
{"ffdh8192", R_FFDH_8192},
};
static double ffdh_results[FFDH_NUM][1]; /* 1 op: derivation */
#endif /* OPENSSL_NO_DH */
#ifndef OPENSSL_NO_EC
enum ec_curves_t {
R_EC_P160, R_EC_P192, R_EC_P224, R_EC_P256, R_EC_P384, R_EC_P521,
@@ -553,6 +575,7 @@ typedef struct loopargs_st {
EC_KEY *ecdsa[ECDSA_NUM];
EVP_PKEY_CTX *ecdh_ctx[EC_NUM];
EVP_MD_CTX *eddsa_ctx[EdDSA_NUM];
EVP_MD_CTX *eddsa_ctx2[EdDSA_NUM];
# ifndef OPENSSL_NO_SM2
EVP_MD_CTX *sm2_ctx[SM2_NUM];
EVP_MD_CTX *sm2_vfy_ctx[SM2_NUM];
@@ -561,6 +584,11 @@ typedef struct loopargs_st {
unsigned char *secret_a;
unsigned char *secret_b;
size_t outlen[EC_NUM];
#endif
#ifndef OPENSSL_NO_DH
EVP_PKEY_CTX *ffdh_ctx[FFDH_NUM];
unsigned char *secret_ff_a;
unsigned char *secret_ff_b;
#endif
EVP_CIPHER_CTX *ctx;
#ifndef OPENSSL_NO_DEPRECATED_3_0
@@ -1067,6 +1095,24 @@ static int RSA_verify_loop(void *args)
}
#endif
#ifndef OPENSSL_NO_DH
static long ffdh_c[FFDH_NUM][1];
static int FFDH_derive_key_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
EVP_PKEY_CTX *ffdh_ctx = tempargs->ffdh_ctx[testnum];
unsigned char *derived_secret = tempargs->secret_ff_a;
size_t outlen = MAX_FFDH_SIZE;
int count;
for (count = 0; COND(ffdh_c[testnum][0]); count++)
EVP_PKEY_derive(ffdh_ctx, derived_secret, &outlen);
return count;
}
#endif /* OPENSSL_NO_DH */
#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DEPRECATED_3_0)
static long dsa_c[DSA_NUM][2];
static int DSA_sign_loop(void *args)
@@ -1197,7 +1243,7 @@ static int EdDSA_verify_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
EVP_MD_CTX **edctx = tempargs->eddsa_ctx;
EVP_MD_CTX **edctx = tempargs->eddsa_ctx2;
unsigned char *eddsasig = tempargs->buf2;
size_t eddsasigsize = tempargs->sigsize;
int ret, count;
@@ -1463,7 +1509,8 @@ int speed_main(int argc, char **argv)
#endif
openssl_speed_sec_t seconds = { SECONDS, RSA_SECONDS, DSA_SECONDS,
ECDSA_SECONDS, ECDH_SECONDS,
EdDSA_SECONDS, SM2_SECONDS };
EdDSA_SECONDS, SM2_SECONDS,
FFDH_SECONDS };
/* What follows are the buffers and key material. */
#if !defined(OPENSSL_NO_RC5) && !defined(OPENSSL_NO_DEPRECATED_3_0)
@@ -1521,6 +1568,23 @@ int speed_main(int argc, char **argv)
uint8_t rsa_doit[RSA_NUM] = { 0 };
int primes = RSA_DEFAULT_PRIME_NUM;
#endif
#ifndef OPENSSL_NO_DH
typedef struct ffdh_params_st {
const char *name;
unsigned int nid;
unsigned int bits;
} FFDH_PARAMS;
static const FFDH_PARAMS ffdh_params[FFDH_NUM] = {
{"ffdh2048", NID_ffdhe2048, 2048},
{"ffdh3072", NID_ffdhe3072, 3072},
{"ffdh4096", NID_ffdhe4096, 4096},
{"ffdh6144", NID_ffdhe6144, 6144},
{"ffdh8192", NID_ffdhe8192, 8192}
};
uint8_t ffdh_doit[FFDH_NUM] = { 0 };
#endif /* OPENSSL_NO_DH */
#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DEPRECATED_3_0)
static const unsigned int dsa_bits[DSA_NUM] = { 512, 1024, 2048 };
uint8_t dsa_doit[DSA_NUM] = { 0 };
@@ -1718,7 +1782,7 @@ int speed_main(int argc, char **argv)
case OPT_SECONDS:
seconds.sym = seconds.rsa = seconds.dsa = seconds.ecdsa
= seconds.ecdh = seconds.eddsa
= seconds.sm2 = atoi(opt_arg());
= seconds.sm2 = seconds.ffdh = atoi(opt_arg());
break;
case OPT_BYTES:
lengths_single = atoi(opt_arg());
@@ -1765,6 +1829,18 @@ int speed_main(int argc, char **argv)
}
}
#endif
#ifndef OPENSSL_NO_DH
if (strncmp(algo, "ffdh", 4) == 0) {
if (algo[4] == '\0') {
memset(ffdh_doit, 1, sizeof(ffdh_doit));
continue;
}
if (opt_found(algo, ffdh_choices, &i)) {
ffdh_doit[i] = 2;
continue;
}
}
#endif
#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DEPRECATED_3_0)
if (strncmp(algo, "dsa", 3) == 0) {
if (algo[3] == '\0') {
@@ -1899,6 +1975,10 @@ int speed_main(int argc, char **argv)
#ifndef OPENSSL_NO_EC
loopargs[i].secret_a = app_malloc(MAX_ECDH_SIZE, "ECDH secret a");
loopargs[i].secret_b = app_malloc(MAX_ECDH_SIZE, "ECDH secret b");
#endif
#ifndef OPENSSL_NO_DH
loopargs[i].secret_ff_a = app_malloc(MAX_FFDH_SIZE, "FFDH secret a");
loopargs[i].secret_ff_b = app_malloc(MAX_FFDH_SIZE, "FFDH secret b");
#endif
}
@@ -1914,9 +1994,21 @@ int speed_main(int argc, char **argv)
if (argc == 0 && !doit[D_EVP] && !doit[D_EVP_HMAC] && !doit[D_EVP_CMAC]) {
memset(doit, 1, sizeof(doit));
doit[D_EVP] = doit[D_EVP_HMAC] = doit[D_EVP_CMAC] = 0;
#if !defined(OPENSSL_NO_MDC2) && !defined(OPENSSL_NO_DEPRECATED_3_0)
doit[D_MDC2] = 0;
#endif
#if !defined(OPENSSL_NO_MD4) && !defined(OPENSSL_NO_DEPRECATED_3_0)
doit[D_MD4] = 0;
#endif
#if !defined(OPENSSL_NO_RMD160) && !defined(OPENSSL_NO_DEPRECATED_3_0)
doit[D_RMD160] = 0;
#endif
#ifndef OPENSSL_NO_RSA
memset(rsa_doit, 1, sizeof(rsa_doit));
#endif
#ifndef OPENSSL_NO_DH
memset(ffdh_doit, 1, sizeof(ffdh_doit));
#endif
#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DEPRECATED_3_0)
memset(dsa_doit, 1, sizeof(dsa_doit));
#endif
@@ -2108,7 +2200,7 @@ int speed_main(int argc, char **argv)
c[D_IGE_256_AES][i] = c[D_IGE_256_AES][i - 1] * l0 / l1;
}
# ifndef OPENSSL_NO_RSA
# if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DEPRECATED_3_0)
rsa_c[R_RSA_512][0] = count / 2000;
rsa_c[R_RSA_512][1] = count / 400;
for (i = 1; i < RSA_NUM; i++) {
@@ -2258,6 +2350,19 @@ int speed_main(int argc, char **argv)
# endif
# endif /* OPENSSL_NO_EC */
# ifndef OPENSSL_NO_DH
ffdh_c[R_FFDH_2048][0] = count / 1000;
for (i = R_FFDH_3072; i <= R_FFDH_8192; i++) {
ffdh_c[i][0] = ffdh_c[i - 1][0] / 2;
if (ffdh_doit[i] <= 1 && ffdh_c[i][0] == 0) {
ffdh_doit[i] = 0;
} else {
if (ffdh_c[i][0] == 0)
ffdh_c[i][0] = 1;
}
}
# endif /* OPENSSL_NO_DH */
# else
/* not worth fixing */
# error "You cannot disable DES on systems without SIGALRM."
@@ -3047,7 +3152,6 @@ int speed_main(int argc, char **argv)
rsa_count = 1;
} else {
for (i = 0; i < loopargs_len; i++) {
EC_KEY_precompute_mult(loopargs[i].ecdsa[testnum], NULL);
/* Perform ECDSA signature test */
EC_KEY_generate_key(loopargs[i].ecdsa[testnum]);
st = ECDSA_sign(0, loopargs[i].buf, 20, loopargs[i].buf2,
@@ -3284,6 +3388,11 @@ int speed_main(int argc, char **argv)
st = 0;
break;
}
loopargs[i].eddsa_ctx2[testnum] = EVP_MD_CTX_new();
if (loopargs[i].eddsa_ctx2[testnum] == NULL) {
st = 0;
break;
}
if ((ed_pctx = EVP_PKEY_CTX_new_id(ed_curves[testnum].nid, NULL))
== NULL
@@ -3301,6 +3410,13 @@ int speed_main(int argc, char **argv)
EVP_PKEY_free(ed_pkey);
break;
}
if (!EVP_DigestVerifyInit(loopargs[i].eddsa_ctx2[testnum], NULL,
NULL, NULL, ed_pkey)) {
st = 0;
EVP_PKEY_free(ed_pkey);
break;
}
EVP_PKEY_free(ed_pkey);
}
if (st == 0) {
@@ -3338,10 +3454,9 @@ int speed_main(int argc, char **argv)
eddsa_results[testnum][0] = (double)count / d;
rsa_count = count;
}
/* Perform EdDSA verification test */
for (i = 0; i < loopargs_len; i++) {
st = EVP_DigestVerify(loopargs[i].eddsa_ctx[testnum],
st = EVP_DigestVerify(loopargs[i].eddsa_ctx2[testnum],
loopargs[i].buf2, loopargs[i].sigsize,
loopargs[i].buf, 20);
if (st != 1)
@@ -3509,8 +3624,188 @@ int speed_main(int argc, char **argv)
}
}
# endif /* OPENSSL_NO_SM2 */
#endif /* OPENSSL_NO_EC */
#ifndef OPENSSL_NO_DH
for (testnum = 0; testnum < FFDH_NUM; testnum++) {
int ffdh_checks = 1;
if (!ffdh_doit[testnum])
continue;
for (i = 0; i < loopargs_len; i++) {
EVP_PKEY *pkey_A = NULL;
EVP_PKEY *pkey_B = NULL;
EVP_PKEY_CTX *ffdh_ctx = NULL;
EVP_PKEY_CTX *test_ctx = NULL;
size_t secret_size;
size_t test_out;
/* Ensure that the error queue is empty */
if (ERR_peek_error()) {
BIO_printf(bio_err,
"WARNING: the error queue contains previous unhandled errors.\n");
ERR_print_errors(bio_err);
}
pkey_A = EVP_PKEY_new();
if (!pkey_A) {
BIO_printf(bio_err, "Error while initialising EVP_PKEY (out of memory?).\n");
ERR_print_errors(bio_err);
rsa_count = 1;
ffdh_checks = 0;
break;
}
pkey_B = EVP_PKEY_new();
if (!pkey_B) {
BIO_printf(bio_err, "Error while initialising EVP_PKEY (out of memory?).\n");
ERR_print_errors(bio_err);
rsa_count = 1;
ffdh_checks = 0;
break;
}
ffdh_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, NULL);
if (!ffdh_ctx) {
BIO_printf(bio_err, "Error while allocating EVP_PKEY_CTX.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
ffdh_checks = 0;
break;
}
if (EVP_PKEY_keygen_init(ffdh_ctx) <= 0) {
BIO_printf(bio_err, "Error while initialising EVP_PKEY_CTX.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
ffdh_checks = 0;
break;
}
if (EVP_PKEY_CTX_set_dh_nid(ffdh_ctx, ffdh_params[testnum].nid) <= 0) {
BIO_printf(bio_err, "Error setting DH key size for keygen.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
ffdh_checks = 0;
break;
}
if (EVP_PKEY_keygen(ffdh_ctx, &pkey_A) <= 0 ||
EVP_PKEY_keygen(ffdh_ctx, &pkey_B) <= 0) {
BIO_printf(bio_err, "FFDH key generation failure.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
ffdh_checks = 0;
break;
}
EVP_PKEY_CTX_free(ffdh_ctx);
/* check if the derivation works correctly both ways so that
* we know if future derive calls will fail, and we can skip
* error checking in benchmarked code */
ffdh_ctx = EVP_PKEY_CTX_new(pkey_A, NULL);
if (!ffdh_ctx) {
BIO_printf(bio_err, "Error while allocating EVP_PKEY_CTX.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
ffdh_checks = 0;
break;
}
if (EVP_PKEY_derive_init(ffdh_ctx) <= 0) {
BIO_printf(bio_err, "FFDH derivation context init failure.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
ffdh_checks = 0;
break;
}
if (EVP_PKEY_derive_set_peer(ffdh_ctx, pkey_B) <= 0) {
BIO_printf(bio_err, "Assigning peer key for derivation failed.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
ffdh_checks = 0;
break;
}
if (EVP_PKEY_derive(ffdh_ctx, NULL, &secret_size) <= 0) {
BIO_printf(bio_err, "Checking size of shared secret failed.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
ffdh_checks = 0;
break;
}
if (secret_size > MAX_FFDH_SIZE) {
BIO_printf(bio_err, "Assertion failure: shared secret too large.\n");
rsa_count = 1;
ffdh_checks = 0;
break;
}
if (EVP_PKEY_derive(ffdh_ctx,
loopargs[i].secret_ff_a,
&secret_size) <= 0) {
BIO_printf(bio_err, "Shared secret derive failure.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
ffdh_checks = 0;
break;
}
/* Now check from side B */
test_ctx = EVP_PKEY_CTX_new(pkey_B, NULL);
if (!test_ctx) {
BIO_printf(bio_err, "Error while allocating EVP_PKEY_CTX.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
ffdh_checks = 0;
break;
}
if (!EVP_PKEY_derive_init(test_ctx) ||
!EVP_PKEY_derive_set_peer(test_ctx, pkey_A) ||
!EVP_PKEY_derive(test_ctx, NULL, &test_out) ||
!EVP_PKEY_derive(test_ctx, loopargs[i].secret_ff_b, &test_out) ||
test_out != secret_size) {
BIO_printf(bio_err, "FFDH computation failure.\n");
rsa_count = 1;
ffdh_checks = 0;
break;
}
/* compare the computed secrets */
if (CRYPTO_memcmp(loopargs[i].secret_ff_a,
loopargs[i].secret_ff_b, secret_size)) {
BIO_printf(bio_err, "FFDH computations don't match.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
ffdh_checks = 0;
break;
}
loopargs[i].ffdh_ctx[testnum] = ffdh_ctx;
EVP_PKEY_free(pkey_A);
pkey_A = NULL;
EVP_PKEY_free(pkey_B);
pkey_B = NULL;
EVP_PKEY_CTX_free(test_ctx);
test_ctx = NULL;
}
if (ffdh_checks != 0) {
pkey_print_message("", "ffdh", ffdh_c[testnum][0],
ffdh_params[testnum].bits, seconds.ffdh);
Time_F(START);
count =
run_benchmark(async_jobs, FFDH_derive_key_loop, loopargs);
d = Time_F(STOP);
BIO_printf(bio_err,
mr ? "+R12:%ld:%d:%.2f\n" :
"%ld %u-bits FFDH ops in %.2fs\n", count,
ffdh_params[testnum].bits, d);
ffdh_results[testnum][0] = (double)count / d;
rsa_count = count;
};
if (rsa_count <= 1) {
/* if longer than 10s, don't do any more */
stop_it(ffdh_doit, testnum);
}
}
#endif /* OPENSSL_NO_DH */
#ifndef NO_FORK
show_res:
#endif
@@ -3687,6 +3982,26 @@ int speed_main(int argc, char **argv)
}
# endif
#endif /* OPENSSL_NO_EC */
#ifndef OPENSSL_NO_DH
testnum = 1;
for (k = 0; k < FFDH_NUM; k++) {
if (!ffdh_doit[k])
continue;
if (testnum && !mr) {
printf("%23sop op/s\n", " ");
testnum = 0;
}
if (mr)
printf("+F8:%u:%u:%f:%f\n",
k, ffdh_params[k].bits,
ffdh_results[k][0], 1.0 / ffdh_results[k][0]);
else
printf("%4u bits ffdh %8.4fs %8.1f\n",
ffdh_params[k].bits,
1.0 / ffdh_results[k][0], ffdh_results[k][0]);
}
#endif /* OPENSSL_NO_DH */
ret = 0;
@@ -3700,6 +4015,13 @@ int speed_main(int argc, char **argv)
for (k = 0; k < RSA_NUM; k++)
RSA_free(loopargs[i].rsa_key[k]);
#endif
#ifndef OPENSSL_NO_DH
OPENSSL_free(loopargs[i].secret_ff_a);
OPENSSL_free(loopargs[i].secret_ff_b);
for (k = 0; k < FFDH_NUM; k++) {
EVP_PKEY_CTX_free(loopargs[i].ffdh_ctx[k]);
}
#endif
#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DEPRECATED_3_0)
for (k = 0; k < DSA_NUM; k++)
DSA_free(loopargs[i].dsa_key[k]);
@@ -3709,8 +4031,10 @@ int speed_main(int argc, char **argv)
EC_KEY_free(loopargs[i].ecdsa[k]);
for (k = 0; k < EC_NUM; k++)
EVP_PKEY_CTX_free(loopargs[i].ecdh_ctx[k]);
for (k = 0; k < EdDSA_NUM; k++)
for (k = 0; k < EdDSA_NUM; k++) {
EVP_MD_CTX_free(loopargs[i].eddsa_ctx[k]);
EVP_MD_CTX_free(loopargs[i].eddsa_ctx2[k]);
}
# ifndef OPENSSL_NO_SM2
for (k = 0; k < SM2_NUM; k++) {
EVP_PKEY_CTX *pctx = NULL;
@@ -3978,7 +4302,20 @@ static int do_multi(int multi, int size_num)
sm2_results[k][1] += d;
}
# endif /* OPENSSL_NO_SM2 */
# endif
# endif /* OPENSSL_NO_EC */
# ifndef OPENSSL_NO_DH
else if (strncmp(buf, "+F8:", 4) == 0) {
int k;
double d;
p = buf + 4;
k = atoi(sstrsep(&p, sep));
sstrsep(&p, sep);
d = atof(sstrsep(&p, sep));
ffdh_results[k][0] += d;
}
# endif /* OPENSSL_NO_DH */
else if (strncmp(buf, "+H:", 3) == 0) {
;