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