Beispiel #1
0
int tls1_prf(const EVP_MD *digest, 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;
  }

  OPENSSL_memset(out, 0, out_len);

  if (digest == EVP_md5_sha1()) {
    /* 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;

    digest = EVP_sha1();
  }

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

  return 1;
}
Beispiel #2
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) {

  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;
}
Beispiel #3
0
int CRYPTO_tls1_prf(const EVP_MD *digest,
                    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;
  }

  OPENSSL_memset(out, 0, out_len);

  if (digest == EVP_md5_sha1()) {
    // If using the MD5/SHA1 PRF, |secret| is partitioned between MD5 and SHA-1.
    size_t secret_half = secret_len - (secret_len / 2);
    if (!tls1_P_hash(out, out_len, EVP_md5(), secret, secret_half, 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_len - secret_half;
    secret_len = secret_half;
    digest = EVP_sha1();
  }

  return tls1_P_hash(out, out_len, digest, secret, secret_len, label, label_len,
                     seed1, seed1_len, seed2, seed2_len);
}
Beispiel #4
0
int tls1_PRF( const u_char* secret, uint32_t secret_len, const char* label, 
		u_char* random1, uint32_t random1_len, u_char* random2, uint32_t random2_len,
		u_char *out, uint32_t out_len )
{
	uint32_t len;
	uint32_t i;
	const u_char *S1,*S2;
	u_char* out_tmp;
	u_char* seed;
	uint32_t seed_len;
	u_char* p;

	if( !label || !out || out_len == 0 ) { _ASSERT( FALSE); return NM_ERROR( DSSL_E_INVALID_PARAMETER ); }

	/* allocate a temporary buffer for second output stream */
	out_tmp = (u_char*) malloc( out_len );
	if( !out_tmp ) return NM_ERROR( DSSL_E_OUT_OF_MEMORY );

	/* allocate and initialize the seed */
	seed_len = (uint32_t)strlen( label ) + random1_len + random2_len;
	seed = (u_char*) malloc( seed_len );
	if( !seed ) 
	{
		free( out_tmp );
		return NM_ERROR( DSSL_E_OUT_OF_MEMORY );
	}

	p = seed;
	memcpy( p, label, strlen( label ) ); p+= strlen( label );
	memcpy( p, random1, random1_len ); p+= random1_len;
	memcpy( p, random2, random2_len );

	/* split the secret into halves */
	len = (secret_len / 2) + (secret_len % 2);
	S1 = secret;
	S2 = secret + secret_len - len;

	DEBUG_TRACE_BUF("secret", secret, secret_len);
	DEBUG_TRACE_BUF("seed", seed, seed_len);
	tls1_P_hash( EVP_md5(), S1, len, seed, seed_len, out, out_len );
	tls1_P_hash( EVP_sha1(), S2, len, seed, seed_len, out_tmp, out_len );

	for( i=0; i < out_len; i++ ) out[i] ^= out_tmp[i];

	DEBUG_TRACE_BUF("result", out, out_len);

	free( seed );
	free( out_tmp );

	return DSSL_RC_OK;
}
Beispiel #5
0
static void tls1_PRF(const EVP_MD *md5, const EVP_MD *sha1,
		     unsigned char *label, int label_len,
		     const unsigned char *sec, int slen, unsigned char *out1,
		     unsigned char *out2, int olen)
	{
	int len,i;
	const unsigned char *S1,*S2;

	len=slen/2;
	S1=sec;
	S2= &(sec[len]);
	len+=(slen&1); /* add for odd, make longer */

	
	tls1_P_hash(md5 ,S1,len,label,label_len,out1,olen);
	tls1_P_hash(sha1,S2,len,label,label_len,out2,olen);

	for (i=0; i<olen; i++)
		out1[i]^=out2[i];
	}
Beispiel #6
0
int tls12_PRF( const EVP_MD *md, const u_char* secret, uint32_t secret_len, const char* label, 
		u_char* random1, uint32_t random1_len, u_char* random2, uint32_t random2_len,
		u_char *out, uint32_t out_len )
{
	uint32_t len;
	uint32_t i;
	const u_char *S1,*S2;
	u_char* out_tmp;
	u_char* seed;
	uint32_t seed_len;
	u_char* p;

	if( !label || !out || out_len == 0 ) { _ASSERT( FALSE); return NM_ERROR( DSSL_E_INVALID_PARAMETER ); }
	
	/* 'sha256' is the default for TLS 1.2.
	 * also, do not allow anything less secure...
	 */
	if ( !md )
		md = EVP_sha256();
	else if ( EVP_MD_size( md ) < EVP_MD_size( EVP_sha256() ) )
		md = EVP_sha256();

	/* allocate a temporary buffer for second output stream */
	out_tmp = (u_char*) malloc( out_len );
	if( !out_tmp ) return NM_ERROR( DSSL_E_OUT_OF_MEMORY );

	/* allocate and initialize the seed */
	seed_len = (uint32_t)strlen( label ) + random1_len + random2_len;
	seed = (u_char*) malloc( seed_len );
	if( !seed ) 
	{
		free( out_tmp );
		return NM_ERROR( DSSL_E_OUT_OF_MEMORY );
	}

	p = seed;
	memcpy( p, label, strlen( label ) ); p+= strlen( label );
	memcpy( p, random1, random1_len ); p+= random1_len;
	memcpy( p, random2, random2_len );

	DEBUG_TRACE_BUF("secret", secret, secret_len);
	DEBUG_TRACE_BUF("seed", seed, seed_len);
	tls1_P_hash( md, secret, secret_len, seed, seed_len, out_tmp, out_len );
	DEBUG_TRACE_BUF("result", out_tmp, out_len);
	
	DEBUG_TRACE3( "\nsecret(%d) + seed(%u)=out(%u)\n", secret_len, seed_len, out_len);

	for( i=0; i < out_len; i++ ) out[i] = out_tmp[i];

	free( seed );
	free( out_tmp );

	return DSSL_RC_OK;
}
/* 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;
}
Beispiel #8
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;
}