sha1-tlsprf.c revision 8d520ff1dc2da35cdca849e982051b86468016d8
124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner/* 224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner * TLS PRF (SHA1 + MD5) 324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> 424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner * 524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner * This program is free software; you can redistribute it and/or modify 624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner * it under the terms of the GNU General Public License version 2 as 724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner * published by the Free Software Foundation. 824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner * 924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner * Alternatively, this software may be distributed under the terms of BSD 1024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner * license. 1123b8abbe214c252028f6e09f79169529c846409dGreg Clayton * 1269aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton * See README and COPYING for more details. 137dd5c51fbab8384b18f20ecc125f9a1bb3c9bcb2Greg Clayton */ 1498f930f429160f9777f626c3ac6aa609f4e965d2Caroline Tice 157dd5c51fbab8384b18f20ecc125f9a1bb3c9bcb2Greg Clayton#include "includes.h" 1623b8abbe214c252028f6e09f79169529c846409dGreg Clayton 177dd5c51fbab8384b18f20ecc125f9a1bb3c9bcb2Greg Clayton#include "common.h" 187dd5c51fbab8384b18f20ecc125f9a1bb3c9bcb2Greg Clayton#include "sha1.h" 1924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "md5.h" 2069aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton#include "crypto.h" 2198f930f429160f9777f626c3ac6aa609f4e965d2Caroline Tice 227dd5c51fbab8384b18f20ecc125f9a1bb3c9bcb2Greg Clayton 237dd5c51fbab8384b18f20ecc125f9a1bb3c9bcb2Greg Clayton/** 247dd5c51fbab8384b18f20ecc125f9a1bb3c9bcb2Greg Clayton * tls_prf - Pseudo-Random Function for TLS (TLS-PRF, RFC 2246) 2524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner * @secret: Key for PRF 2624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner * @secret_len: Length of the key in bytes 2769aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton * @label: A unique label for each purpose of the PRF 2824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner * @seed: Seed value to bind into the key 2924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner * @seed_len: Length of the seed 3024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner * @out: Buffer for the generated pseudo-random key 3163094e0bb161580564954dee512955c1c79d3476Greg Clayton * @outlen: Number of bytes of key to generate 3224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner * Returns: 0 on success, -1 on failure. 3324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner * 3424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner * This function is used to derive new, cryptographically separate keys from a 3524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner * given key in TLS. This PRF is defined in RFC 2246, Chapter 5. 3663094e0bb161580564954dee512955c1c79d3476Greg Clayton */ 3724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerint tls_prf(const u8 *secret, size_t secret_len, const char *label, 3824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const u8 *seed, size_t seed_len, u8 *out, size_t outlen) 3924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 40538eb82a89a68dbc57251915080bd5152b333978Greg Clayton size_t L_S1, L_S2, i; 41538eb82a89a68dbc57251915080bd5152b333978Greg Clayton const u8 *S1, *S2; 42538eb82a89a68dbc57251915080bd5152b333978Greg Clayton u8 A_MD5[MD5_MAC_LEN], A_SHA1[SHA1_MAC_LEN]; 43538eb82a89a68dbc57251915080bd5152b333978Greg Clayton u8 P_MD5[MD5_MAC_LEN], P_SHA1[SHA1_MAC_LEN]; 44538eb82a89a68dbc57251915080bd5152b333978Greg Clayton int MD5_pos, SHA1_pos; 45538eb82a89a68dbc57251915080bd5152b333978Greg Clayton const u8 *MD5_addr[3]; 46538eb82a89a68dbc57251915080bd5152b333978Greg Clayton size_t MD5_len[3]; 47538eb82a89a68dbc57251915080bd5152b333978Greg Clayton const unsigned char *SHA1_addr[3]; 48538eb82a89a68dbc57251915080bd5152b333978Greg Clayton size_t SHA1_len[3]; 49538eb82a89a68dbc57251915080bd5152b333978Greg Clayton 50538eb82a89a68dbc57251915080bd5152b333978Greg Clayton if (secret_len & 1) 51538eb82a89a68dbc57251915080bd5152b333978Greg Clayton return -1; 5224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 5324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner MD5_addr[0] = A_MD5; 5463094e0bb161580564954dee512955c1c79d3476Greg Clayton MD5_len[0] = MD5_MAC_LEN; 5524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner MD5_addr[1] = (unsigned char *) label; 5624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner MD5_len[1] = os_strlen(label); 5724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner MD5_addr[2] = seed; 5824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner MD5_len[2] = seed_len; 5924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 6063094e0bb161580564954dee512955c1c79d3476Greg Clayton SHA1_addr[0] = A_SHA1; 6124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner SHA1_len[0] = SHA1_MAC_LEN; 6224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner SHA1_addr[1] = (unsigned char *) label; 6369aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton SHA1_len[1] = os_strlen(label); 6469aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton SHA1_addr[2] = seed; 6569aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton SHA1_len[2] = seed_len; 6669aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton 6769aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton /* RFC 2246, Chapter 5 6869aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton * A(0) = seed, A(i) = HMAC(secret, A(i-1)) 6969aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton * P_hash = HMAC(secret, A(1) + seed) + HMAC(secret, A(2) + seed) + .. 7069aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton * PRF = P_MD5(S1, label + seed) XOR P_SHA-1(S2, label + seed) 7169aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton */ 7269aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton 7369aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton L_S1 = L_S2 = (secret_len + 1) / 2; 7469aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton S1 = secret; 7569aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton S2 = secret + L_S1; 7669aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton if (secret_len & 1) { 7769aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton /* The last byte of S1 will be shared with S2 */ 7869aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton S2--; 7969aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton } 8069aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton 8169aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton hmac_md5_vector_non_fips_allow(S1, L_S1, 2, &MD5_addr[1], &MD5_len[1], 8269aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton A_MD5); 8369aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton hmac_sha1_vector(S2, L_S2, 2, &SHA1_addr[1], &SHA1_len[1], A_SHA1); 8469aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton 8569aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton MD5_pos = MD5_MAC_LEN; 8669aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton SHA1_pos = SHA1_MAC_LEN; 8769aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton for (i = 0; i < outlen; i++) { 8869aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton if (MD5_pos == MD5_MAC_LEN) { 8969aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton hmac_md5_vector_non_fips_allow(S1, L_S1, 3, MD5_addr, 9069aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton MD5_len, P_MD5); 9169aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton MD5_pos = 0; 9269aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton hmac_md5_non_fips_allow(S1, L_S1, A_MD5, MD5_MAC_LEN, 9369aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton A_MD5); 9469aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton } 9569aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton if (SHA1_pos == SHA1_MAC_LEN) { 9669aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton hmac_sha1_vector(S2, L_S2, 3, SHA1_addr, SHA1_len, 9769aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton P_SHA1); 9869aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton SHA1_pos = 0; 9969aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton hmac_sha1(S2, L_S2, A_SHA1, SHA1_MAC_LEN, A_SHA1); 10069aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton } 10169aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton 10269aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton out[i] = P_MD5[MD5_pos] ^ P_SHA1[SHA1_pos]; 10369aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton 10469aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton MD5_pos++; 10569aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton SHA1_pos++; 10669aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton } 10769aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton 10869aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton return 0; 10969aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton} 11069aa5d9a7620a183cdc4da12cc87ea82e2ffcbf9Greg Clayton