t1_enc.c 36.9 KB
Newer Older
		}

	if (ssl->version == DTLS1_VERSION || ssl->version == DTLS1_BAD_VER)
		{
		unsigned char dtlsseq[8],*p=dtlsseq;

		s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p);
		memcpy (p,&seq[2],6);

		memcpy(header, dtlsseq, 8);
		}
	else
		memcpy(header, seq, 8);

	/* kludge: tls1_cbc_remove_padding passes padding length in rec->type */
	orig_len = rec->length+md_size+((unsigned int)rec->type>>8);
	rec->type &= 0xff;

	header[8]=rec->type;
	header[9]=(unsigned char)(ssl->version>>8);
	header[10]=(unsigned char)(ssl->version);
	header[11]=(rec->length)>>8;
	header[12]=(rec->length)&0xff;

	if (!send &&
	    EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
	    ssl3_cbc_record_digest_supported(mac_ctx))
		{
		/* This is a CBC-encrypted record. We must avoid leaking any
		 * timing-side channel information about how many blocks of
		 * data we are hashing because that gives an attacker a
		 * timing-oracle. */
		ssl3_cbc_digest_record(
			mac_ctx,
			md, &md_size,
			header, rec->input,
			rec->length + md_size, orig_len,
			ssl->s3->read_mac_secret,
			ssl->s3->read_mac_secret_size,
			0 /* not SSLv3 */);
		}
	else
		{
		EVP_DigestSignUpdate(mac_ctx,header,sizeof(header));
		EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length);
		t=EVP_DigestSignFinal(mac_ctx,md,&md_size);
		OPENSSL_assert(t > 0);
#ifdef OPENSSL_FIPS
		if (!send && FIPS_mode())
			tls_fips_digest_extra(
	    				ssl->enc_read_ctx,
					mac_ctx, rec->input,
					rec->length, orig_len);
#endif
		}
		
	if (!stream_mac)
		EVP_MD_CTX_cleanup(&hmac);
#ifdef TLS_DEBUG
printf("seq=");
{int z; for (z=0; z<8; z++) printf("%02X ",seq[z]); printf("\n"); }
printf("rec=");
{unsigned int z; for (z=0; z<rec->length; z++) printf("%02X ",rec->data[z]); printf("\n"); }
#endif

	if (ssl->version != DTLS1_VERSION && ssl->version != DTLS1_BAD_VER)
		{
		for (i=7; i>=0; i--)
			{
			++seq[i];
			if (seq[i] != 0) break; 
			}
		}

#ifdef TLS_DEBUG
{unsigned int z; for (z=0; z<md_size; z++) printf("%02X ",md[z]); printf("\n"); }
#endif
	return(md_size);
	}

int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
	     int len)
	{
	unsigned char buff[SSL_MAX_MASTER_KEY_LENGTH];
	const void *co = NULL, *so = NULL;
	int col = 0, sol = 0;


#ifdef KSSL_DEBUG
	printf ("tls1_generate_master_secret(%p,%p, %p, %d)\n", s,out, p,len);
#endif	/* KSSL_DEBUG */

#ifdef TLSEXT_TYPE_opaque_prf_input
	if (s->s3->client_opaque_prf_input != NULL && s->s3->server_opaque_prf_input != NULL &&
	    s->s3->client_opaque_prf_input_len > 0 &&
	    s->s3->client_opaque_prf_input_len == s->s3->server_opaque_prf_input_len)
		{
		co = s->s3->client_opaque_prf_input;
		col = s->s3->server_opaque_prf_input_len;
		so = s->s3->server_opaque_prf_input;
		sol = s->s3->client_opaque_prf_input_len; /* must be same as col (see draft-rescorla-tls-opaque-prf-input-00.txt, section 3.1) */
		}
#endif

	tls1_PRF(ssl_get_algorithm2(s),
		TLS_MD_MASTER_SECRET_CONST,TLS_MD_MASTER_SECRET_CONST_SIZE,
		s->s3->client_random,SSL3_RANDOM_SIZE,
		co, col,
		s->s3->server_random,SSL3_RANDOM_SIZE,
		so, sol,
		p,len,
		s->session->master_key,buff,sizeof buff);
#ifdef SSL_DEBUG
	fprintf(stderr, "Premaster Secret:\n");
	BIO_dump_fp(stderr, (char *)p, len);
	fprintf(stderr, "Client Random:\n");
	BIO_dump_fp(stderr, (char *)s->s3->client_random, SSL3_RANDOM_SIZE);
	fprintf(stderr, "Server Random:\n");
	BIO_dump_fp(stderr, (char *)s->s3->server_random, SSL3_RANDOM_SIZE);
	fprintf(stderr, "Master Secret:\n");
	BIO_dump_fp(stderr, (char *)s->session->master_key, SSL3_MASTER_SECRET_SIZE);
#endif

#ifdef KSSL_DEBUG
	printf ("tls1_generate_master_secret() complete\n");
#endif	/* KSSL_DEBUG */
	return(SSL3_MASTER_SECRET_SIZE);
	}

int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen,
	 const char *label, size_t llen, const unsigned char *context,
	 size_t contextlen, int use_context)
	{
	unsigned char *buff;
	unsigned char *val = NULL;
	size_t vallen, currentvalpos;
	int rv;

#ifdef KSSL_DEBUG
	printf ("tls1_export_keying_material(%p,%p,%d,%s,%d,%p,%d)\n", s, out, olen, label, llen, context, contextlen);
#endif	/* KSSL_DEBUG */

	buff = OPENSSL_malloc(olen);
	if (buff == NULL) goto err2;

	/* construct PRF arguments
	 * we construct the PRF argument ourself rather than passing separate
	 * values into the TLS PRF to ensure that the concatenation of values
	 * does not create a prohibited label.
	 */
	vallen = llen + SSL3_RANDOM_SIZE * 2;
	if (use_context)
		{
		vallen += 2 + contextlen;
		}

	val = OPENSSL_malloc(vallen);
	if (val == NULL) goto err2;
	currentvalpos = 0;
	memcpy(val + currentvalpos, (unsigned char *) label, llen);
	currentvalpos += llen;
	memcpy(val + currentvalpos, s->s3->client_random, SSL3_RANDOM_SIZE);
	currentvalpos += SSL3_RANDOM_SIZE;
	memcpy(val + currentvalpos, s->s3->server_random, SSL3_RANDOM_SIZE);
	currentvalpos += SSL3_RANDOM_SIZE;

	if (use_context)
		{
		val[currentvalpos] = (contextlen >> 8) & 0xff;
		currentvalpos++;
		val[currentvalpos] = contextlen & 0xff;
		currentvalpos++;
		if ((contextlen > 0) || (context != NULL))
			{
			memcpy(val + currentvalpos, context, contextlen);
			}
		}

	/* disallow prohibited labels
	 * note that SSL3_RANDOM_SIZE > max(prohibited label len) =
	 * 15, so size of val > max(prohibited label len) = 15 and the
	 * comparisons won't have buffer overflow
	 */
	if (memcmp(val, TLS_MD_CLIENT_FINISH_CONST,
		 TLS_MD_CLIENT_FINISH_CONST_SIZE) == 0) goto err1;
	if (memcmp(val, TLS_MD_SERVER_FINISH_CONST,
		 TLS_MD_SERVER_FINISH_CONST_SIZE) == 0) goto err1;
	if (memcmp(val, TLS_MD_MASTER_SECRET_CONST,
		 TLS_MD_MASTER_SECRET_CONST_SIZE) == 0) goto err1;
	if (memcmp(val, TLS_MD_KEY_EXPANSION_CONST,
		 TLS_MD_KEY_EXPANSION_CONST_SIZE) == 0) goto err1;

	rv = tls1_PRF(ssl_get_algorithm2(s),
		      val, vallen,
		      NULL, 0,
		      NULL, 0,
		      NULL, 0,
		      NULL, 0,
		      s->session->master_key,s->session->master_key_length,
		      out,buff,olen);

#ifdef KSSL_DEBUG
	printf ("tls1_export_keying_material() complete\n");
#endif	/* KSSL_DEBUG */
	goto ret;
err1:
	SSLerr(SSL_F_TLS1_EXPORT_KEYING_MATERIAL, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL);
	rv = 0;
	goto ret;
err2:
	SSLerr(SSL_F_TLS1_EXPORT_KEYING_MATERIAL, ERR_R_MALLOC_FAILURE);
	rv = 0;
ret:
	if (buff != NULL) OPENSSL_free(buff);
	if (val != NULL) OPENSSL_free(val);
	return(rv);
	}

int tls1_alert_code(int code)
	{
	switch (code)
		{
	case SSL_AD_CLOSE_NOTIFY:	return(SSL3_AD_CLOSE_NOTIFY);
	case SSL_AD_UNEXPECTED_MESSAGE:	return(SSL3_AD_UNEXPECTED_MESSAGE);
	case SSL_AD_BAD_RECORD_MAC:	return(SSL3_AD_BAD_RECORD_MAC);
	case SSL_AD_DECRYPTION_FAILED:	return(TLS1_AD_DECRYPTION_FAILED);
	case SSL_AD_RECORD_OVERFLOW:	return(TLS1_AD_RECORD_OVERFLOW);
	case SSL_AD_DECOMPRESSION_FAILURE:return(SSL3_AD_DECOMPRESSION_FAILURE);
	case SSL_AD_HANDSHAKE_FAILURE:	return(SSL3_AD_HANDSHAKE_FAILURE);
	case SSL_AD_NO_CERTIFICATE:	return(-1);
	case SSL_AD_BAD_CERTIFICATE:	return(SSL3_AD_BAD_CERTIFICATE);
	case SSL_AD_UNSUPPORTED_CERTIFICATE:return(SSL3_AD_UNSUPPORTED_CERTIFICATE);
	case SSL_AD_CERTIFICATE_REVOKED:return(SSL3_AD_CERTIFICATE_REVOKED);
	case SSL_AD_CERTIFICATE_EXPIRED:return(SSL3_AD_CERTIFICATE_EXPIRED);
	case SSL_AD_CERTIFICATE_UNKNOWN:return(SSL3_AD_CERTIFICATE_UNKNOWN);
	case SSL_AD_ILLEGAL_PARAMETER:	return(SSL3_AD_ILLEGAL_PARAMETER);
	case SSL_AD_UNKNOWN_CA:		return(TLS1_AD_UNKNOWN_CA);
	case SSL_AD_ACCESS_DENIED:	return(TLS1_AD_ACCESS_DENIED);
	case SSL_AD_DECODE_ERROR:	return(TLS1_AD_DECODE_ERROR);
	case SSL_AD_DECRYPT_ERROR:	return(TLS1_AD_DECRYPT_ERROR);
	case SSL_AD_EXPORT_RESTRICTION:	return(TLS1_AD_EXPORT_RESTRICTION);
	case SSL_AD_PROTOCOL_VERSION:	return(TLS1_AD_PROTOCOL_VERSION);
	case SSL_AD_INSUFFICIENT_SECURITY:return(TLS1_AD_INSUFFICIENT_SECURITY);
	case SSL_AD_INTERNAL_ERROR:	return(TLS1_AD_INTERNAL_ERROR);
	case SSL_AD_USER_CANCELLED:	return(TLS1_AD_USER_CANCELLED);
	case SSL_AD_NO_RENEGOTIATION:	return(TLS1_AD_NO_RENEGOTIATION);
	case SSL_AD_UNSUPPORTED_EXTENSION: return(TLS1_AD_UNSUPPORTED_EXTENSION);
	case SSL_AD_CERTIFICATE_UNOBTAINABLE: return(TLS1_AD_CERTIFICATE_UNOBTAINABLE);
	case SSL_AD_UNRECOGNIZED_NAME:	return(TLS1_AD_UNRECOGNIZED_NAME);
	case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: return(TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE);
	case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(TLS1_AD_BAD_CERTIFICATE_HASH_VALUE);
	case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY);
	case SSL_AD_INAPPROPRIATE_FALLBACK:return(TLS1_AD_INAPPROPRIATE_FALLBACK);
#if 0 /* not appropriate for TLS, not used for DTLS */
	case DTLS1_AD_MISSING_HANDSHAKE_MESSAGE: return 
					  (DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
#endif
	default:			return(-1);
		}
	}