linux/crypto/dh.c

921 lines
29 KiB

crypto: dh - implement private key generation primitive for ffdheXYZ(dh) The support for NVME in-band authentication currently in the works ([1]) needs to generate ephemeral DH keys for use with the RFC 7919 safe-prime FFDHE groups. In analogy to ECDH and its ecc_gen_privkey(), implement a dh_safe_prime_gen_privkey() and invoke it from the ffdheXYZ(dh) templates' common ->set_secret(), i.e. dh_safe_prime_set_secret(), in case the input ->key_size is zero. As the RFC 7919 FFDHE groups are classified as approved safe-prime groups by SP800-56Arev3, it's worthwhile to make the new dh_safe_prime_gen_privkey() to follow the approach specified in SP800-56Arev3, sec. 5.6.1.1.3 ("Key-Pair Generation Using Extra Random Bits") in order to achieve conformance. SP800-56Arev3 specifies a lower as well as an upper bound on the generated key's length: - it must be >= two times the maximum supported security strength of the group in question and - it must be <= the length of the domain parameter Q. For any safe-prime group Q = (P - 1)/2 by definition and the individual maximum supported security strengths as specified by SP800-56Arev3 have been made available as part of the FFDHE dh_safe_prime definitions introduced with a previous patch. Make dh_safe_prime_gen_privkey() pick twice the maximum supported strength rounded up to the next power of two for the output key size. This choice respects both, the lower and upper bounds given by SP800-90Arev3 for any of the approved safe-prime groups and is also in line with the NVME base spec 2.0, which requires the key size to be >= 256bits. [1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de Signed-off-by: Nicolai Stange <nstange@suse.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 13:10:55 +01:00
crypto: dh - Fix double free of ctx->p When setting the secret with the software Diffie-Hellman implementation, if allocating 'g' failed (e.g. if it was longer than MAX_EXTERN_MPI_BITS), then 'p' was freed twice: once immediately, and once later when the crypto_kpp tfm was destroyed. Fix it by using dh_free_ctx() (renamed to dh_clear_ctx()) in the error paths, as that correctly sets the pointers to NULL. KASAN report: MPI: mpi too large (32760 bits) ================================================================== BUG: KASAN: use-after-free in mpi_free+0x131/0x170 Read of size 4 at addr ffff88006c7cdf90 by task reproduce_doubl/367 CPU: 1 PID: 367 Comm: reproduce_doubl Not tainted 4.14.0-rc7-00040-g05298abde6fe #7 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Call Trace: dump_stack+0xb3/0x10b ? mpi_free+0x131/0x170 print_address_description+0x79/0x2a0 ? mpi_free+0x131/0x170 kasan_report+0x236/0x340 ? akcipher_register_instance+0x90/0x90 __asan_report_load4_noabort+0x14/0x20 mpi_free+0x131/0x170 ? akcipher_register_instance+0x90/0x90 dh_exit_tfm+0x3d/0x140 crypto_kpp_exit_tfm+0x52/0x70 crypto_destroy_tfm+0xb3/0x250 __keyctl_dh_compute+0x640/0xe90 ? kasan_slab_free+0x12f/0x180 ? dh_data_from_key+0x240/0x240 ? key_create_or_update+0x1ee/0xb20 ? key_instantiate_and_link+0x440/0x440 ? lock_contended+0xee0/0xee0 ? kfree+0xcf/0x210 ? SyS_add_key+0x268/0x340 keyctl_dh_compute+0xb3/0xf1 ? __keyctl_dh_compute+0xe90/0xe90 ? SyS_add_key+0x26d/0x340 ? entry_SYSCALL_64_fastpath+0x5/0xbe ? trace_hardirqs_on_caller+0x3f4/0x560 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe RIP: 0033:0x43ccf9 RSP: 002b:00007ffeeec96158 EFLAGS: 00000246 ORIG_RAX: 00000000000000fa RAX: ffffffffffffffda RBX: 000000000248b9b9 RCX: 000000000043ccf9 RDX: 00007ffeeec96170 RSI: 00007ffeeec96160 RDI: 0000000000000017 RBP: 0000000000000046 R08: 0000000000000000 R09: 0248b9b9143dc936 R10: 0000000000001000 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000409670 R14: 0000000000409700 R15: 0000000000000000 Allocated by task 367: save_stack_trace+0x16/0x20 kasan_kmalloc+0xeb/0x180 kmem_cache_alloc_trace+0x114/0x300 mpi_alloc+0x4b/0x230 mpi_read_raw_data+0xbe/0x360 dh_set_secret+0x1dc/0x460 __keyctl_dh_compute+0x623/0xe90 keyctl_dh_compute+0xb3/0xf1 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe Freed by task 367: save_stack_trace+0x16/0x20 kasan_slab_free+0xab/0x180 kfree+0xb5/0x210 mpi_free+0xcb/0x170 dh_set_secret+0x2d7/0x460 __keyctl_dh_compute+0x623/0xe90 keyctl_dh_compute+0xb3/0xf1 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe Fixes: 802c7f1c84e4 ("crypto: dh - Add DH software implementation") Cc: <stable@vger.kernel.org> # v4.8+ Signed-off-by: Eric Biggers <ebiggers@google.com> Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2017-11-05 18:30:44 -08:00
crypto: dh - Fix double free of ctx->p When setting the secret with the software Diffie-Hellman implementation, if allocating 'g' failed (e.g. if it was longer than MAX_EXTERN_MPI_BITS), then 'p' was freed twice: once immediately, and once later when the crypto_kpp tfm was destroyed. Fix it by using dh_free_ctx() (renamed to dh_clear_ctx()) in the error paths, as that correctly sets the pointers to NULL. KASAN report: MPI: mpi too large (32760 bits) ================================================================== BUG: KASAN: use-after-free in mpi_free+0x131/0x170 Read of size 4 at addr ffff88006c7cdf90 by task reproduce_doubl/367 CPU: 1 PID: 367 Comm: reproduce_doubl Not tainted 4.14.0-rc7-00040-g05298abde6fe #7 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Call Trace: dump_stack+0xb3/0x10b ? mpi_free+0x131/0x170 print_address_description+0x79/0x2a0 ? mpi_free+0x131/0x170 kasan_report+0x236/0x340 ? akcipher_register_instance+0x90/0x90 __asan_report_load4_noabort+0x14/0x20 mpi_free+0x131/0x170 ? akcipher_register_instance+0x90/0x90 dh_exit_tfm+0x3d/0x140 crypto_kpp_exit_tfm+0x52/0x70 crypto_destroy_tfm+0xb3/0x250 __keyctl_dh_compute+0x640/0xe90 ? kasan_slab_free+0x12f/0x180 ? dh_data_from_key+0x240/0x240 ? key_create_or_update+0x1ee/0xb20 ? key_instantiate_and_link+0x440/0x440 ? lock_contended+0xee0/0xee0 ? kfree+0xcf/0x210 ? SyS_add_key+0x268/0x340 keyctl_dh_compute+0xb3/0xf1 ? __keyctl_dh_compute+0xe90/0xe90 ? SyS_add_key+0x26d/0x340 ? entry_SYSCALL_64_fastpath+0x5/0xbe ? trace_hardirqs_on_caller+0x3f4/0x560 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe RIP: 0033:0x43ccf9 RSP: 002b:00007ffeeec96158 EFLAGS: 00000246 ORIG_RAX: 00000000000000fa RAX: ffffffffffffffda RBX: 000000000248b9b9 RCX: 000000000043ccf9 RDX: 00007ffeeec96170 RSI: 00007ffeeec96160 RDI: 0000000000000017 RBP: 0000000000000046 R08: 0000000000000000 R09: 0248b9b9143dc936 R10: 0000000000001000 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000409670 R14: 0000000000409700 R15: 0000000000000000 Allocated by task 367: save_stack_trace+0x16/0x20 kasan_kmalloc+0xeb/0x180 kmem_cache_alloc_trace+0x114/0x300 mpi_alloc+0x4b/0x230 mpi_read_raw_data+0xbe/0x360 dh_set_secret+0x1dc/0x460 __keyctl_dh_compute+0x623/0xe90 keyctl_dh_compute+0xb3/0xf1 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe Freed by task 367: save_stack_trace+0x16/0x20 kasan_slab_free+0xab/0x180 kfree+0xb5/0x210 mpi_free+0xcb/0x170 dh_set_secret+0x2d7/0x460 __keyctl_dh_compute+0x623/0xe90 keyctl_dh_compute+0xb3/0xf1 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe Fixes: 802c7f1c84e4 ("crypto: dh - Add DH software implementation") Cc: <stable@vger.kernel.org> # v4.8+ Signed-off-by: Eric Biggers <ebiggers@google.com> Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2017-11-05 18:30:44 -08:00
crypto: dh - Fix double free of ctx->p When setting the secret with the software Diffie-Hellman implementation, if allocating 'g' failed (e.g. if it was longer than MAX_EXTERN_MPI_BITS), then 'p' was freed twice: once immediately, and once later when the crypto_kpp tfm was destroyed. Fix it by using dh_free_ctx() (renamed to dh_clear_ctx()) in the error paths, as that correctly sets the pointers to NULL. KASAN report: MPI: mpi too large (32760 bits) ================================================================== BUG: KASAN: use-after-free in mpi_free+0x131/0x170 Read of size 4 at addr ffff88006c7cdf90 by task reproduce_doubl/367 CPU: 1 PID: 367 Comm: reproduce_doubl Not tainted 4.14.0-rc7-00040-g05298abde6fe #7 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Call Trace: dump_stack+0xb3/0x10b ? mpi_free+0x131/0x170 print_address_description+0x79/0x2a0 ? mpi_free+0x131/0x170 kasan_report+0x236/0x340 ? akcipher_register_instance+0x90/0x90 __asan_report_load4_noabort+0x14/0x20 mpi_free+0x131/0x170 ? akcipher_register_instance+0x90/0x90 dh_exit_tfm+0x3d/0x140 crypto_kpp_exit_tfm+0x52/0x70 crypto_destroy_tfm+0xb3/0x250 __keyctl_dh_compute+0x640/0xe90 ? kasan_slab_free+0x12f/0x180 ? dh_data_from_key+0x240/0x240 ? key_create_or_update+0x1ee/0xb20 ? key_instantiate_and_link+0x440/0x440 ? lock_contended+0xee0/0xee0 ? kfree+0xcf/0x210 ? SyS_add_key+0x268/0x340 keyctl_dh_compute+0xb3/0xf1 ? __keyctl_dh_compute+0xe90/0xe90 ? SyS_add_key+0x26d/0x340 ? entry_SYSCALL_64_fastpath+0x5/0xbe ? trace_hardirqs_on_caller+0x3f4/0x560 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe RIP: 0033:0x43ccf9 RSP: 002b:00007ffeeec96158 EFLAGS: 00000246 ORIG_RAX: 00000000000000fa RAX: ffffffffffffffda RBX: 000000000248b9b9 RCX: 000000000043ccf9 RDX: 00007ffeeec96170 RSI: 00007ffeeec96160 RDI: 0000000000000017 RBP: 0000000000000046 R08: 0000000000000000 R09: 0248b9b9143dc936 R10: 0000000000001000 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000409670 R14: 0000000000409700 R15: 0000000000000000 Allocated by task 367: save_stack_trace+0x16/0x20 kasan_kmalloc+0xeb/0x180 kmem_cache_alloc_trace+0x114/0x300 mpi_alloc+0x4b/0x230 mpi_read_raw_data+0xbe/0x360 dh_set_secret+0x1dc/0x460 __keyctl_dh_compute+0x623/0xe90 keyctl_dh_compute+0xb3/0xf1 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe Freed by task 367: save_stack_trace+0x16/0x20 kasan_slab_free+0xab/0x180 kfree+0xb5/0x210 mpi_free+0xcb/0x170 dh_set_secret+0x2d7/0x460 __keyctl_dh_compute+0x623/0xe90 keyctl_dh_compute+0xb3/0xf1 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe Fixes: 802c7f1c84e4 ("crypto: dh - Add DH software implementation") Cc: <stable@vger.kernel.org> # v4.8+ Signed-off-by: Eric Biggers <ebiggers@google.com> Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2017-11-05 18:30:44 -08:00
crypto: dh - Fix double free of ctx->p When setting the secret with the software Diffie-Hellman implementation, if allocating 'g' failed (e.g. if it was longer than MAX_EXTERN_MPI_BITS), then 'p' was freed twice: once immediately, and once later when the crypto_kpp tfm was destroyed. Fix it by using dh_free_ctx() (renamed to dh_clear_ctx()) in the error paths, as that correctly sets the pointers to NULL. KASAN report: MPI: mpi too large (32760 bits) ================================================================== BUG: KASAN: use-after-free in mpi_free+0x131/0x170 Read of size 4 at addr ffff88006c7cdf90 by task reproduce_doubl/367 CPU: 1 PID: 367 Comm: reproduce_doubl Not tainted 4.14.0-rc7-00040-g05298abde6fe #7 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Call Trace: dump_stack+0xb3/0x10b ? mpi_free+0x131/0x170 print_address_description+0x79/0x2a0 ? mpi_free+0x131/0x170 kasan_report+0x236/0x340 ? akcipher_register_instance+0x90/0x90 __asan_report_load4_noabort+0x14/0x20 mpi_free+0x131/0x170 ? akcipher_register_instance+0x90/0x90 dh_exit_tfm+0x3d/0x140 crypto_kpp_exit_tfm+0x52/0x70 crypto_destroy_tfm+0xb3/0x250 __keyctl_dh_compute+0x640/0xe90 ? kasan_slab_free+0x12f/0x180 ? dh_data_from_key+0x240/0x240 ? key_create_or_update+0x1ee/0xb20 ? key_instantiate_and_link+0x440/0x440 ? lock_contended+0xee0/0xee0 ? kfree+0xcf/0x210 ? SyS_add_key+0x268/0x340 keyctl_dh_compute+0xb3/0xf1 ? __keyctl_dh_compute+0xe90/0xe90 ? SyS_add_key+0x26d/0x340 ? entry_SYSCALL_64_fastpath+0x5/0xbe ? trace_hardirqs_on_caller+0x3f4/0x560 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe RIP: 0033:0x43ccf9 RSP: 002b:00007ffeeec96158 EFLAGS: 00000246 ORIG_RAX: 00000000000000fa RAX: ffffffffffffffda RBX: 000000000248b9b9 RCX: 000000000043ccf9 RDX: 00007ffeeec96170 RSI: 00007ffeeec96160 RDI: 0000000000000017 RBP: 0000000000000046 R08: 0000000000000000 R09: 0248b9b9143dc936 R10: 0000000000001000 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000409670 R14: 0000000000409700 R15: 0000000000000000 Allocated by task 367: save_stack_trace+0x16/0x20 kasan_kmalloc+0xeb/0x180 kmem_cache_alloc_trace+0x114/0x300 mpi_alloc+0x4b/0x230 mpi_read_raw_data+0xbe/0x360 dh_set_secret+0x1dc/0x460 __keyctl_dh_compute+0x623/0xe90 keyctl_dh_compute+0xb3/0xf1 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe Freed by task 367: save_stack_trace+0x16/0x20 kasan_slab_free+0xab/0x180 kfree+0xb5/0x210 mpi_free+0xcb/0x170 dh_set_secret+0x2d7/0x460 __keyctl_dh_compute+0x623/0xe90 keyctl_dh_compute+0xb3/0xf1 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe Fixes: 802c7f1c84e4 ("crypto: dh - Add DH software implementation") Cc: <stable@vger.kernel.org> # v4.8+ Signed-off-by: Eric Biggers <ebiggers@google.com> Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2017-11-05 18:30:44 -08:00
crypto: dh - Fix double free of ctx->p When setting the secret with the software Diffie-Hellman implementation, if allocating 'g' failed (e.g. if it was longer than MAX_EXTERN_MPI_BITS), then 'p' was freed twice: once immediately, and once later when the crypto_kpp tfm was destroyed. Fix it by using dh_free_ctx() (renamed to dh_clear_ctx()) in the error paths, as that correctly sets the pointers to NULL. KASAN report: MPI: mpi too large (32760 bits) ================================================================== BUG: KASAN: use-after-free in mpi_free+0x131/0x170 Read of size 4 at addr ffff88006c7cdf90 by task reproduce_doubl/367 CPU: 1 PID: 367 Comm: reproduce_doubl Not tainted 4.14.0-rc7-00040-g05298abde6fe #7 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Call Trace: dump_stack+0xb3/0x10b ? mpi_free+0x131/0x170 print_address_description+0x79/0x2a0 ? mpi_free+0x131/0x170 kasan_report+0x236/0x340 ? akcipher_register_instance+0x90/0x90 __asan_report_load4_noabort+0x14/0x20 mpi_free+0x131/0x170 ? akcipher_register_instance+0x90/0x90 dh_exit_tfm+0x3d/0x140 crypto_kpp_exit_tfm+0x52/0x70 crypto_destroy_tfm+0xb3/0x250 __keyctl_dh_compute+0x640/0xe90 ? kasan_slab_free+0x12f/0x180 ? dh_data_from_key+0x240/0x240 ? key_create_or_update+0x1ee/0xb20 ? key_instantiate_and_link+0x440/0x440 ? lock_contended+0xee0/0xee0 ? kfree+0xcf/0x210 ? SyS_add_key+0x268/0x340 keyctl_dh_compute+0xb3/0xf1 ? __keyctl_dh_compute+0xe90/0xe90 ? SyS_add_key+0x26d/0x340 ? entry_SYSCALL_64_fastpath+0x5/0xbe ? trace_hardirqs_on_caller+0x3f4/0x560 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe RIP: 0033:0x43ccf9 RSP: 002b:00007ffeeec96158 EFLAGS: 00000246 ORIG_RAX: 00000000000000fa RAX: ffffffffffffffda RBX: 000000000248b9b9 RCX: 000000000043ccf9 RDX: 00007ffeeec96170 RSI: 00007ffeeec96160 RDI: 0000000000000017 RBP: 0000000000000046 R08: 0000000000000000 R09: 0248b9b9143dc936 R10: 0000000000001000 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000409670 R14: 0000000000409700 R15: 0000000000000000 Allocated by task 367: save_stack_trace+0x16/0x20 kasan_kmalloc+0xeb/0x180 kmem_cache_alloc_trace+0x114/0x300 mpi_alloc+0x4b/0x230 mpi_read_raw_data+0xbe/0x360 dh_set_secret+0x1dc/0x460 __keyctl_dh_compute+0x623/0xe90 keyctl_dh_compute+0xb3/0xf1 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe Freed by task 367: save_stack_trace+0x16/0x20 kasan_slab_free+0xab/0x180 kfree+0xb5/0x210 mpi_free+0xcb/0x170 dh_set_secret+0x2d7/0x460 __keyctl_dh_compute+0x623/0xe90 keyctl_dh_compute+0xb3/0xf1 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe Fixes: 802c7f1c84e4 ("crypto: dh - Add DH software implementation") Cc: <stable@vger.kernel.org> # v4.8+ Signed-off-by: Eric Biggers <ebiggers@google.com> Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2017-11-05 18:30:44 -08:00
crypto: dh - Fix double free of ctx->p When setting the secret with the software Diffie-Hellman implementation, if allocating 'g' failed (e.g. if it was longer than MAX_EXTERN_MPI_BITS), then 'p' was freed twice: once immediately, and once later when the crypto_kpp tfm was destroyed. Fix it by using dh_free_ctx() (renamed to dh_clear_ctx()) in the error paths, as that correctly sets the pointers to NULL. KASAN report: MPI: mpi too large (32760 bits) ================================================================== BUG: KASAN: use-after-free in mpi_free+0x131/0x170 Read of size 4 at addr ffff88006c7cdf90 by task reproduce_doubl/367 CPU: 1 PID: 367 Comm: reproduce_doubl Not tainted 4.14.0-rc7-00040-g05298abde6fe #7 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Call Trace: dump_stack+0xb3/0x10b ? mpi_free+0x131/0x170 print_address_description+0x79/0x2a0 ? mpi_free+0x131/0x170 kasan_report+0x236/0x340 ? akcipher_register_instance+0x90/0x90 __asan_report_load4_noabort+0x14/0x20 mpi_free+0x131/0x170 ? akcipher_register_instance+0x90/0x90 dh_exit_tfm+0x3d/0x140 crypto_kpp_exit_tfm+0x52/0x70 crypto_destroy_tfm+0xb3/0x250 __keyctl_dh_compute+0x640/0xe90 ? kasan_slab_free+0x12f/0x180 ? dh_data_from_key+0x240/0x240 ? key_create_or_update+0x1ee/0xb20 ? key_instantiate_and_link+0x440/0x440 ? lock_contended+0xee0/0xee0 ? kfree+0xcf/0x210 ? SyS_add_key+0x268/0x340 keyctl_dh_compute+0xb3/0xf1 ? __keyctl_dh_compute+0xe90/0xe90 ? SyS_add_key+0x26d/0x340 ? entry_SYSCALL_64_fastpath+0x5/0xbe ? trace_hardirqs_on_caller+0x3f4/0x560 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe RIP: 0033:0x43ccf9 RSP: 002b:00007ffeeec96158 EFLAGS: 00000246 ORIG_RAX: 00000000000000fa RAX: ffffffffffffffda RBX: 000000000248b9b9 RCX: 000000000043ccf9 RDX: 00007ffeeec96170 RSI: 00007ffeeec96160 RDI: 0000000000000017 RBP: 0000000000000046 R08: 0000000000000000 R09: 0248b9b9143dc936 R10: 0000000000001000 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000409670 R14: 0000000000409700 R15: 0000000000000000 Allocated by task 367: save_stack_trace+0x16/0x20 kasan_kmalloc+0xeb/0x180 kmem_cache_alloc_trace+0x114/0x300 mpi_alloc+0x4b/0x230 mpi_read_raw_data+0xbe/0x360 dh_set_secret+0x1dc/0x460 __keyctl_dh_compute+0x623/0xe90 keyctl_dh_compute+0xb3/0xf1 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe Freed by task 367: save_stack_trace+0x16/0x20 kasan_slab_free+0xab/0x180 kfree+0xb5/0x210 mpi_free+0xcb/0x170 dh_set_secret+0x2d7/0x460 __keyctl_dh_compute+0x623/0xe90 keyctl_dh_compute+0xb3/0xf1 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe Fixes: 802c7f1c84e4 ("crypto: dh - Add DH software implementation") Cc: <stable@vger.kernel.org> # v4.8+ Signed-off-by: Eric Biggers <ebiggers@google.com> Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2017-11-05 18:30:44 -08:00
crypto: dh - Fix double free of ctx->p When setting the secret with the software Diffie-Hellman implementation, if allocating 'g' failed (e.g. if it was longer than MAX_EXTERN_MPI_BITS), then 'p' was freed twice: once immediately, and once later when the crypto_kpp tfm was destroyed. Fix it by using dh_free_ctx() (renamed to dh_clear_ctx()) in the error paths, as that correctly sets the pointers to NULL. KASAN report: MPI: mpi too large (32760 bits) ================================================================== BUG: KASAN: use-after-free in mpi_free+0x131/0x170 Read of size 4 at addr ffff88006c7cdf90 by task reproduce_doubl/367 CPU: 1 PID: 367 Comm: reproduce_doubl Not tainted 4.14.0-rc7-00040-g05298abde6fe #7 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Call Trace: dump_stack+0xb3/0x10b ? mpi_free+0x131/0x170 print_address_description+0x79/0x2a0 ? mpi_free+0x131/0x170 kasan_report+0x236/0x340 ? akcipher_register_instance+0x90/0x90 __asan_report_load4_noabort+0x14/0x20 mpi_free+0x131/0x170 ? akcipher_register_instance+0x90/0x90 dh_exit_tfm+0x3d/0x140 crypto_kpp_exit_tfm+0x52/0x70 crypto_destroy_tfm+0xb3/0x250 __keyctl_dh_compute+0x640/0xe90 ? kasan_slab_free+0x12f/0x180 ? dh_data_from_key+0x240/0x240 ? key_create_or_update+0x1ee/0xb20 ? key_instantiate_and_link+0x440/0x440 ? lock_contended+0xee0/0xee0 ? kfree+0xcf/0x210 ? SyS_add_key+0x268/0x340 keyctl_dh_compute+0xb3/0xf1 ? __keyctl_dh_compute+0xe90/0xe90 ? SyS_add_key+0x26d/0x340 ? entry_SYSCALL_64_fastpath+0x5/0xbe ? trace_hardirqs_on_caller+0x3f4/0x560 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe RIP: 0033:0x43ccf9 RSP: 002b:00007ffeeec96158 EFLAGS: 00000246 ORIG_RAX: 00000000000000fa RAX: ffffffffffffffda RBX: 000000000248b9b9 RCX: 000000000043ccf9 RDX: 00007ffeeec96170 RSI: 00007ffeeec96160 RDI: 0000000000000017 RBP: 0000000000000046 R08: 0000000000000000 R09: 0248b9b9143dc936 R10: 0000000000001000 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000409670 R14: 0000000000409700 R15: 0000000000000000 Allocated by task 367: save_stack_trace+0x16/0x20 kasan_kmalloc+0xeb/0x180 kmem_cache_alloc_trace+0x114/0x300 mpi_alloc+0x4b/0x230 mpi_read_raw_data+0xbe/0x360 dh_set_secret+0x1dc/0x460 __keyctl_dh_compute+0x623/0xe90 keyctl_dh_compute+0xb3/0xf1 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe Freed by task 367: save_stack_trace+0x16/0x20 kasan_slab_free+0xab/0x180 kfree+0xb5/0x210 mpi_free+0xcb/0x170 dh_set_secret+0x2d7/0x460 __keyctl_dh_compute+0x623/0xe90 keyctl_dh_compute+0xb3/0xf1 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe Fixes: 802c7f1c84e4 ("crypto: dh - Add DH software implementation") Cc: <stable@vger.kernel.org> # v4.8+ Signed-off-by: Eric Biggers <ebiggers@google.com> Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2017-11-05 18:30:44 -08:00
crypto: dh - Fix double free of ctx->p When setting the secret with the software Diffie-Hellman implementation, if allocating 'g' failed (e.g. if it was longer than MAX_EXTERN_MPI_BITS), then 'p' was freed twice: once immediately, and once later when the crypto_kpp tfm was destroyed. Fix it by using dh_free_ctx() (renamed to dh_clear_ctx()) in the error paths, as that correctly sets the pointers to NULL. KASAN report: MPI: mpi too large (32760 bits) ================================================================== BUG: KASAN: use-after-free in mpi_free+0x131/0x170 Read of size 4 at addr ffff88006c7cdf90 by task reproduce_doubl/367 CPU: 1 PID: 367 Comm: reproduce_doubl Not tainted 4.14.0-rc7-00040-g05298abde6fe #7 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Call Trace: dump_stack+0xb3/0x10b ? mpi_free+0x131/0x170 print_address_description+0x79/0x2a0 ? mpi_free+0x131/0x170 kasan_report+0x236/0x340 ? akcipher_register_instance+0x90/0x90 __asan_report_load4_noabort+0x14/0x20 mpi_free+0x131/0x170 ? akcipher_register_instance+0x90/0x90 dh_exit_tfm+0x3d/0x140 crypto_kpp_exit_tfm+0x52/0x70 crypto_destroy_tfm+0xb3/0x250 __keyctl_dh_compute+0x640/0xe90 ? kasan_slab_free+0x12f/0x180 ? dh_data_from_key+0x240/0x240 ? key_create_or_update+0x1ee/0xb20 ? key_instantiate_and_link+0x440/0x440 ? lock_contended+0xee0/0xee0 ? kfree+0xcf/0x210 ? SyS_add_key+0x268/0x340 keyctl_dh_compute+0xb3/0xf1 ? __keyctl_dh_compute+0xe90/0xe90 ? SyS_add_key+0x26d/0x340 ? entry_SYSCALL_64_fastpath+0x5/0xbe ? trace_hardirqs_on_caller+0x3f4/0x560 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe RIP: 0033:0x43ccf9 RSP: 002b:00007ffeeec96158 EFLAGS: 00000246 ORIG_RAX: 00000000000000fa RAX: ffffffffffffffda RBX: 000000000248b9b9 RCX: 000000000043ccf9 RDX: 00007ffeeec96170 RSI: 00007ffeeec96160 RDI: 0000000000000017 RBP: 0000000000000046 R08: 0000000000000000 R09: 0248b9b9143dc936 R10: 0000000000001000 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000409670 R14: 0000000000409700 R15: 0000000000000000 Allocated by task 367: save_stack_trace+0x16/0x20 kasan_kmalloc+0xeb/0x180 kmem_cache_alloc_trace+0x114/0x300 mpi_alloc+0x4b/0x230 mpi_read_raw_data+0xbe/0x360 dh_set_secret+0x1dc/0x460 __keyctl_dh_compute+0x623/0xe90 keyctl_dh_compute+0xb3/0xf1 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe Freed by task 367: save_stack_trace+0x16/0x20 kasan_slab_free+0xab/0x180 kfree+0xb5/0x210 mpi_free+0xcb/0x170 dh_set_secret+0x2d7/0x460 __keyctl_dh_compute+0x623/0xe90 keyctl_dh_compute+0xb3/0xf1 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe Fixes: 802c7f1c84e4 ("crypto: dh - Add DH software implementation") Cc: <stable@vger.kernel.org> # v4.8+ Signed-off-by: Eric Biggers <ebiggers@google.com> Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2017-11-05 18:30:44 -08:00
crypto: dh - Fix double free of ctx->p When setting the secret with the software Diffie-Hellman implementation, if allocating 'g' failed (e.g. if it was longer than MAX_EXTERN_MPI_BITS), then 'p' was freed twice: once immediately, and once later when the crypto_kpp tfm was destroyed. Fix it by using dh_free_ctx() (renamed to dh_clear_ctx()) in the error paths, as that correctly sets the pointers to NULL. KASAN report: MPI: mpi too large (32760 bits) ================================================================== BUG: KASAN: use-after-free in mpi_free+0x131/0x170 Read of size 4 at addr ffff88006c7cdf90 by task reproduce_doubl/367 CPU: 1 PID: 367 Comm: reproduce_doubl Not tainted 4.14.0-rc7-00040-g05298abde6fe #7 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Call Trace: dump_stack+0xb3/0x10b ? mpi_free+0x131/0x170 print_address_description+0x79/0x2a0 ? mpi_free+0x131/0x170 kasan_report+0x236/0x340 ? akcipher_register_instance+0x90/0x90 __asan_report_load4_noabort+0x14/0x20 mpi_free+0x131/0x170 ? akcipher_register_instance+0x90/0x90 dh_exit_tfm+0x3d/0x140 crypto_kpp_exit_tfm+0x52/0x70 crypto_destroy_tfm+0xb3/0x250 __keyctl_dh_compute+0x640/0xe90 ? kasan_slab_free+0x12f/0x180 ? dh_data_from_key+0x240/0x240 ? key_create_or_update+0x1ee/0xb20 ? key_instantiate_and_link+0x440/0x440 ? lock_contended+0xee0/0xee0 ? kfree+0xcf/0x210 ? SyS_add_key+0x268/0x340 keyctl_dh_compute+0xb3/0xf1 ? __keyctl_dh_compute+0xe90/0xe90 ? SyS_add_key+0x26d/0x340 ? entry_SYSCALL_64_fastpath+0x5/0xbe ? trace_hardirqs_on_caller+0x3f4/0x560 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe RIP: 0033:0x43ccf9 RSP: 002b:00007ffeeec96158 EFLAGS: 00000246 ORIG_RAX: 00000000000000fa RAX: ffffffffffffffda RBX: 000000000248b9b9 RCX: 000000000043ccf9 RDX: 00007ffeeec96170 RSI: 00007ffeeec96160 RDI: 0000000000000017 RBP: 0000000000000046 R08: 0000000000000000 R09: 0248b9b9143dc936 R10: 0000000000001000 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000409670 R14: 0000000000409700 R15: 0000000000000000 Allocated by task 367: save_stack_trace+0x16/0x20 kasan_kmalloc+0xeb/0x180 kmem_cache_alloc_trace+0x114/0x300 mpi_alloc+0x4b/0x230 mpi_read_raw_data+0xbe/0x360 dh_set_secret+0x1dc/0x460 __keyctl_dh_compute+0x623/0xe90 keyctl_dh_compute+0xb3/0xf1 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe Freed by task 367: save_stack_trace+0x16/0x20 kasan_slab_free+0xab/0x180 kfree+0xb5/0x210 mpi_free+0xcb/0x170 dh_set_secret+0x2d7/0x460 __keyctl_dh_compute+0x623/0xe90 keyctl_dh_compute+0xb3/0xf1 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe Fixes: 802c7f1c84e4 ("crypto: dh - Add DH software implementation") Cc: <stable@vger.kernel.org> # v4.8+ Signed-off-by: Eric Biggers <ebiggers@google.com> Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2017-11-05 18:30:44 -08:00
crypto: dh - introduce common code for built-in safe-prime group support Recent work on NVME in-band authentication support ([1]) needs to invoke the "dh" KPP with the FFDHE safe-prime group parameters as specified in RFC 7919 and generate ephemeral keys suitable for the respective group. By coincidence, the requirements from NIST SP800-56Arev3, sec. 5.5.2 ("Assurance of Domain-Parameter Validity") basically boil down to disallowing any group parameters not among the approved safe-prime groups specified in either RFC 7919 or RFC 3526 in FIPS mode. Furthermore, SP800-56Arev3 specifies the respective security strength for each of the approved safe-prime groups, which has a direct impact on the minimum key lengths. In this light, it's desirable to introduce built-in support for the RFC 7919 safe-prime groups to the kernel's DH implementation, provide a SP800-56Arev3 conforming key generation primitive for those and render non-approved group parameters unusable in FIPS mode on the way. As suggested ([2]) in the course of discussion to previous iterations of this patchset, the built-in support for ffdhe groups would be best made available in the form of templates wrapping the existing "dh" implementation, one for each group specified by RFC 7919: ffdhe2048(dh), ffdhe3072(dh), ffdhe4096(dh), ffdhe6144(dh) and ffdhe8192(dh). As these templates differ only in the safe-prime constants they'd configure the inner "dh" transforms with, they can share almost all of their "dh"-wrapping template implementation code. Introduce this common code to dh_generic. The actual dump of the RFC 7919 safe-prime constants will be deferred to the next patch in order to facilitate review. The ephemeral key generation primitive mentioned above likewise deserves a patch on its own, as does the mechanism by which unapproved groups are rendered unusable in FIPS mode. Define a struct dh_safe_prime container for specifying the individual templates' associated safe-prime group constants. All ffdheXYZ(dh) template instances will store a pointer to such a dh_safe_prime in their context areas each. Implement the common __dh_safe_prime_create() template instantiation helper. The intention is that the individual ffdheXYZ(dh) crypto_templates' ->create() implementations will simply forward any calls to __dh_safe_prime_create(), passing a suitable dh_safe_prime in addition to the received ->create() arguments. __dh_safe_prime_create() would then create and register a kpp_instance as appropriate, storing the given dh_safe_prime pointer alongside a crypto_kpp_spawn for the inner "dh" kpp_alg in the context area. As the ffdheXYZ(dh) kpp_instances are supposed to act as proxies to the inner "dh" kpp_alg, make each of their associated crypto_kpp transforms to in turn own an inner "dh" transform, a pointer to which gets stored in the context area. Setup and teardown are getting handled from the outer ->init_tfm() and ->exit_tfm() respectively. In order to achieve the overall goal and let the ffdheXYZ(dh) kpp_instances configure the inner "dh" transforms with the respective group parameters, make their common ->set_secret(), the new dh_safe_prime_set_secret(), fill in the P and G values before forwarding the call to the inner "dh"'s ->set_secret(). Note that the outer ->set_secret() can obtain the P value associated with the given ffdheXYZ(dh) kpp_instance by means of the dh_safe_prime referenced from the latter's context. The value of G OTOH always equals constant 2 for the safe-prime groups. Finally, make the remaining two kpp_alg primitives both operating on kpp_requests, i.e. ->generate_public_key() and ->compute_shared_secret(), to merely forward any request to the inner "dh" implementation. However, a kpp_request instance received from the outside cannot get simply passed on as-is, because its associated transform (crypto_kpp_reqtfm()) will have been set to the outer ffdheXYZ(dh) one. In order to handle this, reserve some space in the outer ffdheXYZ(dh) kpp_requests' context areas for in turn storing an inner kpp_request suitable for "dh" each. Make the outer ->generate_public_key() and ->compute_shared_secret() respectively to setup this inner kpp_request by means of the new dh_safe_prime_prepare_dh_req() helper before handing it over to the "dh" implementation for further processing. dh_safe_prime_prepare_dh_req() basically copies the outer kpp_request received from the outside over to the inner one, but installs the inner transform and its own ->complete() proxy callback therein. This completion callback, the new dh_safe_prime_complete_req(), doesn't do anything beyond completing the outer request. Note that there exist some examples in crypto/, which would simply install the completion handler from the outer request at the inner one in similar setups, e.g. seqiv. However, this would mean that the user-provided completion handler won't get called with the address of the outer kpp_request initially submitted and the handler might not be prepared for this. Users could certainly work around this by setting the callback ->data properly, but IMO it's cleaner this way. Furthermore, it might make sense to extend dh_safe_prime_complete_req() in the future and move e.g. those post-computation FIPS checks from the generic "dh" implementation to the ffdheXYZ(dh) templates. [1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de [2] https://lore.kernel.org/r/20211217055227.GA20698@gondor.apana.org.au Signed-off-by: Nicolai Stange <nstange@suse.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 13:10:52 +01:00
crypto: dh - introduce common code for built-in safe-prime group support Recent work on NVME in-band authentication support ([1]) needs to invoke the "dh" KPP with the FFDHE safe-prime group parameters as specified in RFC 7919 and generate ephemeral keys suitable for the respective group. By coincidence, the requirements from NIST SP800-56Arev3, sec. 5.5.2 ("Assurance of Domain-Parameter Validity") basically boil down to disallowing any group parameters not among the approved safe-prime groups specified in either RFC 7919 or RFC 3526 in FIPS mode. Furthermore, SP800-56Arev3 specifies the respective security strength for each of the approved safe-prime groups, which has a direct impact on the minimum key lengths. In this light, it's desirable to introduce built-in support for the RFC 7919 safe-prime groups to the kernel's DH implementation, provide a SP800-56Arev3 conforming key generation primitive for those and render non-approved group parameters unusable in FIPS mode on the way. As suggested ([2]) in the course of discussion to previous iterations of this patchset, the built-in support for ffdhe groups would be best made available in the form of templates wrapping the existing "dh" implementation, one for each group specified by RFC 7919: ffdhe2048(dh), ffdhe3072(dh), ffdhe4096(dh), ffdhe6144(dh) and ffdhe8192(dh). As these templates differ only in the safe-prime constants they'd configure the inner "dh" transforms with, they can share almost all of their "dh"-wrapping template implementation code. Introduce this common code to dh_generic. The actual dump of the RFC 7919 safe-prime constants will be deferred to the next patch in order to facilitate review. The ephemeral key generation primitive mentioned above likewise deserves a patch on its own, as does the mechanism by which unapproved groups are rendered unusable in FIPS mode. Define a struct dh_safe_prime container for specifying the individual templates' associated safe-prime group constants. All ffdheXYZ(dh) template instances will store a pointer to such a dh_safe_prime in their context areas each. Implement the common __dh_safe_prime_create() template instantiation helper. The intention is that the individual ffdheXYZ(dh) crypto_templates' ->create() implementations will simply forward any calls to __dh_safe_prime_create(), passing a suitable dh_safe_prime in addition to the received ->create() arguments. __dh_safe_prime_create() would then create and register a kpp_instance as appropriate, storing the given dh_safe_prime pointer alongside a crypto_kpp_spawn for the inner "dh" kpp_alg in the context area. As the ffdheXYZ(dh) kpp_instances are supposed to act as proxies to the inner "dh" kpp_alg, make each of their associated crypto_kpp transforms to in turn own an inner "dh" transform, a pointer to which gets stored in the context area. Setup and teardown are getting handled from the outer ->init_tfm() and ->exit_tfm() respectively. In order to achieve the overall goal and let the ffdheXYZ(dh) kpp_instances configure the inner "dh" transforms with the respective group parameters, make their common ->set_secret(), the new dh_safe_prime_set_secret(), fill in the P and G values before forwarding the call to the inner "dh"'s ->set_secret(). Note that the outer ->set_secret() can obtain the P value associated with the given ffdheXYZ(dh) kpp_instance by means of the dh_safe_prime referenced from the latter's context. The value of G OTOH always equals constant 2 for the safe-prime groups. Finally, make the remaining two kpp_alg primitives both operating on kpp_requests, i.e. ->generate_public_key() and ->compute_shared_secret(), to merely forward any request to the inner "dh" implementation. However, a kpp_request instance received from the outside cannot get simply passed on as-is, because its associated transform (crypto_kpp_reqtfm()) will have been set to the outer ffdheXYZ(dh) one. In order to handle this, reserve some space in the outer ffdheXYZ(dh) kpp_requests' context areas for in turn storing an inner kpp_request suitable for "dh" each. Make the outer ->generate_public_key() and ->compute_shared_secret() respectively to setup this inner kpp_request by means of the new dh_safe_prime_prepare_dh_req() helper before handing it over to the "dh" implementation for further processing. dh_safe_prime_prepare_dh_req() basically copies the outer kpp_request received from the outside over to the inner one, but installs the inner transform and its own ->complete() proxy callback therein. This completion callback, the new dh_safe_prime_complete_req(), doesn't do anything beyond completing the outer request. Note that there exist some examples in crypto/, which would simply install the completion handler from the outer request at the inner one in similar setups, e.g. seqiv. However, this would mean that the user-provided completion handler won't get called with the address of the outer kpp_request initially submitted and the handler might not be prepared for this. Users could certainly work around this by setting the callback ->data properly, but IMO it's cleaner this way. Furthermore, it might make sense to extend dh_safe_prime_complete_req() in the future and move e.g. those post-computation FIPS checks from the generic "dh" implementation to the ffdheXYZ(dh) templates. [1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de [2] https://lore.kernel.org/r/20211217055227.GA20698@gondor.apana.org.au Signed-off-by: Nicolai Stange <nstange@suse.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 13:10:52 +01:00
crypto: dh - implement private key generation primitive for ffdheXYZ(dh) The support for NVME in-band authentication currently in the works ([1]) needs to generate ephemeral DH keys for use with the RFC 7919 safe-prime FFDHE groups. In analogy to ECDH and its ecc_gen_privkey(), implement a dh_safe_prime_gen_privkey() and invoke it from the ffdheXYZ(dh) templates' common ->set_secret(), i.e. dh_safe_prime_set_secret(), in case the input ->key_size is zero. As the RFC 7919 FFDHE groups are classified as approved safe-prime groups by SP800-56Arev3, it's worthwhile to make the new dh_safe_prime_gen_privkey() to follow the approach specified in SP800-56Arev3, sec. 5.6.1.1.3 ("Key-Pair Generation Using Extra Random Bits") in order to achieve conformance. SP800-56Arev3 specifies a lower as well as an upper bound on the generated key's length: - it must be >= two times the maximum supported security strength of the group in question and - it must be <= the length of the domain parameter Q. For any safe-prime group Q = (P - 1)/2 by definition and the individual maximum supported security strengths as specified by SP800-56Arev3 have been made available as part of the FFDHE dh_safe_prime definitions introduced with a previous patch. Make dh_safe_prime_gen_privkey() pick twice the maximum supported strength rounded up to the next power of two for the output key size. This choice respects both, the lower and upper bounds given by SP800-90Arev3 for any of the approved safe-prime groups and is also in line with the NVME base spec 2.0, which requires the key size to be >= 256bits. [1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de Signed-off-by: Nicolai Stange <nstange@suse.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 13:10:55 +01:00
crypto: dh - implement private key generation primitive for ffdheXYZ(dh) The support for NVME in-band authentication currently in the works ([1]) needs to generate ephemeral DH keys for use with the RFC 7919 safe-prime FFDHE groups. In analogy to ECDH and its ecc_gen_privkey(), implement a dh_safe_prime_gen_privkey() and invoke it from the ffdheXYZ(dh) templates' common ->set_secret(), i.e. dh_safe_prime_set_secret(), in case the input ->key_size is zero. As the RFC 7919 FFDHE groups are classified as approved safe-prime groups by SP800-56Arev3, it's worthwhile to make the new dh_safe_prime_gen_privkey() to follow the approach specified in SP800-56Arev3, sec. 5.6.1.1.3 ("Key-Pair Generation Using Extra Random Bits") in order to achieve conformance. SP800-56Arev3 specifies a lower as well as an upper bound on the generated key's length: - it must be >= two times the maximum supported security strength of the group in question and - it must be <= the length of the domain parameter Q. For any safe-prime group Q = (P - 1)/2 by definition and the individual maximum supported security strengths as specified by SP800-56Arev3 have been made available as part of the FFDHE dh_safe_prime definitions introduced with a previous patch. Make dh_safe_prime_gen_privkey() pick twice the maximum supported strength rounded up to the next power of two for the output key size. This choice respects both, the lower and upper bounds given by SP800-90Arev3 for any of the approved safe-prime groups and is also in line with the NVME base spec 2.0, which requires the key size to be >= 256bits. [1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de Signed-off-by: Nicolai Stange <nstange@suse.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 13:10:55 +01:00
crypto: dh - introduce common code for built-in safe-prime group support Recent work on NVME in-band authentication support ([1]) needs to invoke the "dh" KPP with the FFDHE safe-prime group parameters as specified in RFC 7919 and generate ephemeral keys suitable for the respective group. By coincidence, the requirements from NIST SP800-56Arev3, sec. 5.5.2 ("Assurance of Domain-Parameter Validity") basically boil down to disallowing any group parameters not among the approved safe-prime groups specified in either RFC 7919 or RFC 3526 in FIPS mode. Furthermore, SP800-56Arev3 specifies the respective security strength for each of the approved safe-prime groups, which has a direct impact on the minimum key lengths. In this light, it's desirable to introduce built-in support for the RFC 7919 safe-prime groups to the kernel's DH implementation, provide a SP800-56Arev3 conforming key generation primitive for those and render non-approved group parameters unusable in FIPS mode on the way. As suggested ([2]) in the course of discussion to previous iterations of this patchset, the built-in support for ffdhe groups would be best made available in the form of templates wrapping the existing "dh" implementation, one for each group specified by RFC 7919: ffdhe2048(dh), ffdhe3072(dh), ffdhe4096(dh), ffdhe6144(dh) and ffdhe8192(dh). As these templates differ only in the safe-prime constants they'd configure the inner "dh" transforms with, they can share almost all of their "dh"-wrapping template implementation code. Introduce this common code to dh_generic. The actual dump of the RFC 7919 safe-prime constants will be deferred to the next patch in order to facilitate review. The ephemeral key generation primitive mentioned above likewise deserves a patch on its own, as does the mechanism by which unapproved groups are rendered unusable in FIPS mode. Define a struct dh_safe_prime container for specifying the individual templates' associated safe-prime group constants. All ffdheXYZ(dh) template instances will store a pointer to such a dh_safe_prime in their context areas each. Implement the common __dh_safe_prime_create() template instantiation helper. The intention is that the individual ffdheXYZ(dh) crypto_templates' ->create() implementations will simply forward any calls to __dh_safe_prime_create(), passing a suitable dh_safe_prime in addition to the received ->create() arguments. __dh_safe_prime_create() would then create and register a kpp_instance as appropriate, storing the given dh_safe_prime pointer alongside a crypto_kpp_spawn for the inner "dh" kpp_alg in the context area. As the ffdheXYZ(dh) kpp_instances are supposed to act as proxies to the inner "dh" kpp_alg, make each of their associated crypto_kpp transforms to in turn own an inner "dh" transform, a pointer to which gets stored in the context area. Setup and teardown are getting handled from the outer ->init_tfm() and ->exit_tfm() respectively. In order to achieve the overall goal and let the ffdheXYZ(dh) kpp_instances configure the inner "dh" transforms with the respective group parameters, make their common ->set_secret(), the new dh_safe_prime_set_secret(), fill in the P and G values before forwarding the call to the inner "dh"'s ->set_secret(). Note that the outer ->set_secret() can obtain the P value associated with the given ffdheXYZ(dh) kpp_instance by means of the dh_safe_prime referenced from the latter's context. The value of G OTOH always equals constant 2 for the safe-prime groups. Finally, make the remaining two kpp_alg primitives both operating on kpp_requests, i.e. ->generate_public_key() and ->compute_shared_secret(), to merely forward any request to the inner "dh" implementation. However, a kpp_request instance received from the outside cannot get simply passed on as-is, because its associated transform (crypto_kpp_reqtfm()) will have been set to the outer ffdheXYZ(dh) one. In order to handle this, reserve some space in the outer ffdheXYZ(dh) kpp_requests' context areas for in turn storing an inner kpp_request suitable for "dh" each. Make the outer ->generate_public_key() and ->compute_shared_secret() respectively to setup this inner kpp_request by means of the new dh_safe_prime_prepare_dh_req() helper before handing it over to the "dh" implementation for further processing. dh_safe_prime_prepare_dh_req() basically copies the outer kpp_request received from the outside over to the inner one, but installs the inner transform and its own ->complete() proxy callback therein. This completion callback, the new dh_safe_prime_complete_req(), doesn't do anything beyond completing the outer request. Note that there exist some examples in crypto/, which would simply install the completion handler from the outer request at the inner one in similar setups, e.g. seqiv. However, this would mean that the user-provided completion handler won't get called with the address of the outer kpp_request initially submitted and the handler might not be prepared for this. Users could certainly work around this by setting the callback ->data properly, but IMO it's cleaner this way. Furthermore, it might make sense to extend dh_safe_prime_complete_req() in the future and move e.g. those post-computation FIPS checks from the generic "dh" implementation to the ffdheXYZ(dh) templates. [1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de [2] https://lore.kernel.org/r/20211217055227.GA20698@gondor.apana.org.au Signed-off-by: Nicolai Stange <nstange@suse.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 13:10:52 +01:00
crypto: dh - implement private key generation primitive for ffdheXYZ(dh) The support for NVME in-band authentication currently in the works ([1]) needs to generate ephemeral DH keys for use with the RFC 7919 safe-prime FFDHE groups. In analogy to ECDH and its ecc_gen_privkey(), implement a dh_safe_prime_gen_privkey() and invoke it from the ffdheXYZ(dh) templates' common ->set_secret(), i.e. dh_safe_prime_set_secret(), in case the input ->key_size is zero. As the RFC 7919 FFDHE groups are classified as approved safe-prime groups by SP800-56Arev3, it's worthwhile to make the new dh_safe_prime_gen_privkey() to follow the approach specified in SP800-56Arev3, sec. 5.6.1.1.3 ("Key-Pair Generation Using Extra Random Bits") in order to achieve conformance. SP800-56Arev3 specifies a lower as well as an upper bound on the generated key's length: - it must be >= two times the maximum supported security strength of the group in question and - it must be <= the length of the domain parameter Q. For any safe-prime group Q = (P - 1)/2 by definition and the individual maximum supported security strengths as specified by SP800-56Arev3 have been made available as part of the FFDHE dh_safe_prime definitions introduced with a previous patch. Make dh_safe_prime_gen_privkey() pick twice the maximum supported strength rounded up to the next power of two for the output key size. This choice respects both, the lower and upper bounds given by SP800-90Arev3 for any of the approved safe-prime groups and is also in line with the NVME base spec 2.0, which requires the key size to be >= 256bits. [1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de Signed-off-by: Nicolai Stange <nstange@suse.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 13:10:55 +01:00
crypto: dh - introduce common code for built-in safe-prime group support Recent work on NVME in-band authentication support ([1]) needs to invoke the "dh" KPP with the FFDHE safe-prime group parameters as specified in RFC 7919 and generate ephemeral keys suitable for the respective group. By coincidence, the requirements from NIST SP800-56Arev3, sec. 5.5.2 ("Assurance of Domain-Parameter Validity") basically boil down to disallowing any group parameters not among the approved safe-prime groups specified in either RFC 7919 or RFC 3526 in FIPS mode. Furthermore, SP800-56Arev3 specifies the respective security strength for each of the approved safe-prime groups, which has a direct impact on the minimum key lengths. In this light, it's desirable to introduce built-in support for the RFC 7919 safe-prime groups to the kernel's DH implementation, provide a SP800-56Arev3 conforming key generation primitive for those and render non-approved group parameters unusable in FIPS mode on the way. As suggested ([2]) in the course of discussion to previous iterations of this patchset, the built-in support for ffdhe groups would be best made available in the form of templates wrapping the existing "dh" implementation, one for each group specified by RFC 7919: ffdhe2048(dh), ffdhe3072(dh), ffdhe4096(dh), ffdhe6144(dh) and ffdhe8192(dh). As these templates differ only in the safe-prime constants they'd configure the inner "dh" transforms with, they can share almost all of their "dh"-wrapping template implementation code. Introduce this common code to dh_generic. The actual dump of the RFC 7919 safe-prime constants will be deferred to the next patch in order to facilitate review. The ephemeral key generation primitive mentioned above likewise deserves a patch on its own, as does the mechanism by which unapproved groups are rendered unusable in FIPS mode. Define a struct dh_safe_prime container for specifying the individual templates' associated safe-prime group constants. All ffdheXYZ(dh) template instances will store a pointer to such a dh_safe_prime in their context areas each. Implement the common __dh_safe_prime_create() template instantiation helper. The intention is that the individual ffdheXYZ(dh) crypto_templates' ->create() implementations will simply forward any calls to __dh_safe_prime_create(), passing a suitable dh_safe_prime in addition to the received ->create() arguments. __dh_safe_prime_create() would then create and register a kpp_instance as appropriate, storing the given dh_safe_prime pointer alongside a crypto_kpp_spawn for the inner "dh" kpp_alg in the context area. As the ffdheXYZ(dh) kpp_instances are supposed to act as proxies to the inner "dh" kpp_alg, make each of their associated crypto_kpp transforms to in turn own an inner "dh" transform, a pointer to which gets stored in the context area. Setup and teardown are getting handled from the outer ->init_tfm() and ->exit_tfm() respectively. In order to achieve the overall goal and let the ffdheXYZ(dh) kpp_instances configure the inner "dh" transforms with the respective group parameters, make their common ->set_secret(), the new dh_safe_prime_set_secret(), fill in the P and G values before forwarding the call to the inner "dh"'s ->set_secret(). Note that the outer ->set_secret() can obtain the P value associated with the given ffdheXYZ(dh) kpp_instance by means of the dh_safe_prime referenced from the latter's context. The value of G OTOH always equals constant 2 for the safe-prime groups. Finally, make the remaining two kpp_alg primitives both operating on kpp_requests, i.e. ->generate_public_key() and ->compute_shared_secret(), to merely forward any request to the inner "dh" implementation. However, a kpp_request instance received from the outside cannot get simply passed on as-is, because its associated transform (crypto_kpp_reqtfm()) will have been set to the outer ffdheXYZ(dh) one. In order to handle this, reserve some space in the outer ffdheXYZ(dh) kpp_requests' context areas for in turn storing an inner kpp_request suitable for "dh" each. Make the outer ->generate_public_key() and ->compute_shared_secret() respectively to setup this inner kpp_request by means of the new dh_safe_prime_prepare_dh_req() helper before handing it over to the "dh" implementation for further processing. dh_safe_prime_prepare_dh_req() basically copies the outer kpp_request received from the outside over to the inner one, but installs the inner transform and its own ->complete() proxy callback therein. This completion callback, the new dh_safe_prime_complete_req(), doesn't do anything beyond completing the outer request. Note that there exist some examples in crypto/, which would simply install the completion handler from the outer request at the inner one in similar setups, e.g. seqiv. However, this would mean that the user-provided completion handler won't get called with the address of the outer kpp_request initially submitted and the handler might not be prepared for this. Users could certainly work around this by setting the callback ->data properly, but IMO it's cleaner this way. Furthermore, it might make sense to extend dh_safe_prime_complete_req() in the future and move e.g. those post-computation FIPS checks from the generic "dh" implementation to the ffdheXYZ(dh) templates. [1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de [2] https://lore.kernel.org/r/20211217055227.GA20698@gondor.apana.org.au Signed-off-by: Nicolai Stange <nstange@suse.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 13:10:52 +01:00
crypto: dh - introduce common code for built-in safe-prime group support Recent work on NVME in-band authentication support ([1]) needs to invoke the "dh" KPP with the FFDHE safe-prime group parameters as specified in RFC 7919 and generate ephemeral keys suitable for the respective group. By coincidence, the requirements from NIST SP800-56Arev3, sec. 5.5.2 ("Assurance of Domain-Parameter Validity") basically boil down to disallowing any group parameters not among the approved safe-prime groups specified in either RFC 7919 or RFC 3526 in FIPS mode. Furthermore, SP800-56Arev3 specifies the respective security strength for each of the approved safe-prime groups, which has a direct impact on the minimum key lengths. In this light, it's desirable to introduce built-in support for the RFC 7919 safe-prime groups to the kernel's DH implementation, provide a SP800-56Arev3 conforming key generation primitive for those and render non-approved group parameters unusable in FIPS mode on the way. As suggested ([2]) in the course of discussion to previous iterations of this patchset, the built-in support for ffdhe groups would be best made available in the form of templates wrapping the existing "dh" implementation, one for each group specified by RFC 7919: ffdhe2048(dh), ffdhe3072(dh), ffdhe4096(dh), ffdhe6144(dh) and ffdhe8192(dh). As these templates differ only in the safe-prime constants they'd configure the inner "dh" transforms with, they can share almost all of their "dh"-wrapping template implementation code. Introduce this common code to dh_generic. The actual dump of the RFC 7919 safe-prime constants will be deferred to the next patch in order to facilitate review. The ephemeral key generation primitive mentioned above likewise deserves a patch on its own, as does the mechanism by which unapproved groups are rendered unusable in FIPS mode. Define a struct dh_safe_prime container for specifying the individual templates' associated safe-prime group constants. All ffdheXYZ(dh) template instances will store a pointer to such a dh_safe_prime in their context areas each. Implement the common __dh_safe_prime_create() template instantiation helper. The intention is that the individual ffdheXYZ(dh) crypto_templates' ->create() implementations will simply forward any calls to __dh_safe_prime_create(), passing a suitable dh_safe_prime in addition to the received ->create() arguments. __dh_safe_prime_create() would then create and register a kpp_instance as appropriate, storing the given dh_safe_prime pointer alongside a crypto_kpp_spawn for the inner "dh" kpp_alg in the context area. As the ffdheXYZ(dh) kpp_instances are supposed to act as proxies to the inner "dh" kpp_alg, make each of their associated crypto_kpp transforms to in turn own an inner "dh" transform, a pointer to which gets stored in the context area. Setup and teardown are getting handled from the outer ->init_tfm() and ->exit_tfm() respectively. In order to achieve the overall goal and let the ffdheXYZ(dh) kpp_instances configure the inner "dh" transforms with the respective group parameters, make their common ->set_secret(), the new dh_safe_prime_set_secret(), fill in the P and G values before forwarding the call to the inner "dh"'s ->set_secret(). Note that the outer ->set_secret() can obtain the P value associated with the given ffdheXYZ(dh) kpp_instance by means of the dh_safe_prime referenced from the latter's context. The value of G OTOH always equals constant 2 for the safe-prime groups. Finally, make the remaining two kpp_alg primitives both operating on kpp_requests, i.e. ->generate_public_key() and ->compute_shared_secret(), to merely forward any request to the inner "dh" implementation. However, a kpp_request instance received from the outside cannot get simply passed on as-is, because its associated transform (crypto_kpp_reqtfm()) will have been set to the outer ffdheXYZ(dh) one. In order to handle this, reserve some space in the outer ffdheXYZ(dh) kpp_requests' context areas for in turn storing an inner kpp_request suitable for "dh" each. Make the outer ->generate_public_key() and ->compute_shared_secret() respectively to setup this inner kpp_request by means of the new dh_safe_prime_prepare_dh_req() helper before handing it over to the "dh" implementation for further processing. dh_safe_prime_prepare_dh_req() basically copies the outer kpp_request received from the outside over to the inner one, but installs the inner transform and its own ->complete() proxy callback therein. This completion callback, the new dh_safe_prime_complete_req(), doesn't do anything beyond completing the outer request. Note that there exist some examples in crypto/, which would simply install the completion handler from the outer request at the inner one in similar setups, e.g. seqiv. However, this would mean that the user-provided completion handler won't get called with the address of the outer kpp_request initially submitted and the handler might not be prepared for this. Users could certainly work around this by setting the callback ->data properly, but IMO it's cleaner this way. Furthermore, it might make sense to extend dh_safe_prime_complete_req() in the future and move e.g. those post-computation FIPS checks from the generic "dh" implementation to the ffdheXYZ(dh) templates. [1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de [2] https://lore.kernel.org/r/20211217055227.GA20698@gondor.apana.org.au Signed-off-by: Nicolai Stange <nstange@suse.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 13:10:52 +01:00
crypto: dh - implement private key generation primitive for ffdheXYZ(dh) The support for NVME in-band authentication currently in the works ([1]) needs to generate ephemeral DH keys for use with the RFC 7919 safe-prime FFDHE groups. In analogy to ECDH and its ecc_gen_privkey(), implement a dh_safe_prime_gen_privkey() and invoke it from the ffdheXYZ(dh) templates' common ->set_secret(), i.e. dh_safe_prime_set_secret(), in case the input ->key_size is zero. As the RFC 7919 FFDHE groups are classified as approved safe-prime groups by SP800-56Arev3, it's worthwhile to make the new dh_safe_prime_gen_privkey() to follow the approach specified in SP800-56Arev3, sec. 5.6.1.1.3 ("Key-Pair Generation Using Extra Random Bits") in order to achieve conformance. SP800-56Arev3 specifies a lower as well as an upper bound on the generated key's length: - it must be >= two times the maximum supported security strength of the group in question and - it must be <= the length of the domain parameter Q. For any safe-prime group Q = (P - 1)/2 by definition and the individual maximum supported security strengths as specified by SP800-56Arev3 have been made available as part of the FFDHE dh_safe_prime definitions introduced with a previous patch. Make dh_safe_prime_gen_privkey() pick twice the maximum supported strength rounded up to the next power of two for the output key size. This choice respects both, the lower and upper bounds given by SP800-90Arev3 for any of the approved safe-prime groups and is also in line with the NVME base spec 2.0, which requires the key size to be >= 256bits. [1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de Signed-off-by: Nicolai Stange <nstange@suse.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 13:10:55 +01:00
crypto: dh - introduce common code for built-in safe-prime group support Recent work on NVME in-band authentication support ([1]) needs to invoke the "dh" KPP with the FFDHE safe-prime group parameters as specified in RFC 7919 and generate ephemeral keys suitable for the respective group. By coincidence, the requirements from NIST SP800-56Arev3, sec. 5.5.2 ("Assurance of Domain-Parameter Validity") basically boil down to disallowing any group parameters not among the approved safe-prime groups specified in either RFC 7919 or RFC 3526 in FIPS mode. Furthermore, SP800-56Arev3 specifies the respective security strength for each of the approved safe-prime groups, which has a direct impact on the minimum key lengths. In this light, it's desirable to introduce built-in support for the RFC 7919 safe-prime groups to the kernel's DH implementation, provide a SP800-56Arev3 conforming key generation primitive for those and render non-approved group parameters unusable in FIPS mode on the way. As suggested ([2]) in the course of discussion to previous iterations of this patchset, the built-in support for ffdhe groups would be best made available in the form of templates wrapping the existing "dh" implementation, one for each group specified by RFC 7919: ffdhe2048(dh), ffdhe3072(dh), ffdhe4096(dh), ffdhe6144(dh) and ffdhe8192(dh). As these templates differ only in the safe-prime constants they'd configure the inner "dh" transforms with, they can share almost all of their "dh"-wrapping template implementation code. Introduce this common code to dh_generic. The actual dump of the RFC 7919 safe-prime constants will be deferred to the next patch in order to facilitate review. The ephemeral key generation primitive mentioned above likewise deserves a patch on its own, as does the mechanism by which unapproved groups are rendered unusable in FIPS mode. Define a struct dh_safe_prime container for specifying the individual templates' associated safe-prime group constants. All ffdheXYZ(dh) template instances will store a pointer to such a dh_safe_prime in their context areas each. Implement the common __dh_safe_prime_create() template instantiation helper. The intention is that the individual ffdheXYZ(dh) crypto_templates' ->create() implementations will simply forward any calls to __dh_safe_prime_create(), passing a suitable dh_safe_prime in addition to the received ->create() arguments. __dh_safe_prime_create() would then create and register a kpp_instance as appropriate, storing the given dh_safe_prime pointer alongside a crypto_kpp_spawn for the inner "dh" kpp_alg in the context area. As the ffdheXYZ(dh) kpp_instances are supposed to act as proxies to the inner "dh" kpp_alg, make each of their associated crypto_kpp transforms to in turn own an inner "dh" transform, a pointer to which gets stored in the context area. Setup and teardown are getting handled from the outer ->init_tfm() and ->exit_tfm() respectively. In order to achieve the overall goal and let the ffdheXYZ(dh) kpp_instances configure the inner "dh" transforms with the respective group parameters, make their common ->set_secret(), the new dh_safe_prime_set_secret(), fill in the P and G values before forwarding the call to the inner "dh"'s ->set_secret(). Note that the outer ->set_secret() can obtain the P value associated with the given ffdheXYZ(dh) kpp_instance by means of the dh_safe_prime referenced from the latter's context. The value of G OTOH always equals constant 2 for the safe-prime groups. Finally, make the remaining two kpp_alg primitives both operating on kpp_requests, i.e. ->generate_public_key() and ->compute_shared_secret(), to merely forward any request to the inner "dh" implementation. However, a kpp_request instance received from the outside cannot get simply passed on as-is, because its associated transform (crypto_kpp_reqtfm()) will have been set to the outer ffdheXYZ(dh) one. In order to handle this, reserve some space in the outer ffdheXYZ(dh) kpp_requests' context areas for in turn storing an inner kpp_request suitable for "dh" each. Make the outer ->generate_public_key() and ->compute_shared_secret() respectively to setup this inner kpp_request by means of the new dh_safe_prime_prepare_dh_req() helper before handing it over to the "dh" implementation for further processing. dh_safe_prime_prepare_dh_req() basically copies the outer kpp_request received from the outside over to the inner one, but installs the inner transform and its own ->complete() proxy callback therein. This completion callback, the new dh_safe_prime_complete_req(), doesn't do anything beyond completing the outer request. Note that there exist some examples in crypto/, which would simply install the completion handler from the outer request at the inner one in similar setups, e.g. seqiv. However, this would mean that the user-provided completion handler won't get called with the address of the outer kpp_request initially submitted and the handler might not be prepared for this. Users could certainly work around this by setting the callback ->data properly, but IMO it's cleaner this way. Furthermore, it might make sense to extend dh_safe_prime_complete_req() in the future and move e.g. those post-computation FIPS checks from the generic "dh" implementation to the ffdheXYZ(dh) templates. [1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de [2] https://lore.kernel.org/r/20211217055227.GA20698@gondor.apana.org.au Signed-off-by: Nicolai Stange <nstange@suse.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 13:10:52 +01:00
crypto: dh - implement private key generation primitive for ffdheXYZ(dh) The support for NVME in-band authentication currently in the works ([1]) needs to generate ephemeral DH keys for use with the RFC 7919 safe-prime FFDHE groups. In analogy to ECDH and its ecc_gen_privkey(), implement a dh_safe_prime_gen_privkey() and invoke it from the ffdheXYZ(dh) templates' common ->set_secret(), i.e. dh_safe_prime_set_secret(), in case the input ->key_size is zero. As the RFC 7919 FFDHE groups are classified as approved safe-prime groups by SP800-56Arev3, it's worthwhile to make the new dh_safe_prime_gen_privkey() to follow the approach specified in SP800-56Arev3, sec. 5.6.1.1.3 ("Key-Pair Generation Using Extra Random Bits") in order to achieve conformance. SP800-56Arev3 specifies a lower as well as an upper bound on the generated key's length: - it must be >= two times the maximum supported security strength of the group in question and - it must be <= the length of the domain parameter Q. For any safe-prime group Q = (P - 1)/2 by definition and the individual maximum supported security strengths as specified by SP800-56Arev3 have been made available as part of the FFDHE dh_safe_prime definitions introduced with a previous patch. Make dh_safe_prime_gen_privkey() pick twice the maximum supported strength rounded up to the next power of two for the output key size. This choice respects both, the lower and upper bounds given by SP800-90Arev3 for any of the approved safe-prime groups and is also in line with the NVME base spec 2.0, which requires the key size to be >= 256bits. [1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de Signed-off-by: Nicolai Stange <nstange@suse.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 13:10:55 +01:00
crypto: dh - introduce common code for built-in safe-prime group support Recent work on NVME in-band authentication support ([1]) needs to invoke the "dh" KPP with the FFDHE safe-prime group parameters as specified in RFC 7919 and generate ephemeral keys suitable for the respective group. By coincidence, the requirements from NIST SP800-56Arev3, sec. 5.5.2 ("Assurance of Domain-Parameter Validity") basically boil down to disallowing any group parameters not among the approved safe-prime groups specified in either RFC 7919 or RFC 3526 in FIPS mode. Furthermore, SP800-56Arev3 specifies the respective security strength for each of the approved safe-prime groups, which has a direct impact on the minimum key lengths. In this light, it's desirable to introduce built-in support for the RFC 7919 safe-prime groups to the kernel's DH implementation, provide a SP800-56Arev3 conforming key generation primitive for those and render non-approved group parameters unusable in FIPS mode on the way. As suggested ([2]) in the course of discussion to previous iterations of this patchset, the built-in support for ffdhe groups would be best made available in the form of templates wrapping the existing "dh" implementation, one for each group specified by RFC 7919: ffdhe2048(dh), ffdhe3072(dh), ffdhe4096(dh), ffdhe6144(dh) and ffdhe8192(dh). As these templates differ only in the safe-prime constants they'd configure the inner "dh" transforms with, they can share almost all of their "dh"-wrapping template implementation code. Introduce this common code to dh_generic. The actual dump of the RFC 7919 safe-prime constants will be deferred to the next patch in order to facilitate review. The ephemeral key generation primitive mentioned above likewise deserves a patch on its own, as does the mechanism by which unapproved groups are rendered unusable in FIPS mode. Define a struct dh_safe_prime container for specifying the individual templates' associated safe-prime group constants. All ffdheXYZ(dh) template instances will store a pointer to such a dh_safe_prime in their context areas each. Implement the common __dh_safe_prime_create() template instantiation helper. The intention is that the individual ffdheXYZ(dh) crypto_templates' ->create() implementations will simply forward any calls to __dh_safe_prime_create(), passing a suitable dh_safe_prime in addition to the received ->create() arguments. __dh_safe_prime_create() would then create and register a kpp_instance as appropriate, storing the given dh_safe_prime pointer alongside a crypto_kpp_spawn for the inner "dh" kpp_alg in the context area. As the ffdheXYZ(dh) kpp_instances are supposed to act as proxies to the inner "dh" kpp_alg, make each of their associated crypto_kpp transforms to in turn own an inner "dh" transform, a pointer to which gets stored in the context area. Setup and teardown are getting handled from the outer ->init_tfm() and ->exit_tfm() respectively. In order to achieve the overall goal and let the ffdheXYZ(dh) kpp_instances configure the inner "dh" transforms with the respective group parameters, make their common ->set_secret(), the new dh_safe_prime_set_secret(), fill in the P and G values before forwarding the call to the inner "dh"'s ->set_secret(). Note that the outer ->set_secret() can obtain the P value associated with the given ffdheXYZ(dh) kpp_instance by means of the dh_safe_prime referenced from the latter's context. The value of G OTOH always equals constant 2 for the safe-prime groups. Finally, make the remaining two kpp_alg primitives both operating on kpp_requests, i.e. ->generate_public_key() and ->compute_shared_secret(), to merely forward any request to the inner "dh" implementation. However, a kpp_request instance received from the outside cannot get simply passed on as-is, because its associated transform (crypto_kpp_reqtfm()) will have been set to the outer ffdheXYZ(dh) one. In order to handle this, reserve some space in the outer ffdheXYZ(dh) kpp_requests' context areas for in turn storing an inner kpp_request suitable for "dh" each. Make the outer ->generate_public_key() and ->compute_shared_secret() respectively to setup this inner kpp_request by means of the new dh_safe_prime_prepare_dh_req() helper before handing it over to the "dh" implementation for further processing. dh_safe_prime_prepare_dh_req() basically copies the outer kpp_request received from the outside over to the inner one, but installs the inner transform and its own ->complete() proxy callback therein. This completion callback, the new dh_safe_prime_complete_req(), doesn't do anything beyond completing the outer request. Note that there exist some examples in crypto/, which would simply install the completion handler from the outer request at the inner one in similar setups, e.g. seqiv. However, this would mean that the user-provided completion handler won't get called with the address of the outer kpp_request initially submitted and the handler might not be prepared for this. Users could certainly work around this by setting the callback ->data properly, but IMO it's cleaner this way. Furthermore, it might make sense to extend dh_safe_prime_complete_req() in the future and move e.g. those post-computation FIPS checks from the generic "dh" implementation to the ffdheXYZ(dh) templates. [1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de [2] https://lore.kernel.org/r/20211217055227.GA20698@gondor.apana.org.au Signed-off-by: Nicolai Stange <nstange@suse.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 13:10:52 +01:00
crypto: dh - implement private key generation primitive for ffdheXYZ(dh) The support for NVME in-band authentication currently in the works ([1]) needs to generate ephemeral DH keys for use with the RFC 7919 safe-prime FFDHE groups. In analogy to ECDH and its ecc_gen_privkey(), implement a dh_safe_prime_gen_privkey() and invoke it from the ffdheXYZ(dh) templates' common ->set_secret(), i.e. dh_safe_prime_set_secret(), in case the input ->key_size is zero. As the RFC 7919 FFDHE groups are classified as approved safe-prime groups by SP800-56Arev3, it's worthwhile to make the new dh_safe_prime_gen_privkey() to follow the approach specified in SP800-56Arev3, sec. 5.6.1.1.3 ("Key-Pair Generation Using Extra Random Bits") in order to achieve conformance. SP800-56Arev3 specifies a lower as well as an upper bound on the generated key's length: - it must be >= two times the maximum supported security strength of the group in question and - it must be <= the length of the domain parameter Q. For any safe-prime group Q = (P - 1)/2 by definition and the individual maximum supported security strengths as specified by SP800-56Arev3 have been made available as part of the FFDHE dh_safe_prime definitions introduced with a previous patch. Make dh_safe_prime_gen_privkey() pick twice the maximum supported strength rounded up to the next power of two for the output key size. This choice respects both, the lower and upper bounds given by SP800-90Arev3 for any of the approved safe-prime groups and is also in line with the NVME base spec 2.0, which requires the key size to be >= 256bits. [1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de Signed-off-by: Nicolai Stange <nstange@suse.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 13:10:55 +01:00
crypto: dh - introduce common code for built-in safe-prime group support Recent work on NVME in-band authentication support ([1]) needs to invoke the "dh" KPP with the FFDHE safe-prime group parameters as specified in RFC 7919 and generate ephemeral keys suitable for the respective group. By coincidence, the requirements from NIST SP800-56Arev3, sec. 5.5.2 ("Assurance of Domain-Parameter Validity") basically boil down to disallowing any group parameters not among the approved safe-prime groups specified in either RFC 7919 or RFC 3526 in FIPS mode. Furthermore, SP800-56Arev3 specifies the respective security strength for each of the approved safe-prime groups, which has a direct impact on the minimum key lengths. In this light, it's desirable to introduce built-in support for the RFC 7919 safe-prime groups to the kernel's DH implementation, provide a SP800-56Arev3 conforming key generation primitive for those and render non-approved group parameters unusable in FIPS mode on the way. As suggested ([2]) in the course of discussion to previous iterations of this patchset, the built-in support for ffdhe groups would be best made available in the form of templates wrapping the existing "dh" implementation, one for each group specified by RFC 7919: ffdhe2048(dh), ffdhe3072(dh), ffdhe4096(dh), ffdhe6144(dh) and ffdhe8192(dh). As these templates differ only in the safe-prime constants they'd configure the inner "dh" transforms with, they can share almost all of their "dh"-wrapping template implementation code. Introduce this common code to dh_generic. The actual dump of the RFC 7919 safe-prime constants will be deferred to the next patch in order to facilitate review. The ephemeral key generation primitive mentioned above likewise deserves a patch on its own, as does the mechanism by which unapproved groups are rendered unusable in FIPS mode. Define a struct dh_safe_prime container for specifying the individual templates' associated safe-prime group constants. All ffdheXYZ(dh) template instances will store a pointer to such a dh_safe_prime in their context areas each. Implement the common __dh_safe_prime_create() template instantiation helper. The intention is that the individual ffdheXYZ(dh) crypto_templates' ->create() implementations will simply forward any calls to __dh_safe_prime_create(), passing a suitable dh_safe_prime in addition to the received ->create() arguments. __dh_safe_prime_create() would then create and register a kpp_instance as appropriate, storing the given dh_safe_prime pointer alongside a crypto_kpp_spawn for the inner "dh" kpp_alg in the context area. As the ffdheXYZ(dh) kpp_instances are supposed to act as proxies to the inner "dh" kpp_alg, make each of their associated crypto_kpp transforms to in turn own an inner "dh" transform, a pointer to which gets stored in the context area. Setup and teardown are getting handled from the outer ->init_tfm() and ->exit_tfm() respectively. In order to achieve the overall goal and let the ffdheXYZ(dh) kpp_instances configure the inner "dh" transforms with the respective group parameters, make their common ->set_secret(), the new dh_safe_prime_set_secret(), fill in the P and G values before forwarding the call to the inner "dh"'s ->set_secret(). Note that the outer ->set_secret() can obtain the P value associated with the given ffdheXYZ(dh) kpp_instance by means of the dh_safe_prime referenced from the latter's context. The value of G OTOH always equals constant 2 for the safe-prime groups. Finally, make the remaining two kpp_alg primitives both operating on kpp_requests, i.e. ->generate_public_key() and ->compute_shared_secret(), to merely forward any request to the inner "dh" implementation. However, a kpp_request instance received from the outside cannot get simply passed on as-is, because its associated transform (crypto_kpp_reqtfm()) will have been set to the outer ffdheXYZ(dh) one. In order to handle this, reserve some space in the outer ffdheXYZ(dh) kpp_requests' context areas for in turn storing an inner kpp_request suitable for "dh" each. Make the outer ->generate_public_key() and ->compute_shared_secret() respectively to setup this inner kpp_request by means of the new dh_safe_prime_prepare_dh_req() helper before handing it over to the "dh" implementation for further processing. dh_safe_prime_prepare_dh_req() basically copies the outer kpp_request received from the outside over to the inner one, but installs the inner transform and its own ->complete() proxy callback therein. This completion callback, the new dh_safe_prime_complete_req(), doesn't do anything beyond completing the outer request. Note that there exist some examples in crypto/, which would simply install the completion handler from the outer request at the inner one in similar setups, e.g. seqiv. However, this would mean that the user-provided completion handler won't get called with the address of the outer kpp_request initially submitted and the handler might not be prepared for this. Users could certainly work around this by setting the callback ->data properly, but IMO it's cleaner this way. Furthermore, it might make sense to extend dh_safe_prime_complete_req() in the future and move e.g. those post-computation FIPS checks from the generic "dh" implementation to the ffdheXYZ(dh) templates. [1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de [2] https://lore.kernel.org/r/20211217055227.GA20698@gondor.apana.org.au Signed-off-by: Nicolai Stange <nstange@suse.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 13:10:52 +01:00
crypto: dh - introduce common code for built-in safe-prime group support Recent work on NVME in-band authentication support ([1]) needs to invoke the "dh" KPP with the FFDHE safe-prime group parameters as specified in RFC 7919 and generate ephemeral keys suitable for the respective group. By coincidence, the requirements from NIST SP800-56Arev3, sec. 5.5.2 ("Assurance of Domain-Parameter Validity") basically boil down to disallowing any group parameters not among the approved safe-prime groups specified in either RFC 7919 or RFC 3526 in FIPS mode. Furthermore, SP800-56Arev3 specifies the respective security strength for each of the approved safe-prime groups, which has a direct impact on the minimum key lengths. In this light, it's desirable to introduce built-in support for the RFC 7919 safe-prime groups to the kernel's DH implementation, provide a SP800-56Arev3 conforming key generation primitive for those and render non-approved group parameters unusable in FIPS mode on the way. As suggested ([2]) in the course of discussion to previous iterations of this patchset, the built-in support for ffdhe groups would be best made available in the form of templates wrapping the existing "dh" implementation, one for each group specified by RFC 7919: ffdhe2048(dh), ffdhe3072(dh), ffdhe4096(dh), ffdhe6144(dh) and ffdhe8192(dh). As these templates differ only in the safe-prime constants they'd configure the inner "dh" transforms with, they can share almost all of their "dh"-wrapping template implementation code. Introduce this common code to dh_generic. The actual dump of the RFC 7919 safe-prime constants will be deferred to the next patch in order to facilitate review. The ephemeral key generation primitive mentioned above likewise deserves a patch on its own, as does the mechanism by which unapproved groups are rendered unusable in FIPS mode. Define a struct dh_safe_prime container for specifying the individual templates' associated safe-prime group constants. All ffdheXYZ(dh) template instances will store a pointer to such a dh_safe_prime in their context areas each. Implement the common __dh_safe_prime_create() template instantiation helper. The intention is that the individual ffdheXYZ(dh) crypto_templates' ->create() implementations will simply forward any calls to __dh_safe_prime_create(), passing a suitable dh_safe_prime in addition to the received ->create() arguments. __dh_safe_prime_create() would then create and register a kpp_instance as appropriate, storing the given dh_safe_prime pointer alongside a crypto_kpp_spawn for the inner "dh" kpp_alg in the context area. As the ffdheXYZ(dh) kpp_instances are supposed to act as proxies to the inner "dh" kpp_alg, make each of their associated crypto_kpp transforms to in turn own an inner "dh" transform, a pointer to which gets stored in the context area. Setup and teardown are getting handled from the outer ->init_tfm() and ->exit_tfm() respectively. In order to achieve the overall goal and let the ffdheXYZ(dh) kpp_instances configure the inner "dh" transforms with the respective group parameters, make their common ->set_secret(), the new dh_safe_prime_set_secret(), fill in the P and G values before forwarding the call to the inner "dh"'s ->set_secret(). Note that the outer ->set_secret() can obtain the P value associated with the given ffdheXYZ(dh) kpp_instance by means of the dh_safe_prime referenced from the latter's context. The value of G OTOH always equals constant 2 for the safe-prime groups. Finally, make the remaining two kpp_alg primitives both operating on kpp_requests, i.e. ->generate_public_key() and ->compute_shared_secret(), to merely forward any request to the inner "dh" implementation. However, a kpp_request instance received from the outside cannot get simply passed on as-is, because its associated transform (crypto_kpp_reqtfm()) will have been set to the outer ffdheXYZ(dh) one. In order to handle this, reserve some space in the outer ffdheXYZ(dh) kpp_requests' context areas for in turn storing an inner kpp_request suitable for "dh" each. Make the outer ->generate_public_key() and ->compute_shared_secret() respectively to setup this inner kpp_request by means of the new dh_safe_prime_prepare_dh_req() helper before handing it over to the "dh" implementation for further processing. dh_safe_prime_prepare_dh_req() basically copies the outer kpp_request received from the outside over to the inner one, but installs the inner transform and its own ->complete() proxy callback therein. This completion callback, the new dh_safe_prime_complete_req(), doesn't do anything beyond completing the outer request. Note that there exist some examples in crypto/, which would simply install the completion handler from the outer request at the inner one in similar setups, e.g. seqiv. However, this would mean that the user-provided completion handler won't get called with the address of the outer kpp_request initially submitted and the handler might not be prepared for this. Users could certainly work around this by setting the callback ->data properly, but IMO it's cleaner this way. Furthermore, it might make sense to extend dh_safe_prime_complete_req() in the future and move e.g. those post-computation FIPS checks from the generic "dh" implementation to the ffdheXYZ(dh) templates. [1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de [2] https://lore.kernel.org/r/20211217055227.GA20698@gondor.apana.org.au Signed-off-by: Nicolai Stange <nstange@suse.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 13:10:52 +01:00
crypto: dh - introduce common code for built-in safe-prime group support Recent work on NVME in-band authentication support ([1]) needs to invoke the "dh" KPP with the FFDHE safe-prime group parameters as specified in RFC 7919 and generate ephemeral keys suitable for the respective group. By coincidence, the requirements from NIST SP800-56Arev3, sec. 5.5.2 ("Assurance of Domain-Parameter Validity") basically boil down to disallowing any group parameters not among the approved safe-prime groups specified in either RFC 7919 or RFC 3526 in FIPS mode. Furthermore, SP800-56Arev3 specifies the respective security strength for each of the approved safe-prime groups, which has a direct impact on the minimum key lengths. In this light, it's desirable to introduce built-in support for the RFC 7919 safe-prime groups to the kernel's DH implementation, provide a SP800-56Arev3 conforming key generation primitive for those and render non-approved group parameters unusable in FIPS mode on the way. As suggested ([2]) in the course of discussion to previous iterations of this patchset, the built-in support for ffdhe groups would be best made available in the form of templates wrapping the existing "dh" implementation, one for each group specified by RFC 7919: ffdhe2048(dh), ffdhe3072(dh), ffdhe4096(dh), ffdhe6144(dh) and ffdhe8192(dh). As these templates differ only in the safe-prime constants they'd configure the inner "dh" transforms with, they can share almost all of their "dh"-wrapping template implementation code. Introduce this common code to dh_generic. The actual dump of the RFC 7919 safe-prime constants will be deferred to the next patch in order to facilitate review. The ephemeral key generation primitive mentioned above likewise deserves a patch on its own, as does the mechanism by which unapproved groups are rendered unusable in FIPS mode. Define a struct dh_safe_prime container for specifying the individual templates' associated safe-prime group constants. All ffdheXYZ(dh) template instances will store a pointer to such a dh_safe_prime in their context areas each. Implement the common __dh_safe_prime_create() template instantiation helper. The intention is that the individual ffdheXYZ(dh) crypto_templates' ->create() implementations will simply forward any calls to __dh_safe_prime_create(), passing a suitable dh_safe_prime in addition to the received ->create() arguments. __dh_safe_prime_create() would then create and register a kpp_instance as appropriate, storing the given dh_safe_prime pointer alongside a crypto_kpp_spawn for the inner "dh" kpp_alg in the context area. As the ffdheXYZ(dh) kpp_instances are supposed to act as proxies to the inner "dh" kpp_alg, make each of their associated crypto_kpp transforms to in turn own an inner "dh" transform, a pointer to which gets stored in the context area. Setup and teardown are getting handled from the outer ->init_tfm() and ->exit_tfm() respectively. In order to achieve the overall goal and let the ffdheXYZ(dh) kpp_instances configure the inner "dh" transforms with the respective group parameters, make their common ->set_secret(), the new dh_safe_prime_set_secret(), fill in the P and G values before forwarding the call to the inner "dh"'s ->set_secret(). Note that the outer ->set_secret() can obtain the P value associated with the given ffdheXYZ(dh) kpp_instance by means of the dh_safe_prime referenced from the latter's context. The value of G OTOH always equals constant 2 for the safe-prime groups. Finally, make the remaining two kpp_alg primitives both operating on kpp_requests, i.e. ->generate_public_key() and ->compute_shared_secret(), to merely forward any request to the inner "dh" implementation. However, a kpp_request instance received from the outside cannot get simply passed on as-is, because its associated transform (crypto_kpp_reqtfm()) will have been set to the outer ffdheXYZ(dh) one. In order to handle this, reserve some space in the outer ffdheXYZ(dh) kpp_requests' context areas for in turn storing an inner kpp_request suitable for "dh" each. Make the outer ->generate_public_key() and ->compute_shared_secret() respectively to setup this inner kpp_request by means of the new dh_safe_prime_prepare_dh_req() helper before handing it over to the "dh" implementation for further processing. dh_safe_prime_prepare_dh_req() basically copies the outer kpp_request received from the outside over to the inner one, but installs the inner transform and its own ->complete() proxy callback therein. This completion callback, the new dh_safe_prime_complete_req(), doesn't do anything beyond completing the outer request. Note that there exist some examples in crypto/, which would simply install the completion handler from the outer request at the inner one in similar setups, e.g. seqiv. However, this would mean that the user-provided completion handler won't get called with the address of the outer kpp_request initially submitted and the handler might not be prepared for this. Users could certainly work around this by setting the callback ->data properly, but IMO it's cleaner this way. Furthermore, it might make sense to extend dh_safe_prime_complete_req() in the future and move e.g. those post-computation FIPS checks from the generic "dh" implementation to the ffdheXYZ(dh) templates. [1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de [2] https://lore.kernel.org/r/20211217055227.GA20698@gondor.apana.org.au Signed-off-by: Nicolai Stange <nstange@suse.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 13:10:52 +01:00