コード例 #1
0
/* seed1 through seed5 are virtually concatenated */
static int tls1_PRF(long digest_mask,
		     const void *seed1, int seed1_len,
		     const void *seed2, int seed2_len,
		     const void *seed3, int seed3_len,
		     const void *seed4, int seed4_len,
		     const void *seed5, int seed5_len,
		     const unsigned char *sec, int slen,
		     unsigned char *out1,
		     unsigned char *out2, int olen)
	{
	int len,i,idx,count;
	const unsigned char *S1;
	long m;
	const EVP_MD *md;
	int ret = 0;

	/* Count number of digests and partition sec evenly */
	count=0;
	for (idx=0;ssl_get_handshake_digest(idx,&m,&md);idx++) {
		if ((m<<TLS1_PRF_DGST_SHIFT) & digest_mask) count++;
	}	
	len=slen/count;
	if (count == 1)
		slen = 0;
	S1=sec;
	memset(out1,0,olen);
	for (idx=0;ssl_get_handshake_digest(idx,&m,&md);idx++) {
		if ((m<<TLS1_PRF_DGST_SHIFT) & digest_mask) {
			if (!md) {
				SSLerr(SSL_F_TLS1_PRF,
				SSL_R_UNSUPPORTED_DIGEST_TYPE);
				goto err;				
			}
			if (!tls1_P_hash(md ,S1,len+(slen&1),
					seed1,seed1_len,seed2,seed2_len,seed3,seed3_len,seed4,seed4_len,seed5,seed5_len,
					out2,olen))
				goto err;
			S1+=len;
			for (i=0; i<olen; i++)
			{
				out1[i]^=out2[i];
			}
		}
	}
	ret = 1;
err:
	return ret;
}
コード例 #2
0
ファイル: t1_enc.c プロジェクト: anthonylauzon/bazel
int tls1_prf(SSL *s, uint8_t *out, size_t out_len, const uint8_t *secret,
             size_t secret_len, const char *label, size_t label_len,
             const uint8_t *seed1, size_t seed1_len,
             const uint8_t *seed2, size_t seed2_len) {

  if (out_len == 0) {
    return 1;
  }

  memset(out, 0, out_len);

  uint32_t algorithm_prf = ssl_get_algorithm_prf(s);
  if (algorithm_prf == SSL_HANDSHAKE_MAC_DEFAULT) {
    /* If using the MD5/SHA1 PRF, |secret| is partitioned between SHA-1 and
     * MD5, MD5 first. */
    size_t secret_half = secret_len - (secret_len / 2);
    if (!tls1_P_hash(out, out_len, EVP_md5(), secret, secret_half,
                     (const uint8_t *)label, label_len, seed1, seed1_len, seed2,
                     seed2_len)) {
      return 0;
    }

    /* Note that, if |secret_len| is odd, the two halves share a byte. */
    secret = secret + (secret_len - secret_half);
    secret_len = secret_half;
  }

  if (!tls1_P_hash(out, out_len, ssl_get_handshake_digest(algorithm_prf),
                   secret, secret_len, (const uint8_t *)label, label_len,
                   seed1, seed1_len, seed2, seed2_len)) {
    return 0;
  }

  return 1;
}
コード例 #3
0
ファイル: tls13_enc.c プロジェクト: onedata/helpers
int tls13_advance_key_schedule(SSL *ssl, const uint8_t *in, size_t len) {
    SSL_HANDSHAKE *hs = ssl->s3->hs;
    const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));

    return HKDF_extract(hs->secret, &hs->hash_len, digest, in, len, hs->secret,
                        hs->hash_len);
}
コード例 #4
0
ファイル: ssl_session.c プロジェクト: boringssl/boringssl
const EVP_MD *SSL_SESSION_get_digest(const SSL_SESSION *session,
                                     const SSL *ssl) {
  uint16_t version;
  if (!ssl->method->version_from_wire(&version, session->ssl_version)) {
    return NULL;
  }

  return ssl_get_handshake_digest(session->cipher->algorithm_prf, version);
}
コード例 #5
0
ファイル: t1_enc.cpp プロジェクト: EddieGarmon/netduino-netmf
int tls1_final_finish_mac(SSL *s,
	     const char *str, int slen, unsigned char *out)
	{
	unsigned int i;
	EVP_MD_CTX ctx;
	unsigned char buf[2*EVP_MAX_MD_SIZE];
	unsigned char *q,buf2[12];
	int idx;
	long mask;
	int err=0;
	const EVP_MD *md; 

	q=buf;

	if (s->s3->handshake_buffer) 
		if (!ssl3_digest_cached_records(s))
			return 0;

	EVP_MD_CTX_init(&ctx);

	for (idx=0;ssl_get_handshake_digest(idx,&mask,&md);idx++)
		{
		if (mask & s->s3->tmp.new_cipher->algorithm2)
			{
			int hashsize = EVP_MD_size(md);
			if (hashsize < 0 || hashsize > (int)(sizeof buf - (size_t)(q-buf)))
				{
				/* internal error: 'buf' is too small for this cipersuite! */
				err = 1;
				}
			else
				{
				EVP_MD_CTX_copy_ex(&ctx,s->s3->handshake_dgst[idx]);
				EVP_DigestFinal_ex(&ctx,q,&i);
				if (i != (unsigned int)hashsize) /* can't really happen */
					err = 1;
				q+=i;
				}
			}
		}
		
	if (!tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
			str,slen, buf,(int)(q-buf), NULL,0, NULL,0, NULL,0,
			s->session->master_key,s->session->master_key_length,
			out,buf2,sizeof buf2))
		err = 1;
	EVP_MD_CTX_cleanup(&ctx);

	if (err)
		return 0;
	else
		return sizeof buf2;
	}
コード例 #6
0
ファイル: t1_enc.c プロジェクト: ThomasWo/proto-quic
int SSL_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len,
                               const char *label, size_t label_len,
                               const uint8_t *context, size_t context_len,
                               int use_context) {
  if (!ssl->s3->have_version || ssl->version == SSL3_VERSION) {
    return 0;
  }

  /* Exporters may not be used in the middle of a renegotiation. */
  if (SSL_in_init(ssl) && !SSL_in_false_start(ssl)) {
    return 0;
  }

  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
    return tls13_export_keying_material(ssl, out, out_len, label, label_len,
                                        context, context_len, use_context);
  }

  size_t seed_len = 2 * SSL3_RANDOM_SIZE;
  if (use_context) {
    if (context_len >= 1u << 16) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
      return 0;
    }
    seed_len += 2 + context_len;
  }
  uint8_t *seed = OPENSSL_malloc(seed_len);
  if (seed == NULL) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
    return 0;
  }

  OPENSSL_memcpy(seed, ssl->s3->client_random, SSL3_RANDOM_SIZE);
  OPENSSL_memcpy(seed + SSL3_RANDOM_SIZE, ssl->s3->server_random,
                 SSL3_RANDOM_SIZE);
  if (use_context) {
    seed[2 * SSL3_RANDOM_SIZE] = (uint8_t)(context_len >> 8);
    seed[2 * SSL3_RANDOM_SIZE + 1] = (uint8_t)context_len;
    OPENSSL_memcpy(seed + 2 * SSL3_RANDOM_SIZE + 2, context, context_len);
  }

  const EVP_MD *digest = ssl_get_handshake_digest(
      SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl));
  if (digest == NULL) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    return 0;
  }
  int ret = tls1_prf(digest, out, out_len, SSL_get_session(ssl)->master_key,
                     SSL_get_session(ssl)->master_key_length, label, label_len,
                     seed, seed_len, NULL, 0);
  OPENSSL_free(seed);
  return ret;
}
コード例 #7
0
ファイル: s3_enc.c プロジェクト: HungMingWu/libquic
int ssl3_digest_cached_records(
    SSL *s, enum should_free_handshake_buffer_t should_free_handshake_buffer) {
  int i;
  long mask;
  const EVP_MD *md;
  const uint8_t *hdata;
  size_t hdatalen;

  /* Allocate handshake_dgst array */
  ssl3_free_digest_list(s);
  s->s3->handshake_dgst = OPENSSL_malloc(SSL_MAX_DIGEST * sizeof(EVP_MD_CTX *));
  if (s->s3->handshake_dgst == NULL) {
    OPENSSL_PUT_ERROR(SSL, ssl3_digest_cached_records, ERR_R_MALLOC_FAILURE);
    return 0;
  }

  memset(s->s3->handshake_dgst, 0, SSL_MAX_DIGEST * sizeof(EVP_MD_CTX *));
  if (!BIO_mem_contents(s->s3->handshake_buffer, &hdata, &hdatalen)) {
    OPENSSL_PUT_ERROR(SSL, ssl3_digest_cached_records,
                      SSL_R_BAD_HANDSHAKE_LENGTH);
    return 0;
  }

  /* Loop through bits of algorithm2 field and create MD_CTX-es */
  for (i = 0; ssl_get_handshake_digest(i, &mask, &md); i++) {
    if ((mask & ssl_get_algorithm2(s)) && md) {
      s->s3->handshake_dgst[i] = EVP_MD_CTX_create();
      if (s->s3->handshake_dgst[i] == NULL) {
        OPENSSL_PUT_ERROR(SSL, ssl3_digest_cached_records, ERR_LIB_EVP);
        return 0;
      }
      if (!EVP_DigestInit_ex(s->s3->handshake_dgst[i], md, NULL)) {
        EVP_MD_CTX_destroy(s->s3->handshake_dgst[i]);
        s->s3->handshake_dgst[i] = NULL;
        OPENSSL_PUT_ERROR(SSL, ssl3_digest_cached_records, ERR_LIB_EVP);
        return 0;
      }
      EVP_DigestUpdate(s->s3->handshake_dgst[i], hdata, hdatalen);
    } else {
      s->s3->handshake_dgst[i] = NULL;
    }
  }

  if (should_free_handshake_buffer == free_handshake_buffer) {
    /* Free handshake_buffer BIO */
    BIO_free(s->s3->handshake_buffer);
    s->s3->handshake_buffer = NULL;
  }

  return 1;
}
コード例 #8
0
ファイル: tls13_enc.c プロジェクト: onedata/helpers
/* derive_secret derives a secret of length |len| and writes the result in |out|
 * with the given label and the current base secret and most recently-saved
 * handshake context. It returns one on success and zero on error. */
static int derive_secret(SSL *ssl, uint8_t *out, size_t len,
                         const uint8_t *label, size_t label_len) {
    SSL_HANDSHAKE *hs = ssl->s3->hs;
    const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));

    uint8_t context_hashes[2 * EVP_MAX_MD_SIZE];
    size_t context_hashes_len;
    if (!tls13_get_context_hashes(ssl, context_hashes, &context_hashes_len)) {
        return 0;
    }

    return hkdf_expand_label(out, digest, hs->secret, hs->hash_len, label,
                             label_len, context_hashes, context_hashes_len, len);
}
コード例 #9
0
ファイル: s3_enc.c プロジェクト: DJHartley/openssl
int ssl3_digest_cached_records(SSL *s)
	{
	int i;
	long mask;
	const EVP_MD *md;
	long hdatalen;
	void *hdata;

	/* Allocate handshake_dgst array */
	ssl3_free_digest_list(s);
	s->s3->handshake_dgst = OPENSSL_malloc(SSL_MAX_DIGEST * sizeof(EVP_MD_CTX *));
	memset(s->s3->handshake_dgst,0,SSL_MAX_DIGEST *sizeof(EVP_MD_CTX *));
	hdatalen = BIO_get_mem_data(s->s3->handshake_buffer,&hdata);
	if (hdatalen <= 0)
		{
		SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, SSL_R_BAD_HANDSHAKE_LENGTH);
		return 0;
		}

	/* Loop through bitso of algorithm2 field and create MD_CTX-es */
	for (i=0;ssl_get_handshake_digest(i,&mask,&md); i++) 
		{
		if ((mask & ssl_get_algorithm2(s)) && md) 
			{
			s->s3->handshake_dgst[i]=EVP_MD_CTX_create();
#ifdef OPENSSL_FIPS
			if (EVP_MD_nid(md) == NID_md5)
				{
				EVP_MD_CTX_set_flags(s->s3->handshake_dgst[i],
						EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
				}
#endif
			EVP_DigestInit_ex(s->s3->handshake_dgst[i],md,NULL);
			EVP_DigestUpdate(s->s3->handshake_dgst[i],hdata,hdatalen);
			} 
		else 
			{	
			s->s3->handshake_dgst[i]=NULL;
			}
		}
	if (!(s->s3->flags & TLS1_FLAGS_KEEP_HANDSHAKE))
		{
		/* Free handshake_buffer BIO */
		BIO_free(s->s3->handshake_buffer);
		s->s3->handshake_buffer = NULL;
		}

	return 1;
	}
コード例 #10
0
ファイル: tls13_enc.c プロジェクト: onedata/helpers
int tls13_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len,
                                 const char *label, size_t label_len,
                                 const uint8_t *context, size_t context_len,
                                 int use_context) {
    const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));

    const uint8_t *hash = NULL;
    size_t hash_len = 0;
    if (use_context) {
        hash = context;
        hash_len = context_len;
    }
    return hkdf_expand_label(out, digest, ssl->s3->exporter_secret,
                             ssl->s3->exporter_secret_len, (const uint8_t *)label,
                             label_len, hash, hash_len, out_len);
}
コード例 #11
0
ファイル: s3_enc.c プロジェクト: nyistsoft/openssl
int ssl3_digest_cached_records(SSL *s, int keep)
{
    int i;
    long mask;
    const EVP_MD *md;
    long hdatalen;
    void *hdata;

    if (s->s3->handshake_dgst == NULL) {
        /* Allocate handshake_dgst array */
        s->s3->handshake_dgst =
            OPENSSL_malloc(sizeof(*s->s3->handshake_dgst) * SSL_MAX_DIGEST);
        if (s->s3->handshake_dgst == NULL) {
            SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, ERR_R_MALLOC_FAILURE);
            return 0;
        }
        hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
        if (hdatalen <= 0) {
            SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, SSL_R_BAD_HANDSHAKE_LENGTH);
            return 0;
        }

        /* Loop through bits of algorithm2 field and create MD_CTX-es */
        for (i = 0; ssl_get_handshake_digest(i, &mask, &md); i++) {
            if ((mask & ssl_get_algorithm2(s)) && md) {
                s->s3->handshake_dgst[i] = EVP_MD_CTX_create();
                if (EVP_MD_nid(md) == NID_md5) {
                    EVP_MD_CTX_set_flags(s->s3->handshake_dgst[i],
                                         EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
                }
                EVP_DigestInit_ex(s->s3->handshake_dgst[i], md, NULL);
                EVP_DigestUpdate(s->s3->handshake_dgst[i], hdata, hdatalen);
            } else {
                s->s3->handshake_dgst[i] = NULL;
            }
        }

    }
    if (keep == 0) {
        BIO_free(s->s3->handshake_buffer);
        s->s3->handshake_buffer = NULL;
    }

    return 1;
}
コード例 #12
0
ファイル: s3_enc.c プロジェクト: LiTianjue/etls
int ssl3_init_handshake_hash(SSL *ssl) {
  ssl3_free_handshake_hash(ssl);

  uint32_t algorithm_prf = ssl_get_algorithm_prf(ssl);
  if (!init_digest_with_data(&ssl->s3->handshake_hash,
                             ssl_get_handshake_digest(algorithm_prf),
                             ssl->s3->handshake_buffer)) {
    return 0;
  }

  if (algorithm_prf == SSL_HANDSHAKE_MAC_DEFAULT &&
      !init_digest_with_data(&ssl->s3->handshake_md5, EVP_md5(),
                             ssl->s3->handshake_buffer)) {
    return 0;
  }

  return 1;
}
コード例 #13
0
ファイル: t1_enc.c プロジェクト: ThomasWo/proto-quic
int SSL_generate_key_block(const SSL *ssl, uint8_t *out, size_t out_len) {
  if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
    return ssl3_prf(out, out_len, SSL_get_session(ssl)->master_key,
                    SSL_get_session(ssl)->master_key_length,
                    TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
                    ssl->s3->server_random, SSL3_RANDOM_SIZE,
                    ssl->s3->client_random, SSL3_RANDOM_SIZE);
  }

  const EVP_MD *digest = ssl_get_handshake_digest(
      SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl));
  if (digest == NULL) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    return 0;
  }
  return tls1_prf(digest, out, out_len, SSL_get_session(ssl)->master_key,
                  SSL_get_session(ssl)->master_key_length,
                  TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
                  ssl->s3->server_random, SSL3_RANDOM_SIZE,
                  ssl->s3->client_random, SSL3_RANDOM_SIZE);
}
コード例 #14
0
int ssl3_digest_cached_records(SSL *s)
	{
	int i;
	long mask;
	const EVP_MD *md;
	long hdatalen;
	void *hdata;

	/* Allocate handshake_dgst array */
	ssl3_free_digest_list(s);
	s->s3->handshake_dgst = OPENSSL_malloc(SSL_MAX_DIGEST * sizeof(EVP_MD_CTX *));
	memset(s->s3->handshake_dgst,0,SSL_MAX_DIGEST *sizeof(EVP_MD_CTX *));
	hdatalen = BIO_get_mem_data(s->s3->handshake_buffer,&hdata);
	if (hdatalen <= 0)
		{
		SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, SSL_R_BAD_HANDSHAKE_LENGTH);
		return 0;
		}

	/* Loop through bitso of algorithm2 field and create MD_CTX-es */
	for (i=0;ssl_get_handshake_digest(i,&mask,&md); i++) 
		{
		if ((mask & s->s3->tmp.new_cipher->algorithm2) && md) 
			{
			s->s3->handshake_dgst[i]=EVP_MD_CTX_create();
			EVP_DigestInit_ex(s->s3->handshake_dgst[i],md,NULL);
			EVP_DigestUpdate(s->s3->handshake_dgst[i],hdata,hdatalen);
			} 
		else 
			{	
			s->s3->handshake_dgst[i]=NULL;
			}
		}
	/* Free handshake_buffer BIO */
	BIO_free(s->s3->handshake_buffer);
	s->s3->handshake_buffer = NULL;

	return 1;
	}
コード例 #15
0
ファイル: tls13_enc.c プロジェクト: onedata/helpers
int tls13_finished_mac(SSL *ssl, uint8_t *out, size_t *out_len, int is_server) {
    SSL_HANDSHAKE *hs = ssl->s3->hs;
    const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));

    uint8_t key[EVP_MAX_MD_SIZE];
    size_t key_len = EVP_MD_size(digest);

    uint8_t *traffic_secret;
    const char *label;
    if (is_server) {
        label = "server finished";
        if (ssl->server) {
            traffic_secret = ssl->s3->write_traffic_secret;
        } else {
            traffic_secret = ssl->s3->read_traffic_secret;
        }
    } else {
        label = "client finished";
        if (!ssl->server) {
            traffic_secret = ssl->s3->write_traffic_secret;
        } else {
            traffic_secret = ssl->s3->read_traffic_secret;
        }
    }

    uint8_t context_hashes[2 * EVP_MAX_MD_SIZE];
    size_t context_hashes_len;
    unsigned len;
    if (!hkdf_expand_label(key, digest, traffic_secret, hs->hash_len,
                           (const uint8_t *)label, strlen(label), NULL, 0,
                           hs->hash_len) ||
            !tls13_get_context_hashes(ssl, context_hashes, &context_hashes_len) ||
            HMAC(digest, key, key_len, context_hashes, context_hashes_len, out,
                 &len) == NULL) {
        return 0;
    }
    *out_len = len;
    return 1;
}
コード例 #16
0
ファイル: tls13_enc.c プロジェクト: onedata/helpers
int tls13_init_key_schedule(SSL *ssl, const uint8_t *resumption_ctx,
                            size_t resumption_ctx_len) {
    SSL_HANDSHAKE *hs = ssl->s3->hs;
    const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));

    hs->hash_len = EVP_MD_size(digest);

    /* Save the hash of the resumption context. */
    unsigned resumption_hash_len;
    if (!EVP_Digest(resumption_ctx, resumption_ctx_len, hs->resumption_hash,
                    &resumption_hash_len, digest, NULL)) {
        return 0;
    }

    /* Initialize the secret to the zero key. */
    memset(hs->secret, 0, hs->hash_len);

    /* Initialize the rolling hashes and release the handshake buffer. */
    if (!ssl3_init_handshake_hash(ssl)) {
        return 0;
    }
    ssl3_free_handshake_buffer(ssl);
    return 1;
}
コード例 #17
0
ファイル: tls13_server.c プロジェクト: gfxcc/iShareOC
static enum ssl_hs_wait_t do_select_parameters(SSL *ssl, SSL_HANDSHAKE *hs) {
  /* Call |cert_cb| to update server certificates if required. */
  if (ssl->cert->cert_cb != NULL) {
    int rv = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
    if (rv == 0) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_CB_ERROR);
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
      return ssl_hs_error;
    }
    if (rv < 0) {
      hs->state = state_select_parameters;
      return ssl_hs_x509_lookup;
    }
  }

  struct ssl_early_callback_ctx client_hello;
  if (!ssl_early_callback_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;
  }

  const SSL_CIPHER *cipher =
      ssl3_choose_cipher(ssl, &client_hello, ssl_get_cipher_preferences(ssl));
  if (cipher == NULL) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
    return ssl_hs_error;
  }

  ssl->s3->new_session->cipher = cipher;
  ssl->s3->tmp.new_cipher = cipher;

  ssl->method->received_flight(ssl);

  /* The PRF hash is now known. Set up the key schedule and hash the
   * ClientHello. */
  size_t hash_len =
      EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)));
  if (!tls13_init_key_schedule(ssl, kZeroes, hash_len)) {
    return ssl_hs_error;
  }

  /* Resolve PSK and incorporate it into the secret. */
  if (!resolve_psk_secret(ssl)) {
    return ssl_hs_error;
  }

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

  hs->state = state_send_server_hello;
  return ssl_hs_ok;
}
コード例 #18
0
ファイル: tls13_client.c プロジェクト: LiTianjue/etls
static enum ssl_hs_wait_t do_process_server_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
  if (!tls13_check_message_type(ssl, SSL3_MT_SERVER_HELLO)) {
    return ssl_hs_error;
  }

  CBS cbs, server_random, extensions;
  uint16_t server_wire_version;
  uint16_t cipher_suite;
  CBS_init(&cbs, ssl->init_msg, ssl->init_num);
  if (!CBS_get_u16(&cbs, &server_wire_version) ||
      !CBS_get_bytes(&cbs, &server_random, SSL3_RANDOM_SIZE) ||
      !CBS_get_u16(&cbs, &cipher_suite) ||
      !CBS_get_u16_length_prefixed(&cbs, &extensions) ||
      CBS_len(&cbs) != 0) {
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
    return ssl_hs_error;
  }

  if (server_wire_version != ssl->version) {
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_NUMBER);
    return ssl_hs_error;
  }

  /* Parse out the extensions. */
  int have_key_share = 0;
  CBS key_share;
  while (CBS_len(&extensions) != 0) {
    uint16_t type;
    CBS extension;
    if (!CBS_get_u16(&extensions, &type) ||
        !CBS_get_u16_length_prefixed(&extensions, &extension)) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
      return ssl_hs_error;
    }

    switch (type) {
      case TLSEXT_TYPE_key_share:
        if (have_key_share) {
          OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_EXTENSION);
          ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
          return ssl_hs_error;
        }
        key_share = extension;
        have_key_share = 1;
        break;
      default:
        OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
        return ssl_hs_error;
    }
  }

  assert(ssl->s3->have_version);
  memcpy(ssl->s3->server_random, CBS_data(&server_random), SSL3_RANDOM_SIZE);

  ssl->hit = 0;
  if (!ssl_get_new_session(ssl, 0)) {
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
    return ssl_hs_error;
  }

  const SSL_CIPHER *cipher = SSL_get_cipher_by_value(cipher_suite);
  if (cipher == NULL) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_RETURNED);
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
    return ssl_hs_error;
  }

  /* Check if the cipher is disabled. */
  if ((cipher->algorithm_mkey & ssl->cert->mask_k) ||
      (cipher->algorithm_auth & ssl->cert->mask_a) ||
      SSL_CIPHER_get_min_version(cipher) > ssl3_protocol_version(ssl) ||
      SSL_CIPHER_get_max_version(cipher) < ssl3_protocol_version(ssl) ||
      !sk_SSL_CIPHER_find(ssl_get_ciphers_by_id(ssl), NULL, cipher)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
    return ssl_hs_error;
  }

  ssl->session->cipher = cipher;
  ssl->s3->tmp.new_cipher = cipher;

  /* The PRF hash is now known. Set up the key schedule. */
  static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};
  size_t hash_len =
      EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)));
  if (!tls13_init_key_schedule(ssl, kZeroes, hash_len)) {
    return ssl_hs_error;
  }

  /* Resolve PSK and incorporate it into the secret. */
  if (cipher->algorithm_auth == SSL_aPSK) {
    /* TODO(davidben): Support PSK. */
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    return ssl_hs_error;
  } else if (!tls13_advance_key_schedule(ssl, kZeroes, hash_len)) {
    return ssl_hs_error;
  }

  /* Resolve ECDHE and incorporate it into the secret. */
  if (cipher->algorithm_mkey == SSL_kECDHE) {
    if (!have_key_share) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION);
      return ssl_hs_error;
    }

    uint8_t *dhe_secret;
    size_t dhe_secret_len;
    uint8_t alert = SSL_AD_DECODE_ERROR;
    if (!ext_key_share_parse_serverhello(ssl, &dhe_secret, &dhe_secret_len,
                                         &alert, &key_share)) {
      ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
      return ssl_hs_error;
    }

    int ok = tls13_advance_key_schedule(ssl, dhe_secret, dhe_secret_len);
    OPENSSL_free(dhe_secret);
    if (!ok) {
      return ssl_hs_error;
    }
  } else {
    if (have_key_share) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
      return ssl_hs_error;
    }
    if (!tls13_advance_key_schedule(ssl, kZeroes, hash_len)) {
      return ssl_hs_error;
    }
  }

  /* If there was no HelloRetryRequest, the version negotiation logic has
   * already hashed the message. */
  if (ssl->s3->hs->retry_group != 0 &&
      !ssl->method->hash_current_message(ssl)) {
    return ssl_hs_error;
  }

  if (!tls13_set_handshake_traffic(ssl)) {
    return ssl_hs_error;
  }

  hs->state = state_process_encrypted_extensions;
  return ssl_hs_read_message;
}
コード例 #19
0
ファイル: t1_enc.c プロジェクト: HungMingWu/libquic
int tls1_prf(SSL *s, uint8_t *out, size_t out_len, const uint8_t *secret,
             size_t secret_len, const char *label, size_t label_len,
             const uint8_t *seed1, size_t seed1_len,
             const uint8_t *seed2, size_t seed2_len) {
  size_t idx, len, count, i;
  const uint8_t *S1;
  long m;
  const EVP_MD *md;
  int ret = 0;
  uint8_t *tmp;

  if (out_len == 0) {
    return 1;
  }

  /* Allocate a temporary buffer. */
  tmp = OPENSSL_malloc(out_len);
  if (tmp == NULL) {
    OPENSSL_PUT_ERROR(SSL, tls1_prf, ERR_R_MALLOC_FAILURE);
    return 0;
  }

  /* Count number of digests and partition |secret| evenly. */
  count = 0;
  for (idx = 0; ssl_get_handshake_digest(idx, &m, &md); idx++) {
    if ((m << TLS1_PRF_DGST_SHIFT) & ssl_get_algorithm2(s)) {
      count++;
    }
  }
  /* TODO(davidben): The only case where count isn't 1 is the old MD5/SHA-1
   * combination. The logic around multiple handshake digests can probably be
   * simplified. */
  assert(count == 1 || count == 2);
  len = secret_len / count;
  if (count == 1) {
    secret_len = 0;
  }
  S1 = secret;
  memset(out, 0, out_len);
  for (idx = 0; ssl_get_handshake_digest(idx, &m, &md); idx++) {
    if ((m << TLS1_PRF_DGST_SHIFT) & ssl_get_algorithm2(s)) {
      /* If |count| is 2 and |secret_len| is odd, |secret| is partitioned into
       * two halves with an overlapping byte. */
      if (!tls1_P_hash(tmp, out_len, md, S1, len + (secret_len & 1),
                       (const uint8_t *)label, label_len, seed1, seed1_len,
                       seed2, seed2_len)) {
        goto err;
      }
      S1 += len;
      for (i = 0; i < out_len; i++) {
        out[i] ^= tmp[i];
      }
    }
  }
  ret = 1;

err:
  OPENSSL_cleanse(tmp, out_len);
  OPENSSL_free(tmp);
  return ret;
}
コード例 #20
0
ファイル: tls13_server.c プロジェクト: baiwyc119/proto-quic
static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) {
  SSL *const ssl = hs->ssl;
  /* The short record header extension is incompatible with early data. */
  if (ssl->s3->skip_early_data && ssl->s3->short_header) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
    return ssl_hs_error;
  }

  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;
  }

  /* Negotiate the cipher suite. */
  ssl->s3->tmp.new_cipher = choose_tls13_cipher(ssl, &client_hello);
  if (ssl->s3->tmp.new_cipher == NULL) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
    return ssl_hs_error;
  }

  /* Decode the ticket if we agree on a PSK key exchange mode. */
  uint8_t alert = SSL_AD_DECODE_ERROR;
  SSL_SESSION *session = NULL;
  CBS pre_shared_key, binders;
  if (hs->accept_psk_mode &&
      ssl_client_hello_get_extension(&client_hello, &pre_shared_key,
                                     TLSEXT_TYPE_pre_shared_key)) {
    /* Verify that the pre_shared_key extension is the last extension in
     * ClientHello. */
    if (CBS_data(&pre_shared_key) + CBS_len(&pre_shared_key) !=
        client_hello.extensions + client_hello.extensions_len) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_PRE_SHARED_KEY_MUST_BE_LAST);
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
      return ssl_hs_error;
    }

    if (!ssl_ext_pre_shared_key_parse_clienthello(hs, &session, &binders,
                                                  &alert, &pre_shared_key)) {
      ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
      return ssl_hs_error;
    }
  }

  if (session != NULL &&
      !ssl_session_is_resumable(ssl, session)) {
    SSL_SESSION_free(session);
    session = NULL;
  }

  /* Set up the new session, either using the original one as a template or
   * creating a fresh one. */
  if (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;
    }

    ssl->s3->new_session->cipher = ssl->s3->tmp.new_cipher;

    /* On new sessions, stash the SNI value in the session. */
    if (hs->hostname != NULL) {
      OPENSSL_free(ssl->s3->new_session->tlsext_hostname);
      ssl->s3->new_session->tlsext_hostname = BUF_strdup(hs->hostname);
      if (ssl->s3->new_session->tlsext_hostname == NULL) {
        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
        return ssl_hs_error;
      }
    }
  } else {
    /* Check the PSK binder. */
    if (!tls13_verify_psk_binder(ssl, session, &binders)) {
      SSL_SESSION_free(session);
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
      return ssl_hs_error;
    }

    /* Only authentication information carries over in TLS 1.3. */
    ssl->s3->new_session = SSL_SESSION_dup(session, SSL_SESSION_DUP_AUTH_ONLY);
    if (ssl->s3->new_session == NULL) {
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
      return ssl_hs_error;
    }
    ssl->s3->session_reused = 1;
    SSL_SESSION_free(session);

    /* Resumption incorporates fresh key material, so refresh the timeout. */
    ssl_session_renew_timeout(ssl, ssl->s3->new_session,
                              ssl->initial_ctx->session_psk_dhe_timeout);
  }

  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;
  }

  /* HTTP/2 negotiation depends on the cipher suite, so ALPN negotiation was
   * deferred. Complete it now. */
  if (!ssl_negotiate_alpn(hs, &alert, &client_hello)) {
    ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
    return ssl_hs_error;
  }

  /* The PRF hash is now known. Set up the key schedule and hash the
   * ClientHello. */
  size_t hash_len =
      EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)));
  if (!tls13_init_key_schedule(hs) ||
      !ssl_hash_current_message(ssl)) {
    return ssl_hs_error;
  }

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

  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) {
      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;
}
コード例 #21
0
ファイル: tls13_enc.c プロジェクト: onedata/helpers
int tls13_set_traffic_key(SSL *ssl, enum tls_record_type_t type,
                          enum evp_aead_direction_t direction,
                          const uint8_t *traffic_secret,
                          size_t traffic_secret_len) {
    if (traffic_secret_len > 0xff) {
        OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
        return 0;
    }

    const char *phase;
    switch (type) {
    case type_early_handshake:
        phase = "early handshake key expansion, ";
        break;
    case type_early_data:
        phase = "early application data key expansion, ";
        break;
    case type_handshake:
        phase = "handshake key expansion, ";
        break;
    case type_data:
        phase = "application data key expansion, ";
        break;
    default:
        return 0;
    }
    size_t phase_len = strlen(phase);

    const char *purpose = "client write key";
    if ((ssl->server && direction == evp_aead_seal) ||
            (!ssl->server && direction == evp_aead_open)) {
        purpose = "server write key";
    }
    size_t purpose_len = strlen(purpose);

    /* The longest label has length 38 (type_early_data) + 16 (either purpose
     * value). */
    uint8_t label[38 + 16];
    size_t label_len = phase_len + purpose_len;
    if (label_len > sizeof(label)) {
        assert(0);
        return 0;
    }
    memcpy(label, phase, phase_len);
    memcpy(label + phase_len, purpose, purpose_len);

    /* Look up cipher suite properties. */
    const EVP_AEAD *aead;
    const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
    size_t mac_secret_len, fixed_iv_len;
    if (!ssl_cipher_get_evp_aead(&aead, &mac_secret_len, &fixed_iv_len,
                                 ssl->session->cipher,
                                 ssl3_protocol_version(ssl))) {
        return 0;
    }

    /* Derive the key. */
    size_t key_len = EVP_AEAD_key_length(aead);
    uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
    if (!hkdf_expand_label(key, digest, traffic_secret, traffic_secret_len, label,
                           label_len, NULL, 0, key_len)) {
        return 0;
    }

    /* The IV's label ends in "iv" instead of "key". */
    if (label_len < 3) {
        assert(0);
        return 0;
    }
    label_len--;
    label[label_len - 2] = 'i';
    label[label_len - 1] = 'v';

    /* Derive the IV. */
    size_t iv_len = EVP_AEAD_nonce_length(aead);
    uint8_t iv[EVP_AEAD_MAX_NONCE_LENGTH];
    if (!hkdf_expand_label(iv, digest, traffic_secret, traffic_secret_len, label,
                           label_len, NULL, 0, iv_len)) {
        return 0;
    }

    SSL_AEAD_CTX *traffic_aead = SSL_AEAD_CTX_new(direction,
                                 ssl3_protocol_version(ssl),
                                 ssl->session->cipher,
                                 key, key_len, NULL, 0,
                                 iv, iv_len);
    if (traffic_aead == NULL) {
        return 0;
    }

    if (direction == evp_aead_open) {
        if (!ssl->method->set_read_state(ssl, traffic_aead)) {
            return 0;
        }
    } else {
        if (!ssl->method->set_write_state(ssl, traffic_aead)) {
            return 0;
        }
    }

    /* Save the traffic secret. */
    if (direction == evp_aead_open) {
        memcpy(ssl->s3->read_traffic_secret, traffic_secret, traffic_secret_len);
        ssl->s3->read_traffic_secret_len = traffic_secret_len;
    } else {
        memcpy(ssl->s3->write_traffic_secret, traffic_secret, traffic_secret_len);
        ssl->s3->write_traffic_secret_len = traffic_secret_len;
    }

    return 1;
}