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