1/*	$OpenBSD: softraid.c,v 1.7 2024/04/25 18:31:49 kn Exp $	*/
2
3/*
4 * Copyright (c) 2012 Joel Sing <jsing@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/param.h>
20#include <sys/queue.h>
21
22#include <dev/biovar.h>
23#include <dev/softraidvar.h>
24
25#include <lib/libsa/bcrypt_pbkdf.h>
26#include <lib/libsa/hmac_sha1.h>
27#include <lib/libsa/pkcs5_pbkdf2.h>
28#include <lib/libsa/rijndael.h>
29
30#include "stand.h"
31#include "softraid.h"
32
33#define RIJNDAEL128_BLOCK_LEN     16
34#define PASSPHRASE_LENGTH 1024
35
36#define SR_CRYPTO_KEYBLOCK_BYTES SR_CRYPTO_MAXKEYS * SR_CRYPTO_KEYBYTES
37
38/* List of softraid volumes. */
39struct sr_boot_volume_head sr_volumes;
40
41/* List of softraid keydisks. */
42struct sr_boot_keydisk_head sr_keydisks;
43
44#ifdef DEBUG
45void
46printhex(const char *s, const u_int8_t *buf, size_t len)
47{
48	u_int8_t n1, n2;
49	size_t i;
50
51	printf("%s: ", s);
52	for (i = 0; i < len; i++) {
53		n1 = buf[i] & 0x0f;
54		n2 = buf[i] >> 4;
55		printf("%c", n2 > 9 ? n2 + 'a' - 10 : n2 + '0');
56		printf("%c", n1 > 9 ? n1 + 'a' - 10 : n1 + '0');
57	}
58	printf("\n");
59}
60#endif
61
62void
63sr_clear_keys(void)
64{
65	struct sr_boot_volume *bv;
66	struct sr_boot_keydisk *kd, *nkd;
67
68	SLIST_FOREACH(bv, &sr_volumes, sbv_link) {
69		if (bv->sbv_level != 'C' && bv->sbv_level != 0x1C)
70			continue;
71		if (bv->sbv_keys != NULL) {
72			explicit_bzero(bv->sbv_keys, SR_CRYPTO_KEYBLOCK_BYTES);
73			free(bv->sbv_keys, SR_CRYPTO_KEYBLOCK_BYTES);
74			bv->sbv_keys = NULL;
75		}
76		if (bv->sbv_maskkey != NULL) {
77			explicit_bzero(bv->sbv_maskkey, SR_CRYPTO_MAXKEYBYTES);
78			free(bv->sbv_maskkey, SR_CRYPTO_MAXKEYBYTES);
79			bv->sbv_maskkey = NULL;
80		}
81	}
82	SLIST_FOREACH_SAFE(kd, &sr_keydisks, kd_link, nkd) {
83		explicit_bzero(kd, sizeof(*kd));
84		free(kd, sizeof(*kd));
85	}
86}
87
88void
89sr_crypto_calculate_check_hmac_sha1(u_int8_t *maskkey, int maskkey_size,
90    u_int8_t *key, int key_size, u_char *check_digest)
91{
92	u_int8_t check_key[SHA1_DIGEST_LENGTH];
93	SHA1_CTX shactx;
94
95	explicit_bzero(check_key, sizeof(check_key));
96	explicit_bzero(&shactx, sizeof(shactx));
97
98	/* k = SHA1(mask_key) */
99	SHA1Init(&shactx);
100	SHA1Update(&shactx, maskkey, maskkey_size);
101	SHA1Final(check_key, &shactx);
102
103	/* mac = HMAC_SHA1_k(unencrypted key) */
104	hmac_sha1(key, key_size, check_key, sizeof(check_key), check_digest);
105
106	explicit_bzero(check_key, sizeof(check_key));
107	explicit_bzero(&shactx, sizeof(shactx));
108}
109
110static int
111sr_crypto_decrypt_keys(struct sr_meta_crypto *cm,
112    struct sr_crypto_kdfinfo *kdfinfo, u_int8_t *kp)
113{
114	u_int8_t digest[SHA1_DIGEST_LENGTH];
115	rijndael_ctx ctx;
116	u_int8_t *cp;
117	int rv = -1;
118	int i;
119
120	if (rijndael_set_key(&ctx, kdfinfo->maskkey, 256) != 0)
121		goto done;
122
123	cp = (u_int8_t *)cm->scm_key;
124	for (i = 0; i < SR_CRYPTO_KEYBLOCK_BYTES; i += RIJNDAEL128_BLOCK_LEN)
125		rijndael_decrypt(&ctx, (u_char *)(cp + i), (u_char *)(kp + i));
126
127	/* Check that the key decrypted properly. */
128	sr_crypto_calculate_check_hmac_sha1(kdfinfo->maskkey,
129	    sizeof(kdfinfo->maskkey), kp, SR_CRYPTO_KEYBLOCK_BYTES, digest);
130
131	if (bcmp(digest, cm->chk_hmac_sha1.sch_mac, sizeof(digest)) == 0)
132		rv = 0;
133
134 done:
135	explicit_bzero(digest, sizeof(digest));
136
137	return rv;
138}
139
140static int
141sr_crypto_passphrase_decrypt(struct sr_meta_crypto *cm,
142    struct sr_crypto_kdfinfo *kdfinfo, u_int8_t *kp)
143{
144	char passphrase[PASSPHRASE_LENGTH];
145	struct sr_crypto_pbkdf *kdfhint;
146	int rv = -1;
147	int c, i;
148
149	kdfhint = (struct sr_crypto_pbkdf *)&cm->scm_kdfhint;
150
151	for (;;) {
152		printf("Passphrase: ");
153#ifdef IDLE_POWEROFF
154extern int idle_poweroff(void);
155		idle_poweroff();
156#endif /* IDLE_POWEROFF */
157		for (i = 0; i < PASSPHRASE_LENGTH - 1; i++) {
158			c = cngetc();
159			if (c == '\r' || c == '\n') {
160				break;
161			} else if (c == '\b') {
162				i = i > 0 ? i - 2 : -1;
163				continue;
164			}
165			passphrase[i] = (c & 0xff);
166		}
167		passphrase[i] = 0;
168		printf("\n");
169
170		/* Abort on an empty passphrase. */
171		if (i == 0) {
172			printf("aborting...\n");
173			goto done;
174		}
175
176#ifdef DEBUG
177		printf("Got passphrase: %s with len %d\n",
178		    passphrase, strlen(passphrase));
179#endif
180
181		switch (kdfhint->generic.type) {
182		case SR_CRYPTOKDFT_PKCS5_PBKDF2:
183			if (pkcs5_pbkdf2(passphrase, strlen(passphrase),
184			    kdfhint->salt, sizeof(kdfhint->salt),
185			    kdfinfo->maskkey, sizeof(kdfinfo->maskkey),
186			    kdfhint->rounds) != 0) {
187				printf("pkcs5_pbkdf2 failed\n");
188				goto done;
189			}
190			break;
191
192		case SR_CRYPTOKDFT_BCRYPT_PBKDF:
193			if (bcrypt_pbkdf(passphrase, strlen(passphrase),
194			    kdfhint->salt, sizeof(kdfhint->salt),
195			    kdfinfo->maskkey, sizeof(kdfinfo->maskkey),
196			    kdfhint->rounds) != 0) {
197				printf("bcrypt_pbkdf failed\n");
198				goto done;
199			}
200			break;
201
202		default:
203			printf("unknown KDF type %u\n", kdfhint->generic.type);
204			goto done;
205		}
206
207		if (sr_crypto_decrypt_keys(cm, kdfinfo, kp) == 0) {
208			rv = 0;
209			goto done;
210		}
211
212		printf("incorrect passphrase\n");
213	}
214
215 done:
216	explicit_bzero(passphrase, PASSPHRASE_LENGTH);
217
218	return rv;
219}
220
221int
222sr_crypto_unlock_volume(struct sr_boot_volume *bv)
223{
224	struct sr_meta_crypto *cm;
225	struct sr_boot_keydisk *kd;
226	struct sr_meta_opt_item *omi;
227	struct sr_crypto_pbkdf *kdfhint;
228	struct sr_crypto_kdfinfo kdfinfo;
229	u_int8_t *keys = NULL;
230	int rv = -1;
231
232	SLIST_FOREACH(omi, &bv->sbv_meta_opt, omi_link)
233		if (omi->omi_som->som_type == SR_OPT_CRYPTO)
234			break;
235
236	if (omi == NULL) {
237		printf("crypto metadata not found!\n");
238		goto done;
239	}
240
241	cm = (struct sr_meta_crypto *)omi->omi_som;
242	kdfhint = (struct sr_crypto_pbkdf *)&cm->scm_kdfhint;
243
244	switch (cm->scm_mask_alg) {
245	case SR_CRYPTOM_AES_ECB_256:
246		break;
247	default:
248		printf("unsupported encryption algorithm %u\n",
249		    cm->scm_mask_alg);
250		goto done;
251	}
252
253	keys = alloc(SR_CRYPTO_KEYBLOCK_BYTES);
254	bzero(keys, SR_CRYPTO_KEYBLOCK_BYTES);
255
256	switch (kdfhint->generic.type) {
257	case SR_CRYPTOKDFT_KEYDISK:
258		SLIST_FOREACH(kd, &sr_keydisks, kd_link) {
259			if (bcmp(&kd->kd_uuid, &bv->sbv_uuid,
260			    sizeof(kd->kd_uuid)) == 0)
261				break;
262		}
263		if (kd == NULL) {
264			printf("keydisk not found\n");
265			goto done;
266		}
267		bcopy(&kd->kd_key, &kdfinfo.maskkey, sizeof(kdfinfo.maskkey));
268		if (sr_crypto_decrypt_keys(cm, &kdfinfo, keys) != 0) {
269			printf("incorrect keydisk\n");
270			goto done;
271		}
272		break;
273
274	case SR_CRYPTOKDFT_BCRYPT_PBKDF:
275	case SR_CRYPTOKDFT_PKCS5_PBKDF2:
276		if (sr_crypto_passphrase_decrypt(cm, &kdfinfo, keys) != 0)
277			goto done;
278		break;
279
280	default:
281		printf("unknown KDF type %u\n", kdfhint->generic.type);
282		goto done;
283	}
284
285	/* Keys and keydisks will be cleared before boot and from _rtt. */
286	bv->sbv_keys = keys;
287	bv->sbv_maskkey = alloc(sizeof(kdfinfo.maskkey));
288	bcopy(&kdfinfo.maskkey, bv->sbv_maskkey, sizeof(kdfinfo.maskkey));
289
290	rv = 0;
291
292 done:
293	explicit_bzero(&kdfinfo, sizeof(kdfinfo));
294
295	if (keys != NULL && rv != 0) {
296		explicit_bzero(keys, SR_CRYPTO_KEYBLOCK_BYTES);
297		free(keys, SR_CRYPTO_KEYBLOCK_BYTES);
298	}
299
300	return (rv);
301}
302