#define COOKIE_SECRET_LENGTH 16
-int verify_depth = 0;
-int verify_quiet = 0;
-int verify_error = X509_V_OK;
-int verify_return_error = 0;
+VERIFY_CB_ARGS verify_args = { 0, 0, X509_V_OK, 0 };
+
#ifndef OPENSSL_NO_SOCK
static unsigned char cookie_secret[COOKIE_SECRET_LENGTH];
static int cookie_initialized = 0;
#endif
+static BIO *bio_keylog = NULL;
+static unsigned long nmflag = XN_FLAG_ONELINE;
+
+int set_nameopt(const char *arg)
+{
+ return set_name_ex(&nmflag, arg);
+}
static const char *lookup(int val, const STRINT_PAIR* list, const char* def)
{
err = X509_STORE_CTX_get_error(ctx);
depth = X509_STORE_CTX_get_error_depth(ctx);
- if (!verify_quiet || !ok) {
+ if (!verify_args.quiet || !ok) {
BIO_printf(bio_err, "depth=%d ", depth);
if (err_cert) {
X509_NAME_print_ex(bio_err,
X509_get_subject_name(err_cert),
- 0, XN_FLAG_ONELINE);
+ 0, nmflag);
BIO_puts(bio_err, "\n");
} else
BIO_puts(bio_err, "<no cert>\n");
if (!ok) {
BIO_printf(bio_err, "verify error:num=%d:%s\n", err,
X509_verify_cert_error_string(err));
- if (verify_depth >= depth) {
- if (!verify_return_error)
+ if (verify_args.depth >= depth) {
+ if (!verify_args.return_error)
ok = 1;
- verify_error = err;
+ verify_args.error = err;
} else {
ok = 0;
- verify_error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
+ verify_args.error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
}
}
switch (err) {
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
BIO_puts(bio_err, "issuer= ");
X509_NAME_print_ex(bio_err, X509_get_issuer_name(err_cert),
- 0, XN_FLAG_ONELINE);
+ 0, nmflag);
BIO_puts(bio_err, "\n");
break;
case X509_V_ERR_CERT_NOT_YET_VALID:
case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
BIO_printf(bio_err, "notBefore=");
- ASN1_TIME_print(bio_err, X509_get_notBefore(err_cert));
+ ASN1_TIME_print(bio_err, X509_get0_notBefore(err_cert));
BIO_printf(bio_err, "\n");
break;
case X509_V_ERR_CERT_HAS_EXPIRED:
case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
BIO_printf(bio_err, "notAfter=");
- ASN1_TIME_print(bio_err, X509_get_notAfter(err_cert));
+ ASN1_TIME_print(bio_err, X509_get0_notAfter(err_cert));
BIO_printf(bio_err, "\n");
break;
case X509_V_ERR_NO_EXPLICIT_POLICY:
- if (!verify_quiet)
+ if (!verify_args.quiet)
policies_print(ctx);
break;
}
- if (err == X509_V_OK && ok == 2 && !verify_quiet)
+ if (err == X509_V_OK && ok == 2 && !verify_args.quiet)
policies_print(ctx);
- if (ok && !verify_quiet)
+ if (ok && !verify_args.quiet)
BIO_printf(bio_err, "verify return:%d\n", ok);
return (ok);
}
BIO_puts(bio, "\n");
}
+static const char *get_sigtype(int nid)
+{
+ switch (nid) {
+ case EVP_PKEY_RSA:
+ return "RSA";
+
+ case EVP_PKEY_RSA_PSS:
+ return "RSA-PSS";
+
+ case EVP_PKEY_DSA:
+ return "DSA";
+
+ case EVP_PKEY_EC:
+ return "ECDSA";
+
+ default:
+ return NULL;
+ }
+}
+
static int do_print_sigalgs(BIO *out, SSL *s, int shared)
{
int i, nsig, client;
client = SSL_is_server(s) ? 0 : 1;
if (shared)
- nsig = SSL_get_shared_sigalgs(s, -1, NULL, NULL, NULL, NULL, NULL);
+ nsig = SSL_get_shared_sigalgs(s, 0, NULL, NULL, NULL, NULL, NULL);
else
nsig = SSL_get_sigalgs(s, -1, NULL, NULL, NULL, NULL, NULL);
if (nsig == 0)
SSL_get_sigalgs(s, i, &sign_nid, &hash_nid, NULL, &rsign, &rhash);
if (i)
BIO_puts(out, ":");
- if (sign_nid == EVP_PKEY_RSA)
- sstr = "RSA";
- else if (sign_nid == EVP_PKEY_DSA)
- sstr = "DSA";
- else if (sign_nid == EVP_PKEY_EC)
- sstr = "ECDSA";
+ sstr = get_sigtype(sign_nid);
if (sstr)
BIO_printf(out, "%s+", sstr);
else
int ssl_print_sigalgs(BIO *out, SSL *s)
{
- int mdnid;
+ int nid;
if (!SSL_is_server(s))
ssl_print_client_cert_types(out, s);
do_print_sigalgs(out, s, 0);
do_print_sigalgs(out, s, 1);
- if (SSL_get_peer_signature_nid(s, &mdnid))
- BIO_printf(out, "Peer signing digest: %s\n", OBJ_nid2sn(mdnid));
+ if (SSL_get_peer_signature_nid(s, &nid))
+ BIO_printf(out, "Peer signing digest: %s\n", OBJ_nid2sn(nid));
+ if (SSL_get_peer_signature_type_nid(s, &nid))
+ BIO_printf(bio_err, "Peer signature type: %s\n", get_sigtype(nid));
return 1;
}
return 1;
}
-int ssl_print_curves(BIO *out, SSL *s, int noshared)
+int ssl_print_groups(BIO *out, SSL *s, int noshared)
{
- int i, ncurves, *curves, nid;
- const char *cname;
+ int i, ngroups, *groups, nid;
+ const char *gname;
- ncurves = SSL_get1_curves(s, NULL);
- if (ncurves <= 0)
+ ngroups = SSL_get1_groups(s, NULL);
+ if (ngroups <= 0)
return 1;
- curves = app_malloc(ncurves * sizeof(int), "curves to print");
- SSL_get1_curves(s, curves);
+ groups = app_malloc(ngroups * sizeof(int), "groups to print");
+ SSL_get1_groups(s, groups);
- BIO_puts(out, "Supported Elliptic Curves: ");
- for (i = 0; i < ncurves; i++) {
+ BIO_puts(out, "Supported Elliptic Groups: ");
+ for (i = 0; i < ngroups; i++) {
if (i)
BIO_puts(out, ":");
- nid = curves[i];
+ nid = groups[i];
/* If unrecognised print out hex version */
if (nid & TLSEXT_nid_unknown)
BIO_printf(out, "0x%04X", nid & 0xFFFF);
else {
+ /* TODO(TLS1.3): Get group name here */
/* Use NIST name for curve if it exists */
- cname = EC_curve_nid2nist(nid);
- if (!cname)
- cname = OBJ_nid2sn(nid);
- BIO_printf(out, "%s", cname);
+ gname = EC_curve_nid2nist(nid);
+ if (!gname)
+ gname = OBJ_nid2sn(nid);
+ BIO_printf(out, "%s", gname);
}
}
- OPENSSL_free(curves);
+ OPENSSL_free(groups);
if (noshared) {
BIO_puts(out, "\n");
return 1;
}
- BIO_puts(out, "\nShared Elliptic curves: ");
- ncurves = SSL_get_shared_curve(s, -1);
- for (i = 0; i < ncurves; i++) {
+ BIO_puts(out, "\nShared Elliptic groups: ");
+ ngroups = SSL_get_shared_group(s, -1);
+ for (i = 0; i < ngroups; i++) {
if (i)
BIO_puts(out, ":");
- nid = SSL_get_shared_curve(s, i);
- cname = EC_curve_nid2nist(nid);
- if (!cname)
- cname = OBJ_nid2sn(nid);
- BIO_printf(out, "%s", cname);
+ nid = SSL_get_shared_group(s, i);
+ /* TODO(TLS1.3): Convert for DH groups */
+ gname = EC_curve_nid2nist(nid);
+ if (!gname)
+ gname = OBJ_nid2sn(nid);
+ BIO_printf(out, "%s", gname);
}
- if (ncurves == 0)
+ if (ngroups == 0)
BIO_puts(out, "NONE");
BIO_puts(out, "\n");
return 1;
cname = OBJ_nid2sn(nid);
BIO_printf(out, "ECDH, %s, %d bits\n", cname, EVP_PKEY_bits(key));
}
+ break;
#endif
+ default:
+ BIO_printf(out, "%s, %d bits\n", OBJ_nid2sn(EVP_PKEY_id(key)),
+ EVP_PKEY_bits(key));
}
EVP_PKEY_free(key);
return 1;
{"TLS 1.0", TLS1_VERSION},
{"TLS 1.1", TLS1_1_VERSION},
{"TLS 1.2", TLS1_2_VERSION},
+ {"TLS 1.3", TLS1_3_VERSION},
{"DTLS 1.0", DTLS1_VERSION},
{"DTLS 1.0 (bad)", DTLS1_BAD_VER},
{NULL}
version == TLS1_VERSION ||
version == TLS1_1_VERSION ||
version == TLS1_2_VERSION ||
+ version == TLS1_3_VERSION ||
version == DTLS1_VERSION || version == DTLS1_BAD_VER) {
switch (content_type) {
case 20:
{"client authz", TLSEXT_TYPE_client_authz},
{"server authz", TLSEXT_TYPE_server_authz},
{"cert type", TLSEXT_TYPE_cert_type},
- {"elliptic curves", TLSEXT_TYPE_elliptic_curves},
+ {"supported_groups", TLSEXT_TYPE_supported_groups},
{"EC point formats", TLSEXT_TYPE_ec_point_formats},
{"SRP", TLSEXT_TYPE_srp},
{"signature algorithms", TLSEXT_TYPE_signature_algorithms},
rv = SSL_check_chain(ssl, exc->cert, exc->key, exc->chain);
BIO_printf(bio_err, "Checking cert chain %d:\nSubject: ", i);
X509_NAME_print_ex(bio_err, X509_get_subject_name(exc->cert), 0,
- XN_FLAG_ONELINE);
+ nmflag);
BIO_puts(bio_err, "\n");
print_chain_flags(ssl, rv);
if (rv & CERT_PKEY_VALID) {
BIO_printf(bio_err, "%s: Error adding xcert\n", opt_getprog());
goto err;
}
+ *pexc = exc;
exc->certfile = opt_arg();
break;
case OPT_X_KEY:
BIO_puts(bio_err, "Peer certificate: ");
X509_NAME_print_ex(bio_err, X509_get_subject_name(peer),
- 0, XN_FLAG_ONELINE);
+ 0, nmflag);
BIO_puts(bio_err, "\n");
if (SSL_get_peer_signature_nid(s, &nid))
BIO_printf(bio_err, "Hash used: %s\n", OBJ_nid2sn(nid));
+ if (SSL_get_peer_signature_type_nid(s, &nid))
+ BIO_printf(bio_err, "Signature type: %s\n", get_sigtype(nid));
print_verify_detail(s, bio_err);
} else
BIO_puts(bio_err, "No peer certificate\n");
#ifndef OPENSSL_NO_EC
ssl_print_point_formats(bio_err, s);
if (SSL_is_server(s))
- ssl_print_curves(bio_err, s, 1);
+ ssl_print_groups(bio_err, s, 1);
else
ssl_print_tmp_key(bio_err, s);
#else
SSL_CTX_set_security_callback(ctx, security_callback_debug);
SSL_CTX_set0_security_ex_data(ctx, &sdb);
}
+
+static void keylog_callback(const SSL *ssl, const char *line)
+{
+ if (bio_keylog == NULL) {
+ BIO_printf(bio_err, "Keylog callback is invoked without valid file!\n");
+ return;
+ }
+
+ /*
+ * There might be concurrent writers to the keylog file, so we must ensure
+ * that the given line is written at once.
+ */
+ BIO_printf(bio_keylog, "%s\n", line);
+ (void)BIO_flush(bio_keylog);
+}
+
+int set_keylog_file(SSL_CTX *ctx, const char *keylog_file)
+{
+ /* Close any open files */
+ BIO_free_all(bio_keylog);
+ bio_keylog = NULL;
+
+ if (ctx == NULL || keylog_file == NULL) {
+ /* Keylogging is disabled, OK. */
+ return 0;
+ }
+
+ /*
+ * Append rather than write in order to allow concurrent modification.
+ * Furthermore, this preserves existing keylog files which is useful when
+ * the tool is run multiple times.
+ */
+ bio_keylog = BIO_new_file(keylog_file, "a");
+ if (bio_keylog == NULL) {
+ BIO_printf(bio_err, "Error writing keylog file %s\n", keylog_file);
+ return 1;
+ }
+
+ /* Write a header for seekable, empty files (this excludes pipes). */
+ if (BIO_tell(bio_keylog) == 0) {
+ BIO_puts(bio_keylog,
+ "# SSL/TLS secrets log file, generated by OpenSSL\n");
+ (void)BIO_flush(bio_keylog);
+ }
+ SSL_CTX_set_keylog_callback(ctx, keylog_callback);
+ return 0;
+}