162bd02ceSWarner Losh /*-
262bd02ceSWarner Losh * Copyright (c) 2005-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
362bd02ceSWarner Losh * Copyright (c) 2015 Allan Jude <allanjude@FreeBSD.org>
462bd02ceSWarner Losh * All rights reserved.
562bd02ceSWarner Losh *
662bd02ceSWarner Losh * Redistribution and use in source and binary forms, with or without
762bd02ceSWarner Losh * modification, are permitted provided that the following conditions
862bd02ceSWarner Losh * are met:
962bd02ceSWarner Losh * 1. Redistributions of source code must retain the above copyright
1062bd02ceSWarner Losh * notice, this list of conditions and the following disclaimer.
1162bd02ceSWarner Losh * 2. Redistributions in binary form must reproduce the above copyright
1262bd02ceSWarner Losh * notice, this list of conditions and the following disclaimer in the
1362bd02ceSWarner Losh * documentation and/or other materials provided with the distribution.
1462bd02ceSWarner Losh *
1562bd02ceSWarner Losh * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
1662bd02ceSWarner Losh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1762bd02ceSWarner Losh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1862bd02ceSWarner Losh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
1962bd02ceSWarner Losh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2062bd02ceSWarner Losh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2162bd02ceSWarner Losh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2262bd02ceSWarner Losh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2362bd02ceSWarner Losh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2462bd02ceSWarner Losh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2562bd02ceSWarner Losh * SUCH DAMAGE.
2662bd02ceSWarner Losh */
2762bd02ceSWarner Losh
2862bd02ceSWarner Losh #include <stdio.h>
2962bd02ceSWarner Losh #include <string.h>
3062bd02ceSWarner Losh #include <strings.h>
3162bd02ceSWarner Losh
3262bd02ceSWarner Losh #include "geliboot_internal.h"
3362bd02ceSWarner Losh #include "geliboot.h"
3462bd02ceSWarner Losh
3562bd02ceSWarner Losh int
geliboot_crypt(u_int algo,geli_op_t enc,u_char * data,size_t datasize,const u_char * key,size_t keysize,u_char * iv)36de776da3SToomas Soome geliboot_crypt(u_int algo, geli_op_t enc, u_char *data, size_t datasize,
37*c7721958SJohn Baldwin const u_char *key, size_t keysize, u_char *iv)
3862bd02ceSWarner Losh {
3962bd02ceSWarner Losh keyInstance aeskey;
4062bd02ceSWarner Losh cipherInstance cipher;
4162bd02ceSWarner Losh struct aes_xts_ctx xtsctx, *ctxp;
4262bd02ceSWarner Losh size_t xts_len;
43b1563623SJohn Baldwin int err, blks;
4462bd02ceSWarner Losh
4562bd02ceSWarner Losh switch (algo) {
4662bd02ceSWarner Losh case CRYPTO_AES_CBC:
4762bd02ceSWarner Losh err = rijndael_makeKey(&aeskey, !enc, keysize,
4862bd02ceSWarner Losh (const char *)key);
4962bd02ceSWarner Losh if (err < 0) {
50de776da3SToomas Soome printf("Failed to setup crypo keys: %d\n", err);
5162bd02ceSWarner Losh return (err);
5262bd02ceSWarner Losh }
5362bd02ceSWarner Losh
5462bd02ceSWarner Losh err = rijndael_cipherInit(&cipher, MODE_CBC, iv);
5562bd02ceSWarner Losh if (err < 0) {
5662bd02ceSWarner Losh printf("Failed to setup IV: %d\n", err);
5762bd02ceSWarner Losh return (err);
5862bd02ceSWarner Losh }
5962bd02ceSWarner Losh
60de776da3SToomas Soome switch (enc) {
61de776da3SToomas Soome case GELI_DECRYPT:
6262bd02ceSWarner Losh blks = rijndael_blockDecrypt(&cipher, &aeskey, data,
6362bd02ceSWarner Losh datasize * 8, data);
64de776da3SToomas Soome break;
65de776da3SToomas Soome case GELI_ENCRYPT:
6662bd02ceSWarner Losh blks = rijndael_blockEncrypt(&cipher, &aeskey, data,
6762bd02ceSWarner Losh datasize * 8, data);
68de776da3SToomas Soome break;
6962bd02ceSWarner Losh }
7062bd02ceSWarner Losh if (datasize != (blks / 8)) {
71de776da3SToomas Soome printf("Failed to %s the entire input: %u != %zu\n",
72de776da3SToomas Soome enc ? "decrypt" : "encrypt",
73de776da3SToomas Soome blks, datasize);
7462bd02ceSWarner Losh return (1);
7562bd02ceSWarner Losh }
7662bd02ceSWarner Losh break;
7762bd02ceSWarner Losh case CRYPTO_AES_XTS:
7862bd02ceSWarner Losh xts_len = keysize << 1;
7962bd02ceSWarner Losh ctxp = &xtsctx;
8062bd02ceSWarner Losh
814f98ffddSJohn Baldwin enc_xform_aes_xts.setkey(ctxp, key, xts_len / 8);
82*c7721958SJohn Baldwin enc_xform_aes_xts.reinit(ctxp, iv, AES_XTS_IV_LEN);
8362bd02ceSWarner Losh
8462bd02ceSWarner Losh switch (enc) {
85de776da3SToomas Soome case GELI_DECRYPT:
86b1563623SJohn Baldwin enc_xform_aes_xts.decrypt_multi(ctxp, data, data,
87b1563623SJohn Baldwin datasize);
8862bd02ceSWarner Losh break;
89de776da3SToomas Soome case GELI_ENCRYPT:
90b1563623SJohn Baldwin enc_xform_aes_xts.encrypt_multi(ctxp, data, data,
91b1563623SJohn Baldwin datasize);
9262bd02ceSWarner Losh break;
9362bd02ceSWarner Losh }
9462bd02ceSWarner Losh break;
9562bd02ceSWarner Losh default:
9662bd02ceSWarner Losh printf("Unsupported crypto algorithm #%d\n", algo);
9762bd02ceSWarner Losh return (1);
9862bd02ceSWarner Losh }
9962bd02ceSWarner Losh
10062bd02ceSWarner Losh return (0);
10162bd02ceSWarner Losh }
10262bd02ceSWarner Losh
10362bd02ceSWarner Losh static int
g_eli_crypto_cipher(u_int algo,geli_op_t enc,u_char * data,size_t datasize,const u_char * key,size_t keysize)104de776da3SToomas Soome g_eli_crypto_cipher(u_int algo, geli_op_t enc, u_char *data, size_t datasize,
10562bd02ceSWarner Losh const u_char *key, size_t keysize)
10662bd02ceSWarner Losh {
107*c7721958SJohn Baldwin u_char iv[G_ELI_IVKEYLEN];
10862bd02ceSWarner Losh
10962bd02ceSWarner Losh explicit_bzero(iv, sizeof(iv));
110*c7721958SJohn Baldwin return (geliboot_crypt(algo, enc, data, datasize, key, keysize, iv));
11162bd02ceSWarner Losh }
11262bd02ceSWarner Losh
11362bd02ceSWarner Losh int
g_eli_crypto_encrypt(u_int algo,u_char * data,size_t datasize,const u_char * key,size_t keysize)11462bd02ceSWarner Losh g_eli_crypto_encrypt(u_int algo, u_char *data, size_t datasize,
11562bd02ceSWarner Losh const u_char *key, size_t keysize)
11662bd02ceSWarner Losh {
11762bd02ceSWarner Losh
11862bd02ceSWarner Losh /* We prefer AES-CBC for metadata protection. */
11962bd02ceSWarner Losh if (algo == CRYPTO_AES_XTS)
12062bd02ceSWarner Losh algo = CRYPTO_AES_CBC;
12162bd02ceSWarner Losh
122de776da3SToomas Soome return (g_eli_crypto_cipher(algo, GELI_ENCRYPT, data, datasize, key,
123de776da3SToomas Soome keysize));
12462bd02ceSWarner Losh }
12562bd02ceSWarner Losh
12662bd02ceSWarner Losh int
g_eli_crypto_decrypt(u_int algo,u_char * data,size_t datasize,const u_char * key,size_t keysize)12762bd02ceSWarner Losh g_eli_crypto_decrypt(u_int algo, u_char *data, size_t datasize,
12862bd02ceSWarner Losh const u_char *key, size_t keysize)
12962bd02ceSWarner Losh {
13062bd02ceSWarner Losh
13162bd02ceSWarner Losh /* We prefer AES-CBC for metadata protection. */
13262bd02ceSWarner Losh if (algo == CRYPTO_AES_XTS)
13362bd02ceSWarner Losh algo = CRYPTO_AES_CBC;
13462bd02ceSWarner Losh
135de776da3SToomas Soome return (g_eli_crypto_cipher(algo, GELI_DECRYPT, data, datasize, key,
136de776da3SToomas Soome keysize));
13762bd02ceSWarner Losh }
138