# ifndef OPENSSL_NO_NEXTPROTONEG
s->next_proto_negotiated = NULL;
# endif
+
+ if (s->ctx->alpn_client_proto_list)
+ {
+ s->alpn_client_proto_list =
+ OPENSSL_malloc(s->ctx->alpn_client_proto_list_len);
+ if (s->alpn_client_proto_list == NULL)
+ goto err;
+ memcpy(s->alpn_client_proto_list, s->ctx->alpn_client_proto_list,
+ s->ctx->alpn_client_proto_list_len);
+ s->alpn_client_proto_list_len = s->ctx->alpn_client_proto_list_len;
+ }
#endif
s->verify_result=X509_V_OK;
return X509_VERIFY_PARAM_set1(ssl->param, vpm);
}
+X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx)
+ {
+ return ctx->param;
+ }
+
+X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl)
+ {
+ return ssl->param;
+ }
+
void SSL_certs_clear(SSL *s)
{
ssl_cert_clear_certs(s->cert);
sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids, OCSP_RESPID_free);
if (s->tlsext_ocsp_resp)
OPENSSL_free(s->tlsext_ocsp_resp);
+ if (s->alpn_client_proto_list)
+ OPENSSL_free(s->alpn_client_proto_list);
#endif
if (s->client_CA != NULL)
return 0;
#endif
- if (SSL_version(s) == DTLS1_VERSION ||
- SSL_version(s) == DTLS1_BAD_VER)
+ if (SSL_IS_DTLS(s))
{
s->d1->mtu = larg;
return larg;
return(s->cert->cert_flags|=larg);
case SSL_CTRL_CLEAR_CERT_FLAGS:
return(s->cert->cert_flags &=~larg);
+
+ case SSL_CTRL_GET_RAW_CIPHERLIST:
+ if (parg)
+ {
+ if (s->cert->ciphers_raw == NULL)
+ return 0;
+ *(unsigned char **)parg = s->cert->ciphers_raw;
+ return (int)s->cert->ciphers_rawlen;
+ }
+ else
+ return ssl_put_cipher_by_char(s,NULL,NULL);
default:
return(s->method->ssl_ctrl(s,cmd,larg,parg));
}
long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd,long larg,void *parg)
{
long l;
+ /* For some cases with ctx == NULL perform syntax checks */
+ if (ctx == NULL)
+ {
+ switch (cmd)
+ {
+#ifndef OPENSSL_NO_EC
+ case SSL_CTRL_SET_CURVES_LIST:
+ return tls1_set_curves_list(NULL, NULL, parg);
+#endif
+ case SSL_CTRL_SET_SIGALGS_LIST:
+ case SSL_CTRL_SET_CLIENT_SIGALGS_LIST:
+ return tls1_set_sigalgs_list(NULL, parg, 0);
+ default:
+ return 0;
+ }
+ }
switch (cmd)
{
p=buf;
sk=s->session->ciphers;
+
+ if (sk_SSL_CIPHER_num(sk) == 0)
+ return NULL;
+
for (i=0; i<sk_SSL_CIPHER_num(sk); i++)
{
int n;
SSL_CIPHER *c;
CERT *ct = s->cert;
unsigned char *q;
+ int no_scsv = s->renegotiate;
/* Set disabled masks for this session */
ssl_set_client_disabled(s);
c->algorithm_mkey & ct->mask_k ||
c->algorithm_auth & ct->mask_a)
continue;
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+ if (c->id == SSL3_CK_SCSV)
+ {
+ if (no_scsv)
+ continue;
+ else
+ no_scsv = 1;
+ }
+#endif
j = put_cb ? put_cb(c,p) : ssl_put_cipher_by_char(s,c,p);
p+=j;
}
/* If p == q, no ciphers and caller indicates an error. Otherwise
* add SCSV if not renegotiating.
*/
- if (p != q && !s->renegotiate)
+ if (p != q && !no_scsv)
{
static SSL_CIPHER scsv =
{
sk_SSL_CIPHER_zero(sk);
}
+ if (s->cert->ciphers_raw)
+ OPENSSL_free(s->cert->ciphers_raw);
+ s->cert->ciphers_raw = BUF_memdup(p, num);
+ if (s->cert->ciphers_raw == NULL)
+ {
+ SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ s->cert->ciphers_rawlen = (size_t)num;
+
for (i=0; i<num; i+=n)
{
/* Check for SCSV */
return -1;
}
-# ifndef OPENSSL_NO_NEXTPROTONEG
/* SSL_select_next_proto implements the standard protocol selection. It is
* expected that this function is called from the callback set by
* SSL_CTX_set_next_proto_select_cb.
return status;
}
+# ifndef OPENSSL_NO_NEXTPROTONEG
/* SSL_get0_next_proto_negotiated sets *data and *len to point to the client's
* requested protocol for this connection and returns 0. If the client didn't
* request any protocol, then *data is set to NULL.
ctx->next_proto_select_cb_arg = arg;
}
# endif
-#endif
+
+int SSL_CTX_set_custom_cli_ext(SSL_CTX *ctx, unsigned short ext_type,
+ custom_cli_ext_first_cb_fn fn1,
+ custom_cli_ext_second_cb_fn fn2, void* arg)
+ {
+ size_t i;
+ custom_cli_ext_record* record;
+
+ /* Check for duplicates */
+ for (i=0; i < ctx->custom_cli_ext_records_count; i++)
+ if (ext_type == ctx->custom_cli_ext_records[i].ext_type)
+ return 0;
+
+ ctx->custom_cli_ext_records = OPENSSL_realloc(ctx->custom_cli_ext_records,
+ (ctx->custom_cli_ext_records_count + 1) *
+ sizeof(custom_cli_ext_record));
+ if (!ctx->custom_cli_ext_records) {
+ ctx->custom_cli_ext_records_count = 0;
+ return 0;
+ }
+ ctx->custom_cli_ext_records_count++;
+ record = &ctx->custom_cli_ext_records[ctx->custom_cli_ext_records_count - 1];
+ record->ext_type = ext_type;
+ record->fn1 = fn1;
+ record->fn2 = fn2;
+ record->arg = arg;
+ return 1;
+ }
+
+int SSL_CTX_set_custom_srv_ext(SSL_CTX *ctx, unsigned short ext_type,
+ custom_srv_ext_first_cb_fn fn1,
+ custom_srv_ext_second_cb_fn fn2, void* arg)
+ {
+ size_t i;
+ custom_srv_ext_record* record;
+
+ /* Check for duplicates */
+ for (i=0; i < ctx->custom_srv_ext_records_count; i++)
+ if (ext_type == ctx->custom_srv_ext_records[i].ext_type)
+ return 0;
+
+ ctx->custom_srv_ext_records = OPENSSL_realloc(ctx->custom_srv_ext_records,
+ (ctx->custom_srv_ext_records_count + 1) *
+ sizeof(custom_srv_ext_record));
+ if (!ctx->custom_srv_ext_records) {
+ ctx->custom_srv_ext_records_count = 0;
+ return 0;
+ }
+ ctx->custom_srv_ext_records_count++;
+ record = &ctx->custom_srv_ext_records[ctx->custom_srv_ext_records_count - 1];
+ record->ext_type = ext_type;
+ record->fn1 = fn1;
+ record->fn2 = fn2;
+ record->arg = arg;
+ return 1;
+ }
+
+/* SSL_CTX_set_alpn_protos sets the ALPN protocol list on |ctx| to |protos|.
+ * |protos| must be in wire-format (i.e. a series of non-empty, 8-bit
+ * length-prefixed strings).
+ *
+ * Returns 0 on success. */
+int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char* protos,
+ unsigned protos_len)
+ {
+ if (ctx->alpn_client_proto_list)
+ OPENSSL_free(ctx->alpn_client_proto_list);
+
+ ctx->alpn_client_proto_list = OPENSSL_malloc(protos_len);
+ if (!ctx->alpn_client_proto_list)
+ return 1;
+ memcpy(ctx->alpn_client_proto_list, protos, protos_len);
+ ctx->alpn_client_proto_list_len = protos_len;
+
+ return 0;
+ }
+
+/* SSL_set_alpn_protos sets the ALPN protocol list on |ssl| to |protos|.
+ * |protos| must be in wire-format (i.e. a series of non-empty, 8-bit
+ * length-prefixed strings).
+ *
+ * Returns 0 on success. */
+int SSL_set_alpn_protos(SSL *ssl, const unsigned char* protos,
+ unsigned protos_len)
+ {
+ if (ssl->alpn_client_proto_list)
+ OPENSSL_free(ssl->alpn_client_proto_list);
+
+ ssl->alpn_client_proto_list = OPENSSL_malloc(protos_len);
+ if (!ssl->alpn_client_proto_list)
+ return 1;
+ memcpy(ssl->alpn_client_proto_list, protos, protos_len);
+ ssl->alpn_client_proto_list_len = protos_len;
+
+ return 0;
+ }
+
+/* SSL_CTX_set_alpn_select_cb sets a callback function on |ctx| that is called
+ * during ClientHello processing in order to select an ALPN protocol from the
+ * client's list of offered protocols. */
+void SSL_CTX_set_alpn_select_cb(SSL_CTX* ctx,
+ int (*cb) (SSL *ssl,
+ const unsigned char **out,
+ unsigned char *outlen,
+ const unsigned char *in,
+ unsigned int inlen,
+ void *arg),
+ void *arg)
+ {
+ ctx->alpn_select_cb = cb;
+ ctx->alpn_select_cb_arg = arg;
+ }
+
+/* SSL_get0_alpn_selected gets the selected ALPN protocol (if any) from |ssl|.
+ * On return it sets |*data| to point to |*len| bytes of protocol name (not
+ * including the leading length-prefix byte). If the server didn't respond with
+ * a negotiated protocol then |*len| will be zero. */
+void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data,
+ unsigned *len)
+ {
+ *data = NULL;
+ if (ssl->s3)
+ *data = ssl->s3->alpn_selected;
+ if (*data == NULL)
+ *len = 0;
+ else
+ *len = ssl->s3->alpn_selected_len;
+ }
+
+#endif /* !OPENSSL_NO_TLSEXT */
int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen,
const char *label, size_t llen, const unsigned char *p, size_t plen,
CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_CTX, ret, &ret->ex_data);
ret->extra_certs=NULL;
- ret->comp_methods=SSL_COMP_get_compression_methods();
+ /* No compression for DTLS */
+ if (meth->version != DTLS1_VERSION)
+ ret->comp_methods=SSL_COMP_get_compression_methods();
ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH;
#ifndef OPENSSL_NO_SRP
SSL_CTX_SRP_CTX_init(ret);
#endif
+ ret->custom_cli_ext_records = NULL;
+ ret->custom_cli_ext_records_count = 0;
+ ret->custom_srv_ext_records = NULL;
+ ret->custom_srv_ext_records_count = 0;
#ifndef OPENSSL_NO_BUF_FREELISTS
ret->freelist_max_len = SSL_MAX_BUF_FREELIST_LEN_DEFAULT;
ret->rbuf_freelist = OPENSSL_malloc(sizeof(SSL3_BUF_FREELIST));
#ifndef OPENSSL_NO_SRP
SSL_CTX_SRP_CTX_free(a);
#endif
+#ifndef OPENSSL_NO_TLSEXT
+ OPENSSL_free(a->custom_cli_ext_records);
+ OPENSSL_free(a->custom_srv_ext_records);
+#endif
#ifndef OPENSSL_NO_ENGINE
if (a->client_cert_engine)
ENGINE_finish(a->client_cert_engine);
if (a->tlsext_ellipticcurvelist)
OPENSSL_free(a->tlsext_ellipticcurvelist);
# endif /* OPENSSL_NO_EC */
+ if (a->alpn_client_proto_list != NULL)
+ OPENSSL_free(a->alpn_client_proto_list);
#endif
OPENSSL_free(a);
int rsa_enc_export,dh_rsa_export,dh_dsa_export;
int rsa_tmp_export,dh_tmp_export,kl;
unsigned long mask_k,mask_a,emask_k,emask_a;
- int have_ecc_cert, ecdh_ok, ecdsa_ok, ecc_pkey_size;
+#ifndef OPENSSL_NO_ECDSA
+ int have_ecc_cert, ecdsa_ok, ecc_pkey_size;
+#endif
#ifndef OPENSSL_NO_ECDH
- int have_ecdh_tmp;
+ int have_ecdh_tmp, ecdh_ok;
#endif
+#ifndef OPENSSL_NO_EC
X509 *x = NULL;
EVP_PKEY *ecc_pkey = NULL;
int signature_nid = 0, pk_nid = 0, md_nid = 0;
-
+#endif
if (c == NULL) return;
kl=SSL_C_EXPORT_PKEYLENGTH(cipher);
dh_dsa= cpk->valid_flags & CERT_PKEY_VALID;
dh_dsa_export=(dh_dsa && EVP_PKEY_size(cpk->privatekey)*8 <= kl);
cpk= &(c->pkeys[SSL_PKEY_ECC]);
+#ifndef OPENSSL_NO_EC
have_ecc_cert= cpk->valid_flags & CERT_PKEY_VALID;
+#endif
mask_k=0;
mask_a=0;
emask_k=0;
/* An ECC certificate may be usable for ECDH and/or
* ECDSA cipher suites depending on the key usage extension.
*/
+#ifndef OPENSSL_NO_EC
if (have_ecc_cert)
{
cpk = &c->pkeys[SSL_PKEY_ECC];
}
#endif
}
+#endif
#ifndef OPENSSL_NO_ECDH
if (have_ecdh_tmp)
#endif
-/* THIS NEEDS CLEANING UP */
static int ssl_get_server_cert_index(const SSL *s)
{
- unsigned long alg_k, alg_a;
-
- alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
- alg_a = s->s3->tmp.new_cipher->algorithm_auth;
-
- if (alg_k & (SSL_kECDHr|SSL_kECDHe))
- {
- /* we don't need to look at SSL_kEECDH
- * since no certificate is needed for
- * anon ECDH and for authenticated
- * EECDH, the check for the auth
- * algorithm will set i correctly
- * NOTE: For ECDH-RSA, we need an ECC
- * not an RSA cert but for EECDH-RSA
- * we need an RSA cert. Placing the
- * checks for SSL_kECDH before RSA
- * checks ensures the correct cert is chosen.
- */
- return SSL_PKEY_ECC;
- }
- else if (alg_a & SSL_aECDSA)
- return SSL_PKEY_ECC;
- else if (alg_k & SSL_kDHr)
- return SSL_PKEY_DH_RSA;
- else if (alg_k & SSL_kDHd)
- return SSL_PKEY_DH_DSA;
- else if (alg_a & SSL_aDSS)
- return SSL_PKEY_DSA_SIGN;
- else if (alg_a & SSL_aRSA)
- {
- if (s->cert->pkeys[SSL_PKEY_RSA_ENC].x509 == NULL)
- return SSL_PKEY_RSA_SIGN;
- else
- return SSL_PKEY_RSA_ENC;
- }
- else if (alg_a & SSL_aKRB5)
- /* VRS something else here? */
- return -1;
- else if (alg_a & SSL_aGOST94)
- return SSL_PKEY_GOST94;
- else if (alg_a & SSL_aGOST01)
- return SSL_PKEY_GOST01;
- else /* if (alg_a & SSL_aNULL) */
- {
+ int idx;
+ idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
+ if (idx == SSL_PKEY_RSA_ENC && !s->cert->pkeys[SSL_PKEY_RSA_ENC].x509)
+ idx = SSL_PKEY_RSA_SIGN;
+ if (idx == -1)
SSLerr(SSL_F_SSL_GET_SERVER_CERT_INDEX,ERR_R_INTERNAL_ERROR);
- return -1;
- }
+ return idx;
}
CERT_PKEY *ssl_get_server_send_pkey(const SSL *s)
int i;
c = s->cert;
+ if (!s->s3 || !s->s3->tmp.new_cipher)
+ return NULL;
ssl_set_cert_masks(c, s->s3->tmp.new_cipher);
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+ /* Broken protocol test: return last used certificate: which may
+ * mismatch the one expected.
+ */
+ if (c->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL)
+ return c->key;
+#endif
+
i = ssl_get_server_cert_index(s);
/* This may or may not be an error. */
alg_a = cipher->algorithm_auth;
c=s->cert;
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+ /* Broken protocol test: use last key: which may
+ * mismatch the one expected.
+ */
+ if (c->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL)
+ idx = c->key - c->pkeys;
+ else
+#endif
+
if ((alg_a & SSL_aDSS) &&
(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
idx = SSL_PKEY_DSA_SIGN;
}
#ifndef OPENSSL_NO_TLSEXT
-unsigned char *ssl_get_authz_data(SSL *s, size_t *authz_length)
+int ssl_get_server_cert_serverinfo(SSL *s, const unsigned char **serverinfo,
+ size_t *serverinfo_length)
{
- CERT *c;
- int i;
+ CERT *c = NULL;
+ int i = 0;
+ *serverinfo_length = 0;
c = s->cert;
i = ssl_get_server_cert_index(s);
if (i == -1)
- return NULL;
-
- *authz_length = 0;
- if (c->pkeys[i].authz == NULL)
- return(NULL);
- *authz_length = c->pkeys[i].authz_length;
+ return 0;
+ if (c->pkeys[i].serverinfo == NULL)
+ return 0;
- return c->pkeys[i].authz;
+ *serverinfo = c->pkeys[i].serverinfo;
+ *serverinfo_length = c->pkeys[i].serverinfo_length;
+ return 1;
}
#endif
}
}
+const SSL_METHOD *SSL_CTX_get_ssl_method(SSL_CTX *ctx)
+ {
+ return ctx->method;
+ }
+
const SSL_METHOD *SSL_get_ssl_method(SSL *s)
{
return(s->method);
#endif
}
-/* Fix this function so that it takes an optional type parameter */
X509 *SSL_get_certificate(const SSL *s)
{
if (s->cert != NULL)
return(NULL);
}
-/* Fix this function so that it takes an optional type parameter */
-EVP_PKEY *SSL_get_privatekey(SSL *s)
+EVP_PKEY *SSL_get_privatekey(const SSL *s)
{
if (s->cert != NULL)
return(s->cert->key->privatekey);
return(NULL);
}
+X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx)
+ {
+ if (ctx->cert != NULL)
+ return ctx->cert->key->x509;
+ else
+ return NULL;
+ }
+
+EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx)
+ {
+ if (ctx->cert != NULL)
+ return ctx->cert->key->privatekey;
+ else
+ return NULL ;
+ }
+
const SSL_CIPHER *SSL_get_current_cipher(const SSL *s)
{
if ((s->session != NULL) && (s->session->cipher != NULL))