xref: /freebsd/sys/contrib/openzfs/module/zfs/zio_crypt_os_icp.c (revision 34f9f5680c9d5d5138e427ba3aeab0138cec3882)
1 // SPDX-License-Identifier: CDDL-1.0
2 /*
3  * This file and its contents are supplied under the terms of the
4  * Common Development and Distribution License ("CDDL"), version 1.0.
5  * You may only use this file in accordance with the terms of version
6  * 1.0 of the CDDL.
7  *
8  * A full copy of the text of the CDDL should have accompanied this
9  * source.  A copy of the CDDL is also available via the Internet at
10  * https://opensource.org/license/CDDL-1.0.
11  */
12 
13 /*
14  * Copyright (c) 2017, Datto, Inc. All rights reserved.
15  * Copyright (c) 2026, TrueNAS.
16  */
17 
18 #include <sys/zio_crypt.h>
19 
20 void
zio_crypt_key_close_os(zio_crypt_key_t * key)21 zio_crypt_key_close_os(zio_crypt_key_t *key)
22 {
23 	/* free crypto templates */
24 	crypto_destroy_ctx_template(key->zk_current_sess.zs_tmpl);
25 	crypto_destroy_ctx_template(key->zk_hmac_sess.zs_tmpl);
26 }
27 
28 int
zio_crypt_key_open_os(zio_crypt_key_t * key,const zio_crypt_info_t * ci)29 zio_crypt_key_open_os(zio_crypt_key_t *key, const zio_crypt_info_t *ci)
30 {
31 	crypto_mechanism_t mech = {0};
32 	int ret;
33 
34 	/*
35 	 * Initialize the crypto templates. It's ok if this fails because
36 	 * this is just an optimization.
37 	 */
38 	mech.cm_type = crypto_mech2id(ci->ci_mechname);
39 	ret = crypto_create_ctx_template(&mech, &key->zk_current_key,
40 	    &key->zk_current_sess.zs_tmpl);
41 	if (ret != CRYPTO_SUCCESS)
42 		key->zk_current_sess.zs_tmpl = NULL;
43 
44 	mech.cm_type = crypto_mech2id(SUN_CKM_SHA512_HMAC);
45 	ret = crypto_create_ctx_template(&mech, &key->zk_hmac_key,
46 	    &key->zk_hmac_sess.zs_tmpl);
47 	if (ret != CRYPTO_SUCCESS)
48 		key->zk_hmac_sess.zs_tmpl = NULL;
49 
50 	return (0);
51 }
52 
53 int
zio_crypt_key_reopen_os(zio_crypt_key_t * key,const zio_crypt_info_t * ci)54 zio_crypt_key_reopen_os(zio_crypt_key_t *key, const zio_crypt_info_t *ci)
55 {
56 	int ret;
57 	crypto_mechanism_t mech = {0};
58 
59 	crypto_destroy_ctx_template(key->zk_current_sess.zs_tmpl);
60 
61 	mech.cm_type = crypto_mech2id(ci->ci_mechname);
62 	ret = crypto_create_ctx_template(&mech, &key->zk_current_key,
63 	    &key->zk_current_sess.zs_tmpl);
64 	if (ret != CRYPTO_SUCCESS)
65 		key->zk_current_sess.zs_tmpl = NULL;
66 	return (0);
67 }
68 
69 /*
70  * Initialise a pair of uios with the requested number of data iovecs. An
71  * additional iovec will be allocated for at the end for the ICP to use for the
72  * MAC buffer.
73  */
74 int
zio_crypt_uios_init_os(zfs_uio_t * u1,zfs_uio_t * u2,int iovcnt,int * idx)75 zio_crypt_uios_init_os(zfs_uio_t *u1, zfs_uio_t *u2, int iovcnt, int *idx)
76 {
77 	memset(u1, 0, sizeof (zfs_uio_t));
78 	memset(u2, 0, sizeof (zfs_uio_t));
79 
80 	/* One extra for the MAC. */
81 	iovcnt++;
82 
83 	zfs_uio_iov(u1) = kmem_zalloc(iovcnt * sizeof (iovec_t), KM_SLEEP);
84 	zfs_uio_iov(u2) = kmem_zalloc(iovcnt * sizeof (iovec_t), KM_SLEEP);
85 
86 	zfs_uio_iovcnt(u1) = zfs_uio_iovcnt(u2) = iovcnt;
87 	zfs_uio_segflg(u1) = zfs_uio_segflg(u2) = UIO_SYSSPACE;
88 
89 	*idx = 0;
90 
91 	return (0);
92 }
93 
94 void
zio_crypt_uios_fini_os(zfs_uio_t * u1,zfs_uio_t * u2)95 zio_crypt_uios_fini_os(zfs_uio_t *u1, zfs_uio_t *u2) {
96 	ASSERT3U(zfs_uio_iovcnt(u1), ==, zfs_uio_iovcnt(u2));
97 
98 	kmem_free(zfs_uio_iov(u1), zfs_uio_iovcnt(u1) * sizeof (iovec_t));
99 	kmem_free(zfs_uio_iov(u2), zfs_uio_iovcnt(u2) * sizeof (iovec_t));
100 }
101 
102 static int
zio_encrypt_decrypt_os_common(boolean_t do_encrypt,const zio_crypt_info_t * ci,crypto_key_t * key,zio_crypt_session_t * sess,zfs_uio_t * src,zfs_uio_t * dst,size_t datalen,const uint8_t iv[ZIO_DATA_IV_LEN],const uint8_t * ad,size_t adlen,uint8_t mac[ZIO_DATA_MAC_LEN])103 zio_encrypt_decrypt_os_common(boolean_t do_encrypt, const zio_crypt_info_t *ci,
104     crypto_key_t *key, zio_crypt_session_t *sess,
105     zfs_uio_t *src, zfs_uio_t *dst, size_t datalen,
106     const uint8_t iv[ZIO_DATA_IV_LEN], const uint8_t *ad, size_t adlen,
107     uint8_t mac[ZIO_DATA_MAC_LEN])
108 {
109 	ASSERT3U(zfs_uio_iovcnt(src), ==, zfs_uio_iovcnt(dst));
110 
111 	/* populate the source and dest structs */
112 	crypto_data_t src_cd = {
113 		.cd_format = CRYPTO_DATA_UIO,
114 		.cd_uio = src,
115 		.cd_offset = 0,
116 	};
117 	crypto_data_t dst_cd = {
118 		.cd_format = CRYPTO_DATA_UIO,
119 		.cd_uio = dst,
120 		.cd_offset = 0,
121 	};
122 
123 	if (do_encrypt) {
124 		/*
125 		 * When encrypting, the MAC will be stored at the end of the
126 		 * encrypted data, so add the MAC buffer to the end of the dest
127 		 * UIO and extend the data length to accomodate it.
128 		 */
129 		zfs_uio_iovbase(dst, zfs_uio_iovcnt(dst)-1) = mac;
130 		zfs_uio_iovlen(dst, zfs_uio_iovcnt(dst)-1) = ZIO_DATA_MAC_LEN;
131 		src_cd.cd_length = datalen;
132 		dst_cd.cd_length = datalen + ZIO_DATA_MAC_LEN;
133 	} else {
134 		/*
135 		 * When decrypting, the MAC is presented at the end of the
136 		 * plaintext data, so add the MAC buffer to the end of the
137 		 * source UIO.
138 		 *
139 		 * Strangely, the ICP requires that the destination/plaintext
140 		 * must include the MAC length when decrypting, even though it
141 		 * will never write anything and does not need to have the
142 		 * extra space allocated. So we extend both source and data
143 		 * length to cover it.
144 		 */
145 		zfs_uio_iovbase(src, zfs_uio_iovcnt(src)-1) = mac;
146 		zfs_uio_iovlen(src, zfs_uio_iovcnt(src)-1) = ZIO_DATA_MAC_LEN;
147 		src_cd.cd_length = dst_cd.cd_length =
148 		    datalen + ZIO_DATA_MAC_LEN;
149 	}
150 
151 	/* setup encryption mechanism */
152 	crypto_mechanism_t mech = {0};
153 	mech.cm_type = crypto_mech2id(ci->ci_mechname);
154 
155 	/* setup encryption params */
156 	union {
157 		CK_AES_CCM_PARAMS ccm;
158 		CK_AES_GCM_PARAMS gcm;
159 	} params;
160 
161 	if (ci->ci_crypt_type == ZC_TYPE_CCM) {
162 		CK_AES_CCM_PARAMS *ccm = &params.ccm;
163 		ccm->nonce = (uchar_t *)iv;
164 		ccm->ulNonceSize = ZIO_DATA_IV_LEN;
165 		ccm->authData = (uchar_t *)ad;
166 		ccm->ulAuthDataSize = adlen;
167 		ccm->ulDataSize = src_cd.cd_length;
168 		ccm->ulMACSize = ZIO_DATA_MAC_LEN;
169 		mech.cm_param = (caddr_t)ccm;
170 		mech.cm_param_len = sizeof (*ccm);
171 	} else {
172 		CK_AES_GCM_PARAMS *gcm = &params.gcm;
173 		gcm->pIv = (uchar_t *)iv;
174 		gcm->ulIvLen = ZIO_DATA_IV_LEN;
175 		gcm->ulIvBits = CRYPTO_BYTES2BITS(ZIO_DATA_IV_LEN);
176 		gcm->pAAD = (uchar_t *)ad;
177 		gcm->ulAADLen = adlen;
178 		gcm->ulTagBits = CRYPTO_BYTES2BITS(ZIO_DATA_MAC_LEN);
179 		mech.cm_param = (caddr_t)gcm;
180 		mech.cm_param_len = sizeof (*gcm);
181 	}
182 
183 	/* perform the actual encryption */
184 	crypto_ctx_template_t *tmpl = sess != NULL ? sess->zs_tmpl : NULL;
185 	int err = 0;
186 	if (do_encrypt) {
187 		err = crypto_encrypt(&mech, &src_cd, key, tmpl, &dst_cd);
188 		if (err != CRYPTO_SUCCESS)
189 			err = SET_ERROR(EIO);
190 	} else {
191 		err = crypto_decrypt(&mech, &src_cd, key, tmpl, &dst_cd);
192 		if (err != CRYPTO_SUCCESS) {
193 			ASSERT3U(err, ==, CRYPTO_INVALID_MAC);
194 			err = SET_ERROR(ECKSUM);
195 		}
196 	}
197 
198 	return (err);
199 }
200 
201 int
zio_encrypt_os(const zio_crypt_info_t * ci,crypto_key_t * key,zio_crypt_session_t * sess,zfs_uio_t * plaintext,zfs_uio_t * ciphertext,size_t datalen,const uint8_t iv[ZIO_DATA_IV_LEN],const uint8_t * ad,size_t adlen,uint8_t mac[ZIO_DATA_MAC_LEN])202 zio_encrypt_os(const zio_crypt_info_t *ci,
203     crypto_key_t *key, zio_crypt_session_t *sess,
204     zfs_uio_t *plaintext, zfs_uio_t *ciphertext, size_t datalen,
205     const uint8_t iv[ZIO_DATA_IV_LEN], const uint8_t *ad, size_t adlen,
206     uint8_t mac[ZIO_DATA_MAC_LEN])
207 {
208 	return (zio_encrypt_decrypt_os_common(B_TRUE, ci, key, sess,
209 	    plaintext, ciphertext, datalen, iv, ad, adlen, mac));
210 }
211 
212 int
zio_decrypt_os(const zio_crypt_info_t * ci,crypto_key_t * key,zio_crypt_session_t * sess,zfs_uio_t * ciphertext,zfs_uio_t * plaintext,size_t datalen,const uint8_t iv[ZIO_DATA_IV_LEN],const uint8_t * ad,size_t adlen,uint8_t mac[ZIO_DATA_MAC_LEN])213 zio_decrypt_os(const zio_crypt_info_t *ci,
214     crypto_key_t *key, zio_crypt_session_t *sess,
215     zfs_uio_t *ciphertext, zfs_uio_t *plaintext, size_t datalen,
216     const uint8_t iv[ZIO_DATA_IV_LEN], const uint8_t *ad, size_t adlen,
217     uint8_t mac[ZIO_DATA_MAC_LEN])
218 {
219 	return (zio_encrypt_decrypt_os_common(B_FALSE, ci, key, sess,
220 	    ciphertext, plaintext, datalen, iv, ad, adlen, mac));
221 }
222 
223 int
zio_crypt_hmac_os(zio_crypt_key_t * key,const uint8_t * data,size_t datalen,uint8_t digest[SHA512_HMAC_LEN])224 zio_crypt_hmac_os(zio_crypt_key_t *key, const uint8_t *data, size_t datalen,
225     uint8_t digest[SHA512_HMAC_LEN])
226 {
227 	/* initialize sha512-hmac mechanism */
228 	crypto_mechanism_t mech = {0};
229 	mech.cm_type = crypto_mech2id(SUN_CKM_SHA512_HMAC);
230 
231 	/* initialize the crypto data */
232 	crypto_data_t in = {
233 		.cd_format = CRYPTO_DATA_RAW,
234 		.cd_offset = 0,
235 		.cd_length = datalen,
236 		.cd_raw.iov_base = (void *)data,
237 		.cd_raw.iov_len = datalen,
238 	};
239 	crypto_data_t out = {
240 		.cd_format = CRYPTO_DATA_RAW,
241 		.cd_offset = 0,
242 		.cd_length = SHA512_HMAC_LEN,
243 		.cd_raw.iov_base = (void *)digest,
244 		.cd_raw.iov_len = SHA512_HMAC_LEN,
245 	};
246 
247 	/* generate the hmac */
248 	if (crypto_mac(&mech, &in, &key->zk_hmac_key,
249 	    key->zk_hmac_sess.zs_tmpl, &out) != CRYPTO_SUCCESS)
250 		return (SET_ERROR(EIO));
251 
252 	return (0);
253 }
254 
255 int
zio_crypt_hmac_init_os(zio_crypt_hmac_t * hmac,zio_crypt_key_t * key)256 zio_crypt_hmac_init_os(zio_crypt_hmac_t *hmac, zio_crypt_key_t *key)
257 {
258 	/* initialize HMAC mechanism */
259 	crypto_mechanism_t mech = {0};
260 	mech.cm_type = crypto_mech2id(SUN_CKM_SHA512_HMAC);
261 
262 	if (crypto_mac_init(&mech, &key->zk_hmac_key, NULL,
263 	    &hmac->zh_ctx) != CRYPTO_SUCCESS)
264 		return (SET_ERROR(EIO));
265 
266 	return (0);
267 }
268 
269 int
zio_crypt_hmac_update_os(zio_crypt_hmac_t * hmac,const uint8_t * data,size_t datalen)270 zio_crypt_hmac_update_os(zio_crypt_hmac_t *hmac, const uint8_t *data,
271     size_t datalen)
272 {
273 	crypto_data_t cd = {
274 		.cd_format = CRYPTO_DATA_RAW,
275 		.cd_offset = 0,
276 		.cd_length = datalen,
277 		.cd_raw.iov_base = (char *)data,
278 		.cd_raw.iov_len = datalen,
279 	};
280 
281 	if (crypto_mac_update(hmac->zh_ctx, &cd) != CRYPTO_SUCCESS)
282 		return (SET_ERROR(EIO));
283 
284 	return (0);
285 }
286 
287 int
zio_crypt_hmac_final_os(zio_crypt_hmac_t * hmac,uint8_t digest[SHA512_HMAC_LEN])288 zio_crypt_hmac_final_os(zio_crypt_hmac_t *hmac, uint8_t digest[SHA512_HMAC_LEN])
289 {
290 	crypto_data_t cd = {
291 		.cd_format = CRYPTO_DATA_RAW,
292 		.cd_offset = 0,
293 		.cd_length = SHA512_HMAC_LEN,
294 		.cd_raw.iov_base = (char *)digest,
295 		.cd_raw.iov_len = SHA512_HMAC_LEN,
296 	};
297 
298 	if (crypto_mac_final(hmac->zh_ctx, &cd) != CRYPTO_SUCCESS)
299 		return (SET_ERROR(EIO));
300 
301 	return (0);
302 }
303