[PATCH] PCI: Make pci_find_upstream_pcie_bridge() handle non PCIE VFs well
pci_find_upstream_pcie_bridge() doesn't handle well non PCIE VFs that are part of a PCIE PF device. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- drivers/pci/search.c |6 ++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/drivers/pci/search.c b/drivers/pci/search.c index bf969ba..8ecdab2 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -23,6 +23,8 @@ EXPORT_SYMBOL_GPL(pci_bus_sem); * if the device isn't connected to a PCIe bridge (that is its parent is a * legacy PCI bridge and the bridge is directly connected to bus 0), return its * parent + * if the device is a VF that doesn't have PCIe cap, + * but the PF is a PCIE, return NULL */ struct pci_dev * pci_find_upstream_pcie_bridge(struct pci_dev *pdev) @@ -31,6 +33,10 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev) if (pci_is_pcie(pdev)) return NULL; + + if (pdev-is_virtfn pci_is_pcie(pdev-physfn)) + return NULL; + while (1) { if (pci_is_root_bus(pdev-bus)) break; -- 1.7.7 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] PCI: Make pci_find_upstream_pcie_bridge() handle non PCIE VFs well
On 01/08/2013 05:05 PM, Don Dutile wrote: (a) no such thing as a non-PCIe VF -- all VFs are PCIe-based. The sriov spec says that a VF doesn't necessarily has to have PCIE cap: 3.5 PCI Express Capability: ... PFs and VFs are required to implement this capability ... subject to the exceptions and additional requirements described below (b) code says to return null if VF doesn't have PCIe cap, but the code checks if pdev is VF and if PF is PCIe, which it must be! ... You are right, I should rather check if the VF is not a pcie. nack until a better /or matching explanation of what the real problem is, and what the solution is trying to do. The problem is that I do have a device where VFs are not PCIE and I get this nasty warning. For now I have a workaround, but it would be nice it Linux would support non PCIE VFs. Thanks, T -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] crypto: Fix DMA-API warning
With DMA-API debug enabled testmgr triggers a DMA-API: device driver maps memory from stack warning, when tested on a crypto HW accelerator. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/testmgr.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index dc3cf35..75c78e6 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -414,16 +414,18 @@ static int __test_aead(struct crypto_aead *tfm, int enc, void *input; void *output; void *assoc; - char iv[MAX_IVLEN]; + char *iv; char *xbuf[XBUFSIZE]; char *xoutbuf[XBUFSIZE]; char *axbuf[XBUFSIZE]; + iv = kzalloc(MAX_IVLEN, GFP_KERNEL); + if (!iv) + return ret; if (testmgr_alloc_buf(xbuf)) goto out_noxbuf; if (testmgr_alloc_buf(axbuf)) goto out_noaxbuf; - if (diff_dst testmgr_alloc_buf(xoutbuf)) goto out_nooutbuf; @@ -767,6 +769,7 @@ out_nooutbuf: out_noaxbuf: testmgr_free_buf(xbuf); out_noxbuf: + kfree(iv); return ret; } -- 1.8.5.rc2.6.gc6f1b92.dirty -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[RFC][PATCH 3/4] crypto: QAT dh895xcc accelerator support
Third patch adds dh895xcc hardware specific code. It hooks to the common infrastructure and provides acceleration for crypto algorithms. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com Acked-by: John Griffin john.grif...@intel.com Reviewed-by: Bruce W. Allan bruce.w.al...@intel.com --- drivers/crypto/qat/qat_dh895xcc/Makefile | 8 + drivers/crypto/qat/qat_dh895xcc/adf_admin.c| 144 +++ .../crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c | 214 ++ .../crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.h | 86 drivers/crypto/qat/qat_dh895xcc/adf_drv.c | 448 + drivers/crypto/qat/qat_dh895xcc/adf_drv.h | 67 +++ drivers/crypto/qat/qat_dh895xcc/adf_hw_arbiter.c | 159 drivers/crypto/qat/qat_dh895xcc/adf_isr.c | 266 drivers/crypto/qat/qat_dh895xcc/qat_admin.c| 107 + 9 files changed, 1499 insertions(+) create mode 100644 drivers/crypto/qat/qat_dh895xcc/Makefile create mode 100644 drivers/crypto/qat/qat_dh895xcc/adf_admin.c create mode 100644 drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c create mode 100644 drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.h create mode 100644 drivers/crypto/qat/qat_dh895xcc/adf_drv.c create mode 100644 drivers/crypto/qat/qat_dh895xcc/adf_drv.h create mode 100644 drivers/crypto/qat/qat_dh895xcc/adf_hw_arbiter.c create mode 100644 drivers/crypto/qat/qat_dh895xcc/adf_isr.c create mode 100644 drivers/crypto/qat/qat_dh895xcc/qat_admin.c diff --git a/drivers/crypto/qat/qat_dh895xcc/Makefile b/drivers/crypto/qat/qat_dh895xcc/Makefile new file mode 100644 index 000..8e4924d --- /dev/null +++ b/drivers/crypto/qat/qat_dh895xcc/Makefile @@ -0,0 +1,8 @@ +ccflags-y := -I$(CURDIR)/drivers/crypto/qat/qat_common +obj-$(CONFIG_CRYPTO_DEV_QAT_DH895xCC) += qat_dh895xcc.o +qat_dh895xcc-objs := adf_drv.o \ + adf_isr.o \ + adf_dh895xcc_hw_data.o \ + adf_hw_arbiter.o \ + qat_admin.o \ + adf_admin.o diff --git a/drivers/crypto/qat/qat_dh895xcc/adf_admin.c b/drivers/crypto/qat/qat_dh895xcc/adf_admin.c new file mode 100644 index 000..978d6c5 --- /dev/null +++ b/drivers/crypto/qat/qat_dh895xcc/adf_admin.c @@ -0,0 +1,144 @@ +/* + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + Copyright(c) 2014 Intel Corporation. + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + Contact Information: + qat-li...@intel.com + + BSD LICENSE + Copyright(c) 2014 Intel Corporation. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* 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. +* Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS 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 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#include linux/types.h +#include linux/mutex.h +#include linux/slab.h +#include linux/delay.h +#include linux/pci.h +#include linux/dma-mapping.h +#include adf_accel_devices.h +#include adf_drv.h +#include adf_dh895xcc_hw_data.h + +#define ADF_ADMINMSG_LEN 32 + +struct adf_admin_comms { + dma_addr_t phy_addr; + void *virt_addr; + void __iomem *mailbox_addr; + struct mutex lock; /* protects adf_admin_comms
[RFC][PATCH 4/4] crypto: Updated makefiles to add QAT
Update to makefiles etc. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- Documentation/ioctl/ioctl-number.txt | 1 + MAINTAINERS | 6 ++ drivers/crypto/Kconfig | 1 + drivers/crypto/Makefile | 1 + firmware/Makefile| 1 + 5 files changed, 10 insertions(+) diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt index d7e43fa..7e240a7 100644 --- a/Documentation/ioctl/ioctl-number.txt +++ b/Documentation/ioctl/ioctl-number.txt @@ -197,6 +197,7 @@ Code Seq#(hex) Include FileComments mailto:gre...@linuxfoundation.org 'a'all linux/atm*.h, linux/sonet.h ATM on linux http://lrcwww.epfl.ch/ +'a'00-0F drivers/crypto/qat/qat_common/adf_cfg_common.h conflict! qat driver 'b'00-FF conflict! bit3 vme host bridge mailto:nata...@nikhefk.nikhef.nl 'c'all linux/cm4000_cs.h conflict! diff --git a/MAINTAINERS b/MAINTAINERS index 3467445..5482679 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7060,6 +7060,12 @@ M: Robert Jarzmik robert.jarz...@free.fr L: rtc-li...@googlegroups.com S: Maintained +QAT DRIVER +M: Tadeusz Struk tadeusz.st...@intel.com +L: qat-li...@intel.com +S: Supported +F: drivers/crypto/qat/ + QIB DRIVER M: Mike Marciniszyn infinip...@intel.com L: linux-r...@vger.kernel.org diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index f066fa2..1f20814 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -418,4 +418,5 @@ config CRYPTO_DEV_MXS_DCP To compile this driver as a module, choose M here: the module will be called mxs-dcp. +source drivers/crypto/qat/Kconfig endif # CRYPTO_HW diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 482f090..f996ed7 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -23,3 +23,4 @@ obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o obj-$(CONFIG_CRYPTO_DEV_SAHARA) += sahara.o obj-$(CONFIG_CRYPTO_DEV_TALITOS) += talitos.o obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/ +obj-$(CONFIG_CRYPTO_DEV_QAT) += qat/ diff --git a/firmware/Makefile b/firmware/Makefile index cbb09ce..89ac80b 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -135,6 +135,7 @@ fw-shipped-$(CONFIG_USB_SERIAL_XIRCOM) += keyspan_pda/xircom_pgs.fw fw-shipped-$(CONFIG_USB_VICAM) += vicam/firmware.fw fw-shipped-$(CONFIG_VIDEO_CPIA2) += cpia2/stv0672_vp4.bin fw-shipped-$(CONFIG_YAM) += yam/1200.bin yam/9600.bin +fw-shipped-$(CONFIG_CRYPTO_DEV_QAT_DH895xCC) += qat_895xcc.bin fw-shipped-all := $(fw-shipped-y) $(fw-shipped-m) $(fw-shipped-) -- 1.8.5.rc2.6.gc6f1b92.dirty -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[RFC][PATCH 0/4] crypto: Intel QAT driver
Hi, This patchset adds support for Intel Quick Assist Technology and DH895xxC hardware accelerator. First patch adds a common infractructure that will be used by all QAT devices. Second patch adds a firmware loader module that is used to load the microcode to the acceleration engines and start them. Third patch adds dh895xcc hardware specific code, which hooks to the common infrastructure and provides acceleration for the following algorithms: authenc(hmac(sha1),cbc(aes)), authenc(hmac(sha256),cbc(aes)), authenc(hmac(sha512),cbc(aes)) Forth patch updates makefiles etc. More info on the hardware accelerator and the Quick Assist can be on: https://01.org/packet-processing/intel%C2%AE-quickassist-technology-drivers-and-patches Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com Signed-off-by: Karen Xiang karen.xi...@intel.com Signed-off-by: Pingchaox Yang pingchaox.y...@intel.com Acked-by: John Griffin john.grif...@intel.com Acked-by: Bo Cui bo@intel.com Reviewed-by: Bruce W. Allan bruce.w.al...@intel.com --- drivers/crypto/Kconfig |1 + drivers/crypto/Makefile |1 + drivers/crypto/qat/qat_common/Makefile | 13 + drivers/crypto/qat/qat_common/adf_accel_devices.h | 204 +++ drivers/crypto/qat/qat_common/adf_accel_engine.c| 168 drivers/crypto/qat/qat_common/adf_aer.c | 258 +++ drivers/crypto/qat/qat_common/adf_cfg.c | 359 ++ drivers/crypto/qat/qat_common/adf_cfg.h | 87 +++ drivers/crypto/qat/qat_common/adf_cfg_common.h | 100 drivers/crypto/qat/qat_common/adf_cfg_strings.h | 83 ++ drivers/crypto/qat/qat_common/adf_cfg_user.h| 94 +++ drivers/crypto/qat/qat_common/adf_common_drv.h | 192 ++ drivers/crypto/qat/qat_common/adf_ctl_drv.c | 490 +++ drivers/crypto/qat/qat_common/adf_dev_mgr.c | 215 drivers/crypto/qat/qat_common/adf_init.c| 388 drivers/crypto/qat/qat_common/adf_transport.c | 565 + drivers/crypto/qat/qat_common/adf_transport.h | 63 + drivers/crypto/qat/qat_common/adf_transport_access_macros.h | 160 drivers/crypto/qat/qat_common/adf_transport_debug.c | 301 ++ drivers/crypto/qat/qat_common/adf_transport_internal.h | 115 + drivers/crypto/qat/qat_common/icp_qat_fw.h | 316 +++ drivers/crypto/qat/qat_common/icp_qat_fw_init_admin.h | 131 ++ drivers/crypto/qat/qat_common/icp_qat_fw_la.h | 403 + drivers/crypto/qat/qat_common/icp_qat_fw_loader_handle.h| 78 ++ drivers/crypto/qat/qat_common/icp_qat_hal.h | 125 + drivers/crypto/qat/qat_common/icp_qat_hw.h | 305 ++ drivers/crypto/qat/qat_common/icp_qat_uclo.h| 377 +++ drivers/crypto/qat/qat_common/qat_algs.c| 1033 ++ drivers/crypto/qat/qat_common/qat_crypto.c | 284 + drivers/crypto/qat/qat_common/qat_crypto.h | 83 ++ drivers/crypto/qat/qat_common/qat_hal.c | 1402 + drivers/crypto/qat/qat_common/qat_uclo.c| 1191 + drivers/crypto/qat/qat_dh895xcc/Makefile|8 + drivers/crypto/qat/qat_dh895xcc/adf_admin.c | 144 +++ drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c | 214 drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.h | 86 +++ drivers/crypto/qat/qat_dh895xcc/adf_drv.c | 448 drivers/crypto/qat/qat_dh895xcc/adf_drv.h | 67 + drivers/crypto/qat/qat_dh895xcc/adf_hw_arbiter.c| 159 drivers/crypto/qat/qat_dh895xcc/adf_isr.c | 266 +++ drivers/crypto/qat/qat_dh895xcc/qat_admin.c | 107 firmware/Makefile |1 + 44 files changed, 11092 insertions(+) create mode 100644 drivers/crypto/qat/qat_common/Makefile create mode 100644 drivers/crypto/qat/qat_common/adf_accel_devices.h create mode 100644 drivers/crypto/qat/qat_common/adf_accel_engine.c
Re: [RFC][PATCH 4/4] crypto: Updated makefiles to add QAT
On 06/03/2014 12:16 PM, Randy Dunlap wrote: +source drivers/crypto/qat/Kconfig Missing that file ^^^ Hi, Something went wrong. I need to resend v2. Thanks Randy -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH RFC 1/2] crypto: Simple crypto algorithm load balancer
Hi, In case of multiple crypto devices implementing the same algorithms the arbitration, which one to use is based on the cra_priority. Currently the algorithm with the highest priority is always be used. In case of two algorithms with the same priority the one added last is used. There is no load balancing and on a busy system there can be a situation when there more crypto accelerators, but only one is used for all crypto jobs and the others sit idle. This patch implements a simple load balancing based on the priority of an algorithm and its usage refctr. The distribution for 10 algorithms and 300 tfm_alloc allocations is as follows: === Algorithm load balancig test results for 300 allocatoins === All different alg priorities: Algorithm 1 with cra_pri 1 allocated 3 times. That's ~0% Algorithm 2 with cra_pri 2 allocated 10 times. That's ~0% Algorithm 3 with cra_pri 3 allocated 38 times. That's ~0% Algorithm 4 with cra_pri 4 allocated 168 times. That's ~0% Algorithm 5 with cra_pri 5 allocated 781 times. That's ~0% Algorithm 6 with cra_pri 6 allocated 3757 times. That's ~0% Algorithm 7 with cra_pri 7 allocated 18483 times. That's ~0% Algorithm 8 with cra_pri 8 allocated 92540 times. That's ~3% Algorithm 9 with cra_pri 9 allocated 469918 times. That's ~15% Algorithm 10 with cra_pri 10 allocated 2414312 times. That's ~80% All the same alg priorities: Algorithm 1 with cra_pri 10 allocated 297521 times. That's ~9% Algorithm 2 with cra_pri 10 allocated 297521 times. That's ~9% Algorithm 3 with cra_pri 10 allocated 297521 times. That's ~9% Algorithm 4 with cra_pri 10 allocated 297522 times. That's ~9% Algorithm 5 with cra_pri 10 allocated 297522 times. That's ~9% Algorithm 6 with cra_pri 10 allocated 297522 times. That's ~9% Algorithm 7 with cra_pri 10 allocated 297522 times. That's ~9% Algorithm 8 with cra_pri 10 allocated 297522 times. That's ~9% Algorithm 9 with cra_pri 10 allocated 297522 times. That's ~9% Algorithm 10 with cra_pri 10 allocated 297522 times. That's ~9% A mix of alg priorities: Algorithm 1 with cra_pri 9 allocated 1938 times. That's ~0% Algorithm 2 with cra_pri 4 allocated 8 times. That's ~0% Algorithm 3 with cra_pri 1 allocated 2 times. That's ~0% Algorithm 4 with cra_pri 4 allocated 9 times. That's ~0% Algorithm 5 with cra_pri 5 allocated 62 times. That's ~0% Algorithm 6 with cra_pri 20 allocated 157052 times. That's ~5% Algorithm 7 with cra_pri 21 allocated 1410070 times. That's ~47% Algorithm 8 with cra_pri 10 allocated 10215 times. That's ~0% Algorithm 9 with cra_pri 21 allocated 1420284 times. That's ~47% Algorithm 10 with cra_pri 7 allocated 370 times. That's ~0% A mix of alg priorities with one very big: Algorithm 1 with cra_pri 9 allocated 6 times. That's ~0% Algorithm 2 with cra_pri 4 allocated 1 times. That's ~0% Algorithm 3 with cra_pri 1 allocated 1 times. That's ~0% Algorithm 4 with cra_pri 4 allocated 1 times. That's ~0% Algorithm 5 with cra_pri 500 allocated 2993808 times. That's ~99% Algorithm 6 with cra_pri 20 allocated 346 times. That's ~0% Algorithm 7 with cra_pri 21 allocated 2899 times. That's ~0% Algorithm 8 with cra_pri 10 allocated 23 times. That's ~0% Algorithm 9 with cra_pri 21 allocated 2922 times. That's ~0% Algorithm 10 with cra_pri 7 allocated 3 times. That's ~0% Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/api.c | 25 ++--- include/linux/crypto.h |3 ++- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/crypto/api.c b/crypto/api.c index a2b39c5..0c0f1c3 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -63,7 +63,7 @@ static struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, int best = -2; list_for_each_entry(q, crypto_alg_list, cra_list) { - int exact, fuzzy; + int exact, fuzzy, relative_priority; if (crypto_is_moribund(q)) continue; @@ -78,13 +78,15 @@ static struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, exact = !strcmp(q-cra_driver_name, name); fuzzy = !strcmp(q-cra_name, name); - if (!exact !(fuzzy q-cra_priority best)) + relative_priority = q-cra_priority - + atomic_read(q-cra_lbalance); + if (!exact !(fuzzy relative_priority best)) continue; if (unlikely(!crypto_mod_get(q))) continue; - best = q-cra_priority; + best = relative_priority; if (alg) crypto_mod_put(alg); alg = q; @@ -92,6 +94,23 @@ static struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, if (exact) break; } + if (!alg) { + list_for_each_entry(q, crypto_alg_list, cra_list
[PATCH RFC 2/2] crypto: Simple load balancer test module
Test module for the simple algorithm load balancer Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/Kconfig|6 ++ crypto/Makefile |1 + crypto/test_alg_loadbalance.c | 231 + 3 files changed, 247 insertions(+) create mode 100644 crypto/test_alg_loadbalance.c diff --git a/crypto/Kconfig b/crypto/Kconfig index 7bcb70d..85e1bc2 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1404,6 +1404,12 @@ config CRYPTO_USER_API_SKCIPHER config CRYPTO_HASH_INFO bool +config CRYPTO_ALG_LOAD_BALANCE_TEST + tristate Crypto Algorithm load balancer test module + default n + help + This option enables the crypto algorithm load balancer test module. + source drivers/crypto/Kconfig source crypto/asymmetric_keys/Kconfig diff --git a/crypto/Makefile b/crypto/Makefile index b29402a..5a49e2a 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -97,6 +97,7 @@ obj-$(CONFIG_CRYPTO_GHASH) += ghash-generic.o obj-$(CONFIG_CRYPTO_USER_API) += af_alg.o obj-$(CONFIG_CRYPTO_USER_API_HASH) += algif_hash.o obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o +obj-$(CONFIG_CRYPTO_ALG_LOAD_BALANCE_TEST) += test_alg_loadbalance.o # # generic algorithms and the async_tx api diff --git a/crypto/test_alg_loadbalance.c b/crypto/test_alg_loadbalance.c new file mode 100644 index 000..2637247 --- /dev/null +++ b/crypto/test_alg_loadbalance.c @@ -0,0 +1,231 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ + +#include linux/err.h +#include linux/module.h +#include linux/crypto.h +#include linux/string.h +#include crypto/algapi.h + +static int encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + return 0; +} +static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) +{ + return 0; +} + + +#define loops 300 +static struct crypto_ablkcipher *tfms[loops]; + +static struct crypto_alg tmp = { + .cra_name = test, + .cra_driver_name= test_driver, + .cra_priority = 1, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER, + .cra_module = THIS_MODULE, + .cra_ctxsize= 0, + .cra_type = crypto_blkcipher_type, + .cra_u = { + .blkcipher = { + .min_keysize= 64, + .max_keysize= 64, + .ivsize = 64, + .setkey = setkey, + .encrypt= encrypt, + .decrypt= encrypt, + }, + }, + }; +static struct crypto_alg algs[10] = { + { { 0 } }, + { { 0 } }, + { { 0 } }, + { { 0 } }, + { { 0 } }, + { { 0 } }, + { { 0 } }, + { { 0 } }, + { { 0 } }, + { { 0 } }, +}; + +static int __init cra_lbtest_init(void) +{ + int i; + + for (i = 0; i 10; i++) { + algs[i] = tmp; + algs[i].cra_priority += i; + } + + if (crypto_register_algs(algs, 10)) + return -1; + + for (i = 0; i loops; i++) { + tfms[i] = crypto_alloc_ablkcipher(test, 0, 0); + if (IS_ERR(tfms[i])) + return PTR_ERR(tfms[i]); + } + pr_info(Algorithm load balancig test results for %d allocatoins\n, + loops); + pr_info(All different alg priorities:\n); + for (i = 0; i 10; i++) { + unsigned long times = atomic_read(algs[i].cra_refcnt); + unsigned long percent = (times * 100) / loops; + + pr_info(Alg with cra_pri %d allocated %lu times. That's ~%lu%%\n, + algs[i].cra_priority, times, percent); + + } + for (i = 0; i loops; i++) + crypto_free_ablkcipher(tfms[i]); + + crypto_unregister_algs(algs, 10); + + for (i = 0; i 10; i++) { + algs[i] = tmp; + algs[i].cra_priority = 10; + } + if (crypto_register_algs(algs, 10)) + return -1; + + for (i = 0; i loops; i++) { + tfms[i] = crypto_alloc_ablkcipher(test, 0, 0); + if (IS_ERR(tfms[i])) + return PTR_ERR(tfms[i]); + } + pr_info(All same alg priorities:\n); + for (i = 0; i 10; i++) { + unsigned long times = atomic_read(algs[i].cra_refcnt
Re: [PATCH v4 6/7] sched: add function nr_running_cpu to expose number of tasks running on cpu
On 07/11/2014 01:33 PM, Tim Chen wrote: +unsigned long nr_running_cpu(int cpu) +{ + if (cpumask_test_cpu(cpu, cpu_online_mask)) + return cpu_rq(cpu)-nr_running; + else + return 0; +} + EXPORT_SYMBOL? -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] firmware: Automatically pull missing FW files
Hi, When a binary FW file is not present in the firmware dir then the build will fail. This patch enables auto-download any missing FW file for both shipped and external targets. Generated against linux-next. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- firmware/Makefile | 25 +++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/firmware/Makefile b/firmware/Makefile index 5747417..3ad12f6 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -178,10 +178,31 @@ wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h \ include/config/superh32.h include/config/superh64.h \ include/config/x86_32.h include/config/x86_64.h) -$(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps) +FW_URL := git.kernel.org/cgit/linux/kernel/git/firmware/linux-firmware.git/plain + +.NOTPARALLEL: get_missing_external $(patsubst %,$(obj)/%.gen.S, $(fw-external-y)) +.NOTPARALLEL: get_missing_shipped $(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)) + +get_missing_shipped: + @for file in $(fw-shipped-y) $(fw-shipped-m); do \ + if [ ! -f $(obj)/$$file ]; then \ + wget $(FW_URL)/$$file -o /dev/null -O $(obj)/$$file; \ + fi; \ + done; + +get_missing_external: + @for file in $(fw-external-y); do \ + if [ ! -f $(obj)/$$file ]; then \ + wget $(FW_URL)/$$file -o /dev/null -O $(obj)/$$file; \ + fi; \ + done; + +$(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps) \ + get_missing_shipped $(call cmd,fwbin,$(patsubst %.gen.S,%,$@)) + $(patsubst %,$(obj)/%.gen.S, $(fw-external-y)): %: $(wordsize_deps) \ - include/config/extra/firmware/dir.h + include/config/extra/firmware/dir.h get_missing_external $(call cmd,fwbin,$(fwabs)/$(patsubst $(obj)/%.gen.S,%,$@)) # The .o files depend on the binaries directly; the .S files don't. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] firmware: Automatically pull missing FW files
Hi David, On 08/20/2014 11:34 AM, David Woodhouse wrote: I'm not sure I understand. Precisely what fails? I clone a subsystem, configure it to use CONFIG_EXTRA_FIRMWARE=qat_895xcc.bin, type make make install and get: MK_FW firmware/qat_895xxc.bin.gen.S make[1]: *** No rule to make target `firmware/qat_895xxc.bin', needed by `firmware/qat_895xxc.bin.gen.o'. Stop. I thought it might be useful if it would pull whatever FW it needs and not just give up. It also might be useful if one wants to refresh the FW binaries. In this case one can do rm firmware/*.[bin|ihex] make make install I don't like this patch very much. We should be removing the legacy firmware/ directory entirely, not patching it up. Userspace is responsible for providing the firmware, and it should generally come from an entirely separate checkout of the linux-firmware repository. Yes, if you use udev helper. When you want to compile in the blobs to your kernel it is needed in build time, right? In both cases you need the binary anyway so you can copy it manually from linux-firmware or use this nice feature to do it for you. If you want to remove firmware/ directory entirely then this makefile will be gone as well so what's the problem? -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] firmware: Automatically pull missing FW files
On 08/20/2014 01:39 PM, David Woodhouse wrote: On Wed, 2014-08-20 at 12:21 -0700, Tadeusz Struk wrote: Hi David, On 08/20/2014 11:34 AM, David Woodhouse wrote: I'm not sure I understand. Precisely what fails? I clone a subsystem, configure it to use CONFIG_EXTRA_FIRMWARE=qat_895xcc.bin, type make make install and get: MK_FW firmware/qat_895xxc.bin.gen.S make[1]: *** No rule to make target `firmware/qat_895xxc.bin', needed by `firmware/qat_895xxc.bin.gen.o'. Stop. Can't you already just use CONFIG_EXTRA_FIRMWARE_DIR ? What for? The point is that you don't have the FW binary file and you have to download it, which can happen automatically and this is what this patch does. The director where it will be stored doesn't really matter here. Yes, if you use udev helper. When you want to compile in the blobs to your kernel it is needed in build time, right? Yes. But seriously: don't do that. Let firmware get loaded from userspace the normal way. Don't build kernel images that you can't distribute because they include non-GPL parts. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] crypto, qat, use generic numa functions
Hi Prarit, On 10/07/2014 05:12 PM, Prarit Bhargava wrote: The method in which the qat code determines the numa node for memory allocations is a bit clunky. On 2 socket, single node systems it is possible that adf_get_dev_node_id() returns node 1, even though node 1 doesn't exist. This code transitions the qat code to the generic numa functions. Changing adf_get_dev_node_id() to a simple call to dev_get_node() results in a change to the adf_accel_dev struct as well. The problem with that is we don't want to use any valid numa node, but the node we are connected to or we don't want to use the accelerator at all. Otherwise, when the first valid numa node happens to be the remote node the dma transactions we be slow and instead of accelerating we will slow things down. A patch that enforces this is on it's way. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2 01/11] crypto: Documentation - crypto API high level spec
Hi, On 11/02/2014 12:35 PM, Stephan Mueller wrote: + * type: + - blkcipher for symmetric block ciphers blkcipher for synchronous block ciphers + - ablkcipher for asymmetric block ciphers ablkcipher for asynchronous block ciphers + - cipher for single block ciphers that may be used with an + additional template + - shash for symmetric message digest shash for synchronous message digest + - ahash for asymmetric message digest ahash for asynchronous message digest T. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 0/3] crypto: algif - change algif_skcipher to be asynchronous
On 02/01/2015 10:31 AM, Stephan Mueller wrote: Hi Tadeusz, The way the algif_skcipher works currently is that on sendmsg/sendpage it builds an sgl for the input data and then on read/recvmsg it sends the job for encryption putting the user to sleep till the data is processed. This way it can only handle one job at a given time. To be able to fuly utilize the potential of existing crypto hardware accelerators it is required to submit multiple jobs in asynchronously. First patch enables asynchronous read and write on socket. Second patch enables af_alg sgl to be linked. Third patch implement asynch read for skcipher. Do you have a code fragment on how to test that patch? I would like to see whether I can test that with my libkcapi. Hi Stephan, This is what I'm using. #include unistd.h #include fcntl.h #include stdio.h #include errno.h #include string.h #include sys/socket.h #include sys/types.h #include linux/types.h #include linux/aio_abi.h #include sys/syscall.h #include sys/uio.h #define SOL_ALG 279 #define SPLICE_F_GIFT (0x08) /* pages passed in are a gift */ struct sockaddr_alg { __u16 salg_family; __u8salg_type[14]; __u32 salg_feat; __u32 salg_mask; __u8salg_name[64]; }; struct af_alg_iv { __u32 ivlen; __u8iv[0]; }; /* Socket options */ #define ALG_SET_KEY 1 #define ALG_SET_IV 2 #define ALG_SET_OP 3 #define ALG_SET_AEAD_ASSOCLEN 4 #define ALG_SET_AEAD_AUTHSIZE 5 /* Operations */ #define ALG_OP_DECRYPT 0 #define ALG_OP_ENCRYPT 1 #define BUFFSIZE (4096) //#define BUFFSIZE (4096) #define PKGSIZE (4096) #define INFLIGTHS 256 #define TO_SEND (1024 * 1024) //#define OUT_OFFSET 2048; //#define IN_OFFSET 4064; #define OUT_OFFSET 0; #define IN_OFFSET 0; static char buf[BUFFSIZE] __attribute__((__aligned__(BUFFSIZE))); static char *buf_out = buf; static inline int io_setup(unsigned n, aio_context_t *ctx) { return syscall(__NR_io_setup, n, ctx); } static inline int io_destroy(aio_context_t ctx) { return syscall(__NR_io_destroy, ctx); } static inline int io_read(aio_context_t ctx, long n, struct iocb **iocb) { return syscall(__NR_io_submit, ctx, n, iocb); } static inline int io_getevents(aio_context_t ctx, long min, long max, struct io_event *events, struct timespec *timeout) { return syscall(__NR_io_getevents, ctx, min, max, events, timeout); } static inline int eventfd(int n) { return syscall(__NR_eventfd, n); } static int crypt_kernel(const char *key, char *oiv, int zcp) { int opfd; int tfmfd; int efd; struct timespec timeout; fd_set rfds; struct timeval tv; struct sockaddr_alg sa = { .salg_family = AF_ALG, .salg_type = skcipher, .salg_name = cbc(aes) }; struct msghdr msg = {}; struct cmsghdr *cmsg; char cbuf[CMSG_SPACE(4) + CMSG_SPACE(20)] = {}; struct aes_iv { __u32 len; __u8 iv[16]; } *iv; struct iovec iov; int pipes[2]; aio_context_t aio_ctx; struct iocb *cb; struct iocb cbt[INFLIGTHS]; struct io_event events[INFLIGTHS]; unsigned int received = 0; int i, r; timeout.tv_sec = 0; timeout.tv_nsec = 0; pipe(pipes); memset(cbt, 0, sizeof(cbt)); efd = eventfd(0); tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0); bind(tfmfd, (struct sockaddr *)sa, sizeof(sa)); setsockopt(tfmfd, SOL_ALG, ALG_SET_KEY, key, 16); opfd = accept(tfmfd, NULL, 0); msg.msg_control = cbuf; msg.msg_controllen = sizeof(cbuf); cmsg = CMSG_FIRSTHDR(msg); cmsg-cmsg_level = SOL_ALG; cmsg-cmsg_type = ALG_SET_OP; cmsg-cmsg_len = CMSG_LEN(4); *(__u32 *)CMSG_DATA(cmsg) = ALG_OP_ENCRYPT; cmsg = CMSG_NXTHDR(msg, cmsg); cmsg-cmsg_level = SOL_ALG; cmsg-cmsg_type = ALG_SET_IV; cmsg-cmsg_len = CMSG_LEN(20); iv = (void *)CMSG_DATA(cmsg); iv-len = 16; memcpy(iv-iv, oiv, 16); iov.iov_base = buf + IN_OFFSET; iov.iov_len = PKGSIZE; msg.msg_flags = MSG_MORE; aio_ctx = 0; r = io_setup(INFLIGTHS, aio_ctx); if (r 0) { perror(io_setup error); return -1; } for (i = 0; i TO_SEND; i++) { if (zcp) { msg.msg_iovlen = 0; msg.msg_iov = NULL; r = sendmsg(opfd, msg, 0); if (r 0) printf(sendmsg returned Error: %d\n, errno); r = vmsplice(pipes[1], iov, 1, SPLICE_F_GIFT); if
Re: [PATCH] crypto: aesni: add setkey for driver-gcm-aes-aesni
On 01/18/2015 02:56 PM, Stephan Mueller wrote: The cipher registered as __driver-gcm-aes-aesni is never intended to be used directly by any caller. Instead it is a service mechanism to rfc4106-gcm-aesni. The kernel crypto API unconditionally calls the registered setkey function. In case a caller erroneously uses __driver-gcm-aes-aesni a call to crypto_aead_setkey will cause a NULL pointer dereference without this patch. Acked-by: Tadeusz Struk tadeusz.st...@intel.com -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: Intel GCM: __driver-gcm-aes-aesni setkey missing
Hi Stephan, On 01/17/2015 10:23 AM, Stephan Mueller wrote: during testing of my algif_aead patch with the different GCM implementations I am able to trigger a kernel crash from user space using __driver-gcm-aes- aesni. As I hope that algif_aead is going to be included, unprivileged userspace would then reliably crash the kernel -- with the current kernel code, userspace has no interface to trigger the issue. Yes, that's a problem. As I am not sure what the purpose of __driver-gcm-aes-aesni is (only a backend for RFC4106 GCM or a regular cipher), I did not yet create a patch. IMHO there are two solutions: - either create a valid setkey callback so that a key is set - or create a noop setkey that returns -EOPNOTSUPP which effectively disables that cipher for regular consumption. __driver-gcm-aes-aesni is only a helper for rfc4106-gcm-aesni and it never supposed to be used on it's own. I think implementing a setkey function that only returns an error would be a good solution for this. Another question is what if someone will ignore the error or skip the setsockopt(ALG_SET_KEY) altogether and still call the sendmsg() and read() to trigger encrypt()? Note, if it is only a backend for the RFC4106 implementation, may I ask why __driver-gcm-aes-aesni is implemented as a separate cipher that is registered with the kernel crypto API? This is because we need to have one instance of the helper tfm with its context per each of the rfc4106-gcm-aesni tfm instance and that was one convenient way to do this. Tadeusz -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] crypto: aesni: add setkey for driver-gcm-aes-aesni
On 01/22/2015 01:20 PM, Stephan Mueller wrote: That would be correct. But if I understood Herbert correctly, he is creating a patch that disables these service ciphers for general usage. Yes, and this should also implicitly fix the problem with user space. Thanks, Tadeusz -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] crypto: aesni: add setkey for driver-gcm-aes-aesni
On 01/22/2015 02:23 PM, Herbert Xu wrote: Yes but we should also fix this so that it's a proper aead algorithm. Ok, I'll do that. Thanks, Tadeusz -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] crypto: aesni: add setkey for driver-gcm-aes-aesni
On 01/20/2015 05:25 PM, Stephan Mueller wrote: Rather than adding a bogus setkey function, please fix this mess properly by moving the top-level setkey function into the __driver one where it should be. Compare with how we handle it in the ablk_helper which is pretty much the same thing. Tadeusz, are you working on that update or shall I have a look? Hi, No, I thought that the agreement was that we don't want to allow user space to use these helpers directly, right? Am I missing something? -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/3] net: socket: enable async read and write
On 01/29/2015 03:13 PM, Tadeusz Struk wrote: AIO read or write are not currently supported on sockets. This patch enables real socket async read/write. Please note - this patch is generated against cryptodev. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- include/net/sock.h |2 ++ net/socket.c | 48 ++-- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 2210fec..2c7d160 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1397,6 +1397,8 @@ static inline struct kiocb *siocb_to_kiocb(struct sock_iocb *si) return si-kiocb; } +void sock_aio_complete(struct kiocb *iocb, long res, long res2); + struct socket_alloc { struct socket socket; struct inode vfs_inode; diff --git a/net/socket.c b/net/socket.c index a2c33a4..368fa9f 100644 --- a/net/socket.c +++ b/net/socket.c @@ -866,14 +866,25 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos, return sock-ops-splice_read(sock, ppos, pipe, len, flags); } +void sock_aio_complete(struct kiocb *iocb, long res, long res2) +{ + struct sock_iocb *siocb = kiocb_to_siocb(iocb); + + kfree(siocb); + aio_complete(iocb, res, res2); +} +EXPORT_SYMBOL(sock_aio_complete); + static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb, struct sock_iocb *siocb) { - if (!is_sync_kiocb(iocb)) - BUG(); + if (!siocb) + siocb = kmalloc(sizeof(*siocb), GFP_KERNEL); - siocb-kiocb = iocb; - iocb-private = siocb; + if (siocb) { + siocb-kiocb = iocb; + iocb-private = siocb; + } return siocb; } @@ -901,7 +912,8 @@ static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb, static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { - struct sock_iocb siocb, *x; + struct sock_iocb siocb, *x = NULL; + int ret; if (pos != 0) return -ESPIPE; @@ -909,11 +921,18 @@ static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, if (iocb-ki_nbytes == 0) /* Match SYS5 behaviour */ return 0; + if (is_sync_kiocb(iocb)) + x = siocb; - x = alloc_sock_iocb(iocb, siocb); + x = alloc_sock_iocb(iocb, x); if (!x) return -ENOMEM; - return do_sock_read(x-async_msg, iocb, iocb-ki_filp, iov, nr_segs); + ret = do_sock_read(x-async_msg, iocb, iocb-ki_filp, iov, nr_segs); + + if (!is_sync_kiocb(iocb) ret != -EIOCBQUEUED) + kfree(x); + + return ret; } static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb, @@ -942,16 +961,25 @@ static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb, static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { - struct sock_iocb siocb, *x; + struct sock_iocb siocb, *x = NULL; + int ret; if (pos != 0) return -ESPIPE; - x = alloc_sock_iocb(iocb, siocb); + if (is_sync_kiocb(iocb)) + x = siocb; + + x = alloc_sock_iocb(iocb, x); if (!x) return -ENOMEM; - return do_sock_write(x-async_msg, iocb, iocb-ki_filp, iov, nr_segs); + ret = do_sock_write(x-async_msg, iocb, iocb-ki_filp, iov, nr_segs); + + if (!is_sync_kiocb(iocb) ret != -EIOCBQUEUED) + kfree(x); + + return ret; } /* Hi Herbert, Just noticed that the struct sock_iocb has just been removed on net-next (see [1]). What we can do is to call aio_complete() directly from algif_skcipher, assuming that it is ok to call asynchronous read or write with the struct msghdr allocated on the stack. Please let me know what you think. Thanks, Tadeusz [1] https://git.kernel.org/cgit/linux/kernel/git/davem/net-next.git/commit/?id=7cc05662682da4b0e0a4fdf3c3f190577803ae81 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: linux-next: build warnings after merge of the crypto tree
On 03/09/2015 11:03 PM, Herbert Xu wrote: This is a bit of a bummer. What happened is that net-next has killed the kiocb argument to sendmsg/recvmsg. However, this change is obviously not part of the crypto tree and algif_aead only exists in the crypto tree. So Stephen could you fix this by hand until one of them is merged upstream (just kill the first argument in aead_sendmsg/aead_recvmsg)? So does it mean that aio operations will not be supported on sockets? -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v12 1/2] crypto: AF_ALG: add AEAD support
On 02/27/2015 02:26 AM, Stephan Mueller wrote: This patch adds the AEAD support for AF_ALG. The implementation is based on algif_skcipher, but contains heavy modifications to streamline the interface for AEAD uses. To use AEAD, the user space consumer has to use the salg_type named aead. I just saw Al Viro's patch to use the iov_iter API in algif_skcipher.c. I looked at it but lacked documentation for using it properly. Now I have a template that I will incorporate into algif_aead.c Please resubmit once you have done this. I have done that, but as indicated with an email to Al, I cannot get his patch for skcipher and hash to work. Similarly, my modification for the AEAD does not work either. So, I do not see that Al's patch can be merged as is. Therefore, I have not submitted my patch as Al mentioned he wanted to look into his patchset. Hi Stephan, There was a problem with the iov_iter changes, but it has been fixed on netdev during merging window. The algif_skcipher works fine for me on the latest (4.0.0-rc1+) cryptodev. Regards, Tadeusz -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2/3] crypto: af_alg - Allow to link sgl
Allow to link af_alg sgls. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/af_alg.c | 16 include/crypto/if_alg.h |4 +++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/crypto/af_alg.c b/crypto/af_alg.c index 76d739d..99608f2 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -374,7 +374,8 @@ int af_alg_make_sg(struct af_alg_sgl *sgl, void __user *addr, int len, err = 0; - sg_init_table(sgl-sg, npages); + /* Add one extra for linking */ + sg_init_table(sgl-sg, npages + 1); for (i = 0; i npages; i++) { int plen = min_t(int, len, PAGE_SIZE - off); @@ -385,20 +386,27 @@ int af_alg_make_sg(struct af_alg_sgl *sgl, void __user *addr, int len, len -= plen; err += plen; } + sg_mark_end(sgl-sg + npages - 1); + sgl-npages = npages; out: return err; } EXPORT_SYMBOL_GPL(af_alg_make_sg); +void af_alg_link_sg(struct af_alg_sgl *sgl_prev, struct af_alg_sgl *sgl_new) +{ + sg_unmark_end(sgl_prev-sg + sgl_prev-npages - 1); + sg_chain(sgl_prev-sg, sgl_prev-npages + 1, sgl_new-sg); +} +EXPORT_SYMBOL(af_alg_link_sg); + void af_alg_free_sg(struct af_alg_sgl *sgl) { int i; - i = 0; - do { + for (i = 0; i sgl-npages; i++) put_page(sgl-pages[i]); - } while (!sg_is_last(sgl-sg + (i++))); } EXPORT_SYMBOL_GPL(af_alg_free_sg); diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h index 5c7b6c5..0908050 100644 --- a/include/crypto/if_alg.h +++ b/include/crypto/if_alg.h @@ -58,8 +58,9 @@ struct af_alg_type { }; struct af_alg_sgl { - struct scatterlist sg[ALG_MAX_PAGES]; + struct scatterlist sg[ALG_MAX_PAGES + 1]; struct page *pages[ALG_MAX_PAGES]; + unsigned int npages; }; int af_alg_register_type(const struct af_alg_type *type); @@ -71,6 +72,7 @@ int af_alg_accept(struct sock *sk, struct socket *newsock); int af_alg_make_sg(struct af_alg_sgl *sgl, void __user *addr, int len, int write); void af_alg_free_sg(struct af_alg_sgl *sgl); +void af_alg_link_sg(struct af_alg_sgl *sgl_prev, struct af_alg_sgl *sgl_new); int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con); -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 0/3] crypto: algif - change algif_skcipher to be asynchronous
The way the algif_skcipher works currently is that on sendmsg/sendpage it builds an sgl for the input data and then on read/recvmsg it sends the job for encryption putting the user to sleep till the data is processed. This way it can only handle one job at a given time. To be able to fuly utilize the potential of existing crypto hardware accelerators it is required to submit multiple jobs in asynchronously. First patch enables asynchronous read and write on socket. Second patch enables af_alg sgl to be linked. Third patch implement asynch read for skcipher. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- Tadeusz Struk (3): net: socket: enable async read and write crypto: af_alg - Allow to link sgl crypto: algif - change algif_skcipher to be asynchronous crypto/af_alg.c | 16 ++ crypto/algif_skcipher.c | 315 ++- include/crypto/if_alg.h |4 - include/net/sock.h |2 net/socket.c| 48 ++- 5 files changed, 364 insertions(+), 21 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/3] net: socket: enable async read and write
AIO read or write are not currently supported on sockets. This patch enables real socket async read/write. Please note - this patch is generated against cryptodev. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- include/net/sock.h |2 ++ net/socket.c | 48 ++-- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 2210fec..2c7d160 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1397,6 +1397,8 @@ static inline struct kiocb *siocb_to_kiocb(struct sock_iocb *si) return si-kiocb; } +void sock_aio_complete(struct kiocb *iocb, long res, long res2); + struct socket_alloc { struct socket socket; struct inode vfs_inode; diff --git a/net/socket.c b/net/socket.c index a2c33a4..368fa9f 100644 --- a/net/socket.c +++ b/net/socket.c @@ -866,14 +866,25 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos, return sock-ops-splice_read(sock, ppos, pipe, len, flags); } +void sock_aio_complete(struct kiocb *iocb, long res, long res2) +{ + struct sock_iocb *siocb = kiocb_to_siocb(iocb); + + kfree(siocb); + aio_complete(iocb, res, res2); +} +EXPORT_SYMBOL(sock_aio_complete); + static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb, struct sock_iocb *siocb) { - if (!is_sync_kiocb(iocb)) - BUG(); + if (!siocb) + siocb = kmalloc(sizeof(*siocb), GFP_KERNEL); - siocb-kiocb = iocb; - iocb-private = siocb; + if (siocb) { + siocb-kiocb = iocb; + iocb-private = siocb; + } return siocb; } @@ -901,7 +912,8 @@ static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb, static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { - struct sock_iocb siocb, *x; + struct sock_iocb siocb, *x = NULL; + int ret; if (pos != 0) return -ESPIPE; @@ -909,11 +921,18 @@ static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, if (iocb-ki_nbytes == 0) /* Match SYS5 behaviour */ return 0; + if (is_sync_kiocb(iocb)) + x = siocb; - x = alloc_sock_iocb(iocb, siocb); + x = alloc_sock_iocb(iocb, x); if (!x) return -ENOMEM; - return do_sock_read(x-async_msg, iocb, iocb-ki_filp, iov, nr_segs); + ret = do_sock_read(x-async_msg, iocb, iocb-ki_filp, iov, nr_segs); + + if (!is_sync_kiocb(iocb) ret != -EIOCBQUEUED) + kfree(x); + + return ret; } static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb, @@ -942,16 +961,25 @@ static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb, static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { - struct sock_iocb siocb, *x; + struct sock_iocb siocb, *x = NULL; + int ret; if (pos != 0) return -ESPIPE; - x = alloc_sock_iocb(iocb, siocb); + if (is_sync_kiocb(iocb)) + x = siocb; + + x = alloc_sock_iocb(iocb, x); if (!x) return -ENOMEM; - return do_sock_write(x-async_msg, iocb, iocb-ki_filp, iov, nr_segs); + ret = do_sock_write(x-async_msg, iocb, iocb-ki_filp, iov, nr_segs); + + if (!is_sync_kiocb(iocb) ret != -EIOCBQUEUED) + kfree(x); + + return ret; } /* -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 3/3] crypto: algif - change algif_skcipher to be asynchronous
The way the algif_skcipher works currently is that on sendmsg/sendpage it builds an sgl for the input data and then on read/recvmsg it sends the job for encryption putting the user to sleep till the data is processed. This way it can only handle one job at a given time. This patch changes it to be asynchronous by adding AIO support. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/algif_skcipher.c | 315 ++- 1 file changed, 309 insertions(+), 6 deletions(-) diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index 38a6757..c953200 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -19,9 +19,11 @@ #include linux/list.h #include linux/kernel.h #include linux/mm.h +#include linux/mempool.h #include linux/module.h #include linux/net.h #include net/sock.h +#include linux/aio.h struct skcipher_sg_list { struct list_head list; @@ -39,6 +41,9 @@ struct skcipher_ctx { struct af_alg_completion completion; + struct kmem_cache *cache; + mempool_t *pool; + atomic_t inflight; unsigned used; unsigned int len; @@ -49,9 +54,135 @@ struct skcipher_ctx { struct ablkcipher_request req; }; +struct skcipher_async_rsgl { + struct af_alg_sgl sgl; + struct list_head list; +}; + +struct skcipher_async_req { + struct kiocb *iocb; + struct skcipher_async_rsgl first_sgl; + struct list_head list; + struct scatterlist *tsg; + char iv[]; +}; + +#define GET_SREQ(areq, ctx) (struct skcipher_async_req *)((char *)areq + \ + crypto_ablkcipher_reqsize(crypto_ablkcipher_reqtfm(ctx-req))) + +#define GET_REQ_SIZE(ctx) \ + crypto_ablkcipher_reqsize(crypto_ablkcipher_reqtfm(ctx-req)) + +#define GET_IV_SIZE(ctx) \ + crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(ctx-req)) + #define MAX_SGL_ENTS ((4096 - sizeof(struct skcipher_sg_list)) / \ sizeof(struct scatterlist) - 1) +static void skcipher_free_async_sgls(struct skcipher_async_req *sreq) +{ + struct skcipher_async_rsgl *rsgl; + struct scatterlist *sgl; + struct scatterlist *sg; + int i, n; + + list_for_each_entry(rsgl, sreq-list, list) { + af_alg_free_sg(rsgl-sgl); + if (rsgl != sreq-first_sgl) + kfree(rsgl); + } + sgl = sreq-tsg; + n = sg_nents(sgl); + for_each_sg(sgl, sg, n, i) + put_page(sg_page(sg)); + + kfree(sreq-tsg); +} + +static void skcipher_async_cb(struct crypto_async_request *req, int err) +{ + struct sock *sk = req-data; + struct alg_sock *ask = alg_sk(sk); + struct skcipher_ctx *ctx = ask-private; + struct skcipher_async_req *sreq = GET_SREQ(req, ctx); + struct kiocb *iocb = sreq-iocb; + + atomic_dec(ctx-inflight); + skcipher_free_async_sgls(sreq); + mempool_free(req, ctx-pool); + sock_aio_complete(iocb, err, err); +} + +static void skcipher_mempool_free(void *_req, void *_sk) +{ + struct sock *sk = _sk; + struct alg_sock *ask = alg_sk(sk); + struct skcipher_ctx *ctx = ask-private; + struct kmem_cache *cache = ctx-cache; + + kmem_cache_free(cache, _req); +} + +static void *skcipher_mempool_alloc(gfp_t gfp_mask, void *_sk) +{ + struct sock *sk = _sk; + struct alg_sock *ask = alg_sk(sk); + struct skcipher_ctx *ctx = ask-private; + struct kmem_cache *cache = ctx-cache; + struct ablkcipher_request *req; + + req = kmem_cache_alloc(cache, gfp_mask); + if (req) { + ablkcipher_request_set_tfm(req, + crypto_ablkcipher_reqtfm(ctx-req)); + ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + skcipher_async_cb, sk); + } + return req; +} + +static void skcipher_cache_constructor(void *v) +{ + memset(v, 0, sizeof(struct skcipher_async_req)); +} + +static int skcipher_mempool_create(struct sock *sk) +{ + struct alg_sock *ask = alg_sk(sk); + struct skcipher_ctx *ctx = ask-private; + unsigned int len = sizeof(struct skcipher_async_req) + + GET_REQ_SIZE(ctx) + GET_IV_SIZE(ctx); + char buf[32]; + + snprintf(buf, sizeof(buf), skcipher_%p, ctx); + ctx-cache = kmem_cache_create(buf, len, 0, SLAB_HWCACHE_ALIGN | + SLAB_TEMPORARY, + skcipher_cache_constructor); + if (unlikely(!ctx-cache)) + return -ENOMEM; + + ctx-pool = mempool_create(128, skcipher_mempool_alloc, + skcipher_mempool_free, sk); + + if (unlikely(!ctx-pool)) { + kmem_cache_destroy(ctx-cache); + return -ENOMEM; + } + return 0; +} + +static void skcipher_mempool_destroy(struct
Re: [PATCH RFC 1/2] crypto: add PKE API
On 05/02/2015 05:07 PM, Herbert Xu wrote: #define CRYPTO_ALG_TYPE_AHASH0x000a +#define CRYPTO_ALG_TYPE_PKE 0x000b #define CRYPTO_ALG_TYPE_RNG 0x000c Will filling a hole cause a problem with something that got obsoleted? I hope not. I checked as far back as 2.6.18 and I don't see any clash. Herbert, what do you think? Indeed you can't use this hole as it'll make you a hash algorithm. So in this case isn't RNG a hash algorithm as well? Anyway will something like this be ok with you: diff --git a/include/linux/crypto.h b/include/linux/crypto.h index ee14140..ac18cd3 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -41,7 +41,7 @@ /* * Algorithm masks and types. */ -#define CRYPTO_ALG_TYPE_MASK 0x000f +#define CRYPTO_ALG_TYPE_MASK 0xf00f #define CRYPTO_ALG_TYPE_CIPHER 0x0001 #define CRYPTO_ALG_TYPE_COMPRESS 0x0002 #define CRYPTO_ALG_TYPE_AEAD 0x0003 @@ -54,6 +54,7 @@ #define CRYPTO_ALG_TYPE_AHASH 0x000a #define CRYPTO_ALG_TYPE_RNG0x000c #define CRYPTO_ALG_TYPE_PCOMPRESS 0x000f +#define CRYPTO_ALG_TYPE_PKE0x1001 #define CRYPTO_ALG_TYPE_HASH_MASK 0x000e #define CRYPTO_ALG_TYPE_AHASH_MASK 0x000c -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC 1/2] crypto: add PKE API
Hi Stephan, On 05/01/2015 12:24 AM, Stephan Mueller wrote: +struct public_key; +struct public_key_signature; Wouldn't it make sense to move the struct definitions here and have them documented? I'm not sure if they belong here. I think we can add some documentation without moving them. +struct pke_alg { + int (*sign)(struct pke_request *pkereq); + int (*verify)(struct pke_request *pkereq); + int (*encrypt)(struct pke_request *pkereq); + int (*decrypt)(struct pke_request *pkereq); + + u8 pub_mpis;/* Number of MPIs in public key */ + u8 sec_mpis;/* Number of MPIs in secret key */ + u8 sig_mpis;/* Number of MPIs in a signature */ May I ask that for such new structs we add some documentation? Currently, I am unclear on what MPIs are. E.g. if somebody needs to add, say, Curve 25519, what shall he add here? Sure, I'll add some description. Up to here I am volunteering to add the documentation comments. But for the following functions, I am not sure how they are supposed to be used correctly. Thus, can you add the documentation for them or at least give me a hint so that I can add the documentation? Same here, I'll add something. Thanks for volunteering. You did a good job documenting the rest and your help will be appreciated. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC 0/2] crypto: Introduce Public Key Encryption API
On 05/01/2015 01:47 AM, Jean Delvare wrote: I have nothing to do with this, please drop me from Cc. Sorry, your name was reported by scripts/get_maintainer.pl -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH RFC 1/2] crypto: add PKE API
Add Public Key Encryption API. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/Kconfig |6 + crypto/Makefile|1 crypto/crypto_user.c | 23 + crypto/pke.c | 114 ++ include/crypto/algapi.h|6 + include/linux/crypto.h | 191 include/linux/cryptouser.h |7 ++ 7 files changed, 347 insertions(+), 1 deletion(-) create mode 100644 crypto/pke.c diff --git a/crypto/Kconfig b/crypto/Kconfig index 8aaf298..9a14b33 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -87,6 +87,12 @@ config CRYPTO_PCOMP2 tristate select CRYPTO_ALGAPI2 +config CRYPTO_PKE + tristate Public Key Algorithms API + select CRYPTO_ALGAPI + help + Crypto API interface for public key algorithms. + config CRYPTO_MANAGER tristate Cryptographic algorithm manager select CRYPTO_MANAGER2 diff --git a/crypto/Makefile b/crypto/Makefile index 97b7d3a..e7dd283 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -27,6 +27,7 @@ crypto_hash-y += shash.o obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o +obj-$(CONFIG_CRYPTO_PKE) += pke.o cryptomgr-y := algboss.o testmgr.o diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index 41dfe76..83b4d0f 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -110,6 +110,23 @@ nla_put_failure: return -EMSGSIZE; } +static int crypto_report_pke(struct sk_buff *skb, struct crypto_alg *alg) +{ + struct crypto_report_pke rpke; + + strncpy(rpke.type, pke, sizeof(rpke.type)); + strncpy(rpke.subtype, alg-cra_name, sizeof(rpke.subtype)); + rpke.capabilities = alg-cra_pke.capabilities; + + if (nla_put(skb, CRYPTOCFGA_REPORT_PKE, + sizeof(struct crypto_report_pke), rpke)) + goto nla_put_failure; + return 0; + +nla_put_failure: + return -EMSGSIZE; +} + static int crypto_report_one(struct crypto_alg *alg, struct crypto_user_alg *ualg, struct sk_buff *skb) { @@ -154,6 +171,12 @@ static int crypto_report_one(struct crypto_alg *alg, goto nla_put_failure; break; + + case CRYPTO_ALG_TYPE_PKE: + if (crypto_report_pke(skb, alg)) + goto nla_put_failure; + + break; } out: diff --git a/crypto/pke.c b/crypto/pke.c new file mode 100644 index 000..c1350fa --- /dev/null +++ b/crypto/pke.c @@ -0,0 +1,114 @@ +/* + * Public Key Encryption operations. + * + * Copyright (c) 2015, Intel Corporation + * Authors: Tadeusz Struk tadeusz.st...@intel.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include linux/errno.h +#include linux/kernel.h +#include linux/module.h +#include linux/seq_file.h +#include linux/slab.h +#include linux/string.h +#include linux/crypto.h +#include linux/cryptouser.h +#include net/netlink.h +#include internal.h + +static unsigned int crypto_pke_ctxsize(struct crypto_alg *alg, u32 type, + u32 mask) +{ + unsigned int len = alg-cra_ctxsize; + + return ALIGN(len, (unsigned long)alg-cra_alignmask + 1); +} + +static int crypto_init_pke_ops(struct crypto_tfm *tfm, u32 type, u32 mask) +{ + struct pke_tfm *crt = tfm-crt_pke; + struct pke_alg *alg = tfm-__crt_alg-cra_pke; + + if (alg-pub_mpis 5 || alg-sec_mpis 5 || alg-sig_mpis 2) + return -EINVAL; + + if ((alg-capabilities PKEY_CAN_ENCRYPT) !alg-encrypt) + return -EINVAL; + + if ((alg-capabilities PKEY_CAN_DECRYPT) !alg-decrypt) + return -EINVAL; + + if ((alg-capabilities PKEY_CAN_SIGN) !alg-sign) + return -EINVAL; + + if ((alg-capabilities PKEY_CAN_VERIFY) !alg-verify) + return -EINVAL; + + crt-sign = alg-sign; + crt-verify = alg-verify; + crt-encrypt = alg-encrypt; + crt-decrypt = alg-decrypt; + crt-base = __crypto_pke_cast(tfm); + + return 0; +} + +#ifdef CONFIG_NET +static int crypto_pke_report(struct sk_buff *skb, struct crypto_alg *alg) +{ + struct crypto_report_pke rep_pke; + + strncpy(rep_pke.type, pke, sizeof(rep_pke.type)); + strncpy(rep_pke.subtype, alg-cra_name, sizeof(rep_pke.subtype)); + rep_pke.capabilities = alg-cra_pke.capabilities; + + if (nla_put(skb, CRYPTOCFGA_REPORT_PKE, + sizeof(struct crypto_report_pke), rep_pke)) + goto nla_put_failure; + return 0; + +nla_put_failure: + return -EMSGSIZE; +} +#else +static int crypto_pke_report(struct sk_buff *skb, struct
[PATCH RFC 2/2] crypto: RSA: KEYS: convert rsa and public key to new PKE API
Change the existing rsa and public key code to integrate it with the new Public Key Encryption API. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- Documentation/crypto/asymmetric-keys.txt | 10 +++- crypto/asymmetric_keys/Kconfig|1 crypto/asymmetric_keys/pkcs7_parser.c |4 +- crypto/asymmetric_keys/pkcs7_trust.c |2 - crypto/asymmetric_keys/pkcs7_verify.c |5 +- crypto/asymmetric_keys/public_key.c | 73 + crypto/asymmetric_keys/public_key.h | 36 -- crypto/asymmetric_keys/rsa.c | 47 +++ crypto/asymmetric_keys/x509_cert_parser.c | 14 -- crypto/asymmetric_keys/x509_public_key.c | 14 ++ include/crypto/public_key.h | 24 +++--- kernel/module_signing.c |9 +++- 12 files changed, 124 insertions(+), 115 deletions(-) delete mode 100644 crypto/asymmetric_keys/public_key.h diff --git a/Documentation/crypto/asymmetric-keys.txt b/Documentation/crypto/asymmetric-keys.txt index b767590..47bb5fb 100644 --- a/Documentation/crypto/asymmetric-keys.txt +++ b/Documentation/crypto/asymmetric-keys.txt @@ -89,11 +89,9 @@ inclusion is required: #include crypto/public_key.h This gives access to functions for dealing with asymmetric / public keys. -Three enums are defined there for representing public-key cryptography +Two enums are defined there for representing public-key cryptography algorithms: - enum pkey_algo - digest algorithms used by those: enum pkey_hash_algo @@ -102,6 +100,11 @@ and key identifier representations: enum pkey_id_type +Additionally public key algorithm names are defined: +#define PKEY_ALGO_DSA dsa +#define PKEY_ALGO_RSA rsa +These will be used to allocate public key tfm instances. + Note that the key type representation types are required because key identifiers from different standards aren't necessarily compatible. For instance, PGP generates key identifiers by hashing the key data plus some @@ -131,6 +134,7 @@ transferred the relevant bits to the structure pointed to by sig. struct public_key_signature { u8 *digest; + char *pkey_algo; u8 digest_size; enum pkey_hash_algo pkey_hash_algo : 8; u8 nr_mpi; diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig index 4870f28..1ad10f1 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -23,6 +23,7 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE config PUBLIC_KEY_ALGO_RSA tristate RSA public-key algorithm select MPILIB + select CRYPTO_PKE help This option enables support for the RSA algorithm (PKCS#1, RFC3447). diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c index 3bd5a1e..d37a608 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.c +++ b/crypto/asymmetric_keys/pkcs7_parser.c @@ -15,7 +15,7 @@ #include linux/slab.h #include linux/err.h #include linux/oid_registry.h -#include public_key.h +#include crypto/public_key.h #include pkcs7_parser.h #include pkcs7-asn1.h @@ -376,7 +376,7 @@ int pkcs7_sig_note_signature(void *context, size_t hdrlen, struct pkcs7_parse_context *ctx = context; MPI mpi; - BUG_ON(ctx-sinfo-sig.pkey_algo != PKEY_ALGO_RSA); + BUG_ON(strcmp(ctx-sinfo-sig.pkey_algo, PKEY_ALGO_RSA)); mpi = mpi_read_raw_data(value, vlen); if (!mpi) diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c index 1d29376..68ebae2 100644 --- a/crypto/asymmetric_keys/pkcs7_trust.c +++ b/crypto/asymmetric_keys/pkcs7_trust.c @@ -17,7 +17,7 @@ #include linux/asn1.h #include linux/key.h #include keys/asymmetric-type.h -#include public_key.h +#include crypto/public_key.h #include pkcs7_parser.h /** diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index cd45545..28f4a77 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c @@ -16,7 +16,7 @@ #include linux/err.h #include linux/asn1.h #include crypto/hash.h -#include public_key.h +#include crypto/public_key.h #include pkcs7_parser.h /* @@ -144,7 +144,8 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7, pr_devel(Sig %u: Found cert serial match X.509[%u]\n, sinfo-index, certix); - if (x509-pub-pkey_algo != sinfo-sig.pkey_algo) { + if (strcmp(pke_alg_name(x509-pub-tfm), + sinfo-sig.pkey_algo)) { pr_warn(Sig %u: X.509 algo and PKCS#7 sig algo don't match\n, sinfo-index); continue; diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c index 2f6e4fb..031112a 100644
[PATCH RFC 0/2] crypto: Introduce Public Key Encryption API
This patch set introduces a Public Key Encryption API. What is proposed is a new crypto type called crypto_pke_type plus new struct pke_alg and struct pke_tfm together with number of helper functions to register pke type algorithms and allocate tfm instances. This is to make it similar to how the existing crypto API works for the ablkcipher, ahash, and aead types. The operations the new interface will allow to provide are: int (*sign)(struct pke_request *pkereq); int (*verify)(struct pke_request *pkereq); int (*encrypt)(struct pke_request *pkereq); int (*decrypt)(struct pke_request *pkereq); The benefits it gives comparing to the struct public_key_algorithm interface are: - drivers can add many implementations of RSA or DSA algorithms and user will allocate instances (tfms) of these, base on algorithm priority, in the same way as it is with the symmetric ciphers. - the new interface allows for asynchronous implementations that can use crypto hardware to offload the calculations to. - integrating it with linux crypto api allows using all its benefits i.e. managing algorithms using NETLINK_CRYPTO, monitoring implementations using /proc/crypto. etc New helper functions have been added to allocate pke_tfm instances and invoke the operations to make it easier to use. For instance to verify a public_signature against a public_key using the RSA algorithm a user would do: struct crypto_pke *tfm = crypto_alloc_pke(rsa, 0, 0); struct pke_request *req = pke_request_alloc(tfm, GFP_KERNEL); pke_request_set_crypt(req, pub_key, signature); int ret = crypto_pke_verify(req); pke_request_free(req); crypto_free_pke(tfm); return ret; Additionally existing public_key and rsa code have been reworked to use the new interface for verifying signed modules. As part of the rework the enum pkey_algo has been removed as the algorithm to allocate will be indicated by a string - for instance rsa or dsa, similarly as it is with the symmetric algs e.g. aes. It will also make it easier to extend in the future when new algorithms will be added. --- Tadeusz Struk (2): crypto: add PKE API crypto: RSA: KEYS: convert rsa and public key to new PKE API Documentation/crypto/asymmetric-keys.txt | 10 +- crypto/Kconfig|6 + crypto/Makefile |1 crypto/asymmetric_keys/Kconfig|1 crypto/asymmetric_keys/pkcs7_parser.c |4 - crypto/asymmetric_keys/pkcs7_trust.c |2 crypto/asymmetric_keys/pkcs7_verify.c |5 - crypto/asymmetric_keys/public_key.c | 73 +++ crypto/asymmetric_keys/public_key.h | 36 - crypto/asymmetric_keys/rsa.c | 47 ++- crypto/asymmetric_keys/x509_cert_parser.c | 14 ++ crypto/asymmetric_keys/x509_public_key.c | 14 +- crypto/crypto_user.c | 23 +++ crypto/pke.c | 114 + include/crypto/algapi.h |6 + include/crypto/public_key.h | 24 +--- include/linux/crypto.h| 191 + include/linux/cryptouser.h|7 + kernel/module_signing.c |9 + 19 files changed, 471 insertions(+), 116 deletions(-) delete mode 100644 crypto/asymmetric_keys/public_key.h create mode 100644 crypto/pke.c -- -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC 1/2] crypto: add PKE API
On 04/30/2015 03:43 PM, Herbert Xu wrote: Please remodel it after pcompress or the newly converted rng type. This union stuff has been obsolete since 2008 and it's time for it to die. Ok, I didn't realize. Will send v2 shortly. Thanks -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC 2/2] crypto: RSA: KEYS: convert rsa and public key to new PKE API
On 05/01/2015 09:21 AM, David Howells wrote: +.verify = RSA_verify_signature, + .capabilities = PKEY_CAN_VERIFY, Can we keep .verify_signature as the name of the first. The second is redundant given the function pointers. I'm thinking that .verify will be more generic. If in the future we would like to implement something that verifies not a signature, but for instance is a number is a prime, then we can register a prime alg that implements verify and returns true if a number is a prime. Given that X.509 certs can hang around for a very long time, having a tfm in the cert is probably a bad idea as it may pin resources such as crypto h/w. - ctx-cert-pub-pkey_algo = PKEY_ALGO_RSA; - I think you need this rather than the above. You should only get the tfm when you actually need it. That's a good point. Thank you David for all your comments. I'll rework my patches and send v2 soon. I'll also try to integrate it with your sign-file as you suggested. Thanks T -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC 1/2] crypto: add PKE API
On 05/01/2015 09:04 AM, David Howells wrote: +config CRYPTO_PKE I would prefer CRYPTO_PKEY and pkey rather than pke generally and algo rather than alg where possible - this will have more consistency with what we have now. I understand, however, that in core crypto code, 'alg' is used. I'm fine with pkey. Herbert do you have preference with regards 'algo' vs 'alg'? #define CRYPTO_ALG_TYPE_AHASH 0x000a +#define CRYPTO_ALG_TYPE_PKE 0x000b #define CRYPTO_ALG_TYPE_RNG 0x000c Will filling a hole cause a problem with something that got obsoleted? I hope not. I checked as far back as 2.6.18 and I don't see any clash. Herbert, what do you think? +struct pke_request { + struct crypto_async_request base; + const struct public_key *pk; + const struct public_key_signature *pks; +}; I recommend: pk - key or pkey pks - sig or signature no problem +u8 pub_mpis;/* Number of MPIs in public key */ + u8 sec_mpis;/* Number of MPIs in secret key */ + u8 sig_mpis;/* Number of MPIs in a signature */ Keep member names as: u8 n_pub_mpi; /* Number of MPIs in public key */ u8 n_sec_mpi; /* Number of MPIs in secret key */ u8 n_sig_mpi; /* Number of MPIs in a signature */ same here. thanks -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH RFC v2 0/2] crypto: Introduce Public Key Encryption API
This patch set introduces a Public Key Encryption API. What is proposed is a new crypto type called crypto_pkey_type plus new struct pkey_alg and struct pkey_tfm together with number of helper functions to register pkey type algorithms and allocate tfm instances. This is to make it similar to how the existing crypto API works for the ablkcipher, ahash, and aead types. The operations the new interface will allow to provide are: int (*sign)(struct pkey_request *pkeyreq); int (*verify)(struct pkey_request *pkeyreq); int (*encrypt)(struct pkey_request *pkeyreq); int (*decrypt)(struct pkey_request *pkeyreq); The benefits it gives comparing to the struct public_key_algorithm interface are: - drivers can add many implementations of RSA or DSA algorithms and user will allocate instances (tfms) of these, base on algorithm priority, in the same way as it is with the symmetric ciphers. - the new interface allows for asynchronous implementations that can use crypto hardware to offload the calculations to. - integrating it with linux crypto api allows using all its benefits i.e. managing algorithms using NETLINK_CRYPTO, monitoring implementations using /proc/crypto. etc New helper functions have been added to allocate pkey_tfm instances and invoke the operations to make it easier to use. For instance to verify a public_signature against a public_key using the RSA algorithm a user would do: struct crypto_pkey *tfm = crypto_alloc_pkey(rsa, 0, 0); struct pkey_request *req = pkey_request_alloc(tfm, GFP_KERNEL); pkey_request_set_crypt(req, pub_key, signature); int ret = crypto_pkey_verify(req); pkey_request_free(req); crypto_free_pkey(tfm); return ret; Additionally existing public_key and rsa code have been reworked to use the new interface for verifying signed modules. As part of the rework the struct public_key_algorithm type has been removed. Algorithm instance is allocated using crypto_alloc_pkey() and name defined in pkey_algo_name table indexed by pkey_algo enum that comes from the public key. In future this can be replaced by the name can be obtained directly from the public key cert. Changes in v2: - remodeled not to use obsolete cra_u and crt_u unions - changed type/funct names from pke_* to pkey_* - retained the enum pkey_algo type for it is external to the kernel - added documentation --- Tadeusz Struk (2): crypto: add PKEY API crypto: RSA: KEYS: convert rsa and public key to new PKEY API crypto/Kconfig|6 crypto/Makefile |1 crypto/asymmetric_keys/Kconfig|1 crypto/asymmetric_keys/pkcs7_parser.c |2 crypto/asymmetric_keys/pkcs7_trust.c |2 crypto/asymmetric_keys/pkcs7_verify.c |3 crypto/asymmetric_keys/public_key.c | 89 --- crypto/asymmetric_keys/public_key.h | 36 --- crypto/asymmetric_keys/rsa.c | 43 ++- crypto/asymmetric_keys/x509_cert_parser.c |3 crypto/asymmetric_keys/x509_public_key.c |6 crypto/crypto_user.c | 24 ++ crypto/pkey.c | 125 + include/crypto/pkey.h | 390 + include/crypto/public_key.h | 10 - include/linux/crypto.h|1 include/linux/cryptouser.h|7 + 17 files changed, 657 insertions(+), 92 deletions(-) delete mode 100644 crypto/asymmetric_keys/public_key.h create mode 100644 crypto/pkey.c create mode 100644 include/crypto/pkey.h -- -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH RFC v2 1/2] crypto: add PKE API
Add Public Key Encryption API. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/Kconfig |6 + crypto/Makefile|1 crypto/crypto_user.c | 24 +++ crypto/pkey.c | 125 ++ include/crypto/pkey.h | 390 include/linux/crypto.h |1 include/linux/cryptouser.h |7 + 7 files changed, 554 insertions(+) create mode 100644 crypto/pkey.c create mode 100644 include/crypto/pkey.h diff --git a/crypto/Kconfig b/crypto/Kconfig index 8aaf298..daa9c07 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -87,6 +87,12 @@ config CRYPTO_PCOMP2 tristate select CRYPTO_ALGAPI2 +config CRYPTO_PKEY + tristate Public Key Algorithms API + select CRYPTO_ALGAPI + help + Crypto API interface for public key algorithms. + config CRYPTO_MANAGER tristate Cryptographic algorithm manager select CRYPTO_MANAGER2 diff --git a/crypto/Makefile b/crypto/Makefile index 97b7d3a..1930f85 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -27,6 +27,7 @@ crypto_hash-y += shash.o obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o +obj-$(CONFIG_CRYPTO_PKEY) += pkey.o cryptomgr-y := algboss.o testmgr.o diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index 41dfe76..ccc7f1d 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -27,6 +27,7 @@ #include net/net_namespace.h #include crypto/internal/aead.h #include crypto/internal/skcipher.h +#include crypto/pkey.h #include internal.h @@ -110,6 +111,23 @@ nla_put_failure: return -EMSGSIZE; } +static int crypto_report_pkey(struct sk_buff *skb, struct crypto_alg *alg) +{ + struct crypto_report_pkey rpkey; + + strncpy(rpkey.type, pke, sizeof(rpkey.type)); + strncpy(rpkey.subtype, alg-cra_name, sizeof(rpkey.subtype)); + rpkey.capabilities = __crypto_pkey_alg(alg)-capabilities; + + if (nla_put(skb, CRYPTOCFGA_REPORT_PKEY, + sizeof(struct crypto_report_pkey), rpkey)) + goto nla_put_failure; + return 0; + +nla_put_failure: + return -EMSGSIZE; +} + static int crypto_report_one(struct crypto_alg *alg, struct crypto_user_alg *ualg, struct sk_buff *skb) { @@ -154,6 +172,12 @@ static int crypto_report_one(struct crypto_alg *alg, goto nla_put_failure; break; + + case CRYPTO_ALG_TYPE_PKEY: + if (crypto_report_pkey(skb, alg)) + goto nla_put_failure; + + break; } out: diff --git a/crypto/pkey.c b/crypto/pkey.c new file mode 100644 index 000..ab8c0e9 --- /dev/null +++ b/crypto/pkey.c @@ -0,0 +1,125 @@ +/* + * Public Key Encryption + * + * Copyright (c) 2015, Intel Corporation + * Authors: Tadeusz Struk tadeusz.st...@intel.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include linux/errno.h +#include linux/kernel.h +#include linux/module.h +#include linux/seq_file.h +#include linux/slab.h +#include linux/string.h +#include linux/crypto.h +#include crypto/algapi.h +#include linux/cryptouser.h +#include net/netlink.h +#include crypto/pkey.h +#include internal.h + +#ifdef CONFIG_NET +static int crypto_pkey_report(struct sk_buff *skb, struct crypto_alg *alg) +{ + struct crypto_report_pkey rep_pkey; + + strncpy(rep_pkey.type, pkey, sizeof(rep_pkey.type)); + strncpy(rep_pkey.subtype, alg-cra_name, sizeof(rep_pkey.subtype)); + rep_pkey.capabilities = __crypto_pkey_alg(alg)-capabilities; + + if (nla_put(skb, CRYPTOCFGA_REPORT_PKEY, + sizeof(struct crypto_report_pkey), rep_pkey)) + goto nla_put_failure; + return 0; + +nla_put_failure: + return -EMSGSIZE; +} +#else +static int crypto_pkey_report(struct sk_buff *skb, struct crypto_alg *alg) +{ + return -ENOSYS; +} +#endif + +static void crypto_pkey_show(struct seq_file *m, struct crypto_alg *alg) + __attribute__ ((unused)); +static void crypto_pkey_show(struct seq_file *m, struct crypto_alg *alg) +{ + int cap = __crypto_pkey_alg(alg)-capabilities; + + seq_puts(m, type : pke\n); + seq_printf(m, subtype : %s\n, alg-cra_name); + seq_printf(m, can encrypt : %s\n, + cap PKEY_CAN_ENCRYPT ? yes : no); + seq_printf(m, can decrypt : %s\n, + cap PKEY_CAN_DECRYPT ? yes : no); + seq_printf(m, can sign : %s\n, + cap PKEY_CAN_SIGN ? yes : no); + seq_printf(m, can verify : %s\n, + cap PKEY_CAN_VERIFY ? yes : no); +} + +static int crypto_pkey_init(struct crypto_tfm
[PATCH RFC v2 2/2] crypto: RSA: KEYS: convert rsa and public key to new PKE API
Change the existing rsa and public key code to integrate it with the new Public Key Encryption API. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/asymmetric_keys/Kconfig|1 crypto/asymmetric_keys/pkcs7_parser.c |2 - crypto/asymmetric_keys/pkcs7_trust.c |2 - crypto/asymmetric_keys/pkcs7_verify.c |3 + crypto/asymmetric_keys/public_key.c | 89 +++-- crypto/asymmetric_keys/public_key.h | 36 crypto/asymmetric_keys/rsa.c | 43 +++--- crypto/asymmetric_keys/x509_cert_parser.c |3 + crypto/asymmetric_keys/x509_public_key.c |6 +- include/crypto/public_key.h | 11 +--- 10 files changed, 104 insertions(+), 92 deletions(-) delete mode 100644 crypto/asymmetric_keys/public_key.h diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig index 4870f28..1b7d7d6 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -23,6 +23,7 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE config PUBLIC_KEY_ALGO_RSA tristate RSA public-key algorithm select MPILIB + select CRYPTO_PKEY help This option enables support for the RSA algorithm (PKCS#1, RFC3447). diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c index 3bd5a1e..054f110 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.c +++ b/crypto/asymmetric_keys/pkcs7_parser.c @@ -15,7 +15,7 @@ #include linux/slab.h #include linux/err.h #include linux/oid_registry.h -#include public_key.h +#include crypto/public_key.h #include pkcs7_parser.h #include pkcs7-asn1.h diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c index 1d29376..68ebae2 100644 --- a/crypto/asymmetric_keys/pkcs7_trust.c +++ b/crypto/asymmetric_keys/pkcs7_trust.c @@ -17,7 +17,7 @@ #include linux/asn1.h #include linux/key.h #include keys/asymmetric-type.h -#include public_key.h +#include crypto/public_key.h #include pkcs7_parser.h /** diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index cd45545..9f1035c 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c @@ -16,7 +16,8 @@ #include linux/err.h #include linux/asn1.h #include crypto/hash.h -#include public_key.h +#include crypto/public_key.h +#include crypto/pkey.h #include pkcs7_parser.h /* diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c index 2f6e4fb..d147ee0 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c @@ -18,30 +18,28 @@ #include linux/slab.h #include linux/seq_file.h #include keys/asymmetric-subtype.h -#include public_key.h +#include crypto/public_key.h +#include crypto/pkey.h MODULE_LICENSE(GPL); const char *const pkey_algo_name[PKEY_ALGO__LAST] = { - [PKEY_ALGO_DSA] = DSA, - [PKEY_ALGO_RSA] = RSA, + [PKEY_ALGO_DSA] = dsa, + [PKEY_ALGO_RSA] = rsa, }; EXPORT_SYMBOL_GPL(pkey_algo_name); -const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST] = { -#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \ - defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE) - [PKEY_ALGO_RSA] = RSA_public_key_algorithm, -#endif -}; -EXPORT_SYMBOL_GPL(pkey_algo); - const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = { [PKEY_ID_PGP] = PGP, [PKEY_ID_X509] = X509, }; EXPORT_SYMBOL_GPL(pkey_id_type_name); +struct public_key_completion { + struct completion completion; + int err; +}; + /* * Provide a part of a description of the key for /proc/keys. */ @@ -52,7 +50,8 @@ static void public_key_describe(const struct key *asymmetric_key, if (key) seq_printf(m, %s.%s, - pkey_id_type_name[key-id_type], key-algo-name); + pkey_id_type_name[key-id_type], + pkey_algo_name[key-pkey_algo]); } /* @@ -71,40 +70,68 @@ void public_key_destroy(void *payload) } EXPORT_SYMBOL_GPL(public_key_destroy); +static void public_key_verify_done(struct crypto_async_request *req, int err) +{ + struct public_key_completion *compl = req-data; + + if (err == -EINPROGRESS) + return; + + compl-err = err; + complete(compl-completion); +} + /* * Verify a signature using a public key. */ -int public_key_verify_signature(const struct public_key *pk, +int public_key_verify_signature(const struct public_key *pkey, const struct public_key_signature *sig) { - const struct public_key_algorithm *algo; - - BUG_ON(!pk); - BUG_ON(!pk-mpi[0]); - BUG_ON(!pk-mpi[1]); + struct crypto_pkey *tfm; + struct pkey_request *req; + struct public_key_completion compl; + int ret
Re: [PATCH RFC 0/2] crypto: Introduce Public Key Encryption API
Hi Horia, On 05/04/2015 06:16 AM, Horia Geantă wrote: int (*sign)(struct pke_request *pkereq); int (*verify)(struct pke_request *pkereq); int (*encrypt)(struct pke_request *pkereq); int (*decrypt)(struct pke_request *pkereq); Where would be the proper place for keygen operation? This will need to be extended to support keygen. AFAICT algorithms currently map to primitives + encoding methods, which is not flexible. For e.g. current RSA implementation hardcodes the PKCS1-v1_5 encoding method, making it hard to add OAEP(+) etc. One solution would be to map algorithms to primitives only. Encoding methods need to be abstracted somehow, maybe using templates to wrap the algorithms. So far there is only one rsa implementation in kernel and it is only used by module signing code. Later we can add templates or simply one can register oaep-rsa algorithm. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH RFC v3 2/3] crypto: RSA: KEYS: convert rsa and public key to new PKE API
Change the existing rsa and public key code to integrate it with the new Public Key Encryption API. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/asymmetric_keys/Kconfig|1 crypto/asymmetric_keys/Makefile |1 crypto/asymmetric_keys/pkcs7_parser.c |2 crypto/asymmetric_keys/pkcs7_trust.c |2 crypto/asymmetric_keys/pkcs7_verify.c |2 crypto/asymmetric_keys/public_key.c | 53 +-- crypto/asymmetric_keys/public_key.h | 36 -- crypto/asymmetric_keys/rsa.c | 467 - crypto/asymmetric_keys/rsa_pkcs1_v1_5.c | 259 crypto/asymmetric_keys/x509_cert_parser.c |2 crypto/asymmetric_keys/x509_public_key.c |4 include/crypto/public_key.h | 11 - 12 files changed, 540 insertions(+), 300 deletions(-) delete mode 100644 crypto/asymmetric_keys/public_key.h create mode 100644 crypto/asymmetric_keys/rsa_pkcs1_v1_5.c diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig index 4870f28..4d27116 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -23,6 +23,7 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE config PUBLIC_KEY_ALGO_RSA tristate RSA public-key algorithm select MPILIB + select CRYPTO_AKCIPHER help This option enables support for the RSA algorithm (PKCS#1, RFC3447). diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile index e47fcd9..a9cb1b8 100644 --- a/crypto/asymmetric_keys/Makefile +++ b/crypto/asymmetric_keys/Makefile @@ -8,6 +8,7 @@ asymmetric_keys-y := asymmetric_type.o signature.o obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o +obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa_pkcs1_v1_5.o # # X.509 Certificate handling diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c index 3bd5a1e..054f110 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.c +++ b/crypto/asymmetric_keys/pkcs7_parser.c @@ -15,7 +15,7 @@ #include linux/slab.h #include linux/err.h #include linux/oid_registry.h -#include public_key.h +#include crypto/public_key.h #include pkcs7_parser.h #include pkcs7-asn1.h diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c index 1d29376..68ebae2 100644 --- a/crypto/asymmetric_keys/pkcs7_trust.c +++ b/crypto/asymmetric_keys/pkcs7_trust.c @@ -17,7 +17,7 @@ #include linux/asn1.h #include linux/key.h #include keys/asymmetric-type.h -#include public_key.h +#include crypto/public_key.h #include pkcs7_parser.h /** diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index cd45545..c32a337 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c @@ -16,7 +16,7 @@ #include linux/err.h #include linux/asn1.h #include crypto/hash.h -#include public_key.h +#include crypto/public_key.h #include pkcs7_parser.h /* diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c index 2f6e4fb..4685aed 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c @@ -18,30 +18,26 @@ #include linux/slab.h #include linux/seq_file.h #include keys/asymmetric-subtype.h -#include public_key.h +#include crypto/public_key.h +#include crypto/akcipher.h MODULE_LICENSE(GPL); const char *const pkey_algo_name[PKEY_ALGO__LAST] = { - [PKEY_ALGO_DSA] = DSA, - [PKEY_ALGO_RSA] = RSA, + [PKEY_ALGO_DSA] = dsa, + [PKEY_ALGO_RSA] = rsa, }; EXPORT_SYMBOL_GPL(pkey_algo_name); -const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST] = { -#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \ - defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE) - [PKEY_ALGO_RSA] = RSA_public_key_algorithm, -#endif -}; -EXPORT_SYMBOL_GPL(pkey_algo); - const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = { [PKEY_ID_PGP] = PGP, [PKEY_ID_X509] = X509, }; EXPORT_SYMBOL_GPL(pkey_id_type_name); +int rsa_pkcs1_v1_5_verify_signature(const struct public_key *pkey, + const struct public_key_signature *sig); + /* * Provide a part of a description of the key for /proc/keys. */ @@ -52,7 +48,8 @@ static void public_key_describe(const struct key *asymmetric_key, if (key) seq_printf(m, %s.%s, - pkey_id_type_name[key-id_type], key-algo-name); + pkey_id_type_name[key-id_type], + pkey_algo_name[key-pkey_algo]); } /* @@ -74,37 +71,20 @@ EXPORT_SYMBOL_GPL(public_key_destroy); /* * Verify a signature using a public key. */ -int public_key_verify_signature(const struct public_key *pk, +int public_key_verify_signature(const struct public_key *pkey
[PATCH RFC v3 0/3] crypto: Introduce Public Key Encryption API
This patch set introduces a Public Key Encryption API. What is proposed is a new crypto type called crypto_pkey_type plus new struct pkey_alg and struct pkey_tfm together with number of helper functions to register pkey type algorithms and allocate tfm instances. This is to make it similar to how the existing crypto API works for the ablkcipher, ahash, and aead types. The operations the new interface will allow to provide are: int (*sign)(struct pkey_request *pkeyreq); int (*verify)(struct pkey_request *pkeyreq); int (*encrypt)(struct pkey_request *pkeyreq); int (*decrypt)(struct pkey_request *pkeyreq); The benefits it gives comparing to the struct public_key_algorithm interface are: - drivers can add many implementations of RSA or DSA algorithms and user will allocate instances (tfms) of these, base on algorithm priority, in the same way as it is with the symmetric ciphers. - the new interface allows for asynchronous implementations that can use crypto hardware to offload the calculations to. - integrating it with linux crypto api allows using all its benefits i.e. managing algorithms using NETLINK_CRYPTO, monitoring implementations using /proc/crypto. etc New helper functions have been added to allocate pkey_tfm instances and invoke the operations to make it easier to use. For instance to verify a public_signature against a public_key using the RSA algorithm a user would do: struct crypto_pkey *tfm = crypto_alloc_pkey(rsa, 0, 0); struct pkey_request *req = pkey_request_alloc(tfm, GFP_KERNEL); pkey_request_set_crypt(req, pub_key, signature); int ret = crypto_pkey_verify(req); pkey_request_free(req); crypto_free_pkey(tfm); return ret; Additionally existing public_key and rsa code have been reworked to use the new interface for verifying signed modules. As part of the rework the struct public_key_algorithm type has been removed. Algorithm instance is allocated using crypto_alloc_pkey() and name defined in pkey_algo_name table indexed by pkey_algo enum that comes from the public key. In future this can be replaced by a string name can be obtained directly from the public key cert. Changes in v3: - changed input and output parameters type from sgl to void * and added separate src_len dst_len - requested by Herbert Xu - separated rsa implementation into cryptographic primitives and left encryption scheme details outside of the algorithm implementation - added SW implementation for RSA encrypt, decrypt and sign operation - added RSA test vectors Changes in v2: - remodeled not to use obsolete cra_u and crt_u unions - changed type/funct names from pke_* to pkey_* - retained the enum pkey_algo type for it is external to the kernel - added documentation --- Tadeusz Struk (3): crypto: add PKE API crypto: RSA: KEYS: convert rsa and public key to new PKE API crypto: add tests vectors for RSA crypto/Kconfig|6 crypto/Makefile |1 crypto/akcipher.c | 100 ++ crypto/asymmetric_keys/Kconfig|1 crypto/asymmetric_keys/Makefile |1 crypto/asymmetric_keys/pkcs7_parser.c |2 crypto/asymmetric_keys/pkcs7_trust.c |2 crypto/asymmetric_keys/pkcs7_verify.c |2 crypto/asymmetric_keys/public_key.c | 53 +-- crypto/asymmetric_keys/public_key.h | 36 -- crypto/asymmetric_keys/rsa.c | 467 - crypto/asymmetric_keys/rsa_pkcs1_v1_5.c | 259 crypto/asymmetric_keys/x509_cert_parser.c |2 crypto/asymmetric_keys/x509_public_key.c |4 crypto/crypto_user.c | 23 + crypto/testmgr.c | 151 + crypto/testmgr.h | 86 + include/crypto/akcipher.h | 385 include/crypto/public_key.h | 11 - include/linux/crypto.h|1 include/linux/cryptouser.h|6 21 files changed, 1299 insertions(+), 300 deletions(-) create mode 100644 crypto/akcipher.c delete mode 100644 crypto/asymmetric_keys/public_key.h create mode 100644 crypto/asymmetric_keys/rsa_pkcs1_v1_5.c create mode 100644 include/crypto/akcipher.h -- -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH RFC v3 1/3] crypto: add PKE API
Add Public Key Encryption API. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/Kconfig |6 + crypto/Makefile|1 crypto/akcipher.c | 100 +++ crypto/crypto_user.c | 23 +++ include/crypto/akcipher.h | 385 include/linux/crypto.h |1 include/linux/cryptouser.h |6 + 7 files changed, 522 insertions(+) create mode 100644 crypto/akcipher.c create mode 100644 include/crypto/akcipher.h diff --git a/crypto/Kconfig b/crypto/Kconfig index 0ff4cd4..917f880 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -87,6 +87,12 @@ config CRYPTO_PCOMP2 tristate select CRYPTO_ALGAPI2 +config CRYPTO_AKCIPHER + tristate Public Key Algorithms API + select CRYPTO_ALGAPI + help + Crypto API interface for public key algorithms. + config CRYPTO_MANAGER tristate Cryptographic algorithm manager select CRYPTO_MANAGER2 diff --git a/crypto/Makefile b/crypto/Makefile index 5db5b95..1ed2929 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -28,6 +28,7 @@ crypto_hash-y += shash.o obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o +obj-$(CONFIG_CRYPTO_AKCIPHER) += akcipher.o cryptomgr-y := algboss.o testmgr.o diff --git a/crypto/akcipher.c b/crypto/akcipher.c new file mode 100644 index 000..92da8da8 --- /dev/null +++ b/crypto/akcipher.c @@ -0,0 +1,100 @@ +/* + * Public Key Encryption + * + * Copyright (c) 2015, Intel Corporation + * Authors: Tadeusz Struk tadeusz.st...@intel.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include linux/errno.h +#include linux/kernel.h +#include linux/module.h +#include linux/seq_file.h +#include linux/slab.h +#include linux/string.h +#include linux/crypto.h +#include crypto/algapi.h +#include linux/cryptouser.h +#include net/netlink.h +#include crypto/akcipher.h +#include internal.h + +#ifdef CONFIG_NET +static int crypto_akcipher_report(struct sk_buff *skb, struct crypto_alg *alg) +{ + struct crypto_report_akcipher rakcipher; + + strncpy(rakcipher.type, akcipher, sizeof(rakcipher.type)); + strncpy(rakcipher.subtype, alg-cra_name, sizeof(rakcipher.subtype)); + + if (nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER, + sizeof(struct crypto_report_akcipher), rakcipher)) + goto nla_put_failure; + return 0; + +nla_put_failure: + return -EMSGSIZE; +} +#else +static int crypto_akcipher_report(struct sk_buff *skb, struct crypto_alg *alg) +{ + return -ENOSYS; +} +#endif + +static void crypto_akcipher_show(struct seq_file *m, struct crypto_alg *alg) + __attribute__ ((unused)); + +static void crypto_akcipher_show(struct seq_file *m, struct crypto_alg *alg) +{ + seq_puts(m, type : akcipher\n); + seq_printf(m, subtype : %s\n, alg-cra_name); +} + +static int crypto_akcipher_init(struct crypto_tfm *tfm) +{ + return 0; +} + +static const struct crypto_type crypto_akcipher_type = { + .extsize = crypto_alg_extsize, + .init_tfm = crypto_akcipher_init, +#ifdef CONFIG_PROC_FS + .show = crypto_akcipher_show, +#endif + .report = crypto_akcipher_report, + .maskclear = ~CRYPTO_ALG_TYPE_MASK, + .maskset = CRYPTO_ALG_TYPE_MASK, + .type = CRYPTO_ALG_TYPE_AKCIPHER, + .tfmsize = offsetof(struct crypto_akcipher, base), +}; + +struct crypto_akcipher *crypto_alloc_akcipher(const char *alg_name, u32 type, + u32 mask) +{ + return crypto_alloc_tfm(alg_name, crypto_akcipher_type, type, mask); +} +EXPORT_SYMBOL_GPL(crypto_alloc_akcipher); + +int crypto_register_akcipher(struct akcipher_alg *alg) +{ + struct crypto_alg *base = alg-base; + + base-cra_type = crypto_akcipher_type; + base-cra_flags = ~CRYPTO_ALG_TYPE_MASK; + base-cra_flags |= CRYPTO_ALG_TYPE_AKCIPHER; + return crypto_register_alg(base); +} +EXPORT_SYMBOL_GPL(crypto_register_akcipher); + +void crypto_unregister_akcipher(struct akcipher_alg *alg) +{ + crypto_unregister_alg(alg-base); +} +EXPORT_SYMBOL_GPL(crypto_unregister_akcipher); +MODULE_LICENSE(GPL); +MODULE_DESCRIPTION(Generic public key cihper type); diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index 41dfe76..508e71d 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -27,6 +27,7 @@ #include net/net_namespace.h #include crypto/internal/aead.h #include crypto/internal/skcipher.h +#include crypto/akcipher.h #include internal.h @@ -110,6 +111,22 @@ nla_put_failure: return -EMSGSIZE; } +static int crypto_report_akcipher(struct sk_buff *skb, struct crypto_alg *alg) +{ + struct
[PATCH RFC v3 3/3] crypto: add tests vectors for RSA
New test vectors for RSA algorithm. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/testmgr.c | 151 ++ crypto/testmgr.h | 86 +++ 2 files changed, 237 insertions(+) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 717d6f2..54a5412 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -30,6 +30,8 @@ #include linux/string.h #include crypto/rng.h #include crypto/drbg.h +#include crypto/public_key.h +#include crypto/akcipher.h #include internal.h @@ -116,6 +118,11 @@ struct drbg_test_suite { unsigned int count; }; +struct akcipher_test_suite { + struct akcipher_testvec *vecs; + unsigned int count; +}; + struct alg_test_desc { const char *alg; int (*test)(const struct alg_test_desc *desc, const char *driver, @@ -130,6 +137,7 @@ struct alg_test_desc { struct hash_test_suite hash; struct cprng_test_suite cprng; struct drbg_test_suite drbg; + struct akcipher_test_suite akcipher; } suite; }; @@ -1825,6 +1833,139 @@ static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver, } +static int do_test_rsa(struct crypto_akcipher *tfm, + struct akcipher_testvec *vecs) +{ + struct akcipher_request *req; + struct public_key pkey; + void *outbuf_enc = NULL; + void *outbuf_dec = NULL; + struct tcrypt_result result; + unsigned int out_len = vecs-c_size; + int err = -ENOMEM; + + req = akcipher_request_alloc(tfm, GFP_KERNEL); + if (!req) + return err; + + pkey.rsa.n = mpi_read_raw_data(vecs-pub_key_n, vecs-pub_key_n_size); + if (!pkey.rsa.n) + goto free_req; + + pkey.rsa.e = mpi_read_raw_data(vecs-pub_key_e, vecs-pub_key_e_size); + if (!pkey.rsa.e) + goto free_n; + + pkey.rsa.d = mpi_read_raw_data(vecs-sec_key_d, vecs-sec_key_d_size); + if (!pkey.rsa.d) + goto free_e; + + outbuf_enc = kzalloc(vecs-c_size, GFP_KERNEL); + if (!outbuf_enc) + goto free_d; + + /* Run RSA encrypt - c = m^e mod n;*/ + init_completion(result.completion); + crypto_akcipher_setkey(tfm, pkey); + akcipher_request_set_crypt(req, vecs-m, outbuf_enc, vecs-m_size, + out_len, out_len); + akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + tcrypt_complete, result); + err = wait_async_op(result, crypto_akcipher_encrypt(req)); + if (err) { + pr_err(alg: rsa: encrypt test failed. err %d\n, err); + goto free_all; + } + + if (out_len != vecs-c_size) { + err = -EINVAL; + goto free_all; + } + + outbuf_dec = kzalloc(out_len, GFP_KERNEL); + if (!outbuf_dec) { + err = -ENOMEM; + goto free_all; + } + + init_completion(result.completion); + akcipher_request_set_crypt(req, outbuf_enc, outbuf_dec, vecs-c_size, + out_len, out_len); + /* Run RSA decrypt - m = c^d mod n;*/ + err = wait_async_op(result, crypto_akcipher_decrypt(req)); + if (err) { + pr_err(alg: rsa: decrypt test failed. err %d\n, err); + goto free_all; + } + + if (out_len != vecs-m_size) { + err = -EINVAL; + goto free_all; + } + + /* verify that decrypted message is equal to the original msg */ + if (memcmp(vecs-m, outbuf_dec, vecs-m_size)) { + pr_err(alg: rsa: encrypt test failed. Invalid output\n); + err = -EINVAL; + } +free_all: + kfree(outbuf_dec); + kfree(outbuf_enc); +free_d: + mpi_free(pkey.rsa.d); +free_e: + mpi_free(pkey.rsa.e); +free_n: + mpi_free(pkey.rsa.n); +free_req: + akcipher_request_free(req); + return err; +} + +static int test_rsa(struct crypto_akcipher *tfm, struct akcipher_testvec *vecs, + unsigned int tcount) +{ + int ret, i; + + for (i = 0; i tcount; i++) { + ret = do_test_rsa(tfm, vecs++); + if (ret) { + pr_err(alg: rsa: test failed on vector %d\n, i + 1); + return ret; + } + } + return 0; +} + +static int test_akcipher(struct crypto_akcipher *tfm, const char *alg, +struct akcipher_testvec *vecs, unsigned int tcount) +{ + if (strncmp(alg, rsa, 3) == 0) + return test_rsa(tfm, vecs, tcount); + + return 0; +} + +static int alg_test_akcipher(const struct alg_test_desc *desc, +const char *driver, u32 type, u32 mask) +{ + struct crypto_akcipher *tfm; + int err = 0; + + tfm
Re: [PATCH RFC v3 1/3] crypto: add PKE API
Hi Herbert, On 06/03/2015 11:49 PM, Herbert Xu wrote: Because the caller is going to be allocating memory for the output, we need to provide a way for them to know how much memory to allocate. This presumably will depend on the key size. So something like int (*maxsize)(struct crypto_akcipher *tfm); is needed. You should also provide setkey here. You can't just save a pointer to the key. The transform must hold the key physically as the original may go away. It should also ensure that the key is actually valid for the transform. base already has ctx so you should get rid of ctx and move base to the end of the struct. right, will do that. Thanks for quick response. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC v3 2/3] crypto: RSA: KEYS: convert rsa and public key to new PKE API
On 06/03/2015 11:53 PM, Herbert Xu wrote: I'd like to see this split into multiple patches. First of all the new crypto_akcipher implementation should coexist with the existing code. That way the exiting users can be converted over one-by-one. Also you should implement the crypto_akcipher completely before converting anybody over, that means doing encoding/wrapping in addition to the crypto. That way we don't have to have craziness like converting in and out of MPI multiple times. That's cool. It will make it easier for me. I wanted to convert one to show that the interface is working. Lastly you should consider adding an MPI helper that writes to an existing buffer instead of allocating a new one and copying it over. I'll think about something. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC v3 2/3] crypto: RSA: KEYS: convert rsa and public key to new PKE API
On 06/05/2015 01:50 AM, Paul Bolle wrote: This builds two modules if PUBLIC_KEY_ALGO_RSA = 'm': rsa.ko and rsa_pkcs1_v1_5.ko. Is that what you want? No, this not what I wanted. public_key.c uses this, so it can end up in public_key.ko. But it's not exported. So a _quick and dirty_ build test generated: WARNING: rsa_pkcs1_v1_5_verify_signature [[...]/crypto/asymmetric_keys/public_key.ko] undefined! Also no MODULE_LICENSE() macro, so loading rsa_pkcs1_v1_5.ko should trigger a warning and taint the kernel. Thank you Paul for taking the time to review the patches and for your feedback. I'll have to change this again based on Herbert's feedback so this rsa_pkcs1_v1_5.c file will go away anyway. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC v3 3/3] crypto: add tests vectors for RSA
Hi Stephan On 06/03/2015 05:15 PM, Stephan Mueller wrote: May I ask that the outbuf_enc is memcmp()ed with an expected value? This check is required for FIPS 140-2 compliance. Without that memcmp, FIPS 140-2 validations will not be successful. Sure, I will do that. I wasn't aware that this was required. Sorry for bringing that one up just now: 512 and 1024 bit test vectors will not be helpful for several use cases, including FIPS. I can offer to give you 2k or 3k vectors. I have one 2K vector from openSSL fips so I'll use it instead of the 512 one. Besides, wouldn't one vector be sufficient? I think there is no harm to have these 3 vectors to make sure an implementation is well tested. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: crypto: rsa - select on undefined AKCIPHER
On 06/18/2015 01:26 AM, Andreas Ruprecht wrote: Hi Tadeusz, your commit cfc2bb32b313 (crypto: rsa - add a new rsa generic implementation) was merged into linux-next today (i.e., next-20150618). It changes the crypto/Kconfig file and adds the CRYPTO_RSA config option: +config CRYPTO_RSA + tristate RSA algorithm + select AKCIPHER [...] The symbol AKCIPHER, however, is not defined in Kconfig. Did you maybe mean CRYPTO_AKCIPHER, which you added in commit 3c339ab83fc0 (crypto: akcipher - add PKE API)? I detected the issue by running undertaker-checkpatch from the Undertaker tool suite (https://undertaker.cs.fau.de) as part of an automated, daily analysis of the most recent linux-next tree. There is also a tool in the Linux tree itself that can detect such issues (scripts/checkkconfigsymbols.py). Hi Andreas, Yes it should have been CRYPTO_AKCIPHER. Thanks for reporting this. --- 8 --- This patch fixes invalid config selection for AKCIPHER Reported-by: Andreas Ruprecht andreas.rupre...@fau.de Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- diff --git a/crypto/Kconfig b/crypto/Kconfig index 6c79ef0..b4cfc57 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -102,7 +102,7 @@ config CRYPTO_AKCIPHER config CRYPTO_RSA tristate RSA algorithm - select AKCIPHER + select CRYPTO_AKCIPHER select MPILIB select ASN1 help -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v13 1/2] crypto: AF_ALG: add AEAD support
Hi Stephan, On 02/28/2015 11:50 AM, Stephan Mueller wrote: + err = af_alg_wait_for_completion(ctx-enc ? + crypto_aead_encrypt(ctx-aead_req) : + crypto_aead_decrypt(ctx-aead_req), + ctx-completion); + + if (err) { + /* EBADMSG implies a valid cipher operation took place */ + if (err == -EBADMSG) + aead_put_sgl(sk); + goto unlock; Shouldn't we free the TX sgl regardless of the error was? Or do we expect that the user will try to read again and it will be Ok the second time? Hope you still remember :) + } + + aead_put_sgl(sk); + + err = 0; + +unlock: + for (i = 0; i cnt; i++) + af_alg_free_sg(ctx-rsgl[i]); + + aead_wmem_wakeup(sk); + release_sock(sk); + + return err ? err : outlen; +} -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH RFC v7 3/3] crypto: add tests vectors for RSA
New test vectors for RSA algorithm. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/Kconfig |1 crypto/testmgr.c | 158 ++ crypto/testmgr.h | 187 ++ 3 files changed, 346 insertions(+) diff --git a/crypto/Kconfig b/crypto/Kconfig index 52467cf..9471ac8 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -122,6 +122,7 @@ config CRYPTO_MANAGER2 select CRYPTO_HASH2 select CRYPTO_BLKCIPHER2 select CRYPTO_PCOMP2 + select CRYPTO_AKCIPHER2 config CRYPTO_USER tristate Userspace cryptographic algorithm configuration diff --git a/crypto/testmgr.c b/crypto/testmgr.c index ccd19cf..975e1ea 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -30,6 +30,7 @@ #include linux/string.h #include crypto/rng.h #include crypto/drbg.h +#include crypto/akcipher.h #include internal.h @@ -116,6 +117,11 @@ struct drbg_test_suite { unsigned int count; }; +struct akcipher_test_suite { + struct akcipher_testvec *vecs; + unsigned int count; +}; + struct alg_test_desc { const char *alg; int (*test)(const struct alg_test_desc *desc, const char *driver, @@ -130,6 +136,7 @@ struct alg_test_desc { struct hash_test_suite hash; struct cprng_test_suite cprng; struct drbg_test_suite drbg; + struct akcipher_test_suite akcipher; } suite; }; @@ -1825,6 +1832,147 @@ static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver, } +static int do_test_rsa(struct crypto_akcipher *tfm, + struct akcipher_testvec *vecs) +{ + struct akcipher_request *req; + void *outbuf_enc = NULL; + void *outbuf_dec = NULL; + struct tcrypt_result result; + unsigned int out_len_max, out_len = 0; + int err = -ENOMEM; + + req = akcipher_request_alloc(tfm, GFP_KERNEL); + if (!req) + return err; + + init_completion(result.completion); + err = crypto_akcipher_setkey(tfm, vecs-key, vecs-key_len); + if (err) + goto free_req; + + akcipher_request_set_crypt(req, vecs-m, outbuf_enc, vecs-m_size, + out_len); + /* expect this to fail, and update the required buf len */ + crypto_akcipher_encrypt(req); + out_len = req-dst_len; + if (!out_len) { + err = -EINVAL; + goto free_req; + } + + out_len_max = out_len; + err = -ENOMEM; + outbuf_enc = kzalloc(out_len_max, GFP_KERNEL); + if (!outbuf_enc) + goto free_req; + + akcipher_request_set_crypt(req, vecs-m, outbuf_enc, vecs-m_size, + out_len); + akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + tcrypt_complete, result); + + /* Run RSA encrypt - c = m^e mod n;*/ + err = wait_async_op(result, crypto_akcipher_encrypt(req)); + if (err) { + pr_err(alg: rsa: encrypt test failed. err %d\n, err); + goto free_all; + } + if (out_len != vecs-c_size) { + pr_err(alg: rsa: encrypt test failed. Invalid output len\n); + err = -EINVAL; + goto free_all; + } + /* verify that encrypted message is equal to expected */ + if (memcmp(vecs-c, outbuf_enc, vecs-c_size)) { + pr_err(alg: rsa: encrypt test failed. Invalid output\n); + err = -EINVAL; + goto free_all; + } + /* Don't invoke decrypt for vectors with public key */ + if (vecs-public_key_vec) { + err = 0; + goto free_all; + } + outbuf_dec = kzalloc(out_len_max, GFP_KERNEL); + if (!outbuf_dec) { + err = -ENOMEM; + goto free_all; + } + init_completion(result.completion); + akcipher_request_set_crypt(req, outbuf_enc, outbuf_dec, vecs-c_size, + out_len); + + /* Run RSA decrypt - m = c^d mod n;*/ + err = wait_async_op(result, crypto_akcipher_decrypt(req)); + if (err) { + pr_err(alg: rsa: decrypt test failed. err %d\n, err); + goto free_all; + } + out_len = req-dst_len; + if (out_len != vecs-m_size) { + pr_err(alg: rsa: decrypt test failed. Invalid output len\n); + err = -EINVAL; + goto free_all; + } + /* verify that decrypted message is equal to the original msg */ + if (memcmp(vecs-m, outbuf_dec, vecs-m_size)) { + pr_err(alg: rsa: decrypt test failed. Invalid output\n); + err = -EINVAL; + } +free_all: + kfree(outbuf_dec); + kfree(outbuf_enc); +free_req: + akcipher_request_free(req); + return err
[PATCH RFC v7 0/3] crypto: Introduce Public Key Encryption API
This patch set introduces a Public Key Encryption API. What is proposed is a new crypto type called crypto_akcipher_type, plus new struct akcipher_alg and struct crypto_akcipher, together with number of helper functions to register akcipher type algorithms and allocate tfm instances. This is to make it similar to how the existing crypto API works for the ablkcipher, ahash, and aead types. The operations the new interface will allow to provide are: int (*sign)(struct akcipher_request *req); int (*verify)(struct akcipher_request *req); int (*encrypt)(struct akcipher_request *req); int (*decrypt)(struct akcipher_request *req); The benefits it gives interface are: - drivers can add many implementations of RSA or DSA algorithms and user will allocate instances (tfms) of these, base on algorithm priority, in the same way as it is with the symmetric ciphers. - the new interface allows for asynchronous implementations that can use crypto hardware to offload the calculations to. - integrating it with linux crypto api allows using all its benefits i.e. managing algorithms using NETLINK_CRYPTO, monitoring implementations using /proc/crypto. etc New helper functions have been added to allocate crypto_akcipher instances and invoke the operations to make it easier to use. For instance to verify a public_signature against a public_key using the RSA algorithm a user would do: struct crypto_akcipher *tfm = crypto_alloc_akcipher(rsa, 0, 0); struct akcipher_request *req = akcipher_request_alloc(tfm, GFP_KERNEL); akcipher_request_set_crypt(req, pub_key, signature); int ret = crypto_akcipher_verify(src, dst, src_len, dst_len, res_len); akcipher_request_free(req); crypto_free_akcipher(tfm); return ret; Changes in v7: - change req-dst_len to be int instead of int * - remove result_len from comments - it's not longer there - use crypto_akcipher_reqtfm helper instead of __crypto_akcipher_tfm - fix memleak in rsa.c - change error code to -EOVERFLOW if dst buf is not big enough - drop redundant cra_ctxsize inits - add type-safe init/exit functions - cleanup headers in rsa_helpers - remove checks for NULL before mpi_free Changes in v6: - in FIPS mode only allow key sizes 2K 3K - remove result_len and use dst_len as in/out param - remove subtype from akcipher reports - store rsa_key in tfm ctx and change ras_parse_key to take struct rsa_key instead of tfm. - export rsa_free_key, which free memory allocated by ras_parse_key. - split akcipher.h into public and internal with public key specific helpers - remove maxsize() and set the required size in enc/dec/sign/verify instead - add public key vector - split AKCIPHER into AKCIPHER and AKCIPHER2 in Kconfig - remove MPI patch from the series - already applied Changes in v5: - make mpi_get_size() function inline. - add a setkey function to the algorithm and rsa_parse_key() helper to parse rsa keys from BER encoded to MPI. The helper will also validate the given key if it is strong enough in case FIPS mode is enabled. - change the format of the key from struct public_key * to void * BER encoded buffer. - change the format of the rsa keys in testmgr to BER encoded form. - change mpi_free to use kzfree instead of kfree because it is used to free crypto keys Changes in v4: - add an rsa generic implementation - don't convert the existing public_key implementation to the new interface. This will be done after the new interface is accepted. - add new mpi_get_buf(), mpi_copy() and mpi_get_size() mpi helpers - on set key the ftm now will clone the key instead of just setting a ptr - add a check on enc/dec/sign/veryfi to make sure a valid (public or private) key is setup - add maxsize fn into algorith that will be used to query implementation what is the max size of a result for a give public key that the user needs to allocate - removed private ctx from crypto_akcipher as the crypto_tfm base has one already - add 2K bit RSA test vectors - add cipher text validation in crypto test mgr as (required for FIPS) Changes in v3: - changed input and output parameters type from sgl to void * and added separate src_len dst_len - requested by Herbert Xu - separated rsa implementation into cryptographic primitives and left encryption scheme details outside of the algorithm implementation - added SW implementation for RSA encrypt, decrypt and sign operation - added RSA test vectors Changes in v2: - remodeled not to use obsolete cra_u and crt_u unions - changed type/funct names from pke_* to pkey_* - retained the enum pkey_algo type for it is external to the kernel - added documentation --- Tadeusz Struk (3): crypto: add PKE API crypto: rsa: add a new rsa generic implementation crypto: add tests vectors for RSA crypto/Kconfig | 19 ++ crypto/Makefile|9
[PATCH RFC v7 2/3] crypto: rsa: add a new rsa generic implementation
Add a new rsa generic SW implementation. This implements only cryptographic primitives. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/Kconfig|7 + crypto/Makefile |8 + crypto/rsa.c | 315 + crypto/rsa_helper.c | 121 crypto/rsakey.asn1|5 + include/crypto/internal/rsa.h | 27 6 files changed, 483 insertions(+) create mode 100644 crypto/rsa.c create mode 100644 crypto/rsa_helper.c create mode 100644 crypto/rsakey.asn1 create mode 100644 include/crypto/internal/rsa.h diff --git a/crypto/Kconfig b/crypto/Kconfig index 264dadb..52467cf 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -102,6 +102,13 @@ config CRYPTO_AKCIPHER help Crypto API interface for public key algorithms. +config CRYPTO_RSA + tristate RSA algorithm + select AKCIPHER + select MPILIB + help + Generic implementation of the RSA public key algorithm. + config CRYPTO_MANAGER tristate Cryptographic algorithm manager select CRYPTO_MANAGER2 diff --git a/crypto/Makefile b/crypto/Makefile index 1ed382d..0077476 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -30,6 +30,14 @@ obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o +$(obj)/rsakey-asn1.o: $(obj)/rsakey-asn1.c $(obj)/rsakey-asn1.h +clean-files += rsakey-asn1.c rsakey-asn1.h + +rsa_generic-y := rsakey-asn1.o +rsa_generic-y += rsa.o +rsa_generic-y += rsa_helper.o +obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o + cryptomgr-y := algboss.o testmgr.o obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o diff --git a/crypto/rsa.c b/crypto/rsa.c new file mode 100644 index 000..752af06 --- /dev/null +++ b/crypto/rsa.c @@ -0,0 +1,315 @@ +/* RSA asymmetric public-key algorithm [RFC3447] + * + * Copyright (c) 2015, Intel Corporation + * Authors: Tadeusz Struk tadeusz.st...@intel.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#include linux/module.h +#include crypto/internal/rsa.h +#include crypto/internal/akcipher.h +#include crypto/akcipher.h + +/* + * RSAEP function [RFC3447 sec 5.1.1] + * c = m^e mod n; + */ +static int _rsa_enc(const struct rsa_key *key, MPI c, MPI m) +{ + /* (1) Validate 0 = m n */ + if (mpi_cmp_ui(m, 0) 0 || mpi_cmp(m, key-n) = 0) + return -EINVAL; + + /* (2) c = m^e mod n */ + return mpi_powm(c, m, key-e, key-n); +} + +/* + * RSADP function [RFC3447 sec 5.1.2] + * m = c^d mod n; + */ +static int _rsa_dec(const struct rsa_key *key, MPI m, MPI c) +{ + /* (1) Validate 0 = c n */ + if (mpi_cmp_ui(c, 0) 0 || mpi_cmp(c, key-n) = 0) + return -EINVAL; + + /* (2) m = c^d mod n */ + return mpi_powm(m, c, key-d, key-n); +} + +/* + * RSASP1 function [RFC3447 sec 5.2.1] + * s = m^d mod n + */ +static int _rsa_sign(const struct rsa_key *key, MPI s, MPI m) +{ + /* (1) Validate 0 = m n */ + if (mpi_cmp_ui(m, 0) 0 || mpi_cmp(m, key-n) = 0) + return -EINVAL; + + /* (2) s = m^d mod n */ + return mpi_powm(s, m, key-d, key-n); +} + +/* + * RSAVP1 function [RFC3447 sec 5.2.2] + * m = s^e mod n; + */ +static int _rsa_verify(const struct rsa_key *key, MPI m, MPI s) +{ + /* (1) Validate 0 = s n */ + if (mpi_cmp_ui(s, 0) 0 || mpi_cmp(s, key-n) = 0) + return -EINVAL; + + /* (2) m = s^e mod n */ + return mpi_powm(m, s, key-e, key-n); +} + +static inline struct rsa_key *rsa_get_key(struct crypto_akcipher *tfm) +{ + return akcipher_tfm_ctx(tfm); +} + +static int rsa_enc(struct akcipher_request *req) +{ + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); + const struct rsa_key *pkey = rsa_get_key(tfm); + MPI m, c = mpi_alloc(0); + int ret = 0; + int sign; + + if (!c) + return -ENOMEM; + + if (unlikely(!pkey-n || !pkey-e)) { + ret = -EINVAL; + goto err_free_c; + } + + if (req-dst_len mpi_get_size(pkey-n)) { + req-dst_len = mpi_get_size(pkey-n); + ret = -EOVERFLOW; + goto err_free_c; + } + + m = mpi_read_raw_data(req-src, req-src_len); + if (!m) { + ret = -ENOMEM; + goto err_free_c; + } + + ret = _rsa_enc(pkey, c, m); + if (ret) + goto err_free_m; + + ret = mpi_read_buffer(c, req-dst, req-dst_len, req-dst_len, sign); + if (ret) + goto err_free_m; + + if (sign 0) { + ret = -EBADMSG; + goto err_free_m; + } + +err_free_m
[PATCH RFC v7 1/3] crypto: add PKE API
Add Public Key Encryption API. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/Kconfig | 11 + crypto/Makefile|1 crypto/akcipher.c | 117 crypto/crypto_user.c | 22 ++ include/crypto/akcipher.h | 340 include/crypto/internal/akcipher.h | 60 ++ include/linux/crypto.h |1 include/linux/cryptouser.h |5 + 8 files changed, 557 insertions(+) create mode 100644 crypto/akcipher.c create mode 100644 include/crypto/akcipher.h create mode 100644 include/crypto/internal/akcipher.h diff --git a/crypto/Kconfig b/crypto/Kconfig index f6fc054..264dadb 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -91,6 +91,17 @@ config CRYPTO_PCOMP2 tristate select CRYPTO_ALGAPI2 +config CRYPTO_AKCIPHER2 + tristate + select CRYPTO_ALGAPI2 + +config CRYPTO_AKCIPHER + tristate Public Key Algorithms API + select CRYPTO_AKCIPHER2 + select CRYPTO_ALGAPI + help + Crypto API interface for public key algorithms. + config CRYPTO_MANAGER tristate Cryptographic algorithm manager select CRYPTO_MANAGER2 diff --git a/crypto/Makefile b/crypto/Makefile index c842035..1ed382d 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -28,6 +28,7 @@ crypto_hash-y += shash.o obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o +obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o cryptomgr-y := algboss.o testmgr.o diff --git a/crypto/akcipher.c b/crypto/akcipher.c new file mode 100644 index 000..d798641 --- /dev/null +++ b/crypto/akcipher.c @@ -0,0 +1,117 @@ +/* + * Public Key Encryption + * + * Copyright (c) 2015, Intel Corporation + * Authors: Tadeusz Struk tadeusz.st...@intel.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include linux/errno.h +#include linux/kernel.h +#include linux/module.h +#include linux/seq_file.h +#include linux/slab.h +#include linux/string.h +#include linux/crypto.h +#include crypto/algapi.h +#include linux/cryptouser.h +#include net/netlink.h +#include crypto/akcipher.h +#include crypto/public_key.h +#include internal.h + +#ifdef CONFIG_NET +static int crypto_akcipher_report(struct sk_buff *skb, struct crypto_alg *alg) +{ + struct crypto_report_akcipher rakcipher; + + strncpy(rakcipher.type, akcipher, sizeof(rakcipher.type)); + + if (nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER, + sizeof(struct crypto_report_akcipher), rakcipher)) + goto nla_put_failure; + return 0; + +nla_put_failure: + return -EMSGSIZE; +} +#else +static int crypto_akcipher_report(struct sk_buff *skb, struct crypto_alg *alg) +{ + return -ENOSYS; +} +#endif + +static void crypto_akcipher_show(struct seq_file *m, struct crypto_alg *alg) + __attribute__ ((unused)); + +static void crypto_akcipher_show(struct seq_file *m, struct crypto_alg *alg) +{ + seq_puts(m, type : akcipher\n); +} + +static void crypto_akcipher_exit_tfm(struct crypto_tfm *tfm) +{ + struct crypto_akcipher *akcipher = __crypto_akcipher_tfm(tfm); + struct akcipher_alg *alg = crypto_akcipher_alg(akcipher); + + alg-exit(akcipher); +} + +static int crypto_akcipher_init_tfm(struct crypto_tfm *tfm) +{ + struct crypto_akcipher *akcipher = __crypto_akcipher_tfm(tfm); + struct akcipher_alg *alg = crypto_akcipher_alg(akcipher); + + if (alg-exit) + akcipher-base.exit = crypto_akcipher_exit_tfm; + + if (alg-init) + return alg-init(akcipher); + + return 0; +} + +static const struct crypto_type crypto_akcipher_type = { + .extsize = crypto_alg_extsize, + .init_tfm = crypto_akcipher_init_tfm, +#ifdef CONFIG_PROC_FS + .show = crypto_akcipher_show, +#endif + .report = crypto_akcipher_report, + .maskclear = ~CRYPTO_ALG_TYPE_MASK, + .maskset = CRYPTO_ALG_TYPE_MASK, + .type = CRYPTO_ALG_TYPE_AKCIPHER, + .tfmsize = offsetof(struct crypto_akcipher, base), +}; + +struct crypto_akcipher *crypto_alloc_akcipher(const char *alg_name, u32 type, + u32 mask) +{ + return crypto_alloc_tfm(alg_name, crypto_akcipher_type, type, mask); +} +EXPORT_SYMBOL_GPL(crypto_alloc_akcipher); + +int crypto_register_akcipher(struct akcipher_alg *alg) +{ + struct crypto_alg *base = alg-base; + + base-cra_type = crypto_akcipher_type; + base-cra_flags = ~CRYPTO_ALG_TYPE_MASK; + base-cra_flags |= CRYPTO_ALG_TYPE_AKCIPHER; + return crypto_register_alg(base); +} +EXPORT_SYMBOL_GPL(crypto_register_akcipher); + +void
Re: [PATCH RFC v4 2/4] crypto: add PKE API
On 06/11/2015 07:59 PM, Herbert Xu wrote: +int crypto_akcipher_setkey(struct crypto_akcipher *tfm, + const struct public_key *pkey) +{ + if (tfm-pkey) + akcipher_free_key(tfm-pkey); + + return akcipher_clone_key(tfm, pkey); +} No please do not expose the struct public_key crap to the new API. The key should be completely opaque to entities outside of the algorithm. So make it raw and read out the MPIs from it. The contents of the function must go into the algorithm setkey function, not the crypto API. So RSA would read out however many MPIs it needs and verify it, and so on. Should I make it MPI[] rather than void * -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC v4 1/4] MPILIB: add mpi_read_buf(), mpi_copy() and mpi_get_size() helpers
On 06/12/2015 09:21 AM, Stephan Mueller wrote: +void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign) +{ + uint8_t *buf, *p; + int n, ret; + + if (!nbytes) + return NULL; + + n = mpi_get_size(a); Shouldn't n be unsigned int? You are right, thanks. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC v7 2/3] crypto: rsa: add a new rsa generic implementation
Hi David, On 06/16/2015 03:10 PM, David Howells wrote: +static int _rsa_sign(const struct rsa_key *key, MPI s, MPI m) +{ + /* (1) Validate 0 = m n */ + if (mpi_cmp_ui(m, 0) 0 || mpi_cmp(m, key-n) = 0) + return -EINVAL; Why -EINVAL not -EBADMSG? I thought that -EBADMSG was mainly used for authenticated ciphers in case when verification of auth data fails. Since this are input params I thought that -EINVAL would be more appropriate. I can change it to -EBADMSG, no problem. Herbert, what do you think? -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC v7 2/3] crypto: rsa: add a new rsa generic implementation
On 06/16/2015 07:36 PM, Herbert Xu wrote: The existing crypto/asymmetric_key errno scheme doesn't really mesh in with the rest of crypto. So you'll just have to pick one scheme and stick with it. I don't really mind either way as long as the error codes are unique and meaningful. So I would use -EINVAL since these are input parameters. Do you agree David? -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC v7 0/3] crypto: Introduce Public Key Encryption API
On 06/17/2015 02:14 AM, Herbert Xu wrote: This patch set introduces a Public Key Encryption API. What is proposed is a new crypto type called crypto_akcipher_type, plus new struct akcipher_alg and struct crypto_akcipher, together with number of helper functions to register akcipher type algorithms and allocate tfm instances. This is to make it similar to how the existing crypto API works for the ablkcipher, ahash, and aead types. The operations the new interface will allow to provide are: int (*sign)(struct akcipher_request *req); int (*verify)(struct akcipher_request *req); int (*encrypt)(struct akcipher_request *req); int (*decrypt)(struct akcipher_request *req); All applied with two minor changes. First of all I made AKCIPHER invisible to the user like the other type config options. I also added a missing select on ASN1 that broke my build. Thank you very much for all your help with this Herbert -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC v5 2/4] crypto: add PKE API
On 06/15/2015 05:05 PM, Herbert Xu wrote: + * @setkey: Function invokes the algorithm specific set key function, which + *knows how to decode and interpret the BER encoded key We should split this into two functions: setpubkey and setprivkey. The two functions will be almost identical. We can do it this way if we want to check if all the required elements of the key are provided. Currently I'm checking this in the actual operation. + * + * @reqsize: Request context size required by algorithm implementation + * @base: Common crypto API algorithm data structure + */ +struct akcipher_alg { + int (*sign)(struct akcipher_request *req); + int (*verify)(struct akcipher_request *req); + int (*encrypt)(struct akcipher_request *req); + int (*decrypt)(struct akcipher_request *req); + int (*maxsize)(struct crypto_akcipher *tfm); Hmm, we could actually get rid of maxsize by just having each function check the dst_len and if it is insufficient write the required length in it and then return an error. Can do it that way too. Thanks for your feedback. I will send v6 soon. Thanks T -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC v5 2/4] crypto: add PKE API
On 06/15/2015 07:50 PM, Herbert Xu wrote: If you want to keep the helper generic what you can do is have it take struct rsa_key instead of struct crypto_ablkcipher. Ok I'll do it that way. It definitely should just be an optional helper as opposed to a required part of crypto_akcipher since you could have a piece of hardware that takes the encoded key directly in which case you wouldn't need the helper at all. Oh yes, it is definitely optional. Thanks -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC v5 4/4] crypto: add tests vectors for RSA
On 06/15/2015 05:37 PM, Herbert Xu wrote: config CRYPTO_MANAGER tristate Cryptographic algorithm manager select CRYPTO_MANAGER2 + select CRYPTO_AKCIPHER Please add this to CRYPTO_MANAGER2 instead. This causes a recursive dependency error crypto/Kconfig:115:error: recursive dependency detected! crypto/Kconfig:115: symbol CRYPTO_MANAGER2 default value contains CRYPTO_ALGAPI crypto/Kconfig:34: symbol CRYPTO_ALGAPI is selected by CRYPTO_AKCIPHER crypto/Kconfig:94: symbol CRYPTO_AKCIPHER is selected by CRYPTO_MANAGER2 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC v5 2/4] crypto: add PKE API
On 06/15/2015 08:25 PM, Herbert Xu wrote: The current parse_key function requires all three number to be present, n, e, and d, no? No, it will handle whatever it will find. So if a public key will be passed it will only set n and e. If a private key will be passed it will set all three n, e, and d. Then during operation I check if there is everything that's required. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC v5 2/4] crypto: add PKE API
On 06/15/2015 09:06 PM, Herbert Xu wrote: No, it will handle whatever it will find. So if a public key will be passed it will only set n and e. If a private key will be passed it will set all three n, e, and d. Then during operation I check if there is everything that's required. AFAICS the ASN1 parser will call all three functions and bomb out if any one of them fails. If you did make them all optional then you'd need to check to ensure that at least n and e are present. Also all your test vectors contain private keys. Please add at least one that contains a public key only to test this. I've just tested it and it works fine for both private and public keys. I'll add one vector to test only public key case. Thanks -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC v5 2/4] crypto: add PKE API
On 06/15/2015 04:59 PM, Herbert Xu wrote: +struct crypto_akcipher { + void *key; Having a void * pointer here is useless. The normal way of doing it is to place the key into the tfm context. I thought that the ctx needs to be available for implementations to store private data. This way we can allocate and store any type of key in the alg_parse_key() helper and still have the cxt available for implementations to use for their stuff (e.g. HW context). -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC v5 2/4] crypto: add PKE API
On 06/15/2015 05:05 PM, Herbert Xu wrote: Hmm, we could actually get rid of maxsize by just having each function check the dst_len and if it is insufficient write the required length in it and then return an error. Actually I think it is useful. Without it the user will need to allocate a buffer, and invoke an operation only to find out that the buffer need to be bigger. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC v5 3/4] crypto: rsa: add a new rsa generic implementation
On 06/15/2015 07:19 PM, Stephan Mueller wrote: I'm not familiar with the FIPS requirements. I checked the NIST recommendations witch states that RSA: |n| = 2048 is acceptable. If FIPS allows 2K and 3K only then we need to change it. The reason for exclusive 2k/3k is the CAVS testing: there is only the ability to test 2/3k. Longer key sizes are even not allowed as per SP800-131A in favor of EC. Ok I'll update it to only accept 2K 3K. Thanks -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH RFC v5 3/4] crypto: rsa: add a new rsa generic implementation
Add a new rsa generic SW implementation. This implements only cryptographic primitives. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/Kconfig|7 + crypto/Makefile |8 + crypto/rsa.c | 295 + crypto/rsa_helper.c | 134 +++ crypto/rsakey.asn1|5 + include/crypto/internal/rsa.h | 30 6 files changed, 479 insertions(+) create mode 100644 crypto/rsa.c create mode 100644 crypto/rsa_helper.c create mode 100644 crypto/rsakey.asn1 create mode 100644 include/crypto/internal/rsa.h diff --git a/crypto/Kconfig b/crypto/Kconfig index ed413d9..a09404b 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -97,6 +97,13 @@ config CRYPTO_AKCIPHER help Crypto API interface for public key algorithms. +config CRYPTO_RSA + tristate RSA algorithm + select AKCIPHER + select MPILIB + help + Generic implementation of the RSA public key algorithm. + config CRYPTO_MANAGER tristate Cryptographic algorithm manager select CRYPTO_MANAGER2 diff --git a/crypto/Makefile b/crypto/Makefile index 6f2940a..c6217ea 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -30,6 +30,14 @@ obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o obj-$(CONFIG_CRYPTO_AKCIPHER) += akcipher.o +$(obj)/rsakey-asn1.o: $(obj)/rsakey-asn1.c $(obj)/rsakey-asn1.h +clean-files += rsakey-asn1.c rsakey-asn1.h + +rsa_generic-y := rsakey-asn1.o +rsa_generic-y += rsa.o +rsa_generic-y += rsa_helper.o +obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o + cryptomgr-y := algboss.o testmgr.o obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o diff --git a/crypto/rsa.c b/crypto/rsa.c new file mode 100644 index 000..176f565 --- /dev/null +++ b/crypto/rsa.c @@ -0,0 +1,295 @@ +/* RSA asymmetric public-key algorithm [RFC3447] + * + * Copyright (c) 2015, Intel Corporation + * Authors: Tadeusz Struk tadeusz.st...@intel.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#include linux/module.h +#include crypto/internal/rsa.h +#include crypto/akcipher.h + +/* + * RSAEP function [RFC3447 sec 5.1.1] + * c = m^e mod n; + */ +static int _rsa_enc(const struct rsa_key *key, MPI c, MPI m) +{ + /* (1) Validate 0 = m n */ + if (mpi_cmp_ui(m, 0) 0 || mpi_cmp(m, key-n) = 0) + return -EINVAL; + + /* (2) c = m^e mod n */ + return mpi_powm(c, m, key-e, key-n); +} + +/* + * RSADP function [RFC3447 sec 5.1.2] + * m = c^d mod n; + */ +static int _rsa_dec(const struct rsa_key *key, MPI m, MPI c) +{ + /* (1) Validate 0 = c n */ + if (mpi_cmp_ui(c, 0) 0 || mpi_cmp(c, key-n) = 0) + return -EINVAL; + + /* (2) m = c^d mod n */ + return mpi_powm(m, c, key-d, key-n); +} + +/* + * RSASP1 function [RFC3447 sec 5.2.1] + * s = m^d mod n + */ +static int _rsa_sign(const struct rsa_key *key, MPI s, MPI m) +{ + /* (1) Validate 0 = m n */ + if (mpi_cmp_ui(m, 0) 0 || mpi_cmp(m, key-n) = 0) + return -EINVAL; + + /* (2) s = m^d mod n */ + return mpi_powm(s, m, key-d, key-n); +} + +/* + * RSAVP1 function [RFC3447 sec 5.2.2] + * m = s^e mod n; + */ +static int _rsa_verify(const struct rsa_key *key, MPI m, MPI s) +{ + /* (1) Validate 0 = s n */ + if (mpi_cmp_ui(s, 0) 0 || mpi_cmp(s, key-n) = 0) + return -EINVAL; + + /* (2) m = s^e mod n */ + return mpi_powm(m, s, key-e, key-n); +} + +static int rsa_enc(struct akcipher_request *req) +{ + struct crypto_akcipher *tfm = akcipher_request_get_tfm(req); + const struct rsa_key *pkey = rsa_get_key(tfm); + MPI m, c = mpi_alloc(0); + unsigned int len; + int ret = 0; + int sign; + + if (!c) + return -ENOMEM; + + if (!pkey-n || !pkey-e || req-dst_len mpi_get_size(pkey-n)) + return -EINVAL; + + m = mpi_read_raw_data(req-src, req-src_len); + if (!m) { + ret = -ENOMEM; + goto err_free_c; + } + + ret = _rsa_enc(pkey, c, m); + if (ret) + goto err_free_m; + + ret = mpi_read_buffer(c, req-dst, req-dst_len, len, sign); + if (ret) + goto err_free_m; + + if (sign 0) { + ret = -EBADMSG; + goto err_free_m; + } + + if (req-result_len) + *req-result_len = len; + +err_free_m: + mpi_free(m); +err_free_c: + mpi_free(c); + return ret; +} + +static int rsa_dec(struct akcipher_request *req) +{ + struct crypto_akcipher *tfm = akcipher_request_get_tfm(req); + const struct rsa_key *pkey = rsa_get_key(tfm
[PATCH RFC v5 2/4] crypto: add PKE API
Add Public Key Encryption API. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/Kconfig |6 + crypto/Makefile|1 crypto/akcipher.c | 102 +++ crypto/crypto_user.c | 23 +++ include/crypto/akcipher.h | 404 include/linux/crypto.h |1 include/linux/cryptouser.h |6 + 7 files changed, 543 insertions(+) create mode 100644 crypto/akcipher.c create mode 100644 include/crypto/akcipher.h diff --git a/crypto/Kconfig b/crypto/Kconfig index f6fc054..ed413d9 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -91,6 +91,12 @@ config CRYPTO_PCOMP2 tristate select CRYPTO_ALGAPI2 +config CRYPTO_AKCIPHER + tristate Public Key Algorithms API + select CRYPTO_ALGAPI + help + Crypto API interface for public key algorithms. + config CRYPTO_MANAGER tristate Cryptographic algorithm manager select CRYPTO_MANAGER2 diff --git a/crypto/Makefile b/crypto/Makefile index c842035..6f2940a 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -28,6 +28,7 @@ crypto_hash-y += shash.o obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o +obj-$(CONFIG_CRYPTO_AKCIPHER) += akcipher.o cryptomgr-y := algboss.o testmgr.o diff --git a/crypto/akcipher.c b/crypto/akcipher.c new file mode 100644 index 000..be65374 --- /dev/null +++ b/crypto/akcipher.c @@ -0,0 +1,102 @@ +/* + * Public Key Encryption + * + * Copyright (c) 2015, Intel Corporation + * Authors: Tadeusz Struk tadeusz.st...@intel.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include linux/errno.h +#include linux/kernel.h +#include linux/module.h +#include linux/seq_file.h +#include linux/slab.h +#include linux/string.h +#include linux/crypto.h +#include crypto/algapi.h +#include linux/cryptouser.h +#include net/netlink.h +#include crypto/akcipher.h +#include crypto/public_key.h +#include internal.h + +#ifdef CONFIG_NET +static int crypto_akcipher_report(struct sk_buff *skb, struct crypto_alg *alg) +{ + struct crypto_report_akcipher rakcipher; + + strncpy(rakcipher.type, akcipher, sizeof(rakcipher.type)); + strncpy(rakcipher.subtype, alg-cra_name, sizeof(rakcipher.subtype)); + + if (nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER, + sizeof(struct crypto_report_akcipher), rakcipher)) + goto nla_put_failure; + return 0; + +nla_put_failure: + return -EMSGSIZE; +} +#else +static int crypto_akcipher_report(struct sk_buff *skb, struct crypto_alg *alg) +{ + return -ENOSYS; +} +#endif + +static void crypto_akcipher_show(struct seq_file *m, struct crypto_alg *alg) + __attribute__ ((unused)); + +static void crypto_akcipher_show(struct seq_file *m, struct crypto_alg *alg) +{ + seq_puts(m, type : akcipher\n); + seq_printf(m, subtype : %s\n, alg-cra_name); +} + +static int crypto_akcipher_init_tfm(struct crypto_tfm *tfm) +{ + return 0; +} + +static const struct crypto_type crypto_akcipher_type = { + .extsize = crypto_alg_extsize, + .init_tfm = crypto_akcipher_init_tfm, +#ifdef CONFIG_PROC_FS + .show = crypto_akcipher_show, +#endif + .report = crypto_akcipher_report, + .maskclear = ~CRYPTO_ALG_TYPE_MASK, + .maskset = CRYPTO_ALG_TYPE_MASK, + .type = CRYPTO_ALG_TYPE_AKCIPHER, + .tfmsize = offsetof(struct crypto_akcipher, base), +}; + +struct crypto_akcipher *crypto_alloc_akcipher(const char *alg_name, u32 type, + u32 mask) +{ + return crypto_alloc_tfm(alg_name, crypto_akcipher_type, type, mask); +} +EXPORT_SYMBOL_GPL(crypto_alloc_akcipher); + +int crypto_register_akcipher(struct akcipher_alg *alg) +{ + struct crypto_alg *base = alg-base; + + base-cra_type = crypto_akcipher_type; + base-cra_flags = ~CRYPTO_ALG_TYPE_MASK; + base-cra_flags |= CRYPTO_ALG_TYPE_AKCIPHER; + return crypto_register_alg(base); +} +EXPORT_SYMBOL_GPL(crypto_register_akcipher); + +void crypto_unregister_akcipher(struct akcipher_alg *alg) +{ + crypto_unregister_alg(alg-base); +} +EXPORT_SYMBOL_GPL(crypto_unregister_akcipher); + +MODULE_LICENSE(GPL); +MODULE_DESCRIPTION(Generic public key cihper type); diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index 41dfe76..508e71d 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -27,6 +27,7 @@ #include net/net_namespace.h #include crypto/internal/aead.h #include crypto/internal/skcipher.h +#include crypto/akcipher.h #include internal.h @@ -110,6 +111,22 @@ nla_put_failure: return -EMSGSIZE; } +static int crypto_report_akcipher(struct sk_buff *skb, struct
[PATCH RFC v5 4/4] crypto: add tests vectors for RSA
New test vectors for RSA algorithm. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/Kconfig |1 crypto/testmgr.c | 149 ++ crypto/testmgr.h | 143 3 files changed, 293 insertions(+) diff --git a/crypto/Kconfig b/crypto/Kconfig index a09404b..90c1f77 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -107,6 +107,7 @@ config CRYPTO_RSA config CRYPTO_MANAGER tristate Cryptographic algorithm manager select CRYPTO_MANAGER2 + select CRYPTO_AKCIPHER help Create default cryptographic template instantiations such as cbc(aes). diff --git a/crypto/testmgr.c b/crypto/testmgr.c index ccd19cf..ff41714 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -30,6 +30,7 @@ #include linux/string.h #include crypto/rng.h #include crypto/drbg.h +#include crypto/akcipher.h #include internal.h @@ -116,6 +117,11 @@ struct drbg_test_suite { unsigned int count; }; +struct akcipher_test_suite { + struct akcipher_testvec *vecs; + unsigned int count; +}; + struct alg_test_desc { const char *alg; int (*test)(const struct alg_test_desc *desc, const char *driver, @@ -130,6 +136,7 @@ struct alg_test_desc { struct hash_test_suite hash; struct cprng_test_suite cprng; struct drbg_test_suite drbg; + struct akcipher_test_suite akcipher; } suite; }; @@ -1825,6 +1832,138 @@ static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver, } +static int do_test_rsa(struct crypto_akcipher *tfm, + struct akcipher_testvec *vecs) +{ + struct akcipher_request *req; + void *outbuf_enc = NULL; + void *outbuf_dec = NULL; + struct tcrypt_result result; + unsigned int max_out_len, out_len; + int err = -ENOMEM; + + req = akcipher_request_alloc(tfm, GFP_KERNEL); + if (!req) + return err; + + init_completion(result.completion); + err = crypto_akcipher_setkey(tfm, vecs-key, vecs-key_len); + if (err) + goto free_req; + + err = -EINVAL; + max_out_len = crypto_akcipher_maxsize(tfm); + if (!(max_out_len 0)) + goto free_req; + + err = -ENOMEM; + outbuf_enc = kzalloc(max_out_len, GFP_KERNEL); + if (!outbuf_enc) + goto free_req; + + akcipher_request_set_crypt(req, vecs-m, outbuf_enc, vecs-m_size, + max_out_len, out_len); + akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + tcrypt_complete, result); + + /* Run RSA encrypt - c = m^e mod n;*/ + err = wait_async_op(result, crypto_akcipher_encrypt(req)); + if (err) { + pr_err(alg: rsa: encrypt test failed. err %d\n, err); + goto free_all; + } + + if (out_len != vecs-c_size) { + err = -EINVAL; + goto free_all; + } + /* verify that encrypted message is equal to expected */ + if (memcmp(vecs-c, outbuf_enc, vecs-c_size)) { + pr_err(alg: rsa: encrypt test failed. Invalid output\n); + err = -EINVAL; + goto free_all; + } + + outbuf_dec = kzalloc(max_out_len, GFP_KERNEL); + if (!outbuf_dec) { + err = -ENOMEM; + goto free_all; + } + + init_completion(result.completion); + akcipher_request_set_crypt(req, outbuf_enc, outbuf_dec, vecs-c_size, + max_out_len, out_len); + + /* Run RSA decrypt - m = c^d mod n;*/ + err = wait_async_op(result, crypto_akcipher_decrypt(req)); + if (err) { + pr_err(alg: rsa: decrypt test failed. err %d\n, err); + goto free_all; + } + + if (out_len != vecs-m_size) { + err = -EINVAL; + goto free_all; + } + + /* verify that decrypted message is equal to the original msg */ + if (memcmp(vecs-m, outbuf_dec, vecs-m_size)) { + pr_err(alg: rsa: encrypt test failed. Invalid output\n); + err = -EINVAL; + } +free_all: + kfree(outbuf_dec); + kfree(outbuf_enc); +free_req: + akcipher_request_free(req); + return err; +} + +static int test_rsa(struct crypto_akcipher *tfm, struct akcipher_testvec *vecs, + unsigned int tcount) +{ + int ret, i; + + for (i = 0; i tcount; i++) { + ret = do_test_rsa(tfm, vecs++); + if (ret) { + pr_err(alg: rsa: test failed on vector %d, err=%d\n, + i + 1, ret); + return ret; + } + } + return 0; +} + +static int test_akcipher(struct crypto_akcipher *tfm
[PATCH RFC v5 1/4] MPILIB: add mpi_read_buf() and mpi_get_size() helpers
Added a mpi_read_buf() helper function to export MPI to a buf provided by the user, and a mpi_get_size() helper, that tells the user how big the buf is. Changed mpi_free to use kzfree instead of kfree because it is used to free crypto keys. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- include/linux/mpi.h | 15 + lib/mpi/mpicoder.c | 87 --- lib/mpi/mpiutil.c |6 ++-- 3 files changed, 86 insertions(+), 22 deletions(-) diff --git a/include/linux/mpi.h b/include/linux/mpi.h index 5af1b81..641b7d6 100644 --- a/include/linux/mpi.h +++ b/include/linux/mpi.h @@ -81,6 +81,8 @@ MPI mpi_read_from_buffer(const void *buffer, unsigned *ret_nread); int mpi_fromstr(MPI val, const char *str); u32 mpi_get_keyid(MPI a, u32 *keyid); void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign); +int mpi_read_buffer(MPI a, uint8_t *buf, unsigned buf_len, unsigned *nbytes, + int *sign); void *mpi_get_secure_buffer(MPI a, unsigned *nbytes, int *sign); int mpi_set_buffer(MPI a, const void *buffer, unsigned nbytes, int sign); @@ -142,4 +144,17 @@ int mpi_rshift(MPI x, MPI a, unsigned n); /*-- mpi-inv.c --*/ int mpi_invm(MPI x, MPI u, MPI v); +/* inline functions */ + +/** + * mpi_get_size() - returns max size required to store the number + * + * @a: A multi precision integer for which we want to allocate a bufer + * + * Return: size required to store the number + */ +static inline unsigned int mpi_get_size(MPI a) +{ + return a-nlimbs * BYTES_PER_MPI_LIMB; +} #endif /*G10_MPI_H */ diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index 4cc6442..bc0a1da 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -128,28 +128,36 @@ leave: } EXPORT_SYMBOL_GPL(mpi_read_from_buffer); -/ - * Return an allocated buffer with the MPI (msb first). - * NBYTES receives the length of this buffer. Caller must free the - * return string (This function does return a 0 byte buffer with NBYTES - * set to zero if the value of A is zero. If sign is not NULL, it will - * be set to the sign of the A. +/** + * mpi_read_buffer() - read MPI to a bufer provided by user (msb first) + * + * @a: a multi precision integer + * @buf: bufer to which the output will be written to. Needs to be at + * leaset mpi_get_size(a) long. + * @buf_len: size of the buf. + * @nbytes:receives the actual length of the data written. + * @sign: if not NULL, it will be set to the sign of a. + * + * Return: 0 on success or error code in case of error */ -void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign) +int mpi_read_buffer(MPI a, uint8_t *buf, unsigned buf_len, unsigned *nbytes, + int *sign) { - uint8_t *p, *buffer; + uint8_t *p; mpi_limb_t alimb; + unsigned int n = mpi_get_size(a); int i; - unsigned int n; + + if (buf_len n || !buf) + return -EINVAL; if (sign) *sign = a-sign; - *nbytes = n = a-nlimbs * BYTES_PER_MPI_LIMB; - if (!n) - n++;/* avoid zero length allocation */ - p = buffer = kmalloc(n, GFP_KERNEL); - if (!p) - return NULL; + + if (nbytes) + *nbytes = n; + + p = buf; for (i = a-nlimbs - 1; i = 0; i--) { alimb = a-d[i]; @@ -171,15 +179,56 @@ void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign) #error please implement for this limb size. #endif } + return 0; +} +EXPORT_SYMBOL_GPL(mpi_read_buffer); + +/* + * mpi_get_buffer() - Returns an allocated buffer with the MPI (msb first). + * Caller must free the return string. + * This function does return a 0 byte buffer with nbytes set to zero if the + * value of A is zero. + * + * @a: a multi precision integer. + * @nbytes:receives the length of this buffer. + * @sign: if not NULL, it will be set to the sign of the a. + * + * Return: Pointer to MPI buffer or NULL on error + */ +void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign) +{ + uint8_t *buf, *p; + unsigned int n; + int ret; + + if (!nbytes) + return NULL; + + n = mpi_get_size(a); + + if (!n) + n++; + + buf = kmalloc(n, GFP_KERNEL); + + if (!buf) + return NULL; + + ret = mpi_read_buffer(a, buf, n, nbytes, sign); + + if (ret) { + kfree(buf); + return NULL; + } /* this is sub-optimal but we need to do the shift operation * because the caller has to free the returned buffer */ - for (p = buffer; !*p *nbytes; p++, --*nbytes) + for (p = buf; !*p *nbytes; p++, --*nbytes) ; - if (p != buffer) - memmove(buffer, p, *nbytes); + if (p != buf) + memmove(buf, p, *nbytes); - return buffer; + return buf
[PATCH RFC v5 0/4] crypto: Introduce Public Key Encryption API
This patch set introduces a Public Key Encryption API. What is proposed is a new crypto type called crypto_akcipher_type, plus new struct akcipher_alg and struct crypto_akcipher, together with number of helper functions to register akcipher type algorithms and allocate tfm instances. This is to make it similar to how the existing crypto API works for the ablkcipher, ahash, and aead types. The operations the new interface will allow to provide are: int (*sign)(struct akcipher_request *req); int (*verify)(struct akcipher_request *req); int (*encrypt)(struct akcipher_request *req); int (*decrypt)(struct akcipher_request *req); The benefits it gives interface are: - drivers can add many implementations of RSA or DSA algorithms and user will allocate instances (tfms) of these, base on algorithm priority, in the same way as it is with the symmetric ciphers. - the new interface allows for asynchronous implementations that can use crypto hardware to offload the calculations to. - integrating it with linux crypto api allows using all its benefits i.e. managing algorithms using NETLINK_CRYPTO, monitoring implementations using /proc/crypto. etc New helper functions have been added to allocate crypto_akcipher instances and invoke the operations to make it easier to use. For instance to verify a public_signature against a public_key using the RSA algorithm a user would do: struct crypto_akcipher *tfm = crypto_alloc_akcipher(rsa, 0, 0); struct akcipher_request *req = akcipher_request_alloc(tfm, GFP_KERNEL); akcipher_request_set_crypt(req, pub_key, signature); int ret = crypto_akcipher_verify(src, dst, src_len, dst_len, res_len); akcipher_request_free(req); crypto_free_akcipher(tfm); return ret; Changes in v5: - make mpi_get_size() function inline. - add a setkey function to the algorithm and rsa_parse_key() helper to parse rsa keys from BER encoded to MPI. The helper will also validate the given key if it is strong enough in case FIPS mode is enabled. - change the format of the key from struct public_key * to void * BER encoded buffer. - change the format of the rsa keys in testmgr to BER encoded form. - change mpi_free to use kzfree instead of kfree because it is used to free crypto keys Changes in v4: - add an rsa generic implementation - don't convert the existing public_key implementation to the new interface. This will be done after the new interface is accepted. - add new mpi_get_buf(), mpi_copy() and mpi_get_size() mpi helpers - on set key the ftm now will clone the key instead of just setting a ptr - add a check on enc/dec/sign/veryfi to make sure a valid (public or private) key is setup - add maxsize fn into algorith that will be used to query implementation what is the max size of a result for a give public key that the user needs to allocate - removed private ctx from crypto_akcipher as the crypto_tfm base has one already - add 2K bit RSA test vectors - add cipher text validation in crypto test mgr as (required for FIPS) Changes in v3: - changed input and output parameters type from sgl to void * and added separate src_len dst_len - requested by Herbert Xu - separated rsa implementation into cryptographic primitives and left encryption scheme details outside of the algorithm implementation - added SW implementation for RSA encrypt, decrypt and sign operation - added RSA test vectors Changes in v2: - remodeled not to use obsolete cra_u and crt_u unions - changed type/funct names from pke_* to pkey_* - retained the enum pkey_algo type for it is external to the kernel - added documentation --- Tadeusz Struk (4): MPILIB: add mpi_read_buf(), mpi_copy() and mpi_get_size() helpers crypto: add PKE API crypto: rsa: add a new rsa generic implementation crypto: add tests vectors for RSA crypto/Kconfig| 14 + crypto/Makefile |9 + crypto/akcipher.c | 102 ++ crypto/crypto_user.c | 23 ++ crypto/rsa.c | 295 ++ crypto/rsa_helper.c | 134 ++ crypto/rsakey.asn1|5 + crypto/testmgr.c | 149 +++ crypto/testmgr.h | 143 +++ include/crypto/akcipher.h | 404 + include/crypto/internal/rsa.h | 30 +++ include/linux/crypto.h|1 include/linux/cryptouser.h|6 + include/linux/mpi.h | 15 ++ lib/mpi/mpicoder.c| 87 +++-- lib/mpi/mpiutil.c | 38 16 files changed, 1434 insertions(+), 21 deletions(-) create mode 100644 crypto/akcipher.c create mode 100644 crypto/rsa.c create mode 100644 crypto/rsa_helper.c create mode 100644 crypto/rsakey.asn1 create mode 100644 include/crypto/akcipher.h create mode 100644 include/crypto
[PATCH RFC v6 2/3] crypto: rsa: add a new rsa generic implementation
Add a new rsa generic SW implementation. This implements only cryptographic primitives. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/Kconfig|7 + crypto/Makefile |8 + crypto/rsa.c | 313 + crypto/rsa_helper.c | 124 crypto/rsakey.asn1|5 + include/crypto/internal/rsa.h | 28 6 files changed, 485 insertions(+) create mode 100644 crypto/rsa.c create mode 100644 crypto/rsa_helper.c create mode 100644 crypto/rsakey.asn1 create mode 100644 include/crypto/internal/rsa.h diff --git a/crypto/Kconfig b/crypto/Kconfig index 264dadb..52467cf 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -102,6 +102,13 @@ config CRYPTO_AKCIPHER help Crypto API interface for public key algorithms. +config CRYPTO_RSA + tristate RSA algorithm + select AKCIPHER + select MPILIB + help + Generic implementation of the RSA public key algorithm. + config CRYPTO_MANAGER tristate Cryptographic algorithm manager select CRYPTO_MANAGER2 diff --git a/crypto/Makefile b/crypto/Makefile index 6f2940a..c6217ea 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -30,6 +30,14 @@ obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o obj-$(CONFIG_CRYPTO_AKCIPHER) += akcipher.o +$(obj)/rsakey-asn1.o: $(obj)/rsakey-asn1.c $(obj)/rsakey-asn1.h +clean-files += rsakey-asn1.c rsakey-asn1.h + +rsa_generic-y := rsakey-asn1.o +rsa_generic-y += rsa.o +rsa_generic-y += rsa_helper.o +obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o + cryptomgr-y := algboss.o testmgr.o obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o diff --git a/crypto/rsa.c b/crypto/rsa.c new file mode 100644 index 000..33bb7f0 --- /dev/null +++ b/crypto/rsa.c @@ -0,0 +1,313 @@ +/* RSA asymmetric public-key algorithm [RFC3447] + * + * Copyright (c) 2015, Intel Corporation + * Authors: Tadeusz Struk tadeusz.st...@intel.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#include linux/module.h +#include crypto/internal/rsa.h +#include crypto/internal/akcipher.h +#include crypto/akcipher.h + +/* + * RSAEP function [RFC3447 sec 5.1.1] + * c = m^e mod n; + */ +static int _rsa_enc(const struct rsa_key *key, MPI c, MPI m) +{ + /* (1) Validate 0 = m n */ + if (mpi_cmp_ui(m, 0) 0 || mpi_cmp(m, key-n) = 0) + return -EINVAL; + + /* (2) c = m^e mod n */ + return mpi_powm(c, m, key-e, key-n); +} + +/* + * RSADP function [RFC3447 sec 5.1.2] + * m = c^d mod n; + */ +static int _rsa_dec(const struct rsa_key *key, MPI m, MPI c) +{ + /* (1) Validate 0 = c n */ + if (mpi_cmp_ui(c, 0) 0 || mpi_cmp(c, key-n) = 0) + return -EINVAL; + + /* (2) m = c^d mod n */ + return mpi_powm(m, c, key-d, key-n); +} + +/* + * RSASP1 function [RFC3447 sec 5.2.1] + * s = m^d mod n + */ +static int _rsa_sign(const struct rsa_key *key, MPI s, MPI m) +{ + /* (1) Validate 0 = m n */ + if (mpi_cmp_ui(m, 0) 0 || mpi_cmp(m, key-n) = 0) + return -EINVAL; + + /* (2) s = m^d mod n */ + return mpi_powm(s, m, key-d, key-n); +} + +/* + * RSAVP1 function [RFC3447 sec 5.2.2] + * m = s^e mod n; + */ +static int _rsa_verify(const struct rsa_key *key, MPI m, MPI s) +{ + /* (1) Validate 0 = s n */ + if (mpi_cmp_ui(s, 0) 0 || mpi_cmp(s, key-n) = 0) + return -EINVAL; + + /* (2) m = s^e mod n */ + return mpi_powm(m, s, key-e, key-n); +} + +static struct rsa_key *rsa_get_key(struct crypto_akcipher *tfm) +{ + return akcipher_tfm_ctx(tfm); +} + +static int rsa_enc(struct akcipher_request *req) +{ + struct crypto_akcipher *tfm = akcipher_request_get_tfm(req); + const struct rsa_key *pkey = rsa_get_key(tfm); + MPI m, c = mpi_alloc(0); + int ret = 0; + int sign; + + if (!c) + return -ENOMEM; + + if (!pkey-n || !pkey-e || !req-dst_len) + return -EINVAL; + + if (*req-dst_len mpi_get_size(pkey-n)) { + *req-dst_len = mpi_get_size(pkey-n); + return -EINVAL; + } + + m = mpi_read_raw_data(req-src, req-src_len); + if (!m) { + ret = -ENOMEM; + goto err_free_c; + } + + ret = _rsa_enc(pkey, c, m); + if (ret) + goto err_free_m; + + ret = mpi_read_buffer(c, req-dst, *req-dst_len, req-dst_len, sign); + if (ret) + goto err_free_m; + + if (sign 0) { + ret = -EBADMSG; + goto err_free_m; + } + +err_free_m: + mpi_free(m); +err_free_c: + mpi_free(c); + return ret
[PATCH RFC v6 0/3] crypto: Introduce Public Key Encryption API
This patch set introduces a Public Key Encryption API. What is proposed is a new crypto type called crypto_akcipher_type, plus new struct akcipher_alg and struct crypto_akcipher, together with number of helper functions to register akcipher type algorithms and allocate tfm instances. This is to make it similar to how the existing crypto API works for the ablkcipher, ahash, and aead types. The operations the new interface will allow to provide are: int (*sign)(struct akcipher_request *req); int (*verify)(struct akcipher_request *req); int (*encrypt)(struct akcipher_request *req); int (*decrypt)(struct akcipher_request *req); The benefits it gives interface are: - drivers can add many implementations of RSA or DSA algorithms and user will allocate instances (tfms) of these, base on algorithm priority, in the same way as it is with the symmetric ciphers. - the new interface allows for asynchronous implementations that can use crypto hardware to offload the calculations to. - integrating it with linux crypto api allows using all its benefits i.e. managing algorithms using NETLINK_CRYPTO, monitoring implementations using /proc/crypto. etc New helper functions have been added to allocate crypto_akcipher instances and invoke the operations to make it easier to use. For instance to verify a public_signature against a public_key using the RSA algorithm a user would do: struct crypto_akcipher *tfm = crypto_alloc_akcipher(rsa, 0, 0); struct akcipher_request *req = akcipher_request_alloc(tfm, GFP_KERNEL); akcipher_request_set_crypt(req, pub_key, signature); int ret = crypto_akcipher_verify(src, dst, src_len, dst_len, res_len); akcipher_request_free(req); crypto_free_akcipher(tfm); return ret; Changes in v6: - in FIPS mode only allow key sizes 2K 3K - remove result_len and use dst_len as in/out param - remove subtype from akcipher reports - store rsa_key in tfm ctx and change ras_parse_key to take struct rsa_key instead of tfm. - export rsa_free_key, which free memory allocated by ras_parse_key. - split akcipher.h into public and internal with public key specific helpers - remove maxsize() and set the required size in enc/dec/sign/verify instead - add public key vector - split AKCIPHER into AKCIPHER and AKCIPHER2 in Kconfig - remove MPI patch from the series - already applied Changes in v5: - make mpi_get_size() function inline. - add a setkey function to the algorithm and rsa_parse_key() helper to parse rsa keys from BER encoded to MPI. The helper will also validate the given key if it is strong enough in case FIPS mode is enabled. - change the format of the key from struct public_key * to void * BER encoded buffer. - change the format of the rsa keys in testmgr to BER encoded form. - change mpi_free to use kzfree instead of kfree because it is used to free crypto keys Changes in v4: - add an rsa generic implementation - don't convert the existing public_key implementation to the new interface. This will be done after the new interface is accepted. - add new mpi_get_buf(), mpi_copy() and mpi_get_size() mpi helpers - on set key the ftm now will clone the key instead of just setting a ptr - add a check on enc/dec/sign/veryfi to make sure a valid (public or private) key is setup - add maxsize fn into algorith that will be used to query implementation what is the max size of a result for a give public key that the user needs to allocate - removed private ctx from crypto_akcipher as the crypto_tfm base has one already - add 2K bit RSA test vectors - add cipher text validation in crypto test mgr as (required for FIPS) Changes in v3: - changed input and output parameters type from sgl to void * and added separate src_len dst_len - requested by Herbert Xu - separated rsa implementation into cryptographic primitives and left encryption scheme details outside of the algorithm implementation - added SW implementation for RSA encrypt, decrypt and sign operation - added RSA test vectors Changes in v2: - remodeled not to use obsolete cra_u and crt_u unions - changed type/funct names from pke_* to pkey_* - retained the enum pkey_algo type for it is external to the kernel - added documentation --- Tadeusz Struk (3): crypto: add PKE API crypto: rsa: add a new rsa generic implementation crypto: add tests vectors for RSA crypto/Kconfig | 19 ++ crypto/Makefile|9 + crypto/akcipher.c | 100 +++ crypto/crypto_user.c | 22 ++ crypto/rsa.c | 313 +++ crypto/rsa_helper.c| 124 ++ crypto/rsakey.asn1 |5 + crypto/testmgr.c | 161 ++ crypto/testmgr.h | 187 + include/crypto
[PATCH RFC v6 1/3] crypto: add PKE API
Add Public Key Encryption API. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/Kconfig | 11 + crypto/Makefile|1 crypto/akcipher.c | 100 +++ crypto/crypto_user.c | 22 ++ include/crypto/akcipher.h | 323 include/crypto/internal/akcipher.h | 66 +++ include/linux/crypto.h |1 include/linux/cryptouser.h |5 + 8 files changed, 529 insertions(+) create mode 100644 crypto/akcipher.c create mode 100644 include/crypto/akcipher.h create mode 100644 include/crypto/internal/akcipher.h diff --git a/crypto/Kconfig b/crypto/Kconfig index f6fc054..264dadb 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -91,6 +91,17 @@ config CRYPTO_PCOMP2 tristate select CRYPTO_ALGAPI2 +config CRYPTO_AKCIPHER2 + tristate + select CRYPTO_ALGAPI2 + +config CRYPTO_AKCIPHER + tristate Public Key Algorithms API + select CRYPTO_AKCIPHER2 + select CRYPTO_ALGAPI + help + Crypto API interface for public key algorithms. + config CRYPTO_MANAGER tristate Cryptographic algorithm manager select CRYPTO_MANAGER2 diff --git a/crypto/Makefile b/crypto/Makefile index c842035..6f2940a 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -28,6 +28,7 @@ crypto_hash-y += shash.o obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o +obj-$(CONFIG_CRYPTO_AKCIPHER) += akcipher.o cryptomgr-y := algboss.o testmgr.o diff --git a/crypto/akcipher.c b/crypto/akcipher.c new file mode 100644 index 000..eefcc49 --- /dev/null +++ b/crypto/akcipher.c @@ -0,0 +1,100 @@ +/* + * Public Key Encryption + * + * Copyright (c) 2015, Intel Corporation + * Authors: Tadeusz Struk tadeusz.st...@intel.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include linux/errno.h +#include linux/kernel.h +#include linux/module.h +#include linux/seq_file.h +#include linux/slab.h +#include linux/string.h +#include linux/crypto.h +#include crypto/algapi.h +#include linux/cryptouser.h +#include net/netlink.h +#include crypto/akcipher.h +#include crypto/public_key.h +#include internal.h + +#ifdef CONFIG_NET +static int crypto_akcipher_report(struct sk_buff *skb, struct crypto_alg *alg) +{ + struct crypto_report_akcipher rakcipher; + + strncpy(rakcipher.type, akcipher, sizeof(rakcipher.type)); + + if (nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER, + sizeof(struct crypto_report_akcipher), rakcipher)) + goto nla_put_failure; + return 0; + +nla_put_failure: + return -EMSGSIZE; +} +#else +static int crypto_akcipher_report(struct sk_buff *skb, struct crypto_alg *alg) +{ + return -ENOSYS; +} +#endif + +static void crypto_akcipher_show(struct seq_file *m, struct crypto_alg *alg) + __attribute__ ((unused)); + +static void crypto_akcipher_show(struct seq_file *m, struct crypto_alg *alg) +{ + seq_puts(m, type : akcipher\n); +} + +static int crypto_akcipher_init_tfm(struct crypto_tfm *tfm) +{ + return 0; +} + +static const struct crypto_type crypto_akcipher_type = { + .extsize = crypto_alg_extsize, + .init_tfm = crypto_akcipher_init_tfm, +#ifdef CONFIG_PROC_FS + .show = crypto_akcipher_show, +#endif + .report = crypto_akcipher_report, + .maskclear = ~CRYPTO_ALG_TYPE_MASK, + .maskset = CRYPTO_ALG_TYPE_MASK, + .type = CRYPTO_ALG_TYPE_AKCIPHER, + .tfmsize = offsetof(struct crypto_akcipher, base), +}; + +struct crypto_akcipher *crypto_alloc_akcipher(const char *alg_name, u32 type, + u32 mask) +{ + return crypto_alloc_tfm(alg_name, crypto_akcipher_type, type, mask); +} +EXPORT_SYMBOL_GPL(crypto_alloc_akcipher); + +int crypto_register_akcipher(struct akcipher_alg *alg) +{ + struct crypto_alg *base = alg-base; + + base-cra_type = crypto_akcipher_type; + base-cra_flags = ~CRYPTO_ALG_TYPE_MASK; + base-cra_flags |= CRYPTO_ALG_TYPE_AKCIPHER; + return crypto_register_alg(base); +} +EXPORT_SYMBOL_GPL(crypto_register_akcipher); + +void crypto_unregister_akcipher(struct akcipher_alg *alg) +{ + crypto_unregister_alg(alg-base); +} +EXPORT_SYMBOL_GPL(crypto_unregister_akcipher); + +MODULE_LICENSE(GPL); +MODULE_DESCRIPTION(Generic public key cihper type); diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index 41dfe76..11dbd5a 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -27,6 +27,7 @@ #include net/net_namespace.h #include crypto/internal/aead.h #include crypto/internal/skcipher.h +#include crypto/akcipher.h #include internal.h @@ -110,6
[PATCH RFC v6 3/3] crypto: add tests vectors for RSA
New test vectors for RSA algorithm. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/Kconfig |1 crypto/testmgr.c | 161 ++ crypto/testmgr.h | 187 ++ 3 files changed, 349 insertions(+) diff --git a/crypto/Kconfig b/crypto/Kconfig index 52467cf..9471ac8 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -122,6 +122,7 @@ config CRYPTO_MANAGER2 select CRYPTO_HASH2 select CRYPTO_BLKCIPHER2 select CRYPTO_PCOMP2 + select CRYPTO_AKCIPHER2 config CRYPTO_USER tristate Userspace cryptographic algorithm configuration diff --git a/crypto/testmgr.c b/crypto/testmgr.c index ccd19cf..c773424 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -30,6 +30,7 @@ #include linux/string.h #include crypto/rng.h #include crypto/drbg.h +#include crypto/akcipher.h #include internal.h @@ -116,6 +117,11 @@ struct drbg_test_suite { unsigned int count; }; +struct akcipher_test_suite { + struct akcipher_testvec *vecs; + unsigned int count; +}; + struct alg_test_desc { const char *alg; int (*test)(const struct alg_test_desc *desc, const char *driver, @@ -130,6 +136,7 @@ struct alg_test_desc { struct hash_test_suite hash; struct cprng_test_suite cprng; struct drbg_test_suite drbg; + struct akcipher_test_suite akcipher; } suite; }; @@ -1825,6 +1832,150 @@ static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver, } +static int do_test_rsa(struct crypto_akcipher *tfm, + struct akcipher_testvec *vecs) +{ + struct akcipher_request *req; + void *outbuf_enc = NULL; + void *outbuf_dec = NULL; + struct tcrypt_result result; + unsigned int out_len_max, out_len = 0; + int err = -ENOMEM; + + req = akcipher_request_alloc(tfm, GFP_KERNEL); + if (!req) + return err; + + init_completion(result.completion); + err = crypto_akcipher_setkey(tfm, vecs-key, vecs-key_len); + if (err) + goto free_req; + + akcipher_request_set_crypt(req, vecs-m, outbuf_enc, vecs-m_size, + out_len); + /* expect this to fail, and update the required buf len */ + crypto_akcipher_encrypt(req); + if (!out_len) { + err = -EINVAL; + goto free_req; + } + + out_len_max = out_len; + + err = -ENOMEM; + outbuf_enc = kzalloc(out_len_max, GFP_KERNEL); + if (!outbuf_enc) + goto free_req; + + akcipher_request_set_crypt(req, vecs-m, outbuf_enc, vecs-m_size, + out_len); + akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + tcrypt_complete, result); + + /* Run RSA encrypt - c = m^e mod n;*/ + err = wait_async_op(result, crypto_akcipher_encrypt(req)); + if (err) { + pr_err(alg: rsa: encrypt test failed. err %d\n, err); + goto free_all; + } + + if (out_len != vecs-c_size) { + err = -EINVAL; + goto free_all; + } + /* verify that encrypted message is equal to expected */ + if (memcmp(vecs-c, outbuf_enc, vecs-c_size)) { + pr_err(alg: rsa: encrypt test failed. Invalid output\n); + err = -EINVAL; + goto free_all; + } + + /* Don't invoke decrypt for vectors with public key */ + if (vecs-public_key_test) { + err = 0; + goto free_all; + } + + outbuf_dec = kzalloc(out_len_max, GFP_KERNEL); + if (!outbuf_dec) { + err = -ENOMEM; + goto free_all; + } + + init_completion(result.completion); + akcipher_request_set_crypt(req, outbuf_enc, outbuf_dec, vecs-c_size, + out_len); + + /* Run RSA decrypt - m = c^d mod n;*/ + err = wait_async_op(result, crypto_akcipher_decrypt(req)); + if (err) { + pr_err(alg: rsa: decrypt test failed. err %d\n, err); + goto free_all; + } + + if (out_len != vecs-m_size) { + err = -EINVAL; + goto free_all; + } + + /* verify that decrypted message is equal to the original msg */ + if (memcmp(vecs-m, outbuf_dec, vecs-m_size)) { + pr_err(alg: rsa: encrypt test failed. Invalid output\n); + err = -EINVAL; + } +free_all: + kfree(outbuf_dec); + kfree(outbuf_enc); +free_req: + akcipher_request_free(req); + return err; +} + +static int test_rsa(struct crypto_akcipher *tfm, struct akcipher_testvec *vecs, + unsigned int tcount) +{ + int ret, i; + + for (i = 0; i tcount; i
Re: [PATCH RFC v5 3/4] crypto: rsa: add a new rsa generic implementation
On 06/15/2015 04:23 PM, Stephan Mueller wrote: +/* In FIPS mode only allow key size minimum 2K */ + if (fips_enabled (mpi_get_size(key-n) 256)) { Considering my previous email, shouldn't that check rather be if (fips_enabled ((mpi_get_size(key-n) != 256) || (mpi_get_size(key-n) != 384)) I'm not familiar with the FIPS requirements. I checked the NIST recommendations witch states that RSA: |n| = 2048 is acceptable. If FIPS allows 2K and 3K only then we need to change it. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC v5 2/4] crypto: add PKE API
On 06/15/2015 07:27 PM, Herbert Xu wrote: The two functions will be almost identical. We can do it this way if we want to check if all the required elements of the key are provided. Currently I'm checking this in the actual operation. Right now your RSA setkey function only works if you supply both the public key and the private key. If the user supplies only one key how are you going to tell whether it's public or private? User can supply only public key and invoke encrypt() or verify() without any problem. When the user invokes decrypt() or sign() then it will work only after the setkey was given a private key. This is checked in the actual operation. So the user is responsible for providing an appropriate key for given operation. We can split it if you think this is the right thing to do, but currently it works fine. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC v5 2/4] crypto: add PKE API
On 06/15/2015 07:29 PM, Herbert Xu wrote: I thought that the ctx needs to be available for implementations to store private data. This way we can allocate and store any type of key in the alg_parse_key() helper and still have the cxt available for implementations to use for their stuff (e.g. HW context). No for symmetric key algorithms we always store the key in the context and never in the tfm proper. Think about it, the generic tfm doesn't have any idea on what the key contains so how can it store it? Only the implementation knows the key format and can store it in a useful way. Ok I wanted to handle everything in the parse_key helper without any help from the implementation. I can change the helper to return the key and implementation will store it in the ctx. Is this what you are suggesting? -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC v4 2/4] crypto: add PKE API
On 06/11/2015 07:42 PM, Herbert Xu wrote: The testmgr code can mark an entire cipher implementation as fips_allowed=1 as already done for RSA. However, unlike with the other ciphers, that flag must go in conjunction with the used key sizes. For FIPS mode, the following restrictions apply: - RSA: 2048/3072 - DSA: L 2048 / N 224; L 2048 / N 256; L 3072 / N 256 - ECDSA: only the NIST curves Any other key sizes for the given ciphers is not allowed in FIPS mode. Should that constraint be considered here? Yes. However it should be placed into a helper that everybody can call so that future hardware implementations can also make the same checks. I will make the algorithm marked as fips allowed always and then fail in setkey if fips is enabled and the given key doesn't meet the fips requirement. Thanks -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC v2 1/2] crypto: add PKE API
On 05/31/2015 10:48 PM, Herbert Xu wrote: On Thu, May 28, 2015 at 09:54:41AM -0700, Tadeusz Struk wrote: If we do this that way then we will be able to pass only one input and one output parameter. There are cases when we will need more that this. For instance for ECDSA signature generation we need one input param hash(m) and two output parameters (r, s). There is no reason why you couldn't encode that within one stream. As far as as the user is concerned the output is one entity, i.e., the signature. The fact that it is made up of two numbers is of no concern to the API. It's a technicality for the algorithm to sort out. So I have used the SG for that. This is not to deal with non-contiguous memory, but to pass more in/out parameters. Each parameter will need to occupy contiguous space in memory. I will update the comment to make it more clear. If you have other idea how to do this I will be happy to try it. If you really wanted to do this then you should be using a simple (u8 *, unsigned int) pair but I don't really think this is at all necessary. Ok, I'll rework this to take one char *src and one *dst ptrs. Thanks T -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC v2 1/2] crypto: add PKE API
On 05/27/2015 09:08 PM, Herbert Xu wrote: Do you have a specific piece of hardware in mind? What are its capabilities? I'm going to use it with Intel's DH985xcc accelerator. It can accelerate RSA, DH, ECDSA and ECDH just to name the most commonly used. But I don't want to add anything that is device specific. I just want it to be flexible enough so that new algorithms can be easily added. If we are going to go with just contiguous memory then we might as well just do u8 *src, *dst, unsigned int slen, dlen. The whole point of the SG complexity is to deal with non-contiguous memory (e.g., fragmented packets with IPsec). If you can't do that then why add the SG complexity? If we do this that way then we will be able to pass only one input and one output parameter. There are cases when we will need more that this. For instance for ECDSA signature generation we need one input param hash(m) and two output parameters (r, s). So I have used the SG for that. This is not to deal with non-contiguous memory, but to pass more in/out parameters. Each parameter will need to occupy contiguous space in memory. I will update the comment to make it more clear. If you have other idea how to do this I will be happy to try it. Regards, T -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH RFC v4 2/4] crypto: add PKE API
Add Public Key Encryption API. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/Kconfig |6 + crypto/Makefile|1 crypto/akcipher.c | 154 + crypto/crypto_user.c | 23 ++ include/crypto/akcipher.h | 408 include/linux/crypto.h |1 include/linux/cryptouser.h |6 + 7 files changed, 599 insertions(+) create mode 100644 crypto/akcipher.c create mode 100644 include/crypto/akcipher.h diff --git a/crypto/Kconfig b/crypto/Kconfig index cb7806f..d119b38 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -91,6 +91,12 @@ config CRYPTO_PCOMP2 tristate select CRYPTO_ALGAPI2 +config CRYPTO_AKCIPHER + tristate Public Key Algorithms API + select CRYPTO_ALGAPI + help + Crypto API interface for public key algorithms. + config CRYPTO_MANAGER tristate Cryptographic algorithm manager select CRYPTO_MANAGER2 diff --git a/crypto/Makefile b/crypto/Makefile index c842035..6f2940a 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -28,6 +28,7 @@ crypto_hash-y += shash.o obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o +obj-$(CONFIG_CRYPTO_AKCIPHER) += akcipher.o cryptomgr-y := algboss.o testmgr.o diff --git a/crypto/akcipher.c b/crypto/akcipher.c new file mode 100644 index 000..286f31f --- /dev/null +++ b/crypto/akcipher.c @@ -0,0 +1,154 @@ +/* + * Public Key Encryption + * + * Copyright (c) 2015, Intel Corporation + * Authors: Tadeusz Struk tadeusz.st...@intel.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include linux/errno.h +#include linux/kernel.h +#include linux/module.h +#include linux/seq_file.h +#include linux/slab.h +#include linux/string.h +#include linux/crypto.h +#include crypto/algapi.h +#include linux/cryptouser.h +#include net/netlink.h +#include crypto/akcipher.h +#include crypto/public_key.h +#include internal.h + +#ifdef CONFIG_NET +static int crypto_akcipher_report(struct sk_buff *skb, struct crypto_alg *alg) +{ + struct crypto_report_akcipher rakcipher; + + strncpy(rakcipher.type, akcipher, sizeof(rakcipher.type)); + strncpy(rakcipher.subtype, alg-cra_name, sizeof(rakcipher.subtype)); + + if (nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER, + sizeof(struct crypto_report_akcipher), rakcipher)) + goto nla_put_failure; + return 0; + +nla_put_failure: + return -EMSGSIZE; +} +#else +static int crypto_akcipher_report(struct sk_buff *skb, struct crypto_alg *alg) +{ + return -ENOSYS; +} +#endif + +static void crypto_akcipher_show(struct seq_file *m, struct crypto_alg *alg) + __attribute__ ((unused)); + +static void crypto_akcipher_show(struct seq_file *m, struct crypto_alg *alg) +{ + seq_puts(m, type : akcipher\n); + seq_printf(m, subtype : %s\n, alg-cra_name); +} + +static void akcipher_free_key(struct public_key *key) +{ + public_key_destroy(key); +} + +static void crypto_akcipher_exit_tfm(struct crypto_tfm *tfm) +{ + struct crypto_akcipher *akcipher = __crypto_akcipher_tfm(tfm); + + if (akcipher-pkey) + akcipher_free_key(akcipher-pkey); + + akcipher-pkey = NULL; +} + +static int crypto_akcipher_init_tfm(struct crypto_tfm *tfm) +{ + struct crypto_akcipher *akcipher = __crypto_akcipher_tfm(tfm); + + akcipher-base.exit = crypto_akcipher_exit_tfm; + return 0; +} + +static const struct crypto_type crypto_akcipher_type = { + .extsize = crypto_alg_extsize, + .init_tfm = crypto_akcipher_init_tfm, +#ifdef CONFIG_PROC_FS + .show = crypto_akcipher_show, +#endif + .report = crypto_akcipher_report, + .maskclear = ~CRYPTO_ALG_TYPE_MASK, + .maskset = CRYPTO_ALG_TYPE_MASK, + .type = CRYPTO_ALG_TYPE_AKCIPHER, + .tfmsize = offsetof(struct crypto_akcipher, base), +}; + +struct crypto_akcipher *crypto_alloc_akcipher(const char *alg_name, u32 type, + u32 mask) +{ + return crypto_alloc_tfm(alg_name, crypto_akcipher_type, type, mask); +} +EXPORT_SYMBOL_GPL(crypto_alloc_akcipher); + +static int akcipher_clone_key(struct crypto_akcipher *tfm, + const struct public_key *pkey) +{ + int i, ret = 0; + + tfm-pkey = kzalloc(sizeof(*tfm-pkey), GFP_KERNEL); + + if (!tfm-pkey) + return -ENOMEM; + + for (i = 0; i ARRAY_SIZE(tfm-pkey-mpi); i++) { + if (!pkey-mpi[i]) + continue; + + if (mpi_copy(tfm-pkey-mpi[i], pkey-mpi[i])) { + akcipher_free_key(tfm-pkey); + tfm
[PATCH RFC v4 1/4] MPILIB: add mpi_read_buf(), mpi_copy() and mpi_get_size() helpers
Added a mpi_read_buf() helper function to export MPI to a buf provided by the user, and a mpi_get_size() helper, that tells the user how big the buf is. Implemented mpi_copy(), which was declared in mpi.h, but never implemented. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- include/linux/mpi.h |3 ++ lib/mpi/mpicoder.c | 86 --- lib/mpi/mpiutil.c | 47 3 files changed, 117 insertions(+), 19 deletions(-) diff --git a/include/linux/mpi.h b/include/linux/mpi.h index 5af1b81..5e55fd0 100644 --- a/include/linux/mpi.h +++ b/include/linux/mpi.h @@ -73,6 +73,7 @@ int mpi_set_ui(MPI w, ulong u); MPI mpi_alloc_set_ui(unsigned long u); void mpi_m_check(MPI a); void mpi_swap(MPI a, MPI b); +unsigned int mpi_get_size(MPI a); /*-- mpicoder.c --*/ MPI do_encode_md(const void *sha_buffer, unsigned nbits); @@ -81,6 +82,8 @@ MPI mpi_read_from_buffer(const void *buffer, unsigned *ret_nread); int mpi_fromstr(MPI val, const char *str); u32 mpi_get_keyid(MPI a, u32 *keyid); void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign); +int mpi_read_buffer(MPI a, uint8_t *buf, unsigned buf_len, unsigned *nbytes, + int *sign); void *mpi_get_secure_buffer(MPI a, unsigned *nbytes, int *sign); int mpi_set_buffer(MPI a, const void *buffer, unsigned nbytes, int sign); diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index 4cc6442..f48b028 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -128,28 +128,36 @@ leave: } EXPORT_SYMBOL_GPL(mpi_read_from_buffer); -/ - * Return an allocated buffer with the MPI (msb first). - * NBYTES receives the length of this buffer. Caller must free the - * return string (This function does return a 0 byte buffer with NBYTES - * set to zero if the value of A is zero. If sign is not NULL, it will - * be set to the sign of the A. +/** + * mpi_read_buffer() - read MPI to a bufer provided by user (msb first) + * + * @a: a multi precision integer + * @buf: bufer to which the output will be written to. Needs to be at + * leaset mpi_get_size(a) long. + * @buf_len: size of the buf. + * @nbytes:receives the actual length of the data written. + * @sign: if not NULL, it will be set to the sign of a. + * + * Return: 0 on success or error code in case of error */ -void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign) +int mpi_read_buffer(MPI a, uint8_t *buf, unsigned buf_len, unsigned *nbytes, + int *sign) { - uint8_t *p, *buffer; + uint8_t *p; mpi_limb_t alimb; + unsigned int n = mpi_get_size(a); int i; - unsigned int n; + + if (buf_len n || !buf) + return -EINVAL; if (sign) *sign = a-sign; - *nbytes = n = a-nlimbs * BYTES_PER_MPI_LIMB; - if (!n) - n++;/* avoid zero length allocation */ - p = buffer = kmalloc(n, GFP_KERNEL); - if (!p) - return NULL; + + if (nbytes) + *nbytes = n; + + p = buf; for (i = a-nlimbs - 1; i = 0; i--) { alimb = a-d[i]; @@ -171,15 +179,55 @@ void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign) #error please implement for this limb size. #endif } + return 0; +} +EXPORT_SYMBOL_GPL(mpi_read_buffer); + +/* + * mpi_get_buffer() - Returns an allocated buffer with the MPI (msb first). + * Caller must free the return string. + * This function does return a 0 byte buffer with nbytes set to zero if the + * value of A is zero. + * + * @a: a multi precision integer. + * @nbytes:receives the length of this buffer. + * @sign: if not NULL, it will be set to the sign of the a. + * + * Return: Pointer to MPI buffer or NULL on error + */ +void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign) +{ + uint8_t *buf, *p; + int n, ret; + + if (!nbytes) + return NULL; + + n = mpi_get_size(a); + + if (!n) + n++; + + buf = kmalloc(n, GFP_KERNEL); + + if (!buf) + return NULL; + + ret = mpi_read_buffer(a, buf, n, nbytes, sign); + + if (ret) { + kfree(buf); + return NULL; + } /* this is sub-optimal but we need to do the shift operation * because the caller has to free the returned buffer */ - for (p = buffer; !*p *nbytes; p++, --*nbytes) + for (p = buf; !*p *nbytes; p++, --*nbytes) ; - if (p != buffer) - memmove(buffer, p, *nbytes); + if (p != buf) + memmove(buf, p, *nbytes); - return buffer; + return buf; } EXPORT_SYMBOL_GPL(mpi_get_buffer); diff --git a/lib/mpi/mpiutil.c b/lib/mpi/mpiutil.c index bf076d2..ee078e2 100644 --- a/lib/mpi/mpiutil.c +++ b/lib/mpi/mpiutil.c @@ -54,6 +54,40 @@ MPI mpi_alloc(unsigned nlimbs
[PATCH RFC v4 3/4] crypto: rsa: add a new rsa generic implementation
Add a new rsa generic SW implementation. This implements only cryptographic primitives. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/Kconfig |7 + crypto/Makefile |1 crypto/rsa.c| 289 +++ 3 files changed, 297 insertions(+) create mode 100644 crypto/rsa.c diff --git a/crypto/Kconfig b/crypto/Kconfig index d119b38..4d1bff3 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -97,6 +97,13 @@ config CRYPTO_AKCIPHER help Crypto API interface for public key algorithms. +config CRYPTO_RSA + tristate RSA algorithm + select AKCIPHER + select MPILIB + help + Generic implementation of the RSA public key algorithm. + config CRYPTO_MANAGER tristate Cryptographic algorithm manager select CRYPTO_MANAGER2 diff --git a/crypto/Makefile b/crypto/Makefile index 6f2940a..7ba05f0 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o obj-$(CONFIG_CRYPTO_AKCIPHER) += akcipher.o +obj-$(CONFIG_CRYPTO_RSA) += rsa.o cryptomgr-y := algboss.o testmgr.o diff --git a/crypto/rsa.c b/crypto/rsa.c new file mode 100644 index 000..8efef17 --- /dev/null +++ b/crypto/rsa.c @@ -0,0 +1,289 @@ +/* RSA asymmetric public-key algorithm [RFC3447] + * + * Copyright (c) 2015, Intel Corporation + * Authors: Tadeusz Struk tadeusz.st...@intel.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#include linux/module.h +#include linux/scatterlist.h +#include crypto/public_key.h +#include crypto/akcipher.h + +/* + * RSAEP function [RFC3447 sec 5.1.1] + * c = m^e mod n; + */ +static int _rsa_enc(const struct public_key *key, MPI c, MPI m) +{ + /* (1) Validate 0 = m n */ + if (mpi_cmp_ui(m, 0) 0 || mpi_cmp(m, key-rsa.n) = 0) + return -EINVAL; + + /* (2) c = m^e mod n */ + return mpi_powm(c, m, key-rsa.e, key-rsa.n); +} + +/* + * RSADP function [RFC3447 sec 5.1.2] + * m = c^d mod n; + */ +static int _rsa_dec(const struct public_key *key, MPI m, MPI c) +{ + /* (1) Validate 0 = c n */ + if (mpi_cmp_ui(c, 0) 0 || mpi_cmp(c, key-rsa.n) = 0) + return -EINVAL; + + /* (2) m = c^d mod n */ + return mpi_powm(m, c, key-rsa.d, key-rsa.n); +} + +/* + * RSASP1 function [RFC3447 sec 5.2.1] + * s = m^d mod n + */ +static int _rsa_sign(const struct public_key *key, MPI s, MPI m) +{ + /* (1) Validate 0 = m n */ + if (mpi_cmp_ui(m, 0) 0 || mpi_cmp(m, key-rsa.n) = 0) + return -EINVAL; + + /* (2) s = m^d mod n */ + return mpi_powm(s, m, key-rsa.d, key-rsa.n); +} + +/* + * RSAVP1 function [RFC3447 sec 5.2.2] + * m = s^e mod n; + */ +static int _rsa_verify(const struct public_key *key, MPI m, MPI s) +{ + /* (1) Validate 0 = s n */ + if (mpi_cmp_ui(s, 0) 0 || mpi_cmp(s, key-rsa.n) = 0) + return -EINVAL; + + /* (2) m = s^e mod n */ + return mpi_powm(m, s, key-rsa.e, key-rsa.n); +} + +static int rsa_enc(struct akcipher_request *req) +{ + struct crypto_akcipher *tfm = akcipher_request_get_tfm(req); + const struct public_key *pkey = crypto_akcipher_getkey(tfm); + MPI m, c = mpi_alloc(0); + unsigned int len; + int ret = 0; + int sign; + + if (!c) + return -ENOMEM; + + if (!pkey-rsa.e || req-dst_len mpi_get_size(pkey-rsa.n)) + return -EINVAL; + + m = mpi_read_raw_data(req-src, req-src_len); + if (!m) { + ret = -ENOMEM; + goto err_free_c; + } + + ret = _rsa_enc(pkey, c, m); + if (ret) + goto err_free_m; + + ret = mpi_read_buffer(c, req-dst, req-dst_len, len, sign); + if (ret) + goto err_free_m; + + if (sign 0) { + ret = -EBADMSG; + goto err_free_m; + } + + if (req-result_len) + *req-result_len = len; + +err_free_m: + mpi_free(m); +err_free_c: + mpi_free(c); + return ret; +} + +static int rsa_dec(struct akcipher_request *req) +{ + struct crypto_akcipher *tfm = akcipher_request_get_tfm(req); + const struct public_key *pkey = crypto_akcipher_getkey(tfm); + MPI c, m = mpi_alloc(0); + unsigned int len; + int ret = 0; + int sign; + + if (!m) + return -ENOMEM; + + if (!pkey-rsa.d || req-dst_len mpi_get_size(pkey-rsa.n)) + return -EINVAL; + + c = mpi_read_raw_data(req-src, req-src_len); + if (!c) { + ret = -ENOMEM; + goto err_free_m; + } + + ret = _rsa_dec(pkey, m, c
[PATCH RFC v4 0/4] crypto: Introduce Public Key Encryption API
This patch set introduces a Public Key Encryption API. What is proposed is a new crypto type called crypto_akcipher_type, plus new struct akcipher_alg and struct crypto_akcipher, together with number of helper functions to register akcipher type algorithms and allocate tfm instances. This is to make it similar to how the existing crypto API works for the ablkcipher, ahash, and aead types. The operations the new interface will allow to provide are: int (*sign)(struct akcipher_request *req); int (*verify)(struct akcipher_request *req); int (*encrypt)(struct akcipher_request *req); int (*decrypt)(struct akcipher_request *req); The benefits it gives interface are: - drivers can add many implementations of RSA or DSA algorithms and user will allocate instances (tfms) of these, base on algorithm priority, in the same way as it is with the symmetric ciphers. - the new interface allows for asynchronous implementations that can use crypto hardware to offload the calculations to. - integrating it with linux crypto api allows using all its benefits i.e. managing algorithms using NETLINK_CRYPTO, monitoring implementations using /proc/crypto. etc New helper functions have been added to allocate crypto_akcipher instances and invoke the operations to make it easier to use. For instance to verify a public_signature against a public_key using the RSA algorithm a user would do: struct crypto_akcipher *tfm = crypto_alloc_akcipher(rsa, 0, 0); struct akcipher_request *req = akcipher_request_alloc(tfm, GFP_KERNEL); akcipher_request_set_crypt(req, pub_key, signature); int ret = crypto_akcipher_verify(src, dst, src_len, dst_len, res_len); akcipher_request_free(req); crypto_free_akcipher(tfm); return ret; Changes in v4: - add a rsa generic implementation - don't convert the existing public_key implementation to the new interface. This will be done after the new interface is accepted. - add new mpi_get_buf(), mpi_copy() and mpi_get_size() mpi helpers - on set key the ftm now will clone the key instead of just setting a ptr - add a check on enc/dec/sign/veryfi to make sure a valid (public or private) key is setup - add maxsize fn into algorith that will be used to query implementation what is the max size of a result for a give public key that the user needs to allocate - removed private ctx from crypto_akcipher as the crypto_tfm base has one already - add 2K bit RSA test vectors - add cipher text validation in crypto test mgr as (required for FIPS) Changes in v3: - changed input and output parameters type from sgl to void * and added separate src_len dst_len - requested by Herbert Xu - separated rsa implementation into cryptographic primitives and left encryption scheme details outside of the algorithm implementation - added SW implementation for RSA encrypt, decrypt and sign operation - added RSA test vectors Changes in v2: - remodeled not to use obsolete cra_u and crt_u unions - changed type/funct names from pke_* to pkey_* - retained the enum pkey_algo type for it is external to the kernel - added documentation --- Tadeusz Struk (4): MPILIB: add mpi_get_buf(), mpi_copy() and mpi_get_size() helpers crypto: add PKE API crypto: RSA: KEYS: convert rsa and public key to new PKE API crypto: add tests vectors for RSA crypto/Kconfig | 14 ++ crypto/Makefile|2 crypto/akcipher.c | 155 + crypto/crypto_user.c | 23 ++ crypto/rsa.c | 289 +++ crypto/testmgr.c | 164 ++ crypto/testmgr.h | 142 +++ include/crypto/akcipher.h | 408 include/linux/crypto.h |1 include/linux/cryptouser.h |6 + include/linux/mpi.h|3 lib/mpi/mpicoder.c | 85 +++-- lib/mpi/mpiutil.c | 46 + 13 files changed, 1319 insertions(+), 19 deletions(-) create mode 100644 crypto/akcipher.c create mode 100644 crypto/rsa.c create mode 100644 include/crypto/akcipher.h -- -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH RFC v4 4/4] crypto: add tests vectors for RSA
New test vectors for RSA algorithm. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/Kconfig |1 crypto/testmgr.c | 164 ++ crypto/testmgr.h | 142 +++ 3 files changed, 307 insertions(+) diff --git a/crypto/Kconfig b/crypto/Kconfig index 4d1bff3..cbae88a 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -107,6 +107,7 @@ config CRYPTO_RSA config CRYPTO_MANAGER tristate Cryptographic algorithm manager select CRYPTO_MANAGER2 + select CRYPTO_AKCIPHER help Create default cryptographic template instantiations such as cbc(aes). diff --git a/crypto/testmgr.c b/crypto/testmgr.c index ccd19cf..f984328 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -30,6 +30,8 @@ #include linux/string.h #include crypto/rng.h #include crypto/drbg.h +#include crypto/public_key.h +#include crypto/akcipher.h #include internal.h @@ -116,6 +118,11 @@ struct drbg_test_suite { unsigned int count; }; +struct akcipher_test_suite { + struct akcipher_testvec *vecs; + unsigned int count; +}; + struct alg_test_desc { const char *alg; int (*test)(const struct alg_test_desc *desc, const char *driver, @@ -130,6 +137,7 @@ struct alg_test_desc { struct hash_test_suite hash; struct cprng_test_suite cprng; struct drbg_test_suite drbg; + struct akcipher_test_suite akcipher; } suite; }; @@ -1825,6 +1833,152 @@ static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver, } +static int do_test_rsa(struct crypto_akcipher *tfm, + struct akcipher_testvec *vecs) +{ + struct akcipher_request *req; + struct public_key pkey = {0}; + void *outbuf_enc = NULL; + void *outbuf_dec = NULL; + struct tcrypt_result result; + unsigned int max_out_len, out_len; + int err = -ENOMEM; + + req = akcipher_request_alloc(tfm, GFP_KERNEL); + if (!req) + return err; + + pkey.rsa.n = mpi_read_raw_data(vecs-pub_key_n, vecs-pub_key_n_size); + if (!pkey.rsa.n) + goto free_req; + + pkey.rsa.e = mpi_read_raw_data(vecs-pub_key_e, vecs-pub_key_e_size); + if (!pkey.rsa.e) + goto free_n; + + pkey.rsa.d = mpi_read_raw_data(vecs-sec_key_d, vecs-sec_key_d_size); + if (!pkey.rsa.d) + goto free_e; + + init_completion(result.completion); + crypto_akcipher_setkey(tfm, pkey); + max_out_len = crypto_akcipher_maxsize(tfm); + if (!(max_out_len 0)) + goto free_d; + + outbuf_enc = kzalloc(max_out_len, GFP_KERNEL); + if (!outbuf_enc) + goto free_d; + + akcipher_request_set_crypt(req, vecs-m, outbuf_enc, vecs-m_size, + max_out_len, out_len); + akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + tcrypt_complete, result); + + /* Run RSA encrypt - c = m^e mod n;*/ + err = wait_async_op(result, crypto_akcipher_encrypt(req)); + if (err) { + pr_err(alg: rsa: encrypt test failed. err %d\n, err); + goto free_all; + } + + if (out_len != vecs-c_size) { + err = -EINVAL; + goto free_all; + } + /* verify that encrypted message is equal to expected */ + if (memcmp(vecs-c, outbuf_enc, vecs-c_size)) { + pr_err(alg: rsa: encrypt test failed. Invalid output\n); + err = -EINVAL; + goto free_all; + } + + outbuf_dec = kzalloc(max_out_len, GFP_KERNEL); + if (!outbuf_dec) { + err = -ENOMEM; + goto free_all; + } + + init_completion(result.completion); + akcipher_request_set_crypt(req, outbuf_enc, outbuf_dec, vecs-c_size, + max_out_len, out_len); + + /* Run RSA decrypt - m = c^d mod n;*/ + err = wait_async_op(result, crypto_akcipher_decrypt(req)); + if (err) { + pr_err(alg: rsa: decrypt test failed. err %d\n, err); + goto free_all; + } + + if (out_len != vecs-m_size) { + err = -EINVAL; + goto free_all; + } + + /* verify that decrypted message is equal to the original msg */ + if (memcmp(vecs-m, outbuf_dec, vecs-m_size)) { + pr_err(alg: rsa: encrypt test failed. Invalid output\n); + err = -EINVAL; + } +free_all: + kfree(outbuf_dec); + kfree(outbuf_enc); +free_d: + mpi_free(pkey.rsa.d); +free_e: + mpi_free(pkey.rsa.e); +free_n: + mpi_free(pkey.rsa.n); +free_req: + akcipher_request_free(req); + return err; +} + +static int test_rsa(struct crypto_akcipher *tfm, struct
Re: [PATCH RFC v2 1/2] crypto: add PKE API
On 05/22/2015 10:47 PM, Herbert Xu wrote: struct akcipher_request { struct crypto_async_request base; struct scatterlist *inparams; struct scatterlist *outparams; void *__ctx[] CRYPTO_MINALIGN_ATTR; }; I think you should rename them to src/dst and add a length argument. Limiting them to one entry also seems strange. When do you need more one parameter? The length would be redundant. It can be obtained by sg_nents(reg-inparams) I don't limit the number of parameters. You can pass as many as you want. For instance to pass 3 in and 2 out you do: struct scatterlist in[3]; struct scatterlist out[2]; sg_init_table(in, 3); sg_init_table(out, 2); sg_set_buf(in, first_in_param, len_of_first_in_param); sg_set_buf(in + 1, second_in_param, len_of_second_in_param); sg_set_buf(in + 2, third_in_param, len_of_third_in_param); sg_set_buf(out, first_out_param, len_of_first_out_param); sg_set_buf(out + 1, second_out_param, len_of_second_out_param); akcipher_request_set_crypt(req, in, out); The limitation here is that one parameter can not span multiple sgs. This should be ok as they will never be bigger than one page. In fact MPI limits it to 2K max with #define MAX_EXTERN_MPI_BITS 16384. I'm ok to rename it to src and dst. struct akcipher_alg { int (*sign)(struct akcipher_request *req); int (*verify)(struct akcipher_request *req); int (*encrypt)(struct akcipher_request *req); int (*decrypt)(struct akcipher_request *req); Looks good. You'll also need a setkey (or perhaps two) function. I have these two: /** * crypto_akcipher_setkey() -- assign a public key to an AKCIPHER tfm handle * * @tfm: AKCIPHER tfm handle allocated with crypto_alloc_akcipher() * @pkey: public key */ static inline void crypto_akcipher_setkey(struct crypto_akcipher *tfm, const struct public_key *pkey); /** * crypto_akcipher_getkey() -- obtain a public key from an AKCIPHER tfm handle * * @tfm: AKCIPHER tfm handle allocated with crypto_alloc_akcipher() * * Return: public key */ static inline const struct public_key *crypto_akcipher_getkey( struct crypto_akcipher *tfm); -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC v2 1/2] crypto: add PKE API
On 05/10/2015 11:32 PM, Herbert Xu wrote: On Wed, May 06, 2015 at 12:36:48PM -0700, Tadeusz Struk wrote: +const struct public_key_signature *signature; Doing this means that you aren't adding it to the crypto API properly. You need to start from scratch and design a proper interface and not just wrap some existing opaque data strcture. Cheers, Hi Herbert, Thanks for your feedback. How about this: /** * struct akcipher_request - public key request * * @base: Common attributes for async crypto requests * @inparams: scatterlist of input parameters (one ent per parameter) * for the operation as defined in RFC. * For instance for rsa encrypt only one input param is required, * (i.e. 'm' - message) as specified in RFC3447 sec 5.1.1 * (Note: the key belongs to the tfm) * @outparams: scatterlist of output parameters (one ent per parameter) * for the operation as defined in RFC. * For instance for rsa encrypt only one output param will be * produced (i.e. 'c' - cipher text) as specified in * RFC3447 sec 5.1.1 * * @__ctx: Start of private context data */ struct akcipher_request { struct crypto_async_request base; struct scatterlist *inparams; struct scatterlist *outparams; void *__ctx[] CRYPTO_MINALIGN_ATTR; }; /** * struct akcipher_alg - generic public key algorithm * * @sign: Function performs a sign operation as defined by public key * algorithm * @verify: Function performs a sign operation as defined by public key * algorithm * @encrypt:Function performs an encrypt operation as defined by public key * algorithm * @decrypt:Function performs a decrypt operation as defined by public key * algorithm * @reqsize:Request context size required by algorithm implementation * * @base: Common crypto API algorithm data structure */ struct akcipher_alg { int (*sign)(struct akcipher_request *req); int (*verify)(struct akcipher_request *req); int (*encrypt)(struct akcipher_request *req); int (*decrypt)(struct akcipher_request *req); unsigned int reqsize; struct crypto_alg base; }; /** * struct crypto_akcipher - user-instantiated objects which encapsulate * algorithms and core processing logic * * @base: Common crypto API algorithm data structure * @pkey: Key representation. Note: this can be both public or private * key, depending on the operation. * @__ctx: Start of private context data */ struct crypto_akcipher { struct crypto_tfm base; const struct public_key *pkey; void *__ctx[] CRYPTO_MINALIGN_ATTR; }; -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: linux-next: Tree for Aug 12 (include/linux/pci.h)
Hi, On 08/12/2015 02:53 PM, Stephen Rothwell wrote: On Wed, 12 Aug 2015 11:05:36 -0700 Randy Dunlap rdun...@infradead.org wrote: on i386 or x86_64: Many (repeated) errors like this one: ../include/linux/pci.h:390:12: error: âstruct pci_devâ has no member named âphysfnâ when CONFIG_PCI_ATS is not enabled. Maybe caused by commit dd0f368398ea (crypto: qat - Add qat dh895xcc VF driver) from the crypto tree Which adds a select PCI_IOV to drivers/crypto/qat/Kconfig without the necessary select PCI but PCI_IOV selects PCI_ATS, so I am not sure what happened here. I am assuming that your config has PCI_IOV enabled? What about PCI? There is a patch submitted, but not yet applied https://patchwork.kernel.org/patch/6994171/ maybe it will help? -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2/2] crypto: qat - Don't move data inside output buffer
Don't need to move data inside of the output buffer because SW doen't need to do this anymore sice the new MPI mpi_read_buf() has been added. Just set the correct output len. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- drivers/crypto/qat/qat_common/qat_asym_algs.c |3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c index fe352a6..6ddb13c 100644 --- a/drivers/crypto/qat/qat_common/qat_asym_algs.c +++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c @@ -144,9 +144,6 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp) ptr++; } - if (areq-dst_len != req-ctx-key_sz) - memcpy(areq-dst, ptr, areq-dst_len); - akcipher_request_complete(areq, err); } -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 0/2] crypto: KEYS: convert public key to the akcipher API
This patch converts the module verification code to the new akcipher API. RSA implementation from crypto/asymmetric_keys has been removed and the new API is used for cryptographic primitives. The signature verification has been moved into a new crypto/asymmetric_keys/rsa_pkcs1_v1_5.c file. There is no need for MPI above the API anymore. Modules can be verified with software as well as HW rsa implementations. Also changed qat rsa implementation not to move data inside the output buff similarly to SW. --- Tadeusz Struk (2): crypto: KEYS: convert public key to the akcipher API crypto: qat - Don't move data inside output buffer crypto/asymmetric_keys/Kconfig|2 crypto/asymmetric_keys/Makefile |7 - crypto/asymmetric_keys/pkcs7_parser.c | 12 - crypto/asymmetric_keys/pkcs7_trust.c |2 crypto/asymmetric_keys/pkcs7_verify.c |2 crypto/asymmetric_keys/public_key.c | 59 + crypto/asymmetric_keys/public_key.h | 36 --- crypto/asymmetric_keys/rsa.c | 278 - crypto/asymmetric_keys/rsa_pkcs1_v1_5.c | 232 + crypto/asymmetric_keys/x509_cert_parser.c | 37 +-- crypto/asymmetric_keys/x509_public_key.c | 17 +- crypto/asymmetric_keys/x509_rsakey.asn1 |4 drivers/crypto/qat/qat_common/qat_asym_algs.c |3 include/crypto/public_key.h | 48 +--- kernel/module_signing.c | 56 ++--- security/integrity/digsig_asymmetric.c| 11 - 16 files changed, 304 insertions(+), 502 deletions(-) delete mode 100644 crypto/asymmetric_keys/public_key.h delete mode 100644 crypto/asymmetric_keys/rsa.c create mode 100644 crypto/asymmetric_keys/rsa_pkcs1_v1_5.c delete mode 100644 crypto/asymmetric_keys/x509_rsakey.asn1 -- -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/2] crypto: KEYS: convert public key to the akcipher API
This patch converts the module verification code to the new akcipher API. RSA implementation from crypto/asymmetric_keys has been removed and the new API is used for cryptographic primitives. The signature verification has been moved into a new crypto/asymmetric_keys/rsa_pkcs1_v1_5.c file. There is no need for MPI above the API anymore. Modules can be verified with software as well as HW rsa implementations. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- crypto/asymmetric_keys/Kconfig|2 crypto/asymmetric_keys/Makefile |7 - crypto/asymmetric_keys/pkcs7_parser.c | 12 + crypto/asymmetric_keys/pkcs7_trust.c |2 crypto/asymmetric_keys/pkcs7_verify.c |2 crypto/asymmetric_keys/public_key.c | 59 ++ crypto/asymmetric_keys/public_key.h | 36 crypto/asymmetric_keys/rsa.c | 278 - crypto/asymmetric_keys/rsa_pkcs1_v1_5.c | 229 crypto/asymmetric_keys/x509_cert_parser.c | 37 +--- crypto/asymmetric_keys/x509_public_key.c | 17 +- crypto/asymmetric_keys/x509_rsakey.asn1 |4 include/crypto/public_key.h | 48 + kernel/module_signing.c | 56 ++ security/integrity/digsig_asymmetric.c| 11 - 15 files changed, 301 insertions(+), 499 deletions(-) delete mode 100644 crypto/asymmetric_keys/public_key.h delete mode 100644 crypto/asymmetric_keys/rsa.c create mode 100644 crypto/asymmetric_keys/rsa_pkcs1_v1_5.c delete mode 100644 crypto/asymmetric_keys/x509_rsakey.asn1 diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig index 4870f28..905d745 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -22,7 +22,7 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE config PUBLIC_KEY_ALGO_RSA tristate RSA public-key algorithm - select MPILIB + select CRYPTO_RSA help This option enables support for the RSA algorithm (PKCS#1, RFC3447). diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile index e47fcd9..895d8ca 100644 --- a/crypto/asymmetric_keys/Makefile +++ b/crypto/asymmetric_keys/Makefile @@ -7,7 +7,7 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o asymmetric_keys-y := asymmetric_type.o signature.o obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o -obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o +obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa_pkcs1_v1_5.o # # X.509 Certificate handling @@ -15,16 +15,13 @@ obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o x509_key_parser-y := \ x509-asn1.o \ - x509_rsakey-asn1.o \ x509_cert_parser.o \ x509_public_key.o -$(obj)/x509_cert_parser.o: $(obj)/x509-asn1.h $(obj)/x509_rsakey-asn1.h +$(obj)/x509_cert_parser.o: $(obj)/x509-asn1.h $(obj)/x509-asn1.o: $(obj)/x509-asn1.c $(obj)/x509-asn1.h -$(obj)/x509_rsakey-asn1.o: $(obj)/x509_rsakey-asn1.c $(obj)/x509_rsakey-asn1.h clean-files+= x509-asn1.c x509-asn1.h -clean-files+= x509_rsakey-asn1.c x509_rsakey-asn1.h # # PKCS#7 message handling diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c index 3bd5a1e..8e3597a 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.c +++ b/crypto/asymmetric_keys/pkcs7_parser.c @@ -15,7 +15,7 @@ #include linux/slab.h #include linux/err.h #include linux/oid_registry.h -#include public_key.h +#include crypto/public_key.h #include pkcs7_parser.h #include pkcs7-asn1.h @@ -41,7 +41,7 @@ struct pkcs7_parse_context { static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo) { if (sinfo) { - mpi_free(sinfo-sig.mpi[0]); + kfree(sinfo-sig.s); kfree(sinfo-sig.digest); kfree(sinfo-signing_cert_id); kfree(sinfo); @@ -374,16 +374,14 @@ int pkcs7_sig_note_signature(void *context, size_t hdrlen, const void *value, size_t vlen) { struct pkcs7_parse_context *ctx = context; - MPI mpi; BUG_ON(ctx-sinfo-sig.pkey_algo != PKEY_ALGO_RSA); - mpi = mpi_read_raw_data(value, vlen); - if (!mpi) + ctx-sinfo-sig.s = kmemdup(value, vlen, GFP_KERNEL); + if (!ctx-sinfo-sig.s) return -ENOMEM; - ctx-sinfo-sig.mpi[0] = mpi; - ctx-sinfo-sig.nr_mpi = 1; + ctx-sinfo-sig.s_size = vlen; return 0; } diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c index 1d29376..68ebae2 100644 --- a/crypto/asymmetric_keys/pkcs7_trust.c +++ b/crypto/asymmetric_keys/pkcs7_trust.c @@ -17,7 +17,7 @@ #include linux/asn1.h #include linux/key.h #include keys/asymmetric-type.h -#include public_key.h +#include crypto/public_key.h #include pkcs7_parser.h /** diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto
Re: [PATCH 2/2] crypto: qat - Don't move data inside output buffer
On 08/17/2015 01:50 AM, Herbert Xu wrote: If you don't like the first option then we still need this, as you pointed out. Yes this looks like the right fix for qat. Please add a sign-off. You might be able to just do it by replying to this thread, and patchwork may be able to pick it up and attach it to the patch. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/2] crypto: KEYS: convert public key to the akcipher API
Hi Stephan, On 08/15/2015 11:08 AM, Stephan Mueller wrote: Am Mittwoch, 12. August 2015, 20:54:39 schrieb Tadeusz Struk: Hi Tadeusz, @@ -41,7 +41,7 @@ struct pkcs7_parse_context { static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo) { if (sinfo) { -mpi_free(sinfo-sig.mpi[0]); +kfree(sinfo-sig.s); kzfree? kfree(sinfo-sig.digest); kzfree? kfree(sinfo-signing_cert_id); kfree(sinfo); kzfree (due to -msdigest)? Sorry for late response. I was on vacation. All these above are module signatures, which are not sensitive, so no need to zero the buffers on free. The only thing that is sensitive is the private key, which is only used for signing modules on make modules_install and never included in the kernel. Thanks, T -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/2] crypto: KEYS: convert public key to the akcipher API
On 08/13/2015 07:23 AM, David Howells wrote: Tadeusz Struk tadeusz.st...@intel.com wrote: const char *const pkey_algo_name[PKEY_ALGO__LAST] = { -[PKEY_ALGO_DSA] = DSA, -[PKEY_ALGO_RSA] = RSA, +[PKEY_ALGO_DSA] = dsa, +[PKEY_ALGO_RSA] = rsa, }; Be aware that these are exposed to userspace through /proc. The change probably doesn't matter, but you might need to update the documentation. +int public_key_verify_signature(const struct public_key *pkey, const struct public_key_signature *sig) { ... -return algo-verify_signature(pk, sig); +return rsa_pkcs1_v1_5_verify_signature(pkey, sig); } No. You can't assume RSA here. It's quite likely we'll have to support ECDSA or similar soon. This must be contingent on the algorithm selected. { const struct public_key *pk = key-payload.data; + return public_key_verify_signature(pk, sig); } That's nothing to do with this patch. +static int rsa_signture_verify(const u8 *H, const u8 *EM, size_t k, 'signture' - 'signature'. +/* + * Perform the RSA signature verification. + * @H: Value of hash of data and metadata + * @EM: The computed signature value + * @k: The size of EM (EM[0] is an invalid location but should hold 0x00) + * @hash_size: The size of H + * @asn1_template: The DigestInfo ASN.1 template + * @asn1_size: Size of asm1_template[] + */ +static int rsa_signture_verify(const u8 *H, const u8 *EM, size_t k, + size_t hash_size, const u8 *asn1_template, + size_t asn1_size) +{ Why is this here and not in crypto/rsa.c? +/* initlialzie out buf */ 'initialise'. -/* Decode the public key */ -ret = asn1_ber_decoder(x509_rsakey_decoder, ctx, - ctx-key, ctx-key_size); -if (ret 0) +cert-pub-key = kmemdup(ctx-key, ctx-key_size, GFP_KERNEL); +if (!cert-pub-key) goto error_decode; The generic public key code should *not* see the container wrappings (ASN.1 from an X.509 cert in this case). The public key could be supplied by OpenPGP instead, for example, or directly by a driver. Further, at this point, we need to make sure that the data we were given has the right bits and emit EBADMSG if it doesn't. Okay, I can accept that the public_key struct might just have a list of void * and size_t fields that get filled in, one for each integer that we extract rather than MPIs, but we should not expose the generic code to the stuff we've parsed away. struct public_key { -const struct public_key_algorithm *algo; -u8 capabilities; -#define PKEY_CAN_ENCRYPT0x01 -#define PKEY_CAN_DECRYPT0x02 -#define PKEY_CAN_SIGN 0x04 -#define PKEY_CAN_VERIFY 0x08 You still need the capabilities. The X.509 certificate and the OpenPGP message indicate restrictions on the key that we need to honour. Thanks David for all your feedback. I'll rework it according to your comments. Regards, T -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2/2] crypto: qat - Don't move data inside output buffer
On 08/12/2015 08:54 PM, Tadeusz Struk wrote: Don't need to move data inside of the output buffer because SW doen't need to do this anymore sice the new MPI mpi_read_buf() has been added. Just set the correct output len. Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com --- drivers/crypto/qat/qat_common/qat_asym_algs.c |3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c index fe352a6..6ddb13c 100644 --- a/drivers/crypto/qat/qat_common/qat_asym_algs.c +++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c @@ -144,9 +144,6 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp) ptr++; } - if (areq-dst_len != req-ctx-key_sz) - memcpy(areq-dst, ptr, areq-dst_len); - akcipher_request_complete(areq, err); } Herbert, Could you take this one and I'll work with David on the rest. Thanks, T -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 0/2] crypto: KEYS: convert public key to the akcipher API
On 08/13/2015 06:56 AM, David Howells wrote: Can you rebase this on top of: http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=modsign-pkcs7 David Will do. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2/2] crypto: qat - Don't move data inside output buffer
On 08/13/2015 10:14 PM, Herbert Xu wrote: diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c index fe352a6..6ddb13c 100644 --- a/drivers/crypto/qat/qat_common/qat_asym_algs.c +++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c @@ -144,9 +144,6 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp) ptr++; } - if (areq-dst_len != req-ctx-key_sz) - memcpy(areq-dst, ptr, areq-dst_len); - This looks wrong. It appears to be trying to remove leading zeroes so you can't just change the length because then you end up removing the trailing digits equal to the number of leading zeroes. What it does is it sets the size of the output number, not the size of the output buffer. The size of the buffer is set beforehand to the size of the modulo, which is the biggest possible output. The existing code is also wrong as you should be using memmove instead of memcpy. Right, but we don't need that anymore. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/