1/* 2 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10#include <assert.h> 11 12#include <openssl/bytestring.h> 13#include <openssl/digest.h> 14#include <openssl/hkdf.h> 15#include <openssl/hmac.h> 16#include <openssl/mem.h> 17 18#include "internal.h" 19#include "../../internal.h" 20#include "../service_indicator/internal.h" 21 22 23// tls1_P_hash computes the TLS P_<hash> function as described in RFC 5246, 24// section 5. It XORs |out_len| bytes to |out|, using |md| as the hash and 25// |secret| as the secret. |label|, |seed1|, and |seed2| are concatenated to 26// form the seed parameter. It returns true on success and false on failure. 27static int tls1_P_hash(uint8_t *out, size_t out_len, 28 const EVP_MD *md, 29 const uint8_t *secret, size_t secret_len, 30 const char *label, size_t label_len, 31 const uint8_t *seed1, size_t seed1_len, 32 const uint8_t *seed2, size_t seed2_len) { 33 HMAC_CTX ctx, ctx_tmp, ctx_init; 34 uint8_t A1[EVP_MAX_MD_SIZE]; 35 unsigned A1_len; 36 int ret = 0; 37 38 const size_t chunk = EVP_MD_size(md); 39 HMAC_CTX_init(&ctx); 40 HMAC_CTX_init(&ctx_tmp); 41 HMAC_CTX_init(&ctx_init); 42 43 if (!HMAC_Init_ex(&ctx_init, secret, secret_len, md, NULL) || 44 !HMAC_CTX_copy_ex(&ctx, &ctx_init) || 45 !HMAC_Update(&ctx, (const uint8_t *) label, label_len) || 46 !HMAC_Update(&ctx, seed1, seed1_len) || 47 !HMAC_Update(&ctx, seed2, seed2_len) || 48 !HMAC_Final(&ctx, A1, &A1_len)) { 49 goto err; 50 } 51 52 for (;;) { 53 unsigned len_u; 54 uint8_t hmac[EVP_MAX_MD_SIZE]; 55 if (!HMAC_CTX_copy_ex(&ctx, &ctx_init) || 56 !HMAC_Update(&ctx, A1, A1_len) || 57 // Save a copy of |ctx| to compute the next A1 value below. 58 (out_len > chunk && !HMAC_CTX_copy_ex(&ctx_tmp, &ctx)) || 59 !HMAC_Update(&ctx, (const uint8_t *) label, label_len) || 60 !HMAC_Update(&ctx, seed1, seed1_len) || 61 !HMAC_Update(&ctx, seed2, seed2_len) || 62 !HMAC_Final(&ctx, hmac, &len_u)) { 63 goto err; 64 } 65 size_t len = len_u; 66 assert(len == chunk); 67 68 // XOR the result into |out|. 69 if (len > out_len) { 70 len = out_len; 71 } 72 for (size_t i = 0; i < len; i++) { 73 out[i] ^= hmac[i]; 74 } 75 out += len; 76 out_len -= len; 77 78 if (out_len == 0) { 79 break; 80 } 81 82 // Calculate the next A1 value. 83 if (!HMAC_Final(&ctx_tmp, A1, &A1_len)) { 84 goto err; 85 } 86 } 87 88 ret = 1; 89 90err: 91 OPENSSL_cleanse(A1, sizeof(A1)); 92 HMAC_CTX_cleanup(&ctx); 93 HMAC_CTX_cleanup(&ctx_tmp); 94 HMAC_CTX_cleanup(&ctx_init); 95 return ret; 96} 97 98int CRYPTO_tls1_prf(const EVP_MD *digest, 99 uint8_t *out, size_t out_len, 100 const uint8_t *secret, size_t secret_len, 101 const char *label, size_t label_len, 102 const uint8_t *seed1, size_t seed1_len, 103 const uint8_t *seed2, size_t seed2_len) { 104 if (out_len == 0) { 105 return 1; 106 } 107 108 OPENSSL_memset(out, 0, out_len); 109 110 const EVP_MD *const original_digest = digest; 111 FIPS_service_indicator_lock_state(); 112 int ret = 0; 113 114 if (digest == EVP_md5_sha1()) { 115 // If using the MD5/SHA1 PRF, |secret| is partitioned between MD5 and SHA-1. 116 size_t secret_half = secret_len - (secret_len / 2); 117 if (!tls1_P_hash(out, out_len, EVP_md5(), secret, secret_half, label, 118 label_len, seed1, seed1_len, seed2, seed2_len)) { 119 goto end; 120 } 121 122 // Note that, if |secret_len| is odd, the two halves share a byte. 123 secret += secret_len - secret_half; 124 secret_len = secret_half; 125 digest = EVP_sha1(); 126 } 127 128 ret = tls1_P_hash(out, out_len, digest, secret, secret_len, label, label_len, 129 seed1, seed1_len, seed2, seed2_len); 130 131end: 132 FIPS_service_indicator_unlock_state(); 133 if (ret) { 134 TLSKDF_verify_service_indicator(original_digest); 135 } 136 return ret; 137} 138 139int CRYPTO_tls13_hkdf_expand_label(uint8_t *out, size_t out_len, 140 const EVP_MD *digest, // 141 const uint8_t *secret, size_t secret_len, 142 const uint8_t *label, size_t label_len, 143 const uint8_t *hash, size_t hash_len) { 144 static const uint8_t kProtocolLabel[] = "tls13 "; 145 CBB cbb, child; 146 uint8_t *hkdf_label = NULL; 147 size_t hkdf_label_len; 148 149 FIPS_service_indicator_lock_state(); 150 CBB_zero(&cbb); 151 if (!CBB_init(&cbb, 2 + 1 + sizeof(kProtocolLabel) - 1 + label_len + 1 + 152 hash_len) || 153 !CBB_add_u16(&cbb, out_len) || 154 !CBB_add_u8_length_prefixed(&cbb, &child) || 155 !CBB_add_bytes(&child, kProtocolLabel, sizeof(kProtocolLabel) - 1) || 156 !CBB_add_bytes(&child, label, label_len) || 157 !CBB_add_u8_length_prefixed(&cbb, &child) || 158 !CBB_add_bytes(&child, hash, hash_len) || 159 !CBB_finish(&cbb, &hkdf_label, &hkdf_label_len)) { 160 CBB_cleanup(&cbb); 161 FIPS_service_indicator_unlock_state(); 162 return 0; 163 } 164 165 const int ret = HKDF_expand(out, out_len, digest, secret, secret_len, 166 hkdf_label, hkdf_label_len); 167 OPENSSL_free(hkdf_label); 168 169 FIPS_service_indicator_unlock_state(); 170 if (ret) { 171 TLSKDF_verify_service_indicator(digest); 172 } 173 return ret; 174} 175 176