示例#1
0
static int pkey_dh_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
{
    DH_PKEY_CTX *dctx, *sctx;
    if (!pkey_dh_init(dst))
        return 0;
    sctx = src->data;
    dctx = dst->data;
    dctx->prime_len = sctx->prime_len;
    dctx->subprime_len = sctx->subprime_len;
    dctx->generator = sctx->generator;
    dctx->use_dsa = sctx->use_dsa;
    dctx->md = sctx->md;
    dctx->rfc5114_param = sctx->rfc5114_param;

    dctx->kdf_type = sctx->kdf_type;
    dctx->kdf_oid = OBJ_dup(sctx->kdf_oid);
    if (!dctx->kdf_oid)
        return 0;
    dctx->kdf_md = sctx->kdf_md;
    if (dctx->kdf_ukm) {
        dctx->kdf_ukm = BUF_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen);
        dctx->kdf_ukmlen = sctx->kdf_ukmlen;
    }
    dctx->kdf_outlen = sctx->kdf_outlen;
    return 1;
}
示例#2
0
文件: dh.c 项目: ro-ot/boringssl
static int int_dh_param_copy(DH *to, const DH *from, int is_x942) {
  if (is_x942 == -1) {
    is_x942 = !!from->q;
  }
  if (!int_dh_bn_cpy(&to->p, from->p) ||
      !int_dh_bn_cpy(&to->g, from->g)) {
    return 0;
  }

  if (!is_x942) {
    return 1;
  }

  if (!int_dh_bn_cpy(&to->q, from->q) ||
      !int_dh_bn_cpy(&to->j, from->j)) {
    return 0;
  }

  OPENSSL_free(to->seed);
  to->seed = NULL;
  to->seedlen = 0;

  if (from->seed) {
    to->seed = BUF_memdup(from->seed, from->seedlen);
    if (!to->seed) {
      return 0;
    }
    to->seedlen = from->seedlen;
  }

  return 1;
}
示例#3
0
static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
{
    EC_PKEY_CTX *dctx, *sctx;
    if (!pkey_ec_init(dst))
        return 0;
    sctx = src->data;
    dctx = dst->data;
    if (sctx->gen_group) {
        dctx->gen_group = EC_GROUP_dup(sctx->gen_group);
        if (!dctx->gen_group)
            return 0;
    }
    dctx->md = sctx->md;

    if (sctx->co_key) {
        dctx->co_key = EC_KEY_dup(sctx->co_key);
        if (!dctx->co_key)
            return 0;
    }
    dctx->kdf_type = sctx->kdf_type;
    dctx->kdf_md = sctx->kdf_md;
    dctx->kdf_outlen = sctx->kdf_outlen;
    if (sctx->kdf_ukm) {
        dctx->kdf_ukm = BUF_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen);
        if (!dctx->kdf_ukm)
            return 0;
    } else
        dctx->kdf_ukm = NULL;
    dctx->kdf_ukmlen = sctx->kdf_ukmlen;
    return 1;
}
示例#4
0
文件: rsa_pmeth.c 项目: 5y/node
static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
{
    RSA_PKEY_CTX *dctx, *sctx;
    if (!pkey_rsa_init(dst))
        return 0;
    sctx = src->data;
    dctx = dst->data;
    dctx->nbits = sctx->nbits;
    if (sctx->pub_exp) {
        dctx->pub_exp = BN_dup(sctx->pub_exp);
        if (!dctx->pub_exp)
            return 0;
    }
    dctx->pad_mode = sctx->pad_mode;
    dctx->md = sctx->md;
    dctx->mgf1md = sctx->mgf1md;
    if (sctx->oaep_label) {
        if (dctx->oaep_label)
            OPENSSL_free(dctx->oaep_label);
        dctx->oaep_label = BUF_memdup(sctx->oaep_label, sctx->oaep_labellen);
        if (!dctx->oaep_label)
            return 0;
        dctx->oaep_labellen = sctx->oaep_labellen;
    }
    return 1;
}
示例#5
0
static int int_x509_param_set1(unsigned char **pdest, size_t *pdestlen,
				const unsigned char *src, size_t srclen)
	{
	void *tmp;
	if (src)
		{
		if (srclen == 0)
			{
			tmp = BUF_strdup((char *)src);
			srclen = strlen((char *)src);
			}
		else
			tmp = BUF_memdup(src, srclen);
		if (!tmp)
			return 0;
		}
	else
		{
		tmp = NULL;
		srclen = 0;
		}
	if (*pdest)
		OPENSSL_free(*pdest);
	*pdest = tmp;
	if (pdestlen)
		*pdestlen = srclen;
	return 1;
	}
示例#6
0
文件: dh_ameth.c 项目: Orav/kbengine
static int int_dh_param_copy(DH *to, const DH *from, int is_x942)
{
    if (is_x942 == -1)
        is_x942 = ! !from->q;
    if (!int_dh_bn_cpy(&to->p, from->p))
        return 0;
    if (!int_dh_bn_cpy(&to->g, from->g))
        return 0;
    if (is_x942) {
        if (!int_dh_bn_cpy(&to->q, from->q))
            return 0;
        if (!int_dh_bn_cpy(&to->j, from->j))
            return 0;
        if (to->seed) {
            OPENSSL_free(to->seed);
            to->seed = NULL;
            to->seedlen = 0;
        }
        if (from->seed) {
            to->seed = BUF_memdup(from->seed, from->seedlen);
            if (!to->seed)
                return 0;
            to->seedlen = from->seedlen;
        }
    } else
        to->length = from->length;
    return 1;
}
示例#7
0
CERT *ssl_cert_dup(CERT *cert) {
  CERT *ret = OPENSSL_malloc(sizeof(CERT));
  if (ret == NULL) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
    return NULL;
  }
  OPENSSL_memset(ret, 0, sizeof(CERT));

  ret->chain = sk_CRYPTO_BUFFER_deep_copy(cert->chain, buffer_up_ref,
                                          CRYPTO_BUFFER_free);

  if (cert->privatekey != NULL) {
    EVP_PKEY_up_ref(cert->privatekey);
    ret->privatekey = cert->privatekey;
  }

  ret->key_method = cert->key_method;
  ret->x509_method = cert->x509_method;

  if (cert->sigalgs != NULL) {
    ret->sigalgs =
        BUF_memdup(cert->sigalgs, cert->num_sigalgs * sizeof(cert->sigalgs[0]));
    if (ret->sigalgs == NULL) {
      goto err;
    }
  }
  ret->num_sigalgs = cert->num_sigalgs;

  ret->cert_cb = cert->cert_cb;
  ret->cert_cb_arg = cert->cert_cb_arg;

  ret->x509_method->cert_dup(ret, cert);

  if (cert->signed_cert_timestamp_list != NULL) {
    CRYPTO_BUFFER_up_ref(cert->signed_cert_timestamp_list);
    ret->signed_cert_timestamp_list = cert->signed_cert_timestamp_list;
  }

  if (cert->ocsp_response != NULL) {
    CRYPTO_BUFFER_up_ref(cert->ocsp_response);
    ret->ocsp_response = cert->ocsp_response;
  }

  ret->sid_ctx_length = cert->sid_ctx_length;
  OPENSSL_memcpy(ret->sid_ctx, cert->sid_ctx, sizeof(ret->sid_ctx));

  ret->enable_early_data = cert->enable_early_data;

  return ret;

err:
  ssl_cert_free(ret);
  return NULL;
}
示例#8
0
/* Copy table of custom extensions */
int custom_exts_copy(custom_ext_methods *dst, const custom_ext_methods *src)
{
    if (src->meths_count) {
        dst->meths =
            BUF_memdup(src->meths,
                       sizeof(custom_ext_method) * src->meths_count);
        if (dst->meths == NULL)
            return 0;
        dst->meths_count = src->meths_count;
    }
    return 1;
}
示例#9
0
static int set_signing_algorithm_prefs(CERT *cert, const uint16_t *prefs,
                                       size_t num_prefs) {
  OPENSSL_free(cert->sigalgs);

  cert->num_sigalgs = 0;
  cert->sigalgs = BUF_memdup(prefs, num_prefs * sizeof(prefs[0]));
  if (cert->sigalgs == NULL) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
    return 0;
  }
  cert->num_sigalgs = num_prefs;

  return 1;
}
示例#10
0
int SSL_SESSION_to_bytes(const SSL_SESSION *in, uint8_t **out_data,
                         size_t *out_len) {
  if (in->not_resumable) {
    /* If the caller has an unresumable session, e.g. if |SSL_get_session| were
     * called on a TLS 1.3 or False Started connection, serialize with a
     * placeholder value so it is not accidentally deserialized into a resumable
     * one. */
    static const char kNotResumableSession[] = "NOT RESUMABLE";

    *out_len = strlen(kNotResumableSession);
    *out_data = BUF_memdup(kNotResumableSession, *out_len);
    if (*out_data == NULL) {
      return 0;
    }

    return 1;
  }

  return SSL_SESSION_to_bytes_full(in, out_data, out_len, 0);
}
示例#11
0
int
STORE_ATTR_INFO_set_sha1str(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
    unsigned char *sha1str, size_t sha1str_size)
{
	if (!attrs) {
		STOREerr(STORE_F_STORE_ATTR_INFO_SET_SHA1STR,
		    ERR_R_PASSED_NULL_PARAMETER);
		return 0;
	}
	if (!ATTR_IS_SET(attrs, code)) {
		if ((attrs->values[code].sha1string =
		    (unsigned char *)BUF_memdup(sha1str,
		    sha1str_size)))
			return 1;
		STOREerr(STORE_F_STORE_ATTR_INFO_SET_SHA1STR,
		    ERR_R_MALLOC_FAILURE);
		return 0;
	}
	STOREerr(STORE_F_STORE_ATTR_INFO_SET_SHA1STR,
	    STORE_R_ALREADY_HAS_A_VALUE);
	return 0;
}
示例#12
0
int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
	{
	unsigned short length;
	unsigned short type;
	unsigned short size;
	unsigned char *data = *p;
	int tlsext_servername = 0;
	int renegotiate_seen = 0;

	if (data >= (d+n-2))
		goto ri_check;

	n2s(data,length);
	if (data+length != d+n)
		{
		*al = SSL_AD_DECODE_ERROR;
		return 0;
		}

	while(data <= (d+n-4))
		{
		n2s(data,type);
		n2s(data,size);

		if (data+size > (d+n))
	   		goto ri_check;

		if (s->tlsext_debug_cb)
			s->tlsext_debug_cb(s, 1, type, data, size,
						s->tlsext_debug_arg);

		if (type == TLSEXT_TYPE_server_name)
			{
			if (s->tlsext_hostname == NULL || size > 0)
				{
				*al = TLS1_AD_UNRECOGNIZED_NAME;
				return 0;
				}
			tlsext_servername = 1;   
			}

#ifndef OPENSSL_NO_EC
		else if (type == TLSEXT_TYPE_ec_point_formats &&
	             s->version != DTLS1_VERSION)
			{
			unsigned char *sdata = data;
			int ecpointformatlist_length = *(sdata++);

			if (ecpointformatlist_length != size - 1)
				{
				*al = TLS1_AD_DECODE_ERROR;
				return 0;
				}
			s->session->tlsext_ecpointformatlist_length = 0;
			if (s->session->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->session->tlsext_ecpointformatlist);
			if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL)
				{
				*al = TLS1_AD_INTERNAL_ERROR;
				return 0;
				}
			s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length;
			memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length);
#if 0
			fprintf(stderr,"ssl_parse_serverhello_tlsext s->session->tlsext_ecpointformatlist ");
			sdata = s->session->tlsext_ecpointformatlist;
			for (i = 0; i < s->session->tlsext_ecpointformatlist_length; i++)
				fprintf(stderr,"%i ",*(sdata++));
			fprintf(stderr,"\n");
#endif
			}
#endif /* OPENSSL_NO_EC */

		else if (type == TLSEXT_TYPE_session_ticket)
			{
			if (s->tls_session_ticket_ext_cb &&
			    !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
				{
				*al = TLS1_AD_INTERNAL_ERROR;
				return 0;
				}
			if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
				|| (size > 0))
				{
				*al = TLS1_AD_UNSUPPORTED_EXTENSION;
				return 0;
				}
			s->tlsext_ticket_expected = 1;
			}
#ifdef TLSEXT_TYPE_opaque_prf_input
		else if (type == TLSEXT_TYPE_opaque_prf_input &&
	             s->version != DTLS1_VERSION)
			{
			unsigned char *sdata = data;

			if (size < 2)
				{
				*al = SSL_AD_DECODE_ERROR;
				return 0;
				}
			n2s(sdata, s->s3->server_opaque_prf_input_len);
			if (s->s3->server_opaque_prf_input_len != size - 2)
				{
				*al = SSL_AD_DECODE_ERROR;
				return 0;
				}
			
			if (s->s3->server_opaque_prf_input != NULL) /* shouldn't really happen */
				OPENSSL_free(s->s3->server_opaque_prf_input);
			if (s->s3->server_opaque_prf_input_len == 0)
				s->s3->server_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */
			else
				s->s3->server_opaque_prf_input = BUF_memdup(sdata, s->s3->server_opaque_prf_input_len);

			if (s->s3->server_opaque_prf_input == NULL)
				{
				*al = TLS1_AD_INTERNAL_ERROR;
				return 0;
				}
			}
#endif
		else if (type == TLSEXT_TYPE_status_request &&
		         s->version != DTLS1_VERSION)
			{
			/* MUST be empty and only sent if we've requested
			 * a status request message.
			 */ 
			if ((s->tlsext_status_type == -1) || (size > 0))
				{
				*al = TLS1_AD_UNSUPPORTED_EXTENSION;
				return 0;
				}
			/* Set flag to expect CertificateStatus message */
			s->tlsext_status_expected = 1;
			}
		else if (type == TLSEXT_TYPE_renegotiate)
			{
			if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al))
				return 0;
			renegotiate_seen = 1;
			}
		data+=size;		
		}

	if (data != d+n)
		{
		*al = SSL_AD_DECODE_ERROR;
		return 0;
		}

	if (!s->hit && tlsext_servername == 1)
		{
 		if (s->tlsext_hostname)
			{
			if (s->session->tlsext_hostname == NULL)
				{
				s->session->tlsext_hostname = BUF_strdup(s->tlsext_hostname);	
				if (!s->session->tlsext_hostname)
					{
					*al = SSL_AD_UNRECOGNIZED_NAME;
					return 0;
					}
				}
			else 
				{
				*al = SSL_AD_DECODE_ERROR;
				return 0;
				}
			}
		}

	*p = data;

	ri_check:

	/* Determine if we need to see RI. Strictly speaking if we want to
	 * avoid an attack we should *always* see RI even on initial server
	 * hello because the client doesn't see any renegotiation during an
	 * attack. However this would mean we could not connect to any server
	 * which doesn't support RI so for the immediate future tolerate RI
	 * absence on initial connect only.
	 */
	if (!renegotiate_seen
		&& !(s->options & SSL_OP_LEGACY_SERVER_CONNECT)
		&& !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
		{
		*al = SSL_AD_HANDSHAKE_FAILURE;
		SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT,
				SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
		return 0;
		}

	return 1;
	}
示例#13
0
CERT *ssl_cert_dup(CERT *cert) {
  CERT *ret;
  int i;

  ret = (CERT *)OPENSSL_malloc(sizeof(CERT));
  if (ret == NULL) {
    OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_MALLOC_FAILURE);
    return NULL;
  }

  memset(ret, 0, sizeof(CERT));

  ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]];
  /* or ret->key = ret->pkeys + (cert->key - cert->pkeys), if you find that
   * more readable */

  ret->mask_k = cert->mask_k;
  ret->mask_a = cert->mask_a;

  if (cert->dh_tmp != NULL) {
    ret->dh_tmp = DHparams_dup(cert->dh_tmp);
    if (ret->dh_tmp == NULL) {
      OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_DH_LIB);
      goto err;
    }
    if (cert->dh_tmp->priv_key) {
      BIGNUM *b = BN_dup(cert->dh_tmp->priv_key);
      if (!b) {
        OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_BN_LIB);
        goto err;
      }
      ret->dh_tmp->priv_key = b;
    }
    if (cert->dh_tmp->pub_key) {
      BIGNUM *b = BN_dup(cert->dh_tmp->pub_key);
      if (!b) {
        OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_BN_LIB);
        goto err;
      }
      ret->dh_tmp->pub_key = b;
    }
  }
  ret->dh_tmp_cb = cert->dh_tmp_cb;

  if (cert->ecdh_tmp) {
    ret->ecdh_tmp = EC_KEY_dup(cert->ecdh_tmp);
    if (ret->ecdh_tmp == NULL) {
      OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_EC_LIB);
      goto err;
    }
  }
  ret->ecdh_tmp_cb = cert->ecdh_tmp_cb;
  ret->ecdh_tmp_auto = cert->ecdh_tmp_auto;

  for (i = 0; i < SSL_PKEY_NUM; i++) {
    CERT_PKEY *cpk = cert->pkeys + i;
    CERT_PKEY *rpk = ret->pkeys + i;
    if (cpk->x509 != NULL) {
      rpk->x509 = X509_up_ref(cpk->x509);
    }

    if (cpk->privatekey != NULL) {
      rpk->privatekey = EVP_PKEY_dup(cpk->privatekey);
    }

    if (cpk->chain) {
      rpk->chain = X509_chain_up_ref(cpk->chain);
      if (!rpk->chain) {
        OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_MALLOC_FAILURE);
        goto err;
      }
    }
  }

  /* Peer sigalgs set to NULL as we get these from handshake too */
  ret->peer_sigalgs = NULL;
  ret->peer_sigalgslen = 0;
  /* Configured sigalgs however we copy across */

  if (cert->conf_sigalgs) {
    ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen);
    if (!ret->conf_sigalgs) {
      goto err;
    }
    memcpy(ret->conf_sigalgs, cert->conf_sigalgs, cert->conf_sigalgslen);
    ret->conf_sigalgslen = cert->conf_sigalgslen;
  } else {
    ret->conf_sigalgs = NULL;
  }

  if (cert->client_sigalgs) {
    ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen);
    if (!ret->client_sigalgs) {
      goto err;
    }
    memcpy(ret->client_sigalgs, cert->client_sigalgs, cert->client_sigalgslen);
    ret->client_sigalgslen = cert->client_sigalgslen;
  } else {
    ret->client_sigalgs = NULL;
  }
  /* Shared sigalgs also NULL */
  ret->shared_sigalgs = NULL;
  /* Copy any custom client certificate types */
  if (cert->client_certificate_types) {
    ret->client_certificate_types = BUF_memdup(
        cert->client_certificate_types, cert->num_client_certificate_types);
    if (!ret->client_certificate_types) {
      goto err;
    }
    ret->num_client_certificate_types = cert->num_client_certificate_types;
  }

  ret->cert_flags = cert->cert_flags;

  ret->cert_cb = cert->cert_cb;
  ret->cert_cb_arg = cert->cert_cb_arg;

  if (cert->verify_store) {
    CRYPTO_add(&cert->verify_store->references, 1, CRYPTO_LOCK_X509_STORE);
    ret->verify_store = cert->verify_store;
  }

  if (cert->chain_store) {
    CRYPTO_add(&cert->chain_store->references, 1, CRYPTO_LOCK_X509_STORE);
    ret->chain_store = cert->chain_store;
  }

  ret->ciphers_raw = NULL;

  return ret;

err:
  ssl_cert_free(ret);
  return NULL;
}
示例#14
0
int ssl_check_clienthello_tlsext(SSL *s)
	{
	int ret=SSL_TLSEXT_ERR_NOACK;
	int al = SSL_AD_UNRECOGNIZED_NAME;

#ifndef OPENSSL_NO_EC
	/* The handling of the ECPointFormats extension is done elsewhere, namely in 
	 * ssl3_choose_cipher in s3_lib.c.
	 */
	/* The handling of the EllipticCurves extension is done elsewhere, namely in 
	 * ssl3_choose_cipher in s3_lib.c.
	 */
#endif

	if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0) 
		ret = s->ctx->tlsext_servername_callback(s, &al, s->ctx->tlsext_servername_arg);
	else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0) 		
		ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg);

	/* If status request then ask callback what to do.
 	 * Note: this must be called after servername callbacks in case 
 	 * the certificate has changed.
 	 */
	if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb)
		{
		int r;
		r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
		switch (r)
			{
			/* We don't want to send a status request response */
			case SSL_TLSEXT_ERR_NOACK:
				s->tlsext_status_expected = 0;
				break;
			/* status request response should be sent */
			case SSL_TLSEXT_ERR_OK:
				if (s->tlsext_ocsp_resp)
					s->tlsext_status_expected = 1;
				else
					s->tlsext_status_expected = 0;
				break;
			/* something bad happened */
			case SSL_TLSEXT_ERR_ALERT_FATAL:
				ret = SSL_TLSEXT_ERR_ALERT_FATAL;
				al = SSL_AD_INTERNAL_ERROR;
				goto err;
			}
		}
	else
		s->tlsext_status_expected = 0;

#ifdef TLSEXT_TYPE_opaque_prf_input
 	{
		/* This sort of belongs into ssl_prepare_serverhello_tlsext(),
		 * but we might be sending an alert in response to the client hello,
		 * so this has to happen here in ssl_check_clienthello_tlsext(). */

		int r = 1;
	
		if (s->ctx->tlsext_opaque_prf_input_callback != 0)
			{
			r = s->ctx->tlsext_opaque_prf_input_callback(s, NULL, 0, s->ctx->tlsext_opaque_prf_input_callback_arg);
			if (!r)
				{
				ret = SSL_TLSEXT_ERR_ALERT_FATAL;
				al = SSL_AD_INTERNAL_ERROR;
				goto err;
				}
			}

		if (s->s3->server_opaque_prf_input != NULL) /* shouldn't really happen */
			OPENSSL_free(s->s3->server_opaque_prf_input);
		s->s3->server_opaque_prf_input = NULL;

		if (s->tlsext_opaque_prf_input != NULL)
			{
			if (s->s3->client_opaque_prf_input != NULL &&
				s->s3->client_opaque_prf_input_len == s->tlsext_opaque_prf_input_len)
				{
				/* can only use this extension if we have a server opaque PRF input
				 * of the same length as the client opaque PRF input! */

				if (s->tlsext_opaque_prf_input_len == 0)
					s->s3->server_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */
				else
					s->s3->server_opaque_prf_input = BUF_memdup(s->tlsext_opaque_prf_input, s->tlsext_opaque_prf_input_len);
				if (s->s3->server_opaque_prf_input == NULL)
					{
					ret = SSL_TLSEXT_ERR_ALERT_FATAL;
					al = SSL_AD_INTERNAL_ERROR;
					goto err;
					}
				s->s3->server_opaque_prf_input_len = s->tlsext_opaque_prf_input_len;
				}
			}

		if (r == 2 && s->s3->server_opaque_prf_input == NULL)
			{
			/* The callback wants to enforce use of the extension,
			 * but we can't do that with the client opaque PRF input;
			 * abort the handshake.
			 */
			ret = SSL_TLSEXT_ERR_ALERT_FATAL;
			al = SSL_AD_HANDSHAKE_FAILURE;
			}
	}

#endif
 err:
	switch (ret)
		{
		case SSL_TLSEXT_ERR_ALERT_FATAL:
			ssl3_send_alert(s,SSL3_AL_FATAL,al); 
			return -1;

		case SSL_TLSEXT_ERR_ALERT_WARNING:
			ssl3_send_alert(s,SSL3_AL_WARNING,al);
			return 1; 
					
		case SSL_TLSEXT_ERR_NOACK:
			s->servername_done=0;
			default:
		return 1;
		}
	}
示例#15
0
int ssl_prepare_clienthello_tlsext(SSL *s)
	{
#ifndef OPENSSL_NO_EC
	/* If we are client and using an elliptic curve cryptography cipher suite, send the point formats 
	 * and elliptic curves we support.
	 */
	int using_ecc = 0;
	int i;
	unsigned char *j;
	unsigned long alg_k, alg_a;
	STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(s);

	for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++)
		{
		SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i);

		alg_k = c->algorithm_mkey;
		alg_a = c->algorithm_auth;
		if ((alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe) || (alg_a & SSL_aECDSA)))
			{
			using_ecc = 1;
			break;
			}
		}
	using_ecc = using_ecc && (s->version == TLS1_VERSION);
	if (using_ecc)
		{
		if (s->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->tlsext_ecpointformatlist);
		if ((s->tlsext_ecpointformatlist = OPENSSL_malloc(3)) == NULL)
			{
			SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
			return -1;
			}
		s->tlsext_ecpointformatlist_length = 3;
		s->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_uncompressed;
		s->tlsext_ecpointformatlist[1] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
		s->tlsext_ecpointformatlist[2] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;

		/* we support all named elliptic curves in draft-ietf-tls-ecc-12 */
		if (s->tlsext_ellipticcurvelist != NULL) OPENSSL_free(s->tlsext_ellipticcurvelist);
		s->tlsext_ellipticcurvelist_length = sizeof(nid_list)/sizeof(nid_list[0]) * 2;
		if ((s->tlsext_ellipticcurvelist = OPENSSL_malloc(s->tlsext_ellipticcurvelist_length)) == NULL)
			{
			s->tlsext_ellipticcurvelist_length = 0;
			SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
			return -1;
			}
		for (i = 1, j = s->tlsext_ellipticcurvelist; (unsigned int)i <=
				sizeof(nid_list)/sizeof(nid_list[0]); i++)
			s2n(i,j);
		}
#endif /* OPENSSL_NO_EC */

#ifdef TLSEXT_TYPE_opaque_prf_input
 	{
		int r = 1;
	
		if (s->ctx->tlsext_opaque_prf_input_callback != 0)
			{
			r = s->ctx->tlsext_opaque_prf_input_callback(s, NULL, 0, s->ctx->tlsext_opaque_prf_input_callback_arg);
			if (!r)
				return -1;
			}

		if (s->tlsext_opaque_prf_input != NULL)
			{
			if (s->s3->client_opaque_prf_input != NULL) /* shouldn't really happen */
				OPENSSL_free(s->s3->client_opaque_prf_input);

			if (s->tlsext_opaque_prf_input_len == 0)
				s->s3->client_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */
			else
				s->s3->client_opaque_prf_input = BUF_memdup(s->tlsext_opaque_prf_input, s->tlsext_opaque_prf_input_len);
			if (s->s3->client_opaque_prf_input == NULL)
				{
				SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
				return -1;
				}
			s->s3->client_opaque_prf_input_len = s->tlsext_opaque_prf_input_len;
			}

		if (r == 2)
			/* at callback's request, insist on receiving an appropriate server opaque PRF input */
			s->s3->server_opaque_prf_input_len = s->tlsext_opaque_prf_input_len;
	}
#endif

	return 1;
	}
示例#16
0
int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
	{
	unsigned short type;
	unsigned short size;
	unsigned short len;
	unsigned char *data = *p;
	int renegotiate_seen = 0;

	s->servername_done = 0;
	s->tlsext_status_type = -1;

	if (data >= (d+n-2))
		goto ri_check;
	n2s(data,len);

	if (data > (d+n-len)) 
		goto ri_check;

	while (data <= (d+n-4))
		{
		n2s(data,type);
		n2s(data,size);

		if (data+size > (d+n))
	   		goto ri_check;
#if 0
		fprintf(stderr,"Received extension type %d size %d\n",type,size);
#endif
		if (s->tlsext_debug_cb)
			s->tlsext_debug_cb(s, 0, type, data, size,
						s->tlsext_debug_arg);
/* The servername extension is treated as follows:

   - Only the hostname type is supported with a maximum length of 255.
   - The servername is rejected if too long or if it contains zeros,
     in which case an fatal alert is generated.
   - The servername field is maintained together with the session cache.
   - When a session is resumed, the servername call back invoked in order
     to allow the application to position itself to the right context. 
   - The servername is acknowledged if it is new for a session or when 
     it is identical to a previously used for the same session. 
     Applications can control the behaviour.  They can at any time
     set a 'desirable' servername for a new SSL object. This can be the
     case for example with HTTPS when a Host: header field is received and
     a renegotiation is requested. In this case, a possible servername
     presented in the new client hello is only acknowledged if it matches
     the value of the Host: field. 
   - Applications must  use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
     if they provide for changing an explicit servername context for the session,
     i.e. when the session has been established with a servername extension. 
   - On session reconnect, the servername extension may be absent. 

*/      

		if (type == TLSEXT_TYPE_server_name)
			{
			unsigned char *sdata;
			int servname_type;
			int dsize; 
		
			if (size < 2) 
				{
				*al = SSL_AD_DECODE_ERROR;
				return 0;
				}
			n2s(data,dsize);  
			size -= 2;
			if (dsize > size  ) 
				{
				*al = SSL_AD_DECODE_ERROR;
				return 0;
				} 

			sdata = data;
			while (dsize > 3) 
				{
	 			servname_type = *(sdata++); 
				n2s(sdata,len);
				dsize -= 3;

				if (len > dsize) 
					{
					*al = SSL_AD_DECODE_ERROR;
					return 0;
					}
				if (s->servername_done == 0)
				switch (servname_type)
					{
				case TLSEXT_NAMETYPE_host_name:
					if (!s->hit)
						{
						if(s->session->tlsext_hostname)
							{
							*al = SSL_AD_DECODE_ERROR;
							return 0;
							}
						if (len > TLSEXT_MAXLEN_host_name)
							{
							*al = TLS1_AD_UNRECOGNIZED_NAME;
							return 0;
							}
						if ((s->session->tlsext_hostname = OPENSSL_malloc(len+1)) == NULL)
							{
							*al = TLS1_AD_INTERNAL_ERROR;
							return 0;
							}
						memcpy(s->session->tlsext_hostname, sdata, len);
						s->session->tlsext_hostname[len]='\0';
						if (strlen(s->session->tlsext_hostname) != len) {
							OPENSSL_free(s->session->tlsext_hostname);
							s->session->tlsext_hostname = NULL;
							*al = TLS1_AD_UNRECOGNIZED_NAME;
							return 0;
						}
						s->servername_done = 1; 

						}
					else 
						s->servername_done = s->session->tlsext_hostname
							&& strlen(s->session->tlsext_hostname) == len 
							&& strncmp(s->session->tlsext_hostname, (char *)sdata, len) == 0;
					
					break;

				default:
					break;
					}
				 
				dsize -= len;
				}
			if (dsize != 0) 
				{
				*al = SSL_AD_DECODE_ERROR;
				return 0;
				}

			}

#ifndef OPENSSL_NO_EC
		else if (type == TLSEXT_TYPE_ec_point_formats &&
	             s->version != DTLS1_VERSION)
			{
			unsigned char *sdata = data;
			int ecpointformatlist_length = *(sdata++);

			if (ecpointformatlist_length != size - 1)
				{
				*al = TLS1_AD_DECODE_ERROR;
				return 0;
				}
			if (!s->hit)
				{
				if(s->session->tlsext_ecpointformatlist)
					{
					*al = TLS1_AD_DECODE_ERROR;
					return 0;
					}
				s->session->tlsext_ecpointformatlist_length = 0;
				if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL)
					{
					*al = TLS1_AD_INTERNAL_ERROR;
					return 0;
					}
				s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length;
				memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length);
				}
#if 0
			fprintf(stderr,"ssl_parse_clienthello_tlsext s->session->tlsext_ecpointformatlist (length=%i) ", s->session->tlsext_ecpointformatlist_length);
			sdata = s->session->tlsext_ecpointformatlist;
			for (i = 0; i < s->session->tlsext_ecpointformatlist_length; i++)
				fprintf(stderr,"%i ",*(sdata++));
			fprintf(stderr,"\n");
#endif
			}
		else if (type == TLSEXT_TYPE_elliptic_curves &&
	             s->version != DTLS1_VERSION)
			{
			unsigned char *sdata = data;
			int ellipticcurvelist_length = (*(sdata++) << 8);
			ellipticcurvelist_length += (*(sdata++));

			if (ellipticcurvelist_length != size - 2)
				{
				*al = TLS1_AD_DECODE_ERROR;
				return 0;
				}
			if (!s->hit)
				{
				if(s->session->tlsext_ellipticcurvelist)
					{
					*al = TLS1_AD_DECODE_ERROR;
					return 0;
					}
				s->session->tlsext_ellipticcurvelist_length = 0;
				if ((s->session->tlsext_ellipticcurvelist = OPENSSL_malloc(ellipticcurvelist_length)) == NULL)
					{
					*al = TLS1_AD_INTERNAL_ERROR;
					return 0;
					}
				s->session->tlsext_ellipticcurvelist_length = ellipticcurvelist_length;
				memcpy(s->session->tlsext_ellipticcurvelist, sdata, ellipticcurvelist_length);
				}
#if 0
			fprintf(stderr,"ssl_parse_clienthello_tlsext s->session->tlsext_ellipticcurvelist (length=%i) ", s->session->tlsext_ellipticcurvelist_length);
			sdata = s->session->tlsext_ellipticcurvelist;
			for (i = 0; i < s->session->tlsext_ellipticcurvelist_length; i++)
				fprintf(stderr,"%i ",*(sdata++));
			fprintf(stderr,"\n");
#endif
			}
#endif /* OPENSSL_NO_EC */
#ifdef TLSEXT_TYPE_opaque_prf_input
		else if (type == TLSEXT_TYPE_opaque_prf_input &&
	             s->version != DTLS1_VERSION)
			{
			unsigned char *sdata = data;

			if (size < 2)
				{
				*al = SSL_AD_DECODE_ERROR;
				return 0;
				}
			n2s(sdata, s->s3->client_opaque_prf_input_len);
			if (s->s3->client_opaque_prf_input_len != size - 2)
				{
				*al = SSL_AD_DECODE_ERROR;
				return 0;
				}

			if (s->s3->client_opaque_prf_input != NULL) /* shouldn't really happen */
				OPENSSL_free(s->s3->client_opaque_prf_input);
			if (s->s3->client_opaque_prf_input_len == 0)
				s->s3->client_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */
			else
				s->s3->client_opaque_prf_input = BUF_memdup(sdata, s->s3->client_opaque_prf_input_len);
			if (s->s3->client_opaque_prf_input == NULL)
				{
				*al = TLS1_AD_INTERNAL_ERROR;
				return 0;
				}
			}
#endif
		else if (type == TLSEXT_TYPE_session_ticket)
			{
			if (s->tls_session_ticket_ext_cb &&
			    !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
				{
				*al = TLS1_AD_INTERNAL_ERROR;
				return 0;
				}
			}
		else if (type == TLSEXT_TYPE_renegotiate)
			{
			if(!ssl_parse_clienthello_renegotiate_ext(s, data, size, al))
				return 0;
			renegotiate_seen = 1;
			}
		else if (type == TLSEXT_TYPE_status_request &&
		         s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
			{
		
			if (size < 5) 
				{
				*al = SSL_AD_DECODE_ERROR;
				return 0;
				}

			s->tlsext_status_type = *data++;
			size--;
			if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
				{
				const unsigned char *sdata;
				int dsize;
				/* Read in responder_id_list */
				n2s(data,dsize);
				size -= 2;
				if (dsize > size  ) 
					{
					*al = SSL_AD_DECODE_ERROR;
					return 0;
					}
				while (dsize > 0)
					{
					OCSP_RESPID *id;
					int idsize;
					if (dsize < 4)
						{
						*al = SSL_AD_DECODE_ERROR;
						return 0;
						}
					n2s(data, idsize);
					dsize -= 2 + idsize;
					if (dsize < 0)
						{
						*al = SSL_AD_DECODE_ERROR;
						return 0;
						}
					sdata = data;
					data += idsize;
					id = d2i_OCSP_RESPID(NULL,
								&sdata, idsize);
					if (!id)
						{
						*al = SSL_AD_DECODE_ERROR;
						return 0;
						}
					if (data != sdata)
						{
						OCSP_RESPID_free(id);
						*al = SSL_AD_DECODE_ERROR;
						return 0;
						}
					if (!s->tlsext_ocsp_ids
						&& !(s->tlsext_ocsp_ids =
						sk_OCSP_RESPID_new_null()))
						{
						OCSP_RESPID_free(id);
						*al = SSL_AD_INTERNAL_ERROR;
						return 0;
						}
					if (!sk_OCSP_RESPID_push(
							s->tlsext_ocsp_ids, id))
						{
						OCSP_RESPID_free(id);
						*al = SSL_AD_INTERNAL_ERROR;
						return 0;
						}
					}

				/* Read in request_extensions */
				n2s(data,dsize);
				size -= 2;
				if (dsize > size) 
					{
					*al = SSL_AD_DECODE_ERROR;
					return 0;
					}
				sdata = data;
				if (dsize > 0)
					{
					s->tlsext_ocsp_exts =
						d2i_X509_EXTENSIONS(NULL,
							&sdata, dsize);
					if (!s->tlsext_ocsp_exts
						|| (data + dsize != sdata))
						{
						*al = SSL_AD_DECODE_ERROR;
						return 0;
						}
					}
				}
				/* We don't know what to do with any other type
 			 	* so ignore it.
 			 	*/
				else
					s->tlsext_status_type = -1;
			}

		/* session ticket processed earlier */
		data+=size;
		}
				
	*p = data;

	ri_check:

	/* Need RI if renegotiating */

	if (!renegotiate_seen && s->new_session &&
		!(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
		{
		*al = SSL_AD_HANDSHAKE_FAILURE;
	 	SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT,
				SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
		return 0;
		}

	return 1;
	}
示例#17
0
SCT *o2i_SCT(SCT **psct, const unsigned char **in, size_t len)
{
    SCT *sct = NULL;
    const unsigned char *p;

    if (len == 0 || len > MAX_SCT_SIZE) {
        CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID);
        goto err;
    }

    if ((sct = SCT_new()) == NULL)
        goto err;

    p = *in;

    sct->version = *p;
    if (sct->version == SCT_VERSION_V1) {
        int sig_len;
        size_t len2;
        /*-
         * Fixed-length header:
         *   struct {
         *     Version sct_version;     (1 byte)
         *     log_id id;               (32 bytes)
         *     uint64 timestamp;        (8 bytes)
         *     CtExtensions extensions; (2 bytes + ?)
         *   }
         */
        if (len < 43) {
            CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID);
            goto err;
        }
        len -= 43;
        p++;
        sct->log_id = BUF_memdup(p, CT_V1_HASHLEN);
        if (sct->log_id == NULL)
            goto err;
        sct->log_id_len = CT_V1_HASHLEN;
        p += CT_V1_HASHLEN;

        n2l8(p, sct->timestamp);

        n2s(p, len2);
        if (len < len2) {
            CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID);
            goto err;
        }
        if (len2 > 0) {
            sct->ext = BUF_memdup(p, len2);
            if (sct->ext == NULL)
                goto err;
        }
        sct->ext_len = len2;
        p += len2;
        len -= len2;

        sig_len = o2i_SCT_signature(sct, &p, len);
        if (sig_len <= 0) {
            CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID);
            goto err;
        }
        len -= sig_len;
        *in = p + len;
    } else {
        /* If not V1 just cache encoding */
        sct->sct = BUF_memdup(p, len);
        if (sct->sct == NULL)
            goto err;
        sct->sct_len = len;
        *in = p + len;
    }

    if (psct != NULL) {
        SCT_free(*psct);
        *psct = sct;
    }

    return sct;
err:
    SCT_free(sct);
    return NULL;
}
示例#18
0
CRYPTO_BUFFER *CRYPTO_BUFFER_new(const uint8_t *data, size_t len,
                                 CRYPTO_BUFFER_POOL *pool) {
  if (pool != NULL) {
    CRYPTO_BUFFER tmp;
    tmp.data = (uint8_t *) data;
    tmp.len = len;

    CRYPTO_MUTEX_lock_read(&pool->lock);
    CRYPTO_BUFFER *const duplicate =
        lh_CRYPTO_BUFFER_retrieve(pool->bufs, &tmp);
    if (duplicate != NULL) {
      CRYPTO_refcount_inc(&duplicate->references);
    }
    CRYPTO_MUTEX_unlock_read(&pool->lock);

    if (duplicate != NULL) {
      return duplicate;
    }
  }

  CRYPTO_BUFFER *const buf = OPENSSL_malloc(sizeof(CRYPTO_BUFFER));
  if (buf == NULL) {
    return NULL;
  }
  OPENSSL_memset(buf, 0, sizeof(CRYPTO_BUFFER));

  buf->data = BUF_memdup(data, len);
  if (len != 0 && buf->data == NULL) {
    OPENSSL_free(buf);
    return NULL;
  }

  buf->len = len;
  buf->references = 1;

  if (pool == NULL) {
    return buf;
  }

  buf->pool = pool;

  CRYPTO_MUTEX_lock_write(&pool->lock);
  CRYPTO_BUFFER *duplicate = lh_CRYPTO_BUFFER_retrieve(pool->bufs, buf);
  int inserted = 0;
  if (duplicate == NULL) {
    CRYPTO_BUFFER *old = NULL;
    inserted = lh_CRYPTO_BUFFER_insert(pool->bufs, &old, buf);
    assert(old == NULL);
  } else {
    CRYPTO_refcount_inc(&duplicate->references);
  }
  CRYPTO_MUTEX_unlock_write(&pool->lock);

  if (!inserted) {
    // We raced to insert |buf| into the pool and lost, or else there was an
    // error inserting.
    OPENSSL_free(buf->data);
    OPENSSL_free(buf);
    return duplicate;
  }

  return buf;
}
示例#19
0
static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) {
  SSL *const ssl = hs->ssl;
  SSL_CLIENT_HELLO client_hello;
  if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
                             ssl->init_num)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
    return ssl_hs_error;
  }

  uint8_t alert = SSL_AD_DECODE_ERROR;
  SSL_SESSION *session = NULL;
  switch (select_session(hs, &alert, &session, &ssl->s3->ticket_age_skew,
                         &client_hello)) {
    case ssl_ticket_aead_ignore_ticket:
      assert(session == NULL);
      if (!ssl_get_new_session(hs, 1 /* server */)) {
        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
        return ssl_hs_error;
      }
      break;

    case ssl_ticket_aead_success:
      /* Carry over authentication information from the previous handshake into
       * a fresh session. */
      hs->new_session = SSL_SESSION_dup(session, SSL_SESSION_DUP_AUTH_ONLY);

      if (/* Early data must be acceptable for this ticket. */
          ssl->cert->enable_early_data &&
          session->ticket_max_early_data != 0 &&
          /* The client must have offered early data. */
          hs->early_data_offered &&
          /* Channel ID is incompatible with 0-RTT. */
          !ssl->s3->tlsext_channel_id_valid &&
          /* The negotiated ALPN must match the one in the ticket. */
          ssl->s3->alpn_selected_len == session->early_alpn_len &&
          OPENSSL_memcmp(ssl->s3->alpn_selected, session->early_alpn,
                         ssl->s3->alpn_selected_len) == 0) {
        ssl->early_data_accepted = 1;
      }

      SSL_SESSION_free(session);
      if (hs->new_session == NULL) {
        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
        return ssl_hs_error;
      }

      ssl->s3->session_reused = 1;

      /* Resumption incorporates fresh key material, so refresh the timeout. */
      ssl_session_renew_timeout(ssl, hs->new_session,
                                ssl->session_ctx->session_psk_dhe_timeout);
      break;

    case ssl_ticket_aead_error:
      ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
      return ssl_hs_error;

    case ssl_ticket_aead_retry:
      hs->tls13_state = state_select_session;
      return ssl_hs_pending_ticket;
  }

  /* Record connection properties in the new session. */
  hs->new_session->cipher = hs->new_cipher;

  if (hs->hostname != NULL) {
    OPENSSL_free(hs->new_session->tlsext_hostname);
    hs->new_session->tlsext_hostname = BUF_strdup(hs->hostname);
    if (hs->new_session->tlsext_hostname == NULL) {
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
      return ssl_hs_error;
    }
  }

  /* Store the initial negotiated ALPN in the session. */
  if (ssl->s3->alpn_selected != NULL) {
    hs->new_session->early_alpn =
        BUF_memdup(ssl->s3->alpn_selected, ssl->s3->alpn_selected_len);
    if (hs->new_session->early_alpn == NULL) {
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
      return ssl_hs_error;
    }
    hs->new_session->early_alpn_len = ssl->s3->alpn_selected_len;
  }

  if (ssl->ctx->dos_protection_cb != NULL &&
      ssl->ctx->dos_protection_cb(&client_hello) == 0) {
    /* Connection rejected for DOS reasons. */
    OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
    return ssl_hs_error;
  }

  /* Incorporate the PSK into the running secret. */
  if (ssl->s3->session_reused) {
    if (!tls13_advance_key_schedule(hs, hs->new_session->master_key,
                                    hs->new_session->master_key_length)) {
      return ssl_hs_error;
    }
  } else if (!tls13_advance_key_schedule(hs, kZeroes, hs->hash_len)) {
    return ssl_hs_error;
  }

  if (ssl->early_data_accepted) {
    if (!tls13_derive_early_secrets(hs)) {
      return ssl_hs_error;
    }
  } else if (hs->early_data_offered) {
    ssl->s3->skip_early_data = 1;
  }

  ssl->method->received_flight(ssl);

  /* Resolve ECDHE and incorporate it into the secret. */
  int need_retry;
  if (!resolve_ecdhe_secret(hs, &need_retry, &client_hello)) {
    if (need_retry) {
      ssl->early_data_accepted = 0;
      ssl->s3->skip_early_data = 1;
      hs->tls13_state = state_send_hello_retry_request;
      return ssl_hs_ok;
    }
    return ssl_hs_error;
  }

  hs->tls13_state = state_send_server_hello;
  return ssl_hs_ok;
}
示例#20
0
文件: dh_ameth.c 项目: Orav/kbengine
static int dh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
{
    int rv = 0;

    X509_ALGOR *alg, *kekalg = NULL;
    ASN1_OCTET_STRING *ukm;
    const unsigned char *p;
    unsigned char *dukm = NULL;
    size_t dukmlen = 0;
    int keylen, plen;
    const EVP_CIPHER *kekcipher;
    EVP_CIPHER_CTX *kekctx;

    if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
        goto err;

    /*
     * For DH we only have one OID permissible. If ever any more get defined
     * we will need something cleverer.
     */
    if (OBJ_obj2nid(alg->algorithm) != NID_id_smime_alg_ESDH) {
        DHerr(DH_F_DH_CMS_SET_SHARED_INFO, DH_R_KDF_PARAMETER_ERROR);
        goto err;
    }

    if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, EVP_PKEY_DH_KDF_X9_42) <= 0)
        goto err;

    if (EVP_PKEY_CTX_set_dh_kdf_md(pctx, EVP_sha1()) <= 0)
        goto err;

    if (alg->parameter->type != V_ASN1_SEQUENCE)
        goto err;

    p = alg->parameter->value.sequence->data;
    plen = alg->parameter->value.sequence->length;
    kekalg = d2i_X509_ALGOR(NULL, &p, plen);
    if (!kekalg)
        goto err;
    kekctx = CMS_RecipientInfo_kari_get0_ctx(ri);
    if (!kekctx)
        goto err;
    kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
    if (!kekcipher || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
        goto err;
    if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
        goto err;
    if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0)
        goto err;

    keylen = EVP_CIPHER_CTX_key_length(kekctx);
    if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 0)
        goto err;
    /* Use OBJ_nid2obj to ensure we use built in OID that isn't freed */
    if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx,
                                     OBJ_nid2obj(EVP_CIPHER_type(kekcipher)))
        <= 0)
        goto err;

    if (ukm) {
        dukmlen = ASN1_STRING_length(ukm);
        dukm = BUF_memdup(ASN1_STRING_data(ukm), dukmlen);
        if (!dukm)
            goto err;
    }

    if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0)
        goto err;
    dukm = NULL;

    rv = 1;
 err:
    if (kekalg)
        X509_ALGOR_free(kekalg);
    if (dukm)
        OPENSSL_free(dukm);
    return rv;
}
示例#21
0
CERT *ssl_cert_dup(CERT *cert) {
  CERT *ret = (CERT *)OPENSSL_malloc(sizeof(CERT));
  if (ret == NULL) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
    return NULL;
  }
  memset(ret, 0, sizeof(CERT));

  ret->mask_k = cert->mask_k;
  ret->mask_a = cert->mask_a;

  if (cert->dh_tmp != NULL) {
    ret->dh_tmp = DHparams_dup(cert->dh_tmp);
    if (ret->dh_tmp == NULL) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB);
      goto err;
    }
    if (cert->dh_tmp->priv_key) {
      BIGNUM *b = BN_dup(cert->dh_tmp->priv_key);
      if (!b) {
        OPENSSL_PUT_ERROR(SSL, ERR_R_BN_LIB);
        goto err;
      }
      ret->dh_tmp->priv_key = b;
    }
    if (cert->dh_tmp->pub_key) {
      BIGNUM *b = BN_dup(cert->dh_tmp->pub_key);
      if (!b) {
        OPENSSL_PUT_ERROR(SSL, ERR_R_BN_LIB);
        goto err;
      }
      ret->dh_tmp->pub_key = b;
    }
  }
  ret->dh_tmp_cb = cert->dh_tmp_cb;

  ret->ecdh_nid = cert->ecdh_nid;
  ret->ecdh_tmp_cb = cert->ecdh_tmp_cb;

  if (cert->x509 != NULL) {
    ret->x509 = X509_up_ref(cert->x509);
  }

  if (cert->privatekey != NULL) {
    ret->privatekey = EVP_PKEY_up_ref(cert->privatekey);
  }

  if (cert->chain) {
    ret->chain = X509_chain_up_ref(cert->chain);
    if (!ret->chain) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
      goto err;
    }
  }

  /* Copy over signature algorithm configuration. */
  if (cert->conf_sigalgs) {
    ret->conf_sigalgs = BUF_memdup(cert->conf_sigalgs, cert->conf_sigalgslen);
    if (!ret->conf_sigalgs) {
      goto err;
    }
    ret->conf_sigalgslen = cert->conf_sigalgslen;
  }

  if (cert->client_sigalgs) {
    ret->client_sigalgs = BUF_memdup(cert->client_sigalgs,
                                     cert->client_sigalgslen);
    if (!ret->client_sigalgs) {
      goto err;
    }
    ret->client_sigalgslen = cert->client_sigalgslen;
  }

  /* Copy any custom client certificate types */
  if (cert->client_certificate_types) {
    ret->client_certificate_types = BUF_memdup(
        cert->client_certificate_types, cert->num_client_certificate_types);
    if (!ret->client_certificate_types) {
      goto err;
    }
    ret->num_client_certificate_types = cert->num_client_certificate_types;
  }

  ret->cert_cb = cert->cert_cb;
  ret->cert_cb_arg = cert->cert_cb_arg;

  if (cert->verify_store) {
    CRYPTO_refcount_inc(&cert->verify_store->references);
    ret->verify_store = cert->verify_store;
  }

  if (cert->chain_store) {
    CRYPTO_refcount_inc(&cert->chain_store->references);
    ret->chain_store = cert->chain_store;
  }

  return ret;

err:
  ssl_cert_free(ret);
  return NULL;
}
示例#22
0
SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
  SSL_SESSION *new_session = ssl_session_new(session->x509_method);
  if (new_session == NULL) {
    goto err;
  }

  new_session->is_server = session->is_server;
  new_session->ssl_version = session->ssl_version;
  new_session->sid_ctx_length = session->sid_ctx_length;
  OPENSSL_memcpy(new_session->sid_ctx, session->sid_ctx, session->sid_ctx_length);

  /* Copy the key material. */
  new_session->master_key_length = session->master_key_length;
  OPENSSL_memcpy(new_session->master_key, session->master_key,
         session->master_key_length);
  new_session->cipher = session->cipher;

  /* Copy authentication state. */
  if (session->psk_identity != NULL) {
    new_session->psk_identity = BUF_strdup(session->psk_identity);
    if (new_session->psk_identity == NULL) {
      goto err;
    }
  }
  if (session->certs != NULL) {
    new_session->certs = sk_CRYPTO_BUFFER_new_null();
    if (new_session->certs == NULL) {
      goto err;
    }
    for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(session->certs); i++) {
      CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(session->certs, i);
      if (!sk_CRYPTO_BUFFER_push(new_session->certs, buffer)) {
        goto err;
      }
      CRYPTO_BUFFER_up_ref(buffer);
    }
  }

  if (!session->x509_method->session_dup(new_session, session)) {
    goto err;
  }

  new_session->verify_result = session->verify_result;

  new_session->ocsp_response_length = session->ocsp_response_length;
  if (session->ocsp_response != NULL) {
    new_session->ocsp_response = BUF_memdup(session->ocsp_response,
                                            session->ocsp_response_length);
    if (new_session->ocsp_response == NULL) {
      goto err;
    }
  }

  new_session->tlsext_signed_cert_timestamp_list_length =
      session->tlsext_signed_cert_timestamp_list_length;
  if (session->tlsext_signed_cert_timestamp_list != NULL) {
    new_session->tlsext_signed_cert_timestamp_list =
        BUF_memdup(session->tlsext_signed_cert_timestamp_list,
                   session->tlsext_signed_cert_timestamp_list_length);
    if (new_session->tlsext_signed_cert_timestamp_list == NULL) {
      goto err;
    }
  }

  OPENSSL_memcpy(new_session->peer_sha256, session->peer_sha256,
                 SHA256_DIGEST_LENGTH);
  new_session->peer_sha256_valid = session->peer_sha256_valid;

  if (session->tlsext_hostname != NULL) {
    new_session->tlsext_hostname = BUF_strdup(session->tlsext_hostname);
    if (new_session->tlsext_hostname == NULL) {
      goto err;
    }
  }

  new_session->peer_signature_algorithm = session->peer_signature_algorithm;

  new_session->timeout = session->timeout;
  new_session->auth_timeout = session->auth_timeout;
  new_session->time = session->time;

  /* Copy non-authentication connection properties. */
  if (dup_flags & SSL_SESSION_INCLUDE_NONAUTH) {
    new_session->session_id_length = session->session_id_length;
    OPENSSL_memcpy(new_session->session_id, session->session_id,
                   session->session_id_length);

    new_session->group_id = session->group_id;

    OPENSSL_memcpy(new_session->original_handshake_hash,
                   session->original_handshake_hash,
                   session->original_handshake_hash_len);
    new_session->original_handshake_hash_len =
        session->original_handshake_hash_len;
    new_session->tlsext_tick_lifetime_hint = session->tlsext_tick_lifetime_hint;
    new_session->ticket_age_add = session->ticket_age_add;
    new_session->ticket_max_early_data = session->ticket_max_early_data;
    new_session->extended_master_secret = session->extended_master_secret;

    if (session->early_alpn != NULL) {
      new_session->early_alpn =
          BUF_memdup(session->early_alpn, session->early_alpn_len);
      if (new_session->early_alpn == NULL) {
        goto err;
      }
    }
    new_session->early_alpn_len = session->early_alpn_len;
  }

  /* Copy the ticket. */
  if (dup_flags & SSL_SESSION_INCLUDE_TICKET) {
    if (session->tlsext_tick != NULL) {
      new_session->tlsext_tick =
          BUF_memdup(session->tlsext_tick, session->tlsext_ticklen);
      if (new_session->tlsext_tick == NULL) {
        goto err;
      }
    }
    new_session->tlsext_ticklen = session->tlsext_ticklen;
  }

  /* The new_session does not get a copy of the ex_data. */

  new_session->not_resumable = 1;
  return new_session;

err:
  SSL_SESSION_free(new_session);
  OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
  return 0;
}
示例#23
0
文件: dh_ameth.c 项目: Orav/kbengine
static int dh_cms_encrypt(CMS_RecipientInfo *ri)
{
    EVP_PKEY_CTX *pctx;
    EVP_PKEY *pkey;
    EVP_CIPHER_CTX *ctx;
    int keylen;
    X509_ALGOR *talg, *wrap_alg = NULL;
    ASN1_OBJECT *aoid;
    ASN1_BIT_STRING *pubkey;
    ASN1_STRING *wrap_str;
    ASN1_OCTET_STRING *ukm;
    unsigned char *penc = NULL, *dukm = NULL;
    int penclen;
    size_t dukmlen = 0;
    int rv = 0;
    int kdf_type, wrap_nid;
    const EVP_MD *kdf_md;
    pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
    if (!pctx)
        return 0;
    /* Get ephemeral key */
    pkey = EVP_PKEY_CTX_get0_pkey(pctx);
    if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey,
                                             NULL, NULL, NULL))
        goto err;
    X509_ALGOR_get0(&aoid, NULL, NULL, talg);
    /* Is everything uninitialised? */
    if (aoid == OBJ_nid2obj(NID_undef)) {
        ASN1_INTEGER *pubk;
        pubk = BN_to_ASN1_INTEGER(pkey->pkey.dh->pub_key, NULL);
        if (!pubk)
            goto err;
        /* Set the key */

        penclen = i2d_ASN1_INTEGER(pubk, &penc);
        ASN1_INTEGER_free(pubk);
        if (penclen <= 0)
            goto err;
        ASN1_STRING_set0(pubkey, penc, penclen);
        pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
        pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT;

        penc = NULL;
        X509_ALGOR_set0(talg, OBJ_nid2obj(NID_dhpublicnumber),
                        V_ASN1_UNDEF, NULL);
    }

    /* See if custom paraneters set */
    kdf_type = EVP_PKEY_CTX_get_dh_kdf_type(pctx);
    if (kdf_type <= 0)
        goto err;
    if (!EVP_PKEY_CTX_get_dh_kdf_md(pctx, &kdf_md))
        goto err;

    if (kdf_type == EVP_PKEY_DH_KDF_NONE) {
        kdf_type = EVP_PKEY_DH_KDF_X9_42;
        if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, kdf_type) <= 0)
            goto err;
    } else if (kdf_type != EVP_PKEY_DH_KDF_X9_42)
        /* Unknown KDF */
        goto err;
    if (kdf_md == NULL) {
        /* Only SHA1 supported */
        kdf_md = EVP_sha1();
        if (EVP_PKEY_CTX_set_dh_kdf_md(pctx, kdf_md) <= 0)
            goto err;
    } else if (EVP_MD_type(kdf_md) != NID_sha1)
        /* Unsupported digest */
        goto err;

    if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
        goto err;

    /* Get wrap NID */
    ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
    wrap_nid = EVP_CIPHER_CTX_type(ctx);
    if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx, OBJ_nid2obj(wrap_nid)) <= 0)
        goto err;
    keylen = EVP_CIPHER_CTX_key_length(ctx);

    /* Package wrap algorithm in an AlgorithmIdentifier */

    wrap_alg = X509_ALGOR_new();
    if (!wrap_alg)
        goto err;
    wrap_alg->algorithm = OBJ_nid2obj(wrap_nid);
    wrap_alg->parameter = ASN1_TYPE_new();
    if (!wrap_alg->parameter)
        goto err;
    if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0)
        goto err;
    if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) {
        ASN1_TYPE_free(wrap_alg->parameter);
        wrap_alg->parameter = NULL;
    }

    if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 0)
        goto err;

    if (ukm) {
        dukmlen = ASN1_STRING_length(ukm);
        dukm = BUF_memdup(ASN1_STRING_data(ukm), dukmlen);
        if (!dukm)
            goto err;
    }

    if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0)
        goto err;
    dukm = NULL;

    /*
     * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter
     * of another AlgorithmIdentifier.
     */
    penc = NULL;
    penclen = i2d_X509_ALGOR(wrap_alg, &penc);
    if (!penc || !penclen)
        goto err;
    wrap_str = ASN1_STRING_new();
    if (!wrap_str)
        goto err;
    ASN1_STRING_set0(wrap_str, penc, penclen);
    penc = NULL;
    X509_ALGOR_set0(talg, OBJ_nid2obj(NID_id_smime_alg_ESDH),
                    V_ASN1_SEQUENCE, wrap_str);

    rv = 1;

 err:
    if (penc)
        OPENSSL_free(penc);
    if (wrap_alg)
        X509_ALGOR_free(wrap_alg);
    return rv;
}
CERT *ssl_cert_dup(CERT *cert)
	{
	CERT *ret;
	int i;

	ret = (CERT *)OPENSSL_malloc(sizeof(CERT));
	if (ret == NULL)
		{
		OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_MALLOC_FAILURE);
		return(NULL);
		}

	memset(ret, 0, sizeof(CERT));

	ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]];
	/* or ret->key = ret->pkeys + (cert->key - cert->pkeys),
	 * if you find that more readable */

	ret->mask_k = cert->mask_k;
	ret->mask_a = cert->mask_a;

	if (cert->dh_tmp != NULL)
		{
		ret->dh_tmp = DHparams_dup(cert->dh_tmp);
		if (ret->dh_tmp == NULL)
			{
			OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_DH_LIB);
			goto err;
			}
		if (cert->dh_tmp->priv_key)
			{
			BIGNUM *b = BN_dup(cert->dh_tmp->priv_key);
			if (!b)
				{
				OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_BN_LIB);
				goto err;
				}
			ret->dh_tmp->priv_key = b;
			}
		if (cert->dh_tmp->pub_key)
			{
			BIGNUM *b = BN_dup(cert->dh_tmp->pub_key);
			if (!b)
				{
				OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_BN_LIB);
				goto err;
				}
			ret->dh_tmp->pub_key = b;
			}
		}
	ret->dh_tmp_cb = cert->dh_tmp_cb;

	if (cert->ecdh_tmp)
		{
		ret->ecdh_tmp = EC_KEY_dup(cert->ecdh_tmp);
		if (ret->ecdh_tmp == NULL)
			{
			OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_EC_LIB);
			goto err;
			}
		}
	ret->ecdh_tmp_cb = cert->ecdh_tmp_cb;
	ret->ecdh_tmp_auto = cert->ecdh_tmp_auto;

	for (i = 0; i < SSL_PKEY_NUM; i++)
		{
		CERT_PKEY *cpk = cert->pkeys + i;
		CERT_PKEY *rpk = ret->pkeys + i;
		if (cpk->x509 != NULL)
			{
			rpk->x509 = X509_up_ref(cpk->x509);
			}
		
		if (cpk->privatekey != NULL)
			{
			rpk->privatekey = cpk->privatekey;
			CRYPTO_add(&cpk->privatekey->references, 1,
				CRYPTO_LOCK_EVP_PKEY);

			switch(i) 
				{
				/* If there was anything special to do for
				 * certain types of keys, we'd do it here.
				 * (Nothing at the moment, I think.) */

			case SSL_PKEY_RSA_ENC:
			case SSL_PKEY_RSA_SIGN:
				/* We have an RSA key. */
				break;
				
			case SSL_PKEY_ECC:
				/* We have an ECC key */
				break;

			default:
				/* Can't happen. */
				OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, SSL_R_LIBRARY_BUG);
				}
			}

		if (cpk->chain)
			{
			rpk->chain = X509_chain_up_ref(cpk->chain);
			if (!rpk->chain)
				{
				OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_MALLOC_FAILURE);
				goto err;
				}
			}
		}
	
	/* Peer sigalgs set to NULL as we get these from handshake too */
	ret->peer_sigalgs = NULL;
	ret->peer_sigalgslen = 0;
	/* Configured sigalgs however we copy across */

	if (cert->conf_sigalgs)
		{
		ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen);
		if (!ret->conf_sigalgs)
			goto err;
		memcpy(ret->conf_sigalgs, cert->conf_sigalgs,
						cert->conf_sigalgslen);
		ret->conf_sigalgslen = cert->conf_sigalgslen;
		}
	else
		ret->conf_sigalgs = NULL;

	if (cert->client_sigalgs)
		{
		ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen);
		if (!ret->client_sigalgs)
			goto err;
		memcpy(ret->client_sigalgs, cert->client_sigalgs,
						cert->client_sigalgslen);
		ret->client_sigalgslen = cert->client_sigalgslen;
		}
	else
		ret->client_sigalgs = NULL;
	/* Shared sigalgs also NULL */
	ret->shared_sigalgs = NULL;
	/* Copy any custom client certificate types */
	if (cert->client_certificate_types)
		{
		ret->client_certificate_types = BUF_memdup(
			cert->client_certificate_types,
			cert->num_client_certificate_types);
		if (!ret->client_certificate_types)
			goto err;
		ret->num_client_certificate_types = cert->num_client_certificate_types;
		}

	ret->cert_flags = cert->cert_flags;

	ret->cert_cb = cert->cert_cb;
	ret->cert_cb_arg = cert->cert_cb_arg;

	if (cert->verify_store)
		{
		CRYPTO_add(&cert->verify_store->references, 1, CRYPTO_LOCK_X509_STORE);
		ret->verify_store = cert->verify_store;
		}

	if (cert->chain_store)
		{
		CRYPTO_add(&cert->chain_store->references, 1, CRYPTO_LOCK_X509_STORE);
		ret->chain_store = cert->chain_store;
		}

	ret->ciphers_raw = NULL;

	return(ret);
	
err:
	ssl_cert_free(ret);
	return NULL;
	}