xref: /freebsd/contrib/wpa/src/crypto/sha512.c (revision a90b9d0159070121c221b966469c3e36d912bf82)
14bc52338SCy Schubert /*
24bc52338SCy Schubert  * SHA-512 hash implementation and interface functions
34bc52338SCy Schubert  * Copyright (c) 2003-2018, Jouni Malinen <j@w1.fi>
44bc52338SCy Schubert  *
54bc52338SCy Schubert  * This software may be distributed under the terms of the BSD license.
64bc52338SCy Schubert  * See README for more details.
74bc52338SCy Schubert  */
84bc52338SCy Schubert 
94bc52338SCy Schubert #include "includes.h"
104bc52338SCy Schubert 
114bc52338SCy Schubert #include "common.h"
124bc52338SCy Schubert #include "sha512.h"
134bc52338SCy Schubert #include "crypto.h"
144bc52338SCy Schubert 
154bc52338SCy Schubert 
164bc52338SCy Schubert /**
174bc52338SCy Schubert  * hmac_sha512_vector - HMAC-SHA512 over data vector (RFC 2104)
184bc52338SCy Schubert  * @key: Key for HMAC operations
194bc52338SCy Schubert  * @key_len: Length of the key in bytes
204bc52338SCy Schubert  * @num_elem: Number of elements in the data vector
214bc52338SCy Schubert  * @addr: Pointers to the data areas
224bc52338SCy Schubert  * @len: Lengths of the data blocks
234bc52338SCy Schubert  * @mac: Buffer for the hash (64 bytes)
244bc52338SCy Schubert  * Returns: 0 on success, -1 on failure
254bc52338SCy Schubert  */
hmac_sha512_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)264bc52338SCy Schubert int hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem,
274bc52338SCy Schubert 		       const u8 *addr[], const size_t *len, u8 *mac)
284bc52338SCy Schubert {
294bc52338SCy Schubert 	unsigned char k_pad[128]; /* padding - key XORd with ipad/opad */
304bc52338SCy Schubert 	unsigned char tk[64];
31*a90b9d01SCy Schubert 	const u8 *_addr[HMAC_VECTOR_MAX_ELEM + 1];
32*a90b9d01SCy Schubert 	size_t _len[HMAC_VECTOR_MAX_ELEM + 1], i;
334bc52338SCy Schubert 
34*a90b9d01SCy Schubert 	if (num_elem > HMAC_VECTOR_MAX_ELEM) {
354bc52338SCy Schubert 		/*
364bc52338SCy Schubert 		 * Fixed limit on the number of fragments to avoid having to
374bc52338SCy Schubert 		 * allocate memory (which could fail).
384bc52338SCy Schubert 		 */
394bc52338SCy Schubert 		return -1;
404bc52338SCy Schubert 	}
414bc52338SCy Schubert 
424bc52338SCy Schubert 	/* if key is longer than 128 bytes reset it to key = SHA512(key) */
434bc52338SCy Schubert 	if (key_len > 128) {
444bc52338SCy Schubert 		if (sha512_vector(1, &key, &key_len, tk) < 0)
454bc52338SCy Schubert 			return -1;
464bc52338SCy Schubert 		key = tk;
474bc52338SCy Schubert 		key_len = 64;
484bc52338SCy Schubert 	}
494bc52338SCy Schubert 
504bc52338SCy Schubert 	/* the HMAC_SHA512 transform looks like:
514bc52338SCy Schubert 	 *
524bc52338SCy Schubert 	 * SHA512(K XOR opad, SHA512(K XOR ipad, text))
534bc52338SCy Schubert 	 *
544bc52338SCy Schubert 	 * where K is an n byte key
554bc52338SCy Schubert 	 * ipad is the byte 0x36 repeated 128 times
564bc52338SCy Schubert 	 * opad is the byte 0x5c repeated 128 times
574bc52338SCy Schubert 	 * and text is the data being protected */
584bc52338SCy Schubert 
594bc52338SCy Schubert 	/* start out by storing key in ipad */
604bc52338SCy Schubert 	os_memset(k_pad, 0, sizeof(k_pad));
614bc52338SCy Schubert 	os_memcpy(k_pad, key, key_len);
624bc52338SCy Schubert 	/* XOR key with ipad values */
634bc52338SCy Schubert 	for (i = 0; i < 128; i++)
644bc52338SCy Schubert 		k_pad[i] ^= 0x36;
654bc52338SCy Schubert 
664bc52338SCy Schubert 	/* perform inner SHA512 */
674bc52338SCy Schubert 	_addr[0] = k_pad;
684bc52338SCy Schubert 	_len[0] = 128;
694bc52338SCy Schubert 	for (i = 0; i < num_elem; i++) {
704bc52338SCy Schubert 		_addr[i + 1] = addr[i];
714bc52338SCy Schubert 		_len[i + 1] = len[i];
724bc52338SCy Schubert 	}
734bc52338SCy Schubert 	if (sha512_vector(1 + num_elem, _addr, _len, mac) < 0)
744bc52338SCy Schubert 		return -1;
754bc52338SCy Schubert 
764bc52338SCy Schubert 	os_memset(k_pad, 0, sizeof(k_pad));
774bc52338SCy Schubert 	os_memcpy(k_pad, key, key_len);
784bc52338SCy Schubert 	/* XOR key with opad values */
794bc52338SCy Schubert 	for (i = 0; i < 128; i++)
804bc52338SCy Schubert 		k_pad[i] ^= 0x5c;
814bc52338SCy Schubert 
824bc52338SCy Schubert 	/* perform outer SHA512 */
834bc52338SCy Schubert 	_addr[0] = k_pad;
844bc52338SCy Schubert 	_len[0] = 128;
854bc52338SCy Schubert 	_addr[1] = mac;
864bc52338SCy Schubert 	_len[1] = SHA512_MAC_LEN;
874bc52338SCy Schubert 	return sha512_vector(2, _addr, _len, mac);
884bc52338SCy Schubert }
894bc52338SCy Schubert 
904bc52338SCy Schubert 
914bc52338SCy Schubert /**
924bc52338SCy Schubert  * hmac_sha512 - HMAC-SHA512 over data buffer (RFC 2104)
934bc52338SCy Schubert  * @key: Key for HMAC operations
944bc52338SCy Schubert  * @key_len: Length of the key in bytes
954bc52338SCy Schubert  * @data: Pointers to the data area
964bc52338SCy Schubert  * @data_len: Length of the data area
974bc52338SCy Schubert  * @mac: Buffer for the hash (64 bytes)
984bc52338SCy Schubert  * Returns: 0 on success, -1 on failure
994bc52338SCy Schubert  */
hmac_sha512(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)1004bc52338SCy Schubert int hmac_sha512(const u8 *key, size_t key_len, const u8 *data,
1014bc52338SCy Schubert 		size_t data_len, u8 *mac)
1024bc52338SCy Schubert {
1034bc52338SCy Schubert 	return hmac_sha512_vector(key, key_len, 1, &data, &data_len, mac);
1044bc52338SCy Schubert }
105