#include <openssl/rand.h>
#include <openssl/x509.h>
#include <openssl/ssl.h>
+#include <openssl/bn.h>
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
#include "s_apps.h"
#define COOKIE_SECRET_LENGTH 16
int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
STACK_OF(X509) *chain, int build_chain)
{
+ int chflags = chain ? SSL_BUILD_CHAIN_FLAG_CHECK : 0;
if (cert == NULL)
return 1;
if (SSL_CTX_use_certificate(ctx,cert) <= 0)
ERR_print_errors(bio_err);
return 0;
}
- if (!chain && build_chain && !SSL_CTX_build_cert_chain(ctx, 0))
+ if (build_chain && !SSL_CTX_build_cert_chain(ctx, chflags))
{
BIO_printf(bio_err,"error building certificate chain\n");
ERR_print_errors(bio_err);
BIO_printf(out, "Peer signing digest: %s\n", OBJ_nid2sn(mdnid));
return 1;
}
-
+#ifndef OPENSSL_NO_EC
int ssl_print_point_formats(BIO *out, SSL *s)
{
int i, nformats;
BIO_puts(out, "\n");
return 1;
}
-
+#endif
int ssl_print_tmp_key(BIO *out, SSL *s)
{
EVP_PKEY *key;
case EVP_PKEY_DH:
BIO_printf(out, "DH, %d bits\n", EVP_PKEY_bits(key));
break;
-
+#ifndef OPENSSL_NO_ECDH
case EVP_PKEY_EC:
{
EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key);
BIO_printf(out, "ECDH, %s, %d bits\n",
cname, EVP_PKEY_bits(key));
}
+#endif
}
EVP_PKEY_free(key);
return 1;
}
}
-
-void MS_CALLBACK msg_cb(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
+static const char *ssl_version_str(int version)
{
- BIO *bio = arg;
- const char *str_write_p, *str_version, *str_content_type = "", *str_details1 = "", *str_details2= "";
-
- str_write_p = write_p ? ">>>" : "<<<";
-
switch (version)
{
- case SSL2_VERSION:
- str_version = "SSL 2.0";
- break;
case SSL3_VERSION:
- str_version = "SSL 3.0 ";
- break;
+ return "SSL 3.0";
case TLS1_VERSION:
- str_version = "TLS 1.0 ";
- break;
+ return "TLS 1.0";
case TLS1_1_VERSION:
- str_version = "TLS 1.1 ";
- break;
+ return "TLS 1.1";
case TLS1_2_VERSION:
- str_version = "TLS 1.2 ";
- break;
+ return "TLS 1.2";
case DTLS1_VERSION:
- str_version = "DTLS 1.0 ";
- break;
+ return "DTLS 1.0";
case DTLS1_BAD_VER:
- str_version = "DTLS 1.0 (bad) ";
- break;
+ return "DTLS 1.0 (bad)";
default:
- str_version = "???";
+ return "???";
}
+ }
- if (version == SSL2_VERSION)
- {
- str_details1 = "???";
-
- if (len > 0)
- {
- switch (((const unsigned char*)buf)[0])
- {
- case 0:
- str_details1 = ", ERROR:";
- str_details2 = " ???";
- if (len >= 3)
- {
- unsigned err = (((const unsigned char*)buf)[1]<<8) + ((const unsigned char*)buf)[2];
-
- switch (err)
- {
- case 0x0001:
- str_details2 = " NO-CIPHER-ERROR";
- break;
- case 0x0002:
- str_details2 = " NO-CERTIFICATE-ERROR";
- break;
- case 0x0004:
- str_details2 = " BAD-CERTIFICATE-ERROR";
- break;
- case 0x0006:
- str_details2 = " UNSUPPORTED-CERTIFICATE-TYPE-ERROR";
- break;
- }
- }
+void MS_CALLBACK msg_cb(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
+ {
+ BIO *bio = arg;
+ const char *str_write_p, *str_version, *str_content_type = "", *str_details1 = "", *str_details2= "";
+
+ str_write_p = write_p ? ">>>" : "<<<";
- break;
- case 1:
- str_details1 = ", CLIENT-HELLO";
- break;
- case 2:
- str_details1 = ", CLIENT-MASTER-KEY";
- break;
- case 3:
- str_details1 = ", CLIENT-FINISHED";
- break;
- case 4:
- str_details1 = ", SERVER-HELLO";
- break;
- case 5:
- str_details1 = ", SERVER-VERIFY";
- break;
- case 6:
- str_details1 = ", SERVER-FINISHED";
- break;
- case 7:
- str_details1 = ", REQUEST-CERTIFICATE";
- break;
- case 8:
- str_details1 = ", CLIENT-CERTIFICATE";
- break;
- }
- }
- }
+ str_version = ssl_version_str(version);
if (version == SSL3_VERSION ||
version == TLS1_VERSION ||
extname = "next protocol";
break;
#endif
+#ifdef TLSEXT_TYPE_encrypt_then_mac
+ case TLSEXT_TYPE_encrypt_then_mac:
+ extname = "encrypt-then-mac";
+ break;
+#endif
+ case TLSEXT_TYPE_padding:
+ extname = "TLS padding";
+ break;
default:
extname = "unknown";
};
-static void print_chain_flags(BIO *out, int flags)
+static void print_chain_flags(BIO *out, SSL *s, int flags)
{
struct chain_flags *ctmp = chain_flags_list;
while(ctmp->name)
flags & ctmp->flag ? "OK" : "NOT OK");
ctmp++;
}
+ BIO_printf(out, "\tSuite B: ");
+ if (SSL_set_cert_flags(s, 0) & SSL_CERT_FLAG_SUITEB_128_LOS)
+ BIO_puts(out, flags & CERT_PKEY_SUITEB ? "OK\n" : "NOT OK\n");
+ else
+ BIO_printf(out, "not tested\n");
}
/* Very basic selection callback: just use any certificate chain
{
int i, rv;
SSL_EXCERT *exc = arg;
+#ifdef CERT_CB_TEST_RETRY
+ static int retry_cnt;
+ if (retry_cnt < 5)
+ {
+ retry_cnt++;
+ fprintf(stderr, "Certificate callback retry test: count %d\n",
+ retry_cnt);
+ return -1;
+ }
+#endif
SSL_certs_clear(ssl);
if (!exc)
XN_FLAG_ONELINE);
BIO_puts(bio_err, "\n");
- print_chain_flags(bio_err, rv);
+ print_chain_flags(bio_err, ssl, rv);
if (rv & CERT_PKEY_VALID)
{
SSL_use_certificate(ssl, exc->cert);
if (!exc->cert)
return 0;
if (exc->keyfile)
- exc->keyfile = exc->certfile;
- exc->key = load_key(err, exc->certfile, exc->certform, 0,
- NULL, NULL, "Server Certificate");
+ {
+ exc->key = load_key(err, exc->keyfile, exc->keyform,
+ 0, NULL, NULL, "Server Key");
+ }
+ else
+ {
+ exc->key = load_key(err, exc->certfile, exc->certform,
+ 0, NULL, NULL, "Server Key");
+ }
if (!exc->key)
return 0;
if (exc->chainfile)
exc->chainfile, FORMAT_PEM,
NULL, NULL,
"Server Chain");
- if (!exc->chainfile)
+ if (!exc->chain)
return 0;
}
}
BIO_puts(bio, "No peer certificate\n");
if (peer)
X509_free(peer);
+#ifndef OPENSSL_NO_EC
ssl_print_point_formats(bio, s);
if (SSL_is_server(s))
ssl_print_curves(bio, s, 1);
else
ssl_print_tmp_key(bio, s);
- }
-
-void print_ssl_cert_checks(BIO *bio, SSL *s,
- const unsigned char *checkhost,
- const unsigned char *checkemail,
- const char *checkip)
- {
- X509 *peer;
- peer = SSL_get_peer_certificate(s);
- if (peer)
- {
- print_cert_checks(bio, peer, checkhost, checkemail, checkip);
- X509_free(peer);
- }
+#else
+ if (!SSL_is_server(s))
+ ssl_print_tmp_key(bio, s);
+#endif
}
int args_ssl(char ***pargs, int *pargc, SSL_CONF_CTX *cctx,
}
int args_ssl_call(SSL_CTX *ctx, BIO *err, SSL_CONF_CTX *cctx,
- STACK_OF(OPENSSL_STRING) *str, int no_ecdhe)
+ STACK_OF(OPENSSL_STRING) *str, int no_ecdhe, int no_jpake)
{
int i;
SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
*/
if (!no_ecdhe && !strcmp(param, "-named_curve"))
no_ecdhe = 1;
+#ifndef OPENSSL_NO_JPAKE
+ if (!no_jpake && !strcmp(param, "-cipher"))
+ {
+ BIO_puts(err, "JPAKE sets cipher to PSK\n");
+ return 0;
+ }
+#endif
if (SSL_CONF_cmd(cctx, param, value) <= 0)
{
BIO_printf(err, "Error with command: \"%s %s\"\n",
return 0;
}
}
+#ifndef OPENSSL_NO_JPAKE
+ if (!no_jpake)
+ {
+ if (SSL_CONF_cmd(cctx, "-cipher", "PSK") <= 0)
+ {
+ BIO_puts(err, "Error setting cipher to PSK\n");
+ ERR_print_errors(err);
+ return 0;
+ }
+ }
+#endif
+ if (!SSL_CONF_CTX_finish(cctx))
+ {
+ BIO_puts(err, "Error finishing context\n");
+ ERR_print_errors(err);
+ return 0;
+ }
return 1;
}
{
X509_CRL *crl;
int i;
- if (crls)
+ for (i = 0; i < sk_X509_CRL_num(crls); i++)
{
- for (i = 0; i < sk_X509_CRL_num(crls); i++)
- {
- crl = sk_X509_CRL_value(crls, i);
- X509_STORE_add_crl(st, crl);
- }
+ crl = sk_X509_CRL_value(crls, i);
+ X509_STORE_add_crl(st, crl);
}
return 1;
}
-int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls)
+int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls, int crl_download)
{
X509_STORE *st;
- if (crls)
- {
- st = SSL_CTX_get_cert_store(ctx);
- add_crls_store(st, crls);
- }
+ st = SSL_CTX_get_cert_store(ctx);
+ add_crls_store(st, crls);
+ if (crl_download)
+ store_setup_crl_download(st);
return 1;
}
int ssl_load_stores(SSL_CTX *ctx,
const char *vfyCApath, const char *vfyCAfile,
const char *chCApath, const char *chCAfile,
- STACK_OF(X509_CRL) *crls)
+ STACK_OF(X509_CRL) *crls, int crl_download)
{
X509_STORE *vfy = NULL, *ch = NULL;
int rv = 0;
goto err;
add_crls_store(vfy, crls);
SSL_CTX_set1_verify_cert_store(ctx, vfy);
+ if (crl_download)
+ store_setup_crl_download(vfy);
}
if (chCApath || chCAfile)
{
X509_STORE_free(ch);
return rv;
}
+
+/* Verbose print out of security callback */
+
+typedef struct
+ {
+ BIO *out;
+ int verbose;
+ int (*old_cb)(SSL *s, SSL_CTX *ctx, int op, int bits, int nid,
+ void *other, void *ex);
+ } security_debug_ex;
+
+static int security_callback_debug(SSL *s, SSL_CTX *ctx,
+ int op, int bits, int nid,
+ void *other, void *ex)
+ {
+ security_debug_ex *sdb = ex;
+ int rv, show_bits = 1, cert_md = 0;
+ const char *nm;
+ rv = sdb->old_cb(s, ctx, op, bits, nid, other, ex);
+ if (rv == 1 && sdb->verbose < 2)
+ return 1;
+ BIO_puts(sdb->out, "Security callback: ");
+
+ switch (op)
+ {
+ case SSL_SECOP_CIPHER_SUPPORTED:
+ nm = "Supported Ciphersuite";
+ break;
+ case SSL_SECOP_CIPHER_SHARED:
+ nm = "Shared Ciphersuite";
+ break;
+ case SSL_SECOP_CIPHER_CHECK:
+ nm = "Check Ciphersuite";
+ break;
+ case SSL_SECOP_TICKET:
+ BIO_puts(sdb->out, "Session ticket");
+ show_bits = 0;
+ nm = NULL;
+ break;
+ case SSL_SECOP_COMPRESSION:
+ BIO_puts(sdb->out, "SSL compression");
+ show_bits = 0;
+ nm = NULL;
+ break;
+#ifndef OPENSSL_NO_DH
+ case SSL_SECOP_TMP_DH:
+ nm = "Temp DH key bits";
+ break;
+#endif
+ case SSL_SECOP_CURVE_SUPPORTED:
+ nm = "Supported Curve";
+ break;
+ case SSL_SECOP_CURVE_SHARED:
+ nm = "Shared Curve";
+ break;
+ case SSL_SECOP_CURVE_CHECK:
+ nm = "Check Curve";
+ break;
+ case SSL_SECOP_VERSION:
+ BIO_printf(sdb->out, "Version=%s", ssl_version_str(nid));
+ show_bits = 0;
+ nm = NULL;
+ break;
+ case SSL_SECOP_SIGALG_SUPPORTED:
+ nm = "Supported Signature Algorithm digest";
+ break;
+ case SSL_SECOP_SIGALG_SHARED:
+ nm = "Shared Signature Algorithm digest";
+ break;
+ case SSL_SECOP_SIGALG_CHECK:
+ nm = "Check Signature Algorithm digest";
+ break;
+ case SSL_SECOP_SIGALG_MASK:
+ nm = "Signature Algorithm mask";
+ break;
+ case SSL_SECOP_EE_KEY:
+ nm = "Certificate chain EE key";
+ break;
+ case SSL_SECOP_CA_KEY:
+ nm = "Certificate chain CA key";
+ break;
+ case SSL_SECOP_CA_MD:
+ cert_md = 1;
+ nm = "Certificate chain CA digest";
+ break;
+ case SSL_SECOP_PEER_EE_KEY:
+ nm = "Peer Chain EE key";
+ break;
+ case SSL_SECOP_PEER_CA_KEY:
+ nm = "Peer Chain CA key";
+ break;
+ case SSL_SECOP_PEER_CA_MD:
+ cert_md = 1;
+ nm = "Peer chain CA digest";
+ break;
+ default:
+ nm = NULL;
+ }
+ if (nm)
+ BIO_printf(sdb->out, "%s=", nm);
+
+ switch (op & SSL_SECOP_OTHER_TYPE)
+ {
+
+ case SSL_SECOP_OTHER_CIPHER:
+ BIO_puts(sdb->out, SSL_CIPHER_get_name(other));
+ break;
+
+ case SSL_SECOP_OTHER_CURVE:
+ {
+ const char *cname;
+ cname = EC_curve_nid2nist(nid);
+ if (cname == NULL)
+ cname = OBJ_nid2sn(nid);
+ BIO_puts(sdb->out, cname);
+ }
+ break;
+
+ case SSL_SECOP_OTHER_DH:
+ {
+ DH *dh = other;
+ BIO_printf(sdb->out, "%d", BN_num_bits(dh->p));
+ break;
+ }
+ case SSL_SECOP_OTHER_CERT:
+ {
+ if (cert_md)
+ {
+ int sig_nid = X509_get_signature_nid(other);
+ BIO_puts(sdb->out, OBJ_nid2sn(sig_nid));
+ }
+ else
+ {
+ EVP_PKEY *pkey = X509_get_pubkey(other);
+ const char *algname = "";
+ EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL,
+ &algname,
+ EVP_PKEY_get0_asn1(pkey));
+ BIO_printf(sdb->out, "%s, bits=%d",
+ algname, EVP_PKEY_bits(pkey));
+ EVP_PKEY_free(pkey);
+ }
+ break;
+ }
+ case SSL_SECOP_OTHER_SIGALG:
+ {
+ const unsigned char *salg = other;
+ const char *sname = NULL;
+ switch (salg[1])
+ {
+ case TLSEXT_signature_anonymous:
+ sname = "anonymous";
+ break;
+ case TLSEXT_signature_rsa:
+ sname = "RSA";
+ break;
+ case TLSEXT_signature_dsa:
+ sname = "DSA";
+ break;
+ case TLSEXT_signature_ecdsa:
+ sname = "ECDSA";
+ break;
+ }
+
+ BIO_puts(sdb->out, OBJ_nid2sn(nid));
+ if (sname)
+ BIO_printf(sdb->out, ", algorithm=%s", sname);
+ else
+ BIO_printf(sdb->out, ", algid=%d", salg[1]);
+ break;
+ }
+
+ }
+
+ if (show_bits)
+ BIO_printf(sdb->out, ", security bits=%d", bits);
+ BIO_printf(sdb->out, ": %s\n", rv ? "yes" : "no");
+ return rv;
+ }
+
+void ssl_ctx_security_debug(SSL_CTX *ctx, BIO *out, int verbose)
+ {
+ static security_debug_ex sdb;
+ sdb.out = out;
+ sdb.verbose = verbose;
+ sdb.old_cb = SSL_CTX_get_security_callback(ctx);
+ SSL_CTX_set_security_callback(ctx, security_callback_debug);
+ SSL_CTX_set0_security_ex_data(ctx, &sdb);
+ }
+
+
+