示例#1
0
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;
}
示例#2
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 & 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;
	}
示例#3
0
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;
}
static int tls1_generate_key_block(SSL *s, unsigned char *km,
	     unsigned char *tmp, int num)
	{
	int ret;
	ret = tls1_PRF(ssl_get_algorithm2(s),
		 TLS_MD_KEY_EXPANSION_CONST,TLS_MD_KEY_EXPANSION_CONST_SIZE,
		 s->s3->server_random,SSL3_RANDOM_SIZE,
		 s->s3->client_random,SSL3_RANDOM_SIZE,
		 NULL,0,NULL,0,
		 s->session->master_key,s->session->master_key_length,
		 km,tmp,num);
#ifdef KSSL_DEBUG
	printf("tls1_generate_key_block() ==> %d byte master_key =\n\t",
                s->session->master_key_length);
	{
        int i;
        for (i=0; i < s->session->master_key_length; i++)
                {
                printf("%02X", s->session->master_key[i]);
                }
        printf("\n");  }
#endif    /* KSSL_DEBUG */
	return ret;
	}
int tls1_change_cipher_state(SSL *s, int which)
	{
	static const unsigned char empty[]="";
	unsigned char *p,*mac_secret;
	unsigned char *exp_label;
	unsigned char tmp1[EVP_MAX_KEY_LENGTH];
	unsigned char tmp2[EVP_MAX_KEY_LENGTH];
	unsigned char iv1[EVP_MAX_IV_LENGTH*2];
	unsigned char iv2[EVP_MAX_IV_LENGTH*2];
	unsigned char *ms,*key,*iv;
	int client_write;
	EVP_CIPHER_CTX *dd;
	const EVP_CIPHER *c;
#ifndef OPENSSL_NO_COMP
	const SSL_COMP *comp;
#endif
	const EVP_MD *m;
	int mac_type;
	int *mac_secret_size;
	EVP_MD_CTX *mac_ctx;
	EVP_PKEY *mac_key;
	int is_export,n,i,j,k,exp_label_len,cl;
	int reuse_dd = 0;

	is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher);
	c=s->s3->tmp.new_sym_enc;
	m=s->s3->tmp.new_hash;
	mac_type = s->s3->tmp.new_mac_pkey_type;
#ifndef OPENSSL_NO_COMP
	comp=s->s3->tmp.new_compression;
#endif

#ifdef KSSL_DEBUG
	printf("tls1_change_cipher_state(which= %d) w/\n", which);
	printf("\talg= %ld/%ld, comp= %p\n",
	       s->s3->tmp.new_cipher->algorithm_mkey,
	       s->s3->tmp.new_cipher->algorithm_auth,
	       comp);
	printf("\tevp_cipher == %p ==? &d_cbc_ede_cipher3\n", c);
	printf("\tevp_cipher: nid, blksz= %d, %d, keylen=%d, ivlen=%d\n",
                c->nid,c->block_size,c->key_len,c->iv_len);
	printf("\tkey_block: len= %d, data= ", s->s3->tmp.key_block_length);
	{
        int i;
        for (i=0; i<s->s3->tmp.key_block_length; i++)
		printf("%02x", s->s3->tmp.key_block[i]);  printf("\n");
        }
#endif	/* KSSL_DEBUG */

	if (which & SSL3_CC_READ)
		{
		if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC)
			s->mac_flags |= SSL_MAC_FLAG_READ_MAC_STREAM;
		else
			s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM;

		if (s->enc_read_ctx != NULL)
			reuse_dd = 1;
		else if ((s->enc_read_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)
			goto err;
		else
			/* make sure it's intialized in case we exit later with an error */
			EVP_CIPHER_CTX_init(s->enc_read_ctx);
		dd= s->enc_read_ctx;
		mac_ctx=ssl_replace_hash(&s->read_hash,NULL);
#ifndef OPENSSL_NO_COMP
		if (s->expand != NULL)
			{
			COMP_CTX_free(s->expand);
			s->expand=NULL;
			}
		if (comp != NULL)
			{
			s->expand=COMP_CTX_new(comp->method);
			if (s->expand == NULL)
				{
				SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR);
				goto err2;
				}
			if (s->s3->rrec.comp == NULL)
				s->s3->rrec.comp=(unsigned char *)
					OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH);
			if (s->s3->rrec.comp == NULL)
				goto err;
			}
#endif
		/* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */
 		if (s->version != DTLS1_VERSION)
			memset(&(s->s3->read_sequence[0]),0,8);
		mac_secret= &(s->s3->read_mac_secret[0]);
		mac_secret_size=&(s->s3->read_mac_secret_size);
		}
	else
		{
		if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC)
			s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM;
			else
			s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_STREAM;
		if (s->enc_write_ctx != NULL && !SSL_IS_DTLS(s))
			reuse_dd = 1;
		else if ((s->enc_write_ctx=EVP_CIPHER_CTX_new()) == NULL)
			goto err;
		dd= s->enc_write_ctx;
		if (SSL_IS_DTLS(s))
			{
			mac_ctx = EVP_MD_CTX_create();
			if (!mac_ctx)
				goto err;
			s->write_hash = mac_ctx;
			}
		else
			mac_ctx = ssl_replace_hash(&s->write_hash,NULL);
#ifndef OPENSSL_NO_COMP
		if (s->compress != NULL)
			{
			COMP_CTX_free(s->compress);
			s->compress=NULL;
			}
		if (comp != NULL)
			{
			s->compress=COMP_CTX_new(comp->method);
			if (s->compress == NULL)
				{
				SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR);
				goto err2;
				}
			}
#endif
		/* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */
 		if (s->version != DTLS1_VERSION)
			memset(&(s->s3->write_sequence[0]),0,8);
		mac_secret= &(s->s3->write_mac_secret[0]);
		mac_secret_size = &(s->s3->write_mac_secret_size);
		}

	if (reuse_dd)
		EVP_CIPHER_CTX_cleanup(dd);

	p=s->s3->tmp.key_block;
	i=*mac_secret_size=s->s3->tmp.new_mac_secret_size;

	cl=EVP_CIPHER_key_length(c);
	j=is_export ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ?
	               cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl;
	/* Was j=(exp)?5:EVP_CIPHER_key_length(c); */
	/* If GCM mode only part of IV comes from PRF */
	if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE)
		k = EVP_GCM_TLS_FIXED_IV_LEN;
	else
		k=EVP_CIPHER_iv_length(c);
	if (	(which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||
		(which == SSL3_CHANGE_CIPHER_SERVER_READ))
		{
		ms=  &(p[ 0]); n=i+i;
		key= &(p[ n]); n+=j+j;
		iv=  &(p[ n]); n+=k+k;
		exp_label=(unsigned char *)TLS_MD_CLIENT_WRITE_KEY_CONST;
		exp_label_len=TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE;
		client_write=1;
		}
	else
		{
		n=i;
		ms=  &(p[ n]); n+=i+j;
		key= &(p[ n]); n+=j+k;
		iv=  &(p[ n]); n+=k;
		exp_label=(unsigned char *)TLS_MD_SERVER_WRITE_KEY_CONST;
		exp_label_len=TLS_MD_SERVER_WRITE_KEY_CONST_SIZE;
		client_write=0;
		}

	if (n > s->s3->tmp.key_block_length)
		{
		SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_INTERNAL_ERROR);
		goto err2;
		}

	memcpy(mac_secret,ms,i);

	if (!(EVP_CIPHER_flags(c)&EVP_CIPH_FLAG_AEAD_CIPHER))
		{
		mac_key = EVP_PKEY_new_mac_key(mac_type, NULL,
				mac_secret,*mac_secret_size);
		EVP_DigestSignInit(mac_ctx,NULL,m,NULL,mac_key);
		EVP_PKEY_free(mac_key);
		}
#ifdef TLS_DEBUG
printf("which = %04X\nmac key=",which);
{ int z; for (z=0; z<i; z++) printf("%02X%c",ms[z],((z+1)%16)?' ':'\n'); }
#endif
	if (is_export)
		{
		/* In here I set both the read and write key/iv to the
		 * same value since only the correct one will be used :-).
		 */
		if (!tls1_PRF(ssl_get_algorithm2(s),
				exp_label,exp_label_len,
				s->s3->client_random,SSL3_RANDOM_SIZE,
				s->s3->server_random,SSL3_RANDOM_SIZE,
				NULL,0,NULL,0,
				key,j,tmp1,tmp2,EVP_CIPHER_key_length(c)))
			goto err2;
		key=tmp1;

		if (k > 0)
			{
			if (!tls1_PRF(ssl_get_algorithm2(s),
					TLS_MD_IV_BLOCK_CONST,TLS_MD_IV_BLOCK_CONST_SIZE,
					s->s3->client_random,SSL3_RANDOM_SIZE,
					s->s3->server_random,SSL3_RANDOM_SIZE,
					NULL,0,NULL,0,
					empty,0,iv1,iv2,k*2))
				goto err2;
			if (client_write)
				iv=iv1;
			else
				iv= &(iv1[k]);
			}
		}

	s->session->key_arg_length=0;
#ifdef KSSL_DEBUG
	{
        int i;
	printf("EVP_CipherInit_ex(dd,c,key=,iv=,which)\n");
	printf("\tkey= "); for (i=0; i<c->key_len; i++) printf("%02x", key[i]);
	printf("\n");
	printf("\t iv= "); for (i=0; i<c->iv_len; i++) printf("%02x", iv[i]);
	printf("\n");
	}
#endif	/* KSSL_DEBUG */

	if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE)
		{
		EVP_CipherInit_ex(dd,c,NULL,key,NULL,(which & SSL3_CC_WRITE));
		EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_GCM_SET_IV_FIXED, k, iv);
		}
	else	
		EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE));

	/* Needed for "composite" AEADs, such as RC4-HMAC-MD5 */
	if ((EVP_CIPHER_flags(c)&EVP_CIPH_FLAG_AEAD_CIPHER) && *mac_secret_size)
		EVP_CIPHER_CTX_ctrl(dd,EVP_CTRL_AEAD_SET_MAC_KEY,
				*mac_secret_size,mac_secret);

#ifdef TLS_DEBUG
printf("which = %04X\nkey=",which);
{ int z; for (z=0; z<EVP_CIPHER_key_length(c); z++) printf("%02X%c",key[z],((z+1)%16)?' ':'\n'); }
printf("\niv=");
{ int z; for (z=0; z<k; z++) printf("%02X%c",iv[z],((z+1)%16)?' ':'\n'); }
printf("\n");
#endif

	OPENSSL_cleanse(tmp1,sizeof(tmp1));
	OPENSSL_cleanse(tmp2,sizeof(tmp1));
	OPENSSL_cleanse(iv1,sizeof(iv1));
	OPENSSL_cleanse(iv2,sizeof(iv2));
	return(1);
err:
	SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_MALLOC_FAILURE);
err2:
	return(0);
	}
示例#6
0
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;
}