g_eli_crypto.c revision 271148
169450Smsmith/*- 269450Smsmith * Copyright (c) 2005-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3167802Sjkim * All rights reserved. 4167802Sjkim * 569450Smsmith * Redistribution and use in source and binary forms, with or without 669450Smsmith * modification, are permitted provided that the following conditions 769450Smsmith * are met: 869450Smsmith * 1. Redistributions of source code must retain the above copyright 969450Smsmith * notice, this list of conditions and the following disclaimer. 1069450Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1169450Smsmith * notice, this list of conditions and the following disclaimer in the 12167802Sjkim * documentation and/or other materials provided with the distribution. 1370243Smsmith * 1469450Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 1569450Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1669450Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1769450Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 1869450Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1969450Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2069450Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2169450Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2269450Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2369450Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2469450Smsmith * SUCH DAMAGE. 2569450Smsmith */ 2669450Smsmith 2769450Smsmith#include <sys/cdefs.h> 2869450Smsmith__FBSDID("$FreeBSD: head/sys/geom/eli/g_eli_crypto.c 271148 2014-09-04 23:53:51Z jmg $"); 2969450Smsmith 3069450Smsmith#include <sys/param.h> 3169450Smsmith#ifdef _KERNEL 3269450Smsmith#include <sys/systm.h> 3369450Smsmith#include <sys/kernel.h> 3469450Smsmith#include <sys/malloc.h> 3569450Smsmith#else 3669450Smsmith#include <stdint.h> 3769450Smsmith#include <string.h> 3869450Smsmith#include <strings.h> 3969450Smsmith#include <errno.h> 4069450Smsmith#include <assert.h> 4169450Smsmith#include <openssl/evp.h> 4269450Smsmith#define _OpenSSL_ 4369450Smsmith#endif 4469450Smsmith#include <geom/eli/g_eli.h> 4569450Smsmith 4669450Smsmith#ifdef _KERNEL 4769450SmsmithMALLOC_DECLARE(M_ELI); 4869450Smsmith 4969450Smsmithstatic int 5069450Smsmithg_eli_crypto_done(struct cryptop *crp) 5169450Smsmith{ 5269450Smsmith 5369450Smsmith crp->crp_opaque = (void *)crp; 5469450Smsmith wakeup(crp); 5569450Smsmith return (0); 5669450Smsmith} 5769450Smsmith 5869450Smsmithstatic int 5969450Smsmithg_eli_crypto_cipher(u_int algo, int enc, u_char *data, size_t datasize, 6069450Smsmith const u_char *key, size_t keysize) 6169450Smsmith{ 6269450Smsmith struct cryptoini cri; 6369450Smsmith struct cryptop *crp; 6469450Smsmith struct cryptodesc *crd; 6569450Smsmith uint64_t sid; 6669450Smsmith u_char *p; 6769450Smsmith int error; 6869450Smsmith 6969450Smsmith KASSERT(algo != CRYPTO_AES_XTS, 7069450Smsmith ("%s: CRYPTO_AES_XTS unexpected here", __func__)); 7169450Smsmith 7269450Smsmith bzero(&cri, sizeof(cri)); 7369450Smsmith cri.cri_alg = algo; 7469450Smsmith cri.cri_key = __DECONST(void *, key); 7569450Smsmith cri.cri_klen = keysize; 7669450Smsmith error = crypto_newsession(&sid, &cri, CRYPTOCAP_F_SOFTWARE); 7769450Smsmith if (error != 0) 7869450Smsmith return (error); 7969450Smsmith p = malloc(sizeof(*crp) + sizeof(*crd), M_ELI, M_NOWAIT | M_ZERO); 8069450Smsmith if (p == NULL) { 8169450Smsmith crypto_freesession(sid); 8269450Smsmith return (ENOMEM); 8369450Smsmith } 8469450Smsmith crp = (struct cryptop *)p; p += sizeof(*crp); 8569450Smsmith crd = (struct cryptodesc *)p; p += sizeof(*crd); 8669450Smsmith 8769450Smsmith crd->crd_skip = 0; 8869450Smsmith crd->crd_len = datasize; 8969450Smsmith crd->crd_flags = CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT; 9069450Smsmith if (enc) 9169450Smsmith crd->crd_flags |= CRD_F_ENCRYPT; 9269450Smsmith crd->crd_alg = algo; 9369450Smsmith crd->crd_key = __DECONST(void *, key); 9469450Smsmith crd->crd_klen = keysize; 9569450Smsmith bzero(crd->crd_iv, sizeof(crd->crd_iv)); 9669450Smsmith crd->crd_next = NULL; 9769450Smsmith 9869450Smsmith crp->crp_sid = sid; 9969450Smsmith crp->crp_ilen = datasize; 10069450Smsmith crp->crp_olen = datasize; 10169450Smsmith crp->crp_opaque = NULL; 10269450Smsmith crp->crp_callback = g_eli_crypto_done; 10369450Smsmith crp->crp_buf = (void *)data; 10469450Smsmith crp->crp_flags = CRYPTO_F_CBIFSYNC | CRYPTO_F_REL; 10569450Smsmith crp->crp_desc = crd; 10669450Smsmith 10769450Smsmith error = crypto_dispatch(crp); 10869450Smsmith if (error == 0) { 10969450Smsmith while (crp->crp_opaque == NULL) 11069450Smsmith tsleep(crp, PRIBIO, "geli", hz / 5); 11169450Smsmith error = crp->crp_etype; 11269450Smsmith } 11369450Smsmith 11469450Smsmith free(crp, M_ELI); 11569450Smsmith crypto_freesession(sid); 11669450Smsmith return (error); 11769450Smsmith} 11869450Smsmith#else /* !_KERNEL */ 11969450Smsmithstatic int 120167802Sjkimg_eli_crypto_cipher(u_int algo, int enc, u_char *data, size_t datasize, 121167802Sjkim const u_char *key, size_t keysize) 122167802Sjkim{ 123167802Sjkim EVP_CIPHER_CTX ctx; 124167802Sjkim const EVP_CIPHER *type; 125167802Sjkim u_char iv[keysize]; 126167802Sjkim int outsize; 127167802Sjkim 128167802Sjkim assert(algo != CRYPTO_AES_XTS); 129167802Sjkim 130167802Sjkim switch (algo) { 131167802Sjkim case CRYPTO_NULL_CBC: 132167802Sjkim type = EVP_enc_null(); 133167802Sjkim break; 134167802Sjkim case CRYPTO_AES_CBC: 135167802Sjkim switch (keysize) { 136167802Sjkim case 128: 137167802Sjkim type = EVP_aes_128_cbc(); 138167802Sjkim break; 139167802Sjkim case 192: 140167802Sjkim type = EVP_aes_192_cbc(); 141167802Sjkim break; 142167802Sjkim case 256: 143167802Sjkim type = EVP_aes_256_cbc(); 144167802Sjkim break; 145167802Sjkim default: 146167802Sjkim return (EINVAL); 147167802Sjkim } 148167802Sjkim break; 149167802Sjkim case CRYPTO_BLF_CBC: 150167802Sjkim type = EVP_bf_cbc(); 151167802Sjkim break; 152167802Sjkim#ifndef OPENSSL_NO_CAMELLIA 153167802Sjkim case CRYPTO_CAMELLIA_CBC: 154167802Sjkim switch (keysize) { 155167802Sjkim case 128: 156167802Sjkim type = EVP_camellia_128_cbc(); 15769450Smsmith break; 15869450Smsmith case 192: 15991116Smsmith type = EVP_camellia_192_cbc(); 160167802Sjkim break; 161167802Sjkim case 256: 162167802Sjkim type = EVP_camellia_256_cbc(); 16391116Smsmith break; 164167802Sjkim default: 165167802Sjkim return (EINVAL); 166167802Sjkim } 167167802Sjkim break; 168167802Sjkim#endif 16969450Smsmith case CRYPTO_3DES_CBC: 170167802Sjkim type = EVP_des_ede3_cbc(); 171167802Sjkim break; 172151937Sjkim default: 173167802Sjkim return (EINVAL); 17469450Smsmith } 17569450Smsmith 176167802Sjkim EVP_CIPHER_CTX_init(&ctx); 177167802Sjkim 178167802Sjkim EVP_CipherInit_ex(&ctx, type, NULL, NULL, NULL, enc); 179167802Sjkim EVP_CIPHER_CTX_set_key_length(&ctx, keysize / 8); 180167802Sjkim EVP_CIPHER_CTX_set_padding(&ctx, 0); 181167802Sjkim bzero(iv, sizeof(iv)); 182167802Sjkim EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, enc); 183167802Sjkim 184167802Sjkim if (EVP_CipherUpdate(&ctx, data, &outsize, data, datasize) == 0) { 185167802Sjkim EVP_CIPHER_CTX_cleanup(&ctx); 186167802Sjkim return (EINVAL); 187167802Sjkim } 188167802Sjkim assert(outsize == (int)datasize); 189167802Sjkim 190167802Sjkim if (EVP_CipherFinal_ex(&ctx, data + outsize, &outsize) == 0) { 191167802Sjkim EVP_CIPHER_CTX_cleanup(&ctx); 192167802Sjkim return (EINVAL); 193167802Sjkim } 194167802Sjkim assert(outsize == 0); 195167802Sjkim 196167802Sjkim EVP_CIPHER_CTX_cleanup(&ctx); 197167802Sjkim return (0); 198167802Sjkim} 199167802Sjkim#endif /* !_KERNEL */ 200167802Sjkim 201167802Sjkimint 202167802Sjkimg_eli_crypto_encrypt(u_int algo, u_char *data, size_t datasize, 203167802Sjkim const u_char *key, size_t keysize) 204167802Sjkim{ 205167802Sjkim 206167802Sjkim /* We prefer AES-CBC for metadata protection. */ 207167802Sjkim if (algo == CRYPTO_AES_XTS) 208167802Sjkim algo = CRYPTO_AES_CBC; 209167802Sjkim 210167802Sjkim return (g_eli_crypto_cipher(algo, 1, data, datasize, key, keysize)); 211167802Sjkim} 212167802Sjkim 213167802Sjkimint 21491116Smsmithg_eli_crypto_decrypt(u_int algo, u_char *data, size_t datasize, 215167802Sjkim const u_char *key, size_t keysize) 21691116Smsmith{ 217167802Sjkim 218167802Sjkim /* We prefer AES-CBC for metadata protection. */ 219167802Sjkim if (algo == CRYPTO_AES_XTS) 220167802Sjkim algo = CRYPTO_AES_CBC; 22169450Smsmith 222167802Sjkim return (g_eli_crypto_cipher(algo, 0, data, datasize, key, keysize)); 223167802Sjkim} 224167802Sjkim 225167802Sjkimvoid 226167802Sjkimg_eli_crypto_hmac_init(struct hmac_ctx *ctx, const uint8_t *hkey, 227167802Sjkim size_t hkeylen) 228167802Sjkim{ 22969450Smsmith u_char k_ipad[128], key[128]; 230167802Sjkim SHA512_CTX lctx; 231151937Sjkim u_int i; 232167802Sjkim 233151937Sjkim bzero(key, sizeof(key)); 234167802Sjkim if (hkeylen == 0) 235167802Sjkim ; /* do nothing */ 236167802Sjkim else if (hkeylen <= 128) 237167802Sjkim bcopy(hkey, key, hkeylen); 238167802Sjkim else { 239167802Sjkim /* If key is longer than 128 bytes reset it to key = SHA512(key). */ 240167802Sjkim SHA512_Init(&lctx); 241151937Sjkim SHA512_Update(&lctx, hkey, hkeylen); 242167802Sjkim SHA512_Final(key, &lctx); 24369450Smsmith } 244167802Sjkim 245167802Sjkim /* XOR key with ipad and opad values. */ 246167802Sjkim for (i = 0; i < sizeof(key); i++) { 247167802Sjkim k_ipad[i] = key[i] ^ 0x36; 248167802Sjkim ctx->k_opad[i] = key[i] ^ 0x5c; 249167802Sjkim } 250167802Sjkim bzero(key, sizeof(key)); 251167802Sjkim /* Perform inner SHA512. */ 252167802Sjkim SHA512_Init(&ctx->shactx); 253167802Sjkim SHA512_Update(&ctx->shactx, k_ipad, sizeof(k_ipad)); 254167802Sjkim bzero(k_ipad, sizeof(k_ipad)); 255167802Sjkim} 256167802Sjkim 257167802Sjkimvoid 25869450Smsmithg_eli_crypto_hmac_update(struct hmac_ctx *ctx, const uint8_t *data, 259167802Sjkim size_t datasize) 260167802Sjkim{ 261167802Sjkim 262167802Sjkim SHA512_Update(&ctx->shactx, data, datasize); 263167802Sjkim} 264167802Sjkim 265167802Sjkimvoid 266167802Sjkimg_eli_crypto_hmac_final(struct hmac_ctx *ctx, uint8_t *md, size_t mdsize) 267167802Sjkim{ 268167802Sjkim u_char digest[SHA512_MDLEN]; 269167802Sjkim SHA512_CTX lctx; 270167802Sjkim 271167802Sjkim SHA512_Final(digest, &ctx->shactx); 272167802Sjkim /* Perform outer SHA512. */ 273167802Sjkim SHA512_Init(&lctx); 274167802Sjkim SHA512_Update(&lctx, ctx->k_opad, sizeof(ctx->k_opad)); 275167802Sjkim bzero(ctx, sizeof(*ctx)); 276167802Sjkim SHA512_Update(&lctx, digest, sizeof(digest)); 277167802Sjkim SHA512_Final(digest, &lctx); 278167802Sjkim bzero(&lctx, sizeof(lctx)); 279167802Sjkim /* mdsize == 0 means "Give me the whole hash!" */ 280167802Sjkim if (mdsize == 0) 281167802Sjkim mdsize = SHA512_MDLEN; 282167802Sjkim bcopy(digest, md, mdsize); 283167802Sjkim bzero(digest, sizeof(digest)); 284167802Sjkim} 285167802Sjkim 286167802Sjkimvoid 287167802Sjkimg_eli_crypto_hmac(const uint8_t *hkey, size_t hkeysize, const uint8_t *data, 288167802Sjkim size_t datasize, uint8_t *md, size_t mdsize) 289167802Sjkim{ 290167802Sjkim struct hmac_ctx ctx; 291167802Sjkim 292167802Sjkim g_eli_crypto_hmac_init(&ctx, hkey, hkeysize); 293167802Sjkim g_eli_crypto_hmac_update(&ctx, data, datasize); 294167802Sjkim g_eli_crypto_hmac_final(&ctx, md, mdsize); 295167802Sjkim} 296167802Sjkim