Path: blob/main/stand/libsa/geli/geliboot_crypto.c
34860 views
/*-1* Copyright (c) 2005-2010 Pawel Jakub Dawidek <[email protected]>2* Copyright (c) 2015 Allan Jude <[email protected]>3* All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND15* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE16* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE17* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE18* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL19* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS20* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)21* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT22* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY23* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF24* SUCH DAMAGE.25*/2627#include <stdio.h>28#include <string.h>29#include <strings.h>3031#include "geliboot_internal.h"32#include "geliboot.h"3334int35geliboot_crypt(u_int algo, geli_op_t enc, u_char *data, size_t datasize,36const u_char *key, size_t keysize, u_char *iv)37{38keyInstance aeskey;39cipherInstance cipher;40struct aes_xts_ctx xtsctx, *ctxp;41size_t xts_len;42int err, blks;4344switch (algo) {45case CRYPTO_AES_CBC:46err = rijndael_makeKey(&aeskey, !enc, keysize,47(const char *)key);48if (err < 0) {49printf("Failed to setup crypo keys: %d\n", err);50return (err);51}5253err = rijndael_cipherInit(&cipher, MODE_CBC, iv);54if (err < 0) {55printf("Failed to setup IV: %d\n", err);56return (err);57}5859switch (enc) {60case GELI_DECRYPT:61blks = rijndael_blockDecrypt(&cipher, &aeskey, data,62datasize * 8, data);63break;64case GELI_ENCRYPT:65blks = rijndael_blockEncrypt(&cipher, &aeskey, data,66datasize * 8, data);67break;68}69if (datasize != (blks / 8)) {70printf("Failed to %s the entire input: %u != %zu\n",71enc ? "decrypt" : "encrypt",72blks, datasize);73return (1);74}75break;76case CRYPTO_AES_XTS:77xts_len = keysize << 1;78ctxp = &xtsctx;7980enc_xform_aes_xts.setkey(ctxp, key, xts_len / 8);81enc_xform_aes_xts.reinit(ctxp, iv, AES_XTS_IV_LEN);8283switch (enc) {84case GELI_DECRYPT:85enc_xform_aes_xts.decrypt_multi(ctxp, data, data,86datasize);87break;88case GELI_ENCRYPT:89enc_xform_aes_xts.encrypt_multi(ctxp, data, data,90datasize);91break;92}93break;94default:95printf("Unsupported crypto algorithm #%d\n", algo);96return (1);97}9899return (0);100}101102static int103g_eli_crypto_cipher(u_int algo, geli_op_t enc, u_char *data, size_t datasize,104const u_char *key, size_t keysize)105{106u_char iv[G_ELI_IVKEYLEN];107108explicit_bzero(iv, sizeof(iv));109return (geliboot_crypt(algo, enc, data, datasize, key, keysize, iv));110}111112int113g_eli_crypto_encrypt(u_int algo, u_char *data, size_t datasize,114const u_char *key, size_t keysize)115{116117/* We prefer AES-CBC for metadata protection. */118if (algo == CRYPTO_AES_XTS)119algo = CRYPTO_AES_CBC;120121return (g_eli_crypto_cipher(algo, GELI_ENCRYPT, data, datasize, key,122keysize));123}124125int126g_eli_crypto_decrypt(u_int algo, u_char *data, size_t datasize,127const u_char *key, size_t keysize)128{129130/* We prefer AES-CBC for metadata protection. */131if (algo == CRYPTO_AES_XTS)132algo = CRYPTO_AES_CBC;133134return (g_eli_crypto_cipher(algo, GELI_DECRYPT, data, datasize, key,135keysize));136}137138139