From ffa13d4fdb0dedbde009df10a8af485c123566eb Mon Sep 17 00:00:00 2001 From: Julian Braha Date: Tue, 31 Mar 2026 13:22:14 +0100 Subject: [PATCH 001/196] keys: cleanup dead code in Kconfig for FIPS_SIGNATURE_SELFTEST There is already an 'if ASYMMETRIC_KEY_TYPE' condition wrapping FIPS_SIGNATURE_SELFTEST, making the 'depends on' statement a duplicate dependency (dead code). I propose leaving the outer 'if ASYMMETRIC_KEY_TYPE...endif' and removing the individual 'depends on' statement. This dead code was found by kconfirm, a static analysis tool for Kconfig. Signed-off-by: Julian Braha Signed-off-by: Herbert Xu --- crypto/asymmetric_keys/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig index e50bd9b3e27b..6a2f664046ef 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -95,7 +95,6 @@ config FIPS_SIGNATURE_SELFTEST verification code, using some built in data. This is required for FIPS. depends on KEYS - depends on ASYMMETRIC_KEY_TYPE depends on PKCS7_MESSAGE_PARSER=X509_CERTIFICATE_PARSER depends on X509_CERTIFICATE_PARSER depends on CRYPTO_RSA From 52d167bb09181452a8358163b034bb038b1d26dc Mon Sep 17 00:00:00 2001 From: Alexander Koskovich Date: Mon, 6 Apr 2026 02:10:07 +0000 Subject: [PATCH 002/196] dt-bindings: crypto: qcom-qce: Document the Milos crypto engine Document the crypto engine on the Milos platform. Signed-off-by: Alexander Koskovich Reviewed-by: Krzysztof Kozlowski Reviewed-by: Kuldeep Singh Signed-off-by: Herbert Xu --- Documentation/devicetree/bindings/crypto/qcom-qce.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/crypto/qcom-qce.yaml b/Documentation/devicetree/bindings/crypto/qcom-qce.yaml index 79d5be2548bc..74a121d8b2a5 100644 --- a/Documentation/devicetree/bindings/crypto/qcom-qce.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom-qce.yaml @@ -46,6 +46,7 @@ properties: - items: - enum: - qcom,kaanapali-qce + - qcom,milos-qce - qcom,qcs615-qce - qcom,qcs8300-qce - qcom,sa8775p-qce From 2e96024632b386c86860aa78639940fc96d6fcc9 Mon Sep 17 00:00:00 2001 From: Damian Muszynski Date: Tue, 7 Apr 2026 12:04:26 +0200 Subject: [PATCH 003/196] crypto: qat - fix heartbeat error injection The current implementation of the heartbeat error injection uses adf_disable_arb_thd() to stop a specific accelerator engine thread from processing requests. This does not reliably prevent the device from generating responses. Fix the error injection by disabling the device arbiter through exit_arb() instead. This properly simulates a device failure by stopping all arbitration, which results in missing responses for sent requests. Remove the now unused adf_disable_arb_thd() function and its declaration. Fixes: e2b67859ab6e ("crypto: qat - add heartbeat error simulator") Signed-off-by: Damian Muszynski Reviewed-by: Ahsan Atta Reviewed-by: Giovanni Cabiddu Signed-off-by: Herbert Xu --- .../intel/qat/qat_common/adf_common_drv.h | 1 - .../qat/qat_common/adf_heartbeat_inject.c | 6 ++--- .../intel/qat/qat_common/adf_hw_arbiter.c | 25 ------------------- 3 files changed, 2 insertions(+), 30 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h index 7b8b295ac459..fb0fd46a79b0 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h +++ b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h @@ -92,7 +92,6 @@ void adf_exit_aer(void); int adf_init_arb(struct adf_accel_dev *accel_dev); void adf_exit_arb(struct adf_accel_dev *accel_dev); void adf_update_ring_arb(struct adf_etr_ring_data *ring); -int adf_disable_arb_thd(struct adf_accel_dev *accel_dev, u32 ae, u32 thr); int adf_dev_get(struct adf_accel_dev *accel_dev); void adf_dev_put(struct adf_accel_dev *accel_dev); diff --git a/drivers/crypto/intel/qat/qat_common/adf_heartbeat_inject.c b/drivers/crypto/intel/qat/qat_common/adf_heartbeat_inject.c index a3b474bdef6c..023c5f1e78b0 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_heartbeat_inject.c +++ b/drivers/crypto/intel/qat/qat_common/adf_heartbeat_inject.c @@ -64,10 +64,8 @@ int adf_heartbeat_inject_error(struct adf_accel_dev *accel_dev) if (ret) return ret; - /* Configure worker threads to stop processing any packet */ - ret = adf_disable_arb_thd(accel_dev, rand_ae, rand_thr); - if (ret) - return ret; + /* Disable arbiter to stop processing any packet */ + hw_device->exit_arb(accel_dev); /* Change HB counters memory to simulate a hang */ adf_set_hb_counters_fail(accel_dev, rand_ae, rand_thr); diff --git a/drivers/crypto/intel/qat/qat_common/adf_hw_arbiter.c b/drivers/crypto/intel/qat/qat_common/adf_hw_arbiter.c index f93d9cca70ce..dd9a31c20bc9 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_hw_arbiter.c +++ b/drivers/crypto/intel/qat/qat_common/adf_hw_arbiter.c @@ -99,28 +99,3 @@ void adf_exit_arb(struct adf_accel_dev *accel_dev) csr_ops->write_csr_ring_srv_arb_en(csr, i, 0); } EXPORT_SYMBOL_GPL(adf_exit_arb); - -int adf_disable_arb_thd(struct adf_accel_dev *accel_dev, u32 ae, u32 thr) -{ - void __iomem *csr = accel_dev->transport->banks[0].csr_addr; - struct adf_hw_device_data *hw_data = accel_dev->hw_device; - const u32 *thd_2_arb_cfg; - struct arb_info info; - u32 ae_thr_map; - - if (ADF_AE_STRAND0_THREAD == thr || ADF_AE_STRAND1_THREAD == thr) - thr = ADF_AE_ADMIN_THREAD; - - hw_data->get_arb_info(&info); - thd_2_arb_cfg = hw_data->get_arb_mapping(accel_dev); - if (!thd_2_arb_cfg) - return -EFAULT; - - /* Disable scheduling for this particular AE and thread */ - ae_thr_map = *(thd_2_arb_cfg + ae); - ae_thr_map &= ~(GENMASK(3, 0) << (thr * BIT(2))); - - WRITE_CSR_ARB_WT2SAM(csr, info.arb_offset, info.wt2sam_offset, ae, - ae_thr_map); - return 0; -} From 1b475aaee4cbf4d2f7d8ac69ce84ff2e22953d30 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 7 Apr 2026 15:51:42 +0200 Subject: [PATCH 004/196] dt-bindings: crypto: qcom-qce: Add Qualcomm Eliza QCE Document the QCE crypto engine on Qualcomm Eliza SoC, fully compatible with earlier generations. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Harshal Dev Reviewed-by: Kuldeep Singh Acked-by: Rob Herring (Arm) Signed-off-by: Herbert Xu --- Documentation/devicetree/bindings/crypto/qcom-qce.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/crypto/qcom-qce.yaml b/Documentation/devicetree/bindings/crypto/qcom-qce.yaml index 74a121d8b2a5..e6c0aa5dabfc 100644 --- a/Documentation/devicetree/bindings/crypto/qcom-qce.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom-qce.yaml @@ -45,6 +45,7 @@ properties: - items: - enum: + - qcom,eliza-qce - qcom,kaanapali-qce - qcom,milos-qce - qcom,qcs615-qce From 4a76a164ba1617f60d1c8a2fd754466c9d9e48e9 Mon Sep 17 00:00:00 2001 From: "Tycho Andersen (AMD)" Date: Wed, 8 Apr 2026 08:32:56 -0600 Subject: [PATCH 005/196] crypto: ccp - Reverse the cleanup order in psp_dev_destroy() Before SNP x86 shutdown [1], all HV_FIXED pages were always leaked on module unload. Now pages can be reclaimed if they are freed before SNP shutdown. The SFS driver does sfs_dev_destroy() -> snp_free_hv_fixed_pages(), marking the command buffer as free. But this happens after sev_dev_destroy() in psp_dev_destroy(), so the pages are always leaked. Rearrange psp_dev_destroy() to destroy things in the reverse order from psp_init(), so that any dependencies can be unwound accordingly. This lets SFS free the page and the subsequent SNP shutdown release it. This was identified with use of Chris Mason's review-prompts: https://github.com/masoncl/review-prompts [1]: https://lore.kernel.org/all/20260324161301.1353976-1-tycho@kernel.org/ Fixes: 648dbccc03a0 ("crypto: ccp - Add AMD Seamless Firmware Servicing (SFS) driver") Reported-by: review-prompts Assisted-by: Claude:claude-4.6-opus Suggested-by: Tom Lendacky Signed-off-by: Tycho Andersen (AMD) Reviewed-by: Ashish Kalra Signed-off-by: Herbert Xu --- drivers/crypto/ccp/psp-dev.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/ccp/psp-dev.c b/drivers/crypto/ccp/psp-dev.c index 5c7f7e02a7d8..b14ce51065d5 100644 --- a/drivers/crypto/ccp/psp-dev.c +++ b/drivers/crypto/ccp/psp-dev.c @@ -316,16 +316,16 @@ void psp_dev_destroy(struct sp_device *sp) if (!psp) return; - sev_dev_destroy(psp); - - tee_dev_destroy(psp); - - sfs_dev_destroy(psp); - dbc_dev_destroy(psp); platform_access_dev_destroy(psp); + sfs_dev_destroy(psp); + + tee_dev_destroy(psp); + + sev_dev_destroy(psp); + sp_free_psp_irq(sp, psp); if (sp->clear_psp_master_device) From 1b864b6cb213bbd7b406e9b2e98c962077f300df Mon Sep 17 00:00:00 2001 From: "Tycho Andersen (AMD)" Date: Wed, 8 Apr 2026 08:32:57 -0600 Subject: [PATCH 006/196] crypto: ccp - Fix snp_filter_reserved_mem_regions() off-by-one Sashiko notes: > regarding the bounds check in snp_filter_reserved_mem_regions() > called via walk_iomem_res_desc(): does the check > if ((range_list->num_elements * 16 + 8) > PAGE_SIZE) > allow an off-by-one heap buffer overflow? > > If range_list->num_elements is 255, 255 * 16 + 8 = 4088, which is <= 4096. > Writing range->base (8 bytes) fills 4088-4095, but writing range->page_count > (4 bytes) would write to 4096-4099, overflowing the kzalloc-allocated > PAGE_SIZE buffer. Fix this by accounting for the entry about to be written to, in addition to the entries that are already allocated. Fixes: 1ca5614b84ee ("crypto: ccp: Add support to initialize the AMD-SP for SEV-SNP") Reported-by: Sashiko Assisted-by: Gemini:gemini-3.1-pro-preview Link: https://sashiko.dev/#/patchset/20260324161301.1353976-1-tycho%40kernel.org Signed-off-by: Tycho Andersen (AMD) Signed-off-by: Herbert Xu --- drivers/crypto/ccp/sev-dev.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index d1e9e0ac63b6..9f3434ffba4f 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -1328,10 +1328,11 @@ static int snp_filter_reserved_mem_regions(struct resource *rs, void *arg) size_t size; /* - * Ensure the list of HV_FIXED pages that will be passed to firmware - * do not exceed the page-sized argument buffer. + * Ensure the list of HV_FIXED pages passed to the firmware including + * the one about to be written to do not exceed the page-sized argument + * buffer. */ - if ((range_list->num_elements * sizeof(struct sev_data_range) + + if (((range_list->num_elements + 1) * sizeof(struct sev_data_range) + sizeof(struct sev_data_range_list)) > PAGE_SIZE) return -E2BIG; From a8d5370eef00eca132a292b1901c9914c817e385 Mon Sep 17 00:00:00 2001 From: "Tycho Andersen (AMD)" Date: Wed, 8 Apr 2026 08:32:58 -0600 Subject: [PATCH 007/196] crypto: ccp - Check for page allocation failure correctly in TIO Sashiko notes: > if __snp_alloc_firmware_pages() returns NULL under memory pressure, is it > safe to pass it directly to page_address()? > > On architectures without HASHED_PAGE_VIRTUAL, page_address(NULL) might > compute a deterministic but invalid, non-zero virtual address. The > subsequent if (tio_status) check would then evaluate to true, and > sev_tsm_init_locked() would dereference the invalid pointer. Indeed, page_address(NULL) will return non-NULL garbage here. Fix this by checking the page allocation itself for NULL, not the resulting virtual address. Fixes: 4be423572da1 ("crypto/ccp: Implement SEV-TIO PCIe IDE (phase1)") Reported-by: Sashiko Assisted-by: Gemini:gemini-3.1-pro-preview Link: https://sashiko.dev/#/patchset/20260324161301.1353976-1-tycho%40kernel.org Signed-off-by: Tycho Andersen (AMD) Signed-off-by: Herbert Xu --- drivers/crypto/ccp/sev-dev.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index 9f3434ffba4f..48caeffcc217 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -1488,6 +1488,8 @@ static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid) &snp_panic_notifier); if (data.tio_en) { + struct page *page; + /* * This executes with the sev_cmd_mutex held so down the stack * snp_reclaim_pages(locked=false) might be needed (which is extremely @@ -1495,12 +1497,14 @@ static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid) * Instead of exporting __snp_alloc_firmware_pages(), allocate a page * for this one call here. */ - void *tio_status = page_address(__snp_alloc_firmware_pages( - GFP_KERNEL_ACCOUNT | __GFP_ZERO, 0, true)); + page = __snp_alloc_firmware_pages(GFP_KERNEL_ACCOUNT | __GFP_ZERO, + 0, true); + if (page) { + void *tio_status = page_address(page); - if (tio_status) { sev_tsm_init_locked(sev, tio_status); - __snp_free_firmware_pages(virt_to_page(tio_status), 0, true); + + __snp_free_firmware_pages(page, 0, true); } } From fed613c1230277105bb512bce6e1fda8f316d178 Mon Sep 17 00:00:00 2001 From: "Tycho Andersen (AMD)" Date: Wed, 8 Apr 2026 08:32:59 -0600 Subject: [PATCH 008/196] crypto: ccp - Initialize data during __sev_snp_init_locked() Sashiko notes: > is the stack variable data left uninitialized when taking the else branch? > Since data.tio_en is later evaluated unconditionally, could stack garbage > cause it to evaluate to true, leading to erroneous attempts to allocate > pages and initialize SEV-TIO on unsupported hardware? If the firmware is too old to support SEV_INIT_EX, data is left uninitialized but used in the debug logging about whether TIO is enabled or not. Fixes: 4be423572da1 ("crypto/ccp: Implement SEV-TIO PCIe IDE (phase1)") Reported-by: Sashiko Assisted-by: Gemini:gemini-3.1-pro-preview Link: https://sashiko.dev/#/patchset/20260324161301.1353976-1-tycho%40kernel.org Signed-off-by: Tycho Andersen (AMD) Signed-off-by: Herbert Xu --- drivers/crypto/ccp/sev-dev.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index 48caeffcc217..8a85439cfa76 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -1356,7 +1356,7 @@ static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid) { struct sev_data_range_list *snp_range_list __free(kfree) = NULL; struct psp_device *psp = psp_master; - struct sev_data_snp_init_ex data; + struct sev_data_snp_init_ex data = {}; struct sev_device *sev; void *arg = &data; int cmd, rc = 0; @@ -1420,8 +1420,6 @@ static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid) */ snp_add_hv_fixed_pages(sev, snp_range_list); - memset(&data, 0, sizeof(data)); - if (max_snp_asid) { data.ciphertext_hiding_en = 1; data.max_snp_asid = max_snp_asid; From b668edaf8dcc8d09f6f1e71797422b44d4bd22a3 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sun, 12 Apr 2026 11:56:43 +0200 Subject: [PATCH 009/196] crypto: atmel-ecc - add support for atecc608b Tested on hardware with an ATECC608B at 0x60. The device binds successfully, passes the driver's sanity check, and registers the ecdh-nist-p256 KPP algorithm. The hardware ECDH path was also exercised using a minimal KPP test module, covering private key generation, public key derivation, and shared secret computation. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-ecc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index 9c380351d2f9..3738a4eb8701 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -372,6 +372,8 @@ static void atmel_ecc_remove(struct i2c_client *client) static const struct of_device_id atmel_ecc_dt_ids[] = { { .compatible = "atmel,atecc508a", + }, { + .compatible = "atmel,atecc608b", }, { /* sentinel */ } @@ -381,6 +383,7 @@ MODULE_DEVICE_TABLE(of, atmel_ecc_dt_ids); static const struct i2c_device_id atmel_ecc_id[] = { { "atecc508a" }, + { "atecc608b" }, { } }; MODULE_DEVICE_TABLE(i2c, atmel_ecc_id); From 59ed9e187f81bef5c8c7c952ea7566e900a13b95 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sun, 12 Apr 2026 11:56:45 +0200 Subject: [PATCH 010/196] dt-bindings: trivial-devices: add atmel,atecc608b Add entry for ATECC608B. Update the ATECC508A comment for consistency. Acked-by: Rob Herring (Arm) Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- Documentation/devicetree/bindings/trivial-devices.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/trivial-devices.yaml b/Documentation/devicetree/bindings/trivial-devices.yaml index 23fd4513933a..a5d5296d76af 100644 --- a/Documentation/devicetree/bindings/trivial-devices.yaml +++ b/Documentation/devicetree/bindings/trivial-devices.yaml @@ -67,8 +67,10 @@ properties: - arduino,unoq-mcu # Temperature monitoring of Astera Labs PT5161L PCIe retimer - asteralabs,pt5161l - # i2c h/w elliptic curve crypto module + # ATECC508A - i2c h/w elliptic curve crypto module - atmel,atecc508a + # ATECC608B - i2c h/w elliptic curve crypto module + - atmel,atecc608b # ATSHA204 - i2c h/w symmetric crypto module - atmel,atsha204 # ATSHA204A - i2c h/w symmetric crypto module From edcc5d486ac69d019d32e694c83e7f24a1003123 Mon Sep 17 00:00:00 2001 From: Harshal Dev Date: Thu, 16 Apr 2026 18:37:20 +0530 Subject: [PATCH 011/196] dt-bindings: crypto: qcom-qce: Document the Glymur crypto engine Document the crypto engine on Glymur platform. Signed-off-by: Harshal Dev Reviewed-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- Documentation/devicetree/bindings/crypto/qcom-qce.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/crypto/qcom-qce.yaml b/Documentation/devicetree/bindings/crypto/qcom-qce.yaml index e6c0aa5dabfc..69101cead3bc 100644 --- a/Documentation/devicetree/bindings/crypto/qcom-qce.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom-qce.yaml @@ -46,6 +46,7 @@ properties: - items: - enum: - qcom,eliza-qce + - qcom,glymur-qce - qcom,kaanapali-qce - qcom,milos-qce - qcom,qcs615-qce From 39a31ad9e2a5ed7e9c9c6f711dca96c8c8f5f26b Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:33:45 -0700 Subject: [PATCH 012/196] crypto: drbg - Fix returning success on failure in CTR_DRBG drbg_ctr_generate() sometimes returns success when it fails, leaving the output buffer uninitialized. Fix it. Fixes: cde001e4c3c3 ("crypto: rng - RNGs must return 0 in success case") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index 9204e6edb426..e4eb78ed222b 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -377,7 +377,7 @@ static int drbg_ctr_generate(struct drbg_state *drbg, if (addtl && !list_empty(addtl)) { ret = drbg_ctr_update(drbg, addtl, 2); if (ret) - return 0; + return ret; } /* 10.2.1.5.2 step 4.1 */ From ddc4dedb9ba3c8eecbc8c050fffd46d1b7e75c21 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:33:46 -0700 Subject: [PATCH 013/196] crypto: drbg - Fix misaligned writes in CTR_DRBG and HASH_DRBG drbg_cpu_to_be32() is being used to do a plain write to a byte array, which doesn't have any alignment guarantee. This can cause a misaligned write. Replace it with the correct function, put_unaligned_be32(). Fixes: 72f3e00dd67e ("crypto: drbg - replace int2byte with cpu_to_be") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/df_sp80090a.c | 7 ++++--- crypto/drbg.c | 3 ++- include/crypto/internal/drbg.h | 18 ------------------ 3 files changed, 6 insertions(+), 22 deletions(-) diff --git a/crypto/df_sp80090a.c b/crypto/df_sp80090a.c index b8134be6f7ad..f4bb7be016e8 100644 --- a/crypto/df_sp80090a.c +++ b/crypto/df_sp80090a.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -141,10 +142,10 @@ int crypto_drbg_ctr_df(struct aes_enckey *aeskey, /* 10.4.2 step 2 -- calculate the entire length of all input data */ list_for_each_entry(seed, seedlist, list) inputlen += seed->len; - drbg_cpu_to_be32(inputlen, &L_N[0]); + put_unaligned_be32(inputlen, &L_N[0]); /* 10.4.2 step 3 */ - drbg_cpu_to_be32(bytes_to_return, &L_N[4]); + put_unaligned_be32(bytes_to_return, &L_N[4]); /* 10.4.2 step 5: length is L_N, input_string, one byte, padding */ padlen = (inputlen + sizeof(L_N) + 1) % (blocklen_bytes); @@ -175,7 +176,7 @@ int crypto_drbg_ctr_df(struct aes_enckey *aeskey, * holds zeros after allocation -- even the increment of i * is irrelevant as the increment remains within length of i */ - drbg_cpu_to_be32(i, iv); + put_unaligned_be32(i, iv); /* 10.4.2 step 9.2 -- BCC and concatenation with temp */ drbg_ctr_bcc(aeskey, temp + templen, K, &bcc_list, blocklen_bytes, keylen); diff --git a/crypto/drbg.c b/crypto/drbg.c index e4eb78ed222b..de4c69032155 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -103,6 +103,7 @@ #include #include #include +#include /*************************************************************** * Backend cipher definitions available to DRBG @@ -601,7 +602,7 @@ static int drbg_hash_df(struct drbg_state *drbg, /* 10.4.1 step 3 */ input[0] = 1; - drbg_cpu_to_be32((outlen * 8), &input[1]); + put_unaligned_be32(outlen * 8, &input[1]); /* 10.4.1 step 4.1 -- concatenation of data for input into hash */ drbg_string_fill(&data, input, 5); diff --git a/include/crypto/internal/drbg.h b/include/crypto/internal/drbg.h index 371e52dcee6c..b4e5ef0be602 100644 --- a/include/crypto/internal/drbg.h +++ b/include/crypto/internal/drbg.h @@ -9,24 +9,6 @@ #ifndef _INTERNAL_DRBG_H #define _INTERNAL_DRBG_H -/* - * Convert an integer into a byte representation of this integer. - * The byte representation is big-endian - * - * @val value to be converted - * @buf buffer holding the converted integer -- caller must ensure that - * buffer size is at least 32 bit - */ -static inline void drbg_cpu_to_be32(__u32 val, unsigned char *buf) -{ - struct s { - __be32 conv; - }; - struct s *conversion = (struct s *)buf; - - conversion->conv = cpu_to_be32(val); -} - /* * Concatenation Helper and string operation helper * From 040ad83b0e8aa065fd2fc641cacba8491a8b186d Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:33:47 -0700 Subject: [PATCH 014/196] crypto: drbg - Fix ineffective sanity check Fix drbg_healthcheck_sanity() to correctly check the return value of drbg_generate(). drbg_generate() returns 0 on success, or a negative errno value on failure. drbg_healthcheck_sanity() incorrectly assumed that it returned a positive value on success. This didn't make the sanity check fail, but it made it ineffective. Fixes: cde001e4c3c3 ("crypto: rng - RNGs must return 0 in success case") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index de4c69032155..f23b431bd490 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -1737,7 +1737,6 @@ static int drbg_kcapi_seed(struct crypto_rng *tfm, */ static inline int __init drbg_healthcheck_sanity(void) { - int len = 0; #define OUTBUFLEN 16 unsigned char buf[OUTBUFLEN]; struct drbg_state *drbg = NULL; @@ -1782,11 +1781,11 @@ static inline int __init drbg_healthcheck_sanity(void) max_request_bytes = drbg_max_request_bytes(drbg); drbg_string_fill(&addtl, buf, max_addtllen + 1); /* overflow addtllen with additional info string */ - len = drbg_generate(drbg, buf, OUTBUFLEN, &addtl); - BUG_ON(0 < len); + ret = drbg_generate(drbg, buf, OUTBUFLEN, &addtl); + BUG_ON(ret == 0); /* overflow max_bits */ - len = drbg_generate(drbg, buf, (max_request_bytes + 1), NULL); - BUG_ON(0 < len); + ret = drbg_generate(drbg, buf, max_request_bytes + 1, NULL); + BUG_ON(ret == 0); /* overflow max addtllen with personalization string */ ret = drbg_seed(drbg, &addtl, false); From 6f49f00c981bbb9ef602966f19bfdbef46b681d2 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:33:48 -0700 Subject: [PATCH 015/196] crypto: drbg - Fix drbg_max_addtl() on 64-bit kernels On 64-bit kernels, drbg_max_addtl() returns 2**35 bytes. That's too large, for two reasons: 1. SP800-90A says the maximum limit is 2**35 *bits*, not 2**35 bytes. So the implemented limit has confused bits and bytes. 2. When drbg_kcapi_hash() calls crypto_shash_update() on the additional information string, the length is implicitly cast to 'unsigned int'. That truncates the additional information string to U32_MAX bytes. Fix the maximum additional information string length to always be U32_MAX - 1, causing an error to be returned for any longer lengths. Fixes: 541af946fe13 ("crypto: drbg - SP800-90A Deterministic Random Bit Generator") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- include/crypto/drbg.h | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h index 2d42518cbdce..c11eaf757ed0 100644 --- a/include/crypto/drbg.h +++ b/include/crypto/drbg.h @@ -148,19 +148,15 @@ static inline size_t drbg_max_request_bytes(struct drbg_state *drbg) return (1 << 16); } +/* + * SP800-90A allows implementations to support additional info / personalization + * strings of up to 2**35 bits. Implementations can have a smaller maximum. We + * use 2**35 - 16 bits == U32_MAX - 1 bytes so that the max + 1 always fits in a + * size_t, allowing drbg_healthcheck_sanity() to verify its enforcement. + */ static inline size_t drbg_max_addtl(struct drbg_state *drbg) { - /* SP800-90A requires 2**35 bytes additional info str / pers str */ -#if (__BITS_PER_LONG == 32) - /* - * SP800-90A allows smaller maximum numbers to be returned -- we - * return SIZE_MAX - 1 to allow the verification of the enforcement - * of this value in drbg_healthcheck_sanity. - */ - return (SIZE_MAX - 1); -#else - return (1UL<<35); -#endif + return U32_MAX - 1; } static inline size_t drbg_max_requests(struct drbg_state *drbg) From a8a1f93080efc83a9ff8452954429ae379e9e614 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:33:49 -0700 Subject: [PATCH 016/196] crypto: drbg - Fix the fips_enabled priority boost When fips_enabled=1, it seems to have been intended for one of the algorithms defined in crypto/drbg.c to be the highest priority "stdrng" algorithm, so that it is what is used by "stdrng" users. However, the code only boosts the priority to 400, which is less than the priority 500 used in drivers/crypto/caam/caamprng.c. Thus, the CAAM RNG could be used instead. Fix this by boosting the priority by 2000 instead of 200. Fixes: 541af946fe13 ("crypto: drbg - SP800-90A Deterministic Random Bit Generator") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index f23b431bd490..e3065fb9541b 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -1832,7 +1832,7 @@ static inline void __init drbg_fill_array(struct rng_alg *alg, * it is selected. */ if (fips_enabled) - alg->base.cra_priority += 200; + alg->base.cra_priority += 2000; alg->base.cra_ctxsize = sizeof(struct drbg_state); alg->base.cra_module = THIS_MODULE; From f01d721cb809cb47db1afcf629d57e2aa18ae3c6 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:33:50 -0700 Subject: [PATCH 017/196] crypto: drbg - Remove always-enabled symbol CRYPTO_DRBG_HMAC The kconfig symbol CRYPTO_DRBG_HMAC is always enabled when CRYPTO_DRBG_MENU is enabled, and all checks for CRYPTO_DRBG_HMAC are in code conditional on CRYPTO_DRBG_MENU. Thus, the only purpose of the CRYPTO_DRBG_HMAC symbol is to select CRYPTO_HMAC and CRYPTO_SHA512. Move those two selections to CRYPTO_DRBG_MENU, remove the checks for CRYPTO_DRBG_HMAC, and remove the CRYPTO_DRBG_HMAC symbol itself. Note that this also fixes an issue where CRYPTO_HMAC and CRYPTO_SHA512 were unnecessarily being forced to built-in when CRYPTO_DRBG=m. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/Kconfig | 10 +++------- crypto/drbg.c | 15 --------------- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/crypto/Kconfig b/crypto/Kconfig index 103d1f58cb7c..34da01c153d6 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1122,12 +1122,6 @@ menuconfig CRYPTO_DRBG_MENU if CRYPTO_DRBG_MENU -config CRYPTO_DRBG_HMAC - bool - default y - select CRYPTO_HMAC - select CRYPTO_SHA512 - config CRYPTO_DRBG_HASH bool "Hash_DRBG" select CRYPTO_SHA256 @@ -1147,8 +1141,10 @@ config CRYPTO_DRBG_CTR config CRYPTO_DRBG tristate default CRYPTO_DRBG_MENU - select CRYPTO_RNG + select CRYPTO_HMAC select CRYPTO_JITTERENTROPY + select CRYPTO_RNG + select CRYPTO_SHA512 endif # if CRYPTO_DRBG_MENU diff --git a/crypto/drbg.c b/crypto/drbg.c index e3065fb9541b..f6bff275c31b 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -161,7 +161,6 @@ static const struct drbg_core drbg_cores[] = { .backend_cra_name = "sha256", }, #endif /* CONFIG_CRYPTO_DRBG_HASH */ -#ifdef CONFIG_CRYPTO_DRBG_HMAC { .flags = DRBG_HMAC | DRBG_STRENGTH256, .statelen = 48, /* block length of cipher */ @@ -181,7 +180,6 @@ static const struct drbg_core drbg_cores[] = { .cra_name = "hmac_sha512", .backend_cra_name = "hmac(sha512)", }, -#endif /* CONFIG_CRYPTO_DRBG_HMAC */ }; static int drbg_uninstantiate(struct drbg_state *drbg); @@ -406,16 +404,13 @@ static const struct drbg_state_ops drbg_ctr_ops = { * HMAC DRBG callback functions ******************************************************************/ -#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC) static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval, const struct list_head *in); static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg, const unsigned char *key); static int drbg_init_hash_kernel(struct drbg_state *drbg); static int drbg_fini_hash_kernel(struct drbg_state *drbg); -#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */ -#ifdef CONFIG_CRYPTO_DRBG_HMAC #define CRYPTO_DRBG_HMAC_STRING "HMAC " MODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha512"); MODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha512"); @@ -527,7 +522,6 @@ static const struct drbg_state_ops drbg_hmac_ops = { .crypto_init = drbg_init_hash_kernel, .crypto_fini = drbg_fini_hash_kernel, }; -#endif /* CONFIG_CRYPTO_DRBG_HMAC */ /****************************************************************** * Hash DRBG callback functions @@ -1046,11 +1040,9 @@ static inline int drbg_alloc_state(struct drbg_state *drbg) unsigned int sb_size = 0; switch (drbg->core->flags & DRBG_TYPE_MASK) { -#ifdef CONFIG_CRYPTO_DRBG_HMAC case DRBG_HMAC: drbg->d_ops = &drbg_hmac_ops; break; -#endif /* CONFIG_CRYPTO_DRBG_HMAC */ #ifdef CONFIG_CRYPTO_DRBG_HASH case DRBG_HASH: drbg->d_ops = &drbg_hash_ops; @@ -1431,7 +1423,6 @@ static void drbg_kcapi_set_entropy(struct crypto_rng *tfm, * Kernel crypto API cipher invocations requested by DRBG ***************************************************************/ -#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC) struct sdesc { struct shash_desc shash; }; @@ -1491,7 +1482,6 @@ static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval, crypto_shash_update(&sdesc->shash, input->buf, input->len); return crypto_shash_final(&sdesc->shash, outval); } -#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */ #ifdef CONFIG_CRYPTO_DRBG_CTR static int drbg_fini_sym_kernel(struct drbg_state *drbg) @@ -1757,9 +1747,7 @@ static inline int __init drbg_healthcheck_sanity(void) #ifdef CONFIG_CRYPTO_DRBG_HASH drbg_convert_tfm_core("drbg_nopr_sha256", &coreref, &pr); #endif -#ifdef CONFIG_CRYPTO_DRBG_HMAC drbg_convert_tfm_core("drbg_nopr_hmac_sha512", &coreref, &pr); -#endif drbg = kzalloc_obj(struct drbg_state); if (!drbg) @@ -1887,9 +1875,6 @@ module_exit(drbg_exit); #ifndef CRYPTO_DRBG_HASH_STRING #define CRYPTO_DRBG_HASH_STRING "" #endif -#ifndef CRYPTO_DRBG_HMAC_STRING -#define CRYPTO_DRBG_HMAC_STRING "" -#endif #ifndef CRYPTO_DRBG_CTR_STRING #define CRYPTO_DRBG_CTR_STRING "" #endif From 1c4f7235112934232975e6ed08a896a4caa71dd9 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:33:51 -0700 Subject: [PATCH 018/196] crypto: drbg - Remove broken commented-out code This commented-out code doesn't compile. Even if it did, it wouldn't actually do what it was apparently intended to do, seeing as the "test" for "drbg_pr_hmac_sha512" and "drbg_pr_ctr_aes256" is alg_test_null(). Just delete it to avoid keeping broken code around, and so that there isn't any perceived need to try to update it as the DRBG code is refactored. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index f6bff275c31b..bb8ddc090307 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -1219,36 +1219,7 @@ static int drbg_generate(struct drbg_state *drbg, * In this case, the entire kernel operation is questionable and it * is unlikely that the integrity violation only affects the * correct operation of the DRBG. - * - * Albeit the following code is commented out, it is provided in - * case somebody has a need to implement the test of 11.3.3. */ -#if 0 - if (drbg->reseed_ctr && !(drbg->reseed_ctr % 4096)) { - int err = 0; - pr_devel("DRBG: start to perform self test\n"); - if (drbg->core->flags & DRBG_HMAC) - err = alg_test("drbg_pr_hmac_sha512", - "drbg_pr_hmac_sha512", 0, 0); - else if (drbg->core->flags & DRBG_CTR) - err = alg_test("drbg_pr_ctr_aes256", - "drbg_pr_ctr_aes256", 0, 0); - else - err = alg_test("drbg_pr_sha256", - "drbg_pr_sha256", 0, 0); - if (err) { - pr_err("DRBG: periodical self test failed\n"); - /* - * uninstantiate implies that from now on, only errors - * are returned when reusing this DRBG cipher handle - */ - drbg_uninstantiate(drbg); - return 0; - } else { - pr_devel("DRBG: self test successful\n"); - } - } -#endif /* * All operations were successful, return 0 as mandated by From 06dc3f01e789cdad4d99b99eba35acb26d227f53 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:33:52 -0700 Subject: [PATCH 019/196] crypto: drbg - Remove unhelpful helper functions Fold the contents of the inline functions crypto_drbg_get_bytes_addtl(), crypto_drbg_get_bytes_addtl_test(), and crypto_drbg_reset_test() into their only caller in drbg_cavs_test(). It ends up being much simpler. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 15 +++------ crypto/testmgr.c | 34 ++++++------------- include/crypto/drbg.h | 76 ------------------------------------------- 3 files changed, 15 insertions(+), 110 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index bb8ddc090307..83cb6c1bbac0 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -55,7 +55,7 @@ * char data[DATALEN]; * * drng = crypto_alloc_rng(drng_name, 0, 0); - * err = crypto_rng_get_bytes(drng, &data, DATALEN); + * err = crypto_rng_get_bytes(drng, data, DATALEN); * crypto_free_rng(drng); * * @@ -64,15 +64,13 @@ * struct crypto_rng *drng; * int err; * char data[DATALEN]; - * struct drbg_string pers; * char personalization[11] = "some-string"; * - * drbg_string_fill(&pers, personalization, strlen(personalization)); * drng = crypto_alloc_rng(drng_name, 0, 0); * // The reset completely re-initializes the DRBG with the provided * // personalization string - * err = crypto_rng_reset(drng, &personalization, strlen(personalization)); - * err = crypto_rng_get_bytes(drng, &data, DATALEN); + * err = crypto_rng_reset(drng, personalization, strlen(personalization)); + * err = crypto_rng_get_bytes(drng, data, DATALEN); * crypto_free_rng(drng); * * @@ -82,13 +80,10 @@ * int err; * char data[DATALEN]; * char addtl_string[11] = "some-string"; - * string drbg_string addtl; * - * drbg_string_fill(&addtl, addtl_string, strlen(addtl_string)); * drng = crypto_alloc_rng(drng_name, 0, 0); - * // The following call is a wrapper to crypto_rng_get_bytes() and returns - * // the same error codes. - * err = crypto_drbg_get_bytes_addtl(drng, &data, DATALEN, &addtl); + * err = crypto_rng_generate(drng, addtl_string, strlen(addtl_string), + data, DATALEN); * crypto_free_rng(drng); * * diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 4d86efae65b2..35ff2b50e3c2 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -3487,8 +3487,6 @@ static int drbg_cavs_test(const struct drbg_testvec *test, int pr, { int ret = -EAGAIN; struct crypto_rng *drng; - struct drbg_test_data test_data; - struct drbg_string addtl, pers, testentropy; unsigned char *buf = kzalloc(test->expectedlen, GFP_KERNEL); if (!buf) @@ -3504,39 +3502,27 @@ static int drbg_cavs_test(const struct drbg_testvec *test, int pr, return PTR_ERR(drng); } - test_data.testentropy = &testentropy; - drbg_string_fill(&testentropy, test->entropy, test->entropylen); - drbg_string_fill(&pers, test->pers, test->perslen); - ret = crypto_drbg_reset_test(drng, &pers, &test_data); + crypto_rng_set_entropy(drng, test->entropy, test->entropylen); + ret = crypto_rng_reset(drng, test->pers, test->perslen); if (ret) { printk(KERN_ERR "alg: drbg: Failed to reset rng\n"); goto outbuf; } - drbg_string_fill(&addtl, test->addtla, test->addtllen); - if (pr) { - drbg_string_fill(&testentropy, test->entpra, test->entprlen); - ret = crypto_drbg_get_bytes_addtl_test(drng, - buf, test->expectedlen, &addtl, &test_data); - } else { - ret = crypto_drbg_get_bytes_addtl(drng, - buf, test->expectedlen, &addtl); - } + if (pr) + crypto_rng_set_entropy(drng, test->entpra, test->entprlen); + ret = crypto_rng_generate(drng, test->addtla, test->addtllen, + buf, test->expectedlen); if (ret < 0) { printk(KERN_ERR "alg: drbg: could not obtain random data for " "driver %s\n", driver); goto outbuf; } - drbg_string_fill(&addtl, test->addtlb, test->addtllen); - if (pr) { - drbg_string_fill(&testentropy, test->entprb, test->entprlen); - ret = crypto_drbg_get_bytes_addtl_test(drng, - buf, test->expectedlen, &addtl, &test_data); - } else { - ret = crypto_drbg_get_bytes_addtl(drng, - buf, test->expectedlen, &addtl); - } + if (pr) + crypto_rng_set_entropy(drng, test->entprb, test->entprlen); + ret = crypto_rng_generate(drng, test->addtlb, test->addtllen, + buf, test->expectedlen); if (ret < 0) { printk(KERN_ERR "alg: drbg: could not obtain random data for " "driver %s\n", driver); diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h index c11eaf757ed0..486aa793688e 100644 --- a/include/crypto/drbg.h +++ b/include/crypto/drbg.h @@ -78,10 +78,6 @@ struct drbg_state_ops { }; -struct drbg_test_data { - struct drbg_string *testentropy; /* TEST PARAMETER: test entropy */ -}; - enum drbg_seed_state { DRBG_SEED_STATE_UNSEEDED, DRBG_SEED_STATE_PARTIAL, /* Seeded with !rng_is_initialized() */ @@ -165,78 +161,6 @@ static inline size_t drbg_max_requests(struct drbg_state *drbg) return (1<<20); } -/* - * This is a wrapper to the kernel crypto API function of - * crypto_rng_generate() to allow the caller to provide additional data. - * - * @drng DRBG handle -- see crypto_rng_get_bytes - * @outbuf output buffer -- see crypto_rng_get_bytes - * @outlen length of output buffer -- see crypto_rng_get_bytes - * @addtl_input additional information string input buffer - * @addtllen length of additional information string buffer - * - * return - * see crypto_rng_get_bytes - */ -static inline int crypto_drbg_get_bytes_addtl(struct crypto_rng *drng, - unsigned char *outbuf, unsigned int outlen, - struct drbg_string *addtl) -{ - return crypto_rng_generate(drng, addtl->buf, addtl->len, - outbuf, outlen); -} - -/* - * TEST code - * - * This is a wrapper to the kernel crypto API function of - * crypto_rng_generate() to allow the caller to provide additional data and - * allow furnishing of test_data - * - * @drng DRBG handle -- see crypto_rng_get_bytes - * @outbuf output buffer -- see crypto_rng_get_bytes - * @outlen length of output buffer -- see crypto_rng_get_bytes - * @addtl_input additional information string input buffer - * @addtllen length of additional information string buffer - * @test_data filled test data - * - * return - * see crypto_rng_get_bytes - */ -static inline int crypto_drbg_get_bytes_addtl_test(struct crypto_rng *drng, - unsigned char *outbuf, unsigned int outlen, - struct drbg_string *addtl, - struct drbg_test_data *test_data) -{ - crypto_rng_set_entropy(drng, test_data->testentropy->buf, - test_data->testentropy->len); - return crypto_rng_generate(drng, addtl->buf, addtl->len, - outbuf, outlen); -} - -/* - * TEST code - * - * This is a wrapper to the kernel crypto API function of - * crypto_rng_reset() to allow the caller to provide test_data - * - * @drng DRBG handle -- see crypto_rng_reset - * @pers personalization string input buffer - * @perslen length of additional information string buffer - * @test_data filled test data - * - * return - * see crypto_rng_reset - */ -static inline int crypto_drbg_reset_test(struct crypto_rng *drng, - struct drbg_string *pers, - struct drbg_test_data *test_data) -{ - crypto_rng_set_entropy(drng, test_data->testentropy->buf, - test_data->testentropy->len); - return crypto_rng_reset(drng, pers->buf, pers->len); -} - /* DRBG type flags */ #define DRBG_CTR ((drbg_flag_t)1<<0) #define DRBG_HMAC ((drbg_flag_t)1<<1) From f4919bbca03c8d130a46eba99535b5730edd89a6 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:33:53 -0700 Subject: [PATCH 020/196] crypto: drbg - Remove obsolete FIPS 140-2 continuous test FIPS 140-2 required that a continuous test for repeated outputs be done on both "Approved RNGs" and "Non-Approved RNGs". That's apparently why crypto/drbg.c does such a test on the bytes it pulls from get_random_bytes(), despite get_random_bytes() being a "Non-Approved RNG" that is credited with zero entropy for FIPS purposes. (From FIPS's point of view, the "Approved RNG" is jitterentropy.) FIPS 140-3 "modernized" the continuous RNG test requirements. They're now a bit more sophisticated, requiring both an "Adaptive Proportion Test" and a "Repetition Count Test". At the same time, FIPS 140-3 doesn't require continuous RNG tests on "Non-Approved RNGs" if a "vetted conditioning component" is used. The SP800-90A DRBGs are exactly such a vetted conditioning component, by their design. (In the case of HASH_DRBG and CTR_DRBG, the derivation function does have to be implemented. But the kernel does that.) In other words: from FIPS 140-3's point of view, get_random_bytes() still produces zero entropy, but the way the DRBG combines those bytes with the jitterentropy bytes preserves all the "approved" entropy from jitterentropy. Thus no test for get_random_bytes() is required. Seeing as FIPS 140-2 certificates stopped being issued in 2021 in favor of FIPS 140-3, this means this code is obsolete. Remove it. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 78 ++----------------------------------------- include/crypto/drbg.h | 2 -- 2 files changed, 2 insertions(+), 78 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index 83cb6c1bbac0..66d7739469c6 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -205,55 +205,6 @@ static inline unsigned short drbg_sec_strength(drbg_flag_t flags) } } -/* - * FIPS 140-2 continuous self test for the noise source - * The test is performed on the noise source input data. Thus, the function - * implicitly knows the size of the buffer to be equal to the security - * strength. - * - * Note, this function disregards the nonce trailing the entropy data during - * initial seeding. - * - * drbg->drbg_mutex must have been taken. - * - * @drbg DRBG handle - * @entropy buffer of seed data to be checked - * - * return: - * %true on success - * %false when the CTRNG is not yet primed - */ -static bool drbg_fips_continuous_test(struct drbg_state *drbg, - const unsigned char *entropy) - __must_hold(&drbg->drbg_mutex) -{ - unsigned short entropylen = drbg_sec_strength(drbg->core->flags); - - if (!IS_ENABLED(CONFIG_CRYPTO_FIPS)) - return true; - - /* skip test if we test the overall system */ - if (list_empty(&drbg->test_data.list)) - return true; - /* only perform test in FIPS mode */ - if (!fips_enabled) - return true; - - if (!drbg->fips_primed) { - /* Priming of FIPS test */ - memcpy(drbg->prev, entropy, entropylen); - drbg->fips_primed = true; - /* priming: another round is needed */ - return false; - } - if (!memcmp(drbg->prev, entropy, entropylen)) - panic("DRBG continuous self test failed\n"); - memcpy(drbg->prev, entropy, entropylen); - - /* the test shall pass when the two values are not equal */ - return true; -} - /****************************************************************** * CTR DRBG callback functions ******************************************************************/ @@ -833,16 +784,6 @@ static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed, return ret; } -static inline void drbg_get_random_bytes(struct drbg_state *drbg, - unsigned char *entropy, - unsigned int entropylen) - __must_hold(&drbg->drbg_mutex) -{ - do - get_random_bytes(entropy, entropylen); - while (!drbg_fips_continuous_test(drbg, entropy)); -} - static int drbg_seed_from_random(struct drbg_state *drbg) __must_hold(&drbg->drbg_mutex) { @@ -858,7 +799,7 @@ static int drbg_seed_from_random(struct drbg_state *drbg) drbg_string_fill(&data, entropy, entropylen); list_add_tail(&data.list, &seedlist); - drbg_get_random_bytes(drbg, entropy, entropylen); + get_random_bytes(entropy, entropylen); ret = __drbg_seed(drbg, &seedlist, true, DRBG_SEED_STATE_FULL); @@ -937,7 +878,7 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers, if (!rng_is_initialized()) new_seed_state = DRBG_SEED_STATE_PARTIAL; - drbg_get_random_bytes(drbg, entropy, entropylen); + get_random_bytes(entropy, entropylen); if (!drbg->jent) { drbg_string_fill(&data1, entropy, entropylen); @@ -1018,11 +959,6 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg) drbg->reseed_ctr = 0; drbg->d_ops = NULL; drbg->core = NULL; - if (IS_ENABLED(CONFIG_CRYPTO_FIPS)) { - kfree_sensitive(drbg->prev); - drbg->prev = NULL; - drbg->fips_primed = false; - } } /* @@ -1088,16 +1024,6 @@ static inline int drbg_alloc_state(struct drbg_state *drbg) drbg->scratchpad = PTR_ALIGN(drbg->scratchpadbuf, ret + 1); } - if (IS_ENABLED(CONFIG_CRYPTO_FIPS)) { - drbg->prev = kzalloc(drbg_sec_strength(drbg->core->flags), - GFP_KERNEL); - if (!drbg->prev) { - ret = -ENOMEM; - goto fini; - } - drbg->fips_primed = false; - } - return 0; fini: diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h index 486aa793688e..4fafc69a8ee6 100644 --- a/include/crypto/drbg.h +++ b/include/crypto/drbg.h @@ -109,8 +109,6 @@ struct drbg_state { enum drbg_seed_state seeded; /* DRBG fully seeded? */ unsigned long last_seed_time; bool pr; /* Prediction resistance enabled? */ - bool fips_primed; /* Continuous test primed? */ - unsigned char *prev; /* FIPS 140-2 continuous test value */ struct crypto_rng *jent; const struct drbg_state_ops *d_ops; const struct drbg_core *core; From 262ec4782cf4ae3b661b30ff11d3af86f667c69c Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:33:54 -0700 Subject: [PATCH 021/196] crypto: drbg - Fold include/crypto/drbg.h into crypto/drbg.c include/crypto/drbg.h no longer contains anything that is used externally to crypto/drbg.c. Therefore, fold it into crypto/drbg.c. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 132 ++++++++++++- crypto/testmgr.c | 3 +- include/crypto/drbg.h | 181 ------------------ .../crypto/chacha20-s390/test-cipher.c | 1 - 4 files changed, 132 insertions(+), 185 deletions(-) delete mode 100644 include/crypto/drbg.h diff --git a/crypto/drbg.c b/crypto/drbg.c index 66d7739469c6..fd1d75addaf7 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -92,14 +92,144 @@ * Just mix both scenarios above. */ -#include #include #include +#include +#include +#include +#include +#include #include #include +#include +#include +#include #include #include +struct drbg_state; +typedef uint32_t drbg_flag_t; + +struct drbg_core { + drbg_flag_t flags; /* flags for the cipher */ + __u8 statelen; /* maximum state length */ + __u8 blocklen_bytes; /* block size of output in bytes */ + char cra_name[CRYPTO_MAX_ALG_NAME]; /* mapping to kernel crypto API */ + /* kernel crypto API backend cipher name */ + char backend_cra_name[CRYPTO_MAX_ALG_NAME]; +}; + +struct drbg_state_ops { + int (*update)(struct drbg_state *drbg, struct list_head *seed, + int reseed); + int (*generate)(struct drbg_state *drbg, + unsigned char *buf, unsigned int buflen, + struct list_head *addtl); + int (*crypto_init)(struct drbg_state *drbg); + int (*crypto_fini)(struct drbg_state *drbg); + +}; + +enum drbg_seed_state { + DRBG_SEED_STATE_UNSEEDED, + DRBG_SEED_STATE_PARTIAL, /* Seeded with !rng_is_initialized() */ + DRBG_SEED_STATE_FULL, +}; + +struct drbg_state { + struct mutex drbg_mutex; /* lock around DRBG */ + unsigned char *V; /* internal state 10.1.1.1 1a) */ + unsigned char *Vbuf; + /* hash: static value 10.1.1.1 1b) hmac / ctr: key */ + unsigned char *C; + unsigned char *Cbuf; + /* Number of RNG requests since last reseed -- 10.1.1.1 1c) */ + size_t reseed_ctr; + size_t reseed_threshold; + /* some memory the DRBG can use for its operation */ + unsigned char *scratchpad; + unsigned char *scratchpadbuf; + void *priv_data; /* Cipher handle */ + + struct crypto_skcipher *ctr_handle; /* CTR mode cipher handle */ + struct skcipher_request *ctr_req; /* CTR mode request handle */ + __u8 *outscratchpadbuf; /* CTR mode output scratchpad */ + __u8 *outscratchpad; /* CTR mode aligned outbuf */ + struct crypto_wait ctr_wait; /* CTR mode async wait obj */ + struct scatterlist sg_in, sg_out; /* CTR mode SGLs */ + + enum drbg_seed_state seeded; /* DRBG fully seeded? */ + unsigned long last_seed_time; + bool pr; /* Prediction resistance enabled? */ + struct crypto_rng *jent; + const struct drbg_state_ops *d_ops; + const struct drbg_core *core; + struct drbg_string test_data; +}; + +static inline __u8 drbg_statelen(struct drbg_state *drbg) +{ + if (drbg && drbg->core) + return drbg->core->statelen; + return 0; +} + +static inline __u8 drbg_blocklen(struct drbg_state *drbg) +{ + if (drbg && drbg->core) + return drbg->core->blocklen_bytes; + return 0; +} + +static inline __u8 drbg_keylen(struct drbg_state *drbg) +{ + if (drbg && drbg->core) + return (drbg->core->statelen - drbg->core->blocklen_bytes); + return 0; +} + +static inline size_t drbg_max_request_bytes(struct drbg_state *drbg) +{ + /* SP800-90A requires the limit 2**19 bits, but we return bytes */ + return (1 << 16); +} + +/* + * SP800-90A allows implementations to support additional info / personalization + * strings of up to 2**35 bits. Implementations can have a smaller maximum. We + * use 2**35 - 16 bits == U32_MAX - 1 bytes so that the max + 1 always fits in a + * size_t, allowing drbg_healthcheck_sanity() to verify its enforcement. + */ +static inline size_t drbg_max_addtl(struct drbg_state *drbg) +{ + return U32_MAX - 1; +} + +static inline size_t drbg_max_requests(struct drbg_state *drbg) +{ + /* SP800-90A requires 2**48 maximum requests before reseeding */ + return (1<<20); +} + +/* DRBG type flags */ +#define DRBG_CTR ((drbg_flag_t)1<<0) +#define DRBG_HMAC ((drbg_flag_t)1<<1) +#define DRBG_HASH ((drbg_flag_t)1<<2) +#define DRBG_TYPE_MASK (DRBG_CTR | DRBG_HMAC | DRBG_HASH) +/* DRBG strength flags */ +#define DRBG_STRENGTH128 ((drbg_flag_t)1<<3) +#define DRBG_STRENGTH192 ((drbg_flag_t)1<<4) +#define DRBG_STRENGTH256 ((drbg_flag_t)1<<5) +#define DRBG_STRENGTH_MASK (DRBG_STRENGTH128 | DRBG_STRENGTH192 | \ + DRBG_STRENGTH256) + +enum drbg_prefixes { + DRBG_PREFIX0 = 0x00, + DRBG_PREFIX1, + DRBG_PREFIX2, + DRBG_PREFIX3 +}; + /*************************************************************** * Backend cipher definitions available to DRBG ***************************************************************/ diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 35ff2b50e3c2..480368a41cc0 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -28,13 +28,12 @@ #include #include #include -#include -#include #include #include #include #include #include +#include #include #include "internal.h" diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h deleted file mode 100644 index 4fafc69a8ee6..000000000000 --- a/include/crypto/drbg.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * DRBG based on NIST SP800-90A - * - * Copyright Stephan Mueller , 2014 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * ALTERNATIVELY, this product may be distributed under the terms of - * the GNU General Public License, in which case the provisions of the GPL are - * required INSTEAD OF the above restrictions. (This clause is - * necessary due to a potential bad interaction between the GPL and - * the restrictions contained in a BSD-style copyright.) - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - */ - -#ifndef _DRBG_H -#define _DRBG_H - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct drbg_state; -typedef uint32_t drbg_flag_t; - -struct drbg_core { - drbg_flag_t flags; /* flags for the cipher */ - __u8 statelen; /* maximum state length */ - __u8 blocklen_bytes; /* block size of output in bytes */ - char cra_name[CRYPTO_MAX_ALG_NAME]; /* mapping to kernel crypto API */ - /* kernel crypto API backend cipher name */ - char backend_cra_name[CRYPTO_MAX_ALG_NAME]; -}; - -struct drbg_state_ops { - int (*update)(struct drbg_state *drbg, struct list_head *seed, - int reseed); - int (*generate)(struct drbg_state *drbg, - unsigned char *buf, unsigned int buflen, - struct list_head *addtl); - int (*crypto_init)(struct drbg_state *drbg); - int (*crypto_fini)(struct drbg_state *drbg); - -}; - -enum drbg_seed_state { - DRBG_SEED_STATE_UNSEEDED, - DRBG_SEED_STATE_PARTIAL, /* Seeded with !rng_is_initialized() */ - DRBG_SEED_STATE_FULL, -}; - -struct drbg_state { - struct mutex drbg_mutex; /* lock around DRBG */ - unsigned char *V; /* internal state 10.1.1.1 1a) */ - unsigned char *Vbuf; - /* hash: static value 10.1.1.1 1b) hmac / ctr: key */ - unsigned char *C; - unsigned char *Cbuf; - /* Number of RNG requests since last reseed -- 10.1.1.1 1c) */ - size_t reseed_ctr; - size_t reseed_threshold; - /* some memory the DRBG can use for its operation */ - unsigned char *scratchpad; - unsigned char *scratchpadbuf; - void *priv_data; /* Cipher handle */ - - struct crypto_skcipher *ctr_handle; /* CTR mode cipher handle */ - struct skcipher_request *ctr_req; /* CTR mode request handle */ - __u8 *outscratchpadbuf; /* CTR mode output scratchpad */ - __u8 *outscratchpad; /* CTR mode aligned outbuf */ - struct crypto_wait ctr_wait; /* CTR mode async wait obj */ - struct scatterlist sg_in, sg_out; /* CTR mode SGLs */ - - enum drbg_seed_state seeded; /* DRBG fully seeded? */ - unsigned long last_seed_time; - bool pr; /* Prediction resistance enabled? */ - struct crypto_rng *jent; - const struct drbg_state_ops *d_ops; - const struct drbg_core *core; - struct drbg_string test_data; -}; - -static inline __u8 drbg_statelen(struct drbg_state *drbg) -{ - if (drbg && drbg->core) - return drbg->core->statelen; - return 0; -} - -static inline __u8 drbg_blocklen(struct drbg_state *drbg) -{ - if (drbg && drbg->core) - return drbg->core->blocklen_bytes; - return 0; -} - -static inline __u8 drbg_keylen(struct drbg_state *drbg) -{ - if (drbg && drbg->core) - return (drbg->core->statelen - drbg->core->blocklen_bytes); - return 0; -} - -static inline size_t drbg_max_request_bytes(struct drbg_state *drbg) -{ - /* SP800-90A requires the limit 2**19 bits, but we return bytes */ - return (1 << 16); -} - -/* - * SP800-90A allows implementations to support additional info / personalization - * strings of up to 2**35 bits. Implementations can have a smaller maximum. We - * use 2**35 - 16 bits == U32_MAX - 1 bytes so that the max + 1 always fits in a - * size_t, allowing drbg_healthcheck_sanity() to verify its enforcement. - */ -static inline size_t drbg_max_addtl(struct drbg_state *drbg) -{ - return U32_MAX - 1; -} - -static inline size_t drbg_max_requests(struct drbg_state *drbg) -{ - /* SP800-90A requires 2**48 maximum requests before reseeding */ - return (1<<20); -} - -/* DRBG type flags */ -#define DRBG_CTR ((drbg_flag_t)1<<0) -#define DRBG_HMAC ((drbg_flag_t)1<<1) -#define DRBG_HASH ((drbg_flag_t)1<<2) -#define DRBG_TYPE_MASK (DRBG_CTR | DRBG_HMAC | DRBG_HASH) -/* DRBG strength flags */ -#define DRBG_STRENGTH128 ((drbg_flag_t)1<<3) -#define DRBG_STRENGTH192 ((drbg_flag_t)1<<4) -#define DRBG_STRENGTH256 ((drbg_flag_t)1<<5) -#define DRBG_STRENGTH_MASK (DRBG_STRENGTH128 | DRBG_STRENGTH192 | \ - DRBG_STRENGTH256) - -enum drbg_prefixes { - DRBG_PREFIX0 = 0x00, - DRBG_PREFIX1, - DRBG_PREFIX2, - DRBG_PREFIX3 -}; - -#endif /* _DRBG_H */ diff --git a/tools/testing/crypto/chacha20-s390/test-cipher.c b/tools/testing/crypto/chacha20-s390/test-cipher.c index 827507844e8f..9f61454ed077 100644 --- a/tools/testing/crypto/chacha20-s390/test-cipher.c +++ b/tools/testing/crypto/chacha20-s390/test-cipher.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include From f2e5cd7baea4f1d6fc9fe1a0472b9316eb29b396 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:33:55 -0700 Subject: [PATCH 022/196] crypto: drbg - Remove import of crypto_cipher functions The inclusion of and the import of the internal crypto namespace became unnecessary in commit ba0570bdf1d9 ("crypto: drbg - Replace AES cipher calls with library calls"). Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index fd1d75addaf7..9dedc6186b42 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -93,7 +93,6 @@ */ #include -#include #include #include #include @@ -1908,4 +1907,3 @@ MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG) " CRYPTO_DRBG_HMAC_STRING CRYPTO_DRBG_CTR_STRING); MODULE_ALIAS_CRYPTO("stdrng"); -MODULE_IMPORT_NS("CRYPTO_INTERNAL"); From 6f88f41eeb7d4ef34e4ddb133d10779a316da67f Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:33:56 -0700 Subject: [PATCH 023/196] crypto: drbg - Remove support for CTR_DRBG Remove the support for CTR_DRBG. It's likely unused code, seeing as HMAC_DRBG is always enabled and prioritized over it unless NETLINK_CRYPTO is used to change the algorithm priorities. There's also no compelling reason to support more than one of [HMAC_DRBG, HASH_DRBG, CTR_DRBG]. By definition, callers cannot tell any difference in their outputs. And all are FIPS-certifiable, which is the only point of the kernel's NIST DRBGs anyway. Switching to CTR_DRBG doesn't seem all that compelling, either. While it's often the fastest NIST DRBG, it has several disadvantages: - CTR_DRBG uses AES. Some platforms don't have AES acceleration at all, causing a fallback to the table-based AES code which is very slow and can be vulnerable to cache-timing attacks. In contrast, HMAC_DRBG uses primitives that are consistently constant-time. - CTR_DRBG is usually considered to be somewhat less cryptographically robust than HMAC_DRBG. Granted, HMAC_DRBG isn't all that great either, e.g. given the negative result from Woodage & Shumow (2018) (https://eprint.iacr.org/2018/349.pdf), but that can be worked around. - CTR_DRBG is more complex than HMAC_DRBG, risking bugs. Indeed, while reviewing the CTR_DRBG code, I found two bugs, including one where it can return success while leaving the output buffer uninitialized. - The kernel's implementation of CTR_DRBG uses an "ctr(aes)" crypto_skcipher and relies on it returning the next counter value. That's fragile, and indeed historically many "ctr(aes)" crypto_skcipher implementations haven't done that. E.g. see commit 511306b2d075 ("crypto: arm/aes-ce - update IV after partial final CTR block"), commit fa5fd3afc7e6 ("crypto: arm64/aes-blk - update IV after partial final CTR block"), commit 371731ec2179 ("crypto: atmel-aes - Fix saving of IV for CTR mode"), commit 25baaf8e2c93 ("crypto: crypto4xx - fix ctr-aes missing output IV"), commit 334d37c9e263 ("crypto: caam - update IV using HW support"), commit 0a4491d3febe ("crypto: chelsio - count incomplete block in IV"), commit e8e3c1ca57d4 ("crypto: s5p - update iv after AES-CBC op end"). I.e., there were many years where the kernel's CTR_DRBG code (if it were to have actually been used) repeated outputs on some platforms. AES-CTR also uses a 128-bit counter, which creates overflow edge cases that are sometimes gotten wrong. E.g. see commit 009b30ac7444 ("crypto: vmx - CTR: always increment IV as quadword"). So, while switching to CTR_DRBG for performance reasons isn't completely out of the question (notably BoringSSL uses it), it would take quite a bit more work to create a solid implementation of it in the kernel, including a more solid implementation of AES-CTR itself (in lib/crypto/, with a scalar bit-sliced fallback, etc). Since HMAC_DRBG has always been the default NIST DRBG variant in the kernel and is in a better state, let's just standardize on it for now. Signed-off-by: Eric Biggers Acked-by: Geert Uytterhoeven # m68k Signed-off-by: Herbert Xu --- arch/m68k/configs/amiga_defconfig | 1 - arch/m68k/configs/apollo_defconfig | 1 - arch/m68k/configs/atari_defconfig | 1 - arch/m68k/configs/bvme6000_defconfig | 1 - arch/m68k/configs/hp300_defconfig | 1 - arch/m68k/configs/mac_defconfig | 1 - arch/m68k/configs/multi_defconfig | 1 - arch/m68k/configs/mvme147_defconfig | 1 - arch/m68k/configs/mvme16x_defconfig | 1 - arch/m68k/configs/q40_defconfig | 1 - arch/m68k/configs/sun3_defconfig | 1 - arch/m68k/configs/sun3x_defconfig | 1 - arch/mips/configs/decstation_64_defconfig | 1 - arch/mips/configs/decstation_defconfig | 1 - arch/mips/configs/decstation_r4k_defconfig | 1 - crypto/Kconfig | 8 - crypto/drbg.c | 332 +-------------------- crypto/testmgr.c | 37 --- crypto/testmgr.h | 252 ---------------- include/crypto/internal/drbg.h | 3 + 20 files changed, 9 insertions(+), 638 deletions(-) diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig index 47e48c18e55c..a8ca9023caf3 100644 --- a/arch/m68k/configs/amiga_defconfig +++ b/arch/m68k/configs/amiga_defconfig @@ -551,7 +551,6 @@ CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m CONFIG_CRYPTO_DRBG_HASH=y -CONFIG_CRYPTO_DRBG_CTR=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig index 161586d611ab..5c6610d9e80a 100644 --- a/arch/m68k/configs/apollo_defconfig +++ b/arch/m68k/configs/apollo_defconfig @@ -506,7 +506,6 @@ CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m CONFIG_CRYPTO_DRBG_HASH=y -CONFIG_CRYPTO_DRBG_CTR=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig index c13c6deeac22..4d080f6f3ddf 100644 --- a/arch/m68k/configs/atari_defconfig +++ b/arch/m68k/configs/atari_defconfig @@ -528,7 +528,6 @@ CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m CONFIG_CRYPTO_DRBG_HASH=y -CONFIG_CRYPTO_DRBG_CTR=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig index d4f3f94b61ff..c61fc9d13d30 100644 --- a/arch/m68k/configs/bvme6000_defconfig +++ b/arch/m68k/configs/bvme6000_defconfig @@ -498,7 +498,6 @@ CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m CONFIG_CRYPTO_DRBG_HASH=y -CONFIG_CRYPTO_DRBG_CTR=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig index 58288f83349d..2bc20cfdfcf6 100644 --- a/arch/m68k/configs/hp300_defconfig +++ b/arch/m68k/configs/hp300_defconfig @@ -508,7 +508,6 @@ CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m CONFIG_CRYPTO_DRBG_HASH=y -CONFIG_CRYPTO_DRBG_CTR=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig index abb369fd1f55..e03877efc7e6 100644 --- a/arch/m68k/configs/mac_defconfig +++ b/arch/m68k/configs/mac_defconfig @@ -527,7 +527,6 @@ CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m CONFIG_CRYPTO_DRBG_HASH=y -CONFIG_CRYPTO_DRBG_CTR=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig index cb8de979700f..d613bfedee8a 100644 --- a/arch/m68k/configs/multi_defconfig +++ b/arch/m68k/configs/multi_defconfig @@ -614,7 +614,6 @@ CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m CONFIG_CRYPTO_DRBG_HASH=y -CONFIG_CRYPTO_DRBG_CTR=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig index 176540bd5074..fe343a8f69f5 100644 --- a/arch/m68k/configs/mvme147_defconfig +++ b/arch/m68k/configs/mvme147_defconfig @@ -498,7 +498,6 @@ CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m CONFIG_CRYPTO_DRBG_HASH=y -CONFIG_CRYPTO_DRBG_CTR=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig index 8b2e5cf4d2f2..c5803f67f30b 100644 --- a/arch/m68k/configs/mvme16x_defconfig +++ b/arch/m68k/configs/mvme16x_defconfig @@ -499,7 +499,6 @@ CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m CONFIG_CRYPTO_DRBG_HASH=y -CONFIG_CRYPTO_DRBG_CTR=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig index d48f3cf5285b..619518c30e0b 100644 --- a/arch/m68k/configs/q40_defconfig +++ b/arch/m68k/configs/q40_defconfig @@ -517,7 +517,6 @@ CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m CONFIG_CRYPTO_DRBG_HASH=y -CONFIG_CRYPTO_DRBG_CTR=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig index 0b96428f25d4..530fa722e3b2 100644 --- a/arch/m68k/configs/sun3_defconfig +++ b/arch/m68k/configs/sun3_defconfig @@ -496,7 +496,6 @@ CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m CONFIG_CRYPTO_DRBG_HASH=y -CONFIG_CRYPTO_DRBG_CTR=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig index 6140e18244a1..f282e05bc8f9 100644 --- a/arch/m68k/configs/sun3x_defconfig +++ b/arch/m68k/configs/sun3x_defconfig @@ -496,7 +496,6 @@ CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m CONFIG_CRYPTO_DRBG_HASH=y -CONFIG_CRYPTO_DRBG_CTR=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/mips/configs/decstation_64_defconfig b/arch/mips/configs/decstation_64_defconfig index 7c43352fac6b..6712143a2842 100644 --- a/arch/mips/configs/decstation_64_defconfig +++ b/arch/mips/configs/decstation_64_defconfig @@ -200,7 +200,6 @@ CONFIG_CRYPTO_842=m CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_DRBG_HASH=y -CONFIG_CRYPTO_DRBG_CTR=y # CONFIG_CRYPTO_HW is not set CONFIG_MAGIC_SYSRQ=y # CONFIG_FTRACE is not set diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig index aee10274f048..1a31bbb99839 100644 --- a/arch/mips/configs/decstation_defconfig +++ b/arch/mips/configs/decstation_defconfig @@ -195,7 +195,6 @@ CONFIG_CRYPTO_842=m CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_DRBG_HASH=y -CONFIG_CRYPTO_DRBG_CTR=y # CONFIG_CRYPTO_HW is not set CONFIG_FRAME_WARN=2048 CONFIG_MAGIC_SYSRQ=y diff --git a/arch/mips/configs/decstation_r4k_defconfig b/arch/mips/configs/decstation_r4k_defconfig index a1698049aa7a..8ff71ca43bfb 100644 --- a/arch/mips/configs/decstation_r4k_defconfig +++ b/arch/mips/configs/decstation_r4k_defconfig @@ -195,7 +195,6 @@ CONFIG_CRYPTO_842=m CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_DRBG_HASH=y -CONFIG_CRYPTO_DRBG_CTR=y # CONFIG_CRYPTO_HW is not set CONFIG_FRAME_WARN=2048 CONFIG_MAGIC_SYSRQ=y diff --git a/crypto/Kconfig b/crypto/Kconfig index 34da01c153d6..b16a1aa95c46 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1130,14 +1130,6 @@ config CRYPTO_DRBG_HASH This uses the SHA-1, SHA-256, SHA-384, or SHA-512 hash algorithms. -config CRYPTO_DRBG_CTR - bool "CTR_DRBG" - select CRYPTO_DF80090A - help - CTR_DRBG variant as defined in NIST SP800-90A. - - This uses the AES cipher algorithm with the counter block mode. - config CRYPTO_DRBG tristate default CRYPTO_DRBG_MENU diff --git a/crypto/drbg.c b/crypto/drbg.c index 9dedc6186b42..b29090bb59bc 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -2,7 +2,6 @@ * DRBG: Deterministic Random Bits Generator * Based on NIST Recommended DRBG from NIST SP800-90A with the following * properties: - * * CTR DRBG with DF with AES-128, AES-192, AES-256 cores * * Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores * * HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores * * with and without prediction resistance @@ -92,17 +91,14 @@ * Just mix both scenarios above. */ -#include #include #include #include -#include #include #include #include #include #include -#include #include #include @@ -139,7 +135,7 @@ struct drbg_state { struct mutex drbg_mutex; /* lock around DRBG */ unsigned char *V; /* internal state 10.1.1.1 1a) */ unsigned char *Vbuf; - /* hash: static value 10.1.1.1 1b) hmac / ctr: key */ + /* hash: static value 10.1.1.1 1b) hmac: key */ unsigned char *C; unsigned char *Cbuf; /* Number of RNG requests since last reseed -- 10.1.1.1 1c) */ @@ -150,13 +146,6 @@ struct drbg_state { unsigned char *scratchpadbuf; void *priv_data; /* Cipher handle */ - struct crypto_skcipher *ctr_handle; /* CTR mode cipher handle */ - struct skcipher_request *ctr_req; /* CTR mode request handle */ - __u8 *outscratchpadbuf; /* CTR mode output scratchpad */ - __u8 *outscratchpad; /* CTR mode aligned outbuf */ - struct crypto_wait ctr_wait; /* CTR mode async wait obj */ - struct scatterlist sg_in, sg_out; /* CTR mode SGLs */ - enum drbg_seed_state seeded; /* DRBG fully seeded? */ unsigned long last_seed_time; bool pr; /* Prediction resistance enabled? */ @@ -180,13 +169,6 @@ static inline __u8 drbg_blocklen(struct drbg_state *drbg) return 0; } -static inline __u8 drbg_keylen(struct drbg_state *drbg) -{ - if (drbg && drbg->core) - return (drbg->core->statelen - drbg->core->blocklen_bytes); - return 0; -} - static inline size_t drbg_max_request_bytes(struct drbg_state *drbg) { /* SP800-90A requires the limit 2**19 bits, but we return bytes */ @@ -211,10 +193,9 @@ static inline size_t drbg_max_requests(struct drbg_state *drbg) } /* DRBG type flags */ -#define DRBG_CTR ((drbg_flag_t)1<<0) #define DRBG_HMAC ((drbg_flag_t)1<<1) #define DRBG_HASH ((drbg_flag_t)1<<2) -#define DRBG_TYPE_MASK (DRBG_CTR | DRBG_HMAC | DRBG_HASH) +#define DRBG_TYPE_MASK (DRBG_HMAC | DRBG_HASH) /* DRBG strength flags */ #define DRBG_STRENGTH128 ((drbg_flag_t)1<<3) #define DRBG_STRENGTH192 ((drbg_flag_t)1<<4) @@ -238,32 +219,9 @@ enum drbg_prefixes { * as stdrng. Each DRBG receives an increasing cra_priority values the later * they are defined in this array (see drbg_fill_array). * - * HMAC DRBGs are favored over Hash DRBGs over CTR DRBGs, and the - * HMAC-SHA512 / SHA256 / AES 256 over other ciphers. Thus, the - * favored DRBGs are the latest entries in this array. + * Thus, the favored DRBGs are the latest entries in this array. */ static const struct drbg_core drbg_cores[] = { -#ifdef CONFIG_CRYPTO_DRBG_CTR - { - .flags = DRBG_CTR | DRBG_STRENGTH128, - .statelen = 32, /* 256 bits as defined in 10.2.1 */ - .blocklen_bytes = 16, - .cra_name = "ctr_aes128", - .backend_cra_name = "aes", - }, { - .flags = DRBG_CTR | DRBG_STRENGTH192, - .statelen = 40, /* 320 bits as defined in 10.2.1 */ - .blocklen_bytes = 16, - .cra_name = "ctr_aes192", - .backend_cra_name = "aes", - }, { - .flags = DRBG_CTR | DRBG_STRENGTH256, - .statelen = 48, /* 384 bits as defined in 10.2.1 */ - .blocklen_bytes = 16, - .cra_name = "ctr_aes256", - .backend_cra_name = "aes", - }, -#endif /* CONFIG_CRYPTO_DRBG_CTR */ #ifdef CONFIG_CRYPTO_DRBG_HASH { .flags = DRBG_HASH | DRBG_STRENGTH256, @@ -334,147 +292,6 @@ static inline unsigned short drbg_sec_strength(drbg_flag_t flags) } } -/****************************************************************** - * CTR DRBG callback functions - ******************************************************************/ - -#ifdef CONFIG_CRYPTO_DRBG_CTR -#define CRYPTO_DRBG_CTR_STRING "CTR " -MODULE_ALIAS_CRYPTO("drbg_pr_ctr_aes256"); -MODULE_ALIAS_CRYPTO("drbg_nopr_ctr_aes256"); -MODULE_ALIAS_CRYPTO("drbg_pr_ctr_aes192"); -MODULE_ALIAS_CRYPTO("drbg_nopr_ctr_aes192"); -MODULE_ALIAS_CRYPTO("drbg_pr_ctr_aes128"); -MODULE_ALIAS_CRYPTO("drbg_nopr_ctr_aes128"); - -static int drbg_init_sym_kernel(struct drbg_state *drbg); -static int drbg_fini_sym_kernel(struct drbg_state *drbg); -static int drbg_kcapi_sym_ctr(struct drbg_state *drbg, - u8 *inbuf, u32 inbuflen, - u8 *outbuf, u32 outlen); -#define DRBG_OUTSCRATCHLEN 256 - -static int drbg_ctr_df(struct drbg_state *drbg, - unsigned char *df_data, size_t bytes_to_return, - struct list_head *seedlist) -{ - return crypto_drbg_ctr_df(drbg->priv_data, df_data, drbg_statelen(drbg), - seedlist, drbg_blocklen(drbg), drbg_statelen(drbg)); -} - -/* - * update function of CTR DRBG as defined in 10.2.1.2 - * - * The reseed variable has an enhanced meaning compared to the update - * functions of the other DRBGs as follows: - * 0 => initial seed from initialization - * 1 => reseed via drbg_seed - * 2 => first invocation from drbg_ctr_update when addtl is present. In - * this case, the df_data scratchpad is not deleted so that it is - * available for another calls to prevent calling the DF function - * again. - * 3 => second invocation from drbg_ctr_update. When the update function - * was called with addtl, the df_data memory already contains the - * DFed addtl information and we do not need to call DF again. - */ -static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed, - int reseed) -{ - int ret = -EFAULT; - /* 10.2.1.2 step 1 */ - unsigned char *temp = drbg->scratchpad; - unsigned char *df_data = drbg->scratchpad + drbg_statelen(drbg) + - drbg_blocklen(drbg); - - if (3 > reseed) - memset(df_data, 0, drbg_statelen(drbg)); - - if (!reseed) { - /* - * The DRBG uses the CTR mode of the underlying AES cipher. The - * CTR mode increments the counter value after the AES operation - * but SP800-90A requires that the counter is incremented before - * the AES operation. Hence, we increment it at the time we set - * it by one. - */ - crypto_inc(drbg->V, drbg_blocklen(drbg)); - - ret = crypto_skcipher_setkey(drbg->ctr_handle, drbg->C, - drbg_keylen(drbg)); - if (ret) - goto out; - } - - /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */ - if (seed) { - ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg), seed); - if (ret) - goto out; - } - - ret = drbg_kcapi_sym_ctr(drbg, df_data, drbg_statelen(drbg), - temp, drbg_statelen(drbg)); - if (ret) - return ret; - - /* 10.2.1.2 step 5 */ - ret = crypto_skcipher_setkey(drbg->ctr_handle, temp, - drbg_keylen(drbg)); - if (ret) - goto out; - /* 10.2.1.2 step 6 */ - memcpy(drbg->V, temp + drbg_keylen(drbg), drbg_blocklen(drbg)); - /* See above: increment counter by one to compensate timing of CTR op */ - crypto_inc(drbg->V, drbg_blocklen(drbg)); - ret = 0; - -out: - memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg)); - if (2 != reseed) - memset(df_data, 0, drbg_statelen(drbg)); - return ret; -} - -/* - * scratchpad use: drbg_ctr_update is called independently from - * drbg_ctr_extract_bytes. Therefore, the scratchpad is reused - */ -/* Generate function of CTR DRBG as defined in 10.2.1.5.2 */ -static int drbg_ctr_generate(struct drbg_state *drbg, - unsigned char *buf, unsigned int buflen, - struct list_head *addtl) -{ - int ret; - int len = min_t(int, buflen, INT_MAX); - - /* 10.2.1.5.2 step 2 */ - if (addtl && !list_empty(addtl)) { - ret = drbg_ctr_update(drbg, addtl, 2); - if (ret) - return ret; - } - - /* 10.2.1.5.2 step 4.1 */ - ret = drbg_kcapi_sym_ctr(drbg, NULL, 0, buf, len); - if (ret) - return ret; - - /* 10.2.1.5.2 step 6 */ - ret = drbg_ctr_update(drbg, NULL, 3); - if (ret) - len = ret; - - return len; -} - -static const struct drbg_state_ops drbg_ctr_ops = { - .update = drbg_ctr_update, - .generate = drbg_ctr_generate, - .crypto_init = drbg_init_sym_kernel, - .crypto_fini = drbg_fini_sym_kernel, -}; -#endif /* CONFIG_CRYPTO_DRBG_CTR */ - /****************************************************************** * HMAC DRBG callback functions ******************************************************************/ @@ -1108,11 +925,6 @@ static inline int drbg_alloc_state(struct drbg_state *drbg) drbg->d_ops = &drbg_hash_ops; break; #endif /* CONFIG_CRYPTO_DRBG_HASH */ -#ifdef CONFIG_CRYPTO_DRBG_CTR - case DRBG_CTR: - drbg->d_ops = &drbg_ctr_ops; - break; -#endif /* CONFIG_CRYPTO_DRBG_CTR */ default: ret = -EOPNOTSUPP; goto err; @@ -1134,13 +946,9 @@ static inline int drbg_alloc_state(struct drbg_state *drbg) goto fini; } drbg->C = PTR_ALIGN(drbg->Cbuf, ret + 1); - /* scratchpad is only generated for CTR and Hash */ + /* scratchpad is only generated for Hash */ if (drbg->core->flags & DRBG_HMAC) sb_size = 0; - else if (drbg->core->flags & DRBG_CTR) - sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg) + /* temp */ - crypto_drbg_ctr_df_datalen(drbg_statelen(drbg), - drbg_blocklen(drbg)); else sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg); @@ -1253,7 +1061,7 @@ static int drbg_generate(struct drbg_state *drbg, /* 9.3.1 step 8 and 10 */ len = drbg->d_ops->generate(drbg, buf, buflen, &addtllist); - /* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */ + /* 10.1.1.4 step 6, 10.1.2.5 step 7 */ drbg->reseed_ctr++; if (0 >= len) goto err; @@ -1504,127 +1312,6 @@ static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval, return crypto_shash_final(&sdesc->shash, outval); } -#ifdef CONFIG_CRYPTO_DRBG_CTR -static int drbg_fini_sym_kernel(struct drbg_state *drbg) -{ - struct aes_enckey *aeskey = drbg->priv_data; - - kfree(aeskey); - drbg->priv_data = NULL; - - if (drbg->ctr_handle) - crypto_free_skcipher(drbg->ctr_handle); - drbg->ctr_handle = NULL; - - if (drbg->ctr_req) - skcipher_request_free(drbg->ctr_req); - drbg->ctr_req = NULL; - - kfree(drbg->outscratchpadbuf); - drbg->outscratchpadbuf = NULL; - - return 0; -} - -static int drbg_init_sym_kernel(struct drbg_state *drbg) -{ - struct aes_enckey *aeskey; - struct crypto_skcipher *sk_tfm; - struct skcipher_request *req; - unsigned int alignmask; - char ctr_name[CRYPTO_MAX_ALG_NAME]; - - aeskey = kzalloc_obj(*aeskey); - if (!aeskey) - return -ENOMEM; - drbg->priv_data = aeskey; - - if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)", - drbg->core->backend_cra_name) >= CRYPTO_MAX_ALG_NAME) { - drbg_fini_sym_kernel(drbg); - return -EINVAL; - } - sk_tfm = crypto_alloc_skcipher(ctr_name, 0, 0); - if (IS_ERR(sk_tfm)) { - pr_info("DRBG: could not allocate CTR cipher TFM handle: %s\n", - ctr_name); - drbg_fini_sym_kernel(drbg); - return PTR_ERR(sk_tfm); - } - drbg->ctr_handle = sk_tfm; - crypto_init_wait(&drbg->ctr_wait); - - req = skcipher_request_alloc(sk_tfm, GFP_KERNEL); - if (!req) { - pr_info("DRBG: could not allocate request queue\n"); - drbg_fini_sym_kernel(drbg); - return -ENOMEM; - } - drbg->ctr_req = req; - skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | - CRYPTO_TFM_REQ_MAY_SLEEP, - crypto_req_done, &drbg->ctr_wait); - - alignmask = crypto_skcipher_alignmask(sk_tfm); - drbg->outscratchpadbuf = kmalloc(DRBG_OUTSCRATCHLEN + alignmask, - GFP_KERNEL); - if (!drbg->outscratchpadbuf) { - drbg_fini_sym_kernel(drbg); - return -ENOMEM; - } - drbg->outscratchpad = (u8 *)PTR_ALIGN(drbg->outscratchpadbuf, - alignmask + 1); - - sg_init_table(&drbg->sg_in, 1); - sg_init_one(&drbg->sg_out, drbg->outscratchpad, DRBG_OUTSCRATCHLEN); - - return alignmask; -} - -static int drbg_kcapi_sym_ctr(struct drbg_state *drbg, - u8 *inbuf, u32 inlen, - u8 *outbuf, u32 outlen) -{ - struct scatterlist *sg_in = &drbg->sg_in, *sg_out = &drbg->sg_out; - u32 scratchpad_use = min_t(u32, outlen, DRBG_OUTSCRATCHLEN); - int ret; - - if (inbuf) { - /* Use caller-provided input buffer */ - sg_set_buf(sg_in, inbuf, inlen); - } else { - /* Use scratchpad for in-place operation */ - inlen = scratchpad_use; - memset(drbg->outscratchpad, 0, scratchpad_use); - sg_set_buf(sg_in, drbg->outscratchpad, scratchpad_use); - } - - while (outlen) { - u32 cryptlen = min3(inlen, outlen, (u32)DRBG_OUTSCRATCHLEN); - - /* Output buffer may not be valid for SGL, use scratchpad */ - skcipher_request_set_crypt(drbg->ctr_req, sg_in, sg_out, - cryptlen, drbg->V); - ret = crypto_wait_req(crypto_skcipher_encrypt(drbg->ctr_req), - &drbg->ctr_wait); - if (ret) - goto out; - - crypto_init_wait(&drbg->ctr_wait); - - memcpy(outbuf, drbg->outscratchpad, cryptlen); - memzero_explicit(drbg->outscratchpad, cryptlen); - - outlen -= cryptlen; - outbuf += cryptlen; - } - ret = 0; - -out: - return ret; -} -#endif /* CONFIG_CRYPTO_DRBG_CTR */ - /*************************************************************** * Kernel crypto API interface to register DRBG ***************************************************************/ @@ -1762,9 +1449,6 @@ static inline int __init drbg_healthcheck_sanity(void) if (!fips_enabled) return 0; -#ifdef CONFIG_CRYPTO_DRBG_CTR - drbg_convert_tfm_core("drbg_nopr_ctr_aes256", &coreref, &pr); -#endif #ifdef CONFIG_CRYPTO_DRBG_HASH drbg_convert_tfm_core("drbg_nopr_sha256", &coreref, &pr); #endif @@ -1896,14 +1580,10 @@ module_exit(drbg_exit); #ifndef CRYPTO_DRBG_HASH_STRING #define CRYPTO_DRBG_HASH_STRING "" #endif -#ifndef CRYPTO_DRBG_CTR_STRING -#define CRYPTO_DRBG_CTR_STRING "" -#endif MODULE_LICENSE("GPL"); MODULE_AUTHOR("Stephan Mueller "); MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG) " "using following cores: " CRYPTO_DRBG_HASH_STRING - CRYPTO_DRBG_HMAC_STRING - CRYPTO_DRBG_CTR_STRING); + CRYPTO_DRBG_HMAC_STRING); MODULE_ALIAS_CRYPTO("stdrng"); diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 480368a41cc0..dbc1e1fb4bd0 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -4638,27 +4638,6 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "digest_null", .test = alg_test_null, - }, { - .alg = "drbg_nopr_ctr_aes128", - .test = alg_test_drbg, - .fips_allowed = 1, - .suite = { - .drbg = __VECS(drbg_nopr_ctr_aes128_tv_template) - } - }, { - .alg = "drbg_nopr_ctr_aes192", - .test = alg_test_drbg, - .fips_allowed = 1, - .suite = { - .drbg = __VECS(drbg_nopr_ctr_aes192_tv_template) - } - }, { - .alg = "drbg_nopr_ctr_aes256", - .test = alg_test_drbg, - .fips_allowed = 1, - .suite = { - .drbg = __VECS(drbg_nopr_ctr_aes256_tv_template) - } }, { .alg = "drbg_nopr_hmac_sha256", .test = alg_test_drbg, @@ -4697,22 +4676,6 @@ static const struct alg_test_desc alg_test_descs[] = { .alg = "drbg_nopr_sha512", .fips_allowed = 1, .test = alg_test_null, - }, { - .alg = "drbg_pr_ctr_aes128", - .test = alg_test_drbg, - .fips_allowed = 1, - .suite = { - .drbg = __VECS(drbg_pr_ctr_aes128_tv_template) - } - }, { - /* covered by drbg_pr_ctr_aes128 test */ - .alg = "drbg_pr_ctr_aes192", - .fips_allowed = 1, - .test = alg_test_null, - }, { - .alg = "drbg_pr_ctr_aes256", - .fips_allowed = 1, - .test = alg_test_null, }, { .alg = "drbg_pr_hmac_sha256", .test = alg_test_drbg, diff --git a/crypto/testmgr.h b/crypto/testmgr.h index 9b4d7e11c9fd..a86275b61b6a 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -23746,122 +23746,6 @@ static const struct drbg_testvec drbg_pr_hmac_sha256_tv_template[] = { }, }; -static const struct drbg_testvec drbg_pr_ctr_aes128_tv_template[] = { - { - .entropy = (unsigned char *) - "\xd1\x44\xc6\x61\x81\x6d\xca\x9d\x15\x28\x8a\x42" - "\x94\xd7\x28\x9c\x43\x77\x19\x29\x1a\x6d\xc3\xa2", - .entropylen = 24, - .entpra = (unsigned char *) - "\x96\xd8\x9e\x45\x32\xc9\xd2\x08\x7a\x6d\x97\x15" - "\xb4\xec\x80\xb1", - .entprb = (unsigned char *) - "\x8b\xb6\x72\xb5\x24\x0b\x98\x65\x95\x95\xe9\xc9" - "\x28\x07\xeb\xc2", - .entprlen = 16, - .expected = (unsigned char *) - "\x70\x19\xd0\x4c\x45\x78\xd6\x68\xa9\x9a\xaa\xfe" - "\xc1\xdf\x27\x9a\x1c\x0d\x0d\xf7\x24\x75\x46\xcc" - "\x77\x6b\xdf\x89\xc6\x94\xdc\x74\x50\x10\x70\x18" - "\x9b\xdc\x96\xb4\x89\x23\x40\x1a\xce\x09\x87\xce" - "\xd2\xf3\xd5\xe4\x51\x67\x74\x11\x5a\xcc\x8b\x3b" - "\x8a\xf1\x23\xa8", - .expectedlen = 64, - .addtla = NULL, - .addtlb = NULL, - .addtllen = 0, - .pers = NULL, - .perslen = 0, - }, { - .entropy = (unsigned char *) - "\x8e\x83\xe0\xeb\x37\xea\x3e\x53\x5e\x17\x6e\x77" - "\xbd\xb1\x53\x90\xfc\xdc\xc1\x3c\x9a\x88\x22\x94", - .entropylen = 24, - .entpra = (unsigned char *) - "\x6a\x85\xe7\x37\xc8\xf1\x04\x31\x98\x4f\xc8\x73" - "\x67\xd1\x08\xf8", - .entprb = (unsigned char *) - "\xd7\xa4\x68\xe2\x12\x74\xc3\xd9\xf1\xb7\x05\xbc" - "\xd4\xba\x04\x58", - .entprlen = 16, - .expected = (unsigned char *) - "\x78\xd6\xa6\x70\xff\xd1\x82\xf5\xa2\x88\x7f\x6d" - "\x3d\x8c\x39\xb1\xa8\xcb\x2c\x91\xab\x14\x7e\xbc" - "\x95\x45\x9f\x24\xb8\x20\xac\x21\x23\xdb\x72\xd7" - "\x12\x8d\x48\x95\xf3\x19\x0c\x43\xc6\x19\x45\xfc" - "\x8b\xac\x40\x29\x73\x00\x03\x45\x5e\x12\xff\x0c" - "\xc1\x02\x41\x82", - .expectedlen = 64, - .addtla = (unsigned char *) - "\xa2\xd9\x38\xcf\x8b\x29\x67\x5b\x65\x62\x6f\xe8" - "\xeb\xb3\x01\x76", - .addtlb = (unsigned char *) - "\x59\x63\x1e\x81\x8a\x14\xa8\xbb\xa1\xb8\x41\x25" - "\xd0\x7f\xcc\x43", - .addtllen = 16, - .pers = NULL, - .perslen = 0, - }, { - .entropy = (unsigned char *) - "\x04\xd9\x49\xa6\xdc\xe8\x6e\xbb\xf1\x08\x77\x2b" - "\x9e\x08\xca\x92\x65\x16\xda\x99\xa2\x59\xf3\xe8", - .entropylen = 24, - .entpra = (unsigned char *) - "\x38\x7e\x3f\x6b\x51\x70\x7b\x20\xec\x53\xd0\x66" - "\xc3\x0f\xe3\xb0", - .entprb = (unsigned char *) - "\xe0\x86\xa6\xaa\x5f\x72\x2f\xad\xf7\xef\x06\xb8" - "\xd6\x9c\x9d\xe8", - .entprlen = 16, - .expected = (unsigned char *) - "\xc9\x0a\xaf\x85\x89\x71\x44\x66\x4f\x25\x0b\x2b" - "\xde\xd8\xfa\xff\x52\x5a\x1b\x32\x5e\x41\x7a\x10" - "\x1f\xef\x1e\x62\x23\xe9\x20\x30\xc9\x0d\xad\x69" - "\xb4\x9c\x5b\xf4\x87\x42\xd5\xae\x5e\x5e\x43\xcc" - "\xd9\xfd\x0b\x93\x4a\xe3\xd4\x06\x37\x36\x0f\x3f" - "\x72\x82\x0c\xcf", - .expectedlen = 64, - .addtla = NULL, - .addtlb = NULL, - .addtllen = 0, - .pers = (unsigned char *) - "\xbf\xa4\x9a\x8f\x7b\xd8\xb1\x7a\x9d\xfa\x45\xed" - "\x21\x52\xb3\xad", - .perslen = 16, - }, { - .entropy = (unsigned char *) - "\x92\x89\x8f\x31\xfa\x1c\xff\x6d\x18\x2f\x26\x06" - "\x43\xdf\xf8\x18\xc2\xa4\xd9\x72\xc3\xb9\xb6\x97", - .entropylen = 24, - .entpra = (unsigned char *) - "\x20\x72\x8a\x06\xf8\x6f\x8d\xd4\x41\xe2\x72\xb7" - "\xc4\x2c\xe8\x10", - .entprb = (unsigned char *) - "\x3d\xb0\xf0\x94\xf3\x05\x50\x33\x17\x86\x3e\x22" - "\x08\xf7\xa5\x01", - .entprlen = 16, - .expected = (unsigned char *) - "\x5a\x35\x39\x87\x0f\x4d\x22\xa4\x09\x24\xee\x71" - "\xc9\x6f\xac\x72\x0a\xd6\xf0\x88\x82\xd0\x83\x28" - "\x73\xec\x3f\x93\xd8\xab\x45\x23\xf0\x7e\xac\x45" - "\x14\x5e\x93\x9f\xb1\xd6\x76\x43\x3d\xb6\xe8\x08" - "\x88\xf6\xda\x89\x08\x77\x42\xfe\x1a\xf4\x3f\xc4" - "\x23\xc5\x1f\x68", - .expectedlen = 64, - .addtla = (unsigned char *) - "\x1a\x40\xfa\xe3\xcc\x6c\x7c\xa0\xf8\xda\xba\x59" - "\x23\x6d\xad\x1d", - .addtlb = (unsigned char *) - "\x9f\x72\x76\x6c\xc7\x46\xe5\xed\x2e\x53\x20\x12" - "\xbc\x59\x31\x8c", - .addtllen = 16, - .pers = (unsigned char *) - "\xea\x65\xee\x60\x26\x4e\x7e\xb6\x0e\x82\x68\xc4" - "\x37\x3c\x5c\x0b", - .perslen = 16, - }, -}; - /* * SP800-90A DRBG Test vectors from * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip @@ -24163,142 +24047,6 @@ static const struct drbg_testvec drbg_nopr_hmac_sha512_tv_template[] = { } }; -static const struct drbg_testvec drbg_nopr_ctr_aes192_tv_template[] = { - { - .entropy = (unsigned char *) - "\xc3\x5c\x2f\xa2\xa8\x9d\x52\xa1\x1f\xa3\x2a\xa9" - "\x6c\x95\xb8\xf1\xc9\xa8\xf9\xcb\x24\x5a\x8b\x40" - "\xf3\xa6\xe5\xa7\xfb\xd9\xd3\xc6\x8e\x27\x7b\xa9" - "\xac\x9b\xbb\x00", - .entropylen = 40, - .expected = (unsigned char *) - "\x8c\x2e\x72\xab\xfd\x9b\xb8\x28\x4d\xb7\x9e\x17" - "\xa4\x3a\x31\x46\xcd\x76\x94\xe3\x52\x49\xfc\x33" - "\x83\x91\x4a\x71\x17\xf4\x13\x68\xe6\xd4\xf1\x48" - "\xff\x49\xbf\x29\x07\x6b\x50\x15\xc5\x9f\x45\x79" - "\x45\x66\x2e\x3d\x35\x03\x84\x3f\x4a\xa5\xa3\xdf" - "\x9a\x9d\xf1\x0d", - .expectedlen = 64, - .addtla = NULL, - .addtlb = NULL, - .addtllen = 0, - .pers = NULL, - .perslen = 0, - }, -}; - -static const struct drbg_testvec drbg_nopr_ctr_aes256_tv_template[] = { - { - .entropy = (unsigned char *) - "\x36\x40\x19\x40\xfa\x8b\x1f\xba\x91\xa1\x66\x1f" - "\x21\x1d\x78\xa0\xb9\x38\x9a\x74\xe5\xbc\xcf\xec" - "\xe8\xd7\x66\xaf\x1a\x6d\x3b\x14\x49\x6f\x25\xb0" - "\xf1\x30\x1b\x4f\x50\x1b\xe3\x03\x80\xa1\x37\xeb", - .entropylen = 48, - .expected = (unsigned char *) - "\x58\x62\xeb\x38\xbd\x55\x8d\xd9\x78\xa6\x96\xe6" - "\xdf\x16\x47\x82\xdd\xd8\x87\xe7\xe9\xa6\xc9\xf3" - "\xf1\xfb\xaf\xb7\x89\x41\xb5\x35\xa6\x49\x12\xdf" - "\xd2\x24\xc6\xdc\x74\x54\xe5\x25\x0b\x3d\x97\x16" - "\x5e\x16\x26\x0c\x2f\xaf\x1c\xc7\x73\x5c\xb7\x5f" - "\xb4\xf0\x7e\x1d", - .expectedlen = 64, - .addtla = NULL, - .addtlb = NULL, - .addtllen = 0, - .pers = NULL, - .perslen = 0, - }, -}; - -static const struct drbg_testvec drbg_nopr_ctr_aes128_tv_template[] = { - { - .entropy = (unsigned char *) - "\x87\xe1\xc5\x32\x99\x7f\x57\xa3\x5c\x28\x6d\xe8" - "\x64\xbf\xf2\x64\xa3\x9e\x98\xdb\x6c\x10\x78\x7f", - .entropylen = 24, - .expected = (unsigned char *) - "\x2c\x14\x7e\x24\x11\x9a\xd8\xd4\xb2\xed\x61\xc1" - "\x53\xd0\x50\xc9\x24\xff\x59\x75\x15\xf1\x17\x3a" - "\x3d\xf4\x4b\x2c\x84\x28\xef\x89\x0e\xb9\xde\xf3" - "\xe4\x78\x04\xb2\xfd\x9b\x35\x7f\xe1\x3f\x8a\x3e" - "\x10\xc8\x67\x0a\xf9\xdf\x2d\x6c\x96\xfb\xb2\xb8" - "\xcb\x2d\xd6\xb0", - .expectedlen = 64, - .addtla = NULL, - .addtlb = NULL, - .addtllen = 0, - .pers = NULL, - .perslen = 0, - }, { - .entropy = (unsigned char *) - "\x71\xbd\xce\x35\x42\x7d\x20\xbf\x58\xcf\x17\x74" - "\xce\x72\xd8\x33\x34\x50\x2d\x8f\x5b\x14\xc4\xdd", - .entropylen = 24, - .expected = (unsigned char *) - "\x97\x33\xe8\x20\x12\xe2\x7b\xa1\x46\x8f\xf2\x34" - "\xb3\xc9\xb6\x6b\x20\xb2\x4f\xee\x27\xd8\x0b\x21" - "\x8c\xff\x63\x73\x69\x29\xfb\xf3\x85\xcd\x88\x8e" - "\x43\x2c\x71\x8b\xa2\x55\xd2\x0f\x1d\x7f\xe3\xe1" - "\x2a\xa3\xe9\x2c\x25\x89\xc7\x14\x52\x99\x56\xcc" - "\xc3\xdf\xb3\x81", - .expectedlen = 64, - .addtla = (unsigned char *) - "\x66\xef\x42\xd6\x9a\x8c\x3d\x6d\x4a\x9e\x95\xa6" - "\x91\x4d\x81\x56", - .addtlb = (unsigned char *) - "\xe3\x18\x83\xd9\x4b\x5e\xc4\xcc\xaa\x61\x2f\xbb" - "\x4a\x55\xd1\xc6", - .addtllen = 16, - .pers = NULL, - .perslen = 0, - }, { - .entropy = (unsigned char *) - "\xca\x4b\x1e\xfa\x75\xbd\x69\x36\x38\x73\xb8\xf9" - "\xdb\x4d\x35\x0e\x47\xbf\x6c\x37\x72\xfd\xf7\xa9", - .entropylen = 24, - .expected = (unsigned char *) - "\x59\xc3\x19\x79\x1b\xb1\xf3\x0e\xe9\x34\xae\x6e" - "\x8b\x1f\xad\x1f\x74\xca\x25\x45\x68\xb8\x7f\x75" - "\x12\xf8\xf2\xab\x4c\x23\x01\x03\x05\xe1\x70\xee" - "\x75\xd8\xcb\xeb\x23\x4c\x7a\x23\x6e\x12\x27\xdb" - "\x6f\x7a\xac\x3c\x44\xb7\x87\x4b\x65\x56\x74\x45" - "\x34\x30\x0c\x3d", - .expectedlen = 64, - .addtla = NULL, - .addtlb = NULL, - .addtllen = 0, - .pers = (unsigned char *) - "\xeb\xaa\x60\x2c\x4d\xbe\x33\xff\x1b\xef\xbf\x0a" - "\x0b\xc6\x97\x54", - .perslen = 16, - }, { - .entropy = (unsigned char *) - "\xc0\x70\x1f\x92\x50\x75\x8f\xcd\xf2\xbe\x73\x98" - "\x80\xdb\x66\xeb\x14\x68\xb4\xa5\x87\x9c\x2d\xa6", - .entropylen = 24, - .expected = (unsigned char *) - "\x97\xc0\xc0\xe5\xa0\xcc\xf2\x4f\x33\x63\x48\x8a" - "\xdb\x13\x0a\x35\x89\xbf\x80\x65\x62\xee\x13\x95" - "\x7c\x33\xd3\x7d\xf4\x07\x77\x7a\x2b\x65\x0b\x5f" - "\x45\x5c\x13\xf1\x90\x77\x7f\xc5\x04\x3f\xcc\x1a" - "\x38\xf8\xcd\x1b\xbb\xd5\x57\xd1\x4a\x4c\x2e\x8a" - "\x2b\x49\x1e\x5c", - .expectedlen = 64, - .addtla = (unsigned char *) - "\xf9\x01\xf8\x16\x7a\x1d\xff\xde\x8e\x3c\x83\xe2" - "\x44\x85\xe7\xfe", - .addtlb = (unsigned char *) - "\x17\x1c\x09\x38\xc2\x38\x9f\x97\x87\x60\x55\xb4" - "\x82\x16\x62\x7f", - .addtllen = 16, - .pers = (unsigned char *) - "\x80\x08\xae\xe8\xe9\x69\x40\xc5\x08\x73\xc7\x9f" - "\x8e\xcf\xe0\x02", - .perslen = 16, - }, -}; - /* Cast5 test vectors from RFC 2144 */ static const struct cipher_testvec cast5_tv_template[] = { { diff --git a/include/crypto/internal/drbg.h b/include/crypto/internal/drbg.h index b4e5ef0be602..5d4174cc6a53 100644 --- a/include/crypto/internal/drbg.h +++ b/include/crypto/internal/drbg.h @@ -9,6 +9,9 @@ #ifndef _INTERNAL_DRBG_H #define _INTERNAL_DRBG_H +#include +#include + /* * Concatenation Helper and string operation helper * From e227be3ffde0ec8063c9967062a43237a5545581 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:33:57 -0700 Subject: [PATCH 024/196] crypto: drbg - Remove support for HASH_DRBG Remove the support for HASH_DRBG. It's likely unused code, seeing as HMAC_DRBG is always enabled and prioritized over it unless NETLINK_CRYPTO is used to change the algorithm priorities. There's also no compelling reason to support more than one of [HMAC_DRBG, HASH_DRBG, CTR_DRBG]. By definition, callers cannot tell any difference in their outputs. And all are FIPS-certifiable, which is the only point of the kernel's NIST DRBGs anyway. Switching to HASH_DRBG doesn't seem all that compelling, either. For one, it's more complex than HMAC_DRBG. Thus, let's just drop HASH_DRBG support and focus on HMAC_DRBG. Signed-off-by: Eric Biggers Acked-by: Geert Uytterhoeven # m68k Signed-off-by: Herbert Xu --- Documentation/crypto/api-samples.rst | 2 +- Documentation/crypto/userspace-if.rst | 2 +- arch/m68k/configs/amiga_defconfig | 1 - arch/m68k/configs/apollo_defconfig | 1 - arch/m68k/configs/atari_defconfig | 1 - arch/m68k/configs/bvme6000_defconfig | 1 - arch/m68k/configs/hp300_defconfig | 1 - arch/m68k/configs/mac_defconfig | 1 - arch/m68k/configs/multi_defconfig | 1 - arch/m68k/configs/mvme147_defconfig | 1 - arch/m68k/configs/mvme16x_defconfig | 1 - arch/m68k/configs/q40_defconfig | 1 - arch/m68k/configs/sun3_defconfig | 1 - arch/m68k/configs/sun3x_defconfig | 1 - arch/mips/configs/decstation_64_defconfig | 1 - arch/mips/configs/decstation_defconfig | 1 - arch/mips/configs/decstation_r4k_defconfig | 1 - crypto/Kconfig | 8 - crypto/drbg.c | 348 +-------------------- crypto/testmgr.c | 32 -- crypto/testmgr.h | 296 ------------------ 21 files changed, 8 insertions(+), 695 deletions(-) diff --git a/Documentation/crypto/api-samples.rst b/Documentation/crypto/api-samples.rst index e923f17bc2bd..388bb7d7a460 100644 --- a/Documentation/crypto/api-samples.rst +++ b/Documentation/crypto/api-samples.rst @@ -159,7 +159,7 @@ Code Example For Random Number Generator Usage static int get_random_numbers(u8 *buf, unsigned int len) { struct crypto_rng *rng = NULL; - char *drbg = "drbg_nopr_sha256"; /* Hash DRBG with SHA-256, no PR */ + char *drbg = "stdrng"; int ret; if (!buf || !len) { diff --git a/Documentation/crypto/userspace-if.rst b/Documentation/crypto/userspace-if.rst index 021759198fe7..a3b13ff83cb3 100644 --- a/Documentation/crypto/userspace-if.rst +++ b/Documentation/crypto/userspace-if.rst @@ -297,7 +297,7 @@ follows: struct sockaddr_alg sa = { .salg_family = AF_ALG, .salg_type = "rng", /* this selects the random number generator */ - .salg_name = "drbg_nopr_sha256" /* this is the RNG name */ + .salg_name = "stdrng" /* this is the RNG name */ }; diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig index a8ca9023caf3..a886494c5a30 100644 --- a/arch/m68k/configs/amiga_defconfig +++ b/arch/m68k/configs/amiga_defconfig @@ -550,7 +550,6 @@ CONFIG_CRYPTO_842=m CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m -CONFIG_CRYPTO_DRBG_HASH=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig index 5c6610d9e80a..14c6298b1175 100644 --- a/arch/m68k/configs/apollo_defconfig +++ b/arch/m68k/configs/apollo_defconfig @@ -505,7 +505,6 @@ CONFIG_CRYPTO_842=m CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m -CONFIG_CRYPTO_DRBG_HASH=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig index 4d080f6f3ddf..86a5c69b3655 100644 --- a/arch/m68k/configs/atari_defconfig +++ b/arch/m68k/configs/atari_defconfig @@ -527,7 +527,6 @@ CONFIG_CRYPTO_842=m CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m -CONFIG_CRYPTO_DRBG_HASH=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig index c61fc9d13d30..b3828dc6ee25 100644 --- a/arch/m68k/configs/bvme6000_defconfig +++ b/arch/m68k/configs/bvme6000_defconfig @@ -497,7 +497,6 @@ CONFIG_CRYPTO_842=m CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m -CONFIG_CRYPTO_DRBG_HASH=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig index 2bc20cfdfcf6..6b890c6bcf35 100644 --- a/arch/m68k/configs/hp300_defconfig +++ b/arch/m68k/configs/hp300_defconfig @@ -507,7 +507,6 @@ CONFIG_CRYPTO_842=m CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m -CONFIG_CRYPTO_DRBG_HASH=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig index e03877efc7e6..1a7694486c08 100644 --- a/arch/m68k/configs/mac_defconfig +++ b/arch/m68k/configs/mac_defconfig @@ -526,7 +526,6 @@ CONFIG_CRYPTO_842=m CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m -CONFIG_CRYPTO_DRBG_HASH=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig index d613bfedee8a..468f0dab58ad 100644 --- a/arch/m68k/configs/multi_defconfig +++ b/arch/m68k/configs/multi_defconfig @@ -613,7 +613,6 @@ CONFIG_CRYPTO_842=m CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m -CONFIG_CRYPTO_DRBG_HASH=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig index fe343a8f69f5..ef6e94e5abcd 100644 --- a/arch/m68k/configs/mvme147_defconfig +++ b/arch/m68k/configs/mvme147_defconfig @@ -497,7 +497,6 @@ CONFIG_CRYPTO_842=m CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m -CONFIG_CRYPTO_DRBG_HASH=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig index c5803f67f30b..cdb8cb030c33 100644 --- a/arch/m68k/configs/mvme16x_defconfig +++ b/arch/m68k/configs/mvme16x_defconfig @@ -498,7 +498,6 @@ CONFIG_CRYPTO_842=m CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m -CONFIG_CRYPTO_DRBG_HASH=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig index 619518c30e0b..a6af67707e9e 100644 --- a/arch/m68k/configs/q40_defconfig +++ b/arch/m68k/configs/q40_defconfig @@ -516,7 +516,6 @@ CONFIG_CRYPTO_842=m CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m -CONFIG_CRYPTO_DRBG_HASH=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig index 530fa722e3b2..1d8233ebb454 100644 --- a/arch/m68k/configs/sun3_defconfig +++ b/arch/m68k/configs/sun3_defconfig @@ -495,7 +495,6 @@ CONFIG_CRYPTO_842=m CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m -CONFIG_CRYPTO_DRBG_HASH=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig index f282e05bc8f9..8366a1d850b0 100644 --- a/arch/m68k/configs/sun3x_defconfig +++ b/arch/m68k/configs/sun3x_defconfig @@ -495,7 +495,6 @@ CONFIG_CRYPTO_842=m CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m -CONFIG_CRYPTO_DRBG_HASH=y CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m diff --git a/arch/mips/configs/decstation_64_defconfig b/arch/mips/configs/decstation_64_defconfig index 6712143a2842..509515cf4751 100644 --- a/arch/mips/configs/decstation_64_defconfig +++ b/arch/mips/configs/decstation_64_defconfig @@ -199,7 +199,6 @@ CONFIG_CRYPTO_LZO=m CONFIG_CRYPTO_842=m CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m -CONFIG_CRYPTO_DRBG_HASH=y # CONFIG_CRYPTO_HW is not set CONFIG_MAGIC_SYSRQ=y # CONFIG_FTRACE is not set diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig index 1a31bbb99839..3a17c080292f 100644 --- a/arch/mips/configs/decstation_defconfig +++ b/arch/mips/configs/decstation_defconfig @@ -194,7 +194,6 @@ CONFIG_CRYPTO_LZO=m CONFIG_CRYPTO_842=m CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m -CONFIG_CRYPTO_DRBG_HASH=y # CONFIG_CRYPTO_HW is not set CONFIG_FRAME_WARN=2048 CONFIG_MAGIC_SYSRQ=y diff --git a/arch/mips/configs/decstation_r4k_defconfig b/arch/mips/configs/decstation_r4k_defconfig index 8ff71ca43bfb..7f5823663702 100644 --- a/arch/mips/configs/decstation_r4k_defconfig +++ b/arch/mips/configs/decstation_r4k_defconfig @@ -194,7 +194,6 @@ CONFIG_CRYPTO_LZO=m CONFIG_CRYPTO_842=m CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m -CONFIG_CRYPTO_DRBG_HASH=y # CONFIG_CRYPTO_HW is not set CONFIG_FRAME_WARN=2048 CONFIG_MAGIC_SYSRQ=y diff --git a/crypto/Kconfig b/crypto/Kconfig index b16a1aa95c46..14519474a67b 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1122,14 +1122,6 @@ menuconfig CRYPTO_DRBG_MENU if CRYPTO_DRBG_MENU -config CRYPTO_DRBG_HASH - bool "Hash_DRBG" - select CRYPTO_SHA256 - help - Hash_DRBG variant as defined in NIST SP800-90A. - - This uses the SHA-1, SHA-256, SHA-384, or SHA-512 hash algorithms. - config CRYPTO_DRBG tristate default CRYPTO_DRBG_MENU diff --git a/crypto/drbg.c b/crypto/drbg.c index b29090bb59bc..6301eb2e304c 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -2,7 +2,6 @@ * DRBG: Deterministic Random Bits Generator * Based on NIST Recommended DRBG from NIST SP800-90A with the following * properties: - * * Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores * * HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores * * with and without prediction resistance * @@ -133,17 +132,13 @@ enum drbg_seed_state { struct drbg_state { struct mutex drbg_mutex; /* lock around DRBG */ - unsigned char *V; /* internal state 10.1.1.1 1a) */ + unsigned char *V; /* internal state -- 10.1.2.1 1a */ unsigned char *Vbuf; - /* hash: static value 10.1.1.1 1b) hmac: key */ - unsigned char *C; + unsigned char *C; /* current key -- 10.1.2.1 1b */ unsigned char *Cbuf; - /* Number of RNG requests since last reseed -- 10.1.1.1 1c) */ + /* Number of RNG requests since last reseed -- 10.1.2.1 1c */ size_t reseed_ctr; size_t reseed_threshold; - /* some memory the DRBG can use for its operation */ - unsigned char *scratchpad; - unsigned char *scratchpadbuf; void *priv_data; /* Cipher handle */ enum drbg_seed_state seeded; /* DRBG fully seeded? */ @@ -194,8 +189,7 @@ static inline size_t drbg_max_requests(struct drbg_state *drbg) /* DRBG type flags */ #define DRBG_HMAC ((drbg_flag_t)1<<1) -#define DRBG_HASH ((drbg_flag_t)1<<2) -#define DRBG_TYPE_MASK (DRBG_HMAC | DRBG_HASH) +#define DRBG_TYPE_MASK DRBG_HMAC /* DRBG strength flags */ #define DRBG_STRENGTH128 ((drbg_flag_t)1<<3) #define DRBG_STRENGTH192 ((drbg_flag_t)1<<4) @@ -206,8 +200,6 @@ static inline size_t drbg_max_requests(struct drbg_state *drbg) enum drbg_prefixes { DRBG_PREFIX0 = 0x00, DRBG_PREFIX1, - DRBG_PREFIX2, - DRBG_PREFIX3 }; /*************************************************************** @@ -222,27 +214,6 @@ enum drbg_prefixes { * Thus, the favored DRBGs are the latest entries in this array. */ static const struct drbg_core drbg_cores[] = { -#ifdef CONFIG_CRYPTO_DRBG_HASH - { - .flags = DRBG_HASH | DRBG_STRENGTH256, - .statelen = 111, /* 888 bits */ - .blocklen_bytes = 48, - .cra_name = "sha384", - .backend_cra_name = "sha384", - }, { - .flags = DRBG_HASH | DRBG_STRENGTH256, - .statelen = 111, /* 888 bits */ - .blocklen_bytes = 64, - .cra_name = "sha512", - .backend_cra_name = "sha512", - }, { - .flags = DRBG_HASH | DRBG_STRENGTH256, - .statelen = 55, /* 440 bits */ - .blocklen_bytes = 32, - .cra_name = "sha256", - .backend_cra_name = "sha256", - }, -#endif /* CONFIG_CRYPTO_DRBG_HASH */ { .flags = DRBG_HMAC | DRBG_STRENGTH256, .statelen = 48, /* block length of cipher */ @@ -303,7 +274,6 @@ static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg, static int drbg_init_hash_kernel(struct drbg_state *drbg); static int drbg_fini_hash_kernel(struct drbg_state *drbg); -#define CRYPTO_DRBG_HMAC_STRING "HMAC " MODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha512"); MODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha512"); MODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha384"); @@ -415,280 +385,6 @@ static const struct drbg_state_ops drbg_hmac_ops = { .crypto_fini = drbg_fini_hash_kernel, }; -/****************************************************************** - * Hash DRBG callback functions - ******************************************************************/ - -#ifdef CONFIG_CRYPTO_DRBG_HASH -#define CRYPTO_DRBG_HASH_STRING "HASH " -MODULE_ALIAS_CRYPTO("drbg_pr_sha512"); -MODULE_ALIAS_CRYPTO("drbg_nopr_sha512"); -MODULE_ALIAS_CRYPTO("drbg_pr_sha384"); -MODULE_ALIAS_CRYPTO("drbg_nopr_sha384"); -MODULE_ALIAS_CRYPTO("drbg_pr_sha256"); -MODULE_ALIAS_CRYPTO("drbg_nopr_sha256"); - -/* - * Increment buffer - * - * @dst buffer to increment - * @add value to add - */ -static inline void drbg_add_buf(unsigned char *dst, size_t dstlen, - const unsigned char *add, size_t addlen) -{ - /* implied: dstlen > addlen */ - unsigned char *dstptr; - const unsigned char *addptr; - unsigned int remainder = 0; - size_t len = addlen; - - dstptr = dst + (dstlen-1); - addptr = add + (addlen-1); - while (len) { - remainder += *dstptr + *addptr; - *dstptr = remainder & 0xff; - remainder >>= 8; - len--; dstptr--; addptr--; - } - len = dstlen - addlen; - while (len && remainder > 0) { - remainder = *dstptr + 1; - *dstptr = remainder & 0xff; - remainder >>= 8; - len--; dstptr--; - } -} - -/* - * scratchpad usage: as drbg_hash_update and drbg_hash_df are used - * interlinked, the scratchpad is used as follows: - * drbg_hash_update - * start: drbg->scratchpad - * length: drbg_statelen(drbg) - * drbg_hash_df: - * start: drbg->scratchpad + drbg_statelen(drbg) - * length: drbg_blocklen(drbg) - * - * drbg_hash_process_addtl uses the scratchpad, but fully completes - * before either of the functions mentioned before are invoked. Therefore, - * drbg_hash_process_addtl does not need to be specifically considered. - */ - -/* Derivation Function for Hash DRBG as defined in 10.4.1 */ -static int drbg_hash_df(struct drbg_state *drbg, - unsigned char *outval, size_t outlen, - struct list_head *entropylist) -{ - int ret = 0; - size_t len = 0; - unsigned char input[5]; - unsigned char *tmp = drbg->scratchpad + drbg_statelen(drbg); - struct drbg_string data; - - /* 10.4.1 step 3 */ - input[0] = 1; - put_unaligned_be32(outlen * 8, &input[1]); - - /* 10.4.1 step 4.1 -- concatenation of data for input into hash */ - drbg_string_fill(&data, input, 5); - list_add(&data.list, entropylist); - - /* 10.4.1 step 4 */ - while (len < outlen) { - short blocklen = 0; - /* 10.4.1 step 4.1 */ - ret = drbg_kcapi_hash(drbg, tmp, entropylist); - if (ret) - goto out; - /* 10.4.1 step 4.2 */ - input[0]++; - blocklen = (drbg_blocklen(drbg) < (outlen - len)) ? - drbg_blocklen(drbg) : (outlen - len); - memcpy(outval + len, tmp, blocklen); - len += blocklen; - } - -out: - memset(tmp, 0, drbg_blocklen(drbg)); - return ret; -} - -/* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */ -static int drbg_hash_update(struct drbg_state *drbg, struct list_head *seed, - int reseed) -{ - int ret = 0; - struct drbg_string data1, data2; - LIST_HEAD(datalist); - LIST_HEAD(datalist2); - unsigned char *V = drbg->scratchpad; - unsigned char prefix = DRBG_PREFIX1; - - if (!seed) - return -EINVAL; - - if (reseed) { - /* 10.1.1.3 step 1 */ - memcpy(V, drbg->V, drbg_statelen(drbg)); - drbg_string_fill(&data1, &prefix, 1); - list_add_tail(&data1.list, &datalist); - drbg_string_fill(&data2, V, drbg_statelen(drbg)); - list_add_tail(&data2.list, &datalist); - } - list_splice_tail(seed, &datalist); - - /* 10.1.1.2 / 10.1.1.3 step 2 and 3 */ - ret = drbg_hash_df(drbg, drbg->V, drbg_statelen(drbg), &datalist); - if (ret) - goto out; - - /* 10.1.1.2 / 10.1.1.3 step 4 */ - prefix = DRBG_PREFIX0; - drbg_string_fill(&data1, &prefix, 1); - list_add_tail(&data1.list, &datalist2); - drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg)); - list_add_tail(&data2.list, &datalist2); - /* 10.1.1.2 / 10.1.1.3 step 4 */ - ret = drbg_hash_df(drbg, drbg->C, drbg_statelen(drbg), &datalist2); - -out: - memset(drbg->scratchpad, 0, drbg_statelen(drbg)); - return ret; -} - -/* processing of additional information string for Hash DRBG */ -static int drbg_hash_process_addtl(struct drbg_state *drbg, - struct list_head *addtl) -{ - int ret = 0; - struct drbg_string data1, data2; - LIST_HEAD(datalist); - unsigned char prefix = DRBG_PREFIX2; - - /* 10.1.1.4 step 2 */ - if (!addtl || list_empty(addtl)) - return 0; - - /* 10.1.1.4 step 2a */ - drbg_string_fill(&data1, &prefix, 1); - drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg)); - list_add_tail(&data1.list, &datalist); - list_add_tail(&data2.list, &datalist); - list_splice_tail(addtl, &datalist); - ret = drbg_kcapi_hash(drbg, drbg->scratchpad, &datalist); - if (ret) - goto out; - - /* 10.1.1.4 step 2b */ - drbg_add_buf(drbg->V, drbg_statelen(drbg), - drbg->scratchpad, drbg_blocklen(drbg)); - -out: - memset(drbg->scratchpad, 0, drbg_blocklen(drbg)); - return ret; -} - -/* Hashgen defined in 10.1.1.4 */ -static int drbg_hash_hashgen(struct drbg_state *drbg, - unsigned char *buf, - unsigned int buflen) -{ - int len = 0; - int ret = 0; - unsigned char *src = drbg->scratchpad; - unsigned char *dst = drbg->scratchpad + drbg_statelen(drbg); - struct drbg_string data; - LIST_HEAD(datalist); - - /* 10.1.1.4 step hashgen 2 */ - memcpy(src, drbg->V, drbg_statelen(drbg)); - - drbg_string_fill(&data, src, drbg_statelen(drbg)); - list_add_tail(&data.list, &datalist); - while (len < buflen) { - unsigned int outlen = 0; - /* 10.1.1.4 step hashgen 4.1 */ - ret = drbg_kcapi_hash(drbg, dst, &datalist); - if (ret) { - len = ret; - goto out; - } - outlen = (drbg_blocklen(drbg) < (buflen - len)) ? - drbg_blocklen(drbg) : (buflen - len); - /* 10.1.1.4 step hashgen 4.2 */ - memcpy(buf + len, dst, outlen); - len += outlen; - /* 10.1.1.4 hashgen step 4.3 */ - if (len < buflen) - crypto_inc(src, drbg_statelen(drbg)); - } - -out: - memset(drbg->scratchpad, 0, - (drbg_statelen(drbg) + drbg_blocklen(drbg))); - return len; -} - -/* generate function for Hash DRBG as defined in 10.1.1.4 */ -static int drbg_hash_generate(struct drbg_state *drbg, - unsigned char *buf, unsigned int buflen, - struct list_head *addtl) -{ - int len = 0; - int ret = 0; - union { - unsigned char req[8]; - __be64 req_int; - } u; - unsigned char prefix = DRBG_PREFIX3; - struct drbg_string data1, data2; - LIST_HEAD(datalist); - - /* 10.1.1.4 step 2 */ - ret = drbg_hash_process_addtl(drbg, addtl); - if (ret) - return ret; - /* 10.1.1.4 step 3 */ - len = drbg_hash_hashgen(drbg, buf, buflen); - - /* this is the value H as documented in 10.1.1.4 */ - /* 10.1.1.4 step 4 */ - drbg_string_fill(&data1, &prefix, 1); - list_add_tail(&data1.list, &datalist); - drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg)); - list_add_tail(&data2.list, &datalist); - ret = drbg_kcapi_hash(drbg, drbg->scratchpad, &datalist); - if (ret) { - len = ret; - goto out; - } - - /* 10.1.1.4 step 5 */ - drbg_add_buf(drbg->V, drbg_statelen(drbg), - drbg->scratchpad, drbg_blocklen(drbg)); - drbg_add_buf(drbg->V, drbg_statelen(drbg), - drbg->C, drbg_statelen(drbg)); - u.req_int = cpu_to_be64(drbg->reseed_ctr); - drbg_add_buf(drbg->V, drbg_statelen(drbg), u.req, 8); - -out: - memset(drbg->scratchpad, 0, drbg_blocklen(drbg)); - return len; -} - -/* - * scratchpad usage: as update and generate are used isolated, both - * can use the scratchpad - */ -static const struct drbg_state_ops drbg_hash_ops = { - .update = drbg_hash_update, - .generate = drbg_hash_generate, - .crypto_init = drbg_init_hash_kernel, - .crypto_fini = drbg_fini_hash_kernel, -}; -#endif /* CONFIG_CRYPTO_DRBG_HASH */ - /****************************************************************** * Functions common for DRBG implementations ******************************************************************/ @@ -703,7 +399,6 @@ static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed, drbg->seeded = new_seed_state; drbg->last_seed_time = jiffies; - /* 10.1.1.2 / 10.1.1.3 step 5 */ drbg->reseed_ctr = 1; switch (drbg->seeded) { @@ -900,8 +595,6 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg) kfree_sensitive(drbg->Cbuf); drbg->Cbuf = NULL; drbg->C = NULL; - kfree_sensitive(drbg->scratchpadbuf); - drbg->scratchpadbuf = NULL; drbg->reseed_ctr = 0; drbg->d_ops = NULL; drbg->core = NULL; @@ -914,17 +607,11 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg) static inline int drbg_alloc_state(struct drbg_state *drbg) { int ret = -ENOMEM; - unsigned int sb_size = 0; switch (drbg->core->flags & DRBG_TYPE_MASK) { case DRBG_HMAC: drbg->d_ops = &drbg_hmac_ops; break; -#ifdef CONFIG_CRYPTO_DRBG_HASH - case DRBG_HASH: - drbg->d_ops = &drbg_hash_ops; - break; -#endif /* CONFIG_CRYPTO_DRBG_HASH */ default: ret = -EOPNOTSUPP; goto err; @@ -946,20 +633,6 @@ static inline int drbg_alloc_state(struct drbg_state *drbg) goto fini; } drbg->C = PTR_ALIGN(drbg->Cbuf, ret + 1); - /* scratchpad is only generated for Hash */ - if (drbg->core->flags & DRBG_HMAC) - sb_size = 0; - else - sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg); - - if (0 < sb_size) { - drbg->scratchpadbuf = kzalloc(sb_size + ret, GFP_KERNEL); - if (!drbg->scratchpadbuf) { - ret = -ENOMEM; - goto fini; - } - drbg->scratchpad = PTR_ALIGN(drbg->scratchpadbuf, ret + 1); - } return 0; @@ -1061,7 +734,7 @@ static int drbg_generate(struct drbg_state *drbg, /* 9.3.1 step 8 and 10 */ len = drbg->d_ops->generate(drbg, buf, buflen, &addtllist); - /* 10.1.1.4 step 6, 10.1.2.5 step 7 */ + /* 10.1.2.5 step 7 */ drbg->reseed_ctr++; if (0 >= len) goto err; @@ -1449,9 +1122,6 @@ static inline int __init drbg_healthcheck_sanity(void) if (!fips_enabled) return 0; -#ifdef CONFIG_CRYPTO_DRBG_HASH - drbg_convert_tfm_core("drbg_nopr_sha256", &coreref, &pr); -#endif drbg_convert_tfm_core("drbg_nopr_hmac_sha512", &coreref, &pr); drbg = kzalloc_obj(struct drbg_state); @@ -1577,13 +1247,7 @@ static void __exit drbg_exit(void) module_init(drbg_init); module_exit(drbg_exit); -#ifndef CRYPTO_DRBG_HASH_STRING -#define CRYPTO_DRBG_HASH_STRING "" -#endif MODULE_LICENSE("GPL"); MODULE_AUTHOR("Stephan Mueller "); -MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG) " - "using following cores: " - CRYPTO_DRBG_HASH_STRING - CRYPTO_DRBG_HMAC_STRING); +MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG)"); MODULE_ALIAS_CRYPTO("stdrng"); diff --git a/crypto/testmgr.c b/crypto/testmgr.c index dbc1e1fb4bd0..fdc5051b73c5 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -4660,22 +4660,6 @@ static const struct alg_test_desc alg_test_descs[] = { .suite = { .drbg = __VECS(drbg_nopr_hmac_sha512_tv_template) } - }, { - .alg = "drbg_nopr_sha256", - .test = alg_test_drbg, - .fips_allowed = 1, - .suite = { - .drbg = __VECS(drbg_nopr_sha256_tv_template) - } - }, { - /* covered by drbg_nopr_sha256 test */ - .alg = "drbg_nopr_sha384", - .test = alg_test_null, - .fips_allowed = 1 - }, { - .alg = "drbg_nopr_sha512", - .fips_allowed = 1, - .test = alg_test_null, }, { .alg = "drbg_pr_hmac_sha256", .test = alg_test_drbg, @@ -4692,22 +4676,6 @@ static const struct alg_test_desc alg_test_descs[] = { .alg = "drbg_pr_hmac_sha512", .test = alg_test_null, .fips_allowed = 1, - }, { - .alg = "drbg_pr_sha256", - .test = alg_test_drbg, - .fips_allowed = 1, - .suite = { - .drbg = __VECS(drbg_pr_sha256_tv_template) - } - }, { - /* covered by drbg_pr_sha256 test */ - .alg = "drbg_pr_sha384", - .test = alg_test_null, - .fips_allowed = 1 - }, { - .alg = "drbg_pr_sha512", - .fips_allowed = 1, - .test = alg_test_null, }, { .alg = "ecb(aes)", .generic_driver = "ecb(aes-lib)", diff --git a/crypto/testmgr.h b/crypto/testmgr.h index a86275b61b6a..d44a4c1e7313 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -23422,172 +23422,6 @@ static const struct aead_testvec aegis128_tv_template[] = { }, }; -/* - * SP800-90A DRBG Test vectors from - * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip - * - * Test vectors for DRBG with prediction resistance. All types of DRBGs - * (Hash, HMAC, CTR) are tested with all permutations of use cases (w/ and - * w/o personalization string, w/ and w/o additional input string). - */ -static const struct drbg_testvec drbg_pr_sha256_tv_template[] = { - { - .entropy = (unsigned char *) - "\x72\x88\x4c\xcd\x6c\x85\x57\x70\xf7\x0b\x8b\x86" - "\xc1\xeb\xd2\x4e\x36\x14\xab\x18\xc4\x9c\xc9\xcf" - "\x1a\xe8\xf7\x7b\x02\x49\x73\xd7\xf1\x42\x7d\xc6" - "\x3f\x29\x2d\xec\xd3\x66\x51\x3f\x1d\x8d\x5b\x4e", - .entropylen = 48, - .entpra = (unsigned char *) - "\x38\x9c\x91\xfa\xc2\xa3\x46\x89\x56\x08\x3f\x62" - "\x73\xd5\x22\xa9\x29\x63\x3a\x1d\xe5\x5d\x5e\x4f" - "\x67\xb0\x67\x7a\x5e\x9e\x0c\x62", - .entprb = (unsigned char *) - "\xb2\x8f\x36\xb2\xf6\x8d\x39\x13\xfa\x6c\x66\xcf" - "\x62\x8a\x7e\x8c\x12\x33\x71\x9c\x69\xe4\xa5\xf0" - "\x8c\xee\xeb\x9c\xf5\x31\x98\x31", - .entprlen = 32, - .expected = (unsigned char *) - "\x52\x7b\xa3\xad\x71\x77\xa4\x49\x42\x04\x61\xc7" - "\xf0\xaf\xa5\xfd\xd3\xb3\x0d\x6a\x61\xba\x35\x49" - "\xbb\xaa\xaf\xe4\x25\x7d\xb5\x48\xaf\x5c\x18\x3d" - "\x33\x8d\x9d\x45\xdf\x98\xd5\x94\xa8\xda\x92\xfe" - "\xc4\x3c\x94\x2a\xcf\x7f\x7b\xf2\xeb\x28\xa9\xf1" - "\xe0\x86\x30\xa8\xfe\xf2\x48\x90\x91\x0c\x75\xb5" - "\x3c\x00\xf0\x4d\x09\x4f\x40\xa7\xa2\x8c\x52\xdf" - "\x52\xef\x17\xbf\x3d\xd1\xa2\x31\xb4\xb8\xdc\xe6" - "\x5b\x0d\x1f\x78\x36\xb4\xe6\x4b\xa7\x11\x25\xd5" - "\x94\xc6\x97\x36\xab\xf0\xe5\x31\x28\x6a\xbb\xce" - "\x30\x81\xa6\x8f\x27\x14\xf8\x1c", - .expectedlen = 128, - .addtla = NULL, - .addtlb = NULL, - .addtllen = 0, - .pers = NULL, - .perslen = 0, - }, { - .entropy = (unsigned char *) - "\x5d\xf2\x14\xbc\xf6\xb5\x4e\x0b\xf0\x0d\x6f\x2d" - "\xe2\x01\x66\x7b\xd0\xa4\x73\xa4\x21\xdd\xb0\xc0" - "\x51\x79\x09\xf4\xea\xa9\x08\xfa\xa6\x67\xe0\xe1" - "\xd1\x88\xa8\xad\xee\x69\x74\xb3\x55\x06\x9b\xf6", - .entropylen = 48, - .entpra = (unsigned char *) - "\xef\x48\x06\xa2\xc2\x45\xf1\x44\xfa\x34\x2c\xeb" - "\x8d\x78\x3c\x09\x8f\x34\x72\x20\xf2\xe7\xfd\x13" - "\x76\x0a\xf6\xdc\x3c\xf5\xc0\x15", - .entprb = (unsigned char *) - "\x4b\xbe\xe5\x24\xed\x6a\x2d\x0c\xdb\x73\x5e\x09" - "\xf9\xad\x67\x7c\x51\x47\x8b\x6b\x30\x2a\xc6\xde" - "\x76\xaa\x55\x04\x8b\x0a\x72\x95", - .entprlen = 32, - .expected = (unsigned char *) - "\x3b\x14\x71\x99\xa1\xda\xa0\x42\xe6\xc8\x85\x32" - "\x70\x20\x32\x53\x9a\xbe\xd1\x1e\x15\xef\xfb\x4c" - "\x25\x6e\x19\x3a\xf0\xb9\xcb\xde\xf0\x3b\xc6\x18" - "\x4d\x85\x5a\x9b\xf1\xe3\xc2\x23\x03\x93\x08\xdb" - "\xa7\x07\x4b\x33\x78\x40\x4d\xeb\x24\xf5\x6e\x81" - "\x4a\x1b\x6e\xa3\x94\x52\x43\xb0\xaf\x2e\x21\xf4" - "\x42\x46\x8e\x90\xed\x34\x21\x75\xea\xda\x67\xb6" - "\xe4\xf6\xff\xc6\x31\x6c\x9a\x5a\xdb\xb3\x97\x13" - "\x09\xd3\x20\x98\x33\x2d\x6d\xd7\xb5\x6a\xa8\xa9" - "\x9a\x5b\xd6\x87\x52\xa1\x89\x2b\x4b\x9c\x64\x60" - "\x50\x47\xa3\x63\x81\x16\xaf\x19", - .expectedlen = 128, - .addtla = (unsigned char *) - "\xbe\x13\xdb\x2a\xe9\xa8\xfe\x09\x97\xe1\xce\x5d" - "\xe8\xbb\xc0\x7c\x4f\xcb\x62\x19\x3f\x0f\xd2\xad" - "\xa9\xd0\x1d\x59\x02\xc4\xff\x70", - .addtlb = (unsigned char *) - "\x6f\x96\x13\xe2\xa7\xf5\x6c\xfe\xdf\x66\xe3\x31" - "\x63\x76\xbf\x20\x27\x06\x49\xf1\xf3\x01\x77\x41" - "\x9f\xeb\xe4\x38\xfe\x67\x00\xcd", - .addtllen = 32, - .pers = NULL, - .perslen = 0, - }, { - .entropy = (unsigned char *) - "\xc6\x1c\xaf\x83\xa2\x56\x38\xf9\xb0\xbc\xd9\x85" - "\xf5\x2e\xc4\x46\x9c\xe1\xb9\x40\x98\x70\x10\x72" - "\xd7\x7d\x15\x85\xa1\x83\x5a\x97\xdf\xc8\xa8\xe8" - "\x03\x4c\xcb\x70\x35\x8b\x90\x94\x46\x8a\x6e\xa1", - .entropylen = 48, - .entpra = (unsigned char *) - "\xc9\x05\xa4\xcf\x28\x80\x4b\x93\x0f\x8b\xc6\xf9" - "\x09\x41\x58\x74\xe9\xec\x28\xc7\x53\x0a\x73\x60" - "\xba\x0a\xde\x57\x5b\x4b\x9f\x29", - .entprb = (unsigned char *) - "\x4f\x31\xd2\xeb\xac\xfa\xa8\xe2\x01\x7d\xf3\xbd" - "\x42\xbd\x20\xa0\x30\x65\x74\xd5\x5d\xd2\xad\xa4" - "\xa9\xeb\x1f\x4d\xf6\xfd\xb8\x26", - .entprlen = 32, - .expected = (unsigned char *) - "\xf6\x13\x05\xcb\x83\x60\x16\x42\x49\x1d\xc6\x25" - "\x3b\x8c\x31\xa3\xbe\x8b\xbd\x1c\xe2\xec\x1d\xde" - "\xbb\xbf\xa1\xac\xa8\x9f\x50\xce\x69\xce\xef\xd5" - "\xd6\xf2\xef\x6a\xf7\x81\x38\xdf\xbc\xa7\x5a\xb9" - "\xb2\x42\x65\xab\xe4\x86\x8d\x2d\x9d\x59\x99\x2c" - "\x5a\x0d\x71\x55\x98\xa4\x45\xc2\x8d\xdb\x05\x5e" - "\x50\x21\xf7\xcd\xe8\x98\x43\xce\x57\x74\x63\x4c" - "\xf3\xb1\xa5\x14\x1e\x9e\x01\xeb\x54\xd9\x56\xae" - "\xbd\xb6\x6f\x1a\x47\x6b\x3b\x44\xe4\xa2\xe9\x3c" - "\x6c\x83\x12\x30\xb8\x78\x7f\x8e\x54\x82\xd4\xfe" - "\x90\x35\x0d\x4c\x4d\x85\xe7\x13", - .expectedlen = 128, - .addtla = NULL, - .addtlb = NULL, - .addtllen = 0, - .pers = (unsigned char *) - "\xa5\xbf\xac\x4f\x71\xa1\xbb\x67\x94\xc6\x50\xc7" - "\x2a\x45\x9e\x10\xa8\xed\xf7\x52\x4f\xfe\x21\x90" - "\xa4\x1b\xe1\xe2\x53\xcc\x61\x47", - .perslen = 32, - }, { - .entropy = (unsigned char *) - "\xb6\xc1\x8d\xdf\x99\x54\xbe\x95\x10\x48\xd9\xf6" - "\xd7\x48\xa8\x73\x2d\x74\xde\x1e\xde\x57\x7e\xf4" - "\x7b\x7b\x64\xef\x88\x7a\xa8\x10\x4b\xe1\xc1\x87" - "\xbb\x0b\xe1\x39\x39\x50\xaf\x68\x9c\xa2\xbf\x5e", - .entropylen = 48, - .entpra = (unsigned char *) - "\xdc\x81\x0a\x01\x58\xa7\x2e\xce\xee\x48\x8c\x7c" - "\x77\x9e\x3c\xf1\x17\x24\x7a\xbb\xab\x9f\xca\x12" - "\x19\xaf\x97\x2d\x5f\xf9\xff\xfc", - .entprb = (unsigned char *) - "\xaf\xfc\x4f\x98\x8b\x93\x95\xc1\xb5\x8b\x7f\x73" - "\x6d\xa6\xbe\x6d\x33\xeb\x2c\x82\xb1\xaf\xc1\xb6" - "\xb6\x05\xe2\x44\xaa\xfd\xe7\xdb", - .entprlen = 32, - .expected = (unsigned char *) - "\x51\x79\xde\x1c\x0f\x58\xf3\xf4\xc9\x57\x2e\x31" - "\xa7\x09\xa1\x53\x64\x63\xa2\xc5\x1d\x84\x88\x65" - "\x01\x1b\xc6\x16\x3c\x49\x5b\x42\x8e\x53\xf5\x18" - "\xad\x94\x12\x0d\x4f\x55\xcc\x45\x5c\x98\x0f\x42" - "\x28\x2f\x47\x11\xf9\xc4\x01\x97\x6b\xa0\x94\x50" - "\xa9\xd1\x5e\x06\x54\x3f\xdf\xbb\xc4\x98\xee\x8b" - "\xba\xa9\xfa\x49\xee\x1d\xdc\xfb\x50\xf6\x51\x9f" - "\x6c\x4a\x9a\x6f\x63\xa2\x7d\xad\xaf\x3a\x24\xa0" - "\xd9\x9f\x07\xeb\x15\xee\x26\xe0\xd5\x63\x39\xda" - "\x3c\x59\xd6\x33\x6c\x02\xe8\x05\x71\x46\x68\x44" - "\x63\x4a\x68\x72\xe9\xf5\x55\xfe", - .expectedlen = 128, - .addtla = (unsigned char *) - "\x15\x20\x2f\xf6\x98\x28\x63\xa2\xc4\x4e\xbb\x6c" - "\xb2\x25\x92\x61\x79\xc9\x22\xc4\x61\x54\x96\xff" - "\x4a\x85\xca\x80\xfe\x0d\x1c\xd0", - .addtlb = (unsigned char *) - "\xde\x29\x8e\x03\x42\x61\xa3\x28\x5e\xc8\x80\xc2" - "\x6d\xbf\xad\x13\xe1\x8d\x2a\xc7\xe8\xc7\x18\x89" - "\x42\x58\x9e\xd6\xcc\xad\x7b\x1e", - .addtllen = 32, - .pers = (unsigned char *) - "\x84\xc3\x73\x9e\xce\xb3\xbc\x89\xf7\x62\xb3\xe1" - "\xd7\x48\x45\x8a\xa9\xcc\xe9\xed\xd5\x81\x84\x52" - "\x82\x4c\xdc\x19\xb8\xf8\x92\x5c", - .perslen = 32, - }, -}; - static const struct drbg_testvec drbg_pr_hmac_sha256_tv_template[] = { { .entropy = (unsigned char *) @@ -23746,136 +23580,6 @@ static const struct drbg_testvec drbg_pr_hmac_sha256_tv_template[] = { }, }; -/* - * SP800-90A DRBG Test vectors from - * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip - * - * Test vectors for DRBG without prediction resistance. All types of DRBGs - * (Hash, HMAC, CTR) are tested with all permutations of use cases (w/ and - * w/o personalization string, w/ and w/o additional input string). - */ -static const struct drbg_testvec drbg_nopr_sha256_tv_template[] = { - { - .entropy = (unsigned char *) - "\xa6\x5a\xd0\xf3\x45\xdb\x4e\x0e\xff\xe8\x75\xc3" - "\xa2\xe7\x1f\x42\xc7\x12\x9d\x62\x0f\xf5\xc1\x19" - "\xa9\xef\x55\xf0\x51\x85\xe0\xfb\x85\x81\xf9\x31" - "\x75\x17\x27\x6e\x06\xe9\x60\x7d\xdb\xcb\xcc\x2e", - .entropylen = 48, - .expected = (unsigned char *) - "\xd3\xe1\x60\xc3\x5b\x99\xf3\x40\xb2\x62\x82\x64" - "\xd1\x75\x10\x60\xe0\x04\x5d\xa3\x83\xff\x57\xa5" - "\x7d\x73\xa6\x73\xd2\xb8\xd8\x0d\xaa\xf6\xa6\xc3" - "\x5a\x91\xbb\x45\x79\xd7\x3f\xd0\xc8\xfe\xd1\x11" - "\xb0\x39\x13\x06\x82\x8a\xdf\xed\x52\x8f\x01\x81" - "\x21\xb3\xfe\xbd\xc3\x43\xe7\x97\xb8\x7d\xbb\x63" - "\xdb\x13\x33\xde\xd9\xd1\xec\xe1\x77\xcf\xa6\xb7" - "\x1f\xe8\xab\x1d\xa4\x66\x24\xed\x64\x15\xe5\x1c" - "\xcd\xe2\xc7\xca\x86\xe2\x83\x99\x0e\xea\xeb\x91" - "\x12\x04\x15\x52\x8b\x22\x95\x91\x02\x81\xb0\x2d" - "\xd4\x31\xf4\xc9\xf7\x04\x27\xdf", - .expectedlen = 128, - .addtla = NULL, - .addtlb = NULL, - .addtllen = 0, - .pers = NULL, - .perslen = 0, - }, { - .entropy = (unsigned char *) - "\x73\xd3\xfb\xa3\x94\x5f\x2b\x5f\xb9\x8f\xf6\x9c" - "\x8a\x93\x17\xae\x19\xc3\x4c\xc3\xd6\xca\xa3\x2d" - "\x16\xfc\x42\xd2\x2d\xd5\x6f\x56\xcc\x1d\x30\xff" - "\x9e\x06\x3e\x09\xce\x58\xe6\x9a\x35\xb3\xa6\x56", - .entropylen = 48, - .expected = (unsigned char *) - "\x71\x7b\x93\x46\x1a\x40\xaa\x35\xa4\xaa\xc5\xe7" - "\x6d\x5b\x5b\x8a\xa0\xdf\x39\x7d\xae\x71\x58\x5b" - "\x3c\x7c\xb4\xf0\x89\xfa\x4a\x8c\xa9\x5c\x54\xc0" - "\x40\xdf\xbc\xce\x26\x81\x34\xf8\xba\x7d\x1c\xe8" - "\xad\x21\xe0\x74\xcf\x48\x84\x30\x1f\xa1\xd5\x4f" - "\x81\x42\x2f\xf4\xdb\x0b\x23\xf8\x73\x27\xb8\x1d" - "\x42\xf8\x44\x58\xd8\x5b\x29\x27\x0a\xf8\x69\x59" - "\xb5\x78\x44\xeb\x9e\xe0\x68\x6f\x42\x9a\xb0\x5b" - "\xe0\x4e\xcb\x6a\xaa\xe2\xd2\xd5\x33\x25\x3e\xe0" - "\x6c\xc7\x6a\x07\xa5\x03\x83\x9f\xe2\x8b\xd1\x1c" - "\x70\xa8\x07\x59\x97\xeb\xf6\xbe", - .expectedlen = 128, - .addtla = (unsigned char *) - "\xf4\xd5\x98\x3d\xa8\xfc\xfa\x37\xb7\x54\x67\x73" - "\xc7\xc3\xdd\x47\x34\x71\x02\x5d\xc1\xa0\xd3\x10" - "\xc1\x8b\xbd\xf5\x66\x34\x6f\xdd", - .addtlb = (unsigned char *) - "\xf7\x9e\x6a\x56\x0e\x73\xe9\xd9\x7a\xd1\x69\xe0" - "\x6f\x8c\x55\x1c\x44\xd1\xce\x6f\x28\xcc\xa4\x4d" - "\xa8\xc0\x85\xd1\x5a\x0c\x59\x40", - .addtllen = 32, - .pers = NULL, - .perslen = 0, - }, { - .entropy = (unsigned char *) - "\x2a\x85\xa9\x8b\xd0\xda\x83\xd6\xad\xab\x9f\xbb" - "\x54\x31\x15\x95\x1c\x4d\x49\x9f\x6a\x15\xf6\xe4" - "\x15\x50\x88\x06\x29\x0d\xed\x8d\xb9\x6f\x96\xe1" - "\x83\x9f\xf7\x88\xda\x84\xbf\x44\x28\xd9\x1d\xaa", - .entropylen = 48, - .expected = (unsigned char *) - "\x2d\x55\xde\xc9\xed\x05\x47\x07\x3d\x04\xfc\x28" - "\x0f\x92\xf0\x4d\xd8\x00\x32\x47\x0a\x1b\x1c\x4b" - "\xef\xd9\x97\xa1\x17\x67\xda\x26\x6c\xfe\x76\x46" - "\x6f\xbc\x6d\x82\x4e\x83\x8a\x98\x66\x6c\x01\xb6" - "\xe6\x64\xe0\x08\x10\x6f\xd3\x5d\x90\xe7\x0d\x72" - "\xa6\xa7\xe3\xbb\x98\x11\x12\x56\x23\xc2\x6d\xd1" - "\xc8\xa8\x7a\x39\xf3\x34\xe3\xb8\xf8\x66\x00\x77" - "\x7d\xcf\x3c\x3e\xfa\xc9\x0f\xaf\xe0\x24\xfa\xe9" - "\x84\xf9\x6a\x01\xf6\x35\xdb\x5c\xab\x2a\xef\x4e" - "\xac\xab\x55\xb8\x9b\xef\x98\x68\xaf\x51\xd8\x16" - "\xa5\x5e\xae\xf9\x1e\xd2\xdb\xe6", - .expectedlen = 128, - .addtla = NULL, - .addtlb = NULL, - .addtllen = 0, - .pers = (unsigned char *) - "\xa8\x80\xec\x98\x30\x98\x15\xd2\xc6\xc4\x68\xf1" - "\x3a\x1c\xbf\xce\x6a\x40\x14\xeb\x36\x99\x53\xda" - "\x57\x6b\xce\xa4\x1c\x66\x3d\xbc", - .perslen = 32, - }, { - .entropy = (unsigned char *) - "\x69\xed\x82\xa9\xc5\x7b\xbf\xe5\x1d\x2f\xcb\x7a" - "\xd3\x50\x7d\x96\xb4\xb9\x2b\x50\x77\x51\x27\x74" - "\x33\x74\xba\xf1\x30\xdf\x8e\xdf\x87\x1d\x87\xbc" - "\x96\xb2\xc3\xa7\xed\x60\x5e\x61\x4e\x51\x29\x1a", - .entropylen = 48, - .expected = (unsigned char *) - "\xa5\x71\x24\x31\x11\xfe\x13\xe1\xa8\x24\x12\xfb" - "\x37\xa1\x27\xa5\xab\x77\xa1\x9f\xae\x8f\xaf\x13" - "\x93\xf7\x53\x85\x91\xb6\x1b\xab\xd4\x6b\xea\xb6" - "\xef\xda\x4c\x90\x6e\xef\x5f\xde\xe1\xc7\x10\x36" - "\xd5\x67\xbd\x14\xb6\x89\x21\x0c\xc9\x92\x65\x64" - "\xd0\xf3\x23\xe0\x7f\xd1\xe8\x75\xc2\x85\x06\xea" - "\xca\xc0\xcb\x79\x2d\x29\x82\xfc\xaa\x9a\xc6\x95" - "\x7e\xdc\x88\x65\xba\xec\x0e\x16\x87\xec\xa3\x9e" - "\xd8\x8c\x80\xab\x3a\x64\xe0\xcb\x0e\x45\x98\xdd" - "\x7c\x6c\x6c\x26\x11\x13\xc8\xce\xa9\x47\xa6\x06" - "\x57\xa2\x66\xbb\x2d\x7f\xf3\xc1", - .expectedlen = 128, - .addtla = (unsigned char *) - "\x74\xd3\x6d\xda\xe8\xd6\x86\x5f\x63\x01\xfd\xf2" - "\x7d\x06\x29\x6d\x94\xd1\x66\xf0\xd2\x72\x67\x4e" - "\x77\xc5\x3d\x9e\x03\xe3\xa5\x78", - .addtlb = (unsigned char *) - "\xf6\xb6\x3d\xf0\x7c\x26\x04\xc5\x8b\xcd\x3e\x6a" - "\x9f\x9c\x3a\x2e\xdb\x47\x87\xe5\x8e\x00\x5e\x2b" - "\x74\x7f\xa6\xf6\x80\xcd\x9b\x21", - .addtllen = 32, - .pers = (unsigned char *) - "\x74\xa6\xe0\x08\xf9\x27\xee\x1d\x6e\x3c\x28\x20" - "\x87\xdd\xd7\x54\x31\x47\x78\x4b\xe5\x6d\xa3\x73" - "\xa9\x65\xb1\x10\xc1\xdc\x77\x7c", - .perslen = 32, - }, -}; - static const struct drbg_testvec drbg_nopr_hmac_sha256_tv_template[] = { { .entropy = (unsigned char *) From 5dd76c87e47879ca2ef70479962bca01263a5428 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:33:58 -0700 Subject: [PATCH 025/196] crypto: drbg - Flatten the DRBG menu Now that the menuconfig CRYPTO_DRBG_MENU has no options in it other than the hidden symbol CRYPTO_DRBG, remove it and move CRYPTO_DRBG to its parent menu. Give CRYPTO_DRBG an appropriate prompt and help text. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/Kconfig | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/crypto/Kconfig b/crypto/Kconfig index 14519474a67b..1abb3d356458 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1113,24 +1113,17 @@ endmenu menu "Random number generation" -menuconfig CRYPTO_DRBG_MENU - tristate "NIST SP800-90A DRBG (Deterministic Random Bit Generator)" - help - DRBG (Deterministic Random Bit Generator) (NIST SP800-90A) - - In the following submenu, one or more of the DRBG types must be selected. - -if CRYPTO_DRBG_MENU - config CRYPTO_DRBG - tristate - default CRYPTO_DRBG_MENU + tristate "NIST SP800-90A DRBG (Deterministic Random Bit Generator)" select CRYPTO_HMAC select CRYPTO_JITTERENTROPY select CRYPTO_RNG select CRYPTO_SHA512 + help + DRBG (Deterministic Random Bit Generator) (NIST SP800-90A) -endif # if CRYPTO_DRBG_MENU + Enable this only if you need it for a FIPS 140 certification. + It's otherwise redundant with the kernel's regular RNG. config CRYPTO_JITTERENTROPY tristate "CPU Jitter Non-Deterministic RNG (Random Number Generator)" From ca952c7504707495ab8cf2fdd958ee10cf41f48f Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:33:59 -0700 Subject: [PATCH 026/196] crypto: testmgr - Add test for drbg_pr_hmac_sha512 Add a test for drbg_pr_hmac_sha512, which previously didn't have a test. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/testmgr.c | 5 +- crypto/testmgr.h | 199 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 203 insertions(+), 1 deletion(-) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index fdc5051b73c5..5a984b3b9a9b 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -4674,8 +4674,11 @@ static const struct alg_test_desc alg_test_descs[] = { .fips_allowed = 1 }, { .alg = "drbg_pr_hmac_sha512", - .test = alg_test_null, + .test = alg_test_drbg, .fips_allowed = 1, + .suite = { + .drbg = __VECS(drbg_pr_hmac_sha512_tv_template) + } }, { .alg = "ecb(aes)", .generic_driver = "ecb(aes-lib)", diff --git a/crypto/testmgr.h b/crypto/testmgr.h index d44a4c1e7313..77935a457313 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -23702,6 +23702,205 @@ static const struct drbg_testvec drbg_nopr_hmac_sha256_tv_template[] = { }, }; +static const struct drbg_testvec drbg_pr_hmac_sha512_tv_template[] = { + /* + * Borrowed from the first applicable test vector from ACVP: + * https://github.com/usnistgov/ACVP-Server/blob/v1.1.0.33/gen-val/json-files/hmacDRBG-1.0/prompt.json#L1161 + * https://github.com/usnistgov/ACVP-Server/blob/v1.1.0.33/gen-val/json-files/hmacDRBG-1.0/expectedResults.json#L271 + */ + { + /* .entropy = ACVP entropyInput || nonce */ + .entropy = "\x9B\xE9\xB2\x87\xA3\x9A\x08\x44\x1D\x67\x82\x20" + "\xC9\x53\xFB\xEB\xA4\xB9\x0F\x44\x0B\x98\x33\x18" + "\xAC\x6E\x25\x4A\x85\x83\x2D\x26\x21\x9F\x93\x64" + "\xC8\x5A\x5F\x72\xDB\x88\x45\x96\x71\x41\xF4\xBF" + "\x6E\xA7\x98\x00\x9D\xD1\x0C\x2E\x4D\x7A\xE2\x03" + "\x0D\xE3\xCD\x62\xFE\xF3\x62\xBD\x12\x69\x92\x3D" + "\xBA\xAC\x15\x17\xC7\x80\x93\x8E\x72\x32\x2D\x52" + "\xE5\x2C\x19\x84\x5C\xA5\xCE\x5B\x98\x19\x1F\xF1" + "\x9F\x0C\x17\x04\xD0\x66\xF1\x9B\xFA\x7E\x2C\xB6" + "\x55\x68\xD4\x1B\xD6\x7A\x1D\x2C\xD4\x6D\x6E\x15" + "\xF7\x32\x23\x04\x05\x8C\xBB\xE6\x63\x6B\x80\x9B" + "\x9C\x69\x09\x8F\x5F\x02\xBF\x53\x42\x11\xB7\x80" + "\xAA\xD4\xE8\x54\x00\x83\x5C\x20\xA8\xB3\x6E\xD9" + "\xF5\x51\x9E\xB9\xD1\x6E\xC7\x0C\xE9\x7F\xF0\xBF" + "\xCE\x1D\xB0\x31\x8D\x16\xC9\x65\x0C\x18\x55\xA4" + "\x46\x8D\x54\x2B\x78\x69\x1B\x8C\x29\xD7\xAC\x0F" + "\x34\x4D\x69\x0B\x76\xC3\x98\x00\x78\x2F\xE2\x54" + "\xAF\xD5\x8A\xC3\x40\x97\xB1\xA2\x60\xD3\x07\x3B" + "\x7A\x3E\xD0\x82\x80\x68\xEE\xB0\x72\x5F\x07\x17" + "\xD9\x0A\xFC\xBD\xBA\xB6\x77\x4E\xC9\xCE\x6A\x48" + "\xEB\x9C\xF5\x18\x88\x1E\x6E\x3B\x65\x43\x16\x73" + "\x80\x53\xB7\xF0\x7E\xAB\x23\x19\x1E\x75\x60\x36" + "\xAF\x39\xC0\xCF\x0F\x6D\x7F\x90\xB2\x50\xD5\x37" + "\x58\x6D\x5C\x95\x78\x25\x8D\x3A\x40\xAB\xF6\x7B" + "\x85\x86\xBB\x48\x5E\x1C\x99\xC1\xD3\x4E\x85\xE5" + "\xB4\xE7\x61\xF3\x7D\x56\x1F\x77\xCF\x3C\x76\x3A" + "\xF4\x82\x36\xB7\x37\x33\x84\x34\xBA\x0E\xE2\xE1" + "\xAF\x0C\xD2\xAE\x97\x5C\x80\xD4\xD2\xFD\x37\x71" + "\xC8\x70\x04\x29\x8B\x44\xB9\xD7\xC9\x8F\xE7\x99" + "\x94\x9E\xFC\x49\x66\x24\xCB\x8B\x41\x40\x66\xC5" + "\xA4\x00\xD5\x3F\x68\xDD\xB5\xA5\x62\x96\x7C\xAC" + "\x63\x58\x95\x85\x99\x24\x21\x15\xD2\x76\xAF\x6D", + .entropylen = 384, + .pers = "\xDD\x07\x10\x10\x17\x34\xD5\xBD\x43\xAF\x03\x79\xE4" + "\x64\x2C\x58\x06\xEA\xE0\x39\xDA\x42\x96\x16\x0B\xF9" + "\xB8\xCE\x57\x7D\x53\x67\xBF\xF8\x0C\x40\x02\xB2\x77" + "\x16\xD5\x23\x75\x9F\x6A\x42\x0E\xE8\xCC\xD0\x9F\x40" + "\x64\xE9\x3B\xE9\x48\x13\xC3\x8E\x4B\xAB\xE1\xB9\x4F" + "\x6D\xBB\xF2\x4C\xF8\x29\xA5\x2B\x44\x23\x15\x2C\xDE" + "\x2A\xCF\x88\x04\x7A\x38\x37\xA2\xD5\x7B\xEA\x59\x39" + "\x2C\x58\xA2\x5B\xF9\x39\xA2\x7E\x94\x11\x97\xEC\x47" + "\x08\xD6\xE2\x39\x65\x26\x43\x81\x3F\x1B\x31\xA6\xA4" + "\x1A\x5C\xCD\x02\xCC\x89\x38\x3F\x32\x7C\x0E\x7E\x88" + "\x3B\x6F\x60\x69\xEA\xBA\xAA\x1F\x53\x93\x70\xD7\x48" + "\x74\x91\x79\x5E\xD4\xB0\xD9\x82\x74\x12\xDE\xFE\xFB" + "\x51\x96\x66\x5C\x6A\x53\x11\xAD\x9A\xD4\xFA\x9D\xF0" + "\xE2\x7F\x26\x8F\x6F\xAC\x00\xC8\xDB\xCF\xA5\x8E\xE6" + "\x61\x8F\x36\xD6\x44\x5B\x07\xDA\x9C\x2A\x46\xE3\x03" + "\x1C\xD8\x11\x4F\x61\x1F\xEC\xBA\x12\x68\xB9\x4B\x57" + "\x39\x05\xD6\xEE\xC1\xAC\x3F\x6D\x6F\xE9\xBF\xEA\x36" + "\x1A\x8A\xAA\xF4\xE8\xE0\xDB\xC6\xE5\x06\x9F\xC9\x91" + "\x52\xCD\x53\xD0\x78\xF6\xC1\x7B\x75\x91\x85\x91\x13" + "\x26\xBE\xC9\x02\xDE\xB0\x19\xF2\x71", + .perslen = 256, + + .entpra = "\xDB\xBA\x25\xC7\x02\x0D\x3D\x95\x9C\xEB\xF5\x42" + "\x52\x3A\x6B\xDA\xE8\xAF\xE9\x3D\x76\x2A\x9E\xB5" + "\xD7\xE7\x5D\xC9\xB8\x1F\x3A\xC2\x91\x95\x9D\xFD" + "\xE5\x48\x5F\x63\xD8\x84\x44\x82\x6A\x71\xF9\xDD" + "\xAF\x4B\xE2\x28\xB4\x30\xCF\x78\xB7\x0B\x0F\x61" + "\x71\x16\x1A\xE0\x6D\x5F\xB4\x4B\x17\x1A\x26\xCA" + "\xD8\x9D\x6D\x46\xA3\x56\xC0\xE7\x49\xCF\xE0\xD2" + "\xFF\xA8\x22\x45\xE0\xB4\x18\x0B\x13\x37\x01\x46" + "\xCB\xE7\xD8\x2A\x59\x43\xAD\x90\x1E\xE1\xD0\xD7" + "\x76\xB0\x2D\xCF\x17\x23\x99\x73\x5D\xE5\xC7\x46" + "\x8A\x0D\x8E\xC4\xAB\x45\xAC\xA8\x74\xE4\xF7\xD0" + "\x26\xD7\x0A\xE2\x43\x3D\xB8\xC7\xEE\xAD\x53\x6F" + "\x78\xC3\x51\xC0\xE0\x76\x2A\xC2\xB7\xFE\x02\x64" + "\x25\xF0\xCE\xD7\xA9\xBF\x85\xCA\x20\xA6\x93\x68" + "\xE3\x79\xE9\x88\xA8\x7F\x45\x8D\x71\xB4\xB4\x79" + "\x1C\x56\x68\xF9\xAE\x18\x76\xB9\x3F\xEE\x5B\x2C" + "\xC6\x61\x47\x34\x3B\xC5\x24\x2D\x3C\x6D\x16\x48" + "\x70\xD9\xDB\x2E\xB8\x42\x52\x81\x1C\x94\x39\xF0" + "\xF4\xC0\x8F\x44\xD3\xCF\xD5\xF9\xC1\x59\x61\x83" + "\xAE\xFD\xD0\xC4\x35\xD1\x0E\x55\x46\x5C\xBA\x3D" + "\x5C\x4A\x89\x15\xE8\x1D\x86\x28\xE5\xF5\x31\x0B" + "\x89\x59\xFE\x4A\xC3\x5D\xA5\x2A\x16\x37\x78\x41" + "\x58\x3A\x9E\xA3\xBD\x1F\xE6\x25\xCC\x18\x9E\xD2" + "\x1A\x99\x56\x66\x83\x78\xBB\x27\x3E\x28\xFE\xD4" + "\x74\xCB\x75\x2D\x82\x86\x55\xFB\x1C\xA4\xAF\x3F" + "\x84\x0A\xA0\xA1\x1C\x70\x34\x87\x2E\x73\x15\x38" + "\x8A\x27\xB1\x6C\x33\x95\xE5\x07", + .entprb = "\x38\xF2\xC4\x8F\x4B\x9C\x2F\x03\x67\x8C\x8A\x47" + "\xE1\xF2\x18\xC5\xB8\x4C\x05\x77\x77\x15\xA8\x94" + "\x1F\x1F\x45\x6D\xD0\xEF\x60\x67\x63\x12\x5D\x38" + "\x89\x22\x76\xF5\xF2\xC4\xE1\x15\x26\x7E\x8F\x52" + "\x79\x1E\x96\x71\xCD\xE7\x32\x95\x2B\x4E\xB2\xC2" + "\x92\x21\xC7\x48\xA2\xB1\xC5\x71\x44\x91\xE4\x4F" + "\xBE\xD3\x5E\xA9\xAB\xD3\xE2\xD1\xE2\xD8\x8F\x98" + "\x38\x03\x18\x29\x84\xA2\xCA\x6E\x72\x34\xC9\x51" + "\x6D\x8C\xE8\x09\x50\x71\x2A\x08\xB7\xCF\x74\xE6" + "\x11\xB6\x38\xF5\xBC\x24\xF7\x5B\x73\x34\xD5\x8B" + "\xBB\x15\xE3\x6F\x9A\x9B\x1E\x32\xB9\x6F\x5F\xE3" + "\xC9\x9F\xF6\xD9\x33\x03\xCD\x0D\x8E\xD4\x3F\x67" + "\x11\x65\x0A\x90\x67\x83\xC1\xCC\x70\xB1\xA9\x46" + "\x4B\x5E\x0B\x84\xDC\x02\xBA\x50\x1D\x4A\x5B\xC7" + "\xB4\x5E\xDF\x35\x01\x45\x3D\x64\x5C\x2E\xCD\xA6" + "\x20\xFB\x35\x74\xC0\x7C\x2D\x24\x66\xAB\x38\x12" + "\x38\xCE\x52\xCB\x38\x9B\x95\xDE\x0C\x2A\x8C\x9D" + "\xF7\x81\x48\x9E\xD6\x10\xF1\x83\x71\x44\x53\x2F" + "\xCE\xF3\xEC\xB3\x29\x67\xF1\x41\xFC\xD6\xB6\x49" + "\xE3\x13\x74\x4D\xB2\x3E\xEA\x73\x2B\x03\x68\xAC" + "\x2F\x57\x8C\x58\xEC\x34\xE9\xEF\x18\x36\xDE\xAD" + "\xE9\x48\x1D\xF7\x9E\xB7\xA1\x60\x2E\x78\xF5\x62" + "\x68\xDD\xB8\x5B\x33\x6B\x66\xAD\xA1\xD5\xFB\x46" + "\x5E\x8F\xF8\x9D\x37\xE5\xC2\xD8\x76\xDC\x2B\x6A" + "\x99\x1E\xDF\x91\xB1\x0A\x81\x2A\x9D\xEB\xE7\xE4" + "\xD1\x21\xD4\xDA\x0E\x55\x8A\x14\xB2\xB6\x15\x7D" + "\x48\x52\x6A\xB0\xA2\x92\x4D\x50", + .entprlen = 320, + .addtla = "\xC2\x89\x7C\x07\x46\x74\x02\x2C\xEA\xAD\xFD\x74" + "\x0C\x40\xEF\xA2\x95\x64\x6B\xC4\x2D\xED\xF4\x16" + "\x26\x25\x06\xB3\x36\x6B\xD8\x9A\x5F\xF4\x25\xC1" + "\xC3\x69\x3F\x7A\x19\xB7\x02\xA6\xCC\x3B\xA2\x4E" + "\x05\xA1\x1C\x7B\x2D\xAD\x44\xE7\x4A\x40\x71\x85" + "\xEF\x1C\xE4\xEC\x54\xCA\xB0\xAF\x8F\xF5\x43\xB1" + "\xE0\x99\x71\x71\xD4\x3E\x56\x97\xAA\xF5\xD0\x1A" + "\x58\x2D\x65\x0F\xA4\xB4\xB6\x07\x1B\x1F\x13\x8B" + "\x29\xD6\xE5\x23\xD3\x4D\x43\xD6\xBC\x74\xA8\x92" + "\xBD\xE9\x9B\x01\x47\x8C\xA5\x02\xA8\x0D\xC3\x3A" + "\xED\x83\xFD\xD2\xCB\xFF\x25\x89\x2C\x2F\x5B\x70" + "\x3F\x9E\x24\x50\xF8\x78\x28\x1B\x67\x52\x92\xA2" + "\x87\x81\x07\x40\xA9\x40\xBA\x84\x47\x25\xC1\xF7" + "\x9E\x3B\x4E\xE4\x8F\x10\xE5\x50\x8B\x22\x83\x4F" + "\xCD\x4E\x42\x63\x92\x0A\x5F\xAF\x7A\x9B\x0E\x1A" + "\xE3\xB4\x99\x11\x7F\xE6\x93\xC3\xED\xF1\x9F\x3A", + .addtlb = "\x1E\x75\xB6\x70\x60\xFD\xE6\xD1\xC7\xA5\x74\xCF" + "\xA7\x50\x17\xAE\xDD\xC4\x6E\xC4\xE0\x15\xF0\x3B" + "\xF7\x1C\x46\x45\xEE\x60\x66\x48\x1D\x2C\x36\xCC" + "\x95\x3E\xB7\xEB\x1B\xFF\x8C\xC0\x78\x6D\x56\x3A" + "\xC7\x24\x18\x9E\x7C\xA1\x60\x54\x41\x4B\xAF\x18" + "\xE8\x02\xD1\x54\x65\xEC\x3D\xFD\x8B\xDF\xD2\xF5" + "\x62\xEA\x66\x41\x6A\x32\x87\xA6\x34\x2F\x48\xBF" + "\xB5\xCC\x35\x5A\x2A\xC1\xAB\x68\x34\x1A\xD6\x82" + "\x40\xF7\xF2\x00\x14\x8B\x69\x0F\xE4\xCD\x6B\xB1" + "\xFC\x8B\x16\xEC\xB4\xE3\x33\xBF\x84\x12\x4B\x58" + "\xED\x51\x88\xF5\xEF\xB6\xC3\xCE\x9B\x63\xCC\x80" + "\x1F\x3C\x8A\x67\xEE\xCD\xD2\x01\x25\x22\xAC\xB3" + "\xB6\x9B\x1F\xF8\xE8\x71\xE6\x0D\x78\x11\x3C\x9E" + "\xF2\x57\xDC\xB6\xCF\x90\xD3\xA8\x3E\xCD\x88\xD4" + "\xDC\x1C\x31\x6B\x1F\xC3\x6A\x29\xF0\x7B\x4C\xCC" + "\x6D\x92\x5E\x6F\x0C\x0B\x4D\xA7\x10\x66\x84\x1F", + .addtllen = 192, + + .expected = "\xAA\x76\x91\xAE\x99\xCD\x8D\x83\x49\x9D\xC5\x51" + "\xA5\x95\xC6\x9D\xAD\x4B\x40\x2B\x5F\x8C\x30\x5D" + "\x1E\x89\x58\xD1\x8A\x86\xF9\x61\x2C\x45\x41\x8E" + "\xC5\xC6\x0E\x33\x7C\xFE\x91\x71\xC9\x53\x76\xD6" + "\xC2\x8D\x05\x09\xB8\x2A\x2B\x9B\x36\x1D\x31\xD7" + "\x50\x45\xB1\x08\x58\xC4\x99\x25\xEA\x2F\x18\xDB" + "\x34\x8A\x02\xD8\x38\xDD\x7B\x9E\x0E\xEF\x9C\x45" + "\xC7\x4F\x7E\x36\x3A\x90\x8B\x41\x51\x4A\x1B\xE9" + "\x8A\x61\xE9\xB5\x4E\xA5\xE2\xBD\x16\x59\x61\x0F" + "\x9C\x5A\x63\xA7\x87\x79\x5C\x0A\x16\xDF\x6D\x88" + "\x11\x25\x56\x8B\x5D\xA6\xF8\x4F\xB9\x01\x19\xAE" + "\x57\x3B\xC4\x06\xBB\xE7\xCB\xAF\xB3\x8D\xE2\x40" + "\xED\x42\x29\xB3\x0D\x64\x20\xF2\x66\x58\xB1\xDD" + "\x59\xB1\x39\x7C\xD9\xB2\x34\x08\x53\x9B\x3A\xB7" + "\x18\x35\xD0\x90\x7F\xB5\x30\xF2\x27\xA0\x90\x63" + "\x6F\xF2\x72\x49\xBF\xD0\xAE\x4A\xF4\xCA\xB3\x1A" + "\xAE\x7F\x93\xF3\xB9\x84\x99\x09\x50\xB9\xA0\x43" + "\x4F\x83\x33\x92\xA5\xC7\x25\x44\x6A\x74\xF4\xFA" + "\xBA\x60\x43\x13\x97\x53\x99\x98\xA3\x05\x02\xC1" + "\x03\xDF\x53\x76\x9E\x74\xE7\xA0\xB5\xD7\xA7\x87" + "\x1E\x00\x1D\x29\x47\x8F\x65\x4E\x0F\x76\xCA\xA9" + "\x2A\xC5\x05\x4F\xA6\xFE\x96\xC6\x81\xC0\x55\xFC" + "\x92\x89\xA6\x81\xF0\x37\xF1\x41\xA6\x88\x0B\x01" + "\xE0\xA5\x78\x4C\xF4\x61\xA7\x91\xD8\x4B\xE9\x2C" + "\xF0\x68\xEE\x46\x41\xD2\x74\xE5\x5F\x6F\x1F\xE6" + "\xBE\x5C\xB1\x3C\x60\x1A\xAA\xB9\x88\x3C\xB9\x1C" + "\xCD\x67\x78\x1F\x45\x18\xE7\x8B\xBD\xE4\x24\xDA" + "\xA8\x26\xD1\x03\xF1\xC7\x6B\x28\x62\xAB\x5C\xAB" + "\x98\xCA\xFB\xCB\x0B\x2D\x01\xD9\xC1\xA6\xFA\x91" + "\x71\x3D\x9B\x3B\x60\xEB\xD7\xA2\x61\xC1\x92\x60" + "\xB1\x02\x44\x0C\x97\x70\x77\x83\xF9\x35\xEA\x24" + "\x85\xF8\x0A\x32\xA2\xC7\x05\x40\x90\x83\x4F\x87" + "\x57\x66\xB5\xDE\xEE\xFF\x8B\x01\xBC\x96\xB0\xC5" + "\x29\xB6\xC1\xF0\x11\x31\x51\x11\xB0\xC2\x0F\x08" + "\xCF\x09\x69\x74\xE1\x0D\x6C\x0A\x10\xD0\x73\xF0" + "\x8E\xDC\x5F\xB1\xBD\x47\x8A\xA7\x90\xB3\x08\x86" + "\xD2\xE4\x58\xE5\x68\x33\x67\x3B\x37\xF1\x28\x28" + "\x59\x91\xB5\x5F\x8D\x84\x54\xCE\x18\x76\xE3\x5C" + "\x55\x37\x8E\x10\x34\x9B\x6E\x1F\x73\x88\x31\xBF" + "\x0D\x5C\xED\x7A\xBC\xF2\xCE\x7A\x2E\x2E\xE7\x04" + "\xE7\xF2\x8F\x33\xCC\x06\x77\x96\xBB\xA8\x65\x03" + "\x26\x79\xC0\xF0\x52\x3B\xD4\xF2\x5D\x00\xE4\x80" + "\x7F\x78\xC0\x45\x29\x55\xCA\x63", + .expectedlen = 512, + } +}; + /* Test vector obtained during NIST ACVP testing */ static const struct drbg_testvec drbg_nopr_hmac_sha512_tv_template[] = { { From 8237a5f626a2fdfbc8325c4ab672b4e04f564619 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:00 -0700 Subject: [PATCH 027/196] crypto: testmgr - Update test for drbg_nopr_hmac_sha512 Synchronize the drbg_nopr_hmac_sha512 test vector with the first test vector from the latest ACVP json files, so that both of the DRBG test vectors are pulled from a consistent source. Note that the new test vector has a nonempty personalization string. That should be helpful as well: Some FIPS labs require this, due to their interpretation of SP800-90A 11.3.2 which says that a "representative" value of the personalization string must be tested. It also now does an explicit reseed, which makes it clearer that the requirement to test "Reseed" is met, without having to interpret the additional input processing as covering that. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/testmgr.c | 13 ++- crypto/testmgr.h | 249 ++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 215 insertions(+), 47 deletions(-) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 5a984b3b9a9b..ad4c2e66b812 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -3504,10 +3504,21 @@ static int drbg_cavs_test(const struct drbg_testvec *test, int pr, crypto_rng_set_entropy(drng, test->entropy, test->entropylen); ret = crypto_rng_reset(drng, test->pers, test->perslen); if (ret) { - printk(KERN_ERR "alg: drbg: Failed to reset rng\n"); + printk(KERN_ERR "alg: drbg: Failed to instantiate rng\n"); goto outbuf; } + if (test->ent_reseed_len) { + crypto_rng_set_entropy(drng, test->ent_reseed, + test->ent_reseed_len); + ret = crypto_rng_reset(drng, test->addtl_reseed, + test->addtl_reseed_len); + if (ret) { + printk(KERN_ERR "alg: drbg: Failed to reseed rng\n"); + goto outbuf; + } + } + if (pr) crypto_rng_set_entropy(drng, test->entpra, test->entprlen); ret = crypto_rng_generate(drng, test->addtla, test->addtllen, diff --git a/crypto/testmgr.h b/crypto/testmgr.h index 77935a457313..fc70ca86d61f 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -120,16 +120,27 @@ struct aead_testvec { }; struct drbg_testvec { + /* Instantiate */ const unsigned char *entropy; size_t entropylen; + const unsigned char *pers; + size_t perslen; + + /* Reseed (optional) */ + const unsigned char *ent_reseed; + size_t ent_reseed_len; + const unsigned char *addtl_reseed; + size_t addtl_reseed_len; + + /* Generate (twice) */ const unsigned char *entpra; const unsigned char *entprb; size_t entprlen; const unsigned char *addtla; const unsigned char *addtlb; size_t addtllen; - const unsigned char *pers; - size_t perslen; + + /* Expected output from last call to Generate */ const unsigned char *expected; size_t expectedlen; }; @@ -23901,52 +23912,198 @@ static const struct drbg_testvec drbg_pr_hmac_sha512_tv_template[] = { } }; -/* Test vector obtained during NIST ACVP testing */ static const struct drbg_testvec drbg_nopr_hmac_sha512_tv_template[] = { + /* + * Borrowed from the first applicable test vector from ACVP: + * https://github.com/usnistgov/ACVP-Server/blob/v1.1.0.33/gen-val/json-files/hmacDRBG-1.0/prompt.json#L4596 + * https://github.com/usnistgov/ACVP-Server/blob/v1.1.0.33/gen-val/json-files/hmacDRBG-1.0/expectedResults.json#L986 + */ { - .entropy = (unsigned char *) - "\xDF\xB0\xF2\x18\xF0\x78\x07\x01\x29\xA4\x29\x26" - "\x2F\x8A\x34\xCB\x37\xEF\xEE\x41\xE6\x96\xF7\xFF" - "\x61\x47\xD3\xED\x41\x97\xEF\x64\x0C\x48\x56\x5A" - "\xE6\x40\x6E\x4A\x3B\x9E\x7F\xAC\x08\xEC\x25\xAE" - "\x0B\x51\x0E\x2C\x44\x2E\xBD\xDB\x57\xD0\x4A\x6D" - "\x80\x3E\x37\x0F", - .entropylen = 64, - .expected = (unsigned char *) - "\x48\xc6\xa8\xdb\x09\xae\xde\x5d\x8c\x77\xf3\x52" - "\x92\x71\xa7\xb9\x6d\x53\x6d\xa3\x73\xe3\x55\xb8" - "\x39\xd6\x44\x2b\xee\xcb\xe1\x32\x15\x30\xbe\x4e" - "\x9b\x1e\x06\xd1\x6b\xbf\xd5\x3e\xea\x7c\xf5\xaa" - "\x4b\x05\xb5\xd3\xa7\xb2\xc4\xfe\xe7\x1b\xda\x11" - "\x43\x98\x03\x70\x90\xbf\x6e\x43\x9b\xe4\x14\xef" - "\x71\xa3\x2a\xef\x9f\x0d\xb9\xe3\x52\xf2\x89\xc9" - "\x66\x9a\x60\x60\x99\x60\x62\x4c\xd6\x45\x52\x54" - "\xe6\x32\xb2\x1b\xd4\x48\xb5\xa6\xf9\xba\xd3\xff" - "\x29\xc5\x21\xe0\x91\x31\xe0\x38\x8c\x93\x0f\x3c" - "\x30\x7b\x53\xa3\xc0\x7f\x2d\xc1\x39\xec\x69\x0e" - "\xf2\x4a\x3c\x65\xcc\xed\x07\x2a\xf2\x33\x83\xdb" - "\x10\x74\x96\x40\xa7\xc5\x1b\xde\x81\xca\x0b\x8f" - "\x1e\x0a\x1a\x7a\xbf\x3c\x4a\xb8\x8c\xaf\x7b\x80" - "\xb7\xdc\x5d\x0f\xef\x1b\x97\x6e\x3d\x17\x23\x5a" - "\x31\xb9\x19\xcf\x5a\xc5\x00\x2a\xb6\xf3\x99\x34" - "\x65\xee\xe9\x1c\x55\xa0\x3b\x07\x60\xc9\xc4\xe4" - "\xf7\x57\x5c\x34\x9f\xc6\x31\x30\x3f\x23\xb2\x89" - "\xc0\xe7\x50\xf3\xde\x59\xd1\x0e\xb3\x0f\x78\xcc" - "\x7e\x54\x5e\x61\xf6\x86\x3d\xb3\x11\x94\x36\x3e" - "\x61\x5c\x48\x99\xf6\x7b\x02\x9a\xdc\x6a\x28\xe6" - "\xd1\xa7\xd1\xa3", - .expectedlen = 256, - .addtla = (unsigned char *) - "\x6B\x0F\x4A\x48\x0B\x12\x85\xE4\x72\x23\x7F\x7F" - "\x94\x7C\x24\x69\x14\x9F\xDC\x72\xA6\x33\xAD\x3C" - "\x8C\x72\xC1\x88\x49\x59\x82\xC5", - .addtlb = (unsigned char *) - "\xC4\xAF\x36\x3D\xB8\x5D\x9D\xFA\x92\xF5\xC3\x3C" - "\x2D\x1E\x22\x2A\xBD\x8B\x05\x6F\xA3\xFC\xBF\x16" - "\xED\xAA\x75\x8D\x73\x9A\xF6\xEC", - .addtllen = 32, - .pers = NULL, - .perslen = 0, + /* .entropy = ACVP entropyInput || nonce */ + .entropy = "\x47\x28\x33\x05\x82\xE8\xA7\x58\x05\xBD\x07\x9E" + "\xDB\x59\x87\x08\x3B\x82\x40\x70\xA1\xB7\x33\x4F" + "\x0F\x53\xBE\xF6\x98\x75\xFA\x21\x00\x04\xBC\x58" + "\x9B\xB1\xB3\xBC\x2A\xF6\xA4\x2A\xE1\xB3\x65\x24" + "\xA8\xEE\x56\x70\x5E\x28\x06\x04\x80\xCE\xB7\x36" + "\xA4\xD1\x4E\xAA\xE7\xE8\x51\x40\x7D\x30\xF7\x91" + "\xF2\x9E\x98\xA7\xBB\xB3\x1D\xC6\x8A\x62\xC7\xE7" + "\x1F\xE1\x0A\x52\x45\x39\x88\x92\x43\xA6\x5B\xC3" + "\x9D\x60\xDE\xFE\x79\xEF\x87\x6F\xD5\x76\x51\x69" + "\x7B\x4C\x3D\x08\x60\xFA\xDC\x00\x94\xEC\x0A\xC5" + "\xE7\xCB\x30\x05\x9F\xCC\x07\x44\x07\x14\xF4\xF9" + "\xBC\x7D\xC0\x66\x63\x5B\xD3\x2A\xA7\xF2\x1D\x75" + "\x3F\x28\x5F\x4A\xEB\x63\xD7\x92\x5A\x9A\x7C\x3A" + "\x56\xEA\xCB\xA9\xA0\xF9\x5B\x99\xC2\x7D\x31\xBF" + "\x44\xC7\x64\x6B\x7E\x64\x60\x64\x05\x86\xF0\x6B" + "\x76\xA7\x3E\x63\xAD\xB6\x76\xED\x3D\x05\x2E\xC7" + "\xC7\x52\x8F\x07\x56\x23\xFC\x2F\x93\xD5\xF2\x29" + "\xC6\x84\x48\xD1\x88\xB9\x3F\x84\xB2\x93\xFC\x2F" + "\x00\xB1\xBC\xBE\xAC\xC4\x94\x36\xF1\x2B\xF0\xC7" + "\x36\xE8\x1D\x45\x0A\xA2\xFE\x72\xD7\x3E\x15\x6A" + "\x74\x23\xB2\xD1\x3C\x20\xF2\xB7\x19\xC5\xF0\x74" + "\x69\x06\xD1\x92\x47\xC9\x68\xDC\xEE\xBC\xF4\x3A" + "\x8B\x7C\xA4\xA4\x4A\x15\xF4\xF0\x26\x26\xC5\x7D" + "\x57\xDC\x00\x59\x07\xDF\x84\x2A\x23\xA9\xC1\xAF" + "\x47\x49\x88\xCC\x2F\x3B\x90\x39\xA0\x09\xAE\x3C" + "\x79\xF9\x97\x9D\xEF\x13\x1D\x2B\xB6\x18\xDB\xCF" + "\x95\x98\x17\x7F\xF6\x95\x44\x3A\x40\x90\x63\x16" + "\x70\x38\x22\xC5\xD8\xE4\x57\xA0\x8E\x51\x6B\xED" + "\x03\x18\xC6\x74\xFA\xCA\xF2\xD5\xB2\x5A\x0C\x02" + "\x48\x9F\x70\x0B\x1C\x0A\xD1\xD6\x4F\x3F\x70\x3C" + "\x1A\x62\x29\x63\xD0\x92\x76\x30\x7C\xB9\x54\xEC" + "\xF6\x92\xA3\x11\x66\xB2\x56\xE0\x75\x3D\x27\x01", + .entropylen = 384, + .pers = "\x03\x75\x33\x7B\x6B\xE5\x14\xAF\x0E\x43\x33\xCC\xD3" + "\xF4\xF0\x8B\x8A\xCC\xFE\x95\xC1\x20\xB9\x56\x3D\x2C" + "\x34\xC7\xA1\x4C\xBC\xDC\x0A\x8D\xBE\x68\x28\x89\x2A" + "\x92\x10\x05\x4E\xF9\xE2\x51\xF7\x4F\xF4\x48\x76\xC9" + "\xCE\xA8\x6D\xC1\xDE\x5C\x05\x95\x77\x24\xB4\x5D\x3D" + "\x16\x1D\xCB\x43\xE5\xD3\x01\x96\xCC\x3E\x2E\xE1\x97" + "\xB3\x42\xC2\xAB\xEC\x56\xA9\xF9\xF2\x28\x59\x01\x4E" + "\xFC\x8A\xC0\x5E\x4E\x33\x30\x91\x96\x93\xBA\xFA\xE1" + "\x9F\x20\xC3\xC1\xD1\xC6\xC3\x2C\x59\x8F\x56\xD5\x73" + "\xE8\x8D\xCF\xAC\xB1\x85\x3E\xC7\x73\x21\x59\x8D\x0F" + "\xF4\xA4\xC4\x0C\xD2\x18\x81\x5F\x3E\x37\xC9\x9F\xD9" + "\xDE\x3F\x15\x6F\xAC\x1A\xEC\x5E\x28\xD5\x56\xA2\x65" + "\xD2\x7C\x41\xDE\x57\x8C\x60\xAB\xA5\x03\x42\xC8\x3C" + "\x70\xC2\xD1\x11\x62\x25\x4E\x17\x58\xBB\x08\x51\x79" + "\xE6\xED\xBA\x9A\xA7\x07\xD5\x0E\x89\x43\x31\x4F\x99" + "\xEE\xED\xF1\x36\xFA\x1E\xC0\x25\x01\xDA\x19\xC2\x7D" + "\x5D\x78\x74\x5C\xC0\x72\x2E\xF1\x7B\x4E\x9C\xDB\xFE" + "\x60\x89\x62\x71\x9C\xEA\xD3\xDF\x82\xC7\x8B\xB4\x7B" + "\x7B\x7F\x6A\x62\x3C\x57\x76\xA5\x67\x5F\x70\xFB\xE0" + "\x1B\x23\x79\x71\xB5\x7C\xEA\x76\x99", + .perslen = 256, + + .ent_reseed = "\xE0\x5B\x69\xC5\xF9\xD4\x5A\x1F\xC1\x71\x0C" + "\x37\x6F\xFE\x31\xE0\xEF\x3E\x9B\xD5\x46\x43" + "\xA2\x15\xFA\x86\x75\x1C\x95\x9F\xE6\xD6\x41" + "\x50\x36\x0F\x67\x68\x4A\x72\x32\x85\xB0\xCB" + "\xA4\x0D\x1F\xA2\x43\xCA\x30\xF1\x42\xF8\xC4" + "\x17\x6A\xD1\x2D\x43\x46\x8C\xA5\x72\x3C\xB1" + "\x44\x8E\xA1\x75\xAA\x20\x30\xDD\xCD\x0B\x5A" + "\x0D\xE6\x28\xCA\xBC\xA9\x3B\x11\x23\x88\x85" + "\xDF\xD8\x84\x11\x89\x7A\x4F\x00\x90\x0B\xD8" + "\x8A\x35\xE9\x5F\xEC\x05\x42\x15\xCA\x7E\xA3" + "\xEF\xEF\xE3\xB7\xBE\x96\x8C\x36\x7D\x15\x3C" + "\x7A\x78\x00\x61\xAF\x62\x45\xA7\x4B\xAE\x4A" + "\xFD\xC9\xE0\x89\x53\x36\x71\x8F\x38\xC4\x00" + "\x57\xD9\xE6\xC1\xEC\xBF\xF7\x4B\x3F\x55\xD6" + "\x54\x15\x72\xB2\x23\x76\xD1\x4E\x8E\x7E\xFB" + "\xC8\xD6\xA4\xA4\x7E\x8E\xD8\x76\xD3\xEB\x90" + "\x90\xEB\xB3\x84\x26\x34\x93\x36\xCA\xA9\x12" + "\xD3\x6D\x84\x07\xE1\x0E\xE7\x63\x24\x54\x90" + "\x42\x8C\x6B\xE7\x21\x53\x2D\x16\xE9\x68\xA9" + "\xC2\x9A\x7A\x93\x31\x5E\x35\x72\xE2\x0F\x3D" + "\x55\x41\x8C\xC5\xD1\xBB\xEE\x5F\x3C\x95\x52" + "\x2A\x65\x47\xB6\x84\x6A\x05\x19\xD9\xE7\x68" + "\x15\xFA\x49\xD9\x9D\xFD\x47\x9F\xB9\xA6\xBB" + "\xA8\xD4\x22\x6C\x8B\x59\x47\xEF\xD1\xD0\xBF" + "\xBC\xE4\x53\x31\x2F\xA5\xD4\x2C\x89\xCA\xE5" + "\x29\x64\xF8\x51\x2A\x02\xDE\x31\x0D\x54\x0E" + "\x0E\xB8\x78\xE6\x2A\x3E\x31\xA2\xA4\xCD\x91" + "\x79\xF2\x9B\x04\xA0\xDB\x78\xAC\x0D\xB5\xCA" + "\x60\x4C\x08\x96\xCA\x8A\xE9\x93\x9F\x62\x38" + "\xAE", + .ent_reseed_len = 320, + .addtl_reseed = "\xD5\x46\x71\x38\x46\xE0\xC1\x27\x2C\xF1\x07" + "\xDD\x29\x73\xD7\xF4\x5A\x3A\xE0\x99\x98\x0A" + "\xEB\xA5\x9E\x2E\x49\x21\x7B\x18\xC0\xD8\x3D" + "\xEE\x49\xF9\x52\x7C\x55\x5E\x5E\x06\xC2\x7E" + "\x34\x3A\xA5\xB7\x78\x21\xC1\xB8\x8B\x4E\x07" + "\x1F\x3F\xC4\xB4\x9B\x3F\x20\x2D\xEE\x70\x3B" + "\x18\xCF\x2B\x50\x15\x1B\xF3\x6C\xE7\x9F\x2A" + "\x2B\x69\x53\xCA\x88\x41\xA9\x07\x31\x14\x55" + "\xBD\x75\x49\x68\x98\x48\xCA\x46\xA5\xEC\xAA" + "\x9D\x8E\x6F\x40\xBA\xCA\xC8\xE9\x9F\xA4\xC5" + "\x94\x89\x2C\x4D\xE4\x0A\x66\xD3\xDB\x1A\xD9" + "\xA7\x3F\x6B\x0A\xE0\xE4\xDC\x0B\x8B\x64\xBF" + "\xB4\x95\xA1\xAE\x92\xA8\x7C\xE2\x4B\xED\xFD" + "\xFD\xE0\x54\x48\x7C\x25\xD6\xD1\x0A\xAB\x5E" + "\x33\x2F\x1D\xD3\x62\x47\xAB\x35\x8C\xA1\xC2" + "\x75\xDD\x75\xCA\x09\xE1\x38\xDE\x87\x79\x0C" + "\xD7\x5D\x3E\x6D\x28\x8F\x12\x98\x2C\x26\x34" + "\x91\x0B\x6B\xB7\x73", + .addtl_reseed_len = 192, + + .addtla = "\xC8\xE1\x03\x59\xEA\x9F\xD3\x1F\xCC\xCB\x5A\x3E" + "\x23\xDB\x47\x75\x1B\x3A\x6C\x0B\xED\xE6\xC0\xB6" + "\x4B\x82\x53\x5B\x6D\xEE\x2B\x97\x0F\x59\x07\xA4" + "\xFE\xE2\x26\x4F\xFF\xF7\x46\xAF\x62\xC4\x42\xE8" + "\x06\xFA\x1F\xAA\x66\xF3\xA4\xCF\x85\x02\x3C\x11" + "\xEF\xD2\x16\x13\x7A\xBD\x03\x66\xC3\x4D\x6F\x3A" + "\xE5\xD3\xFF\x92\xB6\x45\xB8\x88\x94\x42\x2E\x84" + "\x02\xA5\x54\x12\xBF\xCB\xF1\x6E\x1C\x0C\x23\xFE" + "\x8A\xFD\xF5\x1A\x4C\xD6\x2A\x34\x7F\x21\x50\xBB" + "\x06\x64\x9A\x77\x70\x59\x1D\x12\xD1\xA0\x10\x70" + "\xD7\x4F\x3C\xEE\x82\xEF\x5B\x35\x8F\x05\xF6\x51" + "\xBC\x28\xE1\xB1\x54\xFF\x25\x12\x16\x2C\x62\xFC" + "\xB9\x74\x5E\x78\x41\xB2\x04\x80\x4E\xB1\x43\x2E" + "\x88\x7F\x34\xA4\x33\x66\xE8\x68\x60\x54\xEB\xCE" + "\xD1\x5F\xC4\xD6\x21\x5E\x22\x1A\x7E\xC5\x6D\xB7" + "\x93\x8F\x9C\x77\x6E\x56\xA5\xA8\xF7\xB2\x10\x19", + .addtlb = "\xB8\x1E\x9E\xE2\xB3\xE4\x04\x43\x51\x7B\x96\x32" + "\xAC\x95\xF2\x1E\x5E\x7A\xBF\x68\xE3\x7A\xCE\xE5" + "\x2B\x3B\xB0\x34\x7F\xE1\xB5\x37\x3C\x5B\xD2\x6B" + "\x17\xF6\x18\xAF\x7C\x01\xA5\x84\xFE\x07\x0B\x46" + "\xCC\x96\x61\xAB\xCD\x81\x95\x8A\x8A\xB6\xD8\xCC" + "\x94\x80\x45\xF6\xFF\x95\x3A\xB8\xDC\xBF\xB4\xBF" + "\x26\x8C\xE9\x79\x05\x58\x9C\x03\x08\x45\xB5\xC4" + "\xD8\xB4\xCD\x76\x13\xAE\x2B\xCC\xB5\x3E\x3C\x65" + "\x7A\xAA\xDC\x9B\x0B\x13\x8B\x82\x5A\x39\x60\x9A" + "\xF7\xA8\x38\xB5\x83\x8E\x0B\xD1\xE6\xBF\xA1\xDC" + "\x30\x45\xCC\x67\x41\x0F\xF9\x86\x27\xE0\x22\x3E" + "\x0D\x1F\x92\x13\x16\x9B\x84\x79\x91\xFE\xBC\xDF" + "\x15\x6C\xDC\xAE\xC5\x64\x46\x9C\xE8\xEA\xBB\x9D" + "\x27\xA2\x1E\xDF\xB2\xF2\x98\xB4\x88\x4E\x22\x5F" + "\x3C\xD0\x35\x2C\x5C\x89\xC7\xEC\xE3\xF3\x09\x60" + "\xEF\xAC\x78\xBF\x94\xAA\x8C\x30\x7F\xCF\xE4\x4B", + .addtllen = 192, + + .expected = "\x93\xFF\x4F\x4A\xA7\xE0\xFC\x3B\xCF\xCE\x57\xCD" + "\xFD\xE9\x94\x6D\x0D\x45\x7E\xA3\x98\xBB\xE6\x54" + "\x36\xF9\x92\xE6\xBB\xC5\x93\x16\x69\x35\x01\xF0" + "\x5A\xE2\x43\xFC\x73\x7C\xA3\x5C\x5B\x49\x72\x69" + "\x6A\xC4\xB6\xD4\xB2\x48\x27\x72\xCA\xE3\xF3\xB8" + "\xD6\x95\x9F\x39\xC8\xD7\x72\xAF\xC2\x7C\x75\xE5" + "\xA4\xF7\x52\x4F\xDF\x80\x75\xCA\x4B\xFA\x75\x9A" + "\x7A\x8D\x48\x94\x30\x1C\x82\x5E\xD6\x3F\xF1\x78" + "\x84\xAA\x8D\x8B\x4F\x6A\x20\x12\xA2\x65\xC5\x02" + "\x32\xA1\xE4\x6B\x86\x2F\xCF\x92\xCD\x01\x55\xF7" + "\xB8\xAB\xC3\x2C\x42\xC3\xFD\x9B\x59\x2D\x47\x8E" + "\xB6\x8D\xE7\x04\x2E\x67\xD9\x07\x14\xA3\xF2\x74" + "\x79\x9C\xAB\xC6\xD6\x52\x3E\x91\x81\xA4\x3C\x9A" + "\x3E\x10\x1E\xD0\x28\xBC\x1C\x50\xF0\xB6\xEC\x01" + "\xE5\x40\x16\x08\xB5\x58\xE0\xC4\xC2\x9A\xBB\x13" + "\xAB\x10\x4B\x07\x24\x09\xEB\xF9\x5E\xAA\x3E\x3A" + "\x25\x34\x5B\x97\x92\xF9\x46\x8A\x8E\x5A\x06\x9C" + "\x2B\x1C\x8E\x47\x19\xC3\x3B\x14\x8A\xC1\xEB\xF7" + "\xB0\xA2\x05\xE0\x70\x12\x88\x21\xFF\xC0\x35\x6D" + "\xE9\x08\x7E\x11\x6E\xD7\x16\x48\x24\x43\xAF\x33" + "\xA3\x48\x44\x91\xC5\x32\x1D\x87\xF6\x9B\x10\x1C" + "\xA4\x7A\x74\x23\xB3\xFC\xB9\x87\x08\xE6\x9A\xEF" + "\xD5\x93\x82\x17\xD4\x78\xDA\x46\x34\xC2\x61\x8C" + "\xB7\x53\x89\xC4\x8A\xD8\xA0\x2E\xCE\xCA\x24\x16" + "\xF0\x18\x7F\xC3\x12\x3F\xD0\xB1\xEF\x37\x99\xA8" + "\x04\x1F\x76\x50\x81\x08\xCD\x4D\x43\xEF\x64\xB6" + "\x03\x57\xB7\x5F\xDD\xF6\xBA\x34\xE2\x88\xE7\x1F" + "\x62\xA5\xA4\x05\xEB\x1A\xFE\x0B\xFE\x74\x7D\x64" + "\x29\x83\xE8\x0B\x97\x7D\x94\x5B\xF9\x3C\x8E\xC8" + "\x6B\xCD\xAD\x63\x32\x6E\x00\xBF\x8E\x57\xF2\x32" + "\x88\x53\x17\x40\xE3\xF8\xF8\xD9\xFD\xCD\x76\x84" + "\xC6\xFD\xB1\x10\x40\xED\x75\xDD\xBD\x78\x8B\x0A" + "\x61\x1E\xCC\xC4\x4F\x95\xF1\x2F\x8F\x5A\xF0\x12" + "\x00\xCE\x75\xB8\xE9\xAB\x63\xC0\x7A\xF6\x9A\x47" + "\xD2\x3C\xB0\xAD\xAF\x03\xDF\x25\xDD\x0C\x0F\xB6" + "\x29\x09\x0F\x28\x5E\xA8\x67\xBB\xC9\x78\xBE\x12" + "\xD8\xD6\xD0\x98\x82\x29\xA3\x82\xFB\x8E\x1C\x79" + "\x28\x52\x22\x73\x3C\x6F\xB5\x33\xFF\x40\x26\x4C" + "\x30\xE4\xE0\x39\x59\x72\x65\x79\x9F\xB7\x89\x87" + "\x64\xAC\x45\x11\x0D\xDD\xC0\x44\x5E\x0D\xDF\xDB" + "\x91\x42\x5F\x52\x7F\xBB\x66\xEE\x32\x90\x8F\x6F" + "\xF8\xB9\xFE\xEA\x42\xFB\x60\x2B\xE3\xD9\xB2\xD1" + "\x74\x37\x14\xC6\xDA\x68\xE6\x09", + .expectedlen = 512, } }; From 89cfd38c788e9d8a2d05d1487c4513043e6d46a2 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:01 -0700 Subject: [PATCH 028/196] crypto: drbg - Remove support for HMAC-SHA256 and HMAC-SHA384 Remove support for the HMAC-SHA256 and HMAC-SHA384 variants of HMAC_DRBG, leaving only the HMAC-SHA512 variant of HMAC_DRBG. HMAC-SHA512 is already the default. The default did used to be HMAC-SHA256, but several years ago it was upgraded to HMAC-SHA512 "to support compliance with SP800-90B and SP800-90C". Given that the point of crypto/drbg.c is compliance with those standards, and there's also no technical reason to prefer HMAC-SHA384 in this situation even if acceptable, there's really no point in offering anything else. Note: now that only HMAC-SHA512 remains, a lot of unnecessary abstractions can be removed. A later commit will do that. This commit just straightforwardly removes the HMAC-SHA256 and HMAC-SHA384 code. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 22 +--- crypto/testmgr.c | 27 ----- crypto/testmgr.h | 280 ----------------------------------------------- 3 files changed, 2 insertions(+), 327 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index 6301eb2e304c..81bccacd3595 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -1,9 +1,7 @@ /* * DRBG: Deterministic Random Bits Generator - * Based on NIST Recommended DRBG from NIST SP800-90A with the following - * properties: - * * HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores - * * with and without prediction resistance + * Implementation of the HMAC SHA-512 DRBG from NIST SP800-90A, + * both with and without prediction resistance * * Copyright Stephan Mueller , 2014 * @@ -215,18 +213,6 @@ enum drbg_prefixes { */ static const struct drbg_core drbg_cores[] = { { - .flags = DRBG_HMAC | DRBG_STRENGTH256, - .statelen = 48, /* block length of cipher */ - .blocklen_bytes = 48, - .cra_name = "hmac_sha384", - .backend_cra_name = "hmac(sha384)", - }, { - .flags = DRBG_HMAC | DRBG_STRENGTH256, - .statelen = 32, /* block length of cipher */ - .blocklen_bytes = 32, - .cra_name = "hmac_sha256", - .backend_cra_name = "hmac(sha256)", - }, { .flags = DRBG_HMAC | DRBG_STRENGTH256, .statelen = 64, /* block length of cipher */ .blocklen_bytes = 64, @@ -276,10 +262,6 @@ static int drbg_fini_hash_kernel(struct drbg_state *drbg); MODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha512"); MODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha512"); -MODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha384"); -MODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha384"); -MODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha256"); -MODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha256"); /* update function of HMAC DRBG as defined in 10.1.2.2 */ static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed, diff --git a/crypto/testmgr.c b/crypto/testmgr.c index ad4c2e66b812..4199b7d3e9fb 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -4649,21 +4649,6 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "digest_null", .test = alg_test_null, - }, { - .alg = "drbg_nopr_hmac_sha256", - .test = alg_test_drbg, - .fips_allowed = 1, - .suite = { - .drbg = __VECS(drbg_nopr_hmac_sha256_tv_template) - } - }, { - /* - * There is no need to specifically test the DRBG with every - * backend cipher -- covered by drbg_nopr_hmac_sha512 test - */ - .alg = "drbg_nopr_hmac_sha384", - .test = alg_test_null, - .fips_allowed = 1 }, { .alg = "drbg_nopr_hmac_sha512", .test = alg_test_drbg, @@ -4671,18 +4656,6 @@ static const struct alg_test_desc alg_test_descs[] = { .suite = { .drbg = __VECS(drbg_nopr_hmac_sha512_tv_template) } - }, { - .alg = "drbg_pr_hmac_sha256", - .test = alg_test_drbg, - .fips_allowed = 1, - .suite = { - .drbg = __VECS(drbg_pr_hmac_sha256_tv_template) - } - }, { - /* covered by drbg_pr_hmac_sha256 test */ - .alg = "drbg_pr_hmac_sha384", - .test = alg_test_null, - .fips_allowed = 1 }, { .alg = "drbg_pr_hmac_sha512", .test = alg_test_drbg, diff --git a/crypto/testmgr.h b/crypto/testmgr.h index fc70ca86d61f..c47203f73fd1 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -23433,286 +23433,6 @@ static const struct aead_testvec aegis128_tv_template[] = { }, }; -static const struct drbg_testvec drbg_pr_hmac_sha256_tv_template[] = { - { - .entropy = (unsigned char *) - "\x99\x69\xe5\x4b\x47\x03\xff\x31\x78\x5b\x87\x9a" - "\x7e\x5c\x0e\xae\x0d\x3e\x30\x95\x59\xe9\xfe\x96" - "\xb0\x67\x6d\x49\xd5\x91\xea\x4d\x07\xd2\x0d\x46" - "\xd0\x64\x75\x7d\x30\x23\xca\xc2\x37\x61\x27\xab", - .entropylen = 48, - .entpra = (unsigned char *) - "\xc6\x0f\x29\x99\x10\x0f\x73\x8c\x10\xf7\x47\x92" - "\x67\x6a\x3f\xc4\xa2\x62\xd1\x37\x21\x79\x80\x46" - "\xe2\x9a\x29\x51\x81\x56\x9f\x54", - .entprb = (unsigned char *) - "\xc1\x1d\x45\x24\xc9\x07\x1b\xd3\x09\x60\x15\xfc" - "\xf7\xbc\x24\xa6\x07\xf2\x2f\xa0\x65\xc9\x37\x65" - "\x8a\x2a\x77\xa8\x69\x90\x89\xf4", - .entprlen = 32, - .expected = (unsigned char *) - "\xab\xc0\x15\x85\x60\x94\x80\x3a\x93\x8d\xff\xd2" - "\x0d\xa9\x48\x43\x87\x0e\xf9\x35\xb8\x2c\xfe\xc1" - "\x77\x06\xb8\xf5\x51\xb8\x38\x50\x44\x23\x5d\xd4" - "\x4b\x59\x9f\x94\xb3\x9b\xe7\x8d\xd4\x76\xe0\xcf" - "\x11\x30\x9c\x99\x5a\x73\x34\xe0\xa7\x8b\x37\xbc" - "\x95\x86\x23\x50\x86\xfa\x3b\x63\x7b\xa9\x1c\xf8" - "\xfb\x65\xef\xa2\x2a\x58\x9c\x13\x75\x31\xaa\x7b" - "\x2d\x4e\x26\x07\xaa\xc2\x72\x92\xb0\x1c\x69\x8e" - "\x6e\x01\xae\x67\x9e\xb8\x7c\x01\xa8\x9c\x74\x22" - "\xd4\x37\x2d\x6d\x75\x4a\xba\xbb\x4b\xf8\x96\xfc" - "\xb1\xcd\x09\xd6\x92\xd0\x28\x3f", - .expectedlen = 128, - .addtla = NULL, - .addtlb = NULL, - .addtllen = 0, - .pers = NULL, - .perslen = 0, - }, { - .entropy = (unsigned char *) - "\xb9\x1f\xe9\xef\xdd\x9b\x7d\x20\xb6\xec\xe0\x2f" - "\xdb\x76\x24\xce\x41\xc8\x3a\x4a\x12\x7f\x3e\x2f" - "\xae\x05\x99\xea\xb5\x06\x71\x0d\x0c\x4c\xb4\x05" - "\x26\xc6\xbd\xf5\x7f\x2a\x3d\xf2\xb5\x49\x7b\xda", - .entropylen = 48, - .entpra = (unsigned char *) - "\xef\x67\x50\x9c\xa7\x7d\xdf\xb7\x2d\x81\x01\xa4" - "\x62\x81\x6a\x69\x5b\xb3\x37\x45\xa7\x34\x8e\x26" - "\x46\xd9\x26\xa2\x19\xd4\x94\x43", - .entprb = (unsigned char *) - "\x97\x75\x53\x53\xba\xb4\xa6\xb2\x91\x60\x71\x79" - "\xd1\x6b\x4a\x24\x9a\x34\x66\xcc\x33\xab\x07\x98" - "\x51\x78\x72\xb2\x79\xfd\x2c\xff", - .entprlen = 32, - .expected = (unsigned char *) - "\x9c\xdc\x63\x8a\x19\x23\x22\x66\x0c\xc5\xb9\xd7" - "\xfb\x2a\xb0\x31\xe3\x8a\x36\xa8\x5a\xa8\x14\xda" - "\x1e\xa9\xcc\xfe\xb8\x26\x44\x83\x9f\xf6\xff\xaa" - "\xc8\x98\xb8\x30\x35\x3b\x3d\x36\xd2\x49\xd4\x40" - "\x62\x0a\x65\x10\x76\x55\xef\xc0\x95\x9c\xa7\xda" - "\x3f\xcf\xb7\x7b\xc6\xe1\x28\x52\xfc\x0c\xe2\x37" - "\x0d\x83\xa7\x51\x4b\x31\x47\x3c\xe1\x3c\xae\x70" - "\x01\xc8\xa3\xd3\xc2\xac\x77\x9c\xd1\x68\x77\x9b" - "\x58\x27\x3b\xa5\x0f\xc2\x7a\x8b\x04\x65\x62\xd5" - "\xe8\xd6\xfe\x2a\xaf\xd3\xd3\xfe\xbd\x18\xfb\xcd" - "\xcd\x66\xb5\x01\x69\x66\xa0\x3c", - .expectedlen = 128, - .addtla = (unsigned char *) - "\x17\xc1\x56\xcb\xcc\x50\xd6\x03\x7d\x45\x76\xa3" - "\x75\x76\xc1\x4a\x66\x1b\x2e\xdf\xb0\x2e\x7d\x56" - "\x6d\x99\x3b\xc6\x58\xda\x03\xf6", - .addtlb = (unsigned char *) - "\x7c\x7b\x4a\x4b\x32\x5e\x6f\x67\x34\xf5\x21\x4c" - "\xf9\x96\xf9\xbf\x1c\x8c\x81\xd3\x9b\x60\x6a\x44" - "\xc6\x03\xa2\xfb\x13\x20\x19\xb7", - .addtllen = 32, - .pers = NULL, - .perslen = 0, - }, { - .entropy = (unsigned char *) - "\x13\x54\x96\xfc\x1b\x7d\x28\xf3\x18\xc9\xa7\x89" - "\xb6\xb3\xc8\x72\xac\x00\xd4\x59\x36\x25\x05\xaf" - "\xa5\xdb\x96\xcb\x3c\x58\x46\x87\xa5\xaa\xbf\x20" - "\x3b\xfe\x23\x0e\xd1\xc7\x41\x0f\x3f\xc9\xb3\x67", - .entropylen = 48, - .entpra = (unsigned char *) - "\xe2\xbd\xb7\x48\x08\x06\xf3\xe1\x93\x3c\xac\x79" - "\xa7\x2b\x11\xda\xe3\x2e\xe1\x91\xa5\x02\x19\x57" - "\x20\x28\xad\xf2\x60\xd7\xcd\x45", - .entprb = (unsigned char *) - "\x8b\xd4\x69\xfc\xff\x59\x95\x95\xc6\x51\xde\x71" - "\x68\x5f\xfc\xf9\x4a\xab\xec\x5a\xcb\xbe\xd3\x66" - "\x1f\xfa\x74\xd3\xac\xa6\x74\x60", - .entprlen = 32, - .expected = (unsigned char *) - "\x1f\x9e\xaf\xe4\xd2\x46\xb7\x47\x41\x4c\x65\x99" - "\x01\xe9\x3b\xbb\x83\x0c\x0a\xb0\xc1\x3a\xe2\xb3" - "\x31\x4e\xeb\x93\x73\xee\x0b\x26\xc2\x63\xa5\x75" - "\x45\x99\xd4\x5c\x9f\xa1\xd4\x45\x87\x6b\x20\x61" - "\x40\xea\x78\xa5\x32\xdf\x9e\x66\x17\xaf\xb1\x88" - "\x9e\x2e\x23\xdd\xc1\xda\x13\x97\x88\xa5\xb6\x5e" - "\x90\x14\x4e\xef\x13\xab\x5c\xd9\x2c\x97\x9e\x7c" - "\xd7\xf8\xce\xea\x81\xf5\xcd\x71\x15\x49\x44\xce" - "\x83\xb6\x05\xfb\x7d\x30\xb5\x57\x2c\x31\x4f\xfc" - "\xfe\x80\xb6\xc0\x13\x0c\x5b\x9b\x2e\x8f\x3d\xfc" - "\xc2\xa3\x0c\x11\x1b\x80\x5f\xf3", - .expectedlen = 128, - .addtla = NULL, - .addtlb = NULL, - .addtllen = 0, - .pers = (unsigned char *) - "\x64\xb6\xfc\x60\xbc\x61\x76\x23\x6d\x3f\x4a\x0f" - "\xe1\xb4\xd5\x20\x9e\x70\xdd\x03\x53\x6d\xbf\xce" - "\xcd\x56\x80\xbc\xb8\x15\xc8\xaa", - .perslen = 32, - }, { - .entropy = (unsigned char *) - "\xc7\xcc\xbc\x67\x7e\x21\x66\x1e\x27\x2b\x63\xdd" - "\x3a\x78\xdc\xdf\x66\x6d\x3f\x24\xae\xcf\x37\x01" - "\xa9\x0d\x89\x8a\xa7\xdc\x81\x58\xae\xb2\x10\x15" - "\x7e\x18\x44\x6d\x13\xea\xdf\x37\x85\xfe\x81\xfb", - .entropylen = 48, - .entpra = (unsigned char *) - "\x7b\xa1\x91\x5b\x3c\x04\xc4\x1b\x1d\x19\x2f\x1a" - "\x18\x81\x60\x3c\x6c\x62\x91\xb7\xe9\xf5\xcb\x96" - "\xbb\x81\x6a\xcc\xb5\xae\x55\xb6", - .entprb = (unsigned char *) - "\x99\x2c\xc7\x78\x7e\x3b\x88\x12\xef\xbe\xd3\xd2" - "\x7d\x2a\xa5\x86\xda\x8d\x58\x73\x4a\x0a\xb2\x2e" - "\xbb\x4c\x7e\xe3\x9a\xb6\x81\xc1", - .entprlen = 32, - .expected = (unsigned char *) - "\x95\x6f\x95\xfc\x3b\xb7\xfe\x3e\xd0\x4e\x1a\x14" - "\x6c\x34\x7f\x7b\x1d\x0d\x63\x5e\x48\x9c\x69\xe6" - "\x46\x07\xd2\x87\xf3\x86\x52\x3d\x98\x27\x5e\xd7" - "\x54\xe7\x75\x50\x4f\xfb\x4d\xfd\xac\x2f\x4b\x77" - "\xcf\x9e\x8e\xcc\x16\xa2\x24\xcd\x53\xde\x3e\xc5" - "\x55\x5d\xd5\x26\x3f\x89\xdf\xca\x8b\x4e\x1e\xb6" - "\x88\x78\x63\x5c\xa2\x63\x98\x4e\x6f\x25\x59\xb1" - "\x5f\x2b\x23\xb0\x4b\xa5\x18\x5d\xc2\x15\x74\x40" - "\x59\x4c\xb4\x1e\xcf\x9a\x36\xfd\x43\xe2\x03\xb8" - "\x59\x91\x30\x89\x2a\xc8\x5a\x43\x23\x7c\x73\x72" - "\xda\x3f\xad\x2b\xba\x00\x6b\xd1", - .expectedlen = 128, - .addtla = (unsigned char *) - "\x18\xe8\x17\xff\xef\x39\xc7\x41\x5c\x73\x03\x03" - "\xf6\x3d\xe8\x5f\xc8\xab\xe4\xab\x0f\xad\xe8\xd6" - "\x86\x88\x55\x28\xc1\x69\xdd\x76", - .addtlb = (unsigned char *) - "\xac\x07\xfc\xbe\x87\x0e\xd3\xea\x1f\x7e\xb8\xe7" - "\x9d\xec\xe8\xe7\xbc\xf3\x18\x25\x77\x35\x4a\xaa" - "\x00\x99\x2a\xdd\x0a\x00\x50\x82", - .addtllen = 32, - .pers = (unsigned char *) - "\xbc\x55\xab\x3c\xf6\x52\xb0\x11\x3d\x7b\x90\xb8" - "\x24\xc9\x26\x4e\x5a\x1e\x77\x0d\x3d\x58\x4a\xda" - "\xd1\x81\xe9\xf8\xeb\x30\x8f\x6f", - .perslen = 32, - }, -}; - -static const struct drbg_testvec drbg_nopr_hmac_sha256_tv_template[] = { - { - .entropy = (unsigned char *) - "\xca\x85\x19\x11\x34\x93\x84\xbf\xfe\x89\xde\x1c" - "\xbd\xc4\x6e\x68\x31\xe4\x4d\x34\xa4\xfb\x93\x5e" - "\xe2\x85\xdd\x14\xb7\x1a\x74\x88\x65\x9b\xa9\x6c" - "\x60\x1d\xc6\x9f\xc9\x02\x94\x08\x05\xec\x0c\xa8", - .entropylen = 48, - .expected = (unsigned char *) - "\xe5\x28\xe9\xab\xf2\xde\xce\x54\xd4\x7c\x7e\x75" - "\xe5\xfe\x30\x21\x49\xf8\x17\xea\x9f\xb4\xbe\xe6" - "\xf4\x19\x96\x97\xd0\x4d\x5b\x89\xd5\x4f\xbb\x97" - "\x8a\x15\xb5\xc4\x43\xc9\xec\x21\x03\x6d\x24\x60" - "\xb6\xf7\x3e\xba\xd0\xdc\x2a\xba\x6e\x62\x4a\xbf" - "\x07\x74\x5b\xc1\x07\x69\x4b\xb7\x54\x7b\xb0\x99" - "\x5f\x70\xde\x25\xd6\xb2\x9e\x2d\x30\x11\xbb\x19" - "\xd2\x76\x76\xc0\x71\x62\xc8\xb5\xcc\xde\x06\x68" - "\x96\x1d\xf8\x68\x03\x48\x2c\xb3\x7e\xd6\xd5\xc0" - "\xbb\x8d\x50\xcf\x1f\x50\xd4\x76\xaa\x04\x58\xbd" - "\xab\xa8\x06\xf4\x8b\xe9\xdc\xb8", - .expectedlen = 128, - .addtla = NULL, - .addtlb = NULL, - .addtllen = 0, - .pers = NULL, - .perslen = 0, - }, { - .entropy = (unsigned char *) - "\xf9\x7a\x3c\xfd\x91\xfa\xa0\x46\xb9\xe6\x1b\x94" - "\x93\xd4\x36\xc4\x93\x1f\x60\x4b\x22\xf1\x08\x15" - "\x21\xb3\x41\x91\x51\xe8\xff\x06\x11\xf3\xa7\xd4" - "\x35\x95\x35\x7d\x58\x12\x0b\xd1\xe2\xdd\x8a\xed", - .entropylen = 48, - .expected = (unsigned char *) - "\xc6\x87\x1c\xff\x08\x24\xfe\x55\xea\x76\x89\xa5" - "\x22\x29\x88\x67\x30\x45\x0e\x5d\x36\x2d\xa5\xbf" - "\x59\x0d\xcf\x9a\xcd\x67\xfe\xd4\xcb\x32\x10\x7d" - "\xf5\xd0\x39\x69\xa6\x6b\x1f\x64\x94\xfd\xf5\xd6" - "\x3d\x5b\x4d\x0d\x34\xea\x73\x99\xa0\x7d\x01\x16" - "\x12\x6d\x0d\x51\x8c\x7c\x55\xba\x46\xe1\x2f\x62" - "\xef\xc8\xfe\x28\xa5\x1c\x9d\x42\x8e\x6d\x37\x1d" - "\x73\x97\xab\x31\x9f\xc7\x3d\xed\x47\x22\xe5\xb4" - "\xf3\x00\x04\x03\x2a\x61\x28\xdf\x5e\x74\x97\xec" - "\xf8\x2c\xa7\xb0\xa5\x0e\x86\x7e\xf6\x72\x8a\x4f" - "\x50\x9a\x8c\x85\x90\x87\x03\x9c", - .expectedlen = 128, - .addtla = (unsigned char *) - "\x51\x72\x89\xaf\xe4\x44\xa0\xfe\x5e\xd1\xa4\x1d" - "\xbb\xb5\xeb\x17\x15\x00\x79\xbd\xd3\x1e\x29\xcf" - "\x2f\xf3\x00\x34\xd8\x26\x8e\x3b", - .addtlb = (unsigned char *) - "\x88\x02\x8d\x29\xef\x80\xb4\xe6\xf0\xfe\x12\xf9" - "\x1d\x74\x49\xfe\x75\x06\x26\x82\xe8\x9c\x57\x14" - "\x40\xc0\xc9\xb5\x2c\x42\xa6\xe0", - .addtllen = 32, - .pers = NULL, - .perslen = 0, - }, { - .entropy = (unsigned char *) - "\x8d\xf0\x13\xb4\xd1\x03\x52\x30\x73\x91\x7d\xdf" - "\x6a\x86\x97\x93\x05\x9e\x99\x43\xfc\x86\x54\x54" - "\x9e\x7a\xb2\x2f\x7c\x29\xf1\x22\xda\x26\x25\xaf" - "\x2d\xdd\x4a\xbc\xce\x3c\xf4\xfa\x46\x59\xd8\x4e", - .entropylen = 48, - .expected = (unsigned char *) - "\xb9\x1c\xba\x4c\xc8\x4f\xa2\x5d\xf8\x61\x0b\x81" - "\xb6\x41\x40\x27\x68\xa2\x09\x72\x34\x93\x2e\x37" - "\xd5\x90\xb1\x15\x4c\xbd\x23\xf9\x74\x52\xe3\x10" - "\xe2\x91\xc4\x51\x46\x14\x7f\x0d\xa2\xd8\x17\x61" - "\xfe\x90\xfb\xa6\x4f\x94\x41\x9c\x0f\x66\x2b\x28" - "\xc1\xed\x94\xda\x48\x7b\xb7\xe7\x3e\xec\x79\x8f" - "\xbc\xf9\x81\xb7\x91\xd1\xbe\x4f\x17\x7a\x89\x07" - "\xaa\x3c\x40\x16\x43\xa5\xb6\x2b\x87\xb8\x9d\x66" - "\xb3\xa6\x0e\x40\xd4\xa8\xe4\xe9\xd8\x2a\xf6\xd2" - "\x70\x0e\x6f\x53\x5c\xdb\x51\xf7\x5c\x32\x17\x29" - "\x10\x37\x41\x03\x0c\xcc\x3a\x56", - .expectedlen = 128, - .addtla = NULL, - .addtlb = NULL, - .addtllen = 0, - .pers = (unsigned char *) - "\xb5\x71\xe6\x6d\x7c\x33\x8b\xc0\x7b\x76\xad\x37" - "\x57\xbb\x2f\x94\x52\xbf\x7e\x07\x43\x7a\xe8\x58" - "\x1c\xe7\xbc\x7c\x3a\xc6\x51\xa9", - .perslen = 32, - }, { - .entropy = (unsigned char *) - "\xc2\xa5\x66\xa9\xa1\x81\x7b\x15\xc5\xc3\xb7\x78" - "\x17\x7a\xc8\x7c\x24\xe7\x97\xbe\x0a\x84\x5f\x11" - "\xc2\xfe\x39\x9d\xd3\x77\x32\xf2\xcb\x18\x94\xeb" - "\x2b\x97\xb3\xc5\x6e\x62\x83\x29\x51\x6f\x86\xec", - .entropylen = 48, - .expected = (unsigned char *) - "\xb3\xa3\x69\x8d\x77\x76\x99\xa0\xdd\x9f\xa3\xf0" - "\xa9\xfa\x57\x83\x2d\x3c\xef\xac\x5d\xf2\x44\x37" - "\xc6\xd7\x3a\x0f\xe4\x10\x40\xf1\x72\x90\x38\xae" - "\xf1\xe9\x26\x35\x2e\xa5\x9d\xe1\x20\xbf\xb7\xb0" - "\x73\x18\x3a\x34\x10\x6e\xfe\xd6\x27\x8f\xf8\xad" - "\x84\x4b\xa0\x44\x81\x15\xdf\xdd\xf3\x31\x9a\x82" - "\xde\x6b\xb1\x1d\x80\xbd\x87\x1a\x9a\xcd\x35\xc7" - "\x36\x45\xe1\x27\x0f\xb9\xfe\x4f\xa8\x8e\xc0\xe4" - "\x65\x40\x9e\xa0\xcb\xa8\x09\xfe\x2f\x45\xe0\x49" - "\x43\xa2\xe3\x96\xbb\xb7\xdd\x2f\x4e\x07\x95\x30" - "\x35\x24\xcc\x9c\xc5\xea\x54\xa1", - .expectedlen = 128, - .addtla = (unsigned char *) - "\x41\x3d\xd8\x3f\xe5\x68\x35\xab\xd4\x78\xcb\x96" - "\x93\xd6\x76\x35\x90\x1c\x40\x23\x9a\x26\x64\x62" - "\xd3\x13\x3b\x83\xe4\x9c\x82\x0b", - .addtlb = (unsigned char *) - "\xd5\xc4\xa7\x1f\x9d\x6d\x95\xa1\xbe\xdf\x0b\xd2" - "\x24\x7c\x27\x7d\x1f\x84\xa4\xe5\x7a\x4a\x88\x25" - "\xb8\x2a\x2d\x09\x7d\xe6\x3e\xf1", - .addtllen = 32, - .pers = (unsigned char *) - "\x13\xce\x4d\x8d\xd2\xdb\x97\x96\xf9\x41\x56\xc8" - "\xe8\xf0\x76\x9b\x0a\xa1\xc8\x2c\x13\x23\xb6\x15" - "\x36\x60\x3b\xca\x37\xc9\xee\x29", - .perslen = 32, - }, -}; - static const struct drbg_testvec drbg_pr_hmac_sha512_tv_template[] = { /* * Borrowed from the first applicable test vector from ACVP: From b9e081978ea4d21f006d40d6517421142f9fa479 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:02 -0700 Subject: [PATCH 029/196] crypto: drbg - Simplify algorithm registration Now that "drbg_pr_hmac_sha512" and "drbg_nopr_hmac_sha512" are the only crypto_rng algorithms left in crypto/drbg.c, simplify the algorithm registration logic to register these more directly without relying on the drbg_cores[] array (which will be removed). Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 100 ++++++++++++++++++-------------------------------- 1 file changed, 35 insertions(+), 65 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index 81bccacd3595..4a778d0d1fc4 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -1145,86 +1145,56 @@ static inline int __init drbg_healthcheck_sanity(void) return rc; } -static struct rng_alg drbg_algs[22]; - -/* - * Fill the array drbg_algs used to register the different DRBGs - * with the kernel crypto API. To fill the array, the information - * from drbg_cores[] is used. - */ -static inline void __init drbg_fill_array(struct rng_alg *alg, - const struct drbg_core *core, int pr) -{ - int pos = 0; - static int priority = 200; - - memcpy(alg->base.cra_name, "stdrng", 6); - if (pr) { - memcpy(alg->base.cra_driver_name, "drbg_pr_", 8); - pos = 8; - } else { - memcpy(alg->base.cra_driver_name, "drbg_nopr_", 10); - pos = 10; - } - memcpy(alg->base.cra_driver_name + pos, core->cra_name, - strlen(core->cra_name)); - - alg->base.cra_priority = priority; - priority++; - /* - * If FIPS mode enabled, the selected DRBG shall have the - * highest cra_priority over other stdrng instances to ensure - * it is selected. - */ - if (fips_enabled) - alg->base.cra_priority += 2000; - - alg->base.cra_ctxsize = sizeof(struct drbg_state); - alg->base.cra_module = THIS_MODULE; - alg->base.cra_init = drbg_kcapi_init; - alg->base.cra_exit = drbg_kcapi_cleanup; - alg->generate = drbg_kcapi_random; - alg->seed = drbg_kcapi_seed; - alg->set_ent = drbg_kcapi_set_entropy; - alg->seedsize = 0; -} +static struct rng_alg drbg_algs[] = { + { + .base.cra_name = "stdrng", + .base.cra_driver_name = "drbg_pr_hmac_sha512", + .base.cra_priority = 200, + .base.cra_ctxsize = sizeof(struct drbg_state), + .base.cra_module = THIS_MODULE, + .base.cra_init = drbg_kcapi_init, + .set_ent = drbg_kcapi_set_entropy, + .seed = drbg_kcapi_seed, + .generate = drbg_kcapi_random, + .base.cra_exit = drbg_kcapi_cleanup, + }, + { + .base.cra_name = "stdrng", + .base.cra_driver_name = "drbg_nopr_hmac_sha512", + .base.cra_priority = 201, + .base.cra_ctxsize = sizeof(struct drbg_state), + .base.cra_module = THIS_MODULE, + .base.cra_init = drbg_kcapi_init, + .set_ent = drbg_kcapi_set_entropy, + .seed = drbg_kcapi_seed, + .generate = drbg_kcapi_random, + .base.cra_exit = drbg_kcapi_cleanup, + }, +}; static int __init drbg_init(void) { - unsigned int i = 0; /* pointer to drbg_algs */ - unsigned int j = 0; /* pointer to drbg_cores */ int ret; ret = drbg_healthcheck_sanity(); if (ret) return ret; - if (ARRAY_SIZE(drbg_cores) * 2 > ARRAY_SIZE(drbg_algs)) { - pr_info("DRBG: Cannot register all DRBG types" - "(slots needed: %zu, slots available: %zu)\n", - ARRAY_SIZE(drbg_cores) * 2, ARRAY_SIZE(drbg_algs)); - return -EFAULT; + /* + * In FIPS mode, boost the algorithm priorities to ensure that when + * users request "stdrng", they really get an algorithm from here. + */ + if (fips_enabled) { + for (size_t i = 0; i < ARRAY_SIZE(drbg_algs); i++) + drbg_algs[i].base.cra_priority += 2000; } - /* - * each DRBG definition can be used with PR and without PR, thus - * we instantiate each DRBG in drbg_cores[] twice. - * - * As the order of placing them into the drbg_algs array matters - * (the later DRBGs receive a higher cra_priority) we register the - * prediction resistance DRBGs first as the should not be too - * interesting. - */ - for (j = 0; ARRAY_SIZE(drbg_cores) > j; j++, i++) - drbg_fill_array(&drbg_algs[i], &drbg_cores[j], 1); - for (j = 0; ARRAY_SIZE(drbg_cores) > j; j++, i++) - drbg_fill_array(&drbg_algs[i], &drbg_cores[j], 0); - return crypto_register_rngs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2)); + return crypto_register_rngs(drbg_algs, ARRAY_SIZE(drbg_algs)); } static void __exit drbg_exit(void) { - crypto_unregister_rngs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2)); + crypto_unregister_rngs(drbg_algs, ARRAY_SIZE(drbg_algs)); } module_init(drbg_init); From aaa891b7c71a493d8746d877cf4c02ecf261ecc4 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:03 -0700 Subject: [PATCH 030/196] crypto: drbg - De-virtualize drbg_state_ops Now that there's only one set of state operations, use direct calls to those operations. No change in behavior. In particular, drbg_alloc_state() doesn't change behavior, because the only remaining drbg_core uses HMAC_DRBG. drbg_uninstantiate() doesn't change behavior, because a NULL d_ops implied NULL priv_data which makes a drbg_fini_hash_kernel() a no-op. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 50 ++++++-------------------------------------------- 1 file changed, 6 insertions(+), 44 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index 4a778d0d1fc4..04c798d7a8b6 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -111,17 +111,6 @@ struct drbg_core { char backend_cra_name[CRYPTO_MAX_ALG_NAME]; }; -struct drbg_state_ops { - int (*update)(struct drbg_state *drbg, struct list_head *seed, - int reseed); - int (*generate)(struct drbg_state *drbg, - unsigned char *buf, unsigned int buflen, - struct list_head *addtl); - int (*crypto_init)(struct drbg_state *drbg); - int (*crypto_fini)(struct drbg_state *drbg); - -}; - enum drbg_seed_state { DRBG_SEED_STATE_UNSEEDED, DRBG_SEED_STATE_PARTIAL, /* Seeded with !rng_is_initialized() */ @@ -143,7 +132,6 @@ struct drbg_state { unsigned long last_seed_time; bool pr; /* Prediction resistance enabled? */ struct crypto_rng *jent; - const struct drbg_state_ops *d_ops; const struct drbg_core *core; struct drbg_string test_data; }; @@ -250,7 +238,7 @@ static inline unsigned short drbg_sec_strength(drbg_flag_t flags) } /****************************************************************** - * HMAC DRBG callback functions + * HMAC DRBG functions ******************************************************************/ static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval, @@ -360,21 +348,10 @@ static int drbg_hmac_generate(struct drbg_state *drbg, return len; } -static const struct drbg_state_ops drbg_hmac_ops = { - .update = drbg_hmac_update, - .generate = drbg_hmac_generate, - .crypto_init = drbg_init_hash_kernel, - .crypto_fini = drbg_fini_hash_kernel, -}; - -/****************************************************************** - * Functions common for DRBG implementations - ******************************************************************/ - static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed, int reseed, enum drbg_seed_state new_seed_state) { - int ret = drbg->d_ops->update(drbg, seed, reseed); + int ret = drbg_hmac_update(drbg, seed, reseed); if (ret) return ret; @@ -578,7 +555,6 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg) drbg->Cbuf = NULL; drbg->C = NULL; drbg->reseed_ctr = 0; - drbg->d_ops = NULL; drbg->core = NULL; } @@ -590,16 +566,7 @@ static inline int drbg_alloc_state(struct drbg_state *drbg) { int ret = -ENOMEM; - switch (drbg->core->flags & DRBG_TYPE_MASK) { - case DRBG_HMAC: - drbg->d_ops = &drbg_hmac_ops; - break; - default: - ret = -EOPNOTSUPP; - goto err; - } - - ret = drbg->d_ops->crypto_init(drbg); + ret = drbg_init_hash_kernel(drbg); if (ret < 0) goto err; @@ -619,16 +586,12 @@ static inline int drbg_alloc_state(struct drbg_state *drbg) return 0; fini: - drbg->d_ops->crypto_fini(drbg); + drbg_fini_hash_kernel(drbg); err: drbg_dealloc_state(drbg); return ret; } -/************************************************************************* - * DRBG interface functions - *************************************************************************/ - /* * DRBG generate function as required by SP800-90A - this function * generates random numbers @@ -714,7 +677,7 @@ static int drbg_generate(struct drbg_state *drbg, if (addtl && 0 < addtl->len) list_add_tail(&addtl->list, &addtllist); /* 9.3.1 step 8 and 10 */ - len = drbg->d_ops->generate(drbg, buf, buflen, &addtllist); + len = drbg_hmac_generate(drbg, buf, buflen, &addtllist); /* 10.1.2.5 step 7 */ drbg->reseed_ctr++; @@ -879,8 +842,7 @@ static int drbg_uninstantiate(struct drbg_state *drbg) crypto_free_rng(drbg->jent); drbg->jent = NULL; - if (drbg->d_ops) - drbg->d_ops->crypto_fini(drbg); + drbg_fini_hash_kernel(drbg); drbg_dealloc_state(drbg); /* no scrubbing of test_data -- this shall survive an uninstantiate */ return 0; From 7e9a68e83b0f0663d630a1d1cd7e6443c80186ae Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:04 -0700 Subject: [PATCH 031/196] crypto: drbg - Move fixed values into constants Since only one drbg_core remains, the state length, block length, and security strength are now fixed values. Moreover, the maximum request length, maximum additional data length, and maximum number of requests were all already fixed values. Simplify the code by just using #defines for all these fixed values. In drbg_seed_from_random(), take advantage of the constant to define the array size. Remove assertions that are no longer useful. In the case of drbg_blocklen() and drbg_statelen(), replace these with a single value DRBG_STATE_LEN, as for HMAC_DRBG they are the same thing. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 183 +++++++++++++++++--------------------------------- 1 file changed, 61 insertions(+), 122 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index 04c798d7a8b6..34a7cbdda1f1 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -91,6 +91,7 @@ #include #include #include +#include #include #include #include @@ -100,12 +101,8 @@ #include struct drbg_state; -typedef uint32_t drbg_flag_t; struct drbg_core { - drbg_flag_t flags; /* flags for the cipher */ - __u8 statelen; /* maximum state length */ - __u8 blocklen_bytes; /* block size of output in bytes */ char cra_name[CRYPTO_MAX_ALG_NAME]; /* mapping to kernel crypto API */ /* kernel crypto API backend cipher name */ char backend_cra_name[CRYPTO_MAX_ALG_NAME]; @@ -117,6 +114,32 @@ enum drbg_seed_state { DRBG_SEED_STATE_FULL, }; +/* State length in bytes */ +#define DRBG_STATE_LEN SHA512_DIGEST_SIZE + +/* Security strength in bytes */ +#define DRBG_SEC_STRENGTH (SHA512_DIGEST_SIZE / 2) + +/* + * Maximum number of requests before reseeding is forced. + * SP800-90A allows this to be up to 2**48. We use a lower value. + */ +#define DRBG_MAX_REQUESTS (1 << 20) + +/* + * Maximum number of random bytes that can be requested at once. + * SP800-90A allows up to 2**19 bits, which is 2**16 bytes. + */ +#define DRBG_MAX_REQUEST_BYTES (1 << 16) + +/* + * Maximum length of additional info and personalization strings, in bytes. + * SP800-90A allows up to 2**35 bits, i.e. 2**32 bytes. We use 2**32 - 2 bytes + * so that the value never quite completely fills the range of a size_t, + * allowing the health check to verify that larger values are rejected. + */ +#define DRBG_MAX_ADDTL (U32_MAX - 1) + struct drbg_state { struct mutex drbg_mutex; /* lock around DRBG */ unsigned char *V; /* internal state -- 10.1.2.1 1a */ @@ -136,53 +159,6 @@ struct drbg_state { struct drbg_string test_data; }; -static inline __u8 drbg_statelen(struct drbg_state *drbg) -{ - if (drbg && drbg->core) - return drbg->core->statelen; - return 0; -} - -static inline __u8 drbg_blocklen(struct drbg_state *drbg) -{ - if (drbg && drbg->core) - return drbg->core->blocklen_bytes; - return 0; -} - -static inline size_t drbg_max_request_bytes(struct drbg_state *drbg) -{ - /* SP800-90A requires the limit 2**19 bits, but we return bytes */ - return (1 << 16); -} - -/* - * SP800-90A allows implementations to support additional info / personalization - * strings of up to 2**35 bits. Implementations can have a smaller maximum. We - * use 2**35 - 16 bits == U32_MAX - 1 bytes so that the max + 1 always fits in a - * size_t, allowing drbg_healthcheck_sanity() to verify its enforcement. - */ -static inline size_t drbg_max_addtl(struct drbg_state *drbg) -{ - return U32_MAX - 1; -} - -static inline size_t drbg_max_requests(struct drbg_state *drbg) -{ - /* SP800-90A requires 2**48 maximum requests before reseeding */ - return (1<<20); -} - -/* DRBG type flags */ -#define DRBG_HMAC ((drbg_flag_t)1<<1) -#define DRBG_TYPE_MASK DRBG_HMAC -/* DRBG strength flags */ -#define DRBG_STRENGTH128 ((drbg_flag_t)1<<3) -#define DRBG_STRENGTH192 ((drbg_flag_t)1<<4) -#define DRBG_STRENGTH256 ((drbg_flag_t)1<<5) -#define DRBG_STRENGTH_MASK (DRBG_STRENGTH128 | DRBG_STRENGTH192 | \ - DRBG_STRENGTH256) - enum drbg_prefixes { DRBG_PREFIX0 = 0x00, DRBG_PREFIX1, @@ -201,9 +177,6 @@ enum drbg_prefixes { */ static const struct drbg_core drbg_cores[] = { { - .flags = DRBG_HMAC | DRBG_STRENGTH256, - .statelen = 64, /* block length of cipher */ - .blocklen_bytes = 64, .cra_name = "hmac_sha512", .backend_cra_name = "hmac(sha512)", }, @@ -211,32 +184,6 @@ static const struct drbg_core drbg_cores[] = { static int drbg_uninstantiate(struct drbg_state *drbg); -/****************************************************************** - * Generic helper functions - ******************************************************************/ - -/* - * Return strength of DRBG according to SP800-90A section 8.4 - * - * @flags DRBG flags reference - * - * Return: normalized strength in *bytes* value or 32 as default - * to counter programming errors - */ -static inline unsigned short drbg_sec_strength(drbg_flag_t flags) -{ - switch (flags & DRBG_STRENGTH_MASK) { - case DRBG_STRENGTH128: - return 16; - case DRBG_STRENGTH192: - return 24; - case DRBG_STRENGTH256: - return 32; - default: - return 32; - } -} - /****************************************************************** * HMAC DRBG functions ******************************************************************/ @@ -263,11 +210,11 @@ static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed, if (!reseed) { /* 10.1.2.3 step 2 -- memset(0) of C is implicit with kzalloc */ - memset(drbg->V, 1, drbg_statelen(drbg)); + memset(drbg->V, 1, DRBG_STATE_LEN); drbg_kcapi_hmacsetkey(drbg, drbg->C); } - drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg)); + drbg_string_fill(&seed1, drbg->V, DRBG_STATE_LEN); list_add_tail(&seed1.list, &seedlist); /* buffer of seed2 will be filled in for loop below with one byte */ drbg_string_fill(&seed2, NULL, 1); @@ -276,7 +223,7 @@ static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed, if (seed) list_splice_tail(seed, &seedlist); - drbg_string_fill(&vdata, drbg->V, drbg_statelen(drbg)); + drbg_string_fill(&vdata, drbg->V, DRBG_STATE_LEN); list_add_tail(&vdata.list, &vdatalist); for (i = 2; 0 < i; i--) { /* first round uses 0x0, second 0x1 */ @@ -321,7 +268,7 @@ static int drbg_hmac_generate(struct drbg_state *drbg, return ret; } - drbg_string_fill(&data, drbg->V, drbg_statelen(drbg)); + drbg_string_fill(&data, drbg->V, DRBG_STATE_LEN); list_add_tail(&data.list, &datalist); while (len < buflen) { unsigned int outlen = 0; @@ -329,8 +276,8 @@ static int drbg_hmac_generate(struct drbg_state *drbg, ret = drbg_kcapi_hash(drbg, drbg->V, &datalist); if (ret) return ret; - outlen = (drbg_blocklen(drbg) < (buflen - len)) ? - drbg_blocklen(drbg) : (buflen - len); + outlen = (DRBG_STATE_LEN < (buflen - len)) ? + DRBG_STATE_LEN : (buflen - len); /* 10.1.2.5 step 4.2 */ memcpy(buf + len, drbg->V, outlen); @@ -377,7 +324,7 @@ static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed, * Seed source has become fully initialized, frequent * reseeds no longer required. */ - drbg->reseed_threshold = drbg_max_requests(drbg); + drbg->reseed_threshold = DRBG_MAX_REQUESTS; break; } @@ -389,21 +336,17 @@ static int drbg_seed_from_random(struct drbg_state *drbg) { struct drbg_string data; LIST_HEAD(seedlist); - unsigned int entropylen = drbg_sec_strength(drbg->core->flags); - unsigned char entropy[32]; + unsigned char entropy[DRBG_SEC_STRENGTH]; int ret; - BUG_ON(!entropylen); - BUG_ON(entropylen > sizeof(entropy)); - - drbg_string_fill(&data, entropy, entropylen); + drbg_string_fill(&data, entropy, DRBG_SEC_STRENGTH); list_add_tail(&data.list, &seedlist); - get_random_bytes(entropy, entropylen); + get_random_bytes(entropy, DRBG_SEC_STRENGTH); ret = __drbg_seed(drbg, &seedlist, true, DRBG_SEED_STATE_FULL); - memzero_explicit(entropy, entropylen); + memzero_explicit(entropy, DRBG_SEC_STRENGTH); return ret; } @@ -444,13 +387,13 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers, { int ret; unsigned char entropy[((32 + 16) * 2)]; - unsigned int entropylen = drbg_sec_strength(drbg->core->flags); + unsigned int entropylen; struct drbg_string data1; LIST_HEAD(seedlist); enum drbg_seed_state new_seed_state = DRBG_SEED_STATE_FULL; /* 9.1 / 9.2 / 9.3.1 step 3 */ - if (pers && pers->len > (drbg_max_addtl(drbg))) { + if (pers && pers->len > DRBG_MAX_ADDTL) { pr_devel("DRBG: personalization string too long %zu\n", pers->len); return -EINVAL; @@ -469,9 +412,10 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers, * of the strength. The consideration of a nonce is only * applicable during initial seeding. */ - BUG_ON(!entropylen); if (!reseed) - entropylen = ((entropylen + 1) / 2) * 3; + entropylen = ((DRBG_SEC_STRENGTH + 1) / 2) * 3; + else + entropylen = DRBG_SEC_STRENGTH; BUG_ON((entropylen * 2) > sizeof(entropy)); /* Get seed from in-kernel /dev/urandom */ @@ -531,14 +475,14 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers, } if (!reseed) { - memset(drbg->V, 0, drbg_statelen(drbg)); - memset(drbg->C, 0, drbg_statelen(drbg)); + memset(drbg->V, 0, DRBG_STATE_LEN); + memset(drbg->C, 0, DRBG_STATE_LEN); } ret = __drbg_seed(drbg, &seedlist, reseed, new_seed_state); out: - memzero_explicit(entropy, entropylen * 2); + memzero_explicit(entropy, sizeof(entropy)); return ret; } @@ -570,13 +514,13 @@ static inline int drbg_alloc_state(struct drbg_state *drbg) if (ret < 0) goto err; - drbg->Vbuf = kmalloc(drbg_statelen(drbg) + ret, GFP_KERNEL); + drbg->Vbuf = kmalloc(DRBG_STATE_LEN + ret, GFP_KERNEL); if (!drbg->Vbuf) { ret = -ENOMEM; goto fini; } drbg->V = PTR_ALIGN(drbg->Vbuf, ret + 1); - drbg->Cbuf = kmalloc(drbg_statelen(drbg) + ret, GFP_KERNEL); + drbg->Cbuf = kmalloc(DRBG_STATE_LEN + ret, GFP_KERNEL); if (!drbg->Cbuf) { ret = -ENOMEM; goto fini; @@ -630,20 +574,19 @@ static int drbg_generate(struct drbg_state *drbg, } /* 9.3.1 step 2 */ - len = -EINVAL; - if (buflen > (drbg_max_request_bytes(drbg))) { + if (buflen > DRBG_MAX_REQUEST_BYTES) { pr_devel("DRBG: requested random numbers too large %u\n", buflen); - goto err; + return -EINVAL; } /* 9.3.1 step 3 is implicit with the chosen DRBG */ /* 9.3.1 step 4 */ - if (addtl && addtl->len > (drbg_max_addtl(drbg))) { + if (addtl && addtl->len > DRBG_MAX_ADDTL) { pr_devel("DRBG: additional information string too long %zu\n", addtl->len); - goto err; + return -EINVAL; } /* 9.3.1 step 5 is implicit with the chosen DRBG */ @@ -723,8 +666,8 @@ static int drbg_generate_long(struct drbg_state *drbg, do { int err = 0; unsigned int chunk = 0; - slice = ((buflen - len) / drbg_max_request_bytes(drbg)); - chunk = slice ? drbg_max_request_bytes(drbg) : (buflen - len); + slice = (buflen - len) / DRBG_MAX_REQUEST_BYTES; + chunk = slice ? DRBG_MAX_REQUEST_BYTES : (buflen - len); mutex_lock(&drbg->drbg_mutex); err = drbg_generate(drbg, buf + len, chunk, addtl); mutex_unlock(&drbg->drbg_mutex); @@ -785,18 +728,17 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers, /* * 9.1 step 2 is implicit as caller can select prediction resistance - * and the flag is copied into drbg->flags -- * all DRBG types support prediction resistance */ - /* 9.1 step 4 is implicit in drbg_sec_strength */ + /* 9.1 step 4 is implicit in DRBG_SEC_STRENGTH */ if (!drbg->core) { drbg->core = &drbg_cores[coreref]; drbg->pr = pr; drbg->seeded = DRBG_SEED_STATE_UNSEEDED; drbg->last_seed_time = 0; - drbg->reseed_threshold = drbg_max_requests(drbg); + drbg->reseed_threshold = DRBG_MAX_REQUESTS; ret = drbg_alloc_state(drbg); if (ret) @@ -884,7 +826,7 @@ static int drbg_init_hash_kernel(struct drbg_state *drbg) drbg->core->backend_cra_name); return PTR_ERR(tfm); } - BUG_ON(drbg_blocklen(drbg) != crypto_shash_digestsize(tfm)); + BUG_ON(DRBG_STATE_LEN != crypto_shash_digestsize(tfm)); sdesc = kzalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm), GFP_KERNEL); if (!sdesc) { @@ -914,7 +856,7 @@ static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg, { struct sdesc *sdesc = drbg->priv_data; - crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg)); + crypto_shash_setkey(sdesc->shash.tfm, key, DRBG_STATE_LEN); } static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval, @@ -1060,7 +1002,6 @@ static inline int __init drbg_healthcheck_sanity(void) bool pr = false; int coreref = 0; struct drbg_string addtl; - size_t max_addtllen, max_request_bytes; /* only perform test in FIPS mode */ if (!fips_enabled) @@ -1074,7 +1015,7 @@ static inline int __init drbg_healthcheck_sanity(void) guard(mutex_init)(&drbg->drbg_mutex); drbg->core = &drbg_cores[coreref]; - drbg->reseed_threshold = drbg_max_requests(drbg); + drbg->reseed_threshold = DRBG_MAX_REQUESTS; /* * if the following tests fail, it is likely that there is a buffer @@ -1084,14 +1025,12 @@ static inline int __init drbg_healthcheck_sanity(void) * grave bug. */ - max_addtllen = drbg_max_addtl(drbg); - max_request_bytes = drbg_max_request_bytes(drbg); - drbg_string_fill(&addtl, buf, max_addtllen + 1); + drbg_string_fill(&addtl, buf, DRBG_MAX_ADDTL + 1); /* overflow addtllen with additional info string */ ret = drbg_generate(drbg, buf, OUTBUFLEN, &addtl); BUG_ON(ret == 0); /* overflow max_bits */ - ret = drbg_generate(drbg, buf, max_request_bytes + 1, NULL); + ret = drbg_generate(drbg, buf, DRBG_MAX_REQUEST_BYTES + 1, NULL); BUG_ON(ret == 0); /* overflow max addtllen with personalization string */ From fcc62e0991ff0ceb7f53a93f4b12982b7d91d233 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:05 -0700 Subject: [PATCH 032/196] crypto: drbg - Embed V and C into struct drbg_state Now that the sizes of V and C are known at compile time, embed them into struct drbg_state rather than using separate allocations. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 30 ++++-------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index 34a7cbdda1f1..e62bde7aab43 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -142,10 +142,8 @@ enum drbg_seed_state { struct drbg_state { struct mutex drbg_mutex; /* lock around DRBG */ - unsigned char *V; /* internal state -- 10.1.2.1 1a */ - unsigned char *Vbuf; - unsigned char *C; /* current key -- 10.1.2.1 1b */ - unsigned char *Cbuf; + u8 V[DRBG_STATE_LEN]; /* internal state -- 10.1.2.1 1a */ + u8 C[DRBG_STATE_LEN]; /* current key -- 10.1.2.1 1b */ /* Number of RNG requests since last reseed -- 10.1.2.1 1c */ size_t reseed_ctr; size_t reseed_threshold; @@ -492,12 +490,8 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg) { if (!drbg) return; - kfree_sensitive(drbg->Vbuf); - drbg->Vbuf = NULL; - drbg->V = NULL; - kfree_sensitive(drbg->Cbuf); - drbg->Cbuf = NULL; - drbg->C = NULL; + memzero_explicit(drbg->V, sizeof(drbg->V)); + memzero_explicit(drbg->C, sizeof(drbg->C)); drbg->reseed_ctr = 0; drbg->core = NULL; } @@ -513,24 +507,8 @@ static inline int drbg_alloc_state(struct drbg_state *drbg) ret = drbg_init_hash_kernel(drbg); if (ret < 0) goto err; - - drbg->Vbuf = kmalloc(DRBG_STATE_LEN + ret, GFP_KERNEL); - if (!drbg->Vbuf) { - ret = -ENOMEM; - goto fini; - } - drbg->V = PTR_ALIGN(drbg->Vbuf, ret + 1); - drbg->Cbuf = kmalloc(DRBG_STATE_LEN + ret, GFP_KERNEL); - if (!drbg->Cbuf) { - ret = -ENOMEM; - goto fini; - } - drbg->C = PTR_ALIGN(drbg->Cbuf, ret + 1); - return 0; -fini: - drbg_fini_hash_kernel(drbg); err: drbg_dealloc_state(drbg); return ret; From 245c8d0d177f129d105f84331272494e2cd31f2a Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:06 -0700 Subject: [PATCH 033/196] crypto: drbg - Use HMAC-SHA512 library API Since the HMAC algorithm is now fixed at HMAC-SHA512, just use the HMAC-SHA512 library API. This is simpler and more efficient. Remove error-handling code that is no longer needed. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/Kconfig | 3 +- crypto/drbg.c | 213 ++++++++++--------------------------------------- 2 files changed, 41 insertions(+), 175 deletions(-) diff --git a/crypto/Kconfig b/crypto/Kconfig index 1abb3d356458..608b2c739193 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1115,10 +1115,9 @@ menu "Random number generation" config CRYPTO_DRBG tristate "NIST SP800-90A DRBG (Deterministic Random Bit Generator)" - select CRYPTO_HMAC select CRYPTO_JITTERENTROPY + select CRYPTO_LIB_SHA512 select CRYPTO_RNG - select CRYPTO_SHA512 help DRBG (Deterministic Random Bit Generator) (NIST SP800-90A) diff --git a/crypto/drbg.c b/crypto/drbg.c index e62bde7aab43..4f326385cf36 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -4,6 +4,7 @@ * both with and without prediction resistance * * Copyright Stephan Mueller , 2014 + * Copyright 2026 Google LLC * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -90,7 +91,6 @@ #include #include -#include #include #include #include @@ -143,12 +143,11 @@ enum drbg_seed_state { struct drbg_state { struct mutex drbg_mutex; /* lock around DRBG */ u8 V[DRBG_STATE_LEN]; /* internal state -- 10.1.2.1 1a */ + struct hmac_sha512_key key; /* current key -- 10.1.2.1 1b */ u8 C[DRBG_STATE_LEN]; /* current key -- 10.1.2.1 1b */ /* Number of RNG requests since last reseed -- 10.1.2.1 1c */ size_t reseed_ctr; size_t reseed_threshold; - void *priv_data; /* Cipher handle */ - enum drbg_seed_state seeded; /* DRBG fully seeded? */ unsigned long last_seed_time; bool pr; /* Prediction resistance enabled? */ @@ -186,94 +185,67 @@ static int drbg_uninstantiate(struct drbg_state *drbg); * HMAC DRBG functions ******************************************************************/ -static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval, - const struct list_head *in); -static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg, - const unsigned char *key); -static int drbg_init_hash_kernel(struct drbg_state *drbg); -static int drbg_fini_hash_kernel(struct drbg_state *drbg); - MODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha512"); MODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha512"); /* update function of HMAC DRBG as defined in 10.1.2.2 */ -static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed, - int reseed) +static void drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed, + int reseed) { - int ret = -EFAULT; int i = 0; - struct drbg_string seed1, seed2, vdata; - LIST_HEAD(seedlist); - LIST_HEAD(vdatalist); + struct hmac_sha512_ctx hmac_ctx; if (!reseed) { /* 10.1.2.3 step 2 -- memset(0) of C is implicit with kzalloc */ memset(drbg->V, 1, DRBG_STATE_LEN); - drbg_kcapi_hmacsetkey(drbg, drbg->C); + hmac_sha512_preparekey(&drbg->key, drbg->C, DRBG_STATE_LEN); } - drbg_string_fill(&seed1, drbg->V, DRBG_STATE_LEN); - list_add_tail(&seed1.list, &seedlist); - /* buffer of seed2 will be filled in for loop below with one byte */ - drbg_string_fill(&seed2, NULL, 1); - list_add_tail(&seed2.list, &seedlist); - /* input data of seed is allowed to be NULL at this point */ - if (seed) - list_splice_tail(seed, &seedlist); - - drbg_string_fill(&vdata, drbg->V, DRBG_STATE_LEN); - list_add_tail(&vdata.list, &vdatalist); for (i = 2; 0 < i; i--) { /* first round uses 0x0, second 0x1 */ unsigned char prefix = DRBG_PREFIX0; if (1 == i) prefix = DRBG_PREFIX1; /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */ - seed2.buf = &prefix; - ret = drbg_kcapi_hash(drbg, drbg->C, &seedlist); - if (ret) - return ret; - drbg_kcapi_hmacsetkey(drbg, drbg->C); + hmac_sha512_init(&hmac_ctx, &drbg->key); + hmac_sha512_update(&hmac_ctx, drbg->V, DRBG_STATE_LEN); + hmac_sha512_update(&hmac_ctx, &prefix, 1); + if (seed) { + struct drbg_string *input; + + list_for_each_entry(input, seed, list) + hmac_sha512_update(&hmac_ctx, input->buf, + input->len); + } + hmac_sha512_final(&hmac_ctx, drbg->C); + hmac_sha512_preparekey(&drbg->key, drbg->C, DRBG_STATE_LEN); /* 10.1.2.2 step 2 and 5 -- HMAC for V */ - ret = drbg_kcapi_hash(drbg, drbg->V, &vdatalist); - if (ret) - return ret; + hmac_sha512(&drbg->key, drbg->V, DRBG_STATE_LEN, drbg->V); /* 10.1.2.2 step 3 */ if (!seed) - return ret; + break; } - - return 0; } /* generate function of HMAC DRBG as defined in 10.1.2.5 */ -static int drbg_hmac_generate(struct drbg_state *drbg, - unsigned char *buf, - unsigned int buflen, - struct list_head *addtl) +static void drbg_hmac_generate(struct drbg_state *drbg, + unsigned char *buf, + unsigned int buflen, + struct list_head *addtl) { int len = 0; - int ret = 0; - struct drbg_string data; - LIST_HEAD(datalist); /* 10.1.2.5 step 2 */ - if (addtl && !list_empty(addtl)) { - ret = drbg_hmac_update(drbg, addtl, 1); - if (ret) - return ret; - } + if (addtl && !list_empty(addtl)) + drbg_hmac_update(drbg, addtl, 1); - drbg_string_fill(&data, drbg->V, DRBG_STATE_LEN); - list_add_tail(&data.list, &datalist); while (len < buflen) { unsigned int outlen = 0; + /* 10.1.2.5 step 4.1 */ - ret = drbg_kcapi_hash(drbg, drbg->V, &datalist); - if (ret) - return ret; + hmac_sha512(&drbg->key, drbg->V, DRBG_STATE_LEN, drbg->V); outlen = (DRBG_STATE_LEN < (buflen - len)) ? DRBG_STATE_LEN : (buflen - len); @@ -284,22 +256,15 @@ static int drbg_hmac_generate(struct drbg_state *drbg, /* 10.1.2.5 step 6 */ if (addtl && !list_empty(addtl)) - ret = drbg_hmac_update(drbg, addtl, 1); + drbg_hmac_update(drbg, addtl, 1); else - ret = drbg_hmac_update(drbg, NULL, 1); - if (ret) - return ret; - - return len; + drbg_hmac_update(drbg, NULL, 1); } -static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed, - int reseed, enum drbg_seed_state new_seed_state) +static inline void __drbg_seed(struct drbg_state *drbg, struct list_head *seed, + int reseed, enum drbg_seed_state new_seed_state) { - int ret = drbg_hmac_update(drbg, seed, reseed); - - if (ret) - return ret; + drbg_hmac_update(drbg, seed, reseed); drbg->seeded = new_seed_state; drbg->last_seed_time = jiffies; @@ -325,27 +290,23 @@ static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed, drbg->reseed_threshold = DRBG_MAX_REQUESTS; break; } - - return ret; } -static int drbg_seed_from_random(struct drbg_state *drbg) +static void drbg_seed_from_random(struct drbg_state *drbg) __must_hold(&drbg->drbg_mutex) { struct drbg_string data; LIST_HEAD(seedlist); unsigned char entropy[DRBG_SEC_STRENGTH]; - int ret; drbg_string_fill(&data, entropy, DRBG_SEC_STRENGTH); list_add_tail(&data.list, &seedlist); get_random_bytes(entropy, DRBG_SEC_STRENGTH); - ret = __drbg_seed(drbg, &seedlist, true, DRBG_SEED_STATE_FULL); + __drbg_seed(drbg, &seedlist, true, DRBG_SEED_STATE_FULL); memzero_explicit(entropy, DRBG_SEC_STRENGTH); - return ret; } static bool drbg_nopr_reseed_interval_elapsed(struct drbg_state *drbg) @@ -477,8 +438,8 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers, memset(drbg->C, 0, DRBG_STATE_LEN); } - ret = __drbg_seed(drbg, &seedlist, reseed, new_seed_state); - + __drbg_seed(drbg, &seedlist, reseed, new_seed_state); + ret = 0; out: memzero_explicit(entropy, sizeof(entropy)); @@ -490,30 +451,13 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg) { if (!drbg) return; + memzero_explicit(&drbg->key, sizeof(drbg->key)); memzero_explicit(drbg->V, sizeof(drbg->V)); memzero_explicit(drbg->C, sizeof(drbg->C)); drbg->reseed_ctr = 0; drbg->core = NULL; } -/* - * Allocate all sub-structures for a DRBG state. - * The DRBG state structure must already be allocated. - */ -static inline int drbg_alloc_state(struct drbg_state *drbg) -{ - int ret = -ENOMEM; - - ret = drbg_init_hash_kernel(drbg); - if (ret < 0) - goto err; - return 0; - -err: - drbg_dealloc_state(drbg); - return ret; -} - /* * DRBG generate function as required by SP800-90A - this function * generates random numbers @@ -590,20 +534,16 @@ static int drbg_generate(struct drbg_state *drbg, } else if (rng_is_initialized() && (drbg->seeded == DRBG_SEED_STATE_PARTIAL || drbg_nopr_reseed_interval_elapsed(drbg))) { - len = drbg_seed_from_random(drbg); - if (len) - goto err; + drbg_seed_from_random(drbg); } if (addtl && 0 < addtl->len) list_add_tail(&addtl->list, &addtllist); /* 9.3.1 step 8 and 10 */ - len = drbg_hmac_generate(drbg, buf, buflen, &addtllist); + drbg_hmac_generate(drbg, buf, buflen, &addtllist); /* 10.1.2.5 step 7 */ drbg->reseed_ctr++; - if (0 >= len) - goto err; /* * Section 11.3.3 requires to re-perform self tests after some @@ -718,10 +658,6 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers, drbg->last_seed_time = 0; drbg->reseed_threshold = DRBG_MAX_REQUESTS; - ret = drbg_alloc_state(drbg); - if (ret) - goto unlock; - ret = drbg_prepare_hrng(drbg); if (ret) goto free_everything; @@ -737,10 +673,6 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers, mutex_unlock(&drbg->drbg_mutex); return ret; -unlock: - mutex_unlock(&drbg->drbg_mutex); - return ret; - free_everything: mutex_unlock(&drbg->drbg_mutex); drbg_uninstantiate(drbg); @@ -762,7 +694,6 @@ static int drbg_uninstantiate(struct drbg_state *drbg) crypto_free_rng(drbg->jent); drbg->jent = NULL; - drbg_fini_hash_kernel(drbg); drbg_dealloc_state(drbg); /* no scrubbing of test_data -- this shall survive an uninstantiate */ return 0; @@ -785,70 +716,6 @@ static void drbg_kcapi_set_entropy(struct crypto_rng *tfm, mutex_unlock(&drbg->drbg_mutex); } -/*************************************************************** - * Kernel crypto API cipher invocations requested by DRBG - ***************************************************************/ - -struct sdesc { - struct shash_desc shash; -}; - -static int drbg_init_hash_kernel(struct drbg_state *drbg) -{ - struct sdesc *sdesc; - struct crypto_shash *tfm; - - tfm = crypto_alloc_shash(drbg->core->backend_cra_name, 0, 0); - if (IS_ERR(tfm)) { - pr_info("DRBG: could not allocate digest TFM handle: %s\n", - drbg->core->backend_cra_name); - return PTR_ERR(tfm); - } - BUG_ON(DRBG_STATE_LEN != crypto_shash_digestsize(tfm)); - sdesc = kzalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm), - GFP_KERNEL); - if (!sdesc) { - crypto_free_shash(tfm); - return -ENOMEM; - } - - sdesc->shash.tfm = tfm; - drbg->priv_data = sdesc; - - return 0; -} - -static int drbg_fini_hash_kernel(struct drbg_state *drbg) -{ - struct sdesc *sdesc = drbg->priv_data; - if (sdesc) { - crypto_free_shash(sdesc->shash.tfm); - kfree_sensitive(sdesc); - } - drbg->priv_data = NULL; - return 0; -} - -static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg, - const unsigned char *key) -{ - struct sdesc *sdesc = drbg->priv_data; - - crypto_shash_setkey(sdesc->shash.tfm, key, DRBG_STATE_LEN); -} - -static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval, - const struct list_head *in) -{ - struct sdesc *sdesc = drbg->priv_data; - struct drbg_string *input = NULL; - - crypto_shash_init(&sdesc->shash); - list_for_each_entry(input, in, list) - crypto_shash_update(&sdesc->shash, input->buf, input->len); - return crypto_shash_final(&sdesc->shash, outval); -} - /*************************************************************** * Kernel crypto API interface to register DRBG ***************************************************************/ From e8806e2e97dc769e03c1fc50ed32622dad476dfb Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:07 -0700 Subject: [PATCH 034/196] crypto: drbg - Remove drbg_core Now that none of the information in struct drbg_core is used, remove it. The null-ity of the pointer drbg_state::core was used to keep track of whether the DRBG has been instantiated. Replace it with a boolean. No functional change. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 99 +++++++-------------------------------------------- 1 file changed, 13 insertions(+), 86 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index 4f326385cf36..161070b10f85 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -100,14 +100,6 @@ #include #include -struct drbg_state; - -struct drbg_core { - char cra_name[CRYPTO_MAX_ALG_NAME]; /* mapping to kernel crypto API */ - /* kernel crypto API backend cipher name */ - char backend_cra_name[CRYPTO_MAX_ALG_NAME]; -}; - enum drbg_seed_state { DRBG_SEED_STATE_UNSEEDED, DRBG_SEED_STATE_PARTIAL, /* Seeded with !rng_is_initialized() */ @@ -150,9 +142,9 @@ struct drbg_state { size_t reseed_threshold; enum drbg_seed_state seeded; /* DRBG fully seeded? */ unsigned long last_seed_time; + bool instantiated; bool pr; /* Prediction resistance enabled? */ struct crypto_rng *jent; - const struct drbg_core *core; struct drbg_string test_data; }; @@ -161,24 +153,6 @@ enum drbg_prefixes { DRBG_PREFIX1, }; -/*************************************************************** - * Backend cipher definitions available to DRBG - ***************************************************************/ - -/* - * The order of the DRBG definitions here matter: every DRBG is registered - * as stdrng. Each DRBG receives an increasing cra_priority values the later - * they are defined in this array (see drbg_fill_array). - * - * Thus, the favored DRBGs are the latest entries in this array. - */ -static const struct drbg_core drbg_cores[] = { - { - .cra_name = "hmac_sha512", - .backend_cra_name = "hmac(sha512)", - }, -}; - static int drbg_uninstantiate(struct drbg_state *drbg); /****************************************************************** @@ -455,7 +429,7 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg) memzero_explicit(drbg->V, sizeof(drbg->V)); memzero_explicit(drbg->C, sizeof(drbg->C)); drbg->reseed_ctr = 0; - drbg->core = NULL; + drbg->instantiated = false; } /* @@ -482,8 +456,8 @@ static int drbg_generate(struct drbg_state *drbg, int len = 0; LIST_HEAD(addtllist); - if (!drbg->core) { - pr_devel("DRBG: not yet seeded\n"); + if (!drbg->instantiated) { + pr_devel("DRBG: not yet instantiated\n"); return -EINVAL; } if (0 == buflen || !buf) { @@ -625,7 +599,6 @@ static int drbg_prepare_hrng(struct drbg_state *drbg) * the entropy is pulled by the DRBG internally unconditionally * as defined in SP800-90A. The additional input is mixed into * the state in addition to the pulled entropy. - * @coreref reference to core * @pr prediction resistance enabled * * return @@ -633,13 +606,13 @@ static int drbg_prepare_hrng(struct drbg_state *drbg) * error value otherwise */ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers, - int coreref, bool pr) + bool pr) { int ret; bool reseed = true; - pr_devel("DRBG: Initializing DRBG core %d with prediction resistance " - "%s\n", coreref, str_enabled_disabled(pr)); + pr_devel("DRBG: Initializing DRBG with prediction resistance %s\n", + str_enabled_disabled(pr)); mutex_lock(&drbg->drbg_mutex); /* 9.1 step 1 is implicit with the selected DRBG type */ @@ -651,8 +624,8 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers, /* 9.1 step 4 is implicit in DRBG_SEC_STRENGTH */ - if (!drbg->core) { - drbg->core = &drbg_cores[coreref]; + if (!drbg->instantiated) { + drbg->instantiated = true; drbg->pr = pr; drbg->seeded = DRBG_SEED_STATE_UNSEEDED; drbg->last_seed_time = 0; @@ -720,46 +693,6 @@ static void drbg_kcapi_set_entropy(struct crypto_rng *tfm, * Kernel crypto API interface to register DRBG ***************************************************************/ -/* - * Look up the DRBG flags by given kernel crypto API cra_name - * The code uses the drbg_cores definition to do this - * - * @cra_name kernel crypto API cra_name - * @coreref reference to integer which is filled with the pointer to - * the applicable core - * @pr reference for setting prediction resistance - * - * return: flags - */ -static inline void drbg_convert_tfm_core(const char *cra_driver_name, - int *coreref, bool *pr) -{ - int i = 0; - size_t start = 0; - int len = 0; - - *pr = true; - /* disassemble the names */ - if (!memcmp(cra_driver_name, "drbg_nopr_", 10)) { - start = 10; - *pr = false; - } else if (!memcmp(cra_driver_name, "drbg_pr_", 8)) { - start = 8; - } else { - return; - } - - /* remove the first part */ - len = strlen(cra_driver_name) - start; - for (i = 0; ARRAY_SIZE(drbg_cores) > i; i++) { - if (!memcmp(cra_driver_name + start, drbg_cores[i].cra_name, - len)) { - *coreref = i; - return; - } - } -} - static int drbg_kcapi_init(struct crypto_tfm *tfm) { struct drbg_state *drbg = crypto_tfm_ctx(tfm); @@ -808,19 +741,17 @@ static int drbg_kcapi_seed(struct crypto_rng *tfm, { struct drbg_state *drbg = crypto_rng_ctx(tfm); struct crypto_tfm *tfm_base = crypto_rng_tfm(tfm); - bool pr = false; + bool pr = memcmp(crypto_tfm_alg_driver_name(tfm_base), + "drbg_nopr_", 10) != 0; struct drbg_string string; struct drbg_string *seed_string = NULL; - int coreref = 0; - drbg_convert_tfm_core(crypto_tfm_alg_driver_name(tfm_base), &coreref, - &pr); if (0 < slen) { drbg_string_fill(&string, seed, slen); seed_string = &string; } - return drbg_instantiate(drbg, seed_string, coreref, pr); + return drbg_instantiate(drbg, seed_string, pr); } /*************************************************************** @@ -844,22 +775,18 @@ static inline int __init drbg_healthcheck_sanity(void) struct drbg_state *drbg = NULL; int ret; int rc = -EFAULT; - bool pr = false; - int coreref = 0; struct drbg_string addtl; /* only perform test in FIPS mode */ if (!fips_enabled) return 0; - drbg_convert_tfm_core("drbg_nopr_hmac_sha512", &coreref, &pr); - drbg = kzalloc_obj(struct drbg_state); if (!drbg) return -ENOMEM; guard(mutex_init)(&drbg->drbg_mutex); - drbg->core = &drbg_cores[coreref]; + drbg->instantiated = true; drbg->reseed_threshold = DRBG_MAX_REQUESTS; /* From 7f0ef29864ebf2ab5fea04523cc0bd8f1c7d1ccd Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:08 -0700 Subject: [PATCH 035/196] crypto: drbg - Install separate seed functions for pr and nopr Set rng_alg::seed to different functions for the prediction-resistant and non-prediction-resistant algorithms, so that the function does not need to parse the algorithm name to figure out which algorithm it is. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index 161070b10f85..c29f4ca93d1b 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -733,16 +733,11 @@ static int drbg_kcapi_random(struct crypto_rng *tfm, return drbg_generate_long(drbg, dst, dlen, addtl); } -/* - * Seed the DRBG invoked by the kernel crypto API - */ +/* Seed (i.e. instantiate) or re-seed the DRBG. */ static int drbg_kcapi_seed(struct crypto_rng *tfm, - const u8 *seed, unsigned int slen) + const u8 *seed, unsigned int slen, bool pr) { struct drbg_state *drbg = crypto_rng_ctx(tfm); - struct crypto_tfm *tfm_base = crypto_rng_tfm(tfm); - bool pr = memcmp(crypto_tfm_alg_driver_name(tfm_base), - "drbg_nopr_", 10) != 0; struct drbg_string string; struct drbg_string *seed_string = NULL; @@ -754,6 +749,18 @@ static int drbg_kcapi_seed(struct crypto_rng *tfm, return drbg_instantiate(drbg, seed_string, pr); } +static int drbg_kcapi_seed_pr(struct crypto_rng *tfm, + const u8 *seed, unsigned int slen) +{ + return drbg_kcapi_seed(tfm, seed, slen, /* pr= */ true); +} + +static int drbg_kcapi_seed_nopr(struct crypto_rng *tfm, + const u8 *seed, unsigned int slen) +{ + return drbg_kcapi_seed(tfm, seed, slen, /* pr= */ false); +} + /*************************************************************** * Kernel module: code to load the module ***************************************************************/ @@ -827,7 +834,7 @@ static struct rng_alg drbg_algs[] = { .base.cra_module = THIS_MODULE, .base.cra_init = drbg_kcapi_init, .set_ent = drbg_kcapi_set_entropy, - .seed = drbg_kcapi_seed, + .seed = drbg_kcapi_seed_pr, .generate = drbg_kcapi_random, .base.cra_exit = drbg_kcapi_cleanup, }, @@ -839,7 +846,7 @@ static struct rng_alg drbg_algs[] = { .base.cra_module = THIS_MODULE, .base.cra_init = drbg_kcapi_init, .set_ent = drbg_kcapi_set_entropy, - .seed = drbg_kcapi_seed, + .seed = drbg_kcapi_seed_nopr, .generate = drbg_kcapi_random, .base.cra_exit = drbg_kcapi_cleanup, }, From 54957e44db1fc3524da15e34c6c86f77bbd664da Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:09 -0700 Subject: [PATCH 036/196] crypto: drbg - Move module aliases to end of file Move the MODULE_ALIAS_CRYPTO lines in the middle of the file to the end so that they are in the usual place and next to the other one. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index c29f4ca93d1b..439581d7bb83 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -159,9 +159,6 @@ static int drbg_uninstantiate(struct drbg_state *drbg); * HMAC DRBG functions ******************************************************************/ -MODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha512"); -MODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha512"); - /* update function of HMAC DRBG as defined in 10.1.2.2 */ static void drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed, int reseed) @@ -883,3 +880,5 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Stephan Mueller "); MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG)"); MODULE_ALIAS_CRYPTO("stdrng"); +MODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha512"); +MODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha512"); From 2245b1bfecc861e000f115f017e08eeed4808191 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:10 -0700 Subject: [PATCH 037/196] crypto: drbg - Consolidate "instantiate" logic and remove drbg_state::C Currently some of the steps of "Instantiate the DRBG" occur in a convoluted way in different places in the call stack: drbg_instantiate() => drbg_seed(reseed=0) sets the raw HMAC key drbg_state::C to its correct initial value, and it sets the state value drbg_state::V to an *incorrect* initial value. => drbg_hmac_update(reseed=0) overwrites drbg_state::V with the correct initial value, then prepares the hmac_sha512_key drbg_state::key from the initial raw HMAC key drbg_state::C. Later, each time the HMAC key is updated, drbg_hmac_update() also uses drbg_state::C to temporarily store the new raw key. Simplify all of this by: - Making drbg_instantiate() set the correct initial values of drbg_state::V and drbg_state::key. - Converting drbg_hmac_update() to generate the raw key in a temporary on-stack array instead of drbg_state::C. - Removing drbg_state::C. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index 439581d7bb83..7e3ab2f811b6 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -136,7 +136,6 @@ struct drbg_state { struct mutex drbg_mutex; /* lock around DRBG */ u8 V[DRBG_STATE_LEN]; /* internal state -- 10.1.2.1 1a */ struct hmac_sha512_key key; /* current key -- 10.1.2.1 1b */ - u8 C[DRBG_STATE_LEN]; /* current key -- 10.1.2.1 1b */ /* Number of RNG requests since last reseed -- 10.1.2.1 1c */ size_t reseed_ctr; size_t reseed_threshold; @@ -160,17 +159,11 @@ static int drbg_uninstantiate(struct drbg_state *drbg); ******************************************************************/ /* update function of HMAC DRBG as defined in 10.1.2.2 */ -static void drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed, - int reseed) +static void drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed) { int i = 0; struct hmac_sha512_ctx hmac_ctx; - - if (!reseed) { - /* 10.1.2.3 step 2 -- memset(0) of C is implicit with kzalloc */ - memset(drbg->V, 1, DRBG_STATE_LEN); - hmac_sha512_preparekey(&drbg->key, drbg->C, DRBG_STATE_LEN); - } + u8 new_key[DRBG_STATE_LEN]; for (i = 2; 0 < i; i--) { /* first round uses 0x0, second 0x1 */ @@ -188,8 +181,8 @@ static void drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed, hmac_sha512_update(&hmac_ctx, input->buf, input->len); } - hmac_sha512_final(&hmac_ctx, drbg->C); - hmac_sha512_preparekey(&drbg->key, drbg->C, DRBG_STATE_LEN); + hmac_sha512_final(&hmac_ctx, new_key); + hmac_sha512_preparekey(&drbg->key, new_key, DRBG_STATE_LEN); /* 10.1.2.2 step 2 and 5 -- HMAC for V */ hmac_sha512(&drbg->key, drbg->V, DRBG_STATE_LEN, drbg->V); @@ -198,6 +191,7 @@ static void drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed, if (!seed) break; } + memzero_explicit(new_key, sizeof(new_key)); } /* generate function of HMAC DRBG as defined in 10.1.2.5 */ @@ -210,7 +204,7 @@ static void drbg_hmac_generate(struct drbg_state *drbg, /* 10.1.2.5 step 2 */ if (addtl && !list_empty(addtl)) - drbg_hmac_update(drbg, addtl, 1); + drbg_hmac_update(drbg, addtl); while (len < buflen) { unsigned int outlen = 0; @@ -227,15 +221,15 @@ static void drbg_hmac_generate(struct drbg_state *drbg, /* 10.1.2.5 step 6 */ if (addtl && !list_empty(addtl)) - drbg_hmac_update(drbg, addtl, 1); + drbg_hmac_update(drbg, addtl); else - drbg_hmac_update(drbg, NULL, 1); + drbg_hmac_update(drbg, NULL); } static inline void __drbg_seed(struct drbg_state *drbg, struct list_head *seed, - int reseed, enum drbg_seed_state new_seed_state) + enum drbg_seed_state new_seed_state) { - drbg_hmac_update(drbg, seed, reseed); + drbg_hmac_update(drbg, seed); drbg->seeded = new_seed_state; drbg->last_seed_time = jiffies; @@ -275,7 +269,7 @@ static void drbg_seed_from_random(struct drbg_state *drbg) get_random_bytes(entropy, DRBG_SEC_STRENGTH); - __drbg_seed(drbg, &seedlist, true, DRBG_SEED_STATE_FULL); + __drbg_seed(drbg, &seedlist, DRBG_SEED_STATE_FULL); memzero_explicit(entropy, DRBG_SEC_STRENGTH); } @@ -404,12 +398,8 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers, pr_devel("DRBG: using personalization string\n"); } - if (!reseed) { - memset(drbg->V, 0, DRBG_STATE_LEN); - memset(drbg->C, 0, DRBG_STATE_LEN); - } - __drbg_seed(drbg, &seedlist, reseed, new_seed_state); + __drbg_seed(drbg, &seedlist, new_seed_state); ret = 0; out: memzero_explicit(entropy, sizeof(entropy)); @@ -424,7 +414,6 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg) return; memzero_explicit(&drbg->key, sizeof(drbg->key)); memzero_explicit(drbg->V, sizeof(drbg->V)); - memzero_explicit(drbg->C, sizeof(drbg->C)); drbg->reseed_ctr = 0; drbg->instantiated = false; } @@ -605,6 +594,7 @@ static int drbg_prepare_hrng(struct drbg_state *drbg) static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers, bool pr) { + static const u8 initial_key[DRBG_STATE_LEN]; /* all zeroes */ int ret; bool reseed = true; @@ -627,6 +617,8 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers, drbg->seeded = DRBG_SEED_STATE_UNSEEDED; drbg->last_seed_time = 0; drbg->reseed_threshold = DRBG_MAX_REQUESTS; + memset(drbg->V, 1, DRBG_STATE_LEN); + hmac_sha512_preparekey(&drbg->key, initial_key, DRBG_STATE_LEN); ret = drbg_prepare_hrng(drbg); if (ret) From 6585b5b4fddd47c174310a57930369e52335a034 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:11 -0700 Subject: [PATCH 038/196] crypto: drbg - Eliminate use of 'drbg_string' and lists Use straightforward (buffer, len) parameters instead of struct drbg_string or lists of strings. This simplifies the code considerably. For now struct drbg_string is still used in crypto_drbg_ctr_df(), so move its definition to crypto/df_sp80090a.h. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/df_sp80090a.c | 1 - crypto/drbg.c | 179 +++++++++++----------------- drivers/crypto/xilinx/xilinx-trng.c | 1 - include/crypto/df_sp80090a.h | 25 ++++ include/crypto/internal/drbg.h | 39 ------ 5 files changed, 94 insertions(+), 151 deletions(-) delete mode 100644 include/crypto/internal/drbg.h diff --git a/crypto/df_sp80090a.c b/crypto/df_sp80090a.c index f4bb7be016e8..90e1973ee40c 100644 --- a/crypto/df_sp80090a.c +++ b/crypto/df_sp80090a.c @@ -13,7 +13,6 @@ #include #include #include -#include static void drbg_kcapi_sym(struct aes_enckey *aeskey, unsigned char *outval, const struct drbg_string *in, u8 blocklen_bytes) diff --git a/crypto/drbg.c b/crypto/drbg.c index 7e3ab2f811b6..b0cd8da51b26 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -89,7 +89,6 @@ * Just mix both scenarios above. */ -#include #include #include #include @@ -144,7 +143,8 @@ struct drbg_state { bool instantiated; bool pr; /* Prediction resistance enabled? */ struct crypto_rng *jent; - struct drbg_string test_data; + const u8 *test_entropy; + size_t test_entropylen; }; enum drbg_prefixes { @@ -159,7 +159,9 @@ static int drbg_uninstantiate(struct drbg_state *drbg); ******************************************************************/ /* update function of HMAC DRBG as defined in 10.1.2.2 */ -static void drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed) +static void drbg_hmac_update(struct drbg_state *drbg, + const u8 *data1, size_t data1_len, + const u8 *data2, size_t data2_len) { int i = 0; struct hmac_sha512_ctx hmac_ctx; @@ -174,13 +176,8 @@ static void drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed) hmac_sha512_init(&hmac_ctx, &drbg->key); hmac_sha512_update(&hmac_ctx, drbg->V, DRBG_STATE_LEN); hmac_sha512_update(&hmac_ctx, &prefix, 1); - if (seed) { - struct drbg_string *input; - - list_for_each_entry(input, seed, list) - hmac_sha512_update(&hmac_ctx, input->buf, - input->len); - } + hmac_sha512_update(&hmac_ctx, data1, data1_len); + hmac_sha512_update(&hmac_ctx, data2, data2_len); hmac_sha512_final(&hmac_ctx, new_key); hmac_sha512_preparekey(&drbg->key, new_key, DRBG_STATE_LEN); @@ -188,7 +185,7 @@ static void drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed) hmac_sha512(&drbg->key, drbg->V, DRBG_STATE_LEN, drbg->V); /* 10.1.2.2 step 3 */ - if (!seed) + if (data1_len == 0 && data2_len == 0) break; } memzero_explicit(new_key, sizeof(new_key)); @@ -198,13 +195,13 @@ static void drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed) static void drbg_hmac_generate(struct drbg_state *drbg, unsigned char *buf, unsigned int buflen, - struct list_head *addtl) + const u8 *addtl, size_t addtl_len) { int len = 0; /* 10.1.2.5 step 2 */ - if (addtl && !list_empty(addtl)) - drbg_hmac_update(drbg, addtl); + if (addtl_len) + drbg_hmac_update(drbg, addtl, addtl_len, NULL, 0); while (len < buflen) { unsigned int outlen = 0; @@ -220,16 +217,15 @@ static void drbg_hmac_generate(struct drbg_state *drbg, } /* 10.1.2.5 step 6 */ - if (addtl && !list_empty(addtl)) - drbg_hmac_update(drbg, addtl); - else - drbg_hmac_update(drbg, NULL); + drbg_hmac_update(drbg, addtl, addtl_len, NULL, 0); } -static inline void __drbg_seed(struct drbg_state *drbg, struct list_head *seed, +static inline void __drbg_seed(struct drbg_state *drbg, + const u8 *seed1, size_t seed1_len, + const u8 *seed2, size_t seed2_len, enum drbg_seed_state new_seed_state) { - drbg_hmac_update(drbg, seed); + drbg_hmac_update(drbg, seed1, seed1_len, seed2, seed2_len); drbg->seeded = new_seed_state; drbg->last_seed_time = jiffies; @@ -260,16 +256,12 @@ static inline void __drbg_seed(struct drbg_state *drbg, struct list_head *seed, static void drbg_seed_from_random(struct drbg_state *drbg) __must_hold(&drbg->drbg_mutex) { - struct drbg_string data; - LIST_HEAD(seedlist); - unsigned char entropy[DRBG_SEC_STRENGTH]; - - drbg_string_fill(&data, entropy, DRBG_SEC_STRENGTH); - list_add_tail(&data.list, &seedlist); + u8 entropy[DRBG_SEC_STRENGTH]; get_random_bytes(entropy, DRBG_SEC_STRENGTH); - __drbg_seed(drbg, &seedlist, DRBG_SEED_STATE_FULL); + __drbg_seed(drbg, entropy, DRBG_SEC_STRENGTH, NULL, 0, + DRBG_SEED_STATE_FULL); memzero_explicit(entropy, DRBG_SEC_STRENGTH); } @@ -279,7 +271,7 @@ static bool drbg_nopr_reseed_interval_elapsed(struct drbg_state *drbg) unsigned long next_reseed; /* Don't ever reseed from get_random_bytes() in test mode. */ - if (list_empty(&drbg->test_data.list)) + if (drbg->test_entropylen) return false; /* @@ -299,33 +291,33 @@ static bool drbg_nopr_reseed_interval_elapsed(struct drbg_state *drbg) * * @drbg: DRBG state struct * @pers: personalization / additional information buffer - * @reseed: 0 for initial seed process, 1 for reseeding + * @pers_len: length of @pers in bytes + * @reseed: false for initial seeding (instantiation), true for reseeding * * return: * 0 on success * error value otherwise */ -static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers, +static int drbg_seed(struct drbg_state *drbg, const u8 *pers, size_t pers_len, bool reseed) __must_hold(&drbg->drbg_mutex) { int ret; - unsigned char entropy[((32 + 16) * 2)]; - unsigned int entropylen; - struct drbg_string data1; - LIST_HEAD(seedlist); + u8 entropy_buf[(32 + 16) * 2]; + size_t entropylen; + const u8 *entropy; enum drbg_seed_state new_seed_state = DRBG_SEED_STATE_FULL; /* 9.1 / 9.2 / 9.3.1 step 3 */ - if (pers && pers->len > DRBG_MAX_ADDTL) { + if (pers_len > DRBG_MAX_ADDTL) { pr_devel("DRBG: personalization string too long %zu\n", - pers->len); + pers_len); return -EINVAL; } - if (list_empty(&drbg->test_data.list)) { - drbg_string_fill(&data1, drbg->test_data.buf, - drbg->test_data.len); + if (drbg->test_entropylen) { + entropy = drbg->test_entropy; + entropylen = drbg->test_entropylen; pr_devel("DRBG: using test entropy\n"); } else { /* @@ -336,21 +328,21 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers, * of the strength. The consideration of a nonce is only * applicable during initial seeding. */ + entropy = entropy_buf; if (!reseed) entropylen = ((DRBG_SEC_STRENGTH + 1) / 2) * 3; else entropylen = DRBG_SEC_STRENGTH; - BUG_ON((entropylen * 2) > sizeof(entropy)); + BUG_ON(entropylen * 2 > sizeof(entropy_buf)); /* Get seed from in-kernel /dev/urandom */ if (!rng_is_initialized()) new_seed_state = DRBG_SEED_STATE_PARTIAL; - get_random_bytes(entropy, entropylen); + get_random_bytes(entropy_buf, entropylen); if (!drbg->jent) { - drbg_string_fill(&data1, entropy, entropylen); - pr_devel("DRBG: (re)seeding with %u bytes of entropy\n", + pr_devel("DRBG: (re)seeding with %zu bytes of entropy\n", entropylen); } else { /* @@ -358,7 +350,7 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers, * fatal only in FIPS mode. */ ret = crypto_rng_get_bytes(drbg->jent, - entropy + entropylen, + &entropy_buf[entropylen], entropylen); if (fips_enabled && ret) { pr_devel("DRBG: jent failed with %d\n", ret); @@ -381,28 +373,19 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers, goto out; } - drbg_string_fill(&data1, entropy, entropylen * 2); - pr_devel("DRBG: (re)seeding with %u bytes of entropy\n", - entropylen * 2); + entropylen *= 2; + pr_devel("DRBG: (re)seeding with %zu bytes of entropy\n", + entropylen); } } - list_add_tail(&data1.list, &seedlist); - /* - * concatenation of entropy with personalization str / addtl input) - * the variable pers is directly handed in by the caller, so check its - * contents whether it is appropriate - */ - if (pers && pers->buf && 0 < pers->len) { - list_add_tail(&pers->list, &seedlist); + if (pers_len) pr_devel("DRBG: using personalization string\n"); - } - - __drbg_seed(drbg, &seedlist, new_seed_state); + __drbg_seed(drbg, entropy, entropylen, pers, pers_len, new_seed_state); ret = 0; out: - memzero_explicit(entropy, sizeof(entropy)); + memzero_explicit(entropy_buf, sizeof(entropy_buf)); return ret; } @@ -427,20 +410,17 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg) * be pre-allocated by caller * @buflen Length of output buffer - this value defines the number of random * bytes pulled from DRBG - * @addtl Additional input that is mixed into state, may be NULL -- note - * the entropy is pulled by the DRBG internally unconditionally - * as defined in SP800-90A. The additional input is mixed into - * the state in addition to the pulled entropy. + * @addtl Optional additional input that is mixed into state + * @addtl_len Length of @addtl in bytes, may be 0 * * return: 0 when all bytes are generated; < 0 in case of an error */ static int drbg_generate(struct drbg_state *drbg, unsigned char *buf, unsigned int buflen, - struct drbg_string *addtl) + const u8 *addtl, size_t addtl_len) __must_hold(&drbg->drbg_mutex) { int len = 0; - LIST_HEAD(addtllist); if (!drbg->instantiated) { pr_devel("DRBG: not yet instantiated\n"); @@ -450,7 +430,7 @@ static int drbg_generate(struct drbg_state *drbg, pr_devel("DRBG: no output buffer provided\n"); return -EINVAL; } - if (addtl && NULL == addtl->buf && 0 < addtl->len) { + if (addtl == NULL && addtl_len != 0) { pr_devel("DRBG: wrong format of additional information\n"); return -EINVAL; } @@ -465,9 +445,9 @@ static int drbg_generate(struct drbg_state *drbg, /* 9.3.1 step 3 is implicit with the chosen DRBG */ /* 9.3.1 step 4 */ - if (addtl && addtl->len > DRBG_MAX_ADDTL) { + if (addtl_len > DRBG_MAX_ADDTL) { pr_devel("DRBG: additional information string too long %zu\n", - addtl->len); + addtl_len); return -EINVAL; } /* 9.3.1 step 5 is implicit with the chosen DRBG */ @@ -486,21 +466,20 @@ static int drbg_generate(struct drbg_state *drbg, (drbg->seeded == DRBG_SEED_STATE_FULL ? "seeded" : "unseeded")); /* 9.3.1 steps 7.1 through 7.3 */ - len = drbg_seed(drbg, addtl, true); + len = drbg_seed(drbg, addtl, addtl_len, true); if (len) goto err; /* 9.3.1 step 7.4 */ addtl = NULL; + addtl_len = 0; } else if (rng_is_initialized() && (drbg->seeded == DRBG_SEED_STATE_PARTIAL || drbg_nopr_reseed_interval_elapsed(drbg))) { drbg_seed_from_random(drbg); } - if (addtl && 0 < addtl->len) - list_add_tail(&addtl->list, &addtllist); /* 9.3.1 step 8 and 10 */ - drbg_hmac_generate(drbg, buf, buflen, &addtllist); + drbg_hmac_generate(drbg, buf, buflen, addtl, addtl_len); /* 10.1.2.5 step 7 */ drbg->reseed_ctr++; @@ -537,7 +516,7 @@ err: */ static int drbg_generate_long(struct drbg_state *drbg, unsigned char *buf, unsigned int buflen, - struct drbg_string *addtl) + const u8 *addtl, size_t addtl_len) { unsigned int len = 0; unsigned int slice = 0; @@ -547,7 +526,7 @@ static int drbg_generate_long(struct drbg_state *drbg, slice = (buflen - len) / DRBG_MAX_REQUEST_BYTES; chunk = slice ? DRBG_MAX_REQUEST_BYTES : (buflen - len); mutex_lock(&drbg->drbg_mutex); - err = drbg_generate(drbg, buf + len, chunk, addtl); + err = drbg_generate(drbg, buf + len, chunk, addtl, addtl_len); mutex_unlock(&drbg->drbg_mutex); if (0 > err) return err; @@ -559,7 +538,7 @@ static int drbg_generate_long(struct drbg_state *drbg, static int drbg_prepare_hrng(struct drbg_state *drbg) { /* We do not need an HRNG in test mode. */ - if (list_empty(&drbg->test_data.list)) + if (drbg->test_entropylen != 0) return 0; drbg->jent = crypto_alloc_rng("jitterentropy_rng", 0, 0); @@ -581,18 +560,16 @@ static int drbg_prepare_hrng(struct drbg_state *drbg) * checks required by SP800-90A * * @drbg memory of state -- if NULL, new memory is allocated - * @pers Personalization string that is mixed into state, may be NULL -- note - * the entropy is pulled by the DRBG internally unconditionally - * as defined in SP800-90A. The additional input is mixed into - * the state in addition to the pulled entropy. + * @pers Optional personalization string that is mixed into state + * @pers_len Length of personalization string in bytes, may be 0 * @pr prediction resistance enabled * * return * 0 on success * error value otherwise */ -static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers, - bool pr) +static int drbg_instantiate(struct drbg_state *drbg, + const u8 *pers, size_t pers_len, bool pr) { static const u8 initial_key[DRBG_STATE_LEN]; /* all zeroes */ int ret; @@ -627,7 +604,7 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers, reseed = false; } - ret = drbg_seed(drbg, pers, reseed); + ret = drbg_seed(drbg, pers, pers_len, reseed); if (ret && !reseed) goto free_everything; @@ -674,7 +651,8 @@ static void drbg_kcapi_set_entropy(struct crypto_rng *tfm, struct drbg_state *drbg = crypto_rng_ctx(tfm); mutex_lock(&drbg->drbg_mutex); - drbg_string_fill(&drbg->test_data, data, len); + drbg->test_entropy = data; + drbg->test_entropylen = len; mutex_unlock(&drbg->drbg_mutex); } @@ -710,16 +688,8 @@ static int drbg_kcapi_random(struct crypto_rng *tfm, u8 *dst, unsigned int dlen) { struct drbg_state *drbg = crypto_rng_ctx(tfm); - struct drbg_string *addtl = NULL; - struct drbg_string string; - if (slen) { - /* linked list variable is now local to allow modification */ - drbg_string_fill(&string, src, slen); - addtl = &string; - } - - return drbg_generate_long(drbg, dst, dlen, addtl); + return drbg_generate_long(drbg, dst, dlen, src, slen); } /* Seed (i.e. instantiate) or re-seed the DRBG. */ @@ -727,15 +697,8 @@ static int drbg_kcapi_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen, bool pr) { struct drbg_state *drbg = crypto_rng_ctx(tfm); - struct drbg_string string; - struct drbg_string *seed_string = NULL; - if (0 < slen) { - drbg_string_fill(&string, seed, slen); - seed_string = &string; - } - - return drbg_instantiate(drbg, seed_string, pr); + return drbg_instantiate(drbg, seed, slen, pr); } static int drbg_kcapi_seed_pr(struct crypto_rng *tfm, @@ -767,11 +730,9 @@ static int drbg_kcapi_seed_nopr(struct crypto_rng *tfm, static inline int __init drbg_healthcheck_sanity(void) { #define OUTBUFLEN 16 - unsigned char buf[OUTBUFLEN]; + u8 buf[OUTBUFLEN]; struct drbg_state *drbg = NULL; int ret; - int rc = -EFAULT; - struct drbg_string addtl; /* only perform test in FIPS mode */ if (!fips_enabled) @@ -793,25 +754,23 @@ static inline int __init drbg_healthcheck_sanity(void) * grave bug. */ - drbg_string_fill(&addtl, buf, DRBG_MAX_ADDTL + 1); /* overflow addtllen with additional info string */ - ret = drbg_generate(drbg, buf, OUTBUFLEN, &addtl); + ret = drbg_generate(drbg, buf, OUTBUFLEN, buf, DRBG_MAX_ADDTL + 1); BUG_ON(ret == 0); /* overflow max_bits */ - ret = drbg_generate(drbg, buf, DRBG_MAX_REQUEST_BYTES + 1, NULL); + ret = drbg_generate(drbg, buf, DRBG_MAX_REQUEST_BYTES + 1, NULL, 0); BUG_ON(ret == 0); /* overflow max addtllen with personalization string */ - ret = drbg_seed(drbg, &addtl, false); - BUG_ON(0 == ret); + ret = drbg_seed(drbg, buf, DRBG_MAX_ADDTL + 1, false); + BUG_ON(ret == 0); /* all tests passed */ - rc = 0; pr_devel("DRBG: Sanity tests for failure code paths successfully " "completed\n"); kfree(drbg); - return rc; + return 0; } static struct rng_alg drbg_algs[] = { diff --git a/drivers/crypto/xilinx/xilinx-trng.c b/drivers/crypto/xilinx/xilinx-trng.c index 5276ac2d82bb..43a4832f07e7 100644 --- a/drivers/crypto/xilinx/xilinx-trng.c +++ b/drivers/crypto/xilinx/xilinx-trng.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include diff --git a/include/crypto/df_sp80090a.h b/include/crypto/df_sp80090a.h index cb5d6fe15d40..e594fb718eb8 100644 --- a/include/crypto/df_sp80090a.h +++ b/include/crypto/df_sp80090a.h @@ -9,6 +9,31 @@ #include #include +#include + +/* + * Concatenation Helper and string operation helper + * + * SP800-90A requires the concatenation of different data. To avoid copying + * buffers around or allocate additional memory, the following data structure + * is used to point to the original memory with its size. In addition, it + * is used to build a linked list. The linked list defines the concatenation + * of individual buffers. The order of memory block referenced in that + * linked list determines the order of concatenation. + */ +struct drbg_string { + const unsigned char *buf; + size_t len; + struct list_head list; +}; + +static inline void drbg_string_fill(struct drbg_string *string, + const unsigned char *buf, size_t len) +{ + string->buf = buf; + string->len = len; + INIT_LIST_HEAD(&string->list); +} static inline int crypto_drbg_ctr_df_datalen(u8 statelen, u8 blocklen) { diff --git a/include/crypto/internal/drbg.h b/include/crypto/internal/drbg.h deleted file mode 100644 index 5d4174cc6a53..000000000000 --- a/include/crypto/internal/drbg.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/* - * NIST SP800-90A DRBG derivation function - * - * Copyright (C) 2014, Stephan Mueller - */ - -#ifndef _INTERNAL_DRBG_H -#define _INTERNAL_DRBG_H - -#include -#include - -/* - * Concatenation Helper and string operation helper - * - * SP800-90A requires the concatenation of different data. To avoid copying - * buffers around or allocate additional memory, the following data structure - * is used to point to the original memory with its size. In addition, it - * is used to build a linked list. The linked list defines the concatenation - * of individual buffers. The order of memory block referenced in that - * linked list determines the order of concatenation. - */ -struct drbg_string { - const unsigned char *buf; - size_t len; - struct list_head list; -}; - -static inline void drbg_string_fill(struct drbg_string *string, - const unsigned char *buf, size_t len) -{ - string->buf = buf; - string->len = len; - INIT_LIST_HEAD(&string->list); -} - -#endif //_INTERNAL_DRBG_H From 7ba94ec2d896590d2200ac7999f6a7fae970e72b Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:12 -0700 Subject: [PATCH 039/196] crypto: drbg - Simplify drbg_generate_long() and fold into caller Simplify drbg_generate_long() to use a more straightforward loop, and then fold it into its only caller. No functional change. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 48 +++++++++++++++++------------------------------- 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index b0cd8da51b26..9ff1a0e1b129 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -506,35 +506,6 @@ err: return len; } -/* - * Wrapper around drbg_generate which can pull arbitrary long strings - * from the DRBG without hitting the maximum request limitation. - * - * Parameters: see drbg_generate - * Return codes: see drbg_generate -- if one drbg_generate request fails, - * the entire drbg_generate_long request fails - */ -static int drbg_generate_long(struct drbg_state *drbg, - unsigned char *buf, unsigned int buflen, - const u8 *addtl, size_t addtl_len) -{ - unsigned int len = 0; - unsigned int slice = 0; - do { - int err = 0; - unsigned int chunk = 0; - slice = (buflen - len) / DRBG_MAX_REQUEST_BYTES; - chunk = slice ? DRBG_MAX_REQUEST_BYTES : (buflen - len); - mutex_lock(&drbg->drbg_mutex); - err = drbg_generate(drbg, buf + len, chunk, addtl, addtl_len); - mutex_unlock(&drbg->drbg_mutex); - if (0 > err) - return err; - len += chunk; - } while (slice > 0 && (len < buflen)); - return 0; -} - static int drbg_prepare_hrng(struct drbg_state *drbg) { /* We do not need an HRNG in test mode. */ @@ -676,7 +647,6 @@ static void drbg_kcapi_cleanup(struct crypto_tfm *tfm) /* * Generate random numbers invoked by the kernel crypto API: - * The API of the kernel crypto API is extended as follows: * * src is additional input supplied to the RNG. * slen is the length of src. @@ -689,7 +659,23 @@ static int drbg_kcapi_random(struct crypto_rng *tfm, { struct drbg_state *drbg = crypto_rng_ctx(tfm); - return drbg_generate_long(drbg, dst, dlen, src, slen); + /* + * Break the request into multiple requests if needed, to avoid + * exceeding the maximum request length of the core algorithm. + */ + do { + unsigned int n = min(dlen, DRBG_MAX_REQUEST_BYTES); + int err; + + mutex_lock(&drbg->drbg_mutex); + err = drbg_generate(drbg, dst, n, src, slen); + mutex_unlock(&drbg->drbg_mutex); + if (err < 0) + return err; + dst += n; + dlen -= n; + } while (dlen); + return 0; } /* Seed (i.e. instantiate) or re-seed the DRBG. */ From fb2d8b7003467b4c893afd6f4be579d08f8360ce Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:13 -0700 Subject: [PATCH 040/196] crypto: drbg - Put rng_alg methods in logical order Put the DRBG implementation of the rng_alg methods in the order in which they're called (cra_init => set_ent => seed => generate => cra_exit) so that it's easier to understand the flow. Also rename drbg_kcapi_random to drbg_kcapi_generate, and drbg_kcapi_cleanup to drbg_kcapi_exit, so they match the method names. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 108 +++++++++++++++++++++++--------------------------- 1 file changed, 49 insertions(+), 59 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index 9ff1a0e1b129..ef9c3e9fdf6e 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -609,26 +609,8 @@ static int drbg_uninstantiate(struct drbg_state *drbg) return 0; } -/* - * Helper function for setting the test data in the DRBG - * - * @drbg DRBG state handle - * @data test data - * @len test data length - */ -static void drbg_kcapi_set_entropy(struct crypto_rng *tfm, - const u8 *data, unsigned int len) -{ - struct drbg_state *drbg = crypto_rng_ctx(tfm); - - mutex_lock(&drbg->drbg_mutex); - drbg->test_entropy = data; - drbg->test_entropylen = len; - mutex_unlock(&drbg->drbg_mutex); -} - /*************************************************************** - * Kernel crypto API interface to register DRBG + * Kernel crypto API interface to DRBG ***************************************************************/ static int drbg_kcapi_init(struct crypto_tfm *tfm) @@ -640,42 +622,16 @@ static int drbg_kcapi_init(struct crypto_tfm *tfm) return 0; } -static void drbg_kcapi_cleanup(struct crypto_tfm *tfm) -{ - drbg_uninstantiate(crypto_tfm_ctx(tfm)); -} - -/* - * Generate random numbers invoked by the kernel crypto API: - * - * src is additional input supplied to the RNG. - * slen is the length of src. - * dst is the output buffer where random data is to be stored. - * dlen is the length of dst. - */ -static int drbg_kcapi_random(struct crypto_rng *tfm, - const u8 *src, unsigned int slen, - u8 *dst, unsigned int dlen) +/* Set test entropy in the DRBG. */ +static void drbg_kcapi_set_entropy(struct crypto_rng *tfm, + const u8 *data, unsigned int len) { struct drbg_state *drbg = crypto_rng_ctx(tfm); - /* - * Break the request into multiple requests if needed, to avoid - * exceeding the maximum request length of the core algorithm. - */ - do { - unsigned int n = min(dlen, DRBG_MAX_REQUEST_BYTES); - int err; - - mutex_lock(&drbg->drbg_mutex); - err = drbg_generate(drbg, dst, n, src, slen); - mutex_unlock(&drbg->drbg_mutex); - if (err < 0) - return err; - dst += n; - dlen -= n; - } while (dlen); - return 0; + mutex_lock(&drbg->drbg_mutex); + drbg->test_entropy = data; + drbg->test_entropylen = len; + mutex_unlock(&drbg->drbg_mutex); } /* Seed (i.e. instantiate) or re-seed the DRBG. */ @@ -699,9 +655,43 @@ static int drbg_kcapi_seed_nopr(struct crypto_rng *tfm, return drbg_kcapi_seed(tfm, seed, slen, /* pr= */ false); } -/*************************************************************** - * Kernel module: code to load the module - ***************************************************************/ +/* + * Generate random numbers invoked by the kernel crypto API: + * + * src is additional input supplied to the RNG. + * slen is the length of src. + * dst is the output buffer where random data is to be stored. + * dlen is the length of dst. + */ +static int drbg_kcapi_generate(struct crypto_rng *tfm, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int dlen) +{ + struct drbg_state *drbg = crypto_rng_ctx(tfm); + + /* + * Break the request into multiple requests if needed, to avoid + * exceeding the maximum request length of the core algorithm. + */ + do { + unsigned int n = min(dlen, DRBG_MAX_REQUEST_BYTES); + int err; + + mutex_lock(&drbg->drbg_mutex); + err = drbg_generate(drbg, dst, n, src, slen); + mutex_unlock(&drbg->drbg_mutex); + if (err < 0) + return err; + dst += n; + dlen -= n; + } while (dlen); + return 0; +} + +static void drbg_kcapi_exit(struct crypto_tfm *tfm) +{ + drbg_uninstantiate(crypto_tfm_ctx(tfm)); +} /* * Tests as defined in 11.3.2 in addition to the cipher tests: testing @@ -769,8 +759,8 @@ static struct rng_alg drbg_algs[] = { .base.cra_init = drbg_kcapi_init, .set_ent = drbg_kcapi_set_entropy, .seed = drbg_kcapi_seed_pr, - .generate = drbg_kcapi_random, - .base.cra_exit = drbg_kcapi_cleanup, + .generate = drbg_kcapi_generate, + .base.cra_exit = drbg_kcapi_exit, }, { .base.cra_name = "stdrng", @@ -781,8 +771,8 @@ static struct rng_alg drbg_algs[] = { .base.cra_init = drbg_kcapi_init, .set_ent = drbg_kcapi_set_entropy, .seed = drbg_kcapi_seed_nopr, - .generate = drbg_kcapi_random, - .base.cra_exit = drbg_kcapi_cleanup, + .generate = drbg_kcapi_generate, + .base.cra_exit = drbg_kcapi_exit, }, }; From 810ba022870bfdf7b7ac0e04db98b2891e80f59e Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:14 -0700 Subject: [PATCH 041/196] crypto: drbg - Fold drbg_instantiate() into drbg_kcapi_seed() Fold drbg_instantiate() into its only caller. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 111 ++++++++++++++++++++------------------------------ 1 file changed, 45 insertions(+), 66 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index ef9c3e9fdf6e..763c14e3786c 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -525,70 +525,6 @@ static int drbg_prepare_hrng(struct drbg_state *drbg) return 0; } -/* - * DRBG instantiation function as required by SP800-90A - this function - * sets up the DRBG handle, performs the initial seeding and all sanity - * checks required by SP800-90A - * - * @drbg memory of state -- if NULL, new memory is allocated - * @pers Optional personalization string that is mixed into state - * @pers_len Length of personalization string in bytes, may be 0 - * @pr prediction resistance enabled - * - * return - * 0 on success - * error value otherwise - */ -static int drbg_instantiate(struct drbg_state *drbg, - const u8 *pers, size_t pers_len, bool pr) -{ - static const u8 initial_key[DRBG_STATE_LEN]; /* all zeroes */ - int ret; - bool reseed = true; - - pr_devel("DRBG: Initializing DRBG with prediction resistance %s\n", - str_enabled_disabled(pr)); - mutex_lock(&drbg->drbg_mutex); - - /* 9.1 step 1 is implicit with the selected DRBG type */ - - /* - * 9.1 step 2 is implicit as caller can select prediction resistance - * all DRBG types support prediction resistance - */ - - /* 9.1 step 4 is implicit in DRBG_SEC_STRENGTH */ - - if (!drbg->instantiated) { - drbg->instantiated = true; - drbg->pr = pr; - drbg->seeded = DRBG_SEED_STATE_UNSEEDED; - drbg->last_seed_time = 0; - drbg->reseed_threshold = DRBG_MAX_REQUESTS; - memset(drbg->V, 1, DRBG_STATE_LEN); - hmac_sha512_preparekey(&drbg->key, initial_key, DRBG_STATE_LEN); - - ret = drbg_prepare_hrng(drbg); - if (ret) - goto free_everything; - - reseed = false; - } - - ret = drbg_seed(drbg, pers, pers_len, reseed); - - if (ret && !reseed) - goto free_everything; - - mutex_unlock(&drbg->drbg_mutex); - return ret; - -free_everything: - mutex_unlock(&drbg->drbg_mutex); - drbg_uninstantiate(drbg); - return ret; -} - /* * DRBG uninstantiate function as required by SP800-90A - this function * frees all buffers and the DRBG handle @@ -636,11 +572,54 @@ static void drbg_kcapi_set_entropy(struct crypto_rng *tfm, /* Seed (i.e. instantiate) or re-seed the DRBG. */ static int drbg_kcapi_seed(struct crypto_rng *tfm, - const u8 *seed, unsigned int slen, bool pr) + const u8 *pers, size_t pers_len, bool pr) { + static const u8 initial_key[DRBG_STATE_LEN]; /* all zeroes */ struct drbg_state *drbg = crypto_rng_ctx(tfm); + int ret; + bool reseed = true; - return drbg_instantiate(drbg, seed, slen, pr); + pr_devel("DRBG: Initializing DRBG with prediction resistance %s\n", + str_enabled_disabled(pr)); + mutex_lock(&drbg->drbg_mutex); + + /* 9.1 step 1 is implicit with the selected DRBG type */ + + /* + * 9.1 step 2 is implicit as caller can select prediction resistance + * all DRBG types support prediction resistance + */ + + /* 9.1 step 4 is implicit in DRBG_SEC_STRENGTH */ + + if (!drbg->instantiated) { + drbg->instantiated = true; + drbg->pr = pr; + drbg->seeded = DRBG_SEED_STATE_UNSEEDED; + drbg->last_seed_time = 0; + drbg->reseed_threshold = DRBG_MAX_REQUESTS; + memset(drbg->V, 1, DRBG_STATE_LEN); + hmac_sha512_preparekey(&drbg->key, initial_key, DRBG_STATE_LEN); + + ret = drbg_prepare_hrng(drbg); + if (ret) + goto free_everything; + + reseed = false; + } + + ret = drbg_seed(drbg, pers, pers_len, reseed); + + if (ret && !reseed) + goto free_everything; + + mutex_unlock(&drbg->drbg_mutex); + return ret; + +free_everything: + mutex_unlock(&drbg->drbg_mutex); + drbg_uninstantiate(drbg); + return ret; } static int drbg_kcapi_seed_pr(struct crypto_rng *tfm, From ad8883374f34809f04d6839b9e7efe0afa5e92cd Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:15 -0700 Subject: [PATCH 042/196] crypto: drbg - Separate "reseed" case in drbg_kcapi_seed() Clearly separate the code for the "reseed" and "instantiate" cases, since what they need to do is quite different. Note that the mutex guard makes the mutex start being held during the call to drbg_uninstantiate(), which is fine. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index 763c14e3786c..a9d586107ebe 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -577,11 +577,13 @@ static int drbg_kcapi_seed(struct crypto_rng *tfm, static const u8 initial_key[DRBG_STATE_LEN]; /* all zeroes */ struct drbg_state *drbg = crypto_rng_ctx(tfm); int ret; - bool reseed = true; pr_devel("DRBG: Initializing DRBG with prediction resistance %s\n", str_enabled_disabled(pr)); - mutex_lock(&drbg->drbg_mutex); + guard(mutex)(&drbg->drbg_mutex); + + if (drbg->instantiated) + return drbg_seed(drbg, pers, pers_len, /* reseed= */ true); /* 9.1 step 1 is implicit with the selected DRBG type */ @@ -592,32 +594,24 @@ static int drbg_kcapi_seed(struct crypto_rng *tfm, /* 9.1 step 4 is implicit in DRBG_SEC_STRENGTH */ - if (!drbg->instantiated) { - drbg->instantiated = true; - drbg->pr = pr; - drbg->seeded = DRBG_SEED_STATE_UNSEEDED; - drbg->last_seed_time = 0; - drbg->reseed_threshold = DRBG_MAX_REQUESTS; - memset(drbg->V, 1, DRBG_STATE_LEN); - hmac_sha512_preparekey(&drbg->key, initial_key, DRBG_STATE_LEN); + drbg->instantiated = true; + drbg->pr = pr; + drbg->seeded = DRBG_SEED_STATE_UNSEEDED; + drbg->last_seed_time = 0; + drbg->reseed_threshold = DRBG_MAX_REQUESTS; + memset(drbg->V, 1, DRBG_STATE_LEN); + hmac_sha512_preparekey(&drbg->key, initial_key, DRBG_STATE_LEN); - ret = drbg_prepare_hrng(drbg); - if (ret) - goto free_everything; - - reseed = false; - } - - ret = drbg_seed(drbg, pers, pers_len, reseed); - - if (ret && !reseed) + ret = drbg_prepare_hrng(drbg); + if (ret) + goto free_everything; + ret = drbg_seed(drbg, pers, pers_len, /* reseed= */ false); + if (ret) goto free_everything; - mutex_unlock(&drbg->drbg_mutex); return ret; free_everything: - mutex_unlock(&drbg->drbg_mutex); drbg_uninstantiate(drbg); return ret; } From 2b30c567603b6e12f153dc7f584d3be87a96be35 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:16 -0700 Subject: [PATCH 043/196] crypto: drbg - Fold drbg_prepare_hrng() into drbg_kcapi_seed() Fold drbg_prepare_hrng() into its only caller. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index a9d586107ebe..45d97f3ba4ef 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -506,25 +506,6 @@ err: return len; } -static int drbg_prepare_hrng(struct drbg_state *drbg) -{ - /* We do not need an HRNG in test mode. */ - if (drbg->test_entropylen != 0) - return 0; - - drbg->jent = crypto_alloc_rng("jitterentropy_rng", 0, 0); - if (IS_ERR(drbg->jent)) { - const int err = PTR_ERR(drbg->jent); - - drbg->jent = NULL; - if (fips_enabled) - return err; - pr_info("DRBG: Continuing without Jitter RNG\n"); - } - - return 0; -} - /* * DRBG uninstantiate function as required by SP800-90A - this function * frees all buffers and the DRBG handle @@ -602,9 +583,18 @@ static int drbg_kcapi_seed(struct crypto_rng *tfm, memset(drbg->V, 1, DRBG_STATE_LEN); hmac_sha512_preparekey(&drbg->key, initial_key, DRBG_STATE_LEN); - ret = drbg_prepare_hrng(drbg); - if (ret) - goto free_everything; + /* Allocate jitterentropy_rng if not in test mode. */ + if (drbg->test_entropylen == 0) { + drbg->jent = crypto_alloc_rng("jitterentropy_rng", 0, 0); + if (IS_ERR(drbg->jent)) { + ret = PTR_ERR(drbg->jent); + drbg->jent = NULL; + if (fips_enabled) + goto free_everything; + pr_info("DRBG: Continuing without Jitter RNG\n"); + } + } + ret = drbg_seed(drbg, pers, pers_len, /* reseed= */ false); if (ret) goto free_everything; From b87c8286bfe63c176b9af59b5ca1c98005312bd8 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:17 -0700 Subject: [PATCH 044/196] crypto: drbg - Simplify "uninstantiate" logic drbg_kcapi_seed() calls drbg_uninstantiate() only to free drbg->jent and set drbg->instantiated = false. However, the latter is necessary only because drbg_kcapi_seed() sets drbg->instantiated = true too early. Fix that, then just inline the freeing of drbg->jent. Then, simplify the actual "uninstantiate" in drbg_kcapi_exit(). Just free drbg->jent (note that this is a no-op on error and null pointers), then memzero_explicit() the entire drbg_state. Note that in reality the memzero_explicit() is redundant, since the crypto_rng API zeroizes the memory anyway. But the way SP800-90A is worded, it's easy to imagine that someone assessing conformance with it would be looking for code in drbg.c that says it does an "Uninstantiate" and does the zeroization. So it's probably worth keeping it somewhat explicit, even though that means double zeroization in practice. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 57 ++++++++++++--------------------------------------- 1 file changed, 13 insertions(+), 44 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index 45d97f3ba4ef..b2af481aef01 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -152,8 +152,6 @@ enum drbg_prefixes { DRBG_PREFIX1, }; -static int drbg_uninstantiate(struct drbg_state *drbg); - /****************************************************************** * HMAC DRBG functions ******************************************************************/ @@ -390,17 +388,6 @@ out: return ret; } -/* Free all substructures in a DRBG state without the DRBG state structure */ -static inline void drbg_dealloc_state(struct drbg_state *drbg) -{ - if (!drbg) - return; - memzero_explicit(&drbg->key, sizeof(drbg->key)); - memzero_explicit(drbg->V, sizeof(drbg->V)); - drbg->reseed_ctr = 0; - drbg->instantiated = false; -} - /* * DRBG generate function as required by SP800-90A - this function * generates random numbers @@ -506,26 +493,6 @@ err: return len; } -/* - * DRBG uninstantiate function as required by SP800-90A - this function - * frees all buffers and the DRBG handle - * - * @drbg DRBG state handle - * - * return - * 0 on success - */ -static int drbg_uninstantiate(struct drbg_state *drbg) -{ - if (!IS_ERR_OR_NULL(drbg->jent)) - crypto_free_rng(drbg->jent); - drbg->jent = NULL; - - drbg_dealloc_state(drbg); - /* no scrubbing of test_data -- this shall survive an uninstantiate */ - return 0; -} - /*************************************************************** * Kernel crypto API interface to DRBG ***************************************************************/ @@ -575,7 +542,6 @@ static int drbg_kcapi_seed(struct crypto_rng *tfm, /* 9.1 step 4 is implicit in DRBG_SEC_STRENGTH */ - drbg->instantiated = true; drbg->pr = pr; drbg->seeded = DRBG_SEED_STATE_UNSEEDED; drbg->last_seed_time = 0; @@ -590,20 +556,19 @@ static int drbg_kcapi_seed(struct crypto_rng *tfm, ret = PTR_ERR(drbg->jent); drbg->jent = NULL; if (fips_enabled) - goto free_everything; + return ret; pr_info("DRBG: Continuing without Jitter RNG\n"); } } ret = drbg_seed(drbg, pers, pers_len, /* reseed= */ false); - if (ret) - goto free_everything; - - return ret; - -free_everything: - drbg_uninstantiate(drbg); - return ret; + if (ret) { + crypto_free_rng(drbg->jent); + drbg->jent = NULL; + return ret; + } + drbg->instantiated = true; + return 0; } static int drbg_kcapi_seed_pr(struct crypto_rng *tfm, @@ -651,9 +616,13 @@ static int drbg_kcapi_generate(struct crypto_rng *tfm, return 0; } +/* Uninstantiate the DRBG. */ static void drbg_kcapi_exit(struct crypto_tfm *tfm) { - drbg_uninstantiate(crypto_tfm_ctx(tfm)); + struct drbg_state *drbg = crypto_tfm_ctx(tfm); + + crypto_free_rng(drbg->jent); + memzero_explicit(drbg, sizeof(*drbg)); } /* From ca659874af31c6c6e1c5992475b88be8cb65d484 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:18 -0700 Subject: [PATCH 045/196] crypto: drbg - Include get_random_bytes() output in additional input Woodage & Shumow (2018) (https://eprint.iacr.org/2018/349.pdf) showed that contrary to the claims made by NIST in SP800-90A, HMAC_DRBG doesn't satisfy the formal definition of forward secrecy (i.e. "backtracking resistance") when it's called with an empty additional input string. The actual attack seems pretty benign, as it doesn't actually give the attacker any previous RNG output, but rather just allows them to test whether their guess of the previous block of RNG output is correct. Regardless, it's an annoying design flaw, and it's yet another example of why NIST's DRBGs aren't all that great. Meanwhile, the kernel's HMAC_DRBG code also tries to reseed itself automatically after random.c has reseeded itself. But the implementation is buggy, as it just checks whether 300 seconds have elapsed, rather than looking at the actual generation counter. Let's just follow the example of BoringSSL and use the conservative approach of always including 32 bytes of "regular" random data in the additional input string. This fixes both issues described above. This does reduce performance. But this should be tolerable, since: - Due to earlier changes, the kernel code that was previously using drbg.c regardless of FIPS mode is now using it only in FIPS mode. - The additional input string is processed only once per request. So if a lot of bytes are generated at once, the cost is amortized. - The NIST DRBGs are notoriously slow anyway. Note that this fix should have no impact (either positive or negative) on FIPS 140 certifiability. From FIPS's point of view the code added by this commit simply doesn't matter: it adds zero entropy to something that doesn't need to contain entropy. Fixes: 541af946fe13 ("crypto: drbg - SP800-90A Deterministic Random Bit Generator") Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index b2af481aef01..cda79d601f4f 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -193,13 +193,32 @@ static void drbg_hmac_update(struct drbg_state *drbg, static void drbg_hmac_generate(struct drbg_state *drbg, unsigned char *buf, unsigned int buflen, - const u8 *addtl, size_t addtl_len) + const u8 *addtl1, size_t addtl1_len) { int len = 0; + u8 addtl2[32]; + size_t addtl2_len = 0; + + /* + * Append some bytes from get_random_bytes() to the additional input + * string, except when in test mode (as it would break the tests). + * Using a nonempty additional input string works around the forward + * secrecy bug in HMAC_DRBG described by Woodage & Shumow (2018) + * (https://eprint.iacr.org/2018/349.pdf). Filling the string with + * get_random_bytes() rather than a fixed value is safer still, and in + * particular makes random.c reseeds be immediately reflected. + * + * Note that there's no need to pull bytes from jitterentropy here too, + * since FIPS doesn't require any entropy in the additional input. + */ + if (drbg->test_entropylen == 0) { + get_random_bytes(addtl2, sizeof(addtl2)); + addtl2_len = sizeof(addtl2); + } /* 10.1.2.5 step 2 */ - if (addtl_len) - drbg_hmac_update(drbg, addtl, addtl_len, NULL, 0); + if (addtl1_len || addtl2_len) + drbg_hmac_update(drbg, addtl1, addtl1_len, addtl2, addtl2_len); while (len < buflen) { unsigned int outlen = 0; @@ -215,7 +234,9 @@ static void drbg_hmac_generate(struct drbg_state *drbg, } /* 10.1.2.5 step 6 */ - drbg_hmac_update(drbg, addtl, addtl_len, NULL, 0); + drbg_hmac_update(drbg, addtl1, addtl1_len, addtl2, addtl2_len); + + memzero_explicit(addtl2, sizeof(addtl2)); } static inline void __drbg_seed(struct drbg_state *drbg, From 005b19f18ea9fc51fc35fbcb27759ae83c7c89f8 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:19 -0700 Subject: [PATCH 046/196] crypto: drbg - Change DRBG_MAX_REQUESTS to 4096 Currently a formal reseed happens only after each 1048576 requests. That's quite a high number. Let's follow the example of BoringSSL and use a more conservative value of 4096. Note that in practice this makes little difference, now that we're including 32 bytes from get_random_bytes() in the additional input on every request anyway, which is a de facto reseed. But for the same reason, we might as well decrease the actual reseed interval to something more reasonable. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index cda79d601f4f..7fd076ddc105 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -115,7 +115,7 @@ enum drbg_seed_state { * Maximum number of requests before reseeding is forced. * SP800-90A allows this to be up to 2**48. We use a lower value. */ -#define DRBG_MAX_REQUESTS (1 << 20) +#define DRBG_MAX_REQUESTS 4096 /* * Maximum number of random bytes that can be requested at once. From a918c3680d2ea1d3c2df589397c0ffd4dac2ceaa Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:20 -0700 Subject: [PATCH 047/196] crypto: drbg - Remove redundant reseeding based on random.c state We're now incorporating 32 bytes from get_random_bytes() in the additional input string on every request. The additional input string is processed with a call to drbg_hmac_update(), which is exactly how the seed is processed. Thus, in reality this is as good as a reseed. From the perspective of FIPS 140-3, it isn't as good as a reseed. But it doesn't actually matter, because from FIPS's point of view get_random_bytes() provides zero entropy anyway. Thus, neither the reseed with more get_random_bytes() every 300s, nor the logic that reseeds more frequently before rng_is_initialized(), is actually needed anymore. Remove it to simplify the code significantly. (Technically the use of get_random_bytes() in drbg_seed() itself could be removed too. But it's safer to keep it there for now.) Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 107 +++++--------------------------------------------- 1 file changed, 9 insertions(+), 98 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index 7fd076ddc105..bab766026177 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -93,18 +93,11 @@ #include #include #include -#include #include #include #include #include -enum drbg_seed_state { - DRBG_SEED_STATE_UNSEEDED, - DRBG_SEED_STATE_PARTIAL, /* Seeded with !rng_is_initialized() */ - DRBG_SEED_STATE_FULL, -}; - /* State length in bytes */ #define DRBG_STATE_LEN SHA512_DIGEST_SIZE @@ -137,9 +130,6 @@ struct drbg_state { struct hmac_sha512_key key; /* current key -- 10.1.2.1 1b */ /* Number of RNG requests since last reseed -- 10.1.2.1 1c */ size_t reseed_ctr; - size_t reseed_threshold; - enum drbg_seed_state seeded; /* DRBG fully seeded? */ - unsigned long last_seed_time; bool instantiated; bool pr; /* Prediction resistance enabled? */ struct crypto_rng *jent; @@ -239,72 +229,6 @@ static void drbg_hmac_generate(struct drbg_state *drbg, memzero_explicit(addtl2, sizeof(addtl2)); } -static inline void __drbg_seed(struct drbg_state *drbg, - const u8 *seed1, size_t seed1_len, - const u8 *seed2, size_t seed2_len, - enum drbg_seed_state new_seed_state) -{ - drbg_hmac_update(drbg, seed1, seed1_len, seed2, seed2_len); - - drbg->seeded = new_seed_state; - drbg->last_seed_time = jiffies; - drbg->reseed_ctr = 1; - - switch (drbg->seeded) { - case DRBG_SEED_STATE_UNSEEDED: - /* Impossible, but handle it to silence compiler warnings. */ - fallthrough; - case DRBG_SEED_STATE_PARTIAL: - /* - * Require frequent reseeds until the seed source is - * fully initialized. - */ - drbg->reseed_threshold = 50; - break; - - case DRBG_SEED_STATE_FULL: - /* - * Seed source has become fully initialized, frequent - * reseeds no longer required. - */ - drbg->reseed_threshold = DRBG_MAX_REQUESTS; - break; - } -} - -static void drbg_seed_from_random(struct drbg_state *drbg) - __must_hold(&drbg->drbg_mutex) -{ - u8 entropy[DRBG_SEC_STRENGTH]; - - get_random_bytes(entropy, DRBG_SEC_STRENGTH); - - __drbg_seed(drbg, entropy, DRBG_SEC_STRENGTH, NULL, 0, - DRBG_SEED_STATE_FULL); - - memzero_explicit(entropy, DRBG_SEC_STRENGTH); -} - -static bool drbg_nopr_reseed_interval_elapsed(struct drbg_state *drbg) -{ - unsigned long next_reseed; - - /* Don't ever reseed from get_random_bytes() in test mode. */ - if (drbg->test_entropylen) - return false; - - /* - * Obtain fresh entropy for the nopr DRBGs after 300s have - * elapsed in order to still achieve sort of partial - * prediction resistance over the time domain at least. Note - * that the period of 300s has been chosen to match the - * CRNG_RESEED_INTERVAL of the get_random_bytes()' chacha - * rngs. - */ - next_reseed = drbg->last_seed_time + 300 * HZ; - return time_after(jiffies, next_reseed); -} - /* * Seeding or reseeding of the DRBG * @@ -325,7 +249,6 @@ static int drbg_seed(struct drbg_state *drbg, const u8 *pers, size_t pers_len, u8 entropy_buf[(32 + 16) * 2]; size_t entropylen; const u8 *entropy; - enum drbg_seed_state new_seed_state = DRBG_SEED_STATE_FULL; /* 9.1 / 9.2 / 9.3.1 step 3 */ if (pers_len > DRBG_MAX_ADDTL) { @@ -355,9 +278,6 @@ static int drbg_seed(struct drbg_state *drbg, const u8 *pers, size_t pers_len, BUG_ON(entropylen * 2 > sizeof(entropy_buf)); /* Get seed from in-kernel /dev/urandom */ - if (!rng_is_initialized()) - new_seed_state = DRBG_SEED_STATE_PARTIAL; - get_random_bytes(entropy_buf, entropylen); if (!drbg->jent) { @@ -401,7 +321,8 @@ static int drbg_seed(struct drbg_state *drbg, const u8 *pers, size_t pers_len, if (pers_len) pr_devel("DRBG: using personalization string\n"); - __drbg_seed(drbg, entropy, entropylen, pers, pers_len, new_seed_state); + drbg_hmac_update(drbg, entropy, entropylen, pers, pers_len); + drbg->reseed_ctr = 1; ret = 0; out: memzero_explicit(entropy_buf, sizeof(entropy_buf)); @@ -463,16 +384,14 @@ static int drbg_generate(struct drbg_state *drbg, /* * 9.3.1 step 6 and 9 supplemented by 9.3.2 step c is implemented * here. The spec is a bit convoluted here, we make it simpler. + * + * We no longer try to detect when random.c has reseeded itself and call + * drbg_seed() then too, since drbg_hmac_generate() adds bytes from + * random.c to the additional input, which is a de facto reseed anyway. */ - if (drbg->reseed_threshold < drbg->reseed_ctr) - drbg->seeded = DRBG_SEED_STATE_UNSEEDED; - - if (drbg->pr || drbg->seeded == DRBG_SEED_STATE_UNSEEDED) { - pr_devel("DRBG: reseeding before generation (prediction " - "resistance: %s, state %s)\n", - str_true_false(drbg->pr), - (drbg->seeded == DRBG_SEED_STATE_FULL ? - "seeded" : "unseeded")); + if (drbg->pr || drbg->reseed_ctr > DRBG_MAX_REQUESTS) { + pr_devel("DRBG: reseeding before generation (prediction resistance: %s)\n", + str_true_false(drbg->pr)); /* 9.3.1 steps 7.1 through 7.3 */ len = drbg_seed(drbg, addtl, addtl_len, true); if (len) @@ -480,10 +399,6 @@ static int drbg_generate(struct drbg_state *drbg, /* 9.3.1 step 7.4 */ addtl = NULL; addtl_len = 0; - } else if (rng_is_initialized() && - (drbg->seeded == DRBG_SEED_STATE_PARTIAL || - drbg_nopr_reseed_interval_elapsed(drbg))) { - drbg_seed_from_random(drbg); } /* 9.3.1 step 8 and 10 */ @@ -564,9 +479,6 @@ static int drbg_kcapi_seed(struct crypto_rng *tfm, /* 9.1 step 4 is implicit in DRBG_SEC_STRENGTH */ drbg->pr = pr; - drbg->seeded = DRBG_SEED_STATE_UNSEEDED; - drbg->last_seed_time = 0; - drbg->reseed_threshold = DRBG_MAX_REQUESTS; memset(drbg->V, 1, DRBG_STATE_LEN); hmac_sha512_preparekey(&drbg->key, initial_key, DRBG_STATE_LEN); @@ -673,7 +585,6 @@ static inline int __init drbg_healthcheck_sanity(void) guard(mutex_init)(&drbg->drbg_mutex); drbg->instantiated = true; - drbg->reseed_threshold = DRBG_MAX_REQUESTS; /* * if the following tests fail, it is likely that there is a buffer From 7cca456c3e6a0fefc752e9e93634aa63545d6a68 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:21 -0700 Subject: [PATCH 048/196] crypto: drbg - Clean up generation code A few miscellaneous cleanups to make the code a bit more readable: - Replace (buf, buflen) with (out, outlen) - Update (out, outlen) as we go along - Use size_t for lengths - Use min() - Adjust some comments and log messages - Rename a variable named 'len' to 'err', since it isn't a length Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 53 ++++++++++++++++++--------------------------------- 1 file changed, 19 insertions(+), 34 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index bab766026177..b54c807930af 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -180,12 +180,9 @@ static void drbg_hmac_update(struct drbg_state *drbg, } /* generate function of HMAC DRBG as defined in 10.1.2.5 */ -static void drbg_hmac_generate(struct drbg_state *drbg, - unsigned char *buf, - unsigned int buflen, +static void drbg_hmac_generate(struct drbg_state *drbg, u8 *out, size_t outlen, const u8 *addtl1, size_t addtl1_len) { - int len = 0; u8 addtl2[32]; size_t addtl2_len = 0; @@ -210,17 +207,16 @@ static void drbg_hmac_generate(struct drbg_state *drbg, if (addtl1_len || addtl2_len) drbg_hmac_update(drbg, addtl1, addtl1_len, addtl2, addtl2_len); - while (len < buflen) { - unsigned int outlen = 0; + while (outlen) { + size_t n = min(DRBG_STATE_LEN, outlen); /* 10.1.2.5 step 4.1 */ hmac_sha512(&drbg->key, drbg->V, DRBG_STATE_LEN, drbg->V); - outlen = (DRBG_STATE_LEN < (buflen - len)) ? - DRBG_STATE_LEN : (buflen - len); /* 10.1.2.5 step 4.2 */ - memcpy(buf + len, drbg->V, outlen); - len += outlen; + memcpy(out, drbg->V, n); + out += n; + outlen -= n; } /* 10.1.2.5 step 6 */ @@ -331,31 +327,27 @@ out: } /* - * DRBG generate function as required by SP800-90A - this function - * generates random numbers + * Generate random bytes from an SP800-90A DRBG. * * @drbg DRBG state handle - * @buf Buffer where to store the random numbers -- the buffer must already - * be pre-allocated by caller - * @buflen Length of output buffer - this value defines the number of random - * bytes pulled from DRBG + * @out Buffer where to store the random bytes + * @outlen Number of random bytes to generate * @addtl Optional additional input that is mixed into state * @addtl_len Length of @addtl in bytes, may be 0 * * return: 0 when all bytes are generated; < 0 in case of an error */ -static int drbg_generate(struct drbg_state *drbg, - unsigned char *buf, unsigned int buflen, +static int drbg_generate(struct drbg_state *drbg, u8 *out, size_t outlen, const u8 *addtl, size_t addtl_len) __must_hold(&drbg->drbg_mutex) { - int len = 0; + int err; if (!drbg->instantiated) { pr_devel("DRBG: not yet instantiated\n"); return -EINVAL; } - if (0 == buflen || !buf) { + if (out == NULL || outlen == 0) { pr_devel("DRBG: no output buffer provided\n"); return -EINVAL; } @@ -365,9 +357,8 @@ static int drbg_generate(struct drbg_state *drbg, } /* 9.3.1 step 2 */ - if (buflen > DRBG_MAX_REQUEST_BYTES) { - pr_devel("DRBG: requested random numbers too large %u\n", - buflen); + if (outlen > DRBG_MAX_REQUEST_BYTES) { + pr_devel("DRBG: request length is too long %zu\n", outlen); return -EINVAL; } @@ -393,16 +384,16 @@ static int drbg_generate(struct drbg_state *drbg, pr_devel("DRBG: reseeding before generation (prediction resistance: %s)\n", str_true_false(drbg->pr)); /* 9.3.1 steps 7.1 through 7.3 */ - len = drbg_seed(drbg, addtl, addtl_len, true); - if (len) - goto err; + err = drbg_seed(drbg, addtl, addtl_len, true); + if (err) + return err; /* 9.3.1 step 7.4 */ addtl = NULL; addtl_len = 0; } /* 9.3.1 step 8 and 10 */ - drbg_hmac_generate(drbg, buf, buflen, addtl, addtl_len); + drbg_hmac_generate(drbg, out, outlen, addtl, addtl_len); /* 10.1.2.5 step 7 */ drbg->reseed_ctr++; @@ -420,13 +411,7 @@ static int drbg_generate(struct drbg_state *drbg, * correct operation of the DRBG. */ - /* - * All operations were successful, return 0 as mandated by - * the kernel crypto API interface. - */ - len = 0; -err: - return len; + return 0; } /*************************************************************** From 58d0b2b90796d603b01afb8eeaeb14c58131ad57 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Apr 2026 23:34:22 -0700 Subject: [PATCH 049/196] crypto: drbg - Clean up loop in drbg_hmac_update() This loop is a bit hard to read, with the loop counter that's used in the HMAC being separate from the actual loop counter, which counts backwards for some reason. Just replace it with a regular loop. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index b54c807930af..ad7b9577479e 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -137,11 +137,6 @@ struct drbg_state { size_t test_entropylen; }; -enum drbg_prefixes { - DRBG_PREFIX0 = 0x00, - DRBG_PREFIX1, -}; - /****************************************************************** * HMAC DRBG functions ******************************************************************/ @@ -151,19 +146,14 @@ static void drbg_hmac_update(struct drbg_state *drbg, const u8 *data1, size_t data1_len, const u8 *data2, size_t data2_len) { - int i = 0; struct hmac_sha512_ctx hmac_ctx; u8 new_key[DRBG_STATE_LEN]; - for (i = 2; 0 < i; i--) { - /* first round uses 0x0, second 0x1 */ - unsigned char prefix = DRBG_PREFIX0; - if (1 == i) - prefix = DRBG_PREFIX1; + for (u8 i = 0; i < 2; i++) { /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */ hmac_sha512_init(&hmac_ctx, &drbg->key); hmac_sha512_update(&hmac_ctx, drbg->V, DRBG_STATE_LEN); - hmac_sha512_update(&hmac_ctx, &prefix, 1); + hmac_sha512_update(&hmac_ctx, &i, 1); hmac_sha512_update(&hmac_ctx, data1, data1_len); hmac_sha512_update(&hmac_ctx, data2, data2_len); hmac_sha512_final(&hmac_ctx, new_key); From cba5aebae1094a52eb951a66e1edd0a670d6aacb Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 20 Apr 2026 11:41:20 +0200 Subject: [PATCH 050/196] crypto: crypto_null - Drop unused cipher_null crypto_alg The cipher_null crypto_alg cipher is never used in a meaningful way, given that it is always wrapped in ecb(), which has its own dedicated implementation. IOW, the cipher_null crypto_alg should never be used to implement the ecb(cipher_null) skcipher, and using it for other things is bogus. However, it is accessible from user space, and due to the nature of the AF_ALG interface, it may be wrapped in arbitrary ways, exposing issues in template code that wasn't written with block ciphers with a block size of '1' in mind. So drop this code. Signed-off-by: Ard Biesheuvel Reviewed-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/crypto_null.c | 35 ++--------------------------------- 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/crypto/crypto_null.c b/crypto/crypto_null.c index 34588f39fdfc..fea151df1648 100644 --- a/crypto/crypto_null.c +++ b/crypto/crypto_null.c @@ -50,15 +50,6 @@ static int null_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen) { return 0; } -static int null_setkey(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen) -{ return 0; } - -static void null_crypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) -{ - memcpy(dst, src, NULL_BLOCK_SIZE); -} - static int null_skcipher_crypt(struct skcipher_request *req) { if (req->src != req->dst) @@ -97,35 +88,16 @@ static struct skcipher_alg skcipher_null = { .decrypt = null_skcipher_crypt, }; -static struct crypto_alg cipher_null = { - .cra_name = "cipher_null", - .cra_driver_name = "cipher_null-generic", - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = NULL_BLOCK_SIZE, - .cra_ctxsize = 0, - .cra_module = THIS_MODULE, - .cra_u = { .cipher = { - .cia_min_keysize = NULL_KEY_SIZE, - .cia_max_keysize = NULL_KEY_SIZE, - .cia_setkey = null_setkey, - .cia_encrypt = null_crypt, - .cia_decrypt = null_crypt } } -}; - MODULE_ALIAS_CRYPTO("digest_null"); -MODULE_ALIAS_CRYPTO("cipher_null"); +MODULE_ALIAS_CRYPTO("ecb(cipher_null)"); static int __init crypto_null_mod_init(void) { int ret = 0; - ret = crypto_register_alg(&cipher_null); - if (ret < 0) - goto out; - ret = crypto_register_shash(&digest_null); if (ret < 0) - goto out_unregister_algs; + goto out; ret = crypto_register_skcipher(&skcipher_null); if (ret < 0) @@ -135,15 +107,12 @@ static int __init crypto_null_mod_init(void) out_unregister_shash: crypto_unregister_shash(&digest_null); -out_unregister_algs: - crypto_unregister_alg(&cipher_null); out: return ret; } static void __exit crypto_null_mod_fini(void) { - crypto_unregister_alg(&cipher_null); crypto_unregister_shash(&digest_null); crypto_unregister_skcipher(&skcipher_null); } From 7e04a638dee0313db8b8ecd38be5d36ead22cbf5 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 20 Apr 2026 17:34:45 +0100 Subject: [PATCH 051/196] dt-bindings: rng: mtk-rng: fix style problems in example Use 4 spaces for each level indentation, remove unused label, and add missing empty line between header include and body. Signed-off-by: Daniel Golle Acked-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- Documentation/devicetree/bindings/rng/mtk-rng.yaml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/rng/mtk-rng.yaml b/Documentation/devicetree/bindings/rng/mtk-rng.yaml index 7e8dc62e5d3a..8f2f4c32a0cf 100644 --- a/Documentation/devicetree/bindings/rng/mtk-rng.yaml +++ b/Documentation/devicetree/bindings/rng/mtk-rng.yaml @@ -47,9 +47,10 @@ additionalProperties: false examples: - | #include - rng: rng@1020f000 { - compatible = "mediatek,mt7623-rng"; - reg = <0x1020f000 0x1000>; - clocks = <&infracfg CLK_INFRA_TRNG>; - clock-names = "rng"; + + rng@1020f000 { + compatible = "mediatek,mt7623-rng"; + reg = <0x1020f000 0x1000>; + clocks = <&infracfg CLK_INFRA_TRNG>; + clock-names = "rng"; }; From 20f43e30b3f56cc757b2576364d07a4ddb324ab4 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 20 Apr 2026 17:35:09 +0100 Subject: [PATCH 052/196] dt-bindings: rng: mtk-rng: add SMC-based TRNG variants Add compatible strings for MediaTek SoCs where the hardware random number generator is accessed via a vendor-defined Secure Monitor Call (SMC) rather than direct MMIO register access: - mediatek,mt7981-rng - mediatek,mt7987-rng - mediatek,mt7988-rng These variants require no reg, clocks, or clock-names properties since the RNG hardware is managed by ARM Trusted Firmware-A. Relax the $nodename pattern to also allow 'rng' in addition to the existing 'rng@...' pattern. Add a second example showing the minimal SMC variant binding. Signed-off-by: Daniel Golle Reviewed-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- .../devicetree/bindings/rng/mtk-rng.yaml | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/rng/mtk-rng.yaml b/Documentation/devicetree/bindings/rng/mtk-rng.yaml index 8f2f4c32a0cf..38e67861b88f 100644 --- a/Documentation/devicetree/bindings/rng/mtk-rng.yaml +++ b/Documentation/devicetree/bindings/rng/mtk-rng.yaml @@ -11,12 +11,13 @@ maintainers: properties: $nodename: - pattern: "^rng@[0-9a-f]+$" + pattern: "^rng(@[0-9a-f]+)?$" compatible: oneOf: - enum: - mediatek,mt7623-rng + - mediatek,mt7981-rng - items: - enum: - mediatek,mt7622-rng @@ -25,6 +26,11 @@ properties: - mediatek,mt8365-rng - mediatek,mt8516-rng - const: mediatek,mt7623-rng + - items: + - enum: + - mediatek,mt7987-rng + - mediatek,mt7988-rng + - const: mediatek,mt7981-rng reg: maxItems: 1 @@ -38,9 +44,23 @@ properties: required: - compatible - - reg - - clocks - - clock-names + +allOf: + - if: + properties: + compatible: + contains: + const: mediatek,mt7981-rng + then: + properties: + reg: false + clocks: false + clock-names: false + else: + required: + - reg + - clocks + - clock-names additionalProperties: false @@ -54,3 +74,7 @@ examples: clocks = <&infracfg CLK_INFRA_TRNG>; clock-names = "rng"; }; + - | + rng { + compatible = "mediatek,mt7981-rng"; + }; From 066d65adf83db97361fe73745715336c503d1aa9 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 20 Apr 2026 17:35:24 +0100 Subject: [PATCH 053/196] hwrng: mtk - add support for hw access via SMCC Newer versions of ARM TrustedFirmware-A on MediaTek's ARMv8 SoCs no longer allow accessing the TRNG from outside of the trusted firmware. Instead, a vendor-defined custom Secure Monitor Call can be used to acquire random bytes. Add support for newer SoCs (MT7981, MT7987, MT7988). As TF-A for the MT7986 may either follow the old or the new convention, the best bet is to test if firmware blocks direct access to the hwrng and if so, expect the SMCC interface to be usable. Signed-off-by: Daniel Golle Signed-off-by: Herbert Xu --- drivers/char/hw_random/mtk-rng.c | 125 ++++++++++++++++++++++++++----- 1 file changed, 105 insertions(+), 20 deletions(-) diff --git a/drivers/char/hw_random/mtk-rng.c b/drivers/char/hw_random/mtk-rng.c index 5808d09d12c4..1f9793010e6c 100644 --- a/drivers/char/hw_random/mtk-rng.c +++ b/drivers/char/hw_random/mtk-rng.c @@ -3,9 +3,11 @@ * Driver for Mediatek Hardware Random Number Generator * * Copyright (C) 2017 Sean Wang + * Copyright (C) 2026 Daniel Golle */ #define MTK_RNG_DEV KBUILD_MODNAME +#include #include #include #include @@ -17,6 +19,7 @@ #include #include #include +#include /* Runtime PM autosuspend timeout: */ #define RNG_AUTOSUSPEND_TIMEOUT 100 @@ -30,6 +33,11 @@ #define RNG_DATA 0x08 +/* Driver feature flags */ +#define MTK_RNG_SMC BIT(0) + +#define MTK_SIP_KERNEL_GET_RND MTK_SIP_SMC_CMD(0x550) + #define to_mtk_rng(p) container_of(p, struct mtk_rng, rng) struct mtk_rng { @@ -37,6 +45,7 @@ struct mtk_rng { struct clk *clk; struct hwrng rng; struct device *dev; + unsigned long flags; }; static int mtk_rng_init(struct hwrng *rng) @@ -103,6 +112,56 @@ static int mtk_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait) return retval || !wait ? retval : -EIO; } +static int mtk_rng_read_smc(struct hwrng *rng, void *buf, size_t max, + bool wait) +{ + struct arm_smccc_res res; + int retval = 0; + + while (max >= sizeof(u32)) { + arm_smccc_smc(MTK_SIP_KERNEL_GET_RND, 0, 0, 0, 0, 0, 0, 0, + &res); + if (res.a0) + break; + + *(u32 *)buf = res.a1; + retval += sizeof(u32); + buf += sizeof(u32); + max -= sizeof(u32); + } + + return retval || !wait ? retval : -EIO; +} + +static bool mtk_rng_hw_accessible(struct mtk_rng *priv) +{ + u32 val; + int err; + + err = clk_prepare_enable(priv->clk); + if (err) + return false; + + val = readl(priv->base + RNG_CTRL); + val |= RNG_EN; + writel(val, priv->base + RNG_CTRL); + + val = readl(priv->base + RNG_CTRL); + + if (val & RNG_EN) { + /* HW is accessible, clean up: disable RNG and clock */ + writel(val & ~RNG_EN, priv->base + RNG_CTRL); + clk_disable_unprepare(priv->clk); + return true; + } + + /* + * If TF-A blocks direct access, the register reads back as 0. + * Leave the clock enabled as TF-A needs it. + */ + return false; +} + static int mtk_rng_probe(struct platform_device *pdev) { int ret; @@ -114,23 +173,42 @@ static int mtk_rng_probe(struct platform_device *pdev) priv->dev = &pdev->dev; priv->rng.name = pdev->name; -#ifndef CONFIG_PM - priv->rng.init = mtk_rng_init; - priv->rng.cleanup = mtk_rng_cleanup; -#endif - priv->rng.read = mtk_rng_read; priv->rng.quality = 900; + priv->flags = (unsigned long)device_get_match_data(&pdev->dev); - priv->clk = devm_clk_get(&pdev->dev, "rng"); - if (IS_ERR(priv->clk)) { - ret = PTR_ERR(priv->clk); - dev_err(&pdev->dev, "no clock for device: %d\n", ret); - return ret; + if (!(priv->flags & MTK_RNG_SMC)) { + priv->clk = devm_clk_get(&pdev->dev, "rng"); + if (IS_ERR(priv->clk)) { + ret = PTR_ERR(priv->clk); + dev_err(&pdev->dev, "no clock for device: %d\n", ret); + return ret; + } + + priv->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + if (IS_ENABLED(CONFIG_HAVE_ARM_SMCCC) && + of_device_is_compatible(pdev->dev.of_node, + "mediatek,mt7986-rng") && + !mtk_rng_hw_accessible(priv)) { + priv->flags |= MTK_RNG_SMC; + dev_info(&pdev->dev, + "HW RNG not MMIO accessible, using SMC\n"); + } } - priv->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(priv->base)) - return PTR_ERR(priv->base); + if (priv->flags & MTK_RNG_SMC) { + if (!IS_ENABLED(CONFIG_HAVE_ARM_SMCCC)) + return -ENODEV; + priv->rng.read = mtk_rng_read_smc; + } else { +#ifndef CONFIG_PM + priv->rng.init = mtk_rng_init; + priv->rng.cleanup = mtk_rng_cleanup; +#endif + priv->rng.read = mtk_rng_read; + } ret = devm_hwrng_register(&pdev->dev, &priv->rng); if (ret) { @@ -139,12 +217,15 @@ static int mtk_rng_probe(struct platform_device *pdev) return ret; } - dev_set_drvdata(&pdev->dev, priv); - pm_runtime_set_autosuspend_delay(&pdev->dev, RNG_AUTOSUSPEND_TIMEOUT); - pm_runtime_use_autosuspend(&pdev->dev); - ret = devm_pm_runtime_enable(&pdev->dev); - if (ret) - return ret; + if (!(priv->flags & MTK_RNG_SMC)) { + dev_set_drvdata(&pdev->dev, priv); + pm_runtime_set_autosuspend_delay(&pdev->dev, + RNG_AUTOSUSPEND_TIMEOUT); + pm_runtime_use_autosuspend(&pdev->dev); + ret = devm_pm_runtime_enable(&pdev->dev); + if (ret) + return ret; + } dev_info(&pdev->dev, "registered RNG driver\n"); @@ -181,8 +262,11 @@ static const struct dev_pm_ops mtk_rng_pm_ops = { #endif /* CONFIG_PM */ static const struct of_device_id mtk_rng_match[] = { - { .compatible = "mediatek,mt7986-rng" }, { .compatible = "mediatek,mt7623-rng" }, + { .compatible = "mediatek,mt7981-rng", .data = (void *)MTK_RNG_SMC }, + { .compatible = "mediatek,mt7986-rng" }, + { .compatible = "mediatek,mt7987-rng", .data = (void *)MTK_RNG_SMC }, + { .compatible = "mediatek,mt7988-rng", .data = (void *)MTK_RNG_SMC }, {}, }; MODULE_DEVICE_TABLE(of, mtk_rng_match); @@ -200,4 +284,5 @@ module_platform_driver(mtk_rng_driver); MODULE_DESCRIPTION("Mediatek Random Number Generator Driver"); MODULE_AUTHOR("Sean Wang "); +MODULE_AUTHOR("Daniel Golle "); MODULE_LICENSE("GPL"); From ef6127bb4f4b51ca91eab58348861c8adcd8db25 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 23 Apr 2026 08:55:42 +0200 Subject: [PATCH 054/196] crypto: sun8i-ss - avoid hash and rng references While the sun4i-ss and sun8i-ce drivers started selecting CRYPTO_RNG, the sun8i-ss variant does not, and causes a link failure: aarch64-linux-ld: drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.o: in function `sun8i_ss_unregister_algs': sun8i-ss-core.c:(.text.sun8i_ss_unregister_algs+0x94): undefined reference to `crypto_unregister_rng' aarch64-linux-ld: drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.o: in function `sun8i_ss_probe': sun8i-ss-core.c:(.text.sun8i_ss_probe+0x40c): undefined reference to `crypto_register_rng' Looking more closely, I see that all of the allwinner crypto drivers have the same logic where the rng and hash parts of the driver are optional, but then the generic code is still selected, which is a bit inconsistent, aside from the missing CRYPTO_RNG select on sun8i-ss. Change the approach so only the bits that are actually used are built, using ifdef checks around the optional portions that match the optional references to the sub-drivers. Ideally the drivers would get reworked in a way that keeps all the bits related to the skcipher/ahash/rng codecs in the respective sub-drivers, rather than having a common driver that knows about all of these. Fixes: cdadc1435937 ("crypto: cryptomgr - Select algorithm types only when CRYPTO_SELFTESTS") Signed-off-by: Arnd Bergmann Signed-off-by: Herbert Xu --- drivers/crypto/allwinner/Kconfig | 2 -- drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c | 8 ++++++++ drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c | 12 ++++++++++++ drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c | 12 ++++++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/allwinner/Kconfig b/drivers/crypto/allwinner/Kconfig index 7270e5fbc573..b8e75210a0e3 100644 --- a/drivers/crypto/allwinner/Kconfig +++ b/drivers/crypto/allwinner/Kconfig @@ -14,7 +14,6 @@ config CRYPTO_DEV_SUN4I_SS select CRYPTO_SHA1 select CRYPTO_AES select CRYPTO_LIB_DES - select CRYPTO_RNG select CRYPTO_SKCIPHER help Some Allwinner SoC have a crypto accelerator named @@ -50,7 +49,6 @@ config CRYPTO_DEV_SUN8I_CE select CRYPTO_CBC select CRYPTO_AES select CRYPTO_DES - select CRYPTO_RNG depends on CRYPTO_DEV_ALLWINNER depends on PM help diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c index 58a76e2ba64e..813c4bc6312a 100644 --- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c +++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c @@ -247,12 +247,14 @@ static int sun4i_ss_debugfs_show(struct seq_file *seq, void *v) ss_algs[i].stat_req, ss_algs[i].stat_opti, ss_algs[i].stat_fb, ss_algs[i].stat_bytes); break; +#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG case CRYPTO_ALG_TYPE_RNG: seq_printf(seq, "%s %s reqs=%lu tsize=%lu\n", ss_algs[i].alg.rng.base.cra_driver_name, ss_algs[i].alg.rng.base.cra_name, ss_algs[i].stat_req, ss_algs[i].stat_bytes); break; +#endif case CRYPTO_ALG_TYPE_AHASH: seq_printf(seq, "%s %s reqs=%lu\n", ss_algs[i].alg.hash.halg.base.cra_driver_name, @@ -471,6 +473,7 @@ static int sun4i_ss_probe(struct platform_device *pdev) goto error_alg; } break; +#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG case CRYPTO_ALG_TYPE_RNG: err = crypto_register_rng(&ss_algs[i].alg.rng); if (err) { @@ -478,6 +481,7 @@ static int sun4i_ss_probe(struct platform_device *pdev) ss_algs[i].alg.rng.base.cra_name); } break; +#endif } } @@ -497,9 +501,11 @@ error_alg: case CRYPTO_ALG_TYPE_AHASH: crypto_unregister_ahash(&ss_algs[i].alg.hash); break; +#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG case CRYPTO_ALG_TYPE_RNG: crypto_unregister_rng(&ss_algs[i].alg.rng); break; +#endif } } error_pm: @@ -520,9 +526,11 @@ static void sun4i_ss_remove(struct platform_device *pdev) case CRYPTO_ALG_TYPE_AHASH: crypto_unregister_ahash(&ss_algs[i].alg.hash); break; +#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG case CRYPTO_ALG_TYPE_RNG: crypto_unregister_rng(&ss_algs[i].alg.rng); break; +#endif } } diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c index c16bb6ce6ee3..f3b58ed6aed0 100644 --- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c +++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c @@ -676,6 +676,7 @@ static int sun8i_ce_debugfs_show(struct seq_file *seq, void *v) seq_printf(seq, "\tFallback due to SG numbers: %lu\n", ce_algs[i].stat_fb_maxsg); break; +#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_HASH case CRYPTO_ALG_TYPE_AHASH: seq_printf(seq, "%s %s reqs=%lu fallback=%lu\n", ce_algs[i].alg.hash.base.halg.base.cra_driver_name, @@ -692,12 +693,15 @@ static int sun8i_ce_debugfs_show(struct seq_file *seq, void *v) seq_printf(seq, "\tFallback due to SG numbers: %lu\n", ce_algs[i].stat_fb_maxsg); break; +#endif +#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_PRNG case CRYPTO_ALG_TYPE_RNG: seq_printf(seq, "%s %s reqs=%lu bytes=%lu\n", ce_algs[i].alg.rng.base.cra_driver_name, ce_algs[i].alg.rng.base.cra_name, ce_algs[i].stat_req, ce_algs[i].stat_bytes); break; +#endif } } #if defined(CONFIG_CRYPTO_DEV_SUN8I_CE_TRNG) && \ @@ -905,6 +909,7 @@ static int sun8i_ce_register_algs(struct sun8i_ce_dev *ce) return err; } break; +#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_HASH case CRYPTO_ALG_TYPE_AHASH: id = ce_algs[i].ce_algo_id; ce_method = ce->variant->alg_hash[id]; @@ -925,6 +930,8 @@ static int sun8i_ce_register_algs(struct sun8i_ce_dev *ce) return err; } break; +#endif +#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_PRNG case CRYPTO_ALG_TYPE_RNG: if (ce->variant->prng == CE_ID_NOTSUPP) { dev_info(ce->dev, @@ -942,6 +949,7 @@ static int sun8i_ce_register_algs(struct sun8i_ce_dev *ce) ce_algs[i].ce = NULL; } break; +#endif default: ce_algs[i].ce = NULL; dev_err(ce->dev, "ERROR: tried to register an unknown algo\n"); @@ -963,16 +971,20 @@ static void sun8i_ce_unregister_algs(struct sun8i_ce_dev *ce) ce_algs[i].alg.skcipher.base.base.cra_name); crypto_engine_unregister_skcipher(&ce_algs[i].alg.skcipher); break; +#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_HASH case CRYPTO_ALG_TYPE_AHASH: dev_info(ce->dev, "Unregister %d %s\n", i, ce_algs[i].alg.hash.base.halg.base.cra_name); crypto_engine_unregister_ahash(&ce_algs[i].alg.hash); break; +#endif +#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_PRNG case CRYPTO_ALG_TYPE_RNG: dev_info(ce->dev, "Unregister %d %s\n", i, ce_algs[i].alg.rng.base.cra_name); crypto_unregister_rng(&ce_algs[i].alg.rng); break; +#endif } } } diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c index f45685707e0d..59c9bc45ec0f 100644 --- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c +++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c @@ -501,12 +501,15 @@ static int sun8i_ss_debugfs_show(struct seq_file *seq, void *v) seq_printf(seq, "\tFallback due to SG numbers: %lu\n", ss_algs[i].stat_fb_sgnum); break; +#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_PRNG case CRYPTO_ALG_TYPE_RNG: seq_printf(seq, "%s %s reqs=%lu tsize=%lu\n", ss_algs[i].alg.rng.base.cra_driver_name, ss_algs[i].alg.rng.base.cra_name, ss_algs[i].stat_req, ss_algs[i].stat_bytes); break; +#endif +#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_HASH case CRYPTO_ALG_TYPE_AHASH: seq_printf(seq, "%s %s reqs=%lu fallback=%lu\n", ss_algs[i].alg.hash.base.halg.base.cra_driver_name, @@ -523,6 +526,7 @@ static int sun8i_ss_debugfs_show(struct seq_file *seq, void *v) seq_printf(seq, "\tFallback due to SG numbers: %lu\n", ss_algs[i].stat_fb_sgnum); break; +#endif } } return 0; @@ -707,6 +711,7 @@ static int sun8i_ss_register_algs(struct sun8i_ss_dev *ss) return err; } break; +#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_PRNG case CRYPTO_ALG_TYPE_RNG: err = crypto_register_rng(&ss_algs[i].alg.rng); if (err) { @@ -715,6 +720,8 @@ static int sun8i_ss_register_algs(struct sun8i_ss_dev *ss) ss_algs[i].ss = NULL; } break; +#endif +#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_HASH case CRYPTO_ALG_TYPE_AHASH: id = ss_algs[i].ss_algo_id; ss_method = ss->variant->alg_hash[id]; @@ -735,6 +742,7 @@ static int sun8i_ss_register_algs(struct sun8i_ss_dev *ss) return err; } break; +#endif default: ss_algs[i].ss = NULL; dev_err(ss->dev, "ERROR: tried to register an unknown algo\n"); @@ -756,16 +764,20 @@ static void sun8i_ss_unregister_algs(struct sun8i_ss_dev *ss) ss_algs[i].alg.skcipher.base.base.cra_name); crypto_engine_unregister_skcipher(&ss_algs[i].alg.skcipher); break; +#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_PRNG case CRYPTO_ALG_TYPE_RNG: dev_info(ss->dev, "Unregister %d %s\n", i, ss_algs[i].alg.rng.base.cra_name); crypto_unregister_rng(&ss_algs[i].alg.rng); break; +#endif +#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_HASH case CRYPTO_ALG_TYPE_AHASH: dev_info(ss->dev, "Unregister %d %s\n", i, ss_algs[i].alg.hash.base.halg.base.cra_name); crypto_engine_unregister_ahash(&ss_algs[i].alg.hash); break; +#endif } } } From 25056329384010a8672552b134f609601dc4f80e Mon Sep 17 00:00:00 2001 From: Ruoyu Wang Date: Thu, 23 Apr 2026 19:19:56 +0800 Subject: [PATCH 055/196] crypto: ixp4xx - fix buffer chain unwind on allocation failure chainup_buffers() builds a linked list of buffer descriptors for a scatterlist. If dma_pool_alloc() fails while constructing the list, the current code sets buf to NULL and later dereferences it unconditionally at the end of the function: buf->next = NULL; buf->phys_next = 0; This can lead to a null-pointer dereference on allocation failure. If the failure happens after part of the descriptor chain has already been allocated and DMA-mapped, the partially constructed chain also needs to be released. Fix this by terminating the partially constructed chain on allocation failure and letting the callers unwind it via their existing cleanup paths. Also fix ablk_perform() to preserve the hook pointers before checking for failure, so partially built chains can be freed correctly. Signed-off-by: Ruoyu Wang Acked-by: Linus Walleij Signed-off-by: Herbert Xu --- drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c | 25 ++++++++++++--------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c b/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c index fcc0cf4df637..5b90cf0fb0e4 100644 --- a/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c +++ b/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c @@ -884,8 +884,9 @@ static struct buffer_desc *chainup_buffers(struct device *dev, ptr = sg_virt(sg); next_buf = dma_pool_alloc(buffer_pool, flags, &next_buf_phys); if (!next_buf) { - buf = NULL; - break; + buf->next = NULL; + buf->phys_next = 0; + return NULL; } sg_dma_address(sg) = dma_map_single(dev, ptr, len, dir); buf->next = next_buf; @@ -983,7 +984,7 @@ static int ablk_perform(struct skcipher_request *req, int encrypt) unsigned int nbytes = req->cryptlen; enum dma_data_direction src_direction = DMA_BIDIRECTIONAL; struct ablk_ctx *req_ctx = skcipher_request_ctx(req); - struct buffer_desc src_hook; + struct buffer_desc *buf, src_hook; struct device *dev = &pdev->dev; unsigned int offset; gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? @@ -1025,22 +1026,24 @@ static int ablk_perform(struct skcipher_request *req, int encrypt) /* This was never tested by Intel * for more than one dst buffer, I think. */ req_ctx->dst = NULL; - if (!chainup_buffers(dev, req->dst, nbytes, &dst_hook, - flags, DMA_FROM_DEVICE)) - goto free_buf_dest; - src_direction = DMA_TO_DEVICE; + buf = chainup_buffers(dev, req->dst, nbytes, &dst_hook, + flags, DMA_FROM_DEVICE); req_ctx->dst = dst_hook.next; crypt->dst_buf = dst_hook.phys_next; + if (!buf) + goto free_buf_dest; + src_direction = DMA_TO_DEVICE; } else { req_ctx->dst = NULL; } req_ctx->src = NULL; - if (!chainup_buffers(dev, req->src, nbytes, &src_hook, flags, - src_direction)) - goto free_buf_src; - + buf = chainup_buffers(dev, req->src, nbytes, &src_hook, flags, + src_direction); req_ctx->src = src_hook.next; crypt->src_buf = src_hook.phys_next; + if (!buf) + goto free_buf_src; + crypt->ctl_flags |= CTL_FLAG_PERFORM_ABLK; qmgr_put_entry(send_qid, crypt_virt2phys(crypt)); BUG_ON(qmgr_stat_overflow(send_qid)); From 76d2e560c76dabbf9f31f4311069e68610d1ac18 Mon Sep 17 00:00:00 2001 From: Jeff Barnes Date: Thu, 23 Apr 2026 11:21:41 -0400 Subject: [PATCH 056/196] crypto: testmgr - disallow RSA PKCS#1 SHA-1 sig algs in FIPS mode When booted with fips=1, RSA signature generation using SHA-1 must not be available. However, pkcs1pad(rsa,sha1) can currently be instantiated because it is not present in alg_test_descs; alg_test() falls through the no_test path and succeeds, after which the algorithm appears in /proc/crypto as fips-capable. Add explicit alg_test_descs entries for pkcs1pad(rsa,sha1) and pkcs1(rsa,sha1) without marking them fips_allowed, so they are treated as not FIPS-allowed when fips=1 is enabled. Include both names to cover kernels where RSA sign/verify is provided via the pkcs1(...) signature template, while pkcs1pad(...) remains for the traditional wrapper naming and/or RSAES operations. Signed-off-by: Jeff Barnes Signed-off-by: Herbert Xu --- crypto/testmgr.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 4199b7d3e9fb..9059bea7a5b0 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -5198,6 +5198,9 @@ static const struct alg_test_desc alg_test_descs[] = { .suite = { .sig = __VECS(pkcs1_rsa_none_tv_template) } + }, { + .alg = "pkcs1(rsa,sha1)", + .test = alg_test_null, }, { .alg = "pkcs1(rsa,sha224)", .test = alg_test_null, @@ -5233,6 +5236,9 @@ static const struct alg_test_desc alg_test_descs[] = { .alg = "pkcs1pad(rsa)", .test = alg_test_null, .fips_allowed = 1, + }, { + .alg = "pkcs1pad(rsa,sha1)", + .test = alg_test_null, }, { .alg = "rfc3686(ctr(aes))", .generic_driver = "rfc3686(ctr(aes-lib))", From bd11fb14dee63ec5662ec70ec48eb86304d17c4d Mon Sep 17 00:00:00 2001 From: Harshal Dev Date: Fri, 24 Apr 2026 14:05:07 +0530 Subject: [PATCH 057/196] dt-bindings: crypto: qcom,prng: Document Glymur TRNG Document glymur compatible for the True Random Number Generator. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Harshal Dev Signed-off-by: Herbert Xu --- Documentation/devicetree/bindings/crypto/qcom,prng.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/crypto/qcom,prng.yaml b/Documentation/devicetree/bindings/crypto/qcom,prng.yaml index 41402599e9ab..498d6914135e 100644 --- a/Documentation/devicetree/bindings/crypto/qcom,prng.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom,prng.yaml @@ -17,6 +17,7 @@ properties: - qcom,prng-ee # 8996 and later using EE - items: - enum: + - qcom,glymur-trng - qcom,ipq5332-trng - qcom,ipq5424-trng - qcom,ipq9574-trng From 6ef4cd5b0c2b13bbf8689d50abbe51c052f31a03 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 24 Apr 2026 19:32:47 -0700 Subject: [PATCH 058/196] crypto: cesa - allocate engines with main struct Use a flexible array member to combine and simplify allocation. Move struct mv_cesa_dev down as flexible array members require full definitions. Signed-off-by: Rosen Penev Signed-off-by: Herbert Xu --- drivers/crypto/marvell/cesa/cesa.c | 11 +++----- drivers/crypto/marvell/cesa/cesa.h | 42 +++++++++++++++--------------- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/drivers/crypto/marvell/cesa/cesa.c b/drivers/crypto/marvell/cesa/cesa.c index 8afa3a87e38d..687ed730174d 100644 --- a/drivers/crypto/marvell/cesa/cesa.c +++ b/drivers/crypto/marvell/cesa/cesa.c @@ -416,7 +416,7 @@ static int mv_cesa_probe(struct platform_device *pdev) const struct mbus_dram_target_info *dram; struct device *dev = &pdev->dev; struct mv_cesa_dev *cesa; - struct mv_cesa_engine *engines; + struct mv_cesa_engine *engine; int irq, ret, i, cpu; u32 sram_size; @@ -431,7 +431,8 @@ static int mv_cesa_probe(struct platform_device *pdev) return -ENOTSUPP; } - cesa = devm_kzalloc(dev, sizeof(*cesa), GFP_KERNEL); + cesa = devm_kzalloc(dev, struct_size(cesa, engines, caps->nengines), + GFP_KERNEL); if (!cesa) return -ENOMEM; @@ -445,10 +446,6 @@ static int mv_cesa_probe(struct platform_device *pdev) sram_size = CESA_SA_MIN_SRAM_SIZE; cesa->sram_size = sram_size; - cesa->engines = devm_kcalloc(dev, caps->nengines, sizeof(*engines), - GFP_KERNEL); - if (!cesa->engines) - return -ENOMEM; spin_lock_init(&cesa->lock); @@ -465,7 +462,7 @@ static int mv_cesa_probe(struct platform_device *pdev) platform_set_drvdata(pdev, cesa); for (i = 0; i < caps->nengines; i++) { - struct mv_cesa_engine *engine = &cesa->engines[i]; + engine = &cesa->engines[i]; char res_name[16]; engine->id = i; diff --git a/drivers/crypto/marvell/cesa/cesa.h b/drivers/crypto/marvell/cesa/cesa.h index 50ca1039fdaa..18f9f28040a6 100644 --- a/drivers/crypto/marvell/cesa/cesa.h +++ b/drivers/crypto/marvell/cesa/cesa.h @@ -402,27 +402,6 @@ struct mv_cesa_dev_dma { struct dma_pool *padding_pool; }; -/** - * struct mv_cesa_dev - CESA device - * @caps: device capabilities - * @regs: device registers - * @sram_size: usable SRAM size - * @lock: device lock - * @engines: array of engines - * @dma: dma pools - * - * Structure storing CESA device information. - */ -struct mv_cesa_dev { - const struct mv_cesa_caps *caps; - void __iomem *regs; - struct device *dev; - unsigned int sram_size; - spinlock_t lock; - struct mv_cesa_engine *engines; - struct mv_cesa_dev_dma *dma; -}; - /** * struct mv_cesa_engine - CESA engine * @id: engine id @@ -471,6 +450,27 @@ struct mv_cesa_engine { int irq; }; +/** + * struct mv_cesa_dev - CESA device + * @caps: device capabilities + * @regs: device registers + * @sram_size: usable SRAM size + * @lock: device lock + * @dma: dma pools + * @engines: array of engines + * + * Structure storing CESA device information. + */ +struct mv_cesa_dev { + const struct mv_cesa_caps *caps; + void __iomem *regs; + struct device *dev; + unsigned int sram_size; + spinlock_t lock; + struct mv_cesa_dev_dma *dma; + struct mv_cesa_engine engines[]; +}; + /** * struct mv_cesa_req_ops - CESA request operations * @process: process a request chunk result (should return 0 if the From 319400fc5ee15db5793aa45f854968141326effc Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Sun, 26 Apr 2026 21:29:47 +0000 Subject: [PATCH 059/196] crypto: atmel-sha204a - fix blocking and non-blocking rng logic The blocking and non-blocking paths were failing to provide valid entropy due to improper buffer management. Reading the buffer starting from byte 1, only fetch the 32 bytes of random data from the return message. Tested on an Atmel SHA204A device. Before (here for blocking), tests showed repeatedly reading reduced bytes. $ head -c 32 /dev/hwrng | hexdump -C 00000000 02 28 85 b3 47 40 f2 ee 00 00 00 00 00 00 00 00 |.(..G@..........| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 After, the result will be similar to the following: $ head -c 32 /dev/hwrng | hexdump -C 00000000 5a fc 3f 13 14 68 fe 06 68 0a bd 04 83 6e 09 69 |Z.?..h..h....n.i| 00000010 75 ff cf 87 10 84 3b c9 c1 df ae eb 45 53 4c c3 |u.....;.....ESL.| 00000020 Fixes: da001fb651b0 ("crypto: atmel-i2c - add support for SHA204A random number generator") Suggested-by: Ard Biesheuvel Signed-off-by: Lothar Rubusch Tested-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha204a.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index dbb39ed0cea1..5699bb532325 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -48,8 +48,8 @@ static int atmel_sha204a_rng_read_nonblocking(struct hwrng *rng, void *data, if (rng->priv) { work_data = (struct atmel_i2c_work_data *)rng->priv; - max = min(sizeof(work_data->cmd.data), max); - memcpy(data, &work_data->cmd.data, max); + max = min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max); + memcpy(data, &work_data->cmd.data[RSP_DATA_IDX], max); rng->priv = 0; } else { work_data = kmalloc_obj(*work_data, GFP_ATOMIC); @@ -87,8 +87,8 @@ static int atmel_sha204a_rng_read(struct hwrng *rng, void *data, size_t max, if (ret) return ret; - max = min(sizeof(cmd.data), max); - memcpy(data, cmd.data, max); + max = min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max); + memcpy(data, &cmd.data[RSP_DATA_IDX], max); return max; } From 3f57657b6ea23f933371f2c2846322f441773cee Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 27 Apr 2026 18:39:37 +0200 Subject: [PATCH 060/196] crypto: caam - use print_hex_dump_devel to guard key hex dumps Use print_hex_dump_devel() for dumping sensitive key material in *_setkey() and gen_split_key() to avoid leaking secrets at runtime when CONFIG_DYNAMIC_DEBUG is enabled. Fixes: 6e005503199b ("crypto: caam - print debug messages at debug level") Cc: stable@vger.kernel.org Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamalg.c | 12 ++++++------ drivers/crypto/caam/caamalg_qi.c | 12 ++++++------ drivers/crypto/caam/caamhash.c | 4 ++-- drivers/crypto/caam/key_gen.c | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index 32a6e6e15ee2..ddbd60cf3b3c 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -603,7 +603,7 @@ static int aead_setkey(struct crypto_aead *aead, dev_dbg(jrdev, "keylen %d enckeylen %d authkeylen %d\n", keys.authkeylen + keys.enckeylen, keys.enckeylen, keys.authkeylen); - print_hex_dump_debug("key in @"__stringify(__LINE__)": ", + print_hex_dump_devel("key in @"__stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); /* @@ -639,7 +639,7 @@ static int aead_setkey(struct crypto_aead *aead, dma_sync_single_for_device(jrdev, ctx->key_dma, ctx->adata.keylen_pad + keys.enckeylen, ctx->dir); - print_hex_dump_debug("ctx.key@"__stringify(__LINE__)": ", + print_hex_dump_devel("ctx.key@"__stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, ctx->adata.keylen_pad + keys.enckeylen, 1); @@ -680,7 +680,7 @@ static int gcm_setkey(struct crypto_aead *aead, if (err) return err; - print_hex_dump_debug("key in @"__stringify(__LINE__)": ", + print_hex_dump_devel("key in @"__stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); memcpy(ctx->key, key, keylen); @@ -701,7 +701,7 @@ static int rfc4106_setkey(struct crypto_aead *aead, if (err) return err; - print_hex_dump_debug("key in @"__stringify(__LINE__)": ", + print_hex_dump_devel("key in @"__stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); memcpy(ctx->key, key, keylen); @@ -727,7 +727,7 @@ static int rfc4543_setkey(struct crypto_aead *aead, if (err) return err; - print_hex_dump_debug("key in @"__stringify(__LINE__)": ", + print_hex_dump_devel("key in @"__stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); memcpy(ctx->key, key, keylen); @@ -754,7 +754,7 @@ static int skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, u32 *desc; const bool is_rfc3686 = alg->caam.rfc3686; - print_hex_dump_debug("key in @"__stringify(__LINE__)": ", + print_hex_dump_devel("key in @"__stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); /* Here keylen is actual key length */ diff --git a/drivers/crypto/caam/caamalg_qi.c b/drivers/crypto/caam/caamalg_qi.c index 65f6adb6c673..aa779caacfe5 100644 --- a/drivers/crypto/caam/caamalg_qi.c +++ b/drivers/crypto/caam/caamalg_qi.c @@ -212,7 +212,7 @@ static int aead_setkey(struct crypto_aead *aead, const u8 *key, dev_dbg(jrdev, "keylen %d enckeylen %d authkeylen %d\n", keys.authkeylen + keys.enckeylen, keys.enckeylen, keys.authkeylen); - print_hex_dump_debug("key in @" __stringify(__LINE__)": ", + print_hex_dump_devel("key in @" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); /* @@ -248,7 +248,7 @@ static int aead_setkey(struct crypto_aead *aead, const u8 *key, ctx->adata.keylen_pad + keys.enckeylen, ctx->dir); - print_hex_dump_debug("ctx.key@" __stringify(__LINE__)": ", + print_hex_dump_devel("ctx.key@" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, ctx->adata.keylen_pad + keys.enckeylen, 1); @@ -371,7 +371,7 @@ static int gcm_setkey(struct crypto_aead *aead, if (ret) return ret; - print_hex_dump_debug("key in @" __stringify(__LINE__)": ", + print_hex_dump_devel("key in @" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); memcpy(ctx->key, key, keylen); @@ -475,7 +475,7 @@ static int rfc4106_setkey(struct crypto_aead *aead, if (ret) return ret; - print_hex_dump_debug("key in @" __stringify(__LINE__)": ", + print_hex_dump_devel("key in @" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); memcpy(ctx->key, key, keylen); @@ -581,7 +581,7 @@ static int rfc4543_setkey(struct crypto_aead *aead, if (ret) return ret; - print_hex_dump_debug("key in @" __stringify(__LINE__)": ", + print_hex_dump_devel("key in @" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); memcpy(ctx->key, key, keylen); @@ -631,7 +631,7 @@ static int skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, const bool is_rfc3686 = alg->caam.rfc3686; int ret = 0; - print_hex_dump_debug("key in @" __stringify(__LINE__)": ", + print_hex_dump_devel("key in @" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); ctx->cdata.keylen = keylen; diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c index ddb2a35aec2d..3cd71810380f 100644 --- a/drivers/crypto/caam/caamhash.c +++ b/drivers/crypto/caam/caamhash.c @@ -505,7 +505,7 @@ static int axcbc_setkey(struct crypto_ahash *ahash, const u8 *key, DMA_TO_DEVICE); ctx->adata.keylen = keylen; - print_hex_dump_debug("axcbc ctx.key@" __stringify(__LINE__)" : ", + print_hex_dump_devel("axcbc ctx.key@" __stringify(__LINE__)" : ", DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, keylen, 1); return axcbc_set_sh_desc(ahash); @@ -525,7 +525,7 @@ static int acmac_setkey(struct crypto_ahash *ahash, const u8 *key, ctx->adata.key_virt = key; ctx->adata.keylen = keylen; - print_hex_dump_debug("acmac ctx.key@" __stringify(__LINE__)" : ", + print_hex_dump_devel("acmac ctx.key@" __stringify(__LINE__)" : ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); return acmac_set_sh_desc(ahash); diff --git a/drivers/crypto/caam/key_gen.c b/drivers/crypto/caam/key_gen.c index 88cc4fe2a585..de2fcc387477 100644 --- a/drivers/crypto/caam/key_gen.c +++ b/drivers/crypto/caam/key_gen.c @@ -58,7 +58,7 @@ int gen_split_key(struct device *jrdev, u8 *key_out, dev_dbg(jrdev, "split keylen %d split keylen padded %d\n", adata->keylen, adata->keylen_pad); - print_hex_dump_debug("ctx.key@" __stringify(__LINE__)": ", + print_hex_dump_devel("ctx.key@" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key_in, keylen, 1); if (local_max > max_keylen) @@ -113,7 +113,7 @@ int gen_split_key(struct device *jrdev, u8 *key_out, wait_for_completion(&result.completion); ret = result.err; - print_hex_dump_debug("ctx.key@"__stringify(__LINE__)": ", + print_hex_dump_devel("ctx.key@"__stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key_out, adata->keylen_pad, 1); } From 8005dc808bcce7d6cc2ae015a3cde1683bee602d Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 27 Apr 2026 18:39:39 +0200 Subject: [PATCH 061/196] crypto: caam - use print_hex_dump_devel to guard key hex dumps Use print_hex_dump_devel() for dumping sensitive key material in *_setkey() to avoid leaking secrets at runtime when CONFIG_DYNAMIC_DEBUG is enabled. Fixes: 8d818c105501 ("crypto: caam/qi2 - add DPAA2-CAAM driver") Fixes: 226853ac3ebe ("crypto: caam/qi2 - add skcipher algorithms") Cc: stable@vger.kernel.org Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamalg_qi2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c index bf10c3dda745..6b47bcc16a50 100644 --- a/drivers/crypto/caam/caamalg_qi2.c +++ b/drivers/crypto/caam/caamalg_qi2.c @@ -301,7 +301,7 @@ static int aead_setkey(struct crypto_aead *aead, const u8 *key, dev_dbg(dev, "keylen %d enckeylen %d authkeylen %d\n", keys.authkeylen + keys.enckeylen, keys.enckeylen, keys.authkeylen); - print_hex_dump_debug("key in @" __stringify(__LINE__)": ", + print_hex_dump_devel("key in @" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); ctx->adata.keylen = keys.authkeylen; @@ -315,7 +315,7 @@ static int aead_setkey(struct crypto_aead *aead, const u8 *key, memcpy(ctx->key + ctx->adata.keylen_pad, keys.enckey, keys.enckeylen); dma_sync_single_for_device(dev, ctx->key_dma, ctx->adata.keylen_pad + keys.enckeylen, ctx->dir); - print_hex_dump_debug("ctx.key@" __stringify(__LINE__)": ", + print_hex_dump_devel("ctx.key@" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, ctx->adata.keylen_pad + keys.enckeylen, 1); @@ -732,7 +732,7 @@ static int gcm_setkey(struct crypto_aead *aead, ret = aes_check_keylen(keylen); if (ret) return ret; - print_hex_dump_debug("key in @" __stringify(__LINE__)": ", + print_hex_dump_devel("key in @" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); memcpy(ctx->key, key, keylen); @@ -828,7 +828,7 @@ static int rfc4106_setkey(struct crypto_aead *aead, if (ret) return ret; - print_hex_dump_debug("key in @" __stringify(__LINE__)": ", + print_hex_dump_devel("key in @" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); memcpy(ctx->key, key, keylen); @@ -927,7 +927,7 @@ static int rfc4543_setkey(struct crypto_aead *aead, if (ret) return ret; - print_hex_dump_debug("key in @" __stringify(__LINE__)": ", + print_hex_dump_devel("key in @" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); memcpy(ctx->key, key, keylen); @@ -955,7 +955,7 @@ static int skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, u32 *desc; const bool is_rfc3686 = alg->caam.rfc3686; - print_hex_dump_debug("key in @" __stringify(__LINE__)": ", + print_hex_dump_devel("key in @" __stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); ctx->cdata.keylen = keylen; From c207524b73f890d20da26fda0458fcfd73ccfdc2 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 27 Apr 2026 19:20:18 +0200 Subject: [PATCH 062/196] crypto: omap - add omap_aes_unregister_algs helper Add a new helper omap_aes_unregister_algs() and replace two for loops in omap_aes_probe() and omap_aes_remove(), which also ensure ->registered is reset to 0. Replace two additional for loops with crypto_engine_unregister_aeads() while at it and reset ->registered to 0 explicitly. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/omap-aes.c | 43 ++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c index 3eadaf7a64fa..f31555c0d715 100644 --- a/drivers/crypto/omap-aes.c +++ b/drivers/crypto/omap-aes.c @@ -1089,6 +1089,20 @@ static struct attribute *omap_aes_attrs[] = { }; ATTRIBUTE_GROUPS(omap_aes); +static void omap_aes_unregister_algs(const struct omap_aes_pdata *pdata) +{ + struct omap_aes_algs_info *alg_info; + int i; + + for (i = pdata->algs_info_size - 1; i >= 0; i--) { + alg_info = &pdata->algs_info[i]; + + crypto_engine_unregister_skciphers(alg_info->algs_list, + alg_info->registered); + alg_info->registered = 0; + } +} + static int omap_aes_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1215,15 +1229,11 @@ static int omap_aes_probe(struct platform_device *pdev) return 0; err_aead_algs: - for (i = dd->pdata->aead_algs_info->registered - 1; i >= 0; i--) { - aalg = &dd->pdata->aead_algs_info->algs_list[i]; - crypto_engine_unregister_aead(aalg); - } + crypto_engine_unregister_aeads(dd->pdata->aead_algs_info->algs_list, + dd->pdata->aead_algs_info->registered); + dd->pdata->aead_algs_info->registered = 0; err_algs: - for (i = dd->pdata->algs_info_size - 1; i >= 0; i--) - for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) - crypto_engine_unregister_skcipher( - &dd->pdata->algs_info[i].algs_list[j]); + omap_aes_unregister_algs(dd->pdata); err_engine: if (dd->engine) @@ -1244,25 +1254,16 @@ err_data: static void omap_aes_remove(struct platform_device *pdev) { struct omap_aes_dev *dd = platform_get_drvdata(pdev); - struct aead_engine_alg *aalg; - int i, j; spin_lock_bh(&list_lock); list_del(&dd->list); spin_unlock_bh(&list_lock); - for (i = dd->pdata->algs_info_size - 1; i >= 0; i--) - for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) { - crypto_engine_unregister_skcipher( - &dd->pdata->algs_info[i].algs_list[j]); - dd->pdata->algs_info[i].registered--; - } + omap_aes_unregister_algs(dd->pdata); - for (i = dd->pdata->aead_algs_info->registered - 1; i >= 0; i--) { - aalg = &dd->pdata->aead_algs_info->algs_list[i]; - crypto_engine_unregister_aead(aalg); - dd->pdata->aead_algs_info->registered--; - } + crypto_engine_unregister_aeads(dd->pdata->aead_algs_info->algs_list, + dd->pdata->aead_algs_info->registered); + dd->pdata->aead_algs_info->registered = 0; crypto_engine_exit(dd->engine); From 9ab1392b1163daab674484d6ddacf16f0ad4c040 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 27 Apr 2026 19:20:19 +0200 Subject: [PATCH 063/196] crypto: omap - add omap_des_unregister_algs helper Add a new helper omap_des_unregister_algs() and replace two for loops in omap_des_probe() and omap_des_remove(), which also ensure ->registered is reset to 0. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/omap-des.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/crypto/omap-des.c b/drivers/crypto/omap-des.c index 149ebd77710b..16d5c617d5ee 100644 --- a/drivers/crypto/omap-des.c +++ b/drivers/crypto/omap-des.c @@ -938,6 +938,20 @@ static int omap_des_get_pdev(struct omap_des_dev *dd, return 0; } +static void omap_des_unregister_algs(const struct omap_des_pdata *pdata) +{ + struct omap_des_algs_info *alg_info; + int i; + + for (i = pdata->algs_info_size - 1; i >= 0; i--) { + alg_info = &pdata->algs_info[i]; + + crypto_engine_unregister_skciphers(alg_info->algs_list, + alg_info->registered); + alg_info->registered = 0; + } +} + static int omap_des_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1043,11 +1057,7 @@ static int omap_des_probe(struct platform_device *pdev) return 0; err_algs: - for (i = dd->pdata->algs_info_size - 1; i >= 0; i--) - for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) - crypto_engine_unregister_skcipher( - &dd->pdata->algs_info[i].algs_list[j]); - + omap_des_unregister_algs(dd->pdata); err_engine: if (dd->engine) crypto_engine_exit(dd->engine); @@ -1067,16 +1077,12 @@ err_data: static void omap_des_remove(struct platform_device *pdev) { struct omap_des_dev *dd = platform_get_drvdata(pdev); - int i, j; spin_lock_bh(&list_lock); list_del(&dd->list); spin_unlock_bh(&list_lock); - for (i = dd->pdata->algs_info_size - 1; i >= 0; i--) - for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) - crypto_engine_unregister_skcipher( - &dd->pdata->algs_info[i].algs_list[j]); + omap_des_unregister_algs(dd->pdata); cancel_work_sync(&dd->done_task); omap_des_dma_cleanup(dd); From c3494e6fbb35579a131de11369b658a59b1323e5 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 27 Apr 2026 19:20:20 +0200 Subject: [PATCH 064/196] crypto: omap - add omap_sham_unregister_algs helper Add a new helper omap_sham_unregister_algs() and replace two for loops in omap_sham_probe() and omap_sham_remove(), which also ensure ->registered is reset to 0. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/omap-sham.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c index b8c416c5ee70..be1ac640ee59 100644 --- a/drivers/crypto/omap-sham.c +++ b/drivers/crypto/omap-sham.c @@ -2042,6 +2042,20 @@ static struct attribute *omap_sham_attrs[] = { }; ATTRIBUTE_GROUPS(omap_sham); +static void omap_sham_unregister_algs(const struct omap_sham_pdata *pdata) +{ + struct omap_sham_algs_info *alg_info; + int i; + + for (i = pdata->algs_info_size - 1; i >= 0; i--) { + alg_info = &pdata->algs_info[i]; + + crypto_engine_unregister_ahashes(alg_info->algs_list, + alg_info->registered); + alg_info->registered = 0; + } +} + static int omap_sham_probe(struct platform_device *pdev) { struct omap_sham_dev *dd; @@ -2158,10 +2172,7 @@ static int omap_sham_probe(struct platform_device *pdev) return 0; err_algs: - for (i = dd->pdata->algs_info_size - 1; i >= 0; i--) - for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) - crypto_engine_unregister_ahash( - &dd->pdata->algs_info[i].algs_list[j]); + omap_sham_unregister_algs(dd->pdata); err_engine_start: crypto_engine_exit(dd->engine); err_engine: @@ -2182,19 +2193,13 @@ data_err: static void omap_sham_remove(struct platform_device *pdev) { struct omap_sham_dev *dd; - int i, j; dd = platform_get_drvdata(pdev); spin_lock_bh(&sham.lock); list_del(&dd->list); spin_unlock_bh(&sham.lock); - for (i = dd->pdata->algs_info_size - 1; i >= 0; i--) - for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) { - crypto_engine_unregister_ahash( - &dd->pdata->algs_info[i].algs_list[j]); - dd->pdata->algs_info[i].registered--; - } + omap_sham_unregister_algs(dd->pdata); cancel_work_sync(&dd->done_task); pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_disable(&pdev->dev); From bee54677bc516e28ced4276792958f0f1a264871 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 27 Apr 2026 23:35:06 +0200 Subject: [PATCH 065/196] crypto: starfive - use list_first_entry_or_null to simplify cryp_find_dev Use list_first_entry_or_null() to simplify starfive_cryp_find_dev() and remove the now-unused local variable 'struct starfive_cryp_dev *tmp'. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/starfive/jh7110-cryp.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/crypto/starfive/jh7110-cryp.c b/drivers/crypto/starfive/jh7110-cryp.c index 42114e9364f0..e19cd7945968 100644 --- a/drivers/crypto/starfive/jh7110-cryp.c +++ b/drivers/crypto/starfive/jh7110-cryp.c @@ -36,19 +36,14 @@ static struct starfive_dev_list dev_list = { struct starfive_cryp_dev *starfive_cryp_find_dev(struct starfive_cryp_ctx *ctx) { - struct starfive_cryp_dev *cryp = NULL, *tmp; + struct starfive_cryp_dev *cryp; spin_lock_bh(&dev_list.lock); - if (!ctx->cryp) { - list_for_each_entry(tmp, &dev_list.dev_list, list) { - cryp = tmp; - break; - } - ctx->cryp = cryp; - } else { - cryp = ctx->cryp; - } - + if (!ctx->cryp) + ctx->cryp = list_first_entry_or_null(&dev_list.dev_list, + struct starfive_cryp_dev, + list); + cryp = ctx->cryp; spin_unlock_bh(&dev_list.lock); return cryp; From ea5e57cc97185329dcc5ebdcaae7e1500bf0ad0b Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 28 Apr 2026 12:14:32 +0200 Subject: [PATCH 066/196] crypto: atmel-sha204a - drop hwrng quality reduction for ATSHA204A Commit 8006aff15516 ("crypto: atmel-sha204a - Set hwrng quality to lowest possible") reduced the hwrng quality to 1 based on a review by Bill Cox [1]. However, despite its title, the review only tested the ATSHA204, not the ATSHA204A. In the same thread, Atmel engineer Landon Cox wrote "this behavior has been eliminated entirely"[2] in the ATSHA204A and "this problem does not affect the ATECC108 or the ATECC108A (or the ATSHA204A)"[3]. According to the official ATSHA204A datasheet [4], the device contains a high-quality hardware RNG that combines its output with an internal seed value stored in EEPROM or SRAM to generate random numbers. The device also implements all security functions using SHA-256, and the driver uses the chip's Random command in seed-update mode. Keep 'quality = 1' for ATSHA204, but drop the explicit hwrng quality reduction for ATSHA204A and fall back to the hwrng core default. [1] https://www.metzdowd.com/pipermail/cryptography/2014-December/023858.html [2] https://www.metzdowd.com/pipermail/cryptography/2014-December/023852.html [3] https://www.metzdowd.com/pipermail/cryptography/2014-December/023886.html [4] https://ww1.microchip.com/downloads/en/DeviceDoc/ATSHA204A-Data-Sheet-40002025A.pdf Fixes: 8006aff15516 ("crypto: atmel-sha204a - Set hwrng quality to lowest possible") Cc: stable@vger.kernel.org Signed-off-by: Thorsten Blum Reviewed-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha204a.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index 5699bb532325..ed7d69bf6890 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -19,6 +19,12 @@ #include #include "atmel-i2c.h" +/* + * According to review by Bill Cox [1], the ATSHA204 has very low entropy. + * [1] https://www.metzdowd.com/pipermail/cryptography/2014-December/023858.html + */ +static const unsigned short atsha204_quality = 1; + static void atmel_sha204a_rng_done(struct atmel_i2c_work_data *work_data, void *areq, int status) { @@ -158,6 +164,7 @@ static const struct attribute_group atmel_sha204a_groups = { static int atmel_sha204a_probe(struct i2c_client *client) { struct atmel_i2c_client_priv *i2c_priv; + const unsigned short *quality; int ret; ret = atmel_i2c_probe(client); @@ -171,11 +178,9 @@ static int atmel_sha204a_probe(struct i2c_client *client) i2c_priv->hwrng.name = dev_name(&client->dev); i2c_priv->hwrng.read = atmel_sha204a_rng_read; - /* - * According to review by Bill Cox [1], this HWRNG has very low entropy. - * [1] https://www.metzdowd.com/pipermail/cryptography/2014-December/023858.html - */ - i2c_priv->hwrng.quality = 1; + quality = i2c_get_match_data(client); + if (quality) + i2c_priv->hwrng.quality = *quality; ret = devm_hwrng_register(&client->dev, &i2c_priv->hwrng); if (ret) @@ -203,14 +208,14 @@ static void atmel_sha204a_remove(struct i2c_client *client) } static const struct of_device_id atmel_sha204a_dt_ids[] __maybe_unused = { - { .compatible = "atmel,atsha204", }, + { .compatible = "atmel,atsha204", .data = &atsha204_quality }, { .compatible = "atmel,atsha204a", }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, atmel_sha204a_dt_ids); static const struct i2c_device_id atmel_sha204a_id[] = { - { "atsha204" }, + { "atsha204", (kernel_ulong_t)&atsha204_quality }, { "atsha204a" }, { /* sentinel */ } }; From a67afb1884ba815079bd43d5c998e155e03b08b6 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 29 Apr 2026 18:15:44 -0700 Subject: [PATCH 067/196] crypto: af_alg - Document the deprecation of AF_ALG AF_ALG is almost completely unnecessary, and it exposes a massive attack surface that hasn't been standing up to modern vulnerability discovery tools. The latest one even has its own website, providing a small Python script that reliably roots most Linux distros: https://copy.fail/ This isn't sustainable, especially as LLMs have accelerated the rate the vulnerabilities are coming in. The effort that is being put into this thing is vastly disproportional to the few programs that actually use it, and those programs would be better served by userspace code anyway. These issues have been noted in many mailing list discussions already. But until now they haven't been reflected in the documentation or kconfig menu itself, and the vulnerabilities are still coming in. Let's go ahead and document the deprecation. This isn't intended to change anything overnight. After all, most Linux distros won't be able to disable the kconfig options quite yet, mainly because of iwd. But this should create a bit more impetus for these userspace programs to be fixed, and the documentation update should also help prevent more users from appearing. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- Documentation/crypto/userspace-if.rst | 74 +++++++++++++++++++++------ crypto/Kconfig | 69 ++++++++++++++++++------- 2 files changed, 109 insertions(+), 34 deletions(-) diff --git a/Documentation/crypto/userspace-if.rst b/Documentation/crypto/userspace-if.rst index a3b13ff83cb3..2c4e9a1ac3e5 100644 --- a/Documentation/crypto/userspace-if.rst +++ b/Documentation/crypto/userspace-if.rst @@ -4,26 +4,68 @@ User Space Interface Introduction ------------ -The concepts of the kernel crypto API visible to kernel space is fully -applicable to the user space interface as well. Therefore, the kernel -crypto API high level discussion for the in-kernel use cases applies -here as well. +AF_ALG provides unprivileged userspace programs access to arbitrary hash, +symmetric cipher, AEAD, and RNG algorithms that are implemented in kernel-mode +code. -The major difference, however, is that user space can only act as a -consumer and never as a provider of a transformation or cipher -algorithm. +AF_ALG is insecure and is deprecated. Originally added to the kernel in 2010, +most kernel developers now consider it to be a mistake. -The following covers the user space interface exported by the kernel -crypto API. A working example of this description is libkcapi that can -be obtained from [1]. That library can be used by user space -applications that require cryptographic services from the kernel. +AF_ALG continues to be supported only for backwards compatibility. On systems +where no programs using AF_ALG remain, the support for it should be disabled by +disabling ``CONFIG_CRYPTO_USER_API_*``. -Some details of the in-kernel kernel crypto API aspects do not apply to -user space, however. This includes the difference between synchronous -and asynchronous invocations. The user space API call is fully -synchronous. +Deprecation +----------- -[1] https://www.chronox.de/libkcapi/index.html +AF_ALG was originally intended to provide userspace programs access to crypto +accelerators that they wouldn't otherwise have access to. + +However, that capability turned out to not be useful on very many systems. More +significantly, the actual implementation exposes a vastly greater amount of +functionality than that. It actually provides access to all software algorithms. + +This includes arbitrary compositions of different algorithms created via a +complex template system, as well as algorithms that only make sense as internal +implementation details of other algorithms. It also includes full zero-copy +support, which is difficult for the kernel to implement securely. + +Ultimately, these algorithms are just math computations. They use the same +instructions that userspace programs already have access to, just accessed in a +much more convoluted and less efficient way. + +Indeed, userspace code is nearly always what is being used anyway. These same +algorithms are widely implemented in userspace crypto libraries. + +Meanwhile, AF_ALG hasn't been withstanding modern vulnerability discovery tools +such as syzbot and large language models. It receives a steady stream of CVEs. +Some of the examples include: + +- CVE-2026-31677 +- CVE-2026-31431 (https://copy.fail) +- CVE-2025-38079 +- CVE-2025-37808 +- CVE-2024-26824 +- CVE-2022-48781 +- CVE-2019-8912 +- CVE-2018-14619 +- CVE-2017-18075 +- CVE-2017-17806 +- CVE-2017-17805 +- CVE-2016-10147 +- CVE-2015-8970 +- CVE-2015-3331 +- CVE-2014-9644 +- CVE-2013-7421 +- CVE-2011-4081 + +It is recommended that, whenever possible, userspace programs be migrated to +userspace crypto code (which again, is what is normally used anyway) and +``CONFIG_CRYPTO_USER_API_*`` be disabled. On systems that use SELinux, SELinux +can also be used to restrict the use of AF_ALG to trusted programs. + +The remainder of this documentation provides the historical documentation for +the deprecated AF_ALG interface. User Space API General Remarks ------------------------------ diff --git a/crypto/Kconfig b/crypto/Kconfig index 608b2c739193..00b7ce4227ae 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1252,44 +1252,68 @@ config CRYPTO_DF80090A select CRYPTO_CTR endmenu -menu "Userspace interface" +menu "Userspace interface (deprecated)" config CRYPTO_USER_API tristate config CRYPTO_USER_API_HASH - tristate "Hash algorithms" + tristate "Hash algorithms (deprecated)" depends on NET select CRYPTO_HASH select CRYPTO_USER_API help - Enable the userspace interface for hash algorithms. + Enable the AF_ALG userspace interface for hash algorithms. This + provides unprivileged userspace programs access to arbitrary hash + algorithms implemented in the kernel's privileged execution context. - See Documentation/crypto/userspace-if.rst and - https://www.chronox.de/libkcapi/html/index.html + This interface is deprecated and is supported only for backwards + compatibility. It regularly has vulnerabilities, and the capabilities + it provides are redundant with userspace crypto libraries. + + Enable this only if needed for support for a program that hasn't yet + been converted to userspace crypto, for example iwd. + + See also Documentation/crypto/userspace-if.rst config CRYPTO_USER_API_SKCIPHER - tristate "Symmetric key cipher algorithms" + tristate "Symmetric key cipher algorithms (deprecated)" depends on NET select CRYPTO_SKCIPHER select CRYPTO_USER_API help - Enable the userspace interface for symmetric key cipher algorithms. + Enable the AF_ALG userspace interface for symmetric key algorithms. + This provides unprivileged userspace programs access to arbitrary + symmetric key algorithms implemented in the kernel's privileged + execution context. - See Documentation/crypto/userspace-if.rst and - https://www.chronox.de/libkcapi/html/index.html + This interface is deprecated and is supported only for backwards + compatibility. It regularly has vulnerabilities, and the capabilities + it provides are redundant with userspace crypto libraries. + + Enable this only if needed for support for a program that hasn't yet + been converted to userspace crypto, for example iwd, or cryptsetup + with certain algorithms. + + See also Documentation/crypto/userspace-if.rst config CRYPTO_USER_API_RNG - tristate "RNG (random number generator) algorithms" + tristate "Random number generation algorithms (deprecated)" depends on NET select CRYPTO_RNG select CRYPTO_USER_API help - Enable the userspace interface for RNG (random number generator) - algorithms. + Enable the AF_ALG userspace interface for random number generation + (RNG) algorithms. This provides unprivileged userspace programs + access to arbitrary RNG algorithms implemented in the kernel's + privileged execution context. - See Documentation/crypto/userspace-if.rst and - https://www.chronox.de/libkcapi/html/index.html + This interface is deprecated and is supported only for backwards + compatibility. It regularly has vulnerabilities, and the capabilities + it provides are redundant with userspace crypto libraries as well as + the normal kernel RNG (e.g., /dev/urandom and getrandom(2)). + + See also Documentation/crypto/userspace-if.rst config CRYPTO_USER_API_RNG_CAVP bool "Enable CAVP testing of DRBG" @@ -1304,16 +1328,25 @@ config CRYPTO_USER_API_RNG_CAVP no unless you know what this is. config CRYPTO_USER_API_AEAD - tristate "AEAD cipher algorithms" + tristate "AEAD cipher algorithms (deprecated)" depends on NET select CRYPTO_AEAD select CRYPTO_SKCIPHER select CRYPTO_USER_API help - Enable the userspace interface for AEAD cipher algorithms. + Enable the AF_ALG userspace interface for authenticated encryption + with associated data (AEAD) algorithms. This provides unprivileged + userspace programs access to arbitrary AEAD algorithms implemented in + the kernel's privileged execution context. - See Documentation/crypto/userspace-if.rst and - https://www.chronox.de/libkcapi/html/index.html + This interface is deprecated and is supported only for backwards + compatibility. It regularly has vulnerabilities, and the capabilities + it provides are redundant with userspace crypto libraries. + + Enable this only if needed for support for a program that hasn't yet + been converted to userspace crypto, for example iwd. + + See also Documentation/crypto/userspace-if.rst config CRYPTO_USER_API_ENABLE_OBSOLETE bool "Obsolete cryptographic algorithms" From c04337343ef6e1d5ee5b49ac386e468c2d063e07 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 2 May 2026 12:53:42 +0800 Subject: [PATCH 068/196] crypto: authencesn - Use memcpy_from/to_sglist Convert scatterwalk_map_and_copy to memcpy_to/from_sglist as they are more readable and less error-prone. Signed-off-by: Herbert Xu --- crypto/authencesn.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/crypto/authencesn.c b/crypto/authencesn.c index 522df41365d8..ca063576f670 100644 --- a/crypto/authencesn.c +++ b/crypto/authencesn.c @@ -94,11 +94,11 @@ static int crypto_authenc_esn_genicv_tail(struct aead_request *req, u32 tmp[2]; /* Move high-order bits of sequence number back. */ - scatterwalk_map_and_copy(tmp, dst, 4, 4, 0); - scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0); - scatterwalk_map_and_copy(tmp, dst, 0, 8, 1); + memcpy_from_sglist(tmp, dst, 4, 4); + memcpy_from_sglist(tmp + 1, dst, assoclen + cryptlen, 4); + memcpy_to_sglist(dst, 0, tmp, 8); - scatterwalk_map_and_copy(hash, dst, assoclen + cryptlen, authsize, 1); + memcpy_to_sglist(dst, assoclen + cryptlen, hash, authsize); return 0; } @@ -129,9 +129,9 @@ static int crypto_authenc_esn_genicv(struct aead_request *req, return 0; /* Move high-order bits of sequence number to the end. */ - scatterwalk_map_and_copy(tmp, dst, 0, 8, 0); - scatterwalk_map_and_copy(tmp, dst, 4, 4, 1); - scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1); + memcpy_from_sglist(tmp, dst, 0, 8); + memcpy_to_sglist(dst, 4, tmp, 4); + memcpy_to_sglist(dst, assoclen + cryptlen, tmp + 1, 4); sg_init_table(areq_ctx->dst, 2); dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4); @@ -217,9 +217,9 @@ static int crypto_authenc_esn_decrypt_tail(struct aead_request *req, if (src == dst) { /* Move high-order bits of sequence number back. */ - scatterwalk_map_and_copy(tmp, dst, 4, 4, 0); - scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0); - scatterwalk_map_and_copy(tmp, dst, 0, 8, 1); + memcpy_from_sglist(tmp, dst, 4, 4); + memcpy_from_sglist(tmp + 1, dst, assoclen + cryptlen, 4); + memcpy_to_sglist(dst, 0, tmp, 8); } else memcpy_sglist(dst, src, assoclen); @@ -274,18 +274,17 @@ static int crypto_authenc_esn_decrypt(struct aead_request *req) goto tail; cryptlen -= authsize; - scatterwalk_map_and_copy(ihash, req->src, assoclen + cryptlen, - authsize, 0); + memcpy_from_sglist(ihash, req->src, assoclen + cryptlen, authsize); /* Move high-order bits of sequence number to the end. */ - scatterwalk_map_and_copy(tmp, src, 0, 8, 0); + memcpy_from_sglist(tmp, src, 0, 8); if (src == dst) { - scatterwalk_map_and_copy(tmp, dst, 4, 4, 1); - scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1); + memcpy_to_sglist(dst, 4, tmp, 4); + memcpy_to_sglist(dst, assoclen + cryptlen, tmp + 1, 4); dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4); } else { - scatterwalk_map_and_copy(tmp, dst, 0, 4, 1); - scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen - 4, 4, 1); + memcpy_to_sglist(dst, 0, tmp, 4); + memcpy_to_sglist(dst, assoclen + cryptlen - 4, tmp + 1, 4); src = scatterwalk_ffwd(areq_ctx->src, src, 8); dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4); From 2d7b2cfc59998baf5e8622a24dc28f69a5212e06 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sat, 2 May 2026 21:09:04 +0200 Subject: [PATCH 069/196] crypto: ecrdsa - fix unknown OID check in ecrdsa_param_curve The ->curve_oid check in ecrdsa_param_curve() rejects the valid enum value 0 (OID_id_dsa_with_sha1), but look_up_OID() returns OID__NR on lookup failure. Compare ->curve_oid with OID__NR instead to ensure that only unknown OIDs return -EINVAL. Fixes: 0d7a78643f69 ("crypto: ecrdsa - add EC-RDSA (GOST 34.10) algorithm") Signed-off-by: Thorsten Blum Reviewed-by: Lukas Wunner Reviewed-by: Vitaly Chikunov Signed-off-by: Herbert Xu --- crypto/ecrdsa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/ecrdsa.c b/crypto/ecrdsa.c index 2c0602f0cd40..0cd7eb367604 100644 --- a/crypto/ecrdsa.c +++ b/crypto/ecrdsa.c @@ -145,7 +145,7 @@ int ecrdsa_param_curve(void *context, size_t hdrlen, unsigned char tag, struct ecrdsa_ctx *ctx = context; ctx->curve_oid = look_up_OID(value, vlen); - if (!ctx->curve_oid) + if (ctx->curve_oid == OID__NR) return -EINVAL; ctx->curve = get_curve_by_oid(ctx->curve_oid); return 0; From f7dd32c5179d7755de18e21d5674b08f9e5cb180 Mon Sep 17 00:00:00 2001 From: Weiming Shi Date: Thu, 30 Apr 2026 10:36:34 -0700 Subject: [PATCH 070/196] crypto: asymmetric_keys - fix OOB read in pefile_digest_pe_contents pefile_digest_pe_contents() computes the trailing-data hash length as pelen - (hashed_bytes + certs_size). A crafted PE can make the addition exceed pelen, causing the unsigned subtraction to underflow to ~4 GiB. This is passed to crypto_shash_update() which reads out of bounds and panics on unmapped vmalloc guard pages. BUG: unable to handle page fault for address: ffffc900038d8000 Oops: Oops: 0000 [#1] SMP KASAN NOPTI RIP: 0010:sha256_blocks_generic (lib/crypto/sha256.c:152) Call Trace: __sha256_update (lib/crypto/sha256.c:208) crypto_sha256_update (crypto/sha256.c:142) verify_pefile_signature (crypto/asymmetric_keys/verify_pefile.c:436) kexec_kernel_verify_pe_sig (kernel/kexec_file.c:151) __do_sys_kexec_file_load (kernel/kexec_file.c:406) do_syscall_64 (arch/x86/entry/syscall_64.c:94) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) Kernel panic - not syncing: Fatal exception Validate that the addition does not overflow and the result does not exceed pelen before the subtraction. Return -ELIBBAD on failure. Fixes: af316fc442ef ("pefile: Digest the PE binary and compare to the PKCS#7 data") Reported-by: Xiang Mei Signed-off-by: Weiming Shi Signed-off-by: Herbert Xu --- crypto/asymmetric_keys/verify_pefile.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c index 1f3b227ba7f2..cec99db14129 100644 --- a/crypto/asymmetric_keys/verify_pefile.c +++ b/crypto/asymmetric_keys/verify_pefile.c @@ -305,6 +305,8 @@ static int pefile_digest_pe_contents(const void *pebuf, unsigned int pelen, if (pelen > hashed_bytes) { tmp = hashed_bytes + ctx->certs_size; + if (tmp <= hashed_bytes || pelen < tmp) + return -ELIBBAD; ret = crypto_shash_update(desc, pebuf + hashed_bytes, pelen - tmp); From 15f5bc6748a63b0c19f2a6d96219be6ff5d128eb Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 29 Apr 2026 10:10:20 +0200 Subject: [PATCH 071/196] dt-bindings: crypto: qcom-qce: document the Nord crypto engine Document the crypto engine on the Qualcomm Nord Platform. Signed-off-by: Bartosz Golaszewski Acked-by: Rob Herring (Arm) Signed-off-by: Herbert Xu --- Documentation/devicetree/bindings/crypto/qcom-qce.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/crypto/qcom-qce.yaml b/Documentation/devicetree/bindings/crypto/qcom-qce.yaml index 69101cead3bc..08febd66c22b 100644 --- a/Documentation/devicetree/bindings/crypto/qcom-qce.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom-qce.yaml @@ -49,6 +49,7 @@ properties: - qcom,glymur-qce - qcom,kaanapali-qce - qcom,milos-qce + - qcom,nord-qce - qcom,qcs615-qce - qcom,qcs8300-qce - qcom,sa8775p-qce From 650f09718adc327c7dc50f6347580079fdb361f6 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 4 May 2026 10:28:50 +0200 Subject: [PATCH 072/196] crypto: jitterentropy - drop redundant delta check in jent_entropy_init Since start_time = end_time - delta, start_time can only equal end_time when delta is 0, making the explicit end_time == start_time check redundant. Remove it. Signed-off-by: Thorsten Blum Reviewed-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/jitterentropy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/jitterentropy.c b/crypto/jitterentropy.c index d5832caa8ab3..6ac0257e8e0a 100644 --- a/crypto/jitterentropy.c +++ b/crypto/jitterentropy.c @@ -775,7 +775,7 @@ int jent_entropy_init(unsigned int osr, unsigned int flags, * delta even when called shortly after each other -- this * implies that we also have a high resolution timer */ - if (!delta || (end_time == start_time)) { + if (!delta) { ret = JENT_ECOARSETIME; goto out; } From 69e7b807ba7464fe9fd46bc72562cdeabe9a374c Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 4 May 2026 10:28:51 +0200 Subject: [PATCH 073/196] crypto: jitterentropy - fix URL The URL https://www.chronox.de/jent.html resolves to a 404 Not Found. Use https://www.chronox.de/jent/ instead. Signed-off-by: Thorsten Blum Reviewed-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/jitterentropy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto/jitterentropy.c b/crypto/jitterentropy.c index 6ac0257e8e0a..b024bff7024a 100644 --- a/crypto/jitterentropy.c +++ b/crypto/jitterentropy.c @@ -7,7 +7,7 @@ * Design * ====== * - * See https://www.chronox.de/jent.html + * See https://www.chronox.de/jent/ * * License * ======= @@ -47,7 +47,7 @@ /* * This Jitterentropy RNG is based on the jitterentropy library - * version 3.4.0 provided at https://www.chronox.de/jent.html + * version 3.4.0 provided at https://www.chronox.de/jent/ */ #ifdef __OPTIMIZE__ From 69f93dbb40377edc4c4bf3fc67bbd63ba35fde3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Mon, 4 May 2026 11:20:14 +0200 Subject: [PATCH 074/196] hwrng: drivers - Drop unused assignment to pci driver_data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Explicitly assigning 0 to driver_data in drivers not using this member has no benefit. Drop these and similarly depend on the compiler to zero-initialize the list terminator. This is a preparation for making struct pci_device_id::driver_data an anonymous union (which makes initializing using a list expression fail), but it's also a nice cleanup by itself. It was verified on x86 and arm64 that this change doesn't introduce changes to the compiled drivers. Signed-off-by: Uwe Kleine-König (The Capable Hub) Signed-off-by: Herbert Xu --- drivers/char/hw_random/amd-rng.c | 6 +++--- drivers/char/hw_random/cavium-rng.c | 4 ++-- drivers/char/hw_random/geode-rng.c | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c index 332d594bdf70..dff80daae587 100644 --- a/drivers/char/hw_random/amd-rng.c +++ b/drivers/char/hw_random/amd-rng.c @@ -47,9 +47,9 @@ * want to register another driver on the same PCI id. */ static const struct pci_device_id pci_tbl[] = { - { PCI_VDEVICE(AMD, 0x7443), 0, }, - { PCI_VDEVICE(AMD, 0x746b), 0, }, - { 0, }, /* terminate list */ + { PCI_VDEVICE(AMD, 0x7443) }, + { PCI_VDEVICE(AMD, 0x746b) }, + { } /* terminate list */ }; MODULE_DEVICE_TABLE(pci, pci_tbl); diff --git a/drivers/char/hw_random/cavium-rng.c b/drivers/char/hw_random/cavium-rng.c index d9d7b6038c06..3e2c042009f6 100644 --- a/drivers/char/hw_random/cavium-rng.c +++ b/drivers/char/hw_random/cavium-rng.c @@ -73,8 +73,8 @@ static void cavium_rng_remove(struct pci_dev *pdev) } static const struct pci_device_id cavium_rng_pf_id_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xa018), 0, 0, 0}, /* Thunder RNM */ - {0,}, + { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xa018) }, /* Thunder RNM */ + { }, }; MODULE_DEVICE_TABLE(pci, cavium_rng_pf_id_table); diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c index 1b21d58e1768..ae63eff64344 100644 --- a/drivers/char/hw_random/geode-rng.c +++ b/drivers/char/hw_random/geode-rng.c @@ -46,8 +46,8 @@ * want to register another driver on the same PCI id. */ static const struct pci_device_id pci_tbl[] = { - { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_LX_AES), 0, }, - { 0, }, /* terminate list */ + { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_LX_AES) }, + { } /* terminate list */ }; MODULE_DEVICE_TABLE(pci, pci_tbl); From 15d253c5d7fa17d3499c885bdb82070546180e44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Mon, 4 May 2026 17:24:21 +0200 Subject: [PATCH 075/196] crypto: ccp - Define pci_device_ids using named initializers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .driver_data member of the struct pci_device_id array was initialized by list expressions. This isn't easily readable if you're not into PCI. Using the PCI_DEVICE macro and named initializers is more explicit and thus easier to parse. Also skip explicit assignment of 0 (which the compiler then takes care of) in the terminating entry. Signed-off-by: Uwe Kleine-König (The Capable Hub) Acked-by: Tom Lendacky Signed-off-by: Herbert Xu --- drivers/crypto/ccp/sp-pci.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c index 6ac805d99ccb..ede6ff9ad0c2 100644 --- a/drivers/crypto/ccp/sp-pci.c +++ b/drivers/crypto/ccp/sp-pci.c @@ -552,21 +552,21 @@ static const struct sp_dev_vdata dev_vdata[] = { }; static const struct pci_device_id sp_pci_table[] = { - { PCI_VDEVICE(AMD, 0x1537), (kernel_ulong_t)&dev_vdata[0] }, - { PCI_VDEVICE(AMD, 0x1456), (kernel_ulong_t)&dev_vdata[1] }, - { PCI_VDEVICE(AMD, 0x1468), (kernel_ulong_t)&dev_vdata[2] }, - { PCI_VDEVICE(AMD, 0x1486), (kernel_ulong_t)&dev_vdata[3] }, - { PCI_VDEVICE(AMD, 0x15DF), (kernel_ulong_t)&dev_vdata[4] }, - { PCI_VDEVICE(AMD, 0x14CA), (kernel_ulong_t)&dev_vdata[5] }, - { PCI_VDEVICE(AMD, 0x15C7), (kernel_ulong_t)&dev_vdata[6] }, - { PCI_VDEVICE(AMD, 0x1649), (kernel_ulong_t)&dev_vdata[6] }, - { PCI_VDEVICE(AMD, 0x1134), (kernel_ulong_t)&dev_vdata[7] }, - { PCI_VDEVICE(AMD, 0x17E0), (kernel_ulong_t)&dev_vdata[7] }, - { PCI_VDEVICE(AMD, 0x156E), (kernel_ulong_t)&dev_vdata[8] }, - { PCI_VDEVICE(AMD, 0x17D8), (kernel_ulong_t)&dev_vdata[8] }, - { PCI_VDEVICE(AMD, 0x115A), (kernel_ulong_t)&dev_vdata[9] }, + { PCI_VDEVICE(AMD, 0x1537), .driver_data = (kernel_ulong_t)&dev_vdata[0] }, + { PCI_VDEVICE(AMD, 0x1456), .driver_data = (kernel_ulong_t)&dev_vdata[1] }, + { PCI_VDEVICE(AMD, 0x1468), .driver_data = (kernel_ulong_t)&dev_vdata[2] }, + { PCI_VDEVICE(AMD, 0x1486), .driver_data = (kernel_ulong_t)&dev_vdata[3] }, + { PCI_VDEVICE(AMD, 0x15DF), .driver_data = (kernel_ulong_t)&dev_vdata[4] }, + { PCI_VDEVICE(AMD, 0x14CA), .driver_data = (kernel_ulong_t)&dev_vdata[5] }, + { PCI_VDEVICE(AMD, 0x15C7), .driver_data = (kernel_ulong_t)&dev_vdata[6] }, + { PCI_VDEVICE(AMD, 0x1649), .driver_data = (kernel_ulong_t)&dev_vdata[6] }, + { PCI_VDEVICE(AMD, 0x1134), .driver_data = (kernel_ulong_t)&dev_vdata[7] }, + { PCI_VDEVICE(AMD, 0x17E0), .driver_data = (kernel_ulong_t)&dev_vdata[7] }, + { PCI_VDEVICE(AMD, 0x156E), .driver_data = (kernel_ulong_t)&dev_vdata[8] }, + { PCI_VDEVICE(AMD, 0x17D8), .driver_data = (kernel_ulong_t)&dev_vdata[8] }, + { PCI_VDEVICE(AMD, 0x115A), .driver_data = (kernel_ulong_t)&dev_vdata[9] }, /* Last entry must be zero */ - { 0, } + { } }; MODULE_DEVICE_TABLE(pci, sp_pci_table); From 97d1d35b573163176ab817489f2322d97f7bc84f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Mon, 4 May 2026 17:32:21 +0200 Subject: [PATCH 076/196] crypto: drivers - Drop explicit assigment of 0 in pci_device_id array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Assigning .driver_data for drivers that don't use this struct member is just noise that can better be dropped. The same applies for an explicit zero in the terminating entry. Drop these. Signed-off-by: Uwe Kleine-König (The Capable Hub) Signed-off-by: Herbert Xu --- drivers/crypto/cavium/cpt/cptvf_main.c | 4 ++-- drivers/crypto/cavium/nitrox/nitrox_main.c | 4 ++-- drivers/crypto/marvell/octeontx/otx_cptvf_main.c | 4 ++-- drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/crypto/cavium/cpt/cptvf_main.c b/drivers/crypto/cavium/cpt/cptvf_main.c index 2c9a2af38876..6af2650b1ebe 100644 --- a/drivers/crypto/cavium/cpt/cptvf_main.c +++ b/drivers/crypto/cavium/cpt/cptvf_main.c @@ -835,8 +835,8 @@ static void cptvf_shutdown(struct pci_dev *pdev) /* Supported devices */ static const struct pci_device_id cptvf_id_table[] = { - {PCI_VDEVICE(CAVIUM, CPT_81XX_PCI_VF_DEVICE_ID), 0}, - { 0, } /* end of table */ + { PCI_VDEVICE(CAVIUM, CPT_81XX_PCI_VF_DEVICE_ID) }, + { } /* end of table */ }; static struct pci_driver cptvf_pci_driver = { diff --git a/drivers/crypto/cavium/nitrox/nitrox_main.c b/drivers/crypto/cavium/nitrox/nitrox_main.c index 8664d97261fe..e474c84d8d38 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_main.c +++ b/drivers/crypto/cavium/nitrox/nitrox_main.c @@ -38,9 +38,9 @@ static unsigned int num_devices; * nitrox_pci_tbl - PCI Device ID Table */ static const struct pci_device_id nitrox_pci_tbl[] = { - {PCI_VDEVICE(CAVIUM, CNN55XX_DEV_ID), 0}, + { PCI_VDEVICE(CAVIUM, CNN55XX_DEV_ID) }, /* required last entry */ - {0, } + { } }; MODULE_DEVICE_TABLE(pci, nitrox_pci_tbl); diff --git a/drivers/crypto/marvell/octeontx/otx_cptvf_main.c b/drivers/crypto/marvell/octeontx/otx_cptvf_main.c index 587609db6c69..5cc5c84069a9 100644 --- a/drivers/crypto/marvell/octeontx/otx_cptvf_main.c +++ b/drivers/crypto/marvell/octeontx/otx_cptvf_main.c @@ -957,8 +957,8 @@ static void otx_cptvf_remove(struct pci_dev *pdev) /* Supported devices */ static const struct pci_device_id otx_cptvf_id_table[] = { - {PCI_VDEVICE(CAVIUM, OTX_CPT_PCI_VF_DEVICE_ID), 0}, - { 0, } /* end of table */ + { PCI_VDEVICE(CAVIUM, OTX_CPT_PCI_VF_DEVICE_ID) }, + { } /* end of table */ }; static struct pci_driver otx_cptvf_pci_driver = { diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c b/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c index 858f851c9c8a..62b08116f808 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c @@ -460,9 +460,9 @@ static void otx2_cptvf_remove(struct pci_dev *pdev) /* Supported devices */ static const struct pci_device_id otx2_cptvf_id_table[] = { - {PCI_VDEVICE(CAVIUM, OTX2_CPT_PCI_VF_DEVICE_ID), 0}, - {PCI_VDEVICE(CAVIUM, CN10K_CPT_PCI_VF_DEVICE_ID), 0}, - { 0, } /* end of table */ + { PCI_VDEVICE(CAVIUM, OTX2_CPT_PCI_VF_DEVICE_ID) }, + { PCI_VDEVICE(CAVIUM, CN10K_CPT_PCI_VF_DEVICE_ID) }, + { } /* end of table */ }; static struct pci_driver otx2_cptvf_pci_driver = { From fb1758e74b8061aacfbce7bbb7a7cc650537e167 Mon Sep 17 00:00:00 2001 From: "Tycho Andersen (AMD)" Date: Mon, 4 May 2026 10:51:44 -0600 Subject: [PATCH 077/196] crypto: ccp - Do not initialize SNP for SEV ioctls Sashiko notes: > if SEV initialization fails and KVM is actively running normal VMs, could a > userspace process trigger this code path via /dev/sev ioctls (e.g., > SEV_PDH_GEN) and zero out MSR_VM_HSAVE_PA globally? Would the next VMRUN > execution for an active VM trigger a general protection fault and crash the > host? sev_move_to_init_state() is called for ioctls requiring only SEV firmware: SEV_PEK_GEN, SEV_PDH_GEN, SEV_PEK_CSR, SEV_PEK_CERT_IMPORT, and SEV_PDH_CERT_EXPORT. After the firmware command, it does SEV_SHUTDOWN on the SEV firmware. Since these commands do not require SNP to be initialized, skip it by calling __sev_platform_init_locked() which only initializes the SEV firmware. This way SNP is not Initialized at all, and HSAVE_PA is not cleared. The previous code saved any SEV initialization firmware error to init_args.error and then threw it away and hardcoded the return value of INVALID_PLATFORM_STATE regardless of the real firmware error. This patch changes it to surface the underlying error, which is hopefully both more useful and doesn't cause any problems. Note that it is still safe to call __sev_firmware_shutdown() directly: it calls __sev_snp_shutdown_locked(), which skips SNP shutdown if SNP was not initialized. Fixes: ceac7fb89e8d ("crypto: ccp - Ensure implicit SEV/SNP init and shutdown in ioctls") Reported-by: Sashiko Assisted-by: Gemini:gemini-3.1-pro-preview Link: https://sashiko.dev/#/patchset/20260324161301.1353976-1-tycho%40kernel.org CC: Signed-off-by: Tycho Andersen (AMD) Reviewed-by: Tom Lendacky Signed-off-by: Herbert Xu --- drivers/crypto/ccp/sev-dev.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index 8a85439cfa76..46c5d7ee7955 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -1719,14 +1719,11 @@ static int sev_get_platform_state(int *state, int *error) static int sev_move_to_init_state(struct sev_issue_cmd *argp, bool *shutdown_required) { - struct sev_platform_init_args init_args = {0}; int rc; - rc = _sev_platform_init_locked(&init_args); - if (rc) { - argp->error = SEV_RET_INVALID_PLATFORM_STATE; + rc = __sev_platform_init_locked(&argp->error); + if (rc) return rc; - } *shutdown_required = true; From 5a1364da2f04217a36e2fdfa2db4ee025b383a20 Mon Sep 17 00:00:00 2001 From: "Tycho Andersen (AMD)" Date: Mon, 4 May 2026 10:51:45 -0600 Subject: [PATCH 078/196] crypto: ccp - Do not initialize SNP for ioctl(SNP_COMMIT) Sashiko notes: > if SEV initialization fails and KVM is actively running normal VMs, could a > userspace process trigger this code path via /dev/sev ioctls (e.g., > SEV_PDH_GEN) and zero out MSR_VM_HSAVE_PA globally? Would the next VMRUN > execution for an active VM trigger a general protection fault and crash the > host? The SNP_COMMIT command does not require the firmware to be in any particular state. Skip initializing it if it was previously uninitialized. The SEV-SNP firmware specification doc 56860 does not mention SNP_COMMIT in Table 5 as a command that is allowed in the UNINIT state, but it is in fact allowed and a future documentation update will reflect that. Fixes: ceac7fb89e8d ("crypto: ccp - Ensure implicit SEV/SNP init and shutdown in ioctls") Reported-by: Sashiko Assisted-by: Gemini:gemini-3.1-pro-preview Link: https://sashiko.dev/#/patchset/20260324161301.1353976-1-tycho%40kernel.org CC: Signed-off-by: Tycho Andersen (AMD) Reviewed-by: Tom Lendacky Signed-off-by: Herbert Xu --- drivers/crypto/ccp/sev-dev.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index 46c5d7ee7955..de472f0503cb 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -2440,24 +2440,13 @@ cleanup: static int sev_ioctl_do_snp_commit(struct sev_issue_cmd *argp) { - struct sev_device *sev = psp_master->sev_data; struct sev_data_snp_commit buf; - bool shutdown_required = false; - int ret, error; - - if (!sev->snp_initialized) { - ret = snp_move_to_init_state(argp, &shutdown_required); - if (ret) - return ret; - } + int ret; buf.len = sizeof(buf); ret = __sev_do_cmd_locked(SEV_CMD_SNP_COMMIT, &buf, &argp->error); - if (shutdown_required) - __sev_snp_shutdown_locked(&error, false); - return ret; } From f91e9dbb5845d1e5abf1028e6df57dcf61583e1b Mon Sep 17 00:00:00 2001 From: "Tycho Andersen (AMD)" Date: Mon, 4 May 2026 10:51:46 -0600 Subject: [PATCH 079/196] crypto: ccp - Do not initialize SNP for ioctl(SNP_VLEK_LOAD) Sashiko notes: > if SEV initialization fails and KVM is actively running normal VMs, could a > userspace process trigger this code path via /dev/sev ioctls (e.g., > SEV_PDH_GEN) and zero out MSR_VM_HSAVE_PA globally? Would the next VMRUN > execution for an active VM trigger a general protection fault and crash the > host? The SEV firmware docs for SNP_VLEK_LOAD note: > On SNP_SHUTDOWN, the VLEK is deleted. That is, the initialization/shutdown wrapper here is pointless, because the firmware immediately throws away the key anyway. Instead, refuse to do anything if SNP has not been previously initialized. This is an ABI break: before, this was a no-op and almost certainly a mistake by userspace, and now it returns -ENODEV. ABI compatibility could be maintained here by simply returning 0 in the check instead. Fixes: ceac7fb89e8d ("crypto: ccp - Ensure implicit SEV/SNP init and shutdown in ioctls") Reported-by: Sashiko Assisted-by: Gemini:gemini-3.1-pro-preview Link: https://sashiko.dev/#/patchset/20260324161301.1353976-1-tycho%40kernel.org CC: Signed-off-by: Tycho Andersen (AMD) Reviewed-by: Tom Lendacky Signed-off-by: Herbert Xu --- drivers/crypto/ccp/sev-dev.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index de472f0503cb..9fb9267d7636 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -2484,9 +2484,8 @@ static int sev_ioctl_do_snp_vlek_load(struct sev_issue_cmd *argp, bool writable) { struct sev_device *sev = psp_master->sev_data; struct sev_user_data_snp_vlek_load input; - bool shutdown_required = false; - int ret, error; void *blob; + int ret; if (!argp->data) return -EINVAL; @@ -2494,6 +2493,9 @@ static int sev_ioctl_do_snp_vlek_load(struct sev_issue_cmd *argp, bool writable) if (!writable) return -EPERM; + if (!sev->snp_initialized) + return -ENODEV; + if (copy_from_user(&input, u64_to_user_ptr(argp->data), sizeof(input))) return -EFAULT; @@ -2507,18 +2509,7 @@ static int sev_ioctl_do_snp_vlek_load(struct sev_issue_cmd *argp, bool writable) input.vlek_wrapped_address = __psp_pa(blob); - if (!sev->snp_initialized) { - ret = snp_move_to_init_state(argp, &shutdown_required); - if (ret) - goto cleanup; - } - ret = __sev_do_cmd_locked(SEV_CMD_SNP_VLEK_LOAD, &input, &argp->error); - - if (shutdown_required) - __sev_snp_shutdown_locked(&error, false); - -cleanup: kfree(blob); return ret; From 08f0e65e784c4b20e6e620dd4f68d8636073a3d2 Mon Sep 17 00:00:00 2001 From: "Tycho Andersen (AMD)" Date: Mon, 4 May 2026 10:51:47 -0600 Subject: [PATCH 080/196] crypto: ccp - Do not initialize SNP for ioctl(SNP_CONFIG) Sashiko notes: > if SEV initialization fails and KVM is actively running normal VMs, could a > userspace process trigger this code path via /dev/sev ioctls (e.g., > SEV_PDH_GEN) and zero out MSR_VM_HSAVE_PA globally? Would the next VMRUN > execution for an active VM trigger a general protection fault and crash the > host? Refuse to re-try initialization if SNP is not already initialized for SNP_CONFIG. This is technically an ABI break: before if SNP initialization failed it could be transparently retriggered by this ioctl, and if no VMs were running, everything worked fine. Hopefully this is enough of a corner case that nobody will notice, but someone does, there are a few options: * do something like symbol_get() for kvm and refuse to initialize if KVM is loaded * check each cpu's HSAVE_PA for non-zero data before re-initializing * once initialization has failed, continue to refuse to initialize until the ccp module is unloaded Fixes: ceac7fb89e8d ("crypto: ccp - Ensure implicit SEV/SNP init and shutdown in ioctls") Reported-by: Sashiko Assisted-by: Gemini:gemini-3.1-pro-preview Link: https://sashiko.dev/#/patchset/20260324161301.1353976-1-tycho%40kernel.org CC: Signed-off-by: Tycho Andersen (AMD) Reviewed-by: Tom Lendacky Signed-off-by: Herbert Xu --- drivers/crypto/ccp/sev-dev.c | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index 9fb9267d7636..14df519ae7ee 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -1730,21 +1730,6 @@ static int sev_move_to_init_state(struct sev_issue_cmd *argp, bool *shutdown_req return 0; } -static int snp_move_to_init_state(struct sev_issue_cmd *argp, bool *shutdown_required) -{ - int error, rc; - - rc = __sev_snp_init_locked(&error, 0); - if (rc) { - argp->error = SEV_RET_INVALID_PLATFORM_STATE; - return rc; - } - - *shutdown_required = true; - - return 0; -} - static int sev_ioctl_do_reset(struct sev_issue_cmd *argp, bool writable) { int state, rc; @@ -2454,8 +2439,6 @@ static int sev_ioctl_do_snp_set_config(struct sev_issue_cmd *argp, bool writable { struct sev_device *sev = psp_master->sev_data; struct sev_user_data_snp_config config; - bool shutdown_required = false; - int ret, error; if (!argp->data) return -EINVAL; @@ -2463,21 +2446,13 @@ static int sev_ioctl_do_snp_set_config(struct sev_issue_cmd *argp, bool writable if (!writable) return -EPERM; + if (!sev->snp_initialized) + return -ENODEV; + if (copy_from_user(&config, (void __user *)argp->data, sizeof(config))) return -EFAULT; - if (!sev->snp_initialized) { - ret = snp_move_to_init_state(argp, &shutdown_required); - if (ret) - return ret; - } - - ret = __sev_do_cmd_locked(SEV_CMD_SNP_CONFIG, &config, &argp->error); - - if (shutdown_required) - __sev_snp_shutdown_locked(&error, false); - - return ret; + return __sev_do_cmd_locked(SEV_CMD_SNP_CONFIG, &config, &argp->error); } static int sev_ioctl_do_snp_vlek_load(struct sev_issue_cmd *argp, bool writable) From 49f73a9f00c9c825f28132855689ba50833a8157 Mon Sep 17 00:00:00 2001 From: Aleksander Jan Bajkowski Date: Mon, 4 May 2026 19:32:47 +0200 Subject: [PATCH 081/196] crypto: safexcel - Remove repeated plus Remove repeated "+". Signed-off-by: Aleksander Jan Bajkowski Reviewed-by: Antoine Tenart Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/safexcel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/inside-secure/safexcel.c b/drivers/crypto/inside-secure/safexcel.c index fb4936e7afa2..812ebabd1309 100644 --- a/drivers/crypto/inside-secure/safexcel.c +++ b/drivers/crypto/inside-secure/safexcel.c @@ -1475,7 +1475,7 @@ static int safexcel_probe_generic(void *pdev, peid = version & 255; /* Detect EIP206 processing pipe */ - version = readl(EIP197_PE(priv) + + EIP197_PE_VERSION(0)); + version = readl(EIP197_PE(priv) + EIP197_PE_VERSION(0)); if (EIP197_REG_LO16(version) != EIP206_VERSION_LE) { dev_err(priv->dev, "EIP%d: EIP206 not detected\n", peid); return -ENODEV; From ef8c9dacda2871accd64e3eda951fef6b788b1ea Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Mon, 4 May 2026 15:28:12 -0700 Subject: [PATCH 082/196] crypto: ccp - Treat zero-length cert chain as query for blob lengths When handling a PDH export, treat a zero-length userspace cert chain buffer as a request to query the length of the relevant blobs. Failure to account for the zero-length buffer trips a BUG_ON() when running with CONFIG_DEBUG_VIRTUAL=y due to trying to get the physical address of the ZERO_SIZE_PTR (returned by kzalloc() on the bogus allocation). kernel BUG at arch/x86/mm/physaddr.c:28 ! Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI CPU: 30 UID: 0 PID: 28580 Comm: syz.2.18 Kdump: loaded Tainted: G W 6.18.16-smp-DEV #1 NONE Tainted: [W]=WARN Hardware name: Google, Inc. Arcadia_IT_80/Arcadia_IT_80, BIOS 12.62.0-0 11/19/2025 RIP: 0010:__phys_addr+0x16a/0x180 arch/x86/mm/physaddr.c:28 RSP: 0018:ffffc9008329fc80 EFLAGS: 00010293 RAX: ffffffff8179110a RBX: 0000778000000010 RCX: ffff8884e6992600 RDX: 0000000000000000 RSI: 0000000080000010 RDI: 0000778000000010 RBP: ffffc9008329fdf0 R08: 0000000000000dc0 R09: 00000000ffffffff R10: dffffc0000000000 R11: fffffbfff126d297 R12: dffffc0000000000 R13: 1ffff92010653fc8 R14: 0000000080000010 R15: dffffc0000000000 FS: 0000555556bec9c0(0000) GS:ffff88aa4ce1c000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fd3159e7000 CR3: 00000004fbc44000 CR4: 0000000000350ef0 Call Trace: [] sev_ioctl_do_pdh_export+0x559/0x7a0 drivers/crypto/ccp/sev-dev.c:2308 [] sev_ioctl+0x2cd/0x480 drivers/crypto/ccp/sev-dev.c:2556 [] vfs_ioctl fs/ioctl.c:52 [inline] [] __do_sys_ioctl fs/ioctl.c:598 [inline] [] __se_sys_ioctl+0xfc/0x170 fs/ioctl.c:584 [] do_syscall_x64 arch/x86/entry/syscall_64.c:64 [inline] [] do_syscall_64+0x9f/0xf40 arch/x86/entry/syscall_64.c:98 [] entry_SYSCALL_64_after_hwframe+0x76/0x7e RIP: 0033:0x7fd3158eac39 Thankfully, the bug is benign outside of CONFIG_DEBUG_VIRTUAL=y as getting the physical address is just arithmetic, and the PSP errors out before trying to write to the garbage address (which it must, otherwise querying the blob lengths would clobber memory at pfn=0). Fixes: 76a2b524a4b1 ("crypto: ccp: Implement SEV_PDH_CERT_EXPORT ioctl command") Signed-off-by: Sean Christopherson Reviewed-by: Tom Lendacky Signed-off-by: Herbert Xu --- drivers/crypto/ccp/sev-dev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index 14df519ae7ee..068b901034cb 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -2286,7 +2286,8 @@ static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp, bool writable) /* Userspace wants to query the certificate length. */ if (!input.pdh_cert_address || !input.pdh_cert_len || - !input.cert_chain_address) + !input.cert_chain_address || + !input.cert_chain_len) goto cmd; /* Allocate a physically contiguous buffer to store the PDH blob. */ From ffdd2bc378953b525aca61902534e753f1f8e734 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 4 May 2026 15:53:28 -0700 Subject: [PATCH 083/196] crypto: af_alg - Remove zero-copy support from skcipher and aead The zero-copy support is one of the riskiest aspects of AF_ALG. It allows userspace to request cryptographic operations directly on pagecache pages of files like the 'su' binary. It also allows userspace to concurrently modify the memory which is being operated on, a recipe for TOCTOU vulnerabilities. While zero-copy support is more valuable in other areas of the kernel like the frequently used networking and file I/O code, it has far less value in AF_ALG, which is a niche UAPI. AF_ALG primarily just exists for backwards compatibility with a small set of userspace programs such as 'iwd' that haven't yet been fixed to use userspace crypto code. Originally AF_ALG was intended to be used to access hardware crypto accelerators. However, it isn't an efficient interface for that anyway, and it turned out to be rarely used in this way in practice. Thus, the risks of the zero-copy support in AF_ALG vastly outweigh its benefits. Let's just remove it. This commit removes it from the "skcipher" and "aead" algorithm types. "hash" will be handled separately. This is a soft break, not a hard break. Even after this commit, it still works to use splice() or sendfile() to transfer data to an AF_ALG request socket from a pipe or any file, respectively. What changes is just that the kernel now makes an internal, stable copy of the data before doing the crypto operation. So performance is slightly reduced, but the UAPI isn't broken. And, very importantly, it's much safer. Tested with libkcapi/test.sh. All its test cases still pass. I also verified that this would have prevented the copy.fail exploit as well. I also used a custom test program to verify that sendfile() still works. Fixes: 8ff590903d5f ("crypto: algif_skcipher - User-space interface for skcipher operations") Fixes: 400c40cf78da ("crypto: algif - add AEAD support") Reported-by: Taeyang Lee <0wn@theori.io> Link: https://copy.fail/ Reported-by: Feng Ning Closes: https://lore.kernel.org/r/afYcc-tZFwvZZo76@ans-MacBook-Pro.local Reviewed-by: Demi Marie Obenour Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- Documentation/crypto/userspace-if.rst | 31 ++---------- crypto/af_alg.c | 69 +++++++++------------------ crypto/algif_aead.c | 8 ++-- 3 files changed, 31 insertions(+), 77 deletions(-) diff --git a/Documentation/crypto/userspace-if.rst b/Documentation/crypto/userspace-if.rst index 2c4e9a1ac3e5..ea1b1b3f4049 100644 --- a/Documentation/crypto/userspace-if.rst +++ b/Documentation/crypto/userspace-if.rst @@ -369,33 +369,10 @@ CRYPTO_USER_API_RNG_CAVP option: Zero-Copy Interface ------------------- -In addition to the send/write/read/recv system call family, the AF_ALG -interface can be accessed with the zero-copy interface of -splice/vmsplice. As the name indicates, the kernel tries to avoid a copy -operation into kernel space. - -The zero-copy operation requires data to be aligned at the page -boundary. Non-aligned data can be used as well, but may require more -operations of the kernel which would defeat the speed gains obtained -from the zero-copy interface. - -The system-inherent limit for the size of one zero-copy operation is 16 -pages. If more data is to be sent to AF_ALG, user space must slice the -input into segments with a maximum size of 16 pages. - -Zero-copy can be used with the following code example (a complete -working example is provided with libkcapi): - -:: - - int pipes[2]; - - pipe(pipes); - /* input data in iov */ - vmsplice(pipes[1], iov, iovlen, SPLICE_F_GIFT); - /* opfd is the file descriptor returned from accept() system call */ - splice(pipes[0], NULL, opfd, NULL, ret, 0); - read(opfd, out, outlen); +AF_ALG used to have zero-copy support, but it was removed due to it being a +frequent source of vulnerabilities. For backwards compatibility the splice() +and sendfile() system calls are still supported, but the kernel will make an +internal copy of the data before passing it to the crypto code. Setsockopt Interface diff --git a/crypto/af_alg.c b/crypto/af_alg.c index 5a00c18eb145..fce0b87c2b65 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -973,7 +973,7 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size, ssize_t plen; /* use the existing memory in an allocated page */ - if (ctx->merge && !(msg->msg_flags & MSG_SPLICE_PAGES)) { + if (ctx->merge) { sgl = list_entry(ctx->tsgl_list.prev, struct af_alg_tsgl, list); sg = sgl->sg + sgl->cur - 1; @@ -1017,60 +1017,37 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size, if (sgl->cur) sg_unmark_end(sg + sgl->cur - 1); - if (msg->msg_flags & MSG_SPLICE_PAGES) { - struct sg_table sgtable = { - .sgl = sg, - .nents = sgl->cur, - .orig_nents = sgl->cur, - }; + do { + struct page *pg; + unsigned int i = sgl->cur; - plen = extract_iter_to_sg(&msg->msg_iter, len, &sgtable, - MAX_SGL_ENTS - sgl->cur, 0); - if (plen < 0) { - err = plen; + plen = min_t(size_t, len, PAGE_SIZE); + + pg = alloc_page(GFP_KERNEL); + if (!pg) { + err = -ENOMEM; goto unlock; } - for (; sgl->cur < sgtable.nents; sgl->cur++) - get_page(sg_page(&sg[sgl->cur])); + sg_assign_page(sg + i, pg); + + err = memcpy_from_msg(page_address(sg_page(sg + i)), + msg, plen); + if (err) { + __free_page(sg_page(sg + i)); + sg_assign_page(sg + i, NULL); + goto unlock; + } + + sg[i].length = plen; len -= plen; ctx->used += plen; copied += plen; size -= plen; - } else { - do { - struct page *pg; - unsigned int i = sgl->cur; + sgl->cur++; + } while (len && sgl->cur < MAX_SGL_ENTS); - plen = min_t(size_t, len, PAGE_SIZE); - - pg = alloc_page(GFP_KERNEL); - if (!pg) { - err = -ENOMEM; - goto unlock; - } - - sg_assign_page(sg + i, pg); - - err = memcpy_from_msg( - page_address(sg_page(sg + i)), - msg, plen); - if (err) { - __free_page(sg_page(sg + i)); - sg_assign_page(sg + i, NULL); - goto unlock; - } - - sg[i].length = plen; - len -= plen; - ctx->used += plen; - copied += plen; - size -= plen; - sgl->cur++; - } while (len && sgl->cur < MAX_SGL_ENTS); - - ctx->merge = plen & (PAGE_SIZE - 1); - } + ctx->merge = plen & (PAGE_SIZE - 1); if (!size) sg_mark_end(sg + sgl->cur - 1); diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c index cb651ab58d62..c6c2ce21895d 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c @@ -9,10 +9,10 @@ * The following concept of the memory management is used: * * The kernel maintains two SGLs, the TX SGL and the RX SGL. The TX SGL is - * filled by user space with the data submitted via sendmsg (maybe with - * MSG_SPLICE_PAGES). Filling up the TX SGL does not cause a crypto operation - * -- the data will only be tracked by the kernel. Upon receipt of one recvmsg - * call, the caller must provide a buffer which is tracked with the RX SGL. + * filled by user space with the data submitted via sendmsg. Filling up the TX + * SGL does not cause a crypto operation -- the data will only be tracked by the + * kernel. Upon receipt of one recvmsg call, the caller must provide a buffer + * which is tracked with the RX SGL. * * During the processing of the recvmsg operation, the cipher request is * allocated and prepared. As part of the recvmsg operation, the processed From e4c06479d7059888adf2f22bc1ebcf053bf691a2 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 5 May 2026 17:02:45 +0800 Subject: [PATCH 084/196] crypto: af_alg - Cap AEAD AD length to 0x80000000 In order to prevent arithmetic overflows when checking the TX buffer size, cap the associated data length to 0x80000000. Reported-by: Yiming Qian Fixes: 400c40cf78da ("crypto: algif - add AEAD support") Signed-off-by: Herbert Xu --- crypto/af_alg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crypto/af_alg.c b/crypto/af_alg.c index fce0b87c2b65..48c53f488e0f 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -584,6 +584,8 @@ static int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con) if (cmsg->cmsg_len < CMSG_LEN(sizeof(u32))) return -EINVAL; con->aead_assoclen = *(u32 *)CMSG_DATA(cmsg); + if (con->aead_assoclen >= 0x80000000u) + return -EINVAL; break; default: From 101f56451d0af2af9659cca009aeb14343dbd10c Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 5 May 2026 11:45:55 +0200 Subject: [PATCH 085/196] hwrng: core - drop unnecessary forward declarations The forward declarations for drop_current_rng() and rng_get_data() are not needed - remove them. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/char/hw_random/core.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index aba92d777f72..68add1a97f31 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -54,13 +54,9 @@ module_param(default_quality, ushort, 0644); MODULE_PARM_DESC(default_quality, "default maximum entropy content of hwrng per 1024 bits of input"); -static void drop_current_rng(void); static int hwrng_init(struct hwrng *rng); static int hwrng_fillfn(void *unused); -static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size, - int wait); - static size_t rng_buffer_size(void) { return RNG_BUFFER_SIZE; From 3541710791922e6ba090eb18f60b932f76c9b8cb Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 5 May 2026 11:45:56 +0200 Subject: [PATCH 086/196] hwrng: core - use bool for wait parameter in rng_get_data The wait parameter in rng_get_data() is a boolean flag - use bool instead of int to better reflect its actual type. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/char/hw_random/core.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 68add1a97f31..870e77c9ec20 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -210,8 +210,8 @@ static int rng_dev_open(struct inode *inode, struct file *filp) return 0; } -static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size, - int wait) { +static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size, bool wait) +{ int present; BUG_ON(!mutex_is_locked(&reading_mutex)); @@ -534,8 +534,7 @@ static int hwrng_fillfn(void *unused) } mutex_lock(&reading_mutex); - rc = rng_get_data(rng, rng_fillbuf, - rng_buffer_size(), 1); + rc = rng_get_data(rng, rng_fillbuf, rng_buffer_size(), true); if (current_quality != rng->quality) rng->quality = current_quality; /* obsolete */ quality = rng->quality; From dc3ec9af62a92a46378960e599521c2ac5f81343 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 5 May 2026 11:45:57 +0200 Subject: [PATCH 087/196] hwrng: core - use MAX to simplify RNG_BUFFER_SIZE Replace the open-coded variant with MAX(). Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/char/hw_random/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 870e77c9ec20..26c46cd90a83 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -30,7 +30,7 @@ #define RNG_MODULE_NAME "hw_random" -#define RNG_BUFFER_SIZE (SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES) +#define RNG_BUFFER_SIZE MAX(32, SMP_CACHE_BYTES) static struct hwrng __rcu *current_rng; /* the current rng has been explicitly chosen by user via sysfs */ From cdf940215537d6028177eea88e89bd8788719a99 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 5 May 2026 11:45:58 +0200 Subject: [PATCH 088/196] hwrng: core - use sysfs_emit_at in rng_available_show Replace strlcat() with sysfs_emit_at() in rng_available_show() and add 'int len' to keep track of the number of bytes written. sysfs_emit_at() is preferred for formatting sysfs output because it provides safer bounds checking. Inline mutex_lock_interruptible() and drop the now-unused local error variable. Remove the unnecessary 'buf' NUL initialization. Return 'len' directly instead of strlen(buf). Reviewed-by: Andy Shevchenko Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/char/hw_random/core.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 26c46cd90a83..6931657ad2ca 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -414,21 +415,17 @@ static ssize_t rng_available_show(struct device *dev, struct device_attribute *attr, char *buf) { - int err; struct hwrng *rng; + int len = 0; - err = mutex_lock_interruptible(&rng_mutex); - if (err) + if (mutex_lock_interruptible(&rng_mutex)) return -ERESTARTSYS; - buf[0] = '\0'; - list_for_each_entry(rng, &rng_list, list) { - strlcat(buf, rng->name, PAGE_SIZE); - strlcat(buf, " ", PAGE_SIZE); - } - strlcat(buf, "none\n", PAGE_SIZE); + list_for_each_entry(rng, &rng_list, list) + len += sysfs_emit_at(buf, len, "%s ", rng->name); + len += sysfs_emit_at(buf, len, "none\n"); mutex_unlock(&rng_mutex); - return strlen(buf); + return len; } static ssize_t rng_selected_show(struct device *dev, From 81d7e2979e371e5f359a544b53f38601f5150470 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 5 May 2026 12:29:49 +0200 Subject: [PATCH 089/196] crypto: drivers - Move MODULE_DEVICE_TABLE next to the table itself By convention MODULE_DEVICE_TABLE() immediately follows the ID table it exports, because this is easier to read and verify. It also makes more sense since #ifdef for ACPI or OF could hide both of them. Most of the privers already have this correctly placed, so adjust the missing ones. No functional impact. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- drivers/crypto/cavium/cpt/cptpf_main.c | 2 +- drivers/crypto/cavium/cpt/cptvf_main.c | 2 +- drivers/crypto/marvell/octeontx/otx_cptpf_main.c | 2 +- drivers/crypto/marvell/octeontx/otx_cptvf_main.c | 2 +- drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c | 2 +- drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/cavium/cpt/cptpf_main.c b/drivers/crypto/cavium/cpt/cptpf_main.c index 54de869e5374..9358c1c041d4 100644 --- a/drivers/crypto/cavium/cpt/cptpf_main.c +++ b/drivers/crypto/cavium/cpt/cptpf_main.c @@ -651,6 +651,7 @@ static const struct pci_device_id cpt_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, CPT_81XX_PCI_PF_DEVICE_ID) }, { 0, } /* end of table */ }; +MODULE_DEVICE_TABLE(pci, cpt_id_table); static struct pci_driver cpt_pci_driver = { .name = DRV_NAME, @@ -666,4 +667,3 @@ MODULE_AUTHOR("George Cherian "); MODULE_DESCRIPTION("Cavium Thunder CPT Physical Function Driver"); MODULE_LICENSE("GPL v2"); MODULE_VERSION(DRV_VERSION); -MODULE_DEVICE_TABLE(pci, cpt_id_table); diff --git a/drivers/crypto/cavium/cpt/cptvf_main.c b/drivers/crypto/cavium/cpt/cptvf_main.c index 6af2650b1ebe..db76df14c4a0 100644 --- a/drivers/crypto/cavium/cpt/cptvf_main.c +++ b/drivers/crypto/cavium/cpt/cptvf_main.c @@ -838,6 +838,7 @@ static const struct pci_device_id cptvf_id_table[] = { { PCI_VDEVICE(CAVIUM, CPT_81XX_PCI_VF_DEVICE_ID) }, { } /* end of table */ }; +MODULE_DEVICE_TABLE(pci, cptvf_id_table); static struct pci_driver cptvf_pci_driver = { .name = DRV_NAME, @@ -853,4 +854,3 @@ MODULE_AUTHOR("George Cherian "); MODULE_DESCRIPTION("Cavium Thunder CPT Virtual Function Driver"); MODULE_LICENSE("GPL v2"); MODULE_VERSION(DRV_VERSION); -MODULE_DEVICE_TABLE(pci, cptvf_id_table); diff --git a/drivers/crypto/marvell/octeontx/otx_cptpf_main.c b/drivers/crypto/marvell/octeontx/otx_cptpf_main.c index 14a42559f81d..e4c828606a73 100644 --- a/drivers/crypto/marvell/octeontx/otx_cptpf_main.c +++ b/drivers/crypto/marvell/octeontx/otx_cptpf_main.c @@ -283,6 +283,7 @@ static const struct pci_device_id otx_cpt_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OTX_CPT_PCI_PF_DEVICE_ID) }, { 0, } /* end of table */ }; +MODULE_DEVICE_TABLE(pci, otx_cpt_id_table); static struct pci_driver otx_cpt_pci_driver = { .name = DRV_NAME, @@ -298,4 +299,3 @@ MODULE_AUTHOR("Marvell International Ltd."); MODULE_DESCRIPTION("Marvell OcteonTX CPT Physical Function Driver"); MODULE_LICENSE("GPL v2"); MODULE_VERSION(DRV_VERSION); -MODULE_DEVICE_TABLE(pci, otx_cpt_id_table); diff --git a/drivers/crypto/marvell/octeontx/otx_cptvf_main.c b/drivers/crypto/marvell/octeontx/otx_cptvf_main.c index 5cc5c84069a9..159c1d290a36 100644 --- a/drivers/crypto/marvell/octeontx/otx_cptvf_main.c +++ b/drivers/crypto/marvell/octeontx/otx_cptvf_main.c @@ -960,6 +960,7 @@ static const struct pci_device_id otx_cptvf_id_table[] = { { PCI_VDEVICE(CAVIUM, OTX_CPT_PCI_VF_DEVICE_ID) }, { } /* end of table */ }; +MODULE_DEVICE_TABLE(pci, otx_cptvf_id_table); static struct pci_driver otx_cptvf_pci_driver = { .name = DRV_NAME, @@ -974,4 +975,3 @@ MODULE_AUTHOR("Marvell International Ltd."); MODULE_DESCRIPTION("Marvell OcteonTX CPT Virtual Function Driver"); MODULE_LICENSE("GPL v2"); MODULE_VERSION(DRV_VERSION); -MODULE_DEVICE_TABLE(pci, otx_cptvf_id_table); diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c b/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c index 346d1345f11c..f6f47f4e5d83 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c @@ -867,6 +867,7 @@ static const struct pci_device_id otx2_cpt_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, CN10K_CPT_PCI_PF_DEVICE_ID) }, { 0, } /* end of table */ }; +MODULE_DEVICE_TABLE(pci, otx2_cpt_id_table); static struct pci_driver otx2_cpt_pci_driver = { .name = OTX2_CPT_DRV_NAME, @@ -883,4 +884,3 @@ MODULE_IMPORT_NS("CRYPTO_DEV_OCTEONTX2_CPT"); MODULE_AUTHOR("Marvell"); MODULE_DESCRIPTION(OTX2_CPT_DRV_STRING); MODULE_LICENSE("GPL v2"); -MODULE_DEVICE_TABLE(pci, otx2_cpt_id_table); diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c b/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c index 62b08116f808..09ab85e6061c 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c @@ -464,6 +464,7 @@ static const struct pci_device_id otx2_cptvf_id_table[] = { { PCI_VDEVICE(CAVIUM, CN10K_CPT_PCI_VF_DEVICE_ID) }, { } /* end of table */ }; +MODULE_DEVICE_TABLE(pci, otx2_cptvf_id_table); static struct pci_driver otx2_cptvf_pci_driver = { .name = OTX2_CPTVF_DRV_NAME, @@ -479,4 +480,3 @@ MODULE_IMPORT_NS("CRYPTO_DEV_OCTEONTX2_CPT"); MODULE_AUTHOR("Marvell"); MODULE_DESCRIPTION("Marvell RVU CPT Virtual Function Driver"); MODULE_LICENSE("GPL v2"); -MODULE_DEVICE_TABLE(pci, otx2_cptvf_id_table); From 97b376ac3c23cf7f64c38d04653b40a93414b94b Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Tue, 5 May 2026 17:02:17 -0700 Subject: [PATCH 090/196] crypto: drbg - Rename MAX_ADDTL => MAX_ADDTL_BYTES Give this constant a name which is clearer and consistent with DRBG_MAX_REQUEST_BYTES. No functional change. Suggested-by: Joachim Vandersmissen Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index ad7b9577479e..ab443be199a0 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -122,7 +122,7 @@ * so that the value never quite completely fills the range of a size_t, * allowing the health check to verify that larger values are rejected. */ -#define DRBG_MAX_ADDTL (U32_MAX - 1) +#define DRBG_MAX_ADDTL_BYTES (U32_MAX - 1) struct drbg_state { struct mutex drbg_mutex; /* lock around DRBG */ @@ -237,7 +237,7 @@ static int drbg_seed(struct drbg_state *drbg, const u8 *pers, size_t pers_len, const u8 *entropy; /* 9.1 / 9.2 / 9.3.1 step 3 */ - if (pers_len > DRBG_MAX_ADDTL) { + if (pers_len > DRBG_MAX_ADDTL_BYTES) { pr_devel("DRBG: personalization string too long %zu\n", pers_len); return -EINVAL; @@ -355,7 +355,7 @@ static int drbg_generate(struct drbg_state *drbg, u8 *out, size_t outlen, /* 9.3.1 step 3 is implicit with the chosen DRBG */ /* 9.3.1 step 4 */ - if (addtl_len > DRBG_MAX_ADDTL) { + if (addtl_len > DRBG_MAX_ADDTL_BYTES) { pr_devel("DRBG: additional information string too long %zu\n", addtl_len); return -EINVAL; @@ -570,14 +570,15 @@ static inline int __init drbg_healthcheck_sanity(void) */ /* overflow addtllen with additional info string */ - ret = drbg_generate(drbg, buf, OUTBUFLEN, buf, DRBG_MAX_ADDTL + 1); + ret = drbg_generate(drbg, buf, OUTBUFLEN, buf, + DRBG_MAX_ADDTL_BYTES + 1); BUG_ON(ret == 0); /* overflow max_bits */ ret = drbg_generate(drbg, buf, DRBG_MAX_REQUEST_BYTES + 1, NULL, 0); BUG_ON(ret == 0); /* overflow max addtllen with personalization string */ - ret = drbg_seed(drbg, buf, DRBG_MAX_ADDTL + 1, false); + ret = drbg_seed(drbg, buf, DRBG_MAX_ADDTL_BYTES + 1, false); BUG_ON(ret == 0); /* all tests passed */ From bd13e630f9d03510012f1a530f08e9cf533e946a Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Tue, 5 May 2026 17:02:58 -0700 Subject: [PATCH 091/196] crypto: drbg - Remove support for "prediction resistance" "Prediction resistance", i.e. the property that the RNG's output is unpredictable even after a state compromise, might sound like a nice property to have. In reality, it's not very practical, as it requires that fresh entropy be pulled on every request. (The normal Linux RNG doesn't provide prediction resistance.) In the case of drbg.c, that means pulling from "jitterentropy", which is extremely slow. For some perspective, running a simple benchmark, generating 32 random bytes takes the following amount of time: get_random_bytes(): 90 ns drbg_nopr_hmac_sha512: 3707 ns drbg_pr_hmac_sha512: 773082 ns So at least in this case, the "pr" (prediction-resistant) DRBG is over 200 times slower than the "nopr" (non-prediction-resistant) DRBG, or over 8000 times slower than the normal Linux RNG. While anyone using drbg.c has always had to tolerate that it's slower than the normal Linux RNG, the "pr" DRBG is clearly at another level of slowness. Thus, the following is also entirely unsurprising: - FIPS 140-3 doesn't actually require that SP800-90A DRBG implementations support prediction resistance. The non-prediction resistant DRBGs can be, and have been, certified. - drbg.c registers "drbg_nopr_hmac_sha512" with a higher cra_priority than "drbg_pr_hmac_sha512". So "drbg_nopr_hmac_sha512" is already the one actually being used in practice. Given these considerations, it's clear that "drbg_pr_hmac_sha512" isn't actually useful, and it essentially just existed as another curiosity in the museum of crypto algorithms. Remove it to simplify the code. Suggested-by: Joachim Vandersmissen Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/drbg.c | 82 ++++++------------- crypto/testmgr.c | 21 +---- crypto/testmgr.h | 202 ----------------------------------------------- 3 files changed, 27 insertions(+), 278 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index ab443be199a0..d66c7211d6bb 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -1,7 +1,6 @@ /* * DRBG: Deterministic Random Bits Generator - * Implementation of the HMAC SHA-512 DRBG from NIST SP800-90A, - * both with and without prediction resistance + * Implementation of the HMAC SHA-512 DRBG from NIST SP800-90A * * Copyright Stephan Mueller , 2014 * Copyright 2026 Google LLC @@ -131,7 +130,6 @@ struct drbg_state { /* Number of RNG requests since last reseed -- 10.1.2.1 1c */ size_t reseed_ctr; bool instantiated; - bool pr; /* Prediction resistance enabled? */ struct crypto_rng *jent; const u8 *test_entropy; size_t test_entropylen; @@ -370,9 +368,8 @@ static int drbg_generate(struct drbg_state *drbg, u8 *out, size_t outlen, * drbg_seed() then too, since drbg_hmac_generate() adds bytes from * random.c to the additional input, which is a de facto reseed anyway. */ - if (drbg->pr || drbg->reseed_ctr > DRBG_MAX_REQUESTS) { - pr_devel("DRBG: reseeding before generation (prediction resistance: %s)\n", - str_true_false(drbg->pr)); + if (drbg->reseed_ctr > DRBG_MAX_REQUESTS) { + pr_devel("DRBG: reseeding before generation\n"); /* 9.3.1 steps 7.1 through 7.3 */ err = drbg_seed(drbg, addtl, addtl_len, true); if (err) @@ -431,14 +428,13 @@ static void drbg_kcapi_set_entropy(struct crypto_rng *tfm, /* Seed (i.e. instantiate) or re-seed the DRBG. */ static int drbg_kcapi_seed(struct crypto_rng *tfm, - const u8 *pers, size_t pers_len, bool pr) + const u8 *pers, unsigned int pers_len) { static const u8 initial_key[DRBG_STATE_LEN]; /* all zeroes */ struct drbg_state *drbg = crypto_rng_ctx(tfm); int ret; - pr_devel("DRBG: Initializing DRBG with prediction resistance %s\n", - str_enabled_disabled(pr)); + pr_devel("DRBG: Initializing DRBG\n"); guard(mutex)(&drbg->drbg_mutex); if (drbg->instantiated) @@ -447,13 +443,12 @@ static int drbg_kcapi_seed(struct crypto_rng *tfm, /* 9.1 step 1 is implicit with the selected DRBG type */ /* - * 9.1 step 2 is implicit as caller can select prediction resistance - * all DRBG types support prediction resistance + * 9.1 step 2 is implicit, as this implementation doesn't support + * prediction resistance */ /* 9.1 step 4 is implicit in DRBG_SEC_STRENGTH */ - drbg->pr = pr; memset(drbg->V, 1, DRBG_STATE_LEN); hmac_sha512_preparekey(&drbg->key, initial_key, DRBG_STATE_LEN); @@ -479,18 +474,6 @@ static int drbg_kcapi_seed(struct crypto_rng *tfm, return 0; } -static int drbg_kcapi_seed_pr(struct crypto_rng *tfm, - const u8 *seed, unsigned int slen) -{ - return drbg_kcapi_seed(tfm, seed, slen, /* pr= */ true); -} - -static int drbg_kcapi_seed_nopr(struct crypto_rng *tfm, - const u8 *seed, unsigned int slen) -{ - return drbg_kcapi_seed(tfm, seed, slen, /* pr= */ false); -} - /* * Generate random numbers invoked by the kernel crypto API: * @@ -589,31 +572,17 @@ static inline int __init drbg_healthcheck_sanity(void) return 0; } -static struct rng_alg drbg_algs[] = { - { - .base.cra_name = "stdrng", - .base.cra_driver_name = "drbg_pr_hmac_sha512", - .base.cra_priority = 200, - .base.cra_ctxsize = sizeof(struct drbg_state), - .base.cra_module = THIS_MODULE, - .base.cra_init = drbg_kcapi_init, - .set_ent = drbg_kcapi_set_entropy, - .seed = drbg_kcapi_seed_pr, - .generate = drbg_kcapi_generate, - .base.cra_exit = drbg_kcapi_exit, - }, - { - .base.cra_name = "stdrng", - .base.cra_driver_name = "drbg_nopr_hmac_sha512", - .base.cra_priority = 201, - .base.cra_ctxsize = sizeof(struct drbg_state), - .base.cra_module = THIS_MODULE, - .base.cra_init = drbg_kcapi_init, - .set_ent = drbg_kcapi_set_entropy, - .seed = drbg_kcapi_seed_nopr, - .generate = drbg_kcapi_generate, - .base.cra_exit = drbg_kcapi_exit, - }, +static struct rng_alg drbg_alg = { + .base.cra_name = "stdrng", + .base.cra_driver_name = "drbg_nopr_hmac_sha512", + .base.cra_priority = 201, + .base.cra_ctxsize = sizeof(struct drbg_state), + .base.cra_module = THIS_MODULE, + .base.cra_init = drbg_kcapi_init, + .set_ent = drbg_kcapi_set_entropy, + .seed = drbg_kcapi_seed, + .generate = drbg_kcapi_generate, + .base.cra_exit = drbg_kcapi_exit, }; static int __init drbg_init(void) @@ -625,20 +594,18 @@ static int __init drbg_init(void) return ret; /* - * In FIPS mode, boost the algorithm priorities to ensure that when - * users request "stdrng", they really get an algorithm from here. + * In FIPS mode, boost the algorithm priority to ensure that when users + * request "stdrng", they really get the algorithm from here. */ - if (fips_enabled) { - for (size_t i = 0; i < ARRAY_SIZE(drbg_algs); i++) - drbg_algs[i].base.cra_priority += 2000; - } + if (fips_enabled) + drbg_alg.base.cra_priority += 2000; - return crypto_register_rngs(drbg_algs, ARRAY_SIZE(drbg_algs)); + return crypto_register_rng(&drbg_alg); } static void __exit drbg_exit(void) { - crypto_unregister_rngs(drbg_algs, ARRAY_SIZE(drbg_algs)); + crypto_unregister_rng(&drbg_alg); } module_init(drbg_init); @@ -647,5 +614,4 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Stephan Mueller "); MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG)"); MODULE_ALIAS_CRYPTO("stdrng"); -MODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha512"); MODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha512"); diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 9059bea7a5b0..a3e80de91d4d 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -3481,8 +3481,8 @@ static int alg_test_comp(const struct alg_test_desc *desc, const char *driver, return err; } -static int drbg_cavs_test(const struct drbg_testvec *test, int pr, - const char *driver, u32 type, u32 mask) +static int drbg_cavs_test(const struct drbg_testvec *test, const char *driver, + u32 type, u32 mask) { int ret = -EAGAIN; struct crypto_rng *drng; @@ -3519,8 +3519,6 @@ static int drbg_cavs_test(const struct drbg_testvec *test, int pr, } } - if (pr) - crypto_rng_set_entropy(drng, test->entpra, test->entprlen); ret = crypto_rng_generate(drng, test->addtla, test->addtllen, buf, test->expectedlen); if (ret < 0) { @@ -3529,8 +3527,6 @@ static int drbg_cavs_test(const struct drbg_testvec *test, int pr, goto outbuf; } - if (pr) - crypto_rng_set_entropy(drng, test->entprb, test->entprlen); ret = crypto_rng_generate(drng, test->addtlb, test->addtllen, buf, test->expectedlen); if (ret < 0) { @@ -3552,16 +3548,12 @@ static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver, u32 type, u32 mask) { int err = 0; - int pr = 0; int i = 0; const struct drbg_testvec *template = desc->suite.drbg.vecs; unsigned int tcount = desc->suite.drbg.count; - if (0 == memcmp(driver, "drbg_pr_", 8)) - pr = 1; - for (i = 0; i < tcount; i++) { - err = drbg_cavs_test(&template[i], pr, driver, type, mask); + err = drbg_cavs_test(&template[i], driver, type, mask); if (err) { printk(KERN_ERR "alg: drbg: Test %d failed for %s\n", i, driver); @@ -4656,13 +4648,6 @@ static const struct alg_test_desc alg_test_descs[] = { .suite = { .drbg = __VECS(drbg_nopr_hmac_sha512_tv_template) } - }, { - .alg = "drbg_pr_hmac_sha512", - .test = alg_test_drbg, - .fips_allowed = 1, - .suite = { - .drbg = __VECS(drbg_pr_hmac_sha512_tv_template) - } }, { .alg = "ecb(aes)", .generic_driver = "ecb(aes-lib)", diff --git a/crypto/testmgr.h b/crypto/testmgr.h index c47203f73fd1..b7dcf40af6db 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -133,9 +133,6 @@ struct drbg_testvec { size_t addtl_reseed_len; /* Generate (twice) */ - const unsigned char *entpra; - const unsigned char *entprb; - size_t entprlen; const unsigned char *addtla; const unsigned char *addtlb; size_t addtllen; @@ -23433,205 +23430,6 @@ static const struct aead_testvec aegis128_tv_template[] = { }, }; -static const struct drbg_testvec drbg_pr_hmac_sha512_tv_template[] = { - /* - * Borrowed from the first applicable test vector from ACVP: - * https://github.com/usnistgov/ACVP-Server/blob/v1.1.0.33/gen-val/json-files/hmacDRBG-1.0/prompt.json#L1161 - * https://github.com/usnistgov/ACVP-Server/blob/v1.1.0.33/gen-val/json-files/hmacDRBG-1.0/expectedResults.json#L271 - */ - { - /* .entropy = ACVP entropyInput || nonce */ - .entropy = "\x9B\xE9\xB2\x87\xA3\x9A\x08\x44\x1D\x67\x82\x20" - "\xC9\x53\xFB\xEB\xA4\xB9\x0F\x44\x0B\x98\x33\x18" - "\xAC\x6E\x25\x4A\x85\x83\x2D\x26\x21\x9F\x93\x64" - "\xC8\x5A\x5F\x72\xDB\x88\x45\x96\x71\x41\xF4\xBF" - "\x6E\xA7\x98\x00\x9D\xD1\x0C\x2E\x4D\x7A\xE2\x03" - "\x0D\xE3\xCD\x62\xFE\xF3\x62\xBD\x12\x69\x92\x3D" - "\xBA\xAC\x15\x17\xC7\x80\x93\x8E\x72\x32\x2D\x52" - "\xE5\x2C\x19\x84\x5C\xA5\xCE\x5B\x98\x19\x1F\xF1" - "\x9F\x0C\x17\x04\xD0\x66\xF1\x9B\xFA\x7E\x2C\xB6" - "\x55\x68\xD4\x1B\xD6\x7A\x1D\x2C\xD4\x6D\x6E\x15" - "\xF7\x32\x23\x04\x05\x8C\xBB\xE6\x63\x6B\x80\x9B" - "\x9C\x69\x09\x8F\x5F\x02\xBF\x53\x42\x11\xB7\x80" - "\xAA\xD4\xE8\x54\x00\x83\x5C\x20\xA8\xB3\x6E\xD9" - "\xF5\x51\x9E\xB9\xD1\x6E\xC7\x0C\xE9\x7F\xF0\xBF" - "\xCE\x1D\xB0\x31\x8D\x16\xC9\x65\x0C\x18\x55\xA4" - "\x46\x8D\x54\x2B\x78\x69\x1B\x8C\x29\xD7\xAC\x0F" - "\x34\x4D\x69\x0B\x76\xC3\x98\x00\x78\x2F\xE2\x54" - "\xAF\xD5\x8A\xC3\x40\x97\xB1\xA2\x60\xD3\x07\x3B" - "\x7A\x3E\xD0\x82\x80\x68\xEE\xB0\x72\x5F\x07\x17" - "\xD9\x0A\xFC\xBD\xBA\xB6\x77\x4E\xC9\xCE\x6A\x48" - "\xEB\x9C\xF5\x18\x88\x1E\x6E\x3B\x65\x43\x16\x73" - "\x80\x53\xB7\xF0\x7E\xAB\x23\x19\x1E\x75\x60\x36" - "\xAF\x39\xC0\xCF\x0F\x6D\x7F\x90\xB2\x50\xD5\x37" - "\x58\x6D\x5C\x95\x78\x25\x8D\x3A\x40\xAB\xF6\x7B" - "\x85\x86\xBB\x48\x5E\x1C\x99\xC1\xD3\x4E\x85\xE5" - "\xB4\xE7\x61\xF3\x7D\x56\x1F\x77\xCF\x3C\x76\x3A" - "\xF4\x82\x36\xB7\x37\x33\x84\x34\xBA\x0E\xE2\xE1" - "\xAF\x0C\xD2\xAE\x97\x5C\x80\xD4\xD2\xFD\x37\x71" - "\xC8\x70\x04\x29\x8B\x44\xB9\xD7\xC9\x8F\xE7\x99" - "\x94\x9E\xFC\x49\x66\x24\xCB\x8B\x41\x40\x66\xC5" - "\xA4\x00\xD5\x3F\x68\xDD\xB5\xA5\x62\x96\x7C\xAC" - "\x63\x58\x95\x85\x99\x24\x21\x15\xD2\x76\xAF\x6D", - .entropylen = 384, - .pers = "\xDD\x07\x10\x10\x17\x34\xD5\xBD\x43\xAF\x03\x79\xE4" - "\x64\x2C\x58\x06\xEA\xE0\x39\xDA\x42\x96\x16\x0B\xF9" - "\xB8\xCE\x57\x7D\x53\x67\xBF\xF8\x0C\x40\x02\xB2\x77" - "\x16\xD5\x23\x75\x9F\x6A\x42\x0E\xE8\xCC\xD0\x9F\x40" - "\x64\xE9\x3B\xE9\x48\x13\xC3\x8E\x4B\xAB\xE1\xB9\x4F" - "\x6D\xBB\xF2\x4C\xF8\x29\xA5\x2B\x44\x23\x15\x2C\xDE" - "\x2A\xCF\x88\x04\x7A\x38\x37\xA2\xD5\x7B\xEA\x59\x39" - "\x2C\x58\xA2\x5B\xF9\x39\xA2\x7E\x94\x11\x97\xEC\x47" - "\x08\xD6\xE2\x39\x65\x26\x43\x81\x3F\x1B\x31\xA6\xA4" - "\x1A\x5C\xCD\x02\xCC\x89\x38\x3F\x32\x7C\x0E\x7E\x88" - "\x3B\x6F\x60\x69\xEA\xBA\xAA\x1F\x53\x93\x70\xD7\x48" - "\x74\x91\x79\x5E\xD4\xB0\xD9\x82\x74\x12\xDE\xFE\xFB" - "\x51\x96\x66\x5C\x6A\x53\x11\xAD\x9A\xD4\xFA\x9D\xF0" - "\xE2\x7F\x26\x8F\x6F\xAC\x00\xC8\xDB\xCF\xA5\x8E\xE6" - "\x61\x8F\x36\xD6\x44\x5B\x07\xDA\x9C\x2A\x46\xE3\x03" - "\x1C\xD8\x11\x4F\x61\x1F\xEC\xBA\x12\x68\xB9\x4B\x57" - "\x39\x05\xD6\xEE\xC1\xAC\x3F\x6D\x6F\xE9\xBF\xEA\x36" - "\x1A\x8A\xAA\xF4\xE8\xE0\xDB\xC6\xE5\x06\x9F\xC9\x91" - "\x52\xCD\x53\xD0\x78\xF6\xC1\x7B\x75\x91\x85\x91\x13" - "\x26\xBE\xC9\x02\xDE\xB0\x19\xF2\x71", - .perslen = 256, - - .entpra = "\xDB\xBA\x25\xC7\x02\x0D\x3D\x95\x9C\xEB\xF5\x42" - "\x52\x3A\x6B\xDA\xE8\xAF\xE9\x3D\x76\x2A\x9E\xB5" - "\xD7\xE7\x5D\xC9\xB8\x1F\x3A\xC2\x91\x95\x9D\xFD" - "\xE5\x48\x5F\x63\xD8\x84\x44\x82\x6A\x71\xF9\xDD" - "\xAF\x4B\xE2\x28\xB4\x30\xCF\x78\xB7\x0B\x0F\x61" - "\x71\x16\x1A\xE0\x6D\x5F\xB4\x4B\x17\x1A\x26\xCA" - "\xD8\x9D\x6D\x46\xA3\x56\xC0\xE7\x49\xCF\xE0\xD2" - "\xFF\xA8\x22\x45\xE0\xB4\x18\x0B\x13\x37\x01\x46" - "\xCB\xE7\xD8\x2A\x59\x43\xAD\x90\x1E\xE1\xD0\xD7" - "\x76\xB0\x2D\xCF\x17\x23\x99\x73\x5D\xE5\xC7\x46" - "\x8A\x0D\x8E\xC4\xAB\x45\xAC\xA8\x74\xE4\xF7\xD0" - "\x26\xD7\x0A\xE2\x43\x3D\xB8\xC7\xEE\xAD\x53\x6F" - "\x78\xC3\x51\xC0\xE0\x76\x2A\xC2\xB7\xFE\x02\x64" - "\x25\xF0\xCE\xD7\xA9\xBF\x85\xCA\x20\xA6\x93\x68" - "\xE3\x79\xE9\x88\xA8\x7F\x45\x8D\x71\xB4\xB4\x79" - "\x1C\x56\x68\xF9\xAE\x18\x76\xB9\x3F\xEE\x5B\x2C" - "\xC6\x61\x47\x34\x3B\xC5\x24\x2D\x3C\x6D\x16\x48" - "\x70\xD9\xDB\x2E\xB8\x42\x52\x81\x1C\x94\x39\xF0" - "\xF4\xC0\x8F\x44\xD3\xCF\xD5\xF9\xC1\x59\x61\x83" - "\xAE\xFD\xD0\xC4\x35\xD1\x0E\x55\x46\x5C\xBA\x3D" - "\x5C\x4A\x89\x15\xE8\x1D\x86\x28\xE5\xF5\x31\x0B" - "\x89\x59\xFE\x4A\xC3\x5D\xA5\x2A\x16\x37\x78\x41" - "\x58\x3A\x9E\xA3\xBD\x1F\xE6\x25\xCC\x18\x9E\xD2" - "\x1A\x99\x56\x66\x83\x78\xBB\x27\x3E\x28\xFE\xD4" - "\x74\xCB\x75\x2D\x82\x86\x55\xFB\x1C\xA4\xAF\x3F" - "\x84\x0A\xA0\xA1\x1C\x70\x34\x87\x2E\x73\x15\x38" - "\x8A\x27\xB1\x6C\x33\x95\xE5\x07", - .entprb = "\x38\xF2\xC4\x8F\x4B\x9C\x2F\x03\x67\x8C\x8A\x47" - "\xE1\xF2\x18\xC5\xB8\x4C\x05\x77\x77\x15\xA8\x94" - "\x1F\x1F\x45\x6D\xD0\xEF\x60\x67\x63\x12\x5D\x38" - "\x89\x22\x76\xF5\xF2\xC4\xE1\x15\x26\x7E\x8F\x52" - "\x79\x1E\x96\x71\xCD\xE7\x32\x95\x2B\x4E\xB2\xC2" - "\x92\x21\xC7\x48\xA2\xB1\xC5\x71\x44\x91\xE4\x4F" - "\xBE\xD3\x5E\xA9\xAB\xD3\xE2\xD1\xE2\xD8\x8F\x98" - "\x38\x03\x18\x29\x84\xA2\xCA\x6E\x72\x34\xC9\x51" - "\x6D\x8C\xE8\x09\x50\x71\x2A\x08\xB7\xCF\x74\xE6" - "\x11\xB6\x38\xF5\xBC\x24\xF7\x5B\x73\x34\xD5\x8B" - "\xBB\x15\xE3\x6F\x9A\x9B\x1E\x32\xB9\x6F\x5F\xE3" - "\xC9\x9F\xF6\xD9\x33\x03\xCD\x0D\x8E\xD4\x3F\x67" - "\x11\x65\x0A\x90\x67\x83\xC1\xCC\x70\xB1\xA9\x46" - "\x4B\x5E\x0B\x84\xDC\x02\xBA\x50\x1D\x4A\x5B\xC7" - "\xB4\x5E\xDF\x35\x01\x45\x3D\x64\x5C\x2E\xCD\xA6" - "\x20\xFB\x35\x74\xC0\x7C\x2D\x24\x66\xAB\x38\x12" - "\x38\xCE\x52\xCB\x38\x9B\x95\xDE\x0C\x2A\x8C\x9D" - "\xF7\x81\x48\x9E\xD6\x10\xF1\x83\x71\x44\x53\x2F" - "\xCE\xF3\xEC\xB3\x29\x67\xF1\x41\xFC\xD6\xB6\x49" - "\xE3\x13\x74\x4D\xB2\x3E\xEA\x73\x2B\x03\x68\xAC" - "\x2F\x57\x8C\x58\xEC\x34\xE9\xEF\x18\x36\xDE\xAD" - "\xE9\x48\x1D\xF7\x9E\xB7\xA1\x60\x2E\x78\xF5\x62" - "\x68\xDD\xB8\x5B\x33\x6B\x66\xAD\xA1\xD5\xFB\x46" - "\x5E\x8F\xF8\x9D\x37\xE5\xC2\xD8\x76\xDC\x2B\x6A" - "\x99\x1E\xDF\x91\xB1\x0A\x81\x2A\x9D\xEB\xE7\xE4" - "\xD1\x21\xD4\xDA\x0E\x55\x8A\x14\xB2\xB6\x15\x7D" - "\x48\x52\x6A\xB0\xA2\x92\x4D\x50", - .entprlen = 320, - .addtla = "\xC2\x89\x7C\x07\x46\x74\x02\x2C\xEA\xAD\xFD\x74" - "\x0C\x40\xEF\xA2\x95\x64\x6B\xC4\x2D\xED\xF4\x16" - "\x26\x25\x06\xB3\x36\x6B\xD8\x9A\x5F\xF4\x25\xC1" - "\xC3\x69\x3F\x7A\x19\xB7\x02\xA6\xCC\x3B\xA2\x4E" - "\x05\xA1\x1C\x7B\x2D\xAD\x44\xE7\x4A\x40\x71\x85" - "\xEF\x1C\xE4\xEC\x54\xCA\xB0\xAF\x8F\xF5\x43\xB1" - "\xE0\x99\x71\x71\xD4\x3E\x56\x97\xAA\xF5\xD0\x1A" - "\x58\x2D\x65\x0F\xA4\xB4\xB6\x07\x1B\x1F\x13\x8B" - "\x29\xD6\xE5\x23\xD3\x4D\x43\xD6\xBC\x74\xA8\x92" - "\xBD\xE9\x9B\x01\x47\x8C\xA5\x02\xA8\x0D\xC3\x3A" - "\xED\x83\xFD\xD2\xCB\xFF\x25\x89\x2C\x2F\x5B\x70" - "\x3F\x9E\x24\x50\xF8\x78\x28\x1B\x67\x52\x92\xA2" - "\x87\x81\x07\x40\xA9\x40\xBA\x84\x47\x25\xC1\xF7" - "\x9E\x3B\x4E\xE4\x8F\x10\xE5\x50\x8B\x22\x83\x4F" - "\xCD\x4E\x42\x63\x92\x0A\x5F\xAF\x7A\x9B\x0E\x1A" - "\xE3\xB4\x99\x11\x7F\xE6\x93\xC3\xED\xF1\x9F\x3A", - .addtlb = "\x1E\x75\xB6\x70\x60\xFD\xE6\xD1\xC7\xA5\x74\xCF" - "\xA7\x50\x17\xAE\xDD\xC4\x6E\xC4\xE0\x15\xF0\x3B" - "\xF7\x1C\x46\x45\xEE\x60\x66\x48\x1D\x2C\x36\xCC" - "\x95\x3E\xB7\xEB\x1B\xFF\x8C\xC0\x78\x6D\x56\x3A" - "\xC7\x24\x18\x9E\x7C\xA1\x60\x54\x41\x4B\xAF\x18" - "\xE8\x02\xD1\x54\x65\xEC\x3D\xFD\x8B\xDF\xD2\xF5" - "\x62\xEA\x66\x41\x6A\x32\x87\xA6\x34\x2F\x48\xBF" - "\xB5\xCC\x35\x5A\x2A\xC1\xAB\x68\x34\x1A\xD6\x82" - "\x40\xF7\xF2\x00\x14\x8B\x69\x0F\xE4\xCD\x6B\xB1" - "\xFC\x8B\x16\xEC\xB4\xE3\x33\xBF\x84\x12\x4B\x58" - "\xED\x51\x88\xF5\xEF\xB6\xC3\xCE\x9B\x63\xCC\x80" - "\x1F\x3C\x8A\x67\xEE\xCD\xD2\x01\x25\x22\xAC\xB3" - "\xB6\x9B\x1F\xF8\xE8\x71\xE6\x0D\x78\x11\x3C\x9E" - "\xF2\x57\xDC\xB6\xCF\x90\xD3\xA8\x3E\xCD\x88\xD4" - "\xDC\x1C\x31\x6B\x1F\xC3\x6A\x29\xF0\x7B\x4C\xCC" - "\x6D\x92\x5E\x6F\x0C\x0B\x4D\xA7\x10\x66\x84\x1F", - .addtllen = 192, - - .expected = "\xAA\x76\x91\xAE\x99\xCD\x8D\x83\x49\x9D\xC5\x51" - "\xA5\x95\xC6\x9D\xAD\x4B\x40\x2B\x5F\x8C\x30\x5D" - "\x1E\x89\x58\xD1\x8A\x86\xF9\x61\x2C\x45\x41\x8E" - "\xC5\xC6\x0E\x33\x7C\xFE\x91\x71\xC9\x53\x76\xD6" - "\xC2\x8D\x05\x09\xB8\x2A\x2B\x9B\x36\x1D\x31\xD7" - "\x50\x45\xB1\x08\x58\xC4\x99\x25\xEA\x2F\x18\xDB" - "\x34\x8A\x02\xD8\x38\xDD\x7B\x9E\x0E\xEF\x9C\x45" - "\xC7\x4F\x7E\x36\x3A\x90\x8B\x41\x51\x4A\x1B\xE9" - "\x8A\x61\xE9\xB5\x4E\xA5\xE2\xBD\x16\x59\x61\x0F" - "\x9C\x5A\x63\xA7\x87\x79\x5C\x0A\x16\xDF\x6D\x88" - "\x11\x25\x56\x8B\x5D\xA6\xF8\x4F\xB9\x01\x19\xAE" - "\x57\x3B\xC4\x06\xBB\xE7\xCB\xAF\xB3\x8D\xE2\x40" - "\xED\x42\x29\xB3\x0D\x64\x20\xF2\x66\x58\xB1\xDD" - "\x59\xB1\x39\x7C\xD9\xB2\x34\x08\x53\x9B\x3A\xB7" - "\x18\x35\xD0\x90\x7F\xB5\x30\xF2\x27\xA0\x90\x63" - "\x6F\xF2\x72\x49\xBF\xD0\xAE\x4A\xF4\xCA\xB3\x1A" - "\xAE\x7F\x93\xF3\xB9\x84\x99\x09\x50\xB9\xA0\x43" - "\x4F\x83\x33\x92\xA5\xC7\x25\x44\x6A\x74\xF4\xFA" - "\xBA\x60\x43\x13\x97\x53\x99\x98\xA3\x05\x02\xC1" - "\x03\xDF\x53\x76\x9E\x74\xE7\xA0\xB5\xD7\xA7\x87" - "\x1E\x00\x1D\x29\x47\x8F\x65\x4E\x0F\x76\xCA\xA9" - "\x2A\xC5\x05\x4F\xA6\xFE\x96\xC6\x81\xC0\x55\xFC" - "\x92\x89\xA6\x81\xF0\x37\xF1\x41\xA6\x88\x0B\x01" - "\xE0\xA5\x78\x4C\xF4\x61\xA7\x91\xD8\x4B\xE9\x2C" - "\xF0\x68\xEE\x46\x41\xD2\x74\xE5\x5F\x6F\x1F\xE6" - "\xBE\x5C\xB1\x3C\x60\x1A\xAA\xB9\x88\x3C\xB9\x1C" - "\xCD\x67\x78\x1F\x45\x18\xE7\x8B\xBD\xE4\x24\xDA" - "\xA8\x26\xD1\x03\xF1\xC7\x6B\x28\x62\xAB\x5C\xAB" - "\x98\xCA\xFB\xCB\x0B\x2D\x01\xD9\xC1\xA6\xFA\x91" - "\x71\x3D\x9B\x3B\x60\xEB\xD7\xA2\x61\xC1\x92\x60" - "\xB1\x02\x44\x0C\x97\x70\x77\x83\xF9\x35\xEA\x24" - "\x85\xF8\x0A\x32\xA2\xC7\x05\x40\x90\x83\x4F\x87" - "\x57\x66\xB5\xDE\xEE\xFF\x8B\x01\xBC\x96\xB0\xC5" - "\x29\xB6\xC1\xF0\x11\x31\x51\x11\xB0\xC2\x0F\x08" - "\xCF\x09\x69\x74\xE1\x0D\x6C\x0A\x10\xD0\x73\xF0" - "\x8E\xDC\x5F\xB1\xBD\x47\x8A\xA7\x90\xB3\x08\x86" - "\xD2\xE4\x58\xE5\x68\x33\x67\x3B\x37\xF1\x28\x28" - "\x59\x91\xB5\x5F\x8D\x84\x54\xCE\x18\x76\xE3\x5C" - "\x55\x37\x8E\x10\x34\x9B\x6E\x1F\x73\x88\x31\xBF" - "\x0D\x5C\xED\x7A\xBC\xF2\xCE\x7A\x2E\x2E\xE7\x04" - "\xE7\xF2\x8F\x33\xCC\x06\x77\x96\xBB\xA8\x65\x03" - "\x26\x79\xC0\xF0\x52\x3B\xD4\xF2\x5D\x00\xE4\x80" - "\x7F\x78\xC0\x45\x29\x55\xCA\x63", - .expectedlen = 512, - } -}; - static const struct drbg_testvec drbg_nopr_hmac_sha512_tv_template[] = { /* * Borrowed from the first applicable test vector from ACVP: From 24818f77603b3fcb7f3da5802b28bcc5ac7604aa Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Wed, 6 May 2026 01:56:53 -0700 Subject: [PATCH 092/196] crypto: talitos - allocate channels with main struct Use a flexible array member to combine allocations. Add __counted_by for extra runtime analysis. Error in case of no channels as they are required. Signed-off-by: Rosen Penev Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 19 +++++++------------ drivers/crypto/talitos.h | 5 +++-- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index bc61d0fe3514..bd4cc06ee13c 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -3409,14 +3409,20 @@ static int talitos_probe(struct platform_device *ofdev) struct device *dev = &ofdev->dev; struct device_node *np = ofdev->dev.of_node; struct talitos_private *priv; + unsigned int num_channels; int i, err; int stride; struct resource *res; - priv = devm_kzalloc(dev, sizeof(struct talitos_private), GFP_KERNEL); + if (of_property_read_u32(np, "fsl,num-channels", &num_channels)) + return -EINVAL; + + priv = devm_kzalloc(dev, struct_size(priv, chan, num_channels), GFP_KERNEL); if (!priv) return -ENOMEM; + priv->num_channels = num_channels; + INIT_LIST_HEAD(&priv->alg_list); dev_set_drvdata(dev, priv); @@ -3436,7 +3442,6 @@ static int talitos_probe(struct platform_device *ofdev) } /* get SEC version capabilities from device tree */ - of_property_read_u32(np, "fsl,num-channels", &priv->num_channels); of_property_read_u32(np, "fsl,channel-fifo-len", &priv->chfifo_len); of_property_read_u32(np, "fsl,exec-units-mask", &priv->exec_units); of_property_read_u32(np, "fsl,descriptor-types-mask", @@ -3511,16 +3516,6 @@ static int talitos_probe(struct platform_device *ofdev) } } - priv->chan = devm_kcalloc(dev, - priv->num_channels, - sizeof(struct talitos_channel), - GFP_KERNEL); - if (!priv->chan) { - dev_err(dev, "failed to allocate channel management space\n"); - err = -ENOMEM; - goto err_out; - } - priv->fifo_len = roundup_pow_of_two(priv->chfifo_len); for (i = 0; i < priv->num_channels; i++) { diff --git a/drivers/crypto/talitos.h b/drivers/crypto/talitos.h index 1a93ee355929..34b0b5fab7e7 100644 --- a/drivers/crypto/talitos.h +++ b/drivers/crypto/talitos.h @@ -139,8 +139,6 @@ struct talitos_private { */ unsigned int fifo_len; - struct talitos_channel *chan; - /* next channel to be assigned next incoming descriptor */ atomic_t last_chan ____cacheline_aligned; @@ -153,6 +151,9 @@ struct talitos_private { /* hwrng device */ struct hwrng rng; bool rng_registered; + + struct talitos_channel chan[] __counted_by(num_channels); + }; /* .features flag */ From 4e6063436cd21ac813494df4062e8b49c5f93bd6 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Wed, 6 May 2026 11:16:28 +0200 Subject: [PATCH 093/196] crypto: artpec6 - refactor crypto_setup_out_descr for readability Replace if-else with an early return to reduce code nesting, and move the variable declarations to the top of the function. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/axis/artpec6_crypto.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/crypto/axis/artpec6_crypto.c b/drivers/crypto/axis/artpec6_crypto.c index a4793b76300c..2bf8d71c86f4 100644 --- a/drivers/crypto/axis/artpec6_crypto.c +++ b/drivers/crypto/axis/artpec6_crypto.c @@ -706,22 +706,19 @@ artpec6_crypto_setup_out_descr(struct artpec6_crypto_req_common *common, void *dst, unsigned int len, bool eop, bool use_short) { - if (use_short && len < 7) { + dma_addr_t dma_addr; + int ret; + + if (use_short && len < 7) return artpec6_crypto_setup_out_descr_short(common, dst, len, eop); - } else { - int ret; - dma_addr_t dma_addr; - ret = artpec6_crypto_dma_map_single(common, dst, len, - DMA_TO_DEVICE, - &dma_addr); - if (ret) - return ret; + ret = artpec6_crypto_dma_map_single(common, dst, len, DMA_TO_DEVICE, + &dma_addr); + if (ret) + return ret; - return artpec6_crypto_setup_out_descr_phys(common, dma_addr, - len, eop); - } + return artpec6_crypto_setup_out_descr_phys(common, dma_addr, len, eop); } /** artpec6_crypto_setup_in_descr_phys - Setup an in channel with a From 5a44059f02fdc0a0c905c724a25487319f1933cb Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Wed, 6 May 2026 11:21:51 +0200 Subject: [PATCH 094/196] crypto: ccree - replace snprintf("%s") with strscpy Replace snprintf("%s") with the faster and more direct strscpy(). In cc_aead.c, group the includes while at it. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/ccree/cc_aead.c | 9 ++++----- drivers/crypto/ccree/cc_cipher.c | 7 +++---- drivers/crypto/ccree/cc_hash.c | 13 +++++-------- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/drivers/crypto/ccree/cc_aead.c b/drivers/crypto/ccree/cc_aead.c index 81533681f7fb..088c4603047f 100644 --- a/drivers/crypto/ccree/cc_aead.c +++ b/drivers/crypto/ccree/cc_aead.c @@ -3,11 +3,12 @@ #include #include +#include +#include #include #include #include #include -#include #include #include "cc_driver.h" #include "cc_buffer_mgr.h" @@ -2569,11 +2570,9 @@ static struct cc_crypto_alg *cc_create_aead_alg(struct cc_alg_template *tmpl, alg = &tmpl->template_aead; - if (snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", - tmpl->name) >= CRYPTO_MAX_ALG_NAME) + if (strscpy(alg->base.cra_name, tmpl->name) < 0) return ERR_PTR(-EINVAL); - if (snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", - tmpl->driver_name) >= CRYPTO_MAX_ALG_NAME) + if (strscpy(alg->base.cra_driver_name, tmpl->driver_name) < 0) return ERR_PTR(-EINVAL); alg->base.cra_module = THIS_MODULE; diff --git a/drivers/crypto/ccree/cc_cipher.c b/drivers/crypto/ccree/cc_cipher.c index e2cbfdf7a0e4..5339b3796c80 100644 --- a/drivers/crypto/ccree/cc_cipher.c +++ b/drivers/crypto/ccree/cc_cipher.c @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -1386,11 +1387,9 @@ static struct cc_crypto_alg *cc_create_alg(const struct cc_alg_template *tmpl, memcpy(alg, &tmpl->template_skcipher, sizeof(*alg)); - if (snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", - tmpl->name) >= CRYPTO_MAX_ALG_NAME) + if (strscpy(alg->base.cra_name, tmpl->name) < 0) return ERR_PTR(-EINVAL); - if (snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", - tmpl->driver_name) >= CRYPTO_MAX_ALG_NAME) + if (strscpy(alg->base.cra_driver_name, tmpl->driver_name) < 0) return ERR_PTR(-EINVAL); alg->base.cra_module = THIS_MODULE; diff --git a/drivers/crypto/ccree/cc_hash.c b/drivers/crypto/ccree/cc_hash.c index 73179bf725a7..5de721a2ca30 100644 --- a/drivers/crypto/ccree/cc_hash.c +++ b/drivers/crypto/ccree/cc_hash.c @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -1835,16 +1836,12 @@ static struct cc_hash_alg *cc_alloc_hash_alg(struct cc_hash_template *template, alg = &halg->halg.base; if (keyed) { - snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", - template->mac_name); - snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", - template->mac_driver_name); + strscpy(alg->cra_name, template->mac_name); + strscpy(alg->cra_driver_name, template->mac_driver_name); } else { halg->setkey = NULL; - snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", - template->name); - snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", - template->driver_name); + strscpy(alg->cra_name, template->name); + strscpy(alg->cra_driver_name, template->driver_name); } alg->cra_module = THIS_MODULE; alg->cra_ctxsize = sizeof(struct cc_hash_ctx) + crypto_dma_padding(); From c64ba13e2033c3c6dc1a097bf35f9f1fe457c3f7 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 6 May 2026 15:27:49 +0200 Subject: [PATCH 095/196] crypto: ecc - Unbreak the build on arm with CONFIG_KASAN_STACK=y Andrew reports build breakage of arm allmodconfig, reproducible with gcc 14.2.0 and 15.2.0: crypto/ecc.c: In function 'ecc_point_mult': crypto/ecc.c:1380:1: error: the frame size of 1360 bytes is larger than 1280 bytes [-Werror=frame-larger-than=] gcc aggressively inlines functions called by ecc_point_mult() (without there being any explicit inline declarations), which pushes stack usage close to the limit imposed by CONFIG_FRAME_WARN. allmodconfig implies CONFIG_KASAN_STACK=y, which increases the stack above that limit. In the bugzilla entry linked below, gcc maintainers explain that gcc estimates extra stack usage caused by inlining, but ASAN instrumentation is added in post-IPA passes and thus the inlining heuristics cannot account for it. It could be argued that -Werror=frame-larger-than=1280 instructs the compiler to avoid inlining beyond that limit lest the build breaks, which would imply gcc behaves incorrectly. But gcc maintainers reject this notion and believe that a warning switch should never affect code generation, even if it is promoted to an error. One way to unbreak the build is to limit inlining via -finline-limit=100 or by explicitly declaring some functions noinline. However while it does keep stack usage of individual functions below the limit, *total* stack usage increases. A longterm solution is to refactor ecc.c for reduced stack usage. It currently performs ECC point multiplication with a Montgomery ladder which uses co-Z (conjugate) addition to trade off memory for speed. The algorithm is susceptible to timing attacks and needs to be replaced with a constant time Montgomery ladder, which should consume less memory and thus resolve the stack usage issue as a side effect. In the interim, raise the limit for ecc.c, as is already done for several other files in the source tree. Constrain to gcc because clang 19.1.7 does not exhibit the issue. It makes do with a 724 bytes stack frame even though it inlines almost the same functions as gcc. Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124949 Reported-by: Andrew Morton # off-list Signed-off-by: Lukas Wunner Acked-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Signed-off-by: Herbert Xu --- crypto/Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crypto/Makefile b/crypto/Makefile index 162242593c7c..c73f4d51d036 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -178,6 +178,11 @@ obj-$(CONFIG_CRYPTO_ZSTD) += zstd.o obj-$(CONFIG_CRYPTO_ECC) += ecc.o obj-$(CONFIG_CRYPTO_ESSIV) += essiv.o +# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124949 +ifeq ($(CONFIG_ARM)$(CONFIG_KASAN_STACK)$(CONFIG_CC_IS_GCC),yyy) +CFLAGS_ecc.o += $(call cc-option,-Wframe-larger-than=1536) +endif + ecdh_generic-y += ecdh.o ecdh_generic-y += ecdh_helper.o obj-$(CONFIG_CRYPTO_ECDH) += ecdh_generic.o From 5b085b2a038a1458f9398cb3b3b03cba6e38e1e0 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Thu, 7 May 2026 15:55:27 +0200 Subject: [PATCH 096/196] crypto: atmel-ecc - replace min_t with min Use the simpler min() macro since the values are all unsigned and compatible. Signed-off-by: Thorsten Blum Reviewed-by: David Laight Signed-off-by: Herbert Xu --- drivers/crypto/atmel-ecc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index 3738a4eb8701..e47381020606 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -56,7 +56,7 @@ static void atmel_ecdh_done(struct atmel_i2c_work_data *work_data, void *areq, goto free_work_data; /* might want less than we've got */ - n_sz = min_t(size_t, ATMEL_ECC_NIST_P256_N_SIZE, req->dst_len); + n_sz = min(ATMEL_ECC_NIST_P256_N_SIZE, req->dst_len); /* copy the shared secret */ copied = sg_copy_from_buffer(req->dst, sg_nents_for_len(req->dst, n_sz), @@ -150,7 +150,7 @@ static int atmel_ecdh_generate_public_key(struct kpp_request *req) return -EINVAL; /* might want less than we've got */ - nbytes = min_t(size_t, ATMEL_ECC_PUBKEY_SIZE, req->dst_len); + nbytes = min(ATMEL_ECC_PUBKEY_SIZE, req->dst_len); /* public key was saved at private key generation */ copied = sg_copy_from_buffer(req->dst, From 930d9d36ea618a775985446a125aedeb401db522 Mon Sep 17 00:00:00 2001 From: Stepan Ionichev Date: Thu, 7 May 2026 19:06:08 +0500 Subject: [PATCH 097/196] crypto: ccp/sev-dev-tsm - bail out early when pdev->bus is NULL dsm_create() initially checks pdev->bus when computing segment_id: u8 segment_id = pdev->bus ? pci_domain_nr(pdev->bus) : 0; But the next two lines unconditionally dereference pdev->bus via pcie_find_root_port() and especially pci_dev_id(pdev), which expands to PCI_DEVID(dev->bus->number, dev->devfn). If pdev->bus is in fact NULL, segment_id is initialised to 0 but the very next statement crashes the kernel. smatch flags this: drivers/crypto/ccp/sev-dev-tsm.c:253 dsm_create() error: we previously assumed 'pdev->bus' could be null (see line 251) Make the NULL handling consistent: if pdev->bus is NULL the device has no PCI context to work with and SEV TIO setup cannot proceed, so return -ENODEV before any of the bus-dependent lookups. The remaining initialisation now runs only on the path where pdev->bus is known to be valid. No change for callers where pdev->bus is non-NULL, which is the only case where dsm_create() did meaningful work before this change. Fixes: 4be423572da1 ("crypto/ccp: Implement SEV-TIO PCIe IDE (phase1)") Signed-off-by: Stepan Ionichev Signed-off-by: Herbert Xu --- drivers/crypto/ccp/sev-dev-tsm.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/ccp/sev-dev-tsm.c b/drivers/crypto/ccp/sev-dev-tsm.c index b07ae529b591..f303d8f55991 100644 --- a/drivers/crypto/ccp/sev-dev-tsm.c +++ b/drivers/crypto/ccp/sev-dev-tsm.c @@ -248,12 +248,19 @@ static void dsm_remove(struct pci_tsm *tsm) static int dsm_create(struct tio_dsm *dsm) { struct pci_dev *pdev = dsm->tsm.base_tsm.pdev; - u8 segment_id = pdev->bus ? pci_domain_nr(pdev->bus) : 0; - struct pci_dev *rootport = pcie_find_root_port(pdev); - u16 device_id = pci_dev_id(pdev); + struct pci_dev *rootport; + u8 segment_id; + u16 device_id; u16 root_port_id; u32 lnkcap = 0; + if (!pdev->bus) + return -ENODEV; + + segment_id = pci_domain_nr(pdev->bus); + rootport = pcie_find_root_port(pdev); + device_id = pci_dev_id(pdev); + if (pci_read_config_dword(rootport, pci_pcie_cap(rootport) + PCI_EXP_LNKCAP, &lnkcap)) return -ENODEV; From e17ff3d6ff907dc8406261e8fd3e1fc8a908f0f6 Mon Sep 17 00:00:00 2001 From: Paul Louvel Date: Thu, 7 May 2026 16:41:47 +0200 Subject: [PATCH 098/196] crypto: talitos - use dma_sync_single_for_cpu() before reading descriptor header In order to know if a descriptor has been processed by the device, the driver polls the FIFO to see if DESC_HDR_DONE is set on a descriptor header to confirm completion. The current code does not make sure that the CPU gets up to date data before reading the descriptor. Fix this by calling dma_sync_single_for_cpu() before reading memory written by the device. Cc: stable@vger.kernel.org Fixes: 58cdbc6d2263 ("crypto: talitos - fix hash on SEC1.") Signed-off-by: Paul Louvel Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index bd4cc06ee13c..e7ef286f4306 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -322,19 +322,31 @@ static int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc, return -EINPROGRESS; } -static __be32 get_request_hdr(struct talitos_request *request, bool is_sec1) +static __be32 get_request_hdr(struct device *dev, + struct talitos_request *request, bool is_sec1) { struct talitos_edesc *edesc; - if (!is_sec1) + if (!is_sec1) { + dma_sync_single_for_cpu(dev, request->dma_desc, + TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL); + return request->desc->hdr; + } - if (!request->desc->next_desc) + if (!request->desc->next_desc) { + dma_sync_single_for_cpu(dev, request->dma_desc, + TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL); return request->desc->hdr1; + } else { + dma_sync_single_for_cpu(dev, + be32_to_cpu(request->desc->next_desc), + TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL); + edesc = container_of(request->desc, struct talitos_edesc, desc); - edesc = container_of(request->desc, struct talitos_edesc, desc); - - return ((struct talitos_desc *)(edesc->buf + edesc->dma_len))->hdr1; + return ((struct talitos_desc *)(edesc->buf + edesc->dma_len)) + ->hdr1; + } } /* @@ -358,7 +370,7 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch) /* descriptors with their done bits set don't get the error */ rmb(); - hdr = get_request_hdr(request, is_sec1); + hdr = get_request_hdr(dev, request, is_sec1); if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE) status = 0; From f126384ed55279c3b676f89d5ab547b8de8df782 Mon Sep 17 00:00:00 2001 From: Paul Louvel Date: Thu, 7 May 2026 16:41:48 +0200 Subject: [PATCH 099/196] crypto: talitos - add chaining of arbitrary number of descriptor for the SEC1 The SEC1 hardware can process a chain of descriptors without host intervention. Only the hash implementation currently use this feature, but with a chain of at most 2 descriptors added in commit 37b5e8897eb5 ("crypto: talitos - chain in buffered data for ahash on SEC1"). Add supports for chaining an arbitrary number of descriptors in a chain. Adapt the ahash implementation to make it compatible. Cc: stable@vger.kernel.org Signed-off-by: Paul Louvel Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 180 ++++++++++++++++++++++++++------------- drivers/crypto/talitos.h | 2 + 2 files changed, 124 insertions(+), 58 deletions(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index e7ef286f4306..b26b4672a457 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -273,7 +273,10 @@ static int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc, void *context, int error), void *context) { + struct talitos_edesc *edesc = container_of(desc, struct talitos_edesc, desc); struct talitos_private *priv = dev_get_drvdata(dev); + dma_addr_t dma_desc, prev_dma_desc; + struct talitos_edesc *prev_edesc = NULL; struct talitos_request *request; unsigned long flags; int head; @@ -292,10 +295,31 @@ static int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc, /* map descriptor and save caller data */ if (is_sec1) { - desc->hdr1 = desc->hdr; - request->dma_desc = dma_map_single(dev, &desc->hdr1, + while (edesc) { + edesc->desc.hdr1 = edesc->desc.hdr; + + dma_desc = dma_map_single(dev, &edesc->desc.hdr1, + TALITOS_DESC_SIZE, + DMA_BIDIRECTIONAL); + + if (!prev_edesc) { + request->dma_desc = dma_desc; + goto next; + } + + /* Chain in any previous descriptors. */ + + prev_edesc->desc.next_desc = cpu_to_be32(dma_desc); + + dma_sync_single_for_device(dev, prev_dma_desc, TALITOS_DESC_SIZE, - DMA_BIDIRECTIONAL); + DMA_TO_DEVICE); + +next: + prev_edesc = edesc; + prev_dma_desc = dma_desc; + edesc = edesc->next_desc; + } } else { request->dma_desc = dma_map_single(dev, desc, TALITOS_DESC_SIZE, @@ -326,6 +350,7 @@ static __be32 get_request_hdr(struct device *dev, struct talitos_request *request, bool is_sec1) { struct talitos_edesc *edesc; + dma_addr_t dma_desc; if (!is_sec1) { dma_sync_single_for_cpu(dev, request->dma_desc, @@ -334,19 +359,17 @@ static __be32 get_request_hdr(struct device *dev, return request->desc->hdr; } - if (!request->desc->next_desc) { - dma_sync_single_for_cpu(dev, request->dma_desc, - TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL); - return request->desc->hdr1; - } else { - dma_sync_single_for_cpu(dev, - be32_to_cpu(request->desc->next_desc), - TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL); - edesc = container_of(request->desc, struct talitos_edesc, desc); - - return ((struct talitos_desc *)(edesc->buf + edesc->dma_len)) - ->hdr1; + edesc = container_of(request->desc, struct talitos_edesc, desc); + dma_desc = request->dma_desc; + while (edesc->next_desc) { + dma_desc = be32_to_cpu(edesc->desc.next_desc); + edesc = edesc->next_desc; } + + dma_sync_single_for_cpu(dev, dma_desc, TALITOS_DESC_SIZE, + DMA_BIDIRECTIONAL); + + return edesc->desc.hdr1; } /* @@ -356,6 +379,7 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch) { struct talitos_private *priv = dev_get_drvdata(dev); struct talitos_request *request, saved_req; + struct talitos_edesc *edesc; unsigned long flags; int tail, status; bool is_sec1 = has_ftr_sec1(priv); @@ -380,9 +404,22 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch) else status = error; - dma_unmap_single(dev, request->dma_desc, - TALITOS_DESC_SIZE, - DMA_BIDIRECTIONAL); + if (is_sec1) { + dma_unmap_single(dev, request->dma_desc, + TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL); + edesc = container_of(request->desc, + struct talitos_edesc, desc); + while (edesc->next_desc) { + dma_unmap_single( + dev, be32_to_cpu(edesc->desc.next_desc), + TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL); + edesc = edesc->next_desc; + } + } else { + dma_unmap_single(dev, request->dma_desc, + TALITOS_DESC_SIZE, + DMA_BIDIRECTIONAL); + } /* copy entries so we can call callback outside lock */ saved_req.desc = request->desc; @@ -477,8 +514,12 @@ DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE) static __be32 current_desc_hdr(struct device *dev, int ch) { struct talitos_private *priv = dev_get_drvdata(dev); + bool is_sec1 = has_ftr_sec1(priv); + struct talitos_request *request; + struct talitos_edesc *edesc; int tail, iter; dma_addr_t cur_desc; + __be32 hdr = 0; cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32; cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO); @@ -489,27 +530,35 @@ static __be32 current_desc_hdr(struct device *dev, int ch) } tail = priv->chan[ch].tail; - iter = tail; - while (priv->chan[ch].fifo[iter].dma_desc != cur_desc && - priv->chan[ch].fifo[iter].desc->next_desc != cpu_to_be32(cur_desc)) { - iter = (iter + 1) & (priv->fifo_len - 1); - if (iter == tail) { - dev_err(dev, "couldn't locate current descriptor\n"); - return 0; + do { + request = &priv->chan[ch].fifo[iter]; + + if (request->dma_desc == cur_desc) { + hdr = request->desc->hdr; + } else if (is_sec1) { + edesc = container_of(request->desc, + struct talitos_edesc, desc); + while (edesc->next_desc) { + if (edesc->desc.next_desc == + cpu_to_be32(cur_desc)) { + hdr = edesc->next_desc->desc.hdr1; + break; + } + edesc = edesc->next_desc; + } } - } - if (priv->chan[ch].fifo[iter].desc->next_desc == cpu_to_be32(cur_desc)) { - struct talitos_edesc *edesc; + if (hdr) + break; - edesc = container_of(priv->chan[ch].fifo[iter].desc, - struct talitos_edesc, desc); - return ((struct talitos_desc *) - (edesc->buf + edesc->dma_len))->hdr; - } + iter = (iter + 1) & (priv->fifo_len - 1); + } while (iter != tail); - return priv->chan[ch].fifo[iter].desc->hdr; + if (!hdr) + dev_err(dev, "couldn't locate current descriptor\n"); + + return hdr; } /* @@ -1408,10 +1457,6 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev, dma_len = 0; } alloc_len += icv_stashing ? authsize : 0; - - /* if its a ahash, add space for a second desc next to the first one */ - if (is_sec1 && !dst) - alloc_len += sizeof(struct talitos_desc); alloc_len += ivsize; edesc = kmalloc(ALIGN(alloc_len, dma_get_cache_alignment()), flags); @@ -1427,6 +1472,7 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev, edesc->dst_nents = dst_nents; edesc->iv_dma = iv_dma; edesc->dma_len = dma_len; + edesc->next_desc = NULL; if (dma_len) edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0], edesc->dma_len, @@ -1727,8 +1773,10 @@ static void common_nonsnoop_hash_unmap(struct device *dev, struct talitos_private *priv = dev_get_drvdata(dev); bool is_sec1 = has_ftr_sec1(priv); struct talitos_desc *desc = &edesc->desc; - struct talitos_desc *desc2 = (struct talitos_desc *) - (edesc->buf + edesc->dma_len); + struct talitos_desc *desc2; + + if (desc->next_desc) + desc2 = &edesc->next_desc->desc; unmap_single_talitos_ptr(dev, &desc->ptr[5], DMA_FROM_DEVICE); if (desc->next_desc && @@ -1756,10 +1804,17 @@ static void common_nonsnoop_hash_unmap(struct device *dev, if (edesc->dma_len) dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len, DMA_BIDIRECTIONAL); +} - if (desc->next_desc) - dma_unmap_single(dev, be32_to_cpu(desc->next_desc), - TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL); +static void free_edesc_list_from(struct talitos_edesc *edesc) +{ + struct talitos_edesc *next; + + while (edesc) { + next = edesc->next_desc; + kfree(edesc); + edesc = next; + } } static void ahash_done(struct device *dev, @@ -1778,7 +1833,7 @@ static void ahash_done(struct device *dev, } common_nonsnoop_hash_unmap(dev, edesc, areq); - kfree(edesc); + free_edesc_list_from(edesc); if (err) { ahash_request_complete(areq, err); @@ -1894,14 +1949,23 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc, talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]); if (is_sec1 && req_ctx->nbuf && length) { - struct talitos_desc *desc2 = (struct talitos_desc *) - (edesc->buf + edesc->dma_len); - dma_addr_t next_desc; + struct talitos_edesc *edesc2; + struct talitos_desc *desc2; + + edesc2 = kzalloc(sizeof(*edesc2), + areq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? + GFP_KERNEL : + GFP_ATOMIC); + if (!edesc2) { + ret = -ENOMEM; + goto err; + } + edesc->next_desc = edesc2; + + desc2 = &edesc2->desc; - memset(desc2, 0, sizeof(*desc2)); desc2->hdr = desc->hdr; desc2->hdr &= ~DESC_HDR_MODE0_MDEU_INIT; - desc2->hdr1 = desc2->hdr; desc->hdr &= ~DESC_HDR_MODE0_MDEU_PAD; desc->hdr |= DESC_HDR_MODE0_MDEU_CONT; desc->hdr &= ~DESC_HDR_DONE_NOTIFY; @@ -1925,21 +1989,21 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc, req_ctx->hw_context_size, req_ctx->hw_context, DMA_FROM_DEVICE); - - next_desc = dma_map_single(dev, &desc2->hdr1, TALITOS_DESC_SIZE, - DMA_BIDIRECTIONAL); - desc->next_desc = cpu_to_be32(next_desc); } if (sync_needed) dma_sync_single_for_device(dev, edesc->dma_link_tbl, edesc->dma_len, DMA_BIDIRECTIONAL); - ret = talitos_submit(dev, ctx->ch, desc, callback, areq); - if (ret != -EINPROGRESS) { - common_nonsnoop_hash_unmap(dev, edesc, areq); - kfree(edesc); - } + ret = talitos_submit(dev, ctx->ch, desc, callback, + areq); + if (ret != -EINPROGRESS) + goto err; + + return -EINPROGRESS; +err: + common_nonsnoop_hash_unmap(dev, edesc, areq); + kfree(edesc); return ret; } diff --git a/drivers/crypto/talitos.h b/drivers/crypto/talitos.h index 34b0b5fab7e7..1553afa57b0b 100644 --- a/drivers/crypto/talitos.h +++ b/drivers/crypto/talitos.h @@ -49,6 +49,7 @@ struct talitos_desc { * @iv_dma: dma address of iv for checking continuity and link table * @dma_len: length of dma mapped link_tbl space * @dma_link_tbl: bus physical address of link_tbl/buf + * @next_desc: next descriptor * @desc: h/w descriptor * @link_tbl: input and output h/w link tables (if {src,dst}_nents > 1) (SEC2) * @buf: input and output buffeur (if {src,dst}_nents > 1) (SEC1) @@ -63,6 +64,7 @@ struct talitos_edesc { dma_addr_t iv_dma; int dma_len; dma_addr_t dma_link_tbl; + struct talitos_edesc *next_desc; struct talitos_desc desc; union { DECLARE_FLEX_ARRAY(struct talitos_ptr, link_tbl); From 4d9b0b7415b9e79a3d54d18b5ff230974ea78740 Mon Sep 17 00:00:00 2001 From: Paul Louvel Date: Thu, 7 May 2026 16:41:49 +0200 Subject: [PATCH 100/196] crypto: talitos - move dma unmapping code in flush_channel() into a standalone dma_unmap_request() function Previously added code to flush_channel() in order to unmap an entire descriptor. Move that code into a standalone function to improve readability. Cc: stable@vger.kernel.org Signed-off-by: Paul Louvel Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index b26b4672a457..cffd4a2bd587 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -372,6 +372,27 @@ static __be32 get_request_hdr(struct device *dev, return edesc->desc.hdr1; } +static void dma_unmap_request(struct device *dev, + struct talitos_request *request, bool is_sec1) +{ + struct talitos_edesc *edesc; + + if (is_sec1) { + dma_unmap_single(dev, request->dma_desc, TALITOS_DESC_SIZE, + DMA_BIDIRECTIONAL); + edesc = container_of(request->desc, struct talitos_edesc, desc); + while (edesc->next_desc) { + dma_unmap_single(dev, + be32_to_cpu(edesc->desc.next_desc), + TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL); + edesc = edesc->next_desc; + } + } else { + dma_unmap_single(dev, request->dma_desc, TALITOS_DESC_SIZE, + DMA_BIDIRECTIONAL); + } +} + /* * process what was done, notify callback of error if not */ @@ -379,7 +400,6 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch) { struct talitos_private *priv = dev_get_drvdata(dev); struct talitos_request *request, saved_req; - struct talitos_edesc *edesc; unsigned long flags; int tail, status; bool is_sec1 = has_ftr_sec1(priv); @@ -404,22 +424,7 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch) else status = error; - if (is_sec1) { - dma_unmap_single(dev, request->dma_desc, - TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL); - edesc = container_of(request->desc, - struct talitos_edesc, desc); - while (edesc->next_desc) { - dma_unmap_single( - dev, be32_to_cpu(edesc->desc.next_desc), - TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL); - edesc = edesc->next_desc; - } - } else { - dma_unmap_single(dev, request->dma_desc, - TALITOS_DESC_SIZE, - DMA_BIDIRECTIONAL); - } + dma_unmap_request(dev, request, is_sec1); /* copy entries so we can call callback outside lock */ saved_req.desc = request->desc; From 5c0aa8cad7745505297103f05dda3fa06e8ac670 Mon Sep 17 00:00:00 2001 From: Paul Louvel Date: Thu, 7 May 2026 16:41:50 +0200 Subject: [PATCH 101/196] crypto: talitos - move dma mapping code in talitos_submit() into a standalone dma_map_request() function Previously added code to talitos_submit() in order to map an entire descriptor chain. Move that code into a standalone function to improve readability. Cc: stable@vger.kernel.org Signed-off-by: Paul Louvel Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 81 ++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 37 deletions(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index cffd4a2bd587..d8f838add0ff 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -255,45 +255,14 @@ static int init_device(struct device *dev) return 0; } -/** - * talitos_submit - submits a descriptor to the device for processing - * @dev: the SEC device to be used - * @ch: the SEC device channel to be used - * @desc: the descriptor to be processed by the device - * @callback: whom to call when processing is complete - * @context: a handle for use by caller (optional) - * - * desc must contain valid dma-mapped (bus physical) address pointers. - * callback must check err and feedback in descriptor header - * for device processing status. - */ -static int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc, - void (*callback)(struct device *dev, - struct talitos_desc *desc, - void *context, int error), - void *context) +static void dma_map_request(struct device *dev, struct talitos_request *request, + struct talitos_desc *desc, bool is_sec1) { - struct talitos_edesc *edesc = container_of(desc, struct talitos_edesc, desc); - struct talitos_private *priv = dev_get_drvdata(dev); + struct talitos_edesc *edesc = + container_of(desc, struct talitos_edesc, desc); dma_addr_t dma_desc, prev_dma_desc; struct talitos_edesc *prev_edesc = NULL; - struct talitos_request *request; - unsigned long flags; - int head; - bool is_sec1 = has_ftr_sec1(priv); - spin_lock_irqsave(&priv->chan[ch].head_lock, flags); - - if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) { - /* h/w fifo is full */ - spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags); - return -EAGAIN; - } - - head = priv->chan[ch].head; - request = &priv->chan[ch].fifo[head]; - - /* map descriptor and save caller data */ if (is_sec1) { while (edesc) { edesc->desc.hdr1 = edesc->desc.hdr; @@ -321,10 +290,48 @@ next: edesc = edesc->next_desc; } } else { - request->dma_desc = dma_map_single(dev, desc, - TALITOS_DESC_SIZE, + request->dma_desc = dma_map_single(dev, desc, TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL); } +} + +/** + * talitos_submit - submits a descriptor to the device for processing + * @dev: the SEC device to be used + * @ch: the SEC device channel to be used + * @desc: the descriptor to be processed by the device + * @callback: whom to call when processing is complete + * @context: a handle for use by caller (optional) + * + * desc must contain valid dma-mapped (bus physical) address pointers. + * callback must check err and feedback in descriptor header + * for device processing status. + */ +static int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc, + void (*callback)(struct device *dev, + struct talitos_desc *desc, + void *context, int error), + void *context) +{ + struct talitos_private *priv = dev_get_drvdata(dev); + struct talitos_request *request; + unsigned long flags; + int head; + bool is_sec1 = has_ftr_sec1(priv); + + spin_lock_irqsave(&priv->chan[ch].head_lock, flags); + + if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) { + /* h/w fifo is full */ + spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags); + return -EAGAIN; + } + + head = priv->chan[ch].head; + request = &priv->chan[ch].fifo[head]; + + /* map descriptor and save caller data */ + dma_map_request(dev, request, desc, is_sec1); request->callback = callback; request->context = context; From f8713d9e6091755dd30f7f1cfa25f8440cddf81b Mon Sep 17 00:00:00 2001 From: Paul Louvel Date: Thu, 7 May 2026 16:41:51 +0200 Subject: [PATCH 102/196] crypto: talitos - move code in current_desc_hdr() into a standalone function Previously added code in current_desc_hdr() in order to add support for searching an offending descriptor inside a descriptor chain. Move that code into a standalone function to improve readability. Cc: stable@vger.kernel.org Signed-off-by: Paul Louvel Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index d8f838add0ff..c9c5d195b317 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -520,6 +520,24 @@ DEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0_DONE) DEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE) DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE) +static __be32 search_desc_hdr_in_request(struct talitos_request *request, + dma_addr_t cur_desc, bool is_sec1) +{ + struct talitos_edesc *edesc; + + if (request->dma_desc == cur_desc) { + return request->desc->hdr; + } else if (is_sec1) { + edesc = container_of(request->desc, struct talitos_edesc, desc); + while (edesc->next_desc) { + if (edesc->desc.next_desc == cpu_to_be32(cur_desc)) + return edesc->next_desc->desc.hdr1; + edesc = edesc->next_desc; + } + } + return 0; +} + /* * locate current (offending) descriptor */ @@ -528,7 +546,6 @@ static __be32 current_desc_hdr(struct device *dev, int ch) struct talitos_private *priv = dev_get_drvdata(dev); bool is_sec1 = has_ftr_sec1(priv); struct talitos_request *request; - struct talitos_edesc *edesc; int tail, iter; dma_addr_t cur_desc; __be32 hdr = 0; @@ -546,21 +563,7 @@ static __be32 current_desc_hdr(struct device *dev, int ch) do { request = &priv->chan[ch].fifo[iter]; - if (request->dma_desc == cur_desc) { - hdr = request->desc->hdr; - } else if (is_sec1) { - edesc = container_of(request->desc, - struct talitos_edesc, desc); - while (edesc->next_desc) { - if (edesc->desc.next_desc == - cpu_to_be32(cur_desc)) { - hdr = edesc->next_desc->desc.hdr1; - break; - } - edesc = edesc->next_desc; - } - } - + hdr = search_desc_hdr_in_request(request, cur_desc, is_sec1); if (hdr) break; From 59b5d899e33701665f18abe6bebf987427876e3e Mon Sep 17 00:00:00 2001 From: Paul Louvel Date: Thu, 7 May 2026 16:41:52 +0200 Subject: [PATCH 103/196] crypto: talitos/hash - prepare SEC1 descriptor chaining, remove additional descriptor Currently, when SEC1 has buffered data (nbuf != 0), the ahash code creates an additional descriptor on the fly inside common_nonsnoop_hash() to handle the remainder of the data. This approach is incompatible with the arbitrary-length descriptor chaining that follows. Remove the "additional descriptor" logic from common_nonsnoop_hash() and common_nonsnoop_hash_unmap(). Also remove the nbytes adjustment for SEC1 in ahash_edesc_alloc() that subtracted nbuf. Cc: stable@vger.kernel.org Signed-off-by: Paul Louvel Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 101 +++------------------------------------ 1 file changed, 6 insertions(+), 95 deletions(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index c9c5d195b317..72d9c50b055e 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -1788,15 +1788,9 @@ static void common_nonsnoop_hash_unmap(struct device *dev, struct talitos_private *priv = dev_get_drvdata(dev); bool is_sec1 = has_ftr_sec1(priv); struct talitos_desc *desc = &edesc->desc; - struct talitos_desc *desc2; - - if (desc->next_desc) - desc2 = &edesc->next_desc->desc; unmap_single_talitos_ptr(dev, &desc->ptr[5], DMA_FROM_DEVICE); - if (desc->next_desc && - desc->ptr[5].ptr != desc2->ptr[5].ptr) - unmap_single_talitos_ptr(dev, &desc2->ptr[5], DMA_FROM_DEVICE); + if (req_ctx->last_desc) memcpy(areq->result, req_ctx->hw_context, crypto_ahash_digestsize(tfm)); @@ -1808,13 +1802,6 @@ static void common_nonsnoop_hash_unmap(struct device *dev, if (from_talitos_ptr_len(&desc->ptr[1], is_sec1)) unmap_single_talitos_ptr(dev, &desc->ptr[1], DMA_TO_DEVICE); - else if (desc->next_desc) - unmap_single_talitos_ptr(dev, &desc2->ptr[1], - DMA_TO_DEVICE); - - if (is_sec1 && req_ctx->nbuf) - unmap_single_talitos_ptr(dev, &desc->ptr[3], - DMA_TO_DEVICE); if (edesc->dma_len) dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len, @@ -1922,9 +1909,6 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc, to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen, is_sec1); - if (is_sec1 && req_ctx->nbuf) - length -= req_ctx->nbuf; - sg_count = edesc->src_nents ?: 1; if (is_sec1 && sg_count > 1) sg_copy_to_buffer(req_ctx->psrc, sg_count, edesc->buf, length); @@ -1934,16 +1918,10 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc, /* * data in */ - if (is_sec1 && req_ctx->nbuf) { - map_single_talitos_ptr(dev, &desc->ptr[3], req_ctx->nbuf, - req_ctx->buf[req_ctx->buf_idx], - DMA_TO_DEVICE); - } else { - sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc, - &desc->ptr[3], sg_count, 0, 0); - if (sg_count > 1) - sync_needed = true; - } + sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc, + &desc->ptr[3], sg_count, 0, 0); + if (sg_count > 1) + sync_needed = true; /* fifth DWORD empty */ @@ -1963,49 +1941,6 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc, if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0) talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]); - if (is_sec1 && req_ctx->nbuf && length) { - struct talitos_edesc *edesc2; - struct talitos_desc *desc2; - - edesc2 = kzalloc(sizeof(*edesc2), - areq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? - GFP_KERNEL : - GFP_ATOMIC); - if (!edesc2) { - ret = -ENOMEM; - goto err; - } - edesc->next_desc = edesc2; - - desc2 = &edesc2->desc; - - desc2->hdr = desc->hdr; - desc2->hdr &= ~DESC_HDR_MODE0_MDEU_INIT; - desc->hdr &= ~DESC_HDR_MODE0_MDEU_PAD; - desc->hdr |= DESC_HDR_MODE0_MDEU_CONT; - desc->hdr &= ~DESC_HDR_DONE_NOTIFY; - - if (desc->ptr[1].ptr) - copy_talitos_ptr(&desc2->ptr[1], &desc->ptr[1], - is_sec1); - else - map_single_talitos_ptr_nosync(dev, &desc2->ptr[1], - req_ctx->hw_context_size, - req_ctx->hw_context, - DMA_TO_DEVICE); - copy_talitos_ptr(&desc2->ptr[2], &desc->ptr[2], is_sec1); - sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc, - &desc2->ptr[3], sg_count, 0, 0); - if (sg_count > 1) - sync_needed = true; - copy_talitos_ptr(&desc2->ptr[5], &desc->ptr[5], is_sec1); - if (req_ctx->last_desc) - map_single_talitos_ptr_nosync(dev, &desc->ptr[5], - req_ctx->hw_context_size, - req_ctx->hw_context, - DMA_FROM_DEVICE); - } - if (sync_needed) dma_sync_single_for_device(dev, edesc->dma_link_tbl, edesc->dma_len, DMA_BIDIRECTIONAL); @@ -2028,11 +1963,6 @@ static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq, struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); - struct talitos_private *priv = dev_get_drvdata(ctx->dev); - bool is_sec1 = has_ftr_sec1(priv); - - if (is_sec1) - nbytes -= req_ctx->nbuf; return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0, nbytes, 0, 0, 0, areq->base.flags, false); @@ -2051,8 +1981,6 @@ static int ahash_process_req_one(struct ahash_request *areq, unsigned int nbytes unsigned int nsg; int nents; struct device *dev = ctx->dev; - struct talitos_private *priv = dev_get_drvdata(dev); - bool is_sec1 = has_ftr_sec1(priv); u8 *ctx_buf = req_ctx->buf[req_ctx->buf_idx]; if (!req_ctx->last_desc && (nbytes + req_ctx->nbuf <= blocksize)) { @@ -2084,30 +2012,13 @@ static int ahash_process_req_one(struct ahash_request *areq, unsigned int nbytes } /* Chain in any previously buffered data */ - if (!is_sec1 && req_ctx->nbuf) { + if (req_ctx->nbuf) { nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1; sg_init_table(req_ctx->bufsl, nsg); sg_set_buf(req_ctx->bufsl, ctx_buf, req_ctx->nbuf); if (nsg > 1) sg_chain(req_ctx->bufsl, 2, req_ctx->request_sl); req_ctx->psrc = req_ctx->bufsl; - } else if (is_sec1 && req_ctx->nbuf && req_ctx->nbuf < blocksize) { - int offset; - - if (nbytes_to_hash > blocksize) - offset = blocksize - req_ctx->nbuf; - else - offset = nbytes_to_hash - req_ctx->nbuf; - nents = sg_nents_for_len(req_ctx->request_sl, offset); - if (nents < 0) { - dev_err(dev, "Invalid number of src SG.\n"); - return nents; - } - sg_copy_to_buffer(req_ctx->request_sl, nents, - ctx_buf + req_ctx->nbuf, offset); - req_ctx->nbuf += offset; - req_ctx->psrc = scatterwalk_ffwd(req_ctx->bufsl, req_ctx->request_sl, - offset); } else req_ctx->psrc = req_ctx->request_sl; From f1ede6d95d8ad3b32c6a552d2baab805bd00fc38 Mon Sep 17 00:00:00 2001 From: Paul Louvel Date: Thu, 7 May 2026 16:41:53 +0200 Subject: [PATCH 104/196] crypto: talitos/hash - use descriptor chaining for SEC1 instead of workqueue Rework the SEC1 ahash implementation to build a chain of hardware descriptors, replacing the previous approach of submitting one descriptor at a time via a workqueue, introduced by commit 655ef638a2bc ("crypto: talitos - fix SEC1 32k ahash request limitation"). Introduce ahash_process_req_prepare() which iterates over the request data, allocating enough descriptors to cover the entire ahash request. The new fields (bufsl, src, first, last) are added to talitos_edesc for this purpose. common_nonsnoop_hash() no longer calls talitos_submit(); it only maps and sets up the descriptor. Submission is now done by the caller after the chain is built. ahash_free_desc_list_from() takes over calling common_nonsnoop_hash_unmap() for each descriptor during cleanup. Compared to the workqueue based solution, request are slightly faster since there is no more scheduling latency induced by the workqueue, and only one interrupt is generated by the device at the end of a chain. Commit 655ef638a2bc ("crypto: talitos - fix SEC1 32k ahash request limitation") : $ /usr/libexec/libkcapi/sha256sum ./test_5M.bin 013c5609d63c... ./test_5M.bin real 0m 0.41s user 0m 0.01s sys 0m 0.07s Now : $ /usr/libexec/libkcapi/sha256sum ./test_5M.bin 013c5609d63c... ./test_5M.bin real 0m 0.33s user 0m 0.01s sys 0m 0.20s Tested on a system with an MPC885 SoC featuring the SEC1 Lite. The increase in sys time is due to the fact that commit 37b5e8897eb5 ("crypto: talitos - chain in buffered data for ahash on SEC1") can no longer be applied. Cc: stable@vger.kernel.org Signed-off-by: Paul Louvel Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 168 ++++++++++++++++++++++++--------------- drivers/crypto/talitos.h | 10 +++ 2 files changed, 115 insertions(+), 63 deletions(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 72d9c50b055e..5f8ee1f1346f 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -1791,12 +1791,12 @@ static void common_nonsnoop_hash_unmap(struct device *dev, unmap_single_talitos_ptr(dev, &desc->ptr[5], DMA_FROM_DEVICE); - if (req_ctx->last_desc) + if (edesc->last && req_ctx->last_request) memcpy(areq->result, req_ctx->hw_context, crypto_ahash_digestsize(tfm)); - if (req_ctx->psrc) - talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0); + if (edesc->src) + talitos_sg_unmap(dev, edesc, edesc->src, NULL, 0, 0); /* When using hashctx-in, must unmap it. */ if (from_talitos_ptr_len(&desc->ptr[1], is_sec1)) @@ -1808,12 +1808,14 @@ static void common_nonsnoop_hash_unmap(struct device *dev, DMA_BIDIRECTIONAL); } -static void free_edesc_list_from(struct talitos_edesc *edesc) +static void free_edesc_list_from(struct ahash_request *areq, struct talitos_edesc *edesc) { + struct talitos_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); struct talitos_edesc *next; while (edesc) { next = edesc->next_desc; + common_nonsnoop_hash_unmap(ctx->dev, edesc, areq); kfree(edesc); edesc = next; } @@ -1828,19 +1830,18 @@ static void ahash_done(struct device *dev, container_of(desc, struct talitos_edesc, desc); struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); + if (!req_ctx->last_desc && req_ctx->to_hash_later) { /* Position any partial block for next update/final/finup */ req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1; req_ctx->nbuf = req_ctx->to_hash_later; } - common_nonsnoop_hash_unmap(dev, edesc, areq); - free_edesc_list_from(edesc); + free_edesc_list_from(areq, edesc); - if (err) { - ahash_request_complete(areq, err); - return; - } + ahash_request_complete(areq, err); + + return; req_ctx->remaining_ahash_request_bytes -= req_ctx->current_ahash_request_bytes; @@ -1874,18 +1875,15 @@ static void talitos_handle_buggy_hash(struct talitos_ctx *ctx, (char *)padded_hash, DMA_TO_DEVICE); } -static int common_nonsnoop_hash(struct talitos_edesc *edesc, - struct ahash_request *areq, unsigned int length, - void (*callback) (struct device *dev, - struct talitos_desc *desc, - void *context, int error)) +static void common_nonsnoop_hash(struct talitos_edesc *edesc, + struct ahash_request *areq, + unsigned int length) { struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); struct device *dev = ctx->dev; struct talitos_desc *desc = &edesc->desc; - int ret; bool sync_needed = false; struct talitos_private *priv = dev_get_drvdata(dev); bool is_sec1 = has_ftr_sec1(priv); @@ -1894,7 +1892,7 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc, /* first DWORD empty */ /* hash context in */ - if (!req_ctx->first_desc || req_ctx->swinit) { + if (!edesc->first || !req_ctx->first_desc || req_ctx->swinit) { map_single_talitos_ptr_nosync(dev, &desc->ptr[1], req_ctx->hw_context_size, req_ctx->hw_context, @@ -1911,22 +1909,22 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc, sg_count = edesc->src_nents ?: 1; if (is_sec1 && sg_count > 1) - sg_copy_to_buffer(req_ctx->psrc, sg_count, edesc->buf, length); + sg_copy_to_buffer(edesc->src, sg_count, edesc->buf, length); else if (length) - sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count, - DMA_TO_DEVICE); + sg_count = dma_map_sg(dev, edesc->src, sg_count, DMA_TO_DEVICE); + /* * data in */ - sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc, - &desc->ptr[3], sg_count, 0, 0); + sg_count = talitos_sg_map(dev, edesc->src, length, edesc, &desc->ptr[3], + sg_count, 0, 0); if (sg_count > 1) sync_needed = true; /* fifth DWORD empty */ /* hash/HMAC out -or- hash context out */ - if (req_ctx->last_desc) + if (edesc->last && req_ctx->last_request) map_single_talitos_ptr(dev, &desc->ptr[5], crypto_ahash_digestsize(tfm), req_ctx->hw_context, DMA_FROM_DEVICE); @@ -1944,30 +1942,89 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc, if (sync_needed) dma_sync_single_for_device(dev, edesc->dma_link_tbl, edesc->dma_len, DMA_BIDIRECTIONAL); - - ret = talitos_submit(dev, ctx->ch, desc, callback, - areq); - if (ret != -EINPROGRESS) - goto err; - - return -EINPROGRESS; -err: - common_nonsnoop_hash_unmap(dev, edesc, areq); - kfree(edesc); - return ret; } static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq, + struct scatterlist *src, unsigned int nbytes) { struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); - struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); - return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0, + return talitos_edesc_alloc(ctx->dev, src, NULL, NULL, 0, nbytes, 0, 0, 0, areq->base.flags, false); } +static struct talitos_edesc * +ahash_process_req_prepare(struct ahash_request *areq, unsigned int nbytes, + unsigned int blocksize, bool is_sec1) +{ + struct talitos_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); + struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); + struct talitos_edesc *first = NULL, *prev_edesc = NULL, *edesc; + size_t desc_max = is_sec1 ? TALITOS1_MAX_DATA_LEN : SIZE_MAX; + struct scatterlist tmp[2]; + size_t to_hash_this_desc; + struct scatterlist *src; + size_t offset = 0; + + do { + src = scatterwalk_ffwd(tmp, req_ctx->psrc, offset); + + to_hash_this_desc = + min(nbytes, ALIGN_DOWN(desc_max, blocksize)); + + /* Allocate extended descriptor */ + edesc = ahash_edesc_alloc(areq, src, to_hash_this_desc); + if (IS_ERR(edesc)) { + if (first) + free_edesc_list_from(areq, first); + return edesc; + } + + edesc->src = + scatterwalk_ffwd(edesc->bufsl, req_ctx->psrc, offset); + edesc->desc.hdr = ctx->desc_hdr_template; + edesc->first = offset == 0; + edesc->last = nbytes - to_hash_this_desc == 0; + + /* On last one, request SEC to pad; otherwise continue */ + if (req_ctx->last_request && edesc->last) + edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD; + else + edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT; + + /* request SEC to INIT hash. */ + if (req_ctx->first_desc && edesc->first && !req_ctx->swinit) + edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT; + + /* + * When the tfm context has a keylen, it's an HMAC. + * A first or last (ie. not middle) descriptor must request HMAC. + */ + if (ctx->keylen && ((req_ctx->first_desc && edesc->first) || + (req_ctx->last_request && edesc->last))) + edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC; + + /* clear the DN bit */ + if (is_sec1 && !edesc->last) + edesc->desc.hdr &= ~DESC_HDR_DONE_NOTIFY; + + common_nonsnoop_hash(edesc, areq, to_hash_this_desc); + + offset += to_hash_this_desc; + nbytes -= to_hash_this_desc; + + if (!prev_edesc) + first = edesc; + else + prev_edesc->next_desc = edesc; + prev_edesc = edesc; + } while (nbytes); + + return first; +} + static int ahash_process_req_one(struct ahash_request *areq, unsigned int nbytes) { struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); @@ -1976,14 +2033,16 @@ static int ahash_process_req_one(struct ahash_request *areq, unsigned int nbytes struct talitos_edesc *edesc; unsigned int blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); + bool is_sec1 = has_ftr_sec1(dev_get_drvdata(ctx->dev)); unsigned int nbytes_to_hash; unsigned int to_hash_later; unsigned int nsg; int nents; struct device *dev = ctx->dev; u8 *ctx_buf = req_ctx->buf[req_ctx->buf_idx]; + int ret; - if (!req_ctx->last_desc && (nbytes + req_ctx->nbuf <= blocksize)) { + if (!req_ctx->last_request && (nbytes + req_ctx->nbuf <= blocksize)) { /* Buffer up to one whole block */ nents = sg_nents_for_len(req_ctx->request_sl, nbytes); if (nents < 0) { @@ -2000,7 +2059,7 @@ static int ahash_process_req_one(struct ahash_request *areq, unsigned int nbytes nbytes_to_hash = nbytes + req_ctx->nbuf; to_hash_later = nbytes_to_hash & (blocksize - 1); - if (req_ctx->last_desc) + if (req_ctx->last_request) to_hash_later = 0; else if (to_hash_later) /* There is a partial block. Hash the full block(s) now */ @@ -2035,30 +2094,16 @@ static int ahash_process_req_one(struct ahash_request *areq, unsigned int nbytes } req_ctx->to_hash_later = to_hash_later; - /* Allocate extended descriptor */ - edesc = ahash_edesc_alloc(req_ctx->areq, nbytes_to_hash); + edesc = ahash_process_req_prepare(areq, nbytes_to_hash, blocksize, + is_sec1); if (IS_ERR(edesc)) return PTR_ERR(edesc); - edesc->desc.hdr = ctx->desc_hdr_template; + ret = talitos_submit(dev, ctx->ch, &edesc->desc, ahash_done, areq); + if (ret != -EINPROGRESS) + free_edesc_list_from(areq, edesc); - /* On last one, request SEC to pad; otherwise continue */ - if (req_ctx->last_desc) - edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD; - else - edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT; - - /* request SEC to INIT hash. */ - if (req_ctx->first_desc && !req_ctx->swinit) - edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT; - - /* When the tfm context has a keylen, it's an HMAC. - * A first or last (ie. not middle) descriptor must request HMAC. - */ - if (ctx->keylen && (req_ctx->first_desc || req_ctx->last_desc)) - edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC; - - return common_nonsnoop_hash(edesc, req_ctx->areq, nbytes_to_hash, ahash_done); + return ret; } static void sec1_ahash_process_remaining(struct work_struct *work) @@ -2102,16 +2147,13 @@ static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes) req_ctx->remaining_ahash_request_bytes = nbytes; if (is_sec1) { - if (nbytes > TALITOS1_MAX_DATA_LEN) - nbytes = TALITOS1_MAX_DATA_LEN; - else if (req_ctx->last_request) + if (req_ctx->last_request) req_ctx->last_desc = 1; } req_ctx->current_ahash_request_bytes = nbytes; - return ahash_process_req_one(req_ctx->areq, - req_ctx->current_ahash_request_bytes); + return ahash_process_req_one(req_ctx->areq, nbytes); } static int ahash_init(struct ahash_request *areq) diff --git a/drivers/crypto/talitos.h b/drivers/crypto/talitos.h index 1553afa57b0b..d4ff8d589f46 100644 --- a/drivers/crypto/talitos.h +++ b/drivers/crypto/talitos.h @@ -44,6 +44,11 @@ struct talitos_desc { /* * talitos_edesc - s/w-extended descriptor + * @bufsl: scatterlist buffer + * @src: pointer to input scatterlist + * @first: first descriptor of a chain + * @last: last descriptor of a chain + * * @src_nents: number of segments in input scatterlist * @dst_nents: number of segments in output scatterlist * @iv_dma: dma address of iv for checking continuity and link table @@ -59,6 +64,11 @@ struct talitos_desc { * of link_tbl data */ struct talitos_edesc { + struct scatterlist bufsl[2]; + struct scatterlist *src; + int first; + int last; + int src_nents; int dst_nents; dma_addr_t iv_dma; From be4802afb1700534e48cb776d0d1e772c27de130 Mon Sep 17 00:00:00 2001 From: Paul Louvel Date: Thu, 7 May 2026 16:41:54 +0200 Subject: [PATCH 105/196] crypto: talitos/hash - drop workqueue mechanism for SEC1 Now that SEC1 hash uses hardware descriptor chaining instead of a workqueue to process requests exceeding TALITOS1_MAX_DATA_LEN, the workqueue code is no longer needed. Remove sec1_ahash_process_remaining(), the related fields from talitos_ahash_req_ctx (request_bufsl, areq, request_sl, remaining_ahash_request_bytes, current_ahash_request_bytes, sec1_ahash_process_remaining), the dead code in ahash_done(), and simplify ahash_process_req() to call ahash_process_req_one() directly with the original areq->src and areq->nbytes. Cc: stable@vger.kernel.org Signed-off-by: Paul Louvel Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 80 ++++------------------------------------ 1 file changed, 7 insertions(+), 73 deletions(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 5f8ee1f1346f..fe38bc6aaaab 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -12,7 +12,6 @@ * All rights reserved. */ -#include #include #include #include @@ -952,13 +951,6 @@ struct talitos_ahash_req_ctx { unsigned int nbuf; struct scatterlist bufsl[2]; struct scatterlist *psrc; - - struct scatterlist request_bufsl[2]; - struct ahash_request *areq; - struct scatterlist *request_sl; - unsigned int remaining_ahash_request_bytes; - unsigned int current_ahash_request_bytes; - struct work_struct sec1_ahash_process_remaining; }; struct talitos_export_state { @@ -1840,18 +1832,6 @@ static void ahash_done(struct device *dev, free_edesc_list_from(areq, edesc); ahash_request_complete(areq, err); - - return; - - req_ctx->remaining_ahash_request_bytes -= - req_ctx->current_ahash_request_bytes; - - if (!req_ctx->remaining_ahash_request_bytes) { - ahash_request_complete(areq, 0); - return; - } - - schedule_work(&req_ctx->sec1_ahash_process_remaining); } /* @@ -2044,12 +2024,12 @@ static int ahash_process_req_one(struct ahash_request *areq, unsigned int nbytes if (!req_ctx->last_request && (nbytes + req_ctx->nbuf <= blocksize)) { /* Buffer up to one whole block */ - nents = sg_nents_for_len(req_ctx->request_sl, nbytes); + nents = sg_nents_for_len(areq->src, nbytes); if (nents < 0) { dev_err(dev, "Invalid number of src SG.\n"); return nents; } - sg_copy_to_buffer(req_ctx->request_sl, nents, + sg_copy_to_buffer(areq->src, nents, ctx_buf + req_ctx->nbuf, nbytes); req_ctx->nbuf += nbytes; return 0; @@ -2076,18 +2056,18 @@ static int ahash_process_req_one(struct ahash_request *areq, unsigned int nbytes sg_init_table(req_ctx->bufsl, nsg); sg_set_buf(req_ctx->bufsl, ctx_buf, req_ctx->nbuf); if (nsg > 1) - sg_chain(req_ctx->bufsl, 2, req_ctx->request_sl); + sg_chain(req_ctx->bufsl, 2, areq->src); req_ctx->psrc = req_ctx->bufsl; } else - req_ctx->psrc = req_ctx->request_sl; + req_ctx->psrc = areq->src; if (to_hash_later) { - nents = sg_nents_for_len(req_ctx->request_sl, nbytes); + nents = sg_nents_for_len(areq->src, nbytes); if (nents < 0) { dev_err(dev, "Invalid number of src SG.\n"); return nents; } - sg_pcopy_to_buffer(req_ctx->request_sl, nents, + sg_pcopy_to_buffer(areq->src, nents, req_ctx->buf[(req_ctx->buf_idx + 1) & 1], to_hash_later, nbytes - to_hash_later); @@ -2106,54 +2086,9 @@ static int ahash_process_req_one(struct ahash_request *areq, unsigned int nbytes return ret; } -static void sec1_ahash_process_remaining(struct work_struct *work) -{ - struct talitos_ahash_req_ctx *req_ctx = - container_of(work, struct talitos_ahash_req_ctx, - sec1_ahash_process_remaining); - int err = 0; - - req_ctx->request_sl = scatterwalk_ffwd(req_ctx->request_bufsl, - req_ctx->request_sl, TALITOS1_MAX_DATA_LEN); - - if (req_ctx->remaining_ahash_request_bytes > TALITOS1_MAX_DATA_LEN) - req_ctx->current_ahash_request_bytes = TALITOS1_MAX_DATA_LEN; - else { - req_ctx->current_ahash_request_bytes = - req_ctx->remaining_ahash_request_bytes; - - if (req_ctx->last_request) - req_ctx->last_desc = 1; - } - - err = ahash_process_req_one(req_ctx->areq, - req_ctx->current_ahash_request_bytes); - - if (err != -EINPROGRESS) - ahash_request_complete(req_ctx->areq, err); -} - static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes) { - struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); - struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); - struct device *dev = ctx->dev; - struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); - struct talitos_private *priv = dev_get_drvdata(dev); - bool is_sec1 = has_ftr_sec1(priv); - - req_ctx->areq = areq; - req_ctx->request_sl = areq->src; - req_ctx->remaining_ahash_request_bytes = nbytes; - - if (is_sec1) { - if (req_ctx->last_request) - req_ctx->last_desc = 1; - } - - req_ctx->current_ahash_request_bytes = nbytes; - - return ahash_process_req_one(req_ctx->areq, nbytes); + return ahash_process_req_one(areq, nbytes); } static int ahash_init(struct ahash_request *areq) @@ -2176,7 +2111,6 @@ static int ahash_init(struct ahash_request *areq) req_ctx->hw_context_size = size; req_ctx->last_request = 0; req_ctx->last_desc = 0; - INIT_WORK(&req_ctx->sec1_ahash_process_remaining, sec1_ahash_process_remaining); dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size, DMA_TO_DEVICE); From 8bcf00671400ac3b3a4cc3011e6c1496dbd880fd Mon Sep 17 00:00:00 2001 From: Paul Louvel Date: Thu, 7 May 2026 16:41:55 +0200 Subject: [PATCH 106/196] crypto: talitos/hash - rename first_desc/last_desc to first_request/last_request In talitos_ahash_req_ctx and talitos_export_state, the fields first_desc and last_desc describe request-level (not descriptor-level) state. Rename them to first_request and last_request for clarity. last_desc is also removed from talitos_ahash_req_ctx as it is no longer used. Cc: stable@vger.kernel.org Signed-off-by: Paul Louvel Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index fe38bc6aaaab..1d108aec4ab3 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -944,8 +944,7 @@ struct talitos_ahash_req_ctx { u8 buf[2][HASH_MAX_BLOCK_SIZE]; int buf_idx; unsigned int swinit; - unsigned int first_desc; - unsigned int last_desc; + unsigned int first_request; unsigned int last_request; unsigned int to_hash_later; unsigned int nbuf; @@ -957,8 +956,8 @@ struct talitos_export_state { u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)]; u8 buf[HASH_MAX_BLOCK_SIZE]; unsigned int swinit; - unsigned int first_desc; - unsigned int last_desc; + unsigned int first_request; + unsigned int last_request; unsigned int to_hash_later; unsigned int nbuf; }; @@ -1822,8 +1821,7 @@ static void ahash_done(struct device *dev, container_of(desc, struct talitos_edesc, desc); struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); - - if (!req_ctx->last_desc && req_ctx->to_hash_later) { + if (!req_ctx->last_request && req_ctx->to_hash_later) { /* Position any partial block for next update/final/finup */ req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1; req_ctx->nbuf = req_ctx->to_hash_later; @@ -1872,7 +1870,7 @@ static void common_nonsnoop_hash(struct talitos_edesc *edesc, /* first DWORD empty */ /* hash context in */ - if (!edesc->first || !req_ctx->first_desc || req_ctx->swinit) { + if (!edesc->first || !req_ctx->first_request || req_ctx->swinit) { map_single_talitos_ptr_nosync(dev, &desc->ptr[1], req_ctx->hw_context_size, req_ctx->hw_context, @@ -1880,7 +1878,7 @@ static void common_nonsnoop_hash(struct talitos_edesc *edesc, req_ctx->swinit = 0; } /* Indicate next op is not the first. */ - req_ctx->first_desc = 0; + req_ctx->first_request = 0; /* HMAC key */ if (ctx->keylen) @@ -1975,14 +1973,14 @@ ahash_process_req_prepare(struct ahash_request *areq, unsigned int nbytes, edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT; /* request SEC to INIT hash. */ - if (req_ctx->first_desc && edesc->first && !req_ctx->swinit) + if (req_ctx->first_request && edesc->first && !req_ctx->swinit) edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT; /* * When the tfm context has a keylen, it's an HMAC. * A first or last (ie. not middle) descriptor must request HMAC. */ - if (ctx->keylen && ((req_ctx->first_desc && edesc->first) || + if (ctx->keylen && ((req_ctx->first_request && edesc->first) || (req_ctx->last_request && edesc->last))) edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC; @@ -2103,14 +2101,13 @@ static int ahash_init(struct ahash_request *areq) /* Initialize the context */ req_ctx->buf_idx = 0; req_ctx->nbuf = 0; - req_ctx->first_desc = 1; /* first_desc indicates h/w must init its context */ + req_ctx->first_request = 1; req_ctx->swinit = 0; /* assume h/w init of context */ size = (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE) ? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256 : TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512; req_ctx->hw_context_size = size; req_ctx->last_request = 0; - req_ctx->last_desc = 0; dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size, DMA_TO_DEVICE); @@ -2202,8 +2199,8 @@ static int ahash_export(struct ahash_request *areq, void *out) req_ctx->hw_context_size); memcpy(export->buf, req_ctx->buf[req_ctx->buf_idx], req_ctx->nbuf); export->swinit = req_ctx->swinit; - export->first_desc = req_ctx->first_desc; - export->last_desc = req_ctx->last_desc; + export->first_request = req_ctx->first_request; + export->last_request = req_ctx->last_request; export->to_hash_later = req_ctx->to_hash_later; export->nbuf = req_ctx->nbuf; @@ -2228,8 +2225,8 @@ static int ahash_import(struct ahash_request *areq, const void *in) memcpy(req_ctx->hw_context, export->hw_context, size); memcpy(req_ctx->buf[0], export->buf, export->nbuf); req_ctx->swinit = export->swinit; - req_ctx->first_desc = export->first_desc; - req_ctx->last_desc = export->last_desc; + req_ctx->first_request = export->first_request; + req_ctx->last_request = export->last_request; req_ctx->to_hash_later = export->to_hash_later; req_ctx->nbuf = export->nbuf; From 907ae6088c82c9abae2d26477fddd60df6ad003b Mon Sep 17 00:00:00 2001 From: Paul Louvel Date: Thu, 7 May 2026 16:41:56 +0200 Subject: [PATCH 107/196] crypto: talitos/hash - remove useless wrapper ahash_process_req() was a wrapper used in commit 655ef638a2bc ("crypto: talitos - fix SEC1 32k ahash request limitation"). Rename ahash_process_req_one() to ahash_process_req() and remove the wrapper. Cc: stable@vger.kernel.org Signed-off-by: Paul Louvel Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 1d108aec4ab3..551b41e813f0 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -2003,7 +2003,7 @@ ahash_process_req_prepare(struct ahash_request *areq, unsigned int nbytes, return first; } -static int ahash_process_req_one(struct ahash_request *areq, unsigned int nbytes) +static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes) { struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); @@ -2084,11 +2084,6 @@ static int ahash_process_req_one(struct ahash_request *areq, unsigned int nbytes return ret; } -static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes) -{ - return ahash_process_req_one(areq, nbytes); -} - static int ahash_init(struct ahash_request *areq) { struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); From 6e12daff6ec125102a6fdcafc5aa7199f7ce8933 Mon Sep 17 00:00:00 2001 From: Paul Louvel Date: Thu, 7 May 2026 16:41:57 +0200 Subject: [PATCH 108/196] crypto: talitos/hash - fix SEC2 64k - 1 ahash request limitation The problem described in commit 655ef638a2bc ("crypto: talitos - fix SEC1 32k ahash request limitation") also apply for the SEC2 hardware, but with a limitation of 64k - 1 bytes. Split ahash_done() into SEC1 and SEC2 paths: SEC1 continues to free the whole descriptor list at once, while SEC2 now iterates through descriptors one by one, submitting the next only after the previous completes, which is required since SEC2 cannot chain descriptors in hardware. Cc: stable@vger.kernel.org Fixes: c662b043cdca ("crypto: af_alg/hash: Support MSG_SPLICE_PAGES") Signed-off-by: Paul Louvel Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 49 ++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 551b41e813f0..2d69ee608665 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -1820,16 +1820,46 @@ static void ahash_done(struct device *dev, struct talitos_edesc *edesc = container_of(desc, struct talitos_edesc, desc); struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); + bool is_sec1 = has_ftr_sec1(dev_get_drvdata(dev)); + struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); + struct talitos_edesc *next; - if (!req_ctx->last_request && req_ctx->to_hash_later) { - /* Position any partial block for next update/final/finup */ - req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1; - req_ctx->nbuf = req_ctx->to_hash_later; + if (is_sec1) { + if (!req_ctx->last_request && req_ctx->to_hash_later) { + /* Position any partial block for next update/final/finup */ + req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1; + req_ctx->nbuf = req_ctx->to_hash_later; + } + + free_edesc_list_from(areq, edesc); + ahash_request_complete(areq, err); + } else { + next = edesc->next_desc; + + common_nonsnoop_hash_unmap(dev, edesc, areq); + kfree(edesc); + + if (err) + goto out; + + if (next) { + err = talitos_submit(dev, ctx->ch, &next->desc, + ahash_done, areq); + if (err != -EINPROGRESS) + goto out; + return; + } +out: + if (!req_ctx->last_request && req_ctx->to_hash_later) { + /* Position any partial block for next update/final/finup */ + req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1; + req_ctx->nbuf = req_ctx->to_hash_later; + } + if (err && next) + free_edesc_list_from(areq, next); + ahash_request_complete(areq, err); } - - free_edesc_list_from(areq, edesc); - - ahash_request_complete(areq, err); } /* @@ -1940,7 +1970,8 @@ ahash_process_req_prepare(struct ahash_request *areq, unsigned int nbytes, struct talitos_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); struct talitos_edesc *first = NULL, *prev_edesc = NULL, *edesc; - size_t desc_max = is_sec1 ? TALITOS1_MAX_DATA_LEN : SIZE_MAX; + size_t desc_max = is_sec1 ? TALITOS1_MAX_DATA_LEN : + TALITOS2_MAX_DATA_LEN; struct scatterlist tmp[2]; size_t to_hash_this_desc; struct scatterlist *src; From 463be1c718fb9f07bdce3d51363a17eac4522538 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Thu, 7 May 2026 16:44:16 -0700 Subject: [PATCH 109/196] crypto: talitos - use devm_platform_ioremap_resource() platform_get_resource and devm_ioremap effectively open codes this. The return type of devm_platform_ioremap_resource() is also nice as it has multiple errors that it can return. Because it internally calls devm_request_mem_region(), reg values and sizes cannot overlap. This was manually verified to be the case for all talitos users. Signed-off-by: Rosen Penev Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 2d69ee608665..584508963241 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -3413,7 +3413,6 @@ static int talitos_probe(struct platform_device *ofdev) unsigned int num_channels; int i, err; int stride; - struct resource *res; if (of_property_read_u32(np, "fsl,num-channels", &num_channels)) return -EINVAL; @@ -3432,13 +3431,10 @@ static int talitos_probe(struct platform_device *ofdev) spin_lock_init(&priv->reg_lock); - res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); - if (!res) - return -ENXIO; - priv->reg = devm_ioremap(dev, res->start, resource_size(res)); - if (!priv->reg) { + priv->reg = devm_platform_ioremap_resource(ofdev, 0); + if (IS_ERR(priv->reg)) { dev_err(dev, "failed to of_iomap\n"); - err = -ENOMEM; + err = PTR_ERR(priv->reg); goto err_out; } From 6d827ade51a24e18d81afb9f32756d339520a14c Mon Sep 17 00:00:00 2001 From: Dawei Feng Date: Fri, 8 May 2026 12:24:16 +0800 Subject: [PATCH 110/196] crypto: amlogic - avoid double cleanup in meson_crypto_probe() When meson_allocate_chanlist() fails after a partial allocation, it already unwinds the allocated chanlist state through its local error path. meson_crypto_probe() then jump to error_flow and calls meson_free_chanlist() again, causing the same per-flow resources to be torn down twice. In the reproduced failure path, the second teardown re-entered crypto_engine_exit() on an already destroyed worker and KASAN reported a slab-use-after-free in kthread_destroy_worker(). Prevent double-free by handling partial allocation failures locally within meson_allocate_chanlist() and skipping the outer cleanup path. The bug was first flagged by an experimental analysis tool we are developing for kernel memory-management bugs while analyzing v6.13-rc1. The tool is still under development and is not yet publicly available. The bug was reproduced in a QEMU x86_64 guest booted with KASAN on v7.1, using the reproducer under tools/testing/meson_crypto_probe. The reproducer forces the second dma_alloc_attrs() call in the gxl-crypto probe path to return NULL, making meson_allocate_chanlist() fail after partial initialization. On the unpatched kernel this reliably triggered a slab-use-after-free. With this fix applied, the same reproducer no longer emits any KASAN report and the probe fails cleanly with -ENOMEM. ================================================================== BUG: KASAN: slab-use-after-free in kthread_destroy_worker+0xb2/0xd0 Read of size 8 at addr ff1100010c057a68 by task insmod/265 CPU: 1 UID: 0 PID: 265 Comm: insmod Tainted: G O 7.1.0-rc2-00376-g810af9adc907-dirty #10 PREEMPT(lazy) Tainted: [O]=OOT_MODULE Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.15.0-1 04/01/2014 Call Trace: dump_stack_lvl+0x68/0xa0 print_report+0xcb/0x5e0 ? __virt_addr_valid+0x21d/0x3f0 ? kthread_destroy_worker+0xb2/0xd0 ? kthread_destroy_worker+0xb2/0xd0 kasan_report+0xca/0x100 ? kthread_destroy_worker+0xb2/0xd0 kthread_destroy_worker+0xb2/0xd0 meson_crypto_probe+0x4d0/0xc10 [amlogic_gxl_crypto] platform_probe+0x99/0x140 really_probe+0x1c6/0x6a0 ? __pfx___device_attach_driver+0x10/0x10 __driver_probe_device+0x248/0x310 ? acpi_driver_match_device+0xb0/0x100 driver_probe_device+0x48/0x210 ? __pfx___device_attach_driver+0x10/0x10 __device_attach_driver+0x160/0x320 bus_for_each_drv+0x104/0x190 ? __pfx_bus_for_each_drv+0x10/0x10 ? _raw_spin_unlock_irqrestore+0x2c/0x50 __device_attach+0x19d/0x3b0 ? __pfx___device_attach+0x10/0x10 ? do_raw_spin_unlock+0x53/0x220 device_initial_probe+0x78/0xa0 bus_probe_device+0x5b/0x130 device_add+0xcfd/0x1430 ? __pfx_device_add+0x10/0x10 ? insert_resource+0x34/0x50 ? lock_release+0xc9/0x290 platform_device_add+0x24e/0x590 ? __pfx_meson_crypto_probe_repro_init+0x10/0x10 [meson_crypto_probe_repro] meson_crypto_probe_repro_init+0x330/0xff0 [meson_crypto_probe_repro] do_one_initcall+0xc0/0x450 ? __pfx_do_one_initcall+0x10/0x10 ? _raw_spin_unlock_irqrestore+0x2c/0x50 ? __create_object+0x59/0x80 ? kasan_unpoison+0x27/0x60 do_init_module+0x27b/0x7d0 ? __pfx_do_init_module+0x10/0x10 ? kasan_quarantine_put+0x84/0x1d0 ? kfree+0x32c/0x510 ? load_module+0x561e/0x5ff0 load_module+0x54fe/0x5ff0 ? __pfx_load_module+0x10/0x10 ? security_file_permission+0x20/0x40 ? kernel_read_file+0x23d/0x6e0 ? mmap_region+0x235/0x4a0 ? __pfx_kernel_read_file+0x10/0x10 ? __file_has_perm+0x2c0/0x3e0 init_module_from_file+0x158/0x180 ? __pfx_init_module_from_file+0x10/0x10 ? __lock_acquire+0x45a/0x1ba0 ? idempotent_init_module+0x315/0x610 ? lock_release+0xc9/0x290 ? lockdep_init_map_type+0x4b/0x220 ? do_raw_spin_unlock+0x53/0x220 idempotent_init_module+0x330/0x610 ? __pfx_idempotent_init_module+0x10/0x10 ? __pfx_cred_has_capability.isra.0+0x10/0x10 ? ksys_mmap_pgoff+0x385/0x520 __x64_sys_finit_module+0xbe/0x120 do_syscall_64+0x115/0x690 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f7d6d31690d Code: 5b 41 5c c3 66 0f 1f 84 00 00 00 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d f3 b4 0f 00 f7 d8 > RSP: 002b:00007fffc027ac68 EFLAGS: 00000246 ORIG_RAX: 0000000000000139 RAX: ffffffffffffffda RBX: 000055f7b81967c0 RCX: 00007f7d6d31690d RDX: 0000000000000000 RSI: 000055f79a0d6cd2 RDI: 0000000000000003 RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000003 R11: 0000000000000246 R12: 000055f79a0d6cd2 R13: 000055f7b8196790 R14: 000055f79a0d5888 R15: 000055f7b81968e0 Fixes: 48fe583fe541 ("crypto: amlogic - Add crypto accelerator for amlogic GXL") Cc: stable@vger.kernel.org Signed-off-by: Zilin Guan Signed-off-by: Dawei Feng Signed-off-by: Herbert Xu --- drivers/crypto/amlogic/amlogic-gxl-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/amlogic/amlogic-gxl-core.c b/drivers/crypto/amlogic/amlogic-gxl-core.c index 1c18a5b8470e..6cb33949915f 100644 --- a/drivers/crypto/amlogic/amlogic-gxl-core.c +++ b/drivers/crypto/amlogic/amlogic-gxl-core.c @@ -291,8 +291,8 @@ static int meson_crypto_probe(struct platform_device *pdev) return 0; error_alg: meson_unregister_algs(mc); -error_flow: meson_free_chanlist(mc, MAXFLOW - 1); +error_flow: clk_disable_unprepare(mc->busclk); return err; } From c36faca103a685590281412e47df74b550f71886 Mon Sep 17 00:00:00 2001 From: Abdun Nihaal Date: Fri, 8 May 2026 14:33:45 +0530 Subject: [PATCH 111/196] crypto: safexcel - Fix potential memory leak in safexcel_pci_probe() The memory allocated for priv in safexcel_pci_probe() is not freed in the error paths, as well as in the PCI remove function. Fix this by using device managed allocation. Fixes: 625f269a5a7a ("crypto: inside-secure - add support for PCI based FPGA development board") Signed-off-by: Abdun Nihaal Reviewed-by: Antoine Tenart Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/safexcel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/inside-secure/safexcel.c b/drivers/crypto/inside-secure/safexcel.c index 812ebabd1309..52809e57361a 100644 --- a/drivers/crypto/inside-secure/safexcel.c +++ b/drivers/crypto/inside-secure/safexcel.c @@ -1893,7 +1893,7 @@ static int safexcel_pci_probe(struct pci_dev *pdev, ent->vendor, ent->device, ent->subvendor, ent->subdevice, ent->driver_data); - priv = kzalloc_obj(*priv); + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; From 6b261b9bae589b8bbcaca5ededc0caf0b2f3a0af Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Fri, 8 May 2026 12:57:17 +0200 Subject: [PATCH 112/196] crypto: api - use designated initializers for report structs Use designated initializers for the report structs instead of clearing the struct with memset() and then copying fixed strings with strscpy() at runtime. This keeps the structs zero-initialized, lets the compiler diagnose oversized string literals, and makes the code easier to read. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- crypto/acompress.c | 8 +++----- crypto/aead.c | 10 ++++------ crypto/ahash.c | 8 +++----- crypto/akcipher.c | 8 +++----- crypto/crypto_user.c | 14 ++++++-------- crypto/kpp.c | 8 +++----- crypto/lskcipher.c | 10 ++++------ crypto/rng.c | 8 +++----- crypto/scompress.c | 8 +++----- crypto/shash.c | 8 +++----- crypto/sig.c | 6 +++--- crypto/skcipher.c | 10 ++++------ 12 files changed, 42 insertions(+), 64 deletions(-) diff --git a/crypto/acompress.c b/crypto/acompress.c index 6025c1acce49..032de704eb2c 100644 --- a/crypto/acompress.c +++ b/crypto/acompress.c @@ -51,11 +51,9 @@ static inline struct acomp_alg *crypto_acomp_alg(struct crypto_acomp *tfm) static int __maybe_unused crypto_acomp_report( struct sk_buff *skb, struct crypto_alg *alg) { - struct crypto_report_acomp racomp; - - memset(&racomp, 0, sizeof(racomp)); - - strscpy(racomp.type, "acomp", sizeof(racomp.type)); + struct crypto_report_acomp racomp = { + .type = "acomp", + }; return nla_put(skb, CRYPTOCFGA_REPORT_ACOMP, sizeof(racomp), &racomp); } diff --git a/crypto/aead.c b/crypto/aead.c index e009937bf3a5..045b74c3779f 100644 --- a/crypto/aead.c +++ b/crypto/aead.c @@ -136,13 +136,11 @@ static int crypto_aead_init_tfm(struct crypto_tfm *tfm) static int __maybe_unused crypto_aead_report( struct sk_buff *skb, struct crypto_alg *alg) { - struct crypto_report_aead raead; struct aead_alg *aead = container_of(alg, struct aead_alg, base); - - memset(&raead, 0, sizeof(raead)); - - strscpy(raead.type, "aead", sizeof(raead.type)); - strscpy(raead.geniv, "", sizeof(raead.geniv)); + struct crypto_report_aead raead = { + .type = "aead", + .geniv = "", + }; raead.blocksize = alg->cra_blocksize; raead.maxauthsize = aead->maxauthsize; diff --git a/crypto/ahash.c b/crypto/ahash.c index 7a730324c50e..dd56b0e45c0d 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -789,11 +789,9 @@ static void crypto_ahash_free_instance(struct crypto_instance *inst) static int __maybe_unused crypto_ahash_report( struct sk_buff *skb, struct crypto_alg *alg) { - struct crypto_report_hash rhash; - - memset(&rhash, 0, sizeof(rhash)); - - strscpy(rhash.type, "ahash", sizeof(rhash.type)); + struct crypto_report_hash rhash = { + .type = "ahash", + }; rhash.blocksize = alg->cra_blocksize; rhash.digestsize = __crypto_hash_alg_common(alg)->digestsize; diff --git a/crypto/akcipher.c b/crypto/akcipher.c index dfe87b3ce183..630bb19738be 100644 --- a/crypto/akcipher.c +++ b/crypto/akcipher.c @@ -36,11 +36,9 @@ struct crypto_akcipher_sync_data { static int __maybe_unused crypto_akcipher_report( struct sk_buff *skb, struct crypto_alg *alg) { - struct crypto_report_akcipher rakcipher; - - memset(&rakcipher, 0, sizeof(rakcipher)); - - strscpy(rakcipher.type, "akcipher", sizeof(rakcipher.type)); + struct crypto_report_akcipher rakcipher = { + .type = "akcipher", + }; return nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER, sizeof(rakcipher), &rakcipher); diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index 3187e0d276f9..e8b6ae75f31f 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -70,11 +70,9 @@ static struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact) static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg) { - struct crypto_report_cipher rcipher; - - memset(&rcipher, 0, sizeof(rcipher)); - - strscpy(rcipher.type, "cipher", sizeof(rcipher.type)); + struct crypto_report_cipher rcipher = { + .type = "cipher", + }; rcipher.blocksize = alg->cra_blocksize; rcipher.min_keysize = alg->cra_cipher.cia_min_keysize; @@ -103,10 +101,10 @@ static int crypto_report_one(struct crypto_alg *alg, if (nla_put_u32(skb, CRYPTOCFGA_PRIORITY_VAL, alg->cra_priority)) goto nla_put_failure; if (alg->cra_flags & CRYPTO_ALG_LARVAL) { - struct crypto_report_larval rl; + struct crypto_report_larval rl = { + .type = "larval", + }; - memset(&rl, 0, sizeof(rl)); - strscpy(rl.type, "larval", sizeof(rl.type)); if (nla_put(skb, CRYPTOCFGA_REPORT_LARVAL, sizeof(rl), &rl)) goto nla_put_failure; goto out; diff --git a/crypto/kpp.c b/crypto/kpp.c index 7451d39a7ad8..522c352a03af 100644 --- a/crypto/kpp.c +++ b/crypto/kpp.c @@ -20,11 +20,9 @@ static int __maybe_unused crypto_kpp_report( struct sk_buff *skb, struct crypto_alg *alg) { - struct crypto_report_kpp rkpp; - - memset(&rkpp, 0, sizeof(rkpp)); - - strscpy(rkpp.type, "kpp", sizeof(rkpp.type)); + struct crypto_report_kpp rkpp = { + .type = "kpp", + }; return nla_put(skb, CRYPTOCFGA_REPORT_KPP, sizeof(rkpp), &rkpp); } diff --git a/crypto/lskcipher.c b/crypto/lskcipher.c index bb166250b732..e4328df6e26c 100644 --- a/crypto/lskcipher.c +++ b/crypto/lskcipher.c @@ -264,12 +264,10 @@ static int __maybe_unused crypto_lskcipher_report( struct sk_buff *skb, struct crypto_alg *alg) { struct lskcipher_alg *skcipher = __crypto_lskcipher_alg(alg); - struct crypto_report_blkcipher rblkcipher; - - memset(&rblkcipher, 0, sizeof(rblkcipher)); - - strscpy(rblkcipher.type, "lskcipher", sizeof(rblkcipher.type)); - strscpy(rblkcipher.geniv, "", sizeof(rblkcipher.geniv)); + struct crypto_report_blkcipher rblkcipher = { + .type = "lskcipher", + .geniv = "", + }; rblkcipher.blocksize = alg->cra_blocksize; rblkcipher.min_keysize = skcipher->co.min_keysize; diff --git a/crypto/rng.c b/crypto/rng.c index 1d4b9177bad4..eec786c45bdd 100644 --- a/crypto/rng.c +++ b/crypto/rng.c @@ -65,11 +65,9 @@ static unsigned int seedsize(struct crypto_alg *alg) static int __maybe_unused crypto_rng_report( struct sk_buff *skb, struct crypto_alg *alg) { - struct crypto_report_rng rrng; - - memset(&rrng, 0, sizeof(rrng)); - - strscpy(rrng.type, "rng", sizeof(rrng.type)); + struct crypto_report_rng rrng = { + .type = "rng", + }; rrng.seedsize = seedsize(alg); diff --git a/crypto/scompress.c b/crypto/scompress.c index 253655ece83f..de54227203ce 100644 --- a/crypto/scompress.c +++ b/crypto/scompress.c @@ -48,11 +48,9 @@ static DECLARE_WORK(scomp_scratch_work, scomp_scratch_workfn); static int __maybe_unused crypto_scomp_report( struct sk_buff *skb, struct crypto_alg *alg) { - struct crypto_report_comp rscomp; - - memset(&rscomp, 0, sizeof(rscomp)); - - strscpy(rscomp.type, "scomp", sizeof(rscomp.type)); + struct crypto_report_comp rscomp = { + .type = "scomp", + }; return nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS, sizeof(rscomp), &rscomp); diff --git a/crypto/shash.c b/crypto/shash.c index 2f07d0bd1f61..d31a65570f69 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -333,12 +333,10 @@ static void crypto_shash_free_instance(struct crypto_instance *inst) static int __maybe_unused crypto_shash_report( struct sk_buff *skb, struct crypto_alg *alg) { - struct crypto_report_hash rhash; struct shash_alg *salg = __crypto_shash_alg(alg); - - memset(&rhash, 0, sizeof(rhash)); - - strscpy(rhash.type, "shash", sizeof(rhash.type)); + struct crypto_report_hash rhash = { + .type = "shash", + }; rhash.blocksize = alg->cra_blocksize; rhash.digestsize = salg->digestsize; diff --git a/crypto/sig.c b/crypto/sig.c index beba745b6405..7d2048da5c3a 100644 --- a/crypto/sig.c +++ b/crypto/sig.c @@ -53,9 +53,9 @@ static void __maybe_unused crypto_sig_show(struct seq_file *m, static int __maybe_unused crypto_sig_report(struct sk_buff *skb, struct crypto_alg *alg) { - struct crypto_report_sig rsig = {}; - - strscpy(rsig.type, "sig", sizeof(rsig.type)); + struct crypto_report_sig rsig = { + .type = "sig", + }; return nla_put(skb, CRYPTOCFGA_REPORT_SIG, sizeof(rsig), &rsig); } diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 2b31d1d5d268..617e840432b1 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -591,12 +591,10 @@ static int __maybe_unused crypto_skcipher_report( struct sk_buff *skb, struct crypto_alg *alg) { struct skcipher_alg *skcipher = __crypto_skcipher_alg(alg); - struct crypto_report_blkcipher rblkcipher; - - memset(&rblkcipher, 0, sizeof(rblkcipher)); - - strscpy(rblkcipher.type, "skcipher", sizeof(rblkcipher.type)); - strscpy(rblkcipher.geniv, "", sizeof(rblkcipher.geniv)); + struct crypto_report_blkcipher rblkcipher = { + .type = "skcipher", + .geniv = "", + }; rblkcipher.blocksize = alg->cra_blocksize; rblkcipher.min_keysize = skcipher->min_keysize; From 917faaf2bd02da23286172863e3adab363233864 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sat, 9 May 2026 12:11:55 +0200 Subject: [PATCH 113/196] crypto: atmel-sha204a - drop __maybe_unused and of_match_ptr Since MODULE_DEVICE_TABLE() keeps atmel_sha204a_dt_ids referenced, drop the unnecessary __maybe_unused annotation. Also remove of_match_ptr() because OF matching is stubbed out when CONFIG_OF=n. Reformat atmel_sha204a_dt_ids to silence a checkpatch error and atmel_sha204a_id for consistency. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha204a.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index ed7d69bf6890..6e6ac4770416 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -207,17 +207,17 @@ static void atmel_sha204a_remove(struct i2c_client *client) kfree((void *)i2c_priv->hwrng.priv); } -static const struct of_device_id atmel_sha204a_dt_ids[] __maybe_unused = { +static const struct of_device_id atmel_sha204a_dt_ids[] = { { .compatible = "atmel,atsha204", .data = &atsha204_quality }, { .compatible = "atmel,atsha204a", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, atmel_sha204a_dt_ids); static const struct i2c_device_id atmel_sha204a_id[] = { { "atsha204", (kernel_ulong_t)&atsha204_quality }, { "atsha204a" }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(i2c, atmel_sha204a_id); @@ -227,7 +227,7 @@ static struct i2c_driver atmel_sha204a_driver = { .id_table = atmel_sha204a_id, .driver.name = "atmel-sha204a", - .driver.of_match_table = of_match_ptr(atmel_sha204a_dt_ids), + .driver.of_match_table = atmel_sha204a_dt_ids, }; static int __init atmel_sha204a_init(void) From 8e4e40b0d03a11cde9e341b4a422232cb25d2c61 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sat, 9 May 2026 12:11:56 +0200 Subject: [PATCH 114/196] crypto: atmel-ecc - drop CONFIG_OF guard and of_match_ptr Drop the CONFIG_OF preprocessor guard and remove of_match_ptr() because OF matching is stubbed out when CONFIG_OF=n. Reformat atmel_ecc_dt_ids for consistency. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-ecc.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index e47381020606..9660f6426a84 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -368,18 +368,12 @@ static void atmel_ecc_remove(struct i2c_client *client) spin_unlock(&driver_data.i2c_list_lock); } -#ifdef CONFIG_OF static const struct of_device_id atmel_ecc_dt_ids[] = { - { - .compatible = "atmel,atecc508a", - }, { - .compatible = "atmel,atecc608b", - }, { - /* sentinel */ - } + { .compatible = "atmel,atecc508a", }, + { .compatible = "atmel,atecc608b", }, + { } }; MODULE_DEVICE_TABLE(of, atmel_ecc_dt_ids); -#endif static const struct i2c_device_id atmel_ecc_id[] = { { "atecc508a" }, @@ -391,7 +385,7 @@ MODULE_DEVICE_TABLE(i2c, atmel_ecc_id); static struct i2c_driver atmel_ecc_driver = { .driver = { .name = "atmel-ecc", - .of_match_table = of_match_ptr(atmel_ecc_dt_ids), + .of_match_table = atmel_ecc_dt_ids, }, .probe = atmel_ecc_probe, .remove = atmel_ecc_remove, From ea8eca95a25256dcafc11eee31f19a70b91917aa Mon Sep 17 00:00:00 2001 From: Deepti Jaggi Date: Sun, 10 May 2026 10:18:09 +0800 Subject: [PATCH 115/196] dt-bindings: crypto: qcom,prng: Document TRNG on Nord SoC Document True Random Number Generator on Qualcomm Nord SoC. Signed-off-by: Deepti Jaggi Signed-off-by: Shawn Guo Acked-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- Documentation/devicetree/bindings/crypto/qcom,prng.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/crypto/qcom,prng.yaml b/Documentation/devicetree/bindings/crypto/qcom,prng.yaml index 498d6914135e..d054cc114707 100644 --- a/Documentation/devicetree/bindings/crypto/qcom,prng.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom,prng.yaml @@ -23,6 +23,7 @@ properties: - qcom,ipq9574-trng - qcom,kaanapali-trng - qcom,milos-trng + - qcom,nord-trng - qcom,qcs615-trng - qcom,qcs8300-trng - qcom,sa8255p-trng From 6c9dddeb582fde005360f4fe02c760d45ca05fb5 Mon Sep 17 00:00:00 2001 From: Michael Bommarito Date: Sun, 10 May 2026 19:24:55 -0400 Subject: [PATCH 116/196] crypto: krb5 - filter out async aead implementations at alloc krb5_aead_encrypt(), krb5_aead_decrypt() in rfc3961_simplified.c and rfc8009_encrypt(), rfc8009_decrypt() in rfc8009_aes2.c set a NULL completion callback and treat any negative return from crypto_aead_{encrypt,decrypt}() as terminal, falling through to kfree_sensitive(buffer). When the encrypt_name resolves to an async AEAD instance the request returns -EINPROGRESS, the buffer is freed while the backend's worker still holds a pointer, and the worker dereferences the freed slab on completion. KASAN report under UML+SLUB with a synthetic async aead backend bound to krb5->encrypt_name: BUG: KASAN: slab-use-after-free in t5_stub_complete+0x7d/0xc7 The helpers were written synchronously, so filter the async instances out at allocation time instead of plumbing crypto_wait_req() through every call site. Reachable via net/rxrpc/rxgk.c, fs/afs/cm_security.c and net/ceph/crypto.c on systems with an async AEAD provider bound to the krb5 enctype name. Fixes: 00244da40f78 ("crypto/krb5: Implement the Kerberos5 rfc3961 encrypt and decrypt functions") Fixes: 6c3c0e86c2ac ("crypto/krb5: Implement the AES enctypes from rfc8009") Cc: stable@vger.kernel.org Suggested-by: Herbert Xu Assisted-by: Claude:claude-opus-4-7 Signed-off-by: Michael Bommarito Signed-off-by: Herbert Xu --- crypto/krb5/krb5_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/krb5/krb5_api.c b/crypto/krb5/krb5_api.c index 23026d4206c8..2b20284fa0ab 100644 --- a/crypto/krb5/krb5_api.c +++ b/crypto/krb5/krb5_api.c @@ -165,7 +165,7 @@ struct crypto_aead *krb5_prepare_encryption(const struct krb5_enctype *krb5, struct crypto_aead *ci = NULL; int ret = -ENOMEM; - ci = crypto_alloc_aead(krb5->encrypt_name, 0, 0); + ci = crypto_alloc_aead(krb5->encrypt_name, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(ci)) { ret = PTR_ERR(ci); if (ret == -ENOENT) From 7452b3a025484abb147d109237599c5c4231c639 Mon Sep 17 00:00:00 2001 From: lizhi Date: Mon, 11 May 2026 08:49:27 +0800 Subject: [PATCH 117/196] crypto: hisilicon/sec2 - lower priority for hisilicon crypto implementations Lower the priority of HiSilicon's crypto implementations to allow more suitable alternatives to be selected. For example, certain kernel use-cases do not benefit from HiSilicon's symmetric crypto algorithms. This change ensures that more appropriate options are chosen first while retaining HiSilicon's implementations as alternatives. Signed-off-by: lizhi Signed-off-by: Chenghai Huang Reviewed-by: Longfang Liu Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/sec2/sec_crypto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.c b/drivers/crypto/hisilicon/sec2/sec_crypto.c index 2471a4dd0b50..77e0e03cbcab 100644 --- a/drivers/crypto/hisilicon/sec2/sec_crypto.c +++ b/drivers/crypto/hisilicon/sec2/sec_crypto.c @@ -20,7 +20,7 @@ #include "sec.h" #include "sec_crypto.h" -#define SEC_PRIORITY 4001 +#define SEC_PRIORITY 80 #define SEC_XTS_MIN_KEY_SIZE (2 * AES_MIN_KEY_SIZE) #define SEC_XTS_MID_KEY_SIZE (3 * AES_MIN_KEY_SIZE) #define SEC_XTS_MAX_KEY_SIZE (2 * AES_MAX_KEY_SIZE) From d237230728c567297f2f98b425d63156ab2ed17f Mon Sep 17 00:00:00 2001 From: Giovanni Cabiddu Date: Mon, 11 May 2026 11:04:08 +0100 Subject: [PATCH 118/196] crypto: qat - remove unused character device and IOCTLs The QAT driver exposes a character device (qat_adf_ctl) with IOCTLs for device configuration, start, stop, status query and enumeration. These IOCTLs are not part of any public uAPI header and have no known in-tree or out-of-tree users. Device lifecycle is already managed via sysfs. The ioctl interface also increases the attack surface and is the subject of a number of bug reports. Remove the character device, the IOCTL definitions, and the related data structures (adf_dev_status_info, adf_user_cfg_key_val, adf_user_cfg_section, adf_user_cfg_ctl_data). Drop the now-unused adf_cfg_user.h header and strip adf_ctl_drv.c down to the minimal module_init/module_exit hooks for workqueue, AER, and crypto/compression algorithm registration. Clean up leftover dead code that was only reachable from the removed IOCTL paths: adf_cfg_del_all(), adf_devmgr_verify_id(), adf_devmgr_get_num_dev(), adf_devmgr_get_dev_by_id(), adf_get_vf_real_id() and the unused ADF_CFG macros. Additionally, drop the entry associated to QAT IOCTLs in ioctl-number.rst. Cc: stable@vger.kernel.org Fixes: d8cba25d2c68 ("crypto: qat - Intel(R) QAT driver framework") Reported-by: Zhi Wang Reported-by: Bin Yu Reported-by: MingYu Wang Closes: https://lore.kernel.org/all/61d6d499.ab89.19b9b7f3186.Coremail.wangzhi_xd@stu.xidian.edu.cn/ Link: https://lore.kernel.org/all/20260508034841.256794-1-w15303746062@163.com/ Link: https://lore.kernel.org/all/20260508023542.256299-1-w15303746062@163.com/ Link: https://lore.kernel.org/all/20260504025120.98242-1-w15303746062@163.com/ Signed-off-by: Giovanni Cabiddu Reviewed-by: Ahsan Atta Signed-off-by: Herbert Xu --- .../userspace-api/ioctl/ioctl-number.rst | 1 - drivers/crypto/intel/qat/qat_common/adf_cfg.c | 10 - drivers/crypto/intel/qat/qat_common/adf_cfg.h | 1 - .../intel/qat/qat_common/adf_cfg_common.h | 32 -- .../intel/qat/qat_common/adf_cfg_user.h | 38 -- .../intel/qat/qat_common/adf_common_drv.h | 3 - .../crypto/intel/qat/qat_common/adf_ctl_drv.c | 404 +----------------- .../crypto/intel/qat/qat_common/adf_dev_mgr.c | 70 --- 8 files changed, 1 insertion(+), 558 deletions(-) delete mode 100644 drivers/crypto/intel/qat/qat_common/adf_cfg_user.h diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst index 331223761fff..29a08bc059dd 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -229,7 +229,6 @@ Code Seq# Include File Comments 'a' all linux/atm*.h, linux/sonet.h ATM on linux -'a' 00-0F drivers/crypto/qat/qat_common/adf_cfg_common.h conflict! qat driver 'b' 00-FF conflict! bit3 vme host bridge 'b' 00-0F linux/dma-buf.h conflict! diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg.c b/drivers/crypto/intel/qat/qat_common/adf_cfg.c index c202209f17d5..ea5d72d5090c 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_cfg.c +++ b/drivers/crypto/intel/qat/qat_common/adf_cfg.c @@ -103,16 +103,6 @@ static void adf_cfg_section_del_all(struct list_head *head); static void adf_cfg_section_del_all_except(struct list_head *head, const char *section_name); -void adf_cfg_del_all(struct adf_accel_dev *accel_dev) -{ - struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg; - - down_write(&dev_cfg_data->lock); - adf_cfg_section_del_all(&dev_cfg_data->sec_list); - up_write(&dev_cfg_data->lock); - clear_bit(ADF_STATUS_CONFIGURED, &accel_dev->status); -} - void adf_cfg_del_all_except(struct adf_accel_dev *accel_dev, const char *section_name) { diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg.h b/drivers/crypto/intel/qat/qat_common/adf_cfg.h index 2afa6f0d15c5..108032b39242 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_cfg.h +++ b/drivers/crypto/intel/qat/qat_common/adf_cfg.h @@ -34,7 +34,6 @@ void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev); void adf_cfg_dev_dbgfs_add(struct adf_accel_dev *accel_dev); void adf_cfg_dev_dbgfs_rm(struct adf_accel_dev *accel_dev); int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name); -void adf_cfg_del_all(struct adf_accel_dev *accel_dev); void adf_cfg_del_all_except(struct adf_accel_dev *accel_dev, const char *section_name); int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev, diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg_common.h b/drivers/crypto/intel/qat/qat_common/adf_cfg_common.h index 81e9e9d7eccd..d63f4dcccbb5 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_cfg_common.h +++ b/drivers/crypto/intel/qat/qat_common/adf_cfg_common.h @@ -4,18 +4,11 @@ #define ADF_CFG_COMMON_H_ #include -#include #define ADF_CFG_MAX_STR_LEN 64 #define ADF_CFG_MAX_KEY_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN #define ADF_CFG_MAX_VAL_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN #define ADF_CFG_MAX_SECTION_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN -#define ADF_CFG_BASE_DEC 10 -#define ADF_CFG_BASE_HEX 16 -#define ADF_CFG_ALL_DEVICES 0xFE -#define ADF_CFG_NO_DEVICE 0xFF -#define ADF_CFG_AFFINITY_WHATEVER 0xFF -#define MAX_DEVICE_NAME_SIZE 32 #define ADF_MAX_DEVICES (32 * 32) #define ADF_DEVS_ARRAY_SIZE BITS_TO_LONGS(ADF_MAX_DEVICES) @@ -51,29 +44,4 @@ enum adf_device_type { DEV_420XX, DEV_6XXX, }; - -struct adf_dev_status_info { - enum adf_device_type type; - __u32 accel_id; - __u32 instance_id; - __u8 num_ae; - __u8 num_accel; - __u8 num_logical_accel; - __u8 banks_per_accel; - __u8 state; - __u8 bus; - __u8 dev; - __u8 fun; - char name[MAX_DEVICE_NAME_SIZE]; -}; - -#define ADF_CTL_IOC_MAGIC 'a' -#define IOCTL_CONFIG_SYS_RESOURCE_PARAMETERS _IOW(ADF_CTL_IOC_MAGIC, 0, \ - struct adf_user_cfg_ctl_data) -#define IOCTL_STOP_ACCEL_DEV _IOW(ADF_CTL_IOC_MAGIC, 1, \ - struct adf_user_cfg_ctl_data) -#define IOCTL_START_ACCEL_DEV _IOW(ADF_CTL_IOC_MAGIC, 2, \ - struct adf_user_cfg_ctl_data) -#define IOCTL_STATUS_ACCEL_DEV _IOW(ADF_CTL_IOC_MAGIC, 3, __u32) -#define IOCTL_GET_NUM_DEVICES _IOW(ADF_CTL_IOC_MAGIC, 4, __s32) #endif diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg_user.h b/drivers/crypto/intel/qat/qat_common/adf_cfg_user.h deleted file mode 100644 index 421f4fb8b4dd..000000000000 --- a/drivers/crypto/intel/qat/qat_common/adf_cfg_user.h +++ /dev/null @@ -1,38 +0,0 @@ -/* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) */ -/* Copyright(c) 2014 - 2020 Intel Corporation */ -#ifndef ADF_CFG_USER_H_ -#define ADF_CFG_USER_H_ - -#include "adf_cfg_common.h" -#include "adf_cfg_strings.h" - -struct adf_user_cfg_key_val { - char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; - char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; - union { - struct adf_user_cfg_key_val *next; - __u64 padding3; - }; - enum adf_cfg_val_type type; -} __packed; - -struct adf_user_cfg_section { - char name[ADF_CFG_MAX_SECTION_LEN_IN_BYTES]; - union { - struct adf_user_cfg_key_val *params; - __u64 padding1; - }; - union { - struct adf_user_cfg_section *next; - __u64 padding3; - }; -} __packed; - -struct adf_user_cfg_ctl_data { - union { - struct adf_user_cfg_section *config_section; - __u64 padding; - }; - __u8 device_id; -} __packed; -#endif diff --git a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h index fb0fd46a79b0..e8dd76751dfb 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h +++ b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h @@ -68,10 +68,7 @@ int adf_devmgr_add_dev(struct adf_accel_dev *accel_dev, void adf_devmgr_rm_dev(struct adf_accel_dev *accel_dev, struct adf_accel_dev *pf); struct list_head *adf_devmgr_get_head(void); -struct adf_accel_dev *adf_devmgr_get_dev_by_id(u32 id); struct adf_accel_dev *adf_devmgr_pci_to_accel_dev(struct pci_dev *pci_dev); -int adf_devmgr_verify_id(u32 id); -void adf_devmgr_get_num_dev(u32 *num); int adf_devmgr_in_reset(struct adf_accel_dev *accel_dev); int adf_dev_started(struct adf_accel_dev *accel_dev); int adf_dev_restarting_notify(struct adf_accel_dev *accel_dev); diff --git a/drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c b/drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c index c2e6f0cb7480..f01f2946de6e 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c +++ b/drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c @@ -2,410 +2,13 @@ /* Copyright(c) 2014 - 2020 Intel Corporation */ #include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include "adf_accel_devices.h" #include "adf_common_drv.h" -#include "adf_cfg.h" -#include "adf_cfg_common.h" -#include "adf_cfg_user.h" - -#define ADF_CFG_MAX_SECTION 512 -#define ADF_CFG_MAX_KEY_VAL 256 - -#define DEVICE_NAME "qat_adf_ctl" - -static DEFINE_MUTEX(adf_ctl_lock); -static long adf_ctl_ioctl(struct file *fp, unsigned int cmd, unsigned long arg); - -static const struct file_operations adf_ctl_ops = { - .owner = THIS_MODULE, - .unlocked_ioctl = adf_ctl_ioctl, - .compat_ioctl = compat_ptr_ioctl, -}; - -static const struct class adf_ctl_class = { - .name = DEVICE_NAME, -}; - -struct adf_ctl_drv_info { - unsigned int major; - struct cdev drv_cdev; -}; - -static struct adf_ctl_drv_info adf_ctl_drv; - -static void adf_chr_drv_destroy(void) -{ - device_destroy(&adf_ctl_class, MKDEV(adf_ctl_drv.major, 0)); - cdev_del(&adf_ctl_drv.drv_cdev); - class_unregister(&adf_ctl_class); - unregister_chrdev_region(MKDEV(adf_ctl_drv.major, 0), 1); -} - -static int adf_chr_drv_create(void) -{ - dev_t dev_id; - struct device *drv_device; - int ret; - - if (alloc_chrdev_region(&dev_id, 0, 1, DEVICE_NAME)) { - pr_err("QAT: unable to allocate chrdev region\n"); - return -EFAULT; - } - - ret = class_register(&adf_ctl_class); - if (ret) - goto err_chrdev_unreg; - - adf_ctl_drv.major = MAJOR(dev_id); - cdev_init(&adf_ctl_drv.drv_cdev, &adf_ctl_ops); - if (cdev_add(&adf_ctl_drv.drv_cdev, dev_id, 1)) { - pr_err("QAT: cdev add failed\n"); - goto err_class_destr; - } - - drv_device = device_create(&adf_ctl_class, NULL, - MKDEV(adf_ctl_drv.major, 0), - NULL, DEVICE_NAME); - if (IS_ERR(drv_device)) { - pr_err("QAT: failed to create device\n"); - goto err_cdev_del; - } - return 0; -err_cdev_del: - cdev_del(&adf_ctl_drv.drv_cdev); -err_class_destr: - class_unregister(&adf_ctl_class); -err_chrdev_unreg: - unregister_chrdev_region(dev_id, 1); - return -EFAULT; -} - -static struct adf_user_cfg_ctl_data *adf_ctl_alloc_resources(unsigned long arg) -{ - struct adf_user_cfg_ctl_data *cfg_data; - - cfg_data = memdup_user((void __user *)arg, sizeof(*cfg_data)); - if (IS_ERR(cfg_data)) - pr_err("QAT: failed to copy from user cfg_data.\n"); - return cfg_data; -} - -static int adf_add_key_value_data(struct adf_accel_dev *accel_dev, - const char *section, - const struct adf_user_cfg_key_val *key_val) -{ - if (key_val->type == ADF_HEX) { - long *ptr = (long *)key_val->val; - long val = *ptr; - - if (adf_cfg_add_key_value_param(accel_dev, section, - key_val->key, (void *)val, - key_val->type)) { - dev_err(&GET_DEV(accel_dev), - "failed to add hex keyvalue.\n"); - return -EFAULT; - } - } else { - if (adf_cfg_add_key_value_param(accel_dev, section, - key_val->key, key_val->val, - key_val->type)) { - dev_err(&GET_DEV(accel_dev), - "failed to add keyvalue.\n"); - return -EFAULT; - } - } - return 0; -} - -static int adf_copy_key_value_data(struct adf_accel_dev *accel_dev, - struct adf_user_cfg_ctl_data *ctl_data) -{ - struct adf_user_cfg_key_val key_val; - struct adf_user_cfg_key_val *params_head; - struct adf_user_cfg_section section, *section_head; - int i, j; - - section_head = ctl_data->config_section; - - for (i = 0; section_head && i < ADF_CFG_MAX_SECTION; i++) { - if (copy_from_user(§ion, (void __user *)section_head, - sizeof(*section_head))) { - dev_err(&GET_DEV(accel_dev), - "failed to copy section info\n"); - goto out_err; - } - - if (adf_cfg_section_add(accel_dev, section.name)) { - dev_err(&GET_DEV(accel_dev), - "failed to add section.\n"); - goto out_err; - } - - params_head = section.params; - - for (j = 0; params_head && j < ADF_CFG_MAX_KEY_VAL; j++) { - if (copy_from_user(&key_val, (void __user *)params_head, - sizeof(key_val))) { - dev_err(&GET_DEV(accel_dev), - "Failed to copy keyvalue.\n"); - goto out_err; - } - if (adf_add_key_value_data(accel_dev, section.name, - &key_val)) { - goto out_err; - } - params_head = key_val.next; - } - section_head = section.next; - } - return 0; -out_err: - adf_cfg_del_all(accel_dev); - return -EFAULT; -} - -static int adf_ctl_ioctl_dev_config(struct file *fp, unsigned int cmd, - unsigned long arg) -{ - struct adf_user_cfg_ctl_data *ctl_data; - struct adf_accel_dev *accel_dev; - int ret = 0; - - ctl_data = adf_ctl_alloc_resources(arg); - if (IS_ERR(ctl_data)) - return PTR_ERR(ctl_data); - - accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id); - if (!accel_dev) { - ret = -EFAULT; - goto out; - } - - if (adf_dev_started(accel_dev)) { - ret = -EFAULT; - goto out; - } - - if (adf_copy_key_value_data(accel_dev, ctl_data)) { - ret = -EFAULT; - goto out; - } - set_bit(ADF_STATUS_CONFIGURED, &accel_dev->status); -out: - kfree(ctl_data); - return ret; -} - -static int adf_ctl_is_device_in_use(int id) -{ - struct adf_accel_dev *dev; - - list_for_each_entry(dev, adf_devmgr_get_head(), list) { - if (id == dev->accel_id || id == ADF_CFG_ALL_DEVICES) { - if (adf_devmgr_in_reset(dev) || adf_dev_in_use(dev)) { - dev_info(&GET_DEV(dev), - "device qat_dev%d is busy\n", - dev->accel_id); - return -EBUSY; - } - } - } - return 0; -} - -static void adf_ctl_stop_devices(u32 id) -{ - struct adf_accel_dev *accel_dev; - - list_for_each_entry(accel_dev, adf_devmgr_get_head(), list) { - if (id == accel_dev->accel_id || id == ADF_CFG_ALL_DEVICES) { - if (!adf_dev_started(accel_dev)) - continue; - - /* First stop all VFs */ - if (!accel_dev->is_vf) - continue; - - adf_dev_down(accel_dev); - } - } - - list_for_each_entry(accel_dev, adf_devmgr_get_head(), list) { - if (id == accel_dev->accel_id || id == ADF_CFG_ALL_DEVICES) { - if (!adf_dev_started(accel_dev)) - continue; - - adf_dev_down(accel_dev); - } - } -} - -static int adf_ctl_ioctl_dev_stop(struct file *fp, unsigned int cmd, - unsigned long arg) -{ - int ret; - struct adf_user_cfg_ctl_data *ctl_data; - - ctl_data = adf_ctl_alloc_resources(arg); - if (IS_ERR(ctl_data)) - return PTR_ERR(ctl_data); - - if (adf_devmgr_verify_id(ctl_data->device_id)) { - pr_err("QAT: Device %d not found\n", ctl_data->device_id); - ret = -ENODEV; - goto out; - } - - ret = adf_ctl_is_device_in_use(ctl_data->device_id); - if (ret) - goto out; - - if (ctl_data->device_id == ADF_CFG_ALL_DEVICES) - pr_info("QAT: Stopping all acceleration devices.\n"); - else - pr_info("QAT: Stopping acceleration device qat_dev%d.\n", - ctl_data->device_id); - - adf_ctl_stop_devices(ctl_data->device_id); - -out: - kfree(ctl_data); - return ret; -} - -static int adf_ctl_ioctl_dev_start(struct file *fp, unsigned int cmd, - unsigned long arg) -{ - int ret; - struct adf_user_cfg_ctl_data *ctl_data; - struct adf_accel_dev *accel_dev; - - ctl_data = adf_ctl_alloc_resources(arg); - if (IS_ERR(ctl_data)) - return PTR_ERR(ctl_data); - - ret = -ENODEV; - accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id); - if (!accel_dev) - goto out; - - dev_info(&GET_DEV(accel_dev), - "Starting acceleration device qat_dev%d.\n", - ctl_data->device_id); - - ret = adf_dev_up(accel_dev, false); - - if (ret) { - dev_err(&GET_DEV(accel_dev), "Failed to start qat_dev%d\n", - ctl_data->device_id); - adf_dev_down(accel_dev); - } -out: - kfree(ctl_data); - return ret; -} - -static int adf_ctl_ioctl_get_num_devices(struct file *fp, unsigned int cmd, - unsigned long arg) -{ - u32 num_devices = 0; - - adf_devmgr_get_num_dev(&num_devices); - if (copy_to_user((void __user *)arg, &num_devices, sizeof(num_devices))) - return -EFAULT; - - return 0; -} - -static int adf_ctl_ioctl_get_status(struct file *fp, unsigned int cmd, - unsigned long arg) -{ - struct adf_hw_device_data *hw_data; - struct adf_dev_status_info dev_info; - struct adf_accel_dev *accel_dev; - - if (copy_from_user(&dev_info, (void __user *)arg, - sizeof(struct adf_dev_status_info))) { - pr_err("QAT: failed to copy from user.\n"); - return -EFAULT; - } - - accel_dev = adf_devmgr_get_dev_by_id(dev_info.accel_id); - if (!accel_dev) - return -ENODEV; - - hw_data = accel_dev->hw_device; - dev_info.state = adf_dev_started(accel_dev) ? DEV_UP : DEV_DOWN; - dev_info.num_ae = hw_data->get_num_aes(hw_data); - dev_info.num_accel = hw_data->get_num_accels(hw_data); - dev_info.num_logical_accel = hw_data->num_logical_accel; - dev_info.banks_per_accel = hw_data->num_banks - / hw_data->num_logical_accel; - strscpy(dev_info.name, hw_data->dev_class->name, sizeof(dev_info.name)); - dev_info.instance_id = hw_data->instance_id; - dev_info.type = hw_data->dev_class->type; - dev_info.bus = accel_to_pci_dev(accel_dev)->bus->number; - dev_info.dev = PCI_SLOT(accel_to_pci_dev(accel_dev)->devfn); - dev_info.fun = PCI_FUNC(accel_to_pci_dev(accel_dev)->devfn); - - if (copy_to_user((void __user *)arg, &dev_info, - sizeof(struct adf_dev_status_info))) { - dev_err(&GET_DEV(accel_dev), "failed to copy status.\n"); - return -EFAULT; - } - return 0; -} - -static long adf_ctl_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) -{ - int ret; - - if (mutex_lock_interruptible(&adf_ctl_lock)) - return -EFAULT; - - switch (cmd) { - case IOCTL_CONFIG_SYS_RESOURCE_PARAMETERS: - ret = adf_ctl_ioctl_dev_config(fp, cmd, arg); - break; - - case IOCTL_STOP_ACCEL_DEV: - ret = adf_ctl_ioctl_dev_stop(fp, cmd, arg); - break; - - case IOCTL_START_ACCEL_DEV: - ret = adf_ctl_ioctl_dev_start(fp, cmd, arg); - break; - - case IOCTL_GET_NUM_DEVICES: - ret = adf_ctl_ioctl_get_num_devices(fp, cmd, arg); - break; - - case IOCTL_STATUS_ACCEL_DEV: - ret = adf_ctl_ioctl_get_status(fp, cmd, arg); - break; - default: - pr_err_ratelimited("QAT: Invalid ioctl %d\n", cmd); - ret = -EFAULT; - break; - } - mutex_unlock(&adf_ctl_lock); - return ret; -} static int __init adf_register_ctl_device_driver(void) { - if (adf_chr_drv_create()) - goto err_chr_dev; - if (adf_init_misc_wq()) goto err_misc_wq; @@ -437,15 +40,11 @@ err_pf_wq: err_aer: adf_exit_misc_wq(); err_misc_wq: - adf_chr_drv_destroy(); -err_chr_dev: - mutex_destroy(&adf_ctl_lock); return -EFAULT; } static void __exit adf_unregister_ctl_device_driver(void) { - adf_chr_drv_destroy(); adf_exit_misc_wq(); adf_exit_aer(); adf_exit_vf_wq(); @@ -453,7 +52,6 @@ static void __exit adf_unregister_ctl_device_driver(void) qat_crypto_unregister(); qat_compression_unregister(); adf_clean_vf_map(false); - mutex_destroy(&adf_ctl_lock); } module_init(adf_register_ctl_device_driver); diff --git a/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c b/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c index e050de16ab5d..161863841a52 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c +++ b/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c @@ -45,19 +45,6 @@ static struct vf_id_map *adf_find_vf(u32 bdf) return NULL; } -static int adf_get_vf_real_id(u32 fake) -{ - struct list_head *itr; - - list_for_each(itr, &vfs_table) { - struct vf_id_map *ptr = - list_entry(itr, struct vf_id_map, list); - if (ptr->fake_id == fake) - return ptr->id; - } - return -1; -} - /** * adf_clean_vf_map() - Cleans VF id mappings * @vf: flag indicating whether mappings is cleaned @@ -304,63 +291,6 @@ struct adf_accel_dev *adf_devmgr_pci_to_accel_dev(struct pci_dev *pci_dev) } EXPORT_SYMBOL_GPL(adf_devmgr_pci_to_accel_dev); -struct adf_accel_dev *adf_devmgr_get_dev_by_id(u32 id) -{ - struct list_head *itr; - int real_id; - - mutex_lock(&table_lock); - real_id = adf_get_vf_real_id(id); - if (real_id < 0) - goto unlock; - - id = real_id; - - list_for_each(itr, &accel_table) { - struct adf_accel_dev *ptr = - list_entry(itr, struct adf_accel_dev, list); - if (ptr->accel_id == id) { - mutex_unlock(&table_lock); - return ptr; - } - } -unlock: - mutex_unlock(&table_lock); - return NULL; -} - -int adf_devmgr_verify_id(u32 id) -{ - if (id == ADF_CFG_ALL_DEVICES) - return 0; - - if (adf_devmgr_get_dev_by_id(id)) - return 0; - - return -ENODEV; -} - -static int adf_get_num_dettached_vfs(void) -{ - struct list_head *itr; - int vfs = 0; - - mutex_lock(&table_lock); - list_for_each(itr, &vfs_table) { - struct vf_id_map *ptr = - list_entry(itr, struct vf_id_map, list); - if (ptr->bdf != ~0 && !ptr->attached) - vfs++; - } - mutex_unlock(&table_lock); - return vfs; -} - -void adf_devmgr_get_num_dev(u32 *num) -{ - *num = num_devices - adf_get_num_dettached_vfs(); -} - /** * adf_dev_in_use() - Check whether accel_dev is currently in use * @accel_dev: Pointer to acceleration device. From 9206f1b3f8cf76d0dcacd3eab5813244e9fc9964 Mon Sep 17 00:00:00 2001 From: Giovanni Cabiddu Date: Mon, 11 May 2026 11:04:09 +0100 Subject: [PATCH 119/196] crypto: qat - rename adf_ctl_drv.c to adf_module.c Now that the character device and IOCTL interface have been removed, adf_ctl_drv.c only contains module_init/module_exit hooks. Rename it to adf_module.c to better reflect its purpose and rename the init/exit functions accordingly. Signed-off-by: Giovanni Cabiddu Reviewed-by: Ahsan Atta Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/Makefile | 2 +- .../intel/qat/qat_common/{adf_ctl_drv.c => adf_module.c} | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) rename drivers/crypto/intel/qat/qat_common/{adf_ctl_drv.c => adf_module.c} (84%) diff --git a/drivers/crypto/intel/qat/qat_common/Makefile b/drivers/crypto/intel/qat/qat_common/Makefile index 9478111c8437..2b1649001518 100644 --- a/drivers/crypto/intel/qat/qat_common/Makefile +++ b/drivers/crypto/intel/qat/qat_common/Makefile @@ -9,7 +9,6 @@ intel_qat-y := adf_accel_engine.o \ adf_cfg.o \ adf_cfg_services.o \ adf_clock.o \ - adf_ctl_drv.o \ adf_dc.o \ adf_dev_mgr.o \ adf_gen2_config.o \ @@ -26,6 +25,7 @@ intel_qat-y := adf_accel_engine.o \ adf_hw_arbiter.o \ adf_init.o \ adf_isr.o \ + adf_module.o \ adf_mstate_mgr.o \ adf_rl_admin.o \ adf_rl.o \ diff --git a/drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c b/drivers/crypto/intel/qat/qat_common/adf_module.c similarity index 84% rename from drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c rename to drivers/crypto/intel/qat/qat_common/adf_module.c index f01f2946de6e..fccaa71eeedc 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c +++ b/drivers/crypto/intel/qat/qat_common/adf_module.c @@ -7,7 +7,7 @@ #include "adf_common_drv.h" -static int __init adf_register_ctl_device_driver(void) +static int __init adf_register_module(void) { if (adf_init_misc_wq()) goto err_misc_wq; @@ -43,7 +43,7 @@ err_misc_wq: return -EFAULT; } -static void __exit adf_unregister_ctl_device_driver(void) +static void __exit adf_unregister_module(void) { adf_exit_misc_wq(); adf_exit_aer(); @@ -54,8 +54,8 @@ static void __exit adf_unregister_ctl_device_driver(void) adf_clean_vf_map(false); } -module_init(adf_register_ctl_device_driver); -module_exit(adf_unregister_ctl_device_driver); +module_init(adf_register_module); +module_exit(adf_unregister_module); MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Intel"); MODULE_DESCRIPTION("Intel(R) QuickAssist Technology"); From 209466c5fe352b81b9fa9d135bbffbac18350fb2 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 12 May 2026 15:34:15 +0200 Subject: [PATCH 120/196] crypto: cesa - use max to simplify mv_cesa_probe Use max() to simplify mv_cesa_probe() and improve its readability. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/marvell/cesa/cesa.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/marvell/cesa/cesa.c b/drivers/crypto/marvell/cesa/cesa.c index 687ed730174d..75d8ba23d9a2 100644 --- a/drivers/crypto/marvell/cesa/cesa.c +++ b/drivers/crypto/marvell/cesa/cesa.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -442,10 +443,8 @@ static int mv_cesa_probe(struct platform_device *pdev) sram_size = CESA_SA_DEFAULT_SRAM_SIZE; of_property_read_u32(cesa->dev->of_node, "marvell,crypto-sram-size", &sram_size); - if (sram_size < CESA_SA_MIN_SRAM_SIZE) - sram_size = CESA_SA_MIN_SRAM_SIZE; - cesa->sram_size = sram_size; + cesa->sram_size = max(sram_size, CESA_SA_MIN_SRAM_SIZE); spin_lock_init(&cesa->lock); From e1ad89211938dcf0d5fffbbab6a178ce54b9ae38 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 12 May 2026 16:51:24 +0200 Subject: [PATCH 121/196] crypto: atmel - use min3 to simplify atmel_sha_append_sg Replace two consecutive min() calls with min3() to simplify the code. And since count is unsigned and cannot be less than zero, adjust the if check and update the comment accordingly. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index 002b62902553..7e7c83a3d8cd 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -305,12 +305,12 @@ static size_t atmel_sha_append_sg(struct atmel_sha_reqctx *ctx) size_t count; while ((ctx->bufcnt < ctx->buflen) && ctx->total) { - count = min(ctx->sg->length - ctx->offset, ctx->total); - count = min(count, ctx->buflen - ctx->bufcnt); + count = min3(ctx->sg->length - ctx->offset, ctx->total, + ctx->buflen - ctx->bufcnt); - if (count <= 0) { + if (count == 0) { /* - * Check if count <= 0 because the buffer is full or + * Check if count == 0 because the buffer is full or * because the sg length is 0. In the latest case, * check if there is another sg in the list, a 0 length * sg doesn't necessarily mean the end of the sg list. From 310bcf581dc57506160ef138ad6276e965b550cd Mon Sep 17 00:00:00 2001 From: Giovanni Cabiddu Date: Wed, 13 May 2026 09:57:45 +0100 Subject: [PATCH 122/196] crypto: qat - remove MODULE_VERSION In-tree drivers do not need MODULE_VERSION as the kernel release identifies the version of their code. The static version "0.6.0", which the QAT drivers currently report, can be misleading as it might suggest the drivers are outdated. Remove MODULE_VERSION() from all QAT driver modules and the related ADF_DRV_VERSION, ADF_MAJOR_VERSION, ADF_MINOR_VERSION and ADF_BUILD_VERSION macros from adf_common_drv.h. Signed-off-by: Giovanni Cabiddu Reviewed-by: Ahsan Atta Reviewed-by: Andy Shevchenko Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_420xx/adf_drv.c | 1 - drivers/crypto/intel/qat/qat_4xxx/adf_drv.c | 1 - drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c | 1 - drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c | 1 - drivers/crypto/intel/qat/qat_c62x/adf_drv.c | 1 - drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c | 1 - drivers/crypto/intel/qat/qat_common/adf_common_drv.h | 7 ------- drivers/crypto/intel/qat/qat_common/adf_module.c | 1 - drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c | 1 - drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c | 1 - 10 files changed, 16 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_420xx/adf_drv.c b/drivers/crypto/intel/qat/qat_420xx/adf_drv.c index cfa00daeb4fb..566adc0a2d11 100644 --- a/drivers/crypto/intel/qat/qat_420xx/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_420xx/adf_drv.c @@ -210,6 +210,5 @@ MODULE_AUTHOR("Intel"); MODULE_FIRMWARE(ADF_420XX_FW); MODULE_FIRMWARE(ADF_420XX_MMP); MODULE_DESCRIPTION("Intel(R) QuickAssist Technology"); -MODULE_VERSION(ADF_DRV_VERSION); MODULE_SOFTDEP("pre: crypto-intel_qat"); MODULE_IMPORT_NS("CRYPTO_QAT"); diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c index c9be5dcddb27..daca73651c14 100644 --- a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c @@ -214,6 +214,5 @@ MODULE_FIRMWARE(ADF_402XX_FW); MODULE_FIRMWARE(ADF_4XXX_MMP); MODULE_FIRMWARE(ADF_402XX_MMP); MODULE_DESCRIPTION("Intel(R) QuickAssist Technology"); -MODULE_VERSION(ADF_DRV_VERSION); MODULE_SOFTDEP("pre: crypto-intel_qat"); MODULE_IMPORT_NS("CRYPTO_QAT"); diff --git a/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c index bceb5dd8b148..7a59bca3242f 100644 --- a/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c @@ -256,5 +256,4 @@ MODULE_AUTHOR("Intel"); MODULE_FIRMWARE(ADF_C3XXX_FW); MODULE_FIRMWARE(ADF_C3XXX_MMP); MODULE_DESCRIPTION("Intel(R) QuickAssist Technology"); -MODULE_VERSION(ADF_DRV_VERSION); MODULE_IMPORT_NS("CRYPTO_QAT"); diff --git a/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c b/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c index c622793e94a8..0881575f7670 100644 --- a/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c @@ -225,5 +225,4 @@ module_exit(adfdrv_release); MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Intel"); MODULE_DESCRIPTION("Intel(R) QuickAssist Technology"); -MODULE_VERSION(ADF_DRV_VERSION); MODULE_IMPORT_NS("CRYPTO_QAT"); diff --git a/drivers/crypto/intel/qat/qat_c62x/adf_drv.c b/drivers/crypto/intel/qat/qat_c62x/adf_drv.c index 23ccb72b6ea2..4972e52dd944 100644 --- a/drivers/crypto/intel/qat/qat_c62x/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_c62x/adf_drv.c @@ -256,5 +256,4 @@ MODULE_AUTHOR("Intel"); MODULE_FIRMWARE(ADF_C62X_FW); MODULE_FIRMWARE(ADF_C62X_MMP); MODULE_DESCRIPTION("Intel(R) QuickAssist Technology"); -MODULE_VERSION(ADF_DRV_VERSION); MODULE_IMPORT_NS("CRYPTO_QAT"); diff --git a/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c b/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c index 4840d44bbd5b..d3f728b9f2f2 100644 --- a/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c @@ -225,5 +225,4 @@ module_exit(adfdrv_release); MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Intel"); MODULE_DESCRIPTION("Intel(R) QuickAssist Technology"); -MODULE_VERSION(ADF_DRV_VERSION); MODULE_IMPORT_NS("CRYPTO_QAT"); diff --git a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h index e8dd76751dfb..a05d149423b0 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h +++ b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h @@ -9,13 +9,6 @@ #include "icp_qat_fw_loader_handle.h" #include "icp_qat_hal.h" -#define ADF_MAJOR_VERSION 0 -#define ADF_MINOR_VERSION 6 -#define ADF_BUILD_VERSION 0 -#define ADF_DRV_VERSION __stringify(ADF_MAJOR_VERSION) "." \ - __stringify(ADF_MINOR_VERSION) "." \ - __stringify(ADF_BUILD_VERSION) - #define ADF_STATUS_RESTARTING 0 #define ADF_STATUS_STARTING 1 #define ADF_STATUS_CONFIGURED 2 diff --git a/drivers/crypto/intel/qat/qat_common/adf_module.c b/drivers/crypto/intel/qat/qat_common/adf_module.c index fccaa71eeedc..30069feec3c1 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_module.c +++ b/drivers/crypto/intel/qat/qat_common/adf_module.c @@ -60,5 +60,4 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Intel"); MODULE_DESCRIPTION("Intel(R) QuickAssist Technology"); MODULE_ALIAS_CRYPTO("intel_qat"); -MODULE_VERSION(ADF_DRV_VERSION); MODULE_IMPORT_NS("CRYPTO_INTERNAL"); diff --git a/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c b/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c index b59e0cc49e52..8a863d7d86d7 100644 --- a/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c @@ -256,5 +256,4 @@ MODULE_AUTHOR("Intel"); MODULE_FIRMWARE(ADF_DH895XCC_FW); MODULE_FIRMWARE(ADF_DH895XCC_MMP); MODULE_DESCRIPTION("Intel(R) QuickAssist Technology"); -MODULE_VERSION(ADF_DRV_VERSION); MODULE_IMPORT_NS("CRYPTO_QAT"); diff --git a/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c b/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c index 7cd528ee31e7..f8a6e10a1de7 100644 --- a/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c @@ -225,5 +225,4 @@ module_exit(adfdrv_release); MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Intel"); MODULE_DESCRIPTION("Intel(R) QuickAssist Technology"); -MODULE_VERSION(ADF_DRV_VERSION); MODULE_IMPORT_NS("CRYPTO_QAT"); From 27b536a2ec8e2f85a0380c2d13c9ecbc7aaab406 Mon Sep 17 00:00:00 2001 From: Anastasia Tishchenko Date: Wed, 13 May 2026 13:57:40 +0300 Subject: [PATCH 123/196] crypto: ecc - Fix carry overflow in vli multiplication The carry flag calculation fails when r01.m_high is saturated (0xFFFFFFFFFFFFFFFF) and addition of lower bits overflows. The condition (r01.m_high < product.m_high) doesn't handle the case where r01.m_high == product.m_high and an additional carry exists from lower-bit overflow. When commit 3c4b23901a0c ("crypto: ecdh - Add ECDH software support") introduced crypto/ecc.c, it split the muladd() function in the micro-ecc library into separate mul_64_64() and add_128_128() helpers. It seems the check got lost in translation. Add proper handling for this boundary by accounting for the carry from the lower addition. Fixes: 3c4b23901a0c ("crypto: ecdh - Add ECDH software support") Signed-off-by: Anastasia Tishchenko Cc: stable@vger.kernel.org # v4.8+ Reviewed-by: Lukas Wunner Signed-off-by: Herbert Xu --- crypto/ecc.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/crypto/ecc.c b/crypto/ecc.c index 43b0def3a225..6eb4d97a5f0d 100644 --- a/crypto/ecc.c +++ b/crypto/ecc.c @@ -393,14 +393,26 @@ static uint128_t mul_64_64(u64 left, u64 right) return result; } -static uint128_t add_128_128(uint128_t a, uint128_t b) +/* Calculate addition with overflow checking. Returns true on wrap-around, + * false otherwise. + */ +static bool check_add_128_128_overflow(uint128_t *result, uint128_t a, + uint128_t b) { - uint128_t result; + bool carry; - result.m_low = a.m_low + b.m_low; - result.m_high = a.m_high + b.m_high + (result.m_low < a.m_low); + result->m_low = a.m_low + b.m_low; + carry = (result->m_low < a.m_low); - return result; + result->m_high = a.m_high + b.m_high + carry; + + /* Using constant-time bitwise arithmetic to prevent timing + * side-channels. + */ + carry = (result->m_high < a.m_high) | + ((result->m_high == a.m_high) & carry); + + return carry; } static void vli_mult(u64 *result, const u64 *left, const u64 *right, @@ -425,9 +437,7 @@ static void vli_mult(u64 *result, const u64 *left, const u64 *right, uint128_t product; product = mul_64_64(left[i], right[k - i]); - - r01 = add_128_128(r01, product); - r2 += (r01.m_high < product.m_high); + r2 += check_add_128_128_overflow(&r01, r01, product); } result[k] = r01.m_low; @@ -450,7 +460,7 @@ static void vli_umult(u64 *result, const u64 *left, u32 right, uint128_t product; product = mul_64_64(left[k], right); - r01 = add_128_128(r01, product); + check_add_128_128_overflow(&r01, r01, product); /* no carry */ result[k] = r01.m_low; r01.m_low = r01.m_high; @@ -487,8 +497,7 @@ static void vli_square(u64 *result, const u64 *left, unsigned int ndigits) product.m_low <<= 1; } - r01 = add_128_128(r01, product); - r2 += (r01.m_high < product.m_high); + r2 += check_add_128_128_overflow(&r01, r01, product); } result[k] = r01.m_low; From 277281c10c63791067d24d421f7c43a15faa9096 Mon Sep 17 00:00:00 2001 From: Giovanni Cabiddu Date: Wed, 13 May 2026 15:47:32 +0100 Subject: [PATCH 124/196] crypto: qat - fix VF2PF work teardown race in adf_disable_sriov() The VF2PF interrupt handler queues PF-side response work that stores a raw pointer to per-VF state (struct adf_accel_vf_info). Currently, adf_disable_sriov() destroys per-VF mutexes and frees vf_info without stopping new VF2PF work or waiting for in-flight workers to complete. A concurrently scheduled or already queued worker can then dereference freed memory. This manifests as a use-after-free when KASAN is enabled: BUG: KASAN: null-ptr-deref in mutex_lock+0x76/0xe0 Write of size 8 at addr 0000000000000260 by task kworker/24:2/... Workqueue: qat_pf2vf_resp_wq adf_iov_send_resp [intel_qat] Call Trace: kasan_report+0x119/0x140 mutex_lock+0x76/0xe0 adf_gen4_pfvf_send+0xd4/0x1f0 [intel_qat] adf_recv_and_handle_vf2pf_msg+0x290/0x360 [intel_qat] adf_iov_send_resp+0x8c/0xe0 [intel_qat] process_one_work+0x6ac/0xfd0 worker_thread+0x4dd/0xd30 kthread+0x326/0x410 ret_from_fork+0x33b/0x670 Add a PF-local flag, vf2pf_disabled, that gates work queueing, worker processing, and interrupt re-enabling during teardown. Set this flag atomically with the hardware interrupt mask inside adf_disable_all_vf2pf_interrupts(). After masking, synchronize the AE cluster MSI-X interrupt and flush the PF response workqueue before tearing down per-VF locks and state so all in-flight work completes before vf_info is destroyed. Introduce adf_enable_all_vf2pf_interrupts() to clear the flag and unmask all VF2PF interrupts under the same lock when SR-IOV is re-enabled. This ensures the software flag and hardware state transition atomically on both the enable and disable paths. Cc: stable@vger.kernel.org Fixes: ed8ccaef52fa ("crypto: qat - Add support for SRIOV") Signed-off-by: Giovanni Cabiddu Reviewed-by: Ahsan Atta Signed-off-by: Herbert Xu --- .../intel/qat/qat_common/adf_accel_devices.h | 2 + .../intel/qat/qat_common/adf_common_drv.h | 2 + drivers/crypto/intel/qat/qat_common/adf_isr.c | 39 +++++++++++++++++++ .../crypto/intel/qat/qat_common/adf_sriov.c | 20 +++++++++- 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h b/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h index 03a4e9690208..d9b2a1cf474e 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h +++ b/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h @@ -480,6 +480,8 @@ struct adf_accel_dev { struct { /* protects VF2PF interrupts access */ spinlock_t vf2pf_ints_lock; + /* prevents VF2PF handling from racing with VF state teardown */ + bool vf2pf_disabled; /* vf_info is non-zero when SR-IOV is init'ed */ struct adf_accel_vf_info *vf_info; } pf; diff --git a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h index a05d149423b0..b9188ea9aa72 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h +++ b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h @@ -110,6 +110,7 @@ void qat_comp_alg_callback(void *resp); int adf_isr_resource_alloc(struct adf_accel_dev *accel_dev); void adf_isr_resource_free(struct adf_accel_dev *accel_dev); +void adf_isr_sync_ae_cluster(struct adf_accel_dev *accel_dev); int adf_vf_isr_resource_alloc(struct adf_accel_dev *accel_dev); void adf_vf_isr_resource_free(struct adf_accel_dev *accel_dev); @@ -183,6 +184,7 @@ int adf_sriov_configure(struct pci_dev *pdev, int numvfs); void adf_disable_sriov(struct adf_accel_dev *accel_dev); void adf_reenable_sriov(struct adf_accel_dev *accel_dev); void adf_enable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, u32 vf_mask); +void adf_enable_all_vf2pf_interrupts(struct adf_accel_dev *accel_dev, u32 num_vfs); void adf_disable_all_vf2pf_interrupts(struct adf_accel_dev *accel_dev); bool adf_recv_and_handle_pf2vf_msg(struct adf_accel_dev *accel_dev); bool adf_recv_and_handle_vf2pf_msg(struct adf_accel_dev *accel_dev, u32 vf_nr); diff --git a/drivers/crypto/intel/qat/qat_common/adf_isr.c b/drivers/crypto/intel/qat/qat_common/adf_isr.c index 4639d7fd93e6..159e91a50106 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_isr.c +++ b/drivers/crypto/intel/qat/qat_common/adf_isr.c @@ -62,6 +62,23 @@ void adf_enable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, u32 vf_mask) unsigned long flags; spin_lock_irqsave(&accel_dev->pf.vf2pf_ints_lock, flags); + if (!READ_ONCE(accel_dev->pf.vf2pf_disabled)) + GET_PFVF_OPS(accel_dev)->enable_vf2pf_interrupts(pmisc_addr, vf_mask); + spin_unlock_irqrestore(&accel_dev->pf.vf2pf_ints_lock, flags); +} + +void adf_enable_all_vf2pf_interrupts(struct adf_accel_dev *accel_dev, u32 num_vfs) +{ + void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev); + unsigned long flags; + u32 vf_mask; + + vf_mask = BIT_ULL(num_vfs) - 1; + if (!vf_mask) + return; + + spin_lock_irqsave(&accel_dev->pf.vf2pf_ints_lock, flags); + WRITE_ONCE(accel_dev->pf.vf2pf_disabled, false); GET_PFVF_OPS(accel_dev)->enable_vf2pf_interrupts(pmisc_addr, vf_mask); spin_unlock_irqrestore(&accel_dev->pf.vf2pf_ints_lock, flags); } @@ -72,6 +89,7 @@ void adf_disable_all_vf2pf_interrupts(struct adf_accel_dev *accel_dev) unsigned long flags; spin_lock_irqsave(&accel_dev->pf.vf2pf_ints_lock, flags); + WRITE_ONCE(accel_dev->pf.vf2pf_disabled, true); GET_PFVF_OPS(accel_dev)->disable_all_vf2pf_interrupts(pmisc_addr); spin_unlock_irqrestore(&accel_dev->pf.vf2pf_ints_lock, flags); } @@ -174,6 +192,27 @@ static irqreturn_t adf_msix_isr_ae(int irq, void *dev_ptr) return IRQ_NONE; } +void adf_isr_sync_ae_cluster(struct adf_accel_dev *accel_dev) +{ + struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev; + struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev); + u32 num_entries = pci_dev_info->msix_entries.num_entries; + struct adf_irq *irqs = pci_dev_info->msix_entries.irqs; + u32 irq_idx; + int irq; + + if (!test_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status) || !irqs) + return; + + irq_idx = num_entries > 1 ? hw_data->num_banks : 0; + if (irq_idx >= num_entries || !irqs[irq_idx].enabled) + return; + + irq = pci_irq_vector(pci_dev_info->pci_dev, hw_data->num_banks); + if (irq > 0) + synchronize_irq(irq); +} + static void adf_free_irqs(struct adf_accel_dev *accel_dev) { struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev; diff --git a/drivers/crypto/intel/qat/qat_common/adf_sriov.c b/drivers/crypto/intel/qat/qat_common/adf_sriov.c index 8bf0fe1fcb4d..96939572109e 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_sriov.c +++ b/drivers/crypto/intel/qat/qat_common/adf_sriov.c @@ -26,6 +26,9 @@ static void adf_iov_send_resp(struct work_struct *work) u32 vf_nr = vf_info->vf_nr; bool ret; + if (READ_ONCE(accel_dev->pf.vf2pf_disabled)) + goto out; + mutex_lock(&vf_info->pfvf_mig_lock); ret = adf_recv_and_handle_vf2pf_msg(accel_dev, vf_nr); if (ret) @@ -33,13 +36,18 @@ static void adf_iov_send_resp(struct work_struct *work) adf_enable_vf2pf_interrupts(accel_dev, 1 << vf_nr); mutex_unlock(&vf_info->pfvf_mig_lock); +out: kfree(pf2vf_resp); } void adf_schedule_vf2pf_handler(struct adf_accel_vf_info *vf_info) { + struct adf_accel_dev *accel_dev = vf_info->accel_dev; struct adf_pf2vf_resp *pf2vf_resp; + if (READ_ONCE(accel_dev->pf.vf2pf_disabled)) + return; + pf2vf_resp = kzalloc_obj(*pf2vf_resp, GFP_ATOMIC); if (!pf2vf_resp) return; @@ -49,6 +57,12 @@ void adf_schedule_vf2pf_handler(struct adf_accel_vf_info *vf_info) queue_work(pf2vf_resp_wq, &pf2vf_resp->pf2vf_resp_work); } +static void adf_flush_pf2vf_resp_wq(void) +{ + if (pf2vf_resp_wq) + flush_workqueue(pf2vf_resp_wq); +} + static int adf_enable_sriov(struct adf_accel_dev *accel_dev) { struct pci_dev *pdev = accel_to_pci_dev(accel_dev); @@ -75,7 +89,7 @@ static int adf_enable_sriov(struct adf_accel_dev *accel_dev) hw_data->configure_iov_threads(accel_dev, true); /* Enable VF to PF interrupts for all VFs */ - adf_enable_vf2pf_interrupts(accel_dev, BIT_ULL(totalvfs) - 1); + adf_enable_all_vf2pf_interrupts(accel_dev, totalvfs); /* * Due to the hardware design, when SR-IOV and the ring arbiter @@ -248,8 +262,10 @@ void adf_disable_sriov(struct adf_accel_dev *accel_dev) adf_pf2vf_wait_for_restarting_complete(accel_dev); pci_disable_sriov(accel_to_pci_dev(accel_dev)); - /* Disable VF to PF interrupts */ + /* Block VF2PF work and disable VF to PF interrupts */ adf_disable_all_vf2pf_interrupts(accel_dev); + adf_isr_sync_ae_cluster(accel_dev); + adf_flush_pf2vf_resp_wq(); /* Clear Valid bits in AE Thread to PCIe Function Mapping */ if (hw_data->configure_iov_threads) From 57518500053987672050dc2f7bf8a774d5d52fd9 Mon Sep 17 00:00:00 2001 From: Ahsan Atta Date: Wed, 13 May 2026 17:16:54 +0200 Subject: [PATCH 125/196] crypto: qat - keep VFs enabled during reset When a reset is triggered via sysfs, the PCI core invokes the reset_prepare() callback while holding pci_dev_lock(), which includes the PCI configuration space access semaphore. If reset_prepare() calls adf_dev_down(), the call chain adf_dev_stop() -> adf_disable_sriov() -> pci_disable_sriov() attempts to acquire the same semaphore, resulting in a deadlock. Avoid this by skipping pci_disable_sriov() when ADF_STATUS_RESTARTING is set. During reset the PCI topology is preserved, so VF devices remain valid and enumerated across the reset. VF notification and the quiesce handshake via adf_pf2vf_notify_restarting() are still performed unconditionally so that VFs stop submitting work before the PF shuts down. Correspondingly, skip pci_enable_sriov() in adf_enable_sriov() when VFs are already present, since their PCI devices were preserved from before the restart. This is in preparation for adding reset_prepare() and reset_done() callbacks in adf_aer.c. Cc: stable@vger.kernel.org Signed-off-by: Ahsan Atta Reviewed-by: Giovanni Cabiddu Reviewed-by: Damian Muszynski Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/adf_sriov.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/intel/qat/qat_common/adf_sriov.c b/drivers/crypto/intel/qat/qat_common/adf_sriov.c index 96939572109e..f2011300a929 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_sriov.c +++ b/drivers/crypto/intel/qat/qat_common/adf_sriov.c @@ -91,6 +91,10 @@ static int adf_enable_sriov(struct adf_accel_dev *accel_dev) /* Enable VF to PF interrupts for all VFs */ adf_enable_all_vf2pf_interrupts(accel_dev, totalvfs); + /* Do not enable SR-IOV if already enabled */ + if (pci_num_vf(pdev)) + return 0; + /* * Due to the hardware design, when SR-IOV and the ring arbiter * are enabled all the VFs supported in hardware must be enabled in @@ -260,7 +264,13 @@ void adf_disable_sriov(struct adf_accel_dev *accel_dev) adf_pf2vf_notify_restarting(accel_dev); adf_pf2vf_wait_for_restarting_complete(accel_dev); - pci_disable_sriov(accel_to_pci_dev(accel_dev)); + /* + * When the device is restarting, preserve VF PCI devices across + * the reset by skipping pci_disable_sriov(). VFs are notified to + * quiesce regardless so the PF can safely shut down. + */ + if (!test_bit(ADF_STATUS_RESTARTING, &accel_dev->status)) + pci_disable_sriov(accel_to_pci_dev(accel_dev)); /* Block VF2PF work and disable VF to PF interrupts */ adf_disable_all_vf2pf_interrupts(accel_dev); From 6931835f2fdd0cb9b1c7791748d7e67d0749056a Mon Sep 17 00:00:00 2001 From: Ahsan Atta Date: Wed, 13 May 2026 17:16:55 +0200 Subject: [PATCH 126/196] crypto: qat - notify fatal error before AER reset preparation Send fatal error notifications to subsystems and VFs as soon as AER error detection starts, before entering the reset preparation shutdown sequence. This reduces notification latency and ensures peers are informed immediately on fatal detection, rather than after restart-state setup and arbitration teardown. Cc: stable@vger.kernel.org Signed-off-by: Ahsan Atta Reviewed-by: Giovanni Cabiddu Reviewed-by: Damian Muszynski Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/adf_aer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_common/adf_aer.c b/drivers/crypto/intel/qat/qat_common/adf_aer.c index ed01fb9ad74e..9c6bfb9fef80 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_aer.c +++ b/drivers/crypto/intel/qat/qat_common/adf_aer.c @@ -33,13 +33,13 @@ static pci_ers_result_t adf_error_detected(struct pci_dev *pdev, return PCI_ERS_RESULT_DISCONNECT; } + adf_error_notifier(accel_dev); + adf_pf2vf_notify_fatal_error(accel_dev); set_bit(ADF_STATUS_RESTARTING, &accel_dev->status); if (accel_dev->hw_device->exit_arb) { dev_dbg(&pdev->dev, "Disabling arbitration\n"); accel_dev->hw_device->exit_arb(accel_dev); } - adf_error_notifier(accel_dev); - adf_pf2vf_notify_fatal_error(accel_dev); adf_dev_restarting_notify(accel_dev); pci_clear_master(pdev); adf_dev_down(accel_dev); From e5712ff82947dd02d118cee119ed36cec671d814 Mon Sep 17 00:00:00 2001 From: Ahsan Atta Date: Wed, 13 May 2026 17:16:56 +0200 Subject: [PATCH 127/196] crypto: qat - centralize bus master enable QAT driver currently toggles PCI bus mastering in multiple places (probe paths, and reset callbacks). This makes BME state depend on call ordering and on what PCI command bits were captured in saved PCI config state. Make BME control explicit and deterministic: - remove pci_set_master() from device-specific probe paths - add adf_set_bme() and call it from adf_dev_init() so BME is enabled at one point before device bring-up - drop redundant pci_set_master() and pci_clear_master from adf_aer.c and rely on the unified init path for BME enablement This is in preparation for adding reset_prepare() and reset_done() hooks. In the PCI reset callback flow, the PCI core saves and restores device configuration state around reset_prepare() and reset_done(). This change is needed to ensure that we are able to properly shutdown or reinitialize the device post sysfs triggered resets. Cc: stable@vger.kernel.org Signed-off-by: Ahsan Atta Reviewed-by: Giovanni Cabiddu Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_420xx/adf_drv.c | 2 -- drivers/crypto/intel/qat/qat_4xxx/adf_drv.c | 2 -- drivers/crypto/intel/qat/qat_6xxx/adf_drv.c | 2 -- drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c | 1 - drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c | 1 - drivers/crypto/intel/qat/qat_c62x/adf_drv.c | 1 - drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c | 1 - drivers/crypto/intel/qat/qat_common/adf_aer.c | 10 +++++++--- drivers/crypto/intel/qat/qat_common/adf_common_drv.h | 1 + drivers/crypto/intel/qat/qat_common/adf_init.c | 2 ++ drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c | 1 - drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c | 1 - 12 files changed, 10 insertions(+), 15 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_420xx/adf_drv.c b/drivers/crypto/intel/qat/qat_420xx/adf_drv.c index 566adc0a2d11..265bd52778c5 100644 --- a/drivers/crypto/intel/qat/qat_420xx/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_420xx/adf_drv.c @@ -146,8 +146,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } } - pci_set_master(pdev); - if (pci_save_state(pdev)) { dev_err(&pdev->dev, "Failed to save pci state.\n"); ret = -ENOMEM; diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c index daca73651c14..681c4dd8f3d2 100644 --- a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c @@ -148,8 +148,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } } - pci_set_master(pdev); - if (pci_save_state(pdev)) { dev_err(&pdev->dev, "Failed to save pci state.\n"); ret = -ENOMEM; diff --git a/drivers/crypto/intel/qat/qat_6xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_6xxx/adf_drv.c index c52462a48c34..ab62b91ecb51 100644 --- a/drivers/crypto/intel/qat/qat_6xxx/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_6xxx/adf_drv.c @@ -189,8 +189,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } } - pci_set_master(pdev); - /* * The PCI config space is saved at this point and will be restored * after a Function Level Reset (FLR) as the FLR does not completely diff --git a/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c index 7a59bca3242f..ded52744b4fc 100644 --- a/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c @@ -167,7 +167,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err_free_reg; } } - pci_set_master(pdev); if (pci_save_state(pdev)) { dev_err(&pdev->dev, "Failed to save pci state\n"); diff --git a/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c b/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c index 0881575f7670..e7600d284ed3 100644 --- a/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c @@ -163,7 +163,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err_free_reg; } } - pci_set_master(pdev); /* Completion for VF2PF request/response message exchange */ init_completion(&accel_dev->vf.msg_received); diff --git a/drivers/crypto/intel/qat/qat_c62x/adf_drv.c b/drivers/crypto/intel/qat/qat_c62x/adf_drv.c index 4972e52dd944..2ebff5855b01 100644 --- a/drivers/crypto/intel/qat/qat_c62x/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_c62x/adf_drv.c @@ -167,7 +167,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err_free_reg; } } - pci_set_master(pdev); if (pci_save_state(pdev)) { dev_err(&pdev->dev, "Failed to save pci state\n"); diff --git a/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c b/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c index d3f728b9f2f2..91e148bb4870 100644 --- a/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c @@ -163,7 +163,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err_free_reg; } } - pci_set_master(pdev); /* Completion for VF2PF request/response message exchange */ init_completion(&accel_dev->vf.msg_received); diff --git a/drivers/crypto/intel/qat/qat_common/adf_aer.c b/drivers/crypto/intel/qat/qat_common/adf_aer.c index 9c6bfb9fef80..365637e40439 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_aer.c +++ b/drivers/crypto/intel/qat/qat_common/adf_aer.c @@ -41,7 +41,6 @@ static pci_ers_result_t adf_error_detected(struct pci_dev *pdev, accel_dev->hw_device->exit_arb(accel_dev); } adf_dev_restarting_notify(accel_dev); - pci_clear_master(pdev); adf_dev_down(accel_dev); return PCI_ERS_RESULT_NEED_RESET; @@ -106,6 +105,13 @@ void adf_dev_restore(struct adf_accel_dev *accel_dev) } } +void adf_set_bme(struct adf_accel_dev *accel_dev) +{ + struct pci_dev *pdev = accel_to_pci_dev(accel_dev); + + pci_set_master(pdev); +} + static void adf_device_sriov_worker(struct work_struct *work) { struct adf_sriov_dev_data *sriov_data = @@ -198,8 +204,6 @@ static pci_ers_result_t adf_slot_reset(struct pci_dev *pdev) return PCI_ERS_RESULT_DISCONNECT; } - if (!pdev->is_busmaster) - pci_set_master(pdev); pci_restore_state(pdev); res = adf_dev_up(accel_dev, false); if (res && res != -EALREADY) diff --git a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h index b9188ea9aa72..762a0b5e774a 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h +++ b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h @@ -77,6 +77,7 @@ extern const struct pci_error_handlers adf_err_handler; void adf_reset_sbr(struct adf_accel_dev *accel_dev); void adf_reset_flr(struct adf_accel_dev *accel_dev); void adf_dev_restore(struct adf_accel_dev *accel_dev); +void adf_set_bme(struct adf_accel_dev *accel_dev); int adf_init_aer(void); void adf_exit_aer(void); int adf_init_arb(struct adf_accel_dev *accel_dev); diff --git a/drivers/crypto/intel/qat/qat_common/adf_init.c b/drivers/crypto/intel/qat/qat_common/adf_init.c index f8088388cf12..f9f5696ed476 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_init.c +++ b/drivers/crypto/intel/qat/qat_common/adf_init.c @@ -74,6 +74,8 @@ static int adf_dev_init(struct adf_accel_dev *accel_dev) return -EFAULT; } + adf_set_bme(accel_dev); + if (!test_bit(ADF_STATUS_CONFIGURED, &accel_dev->status) && !accel_dev->is_vf) { dev_err(&GET_DEV(accel_dev), "Device not configured\n"); diff --git a/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c b/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c index 8a863d7d86d7..97ad53eef38f 100644 --- a/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c @@ -167,7 +167,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err_free_reg; } } - pci_set_master(pdev); if (pci_save_state(pdev)) { dev_err(&pdev->dev, "Failed to save pci state\n"); diff --git a/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c b/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c index f8a6e10a1de7..a5edda8bad32 100644 --- a/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c @@ -163,7 +163,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err_free_reg; } } - pci_set_master(pdev); /* Completion for VF2PF request/response message exchange */ init_completion(&accel_dev->vf.msg_received); From 9676657117b79f88c22875680c36d7da84b75eca Mon Sep 17 00:00:00 2001 From: Ahsan Atta Date: Wed, 13 May 2026 17:16:57 +0200 Subject: [PATCH 128/196] crypto: qat - skip restart for down devices Skip the shutdown and restart flow when adf_slot_reset() is entered for a device that is already down. In that case, leave ADF_STATUS_RESTARTING clear and let adf_slot_reset() restore PCI function state without calling adf_dev_up(), re-enabling SR-IOV, or sending restarted notifications. This is in preparation for adding reset_prepare() and reset_done() callbacks in adf_aer.c. Cc: stable@vger.kernel.org Signed-off-by: Ahsan Atta Reviewed-by: Giovanni Cabiddu Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/adf_aer.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/crypto/intel/qat/qat_common/adf_aer.c b/drivers/crypto/intel/qat/qat_common/adf_aer.c index 365637e40439..7255cac5aaa6 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_aer.c +++ b/drivers/crypto/intel/qat/qat_common/adf_aer.c @@ -33,6 +33,9 @@ static pci_ers_result_t adf_error_detected(struct pci_dev *pdev, return PCI_ERS_RESULT_DISCONNECT; } + if (!adf_dev_started(accel_dev)) + return PCI_ERS_RESULT_CAN_RECOVER; + adf_error_notifier(accel_dev); adf_pf2vf_notify_fatal_error(accel_dev); set_bit(ADF_STATUS_RESTARTING, &accel_dev->status); @@ -204,6 +207,9 @@ static pci_ers_result_t adf_slot_reset(struct pci_dev *pdev) return PCI_ERS_RESULT_DISCONNECT; } + if (!adf_devmgr_in_reset(accel_dev)) + goto reset_complete; + pci_restore_state(pdev); res = adf_dev_up(accel_dev, false); if (res && res != -EALREADY) @@ -213,6 +219,8 @@ static pci_ers_result_t adf_slot_reset(struct pci_dev *pdev) adf_pf2vf_notify_restarted(accel_dev); adf_dev_restarted_notify(accel_dev); clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status); + +reset_complete: return PCI_ERS_RESULT_RECOVERED; } From 56707afb92fee371c0f2e04332c9aa03cdb89793 Mon Sep 17 00:00:00 2001 From: Ahsan Atta Date: Wed, 13 May 2026 17:16:58 +0200 Subject: [PATCH 129/196] crypto: qat - factor out AER reset helpers Move the shutdown and recovery sequences out of adf_error_detected() and adf_slot_reset() into reset_prepare() and reset_done() helpers. This makes the AER recovery path easier to follow and prepares the common reset flow for reuse by additional PCI reset callbacks without duplicating the logic. No functional change intended. Cc: stable@vger.kernel.org Signed-off-by: Ahsan Atta Reviewed-by: Giovanni Cabiddu Reviewed-by: Damian Muszynski Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/adf_aer.c | 88 ++++++++++++------- 1 file changed, 54 insertions(+), 34 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_common/adf_aer.c b/drivers/crypto/intel/qat/qat_common/adf_aer.c index 7255cac5aaa6..d29f70eb84b8 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_aer.c +++ b/drivers/crypto/intel/qat/qat_common/adf_aer.c @@ -17,6 +17,58 @@ struct adf_fatal_error_data { static struct workqueue_struct *device_reset_wq; static struct workqueue_struct *device_sriov_wq; +static pci_ers_result_t reset_prepare(struct pci_dev *pdev) +{ + struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev); + + if (!accel_dev) { + dev_err(&pdev->dev, "Can't find acceleration device\n"); + return PCI_ERS_RESULT_DISCONNECT; + } + + if (!adf_dev_started(accel_dev)) + return PCI_ERS_RESULT_CAN_RECOVER; + + set_bit(ADF_STATUS_RESTARTING, &accel_dev->status); + if (accel_dev->hw_device->exit_arb) { + dev_dbg(&pdev->dev, "Disabling arbitration\n"); + accel_dev->hw_device->exit_arb(accel_dev); + } + adf_dev_restarting_notify(accel_dev); + adf_dev_down(accel_dev); + + return PCI_ERS_RESULT_NEED_RESET; +} + +static pci_ers_result_t reset_done(struct pci_dev *pdev) +{ + struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev); + int res; + + if (!accel_dev) { + dev_err(&pdev->dev, "Can't find acceleration device\n"); + return PCI_ERS_RESULT_DISCONNECT; + } + + if (!adf_devmgr_in_reset(accel_dev)) + goto reset_complete; + + pci_restore_state(pdev); + res = adf_dev_up(accel_dev, false); + if (res && res != -EALREADY) + return PCI_ERS_RESULT_DISCONNECT; + + adf_reenable_sriov(accel_dev); + adf_pf2vf_notify_restarted(accel_dev); + adf_dev_restarted_notify(accel_dev); + clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status); + +reset_complete: + dev_info(&pdev->dev, "Device reset completed successfully\n"); + + return PCI_ERS_RESULT_RECOVERED; +} + static pci_ers_result_t adf_error_detected(struct pci_dev *pdev, pci_channel_state_t state) { @@ -33,20 +85,10 @@ static pci_ers_result_t adf_error_detected(struct pci_dev *pdev, return PCI_ERS_RESULT_DISCONNECT; } - if (!adf_dev_started(accel_dev)) - return PCI_ERS_RESULT_CAN_RECOVER; - adf_error_notifier(accel_dev); adf_pf2vf_notify_fatal_error(accel_dev); - set_bit(ADF_STATUS_RESTARTING, &accel_dev->status); - if (accel_dev->hw_device->exit_arb) { - dev_dbg(&pdev->dev, "Disabling arbitration\n"); - accel_dev->hw_device->exit_arb(accel_dev); - } - adf_dev_restarting_notify(accel_dev); - adf_dev_down(accel_dev); - return PCI_ERS_RESULT_NEED_RESET; + return reset_prepare(pdev); } /* reset dev data */ @@ -199,29 +241,7 @@ static int adf_dev_aer_schedule_reset(struct adf_accel_dev *accel_dev, static pci_ers_result_t adf_slot_reset(struct pci_dev *pdev) { - struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev); - int res = 0; - - if (!accel_dev) { - pr_err("QAT: Can't find acceleration device\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - - if (!adf_devmgr_in_reset(accel_dev)) - goto reset_complete; - - pci_restore_state(pdev); - res = adf_dev_up(accel_dev, false); - if (res && res != -EALREADY) - return PCI_ERS_RESULT_DISCONNECT; - - adf_reenable_sriov(accel_dev); - adf_pf2vf_notify_restarted(accel_dev); - adf_dev_restarted_notify(accel_dev); - clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status); - -reset_complete: - return PCI_ERS_RESULT_RECOVERED; + return reset_done(pdev); } static void adf_resume(struct pci_dev *pdev) From 4627ef7019bc532f992c0723e881811ce12f0a02 Mon Sep 17 00:00:00 2001 From: Ahsan Atta Date: Wed, 13 May 2026 17:16:59 +0200 Subject: [PATCH 130/196] crypto: qat - handle sysfs-triggered reset callbacks A reset requested through /sys/bus/pci/devices/.../reset invokes the driver reset_prepare() and reset_done() callbacks. The QAT driver does not implement those callbacks today, so the reset proceeds without quiescing the device or bringing it back up afterward, which leaves the device unusable. Hook reset_prepare() and reset_done() into adf_err_handler so the common shutdown and recovery flow also runs for reset. Skip device quiesce if the device is already in a down state. Cc: stable@vger.kernel.org Signed-off-by: Ahsan Atta Reviewed-by: Giovanni Cabiddu Reviewed-by: Damian Muszynski Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/adf_aer.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/crypto/intel/qat/qat_common/adf_aer.c b/drivers/crypto/intel/qat/qat_common/adf_aer.c index d29f70eb84b8..af028488e660 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_aer.c +++ b/drivers/crypto/intel/qat/qat_common/adf_aer.c @@ -250,10 +250,22 @@ static void adf_resume(struct pci_dev *pdev) dev_info(&pdev->dev, "Device is up and running\n"); } +static void adf_reset_prepare(struct pci_dev *pdev) +{ + reset_prepare(pdev); +} + +static void adf_reset_done(struct pci_dev *pdev) +{ + reset_done(pdev); +} + const struct pci_error_handlers adf_err_handler = { .error_detected = adf_error_detected, .slot_reset = adf_slot_reset, .resume = adf_resume, + .reset_prepare = adf_reset_prepare, + .reset_done = adf_reset_done, }; EXPORT_SYMBOL_GPL(adf_err_handler); From 86ad8069366642fec18c1bc53c24cad3da720ce5 Mon Sep 17 00:00:00 2001 From: Fiona Trahe Date: Wed, 13 May 2026 16:33:08 +0100 Subject: [PATCH 131/196] Documentation: qat_rl: make rate limiting wording clearer The term "capability" typically refers to an ability to perform an action, whereas "capacity" denotes a measurable amount of resources. Since the sysfs-driver-qat_rl document describes remaining resources available to perform work, "capacity" is the more accurate term. Replace "capability" with "capacity" in the document. Signed-off-by: Fiona Trahe Reviewed-by: Ahsan Atta Signed-off-by: Giovanni Cabiddu Signed-off-by: Herbert Xu --- Documentation/ABI/testing/sysfs-driver-qat_rl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-driver-qat_rl b/Documentation/ABI/testing/sysfs-driver-qat_rl index d534f89b4971..422333a0eb69 100644 --- a/Documentation/ABI/testing/sysfs-driver-qat_rl +++ b/Documentation/ABI/testing/sysfs-driver-qat_rl @@ -209,7 +209,7 @@ Date: January 2024 KernelVersion: 6.7 Contact: qat-linux@intel.com Description: - (RW) This file will return the remaining capability for a + (RW) This file will return the remaining capacity for a particular service/sla. This is the remaining value that a new SLA can be set to or a current SLA can be increased with. From 3b626ba431c4501512ad07549310685e07fe4706 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Thu, 14 May 2026 08:55:58 +0200 Subject: [PATCH 132/196] X.509: Fix validation of ASN.1 certificate header x509_load_certificate_list() seeks to enforce that a certificate starts with 0x30 0x82 (ASN.1 SEQUENCE tag followed by a length of more than 256 and less than 65535 bytes). But it only enforces that *either* of those two byte values are present, instead of checking for the *conjunction* of the two values. Fix it. Fixes: 631cc66eb9ea ("MODSIGN: Provide module signing public keys to the kernel") Reported-by: Sashiko Closes: https://lore.kernel.org/r/20260508033917.B5873C2BCB0@smtp.kernel.org/ Signed-off-by: Lukas Wunner Cc: stable@vger.kernel.org # v3.7+ Reviewed-by: Ignat Korchagin Reviewed-by: Alistair Francis Signed-off-by: Herbert Xu --- crypto/asymmetric_keys/x509_loader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/asymmetric_keys/x509_loader.c b/crypto/asymmetric_keys/x509_loader.c index a41741326998..0d516c77cc26 100644 --- a/crypto/asymmetric_keys/x509_loader.c +++ b/crypto/asymmetric_keys/x509_loader.c @@ -20,7 +20,7 @@ int x509_load_certificate_list(const u8 cert_list[], */ if (end - p < 4) goto dodgy_cert; - if (p[0] != 0x30 && + if (p[0] != 0x30 || p[1] != 0x82) goto dodgy_cert; plen = (p[2] << 8) | p[3]; From fc2d791a43d3880496d1c729b8bd74d2c19cb4e7 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Thu, 14 May 2026 18:55:10 +0200 Subject: [PATCH 133/196] crypto: riscv/aes - replace min_t with min in riscv64_aes_ctr_crypt Use the simpler min() macro since the values are unsigned and compatible. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- arch/riscv/crypto/aes-riscv64-glue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/riscv/crypto/aes-riscv64-glue.c b/arch/riscv/crypto/aes-riscv64-glue.c index 8bbf7f348c23..bbd920c9e29d 100644 --- a/arch/riscv/crypto/aes-riscv64-glue.c +++ b/arch/riscv/crypto/aes-riscv64-glue.c @@ -19,6 +19,7 @@ #include #include #include +#include #include asmlinkage void aes_ecb_encrypt_zvkned(const struct crypto_aes_ctx *key, @@ -266,8 +267,7 @@ static int riscv64_aes_ctr_crypt(struct skcipher_request *req) * operation into two at the point where the overflow * will occur. After the first part, add the carry bit. */ - p1_nbytes = min_t(unsigned int, nbytes, - (nblocks - ctr32) * AES_BLOCK_SIZE); + p1_nbytes = min(nbytes, (nblocks - ctr32) * AES_BLOCK_SIZE); aes_ctr32_crypt_zvkned_zvkb(ctx, walk.src.virt.addr, walk.dst.virt.addr, p1_nbytes, req->iv); From f8c9c57d750346abd213ffed2ae3cacb0268e9f1 Mon Sep 17 00:00:00 2001 From: Mikko Perttunen Date: Fri, 15 May 2026 11:34:52 +0900 Subject: [PATCH 134/196] crypto: tegra - Don't touch bo refcount in host1x bo pin/unpin Since commit "gpu: host1x: Allow entries in BO caches to be freed", host1x_bo_pin() and host1x_bo_unpin() handle the bo's refcount themselves. .pin/.unpin callbacks should not adjust it. Signed-off-by: Mikko Perttunen Signed-off-by: Herbert Xu --- drivers/crypto/tegra/tegra-se-main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/crypto/tegra/tegra-se-main.c b/drivers/crypto/tegra/tegra-se-main.c index eb71113ed146..d7541a9c0a92 100644 --- a/drivers/crypto/tegra/tegra-se-main.c +++ b/drivers/crypto/tegra/tegra-se-main.c @@ -52,7 +52,7 @@ tegra_se_cmdbuf_pin(struct device *dev, struct host1x_bo *bo, enum dma_data_dire return ERR_PTR(-ENOMEM); kref_init(&map->ref); - map->bo = host1x_bo_get(bo); + map->bo = bo; map->direction = direction; map->dev = dev; @@ -93,7 +93,6 @@ static void tegra_se_cmdbuf_unpin(struct host1x_bo_mapping *map) dma_unmap_sgtable(map->dev, map->sgt, map->direction, 0); sg_free_table(map->sgt); kfree(map->sgt); - host1x_bo_put(map->bo); kfree(map); } From 43079e21ff53c6a77e669cec5b5b673b45f46e87 Mon Sep 17 00:00:00 2001 From: Costa Shulyupin Date: Fri, 15 May 2026 22:02:14 +0300 Subject: [PATCH 135/196] include: Remove unused crypto-ux500.h The UX500 crypto drivers were removed in commit 453de3eb08c4 ("crypto: ux500/cryp - delete driver") and commit dd7b7972cb89 ("crypto: ux500/hash - delete driver"). No file includes this header. Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Costa Shulyupin Reviewed-by: Linus Walleij Signed-off-by: Herbert Xu --- include/linux/platform_data/crypto-ux500.h | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 include/linux/platform_data/crypto-ux500.h diff --git a/include/linux/platform_data/crypto-ux500.h b/include/linux/platform_data/crypto-ux500.h deleted file mode 100644 index 5d43350e32cc..000000000000 --- a/include/linux/platform_data/crypto-ux500.h +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) ST-Ericsson SA 2011 - * - * Author: Joakim Bech for ST-Ericsson - */ -#ifndef _CRYPTO_UX500_H -#define _CRYPTO_UX500_H -#include -#include - -struct hash_platform_data { - void *mem_to_engine; - bool (*dma_filter)(struct dma_chan *chan, void *filter_param); -}; - -struct cryp_platform_data { - struct stedma40_chan_cfg mem_to_engine; - struct stedma40_chan_cfg engine_to_mem; -}; - -#endif From 01c8d5662dd2f11a705edc55be3583b05288a26b Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Fri, 15 May 2026 22:29:48 +0200 Subject: [PATCH 136/196] crypto: atmel-i2c - drop redundant void * callback cast in enqueue The callback already has the correct type - remove the redundant cast. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c index 0e275dbdc8c5..ff19857894d0 100644 --- a/drivers/crypto/atmel-i2c.c +++ b/drivers/crypto/atmel-i2c.c @@ -294,7 +294,7 @@ void atmel_i2c_enqueue(struct atmel_i2c_work_data *work_data, void *areq, int status), void *areq) { - work_data->cbk = (void *)cbk; + work_data->cbk = cbk; work_data->areq = areq; INIT_WORK(&work_data->work, atmel_i2c_work_handler); From 09e6b79b8ce388993aec9ac91b1cb2c181c27bd9 Mon Sep 17 00:00:00 2001 From: Aleksander Jan Bajkowski Date: Sat, 16 May 2026 14:26:51 +0200 Subject: [PATCH 137/196] crypto: eip93 - fix reset ring register definition This patch fixes a descriptor ring reset. This causes a hang in the driver's unload/load sequence. Fixes: 9739f5f93b78 ("crypto: eip93 - Add Inside Secure SafeXcel EIP-93 crypto engine support") Suggested-by: Benjamin Larsson Signed-off-by: Aleksander Jan Bajkowski Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/eip93/eip93-regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/inside-secure/eip93/eip93-regs.h b/drivers/crypto/inside-secure/eip93/eip93-regs.h index 96285ca6fbbe..96d28c6651bd 100644 --- a/drivers/crypto/inside-secure/eip93/eip93-regs.h +++ b/drivers/crypto/inside-secure/eip93/eip93-regs.h @@ -103,7 +103,7 @@ #define EIP93_PE_TARGET_COMMAND_NO_RDR_MODE FIELD_PREP(EIP93_PE_CONFIG_PE_MODE, 0x2) #define EIP93_PE_TARGET_COMMAND_WITH_RDR_MODE FIELD_PREP(EIP93_PE_CONFIG_PE_MODE, 0x1) #define EIP93_PE_DIRECT_HOST_MODE FIELD_PREP(EIP93_PE_CONFIG_PE_MODE, 0x0) -#define EIP93_PE_CONFIG_RST_RING BIT(2) +#define EIP93_PE_CONFIG_RST_RING BIT(1) #define EIP93_PE_CONFIG_RST_PE BIT(0) #define EIP93_REG_PE_STATUS 0x104 #define EIP93_REG_PE_BUF_THRESH 0x10c From 2b7b16c905b08a4cd28cbb2809ee38a78bfe0489 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sat, 16 May 2026 20:23:36 +0200 Subject: [PATCH 138/196] crypto: drivers - remove of_match_ptr from OF match tables Drop of_match_ptr() because OF matching is stubbed out when CONFIG_OF=n. Indent bcm_spu_pdriver.driver and its members while at it. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/bcm/cipher.c | 6 +++--- drivers/crypto/qcom-rng.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/bcm/cipher.c b/drivers/crypto/bcm/cipher.c index 2bce15dc0aa8..240b40ae9cd6 100644 --- a/drivers/crypto/bcm/cipher.c +++ b/drivers/crypto/bcm/cipher.c @@ -4698,9 +4698,9 @@ static void bcm_spu_remove(struct platform_device *pdev) static struct platform_driver bcm_spu_pdriver = { .driver = { - .name = "brcm-spu-crypto", - .of_match_table = of_match_ptr(bcm_spu_dt_ids), - }, + .name = "brcm-spu-crypto", + .of_match_table = bcm_spu_dt_ids, + }, .probe = bcm_spu_probe, .remove = bcm_spu_remove, }; diff --git a/drivers/crypto/qcom-rng.c b/drivers/crypto/qcom-rng.c index 0685ba122e8a..150e5802e351 100644 --- a/drivers/crypto/qcom-rng.c +++ b/drivers/crypto/qcom-rng.c @@ -265,7 +265,7 @@ static struct platform_driver qcom_rng_driver = { .remove = qcom_rng_remove, .driver = { .name = KBUILD_MODNAME, - .of_match_table = of_match_ptr(qcom_rng_of_match), + .of_match_table = qcom_rng_of_match, .acpi_match_table = ACPI_PTR(qcom_rng_acpi_match), } }; From 08b0f3a77561550d2358c73ceba59e1c5fa5721a Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sun, 17 May 2026 01:42:12 +0200 Subject: [PATCH 139/196] crypto: atmel-sha - use memcpy_and_pad to simplify hmac_setup Use memcpy_and_pad() instead of memcpy() followed by memset() to simplify atmel_sha_hmac_setup(). Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index 7e7c83a3d8cd..8e3b8efa8109 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -1724,8 +1724,7 @@ static int atmel_sha_hmac_setup(struct atmel_sha_dev *dd, return atmel_sha_hmac_prehash_key(dd, key, keylen); /* Prepare ipad. */ - memcpy((u8 *)hmac->ipad, key, keylen); - memset((u8 *)hmac->ipad + keylen, 0, bs - keylen); + memcpy_and_pad(hmac->ipad, bs, key, keylen, 0); return atmel_sha_hmac_compute_ipad_hash(dd); } From 42e4579846d58ec790c4cde4094a1b5f80b13703 Mon Sep 17 00:00:00 2001 From: Ethan Nelson-Moore Date: Sat, 16 May 2026 20:14:26 -0700 Subject: [PATCH 140/196] LoongArch: Remove unused arch/loongarch/crypto directory All LoongArch crypto code was moved to arch/loongarch/lib in commit 72f51a4f4b07 ("loongarch/crc32: expose CRC32 functions through lib"). However, arch/loongarch/crypto still contains stub Kconfig and Makefile files. Remove these unnecessary files. Signed-off-by: Ethan Nelson-Moore Signed-off-by: Herbert Xu --- arch/loongarch/Makefile | 2 -- arch/loongarch/crypto/Kconfig | 5 ----- arch/loongarch/crypto/Makefile | 4 ---- crypto/Kconfig | 3 --- 4 files changed, 14 deletions(-) delete mode 100644 arch/loongarch/crypto/Kconfig delete mode 100644 arch/loongarch/crypto/Makefile diff --git a/arch/loongarch/Makefile b/arch/loongarch/Makefile index 47516aeea9d2..897f85d53a55 100644 --- a/arch/loongarch/Makefile +++ b/arch/loongarch/Makefile @@ -195,8 +195,6 @@ endif libs-y += arch/loongarch/lib/ libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a -drivers-y += arch/loongarch/crypto/ - # suspend and hibernation support drivers-$(CONFIG_PM) += arch/loongarch/power/ diff --git a/arch/loongarch/crypto/Kconfig b/arch/loongarch/crypto/Kconfig deleted file mode 100644 index a0270b3e5b30..000000000000 --- a/arch/loongarch/crypto/Kconfig +++ /dev/null @@ -1,5 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -menu "Accelerated Cryptographic Algorithms for CPU (loongarch)" - -endmenu diff --git a/arch/loongarch/crypto/Makefile b/arch/loongarch/crypto/Makefile deleted file mode 100644 index ba83755dde2b..000000000000 --- a/arch/loongarch/crypto/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for LoongArch crypto files.. -# diff --git a/crypto/Kconfig b/crypto/Kconfig index 00b7ce4227ae..40b7601f00f1 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1366,9 +1366,6 @@ endif if ARM64 source "arch/arm64/crypto/Kconfig" endif -if LOONGARCH -source "arch/loongarch/crypto/Kconfig" -endif if MIPS source "arch/mips/crypto/Kconfig" endif From 2f07f4192687a4fd7352c30bb01160f02f10e9d6 Mon Sep 17 00:00:00 2001 From: Ethan Nelson-Moore Date: Sat, 16 May 2026 20:20:56 -0700 Subject: [PATCH 141/196] MIPS: Remove unused arch/mips/crypto directory The last MIPS crypto code was moved to lib/crypto/mips in commit c9e5ac0ab9d1 ("lib/crypto: mips/md5: Migrate optimized code into library"). However, arch/mips/crypto still contains stub Kconfig, Makefile, and .gitignore files. Remove these unnecessary files. Signed-off-by: Ethan Nelson-Moore Signed-off-by: Herbert Xu --- arch/mips/Makefile | 2 -- arch/mips/crypto/.gitignore | 2 -- arch/mips/crypto/Kconfig | 5 ----- arch/mips/crypto/Makefile | 5 ----- crypto/Kconfig | 3 --- 5 files changed, 17 deletions(-) delete mode 100644 arch/mips/crypto/.gitignore delete mode 100644 arch/mips/crypto/Kconfig delete mode 100644 arch/mips/crypto/Makefile diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 6705fa5d9211..cff1a9a43b89 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -350,8 +350,6 @@ OBJCOPYFLAGS += --remove-section=.reginfo libs-y += arch/mips/lib/ libs-$(CONFIG_MIPS_FP_SUPPORT) += arch/mips/math-emu/ -drivers-y += arch/mips/crypto/ - # suspend and hibernation support drivers-$(CONFIG_PM) += arch/mips/power/ diff --git a/arch/mips/crypto/.gitignore b/arch/mips/crypto/.gitignore deleted file mode 100644 index 0d47d4f21c6d..000000000000 --- a/arch/mips/crypto/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -poly1305-core.S diff --git a/arch/mips/crypto/Kconfig b/arch/mips/crypto/Kconfig deleted file mode 100644 index 6a5bd5074867..000000000000 --- a/arch/mips/crypto/Kconfig +++ /dev/null @@ -1,5 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -menu "Accelerated Cryptographic Algorithms for CPU (mips)" - -endmenu diff --git a/arch/mips/crypto/Makefile b/arch/mips/crypto/Makefile deleted file mode 100644 index 5adb631a69c1..000000000000 --- a/arch/mips/crypto/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for MIPS crypto files.. -# - diff --git a/crypto/Kconfig b/crypto/Kconfig index 40b7601f00f1..b5c5a1e04435 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1366,9 +1366,6 @@ endif if ARM64 source "arch/arm64/crypto/Kconfig" endif -if MIPS -source "arch/mips/crypto/Kconfig" -endif if PPC source "arch/powerpc/crypto/Kconfig" endif From 083c9ab12c402efe9ed55c942ede92eb35f8bf2a Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sun, 17 May 2026 12:34:14 +0200 Subject: [PATCH 142/196] crypto: omap-des - add COMPILE_TEST and fix CONFIG_OF=n build CRYPTO_DEV_OMAP_DES only depends on ARCH_OMAP2PLUS, which is ARM-only and selects OF via ARM's USE_OF, making any non-OF code unreachable. Add COMPILE_TEST so the driver can be built with CONFIG_OF=n, making the non-OF code reachable. Fix the resulting non-OF build failures: - omap_des_irq() was defined inside a CONFIG_OF block, but is referenced unconditionally from omap_des_probe(). Move the CONFIG_OF guard so it only covers omap_des_get_of(). - The non-OF omap_des_get_of() stub took a struct device *, while omap_des_probe() passes a struct platform_device *. Make the stub prototype match the OF implementation and the caller. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 4 ++-- drivers/crypto/omap-des.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index d23b58b81ca3..3449b3c9c6ad 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -316,7 +316,7 @@ config HW_RANDOM_PPC4XX config CRYPTO_DEV_OMAP tristate "Support for OMAP crypto HW accelerators" - depends on ARCH_OMAP2PLUS + depends on ARCH_OMAP2PLUS || COMPILE_TEST help OMAP processors have various crypto HW accelerators. Select this if you want to use the OMAP modules for any of the crypto algorithms. @@ -352,7 +352,7 @@ config CRYPTO_DEV_OMAP_AES config CRYPTO_DEV_OMAP_DES tristate "Support for OMAP DES/3DES hw engine" - depends on ARCH_OMAP2PLUS + depends on ARCH_OMAP2PLUS || COMPILE_TEST select CRYPTO_LIB_DES select CRYPTO_SKCIPHER select CRYPTO_ENGINE diff --git a/drivers/crypto/omap-des.c b/drivers/crypto/omap-des.c index 16d5c617d5ee..f6f3b22e4ee5 100644 --- a/drivers/crypto/omap-des.c +++ b/drivers/crypto/omap-des.c @@ -800,7 +800,6 @@ static struct omap_des_algs_info omap_des_algs_info_ecb_cbc[] = { }, }; -#ifdef CONFIG_OF static const struct omap_des_pdata omap_des_pdata_omap4 = { .algs_info = omap_des_algs_info_ecb_cbc, .algs_info_size = ARRAY_SIZE(omap_des_algs_info_ecb_cbc), @@ -909,6 +908,7 @@ static const struct of_device_id omap_des_of_match[] = { }; MODULE_DEVICE_TABLE(of, omap_des_of_match); +#ifdef CONFIG_OF static int omap_des_get_of(struct omap_des_dev *dd, struct platform_device *pdev) { @@ -923,7 +923,7 @@ static int omap_des_get_of(struct omap_des_dev *dd, } #else static int omap_des_get_of(struct omap_des_dev *dd, - struct device *dev) + struct platform_device *pdev) { return -EINVAL; } From 0a06b86d4b748188878a132c637029eae4d9ac8d Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sun, 17 May 2026 12:36:52 +0200 Subject: [PATCH 143/196] crypto: omap-des - drop of_match_ptr from OF match table Drop of_match_ptr() because OF matching is stubbed out when CONFIG_OF=n. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/omap-des.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/omap-des.c b/drivers/crypto/omap-des.c index f6f3b22e4ee5..dfaf831dd8ec 100644 --- a/drivers/crypto/omap-des.c +++ b/drivers/crypto/omap-des.c @@ -1117,7 +1117,7 @@ static struct platform_driver omap_des_driver = { .driver = { .name = "omap-des", .pm = &omap_des_pm_ops, - .of_match_table = of_match_ptr(omap_des_of_match), + .of_match_table = omap_des_of_match, }, }; From d58b4a09d7f06750a706b70d068f5a678dad8233 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sun, 17 May 2026 14:37:07 +0200 Subject: [PATCH 144/196] crypto: atmel-sha204a - remove sysfs group before hwrng atmel_sha204a_probe() registers the hwrng before creating the sysfs group. Mirror this order in atmel_sha204a_remove() by removing the sysfs group before unregistering the hwrng. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha204a.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index 6e6ac4770416..37538b0fd7c2 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -199,11 +199,10 @@ static void atmel_sha204a_remove(struct i2c_client *client) { struct atmel_i2c_client_priv *i2c_priv = i2c_get_clientdata(client); + sysfs_remove_group(&client->dev.kobj, &atmel_sha204a_groups); devm_hwrng_unregister(&client->dev, &i2c_priv->hwrng); atmel_i2c_flush_queue(); - sysfs_remove_group(&client->dev.kobj, &atmel_sha204a_groups); - kfree((void *)i2c_priv->hwrng.priv); } From 49e05bb00f2e8168695f7af4d694c39e1423e8a2 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sun, 17 May 2026 18:27:40 +0200 Subject: [PATCH 145/196] crypto: atmel-sha204a - fail on hwrng registration error in probe path Commit 13909a0c8897 ("crypto: atmel-sha204a - provide the otp content") overwrote the hwrng registration return value when creating the sysfs group, which allowed atmel_sha204a_probe() to succeed even if devm_hwrng_register() failed. Return immediately when devm_hwrng_register() fails, and report both hwrng and sysfs registration errors with dev_err(). Adjust the sysfs error log message for consistency. Fixes: 13909a0c8897 ("crypto: atmel-sha204a - provide the otp content") Cc: stable@vger.kernel.org Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha204a.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index 37538b0fd7c2..12eb85b57380 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -183,12 +183,14 @@ static int atmel_sha204a_probe(struct i2c_client *client) i2c_priv->hwrng.quality = *quality; ret = devm_hwrng_register(&client->dev, &i2c_priv->hwrng); - if (ret) - dev_warn(&client->dev, "failed to register RNG (%d)\n", ret); + if (ret) { + dev_err(&client->dev, "failed to register RNG (%d)\n", ret); + return ret; + } ret = sysfs_create_group(&client->dev.kobj, &atmel_sha204a_groups); if (ret) { - dev_err(&client->dev, "failed to register sysfs entry\n"); + dev_err(&client->dev, "failed to create sysfs group (%d)\n", ret); return ret; } From e054cdee673181622bc12f2b5049134ecbc2eeb1 Mon Sep 17 00:00:00 2001 From: Zhushuai Yin Date: Mon, 18 May 2026 22:29:51 +0800 Subject: [PATCH 146/196] crypto: hisilicon/qm - allow VF devices to query hardware isolation status The problem that the VF device cannot obtain the isolation status and isolation threshold of the device is resolved. The accelerator driver can query the device isolation status and threshold via the VF device using the fault query sysfs interface under uacce. Note that only the PF device supports isolation policy configuration, while the VF device is limited to read-only query operations. Signed-off-by: Zhushuai Yin Signed-off-by: Zongyu Wu Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/hpre/hpre_main.c | 10 +- drivers/crypto/hisilicon/qm.c | 128 ++++++++++++++++++++-- drivers/crypto/hisilicon/sec2/sec_main.c | 10 +- drivers/crypto/hisilicon/zip/zip_main.c | 10 +- include/linux/hisi_acc_qm.h | 1 + 5 files changed, 129 insertions(+), 30 deletions(-) diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c index 357ab5e5887e..a484381f522a 100644 --- a/drivers/crypto/hisilicon/hpre/hpre_main.c +++ b/drivers/crypto/hisilicon/hpre/hpre_main.c @@ -1631,12 +1631,10 @@ static int hpre_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_qm_del_list; } - if (qm->uacce) { - ret = uacce_register(qm->uacce); - if (ret) { - pci_err(pdev, "failed to register uacce (%d)!\n", ret); - goto err_with_alg_register; - } + ret = hisi_qm_register_uacce(qm); + if (ret) { + pci_err(pdev, "failed to register uacce (%d)!\n", ret); + goto err_with_alg_register; } if (qm->fun_type == QM_HW_PF && vfs_num) { diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index 3ca47e2a9719..9cf52873a891 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -246,6 +246,10 @@ #define QM_QOS_MAX_CIR_U 6 #define QM_AUTOSUSPEND_DELAY 3000 +/* qm isolation state mask */ +#define QM_ISOLATED_STATE BIT(31) +#define QM_ISOLATED_THRESHOLD_MASK GENMASK(15, 0) + /* abnormal status value for stopping queue */ #define QM_STOP_QUEUE_FAIL 1 #define QM_DUMP_SQC_FAIL 3 @@ -286,6 +290,20 @@ enum qm_alg_type { ALG_TYPE_1, }; +/* + * Message format for QM_VF_GET_ISOLATE and QM_PF_SET_ISOLATE commands + * + * These commands use a 32-bit command field (cmd) and 32-bit data field (data) + * + * Command behavior: + * - QM_VF_GET_ISOLATE: VF requests isolation status and threshold + * - QM_PF_SET_ISOLATE: PF sets isolation status and threshold + * + * Data field bit layout: + * - bit31 (MSB): Isolation status flag (1 = isolated, 0 = non-isolated) + * - bit15-0 (16 LSB): Isolation threshold value + * - bit30-16 (15 bits): Reserved + */ enum qm_ifc_cmd { QM_PF_FLR_PREPARE = 0x01, QM_PF_SRST_PREPARE, @@ -296,6 +314,8 @@ enum qm_ifc_cmd { QM_VF_START_FAIL, QM_PF_SET_QOS, QM_VF_GET_QOS, + QM_VF_GET_ISOLATE, + QM_PF_SET_ISOLATE, }; enum qm_basic_type { @@ -1734,7 +1754,7 @@ err_unlock: return ret; } -static int qm_ping_all_vfs(struct hisi_qm *qm, enum qm_ifc_cmd cmd) +static int qm_ping_all_vfs(struct hisi_qm *qm, enum qm_ifc_cmd cmd, u32 data) { struct device *dev = &qm->pdev->dev; u32 vfs_num = qm->vfs_num; @@ -1743,7 +1763,7 @@ static int qm_ping_all_vfs(struct hisi_qm *qm, enum qm_ifc_cmd cmd) int ret; u32 i; - ret = qm->ops->set_ifc_begin(qm, cmd, 0, QM_MB_PING_ALL_VFS); + ret = qm->ops->set_ifc_begin(qm, cmd, data, QM_MB_PING_ALL_VFS); if (ret) { dev_err(dev, "failed to send command(0x%x) to all vfs!\n", cmd); qm->ops->set_ifc_end(qm); @@ -2779,6 +2799,7 @@ static enum uacce_dev_state hisi_qm_get_isolate_state(struct uacce_device *uacce static int hisi_qm_isolate_threshold_write(struct uacce_device *uacce, u32 num) { struct hisi_qm *qm = uacce->priv; + int ret; /* Must be set by PF */ if (uacce->is_vf) @@ -2792,6 +2813,18 @@ static int hisi_qm_isolate_threshold_write(struct uacce_device *uacce, u32 num) /* After the policy is updated, need to reset the hardware err list */ qm_hw_err_destroy(qm); + + if (!qm->vfs_num) { + mutex_unlock(&qm->isolate_data.isolate_lock); + return 0; + } + + /* Notify all VFs to update the isolation threshold. */ + if (test_bit(QM_SUPPORT_MB_COMMAND, &qm->caps)) { + ret = qm_ping_all_vfs(qm, QM_PF_SET_ISOLATE, qm->isolate_data.err_threshold); + if (ret) + dev_err(&qm->pdev->dev, "failed to send command to all VFs set isolate!\n"); + } mutex_unlock(&qm->isolate_data.isolate_lock); return 0; @@ -2802,7 +2835,7 @@ static u32 hisi_qm_isolate_threshold_read(struct uacce_device *uacce) struct hisi_qm *qm = uacce->priv; struct hisi_qm *pf_qm; - if (uacce->is_vf) { + if (uacce->is_vf && !test_bit(QM_SUPPORT_MB_COMMAND, &qm->caps)) { pf_qm = pci_get_drvdata(pci_physfn(qm->pdev)); return pf_qm->isolate_data.err_threshold; } @@ -2889,7 +2922,10 @@ static int qm_alloc_uacce(struct hisi_qm *qm) return -EINVAL; } - uacce->is_vf = pdev->is_virtfn; + if (qm->fun_type == QM_HW_PF) + uacce->is_vf = false; + else + uacce->is_vf = true; uacce->priv = qm; if (qm->ver == QM_HW_V1) @@ -2918,6 +2954,25 @@ static int qm_alloc_uacce(struct hisi_qm *qm) return 0; } +int hisi_qm_register_uacce(struct hisi_qm *qm) +{ + int ret; + + if (!qm->uacce) + return 0; + + dev_info(&qm->pdev->dev, "qm register to uacce\n"); + + if (qm->fun_type == QM_HW_VF && test_bit(QM_SUPPORT_MB_COMMAND, &qm->caps)) { + ret = qm_ping_pf(qm, QM_VF_GET_ISOLATE); + if (ret) + dev_err(&qm->pdev->dev, "failed to send cmd to PF to get isolate!\n"); + } + + return uacce_register(qm->uacce); +} +EXPORT_SYMBOL_GPL(hisi_qm_register_uacce); + /** * qm_frozen() - Try to froze QM to cut continuous queue request. If * there is user on the QM, return failure without doing anything. @@ -4484,7 +4539,7 @@ static int qm_try_stop_vfs(struct hisi_qm *qm, enum qm_ifc_cmd cmd, /* Kunpeng930 supports to notify VFs to stop before PF reset */ if (test_bit(QM_SUPPORT_MB_COMMAND, &qm->caps)) { - ret = qm_ping_all_vfs(qm, cmd); + ret = qm_ping_all_vfs(qm, cmd, 0); if (ret) pci_err(pdev, "failed to send command to all VFs before PF reset!\n"); } else { @@ -4671,6 +4726,7 @@ restart_fail: static int qm_try_start_vfs(struct hisi_qm *qm, enum qm_ifc_cmd cmd) { struct pci_dev *pdev = qm->pdev; + u32 data; int ret; if (!qm->vfs_num) @@ -4684,7 +4740,11 @@ static int qm_try_start_vfs(struct hisi_qm *qm, enum qm_ifc_cmd cmd) /* Kunpeng930 supports to notify VFs to start after PF reset. */ if (test_bit(QM_SUPPORT_MB_COMMAND, &qm->caps)) { - ret = qm_ping_all_vfs(qm, cmd); + data = qm->isolate_data.err_threshold; + if (qm->isolate_data.is_isolate) + data |= QM_ISOLATED_STATE; + /* Broadcasting isolate info via RAS to all VFs. */ + ret = qm_ping_all_vfs(qm, cmd, data); if (ret) pci_warn(pdev, "failed to send cmd to all VFs after PF reset!\n"); } else { @@ -5131,10 +5191,22 @@ static void qm_pf_reset_vf_done(struct hisi_qm *qm) qm_reset_bit_clear(qm); } -static int qm_wait_pf_reset_finish(struct hisi_qm *qm) +static void qm_vf_update_isolate_info(struct hisi_qm *qm, u32 data) +{ + /* Updating the local isolation status. */ + mutex_lock(&qm->isolate_data.isolate_lock); + if (data & QM_ISOLATED_STATE) + qm->isolate_data.is_isolate = true; + else + qm->isolate_data.is_isolate = false; + qm->isolate_data.err_threshold = data & QM_ISOLATED_THRESHOLD_MASK; + mutex_unlock(&qm->isolate_data.isolate_lock); +} + +static int qm_wait_pf_reset_finish(struct hisi_qm *qm, enum qm_stop_reason stop_reason) { struct device *dev = &qm->pdev->dev; - u32 val, cmd; + u32 val, cmd, data; int ret; /* Wait for reset to finish */ @@ -5151,7 +5223,7 @@ static int qm_wait_pf_reset_finish(struct hisi_qm *qm) * Whether message is got successfully, * VF needs to ack PF by clearing the interrupt. */ - ret = qm->ops->get_ifc(qm, &cmd, NULL, 0); + ret = qm->ops->get_ifc(qm, &cmd, &data, 0); qm_clear_cmd_interrupt(qm, 0); if (ret) { dev_err(dev, "failed to get command from PF in reset done!\n"); @@ -5160,10 +5232,14 @@ static int qm_wait_pf_reset_finish(struct hisi_qm *qm) if (cmd != QM_PF_RESET_DONE) { dev_err(dev, "the command(0x%x) is not reset done!\n", cmd); - ret = -EINVAL; + return -EINVAL; } - return ret; + /* The VF processes the device isolation information received from the RAS reset. */ + if (stop_reason == QM_SOFT_RESET) + qm_vf_update_isolate_info(qm, data); + + return 0; } static void qm_pf_reset_vf_process(struct hisi_qm *qm, @@ -5178,7 +5254,7 @@ static void qm_pf_reset_vf_process(struct hisi_qm *qm, qm_cmd_uninit(qm); qm_pf_reset_vf_prepare(qm, stop_reason); - ret = qm_wait_pf_reset_finish(qm); + ret = qm_wait_pf_reset_finish(qm, stop_reason); if (ret) goto err_get_status; @@ -5189,10 +5265,31 @@ static void qm_pf_reset_vf_process(struct hisi_qm *qm, return; err_get_status: + if (stop_reason == QM_SOFT_RESET) { + /* Update local isolation status on PF-VF reset failure. */ + mutex_lock(&qm->isolate_data.isolate_lock); + qm->isolate_data.is_isolate = true; + mutex_unlock(&qm->isolate_data.isolate_lock); + } qm_cmd_init(qm); qm_reset_bit_clear(qm); } +static void qm_vf_get_isolate_data(struct hisi_qm *qm, u32 fun_num) +{ + u32 data = qm->isolate_data.err_threshold; + struct device *dev = &qm->pdev->dev; + int ret; + + if (qm->isolate_data.is_isolate) + data |= QM_ISOLATED_STATE; + + ret = qm_ping_single_vf(qm, QM_PF_SET_ISOLATE, data, fun_num); + if (ret) + dev_err(dev, "failed to send command(0x%x) to VF(%u)!\n", + (unsigned int)QM_PF_SET_ISOLATE, fun_num); +} + static void qm_handle_cmd_msg(struct hisi_qm *qm, u32 fun_num) { struct device *dev = &qm->pdev->dev; @@ -5224,6 +5321,13 @@ static void qm_handle_cmd_msg(struct hisi_qm *qm, u32 fun_num) case QM_PF_SET_QOS: qm->mb_qos = data; break; + case QM_VF_GET_ISOLATE: + /* Read the isolation policy of the PF during VF initialization. */ + qm_vf_get_isolate_data(qm, fun_num); + break; + case QM_PF_SET_ISOLATE: + qm_vf_update_isolate_info(qm, data); + break; default: dev_err(dev, "unsupported command(0x%x) sent by function(%u)!\n", cmd, fun_num); break; diff --git a/drivers/crypto/hisilicon/sec2/sec_main.c b/drivers/crypto/hisilicon/sec2/sec_main.c index 056bd8f4da5a..e8bea1e496f7 100644 --- a/drivers/crypto/hisilicon/sec2/sec_main.c +++ b/drivers/crypto/hisilicon/sec2/sec_main.c @@ -1449,12 +1449,10 @@ static int sec_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_qm_del_list; } - if (qm->uacce) { - ret = uacce_register(qm->uacce); - if (ret) { - pci_err(pdev, "failed to register uacce (%d)!\n", ret); - goto err_alg_unregister; - } + ret = hisi_qm_register_uacce(qm); + if (ret) { + pci_err(pdev, "failed to register uacce (%d)!\n", ret); + goto err_alg_unregister; } if (qm->fun_type == QM_HW_PF && vfs_num) { diff --git a/drivers/crypto/hisilicon/zip/zip_main.c b/drivers/crypto/hisilicon/zip/zip_main.c index 44df9c859bd8..5135b3028cb2 100644 --- a/drivers/crypto/hisilicon/zip/zip_main.c +++ b/drivers/crypto/hisilicon/zip/zip_main.c @@ -1559,12 +1559,10 @@ static int hisi_zip_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_qm_del_list; } - if (qm->uacce) { - ret = uacce_register(qm->uacce); - if (ret) { - pci_err(pdev, "failed to register uacce (%d)!\n", ret); - goto err_qm_alg_unregister; - } + ret = hisi_qm_register_uacce(qm); + if (ret) { + pci_err(pdev, "failed to register uacce (%d)!\n", ret); + goto err_qm_alg_unregister; } if (qm->fun_type == QM_HW_PF && vfs_num > 0) { diff --git a/include/linux/hisi_acc_qm.h b/include/linux/hisi_acc_qm.h index a6268dc4f7cb..ddecdc2531a2 100644 --- a/include/linux/hisi_acc_qm.h +++ b/include/linux/hisi_acc_qm.h @@ -552,6 +552,7 @@ static inline void hisi_qm_del_list(struct hisi_qm *qm, struct hisi_qm_list *qm_ mutex_unlock(&qm_list->lock); } +int hisi_qm_register_uacce(struct hisi_qm *qm); int hisi_qm_q_num_set(const char *val, const struct kernel_param *kp, unsigned int device); int hisi_qm_init(struct hisi_qm *qm); From 789fc74a220b33bb21257c707467985aac536ecd Mon Sep 17 00:00:00 2001 From: Zhushuai Yin Date: Mon, 18 May 2026 22:29:52 +0800 Subject: [PATCH 147/196] crypto: hisilicon/qm - place the interrupt status interface after the PM usage counter To avoid accessing memory of a suspended device, and since the counter interface used by PM involves sleep operations, the counter interface cannot be placed in the interrupt top half. Therefore, the interface for acquiring the interrupt status in the RAS reset flow that resides in the interrupt context needs to be moved to the bottom half for processing. Signed-off-by: Zhushuai Yin Signed-off-by: Zongyu Wu Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/qm.c | 34 ++++++++++++++++++---------------- include/linux/hisi_acc_qm.h | 1 - 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index 9cf52873a891..71af462daf5b 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -1195,6 +1195,11 @@ static irqreturn_t qm_aeq_thread(int irq, void *data) atomic64_inc(&qm->debug.dfx.aeq_irq_cnt); + if (qm_pm_get_sync(qm)) { + dev_err(&qm->pdev->dev, "failed to get runtime PM for aeq handle\n"); + return IRQ_HANDLED; + } + while (QM_AEQE_PHASE(dw0) == qm->status.aeqc_phase) { type = (dw0 >> QM_AEQE_TYPE_SHIFT) & QM_AEQE_TYPE_MASK; qp_id = dw0 & QM_AEQE_CQN_MASK; @@ -1230,6 +1235,8 @@ static irqreturn_t qm_aeq_thread(int irq, void *data) qm_db(qm, 0, QM_DOORBELL_CMD_AEQ, qm->status.aeq_head, 0); + qm_pm_put_sync(qm); + return IRQ_HANDLED; } @@ -3043,9 +3050,9 @@ void hisi_qm_wait_task_finish(struct hisi_qm *qm, struct hisi_qm_list *qm_list) msleep(WAIT_PERIOD); } - while (test_bit(QM_RST_SCHED, &qm->misc_ctl) || - test_bit(QM_RESETTING, &qm->misc_ctl)) - msleep(WAIT_PERIOD); + /* Cancel possible RAS reset process during the uninstallation procedure. */ + if (qm->fun_type == QM_HW_PF) + cancel_work_sync(&qm->rst_work); if (test_bit(QM_SUPPORT_MB_COMMAND, &qm->caps)) flush_work(&qm->cmd_process); @@ -4595,8 +4602,6 @@ static int qm_controller_reset_prepare(struct hisi_qm *qm) if (ret) pci_err(pdev, "failed to stop by vfs in soft reset!\n"); - clear_bit(QM_RST_SCHED, &qm->misc_ctl); - return 0; } @@ -4914,7 +4919,6 @@ static int qm_controller_reset(struct hisi_qm *qm) if (ret) { hisi_qm_set_hw_reset(qm, QM_RESET_STOP_TX_OFFSET); hisi_qm_set_hw_reset(qm, QM_RESET_STOP_RX_OFFSET); - clear_bit(QM_RST_SCHED, &qm->misc_ctl); return ret; } @@ -5087,14 +5091,13 @@ static irqreturn_t qm_rsvd_irq(int irq, void *data) static irqreturn_t qm_abnormal_irq(int irq, void *data) { struct hisi_qm *qm = data; - enum acc_err_result ret; atomic64_inc(&qm->debug.dfx.abnormal_irq_cnt); - ret = qm_process_dev_error(qm); - if (ret == ACC_ERR_NEED_RESET && - !test_bit(QM_DRIVER_REMOVING, &qm->misc_ctl) && - !test_and_set_bit(QM_RST_SCHED, &qm->misc_ctl)) + + if (!test_bit(QM_DRIVER_REMOVING, &qm->misc_ctl)) schedule_work(&qm->rst_work); + else + pci_warn(qm->pdev, "Driver is down, need to reload driver!\n"); return IRQ_HANDLED; } @@ -5123,14 +5126,13 @@ static void hisi_qm_controller_reset(struct work_struct *rst_work) ret = qm_pm_get_sync(qm); if (ret) { - clear_bit(QM_RST_SCHED, &qm->misc_ctl); + dev_err(&qm->pdev->dev, "failed to get runtime PM for controller\n"); return; } - /* reset pcie device controller */ - ret = qm_controller_reset(qm); - if (ret) - dev_err(&qm->pdev->dev, "controller reset failed (%d)\n", ret); + ret = qm_process_dev_error(qm); + if (ret == ACC_ERR_NEED_RESET) + (void)qm_controller_reset(qm); qm_pm_put_sync(qm); } diff --git a/include/linux/hisi_acc_qm.h b/include/linux/hisi_acc_qm.h index ddecdc2531a2..98ff6bcfdebe 100644 --- a/include/linux/hisi_acc_qm.h +++ b/include/linux/hisi_acc_qm.h @@ -158,7 +158,6 @@ enum qm_vf_state { enum qm_misc_ctl_bits { QM_DRIVER_REMOVING = 0x0, - QM_RST_SCHED, QM_RESETTING, QM_MODULE_PARAM, }; From 86cad7009fb4ac2c617077bc1c44a51c60d4ae2e Mon Sep 17 00:00:00 2001 From: Zhushuai Yin Date: Mon, 18 May 2026 22:29:53 +0800 Subject: [PATCH 148/196] crypto: hisilicon/qm - support function-level error reset When executing operations on crypto devices, hardware errors are inevitable. For certain errors, a full device reset is required to recover. However, in certain cases, only a specific function may fail, while other functions can still operate normally. A system-wide RAS reset in such cases would unnecessarily impact functioning components. This patch introduces function-level granularity handling, enabling targeted resets of only the error-reporting functions without affecting other operational functions. Signed-off-by: Zhushuai Yin Signed-off-by: Zongyu Wu Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/qm.c | 90 +++++++++++++++++++++++++++++++---- include/linux/hisi_acc_qm.h | 1 + 2 files changed, 83 insertions(+), 8 deletions(-) diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index 71af462daf5b..2b3132595e42 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -246,6 +246,11 @@ #define QM_QOS_MAX_CIR_U 6 #define QM_AUTOSUSPEND_DELAY 3000 +/* qm function err mask */ +#define QM_FUNC_AXI_ERR_ST0 0x100280 +#define QM_RAS_FUNC_ERROR (BIT(0) | BIT(1)) +#define QM_FUNC_RAS_CLEAR_ALL GENMASK(63, 0) + /* qm isolation state mask */ #define QM_ISOLATED_STATE BIT(31) #define QM_ISOLATED_THRESHOLD_MASK GENMASK(15, 0) @@ -314,6 +319,7 @@ enum qm_ifc_cmd { QM_VF_START_FAIL, QM_PF_SET_QOS, QM_VF_GET_QOS, + QM_FUNCTION_RESET, QM_VF_GET_ISOLATE, QM_PF_SET_ISOLATE, }; @@ -493,6 +499,7 @@ static struct qm_typical_qos_table shaper_cbs_s[] = { static void qm_irqs_unregister(struct hisi_qm *qm); static int qm_reset_device(struct hisi_qm *qm); static void hisi_qm_stop_qp(struct hisi_qp *qp); +static int qm_restart(struct hisi_qm *qm); int hisi_qm_q_num_set(const char *val, const struct kernel_param *kp, unsigned int device) @@ -1171,18 +1178,20 @@ static void qm_reset_function(struct hisi_qm *qm) return; } + dev_info(dev, "function reset start...\n"); ret = hisi_qm_stop(qm, QM_DOWN); if (ret) { dev_err(dev, "failed to stop qm when reset function\n"); goto clear_bit; } - ret = hisi_qm_start(qm); + ret = qm_restart(qm); if (ret) dev_err(dev, "failed to start qm when reset function\n"); clear_bit: qm_reset_bit_clear(qm); + dev_info(dev, "function reset end...\n"); } static irqreturn_t qm_aeq_thread(int irq, void *data) @@ -1505,6 +1514,8 @@ static void qm_hw_error_cfg(struct hisi_qm *qm) qm->error_mask = qm_err->nfe | qm_err->ce | qm_err->fe; /* clear QM hw residual error source */ writel(qm->error_mask, qm->io_base + QM_ABNORMAL_INT_SOURCE); + if (qm->ver >= QM_HW_V5) + writeq(QM_FUNC_RAS_CLEAR_ALL, qm->io_base + QM_FUNC_AXI_ERR_ST0); /* configure error type */ writel(qm_err->ce, qm->io_base + QM_RAS_CE_ENABLE); @@ -1610,6 +1621,15 @@ static enum acc_err_result qm_hw_error_handle_v2(struct hisi_qm *qm) qm->err_status.is_qm_ecc_mbit = true; qm_log_hw_error(qm, error_status); + /* Trigger func reset only when error is detected in bit 0 or bit 1. */ + if ((qm->ver >= QM_HW_V5) && + (error_status & QM_RAS_FUNC_ERROR) && + (error_status & qm_err->reset_mask) == 0) { + writel(error_status, qm->io_base + QM_ABNORMAL_INT_SOURCE); + writel(qm_err->nfe, qm->io_base + QM_RAS_NFE_ENABLE); + return ACC_ERR_NEED_FUNC_RESET; + } + if (error_status & qm_err->reset_mask) { /* Disable the same error reporting until device is recovered. */ writel(qm_err->nfe & (~error_status), qm->io_base + QM_RAS_NFE_ENABLE); @@ -4364,10 +4384,13 @@ static enum acc_err_result qm_process_dev_error(struct hisi_qm *qm) /* log device error */ dev_ret = qm_dev_err_handle(qm); + if (qm_ret == ACC_ERR_NEED_RESET || dev_ret == ACC_ERR_NEED_RESET) + return ACC_ERR_NEED_RESET; - return (qm_ret == ACC_ERR_NEED_RESET || - dev_ret == ACC_ERR_NEED_RESET) ? - ACC_ERR_NEED_RESET : ACC_ERR_RECOVERED; + if (qm_ret == ACC_ERR_NEED_FUNC_RESET) + return ACC_ERR_NEED_FUNC_RESET; + + return ACC_ERR_RECOVERED; } /** @@ -4392,7 +4415,7 @@ pci_ers_result_t hisi_qm_dev_err_detected(struct pci_dev *pdev, return PCI_ERS_RESULT_DISCONNECT; ret = qm_process_dev_error(qm); - if (ret == ACC_ERR_NEED_RESET) + if (ret == ACC_ERR_NEED_RESET || ret == ACC_ERR_NEED_FUNC_RESET) return PCI_ERS_RESULT_NEED_RESET; return PCI_ERS_RESULT_RECOVERED; @@ -5119,9 +5142,53 @@ void hisi_qm_dev_shutdown(struct pci_dev *pdev) } EXPORT_SYMBOL_GPL(hisi_qm_dev_shutdown); +static u64 qm_get_function_mask(struct hisi_qm *qm) +{ + return readq(qm->io_base + QM_FUNC_AXI_ERR_ST0); +} + +static void qm_clear_function_mask(struct hisi_qm *qm, u64 func_mask) +{ + /* Register write 1 clear */ + writeq(func_mask, qm->io_base + QM_FUNC_AXI_ERR_ST0); +} + +static void qm_function_reset(struct hisi_qm *qm) +{ + struct device *dev = &qm->pdev->dev; + u64 func_mask; + u32 fun_num; + int ret; + + func_mask = qm_get_function_mask(qm); + if (!func_mask) { + dev_info(dev, "no function need reset!\n"); + return; + } + + for (fun_num = 1; fun_num <= qm->vfs_num; fun_num++) { + if (func_mask & BIT(fun_num)) { + ret = qm_ping_single_vf(qm, QM_FUNCTION_RESET, 0, fun_num); + /* When function ping fail, user decides the VF reset method. */ + if (ret) + dev_err(dev, "failed to send command(0x%x) to VF(%u)!\n", + (unsigned int)QM_FUNCTION_RESET, fun_num); + } + } + + if (func_mask & BIT(0)) { + dev_info(dev, "function reset start...\n"); + qm_reset_function(qm); + dev_info(dev, "function reset end!\n"); + } + + qm_clear_function_mask(qm, func_mask); +} + static void hisi_qm_controller_reset(struct work_struct *rst_work) { struct hisi_qm *qm = container_of(rst_work, struct hisi_qm, rst_work); + enum acc_err_result err_result; int ret; ret = qm_pm_get_sync(qm); @@ -5130,9 +5197,11 @@ static void hisi_qm_controller_reset(struct work_struct *rst_work) return; } - ret = qm_process_dev_error(qm); - if (ret == ACC_ERR_NEED_RESET) + err_result = qm_process_dev_error(qm); + if (err_result == ACC_ERR_NEED_RESET) (void)qm_controller_reset(qm); + else if (err_result == ACC_ERR_NEED_FUNC_RESET) + qm_function_reset(qm); qm_pm_put_sync(qm); } @@ -5179,7 +5248,7 @@ static void qm_pf_reset_vf_done(struct hisi_qm *qm) int ret; pci_restore_state(pdev); - ret = hisi_qm_start(qm); + ret = qm_restart(qm); if (ret) { dev_err(&pdev->dev, "failed to start QM, ret = %d.\n", ret); cmd = QM_VF_START_FAIL; @@ -5323,6 +5392,11 @@ static void qm_handle_cmd_msg(struct hisi_qm *qm, u32 fun_num) case QM_PF_SET_QOS: qm->mb_qos = data; break; + case QM_FUNCTION_RESET: + dev_info(dev, "function reset start...\n"); + qm_reset_function(qm); + dev_info(dev, "function reset end!\n"); + break; case QM_VF_GET_ISOLATE: /* Read the isolation policy of the PF during VF initialization. */ qm_vf_get_isolate_data(qm, fun_num); diff --git a/include/linux/hisi_acc_qm.h b/include/linux/hisi_acc_qm.h index 98ff6bcfdebe..0a2da1029a3f 100644 --- a/include/linux/hisi_acc_qm.h +++ b/include/linux/hisi_acc_qm.h @@ -248,6 +248,7 @@ enum acc_err_result { ACC_ERR_NONE, ACC_ERR_NEED_RESET, ACC_ERR_RECOVERED, + ACC_ERR_NEED_FUNC_RESET, }; struct hisi_qm_err_mask { From e71dc5602b9a29027f6aedd5990d3e8c4f638c8c Mon Sep 17 00:00:00 2001 From: Weili Qian Date: Mon, 18 May 2026 22:29:54 +0800 Subject: [PATCH 149/196] crypto: hisilicon/qm - disable error report before flr Before function level reset, driver first disable device error report and then waits for the device reset to complete. However, when the error is recovered, the error bits will be enabled again, resulting in invalid disable. It is modified to detect that there is no error before disable error report, and then do FLR. Fixes: 7ce396fa12a9 ("crypto: hisilicon - add FLR support") Signed-off-by: Weili Qian Signed-off-by: Zongyu Wu Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/qm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index 2b3132595e42..90b447b934c6 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -5004,8 +5004,6 @@ void hisi_qm_reset_prepare(struct pci_dev *pdev) u32 delay = 0; int ret; - hisi_qm_dev_err_uninit(pf_qm); - /* * Check whether there is an ECC mbit error, If it occurs, need to * wait for soft reset to fix it. @@ -5022,6 +5020,8 @@ void hisi_qm_reset_prepare(struct pci_dev *pdev) return; } + hisi_qm_dev_err_uninit(pf_qm); + /* PF obtains the information of VF by querying the register. */ if (qm->fun_type == QM_HW_PF) qm_cmd_uninit(qm); From b632bd38f2072982c7588629a1437e8ffa05c6e7 Mon Sep 17 00:00:00 2001 From: Weili Qian Date: Mon, 18 May 2026 22:29:55 +0800 Subject: [PATCH 150/196] crypto: hisilicon - mask all error type when removing driver Each bit in the error interrupt register corresponds to a specific error type. A bit value of 0 enables the interrupt, and a bit value of 1 disables the interrupt. Currently, when disabling interrupts, it incorrectly enables the interrupt types that were not enabled. Therefore, when disabling interrupts, all bits should be directly written to 1. Signed-off-by: Weili Qian Signed-off-by: Zongyu Wu Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/hpre/hpre_main.c | 9 +++---- drivers/crypto/hisilicon/qm.c | 30 ++++++----------------- drivers/crypto/hisilicon/sec2/sec_main.c | 3 ++- drivers/crypto/hisilicon/zip/zip_main.c | 10 +++----- 4 files changed, 18 insertions(+), 34 deletions(-) diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c index a484381f522a..b6903fce6071 100644 --- a/drivers/crypto/hisilicon/hpre/hpre_main.c +++ b/drivers/crypto/hisilicon/hpre/hpre_main.c @@ -55,6 +55,8 @@ #define HPRE_RAS_FE_ENB 0x301418 #define HPRE_OOO_SHUTDOWN_SEL 0x301a3c #define HPRE_HAC_RAS_FE_ENABLE 0 +#define HPRE_RAS_MASK_ALL GENMASK(31, 0) +#define HPRE_RAS_CLEAR_ALL GENMASK(31, 0) #define HPRE_CORE_ENB (HPRE_CLSTR_BASE + HPRE_CORE_EN_OFFSET) #define HPRE_CORE_INI_CFG (HPRE_CLSTR_BASE + HPRE_CORE_INI_CFG_OFFSET) @@ -820,11 +822,8 @@ static void hpre_master_ooo_ctrl(struct hisi_qm *qm, bool enable) static void hpre_hw_error_disable(struct hisi_qm *qm) { - struct hisi_qm_err_mask *dev_err = &qm->err_info.dev_err; - u32 err_mask = dev_err->ce | dev_err->nfe | dev_err->fe; - /* disable hpre hw error interrupts */ - writel(err_mask, qm->io_base + HPRE_INT_MASK); + writel(HPRE_RAS_MASK_ALL, qm->io_base + HPRE_INT_MASK); /* disable HPRE block master OOO when nfe occurs on Kunpeng930 */ hpre_master_ooo_ctrl(qm, false); } @@ -835,7 +834,7 @@ static void hpre_hw_error_enable(struct hisi_qm *qm) u32 err_mask = dev_err->ce | dev_err->nfe | dev_err->fe; /* clear HPRE hw error source if having */ - writel(err_mask, qm->io_base + HPRE_HAC_SOURCE_INT); + writel(HPRE_RAS_CLEAR_ALL, qm->io_base + HPRE_HAC_SOURCE_INT); /* configure error type */ writel(dev_err->ce, qm->io_base + HPRE_RAS_CE_ENB); diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index 90b447b934c6..bfee16503c38 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -128,7 +128,6 @@ #define QM_ABNORMAL_INT_SOURCE 0x100000 #define QM_ABNORMAL_INT_MASK 0x100004 -#define QM_ABNORMAL_INT_MASK_VALUE 0x7fff #define QM_ABNORMAL_INT_STATUS 0x100008 #define QM_ABNORMAL_INT_SET 0x10000c #define QM_ABNORMAL_INF00 0x100010 @@ -153,6 +152,8 @@ #define QM_DB_TIMEOUT BIT(10) #define QM_OF_FIFO_OF BIT(11) #define QM_RAS_AXI_ERROR (BIT(0) | BIT(1) | BIT(12)) +#define QM_RAS_MASK_ALL GENMASK(31, 0) +#define QM_RAS_CLEAR_ALL GENMASK(31, 0) #define QM_RESET_WAIT_TIMEOUT 400 #define QM_PEH_VENDOR_ID 0x1000d8 @@ -1504,7 +1505,7 @@ static int qm_get_vft_v2(struct hisi_qm *qm, u32 *base, u32 *number) static void qm_hw_error_init_v1(struct hisi_qm *qm) { - writel(QM_ABNORMAL_INT_MASK_VALUE, qm->io_base + QM_ABNORMAL_INT_MASK); + writel(QM_RAS_MASK_ALL, qm->io_base + QM_ABNORMAL_INT_MASK); } static void qm_hw_error_cfg(struct hisi_qm *qm) @@ -1513,7 +1514,7 @@ static void qm_hw_error_cfg(struct hisi_qm *qm) qm->error_mask = qm_err->nfe | qm_err->ce | qm_err->fe; /* clear QM hw residual error source */ - writel(qm->error_mask, qm->io_base + QM_ABNORMAL_INT_SOURCE); + writel(QM_RAS_CLEAR_ALL, qm->io_base + QM_ABNORMAL_INT_SOURCE); if (qm->ver >= QM_HW_V5) writeq(QM_FUNC_RAS_CLEAR_ALL, qm->io_base + QM_FUNC_AXI_ERR_ST0); @@ -1526,43 +1527,28 @@ static void qm_hw_error_cfg(struct hisi_qm *qm) static void qm_hw_error_init_v2(struct hisi_qm *qm) { - u32 irq_unmask; - qm_hw_error_cfg(qm); - irq_unmask = ~qm->error_mask; - irq_unmask &= readl(qm->io_base + QM_ABNORMAL_INT_MASK); - writel(irq_unmask, qm->io_base + QM_ABNORMAL_INT_MASK); + writel(~qm->error_mask, qm->io_base + QM_ABNORMAL_INT_MASK); } static void qm_hw_error_uninit_v2(struct hisi_qm *qm) { - u32 irq_mask = qm->error_mask; - - irq_mask |= readl(qm->io_base + QM_ABNORMAL_INT_MASK); - writel(irq_mask, qm->io_base + QM_ABNORMAL_INT_MASK); + writel(QM_RAS_MASK_ALL, qm->io_base + QM_ABNORMAL_INT_MASK); } static void qm_hw_error_init_v3(struct hisi_qm *qm) { - u32 irq_unmask; - qm_hw_error_cfg(qm); /* enable close master ooo when hardware error happened */ writel(qm->err_info.qm_err.shutdown_mask, qm->io_base + QM_OOO_SHUTDOWN_SEL); - - irq_unmask = ~qm->error_mask; - irq_unmask &= readl(qm->io_base + QM_ABNORMAL_INT_MASK); - writel(irq_unmask, qm->io_base + QM_ABNORMAL_INT_MASK); + writel(~qm->error_mask, qm->io_base + QM_ABNORMAL_INT_MASK); } static void qm_hw_error_uninit_v3(struct hisi_qm *qm) { - u32 irq_mask = qm->error_mask; - - irq_mask |= readl(qm->io_base + QM_ABNORMAL_INT_MASK); - writel(irq_mask, qm->io_base + QM_ABNORMAL_INT_MASK); + writel(QM_RAS_MASK_ALL, qm->io_base + QM_ABNORMAL_INT_MASK); /* disable close master ooo when hardware error happened */ writel(0x0, qm->io_base + QM_OOO_SHUTDOWN_SEL); diff --git a/drivers/crypto/hisilicon/sec2/sec_main.c b/drivers/crypto/hisilicon/sec2/sec_main.c index e8bea1e496f7..752565200c16 100644 --- a/drivers/crypto/hisilicon/sec2/sec_main.c +++ b/drivers/crypto/hisilicon/sec2/sec_main.c @@ -48,6 +48,7 @@ #define SEC_OOO_SHUTDOWN_SEL 0x301014 #define SEC_RAS_DISABLE 0x0 #define SEC_AXI_ERROR_MASK (BIT(0) | BIT(1)) +#define SEC_RAS_CLEAR_ALL GENMASK(31, 0) #define SEC_MEM_START_INIT_REG 0x301100 #define SEC_MEM_INIT_DONE_REG 0x301104 @@ -752,7 +753,7 @@ static void sec_hw_error_enable(struct hisi_qm *qm) } /* clear SEC hw error source if having */ - writel(err_mask, qm->io_base + SEC_CORE_INT_SOURCE); + writel(SEC_RAS_CLEAR_ALL, qm->io_base + SEC_CORE_INT_SOURCE); /* enable RAS int */ writel(dev_err->ce, qm->io_base + SEC_RAS_CE_REG); diff --git a/drivers/crypto/hisilicon/zip/zip_main.c b/drivers/crypto/hisilicon/zip/zip_main.c index 5135b3028cb2..706a73656977 100644 --- a/drivers/crypto/hisilicon/zip/zip_main.c +++ b/drivers/crypto/hisilicon/zip/zip_main.c @@ -64,7 +64,8 @@ #define HZIP_OOO_SHUTDOWN_SEL 0x30120C #define HZIP_SRAM_ECC_ERR_NUM_SHIFT 16 #define HZIP_SRAM_ECC_ERR_ADDR_SHIFT 24 -#define HZIP_CORE_INT_MASK_ALL GENMASK(12, 0) +#define HZIP_CORE_INT_MASK_ALL GENMASK(31, 0) +#define HZIP_CORE_RAS_CLEAR_ALL GENMASK(31, 0) #define HZIP_AXI_ERROR_MASK (BIT(2) | BIT(3)) #define HZIP_SQE_SIZE 128 #define HZIP_PF_DEF_Q_NUM 64 @@ -696,7 +697,7 @@ static void hisi_zip_hw_error_enable(struct hisi_qm *qm) } /* clear ZIP hw error source if having */ - writel(err_mask, qm->io_base + HZIP_CORE_INT_SOURCE); + writel(HZIP_CORE_RAS_CLEAR_ALL, qm->io_base + HZIP_CORE_INT_SOURCE); /* configure error type */ writel(dev_err->ce, qm->io_base + HZIP_CORE_INT_RAS_CE_ENB); @@ -713,11 +714,8 @@ static void hisi_zip_hw_error_enable(struct hisi_qm *qm) static void hisi_zip_hw_error_disable(struct hisi_qm *qm) { - struct hisi_qm_err_mask *dev_err = &qm->err_info.dev_err; - u32 err_mask = dev_err->ce | dev_err->nfe | dev_err->fe; - /* disable ZIP hw error interrupts */ - writel(err_mask, qm->io_base + HZIP_CORE_INT_MASK_REG); + writel(HZIP_CORE_INT_MASK_ALL, qm->io_base + HZIP_CORE_INT_MASK_REG); hisi_zip_master_ooo_ctrl(qm, false); From cc3b6331ccb06ec481439cef464b38cfa35c2802 Mon Sep 17 00:00:00 2001 From: Zongyu Wu Date: Mon, 18 May 2026 22:29:56 +0800 Subject: [PATCH 151/196] crypto: hisilicon/qm - support doorbell enable control The driver notifies the hardware to handle task through doorbell. Currently, doorbell is enabled by default. To prevent the process from sending doorbells during hardware reset scenarios, which could cause the hardware to process doorbells and trigger new errors: For example, when the physical machine is resetting the device, doorbells are still being sent from the virtual machine. Therefore, the driver disables doorbell during hardware unavailability. After hardware initialization is completed, doorbell is enabled, and any task sent during the unavailability period will return errors. The hardware supports the PF to disable doorbells for all functions, while the VF can only disable its own doorbell function. When the PF is reset, it will disable doorbells for all functions. When VF is reset, it only disables its own doorbell and does not affect tasks on other functions. Signed-off-by: Zongyu Wu Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/qm.c | 54 +++++++++++++++++++++++++++++++---- include/linux/hisi_acc_qm.h | 12 ++++++++ 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index bfee16503c38..a951d2ef7833 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -247,6 +247,11 @@ #define QM_QOS_MAX_CIR_U 6 #define QM_AUTOSUSPEND_DELAY 3000 +#define QM_DB_DROP_ALL_FUNC_ENABLE GENMASK(63, 0) +#define QM_DB_DROP_ALL_FUNC_DISABLE 0 +#define QM_DEV_DB_DROP 0x0100250 +#define QM_FUN_DB_DROP 0x0038 + /* qm function err mask */ #define QM_FUNC_AXI_ERR_ST0 0x100280 #define QM_RAS_FUNC_ERROR (BIT(0) | BIT(1)) @@ -577,6 +582,29 @@ static int qm_wait_reset_finish(struct hisi_qm *qm) return 0; } +static void qm_fun_db_ctrl(struct hisi_qm *qm, bool enable) +{ + u32 val; + + if (qm->ver >= QM_HW_V5) { + val = readl(qm->io_base + QM_FUN_DB_DROP); + val = enable ? (val | BIT(0)) : (val & ~BIT(0)); + + writel(val, qm->io_base + QM_FUN_DB_DROP); + } +} + +static void qm_dev_db_ctrl(struct hisi_qm *qm, bool enable) +{ + u64 val; + + if (qm->ver >= QM_HW_V5 && qm->fun_type == QM_HW_PF) { + val = enable ? QM_DB_DROP_ALL_FUNC_ENABLE : QM_DB_DROP_ALL_FUNC_DISABLE; + + writeq(val, qm->io_base + QM_DEV_DB_DROP); + } +} + static int qm_reset_prepare_ready(struct hisi_qm *qm) { struct pci_dev *pdev = qm->pdev; @@ -3434,6 +3462,9 @@ static int __hisi_qm_start(struct hisi_qm *qm) if (ret) return ret; + /* Enables the doorbell function when the device is enabled. */ + qm_dev_db_ctrl(qm, false); + qm_fun_db_ctrl(qm, false); qm_init_prefetch(qm); qm_enable_eq_aeq_interrupts(qm); @@ -3541,7 +3572,7 @@ static void qm_invalid_queues(struct hisi_qm *qm) if (qm->status.stop_reason == QM_NORMAL) return; - if (qm->status.stop_reason == QM_DOWN) + if (qm->status.stop_reason == QM_DOWN || qm->status.stop_reason == QM_SHUTDOWN) hisi_qm_cache_wb(qm); for (i = 0; i < qm->qp_num; i++) { @@ -3585,6 +3616,8 @@ int hisi_qm_stop(struct hisi_qm *qm, enum qm_stop_reason r) if (qm->status.stop_reason != QM_NORMAL) { hisi_qm_set_hw_reset(qm, QM_RESET_STOP_TX_OFFSET); + if (qm->status.stop_reason != QM_SHUTDOWN) + qm_fun_db_ctrl(qm, true); /* * When performing soft reset, the hardware will no longer * do tasks, and the tasks in the device will be flushed @@ -4611,6 +4644,8 @@ static int qm_controller_reset_prepare(struct hisi_qm *qm) if (ret) pci_err(pdev, "failed to stop by vfs in soft reset!\n"); + qm_dev_db_ctrl(qm, true); + return 0; } @@ -5019,16 +5054,25 @@ void hisi_qm_reset_prepare(struct pci_dev *pdev) ret = hisi_qm_stop(qm, QM_DOWN); if (ret) { pci_err(pdev, "Failed to stop QM, ret = %d.\n", ret); - hisi_qm_set_hw_reset(qm, QM_RESET_STOP_TX_OFFSET); - hisi_qm_set_hw_reset(qm, QM_RESET_STOP_RX_OFFSET); - return; + goto err_prepare; } ret = qm_wait_vf_prepare_finish(qm); if (ret) pci_err(pdev, "failed to stop by vfs in FLR!\n"); + qm_dev_db_ctrl(qm, true); + pci_info(pdev, "FLR resetting...\n"); + + return; + +err_prepare: + pci_info(pdev, "FLR resetting prepare failed!\n"); + atomic_set(&qm->status.flags, QM_STOP); + hisi_qm_set_hw_reset(qm, QM_RESET_STOP_TX_OFFSET); + hisi_qm_set_hw_reset(qm, QM_RESET_STOP_RX_OFFSET); + qm_dev_db_ctrl(qm, true); } EXPORT_SYMBOL_GPL(hisi_qm_reset_prepare); @@ -5122,7 +5166,7 @@ void hisi_qm_dev_shutdown(struct pci_dev *pdev) struct hisi_qm *qm = pci_get_drvdata(pdev); int ret; - ret = hisi_qm_stop(qm, QM_DOWN); + ret = hisi_qm_stop(qm, QM_SHUTDOWN); if (ret) dev_err(&pdev->dev, "Fail to stop qm in shutdown!\n"); } diff --git a/include/linux/hisi_acc_qm.h b/include/linux/hisi_acc_qm.h index 0a2da1029a3f..f7570a409905 100644 --- a/include/linux/hisi_acc_qm.h +++ b/include/linux/hisi_acc_qm.h @@ -115,10 +115,22 @@ #define QM_ECC_MBIT BIT(2) +/** + * enum qm_stop_reason - Queue manager stop reasons + * @QM_NORMAL: Graceful stop. Used for device unbind, driver removal, + * or runtime power management (runtime_suspend). + * @QM_SOFT_RESET: Error recovery reset. Triggered by unrecoverable hardware + * errors (e.g., PCIe AER, timeout) to recover device state. + * @QM_DOWN: Function Level Reset. Used when the device needs to + * be reset at the function level without resetting the link. + * @QM_SHUTDOWN: System shutdown. Used during system poweroff, reboot, or + * kexec to ensure hardware is in a safe state. + */ enum qm_stop_reason { QM_NORMAL, QM_SOFT_RESET, QM_DOWN, + QM_SHUTDOWN, }; enum qm_state { From 8cfd577a5c9e37f3a05088aecf6112dce0f36b14 Mon Sep 17 00:00:00 2001 From: Aleksander Jan Bajkowski Date: Mon, 18 May 2026 23:22:56 +0200 Subject: [PATCH 152/196] crypto: inside-secure/eip93 - Drop superfluous blank line No need for a blank line. Signed-off-by: Aleksander Jan Bajkowski Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/eip93/eip93-main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/crypto/inside-secure/eip93/eip93-main.c b/drivers/crypto/inside-secure/eip93/eip93-main.c index 7dccfdeb7b11..320a37d1f7dc 100644 --- a/drivers/crypto/inside-secure/eip93/eip93-main.c +++ b/drivers/crypto/inside-secure/eip93/eip93-main.c @@ -439,7 +439,6 @@ static int eip93_crypto_probe(struct platform_device *pdev) return -ENOMEM; ret = eip93_desc_init(eip93); - if (ret) return ret; From 85a61bf9145d4097c740ffcf3aa832d930a8913b Mon Sep 17 00:00:00 2001 From: Aleksander Jan Bajkowski Date: Mon, 18 May 2026 23:24:59 +0200 Subject: [PATCH 153/196] crypto: inside-secure/eip93 - Add check for devm_request_threaded_irq As the potential failure of the devm_request_threaded_irq(), it should be better to check the return value and return error if fails. Fixes: 9739f5f93b78 ("crypto: eip93 - Add Inside Secure SafeXcel EIP-93 crypto engine support") Signed-off-by: Aleksander Jan Bajkowski Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/eip93/eip93-main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/crypto/inside-secure/eip93/eip93-main.c b/drivers/crypto/inside-secure/eip93/eip93-main.c index 320a37d1f7dc..1a8dabc4ada4 100644 --- a/drivers/crypto/inside-secure/eip93/eip93-main.c +++ b/drivers/crypto/inside-secure/eip93/eip93-main.c @@ -433,6 +433,8 @@ static int eip93_crypto_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(eip93->dev, eip93->irq, eip93_irq_handler, NULL, IRQF_ONESHOT, dev_name(eip93->dev), eip93); + if (ret) + return ret; eip93->ring = devm_kcalloc(eip93->dev, 1, sizeof(*eip93->ring), GFP_KERNEL); if (!eip93->ring) From 03215b8457784540acc741e6331e355b62c6c8ab Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 19 May 2026 12:22:18 +0800 Subject: [PATCH 154/196] crypto: tegra - Fix dma_free_coherent size error When freeing a coherent DMA buffer, the size must match the value that was used during the allocation. Unfortunately the size field in the tegra driver gets overwritten by this point so it no longer matches and creates a warning. Fix this by saving a copy of the size on the stack. Note that the ccm function actually mixes up the inbuf and outbuf sizes, but it doesn't matter because the two sizes are actually equal. Fixes: 1cb328da4e8f ("crypto: tegra - Do not use fixed size buffers") Reporeted-by: Patrick Talbert Signed-off-by: Herbert Xu Reviewed-by: Vladislav Dronov Signed-off-by: Herbert Xu --- drivers/crypto/tegra/tegra-se-aes.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/crypto/tegra/tegra-se-aes.c b/drivers/crypto/tegra/tegra-se-aes.c index 30c78afe3dea..5086e7f140c3 100644 --- a/drivers/crypto/tegra/tegra-se-aes.c +++ b/drivers/crypto/tegra/tegra-se-aes.c @@ -1201,6 +1201,7 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq) struct crypto_aead *tfm = crypto_aead_reqtfm(req); struct tegra_aead_ctx *ctx = crypto_aead_ctx(tfm); struct tegra_se *se = ctx->se; + unsigned int bufsize; int ret; ret = tegra_ccm_crypt_init(req, se, rctx); @@ -1210,14 +1211,15 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq) rctx->key_id = ctx->key_id; /* Allocate buffers required */ - rctx->inbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen + 100; - rctx->inbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->inbuf.size, + bufsize = rctx->assoclen + rctx->authsize + rctx->cryptlen + 100; + rctx->inbuf.size = bufsize; + rctx->inbuf.buf = dma_alloc_coherent(ctx->se->dev, bufsize, &rctx->inbuf.addr, GFP_KERNEL); if (!rctx->inbuf.buf) goto out_finalize; - rctx->outbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen + 100; - rctx->outbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->outbuf.size, + rctx->outbuf.size = bufsize; + rctx->outbuf.buf = dma_alloc_coherent(ctx->se->dev, bufsize, &rctx->outbuf.addr, GFP_KERNEL); if (!rctx->outbuf.buf) { ret = -ENOMEM; @@ -1254,11 +1256,11 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq) } out: - dma_free_coherent(ctx->se->dev, rctx->inbuf.size, + dma_free_coherent(ctx->se->dev, bufsize, rctx->outbuf.buf, rctx->outbuf.addr); out_free_inbuf: - dma_free_coherent(ctx->se->dev, rctx->outbuf.size, + dma_free_coherent(ctx->se->dev, bufsize, rctx->inbuf.buf, rctx->inbuf.addr); if (tegra_key_is_reserved(rctx->key_id)) @@ -1278,6 +1280,7 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq) struct crypto_aead *tfm = crypto_aead_reqtfm(req); struct tegra_aead_ctx *ctx = crypto_aead_ctx(tfm); struct tegra_aead_reqctx *rctx = aead_request_ctx(req); + unsigned int bufsize; int ret; rctx->src_sg = req->src; @@ -1296,16 +1299,17 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq) rctx->key_id = ctx->key_id; /* Allocate buffers required */ - rctx->inbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen; - rctx->inbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->inbuf.size, + bufsize = rctx->assoclen + rctx->authsize + rctx->cryptlen; + rctx->inbuf.size = bufsize; + rctx->inbuf.buf = dma_alloc_coherent(ctx->se->dev, bufsize, &rctx->inbuf.addr, GFP_KERNEL); if (!rctx->inbuf.buf) { ret = -ENOMEM; goto out_finalize; } - rctx->outbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen; - rctx->outbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->outbuf.size, + rctx->outbuf.size = bufsize; + rctx->outbuf.buf = dma_alloc_coherent(ctx->se->dev, bufsize, &rctx->outbuf.addr, GFP_KERNEL); if (!rctx->outbuf.buf) { ret = -ENOMEM; @@ -1342,11 +1346,11 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq) ret = tegra_gcm_do_verify(ctx->se, rctx); out: - dma_free_coherent(ctx->se->dev, rctx->outbuf.size, + dma_free_coherent(ctx->se->dev, bufsize, rctx->outbuf.buf, rctx->outbuf.addr); out_free_inbuf: - dma_free_coherent(ctx->se->dev, rctx->inbuf.size, + dma_free_coherent(ctx->se->dev, bufsize, rctx->inbuf.buf, rctx->inbuf.addr); if (tegra_key_is_reserved(rctx->key_id)) From 370d6c3d411af8d34fcc227c244f4926fc743da7 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 19 May 2026 10:36:32 +0200 Subject: [PATCH 155/196] crypto: ecrdsa - remove empty sig_alg exit callback ecrdsa_exit_tfm() is empty, and sig_alg .exit is optional. The corresponding .init callback is not set either, so there is nothing to release in .exit. Remove the empty function and leave .exit unset. Signed-off-by: Thorsten Blum Reviewed-by: Lukas Wunner Signed-off-by: Herbert Xu --- crypto/ecrdsa.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/crypto/ecrdsa.c b/crypto/ecrdsa.c index 0cd7eb367604..93c9e7d76792 100644 --- a/crypto/ecrdsa.c +++ b/crypto/ecrdsa.c @@ -259,16 +259,11 @@ static unsigned int ecrdsa_max_size(struct crypto_sig *tfm) return 2 * ctx->pub_key.ndigits * sizeof(u64); } -static void ecrdsa_exit_tfm(struct crypto_sig *tfm) -{ -} - static struct sig_alg ecrdsa_alg = { .verify = ecrdsa_verify, .set_pub_key = ecrdsa_set_pub_key, .key_size = ecrdsa_key_size, .max_size = ecrdsa_max_size, - .exit = ecrdsa_exit_tfm, .base = { .cra_name = "ecrdsa", .cra_driver_name = "ecrdsa-generic", From 690a5f9e5c972a580565ce544ed1627ccf1e84de Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 20 May 2026 10:51:14 +0800 Subject: [PATCH 156/196] crypto: tegra - Return ENOMEM when input buffer allocation fails for ccm Ensure the ENOMEM error value is set when the input buffer allocation fails in tegra_ccm_do_one_req. Fixes: 1e245948ca0c ("crypto: tegra - finalize crypto req on error") Reported-by: Vladislav Dronov Signed-off-by: Herbert Xu Reviewed-by: Vladislav Dronov Signed-off-by: Herbert Xu --- drivers/crypto/tegra/tegra-se-aes.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/tegra/tegra-se-aes.c b/drivers/crypto/tegra/tegra-se-aes.c index 5086e7f140c3..9094c03e991f 100644 --- a/drivers/crypto/tegra/tegra-se-aes.c +++ b/drivers/crypto/tegra/tegra-se-aes.c @@ -1215,16 +1215,15 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq) rctx->inbuf.size = bufsize; rctx->inbuf.buf = dma_alloc_coherent(ctx->se->dev, bufsize, &rctx->inbuf.addr, GFP_KERNEL); + ret = -ENOMEM; if (!rctx->inbuf.buf) goto out_finalize; rctx->outbuf.size = bufsize; rctx->outbuf.buf = dma_alloc_coherent(ctx->se->dev, bufsize, &rctx->outbuf.addr, GFP_KERNEL); - if (!rctx->outbuf.buf) { - ret = -ENOMEM; + if (!rctx->outbuf.buf) goto out_free_inbuf; - } if (!ctx->key_id) { ret = tegra_key_submit_reserved_aes(ctx->se, ctx->key, From 5ec1a676301ad1adab10e6200ead363e5efb4e15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Wed, 20 May 2026 09:01:28 +0200 Subject: [PATCH 157/196] crypto: atmel-sha204a - Drop of_device_id data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver binds to i2c devices only and thus in the absence of an assignment for .data in the of_device_id array i2c_get_match_data() falls back to .driver_data from the i2c_device_id array. So only provide &atsha204_quality once to reduce duplication. Signed-off-by: Uwe Kleine-König (The Capable Hub) Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha204a.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index 12eb85b57380..a51e1f1e0088 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -209,8 +209,8 @@ static void atmel_sha204a_remove(struct i2c_client *client) } static const struct of_device_id atmel_sha204a_dt_ids[] = { - { .compatible = "atmel,atsha204", .data = &atsha204_quality }, - { .compatible = "atmel,atsha204a", }, + { .compatible = "atmel,atsha204" }, + { .compatible = "atmel,atsha204a" }, { } }; MODULE_DEVICE_TABLE(of, atmel_sha204a_dt_ids); From 42a58f08b70a7a320c168a1ce15e3fcfc8568708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Wed, 20 May 2026 09:01:29 +0200 Subject: [PATCH 158/196] crypto: atmel-sha204a - Use named initializers for struct i2c_device_id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While being less compact, using named initializers allows to more easily see which members of the structs are assigned which value without having to lookup the declaration of the struct. And it's also more robust against changes to the struct definition. This patch doesn't modify the compiled array, only its representation in source form benefits. The former was confirmed with x86 and arm64 builds. For consistency also assign .driver_data for the array item that the driver relies on i2c_get_match_data() returning NULL for. Signed-off-by: Uwe Kleine-König (The Capable Hub) Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha204a.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index a51e1f1e0088..4c9af737b33a 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -216,8 +216,8 @@ static const struct of_device_id atmel_sha204a_dt_ids[] = { MODULE_DEVICE_TABLE(of, atmel_sha204a_dt_ids); static const struct i2c_device_id atmel_sha204a_id[] = { - { "atsha204", (kernel_ulong_t)&atsha204_quality }, - { "atsha204a" }, + { .name = "atsha204", .driver_data = (kernel_ulong_t)&atsha204_quality }, + { .name = "atsha204a", .driver_data = (kernel_ulong_t)NULL }, { } }; MODULE_DEVICE_TABLE(i2c, atmel_sha204a_id); From 59f61b242400939084fe644e4e0cb7f141279ad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Wed, 20 May 2026 09:01:30 +0200 Subject: [PATCH 159/196] crypto: atmel-ecc - Use named initializers for struct i2c_device_id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While being less compact, using named initializers allows to more easily see which members of the structs are assigned which value without having to lookup the declaration of the struct. And it's also more robust against changes to the struct definition. This patch doesn't modify the compiled array, only its representation in source form benefits. The former was confirmed with x86 and arm64 builds. Signed-off-by: Uwe Kleine-König (The Capable Hub) Signed-off-by: Herbert Xu --- drivers/crypto/atmel-ecc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index 9660f6426a84..0ca02995a1de 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -376,8 +376,8 @@ static const struct of_device_id atmel_ecc_dt_ids[] = { MODULE_DEVICE_TABLE(of, atmel_ecc_dt_ids); static const struct i2c_device_id atmel_ecc_id[] = { - { "atecc508a" }, - { "atecc608b" }, + { .name = "atecc508a" }, + { .name = "atecc608b" }, { } }; MODULE_DEVICE_TABLE(i2c, atmel_ecc_id); From a43b47340b6bf809f282db8639fc4deea0180208 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Wed, 20 May 2026 12:00:30 +0200 Subject: [PATCH 160/196] crypto: octeontx - use strscpy_pad in ucode_load_store Instead of zero-initializing the temporary buffer and then copying into it with strscpy(), use strscpy_pad() to copy the string and zero-pad any trailing bytes. Drop the explicit size argument to further simplify the code since strscpy_pad() can determine it automatically when the destination buffer has a fixed length. Also use strscpy_pad() to check for string truncation instead of the hard-coded OTX_CPT_UCODE_NAME_LENGTH. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c b/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c index e0f38d32bc93..205579a6ba2b 100644 --- a/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c +++ b/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c @@ -1318,7 +1318,7 @@ static ssize_t ucode_load_store(struct device *dev, { struct otx_cpt_engines engs[OTX_CPT_MAX_ETYPES_PER_GRP] = { {0} }; char *ucode_filename[OTX_CPT_MAX_ETYPES_PER_GRP]; - char tmp_buf[OTX_CPT_UCODE_NAME_LENGTH] = { 0 }; + char tmp_buf[OTX_CPT_UCODE_NAME_LENGTH]; char *start, *val, *err_msg, *tmp; struct otx_cpt_eng_grps *eng_grps; int grp_idx = 0, ret = -EINVAL; @@ -1326,12 +1326,11 @@ static ssize_t ucode_load_store(struct device *dev, int del_grp_idx = -1; int ucode_idx = 0; - if (count >= OTX_CPT_UCODE_NAME_LENGTH) + if (strscpy_pad(tmp_buf, buf) < 0) return -EINVAL; eng_grps = container_of(attr, struct otx_cpt_eng_grps, ucode_load_attr); err_msg = "Invalid engine group format"; - strscpy(tmp_buf, buf, OTX_CPT_UCODE_NAME_LENGTH); start = tmp_buf; has_se = has_ie = has_ae = false; From 7d3ed20f7e46b3e991936fedd7a28f3ff4aec8d2 Mon Sep 17 00:00:00 2001 From: Ahsan Atta Date: Wed, 20 May 2026 13:33:00 +0100 Subject: [PATCH 161/196] crypto: qat - fix restarting state leak on allocation failure In adf_dev_aer_schedule_reset(), ADF_STATUS_RESTARTING is set before allocating reset_data. If the allocation fails, the function returns -ENOMEM without queuing reset work, so nothing ever clears the bit. This leaves the device permanently stuck in the restarting state, causing all subsequent reset attempts to be silently skipped. Fix this by using test_and_set_bit() to atomically claim the RESTARTING state, preventing duplicate reset scheduling races under concurrent fatal error reporting. If the subsequent allocation fails, clear the bit to restore clean state so future reset attempts can proceed. Cc: stable@vger.kernel.org Fixes: d8cba25d2c68 ("crypto: qat - Intel(R) QAT driver framework") Signed-off-by: Ahsan Atta Co-developed-by: Maksim Lukoshkov Signed-off-by: Maksim Lukoshkov Reviewed-by: Giovanni Cabiddu Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/adf_aer.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_common/adf_aer.c b/drivers/crypto/intel/qat/qat_common/adf_aer.c index af028488e660..3fc7d13e882c 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_aer.c +++ b/drivers/crypto/intel/qat/qat_common/adf_aer.c @@ -207,13 +207,14 @@ static int adf_dev_aer_schedule_reset(struct adf_accel_dev *accel_dev, struct adf_reset_dev_data *reset_data; if (!adf_dev_started(accel_dev) || - test_bit(ADF_STATUS_RESTARTING, &accel_dev->status)) + test_and_set_bit(ADF_STATUS_RESTARTING, &accel_dev->status)) return 0; - set_bit(ADF_STATUS_RESTARTING, &accel_dev->status); reset_data = kzalloc_obj(*reset_data); - if (!reset_data) + if (!reset_data) { + clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status); return -ENOMEM; + } reset_data->accel_dev = accel_dev; init_completion(&reset_data->compl); reset_data->mode = mode; From 5c6f845e77ec35f9b7b047cc8f9789bf397cdd3e Mon Sep 17 00:00:00 2001 From: Ahsan Atta Date: Wed, 20 May 2026 13:41:55 +0100 Subject: [PATCH 162/196] crypto: qat - protect service table iterations with service_lock The service_table list is protected by service_lock when entries are added or removed (in adf_service_add() and adf_service_remove()), but several functions iterate over the list without holding this lock. A concurrent adf_service_register() or adf_service_unregister() call could modify the list during traversal, leading to list corruption or a use-after-free. Fix this by holding service_lock across all list_for_each_entry() iterations of service_table in adf_dev_init(), adf_dev_start(), adf_dev_stop(), adf_dev_shutdown(), adf_dev_restarting_notify(), adf_dev_restarted_notify(), and adf_error_notifier(). The lock ordering is safe: callers of the static helpers (adf_dev_up() and adf_dev_down()) acquire state_lock before service_lock, and no event_hld callback or service_lock holder ever acquires state_lock in the reverse order. Cc: stable@vger.kernel.org Fixes: d8cba25d2c68 ("crypto: qat - Intel(R) QAT driver framework") Signed-off-by: Ahsan Atta Co-developed-by: Maksim Lukoshkov Signed-off-by: Maksim Lukoshkov Reviewed-by: Giovanni Cabiddu Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/adf_init.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/crypto/intel/qat/qat_common/adf_init.c b/drivers/crypto/intel/qat/qat_common/adf_init.c index f9f5696ed476..1c7f9e49914d 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_init.c +++ b/drivers/crypto/intel/qat/qat_common/adf_init.c @@ -155,15 +155,18 @@ static int adf_dev_init(struct adf_accel_dev *accel_dev) * This is to facilitate any ordering dependencies between services * prior to starting any of the accelerators. */ + mutex_lock(&service_lock); list_for_each_entry(service, &service_table, list) { if (service->event_hld(accel_dev, ADF_EVENT_INIT)) { dev_err(&GET_DEV(accel_dev), "Failed to initialise service %s\n", service->name); + mutex_unlock(&service_lock); return -EFAULT; } set_bit(accel_dev->accel_id, service->init_status); } + mutex_unlock(&service_lock); return 0; } @@ -233,15 +236,18 @@ static int adf_dev_start(struct adf_accel_dev *accel_dev) if (ret && ret != -EOPNOTSUPP) return ret; + mutex_lock(&service_lock); list_for_each_entry(service, &service_table, list) { if (service->event_hld(accel_dev, ADF_EVENT_START)) { dev_err(&GET_DEV(accel_dev), "Failed to start service %s\n", service->name); + mutex_unlock(&service_lock); return -EFAULT; } set_bit(accel_dev->accel_id, service->start_status); } + mutex_unlock(&service_lock); clear_bit(ADF_STATUS_STARTING, &accel_dev->status); set_bit(ADF_STATUS_STARTED, &accel_dev->status); @@ -315,6 +321,7 @@ static void adf_dev_stop(struct adf_accel_dev *accel_dev) qat_comp_algs_unregister(hw_data->accel_capabilities_ext_mask); clear_bit(ADF_STATUS_COMP_ALGS_REGISTERED, &accel_dev->status); + mutex_lock(&service_lock); list_for_each_entry(service, &service_table, list) { if (!test_bit(accel_dev->accel_id, service->start_status)) continue; @@ -326,6 +333,7 @@ static void adf_dev_stop(struct adf_accel_dev *accel_dev) clear_bit(accel_dev->accel_id, service->start_status); } } + mutex_unlock(&service_lock); if (hw_data->stop_timer) hw_data->stop_timer(accel_dev); @@ -375,6 +383,7 @@ static void adf_dev_shutdown(struct adf_accel_dev *accel_dev) &accel_dev->status); } + mutex_lock(&service_lock); list_for_each_entry(service, &service_table, list) { if (!test_bit(accel_dev->accel_id, service->init_status)) continue; @@ -385,6 +394,7 @@ static void adf_dev_shutdown(struct adf_accel_dev *accel_dev) else clear_bit(accel_dev->accel_id, service->init_status); } + mutex_unlock(&service_lock); adf_rl_exit(accel_dev); @@ -419,12 +429,14 @@ int adf_dev_restarting_notify(struct adf_accel_dev *accel_dev) { struct service_hndl *service; + mutex_lock(&service_lock); list_for_each_entry(service, &service_table, list) { if (service->event_hld(accel_dev, ADF_EVENT_RESTARTING)) dev_err(&GET_DEV(accel_dev), "Failed to restart service %s.\n", service->name); } + mutex_unlock(&service_lock); return 0; } @@ -432,12 +444,14 @@ int adf_dev_restarted_notify(struct adf_accel_dev *accel_dev) { struct service_hndl *service; + mutex_lock(&service_lock); list_for_each_entry(service, &service_table, list) { if (service->event_hld(accel_dev, ADF_EVENT_RESTARTED)) dev_err(&GET_DEV(accel_dev), "Failed to restart service %s.\n", service->name); } + mutex_unlock(&service_lock); return 0; } @@ -445,12 +459,14 @@ void adf_error_notifier(struct adf_accel_dev *accel_dev) { struct service_hndl *service; + mutex_lock(&service_lock); list_for_each_entry(service, &service_table, list) { if (service->event_hld(accel_dev, ADF_EVENT_FATAL_ERROR)) dev_err(&GET_DEV(accel_dev), "Failed to send error event to %s.\n", service->name); } + mutex_unlock(&service_lock); } int adf_dev_down(struct adf_accel_dev *accel_dev) From 90fe909ed6956a8bcc627cbefe6e225ad4cbcd4b Mon Sep 17 00:00:00 2001 From: Ahsan Atta Date: Wed, 20 May 2026 13:51:50 +0100 Subject: [PATCH 163/196] crypto: qat - use pci logging variants for PCI-specific messages Replace dev_err(&pdev->dev, ...), dev_info(&pdev->dev, ...) and dev_dbg(&pdev->dev, ...) with pci_err(), pci_info() and pci_dbg() where the log message relates to a PCI subsystem operation such as device enable, BAR mapping, PCI region requests, PCI state save/restore, and SR-IOV management. Messages about driver-level logic (NUMA topology, device matching, accelerator units, capabilities, configuration, DMA) are intentionally left as dev_err() even when a struct pci_dev pointer is in scope, since those concern the device or driver rather than the PCI bus. No functional change. Suggested-by: Andy Shevchenko Signed-off-by: Ahsan Atta Reviewed-by: Giovanni Cabiddu Reviewed-by: Andy Shevchenko Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_420xx/adf_drv.c | 8 +++---- drivers/crypto/intel/qat/qat_4xxx/adf_drv.c | 8 +++---- drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c | 4 ++-- .../crypto/intel/qat/qat_c3xxxvf/adf_drv.c | 2 +- drivers/crypto/intel/qat/qat_c62x/adf_drv.c | 4 ++-- drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c | 2 +- drivers/crypto/intel/qat/qat_common/adf_aer.c | 21 +++++++++---------- .../crypto/intel/qat/qat_common/adf_sriov.c | 2 +- .../crypto/intel/qat/qat_dh895xcc/adf_drv.c | 4 ++-- .../crypto/intel/qat/qat_dh895xccvf/adf_drv.c | 2 +- 10 files changed, 28 insertions(+), 29 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_420xx/adf_drv.c b/drivers/crypto/intel/qat/qat_420xx/adf_drv.c index 265bd52778c5..0f0827e2b0bd 100644 --- a/drivers/crypto/intel/qat/qat_420xx/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_420xx/adf_drv.c @@ -101,7 +101,7 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Enable PCI device */ ret = pcim_enable_device(pdev); if (ret) { - dev_err(&pdev->dev, "Can't enable PCI device.\n"); + pci_err(pdev, "Can't enable PCI device.\n"); goto out_err; } @@ -131,7 +131,7 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ret = pcim_request_all_regions(pdev, pci_name(pdev)); if (ret) { - dev_err(&pdev->dev, "Failed to request PCI regions.\n"); + pci_err(pdev, "Failed to request PCI regions.\n"); goto out_err; } @@ -140,14 +140,14 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) bar = &accel_pci_dev->pci_bars[i++]; bar->virt_addr = pcim_iomap(pdev, bar_nr, 0); if (!bar->virt_addr) { - dev_err(&pdev->dev, "Failed to ioremap PCI region.\n"); + pci_err(pdev, "Failed to ioremap PCI region.\n"); ret = -ENOMEM; goto out_err; } } if (pci_save_state(pdev)) { - dev_err(&pdev->dev, "Failed to save pci state.\n"); + pci_err(pdev, "Failed to save pci state.\n"); ret = -ENOMEM; goto out_err; } diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c index 681c4dd8f3d2..aa95f762cb4b 100644 --- a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c @@ -103,7 +103,7 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Enable PCI device */ ret = pcim_enable_device(pdev); if (ret) { - dev_err(&pdev->dev, "Can't enable PCI device.\n"); + pci_err(pdev, "Can't enable PCI device.\n"); goto out_err; } @@ -133,7 +133,7 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ret = pcim_request_all_regions(pdev, pci_name(pdev)); if (ret) { - dev_err(&pdev->dev, "Failed to request PCI regions.\n"); + pci_err(pdev, "Failed to request PCI regions.\n"); goto out_err; } @@ -142,14 +142,14 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) bar = &accel_pci_dev->pci_bars[i++]; bar->virt_addr = pcim_iomap(pdev, bar_nr, 0); if (!bar->virt_addr) { - dev_err(&pdev->dev, "Failed to ioremap PCI region.\n"); + pci_err(pdev, "Failed to ioremap PCI region.\n"); ret = -ENOMEM; goto out_err; } } if (pci_save_state(pdev)) { - dev_err(&pdev->dev, "Failed to save pci state.\n"); + pci_err(pdev, "Failed to save pci state.\n"); ret = -ENOMEM; goto out_err; } diff --git a/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c index ded52744b4fc..e816cc00632f 100644 --- a/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c @@ -162,14 +162,14 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) bar->size = pci_resource_len(pdev, bar_nr); bar->virt_addr = pci_iomap(accel_pci_dev->pci_dev, bar_nr, 0); if (!bar->virt_addr) { - dev_err(&pdev->dev, "Failed to map BAR %d\n", bar_nr); + pci_err(pdev, "Failed to map BAR %d\n", bar_nr); ret = -EFAULT; goto out_err_free_reg; } } if (pci_save_state(pdev)) { - dev_err(&pdev->dev, "Failed to save pci state\n"); + pci_err(pdev, "Failed to save pci state\n"); ret = -ENOMEM; goto out_err_free_reg; } diff --git a/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c b/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c index e7600d284ed3..1c77f0a1882b 100644 --- a/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c @@ -158,7 +158,7 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) bar->size = pci_resource_len(pdev, bar_nr); bar->virt_addr = pci_iomap(accel_pci_dev->pci_dev, bar_nr, 0); if (!bar->virt_addr) { - dev_err(&pdev->dev, "Failed to map BAR %d\n", bar_nr); + pci_err(pdev, "Failed to map BAR %d\n", bar_nr); ret = -EFAULT; goto out_err_free_reg; } diff --git a/drivers/crypto/intel/qat/qat_c62x/adf_drv.c b/drivers/crypto/intel/qat/qat_c62x/adf_drv.c index 2ebff5855b01..f48f3b437545 100644 --- a/drivers/crypto/intel/qat/qat_c62x/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_c62x/adf_drv.c @@ -162,14 +162,14 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) bar->size = pci_resource_len(pdev, bar_nr); bar->virt_addr = pci_iomap(accel_pci_dev->pci_dev, bar_nr, 0); if (!bar->virt_addr) { - dev_err(&pdev->dev, "Failed to map BAR %d\n", bar_nr); + pci_err(pdev, "Failed to map BAR %d\n", bar_nr); ret = -EFAULT; goto out_err_free_reg; } } if (pci_save_state(pdev)) { - dev_err(&pdev->dev, "Failed to save pci state\n"); + pci_err(pdev, "Failed to save pci state\n"); ret = -ENOMEM; goto out_err_free_reg; } diff --git a/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c b/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c index 91e148bb4870..b96f19e31d05 100644 --- a/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c @@ -158,7 +158,7 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) bar->size = pci_resource_len(pdev, bar_nr); bar->virt_addr = pci_iomap(accel_pci_dev->pci_dev, bar_nr, 0); if (!bar->virt_addr) { - dev_err(&pdev->dev, "Failed to map BAR %d\n", bar_nr); + pci_err(pdev, "Failed to map BAR %d\n", bar_nr); ret = -EFAULT; goto out_err_free_reg; } diff --git a/drivers/crypto/intel/qat/qat_common/adf_aer.c b/drivers/crypto/intel/qat/qat_common/adf_aer.c index 3fc7d13e882c..d58cd7fbf707 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_aer.c +++ b/drivers/crypto/intel/qat/qat_common/adf_aer.c @@ -22,7 +22,7 @@ static pci_ers_result_t reset_prepare(struct pci_dev *pdev) struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev); if (!accel_dev) { - dev_err(&pdev->dev, "Can't find acceleration device\n"); + pci_err(pdev, "Can't find acceleration device\n"); return PCI_ERS_RESULT_DISCONNECT; } @@ -46,7 +46,7 @@ static pci_ers_result_t reset_done(struct pci_dev *pdev) int res; if (!accel_dev) { - dev_err(&pdev->dev, "Can't find acceleration device\n"); + pci_err(pdev, "Can't find acceleration device\n"); return PCI_ERS_RESULT_DISCONNECT; } @@ -64,7 +64,7 @@ static pci_ers_result_t reset_done(struct pci_dev *pdev) clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status); reset_complete: - dev_info(&pdev->dev, "Device reset completed successfully\n"); + pci_info(pdev, "Device reset completed successfully\n"); return PCI_ERS_RESULT_RECOVERED; } @@ -74,14 +74,14 @@ static pci_ers_result_t adf_error_detected(struct pci_dev *pdev, { struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev); - dev_info(&pdev->dev, "Acceleration driver hardware error detected.\n"); + pci_info(pdev, "Acceleration driver hardware error detected.\n"); if (!accel_dev) { - dev_err(&pdev->dev, "Can't find acceleration device\n"); + pci_err(pdev, "Can't find acceleration device\n"); return PCI_ERS_RESULT_DISCONNECT; } if (state == pci_channel_io_perm_failure) { - dev_err(&pdev->dev, "Can't recover from device error\n"); + pci_err(pdev, "Can't recover from device error\n"); return PCI_ERS_RESULT_DISCONNECT; } @@ -116,10 +116,9 @@ void adf_reset_sbr(struct adf_accel_dev *accel_dev) parent = pdev; if (!pci_wait_for_pending_transaction(pdev)) - dev_info(&GET_DEV(accel_dev), - "Transaction still in progress. Proceeding\n"); + pci_info(pdev, "Transaction still in progress. Proceeding\n"); - dev_info(&GET_DEV(accel_dev), "Secondary bus reset\n"); + pci_info(pdev, "Secondary bus reset\n"); pci_read_config_word(parent, PCI_BRIDGE_CONTROL, &bridge_ctl); bridge_ctl |= PCI_BRIDGE_CTL_BUS_RESET; @@ -247,8 +246,8 @@ static pci_ers_result_t adf_slot_reset(struct pci_dev *pdev) static void adf_resume(struct pci_dev *pdev) { - dev_info(&pdev->dev, "Acceleration driver reset completed\n"); - dev_info(&pdev->dev, "Device is up and running\n"); + pci_info(pdev, "Acceleration driver reset completed\n"); + pci_info(pdev, "Device is up and running\n"); } static void adf_reset_prepare(struct pci_dev *pdev) diff --git a/drivers/crypto/intel/qat/qat_common/adf_sriov.c b/drivers/crypto/intel/qat/qat_common/adf_sriov.c index f2011300a929..f45ca2eecc00 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_sriov.c +++ b/drivers/crypto/intel/qat/qat_common/adf_sriov.c @@ -240,7 +240,7 @@ void adf_reenable_sriov(struct adf_accel_dev *accel_dev) if (adf_add_sriov_configuration(accel_dev)) return; - dev_dbg(&pdev->dev, "Re-enabling SRIOV\n"); + pci_dbg(pdev, "Re-enabling SRIOV\n"); adf_enable_sriov(accel_dev); } diff --git a/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c b/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c index 97ad53eef38f..571f302edea3 100644 --- a/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c @@ -162,14 +162,14 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) bar->size = pci_resource_len(pdev, bar_nr); bar->virt_addr = pci_iomap(accel_pci_dev->pci_dev, bar_nr, 0); if (!bar->virt_addr) { - dev_err(&pdev->dev, "Failed to map BAR %d\n", bar_nr); + pci_err(pdev, "Failed to map BAR %d\n", bar_nr); ret = -EFAULT; goto out_err_free_reg; } } if (pci_save_state(pdev)) { - dev_err(&pdev->dev, "Failed to save pci state\n"); + pci_err(pdev, "Failed to save pci state\n"); ret = -ENOMEM; goto out_err_free_reg; } diff --git a/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c b/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c index a5edda8bad32..481551a08708 100644 --- a/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c @@ -158,7 +158,7 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) bar->size = pci_resource_len(pdev, bar_nr); bar->virt_addr = pci_iomap(accel_pci_dev->pci_dev, bar_nr, 0); if (!bar->virt_addr) { - dev_err(&pdev->dev, "Failed to map BAR %d\n", bar_nr); + pci_err(pdev, "Failed to map BAR %d\n", bar_nr); ret = -EFAULT; goto out_err_free_reg; } From 50e506201bab875545c7a9443bd7e1c71804e553 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Thu, 21 May 2026 17:43:01 +1000 Subject: [PATCH 164/196] crypto: ccp/tsm - Enable the root port after the endpoint The PCIe r7.0, chapter "6.33.8 Other IDE Rules" mandates if selective IDE is enabled for config requersts, a stream must be enabled on the endpoint before enabling it on the rootport: === For Selective IDE, the Stream must not be used until it has been enabled in both Partner Ports. For cases where one of the Partner Ports is a Root Port and Selective IDE for Configuration Requests is enabled, the other Partner Port must be enabled prior to the Root Port. For other scenarios, the mechanisms to satisfy this requirement are implementation-specific. === Do what the spec says. Fixes: 4be423572da1 ("crypto/ccp: Implement SEV-TIO PCIe IDE (phase1)") Signed-off-by: Alexey Kardashevskiy Signed-off-by: Herbert Xu --- drivers/crypto/ccp/sev-dev-tsm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/crypto/ccp/sev-dev-tsm.c b/drivers/crypto/ccp/sev-dev-tsm.c index f303d8f55991..46f2539d2d5a 100644 --- a/drivers/crypto/ccp/sev-dev-tsm.c +++ b/drivers/crypto/ccp/sev-dev-tsm.c @@ -58,13 +58,13 @@ static int stream_enable(struct pci_ide *ide) struct pci_dev *rp = pcie_find_root_port(ide->pdev); int ret; - ret = pci_ide_stream_enable(rp, ide); - if (ret) + ret = pci_ide_stream_enable(ide->pdev, ide); + if (ret && ret != -ENXIO) return ret; - ret = pci_ide_stream_enable(ide->pdev, ide); - if (ret) - pci_ide_stream_disable(rp, ide); + ret = pci_ide_stream_enable(rp, ide); + if (ret && ret != -ENXIO) + pci_ide_stream_disable(ide->pdev, ide); return ret; } From 4c600ab0d8cfc9d75b92f3426dbcb2ad85eac91d Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 21 May 2026 21:25:25 -0500 Subject: [PATCH 165/196] crypto: loongson - Select CRYPTO_RNG This driver registers a rng_alg, so it requires CRYPTO_RNG. Fixes: 766b2d724c8d ("crypto: loongson - add Loongson RNG driver support") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202605201622.qWOiiZTV-lkp@intel.com/ Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers Reviewed-by: Huacai Chen Signed-off-by: Herbert Xu --- drivers/crypto/loongson/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/crypto/loongson/Kconfig b/drivers/crypto/loongson/Kconfig index 15475da8fc11..f4e1544ffbb4 100644 --- a/drivers/crypto/loongson/Kconfig +++ b/drivers/crypto/loongson/Kconfig @@ -1,5 +1,6 @@ config CRYPTO_DEV_LOONGSON_RNG tristate "Support for Loongson RNG Driver" depends on MFD_LOONGSON_SE + select CRYPTO_RNG help Support for Loongson RNG Driver. From fcc77d33a34cf271702e8daafb6c593e4626776d Mon Sep 17 00:00:00 2001 From: Demi Marie Obenour Date: Sat, 23 May 2026 15:43:02 -0400 Subject: [PATCH 166/196] net: Remove support for AIO on sockets The only user of msg->msg_iocb was AF_ALG, but that's deprecated. It can be removed entirely at the cost of only supporting synchronous operations. This doesn't break userspace, which will silently block (for a bounded amount of time) in io_submit instead of operating asynchronously. This also makes struct msghdr smaller, helping every other caller of sendmsg(). Signed-off-by: Demi Marie Obenour Acked-by: Jakub Kicinski Signed-off-by: Herbert Xu --- crypto/af_alg.c | 33 +--------- crypto/algif_aead.c | 39 +++--------- crypto/algif_skcipher.c | 62 ++++--------------- include/crypto/if_alg.h | 5 +- include/linux/socket.h | 1 - io_uring/net.c | 1 - net/compat.c | 1 - net/socket.c | 7 +-- .../perf/trace/beauty/include/linux/socket.h | 1 - 9 files changed, 25 insertions(+), 125 deletions(-) diff --git a/crypto/af_alg.c b/crypto/af_alg.c index 48c53f488e0f..8ccf7a737cd6 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -1085,35 +1085,6 @@ void af_alg_free_resources(struct af_alg_async_req *areq) } EXPORT_SYMBOL_GPL(af_alg_free_resources); -/** - * af_alg_async_cb - AIO callback handler - * @data: async request completion data - * @err: if non-zero, error result to be returned via ki_complete(); - * otherwise return the AIO output length via ki_complete(). - * - * This handler cleans up the struct af_alg_async_req upon completion of the - * AIO operation. - * - * The number of bytes to be generated with the AIO operation must be set - * in areq->outlen before the AIO callback handler is invoked. - */ -void af_alg_async_cb(void *data, int err) -{ - struct af_alg_async_req *areq = data; - struct sock *sk = areq->sk; - struct kiocb *iocb = areq->iocb; - unsigned int resultlen; - - /* Buffer size written by crypto operation. */ - resultlen = areq->outlen; - - af_alg_free_resources(areq); - sock_put(sk); - - iocb->ki_complete(iocb, err ? err : (int)resultlen); -} -EXPORT_SYMBOL_GPL(af_alg_async_cb); - /** * af_alg_poll - poll system call handler * @file: file pointer @@ -1154,8 +1125,8 @@ struct af_alg_async_req *af_alg_alloc_areq(struct sock *sk, struct af_alg_ctx *ctx = alg_sk(sk)->private; struct af_alg_async_req *areq; - /* Only one AIO request can be in flight. */ - if (ctx->inflight) + /* Only one request can be in flight. */ + if (WARN_ON_ONCE(ctx->inflight)) return ERR_PTR(-EBUSY); areq = sock_kmalloc(sk, areqlen, GFP_KERNEL); diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c index c6c2ce21895d..60f06597cb0b 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c @@ -197,37 +197,14 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, aead_request_set_ad(&areq->cra_u.aead_req, ctx->aead_assoclen); aead_request_set_tfm(&areq->cra_u.aead_req, tfm); - if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) { - /* AIO operation */ - sock_hold(sk); - areq->iocb = msg->msg_iocb; - - /* Remember output size that will be generated. */ - areq->outlen = outlen; - - aead_request_set_callback(&areq->cra_u.aead_req, - CRYPTO_TFM_REQ_MAY_SLEEP, - af_alg_async_cb, areq); - err = ctx->enc ? crypto_aead_encrypt(&areq->cra_u.aead_req) : - crypto_aead_decrypt(&areq->cra_u.aead_req); - - /* AIO operation in progress */ - if (err == -EINPROGRESS) - return -EIOCBQUEUED; - - sock_put(sk); - } else { - /* Synchronous operation */ - aead_request_set_callback(&areq->cra_u.aead_req, - CRYPTO_TFM_REQ_MAY_SLEEP | - CRYPTO_TFM_REQ_MAY_BACKLOG, - crypto_req_done, &ctx->wait); - err = crypto_wait_req(ctx->enc ? - crypto_aead_encrypt(&areq->cra_u.aead_req) : - crypto_aead_decrypt(&areq->cra_u.aead_req), - &ctx->wait); - } - + aead_request_set_callback(&areq->cra_u.aead_req, + CRYPTO_TFM_REQ_MAY_SLEEP | + CRYPTO_TFM_REQ_MAY_BACKLOG, + crypto_req_done, &ctx->wait); + err = crypto_wait_req(ctx->enc ? + crypto_aead_encrypt(&areq->cra_u.aead_req) : + crypto_aead_decrypt(&areq->cra_u.aead_req), + &ctx->wait); free: af_alg_free_resources(areq); diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index ba0a17fd95ac..9dbccabd87b1 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -79,20 +79,6 @@ static int algif_skcipher_export(struct sock *sk, struct skcipher_request *req) return err; } -static void algif_skcipher_done(void *data, int err) -{ - struct af_alg_async_req *areq = data; - struct sock *sk = areq->sk; - - if (err) - goto out; - - err = algif_skcipher_export(sk, &areq->cra_u.skcipher_req); - -out: - af_alg_async_cb(data, err); -} - static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, int flags) { @@ -171,43 +157,19 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg, cflags |= CRYPTO_SKCIPHER_REQ_CONT; } - if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) { - /* AIO operation */ - sock_hold(sk); - areq->iocb = msg->msg_iocb; + skcipher_request_set_callback(&areq->cra_u.skcipher_req, + cflags | + CRYPTO_TFM_REQ_MAY_SLEEP | + CRYPTO_TFM_REQ_MAY_BACKLOG, + crypto_req_done, &ctx->wait); + err = crypto_wait_req(ctx->enc ? + crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) : + crypto_skcipher_decrypt(&areq->cra_u.skcipher_req), + &ctx->wait); - /* Remember output size that will be generated. */ - areq->outlen = len; - - skcipher_request_set_callback(&areq->cra_u.skcipher_req, - cflags | - CRYPTO_TFM_REQ_MAY_SLEEP, - algif_skcipher_done, areq); - err = ctx->enc ? - crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) : - crypto_skcipher_decrypt(&areq->cra_u.skcipher_req); - - /* AIO operation in progress */ - if (err == -EINPROGRESS) - return -EIOCBQUEUED; - - sock_put(sk); - } else { - /* Synchronous operation */ - skcipher_request_set_callback(&areq->cra_u.skcipher_req, - cflags | - CRYPTO_TFM_REQ_MAY_SLEEP | - CRYPTO_TFM_REQ_MAY_BACKLOG, - crypto_req_done, &ctx->wait); - err = crypto_wait_req(ctx->enc ? - crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) : - crypto_skcipher_decrypt(&areq->cra_u.skcipher_req), - &ctx->wait); - - if (!err) - err = algif_skcipher_export( - sk, &areq->cra_u.skcipher_req); - } + if (!err) + err = algif_skcipher_export( + sk, &areq->cra_u.skcipher_req); free: af_alg_free_resources(areq); diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h index 0cc8fa749f68..62867daca47d 100644 --- a/include/crypto/if_alg.h +++ b/include/crypto/if_alg.h @@ -80,7 +80,6 @@ struct af_alg_rsgl { /** * struct af_alg_async_req - definition of crypto request - * @iocb: IOCB for AIO operations * @sk: Socket the request is associated with * @first_rsgl: First RX SG * @last_rsgl: Pointer to last RX SG @@ -92,7 +91,6 @@ struct af_alg_rsgl { * @cra_u: Cipher request */ struct af_alg_async_req { - struct kiocb *iocb; struct sock *sk; struct af_alg_rsgl first_rsgl; @@ -138,7 +136,7 @@ struct af_alg_async_req { * @write: True if we are in the middle of a write. * @init: True if metadata has been sent. * @len: Length of memory allocated for this data structure. - * @inflight: Non-zero when AIO requests are in flight. + * @inflight: Non-zero when requests are in flight, for debugging only. */ struct af_alg_ctx { struct list_head tsgl_list; @@ -237,7 +235,6 @@ int af_alg_wait_for_data(struct sock *sk, unsigned flags, unsigned min); int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size, unsigned int ivsize); void af_alg_free_resources(struct af_alg_async_req *areq); -void af_alg_async_cb(void *data, int err); __poll_t af_alg_poll(struct file *file, struct socket *sock, poll_table *wait); struct af_alg_async_req *af_alg_alloc_areq(struct sock *sk, diff --git a/include/linux/socket.h b/include/linux/socket.h index ec4a0a025793..3ffdfe184b23 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -89,7 +89,6 @@ struct msghdr { bool msg_get_inq : 1;/* return INQ after receive */ unsigned int msg_flags; /* flags on received message */ __kernel_size_t msg_controllen; /* ancillary data buffer length */ - struct kiocb *msg_iocb; /* ptr to iocb for async requests */ struct ubuf_info *msg_ubuf; int (*sg_from_iter)(struct sk_buff *skb, struct iov_iter *from, size_t length); diff --git a/io_uring/net.c b/io_uring/net.c index 30cd22c0b934..22100933966a 100644 --- a/io_uring/net.c +++ b/io_uring/net.c @@ -771,7 +771,6 @@ static int io_recvmsg_prep_setup(struct io_kiocb *req) kmsg->msg.msg_control = NULL; kmsg->msg.msg_get_inq = 1; kmsg->msg.msg_controllen = 0; - kmsg->msg.msg_iocb = NULL; kmsg->msg.msg_ubuf = NULL; if (req->flags & REQ_F_BUFFER_SELECT) diff --git a/net/compat.c b/net/compat.c index 2c9bd0edac99..d68cf9c3aad5 100644 --- a/net/compat.c +++ b/net/compat.c @@ -75,7 +75,6 @@ int __get_compat_msghdr(struct msghdr *kmsg, if (msg->msg_iovlen > UIO_MAXIOV) return -EMSGSIZE; - kmsg->msg_iocb = NULL; kmsg->msg_ubuf = NULL; return 0; } diff --git a/net/socket.c b/net/socket.c index 22a412fdec07..9785363858ce 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1213,8 +1213,7 @@ static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to) { struct file *file = iocb->ki_filp; struct socket *sock = file->private_data; - struct msghdr msg = {.msg_iter = *to, - .msg_iocb = iocb}; + struct msghdr msg = {.msg_iter = *to}; ssize_t res; if (file->f_flags & O_NONBLOCK || (iocb->ki_flags & IOCB_NOWAIT)) @@ -1235,8 +1234,7 @@ static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from) { struct file *file = iocb->ki_filp; struct socket *sock = file->private_data; - struct msghdr msg = {.msg_iter = *from, - .msg_iocb = iocb}; + struct msghdr msg = {.msg_iter = *from}; ssize_t res; if (iocb->ki_pos != 0) @@ -2612,7 +2610,6 @@ int __copy_msghdr(struct msghdr *kmsg, if (msg->msg_iovlen > UIO_MAXIOV) return -EMSGSIZE; - kmsg->msg_iocb = NULL; kmsg->msg_ubuf = NULL; return 0; } diff --git a/tools/perf/trace/beauty/include/linux/socket.h b/tools/perf/trace/beauty/include/linux/socket.h index ec715ad4bf25..2a0a50fd66f4 100644 --- a/tools/perf/trace/beauty/include/linux/socket.h +++ b/tools/perf/trace/beauty/include/linux/socket.h @@ -89,7 +89,6 @@ struct msghdr { bool msg_get_inq : 1;/* return INQ after receive */ unsigned int msg_flags; /* flags on received message */ __kernel_size_t msg_controllen; /* ancillary data buffer length */ - struct kiocb *msg_iocb; /* ptr to iocb for async requests */ struct ubuf_info *msg_ubuf; int (*sg_from_iter)(struct sk_buff *skb, struct iov_iter *from, size_t length); From 7524070f26d8d347c26787dc297fb844baa26abf Mon Sep 17 00:00:00 2001 From: Demi Marie Obenour Date: Sat, 23 May 2026 15:43:03 -0400 Subject: [PATCH 167/196] crypto: af_alg - Drop support for off-CPU cryptography AF_ALG is deprecated and exposed to unprivileged userspace. Only use the least buggy algorithm implementations: the pure software ones. This removes one of the main advantages of AF_ALG, which is the ability to use it with off-CPU accelerators. However, using off-CPU accelerators has huge overheads, both in performance and attack surface. I have yet to see real-world, performance-critical workloads where using an accelerator via AF_ALG is actually a win over doing cryptography in userspace. If using an off-CPU accelerator really does turn out to be a win, a new API should be developed that is actually a good fit for it. Signed-off-by: Demi Marie Obenour Signed-off-by: Herbert Xu --- Documentation/crypto/userspace-if.rst | 7 ++++++- crypto/af_alg.c | 2 +- crypto/algif_aead.c | 4 ++-- crypto/algif_hash.c | 4 ++-- crypto/algif_rng.c | 4 ++-- crypto/algif_skcipher.c | 4 ++-- include/crypto/if_alg.h | 14 +++++++++++++- 7 files changed, 28 insertions(+), 11 deletions(-) diff --git a/Documentation/crypto/userspace-if.rst b/Documentation/crypto/userspace-if.rst index ea1b1b3f4049..b31117d4415d 100644 --- a/Documentation/crypto/userspace-if.rst +++ b/Documentation/crypto/userspace-if.rst @@ -9,7 +9,8 @@ symmetric cipher, AEAD, and RNG algorithms that are implemented in kernel-mode code. AF_ALG is insecure and is deprecated. Originally added to the kernel in 2010, -most kernel developers now consider it to be a mistake. +most kernel developers now consider it to be a mistake. Support for hardware +accelerators, which was the original purpose of AF_ALG, has been removed. AF_ALG continues to be supported only for backwards compatibility. On systems where no programs using AF_ALG remain, the support for it should be disabled by @@ -59,6 +60,10 @@ Some of the examples include: - CVE-2013-7421 - CVE-2011-4081 +Hardware accelerator drivers are frequently buggy. To reduce attack surface, +AF_ALG now only provides access to algorithms implemented in software. This +means that AF_ALG no longer fulfills its original purpose. + It is recommended that, whenever possible, userspace programs be migrated to userspace crypto code (which again, is what is normally used anyway) and ``CONFIG_CRYPTO_USER_API_*`` be disabled. On systems that use SELinux, SELinux diff --git a/crypto/af_alg.c b/crypto/af_alg.c index 8ccf7a737cd6..cce000e8590e 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -181,7 +181,7 @@ static int alg_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int add if (IS_ERR(type)) return PTR_ERR(type); - private = type->bind(sa->salg_name, sa->salg_feat, sa->salg_mask); + private = type->bind(sa->salg_name); if (IS_ERR(private)) { module_put(type->owner); return PTR_ERR(private); diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c index 60f06597cb0b..787aac8aeb24 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c @@ -342,9 +342,9 @@ static struct proto_ops algif_aead_ops_nokey = { .poll = af_alg_poll, }; -static void *aead_bind(const char *name, u32 type, u32 mask) +static void *aead_bind(const char *name) { - return crypto_alloc_aead(name, type, mask); + return crypto_alloc_aead(name, 0, AF_ALG_CRYPTOAPI_MASK); } static void aead_release(void *private) diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c index 4d3dfc60a16a..5452ad6c1506 100644 --- a/crypto/algif_hash.c +++ b/crypto/algif_hash.c @@ -380,9 +380,9 @@ static struct proto_ops algif_hash_ops_nokey = { .accept = hash_accept_nokey, }; -static void *hash_bind(const char *name, u32 type, u32 mask) +static void *hash_bind(const char *name) { - return crypto_alloc_ahash(name, type, mask); + return crypto_alloc_ahash(name, 0, AF_ALG_CRYPTOAPI_MASK); } static void hash_release(void *private) diff --git a/crypto/algif_rng.c b/crypto/algif_rng.c index a9fb492e929a..4dfe7899f8fa 100644 --- a/crypto/algif_rng.c +++ b/crypto/algif_rng.c @@ -197,7 +197,7 @@ static struct proto_ops __maybe_unused algif_rng_test_ops = { .sendmsg = rng_test_sendmsg, }; -static void *rng_bind(const char *name, u32 type, u32 mask) +static void *rng_bind(const char *name) { struct rng_parent_ctx *pctx; struct crypto_rng *rng; @@ -206,7 +206,7 @@ static void *rng_bind(const char *name, u32 type, u32 mask) if (!pctx) return ERR_PTR(-ENOMEM); - rng = crypto_alloc_rng(name, type, mask); + rng = crypto_alloc_rng(name, 0, AF_ALG_CRYPTOAPI_MASK); if (IS_ERR(rng)) { kfree(pctx); return ERR_CAST(rng); diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index 9dbccabd87b1..df20bdfe1f1f 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -307,9 +307,9 @@ static struct proto_ops algif_skcipher_ops_nokey = { .poll = af_alg_poll, }; -static void *skcipher_bind(const char *name, u32 type, u32 mask) +static void *skcipher_bind(const char *name) { - return crypto_alloc_skcipher(name, type, mask); + return crypto_alloc_skcipher(name, 0, AF_ALG_CRYPTOAPI_MASK); } static void skcipher_release(void *private) diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h index 62867daca47d..7643ba954125 100644 --- a/include/crypto/if_alg.h +++ b/include/crypto/if_alg.h @@ -41,7 +41,7 @@ struct af_alg_control { }; struct af_alg_type { - void *(*bind)(const char *name, u32 type, u32 mask); + void *(*bind)(const char *name); void (*release)(void *private); int (*setkey)(void *private, const u8 *key, unsigned int keylen); int (*setentropy)(void *private, sockptr_t entropy, unsigned int len); @@ -243,4 +243,16 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags, struct af_alg_async_req *areq, size_t maxsize, size_t *outlen); +/* + * Mask used to disable unsupported algorithm implementations. + * + * This is the same as FSCRYPT_CRYPTOAPI_MASK in fs/crypto/fscrypt_private.h. + * In additions to the motivations there, this API is exposed to userspace + * that might not be fully trusted. + */ +#define AF_ALG_CRYPTOAPI_MASK \ + (CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY | \ + CRYPTO_ALG_KERN_DRIVER_ONLY) + + #endif /* _CRYPTO_IF_ALG_H */ From 5624ea54f3ba5c83d2e5503411a31a8be0278c1e Mon Sep 17 00:00:00 2001 From: Demi Marie Obenour Date: Sat, 23 May 2026 15:43:04 -0400 Subject: [PATCH 168/196] crypto: af_alg - Document that it is *always* slower Without support for zero-copy or off-CPU offloads, AF_ALG is always slower than software cryptography. Its only advantage is that it might save code size. However, this is largely mitigated by lightweight userspace cryptographic libraries. Signed-off-by: Demi Marie Obenour Signed-off-by: Herbert Xu --- Documentation/crypto/userspace-if.rst | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/Documentation/crypto/userspace-if.rst b/Documentation/crypto/userspace-if.rst index b31117d4415d..ab93300c8e04 100644 --- a/Documentation/crypto/userspace-if.rst +++ b/Documentation/crypto/userspace-if.rst @@ -28,8 +28,8 @@ functionality than that. It actually provides access to all software algorithms. This includes arbitrary compositions of different algorithms created via a complex template system, as well as algorithms that only make sense as internal -implementation details of other algorithms. It also includes full zero-copy -support, which is difficult for the kernel to implement securely. +implementation details of other algorithms. In the past, it also included full +zero-copy support, which was difficult for the kernel to implement securely. Ultimately, these algorithms are just math computations. They use the same instructions that userspace programs already have access to, just accessed in a @@ -38,6 +38,21 @@ much more convoluted and less efficient way. Indeed, userspace code is nearly always what is being used anyway. These same algorithms are widely implemented in userspace crypto libraries. +Even when zero-copy and off-CPU accelerators were supported, AF_ALG was usually +much slower than optimized software cryptography in userspace. This was +especially true for the small message sizes usually seen in performance-critical +workloads. While it was possible to demonstrate performance wins for hashing +large files on embedded devices, it is hard to imagine a situation where this +would be performance-critical. + +Nowadays, AF_ALG no longer supports zero-copy or off-CPU accelerators. +Therefore, it is *always* slower than an optimized userspace implementation, +even for large messages. The only possible advantage left is that it avoids +duplicating code between kernel and userspace. However, userspace +implementations, especially hardware-accelerated ones, do not need to be large. +Just because OpenSSL is huge does not mean that all userspace cryptography +libraries are. + Meanwhile, AF_ALG hasn't been withstanding modern vulnerability discovery tools such as syzbot and large language models. It receives a steady stream of CVEs. Some of the examples include: From 214f94e56423f4097bb62692fe63d217d02a443d Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Thu, 21 May 2026 12:36:20 +0000 Subject: [PATCH 169/196] dt-bindings: crypto: qcom,prng: Document Hawi TRNG Hawi SoC has the True Random Number Generator (TRNG) which is compatible with the baseline IP "qcom,trng". Hence, document the compatible as such. Signed-off-by: Manivannan Sadhasivam Reviewed-by: Konrad Dybcio Acked-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- Documentation/devicetree/bindings/crypto/qcom,prng.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/crypto/qcom,prng.yaml b/Documentation/devicetree/bindings/crypto/qcom,prng.yaml index d054cc114707..dc270c8aedf3 100644 --- a/Documentation/devicetree/bindings/crypto/qcom,prng.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom,prng.yaml @@ -18,6 +18,7 @@ properties: - items: - enum: - qcom,glymur-trng + - qcom,hawi-trng - qcom,ipq5332-trng - qcom,ipq5424-trng - qcom,ipq9574-trng From d273b258d8d582626f2270809874b94c71a27bf5 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Thu, 21 May 2026 12:36:21 +0000 Subject: [PATCH 170/196] dt-bindings: crypto: qcom,inline-crypto-engine: Document Hawi ICE The Inline Crypto Engine found in Hawi SoC is compatible with the common baseline IP 'qcom,inline-crypto-engine'. Hence, document the compatible as such. Signed-off-by: Manivannan Sadhasivam Acked-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- .../devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml index 876bf90ed96e..2a183b07b03a 100644 --- a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml @@ -14,6 +14,7 @@ properties: items: - enum: - qcom,eliza-inline-crypto-engine + - qcom,hawi-inline-crypto-engine - qcom,kaanapali-inline-crypto-engine - qcom,milos-inline-crypto-engine - qcom,qcs8300-inline-crypto-engine From 4e67f504ee9ded15e256b64f4fde150e917381d7 Mon Sep 17 00:00:00 2001 From: Sam James Date: Mon, 25 May 2026 08:56:19 +0100 Subject: [PATCH 171/196] crypto: nx - fix nx_crypto_ctx_exit argument nx_crypto_ctx_shash_exit calls nx_crypto_ctx_exit with crypto_shash_ctx(...) but crypto_shash_ctx gives a nx_crypto_ctx *, not a crypto_tfm *. Fix the type in nx_crypto_ctx_exit and drop the bogus crypto_tfm_ctx call. This fixes the following oops: BUG: Unable to handle kernel data access at 0xc0403effffffffc8 Faulting instruction address: 0xc000000000396cb4 Oops: Kernel access of bad area, sig: 11 [#15] Call Trace: nx_crypto_ctx_shash_exit+0x24/0x60 crypto_shash_exit_tfm+0x28/0x40 crypto_destroy_tfm+0x98/0x140 crypto_exit_ahash_using_shash+0x20/0x40 crypto_destroy_tfm+0x98/0x140 hash_release+0x1c/0x30 alg_sock_destruct+0x38/0x60 __sk_destruct+0x48/0x2b0 af_alg_release+0x58/0xb0 __sock_release+0x68/0x150 sock_close+0x20/0x40 __fput+0x110/0x3a0 sys_close+0x48/0xa0 system_call_exception+0x140/0x2d0 system_call_common+0xf4/0x258 .. which came from hardlink(1) opportunistically using AF_ALG. The same problem exists with nx_crypto_ctx_skcipher_exit getting a context it wasn't expecting, but apparently nobody hit that for years. Cc: Eric Biggers Cc: stable@vger.kernel.org Fixes: bfd9efddf990 ("crypto: nx - convert AES-ECB to skcipher API") Fixes: 9420e628e7d8 ("crypto: nx - Use API partial block handling") Acked-by: Breno Leitao Reviewed-by: Eric Biggers Reported-by: Calvin Buckley Tested-by: Calvin Buckley Suggested-by: Brad Spengler Signed-off-by: Sam James Signed-off-by: Herbert Xu --- drivers/crypto/nx/nx.c | 6 ++---- drivers/crypto/nx/nx.h | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/crypto/nx/nx.c b/drivers/crypto/nx/nx.c index 78135fb13f5c..1b7509e2ce44 100644 --- a/drivers/crypto/nx/nx.c +++ b/drivers/crypto/nx/nx.c @@ -714,15 +714,13 @@ int nx_crypto_ctx_aes_xcbc_init(struct crypto_shash *tfm) /** * nx_crypto_ctx_exit - destroy a crypto api context * - * @tfm: the crypto transform pointer for the context + * @nx_ctx: the crypto api context * * As crypto API contexts are destroyed, this exit hook is called to free the * memory associated with it. */ -void nx_crypto_ctx_exit(struct crypto_tfm *tfm) +void nx_crypto_ctx_exit(struct nx_crypto_ctx *nx_ctx) { - struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm); - kfree_sensitive(nx_ctx->kmem); nx_ctx->csbcpb = NULL; nx_ctx->csbcpb_aead = NULL; diff --git a/drivers/crypto/nx/nx.h b/drivers/crypto/nx/nx.h index 36974f08490a..6dfabfbf8192 100644 --- a/drivers/crypto/nx/nx.h +++ b/drivers/crypto/nx/nx.h @@ -153,7 +153,7 @@ int nx_crypto_ctx_aes_ctr_init(struct crypto_skcipher *tfm); int nx_crypto_ctx_aes_cbc_init(struct crypto_skcipher *tfm); int nx_crypto_ctx_aes_ecb_init(struct crypto_skcipher *tfm); int nx_crypto_ctx_sha_init(struct crypto_shash *tfm); -void nx_crypto_ctx_exit(struct crypto_tfm *tfm); +void nx_crypto_ctx_exit(struct nx_crypto_ctx *nx_ctx); void nx_crypto_ctx_skcipher_exit(struct crypto_skcipher *tfm); void nx_crypto_ctx_aead_exit(struct crypto_aead *tfm); void nx_crypto_ctx_shash_exit(struct crypto_shash *tfm); From ed459fe319376e876de433d12b6c6772e612ca36 Mon Sep 17 00:00:00 2001 From: Ruijie Li Date: Mon, 25 May 2026 19:45:21 +0800 Subject: [PATCH 172/196] crypto: pcrypt - restore callback for non-parallel fallback pcrypt installs pcrypt_aead_done() on the child AEAD request before trying to submit it through padata. If padata_do_parallel() returns -EBUSY, pcrypt falls back to calling the child AEAD directly. That fallback must not keep the padata completion callback. Otherwise an asynchronous completion runs pcrypt_aead_done() even though the request was never enrolled in padata. Restore the original request callback and callback data before calling the child AEAD directly. This keeps the fallback path aligned with a direct AEAD request while leaving the parallel path unchanged. Fixes: 662f2f13e66d ("crypto: pcrypt - Call crypto layer directly when padata_do_parallel() return -EBUSY") Cc: stable@kernel.org Reported-by: Yuan Tan Reported-by: Yifan Wu Reported-by: Juefei Pu Reported-by: Zhengchuan Liang Reported-by: Xin Liu Assisted-by: Codex:gpt-5.4 Signed-off-by: Ruijie Li Signed-off-by: Ren Wei Signed-off-by: Herbert Xu --- crypto/pcrypt.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c index ed0feaba2383..9f372442981e 100644 --- a/crypto/pcrypt.c +++ b/crypto/pcrypt.c @@ -122,6 +122,8 @@ static int pcrypt_aead_encrypt(struct aead_request *req) return -EINPROGRESS; if (err == -EBUSY) { /* try non-parallel mode */ + aead_request_set_callback(creq, flags, req->base.complete, + req->base.data); return crypto_aead_encrypt(creq); } @@ -173,6 +175,8 @@ static int pcrypt_aead_decrypt(struct aead_request *req) return -EINPROGRESS; if (err == -EBUSY) { /* try non-parallel mode */ + aead_request_set_callback(creq, flags, req->base.complete, + req->base.data); return crypto_aead_decrypt(creq); } From fb98254a5eb9c5ddd22e9bffdd8ae709769bee9f Mon Sep 17 00:00:00 2001 From: Junyuan Wang Date: Tue, 26 May 2026 09:28:39 +0000 Subject: [PATCH 173/196] crypto: qat - add KPT support for GEN6 devices Add support for Intel Key Protection Technology (KPT) on QAT GEN6 devices. KPT protects private keys from exposure by keeping them wrapped (encrypted) while in use, in-flight, and at rest. Keys remain in wrapped form and are not exposed in plaintext in host memory. This feature operates outside of the Linux crypto framework and kernel keyring. Extend the firmware admin interface to enable and configure KPT. During device initialisation, if KPT is enabled, the driver sends an admin message to firmware to enable KPT mode and configure parameters such as the maximum number of SWK (Symmetric Wrapping Key) slots and the SWK time-to-live (TTL). Expose KPT configuration via a new sysfs attribute group, "qat_kpt", and add ABI documentation. Co-developed-by: Nitesh Venkatesh Signed-off-by: Nitesh Venkatesh Signed-off-by: Junyuan Wang Reviewed-by: Giovanni Cabiddu Reviewed-by: Ahsan Atta Signed-off-by: Herbert Xu --- .../ABI/testing/sysfs-driver-qat_kpt | 97 ++++++ .../intel/qat/qat_6xxx/adf_6xxx_hw_data.c | 21 +- .../intel/qat/qat_6xxx/adf_6xxx_hw_data.h | 9 + drivers/crypto/intel/qat/qat_6xxx/adf_drv.c | 6 + drivers/crypto/intel/qat/qat_common/Makefile | 2 + .../intel/qat/qat_common/adf_accel_devices.h | 2 + .../crypto/intel/qat/qat_common/adf_admin.c | 39 +++ .../crypto/intel/qat/qat_common/adf_admin.h | 2 + .../crypto/intel/qat/qat_common/adf_init.c | 8 + drivers/crypto/intel/qat/qat_common/adf_kpt.c | 56 ++++ drivers/crypto/intel/qat/qat_common/adf_kpt.h | 29 ++ .../intel/qat/qat_common/adf_sysfs_kpt.c | 296 ++++++++++++++++++ .../intel/qat/qat_common/adf_sysfs_kpt.h | 10 + .../qat/qat_common/icp_qat_fw_init_admin.h | 8 + .../crypto/intel/qat/qat_common/icp_qat_hw.h | 3 +- 15 files changed, 586 insertions(+), 2 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-driver-qat_kpt create mode 100644 drivers/crypto/intel/qat/qat_common/adf_kpt.c create mode 100644 drivers/crypto/intel/qat/qat_common/adf_kpt.h create mode 100644 drivers/crypto/intel/qat/qat_common/adf_sysfs_kpt.c create mode 100644 drivers/crypto/intel/qat/qat_common/adf_sysfs_kpt.h diff --git a/Documentation/ABI/testing/sysfs-driver-qat_kpt b/Documentation/ABI/testing/sysfs-driver-qat_kpt new file mode 100644 index 000000000000..c6480ea1fa4f --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-qat_kpt @@ -0,0 +1,97 @@ +What: /sys/bus/pci/devices//qat_kpt/ +Date: August 2026 +KernelVersion: 7.2 +Contact: qat-linux@intel.com +Description: + Directory containing attributes related to the QAT Key Protection + Technology (KPT) feature. KPT allows cryptographic keys to be used + by the accelerator without being exposed in plaintext to the host. + +What: /sys/bus/pci/devices//qat_kpt/enable +Date: August 2026 +KernelVersion: 7.2 +Contact: qat-linux@intel.com +Description: + (RW) Enables or disables Key Protection Technology (KPT). + + Write 1 to enable KPT, or 0 to disable it. + + Example usage:: + + # cat /sys/bus/pci/devices//qat_kpt/enable + 0 + # echo 1 > /sys/bus/pci/devices//qat_kpt/enable + + This attribute is only available on devices that support KPT. + +What: /sys/bus/pci/devices//qat_kpt/swk_cnt_per_fn +Date: August 2026 +KernelVersion: 7.2 +Contact: qat-linux@intel.com +Description: + (RW) Configures the maximum number of KPT symmetric wrapping keys + (SWKs) that a Virtual Function (VF) may be associated with. + + Valid values range from 0 to 128. A value of 0 indicates no limit. + + Example usage:: + + # cat /sys/bus/pci/devices//qat_kpt/swk_cnt_per_fn + 128 + # echo 128 > /sys/bus/pci/devices//qat_kpt/swk_cnt_per_fn + + This attribute is only available on devices that support KPT. + +What: /sys/bus/pci/devices//qat_kpt/swk_cnt_per_pasid +Date: August 2026 +KernelVersion: 7.2 +Contact: qat-linux@intel.com +Description: + (RW) Configures the maximum number of KPT symmetric wrapping keys + (SWKs) per Process Address Space ID (PASID). + + Valid values range from 0 to 128. A value of 0 indicates no limit. + + Example usage:: + + # cat /sys/bus/pci/devices//qat_kpt/swk_cnt_per_pasid + 128 + # echo 128 > /sys/bus/pci/devices//qat_kpt/swk_cnt_per_pasid + + This attribute is only available on devices that support KPT. + +What: /sys/bus/pci/devices//qat_kpt/swk_max_ttl +Date: August 2026 +KernelVersion: 7.2 +Contact: qat-linux@intel.com +Description: + (RW) Configures the maximum Time To Live (TTL) for KPT symmetric + wrapping keys (SWK). + + Valid values range from 0 to 31536000 seconds. A value of 0 + indicates that the SWK TTL is unlimited. + + Example usage:: + + # cat /sys/bus/pci/devices//qat_kpt/swk_max_ttl + 1000 + # echo 1000 > /sys/bus/pci/devices//qat_kpt/swk_max_ttl + + This attribute is only available on devices that support KPT. + +What: /sys/bus/pci/devices//qat_kpt/swk_shared +Date: August 2026 +KernelVersion: 7.2 +Contact: qat-linux@intel.com +Description: + (RW) Controls shared mode for KPT symmetric wrapping keys (SWK). + + Write 1 to enable shared mode, or 0 to disable it (non-shared mode). + + Example usage:: + + # cat /sys/bus/pci/devices//qat_kpt/swk_shared + 0 + # echo 1 > /sys/bus/pci/devices//qat_kpt/swk_shared + + This attribute is only available on devices that support KPT. diff --git a/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.c b/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.c index 205680797e2c..388087e64540 100644 --- a/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.c +++ b/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.c @@ -752,10 +752,12 @@ static u32 get_accel_cap(struct adf_accel_dev *accel_dev) unsigned long mask; u32 caps = 0; u32 fusectl1; + u32 fusectl0; if (adf_6xxx_is_wcy(GET_HW_DATA(accel_dev))) return get_accel_cap_wcy(accel_dev); + fusectl0 = GET_HW_DATA(accel_dev)->fuses[ADF_FUSECTL0]; fusectl1 = GET_HW_DATA(accel_dev)->fuses[ADF_FUSECTL1]; /* Read accelerator capabilities mask */ @@ -785,7 +787,8 @@ static u32 get_accel_cap(struct adf_accel_dev *accel_dev) capabilities_asym = ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC | ICP_ACCEL_CAPABILITIES_SM2 | - ICP_ACCEL_CAPABILITIES_ECEDMONT; + ICP_ACCEL_CAPABILITIES_ECEDMONT | + ICP_ACCEL_CAPABILITIES_KPT; if (fusectl1 & ICP_ACCEL_GEN6_MASK_PKE_SLICE) { capabilities_asym &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; @@ -793,6 +796,9 @@ static u32 get_accel_cap(struct adf_accel_dev *accel_dev) capabilities_asym &= ~ICP_ACCEL_CAPABILITIES_ECEDMONT; } + if (fusectl0 & ADF_GEN6_KPT_FUSE_BIT) + capabilities_asym &= ~ICP_ACCEL_CAPABILITIES_KPT; + capabilities_dc = ICP_ACCEL_CAPABILITIES_COMPRESSION | ICP_ACCEL_CAPABILITIES_LZ4_COMPRESSION | ICP_ACCEL_CAPABILITIES_LZ4S_COMPRESSION | @@ -960,6 +966,18 @@ static int dev_config(struct adf_accel_dev *accel_dev) return ret; } +static void adf_gen6_init_kpt(struct adf_kpt_hw_data *kpt_data) +{ + kpt_data->max_swk_cnt_per_fn_pasid = ADF_6XXX_KPT_MAX_SWK_COUNT_PER_FNPASID; + kpt_data->max_swk_ttl = ADF_6XXX_KPT_MAX_SWK_TTL; + + kpt_data->user_input.enable = false; + kpt_data->user_input.swk_shared = ADF_6XXX_KPT_DEFAULT_SWK_SHARED_MODE; + kpt_data->user_input.swk_max_ttl = ADF_6XXX_KPT_DEFAULT_SWK_TTL; + kpt_data->user_input.swk_cnt_per_fn = ADF_6XXX_KPT_DEFAULT_SWK_CNT_PER_FN; + kpt_data->user_input.swk_cnt_per_pasid = ADF_6XXX_KPT_DEFAULT_SWK_CNT_PER_PASID; +} + static void adf_gen6_init_rl_data(struct adf_rl_hw_data *rl_data) { rl_data->pciout_tb_offset = ADF_GEN6_RL_TOKEN_PCIEOUT_BUCKET_OFFSET; @@ -1057,6 +1075,7 @@ void adf_init_hw_data_6xxx(struct adf_hw_device_data *hw_data) adf_gen6_init_tl_data(&hw_data->tl_data); adf_gen6_init_rl_data(&hw_data->rl_data); adf_gen6_init_anti_rb(&hw_data->anti_rb_data); + adf_gen6_init_kpt(&hw_data->kpt_data); } void adf_clean_hw_data_6xxx(struct adf_hw_device_data *hw_data) diff --git a/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.h b/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.h index e4d433bdd379..2719ddbc1e05 100644 --- a/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.h +++ b/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.h @@ -58,6 +58,7 @@ /* Fuse bits */ #define ADF_GEN6_ANTI_RB_FUSE_BIT BIT(24) +#define ADF_GEN6_KPT_FUSE_BIT BIT(16) /* * Watchdog timers @@ -164,6 +165,14 @@ /* Clock frequency */ #define ADF_6XXX_AE_FREQ (1000 * HZ_PER_MHZ) +/* KPT */ +#define ADF_6XXX_KPT_MAX_SWK_COUNT_PER_FNPASID 128 +#define ADF_6XXX_KPT_MAX_SWK_TTL 31536000 +#define ADF_6XXX_KPT_DEFAULT_SWK_SHARED_MODE 1 +#define ADF_6XXX_KPT_DEFAULT_SWK_TTL 0 +#define ADF_6XXX_KPT_DEFAULT_SWK_CNT_PER_FN 0 +#define ADF_6XXX_KPT_DEFAULT_SWK_CNT_PER_PASID 0 + enum icp_qat_gen6_slice_mask { ICP_ACCEL_GEN6_MASK_UCS_SLICE = BIT(0), ICP_ACCEL_GEN6_MASK_AUTH_SLICE = BIT(1), diff --git a/drivers/crypto/intel/qat/qat_6xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_6xxx/adf_drv.c index ab62b91ecb51..319b4251ad46 100644 --- a/drivers/crypto/intel/qat/qat_6xxx/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_6xxx/adf_drv.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "adf_gen6_shared.h" #include "adf_6xxx_hw_data.h" @@ -217,6 +218,11 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return ret; ret = adf_sysfs_init(accel_dev); + if (ret) + return ret; + + if (!(hw_data->fuses[ADF_FUSECTL0] & ADF_GEN6_KPT_FUSE_BIT)) + ret = adf_sysfs_init_kpt(accel_dev); return ret; } diff --git a/drivers/crypto/intel/qat/qat_common/Makefile b/drivers/crypto/intel/qat/qat_common/Makefile index 2b1649001518..306ec71bb6fa 100644 --- a/drivers/crypto/intel/qat/qat_common/Makefile +++ b/drivers/crypto/intel/qat/qat_common/Makefile @@ -25,12 +25,14 @@ intel_qat-y := adf_accel_engine.o \ adf_hw_arbiter.o \ adf_init.o \ adf_isr.o \ + adf_kpt.o \ adf_module.o \ adf_mstate_mgr.o \ adf_rl_admin.o \ adf_rl.o \ adf_sysfs.o \ adf_sysfs_anti_rb.o \ + adf_sysfs_kpt.o \ adf_sysfs_ras_counters.o \ adf_sysfs_rl.o \ adf_timer.o \ diff --git a/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h b/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h index d9b2a1cf474e..f2d70641c377 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h +++ b/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h @@ -14,6 +14,7 @@ #include "adf_anti_rb.h" #include "adf_cfg_common.h" #include "adf_dc.h" +#include "adf_kpt.h" #include "adf_rl.h" #include "adf_telemetry.h" #include "adf_pfvf_msg.h" @@ -335,6 +336,7 @@ struct adf_hw_device_data { struct adf_rl_hw_data rl_data; struct adf_tl_hw_data tl_data; struct adf_anti_rb_hw_data anti_rb_data; + struct adf_kpt_hw_data kpt_data; struct qat_migdev_ops vfmig_ops; const char *fw_name; const char *fw_mmp_name; diff --git a/drivers/crypto/intel/qat/qat_common/adf_admin.c b/drivers/crypto/intel/qat/qat_common/adf_admin.c index 841aa802c79e..1eea74c2a8a5 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_admin.c +++ b/drivers/crypto/intel/qat/qat_common/adf_admin.c @@ -13,6 +13,7 @@ #include "adf_common_drv.h" #include "adf_cfg.h" #include "adf_heartbeat.h" +#include "adf_kpt.h" #include "icp_qat_fw_init_admin.h" #define ADF_ADMIN_MAILBOX_STRIDE 0x1000 @@ -606,6 +607,44 @@ int adf_send_admin_arb_commit(struct adf_accel_dev *accel_dev) return adf_send_admin_svn(accel_dev, ICP_QAT_FW_SVN_COMMIT, &resp); } +static_assert(sizeof(struct icp_qat_fw_init_admin_kpt_cfg) < PAGE_SIZE); + +static void adf_cfg_kpt_config(struct adf_accel_dev *accel_dev, + struct icp_qat_fw_init_admin_kpt_cfg *kpt_config) +{ + struct adf_kpt_interface_data *user_data = GET_KPT_USER_DATA(accel_dev); + + kpt_config->swk_cnt_per_fn = user_data->swk_cnt_per_fn; + kpt_config->swk_cnt_per_pasid = user_data->swk_cnt_per_pasid; + kpt_config->swk_ttl_in_secs = user_data->swk_max_ttl; + kpt_config->swk_shared_disable = !user_data->swk_shared; +} + +int adf_send_admin_kpt_init(struct adf_accel_dev *accel_dev, void *init_cfg, + size_t init_cfg_sz, dma_addr_t init_ptr) +{ + struct icp_qat_fw_init_admin_kpt_cfg *kpt_config = init_cfg; + u32 ae_mask = GET_HW_DATA(accel_dev)->admin_ae_mask; + struct icp_qat_fw_init_admin_resp resp = { }; + struct icp_qat_fw_init_admin_req req = { }; + int ret; + + if (!kpt_config || init_cfg_sz < sizeof(*kpt_config)) + return -EINVAL; + + adf_cfg_kpt_config(accel_dev, kpt_config); + + req.cmd_id = ICP_QAT_FW_KPT_ENABLE; + req.init_cfg_ptr = init_ptr; + req.init_cfg_sz = sizeof(*kpt_config); + + ret = adf_send_admin(accel_dev, &req, &resp, ae_mask); + if (ret) + dev_err(&GET_DEV(accel_dev), "Failed to send KPT init admin message\n"); + + return ret; +} + int adf_init_admin_comms(struct adf_accel_dev *accel_dev) { struct adf_admin_comms *admin; diff --git a/drivers/crypto/intel/qat/qat_common/adf_admin.h b/drivers/crypto/intel/qat/qat_common/adf_admin.h index 9704219f2eb7..44eb6dc92e45 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_admin.h +++ b/drivers/crypto/intel/qat/qat_common/adf_admin.h @@ -29,5 +29,7 @@ int adf_send_admin_tl_start(struct adf_accel_dev *accel_dev, int adf_send_admin_tl_stop(struct adf_accel_dev *accel_dev); int adf_send_admin_arb_query(struct adf_accel_dev *accel_dev, int cmd, u8 *svn); int adf_send_admin_arb_commit(struct adf_accel_dev *accel_dev); +int adf_send_admin_kpt_init(struct adf_accel_dev *accel_dev, void *init_cfg, + size_t init_cfg_sz, dma_addr_t init_ptr); #endif diff --git a/drivers/crypto/intel/qat/qat_common/adf_init.c b/drivers/crypto/intel/qat/qat_common/adf_init.c index 1c7f9e49914d..3e39c53814de 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_init.c +++ b/drivers/crypto/intel/qat/qat_common/adf_init.c @@ -10,6 +10,7 @@ #include "adf_dbgfs.h" #include "adf_heartbeat.h" #include "adf_rl.h" +#include "adf_kpt.h" #include "adf_sysfs_anti_rb.h" #include "adf_sysfs_ras_counters.h" #include "adf_telemetry.h" @@ -219,6 +220,13 @@ static int adf_dev_start(struct adf_accel_dev *accel_dev) return -EFAULT; } + /* Enable Key Protection Technology (KPT) */ + ret = adf_enable_kpt(accel_dev); + if (ret) { + dev_err(&GET_DEV(accel_dev), "Failed to enable KPT\n"); + return ret; + } + if (hw_data->start_timer) { ret = hw_data->start_timer(accel_dev); if (ret) { diff --git a/drivers/crypto/intel/qat/qat_common/adf_kpt.c b/drivers/crypto/intel/qat/qat_common/adf_kpt.c new file mode 100644 index 000000000000..a0430141ea0e --- /dev/null +++ b/drivers/crypto/intel/qat/qat_common/adf_kpt.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2026 Intel Corporation */ +#include + +#include "adf_admin.h" +#include "adf_cfg_services.h" +#include "adf_common_drv.h" +#include "adf_kpt.h" + +static bool adf_kpt_supported(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev); + + return hw_data->accel_capabilities_mask & ICP_ACCEL_CAPABILITIES_KPT; +} + +int adf_enable_kpt(struct adf_accel_dev *accel_dev) +{ + struct adf_kpt_interface_data *user_data = GET_KPT_USER_DATA(accel_dev); + struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev); + dma_addr_t paddr; + void *vaddr; + int ret; + int svc; + + /* Return 0 if KPT is not supported by the hardware */ + if (!adf_kpt_supported(accel_dev)) + return 0; + + if (!user_data->enable) { + /* Disable KPT capability if user has not enabled it */ + hw_data->accel_capabilities_mask &= ~ICP_ACCEL_CAPABILITIES_KPT; + return 0; + } + + svc = adf_get_service_enabled(accel_dev); + if (svc < 0) + return svc; + + if (svc != SVC_ASYM) { + dev_err(&GET_DEV(accel_dev), + "KPT can only be enabled when service is configured as 'asym'\n"); + return -EINVAL; + } + + vaddr = dma_alloc_coherent(&GET_DEV(accel_dev), PAGE_SIZE, &paddr, + GFP_KERNEL); + if (!vaddr) + return -ENOMEM; + + ret = adf_send_admin_kpt_init(accel_dev, vaddr, PAGE_SIZE, paddr); + + dma_free_coherent(&GET_DEV(accel_dev), PAGE_SIZE, vaddr, paddr); + + return ret; +} diff --git a/drivers/crypto/intel/qat/qat_common/adf_kpt.h b/drivers/crypto/intel/qat/qat_common/adf_kpt.h new file mode 100644 index 000000000000..17d07d24a319 --- /dev/null +++ b/drivers/crypto/intel/qat/qat_common/adf_kpt.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright(c) 2026 Intel Corporation */ +#ifndef ADF_KPT_H_ +#define ADF_KPT_H_ + +#include + +#define GET_KPT_CFG_DATA(accel_dev) (&(accel_dev)->hw_device->kpt_data) +#define GET_KPT_USER_DATA(accel_dev) (&(accel_dev)->hw_device->kpt_data.user_input) + +struct adf_accel_dev; + +struct adf_kpt_interface_data { + bool enable; + bool swk_shared; + unsigned int swk_cnt_per_fn; + unsigned int swk_cnt_per_pasid; + unsigned int swk_max_ttl; +}; + +struct adf_kpt_hw_data { + unsigned int max_swk_cnt_per_fn_pasid; + unsigned int max_swk_ttl; + struct adf_kpt_interface_data user_input; +}; + +int adf_enable_kpt(struct adf_accel_dev *accel_dev); + +#endif /* ADF_KPT_H_ */ diff --git a/drivers/crypto/intel/qat/qat_common/adf_sysfs_kpt.c b/drivers/crypto/intel/qat/qat_common/adf_sysfs_kpt.c new file mode 100644 index 000000000000..1f733ae80bdf --- /dev/null +++ b/drivers/crypto/intel/qat/qat_common/adf_sysfs_kpt.c @@ -0,0 +1,296 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2026 Intel Corporation */ +#include +#include + +#include "adf_cfg.h" +#include "adf_cfg_services.h" +#include "adf_common_drv.h" +#include "adf_kpt.h" +#include "adf_sysfs_kpt.h" + +static ssize_t enable_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct adf_kpt_interface_data *user_data; + struct adf_accel_dev *accel_dev; + + accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); + if (!accel_dev) + return -EINVAL; + + user_data = GET_KPT_USER_DATA(accel_dev); + + return sysfs_emit(buf, "%d\n", user_data->enable); +} + +static ssize_t enable_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct adf_kpt_interface_data *user_data; + struct adf_hw_device_data *hw_data; + struct adf_accel_dev *accel_dev; + bool enable; + int ret; + + accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); + if (!accel_dev) + return -EINVAL; + + if (adf_dev_started(accel_dev)) { + dev_info(dev, "Device qat_dev%d must be down before enabling KPT\n", + accel_dev->accel_id); + return -EINVAL; + } + + if (adf_get_service_enabled(accel_dev) != SVC_ASYM) { + dev_info(dev, "KPT can only be enabled when the asymmetric service is enabled\n"); + return -EINVAL; + } + + hw_data = GET_HW_DATA(accel_dev); + + /* + * Restore the KPT capability bit in the device's capabilities mask + * before processing user input, as the bit may have been cleared if + * KPT was previously disabled by the user. + */ + hw_data->accel_capabilities_mask = hw_data->get_accel_cap(accel_dev); + if (!hw_data->accel_capabilities_mask) + return -EINVAL; + + ret = kstrtobool(buf, &enable); + if (ret) + return ret; + + user_data = GET_KPT_USER_DATA(accel_dev); + user_data->enable = enable; + + return count; +} +static DEVICE_ATTR_RW(enable); + +static ssize_t swk_shared_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct adf_kpt_interface_data *user_data; + struct adf_accel_dev *accel_dev; + + accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); + if (!accel_dev) + return -EINVAL; + + user_data = GET_KPT_USER_DATA(accel_dev); + + return sysfs_emit(buf, "%d\n", user_data->swk_shared); +} + +static ssize_t swk_shared_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct adf_kpt_interface_data *user_data; + struct adf_accel_dev *accel_dev; + bool swk_shared; + int ret; + + accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); + if (!accel_dev) + return -EINVAL; + + if (adf_dev_started(accel_dev)) { + dev_info(dev, "Device qat_dev%d must be down before setting swk_shared\n", + accel_dev->accel_id); + return -EINVAL; + } + + ret = kstrtobool(buf, &swk_shared); + if (ret) + return ret; + + user_data = GET_KPT_USER_DATA(accel_dev); + user_data->swk_shared = swk_shared; + + return count; +} +static DEVICE_ATTR_RW(swk_shared); + +static ssize_t swk_max_ttl_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct adf_kpt_interface_data *user_data; + struct adf_accel_dev *accel_dev; + + accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); + if (!accel_dev) + return -EINVAL; + + user_data = GET_KPT_USER_DATA(accel_dev); + + return sysfs_emit(buf, "%u\n", user_data->swk_max_ttl); +} + +static ssize_t swk_max_ttl_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct adf_kpt_hw_data *kpt_data; + struct adf_accel_dev *accel_dev; + unsigned int swk_max_ttl; + int ret; + + accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); + if (!accel_dev) + return -EINVAL; + + if (adf_dev_started(accel_dev)) { + dev_info(dev, "Device qat_dev%d must be down before setting swk_max_ttl\n", + accel_dev->accel_id); + return -EINVAL; + } + + ret = kstrtouint(buf, 10, &swk_max_ttl); + if (ret) + return ret; + + kpt_data = GET_KPT_CFG_DATA(accel_dev); + + if (swk_max_ttl > kpt_data->max_swk_ttl) { + dev_info(dev, "Configuration value is out of range (%u - %u)\n", + 0, kpt_data->max_swk_ttl); + return -EINVAL; + } + + kpt_data->user_input.swk_max_ttl = swk_max_ttl; + + return count; +} +static DEVICE_ATTR_RW(swk_max_ttl); + +static ssize_t swk_cnt_per_fn_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct adf_kpt_interface_data *user_data; + struct adf_accel_dev *accel_dev; + + accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); + if (!accel_dev) + return -EINVAL; + + user_data = GET_KPT_USER_DATA(accel_dev); + + return sysfs_emit(buf, "%u\n", user_data->swk_cnt_per_fn); +} + +static ssize_t swk_cnt_per_fn_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct adf_kpt_hw_data *kpt_data; + struct adf_accel_dev *accel_dev; + unsigned int swk_cnt_per_fn; + int ret; + + accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); + if (!accel_dev) + return -EINVAL; + + if (adf_dev_started(accel_dev)) { + dev_info(dev, "Device qat_dev%d must be down before setting swk_cnt_per_fn\n", + accel_dev->accel_id); + return -EINVAL; + } + + ret = kstrtouint(buf, 10, &swk_cnt_per_fn); + if (ret) + return ret; + + kpt_data = GET_KPT_CFG_DATA(accel_dev); + + if (swk_cnt_per_fn > kpt_data->max_swk_cnt_per_fn_pasid) { + dev_info(dev, "swk_cnt_per_fn: value out of range (0 - %u)\n", + kpt_data->max_swk_cnt_per_fn_pasid); + return -EINVAL; + } + + kpt_data->user_input.swk_cnt_per_fn = swk_cnt_per_fn; + + return count; +} +static DEVICE_ATTR_RW(swk_cnt_per_fn); + +static ssize_t swk_cnt_per_pasid_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct adf_kpt_interface_data *user_data; + struct adf_accel_dev *accel_dev; + + accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); + if (!accel_dev) + return -EINVAL; + + user_data = GET_KPT_USER_DATA(accel_dev); + + return sysfs_emit(buf, "%u\n", user_data->swk_cnt_per_pasid); +} + +static ssize_t swk_cnt_per_pasid_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct adf_kpt_hw_data *kpt_data; + struct adf_accel_dev *accel_dev; + unsigned int swk_cnt_per_pasid; + int ret; + + accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); + if (!accel_dev) + return -EINVAL; + + if (adf_dev_started(accel_dev)) { + dev_info(dev, "Device qat_dev%d must be down before setting swk_cnt_per_pasid\n", + accel_dev->accel_id); + return -EINVAL; + } + + ret = kstrtouint(buf, 10, &swk_cnt_per_pasid); + if (ret) + return ret; + + kpt_data = GET_KPT_CFG_DATA(accel_dev); + + if (swk_cnt_per_pasid > kpt_data->max_swk_cnt_per_fn_pasid) { + dev_info(dev, "swk_cnt_per_pasid: value out of range (0 - %u)\n", + kpt_data->max_swk_cnt_per_fn_pasid); + return -EINVAL; + } + + kpt_data->user_input.swk_cnt_per_pasid = swk_cnt_per_pasid; + + return count; +} +static DEVICE_ATTR_RW(swk_cnt_per_pasid); + +static struct attribute *qat_kpt_attrs[] = { + &dev_attr_enable.attr, + &dev_attr_swk_shared.attr, + &dev_attr_swk_max_ttl.attr, + &dev_attr_swk_cnt_per_fn.attr, + &dev_attr_swk_cnt_per_pasid.attr, + NULL, +}; + +static const struct attribute_group qat_kpt_group = { + .attrs = qat_kpt_attrs, + .name = "qat_kpt", +}; + +int adf_sysfs_init_kpt(struct adf_accel_dev *accel_dev) +{ + int ret; + + ret = devm_device_add_group(&GET_DEV(accel_dev), &qat_kpt_group); + if (ret) { + dev_err(&GET_DEV(accel_dev), "Failed to create qat_kpt attribute group\n"); + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(adf_sysfs_init_kpt); diff --git a/drivers/crypto/intel/qat/qat_common/adf_sysfs_kpt.h b/drivers/crypto/intel/qat/qat_common/adf_sysfs_kpt.h new file mode 100644 index 000000000000..d9d065f75114 --- /dev/null +++ b/drivers/crypto/intel/qat/qat_common/adf_sysfs_kpt.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright(c) 2026 Intel Corporation */ +#ifndef ADF_SYSFS_KPT_H_ +#define ADF_SYSFS_KPT_H_ + +struct adf_accel_dev; + +int adf_sysfs_init_kpt(struct adf_accel_dev *accel_dev); + +#endif /* ADF_SYSFS_KPT_H_ */ diff --git a/drivers/crypto/intel/qat/qat_common/icp_qat_fw_init_admin.h b/drivers/crypto/intel/qat/qat_common/icp_qat_fw_init_admin.h index 6b0f0d100cb9..95f7f514cb63 100644 --- a/drivers/crypto/intel/qat/qat_common/icp_qat_fw_init_admin.h +++ b/drivers/crypto/intel/qat/qat_common/icp_qat_fw_init_admin.h @@ -31,6 +31,7 @@ enum icp_qat_fw_init_admin_cmd_id { ICP_QAT_FW_RL_REMOVE = 136, ICP_QAT_FW_TL_START = 137, ICP_QAT_FW_TL_STOP = 138, + ICP_QAT_FW_KPT_ENABLE = 144, ICP_QAT_FW_SVN_READ = 146, ICP_QAT_FW_SVN_COMMIT = 147, }; @@ -212,4 +213,11 @@ struct icp_qat_fw_init_admin_pm_info { __u32 resvrd3[6]; }; +struct icp_qat_fw_init_admin_kpt_cfg { + __u32 swk_cnt_per_fn; + __u32 swk_cnt_per_pasid; + __u32 swk_ttl_in_secs; + __u32 swk_shared_disable; +}; + #endif diff --git a/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h b/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h index 16ef6d98fa42..e38115d3cd75 100644 --- a/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h +++ b/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h @@ -114,7 +114,8 @@ enum icp_qat_capabilities_mask { ICP_ACCEL_CAPABILITIES_LZ4_COMPRESSION = BIT(24), ICP_ACCEL_CAPABILITIES_LZ4S_COMPRESSION = BIT(25), ICP_ACCEL_CAPABILITIES_AES_V2 = BIT(26), - /* Bits 27-28 are currently reserved */ + ICP_ACCEL_CAPABILITIES_KPT = BIT(27), + /* Bit 28 is currently reserved */ ICP_ACCEL_CAPABILITIES_ZUC_256 = BIT(29), ICP_ACCEL_CAPABILITIES_WIRELESS_CRYPTO_EXT = BIT(30), }; From 265b861bece38318b8e0fc8fac0643d4ef906d31 Mon Sep 17 00:00:00 2001 From: Xiaonan Zhao Date: Tue, 26 May 2026 18:11:43 +0800 Subject: [PATCH 174/196] crypto: chacha20poly1305 - validate poly1305 template argument chachapoly_create() still accepts the compatibility poly1305 parameter in the template name, but it assumes the second template argument is always present and immediately passes it to strcmp(). When the argument is missing, crypto_attr_alg_name() returns an error pointer. Check for that before comparing the name so malformed template instantiations fail with an error instead of dereferencing the error pointer in strcmp(). This matches the surrounding Crypto API template pattern where crypto_attr_alg_name() results are validated before string-specific use. Fixes: a298765e28ad ("crypto: chacha20poly1305 - Use lib/crypto poly1305") Cc: stable@kernel.org Reported-by: Yuan Tan Reported-by: Zhengchuan Liang Reported-by: Xin Liu Co-developed-by: Luxing Yin Signed-off-by: Luxing Yin Signed-off-by: Xiaonan Zhao Signed-off-by: Ren Wei Signed-off-by: Herbert Xu --- crypto/chacha20poly1305.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/crypto/chacha20poly1305.c b/crypto/chacha20poly1305.c index b4b5a7198d84..27df9e1eb058 100644 --- a/crypto/chacha20poly1305.c +++ b/crypto/chacha20poly1305.c @@ -375,6 +375,7 @@ static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb, struct aead_instance *inst; struct chachapoly_instance_ctx *ctx; struct skcipher_alg_common *chacha; + const char *poly_name; int err; if (ivsize > CHACHAPOLY_IV_SIZE) @@ -396,9 +397,15 @@ static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb, goto err_free_inst; chacha = crypto_spawn_skcipher_alg_common(&ctx->chacha); + poly_name = crypto_attr_alg_name(tb[2]); + if (IS_ERR(poly_name)) { + err = PTR_ERR(poly_name); + goto err_free_inst; + } + err = -EINVAL; - if (strcmp(crypto_attr_alg_name(tb[2]), "poly1305") && - strcmp(crypto_attr_alg_name(tb[2]), "poly1305-generic")) + if (strcmp(poly_name, "poly1305") && + strcmp(poly_name, "poly1305-generic")) goto err_free_inst; /* Need 16-byte IV size, including Initial Block Counter value */ if (chacha->ivsize != CHACHA_IV_SIZE) From b2b24a98863fee9a495c8afb602fe75b964a1a84 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Wed, 27 May 2026 16:11:47 +0200 Subject: [PATCH 175/196] crypto: powerpc/aes - use min in ppc_{ecb,cbc,ctr,xts}_crypt Replace min_t() with the simpler min() macro since the values are unsigned and compatible. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- arch/powerpc/crypto/aes-spe-glue.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/crypto/aes-spe-glue.c b/arch/powerpc/crypto/aes-spe-glue.c index 7d2827e65240..e038488087e6 100644 --- a/arch/powerpc/crypto/aes-spe-glue.c +++ b/arch/powerpc/crypto/aes-spe-glue.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -140,7 +141,7 @@ static int ppc_ecb_crypt(struct skcipher_request *req, bool enc) err = skcipher_walk_virt(&walk, req, false); while ((nbytes = walk.nbytes) != 0) { - nbytes = min_t(unsigned int, nbytes, MAX_BYTES); + nbytes = min(nbytes, MAX_BYTES); nbytes = round_down(nbytes, AES_BLOCK_SIZE); spe_begin(); @@ -179,7 +180,7 @@ static int ppc_cbc_crypt(struct skcipher_request *req, bool enc) err = skcipher_walk_virt(&walk, req, false); while ((nbytes = walk.nbytes) != 0) { - nbytes = min_t(unsigned int, nbytes, MAX_BYTES); + nbytes = min(nbytes, MAX_BYTES); nbytes = round_down(nbytes, AES_BLOCK_SIZE); spe_begin(); @@ -220,7 +221,7 @@ static int ppc_ctr_crypt(struct skcipher_request *req) err = skcipher_walk_virt(&walk, req, false); while ((nbytes = walk.nbytes) != 0) { - nbytes = min_t(unsigned int, nbytes, MAX_BYTES); + nbytes = min(nbytes, MAX_BYTES); if (nbytes < walk.total) nbytes = round_down(nbytes, AES_BLOCK_SIZE); @@ -248,7 +249,7 @@ static int ppc_xts_crypt(struct skcipher_request *req, bool enc) twk = ctx->key_twk; while ((nbytes = walk.nbytes) != 0) { - nbytes = min_t(unsigned int, nbytes, MAX_BYTES); + nbytes = min(nbytes, MAX_BYTES); nbytes = round_down(nbytes, AES_BLOCK_SIZE); spe_begin(); From 79bbe453e5bfa6e1c6aa2e8329bfc8f152b81c9b Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Wed, 27 May 2026 19:46:55 +0200 Subject: [PATCH 176/196] crypto: qat - simplify adf_service_mask_to_string helper Use a single scnprintf() for each set bit and drop the offset in the else branch to simplify adf_service_mask_to_string(). Signed-off-by: Thorsten Blum Acked-by: Giovanni Cabiddu Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/adf_cfg_services.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg_services.c b/drivers/crypto/intel/qat/qat_common/adf_cfg_services.c index 7d00bcb41ce7..1af6da8b263f 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_cfg_services.c +++ b/drivers/crypto/intel/qat/qat_common/adf_cfg_services.c @@ -94,10 +94,9 @@ static int adf_service_mask_to_string(unsigned long mask, char *buf, size_t len) for_each_set_bit(bit, &mask, SVC_COUNT) { if (offset) offset += scnprintf(buf + offset, len - offset, - ADF_SERVICES_DELIMITER); - - offset += scnprintf(buf + offset, len - offset, "%s", - adf_cfg_services[bit]); + ADF_SERVICES_DELIMITER "%s", adf_cfg_services[bit]); + else + offset += scnprintf(buf, len, "%s", adf_cfg_services[bit]); } return 0; From b3ac78756588059729b9195fcc9f4b37d54057a5 Mon Sep 17 00:00:00 2001 From: Giovanni Cabiddu Date: Thu, 28 May 2026 16:57:44 +0100 Subject: [PATCH 177/196] crypto: qat - validate RSA CRT component lengths The generic RSA key parser (rsa_helper.c) bounds each CRT component (p, q, dp, dq, qinv) by the modulus size n_sz, but qat_rsa_setkey_crt() allocates half-size DMA buffers (key_sz / 2) and right-aligns each component with: memcpy(dst + half_key_sz - len, src, len) When a CRT component is larger than half_key_sz the subtraction underflows and memcpy writes past the DMA buffer, causing memory corruption. Add a len > half_key_sz check next to the existing !len check for each of the five CRT components so the driver falls back to the non-CRT path instead of writing out of bounds. Fixes: 879f77e9071f ("crypto: qat - Add RSA CRT mode") Cc: stable@vger.kernel.org Signed-off-by: Giovanni Cabiddu Reviewed-by: Ahsan Atta Reviewed-by: Laurent M Coquerel Tested-by: Laurent M Coquerel Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/qat_asym_algs.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c b/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c index e09b9edfce42..75c15c8e41db 100644 --- a/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c +++ b/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c @@ -1085,7 +1085,7 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key) ptr = rsa_key->p; len = rsa_key->p_sz; qat_rsa_drop_leading_zeros(&ptr, &len); - if (!len) + if (!len || len > half_key_sz) goto err; ctx->p = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_p, GFP_KERNEL); if (!ctx->p) @@ -1096,7 +1096,7 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key) ptr = rsa_key->q; len = rsa_key->q_sz; qat_rsa_drop_leading_zeros(&ptr, &len); - if (!len) + if (!len || len > half_key_sz) goto free_p; ctx->q = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_q, GFP_KERNEL); if (!ctx->q) @@ -1107,7 +1107,7 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key) ptr = rsa_key->dp; len = rsa_key->dp_sz; qat_rsa_drop_leading_zeros(&ptr, &len); - if (!len) + if (!len || len > half_key_sz) goto free_q; ctx->dp = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_dp, GFP_KERNEL); @@ -1119,7 +1119,7 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key) ptr = rsa_key->dq; len = rsa_key->dq_sz; qat_rsa_drop_leading_zeros(&ptr, &len); - if (!len) + if (!len || len > half_key_sz) goto free_dp; ctx->dq = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_dq, GFP_KERNEL); @@ -1131,7 +1131,7 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key) ptr = rsa_key->qinv; len = rsa_key->qinv_sz; qat_rsa_drop_leading_zeros(&ptr, &len); - if (!len) + if (!len || len > half_key_sz) goto free_dq; ctx->qinv = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_qinv, GFP_KERNEL); From 7811ec9e973d2c9e465083699f0c8240b98cb8c4 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 29 May 2026 15:04:30 -0700 Subject: [PATCH 178/196] crypto: crypto4xx - Remove insecure and unused rng_alg Remove crypto4xx_rng, as it is insecure and unused: - It has only a 64-bit security strength, which is highly inadequate. This can be seen by the fact that crypto4xx_hw_init() seeds it with only 64 bits of entropy, and the fact that the original commit mentions that it implements ANSI X9.17 Annex C. Another issue was that this driver didn't implement the crypto_rng API correctly, as crypto4xx_prng_generate() didn't return 0 on success. - No user of this code is known. It's usable only theoretically via the "rng" algorithm type of AF_ALG. But userspace actually just uses the actual Linux RNG (/dev/random etc) instead. And rng_algs don't contribute entropy to the actual Linux RNG either. (This may have been confused with hwrng, which does contribute entropy.) Fixes: d072bfa48853 ("crypto: crypto4xx - add prng crypto support") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers Acked-by: Christian Lamparter Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 1 - drivers/crypto/amcc/crypto4xx_core.c | 88 ------------------------- drivers/crypto/amcc/crypto4xx_core.h | 4 -- drivers/crypto/amcc/crypto4xx_reg_def.h | 11 ---- 4 files changed, 104 deletions(-) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 3449b3c9c6ad..5dab813a9f74 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -301,7 +301,6 @@ config CRYPTO_DEV_PPC4XX select CRYPTO_CCM select CRYPTO_CTR select CRYPTO_GCM - select CRYPTO_RNG select CRYPTO_SKCIPHER help This option allows you to have support for AMCC crypto acceleration. diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c index b7b6c97d2147..68c5ff7a85b4 100644 --- a/drivers/crypto/amcc/crypto4xx_core.c +++ b/drivers/crypto/amcc/crypto4xx_core.c @@ -31,11 +31,9 @@ #include #include #include -#include #include #include #include -#include #include #include "crypto4xx_reg_def.h" #include "crypto4xx_core.h" @@ -985,10 +983,6 @@ static int crypto4xx_register_alg(struct crypto4xx_device *sec_dev, rc = crypto_register_aead(&alg->alg.u.aead); break; - case CRYPTO_ALG_TYPE_RNG: - rc = crypto_register_rng(&alg->alg.u.rng); - break; - default: rc = crypto_register_skcipher(&alg->alg.u.cipher); break; @@ -1014,10 +1008,6 @@ static void crypto4xx_unregister_alg(struct crypto4xx_device *sec_dev) crypto_unregister_aead(&alg->alg.u.aead); break; - case CRYPTO_ALG_TYPE_RNG: - crypto_unregister_rng(&alg->alg.u.rng); - break; - default: crypto_unregister_skcipher(&alg->alg.u.cipher); } @@ -1076,69 +1066,6 @@ static irqreturn_t crypto4xx_ce_interrupt_handler_revb(int irq, void *data) PPC4XX_TMO_ERR_INT); } -static int ppc4xx_prng_data_read(struct crypto4xx_device *dev, - u8 *data, unsigned int max) -{ - unsigned int i, curr = 0; - u32 val[2]; - - do { - /* trigger PRN generation */ - writel(PPC4XX_PRNG_CTRL_AUTO_EN, - dev->ce_base + CRYPTO4XX_PRNG_CTRL); - - for (i = 0; i < 1024; i++) { - /* usually 19 iterations are enough */ - if ((readl(dev->ce_base + CRYPTO4XX_PRNG_STAT) & - CRYPTO4XX_PRNG_STAT_BUSY)) - continue; - - val[0] = readl_be(dev->ce_base + CRYPTO4XX_PRNG_RES_0); - val[1] = readl_be(dev->ce_base + CRYPTO4XX_PRNG_RES_1); - break; - } - if (i == 1024) - return -ETIMEDOUT; - - if ((max - curr) >= 8) { - memcpy(data, &val, 8); - data += 8; - curr += 8; - } else { - /* copy only remaining bytes */ - memcpy(data, &val, max - curr); - break; - } - } while (curr < max); - - return curr; -} - -static int crypto4xx_prng_generate(struct crypto_rng *tfm, - const u8 *src, unsigned int slen, - u8 *dstn, unsigned int dlen) -{ - struct rng_alg *alg = crypto_rng_alg(tfm); - struct crypto4xx_alg *amcc_alg; - struct crypto4xx_device *dev; - int ret; - - amcc_alg = container_of(alg, struct crypto4xx_alg, alg.u.rng); - dev = amcc_alg->dev; - - mutex_lock(&dev->core_dev->rng_lock); - ret = ppc4xx_prng_data_read(dev, dstn, dlen); - mutex_unlock(&dev->core_dev->rng_lock); - return ret; -} - - -static int crypto4xx_prng_seed(struct crypto_rng *tfm, const u8 *seed, - unsigned int slen) -{ - return 0; -} - /* * Supported Crypto Algorithms */ @@ -1268,18 +1195,6 @@ static struct crypto4xx_alg_common crypto4xx_alg[] = { .cra_module = THIS_MODULE, }, } }, - { .type = CRYPTO_ALG_TYPE_RNG, .u.rng = { - .base = { - .cra_name = "stdrng", - .cra_driver_name = "crypto4xx_rng", - .cra_priority = 300, - .cra_ctxsize = 0, - .cra_module = THIS_MODULE, - }, - .generate = crypto4xx_prng_generate, - .seed = crypto4xx_prng_seed, - .seedsize = 0, - } }, }; /* @@ -1353,9 +1268,6 @@ static int crypto4xx_probe(struct platform_device *ofdev) core_dev->dev->core_dev = core_dev; core_dev->dev->is_revb = is_revb; core_dev->device = dev; - rc = devm_mutex_init(&ofdev->dev, &core_dev->rng_lock); - if (rc) - return rc; spin_lock_init(&core_dev->lock); INIT_LIST_HEAD(&core_dev->dev->alg_list); ratelimit_default_init(&core_dev->dev->aead_ratelimit); diff --git a/drivers/crypto/amcc/crypto4xx_core.h b/drivers/crypto/amcc/crypto4xx_core.h index ee36630c670f..3a028aec3f0c 100644 --- a/drivers/crypto/amcc/crypto4xx_core.h +++ b/drivers/crypto/amcc/crypto4xx_core.h @@ -14,10 +14,8 @@ #define __CRYPTO4XX_CORE_H__ #include -#include #include #include -#include #include #include "crypto4xx_reg_def.h" #include "crypto4xx_sa.h" @@ -111,7 +109,6 @@ struct crypto4xx_core_device { u32 irq; struct tasklet_struct tasklet; spinlock_t lock; - struct mutex rng_lock; }; struct crypto4xx_ctx { @@ -135,7 +132,6 @@ struct crypto4xx_alg_common { union { struct skcipher_alg cipher; struct aead_alg aead; - struct rng_alg rng; } u; }; diff --git a/drivers/crypto/amcc/crypto4xx_reg_def.h b/drivers/crypto/amcc/crypto4xx_reg_def.h index 1038061224da..73d626308a84 100644 --- a/drivers/crypto/amcc/crypto4xx_reg_def.h +++ b/drivers/crypto/amcc/crypto4xx_reg_def.h @@ -90,20 +90,9 @@ #define CRYPTO4XX_BYTE_ORDER_CFG 0x000600d8 #define CRYPTO4XX_ENDIAN_CFG 0x000600d8 -#define CRYPTO4XX_PRNG_STAT 0x00070000 -#define CRYPTO4XX_PRNG_STAT_BUSY 0x1 #define CRYPTO4XX_PRNG_CTRL 0x00070004 #define CRYPTO4XX_PRNG_SEED_L 0x00070008 #define CRYPTO4XX_PRNG_SEED_H 0x0007000c - -#define CRYPTO4XX_PRNG_RES_0 0x00070020 -#define CRYPTO4XX_PRNG_RES_1 0x00070024 -#define CRYPTO4XX_PRNG_RES_2 0x00070028 -#define CRYPTO4XX_PRNG_RES_3 0x0007002C - -#define CRYPTO4XX_PRNG_LFSR_L 0x00070030 -#define CRYPTO4XX_PRNG_LFSR_H 0x00070034 - /* * Initialize CRYPTO ENGINE registers, and memory bases. */ From af3d1bb9a09daf928fc3f173689fb7904d6a6d4f Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 29 May 2026 16:32:08 -0700 Subject: [PATCH 179/196] crypto: loongson - Remove broken and unused loongson-rng The loongson-rng rng_alg has several vulnerabilities, including not providing forward security, and a use-after-free bug due to the use of wait_for_completion_interruptible(). Meanwhile, the rng_alg framework doesn't really have any purpose in the first place other than to access the software algorithms crypto/drbg.c and crypto/jitterentropy.c. Hardware-specific rng_algs have no in-kernel user, and unlike hwrng there's no feed into the actual Linux RNG. As such, there's really no point to this code. There are of course other rng_alg drivers that are similarly unused, but they're similarly in the process of being phased out, e.g. https://lore.kernel.org/r/20260529193648.18172-1-ebiggers@kernel.org and https://lore.kernel.org/r/20260529220430.34135-1-ebiggers@kernel.org Given that, there's no point in fixing forward these vulnerabilities, and it makes much more sense to simply roll back the addition of this driver. If this platform provides TRNG (not PRNG) functionality, it could make sense to add a hwrng driver, but it would be quite different. Link: https://lore.kernel.org/linux-crypto/20260525145939.GC2018@quark/ Fixes: 766b2d724c8d ("crypto: loongson - add Loongson RNG driver support") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- MAINTAINERS | 1 - arch/loongarch/configs/loongson32_defconfig | 1 - arch/loongarch/configs/loongson64_defconfig | 1 - drivers/crypto/Kconfig | 1 - drivers/crypto/Makefile | 1 - drivers/crypto/loongson/Kconfig | 6 - drivers/crypto/loongson/Makefile | 1 - drivers/crypto/loongson/loongson-rng.c | 209 -------------------- 8 files changed, 221 deletions(-) delete mode 100644 drivers/crypto/loongson/Kconfig delete mode 100644 drivers/crypto/loongson/Makefile delete mode 100644 drivers/crypto/loongson/loongson-rng.c diff --git a/MAINTAINERS b/MAINTAINERS index 882214b0e7db..6c805560c77c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15070,7 +15070,6 @@ M: Qunqin Zhao L: linux-crypto@vger.kernel.org S: Maintained F: drivers/char/tpm/tpm_loongson.c -F: drivers/crypto/loongson/ F: drivers/mfd/loongson-se.c F: include/linux/mfd/loongson-se.h diff --git a/arch/loongarch/configs/loongson32_defconfig b/arch/loongarch/configs/loongson32_defconfig index d5ef396dffe3..82897236863f 100644 --- a/arch/loongarch/configs/loongson32_defconfig +++ b/arch/loongarch/configs/loongson32_defconfig @@ -1091,7 +1091,6 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_CRYPTO_DEV_VIRTIO=m -CONFIG_CRYPTO_DEV_LOONGSON_RNG=m CONFIG_DMA_CMA=y CONFIG_CMA_SIZE_MBYTES=0 CONFIG_PRINTK_TIME=y diff --git a/arch/loongarch/configs/loongson64_defconfig b/arch/loongarch/configs/loongson64_defconfig index cba4cdff5acd..a94e88bd7ec5 100644 --- a/arch/loongarch/configs/loongson64_defconfig +++ b/arch/loongarch/configs/loongson64_defconfig @@ -1124,7 +1124,6 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_CRYPTO_DEV_VIRTIO=m -CONFIG_CRYPTO_DEV_LOONGSON_RNG=m CONFIG_DMA_CMA=y CONFIG_DMA_NUMA_CMA=y CONFIG_CMA_SIZE_MBYTES=0 diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 5dab813a9f74..223cb3c32261 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -845,7 +845,6 @@ config CRYPTO_DEV_CCREE If unsure say Y. source "drivers/crypto/hisilicon/Kconfig" -source "drivers/crypto/loongson/Kconfig" source "drivers/crypto/amlogic/Kconfig" diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 283bbc650b5b..ad773158ae56 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -43,7 +43,6 @@ obj-y += inside-secure/ obj-$(CONFIG_CRYPTO_DEV_ARTPEC6) += axis/ obj-y += xilinx/ obj-y += hisilicon/ -obj-y += loongson/ obj-$(CONFIG_CRYPTO_DEV_AMLOGIC_GXL) += amlogic/ obj-y += intel/ obj-y += starfive/ diff --git a/drivers/crypto/loongson/Kconfig b/drivers/crypto/loongson/Kconfig deleted file mode 100644 index f4e1544ffbb4..000000000000 --- a/drivers/crypto/loongson/Kconfig +++ /dev/null @@ -1,6 +0,0 @@ -config CRYPTO_DEV_LOONGSON_RNG - tristate "Support for Loongson RNG Driver" - depends on MFD_LOONGSON_SE - select CRYPTO_RNG - help - Support for Loongson RNG Driver. diff --git a/drivers/crypto/loongson/Makefile b/drivers/crypto/loongson/Makefile deleted file mode 100644 index 1ce5ec32b553..000000000000 --- a/drivers/crypto/loongson/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_CRYPTO_DEV_LOONGSON_RNG) += loongson-rng.o diff --git a/drivers/crypto/loongson/loongson-rng.c b/drivers/crypto/loongson/loongson-rng.c deleted file mode 100644 index 3a4940260f9e..000000000000 --- a/drivers/crypto/loongson/loongson-rng.c +++ /dev/null @@ -1,209 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2019 HiSilicon Limited. */ -/* Copyright (c) 2025 Loongson Technology Corporation Limited. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define SE_SEED_SIZE 32 - -struct loongson_rng_list { - struct mutex lock; - struct list_head list; - int registered; -}; - -struct loongson_rng { - u32 used; - struct loongson_se_engine *engine; - struct list_head list; - struct mutex lock; -}; - -struct loongson_rng_ctx { - struct loongson_rng *rng; -}; - -struct loongson_rng_cmd { - u32 cmd_id; - union { - u32 len; - u32 ret; - } u; - u32 seed_off; - u32 out_off; - u32 pad[4]; -}; - -static struct loongson_rng_list rng_devices = { - .lock = __MUTEX_INITIALIZER(rng_devices.lock), - .list = LIST_HEAD_INIT(rng_devices.list), -}; - -static int loongson_rng_generate(struct crypto_rng *tfm, const u8 *src, - unsigned int slen, u8 *dstn, unsigned int dlen) -{ - struct loongson_rng_ctx *ctx = crypto_rng_ctx(tfm); - struct loongson_rng *rng = ctx->rng; - struct loongson_rng_cmd *cmd = rng->engine->command; - int err, len; - - mutex_lock(&rng->lock); - cmd->seed_off = 0; - do { - len = min(dlen, rng->engine->buffer_size); - cmd = rng->engine->command; - cmd->u.len = len; - err = loongson_se_send_engine_cmd(rng->engine); - if (err) - break; - - cmd = rng->engine->command_ret; - if (cmd->u.ret) { - err = -EIO; - break; - } - - memcpy(dstn, rng->engine->data_buffer, len); - dlen -= len; - dstn += len; - } while (dlen > 0); - mutex_unlock(&rng->lock); - - return err; -} - -static int loongson_rng_init(struct crypto_tfm *tfm) -{ - struct loongson_rng_ctx *ctx = crypto_tfm_ctx(tfm); - struct loongson_rng *rng; - u32 min_used = U32_MAX; - - mutex_lock(&rng_devices.lock); - list_for_each_entry(rng, &rng_devices.list, list) { - if (rng->used < min_used) { - ctx->rng = rng; - min_used = rng->used; - } - } - ctx->rng->used++; - mutex_unlock(&rng_devices.lock); - - return 0; -} - -static void loongson_rng_exit(struct crypto_tfm *tfm) -{ - struct loongson_rng_ctx *ctx = crypto_tfm_ctx(tfm); - - mutex_lock(&rng_devices.lock); - ctx->rng->used--; - mutex_unlock(&rng_devices.lock); -} - -static int loongson_rng_seed(struct crypto_rng *tfm, const u8 *seed, - unsigned int slen) -{ - struct loongson_rng_ctx *ctx = crypto_rng_ctx(tfm); - struct loongson_rng *rng = ctx->rng; - struct loongson_rng_cmd *cmd; - int err; - - if (slen < SE_SEED_SIZE) - return -EINVAL; - - slen = min(slen, rng->engine->buffer_size); - - mutex_lock(&rng->lock); - cmd = rng->engine->command; - cmd->u.len = slen; - cmd->seed_off = rng->engine->buffer_off; - memcpy(rng->engine->data_buffer, seed, slen); - err = loongson_se_send_engine_cmd(rng->engine); - if (err) - goto out; - - cmd = rng->engine->command_ret; - if (cmd->u.ret) - err = -EIO; -out: - mutex_unlock(&rng->lock); - - return err; -} - -static struct rng_alg loongson_rng_alg = { - .generate = loongson_rng_generate, - .seed = loongson_rng_seed, - .seedsize = SE_SEED_SIZE, - .base = { - .cra_name = "stdrng", - .cra_driver_name = "loongson_stdrng", - .cra_priority = 300, - .cra_ctxsize = sizeof(struct loongson_rng_ctx), - .cra_module = THIS_MODULE, - .cra_init = loongson_rng_init, - .cra_exit = loongson_rng_exit, - }, -}; - -static int loongson_rng_probe(struct platform_device *pdev) -{ - struct loongson_rng_cmd *cmd; - struct loongson_rng *rng; - int ret = 0; - - rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL); - if (!rng) - return -ENOMEM; - - rng->engine = loongson_se_init_engine(pdev->dev.parent, SE_ENGINE_RNG); - if (!rng->engine) - return -ENODEV; - cmd = rng->engine->command; - cmd->cmd_id = SE_CMD_RNG; - cmd->out_off = rng->engine->buffer_off; - mutex_init(&rng->lock); - - mutex_lock(&rng_devices.lock); - - if (!rng_devices.registered) { - ret = crypto_register_rng(&loongson_rng_alg); - if (ret) { - dev_err(&pdev->dev, "failed to register crypto(%d)\n", ret); - goto out; - } - rng_devices.registered = 1; - } - - list_add_tail(&rng->list, &rng_devices.list); -out: - mutex_unlock(&rng_devices.lock); - - return ret; -} - -static struct platform_driver loongson_rng_driver = { - .probe = loongson_rng_probe, - .driver = { - .name = "loongson-rng", - }, -}; -module_platform_driver(loongson_rng_driver); - -MODULE_ALIAS("platform:loongson-rng"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Yinggang Gu "); -MODULE_AUTHOR("Qunqin Zhao "); -MODULE_DESCRIPTION("Loongson Random Number Generator driver"); From 216a7795ec210bdabd5dad42323eee70bbfc8d90 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 30 May 2026 13:26:23 -0700 Subject: [PATCH 180/196] crypto: hisi-trng - Remove crypto_rng interface drivers/crypto/hisilicon/trng/trng.c exposes the same hardware through two completely separate interfaces, crypto_rng and hwrng. However, the implementation of this is buggy because it permits generation operations from these interfaces to run concurrently with each other, accessing the same registers. That is, hisi_trng_generate() synchronizes with itself but not with hisi_trng_read(). This results in potential repetition of output from the RNG, output of non-random values, etc. Fortunately, there's actually no point in hardware RNG drivers implementing the crypto_rng interface. It's not actually used by anything besides the "rng" algorithm type of AF_ALG, which in turn is not actually used in practice. Other crypto_rng hardware drivers are likewise being phased out, leaving just the hwrng support. Thus, remove it to simplify the code and avoid conflict (and confusion) with the hwrng interface which is the one that actually matters. Fixes: e4d9d10ef4be ("crypto: hisilicon/trng - add support for PRNG") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/Kconfig | 1 - drivers/crypto/hisilicon/trng/trng.c | 296 +-------------------------- 2 files changed, 2 insertions(+), 295 deletions(-) diff --git a/drivers/crypto/hisilicon/Kconfig b/drivers/crypto/hisilicon/Kconfig index 1e6d772f4bb6..8aa23c939775 100644 --- a/drivers/crypto/hisilicon/Kconfig +++ b/drivers/crypto/hisilicon/Kconfig @@ -80,6 +80,5 @@ config CRYPTO_DEV_HISI_TRNG tristate "Support for HISI TRNG Driver" depends on ARM64 && ACPI select HW_RANDOM - select CRYPTO_RNG help Support for HiSilicon TRNG Driver. diff --git a/drivers/crypto/hisilicon/trng/trng.c b/drivers/crypto/hisilicon/trng/trng.c index 5ca0b90859a8..6584ed051e09 100644 --- a/drivers/crypto/hisilicon/trng/trng.c +++ b/drivers/crypto/hisilicon/trng/trng.c @@ -1,234 +1,27 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2019 HiSilicon Limited. */ -#include #include -#include #include #include #include #include #include -#include #include -#include #include #include #define HISI_TRNG_REG 0x00F0 #define HISI_TRNG_BYTES 4 #define HISI_TRNG_QUALITY 512 -#define HISI_TRNG_VERSION 0x01B8 -#define HISI_TRNG_VER_V1 GENMASK(31, 0) #define SLEEP_US 10 #define TIMEOUT_US 10000 -#define SW_DRBG_NUM_SHIFT 2 -#define SW_DRBG_KEY_BASE 0x082C -#define SW_DRBG_SEED(n) (SW_DRBG_KEY_BASE - ((n) << SW_DRBG_NUM_SHIFT)) -#define SW_DRBG_SEED_REGS_NUM 12 -#define SW_DRBG_SEED_SIZE 48 -#define SW_DRBG_BLOCKS 0x0830 -#define SW_DRBG_INIT 0x0834 -#define SW_DRBG_GEN 0x083c -#define SW_DRBG_STATUS 0x0840 -#define SW_DRBG_BLOCKS_NUM 4095 -#define SW_DRBG_DATA_BASE 0x0850 -#define SW_DRBG_DATA_NUM 4 -#define SW_DRBG_DATA(n) (SW_DRBG_DATA_BASE - ((n) << SW_DRBG_NUM_SHIFT)) -#define SW_DRBG_BYTES 16 -#define SW_DRBG_ENABLE_SHIFT 12 -#define SEED_SHIFT_24 24 -#define SEED_SHIFT_16 16 -#define SEED_SHIFT_8 8 -#define SW_MAX_RANDOM_BYTES 65520 - -struct hisi_trng_list { - struct mutex lock; - struct list_head list; - bool is_init; -}; struct hisi_trng { void __iomem *base; - struct hisi_trng_list *trng_list; - struct list_head list; struct hwrng rng; - u32 ver; - u32 ctx_num; - /* The bytes of the random number generated since the last seeding. */ - u32 random_bytes; - struct mutex lock; }; -struct hisi_trng_ctx { - struct hisi_trng *trng; -}; - -static atomic_t trng_active_devs; -static struct hisi_trng_list trng_devices; -static int hisi_trng_read(struct hwrng *rng, void *buf, size_t max, bool wait); - -static int hisi_trng_set_seed(struct hisi_trng *trng, const u8 *seed) -{ - u32 val, seed_reg, i; - int ret; - - writel(0x0, trng->base + SW_DRBG_BLOCKS); - - for (i = 0; i < SW_DRBG_SEED_SIZE; - i += SW_DRBG_SEED_SIZE / SW_DRBG_SEED_REGS_NUM) { - val = seed[i] << SEED_SHIFT_24; - val |= seed[i + 1UL] << SEED_SHIFT_16; - val |= seed[i + 2UL] << SEED_SHIFT_8; - val |= seed[i + 3UL]; - - seed_reg = (i >> SW_DRBG_NUM_SHIFT) % SW_DRBG_SEED_REGS_NUM; - writel(val, trng->base + SW_DRBG_SEED(seed_reg)); - } - - writel(SW_DRBG_BLOCKS_NUM | (0x1 << SW_DRBG_ENABLE_SHIFT), - trng->base + SW_DRBG_BLOCKS); - writel(0x1, trng->base + SW_DRBG_INIT); - ret = readl_relaxed_poll_timeout(trng->base + SW_DRBG_STATUS, - val, val & BIT(0), SLEEP_US, TIMEOUT_US); - if (ret) { - pr_err("failed to init trng(%d)\n", ret); - return -EIO; - } - - trng->random_bytes = 0; - - return 0; -} - -static int hisi_trng_seed(struct crypto_rng *tfm, const u8 *seed, - unsigned int slen) -{ - struct hisi_trng_ctx *ctx = crypto_rng_ctx(tfm); - struct hisi_trng *trng = ctx->trng; - int ret; - - if (slen < SW_DRBG_SEED_SIZE) { - pr_err("slen(%u) is not matched with trng(%d)\n", slen, - SW_DRBG_SEED_SIZE); - return -EINVAL; - } - - mutex_lock(&trng->lock); - ret = hisi_trng_set_seed(trng, seed); - mutex_unlock(&trng->lock); - - return ret; -} - -static int hisi_trng_reseed(struct hisi_trng *trng) -{ - u8 seed[SW_DRBG_SEED_SIZE]; - int size; - - if (!trng->random_bytes) - return 0; - - size = hisi_trng_read(&trng->rng, seed, SW_DRBG_SEED_SIZE, false); - if (size != SW_DRBG_SEED_SIZE) - return -EIO; - - return hisi_trng_set_seed(trng, seed); -} - -static int hisi_trng_get_bytes(struct hisi_trng *trng, u8 *dstn, unsigned int dlen) -{ - u32 data[SW_DRBG_DATA_NUM]; - u32 currsize = 0; - u32 val = 0; - int ret; - u32 i; - - ret = hisi_trng_reseed(trng); - if (ret) - return ret; - - do { - ret = readl_relaxed_poll_timeout(trng->base + SW_DRBG_STATUS, - val, val & BIT(1), SLEEP_US, TIMEOUT_US); - if (ret) { - pr_err("failed to generate random number(%d)!\n", ret); - break; - } - - for (i = 0; i < SW_DRBG_DATA_NUM; i++) - data[i] = readl(trng->base + SW_DRBG_DATA(i)); - - if (dlen - currsize >= SW_DRBG_BYTES) { - memcpy(dstn + currsize, data, SW_DRBG_BYTES); - currsize += SW_DRBG_BYTES; - } else { - memcpy(dstn + currsize, data, dlen - currsize); - currsize = dlen; - } - - trng->random_bytes += SW_DRBG_BYTES; - writel(0x1, trng->base + SW_DRBG_GEN); - } while (currsize < dlen); - - return ret; -} - -static int hisi_trng_generate(struct crypto_rng *tfm, const u8 *src, - unsigned int slen, u8 *dstn, unsigned int dlen) -{ - struct hisi_trng_ctx *ctx = crypto_rng_ctx(tfm); - struct hisi_trng *trng = ctx->trng; - unsigned int currsize = 0; - unsigned int block_size; - int ret; - - if (!dstn || !dlen) { - pr_err("output is error, dlen %u!\n", dlen); - return -EINVAL; - } - - do { - block_size = min_t(unsigned int, dlen - currsize, SW_MAX_RANDOM_BYTES); - mutex_lock(&trng->lock); - ret = hisi_trng_get_bytes(trng, dstn + currsize, block_size); - mutex_unlock(&trng->lock); - if (ret) - return ret; - currsize += block_size; - } while (currsize < dlen); - - return 0; -} - -static int hisi_trng_init(struct crypto_tfm *tfm) -{ - struct hisi_trng_ctx *ctx = crypto_tfm_ctx(tfm); - struct hisi_trng *trng; - u32 ctx_num = ~0; - - mutex_lock(&trng_devices.lock); - list_for_each_entry(trng, &trng_devices.list, list) { - if (trng->ctx_num < ctx_num) { - ctx_num = trng->ctx_num; - ctx->trng = trng; - } - } - ctx->trng->ctx_num++; - mutex_unlock(&trng_devices.lock); - - return 0; -} - -static void hisi_trng_exit(struct crypto_tfm *tfm) -{ - struct hisi_trng_ctx *ctx = crypto_tfm_ctx(tfm); - - mutex_lock(&trng_devices.lock); - ctx->trng->ctx_num--; - mutex_unlock(&trng_devices.lock); -} - static int hisi_trng_read(struct hwrng *rng, void *buf, size_t max, bool wait) { struct hisi_trng *trng; @@ -260,42 +53,6 @@ static int hisi_trng_read(struct hwrng *rng, void *buf, size_t max, bool wait) return currsize; } -static struct rng_alg hisi_trng_alg = { - .generate = hisi_trng_generate, - .seed = hisi_trng_seed, - .seedsize = SW_DRBG_SEED_SIZE, - .base = { - .cra_name = "stdrng", - .cra_driver_name = "hisi_stdrng", - .cra_priority = 300, - .cra_ctxsize = sizeof(struct hisi_trng_ctx), - .cra_module = THIS_MODULE, - .cra_init = hisi_trng_init, - .cra_exit = hisi_trng_exit, - }, -}; - -static void hisi_trng_add_to_list(struct hisi_trng *trng) -{ - mutex_lock(&trng_devices.lock); - list_add_tail(&trng->list, &trng_devices.list); - mutex_unlock(&trng_devices.lock); -} - -static int hisi_trng_del_from_list(struct hisi_trng *trng) -{ - int ret = -EBUSY; - - mutex_lock(&trng_devices.lock); - if (!trng->ctx_num) { - list_del(&trng->list); - ret = 0; - } - mutex_unlock(&trng_devices.lock); - - return ret; -} - static int hisi_trng_probe(struct platform_device *pdev) { struct hisi_trng *trng; @@ -305,66 +62,18 @@ static int hisi_trng_probe(struct platform_device *pdev) if (!trng) return -ENOMEM; - platform_set_drvdata(pdev, trng); - trng->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(trng->base)) return PTR_ERR(trng->base); - trng->ctx_num = 0; - trng->random_bytes = SW_MAX_RANDOM_BYTES; - mutex_init(&trng->lock); - trng->ver = readl(trng->base + HISI_TRNG_VERSION); - if (!trng_devices.is_init) { - INIT_LIST_HEAD(&trng_devices.list); - mutex_init(&trng_devices.lock); - trng_devices.is_init = true; - } - - hisi_trng_add_to_list(trng); - if (trng->ver != HISI_TRNG_VER_V1 && - atomic_inc_return(&trng_active_devs) == 1) { - ret = crypto_register_rng(&hisi_trng_alg); - if (ret) { - dev_err(&pdev->dev, - "failed to register crypto(%d)\n", ret); - atomic_dec_return(&trng_active_devs); - goto err_remove_from_list; - } - } - trng->rng.name = pdev->name; trng->rng.read = hisi_trng_read; trng->rng.quality = HISI_TRNG_QUALITY; + ret = devm_hwrng_register(&pdev->dev, &trng->rng); - if (ret) { + if (ret) dev_err(&pdev->dev, "failed to register hwrng: %d!\n", ret); - goto err_crypto_unregister; - } - return ret; - -err_crypto_unregister: - if (trng->ver != HISI_TRNG_VER_V1 && - atomic_dec_return(&trng_active_devs) == 0) - crypto_unregister_rng(&hisi_trng_alg); - -err_remove_from_list: - hisi_trng_del_from_list(trng); - return ret; -} - -static void hisi_trng_remove(struct platform_device *pdev) -{ - struct hisi_trng *trng = platform_get_drvdata(pdev); - - /* Wait until the task is finished */ - while (hisi_trng_del_from_list(trng)) - ; - - if (trng->ver != HISI_TRNG_VER_V1 && - atomic_dec_return(&trng_active_devs) == 0) - crypto_unregister_rng(&hisi_trng_alg); } static const struct acpi_device_id hisi_trng_acpi_match[] = { @@ -375,7 +84,6 @@ MODULE_DEVICE_TABLE(acpi, hisi_trng_acpi_match); static struct platform_driver hisi_trng_driver = { .probe = hisi_trng_probe, - .remove = hisi_trng_remove, .driver = { .name = "hisi-trng-v2", .acpi_match_table = ACPI_PTR(hisi_trng_acpi_match), From ffbb2ebd0c3a7ead6c9128bbbb62fc6d851779bb Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 30 May 2026 13:26:24 -0700 Subject: [PATCH 181/196] hwrng: hisi-trng - Move hisi-trng into drivers/char/hw_random/ Since this file just implements a hwrng driver, move it into drivers/char/hw_random/. Rename the kconfig option accordingly as well. Note that this moves the file back to its original location. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- MAINTAINERS | 2 +- arch/arm64/configs/defconfig | 2 +- drivers/char/hw_random/Kconfig | 10 ++++++++++ drivers/char/hw_random/Makefile | 1 + .../trng/trng.c => char/hw_random/hisi-trng-v2.c} | 0 drivers/crypto/hisilicon/Kconfig | 7 ------- drivers/crypto/hisilicon/Makefile | 1 - drivers/crypto/hisilicon/trng/Makefile | 2 -- 8 files changed, 13 insertions(+), 12 deletions(-) rename drivers/{crypto/hisilicon/trng/trng.c => char/hw_random/hisi-trng-v2.c} (100%) delete mode 100644 drivers/crypto/hisilicon/trng/Makefile diff --git a/MAINTAINERS b/MAINTAINERS index 6c805560c77c..6a9c618586b0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11705,7 +11705,7 @@ F: drivers/mfd/hi6421-spmi-pmic.c HISILICON TRUE RANDOM NUMBER GENERATOR V2 SUPPORT M: Weili Qian S: Maintained -F: drivers/crypto/hisilicon/trng/trng.c +F: drivers/char/hw_random/hisi-trng-v2.c HISILICON V3XX SPI NOR FLASH Controller Driver M: Yang Shen diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index d905a0777f93..cbb0ffe0a9d3 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -550,6 +550,7 @@ CONFIG_IPMI_DEVICE_INTERFACE=m CONFIG_IPMI_SI=m CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_VIRTIO=y +CONFIG_HW_RANDOM_HISI_TRNG=m CONFIG_TCG_TPM=y CONFIG_TCG_TIS=m CONFIG_TCG_TIS_SPI=m @@ -1962,7 +1963,6 @@ CONFIG_CRYPTO_DEV_CCREE=m CONFIG_CRYPTO_DEV_HISI_SEC2=m CONFIG_CRYPTO_DEV_HISI_ZIP=m CONFIG_CRYPTO_DEV_HISI_HPRE=m -CONFIG_CRYPTO_DEV_HISI_TRNG=m CONFIG_CRYPTO_DEV_SA2UL=m CONFIG_DMA_RESTRICTED_POOL=y CONFIG_CMA_SIZE_MBYTES=32 diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 492a2a61a65b..3ea74f208f06 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -373,6 +373,16 @@ config HW_RANDOM_HISTB To compile this driver as a module, choose M here: the module will be called histb-rng. +config HW_RANDOM_HISI_TRNG + tristate "HiSilicon True Random Number Generator support" + depends on ARM64 && ACPI + help + This driver provides kernel-side support for the True Random Number + Generator hardware found on some HiSilicon SoCs. + + To compile this driver as a module, choose M here: the module will be + called hisi-trng-v2. + config HW_RANDOM_ST tristate "ST Microelectronics HW Random Number Generator support" depends on ARCH_STI || COMPILE_TEST diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index b9132b3f5d21..3e655d6e116b 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o obj-$(CONFIG_HW_RANDOM_HISI) += hisi-rng.o obj-$(CONFIG_HW_RANDOM_HISTB) += histb-rng.o +obj-$(CONFIG_HW_RANDOM_HISI_TRNG) += hisi-trng-v2.o obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o obj-$(CONFIG_HW_RANDOM_BCM74110) += bcm74110-rng.o obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o diff --git a/drivers/crypto/hisilicon/trng/trng.c b/drivers/char/hw_random/hisi-trng-v2.c similarity index 100% rename from drivers/crypto/hisilicon/trng/trng.c rename to drivers/char/hw_random/hisi-trng-v2.c diff --git a/drivers/crypto/hisilicon/Kconfig b/drivers/crypto/hisilicon/Kconfig index 8aa23c939775..aeff08ccbadd 100644 --- a/drivers/crypto/hisilicon/Kconfig +++ b/drivers/crypto/hisilicon/Kconfig @@ -75,10 +75,3 @@ config CRYPTO_DEV_HISI_HPRE help Support for HiSilicon HPRE(High Performance RSA Engine) accelerator, which can accelerate RSA and DH algorithms. - -config CRYPTO_DEV_HISI_TRNG - tristate "Support for HISI TRNG Driver" - depends on ARM64 && ACPI - select HW_RANDOM - help - Support for HiSilicon TRNG Driver. diff --git a/drivers/crypto/hisilicon/Makefile b/drivers/crypto/hisilicon/Makefile index 8595a5a5d228..e1068ee9f973 100644 --- a/drivers/crypto/hisilicon/Makefile +++ b/drivers/crypto/hisilicon/Makefile @@ -5,4 +5,3 @@ obj-$(CONFIG_CRYPTO_DEV_HISI_SEC2) += sec2/ obj-$(CONFIG_CRYPTO_DEV_HISI_QM) += hisi_qm.o hisi_qm-objs = qm.o sgl.o debugfs.o obj-$(CONFIG_CRYPTO_DEV_HISI_ZIP) += zip/ -obj-$(CONFIG_CRYPTO_DEV_HISI_TRNG) += trng/ diff --git a/drivers/crypto/hisilicon/trng/Makefile b/drivers/crypto/hisilicon/trng/Makefile deleted file mode 100644 index d909079f351c..000000000000 --- a/drivers/crypto/hisilicon/trng/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_CRYPTO_DEV_HISI_TRNG) += hisi-trng-v2.o -hisi-trng-v2-objs = trng.o From c9fedb3b23d4664b824f60085bcdba92e5d9dd48 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 31 May 2026 10:59:31 -0700 Subject: [PATCH 182/196] crypto: exynos-rng - Remove exynos-rng driver This driver has no purpose. It doesn't feed into the Linux RNG, nor does it implement the hwrng interface. It is accessible only via the "rng" algorithm type of AF_ALG, which isn't used in practice. Everyone uses either the Linux RNG, or rarely /dev/hwrng. Moreover, this is a PRNG whose only source of entropy is the 160-bit seed the user passes in. So this can be used only by a user who already has a source of cryptographically secure random numbers, such as /dev/random. Which they can, and do, just use in the first place. Just remove this driver. There's no need to keep useless code around. Note that the other crypto_rng drivers in drivers/crypto/ are similarly unused and are being removed too. This commit just handles exynos-rng. Signed-off-by: Eric Biggers Acked-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- MAINTAINERS | 8 - arch/arm/configs/exynos_defconfig | 1 - arch/arm/configs/multi_v7_defconfig | 1 - drivers/crypto/Kconfig | 18 -- drivers/crypto/Makefile | 1 - drivers/crypto/exynos-rng.c | 399 ---------------------------- 6 files changed, 428 deletions(-) delete mode 100644 drivers/crypto/exynos-rng.c diff --git a/MAINTAINERS b/MAINTAINERS index 6a9c618586b0..afad0783395d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23702,14 +23702,6 @@ F: Documentation/devicetree/bindings/mailbox/google,gs101-mbox.yaml F: drivers/mailbox/exynos-mailbox.c F: include/linux/mailbox/exynos-message.h -SAMSUNG EXYNOS PSEUDO RANDOM NUMBER GENERATOR (RNG) DRIVER -M: Krzysztof Kozlowski -L: linux-crypto@vger.kernel.org -L: linux-samsung-soc@vger.kernel.org -S: Maintained -F: Documentation/devicetree/bindings/rng/samsung,exynos4-rng.yaml -F: drivers/crypto/exynos-rng.c - SAMSUNG EXYNOS TRUE RANDOM NUMBER GENERATOR (TRNG) DRIVER M: Ɓukasz Stelmach L: linux-samsung-soc@vger.kernel.org diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig index 84070e9698e8..8b072a5c0a5e 100644 --- a/arch/arm/configs/exynos_defconfig +++ b/arch/arm/configs/exynos_defconfig @@ -364,7 +364,6 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_CRYPTO_AES_ARM_BS=m -CONFIG_CRYPTO_DEV_EXYNOS_RNG=y CONFIG_CRYPTO_DEV_S5P=y CONFIG_DMA_CMA=y CONFIG_CMA_SIZE_MBYTES=96 diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index bcc9aabc1202..3672dd12df60 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -1329,7 +1329,6 @@ CONFIG_CRYPTO_AES_ARM_BS=m CONFIG_CRYPTO_AES_ARM_CE=m CONFIG_CRYPTO_DEV_SUN4I_SS=m CONFIG_CRYPTO_DEV_FSL_CAAM=m -CONFIG_CRYPTO_DEV_EXYNOS_RNG=m CONFIG_CRYPTO_DEV_S5P=m CONFIG_CRYPTO_DEV_ATMEL_AES=m CONFIG_CRYPTO_DEV_ATMEL_TDES=m diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 223cb3c32261..4c47ab6bb267 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -374,21 +374,6 @@ config CRYPTO_DEV_SAHARA This option enables support for the SAHARA HW crypto accelerator found in some Freescale i.MX chips. -config CRYPTO_DEV_EXYNOS_RNG - tristate "Exynos HW pseudo random number generator support" - depends on ARCH_EXYNOS || COMPILE_TEST - depends on HAS_IOMEM - select CRYPTO_RNG - help - This driver provides kernel-side support through the - cryptographic API for the pseudo random number generator hardware - found on Exynos SoCs. - - To compile this driver as a module, choose M here: the - module will be called exynos-rng. - - If unsure, say Y. - config CRYPTO_DEV_S5P tristate "Support for Samsung S5PV210/Exynos crypto accelerator" depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST @@ -403,7 +388,6 @@ config CRYPTO_DEV_S5P config CRYPTO_DEV_EXYNOS_HASH bool "Support for Samsung Exynos HASH accelerator" depends on CRYPTO_DEV_S5P - depends on !CRYPTO_DEV_EXYNOS_RNG && CRYPTO_DEV_EXYNOS_RNG!=m select CRYPTO_SHA1 select CRYPTO_MD5 select CRYPTO_SHA256 @@ -411,8 +395,6 @@ config CRYPTO_DEV_EXYNOS_HASH Select this to offload Exynos from HASH MD5/SHA1/SHA256. This will select software SHA1, MD5 and SHA256 as they are needed for small and zero-size messages. - HASH algorithms will be disabled if EXYNOS_RNG - is enabled due to hw conflict. config CRYPTO_DEV_NX bool "Support for IBM PowerPC Nest (NX) cryptographic acceleration" diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index ad773158ae56..5a950c7abc39 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_CRYPTO_DEV_ATMEL_SHA204A) += atmel-sha204a.o obj-$(CONFIG_CRYPTO_DEV_CCP) += ccp/ obj-$(CONFIG_CRYPTO_DEV_CCREE) += ccree/ obj-$(CONFIG_CRYPTO_DEV_CHELSIO) += chelsio/ -obj-$(CONFIG_CRYPTO_DEV_EXYNOS_RNG) += exynos-rng.o obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_COMMON) += caam/ obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o obj-$(CONFIG_CRYPTO_DEV_HIFN_795X) += hifn_795x.o diff --git a/drivers/crypto/exynos-rng.c b/drivers/crypto/exynos-rng.c deleted file mode 100644 index 2aaa98f9b44e..000000000000 --- a/drivers/crypto/exynos-rng.c +++ /dev/null @@ -1,399 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * exynos-rng.c - Random Number Generator driver for the Exynos - * - * Copyright (c) 2017 Krzysztof Kozlowski - * - * Loosely based on old driver from drivers/char/hw_random/exynos-rng.c: - * Copyright (C) 2012 Samsung Electronics - * Jonghwa Lee - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define EXYNOS_RNG_CONTROL 0x0 -#define EXYNOS_RNG_STATUS 0x10 - -#define EXYNOS_RNG_SEED_CONF 0x14 -#define EXYNOS_RNG_GEN_PRNG BIT(1) - -#define EXYNOS_RNG_SEED_BASE 0x140 -#define EXYNOS_RNG_SEED(n) (EXYNOS_RNG_SEED_BASE + (n * 0x4)) -#define EXYNOS_RNG_OUT_BASE 0x160 -#define EXYNOS_RNG_OUT(n) (EXYNOS_RNG_OUT_BASE + (n * 0x4)) - -/* EXYNOS_RNG_CONTROL bit fields */ -#define EXYNOS_RNG_CONTROL_START 0x18 -/* EXYNOS_RNG_STATUS bit fields */ -#define EXYNOS_RNG_STATUS_SEED_SETTING_DONE BIT(1) -#define EXYNOS_RNG_STATUS_RNG_DONE BIT(5) - -/* Five seed and output registers, each 4 bytes */ -#define EXYNOS_RNG_SEED_REGS 5 -#define EXYNOS_RNG_SEED_SIZE (EXYNOS_RNG_SEED_REGS * 4) - -enum exynos_prng_type { - EXYNOS_PRNG_UNKNOWN = 0, - EXYNOS_PRNG_EXYNOS4, - EXYNOS_PRNG_EXYNOS5, -}; - -/* - * Driver re-seeds itself with generated random numbers to hinder - * backtracking of the original seed. - * - * Time for next re-seed in ms. - */ -#define EXYNOS_RNG_RESEED_TIME 1000 -#define EXYNOS_RNG_RESEED_BYTES 65536 - -/* - * In polling mode, do not wait infinitely for the engine to finish the work. - */ -#define EXYNOS_RNG_WAIT_RETRIES 100 - -/* Context for crypto */ -struct exynos_rng_ctx { - struct exynos_rng_dev *rng; -}; - -/* Device associated memory */ -struct exynos_rng_dev { - struct device *dev; - enum exynos_prng_type type; - void __iomem *mem; - struct clk *clk; - struct mutex lock; - /* Generated numbers stored for seeding during resume */ - u8 seed_save[EXYNOS_RNG_SEED_SIZE]; - unsigned int seed_save_len; - /* Time of last seeding in jiffies */ - unsigned long last_seeding; - /* Bytes generated since last seeding */ - unsigned long bytes_seeding; -}; - -static struct exynos_rng_dev *exynos_rng_dev; - -static u32 exynos_rng_readl(struct exynos_rng_dev *rng, u32 offset) -{ - return readl_relaxed(rng->mem + offset); -} - -static void exynos_rng_writel(struct exynos_rng_dev *rng, u32 val, u32 offset) -{ - writel_relaxed(val, rng->mem + offset); -} - -static int exynos_rng_set_seed(struct exynos_rng_dev *rng, - const u8 *seed, unsigned int slen) -{ - u32 val; - int i; - - /* Round seed length because loop iterates over full register size */ - slen = ALIGN_DOWN(slen, 4); - - if (slen < EXYNOS_RNG_SEED_SIZE) - return -EINVAL; - - for (i = 0; i < slen ; i += 4) { - unsigned int seed_reg = (i / 4) % EXYNOS_RNG_SEED_REGS; - - val = seed[i] << 24; - val |= seed[i + 1] << 16; - val |= seed[i + 2] << 8; - val |= seed[i + 3] << 0; - - exynos_rng_writel(rng, val, EXYNOS_RNG_SEED(seed_reg)); - } - - val = exynos_rng_readl(rng, EXYNOS_RNG_STATUS); - if (!(val & EXYNOS_RNG_STATUS_SEED_SETTING_DONE)) { - dev_warn(rng->dev, "Seed setting not finished\n"); - return -EIO; - } - - rng->last_seeding = jiffies; - rng->bytes_seeding = 0; - - return 0; -} - -/* - * Start the engine and poll for finish. Then read from output registers - * filling the 'dst' buffer up to 'dlen' bytes or up to size of generated - * random data (EXYNOS_RNG_SEED_SIZE). - * - * On success: return 0 and store number of read bytes under 'read' address. - * On error: return -ERRNO. - */ -static int exynos_rng_get_random(struct exynos_rng_dev *rng, - u8 *dst, unsigned int dlen, - unsigned int *read) -{ - int retry = EXYNOS_RNG_WAIT_RETRIES; - - if (rng->type == EXYNOS_PRNG_EXYNOS4) { - exynos_rng_writel(rng, EXYNOS_RNG_CONTROL_START, - EXYNOS_RNG_CONTROL); - } else if (rng->type == EXYNOS_PRNG_EXYNOS5) { - exynos_rng_writel(rng, EXYNOS_RNG_GEN_PRNG, - EXYNOS_RNG_SEED_CONF); - } - - while (!(exynos_rng_readl(rng, - EXYNOS_RNG_STATUS) & EXYNOS_RNG_STATUS_RNG_DONE) && --retry) - cpu_relax(); - - if (!retry) - return -ETIMEDOUT; - - /* Clear status bit */ - exynos_rng_writel(rng, EXYNOS_RNG_STATUS_RNG_DONE, - EXYNOS_RNG_STATUS); - *read = min_t(size_t, dlen, EXYNOS_RNG_SEED_SIZE); - memcpy_fromio(dst, rng->mem + EXYNOS_RNG_OUT_BASE, *read); - rng->bytes_seeding += *read; - - return 0; -} - -/* Re-seed itself from time to time */ -static void exynos_rng_reseed(struct exynos_rng_dev *rng) -{ - unsigned long next_seeding = rng->last_seeding + \ - msecs_to_jiffies(EXYNOS_RNG_RESEED_TIME); - unsigned long now = jiffies; - unsigned int read = 0; - u8 seed[EXYNOS_RNG_SEED_SIZE]; - - if (time_before(now, next_seeding) && - rng->bytes_seeding < EXYNOS_RNG_RESEED_BYTES) - return; - - if (exynos_rng_get_random(rng, seed, sizeof(seed), &read)) - return; - - exynos_rng_set_seed(rng, seed, read); - - /* Let others do some of their job. */ - mutex_unlock(&rng->lock); - mutex_lock(&rng->lock); -} - -static int exynos_rng_generate(struct crypto_rng *tfm, - const u8 *src, unsigned int slen, - u8 *dst, unsigned int dlen) -{ - struct exynos_rng_ctx *ctx = crypto_rng_ctx(tfm); - struct exynos_rng_dev *rng = ctx->rng; - unsigned int read = 0; - int ret; - - ret = clk_prepare_enable(rng->clk); - if (ret) - return ret; - - mutex_lock(&rng->lock); - do { - ret = exynos_rng_get_random(rng, dst, dlen, &read); - if (ret) - break; - - dlen -= read; - dst += read; - - exynos_rng_reseed(rng); - } while (dlen > 0); - mutex_unlock(&rng->lock); - - clk_disable_unprepare(rng->clk); - - return ret; -} - -static int exynos_rng_seed(struct crypto_rng *tfm, const u8 *seed, - unsigned int slen) -{ - struct exynos_rng_ctx *ctx = crypto_rng_ctx(tfm); - struct exynos_rng_dev *rng = ctx->rng; - int ret; - - ret = clk_prepare_enable(rng->clk); - if (ret) - return ret; - - mutex_lock(&rng->lock); - ret = exynos_rng_set_seed(ctx->rng, seed, slen); - mutex_unlock(&rng->lock); - - clk_disable_unprepare(rng->clk); - - return ret; -} - -static int exynos_rng_kcapi_init(struct crypto_tfm *tfm) -{ - struct exynos_rng_ctx *ctx = crypto_tfm_ctx(tfm); - - ctx->rng = exynos_rng_dev; - - return 0; -} - -static struct rng_alg exynos_rng_alg = { - .generate = exynos_rng_generate, - .seed = exynos_rng_seed, - .seedsize = EXYNOS_RNG_SEED_SIZE, - .base = { - .cra_name = "stdrng", - .cra_driver_name = "exynos_rng", - .cra_priority = 300, - .cra_ctxsize = sizeof(struct exynos_rng_ctx), - .cra_module = THIS_MODULE, - .cra_init = exynos_rng_kcapi_init, - } -}; - -static int exynos_rng_probe(struct platform_device *pdev) -{ - struct exynos_rng_dev *rng; - int ret; - - if (exynos_rng_dev) - return -EEXIST; - - rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL); - if (!rng) - return -ENOMEM; - - rng->type = (uintptr_t)of_device_get_match_data(&pdev->dev); - - mutex_init(&rng->lock); - - rng->dev = &pdev->dev; - rng->clk = devm_clk_get(&pdev->dev, "secss"); - if (IS_ERR(rng->clk)) { - dev_err(&pdev->dev, "Couldn't get clock.\n"); - return PTR_ERR(rng->clk); - } - - rng->mem = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(rng->mem)) - return PTR_ERR(rng->mem); - - platform_set_drvdata(pdev, rng); - - exynos_rng_dev = rng; - - ret = crypto_register_rng(&exynos_rng_alg); - if (ret) { - dev_err(&pdev->dev, - "Couldn't register rng crypto alg: %d\n", ret); - exynos_rng_dev = NULL; - } - - return ret; -} - -static void exynos_rng_remove(struct platform_device *pdev) -{ - crypto_unregister_rng(&exynos_rng_alg); - - exynos_rng_dev = NULL; -} - -static int __maybe_unused exynos_rng_suspend(struct device *dev) -{ - struct exynos_rng_dev *rng = dev_get_drvdata(dev); - int ret; - - /* If we were never seeded then after resume it will be the same */ - if (!rng->last_seeding) - return 0; - - rng->seed_save_len = 0; - ret = clk_prepare_enable(rng->clk); - if (ret) - return ret; - - mutex_lock(&rng->lock); - - /* Get new random numbers and store them for seeding on resume. */ - exynos_rng_get_random(rng, rng->seed_save, sizeof(rng->seed_save), - &(rng->seed_save_len)); - - mutex_unlock(&rng->lock); - - dev_dbg(rng->dev, "Stored %u bytes for seeding on system resume\n", - rng->seed_save_len); - - clk_disable_unprepare(rng->clk); - - return 0; -} - -static int __maybe_unused exynos_rng_resume(struct device *dev) -{ - struct exynos_rng_dev *rng = dev_get_drvdata(dev); - int ret; - - /* Never seeded so nothing to do */ - if (!rng->last_seeding) - return 0; - - ret = clk_prepare_enable(rng->clk); - if (ret) - return ret; - - mutex_lock(&rng->lock); - - ret = exynos_rng_set_seed(rng, rng->seed_save, rng->seed_save_len); - - mutex_unlock(&rng->lock); - - clk_disable_unprepare(rng->clk); - - return ret; -} - -static SIMPLE_DEV_PM_OPS(exynos_rng_pm_ops, exynos_rng_suspend, - exynos_rng_resume); - -static const struct of_device_id exynos_rng_dt_match[] = { - { - .compatible = "samsung,exynos4-rng", - .data = (const void *)EXYNOS_PRNG_EXYNOS4, - }, { - .compatible = "samsung,exynos5250-prng", - .data = (const void *)EXYNOS_PRNG_EXYNOS5, - }, - { }, -}; -MODULE_DEVICE_TABLE(of, exynos_rng_dt_match); - -static struct platform_driver exynos_rng_driver = { - .driver = { - .name = "exynos-rng", - .pm = &exynos_rng_pm_ops, - .of_match_table = exynos_rng_dt_match, - }, - .probe = exynos_rng_probe, - .remove = exynos_rng_remove, -}; - -module_platform_driver(exynos_rng_driver); - -MODULE_DESCRIPTION("Exynos H/W Random Number Generator driver"); -MODULE_AUTHOR("Krzysztof Kozlowski "); -MODULE_LICENSE("GPL v2"); From 32b4d29280ed2a991dc196d5845b892acedc63b8 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 31 May 2026 12:17:35 -0700 Subject: [PATCH 183/196] crypto: xilinx-trng - Remove crypto_rng interface Implementing the crypto_rng interface has no purpose, as it isn't used in practice. It's being removed from other drivers too. Just remove it. This leaves hwrng, which is actually used. Tagging with 'Cc stable' due to the bugs that this removes: - xtrng_trng_generate() sometimes returned success even when it didn't fill in all the bytes. - It was possible for xtrng_trng_generate() and xtrng_hwrng_trng_read() to run concurrently and interfere with each other, as the locking code in xtrng_hwrng_trng_read() was broken. Fixes: 8979744aca80 ("crypto: xilinx - Add TRNG driver for Versal") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 1 - drivers/crypto/xilinx/xilinx-trng.c | 85 ++--------------------------- 2 files changed, 4 insertions(+), 82 deletions(-) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 4c47ab6bb267..851904fb9ba4 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -703,7 +703,6 @@ config CRYPTO_DEV_XILINX_TRNG tristate "Support for Xilinx True Random Generator" depends on ZYNQMP_FIRMWARE || COMPILE_TEST select CRYPTO_DF80090A - select CRYPTO_RNG select HW_RANDOM help Xilinx Versal SoC driver provides kernel-side support for True Random Number diff --git a/drivers/crypto/xilinx/xilinx-trng.c b/drivers/crypto/xilinx/xilinx-trng.c index 43a4832f07e7..a35643baa489 100644 --- a/drivers/crypto/xilinx/xilinx-trng.c +++ b/drivers/crypto/xilinx/xilinx-trng.c @@ -6,7 +6,6 @@ #include #include -#include #include #include #include @@ -14,13 +13,11 @@ #include #include #include -#include #include #include #include #include #include -#include /* TRNG Registers Offsets */ #define TRNG_STATUS_OFFSET 0x4U @@ -60,16 +57,9 @@ struct xilinx_rng { struct device *dev; unsigned char *scratchpadbuf; struct aes_enckey *aeskey; - struct mutex lock; /* Protect access to TRNG device */ struct hwrng trng; }; -struct xilinx_rng_ctx { - struct xilinx_rng *rng; -}; - -static struct xilinx_rng *xilinx_rng_dev; - static void xtrng_readwrite32(void __iomem *addr, u32 mask, u8 value) { u32 val; @@ -245,47 +235,6 @@ static int xtrng_random_bytes_generate(struct xilinx_rng *rng, u8 *rand_buf_ptr, return nbytes; } -static int xtrng_trng_generate(struct crypto_rng *tfm, const u8 *src, u32 slen, - u8 *dst, u32 dlen) -{ - struct xilinx_rng_ctx *ctx = crypto_rng_ctx(tfm); - int ret; - - mutex_lock(&ctx->rng->lock); - ret = xtrng_random_bytes_generate(ctx->rng, dst, dlen, true); - mutex_unlock(&ctx->rng->lock); - - return ret < 0 ? ret : 0; -} - -static int xtrng_trng_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen) -{ - return 0; -} - -static int xtrng_trng_init(struct crypto_tfm *rtfm) -{ - struct xilinx_rng_ctx *ctx = crypto_tfm_ctx(rtfm); - - ctx->rng = xilinx_rng_dev; - - return 0; -} - -static struct rng_alg xtrng_trng_alg = { - .generate = xtrng_trng_generate, - .seed = xtrng_trng_seed, - .seedsize = 0, - .base = { - .cra_name = "stdrng", - .cra_driver_name = "xilinx-trng", - .cra_priority = 300, - .cra_ctxsize = sizeof(struct xilinx_rng_ctx), - .cra_module = THIS_MODULE, - .cra_init = xtrng_trng_init, - }, -}; - static int xtrng_hwrng_trng_read(struct hwrng *hwrng, void *data, size_t max, bool wait) { u8 buf[TRNG_SEC_STRENGTH_BYTES]; @@ -293,12 +242,6 @@ static int xtrng_hwrng_trng_read(struct hwrng *hwrng, void *data, size_t max, bo int ret = -EINVAL, i = 0; rng = container_of(hwrng, struct xilinx_rng, trng); - /* Return in case wait not set and lock not available. */ - if (!mutex_trylock(&rng->lock) && !wait) - return 0; - else if (!mutex_is_locked(&rng->lock) && wait) - mutex_lock(&rng->lock); - while (i < max) { ret = xtrng_random_bytes_generate(rng, buf, TRNG_SEC_STRENGTH_BYTES, wait); if (ret < 0) @@ -307,8 +250,6 @@ static int xtrng_hwrng_trng_read(struct hwrng *hwrng, void *data, size_t max, bo memcpy(data + i, buf, min_t(int, ret, (max - i))); i += min_t(int, ret, (max - i)); } - mutex_unlock(&rng->lock); - return ret; } @@ -354,40 +295,24 @@ static int xtrng_probe(struct platform_device *pdev) sb_size = crypto_drbg_ctr_df_datalen(TRNG_SEED_LEN_BYTES, AES_BLOCK_SIZE); rng->scratchpadbuf = devm_kzalloc(&pdev->dev, sb_size, GFP_KERNEL); - if (!rng->scratchpadbuf) { - ret = -ENOMEM; - goto end; - } + if (!rng->scratchpadbuf) + return -ENOMEM; xtrng_trng_reset(rng->rng_base); ret = xtrng_reseed_internal(rng); if (ret) { dev_err(&pdev->dev, "TRNG Seed fail\n"); - goto end; - } - - xilinx_rng_dev = rng; - mutex_init(&rng->lock); - ret = crypto_register_rng(&xtrng_trng_alg); - if (ret) { - dev_err(&pdev->dev, "Crypto Random device registration failed: %d\n", ret); - goto end; + return ret; } ret = xtrng_hwrng_register(&rng->trng); if (ret) { dev_err(&pdev->dev, "HWRNG device registration failed: %d\n", ret); - goto crypto_rng_free; + return ret; } platform_set_drvdata(pdev, rng); return 0; - -crypto_rng_free: - crypto_unregister_rng(&xtrng_trng_alg); - -end: - return ret; } static void xtrng_remove(struct platform_device *pdev) @@ -397,13 +322,11 @@ static void xtrng_remove(struct platform_device *pdev) rng = platform_get_drvdata(pdev); xtrng_hwrng_unregister(&rng->trng); - crypto_unregister_rng(&xtrng_trng_alg); xtrng_write_multiple_registers(rng->rng_base + TRNG_EXT_SEED_OFFSET, zero, TRNG_NUM_INIT_REGS); xtrng_write_multiple_registers(rng->rng_base + TRNG_PER_STRNG_OFFSET, zero, TRNG_NUM_INIT_REGS); xtrng_hold_reset(rng->rng_base); - xilinx_rng_dev = NULL; } static const struct of_device_id xtrng_of_match[] = { From 2dd67774228930ccf6441e5628996021f410c4e0 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 31 May 2026 12:17:36 -0700 Subject: [PATCH 184/196] crypto: xilinx-trng - Fix return value of xtrng_hwrng_trng_read() Implementations of hwrng::read are expected to return the number of bytes generated. Update xtrng_hwrng_trng_read() to match that. Fixes: 8979744aca80 ("crypto: xilinx - Add TRNG driver for Versal") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- drivers/crypto/xilinx/xilinx-trng.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/xilinx/xilinx-trng.c b/drivers/crypto/xilinx/xilinx-trng.c index a35643baa489..a30b0b3b3685 100644 --- a/drivers/crypto/xilinx/xilinx-trng.c +++ b/drivers/crypto/xilinx/xilinx-trng.c @@ -239,18 +239,21 @@ static int xtrng_hwrng_trng_read(struct hwrng *hwrng, void *data, size_t max, bo { u8 buf[TRNG_SEC_STRENGTH_BYTES]; struct xilinx_rng *rng; - int ret = -EINVAL, i = 0; + int ret = 0, i = 0; rng = container_of(hwrng, struct xilinx_rng, trng); while (i < max) { ret = xtrng_random_bytes_generate(rng, buf, TRNG_SEC_STRENGTH_BYTES, wait); - if (ret < 0) + if (ret < 0) { + if (i == 0) + return ret; break; + } memcpy(data + i, buf, min_t(int, ret, (max - i))); i += min_t(int, ret, (max - i)); } - return ret; + return i; } static int xtrng_hwrng_register(struct hwrng *trng) From 5f1d444e084ce3e4619e38c45a8cc29e6fffb2bf Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 31 May 2026 12:17:37 -0700 Subject: [PATCH 185/196] crypto: xilinx-trng - Replace crypto_drbg_ctr_df() with HMAC-SHA512 This code is just trying to condition 48 bytes of random data. This can be done easily using HKDF-SHA512-Extract, saving 300 lines of code. This commit also fixes forward security (in this particular case) by clearing the entropy from memory after it's used. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/Kconfig | 5 - crypto/Makefile | 2 - crypto/df_sp80090a.c | 222 ---------------------------- drivers/crypto/Kconfig | 2 +- drivers/crypto/xilinx/xilinx-trng.c | 44 ++---- include/crypto/df_sp80090a.h | 53 ------- 6 files changed, 16 insertions(+), 312 deletions(-) delete mode 100644 crypto/df_sp80090a.c delete mode 100644 include/crypto/df_sp80090a.h diff --git a/crypto/Kconfig b/crypto/Kconfig index b5c5a1e04435..c3d7a20d5cb1 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1246,11 +1246,6 @@ config CRYPTO_KDF800108_CTR select CRYPTO_HMAC select CRYPTO_SHA256 -config CRYPTO_DF80090A - tristate - select CRYPTO_AES - select CRYPTO_CTR - endmenu menu "Userspace interface (deprecated)" diff --git a/crypto/Makefile b/crypto/Makefile index c73f4d51d036..f98f57c7a49f 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -208,6 +208,4 @@ obj-$(CONFIG_CRYPTO_SIMD) += crypto_simd.o # obj-$(CONFIG_CRYPTO_KDF800108_CTR) += kdf_sp800108.o -obj-$(CONFIG_CRYPTO_DF80090A) += df_sp80090a.o - obj-$(CONFIG_CRYPTO_KRB5) += krb5/ diff --git a/crypto/df_sp80090a.c b/crypto/df_sp80090a.c deleted file mode 100644 index 90e1973ee40c..000000000000 --- a/crypto/df_sp80090a.c +++ /dev/null @@ -1,222 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/* - * NIST SP800-90A DRBG derivation function - * - * Copyright (C) 2014, Stephan Mueller - */ - -#include -#include -#include -#include -#include -#include -#include - -static void drbg_kcapi_sym(struct aes_enckey *aeskey, unsigned char *outval, - const struct drbg_string *in, u8 blocklen_bytes) -{ - /* there is only component in *in */ - BUG_ON(in->len < blocklen_bytes); - aes_encrypt(aeskey, outval, in->buf); -} - -/* BCC function for CTR DRBG as defined in 10.4.3 */ - -static void drbg_ctr_bcc(struct aes_enckey *aeskey, - unsigned char *out, const unsigned char *key, - struct list_head *in, - u8 blocklen_bytes, - u8 keylen) -{ - struct drbg_string *curr = NULL; - struct drbg_string data; - short cnt = 0; - - drbg_string_fill(&data, out, blocklen_bytes); - - /* 10.4.3 step 2 / 4 */ - aes_prepareenckey(aeskey, key, keylen); - list_for_each_entry(curr, in, list) { - const unsigned char *pos = curr->buf; - size_t len = curr->len; - /* 10.4.3 step 4.1 */ - while (len) { - /* 10.4.3 step 4.2 */ - if (blocklen_bytes == cnt) { - cnt = 0; - drbg_kcapi_sym(aeskey, out, &data, blocklen_bytes); - } - out[cnt] ^= *pos; - pos++; - cnt++; - len--; - } - } - /* 10.4.3 step 4.2 for last block */ - if (cnt) - drbg_kcapi_sym(aeskey, out, &data, blocklen_bytes); -} - -/* - * scratchpad usage: drbg_ctr_update is interlinked with crypto_drbg_ctr_df - * (and drbg_ctr_bcc, but this function does not need any temporary buffers), - * the scratchpad is used as follows: - * drbg_ctr_update: - * temp - * start: drbg->scratchpad - * length: drbg_statelen(drbg) + drbg_blocklen(drbg) - * note: the cipher writing into this variable works - * blocklen-wise. Now, when the statelen is not a multiple - * of blocklen, the generateion loop below "spills over" - * by at most blocklen. Thus, we need to give sufficient - * memory. - * df_data - * start: drbg->scratchpad + - * drbg_statelen(drbg) + drbg_blocklen(drbg) - * length: drbg_statelen(drbg) - * - * crypto_drbg_ctr_df: - * pad - * start: df_data + drbg_statelen(drbg) - * length: drbg_blocklen(drbg) - * iv - * start: pad + drbg_blocklen(drbg) - * length: drbg_blocklen(drbg) - * temp - * start: iv + drbg_blocklen(drbg) - * length: drbg_satelen(drbg) + drbg_blocklen(drbg) - * note: temp is the buffer that the BCC function operates - * on. BCC operates blockwise. drbg_statelen(drbg) - * is sufficient when the DRBG state length is a multiple - * of the block size. For AES192 (and maybe other ciphers) - * this is not correct and the length for temp is - * insufficient (yes, that also means for such ciphers, - * the final output of all BCC rounds are truncated). - * Therefore, add drbg_blocklen(drbg) to cover all - * possibilities. - * refer to crypto_drbg_ctr_df_datalen() to get required length - */ - -/* Derivation Function for CTR DRBG as defined in 10.4.2 */ -int crypto_drbg_ctr_df(struct aes_enckey *aeskey, - unsigned char *df_data, size_t bytes_to_return, - struct list_head *seedlist, - u8 blocklen_bytes, - u8 statelen) -{ - unsigned char L_N[8]; - /* S3 is input */ - struct drbg_string S1, S2, S4, cipherin; - LIST_HEAD(bcc_list); - unsigned char *pad = df_data + statelen; - unsigned char *iv = pad + blocklen_bytes; - unsigned char *temp = iv + blocklen_bytes; - size_t padlen = 0; - unsigned int templen = 0; - /* 10.4.2 step 7 */ - unsigned int i = 0; - /* 10.4.2 step 8 */ - const unsigned char *K = (unsigned char *) - "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"; - unsigned char *X; - size_t generated_len = 0; - size_t inputlen = 0; - struct drbg_string *seed = NULL; - u8 keylen; - - memset(pad, 0, blocklen_bytes); - memset(iv, 0, blocklen_bytes); - keylen = statelen - blocklen_bytes; - /* 10.4.2 step 1 is implicit as we work byte-wise */ - - /* 10.4.2 step 2 */ - if ((512 / 8) < bytes_to_return) - return -EINVAL; - - /* 10.4.2 step 2 -- calculate the entire length of all input data */ - list_for_each_entry(seed, seedlist, list) - inputlen += seed->len; - put_unaligned_be32(inputlen, &L_N[0]); - - /* 10.4.2 step 3 */ - put_unaligned_be32(bytes_to_return, &L_N[4]); - - /* 10.4.2 step 5: length is L_N, input_string, one byte, padding */ - padlen = (inputlen + sizeof(L_N) + 1) % (blocklen_bytes); - /* wrap the padlen appropriately */ - if (padlen) - padlen = blocklen_bytes - padlen; - /* - * pad / padlen contains the 0x80 byte and the following zero bytes. - * As the calculated padlen value only covers the number of zero - * bytes, this value has to be incremented by one for the 0x80 byte. - */ - padlen++; - pad[0] = 0x80; - - /* 10.4.2 step 4 -- first fill the linked list and then order it */ - drbg_string_fill(&S1, iv, blocklen_bytes); - list_add_tail(&S1.list, &bcc_list); - drbg_string_fill(&S2, L_N, sizeof(L_N)); - list_add_tail(&S2.list, &bcc_list); - list_splice_tail(seedlist, &bcc_list); - drbg_string_fill(&S4, pad, padlen); - list_add_tail(&S4.list, &bcc_list); - - /* 10.4.2 step 9 */ - while (templen < (keylen + (blocklen_bytes))) { - /* - * 10.4.2 step 9.1 - the padding is implicit as the buffer - * holds zeros after allocation -- even the increment of i - * is irrelevant as the increment remains within length of i - */ - put_unaligned_be32(i, iv); - /* 10.4.2 step 9.2 -- BCC and concatenation with temp */ - drbg_ctr_bcc(aeskey, temp + templen, K, &bcc_list, - blocklen_bytes, keylen); - /* 10.4.2 step 9.3 */ - i++; - templen += blocklen_bytes; - } - - /* 10.4.2 step 11 */ - X = temp + (keylen); - drbg_string_fill(&cipherin, X, blocklen_bytes); - - /* 10.4.2 step 12: overwriting of outval is implemented in next step */ - - /* 10.4.2 step 13 */ - aes_prepareenckey(aeskey, temp, keylen); - while (generated_len < bytes_to_return) { - short blocklen = 0; - /* - * 10.4.2 step 13.1: the truncation of the key length is - * implicit as the key is only drbg_blocklen in size based on - * the implementation of the cipher function callback - */ - drbg_kcapi_sym(aeskey, X, &cipherin, blocklen_bytes); - blocklen = (blocklen_bytes < - (bytes_to_return - generated_len)) ? - blocklen_bytes : - (bytes_to_return - generated_len); - /* 10.4.2 step 13.2 and 14 */ - memcpy(df_data + generated_len, X, blocklen); - generated_len += blocklen; - } - - memset(iv, 0, blocklen_bytes); - memset(temp, 0, statelen + blocklen_bytes); - memset(pad, 0, blocklen_bytes); - return 0; -} -EXPORT_SYMBOL_GPL(crypto_drbg_ctr_df); - -MODULE_IMPORT_NS("CRYPTO_INTERNAL"); -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Stephan Mueller "); -MODULE_DESCRIPTION("Derivation Function conformant to SP800-90A"); diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 851904fb9ba4..b94ba934e2d8 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -702,7 +702,7 @@ config CRYPTO_DEV_TEGRA config CRYPTO_DEV_XILINX_TRNG tristate "Support for Xilinx True Random Generator" depends on ZYNQMP_FIRMWARE || COMPILE_TEST - select CRYPTO_DF80090A + select CRYPTO_LIB_SHA512 select HW_RANDOM help Xilinx Versal SoC driver provides kernel-side support for True Random Number diff --git a/drivers/crypto/xilinx/xilinx-trng.c b/drivers/crypto/xilinx/xilinx-trng.c index a30b0b3b3685..f615d5adddde 100644 --- a/drivers/crypto/xilinx/xilinx-trng.c +++ b/drivers/crypto/xilinx/xilinx-trng.c @@ -4,6 +4,7 @@ * Copyright (c) 2024 - 2025 Advanced Micro Devices, Inc. */ +#include #include #include #include @@ -15,9 +16,6 @@ #include #include #include -#include -#include -#include /* TRNG Registers Offsets */ #define TRNG_STATUS_OFFSET 0x4U @@ -43,7 +41,6 @@ /* Sizes in bytes */ #define TRNG_SEED_LEN_BYTES 48U -#define TRNG_ENTROPY_SEED_LEN_BYTES 64U #define TRNG_SEC_STRENGTH_SHIFT 5U #define TRNG_SEC_STRENGTH_BYTES BIT(TRNG_SEC_STRENGTH_SHIFT) #define TRNG_BYTES_PER_REG 4U @@ -55,8 +52,6 @@ struct xilinx_rng { void __iomem *rng_base; struct device *dev; - unsigned char *scratchpadbuf; - struct aes_enckey *aeskey; struct hwrng trng; }; @@ -172,29 +167,30 @@ static void xtrng_enable_entropy(struct xilinx_rng *rng) static int xtrng_reseed_internal(struct xilinx_rng *rng) { - u8 entropy[TRNG_ENTROPY_SEED_LEN_BYTES]; - struct drbg_string data; - LIST_HEAD(seedlist); + static const u8 default_salt[SHA512_DIGEST_SIZE]; + u8 entropy[SHA512_DIGEST_SIZE] __aligned(4); u32 val; int ret; - drbg_string_fill(&data, entropy, TRNG_SEED_LEN_BYTES); - list_add_tail(&data.list, &seedlist); - memset(entropy, 0, sizeof(entropy)); xtrng_enable_entropy(rng); - /* collect random data to use it as entropy (input for DF) */ + /* Collect some output from the TRNG. */ + static_assert(sizeof(entropy) >= TRNG_SEED_LEN_BYTES); ret = xtrng_collect_random_data(rng, entropy, TRNG_SEED_LEN_BYTES, true); if (ret != TRNG_SEED_LEN_BYTES) return -EINVAL; - ret = crypto_drbg_ctr_df(rng->aeskey, rng->scratchpadbuf, - TRNG_SEED_LEN_BYTES, &seedlist, AES_BLOCK_SIZE, - TRNG_SEED_LEN_BYTES); - if (ret) - return ret; + /* Extract entropy from the TRNG output using HKDF-SHA512-Extract. */ + hmac_sha512_usingrawkey(default_salt, sizeof(default_salt), entropy, + TRNG_SEED_LEN_BYTES, entropy); + + /* Write the extracted entropy to the hardware. */ xtrng_write_multiple_registers(rng->rng_base + TRNG_EXT_SEED_OFFSET, - (u32 *)rng->scratchpadbuf, TRNG_NUM_INIT_REGS); + (u32 *)entropy, TRNG_NUM_INIT_REGS); + + /* Clear the entropy from the stack. */ + memzero_explicit(entropy, sizeof(entropy)); + /* select reseed operation */ iowrite32(TRNG_CTRL_PRNGXS_MASK, rng->rng_base + TRNG_CTRL_OFFSET); @@ -278,7 +274,6 @@ static void xtrng_hwrng_unregister(struct hwrng *trng) static int xtrng_probe(struct platform_device *pdev) { struct xilinx_rng *rng; - size_t sb_size; int ret; rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL); @@ -292,15 +287,6 @@ static int xtrng_probe(struct platform_device *pdev) return PTR_ERR(rng->rng_base); } - rng->aeskey = devm_kzalloc(&pdev->dev, sizeof(*rng->aeskey), GFP_KERNEL); - if (!rng->aeskey) - return -ENOMEM; - - sb_size = crypto_drbg_ctr_df_datalen(TRNG_SEED_LEN_BYTES, AES_BLOCK_SIZE); - rng->scratchpadbuf = devm_kzalloc(&pdev->dev, sb_size, GFP_KERNEL); - if (!rng->scratchpadbuf) - return -ENOMEM; - xtrng_trng_reset(rng->rng_base); ret = xtrng_reseed_internal(rng); if (ret) { diff --git a/include/crypto/df_sp80090a.h b/include/crypto/df_sp80090a.h deleted file mode 100644 index e594fb718eb8..000000000000 --- a/include/crypto/df_sp80090a.h +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/* - * Copyright Stephan Mueller , 2014 - */ - -#ifndef _CRYPTO_DF80090A_H -#define _CRYPTO_DF80090A_H - -#include -#include -#include - -/* - * Concatenation Helper and string operation helper - * - * SP800-90A requires the concatenation of different data. To avoid copying - * buffers around or allocate additional memory, the following data structure - * is used to point to the original memory with its size. In addition, it - * is used to build a linked list. The linked list defines the concatenation - * of individual buffers. The order of memory block referenced in that - * linked list determines the order of concatenation. - */ -struct drbg_string { - const unsigned char *buf; - size_t len; - struct list_head list; -}; - -static inline void drbg_string_fill(struct drbg_string *string, - const unsigned char *buf, size_t len) -{ - string->buf = buf; - string->len = len; - INIT_LIST_HEAD(&string->list); -} - -static inline int crypto_drbg_ctr_df_datalen(u8 statelen, u8 blocklen) -{ - return statelen + /* df_data */ - blocklen + /* pad */ - blocklen + /* iv */ - statelen + blocklen; /* temp */ -} - -int crypto_drbg_ctr_df(struct aes_enckey *aes, - unsigned char *df_data, - size_t bytes_to_return, - struct list_head *seedlist, - u8 blocklen_bytes, - u8 statelen); - -#endif /* _CRYPTO_DF80090A_H */ From be6498ca1cca9084330bdefb68ad8379d1ac5ea7 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 31 May 2026 12:17:38 -0700 Subject: [PATCH 186/196] hwrng: xilinx - Move xilinx-rng into drivers/char/hw_random/ Since this file just implements a hwrng driver, move it into drivers/char/hw_random/. Rename the kconfig option accordingly as well. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- MAINTAINERS | 2 +- arch/arm64/configs/defconfig | 2 +- drivers/char/hw_random/Kconfig | 11 +++++++++++ drivers/char/hw_random/Makefile | 1 + .../{crypto/xilinx => char/hw_random}/xilinx-trng.c | 0 drivers/crypto/Kconfig | 12 ------------ drivers/crypto/xilinx/Makefile | 1 - 7 files changed, 14 insertions(+), 15 deletions(-) rename drivers/{crypto/xilinx => char/hw_random}/xilinx-trng.c (100%) diff --git a/MAINTAINERS b/MAINTAINERS index afad0783395d..3036d80710af 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -29211,7 +29211,7 @@ XILINX TRNG DRIVER M: Mounika Botcha M: Harsh Jain S: Maintained -F: drivers/crypto/xilinx/xilinx-trng.c +F: drivers/char/hw_random/xilinx-trng.c XILINX UARTLITE SERIAL DRIVER M: Peter Korsgaard diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index cbb0ffe0a9d3..6745189b1fbc 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -551,6 +551,7 @@ CONFIG_IPMI_SI=m CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_VIRTIO=y CONFIG_HW_RANDOM_HISI_TRNG=m +CONFIG_HW_RANDOM_XILINX=m CONFIG_TCG_TPM=y CONFIG_TCG_TIS=m CONFIG_TCG_TIS_SPI=m @@ -1956,7 +1957,6 @@ CONFIG_CRYPTO_DEV_FSL_DPAA2_CAAM=m CONFIG_CRYPTO_DEV_QCE=m CONFIG_CRYPTO_DEV_QCOM_RNG=m CONFIG_CRYPTO_DEV_TEGRA=m -CONFIG_CRYPTO_DEV_XILINX_TRNG=m CONFIG_CRYPTO_DEV_ZYNQMP_AES=m CONFIG_CRYPTO_DEV_ZYNQMP_SHA3=m CONFIG_CRYPTO_DEV_CCREE=m diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 3ea74f208f06..a5bcef4a54ee 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -625,6 +625,17 @@ config HW_RANDOM_ROCKCHIP If unsure, say Y. +config HW_RANDOM_XILINX + tristate "Support for Xilinx True Random Generator" + depends on ZYNQMP_FIRMWARE || COMPILE_TEST + select CRYPTO_LIB_SHA512 + help + Xilinx Versal SoC driver provides kernel-side support for True Random Number + Generator and Pseudo random Number in CTR_DRBG mode as defined in NIST SP800-90A. + + To compile this driver as a module, choose M here: the module + will be called xilinx-trng. + endif # HW_RANDOM config UML_RANDOM diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index 3e655d6e116b..95b5adb49560 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -53,3 +53,4 @@ obj-$(CONFIG_HW_RANDOM_CN10K) += cn10k-rng.o obj-$(CONFIG_HW_RANDOM_POLARFIRE_SOC) += mpfs-rng.o obj-$(CONFIG_HW_RANDOM_ROCKCHIP) += rockchip-rng.o obj-$(CONFIG_HW_RANDOM_JH7110) += jh7110-trng.o +obj-$(CONFIG_HW_RANDOM_XILINX) += xilinx-trng.o diff --git a/drivers/crypto/xilinx/xilinx-trng.c b/drivers/char/hw_random/xilinx-trng.c similarity index 100% rename from drivers/crypto/xilinx/xilinx-trng.c rename to drivers/char/hw_random/xilinx-trng.c diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index b94ba934e2d8..216a00bad5d7 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -699,18 +699,6 @@ config CRYPTO_DEV_TEGRA Select this to enable Tegra Security Engine which accelerates various AES encryption/decryption and HASH algorithms. -config CRYPTO_DEV_XILINX_TRNG - tristate "Support for Xilinx True Random Generator" - depends on ZYNQMP_FIRMWARE || COMPILE_TEST - select CRYPTO_LIB_SHA512 - select HW_RANDOM - help - Xilinx Versal SoC driver provides kernel-side support for True Random Number - Generator and Pseudo random Number in CTR_DRBG mode as defined in NIST SP800-90A. - - To compile this driver as a module, choose M here: the module - will be called xilinx-trng. - config CRYPTO_DEV_ZYNQMP_AES tristate "Support for Xilinx ZynqMP AES hw accelerator" depends on ZYNQMP_FIRMWARE || COMPILE_TEST diff --git a/drivers/crypto/xilinx/Makefile b/drivers/crypto/xilinx/Makefile index 9b51636ef75e..730feff5b5f2 100644 --- a/drivers/crypto/xilinx/Makefile +++ b/drivers/crypto/xilinx/Makefile @@ -1,4 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_CRYPTO_DEV_XILINX_TRNG) += xilinx-trng.o obj-$(CONFIG_CRYPTO_DEV_ZYNQMP_AES) += zynqmp-aes-gcm.o obj-$(CONFIG_CRYPTO_DEV_ZYNQMP_SHA3) += zynqmp-sha.o From b2c41fa9dd8fc740c489e060b199165771f268d1 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 1 Jun 2026 16:07:57 +0000 Subject: [PATCH 187/196] crypto: sun4i-ss - Remove insecure and unused rng_alg Remove sun4i_ss_rng, as it is insecure and unused: - It has multiple vulnerabilities. sun4i_ss_prng_seed() is missing locking and has a buffer overflow. sun4i_ss_prng_generate() fails to fill the entire buffer with cryptographic random bytes, because it rounds the destination length down and also doesn't actually wait for the hardware to be ready before pulling bytes from it. - No user of this code is known. It's usable only theoretically via the "rng" algorithm type of AF_ALG. But userspace actually just uses the actual Linux RNG (/dev/random etc) instead. And rng_algs don't contribute entropy to the actual Linux RNG either. (This may have been confused with hwrng, which does contribute entropy.) The sun4i_ss_prng_seed() buffer overflow was reported by Tianchu Chen and discovered by Atuin - Automated Vulnerability Discovery Engine There's no point in fixing all these vulnerabilities individually when this is unused code, so let's just remove it. Fixes: b8ae5c7387ad ("crypto: sun4i-ss - support the Security System PRNG") Cc: stable@vger.kernel.org Reported-by: Tianchu Chen Closes: https://lore.kernel.org/r/af749a8447bd7f0e9dd26ca6c87e9c6afecb09d9@linux.dev/ Acked-by: Corentin LABBE Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- arch/arm/configs/sunxi_defconfig | 1 - drivers/crypto/allwinner/Kconfig | 8 --- drivers/crypto/allwinner/sun4i-ss/Makefile | 1 - .../crypto/allwinner/sun4i-ss/sun4i-ss-core.c | 44 ------------ .../crypto/allwinner/sun4i-ss/sun4i-ss-prng.c | 69 ------------------- drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h | 20 ------ 6 files changed, 143 deletions(-) delete mode 100644 drivers/crypto/allwinner/sun4i-ss/sun4i-ss-prng.c diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig index a83d29fed175..f4b8d8f7dbef 100644 --- a/arch/arm/configs/sunxi_defconfig +++ b/arch/arm/configs/sunxi_defconfig @@ -170,7 +170,6 @@ CONFIG_ROOT_NFS=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_CRYPTO_DEV_SUN4I_SS=y -CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG=y CONFIG_CRYPTO_DEV_SUN8I_CE=y CONFIG_CRYPTO_DEV_SUN8I_SS=y CONFIG_DMA_CMA=y diff --git a/drivers/crypto/allwinner/Kconfig b/drivers/crypto/allwinner/Kconfig index b8e75210a0e3..06ea0e9fe6f2 100644 --- a/drivers/crypto/allwinner/Kconfig +++ b/drivers/crypto/allwinner/Kconfig @@ -24,14 +24,6 @@ config CRYPTO_DEV_SUN4I_SS To compile this driver as a module, choose M here: the module will be called sun4i-ss. -config CRYPTO_DEV_SUN4I_SS_PRNG - bool "Support for Allwinner Security System PRNG" - depends on CRYPTO_DEV_SUN4I_SS - select CRYPTO_RNG - help - Select this option if you want to provide kernel-side support for - the Pseudo-Random Number Generator found in the Security System. - config CRYPTO_DEV_SUN4I_SS_DEBUG bool "Enable sun4i-ss stats" depends on CRYPTO_DEV_SUN4I_SS diff --git a/drivers/crypto/allwinner/sun4i-ss/Makefile b/drivers/crypto/allwinner/sun4i-ss/Makefile index c0a2797d3168..06a9ae81f9f8 100644 --- a/drivers/crypto/allwinner/sun4i-ss/Makefile +++ b/drivers/crypto/allwinner/sun4i-ss/Makefile @@ -1,4 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sun4i-ss.o sun4i-ss-y += sun4i-ss-core.o sun4i-ss-hash.o sun4i-ss-cipher.o -sun4i-ss-$(CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG) += sun4i-ss-prng.o diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c index 813c4bc6312a..35ef0930e77f 100644 --- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c +++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c @@ -213,23 +213,6 @@ static struct sun4i_ss_alg_template ss_algs[] = { } } }, -#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG -{ - .type = CRYPTO_ALG_TYPE_RNG, - .alg.rng = { - .base = { - .cra_name = "stdrng", - .cra_driver_name = "sun4i_ss_rng", - .cra_priority = 300, - .cra_ctxsize = 0, - .cra_module = THIS_MODULE, - }, - .generate = sun4i_ss_prng_generate, - .seed = sun4i_ss_prng_seed, - .seedsize = SS_SEED_LEN / BITS_PER_BYTE, - } -}, -#endif }; static int sun4i_ss_debugfs_show(struct seq_file *seq, void *v) @@ -247,14 +230,6 @@ static int sun4i_ss_debugfs_show(struct seq_file *seq, void *v) ss_algs[i].stat_req, ss_algs[i].stat_opti, ss_algs[i].stat_fb, ss_algs[i].stat_bytes); break; -#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG - case CRYPTO_ALG_TYPE_RNG: - seq_printf(seq, "%s %s reqs=%lu tsize=%lu\n", - ss_algs[i].alg.rng.base.cra_driver_name, - ss_algs[i].alg.rng.base.cra_name, - ss_algs[i].stat_req, ss_algs[i].stat_bytes); - break; -#endif case CRYPTO_ALG_TYPE_AHASH: seq_printf(seq, "%s %s reqs=%lu\n", ss_algs[i].alg.hash.halg.base.cra_driver_name, @@ -473,15 +448,6 @@ static int sun4i_ss_probe(struct platform_device *pdev) goto error_alg; } break; -#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG - case CRYPTO_ALG_TYPE_RNG: - err = crypto_register_rng(&ss_algs[i].alg.rng); - if (err) { - dev_err(ss->dev, "Fail to register %s\n", - ss_algs[i].alg.rng.base.cra_name); - } - break; -#endif } } @@ -501,11 +467,6 @@ error_alg: case CRYPTO_ALG_TYPE_AHASH: crypto_unregister_ahash(&ss_algs[i].alg.hash); break; -#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG - case CRYPTO_ALG_TYPE_RNG: - crypto_unregister_rng(&ss_algs[i].alg.rng); - break; -#endif } } error_pm: @@ -526,11 +487,6 @@ static void sun4i_ss_remove(struct platform_device *pdev) case CRYPTO_ALG_TYPE_AHASH: crypto_unregister_ahash(&ss_algs[i].alg.hash); break; -#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG - case CRYPTO_ALG_TYPE_RNG: - crypto_unregister_rng(&ss_algs[i].alg.rng); - break; -#endif } } diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-prng.c b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-prng.c deleted file mode 100644 index 491fcb7b81b4..000000000000 --- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-prng.c +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -#include "sun4i-ss.h" - -int sun4i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed, - unsigned int slen) -{ - struct sun4i_ss_alg_template *algt; - struct rng_alg *alg = crypto_rng_alg(tfm); - - algt = container_of(alg, struct sun4i_ss_alg_template, alg.rng); - memcpy(algt->ss->seed, seed, slen); - - return 0; -} - -int sun4i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src, - unsigned int slen, u8 *dst, unsigned int dlen) -{ - struct sun4i_ss_alg_template *algt; - struct rng_alg *alg = crypto_rng_alg(tfm); - int i, err; - u32 v; - u32 *data = (u32 *)dst; - const u32 mode = SS_OP_PRNG | SS_PRNG_CONTINUE | SS_ENABLED; - size_t len; - struct sun4i_ss_ctx *ss; - unsigned int todo = (dlen / 4) * 4; - - algt = container_of(alg, struct sun4i_ss_alg_template, alg.rng); - ss = algt->ss; - - err = pm_runtime_resume_and_get(ss->dev); - if (err < 0) - return err; - - if (IS_ENABLED(CONFIG_CRYPTO_DEV_SUN4I_SS_DEBUG)) { - algt->stat_req++; - algt->stat_bytes += todo; - } - - spin_lock_bh(&ss->slock); - - writel(mode, ss->base + SS_CTL); - - while (todo > 0) { - /* write the seed */ - for (i = 0; i < SS_SEED_LEN / BITS_PER_LONG; i++) - writel(ss->seed[i], ss->base + SS_KEY0 + i * 4); - - /* Read the random data */ - len = min_t(size_t, SS_DATA_LEN / BITS_PER_BYTE, todo); - readsl(ss->base + SS_TXFIFO, data, len / 4); - data += len / 4; - todo -= len; - - /* Update the seed */ - for (i = 0; i < SS_SEED_LEN / BITS_PER_LONG; i++) { - v = readl(ss->base + SS_KEY0 + i * 4); - ss->seed[i] = v; - } - } - - writel(0, ss->base + SS_CTL); - spin_unlock_bh(&ss->slock); - - pm_runtime_put(ss->dev); - - return 0; -} diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h index 6c5d4aa6453c..f7d1c79ac677 100644 --- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h +++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h @@ -31,8 +31,6 @@ #include #include #include -#include -#include #define SS_CTL 0x00 #define SS_KEY0 0x04 @@ -62,10 +60,6 @@ /* SS_CTL configuration values */ -/* PRNG generator mode - bit 15 */ -#define SS_PRNG_ONESHOT (0 << 15) -#define SS_PRNG_CONTINUE (1 << 15) - /* IV mode for hash */ #define SS_IV_ARBITRARY (1 << 14) @@ -94,14 +88,10 @@ #define SS_OP_3DES (2 << 4) #define SS_OP_SHA1 (3 << 4) #define SS_OP_MD5 (4 << 4) -#define SS_OP_PRNG (5 << 4) /* Data end bit - bit 2 */ #define SS_DATA_END (1 << 2) -/* PRNG start bit - bit 1 */ -#define SS_PRNG_START (1 << 1) - /* SS Enable bit - bit 0 */ #define SS_DISABLED (0 << 0) #define SS_ENABLED (1 << 0) @@ -128,9 +118,6 @@ #define SS_RXFIFO_EMP_INT_ENABLE (1 << 2) #define SS_TXFIFO_AVA_INT_ENABLE (1 << 0) -#define SS_SEED_LEN 192 -#define SS_DATA_LEN 160 - /* * struct ss_variant - Describe SS hardware variant * @sha1_in_be: The SHA1 digest is given by SS in BE, and so need to be inverted. @@ -151,9 +138,6 @@ struct sun4i_ss_ctx { char buf[4 * SS_RX_MAX];/* buffer for linearize SG src */ char bufo[4 * SS_TX_MAX]; /* buffer for linearize SG dst */ spinlock_t slock; /* control the use of the device */ -#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG - u32 seed[SS_SEED_LEN / BITS_PER_LONG]; -#endif struct dentry *dbgfs_dir; struct dentry *dbgfs_stats; }; @@ -164,7 +148,6 @@ struct sun4i_ss_alg_template { union { struct skcipher_alg crypto; struct ahash_alg hash; - struct rng_alg rng; } alg; struct sun4i_ss_ctx *ss; unsigned long stat_req; @@ -231,6 +214,3 @@ int sun4i_ss_des_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen); int sun4i_ss_des3_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen); -int sun4i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src, - unsigned int slen, u8 *dst, unsigned int dlen); -int sun4i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen); From 1cecde1005399eb4e4069c036dcfcbe3c240b6e0 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Mon, 1 Jun 2026 18:46:45 -0700 Subject: [PATCH 188/196] crypto: amcc - convert irq_of_parse_and_map to platform_get_irq Replace the deprecated irq_of_parse_and_map() call with the modern platform_get_irq() in the probe function. This also improves error handling: platform_get_irq() returns a negative errno on failure, whereas irq_of_parse_and_map() returned 0. Change the irq field in struct crypto4xx_core_device from u32 to int to match the return type of platform_get_irq(). Assisted-by: opencode:big-pickle Signed-off-by: Rosen Penev Signed-off-by: Herbert Xu --- drivers/crypto/amcc/crypto4xx_core.c | 6 +++++- drivers/crypto/amcc/crypto4xx_core.h | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c index 68c5ff7a85b4..001da785af07 100644 --- a/drivers/crypto/amcc/crypto4xx_core.c +++ b/drivers/crypto/amcc/crypto4xx_core.c @@ -1294,7 +1294,11 @@ static int crypto4xx_probe(struct platform_device *ofdev) } /* Register for Crypto isr, Crypto Engine IRQ */ - core_dev->irq = irq_of_parse_and_map(ofdev->dev.of_node, 0); + core_dev->irq = platform_get_irq(ofdev, 0); + if (core_dev->irq < 0) { + rc = core_dev->irq; + goto err_iomap; + } rc = devm_request_irq(&ofdev->dev, core_dev->irq, is_revb ? crypto4xx_ce_interrupt_handler_revb : crypto4xx_ce_interrupt_handler, diff --git a/drivers/crypto/amcc/crypto4xx_core.h b/drivers/crypto/amcc/crypto4xx_core.h index 3a028aec3f0c..66a95733c86d 100644 --- a/drivers/crypto/amcc/crypto4xx_core.h +++ b/drivers/crypto/amcc/crypto4xx_core.h @@ -106,7 +106,7 @@ struct crypto4xx_core_device { struct crypto4xx_device *dev; struct hwrng *trng; u32 int_status; - u32 irq; + int irq; struct tasklet_struct tasklet; spinlock_t lock; }; From 51f449308506269ec31a886c83da93f7a7a4d780 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 2 Jun 2026 14:46:56 +0200 Subject: [PATCH 189/196] MAINTAINERS: make myself the maintainer of the Qualcomm QCE driver Qualcomm wants to keep supporting and extending the crypto engine driver. Thara has not been active for many months, so change the maintainer to myself and upgrade the driver to Supported. Signed-off-by: Bartosz Golaszewski Acked-by: Krzysztof Kozlowski Reviewed-by: Konrad Dybcio Signed-off-by: Herbert Xu --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 3036d80710af..90034eb7874e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21898,10 +21898,10 @@ F: Documentation/devicetree/bindings/opp/opp-v2-kryo-cpu.yaml F: drivers/cpufreq/qcom-cpufreq-nvmem.c QUALCOMM CRYPTO DRIVERS -M: Thara Gopinath +M: Bartosz Golaszewski L: linux-crypto@vger.kernel.org L: linux-arm-msm@vger.kernel.org -S: Maintained +S: Supported F: Documentation/devicetree/bindings/crypto/qcom-qce.yaml F: drivers/crypto/qce/ From 7891c64c0520519782470ba29bac8a5761e295d8 Mon Sep 17 00:00:00 2001 From: Felix Gu Date: Tue, 2 Jun 2026 22:38:26 +0800 Subject: [PATCH 190/196] crypto: marvell/octeontx - fix DMA cleanup using wrong loop index The sg_cleanup path used list[i] instead of list[j] when unmapping DMA buffers, leaking successfully mapped entries and repeatedly unmapping the failed one. Fixes: 10b4f09491bf ("crypto: marvell - add the Virtual Function driver for CPT") Signed-off-by: Felix Gu Signed-off-by: Herbert Xu --- drivers/crypto/marvell/octeontx/otx_cptvf_reqmgr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/marvell/octeontx/otx_cptvf_reqmgr.c b/drivers/crypto/marvell/octeontx/otx_cptvf_reqmgr.c index c80baf1ad90b..89030e2711ce 100644 --- a/drivers/crypto/marvell/octeontx/otx_cptvf_reqmgr.c +++ b/drivers/crypto/marvell/octeontx/otx_cptvf_reqmgr.c @@ -157,8 +157,8 @@ static inline int setup_sgio_components(struct pci_dev *pdev, sg_cleanup: for (j = 0; j < i; j++) { if (list[j].dma_addr) { - dma_unmap_single(&pdev->dev, list[i].dma_addr, - list[i].size, DMA_BIDIRECTIONAL); + dma_unmap_single(&pdev->dev, list[j].dma_addr, + list[j].size, DMA_BIDIRECTIONAL); } list[j].dma_addr = 0; From 9dbf173bd32d5f81b005008b682bfb50aa093455 Mon Sep 17 00:00:00 2001 From: Felix Gu Date: Tue, 2 Jun 2026 22:55:35 +0800 Subject: [PATCH 191/196] crypto: cavium/cpt - fix DMA cleanup using wrong loop index The sg_cleanup error path used list[i] instead of list[j] when unmapping DMA buffers, leaking successfully mapped entries and repeatedly unmapping the failed one. Fixes: c694b233295b ("crypto: cavium - Add the Virtual Function driver for CPT") Signed-off-by: Felix Gu Signed-off-by: Herbert Xu --- drivers/crypto/cavium/cpt/cptvf_reqmanager.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/cavium/cpt/cptvf_reqmanager.c b/drivers/crypto/cavium/cpt/cptvf_reqmanager.c index e183b60277ff..de305cbeccbe 100644 --- a/drivers/crypto/cavium/cpt/cptvf_reqmanager.c +++ b/drivers/crypto/cavium/cpt/cptvf_reqmanager.c @@ -108,8 +108,8 @@ static int setup_sgio_components(struct cpt_vf *cptvf, struct buf_ptr *list, sg_cleanup: for (j = 0; j < i; j++) { if (list[j].dma_addr) { - dma_unmap_single(&pdev->dev, list[i].dma_addr, - list[i].size, DMA_BIDIRECTIONAL); + dma_unmap_single(&pdev->dev, list[j].dma_addr, + list[j].size, DMA_BIDIRECTIONAL); } list[j].dma_addr = 0; From 70fd646ae5ddaae0a7fbbba94b500bde2e1211f0 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Wed, 3 Jun 2026 00:25:19 +0200 Subject: [PATCH 192/196] crypto: atmel-ecc - drop dead code in atmel_ecdh_max_size atmel_ecdh_init_tfm() always allocates ctx->fallback, so it is never NULL in atmel_ecdh_max_size(). Remove the dead code and return crypto_kpp_maxsize() directly. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-ecc.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index 0ca02995a1de..9da9dd6585df 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -284,15 +284,7 @@ static unsigned int atmel_ecdh_max_size(struct crypto_kpp *tfm) { struct atmel_ecdh_ctx *ctx = kpp_tfm_ctx(tfm); - if (ctx->fallback) - return crypto_kpp_maxsize(ctx->fallback); - - /* - * The device only supports NIST P256 ECC keys. The public key size will - * always be the same. Use a macro for the key size to avoid unnecessary - * computations. - */ - return ATMEL_ECC_PUBKEY_SIZE; + return crypto_kpp_maxsize(ctx->fallback); } static struct kpp_alg atmel_ecdh_nist_p256 = { From 8d13f7a8450206e3f820cdb26e33e91d181071b4 Mon Sep 17 00:00:00 2001 From: Wentao Liang Date: Wed, 3 Jun 2026 11:03:27 +0000 Subject: [PATCH 193/196] hwrng: jh7110 - fix refcount leak in starfive_trng_read() The starfive_trng_read() function acquires a runtime PM reference via pm_runtime_get_sync() but fails to release it on two error paths. If starfive_trng_wait_idle() or starfive_trng_cmd() returns an error, the function exits without calling pm_runtime_put_sync_autosuspend(), leaving the runtime PM usage counter permanently elevated and preventing the device from entering runtime suspend. Refactor the function to use a unified error path that calls pm_runtime_put_sync_autosuspend() before returning. Cc: stable@vger.kernel.org Fixes: c388f458bc34 ("hwrng: starfive - Add TRNG driver for StarFive SoC") Signed-off-by: Wentao Liang Signed-off-by: Herbert Xu --- drivers/char/hw_random/jh7110-trng.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/char/hw_random/jh7110-trng.c b/drivers/char/hw_random/jh7110-trng.c index 9776f4daa044..4712c3c530e4 100644 --- a/drivers/char/hw_random/jh7110-trng.c +++ b/drivers/char/hw_random/jh7110-trng.c @@ -256,19 +256,22 @@ static int starfive_trng_read(struct hwrng *rng, void *buf, size_t max, bool wai if (wait) { ret = starfive_trng_wait_idle(trng); - if (ret) - return -ETIMEDOUT; + if (ret) { + ret = -ETIMEDOUT; + goto out_put; + } } ret = starfive_trng_cmd(trng, STARFIVE_CTRL_GENE_RANDNUM, wait); if (ret) - return ret; + goto out_put; memcpy_fromio(buf, trng->base + STARFIVE_RAND0, max); + ret = max; +out_put: pm_runtime_put_sync_autosuspend(trng->dev); - - return max; + return ret; } static int starfive_trng_probe(struct platform_device *pdev) From 6b7e97752854b1f7bccc41864428ea3b55c53cde Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Wed, 3 Jun 2026 17:50:04 +0200 Subject: [PATCH 194/196] crypto: testmgr - allow authenc(hmac(sha{256,384}),cts(cbc(aes))) in FIPS mode hmac(sha256), hmac(sha384) and cts(cbc(aes)) algorithms have been marked as FIPS allowed for years. Mark the respective authenc() constructions per RFC 8009 ("AES Encryption with HMAC-SHA2 for Kerberos 5") as such as well. SP 800-57 Part 3 Rev. 1 from Jan 2015 [1] links the draft of what became RFC 8009 in Oct 2016 as approved in section 6.3 Procurement Guidance (item/recommendation 3). [1] https://csrc.nist.gov/pubs/sp/800/57/pt3/r1/final Signed-off-by: Ilya Dryomov Reviewed-by: Viacheslav Dubeyko Signed-off-by: Herbert Xu --- crypto/testmgr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index a3e80de91d4d..b84d5fcbe107 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -4203,6 +4203,7 @@ static const struct alg_test_desc alg_test_descs[] = { .alg = "authenc(hmac(sha256),cts(cbc(aes)))", .generic_driver = "authenc(hmac-sha256-lib,cts(cbc(aes-lib)))", .test = alg_test_aead, + .fips_allowed = 1, .suite = { .aead = __VECS(krb5_test_aes128_cts_hmac_sha256_128) } @@ -4244,6 +4245,7 @@ static const struct alg_test_desc alg_test_descs[] = { .alg = "authenc(hmac(sha384),cts(cbc(aes)))", .generic_driver = "authenc(hmac-sha384-lib,cts(cbc(aes-lib)))", .test = alg_test_aead, + .fips_allowed = 1, .suite = { .aead = __VECS(krb5_test_aes256_cts_hmac_sha384_192) } From 606ba888b98e0d26a2c4e5c8dc0542e3ad8f0f3a Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 4 Jun 2026 12:30:54 +0800 Subject: [PATCH 195/196] crypto: rng - Free default RNG on module exit When the rng module is removed the default RNG will be leaked. Call crypto_del_default_rng to free it if possible. Fixes: 7cecadb7cca8 ("crypto: rng - Do not free default RNG when it becomes unused") Signed-off-by: Herbert Xu --- crypto/rng.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/crypto/rng.c b/crypto/rng.c index eec786c45bdd..828b0d807473 100644 --- a/crypto/rng.c +++ b/crypto/rng.c @@ -230,5 +230,16 @@ void crypto_unregister_rngs(struct rng_alg *algs, int count) } EXPORT_SYMBOL_GPL(crypto_unregister_rngs); +static void __exit rng_exit(void) +{ + int err; + + err = crypto_del_default_rng(); + if (err) + pr_err("Failed delete default RNG: %d\n", err); +} + +module_exit(rng_exit); + MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Random Number Generator"); From 6ea0ce3a19f9c37a014099e2b0a46b27fa164564 Mon Sep 17 00:00:00 2001 From: Wentao Liang Date: Thu, 4 Jun 2026 10:27:06 +0000 Subject: [PATCH 196/196] crypto: tegra - fix refcount leak in tegra_se_host1x_submit() The timeout error path in tegra_se_host1x_submit() returns without calling host1x_job_put(), while all other paths (success, submit error, pin error) properly release the job reference through the job_put label. Since host1x_job_alloc() initializes the reference count and host1x_job_put() is required to drop it, omitting it on timeout causes a permanent refcount leak. Fix this by redirecting the timeout return to the existing job_put label, ensuring the job reference and any associated syncpt references are consistently released. Cc: stable@vger.kernel.org Fixes: 0880bb3b00c8 ("crypto: tegra - Add Tegra Security Engine driver") Signed-off-by: Wentao Liang Reviewed-by: Akhil R Signed-off-by: Herbert Xu --- drivers/crypto/tegra/tegra-se-main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/tegra/tegra-se-main.c b/drivers/crypto/tegra/tegra-se-main.c index d7541a9c0a92..d2f518ef9a10 100644 --- a/drivers/crypto/tegra/tegra-se-main.c +++ b/drivers/crypto/tegra/tegra-se-main.c @@ -179,7 +179,7 @@ int tegra_se_host1x_submit(struct tegra_se *se, struct tegra_se_cmdbuf *cmdbuf, MAX_SCHEDULE_TIMEOUT, NULL); if (ret) { dev_err(se->dev, "host1x job timed out\n"); - return ret; + goto job_put; } host1x_job_put(job);