xref: /freebsd/stand/libsa/geli/geliboot_crypto.c (revision b3e76948)
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,
37c7721958SJohn 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);
82c7721958SJohn 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 {
107c7721958SJohn Baldwin 	u_char iv[G_ELI_IVKEYLEN];
10862bd02ceSWarner Losh 
10962bd02ceSWarner Losh 	explicit_bzero(iv, sizeof(iv));
110c7721958SJohn 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