Skip to content

Commit e270db8

Browse files
committed
Chacha20-Poly1305 encryption
This commit implements the Chacha20-Poly1305 AEAD from RFC 8439 as a new algorithm option for encrypted datasets. AES (and particularly the default AES-GCM mode used in OpenZFS) is known to be very slow on systems without hardware assistance. There are many such machines out there could make good use of OpenZFS, especially low-cost machines and small boards that would otherwise make very nice storage machines. The Raspberry Pi series of machines are a good example. The best option for these systems is an encryption option that performs well in software. Chacha20-Poly1305 is the current "standard" option for this in many contexts, and is a good choice for OpenZFS. The core Chacha20 and Poly1305 implementations are taken from Loup Valliant's Monocypher. These were chosen because they are compact, easy to read, easy to use and the author has written extensively about its development, all of which give me confidence that there are unlikely to be any surprises. I've added a KCF-style module to the ICP to implement the AEAD. This implements just enough for OpenZFS, and is not suitable as a general-purpose KCF for Illumos (though it could be the starting point for one). For FreeBSD, which does not use the ICP, I've instead hooked it up to FreeBSD's builtin crypto stack. The rest is adding an enabling property value and a feature flag and and hooking it up to all the right touch points, and documentation updates. The existing tests that cycle through the possible encryption options have been extended to add one more. I've added a test to ensure that raw receives of chacha20-poly1305 datasets do the right thing based on the state of the feature flag on the receiving side. There's also a test unit that runs the test vectors in RFC 8439 against Chacha20, Poly1305 and the AEAD in the ICP that combines them. This is most useful as a sanity check during future work to add alternate (accelerated) implementations. Finally, manual interop testing has been done to confirm that pools and streams can be moved between Linux and FreeBSD correctly. Light and uncontrolled performance testing on a Raspberry Pi 4B (Broadcom BCM2711, no hardware AES) writing to a chacha20-poly1305 dataset was ~2.4x faster than aes-256-gcm on the same hardware. On a Fitlet2 (Celeron J3455, AES-NI but no AVX (#10846)) it was ~1.3x faster. Sponsored-by: https://despairlabs.com/sponsor/ Signed-off-by: Rob Norris <robn@despairlabs.com>
1 parent cb36f4f commit e270db8

File tree

33 files changed

+2085
-52
lines changed

33 files changed

+2085
-52
lines changed

Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ cstyle:
124124
! -name 'zfs_config.*' ! -name '*.mod.c' \
125125
! -name 'opt_global.h' ! -name '*_if*.h' \
126126
! -name 'zstd_compat_wrapper.h' \
127+
! -name 'monocypher.[ch]' \
127128
! -path './module/zstd/lib/*' \
128129
! -path './include/sys/lua/*' \
129130
! -path './module/lua/l*.[ch]' \

include/os/freebsd/zfs/sys/freebsd_crypto.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#define SUN_CKM_AES_CCM "CKM_AES_CCM"
4242
#define SUN_CKM_AES_GCM "CKM_AES_GCM"
4343
#define SUN_CKM_SHA512_HMAC "CKM_SHA512_HMAC"
44+
#define SUN_CKM_CHACHA20_POLY1305 "CKM_CHACHA20_POLY1305"
4445

4546
#define CRYPTO_BITS2BYTES(n) ((n) == 0 ? 0 : (((n) - 1) >> 3) + 1)
4647
#define CRYPTO_BYTES2BITS(n) ((n) << 3)

include/sys/crypto/common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ typedef uint32_t crypto_keysize_unit_t;
8282
#define SUN_CKM_SHA512_HMAC "CKM_SHA512_HMAC"
8383
#define SUN_CKM_AES_CCM "CKM_AES_CCM"
8484
#define SUN_CKM_AES_GCM "CKM_AES_GCM"
85+
#define SUN_CKM_CHACHA20_POLY1305 "CKM_CHACHA20_POLY1305"
8586

8687
/* Data arguments of cryptographic operations */
8788

include/sys/crypto/icp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
#ifndef _SYS_CRYPTO_ALGS_H
2727
#define _SYS_CRYPTO_ALGS_H
2828

29+
int chapoly_mod_init(void);
30+
int chapoly_mod_fini(void);
31+
2932
int aes_mod_init(void);
3033
int aes_mod_fini(void);
3134

include/sys/fs/zfs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1888,6 +1888,7 @@ enum zio_encrypt {
18881888
ZIO_CRYPT_AES_128_GCM,
18891889
ZIO_CRYPT_AES_192_GCM,
18901890
ZIO_CRYPT_AES_256_GCM,
1891+
ZIO_CRYPT_CHACHA20_POLY1305,
18911892
ZIO_CRYPT_FUNCTIONS
18921893
};
18931894

include/sys/zio_crypt.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ struct zbookmark_phys;
4545
typedef enum zio_crypt_type {
4646
ZC_TYPE_NONE = 0,
4747
ZC_TYPE_CCM,
48-
ZC_TYPE_GCM
48+
ZC_TYPE_GCM,
49+
ZC_TYPE_CHACHA20_POLY1305,
4950
} zio_crypt_type_t;
5051

5152
/* table of supported crypto algorithms, modes and keylengths. */
@@ -60,7 +61,7 @@ typedef struct zio_crypt_info {
6061
#else
6162
crypto_mech_name_t ci_mechname;
6263
#endif
63-
/* cipher mode type (GCM, CCM) */
64+
/* cipher mode type (GCM, CCM, ChaCha20-Poly1305) */
6465
zio_crypt_type_t ci_crypt_type;
6566

6667
/* length of the encryption key */

include/zfeature_common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ typedef enum spa_feature {
8383
SPA_FEATURE_REDACTION_LIST_SPILL,
8484
SPA_FEATURE_RAIDZ_EXPANSION,
8585
SPA_FEATURE_FAST_DEDUP,
86+
SPA_FEATURE_CHACHA20_POLY1305,
8687
SPA_FEATURES
8788
} spa_feature_t;
8889

lib/libicp/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ nodist_libicp_la_SOURCES = \
2929
module/icp/algs/skein/skein_block.c \
3030
module/icp/algs/skein/skein_iv.c \
3131
module/icp/illumos-crypto.c \
32+
module/icp/monocypher.c \
3233
module/icp/io/aes.c \
3334
module/icp/io/sha2_mod.c \
35+
module/icp/io/chapoly.c \
3436
module/icp/core/kcf_sched.c \
3537
module/icp/core/kcf_prov_lib.c \
3638
module/icp/core/kcf_callprov.c \

lib/libzfs/libzfs.abi

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,8 @@
183183
<elf-symbol name='fsleep' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
184184
<elf-symbol name='get_dataset_depth' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
185185
<elf-symbol name='get_system_hostid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
186-
<elf-symbol name='getexecname' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
187186
<elf-symbol name='get_timestamp' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
187+
<elf-symbol name='getexecname' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
188188
<elf-symbol name='getextmntent' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
189189
<elf-symbol name='getmntany' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
190190
<elf-symbol name='getprop_uint64' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -466,6 +466,7 @@
466466
<elf-symbol name='zpool_clear' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
467467
<elf-symbol name='zpool_clear_label' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
468468
<elf-symbol name='zpool_close' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
469+
<elf-symbol name='zpool_collect_unsup_feat' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
469470
<elf-symbol name='zpool_create' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
470471
<elf-symbol name='zpool_default_search_paths' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
471472
<elf-symbol name='zpool_destroy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -485,8 +486,8 @@
485486
<elf-symbol name='zpool_export_force' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
486487
<elf-symbol name='zpool_feature_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
487488
<elf-symbol name='zpool_find_config' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
488-
<elf-symbol name='zpool_find_vdev' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
489489
<elf-symbol name='zpool_find_parent_vdev' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
490+
<elf-symbol name='zpool_find_vdev' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
490491
<elf-symbol name='zpool_find_vdev_by_physpath' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
491492
<elf-symbol name='zpool_free_handles' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
492493
<elf-symbol name='zpool_get_all_vdev_props' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -529,7 +530,6 @@
529530
<elf-symbol name='zpool_prefetch' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
530531
<elf-symbol name='zpool_prepare_and_label_disk' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
531532
<elf-symbol name='zpool_prepare_disk' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
532-
<elf-symbol name='zpool_collect_unsup_feat' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
533533
<elf-symbol name='zpool_prop_align_right' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
534534
<elf-symbol name='zpool_prop_column_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
535535
<elf-symbol name='zpool_prop_default_numeric' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -616,7 +616,7 @@
616616
<elf-symbol name='fletcher_4_superscalar_ops' size='128' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
617617
<elf-symbol name='libzfs_config_ops' size='16' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
618618
<elf-symbol name='sa_protocol_names' size='16' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
619-
<elf-symbol name='spa_feature_table' size='2352' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
619+
<elf-symbol name='spa_feature_table' size='2408' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
620620
<elf-symbol name='zfeature_checks_disable' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
621621
<elf-symbol name='zfs_deleg_perm_tab' size='512' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
622622
<elf-symbol name='zfs_history_event_names' size='328' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -6007,7 +6007,8 @@
60076007
<enumerator name='SPA_FEATURE_REDACTION_LIST_SPILL' value='39'/>
60086008
<enumerator name='SPA_FEATURE_RAIDZ_EXPANSION' value='40'/>
60096009
<enumerator name='SPA_FEATURE_FAST_DEDUP' value='41'/>
6010-
<enumerator name='SPA_FEATURES' value='42'/>
6010+
<enumerator name='SPA_FEATURE_CHACHA20_POLY1305' value='42'/>
6011+
<enumerator name='SPA_FEATURES' value='43'/>
60116012
</enum-decl>
60126013
<typedef-decl name='spa_feature_t' type-id='33ecb627' id='d6618c78'/>
60136014
<qualified-type-def type-id='80f4b756' const='yes' id='b99c00c9'/>
@@ -7831,7 +7832,7 @@
78317832
</data-member>
78327833
</class-decl>
78337834
<typedef-decl name='vdev_cbdata_t' type-id='b8006be8' id='a9679c94'/>
7834-
<class-decl name='zprop_get_cbdata' size-in-bits='832' is-struct='yes' visibility='default' id='f3d3c319'>
7835+
<class-decl name='zprop_get_cbdata' size-in-bits='960' is-struct='yes' visibility='default' id='f3d3c319'>
78357836
<data-member access='public' layout-offset-in-bits='0'>
78367837
<var-decl name='cb_sources' type-id='95e97e5e' visibility='default'/>
78377838
</data-member>
@@ -7850,6 +7851,9 @@
78507851
<data-member access='public' layout-offset-in-bits='448'>
78517852
<var-decl name='cb_first' type-id='c19b74c3' visibility='default'/>
78527853
</data-member>
7854+
<data-member access='public' layout-offset-in-bits='480'>
7855+
<var-decl name='cb_json' type-id='c19b74c3' visibility='default'/>
7856+
</data-member>
78537857
<data-member access='public' layout-offset-in-bits='512'>
78547858
<var-decl name='cb_proplist' type-id='3a9b2288' visibility='default'/>
78557859
</data-member>
@@ -7859,6 +7863,15 @@
78597863
<data-member access='public' layout-offset-in-bits='640'>
78607864
<var-decl name='cb_vdevs' type-id='a9679c94' visibility='default'/>
78617865
</data-member>
7866+
<data-member access='public' layout-offset-in-bits='832'>
7867+
<var-decl name='cb_jsobj' type-id='5ce45b60' visibility='default'/>
7868+
</data-member>
7869+
<data-member access='public' layout-offset-in-bits='896'>
7870+
<var-decl name='cb_json_as_int' type-id='c19b74c3' visibility='default'/>
7871+
</data-member>
7872+
<data-member access='public' layout-offset-in-bits='928'>
7873+
<var-decl name='cb_json_pool_key_guid' type-id='c19b74c3' visibility='default'/>
7874+
</data-member>
78627875
</class-decl>
78637876
<typedef-decl name='zprop_get_cbdata_t' type-id='f3d3c319' id='f3d87113'/>
78647877
<typedef-decl name='zprop_func' type-id='2e711a2a' id='1ec3747a'/>
@@ -7962,6 +7975,11 @@
79627975
<qualified-type-def type-id='d33f11cb' restrict='yes' id='5c53ba29'/>
79637976
<pointer-type-def type-id='ffa52b96' size-in-bits='64' id='76c8174b'/>
79647977
<pointer-type-def type-id='f3d87113' size-in-bits='64' id='0d2a0670'/>
7978+
<function-decl name='nvlist_print_json' visibility='default' binding='global' size-in-bits='64'>
7979+
<parameter type-id='822cd80b'/>
7980+
<parameter type-id='5ce45b60'/>
7981+
<return type-id='95e97e5e'/>
7982+
</function-decl>
79657983
<function-decl name='zpool_label_disk' mangled-name='zpool_label_disk' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_label_disk'>
79667984
<parameter type-id='b0382bb3'/>
79677985
<parameter type-id='4c81de99'/>
@@ -8069,6 +8087,11 @@
80698087
<parameter type-id='d33f11cb'/>
80708088
<return type-id='48b5725f'/>
80718089
</function-decl>
8090+
<function-decl name='putc' visibility='default' binding='global' size-in-bits='64'>
8091+
<parameter type-id='95e97e5e'/>
8092+
<parameter type-id='822cd80b'/>
8093+
<return type-id='95e97e5e'/>
8094+
</function-decl>
80728095
<function-decl name='puts' visibility='default' binding='global' size-in-bits='64'>
80738096
<parameter type-id='80f4b756'/>
80748097
<return type-id='95e97e5e'/>
@@ -8087,6 +8110,11 @@
80878110
<parameter type-id='95e97e5e'/>
80888111
<return type-id='48b5725f'/>
80898112
</function-decl>
8113+
<function-decl name='strspn' visibility='default' binding='global' size-in-bits='64'>
8114+
<parameter type-id='80f4b756'/>
8115+
<parameter type-id='80f4b756'/>
8116+
<return type-id='b59d7dce'/>
8117+
</function-decl>
80908118
<function-decl name='strnlen' visibility='default' binding='global' size-in-bits='64'>
80918119
<parameter type-id='80f4b756'/>
80928120
<parameter type-id='b59d7dce'/>
@@ -8286,12 +8314,12 @@
82868314
<function-decl name='zfs_version_print' mangled-name='zfs_version_print' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_version_print'>
82878315
<return type-id='95e97e5e'/>
82888316
</function-decl>
8289-
<function-decl name='use_color' mangled-name='use_color' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='use_color'>
8290-
<return type-id='95e97e5e'/>
8291-
</function-decl>
82928317
<function-decl name='zfs_version_nvlist' mangled-name='zfs_version_nvlist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_version_nvlist'>
82938318
<return type-id='5ce45b60'/>
82948319
</function-decl>
8320+
<function-decl name='use_color' mangled-name='use_color' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='use_color'>
8321+
<return type-id='95e97e5e'/>
8322+
</function-decl>
82958323
<function-decl name='printf_color' mangled-name='printf_color' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='printf_color'>
82968324
<parameter type-id='80f4b756' name='color'/>
82978325
<parameter type-id='80f4b756' name='format'/>
@@ -8796,11 +8824,6 @@
87968824
<parameter type-id='78c01427'/>
87978825
<return type-id='13956559'/>
87988826
</function-decl>
8799-
<function-decl name='strspn' visibility='default' binding='global' size-in-bits='64'>
8800-
<parameter type-id='80f4b756'/>
8801-
<parameter type-id='80f4b756'/>
8802-
<return type-id='b59d7dce'/>
8803-
</function-decl>
88048827
<function-decl name='zfs_dirnamelen' mangled-name='zfs_dirnamelen' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_dirnamelen'>
88058828
<parameter type-id='80f4b756' name='path'/>
88068829
<return type-id='79a0948f'/>
@@ -9132,8 +9155,8 @@
91329155
</function-decl>
91339156
</abi-instr>
91349157
<abi-instr address-size='64' path='module/zcommon/zfeature_common.c' language='LANG_C99'>
9135-
<array-type-def dimensions='1' type-id='83f29ca2' size-in-bits='18816' id='b937914f'>
9136-
<subrange length='42' type-id='7359adad' id='cb7c937f'/>
9158+
<array-type-def dimensions='1' type-id='83f29ca2' size-in-bits='19264' id='bd39d632'>
9159+
<subrange length='43' type-id='7359adad' id='8f7e73a2'/>
91379160
</array-type-def>
91389161
<enum-decl name='zfeature_flags' id='6db816a4'>
91399162
<underlying-type type-id='9cac1fee'/>
@@ -9210,7 +9233,7 @@
92109233
<pointer-type-def type-id='611586a1' size-in-bits='64' id='2e243169'/>
92119234
<qualified-type-def type-id='eaa32e2f' const='yes' id='83be723c'/>
92129235
<pointer-type-def type-id='83be723c' size-in-bits='64' id='7acd98a2'/>
9213-
<var-decl name='spa_feature_table' type-id='b937914f' mangled-name='spa_feature_table' visibility='default' elf-symbol-id='spa_feature_table'/>
9236+
<var-decl name='spa_feature_table' type-id='bd39d632' mangled-name='spa_feature_table' visibility='default' elf-symbol-id='spa_feature_table'/>
92149237
<var-decl name='zfeature_checks_disable' type-id='c19b74c3' mangled-name='zfeature_checks_disable' visibility='default' elf-symbol-id='zfeature_checks_disable'/>
92159238
<function-decl name='opendir' visibility='default' binding='global' size-in-bits='64'>
92169239
<parameter type-id='80f4b756'/>

man/man7/zfsprops.7

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,9 @@
3737
.\" Copyright 2019 Joyent, Inc.
3838
.\" Copyright (c) 2019, Kjeld Schouten-Lebbing
3939
.\" Copyright (c) 2022 Hewlett Packard Enterprise Development LP.
40+
.\" Copyright (c) 2023, Rob Norris <robn@despairlabs.com>
4041
.\"
41-
.Dd June 29, 2024
42+
.Dd July 26, 2024
4243
.Dt ZFSPROPS 7
4344
.Os
4445
.
@@ -1077,7 +1078,7 @@ This property can also be referred to by its shortened column name,
10771078
.It Xo
10781079
.Sy encryption Ns = Ns Sy off Ns | Ns Sy on Ns | Ns Sy aes-128-ccm Ns | Ns
10791080
.Sy aes-192-ccm Ns | Ns Sy aes-256-ccm Ns | Ns Sy aes-128-gcm Ns | Ns
1080-
.Sy aes-192-gcm Ns | Ns Sy aes-256-gcm
1081+
.Sy aes-192-gcm Ns | Ns Sy aes-256-gcm Ns | Ns Sy chacha20-poly1305
10811082
.Xc
10821083
Controls the encryption cipher suite (block cipher, key length, and mode) used
10831084
for this dataset.
@@ -1096,6 +1097,12 @@ selected, which is currently
10961097
In order to provide consistent data protection, encryption must be specified at
10971098
dataset creation time and it cannot be changed afterwards.
10981099
.Pp
1100+
On systems lacking hardware-accelerated AES (many non-x86 boards)
1101+
.Sy chacha20-poly1305
1102+
will usually offer better performance without compromising security.
1103+
On x86, or when datasets may be mounted on on older versions of ZFS, an AES
1104+
suite is the best choice.
1105+
.Pp
10991106
For more details and caveats about encryption see the
11001107
.Sx Encryption
11011108
section of

0 commit comments

Comments
 (0)