xref: /freebsd/sys/geom/eli/g_eli_hmac.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
14332fecaSAllan Jude /*-
24332fecaSAllan Jude  * Copyright (c) 2005-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
34332fecaSAllan Jude  * All rights reserved.
44332fecaSAllan Jude  *
54332fecaSAllan Jude  * Redistribution and use in source and binary forms, with or without
64332fecaSAllan Jude  * modification, are permitted provided that the following conditions
74332fecaSAllan Jude  * are met:
84332fecaSAllan Jude  * 1. Redistributions of source code must retain the above copyright
94332fecaSAllan Jude  *    notice, this list of conditions and the following disclaimer.
104332fecaSAllan Jude  * 2. Redistributions in binary form must reproduce the above copyright
114332fecaSAllan Jude  *    notice, this list of conditions and the following disclaimer in the
124332fecaSAllan Jude  *    documentation and/or other materials provided with the distribution.
134332fecaSAllan Jude  *
144332fecaSAllan Jude  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
154332fecaSAllan Jude  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
164332fecaSAllan Jude  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
174332fecaSAllan Jude  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
184332fecaSAllan Jude  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
194332fecaSAllan Jude  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
204332fecaSAllan Jude  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
214332fecaSAllan Jude  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
224332fecaSAllan Jude  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
234332fecaSAllan Jude  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
244332fecaSAllan Jude  * SUCH DAMAGE.
254332fecaSAllan Jude  */
264332fecaSAllan Jude 
274332fecaSAllan Jude #include <sys/param.h>
284332fecaSAllan Jude #ifdef _KERNEL
294332fecaSAllan Jude #include <sys/systm.h>
304332fecaSAllan Jude #include <sys/kernel.h>
314332fecaSAllan Jude #include <sys/malloc.h>
32700b6f8eSWarner Losh #elif defined(_STANDALONE)
33700b6f8eSWarner Losh #include "stand.h"
344332fecaSAllan Jude #else
354332fecaSAllan Jude #include <stdint.h>
364332fecaSAllan Jude #include <string.h>
374332fecaSAllan Jude #include <strings.h>
384332fecaSAllan Jude #include <errno.h>
394332fecaSAllan Jude #include <assert.h>
404332fecaSAllan Jude #include <openssl/evp.h>
414332fecaSAllan Jude #define	_OpenSSL_
424332fecaSAllan Jude #endif
434332fecaSAllan Jude #include <geom/eli/g_eli.h>
444332fecaSAllan Jude 
454332fecaSAllan Jude void
g_eli_crypto_hmac_init(struct hmac_ctx * ctx,const char * hkey,size_t hkeylen)46*e7630efbSMariusz Zaborski g_eli_crypto_hmac_init(struct hmac_ctx *ctx, const char *hkey,
474332fecaSAllan Jude     size_t hkeylen)
484332fecaSAllan Jude {
4985c15ab8SAllan Jude 	u_char k_ipad[128], k_opad[128], key[128];
504332fecaSAllan Jude 	SHA512_CTX lctx;
514332fecaSAllan Jude 	u_int i;
524332fecaSAllan Jude 
534332fecaSAllan Jude 	bzero(key, sizeof(key));
544332fecaSAllan Jude 	if (hkeylen == 0)
554332fecaSAllan Jude 		; /* do nothing */
564332fecaSAllan Jude 	else if (hkeylen <= 128)
574332fecaSAllan Jude 		bcopy(hkey, key, hkeylen);
584332fecaSAllan Jude 	else {
594332fecaSAllan Jude 		/* If key is longer than 128 bytes reset it to key = SHA512(key). */
604332fecaSAllan Jude 		SHA512_Init(&lctx);
614332fecaSAllan Jude 		SHA512_Update(&lctx, hkey, hkeylen);
624332fecaSAllan Jude 		SHA512_Final(key, &lctx);
634332fecaSAllan Jude 	}
644332fecaSAllan Jude 
654332fecaSAllan Jude 	/* XOR key with ipad and opad values. */
664332fecaSAllan Jude 	for (i = 0; i < sizeof(key); i++) {
674332fecaSAllan Jude 		k_ipad[i] = key[i] ^ 0x36;
6885c15ab8SAllan Jude 		k_opad[i] = key[i] ^ 0x5c;
694332fecaSAllan Jude 	}
7085c15ab8SAllan Jude 	explicit_bzero(key, sizeof(key));
7185c15ab8SAllan Jude 	/* Start inner SHA512. */
7285c15ab8SAllan Jude 	SHA512_Init(&ctx->innerctx);
7385c15ab8SAllan Jude 	SHA512_Update(&ctx->innerctx, k_ipad, sizeof(k_ipad));
7485c15ab8SAllan Jude 	explicit_bzero(k_ipad, sizeof(k_ipad));
7585c15ab8SAllan Jude 	/* Start outer SHA512. */
7685c15ab8SAllan Jude 	SHA512_Init(&ctx->outerctx);
7785c15ab8SAllan Jude 	SHA512_Update(&ctx->outerctx, k_opad, sizeof(k_opad));
7885c15ab8SAllan Jude 	explicit_bzero(k_opad, sizeof(k_opad));
794332fecaSAllan Jude }
804332fecaSAllan Jude 
814332fecaSAllan Jude void
g_eli_crypto_hmac_update(struct hmac_ctx * ctx,const uint8_t * data,size_t datasize)824332fecaSAllan Jude g_eli_crypto_hmac_update(struct hmac_ctx *ctx, const uint8_t *data,
834332fecaSAllan Jude     size_t datasize)
844332fecaSAllan Jude {
854332fecaSAllan Jude 
8685c15ab8SAllan Jude 	SHA512_Update(&ctx->innerctx, data, datasize);
874332fecaSAllan Jude }
884332fecaSAllan Jude 
894332fecaSAllan Jude void
g_eli_crypto_hmac_final(struct hmac_ctx * ctx,uint8_t * md,size_t mdsize)904332fecaSAllan Jude g_eli_crypto_hmac_final(struct hmac_ctx *ctx, uint8_t *md, size_t mdsize)
914332fecaSAllan Jude {
924332fecaSAllan Jude 	u_char digest[SHA512_MDLEN];
934332fecaSAllan Jude 
9485c15ab8SAllan Jude 	/* Complete inner hash */
9585c15ab8SAllan Jude 	SHA512_Final(digest, &ctx->innerctx);
9685c15ab8SAllan Jude 
9785c15ab8SAllan Jude 	/* Complete outer hash */
9885c15ab8SAllan Jude 	SHA512_Update(&ctx->outerctx, digest, sizeof(digest));
9985c15ab8SAllan Jude 	SHA512_Final(digest, &ctx->outerctx);
10085c15ab8SAllan Jude 
10185c15ab8SAllan Jude 	explicit_bzero(ctx, sizeof(*ctx));
1024332fecaSAllan Jude 	/* mdsize == 0 means "Give me the whole hash!" */
1034332fecaSAllan Jude 	if (mdsize == 0)
1044332fecaSAllan Jude 		mdsize = SHA512_MDLEN;
1054332fecaSAllan Jude 	bcopy(digest, md, mdsize);
10685c15ab8SAllan Jude 	explicit_bzero(digest, sizeof(digest));
1074332fecaSAllan Jude }
1084332fecaSAllan Jude 
1094332fecaSAllan Jude void
g_eli_crypto_hmac(const char * hkey,size_t hkeysize,const uint8_t * data,size_t datasize,uint8_t * md,size_t mdsize)110*e7630efbSMariusz Zaborski g_eli_crypto_hmac(const char *hkey, size_t hkeysize, const uint8_t *data,
1114332fecaSAllan Jude     size_t datasize, uint8_t *md, size_t mdsize)
1124332fecaSAllan Jude {
1134332fecaSAllan Jude 	struct hmac_ctx ctx;
1144332fecaSAllan Jude 
1154332fecaSAllan Jude 	g_eli_crypto_hmac_init(&ctx, hkey, hkeysize);
1164332fecaSAllan Jude 	g_eli_crypto_hmac_update(&ctx, data, datasize);
1174332fecaSAllan Jude 	g_eli_crypto_hmac_final(&ctx, md, mdsize);
1184332fecaSAllan Jude }
1194332fecaSAllan Jude 
1204332fecaSAllan Jude /*
1214332fecaSAllan Jude  * Here we generate IV. It is unique for every sector.
1224332fecaSAllan Jude  */
1234332fecaSAllan Jude void
g_eli_crypto_ivgen(struct g_eli_softc * sc,off_t offset,u_char * iv,size_t size)1244332fecaSAllan Jude g_eli_crypto_ivgen(struct g_eli_softc *sc, off_t offset, u_char *iv,
1254332fecaSAllan Jude     size_t size)
1264332fecaSAllan Jude {
1274332fecaSAllan Jude 	uint8_t off[8];
1284332fecaSAllan Jude 
1294332fecaSAllan Jude 	if ((sc->sc_flags & G_ELI_FLAG_NATIVE_BYTE_ORDER) != 0)
1304332fecaSAllan Jude 		bcopy(&offset, off, sizeof(off));
1314332fecaSAllan Jude 	else
1324332fecaSAllan Jude 		le64enc(off, (uint64_t)offset);
1334332fecaSAllan Jude 
1344332fecaSAllan Jude 	switch (sc->sc_ealgo) {
1354332fecaSAllan Jude 	case CRYPTO_AES_XTS:
1364332fecaSAllan Jude 		bcopy(off, iv, sizeof(off));
1374332fecaSAllan Jude 		bzero(iv + sizeof(off), size - sizeof(off));
1384332fecaSAllan Jude 		break;
1394332fecaSAllan Jude 	default:
1404332fecaSAllan Jude 	    {
1414332fecaSAllan Jude 		u_char hash[SHA256_DIGEST_LENGTH];
1424332fecaSAllan Jude 		SHA256_CTX ctx;
1434332fecaSAllan Jude 
1444332fecaSAllan Jude 		/* Copy precalculated SHA256 context for IV-Key. */
1454332fecaSAllan Jude 		bcopy(&sc->sc_ivctx, &ctx, sizeof(ctx));
1464332fecaSAllan Jude 		SHA256_Update(&ctx, off, sizeof(off));
1474332fecaSAllan Jude 		SHA256_Final(hash, &ctx);
1484332fecaSAllan Jude 		bcopy(hash, iv, MIN(sizeof(hash), size));
1494332fecaSAllan Jude 		break;
1504332fecaSAllan Jude 	    }
1514332fecaSAllan Jude 	}
1524332fecaSAllan Jude }
153