X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=apps%2Fs_cb.c;h=a463dac4ffb66c3f43d7552a215e7f3a81b65083;hp=a14e00cd33e73e7dd17936e2c13f95415561c8c2;hb=dba317774555fbd5bccdfc5270fc486e0d02d9db;hpb=3b061a00e39d2e4ad524ff01cbdc0c53fe8171ee diff --git a/apps/s_cb.c b/apps/s_cb.c index a14e00cd33..a463dac4ff 100644 --- a/apps/s_cb.c +++ b/apps/s_cb.c @@ -131,8 +131,8 @@ int verify_depth = 0; int verify_quiet = 0; int verify_error = X509_V_OK; int verify_return_error = 0; -unsigned char cookie_secret[COOKIE_SECRET_LENGTH]; -int cookie_initialized = 0; +static unsigned char cookie_secret[COOKIE_SECRET_LENGTH]; +static int cookie_initialized = 0; static const char *lookup(int val, const STRINT_PAIR* list, const char* def) { @@ -167,7 +167,7 @@ int verify_callback(int ok, X509_STORE_CTX *ctx) if (verify_depth >= depth) { if (!verify_return_error) ok = 1; - verify_error = X509_V_OK; + verify_error = err; } else { ok = 0; verify_error = X509_V_ERR_CERT_CHAIN_TOO_LONG; @@ -288,7 +288,6 @@ static STRINT_PAIR cert_type_list[] = { {"ECDSA sign", TLS_CT_ECDSA_SIGN}, {"RSA fixed ECDH", TLS_CT_RSA_FIXED_ECDH}, {"ECDSA fixed ECDH", TLS_CT_ECDSA_FIXED_ECDH}, - {"GOST94 Sign", TLS_CT_GOST94_SIGN}, {"GOST01 Sign", TLS_CT_GOST01_SIGN}, {NULL} }; @@ -597,6 +596,7 @@ static STRINT_PAIR handshakes[] = { {", ClientHello", 1}, {", ServerHello", 2}, {", HelloVerifyRequest", 3}, + {", NewSessionTicket", 4}, {", Certificate", 11}, {", ServerKeyExchange", 12}, {", CertificateRequest", 13}, @@ -604,6 +604,9 @@ static STRINT_PAIR handshakes[] = { {", CertificateVerify", 15}, {", ClientKeyExchange", 16}, {", Finished", 20}, + {", CertificateUrl", 21}, + {", CertificateStatus", 22}, + {", SupplementalData", 23}, {NULL} }; @@ -646,6 +649,9 @@ void msg_cb(int write_p, int version, int content_type, const void *buf, if (len > 0) str_details1 = lookup((int)bp[0], handshakes, "???"); break; + case 23: + str_content_type = "ApplicationData"; + break; #ifndef OPENSSL_NO_HEARTBEATS case 24: str_details1 = ", Heartbeat"; @@ -711,34 +717,36 @@ static STRINT_PAIR tlsext_types[] = { #endif #ifdef TLSEXT_TYPE_encrypt_then_mac {"encrypt-then-mac", TLSEXT_TYPE_encrypt_then_mac}, +#endif +#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation + {"application layer protocol negotiation", + TLSEXT_TYPE_application_layer_protocol_negotiation}, +#endif +#ifdef TLSEXT_TYPE_extended_master_secret + {"extended master secret", TLSEXT_TYPE_extended_master_secret}, #endif {NULL} }; void tlsext_cb(SSL *s, int client_server, int type, - unsigned char *data, int len, void *arg) + const unsigned char *data, int len, void *arg) { BIO *bio = arg; const char *extname = lookup(type, tlsext_types, "unknown"); BIO_printf(bio, "TLS %s extension \"%s\" (id=%d), len=%d\n", client_server ? "server" : "client", extname, type, len); - BIO_dump(bio, (char *)data, len); + BIO_dump(bio, (const char *)data, len); (void)BIO_flush(bio); } int generate_cookie_callback(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len) { - unsigned char *buffer, result[EVP_MAX_MD_SIZE]; - unsigned int length, resultlength; - union { - struct sockaddr sa; - struct sockaddr_in s4; -#if OPENSSL_USE_IPV6 - struct sockaddr_in6 s6; -#endif - } peer; + unsigned char *buffer; + size_t length; + unsigned short port; + BIO_ADDR *peer = NULL; /* Initialize a random secret */ if (!cookie_initialized) { @@ -749,120 +757,46 @@ int generate_cookie_callback(SSL *ssl, unsigned char *cookie, cookie_initialized = 1; } + peer = BIO_ADDR_new(); + if (peer == NULL) { + BIO_printf(bio_err, "memory full\n"); + return 0; + } + /* Read peer information */ - (void)BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer); + (void)BIO_dgram_get_peer(SSL_get_rbio(ssl), peer); /* Create buffer with peer's address and port */ - length = 0; - switch (peer.sa.sa_family) { - case AF_INET: - length += sizeof(struct in_addr); - length += sizeof(peer.s4.sin_port); - break; -#if OPENSSL_USE_IPV6 - case AF_INET6: - length += sizeof(struct in6_addr); - length += sizeof(peer.s6.sin6_port); - break; -#endif - default: - OPENSSL_assert(0); - break; - } + BIO_ADDR_rawaddress(peer, NULL, &length); + OPENSSL_assert(length != 0); + port = BIO_ADDR_rawport(peer); + length += sizeof(port); buffer = app_malloc(length, "cookie generate buffer"); - switch (peer.sa.sa_family) { - case AF_INET: - memcpy(buffer, &peer.s4.sin_port, sizeof(peer.s4.sin_port)); - memcpy(buffer + sizeof(peer.s4.sin_port), - &peer.s4.sin_addr, sizeof(struct in_addr)); - break; -#if OPENSSL_USE_IPV6 - case AF_INET6: - memcpy(buffer, &peer.s6.sin6_port, sizeof(peer.s6.sin6_port)); - memcpy(buffer + sizeof(peer.s6.sin6_port), - &peer.s6.sin6_addr, sizeof(struct in6_addr)); - break; -#endif - default: - OPENSSL_assert(0); - break; - } + memcpy(buffer, &port, sizeof(port)); + BIO_ADDR_rawaddress(peer, buffer + sizeof(port), NULL); /* Calculate HMAC of buffer using the secret */ HMAC(EVP_sha1(), cookie_secret, COOKIE_SECRET_LENGTH, - buffer, length, result, &resultlength); - OPENSSL_free(buffer); + buffer, length, cookie, cookie_len); - memcpy(cookie, result, resultlength); - *cookie_len = resultlength; + OPENSSL_free(buffer); + BIO_ADDR_free(peer); return 1; } -int verify_cookie_callback(SSL *ssl, unsigned char *cookie, +int verify_cookie_callback(SSL *ssl, const unsigned char *cookie, unsigned int cookie_len) { - unsigned char *buffer, result[EVP_MAX_MD_SIZE]; - unsigned int length, resultlength; - union { - struct sockaddr sa; - struct sockaddr_in s4; -#if OPENSSL_USE_IPV6 - struct sockaddr_in6 s6; -#endif - } peer; - - /* If secret isn't initialized yet, the cookie can't be valid */ - if (!cookie_initialized) - return 0; - - /* Read peer information */ - (void)BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer); - - /* Create buffer with peer's address and port */ - length = 0; - switch (peer.sa.sa_family) { - case AF_INET: - length += sizeof(struct in_addr); - length += sizeof(peer.s4.sin_port); - break; -#if OPENSSL_USE_IPV6 - case AF_INET6: - length += sizeof(struct in6_addr); - length += sizeof(peer.s6.sin6_port); - break; -#endif - default: - OPENSSL_assert(0); - break; - } - buffer = app_malloc(length, "cookie verify buffer"); - - switch (peer.sa.sa_family) { - case AF_INET: - memcpy(buffer, &peer.s4.sin_port, sizeof(peer.s4.sin_port)); - memcpy(buffer + sizeof(peer.s4.sin_port), - &peer.s4.sin_addr, sizeof(struct in_addr)); - break; -#if OPENSSL_USE_IPV6 - case AF_INET6: - memcpy(buffer, &peer.s6.sin6_port, sizeof(peer.s6.sin6_port)); - memcpy(buffer + sizeof(peer.s6.sin6_port), - &peer.s6.sin6_addr, sizeof(struct in6_addr)); - break; -#endif - default: - OPENSSL_assert(0); - break; - } - - /* Calculate HMAC of buffer using the secret */ - HMAC(EVP_sha1(), cookie_secret, COOKIE_SECRET_LENGTH, - buffer, length, result, &resultlength); - OPENSSL_free(buffer); - - if (cookie_len == resultlength + unsigned char result[EVP_MAX_MD_SIZE]; + unsigned int resultlength; + + /* Note: we check cookie_initialized because if it's not, + * it cannot be valid */ + if (cookie_initialized + && generate_cookie_callback(ssl, result, &resultlength) + && cookie_len == resultlength && memcmp(result, cookie, resultlength) == 0) return 1; @@ -897,7 +831,7 @@ static STRINT_PAIR chain_flags[] = { {"CA signature", CERT_PKEY_CA_SIGNATURE}, {"EE key parameters", CERT_PKEY_EE_PARAM}, {"CA key parameters", CERT_PKEY_CA_PARAM}, - {"Explicity sign with EE key", CERT_PKEY_EXPLICIT_SIGN}, + {"Explicitly sign with EE key", CERT_PKEY_EXPLICIT_SIGN}, {"Issuer Name", CERT_PKEY_ISSUER_NAME}, {"Certificate Type", CERT_PKEY_CERT_TYPE}, {NULL} @@ -988,14 +922,7 @@ static int ssl_excert_prepend(SSL_EXCERT **pexc) { SSL_EXCERT *exc = app_malloc(sizeof(*exc), "prepend cert"); - exc->certfile = NULL; - exc->keyfile = NULL; - exc->chainfile = NULL; - exc->cert = NULL; - exc->key = NULL; - exc->chain = NULL; - exc->prev = NULL; - exc->build_chain = 0; + memset(exc, 0, sizeof(*exc)); exc->next = *pexc; *pexc = exc; @@ -1058,9 +985,8 @@ int load_excert(SSL_EXCERT **pexc) if (!exc->key) return 0; if (exc->chainfile) { - exc->chain = load_certs(exc->chainfile, FORMAT_PEM, - NULL, NULL, "Server Chain"); - if (!exc->chain) + if (!load_certs(exc->chainfile, &exc->chain, FORMAT_PEM, NULL, + NULL, "Server Chain")) return 0; } } @@ -1160,6 +1086,80 @@ static void print_raw_cipherlist(SSL *s) BIO_puts(bio_err, "\n"); } +/* + * Hex encoder for TLSA RRdata, not ':' delimited. + */ +static char *hexencode(const unsigned char *data, size_t len) +{ + static const char *hex = "0123456789abcdef"; + char *out; + char *cp; + size_t outlen = 2 * len + 1; + int ilen = (int) outlen; + + if (outlen < len || ilen < 0 || outlen != (size_t)ilen) { + BIO_printf(bio_err, "%s: %" PRIu64 "-byte buffer too large to hexencode\n", + opt_getprog(), (uint64_t)len); + exit(1); + } + cp = out = app_malloc(ilen, "TLSA hex data buffer"); + + while (ilen-- > 0) { + *cp++ = hex[(*data >> 4) & 0x0f]; + *cp++ = hex[*data++ & 0x0f]; + } + *cp = '\0'; + return out; +} + +void print_verify_detail(SSL *s, BIO *bio) +{ + int mdpth; + EVP_PKEY *mspki; + long verify_err = SSL_get_verify_result(s); + + if (verify_err == X509_V_OK) { + const char *peername = SSL_get0_peername(s); + + BIO_printf(bio, "Verification: OK\n"); + if (peername != NULL) + BIO_printf(bio, "Verified peername: %s\n", peername); + } else { + const char *reason = X509_verify_cert_error_string(verify_err); + + BIO_printf(bio, "Verification error: %s\n", reason); + } + + if ((mdpth = SSL_get0_dane_authority(s, NULL, &mspki)) >= 0) { + uint8_t usage, selector, mtype; + const unsigned char *data = NULL; + size_t dlen = 0; + char *hexdata; + + mdpth = SSL_get0_dane_tlsa(s, &usage, &selector, &mtype, &data, &dlen); + + /* + * The TLSA data field can be quite long when it is a certificate, + * public key or even a SHA2-512 digest. Because the initial octets of + * ASN.1 certificates and public keys contain mostly boilerplate OIDs + * and lengths, we show the last 12 bytes of the data instead, as these + * are more likely to distinguish distinct TLSA records. + */ +#define TLSA_TAIL_SIZE 12 + if (dlen > TLSA_TAIL_SIZE) + hexdata = hexencode(data + dlen - TLSA_TAIL_SIZE, TLSA_TAIL_SIZE); + else + hexdata = hexencode(data, dlen); + BIO_printf(bio, "DANE TLSA %d %d %d %s%s %s at depth %d\n", + usage, selector, mtype, + (dlen > TLSA_TAIL_SIZE) ? "..." : "", hexdata, + (mspki != NULL) ? "signed the certificate" : + mdpth ? "matched TA certificate" : "matched EE certificate", + mdpth); + OPENSSL_free(hexdata); + } +} + void print_ssl_summary(SSL *s) { const SSL_CIPHER *c; @@ -1174,12 +1174,14 @@ void print_ssl_summary(SSL *s) peer = SSL_get_peer_certificate(s); if (peer) { int nid; + BIO_puts(bio_err, "Peer certificate: "); X509_NAME_print_ex(bio_err, X509_get_subject_name(peer), 0, XN_FLAG_ONELINE); BIO_puts(bio_err, "\n"); if (SSL_get_peer_signature_nid(s, &nid)) BIO_printf(bio_err, "Hash used: %s\n", OBJ_nid2sn(nid)); + print_verify_detail(s, bio_err); } else BIO_puts(bio_err, "No peer certificate\n"); X509_free(peer); @@ -1196,7 +1198,7 @@ void print_ssl_summary(SSL *s) } int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str, - SSL_CTX *ctx, int no_ecdhe, int no_jpake) + SSL_CTX *ctx) { int i; @@ -1204,15 +1206,6 @@ int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str, for (i = 0; i < sk_OPENSSL_STRING_num(str); i += 2) { const char *flag = sk_OPENSSL_STRING_value(str, i); const char *arg = sk_OPENSSL_STRING_value(str, i + 1); - /* If no_ecdhe or named curve already specified don't need a default. */ - if (!no_ecdhe && strcmp(flag, "-named_curve") == 0) - no_ecdhe = 1; -#ifndef OPENSSL_NO_JPAKE - if (!no_jpake && (strcmp(flag, "-cipher") == 0)) { - BIO_puts(bio_err, "JPAKE sets cipher to PSK\n"); - return 0; - } -#endif if (SSL_CONF_cmd(cctx, flag, arg) <= 0) { if (arg) BIO_printf(bio_err, "Error with command: \"%s %s\"\n", @@ -1223,27 +1216,6 @@ int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str, return 0; } } - /* - * This is a special case to keep existing s_server functionality: if we - * don't have any curve specified *and* we haven't disabled ECDHE then - * use P-256. - */ - if (!no_ecdhe) { - if (SSL_CONF_cmd(cctx, "-named_curve", "P-256") <= 0) { - BIO_puts(bio_err, "Error setting EC curve\n"); - ERR_print_errors(bio_err); - return 0; - } - } -#ifndef OPENSSL_NO_JPAKE - if (!no_jpake) { - if (SSL_CONF_cmd(cctx, "-cipher", "PSK") <= 0) { - BIO_puts(bio_err, "Error setting cipher to PSK\n"); - ERR_print_errors(bio_err); - return 0; - } - } -#endif if (!SSL_CONF_CTX_finish(cctx)) { BIO_puts(bio_err, "Error finishing context\n"); ERR_print_errors(bio_err); @@ -1280,8 +1252,10 @@ int ssl_load_stores(SSL_CTX *ctx, { X509_STORE *vfy = NULL, *ch = NULL; int rv = 0; - if (vfyCApath || vfyCAfile) { + if (vfyCApath != NULL || vfyCAfile != NULL) { vfy = X509_STORE_new(); + if (vfy == NULL) + goto err; if (!X509_STORE_load_locations(vfy, vfyCAfile, vfyCApath)) goto err; add_crls_store(vfy, crls); @@ -1289,8 +1263,10 @@ int ssl_load_stores(SSL_CTX *ctx, if (crl_download) store_setup_crl_download(vfy); } - if (chCApath || chCAfile) { + if (chCApath != NULL || chCAfile != NULL) { ch = X509_STORE_new(); + if (ch == NULL) + goto err; if (!X509_STORE_load_locations(ch, chCAfile, chCApath)) goto err; SSL_CTX_set1_chain_cert_store(ctx, ch); @@ -1385,26 +1361,26 @@ static int security_callback_debug(SSL *s, SSL_CTX *ctx, } break; #endif - +#ifndef OPENSSL_NO_DH case SSL_SECOP_OTHER_DH: { DH *dh = other; BIO_printf(sdb->out, "%d", BN_num_bits(dh->p)); break; } +#endif 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); + EVP_PKEY *pkey = X509_get0_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; }