/*1* Copyright (c) 2016 Thomas Pornin <[email protected]>2*3* Permission is hereby granted, free of charge, to any person obtaining4* a copy of this software and associated documentation files (the5* "Software"), to deal in the Software without restriction, including6* without limitation the rights to use, copy, modify, merge, publish,7* distribute, sublicense, and/or sell copies of the Software, and to8* permit persons to whom the Software is furnished to do so, subject to9* the following conditions:10*11* The above copyright notice and this permission notice shall be12* included in all copies or substantial portions of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,15* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF16* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND17* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS18* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN19* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN20* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE21* SOFTWARE.22*/2324#include "inner.h"2526/* see inner.h */27void28br_tls_phash(void *dst, size_t len,29const br_hash_class *dig,30const void *secret, size_t secret_len, const char *label,31size_t seed_num, const br_tls_prf_seed_chunk *seed)32{33unsigned char *buf;34unsigned char tmp[64], a[64];35br_hmac_key_context kc;36br_hmac_context hc;37size_t label_len, hlen, u;3839if (len == 0) {40return;41}42buf = dst;43for (label_len = 0; label[label_len]; label_len ++);44hlen = br_digest_size(dig);45br_hmac_key_init(&kc, dig, secret, secret_len);46br_hmac_init(&hc, &kc, 0);47br_hmac_update(&hc, label, label_len);48for (u = 0; u < seed_num; u ++) {49br_hmac_update(&hc, seed[u].data, seed[u].len);50}51br_hmac_out(&hc, a);52for (;;) {53br_hmac_init(&hc, &kc, 0);54br_hmac_update(&hc, a, hlen);55br_hmac_update(&hc, label, label_len);56for (u = 0; u < seed_num; u ++) {57br_hmac_update(&hc, seed[u].data, seed[u].len);58}59br_hmac_out(&hc, tmp);60for (u = 0; u < hlen && u < len; u ++) {61buf[u] ^= tmp[u];62}63buf += u;64len -= u;65if (len == 0) {66return;67}68br_hmac_init(&hc, &kc, 0);69br_hmac_update(&hc, a, hlen);70br_hmac_out(&hc, a);71}72}737475