* [RFC PATCH v1 23/28] KVM: SVM: add SEV launch update command
From: Brijesh Singh @ 2016-08-22 23:28 UTC (permalink / raw)
To: simon.guinot, linux-efi, brijesh.singh, kvm, rkrcmar, matt,
linus.walleij, linux-mm, paul.gortmaker, hpa, dan.j.williams,
aarcange, sfr, andriy.shevchenko, herbert, bhe, xemul, joro, x86,
mingo, msalter, ross.zwisler, bp, dyoung, thomas.lendacky,
jroedel, keescook, toshi.kani, mathieu.desnoyers, devel, tglx,
mchehab
In-Reply-To: <147190820782.9523.4967724730957229273.stgit@brijesh-build-machine>
The command is used for encrypting guest memory region.
For more information see [1], section 6.2
[1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/kvm/svm.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 126 insertions(+)
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 0b6da4a..c78bdc6 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -35,6 +35,8 @@
#include <linux/trace_events.h>
#include <linux/slab.h>
#include <linux/ccp-psp.h>
+#include <linux/pagemap.h>
+#include <linux/swap.h>
#include <asm/apic.h>
#include <asm/perf_event.h>
@@ -263,6 +265,8 @@ static unsigned long *sev_asid_bitmap;
#define svm_sev_guest() (svm->vcpu.kvm->arch.sev_info.handle)
#define svm_sev_ref_count() (svm->vcpu.kvm->arch.sev_info.ref_count)
+#define __sev_page_pa(x) ((page_to_pfn(x) << PAGE_SHIFT) | sme_me_mask)
+
static int sev_asid_new(void);
static void sev_asid_free(int asid);
static void sev_deactivate_handle(unsigned int handle);
@@ -5376,6 +5380,123 @@ err_1:
return ret;
}
+static int sev_pre_update(struct page **pages, unsigned long uaddr, int npages)
+{
+ int pinned;
+
+ /* pin the user virtual address */
+ down_read(¤t->mm->mmap_sem);
+ pinned = get_user_pages(uaddr, npages, 1, 0, pages, NULL);
+ up_read(¤t->mm->mmap_sem);
+ if (pinned != npages) {
+ printk(KERN_ERR "SEV: failed to pin %d pages (got %d)\n",
+ npages, pinned);
+ goto err;
+ }
+
+ return 0;
+err:
+ if (pinned > 0)
+ release_pages(pages, pinned, 0);
+ return 1;
+}
+
+static int sev_launch_update(struct kvm *kvm,
+ struct kvm_sev_launch_update __user *arg,
+ int *psp_ret)
+{
+ int first, last;
+ struct page **inpages;
+ int ret, nr_pages;
+ unsigned long uaddr, ulen;
+ int i, buffer_len, len, offset;
+ struct kvm_sev_launch_update params;
+ struct psp_data_launch_update *update;
+
+ /* Get the parameters from the user */
+ if (copy_from_user(¶ms, arg, sizeof(*arg)))
+ return -EFAULT;
+
+ uaddr = params.address;
+ ulen = params.length;
+
+ /* Get number of pages */
+ first = (uaddr & PAGE_MASK) >> PAGE_SHIFT;
+ last = ((uaddr + ulen - 1) & PAGE_MASK) >> PAGE_SHIFT;
+ nr_pages = (last - first + 1);
+
+ /* allocate the buffers */
+ buffer_len = sizeof(*update);
+ update = kzalloc(buffer_len, GFP_KERNEL);
+ if (!update)
+ return -ENOMEM;
+
+ ret = -ENOMEM;
+ inpages = kzalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
+ if (!inpages)
+ goto err_1;
+
+ ret = sev_pre_update(inpages, uaddr, nr_pages);
+ if (ret)
+ goto err_2;
+
+ /* the array of pages returned by get_user_pages() is a page-aligned
+ * memory. Since the user buffer is probably not page-aligned, we need
+ * to calculate the offset within a page for first update entry.
+ */
+ offset = uaddr & (PAGE_SIZE - 1);
+ len = min_t(size_t, (PAGE_SIZE - offset), ulen);
+ ulen -= len;
+
+ /* update first page -
+ * special care need to be taken for the first page because we might
+ * be dealing with offset within the page
+ */
+ update->hdr.buffer_len = buffer_len;
+ update->handle = kvm_sev_handle();
+ update->length = len;
+ update->address = __sev_page_pa(inpages[0]) + offset;
+ clflush_cache_range(page_address(inpages[0]), PAGE_SIZE);
+ ret = psp_guest_launch_update(update, 5, psp_ret);
+ if (ret) {
+ printk(KERN_ERR "SEV: LAUNCH_UPDATE addr %#llx len %d "
+ "ret=%d (%#010x)\n", update->address,
+ update->length, ret, *psp_ret);
+ goto err_3;
+ }
+
+ /* update remaining pages */
+ for (i = 1; i < nr_pages; i++) {
+
+ len = min_t(size_t, PAGE_SIZE, ulen);
+ ulen -= len;
+ update->length = len;
+ update->address = __sev_page_pa(inpages[i]);
+ clflush_cache_range(page_address(inpages[i]), PAGE_SIZE);
+
+ ret = psp_guest_launch_update(update, 5, psp_ret);
+ if (ret) {
+ printk(KERN_ERR "SEV: LAUNCH_UPDATE addr %#llx len %d "
+ "ret=%d (%#010x)\n", update->address,
+ update->length, ret, *psp_ret);
+ goto err_3;
+ }
+ }
+
+err_3:
+ /* mark pages dirty */
+ for (i = 0; i < nr_pages; i++) {
+ set_page_dirty_lock(inpages[i]);
+ mark_page_accessed(inpages[i]);
+ }
+ release_pages(inpages, nr_pages, 0);
+err_2:
+ kfree(inpages);
+err_1:
+ kfree(update);
+ return ret;
+}
+
static int amd_sev_issue_cmd(struct kvm *kvm,
struct kvm_sev_issue_cmd __user *user_data)
{
@@ -5391,6 +5512,11 @@ static int amd_sev_issue_cmd(struct kvm *kvm,
&arg.ret_code);
break;
}
+ case KVM_SEV_LAUNCH_UPDATE: {
+ r = sev_launch_update(kvm, (void *)arg.opaque,
+ &arg.ret_code);
+ break;
+ }
default:
break;
}
^ permalink raw reply related
* [RFC PATCH v1 21/28] KVM: introduce KVM_SEV_ISSUE_CMD ioctl
From: Brijesh Singh @ 2016-08-22 23:28 UTC (permalink / raw)
To: simon.guinot, linux-efi, brijesh.singh, kvm, rkrcmar, matt,
linus.walleij, linux-mm, paul.gortmaker, hpa, dan.j.williams,
aarcange, sfr, andriy.shevchenko, herbert, bhe, xemul, joro, x86,
mingo, msalter, ross.zwisler, bp, dyoung, thomas.lendacky,
jroedel, keescook, toshi.kani, mathieu.desnoyers, devel, tglx,
mchehab
In-Reply-To: <147190820782.9523.4967724730957229273.stgit@brijesh-build-machine>
The ioctl will be used by qemu to issue the Secure Encrypted
Virtualization (SEV) guest commands to transition a guest into
into SEV-enabled mode.
a typical usage:
struct kvm_sev_launch_start start;
struct kvm_sev_issue_cmd data;
data.cmd = KVM_SEV_LAUNCH_START;
data.opaque = &start;
ret = ioctl(fd, KVM_SEV_ISSUE_CMD, &data);
On SEV command failure, data.ret_code will contain the firmware error code.
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/include/asm/kvm_host.h | 3 +
arch/x86/kvm/x86.c | 13 ++++
include/uapi/linux/kvm.h | 125 +++++++++++++++++++++++++++++++++++++++
3 files changed, 141 insertions(+)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 9b885fc..a94e37d 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1040,6 +1040,9 @@ struct kvm_x86_ops {
void (*cancel_hv_timer)(struct kvm_vcpu *vcpu);
void (*setup_mce)(struct kvm_vcpu *vcpu);
+
+ int (*sev_issue_cmd)(struct kvm *kvm,
+ struct kvm_sev_issue_cmd __user *argp);
};
struct kvm_arch_async_pf {
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index d6f2f4b..0c0adad 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3820,6 +3820,15 @@ split_irqchip_unlock:
return r;
}
+static int kvm_vm_ioctl_sev_issue_cmd(struct kvm *kvm,
+ struct kvm_sev_issue_cmd __user *argp)
+{
+ if (kvm_x86_ops->sev_issue_cmd)
+ return kvm_x86_ops->sev_issue_cmd(kvm, argp);
+
+ return -ENOTTY;
+}
+
long kvm_arch_vm_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg)
{
@@ -4085,6 +4094,10 @@ long kvm_arch_vm_ioctl(struct file *filp,
r = kvm_vm_ioctl_enable_cap(kvm, &cap);
break;
}
+ case KVM_SEV_ISSUE_CMD: {
+ r = kvm_vm_ioctl_sev_issue_cmd(kvm, argp);
+ break;
+ }
default:
r = kvm_vm_ioctl_assigned_device(kvm, ioctl, arg);
}
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 300ef25..72c18c3 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1274,6 +1274,131 @@ struct kvm_s390_ucas_mapping {
/* Available with KVM_CAP_X86_SMM */
#define KVM_SMI _IO(KVMIO, 0xb7)
+/* Secure Encrypted Virtualization mode */
+enum sev_cmd {
+ KVM_SEV_LAUNCH_START = 0,
+ KVM_SEV_LAUNCH_UPDATE,
+ KVM_SEV_LAUNCH_FINISH,
+ KVM_SEV_GUEST_STATUS,
+ KVM_SEV_DBG_DECRYPT,
+ KVM_SEV_DBG_ENCRYPT,
+ KVM_SEV_RECEIVE_START,
+ KVM_SEV_RECEIVE_UPDATE,
+ KVM_SEV_RECEIVE_FINISH,
+ KVM_SEV_SEND_START,
+ KVM_SEV_SEND_UPDATE,
+ KVM_SEV_SEND_FINISH,
+ KVM_SEV_API_VERSION,
+ KVM_SEV_NR_MAX,
+};
+
+struct kvm_sev_issue_cmd {
+ __u32 cmd;
+ __u64 opaque;
+ __u32 ret_code;
+};
+
+struct kvm_sev_launch_start {
+ __u32 handle;
+ __u32 flags;
+ __u32 policy;
+ __u8 nonce[16];
+ __u8 dh_pub_qx[32];
+ __u8 dh_pub_qy[32];
+};
+
+struct kvm_sev_launch_update {
+ __u64 address;
+ __u32 length;
+};
+
+struct kvm_sev_launch_finish {
+ __u32 vcpu_count;
+ __u32 vcpu_length;
+ __u64 vcpu_mask_addr;
+ __u32 vcpu_mask_length;
+ __u8 measurement[32];
+};
+
+struct kvm_sev_guest_status {
+ __u32 policy;
+ __u32 state;
+};
+
+struct kvm_sev_dbg_decrypt {
+ __u64 src_addr;
+ __u64 dst_addr;
+ __u32 length;
+};
+
+struct kvm_sev_dbg_encrypt {
+ __u64 src_addr;
+ __u64 dst_addr;
+ __u32 length;
+};
+
+struct kvm_sev_receive_start {
+ __u32 handle;
+ __u32 flags;
+ __u32 policy;
+ __u8 policy_meas[32];
+ __u8 wrapped_tek[24];
+ __u8 wrapped_tik[24];
+ __u8 ten[16];
+ __u8 dh_pub_qx[32];
+ __u8 dh_pub_qy[32];
+ __u8 nonce[16];
+};
+
+struct kvm_sev_receive_update {
+ __u8 iv[16];
+ __u64 address;
+ __u32 length;
+};
+
+struct kvm_sev_receive_finish {
+ __u8 measurement[32];
+};
+
+struct kvm_sev_send_start {
+ __u8 nonce[16];
+ __u32 policy;
+ __u8 policy_meas[32];
+ __u8 wrapped_tek[24];
+ __u8 wrapped_tik[24];
+ __u8 ten[16];
+ __u8 iv[16];
+ __u32 flags;
+ __u8 api_major;
+ __u8 api_minor;
+ __u32 serial;
+ __u8 dh_pub_qx[32];
+ __u8 dh_pub_qy[32];
+ __u8 pek_sig_r[32];
+ __u8 pek_sig_s[32];
+ __u8 cek_sig_r[32];
+ __u8 cek_sig_s[32];
+ __u8 cek_pub_qx[32];
+ __u8 cek_pub_qy[32];
+ __u8 ask_sig_r[32];
+ __u8 ask_sig_s[32];
+ __u32 ncerts;
+ __u32 cert_length;
+ __u64 certs_addr;
+};
+
+struct kvm_sev_send_update {
+ __u32 length;
+ __u64 src_addr;
+ __u64 dst_addr;
+};
+
+struct kvm_sev_send_finish {
+ __u8 measurement[32];
+};
+
+#define KVM_SEV_ISSUE_CMD _IOWR(KVMIO, 0xb8, struct kvm_sev_issue_cmd)
+
#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
#define KVM_DEV_ASSIGN_MASK_INTX (1 << 2)
^ permalink raw reply related
* [RFC PATCH v1 00/28] x86: Secure Encrypted Virtualization (AMD)
From: Brijesh Singh @ 2016-08-22 23:21 UTC (permalink / raw)
To: kvm, rkrcmar, matt, linus.walleij, linux-mm, paul.gortmaker, hpa,
dan.j.williams, aarcange, sfr, andriy.shevchenko, herbert, bhe,
xemul, joro, x86, mingo, labbott, msalter, ross.zwisler, bp,
dyoung, thomas.lendacky, jroedel, keescook, toshi.kani,
mathieu.desnoyers, devel, tglx, mchehab, iamjoonsoo.kim,
simon.guinot, tony.luck, alexandre.bounine, kuleshovmail, <
This RFC series provides support for AMD's new Secure Encrypted
Virtualization (SEV) feature. This RFC is build upon Secure Memory
Encryption (SME) RFC.
SEV is an extension to the AMD-V architecture which supports running
multiple VMs under the control of a hypervisor. When enabled, SEV
hardware tags all code and data with its VM ASID which indicates which
VM the data originated from or is intended for. This tag is kept with
the data at all times when inside the SOC, and prevents that data from
being used by anyone other than the owner. While the tag protects VM
data inside the SOC, AES with 128 bit encryption protects data outside
the SOC. When data leaves or enters the SOC, it is encrypted/decrypted
respectively by hardware with a key based on the associated tag.
SEV guest VMs have the concept of private and shared memory. Private memory
is encrypted with the guest-specific key, while shared memory may be encrypted
with hypervisor key. Certain types of memory (namely instruction pages and
guest page tables) are always treated as private memory by the hardware.
For data memory, SEV guest VMs can choose which pages they would like to
be private. The choice is done using the standard CPU page tables using
the C-bit, and is fully controlled by the guest. Due to security reasons
all the DMA operations inside the guest must be performed on shared pages
(C-bit clear). Note that since C-bit is only controllable by the guest OS
when it is operating in 64-bit or 32-bit PAE mode, in all other modes the
SEV hardware forces the C-bit to a 1.
SEV is designed to protect guest VMs from a benign but vulnerable
(i.e. not fully malicious) hypervisor. In particular, it reduces the attack
surface of guest VMs and can prevent certain types of VM-escape bugs
(e.g. hypervisor read-anywhere) from being used to steal guest data.
The RFC series also includes a crypto driver (psp.ko) which communicates
with SEV firmware that runs within the AMD secure processor provides a
secure key management interfaces. The hypervisor uses this interface to
enable SEV for secure guest and perform common hypervisor activities
such as launching, running, snapshotting , migrating and debugging a
guest. A new ioctl (KVM_SEV_ISSUE_CMD) is introduced which will enable
Qemu to send commands to the SEV firmware during guest life cycle.
The RFC series also includes patches required in guest OS to enable SEV
feature. A guest OS can check SEV support by calling KVM_FEATURE cpuid
instruction.
The following links provide additional details:
AMD Memory Encryption whitepaper:
http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf
AMD64 Architecture Programmer's Manual:
http://support.amd.com/TechDocs/24593.pdf
SME is section 7.10
SEV is section 15.34
Secure Encrypted Virutualization Key Management:
http://support.amd.com/TechDocs/55766_SEV-KM API_Spec.pdf
---
TODO:
- send qemu/seabios RFC's on respective mailing list
- integrate the psp driver with CCP driver (they share the PCI id's)
- add SEV guest migration command support
- add SEV snapshotting command support
- determine how to do ioremap of physical memory with mem encryption enabled
(e.g acpi tables)
- determine how to share the guest memory with hypervisor for to support
pvclock driver
Brijesh Singh (11):
crypto: add AMD Platform Security Processor driver
KVM: SVM: prepare to reserve asid for SEV guest
KVM: SVM: prepare for SEV guest management API support
KVM: introduce KVM_SEV_ISSUE_CMD ioctl
KVM: SVM: add SEV launch start command
KVM: SVM: add SEV launch update command
KVM: SVM: add SEV_LAUNCH_FINISH command
KVM: SVM: add KVM_SEV_GUEST_STATUS command
KVM: SVM: add KVM_SEV_DEBUG_DECRYPT command
KVM: SVM: add KVM_SEV_DEBUG_ENCRYPT command
KVM: SVM: add command to query SEV API version
Tom Lendacky (17):
kvm: svm: Add support for additional SVM NPF error codes
kvm: svm: Add kvm_fast_pio_in support
kvm: svm: Use the hardware provided GPA instead of page walk
x86: Secure Encrypted Virtualization (SEV) support
KVM: SVM: prepare for new bit definition in nested_ctl
KVM: SVM: Add SEV feature definitions to KVM
x86: Do not encrypt memory areas if SEV is enabled
Access BOOT related data encrypted with SEV active
x86/efi: Access EFI data as encrypted when SEV is active
x86: Change early_ioremap to early_memremap for BOOT data
x86: Don't decrypt trampoline area if SEV is active
x86: DMA support for SEV memory encryption
iommu/amd: AMD IOMMU support for SEV
x86: Don't set the SME MSR bit when SEV is active
x86: Unroll string I/O when SEV is active
x86: Add support to determine if running with SEV enabled
KVM: SVM: Enable SEV by setting the SEV_ENABLE cpu feature
arch/x86/boot/compressed/Makefile | 2
arch/x86/boot/compressed/head_64.S | 19 +
arch/x86/boot/compressed/mem_encrypt.S | 123 ++++
arch/x86/include/asm/io.h | 26 +
arch/x86/include/asm/kvm_emulate.h | 3
arch/x86/include/asm/kvm_host.h | 27 +
arch/x86/include/asm/mem_encrypt.h | 3
arch/x86/include/asm/svm.h | 3
arch/x86/include/uapi/asm/hyperv.h | 4
arch/x86/include/uapi/asm/kvm_para.h | 4
arch/x86/kernel/acpi/boot.c | 4
arch/x86/kernel/head64.c | 4
arch/x86/kernel/mem_encrypt.S | 44 ++
arch/x86/kernel/mpparse.c | 10
arch/x86/kernel/setup.c | 7
arch/x86/kernel/x8664_ksyms_64.c | 1
arch/x86/kvm/cpuid.c | 4
arch/x86/kvm/mmu.c | 20 +
arch/x86/kvm/svm.c | 906 ++++++++++++++++++++++++++++++++
arch/x86/kvm/x86.c | 73 +++
arch/x86/mm/ioremap.c | 7
arch/x86/mm/mem_encrypt.c | 50 ++
arch/x86/platform/efi/efi_64.c | 14
arch/x86/realmode/init.c | 11
drivers/crypto/Kconfig | 11
drivers/crypto/Makefile | 1
drivers/crypto/psp/Kconfig | 8
drivers/crypto/psp/Makefile | 3
drivers/crypto/psp/psp-dev.c | 220 ++++++++
drivers/crypto/psp/psp-dev.h | 95 +++
drivers/crypto/psp/psp-ops.c | 454 ++++++++++++++++
drivers/crypto/psp/psp-pci.c | 376 +++++++++++++
drivers/sfi/sfi_core.c | 6
include/linux/ccp-psp.h | 833 +++++++++++++++++++++++++++++
include/uapi/linux/Kbuild | 1
include/uapi/linux/ccp-psp.h | 182 ++++++
include/uapi/linux/kvm.h | 125 ++++
37 files changed, 3643 insertions(+), 41 deletions(-)
create mode 100644 arch/x86/boot/compressed/mem_encrypt.S
create mode 100644 drivers/crypto/psp/Kconfig
create mode 100644 drivers/crypto/psp/Makefile
create mode 100644 drivers/crypto/psp/psp-dev.c
create mode 100644 drivers/crypto/psp/psp-dev.h
create mode 100644 drivers/crypto/psp/psp-ops.c
create mode 100644 drivers/crypto/psp/psp-pci.c
create mode 100644 include/linux/ccp-psp.h
create mode 100644 include/uapi/linux/ccp-psp.h
--
Brijesh Singh
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [PATCH 1/2] PCI/IOV: Add function to allow Function Dependency Link override.
From: Bjorn Helgaas @ 2016-08-22 16:14 UTC (permalink / raw)
To: David Daney
Cc: Omer Khaliq, linux-kernel, linux-pci, linux-crypto,
linux-arm-kernel, bhelgaas, mpm, herbert, Ananth.Jasty,
david.daney
In-Reply-To: <57BB10E5.1050506@caviumnetworks.com>
On Mon, Aug 22, 2016 at 07:49:09AM -0700, David Daney wrote:
> On 08/22/2016 07:36 AM, Bjorn Helgaas wrote:
> >Hi David & Omer,
> >
> >On Fri, Aug 19, 2016 at 03:32:12PM -0700, Omer Khaliq wrote:
> >>From: David Daney <david.daney@cavium.com>
> >>
> >>Some hardware presents an incorrect SR-IOV Function Dependency Link,
> >>add a function to allow this to be overridden in the PF driver for
> >>such devices.
> >>
> >>Signed-off-by: David Daney <david.daney@cavium.com>
> >>Signed-off-by: Omer Khaliq <okhaliq@caviumnetworks.com>
> >>---
> >> drivers/pci/iov.c | 14 ++++++++++++++
> >> include/linux/pci.h | 1 +
> >> 2 files changed, 15 insertions(+)
> >>
> >>diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
> >>index 2194b44..81f0672 100644
> >>--- a/drivers/pci/iov.c
> >>+++ b/drivers/pci/iov.c
> >>@@ -640,6 +640,20 @@ int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn)
> >> EXPORT_SYMBOL_GPL(pci_enable_sriov);
> >>
> >> /**
> >>+ * pci_sriov_fdl_override - fix incorrect Function Dependency Link
> >>+ * @dev: the PCI device
> >>+ * @fdl: the corrected Function Dependency Link value
> >>+ *
> >>+ * For hardware presenting an incorrect Function Dependency Link in
> >>+ * the SR-IOV Extended Capability, allow a driver to override it.
> >>+ */
> >>+void pci_sriov_fdl_override(struct pci_dev *dev, u8 fdl)
> >>+{
> >>+ dev->sriov->link = fdl;
> >>+}
> >>+EXPORT_SYMBOL_GPL(pci_sriov_fdl_override);
> >
> >We usually use quirks to work around problems in config space. That's
> >a nice mechanism because we don't have to add new PCI core interfaces
> >and it makes it clear that we're working around a hardware problem.
> >
> >Can you use a quirk here? We allocate dev->sriov in the
> >pci_init_capabilities() path, so it looks like a pci_fixup_final quirk
> >should work.
> >
>
> The struct pci_sriov definition is private to drivers/pci, so in
> order to use a quirk to fix this, we would have to put it in
> drivers/pci/quirks.c. I was trying to keep this very device
> specific code in the driver, which requires an accessor to be able
> to manipulate the dev->sriov->link field.
>
> If you prefer a quirk in drivers/pci/quirks.c, we can certainly do
> that instead.
Oh, I didn't notice that pci_sriov was declared in drivers/pci/pci.h
instead of linux/pci.h. I do think I would prefer a quirk, and I
think it's fine to put it in drivers/pci/quirks.c.
Bjorn
^ permalink raw reply
* [PATCH -next] chcr: Fix non static symbol warning
From: Wei Yongjun @ 2016-08-22 16:11 UTC (permalink / raw)
To: Herbert Xu, David S. Miller, Hariprasad Shenai, Atul Gupta
Cc: Wei Yongjun, linux-crypto
From: Wei Yongjun <weiyongjun1@huawei.com>
Fixes the following sparse warning:
drivers/crypto/chelsio/chcr_algo.c:593:5: warning:
symbol 'cxgb4_is_crypto_q_full' was not declared. Should it be static?
Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
---
drivers/crypto/chelsio/chcr_algo.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/crypto/chelsio/chcr_algo.c b/drivers/crypto/chelsio/chcr_algo.c
index ad8e353..e4ddb92 100644
--- a/drivers/crypto/chelsio/chcr_algo.c
+++ b/drivers/crypto/chelsio/chcr_algo.c
@@ -590,7 +590,7 @@ badkey_err:
return -EINVAL;
}
-int cxgb4_is_crypto_q_full(struct net_device *dev, unsigned int idx)
+static int cxgb4_is_crypto_q_full(struct net_device *dev, unsigned int idx)
{
int ret = 0;
struct sge_ofld_txq *q;
^ permalink raw reply related
* Re: [PATCH 1/2] PCI/IOV: Add function to allow Function Dependency Link override.
From: David Daney @ 2016-08-22 14:49 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Omer Khaliq, linux-kernel, linux-pci, linux-crypto,
linux-arm-kernel, bhelgaas, mpm, herbert, Ananth.Jasty,
david.daney
In-Reply-To: <20160822143637.GA18628@localhost>
On 08/22/2016 07:36 AM, Bjorn Helgaas wrote:
> Hi David & Omer,
>
> On Fri, Aug 19, 2016 at 03:32:12PM -0700, Omer Khaliq wrote:
>> From: David Daney <david.daney@cavium.com>
>>
>> Some hardware presents an incorrect SR-IOV Function Dependency Link,
>> add a function to allow this to be overridden in the PF driver for
>> such devices.
>>
>> Signed-off-by: David Daney <david.daney@cavium.com>
>> Signed-off-by: Omer Khaliq <okhaliq@caviumnetworks.com>
>> ---
>> drivers/pci/iov.c | 14 ++++++++++++++
>> include/linux/pci.h | 1 +
>> 2 files changed, 15 insertions(+)
>>
>> diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
>> index 2194b44..81f0672 100644
>> --- a/drivers/pci/iov.c
>> +++ b/drivers/pci/iov.c
>> @@ -640,6 +640,20 @@ int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn)
>> EXPORT_SYMBOL_GPL(pci_enable_sriov);
>>
>> /**
>> + * pci_sriov_fdl_override - fix incorrect Function Dependency Link
>> + * @dev: the PCI device
>> + * @fdl: the corrected Function Dependency Link value
>> + *
>> + * For hardware presenting an incorrect Function Dependency Link in
>> + * the SR-IOV Extended Capability, allow a driver to override it.
>> + */
>> +void pci_sriov_fdl_override(struct pci_dev *dev, u8 fdl)
>> +{
>> + dev->sriov->link = fdl;
>> +}
>> +EXPORT_SYMBOL_GPL(pci_sriov_fdl_override);
>
> We usually use quirks to work around problems in config space. That's
> a nice mechanism because we don't have to add new PCI core interfaces
> and it makes it clear that we're working around a hardware problem.
>
> Can you use a quirk here? We allocate dev->sriov in the
> pci_init_capabilities() path, so it looks like a pci_fixup_final quirk
> should work.
>
The struct pci_sriov definition is private to drivers/pci, so in order
to use a quirk to fix this, we would have to put it in
drivers/pci/quirks.c. I was trying to keep this very device specific
code in the driver, which requires an accessor to be able to manipulate
the dev->sriov->link field.
If you prefer a quirk in drivers/pci/quirks.c, we can certainly do that
instead.
Thanks for taking the time to look at this,
David Daney
>> +
>> +/**
>> * pci_disable_sriov - disable the SR-IOV capability
>> * @dev: the PCI device
>> */
>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>> index 2599a98..da8a5b3 100644
>> --- a/include/linux/pci.h
>> +++ b/include/linux/pci.h
>> @@ -1823,6 +1823,7 @@ int pci_num_vf(struct pci_dev *dev);
>> int pci_vfs_assigned(struct pci_dev *dev);
>> int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs);
>> int pci_sriov_get_totalvfs(struct pci_dev *dev);
>> +void pci_sriov_fdl_override(struct pci_dev *dev, u8 fdl);
>> resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno);
>> #else
>> static inline int pci_iov_virtfn_bus(struct pci_dev *dev, int id)
>> --
>> 1.9.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 1/2] PCI/IOV: Add function to allow Function Dependency Link override.
From: Bjorn Helgaas @ 2016-08-22 14:36 UTC (permalink / raw)
To: Omer Khaliq
Cc: linux-kernel, linux-pci, linux-crypto, linux-arm-kernel, bhelgaas,
mpm, herbert, Ananth.Jasty, david.daney
In-Reply-To: <1471645933-3643-2-git-send-email-okhaliq@caviumnetworks.com>
Hi David & Omer,
On Fri, Aug 19, 2016 at 03:32:12PM -0700, Omer Khaliq wrote:
> From: David Daney <david.daney@cavium.com>
>
> Some hardware presents an incorrect SR-IOV Function Dependency Link,
> add a function to allow this to be overridden in the PF driver for
> such devices.
>
> Signed-off-by: David Daney <david.daney@cavium.com>
> Signed-off-by: Omer Khaliq <okhaliq@caviumnetworks.com>
> ---
> drivers/pci/iov.c | 14 ++++++++++++++
> include/linux/pci.h | 1 +
> 2 files changed, 15 insertions(+)
>
> diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
> index 2194b44..81f0672 100644
> --- a/drivers/pci/iov.c
> +++ b/drivers/pci/iov.c
> @@ -640,6 +640,20 @@ int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn)
> EXPORT_SYMBOL_GPL(pci_enable_sriov);
>
> /**
> + * pci_sriov_fdl_override - fix incorrect Function Dependency Link
> + * @dev: the PCI device
> + * @fdl: the corrected Function Dependency Link value
> + *
> + * For hardware presenting an incorrect Function Dependency Link in
> + * the SR-IOV Extended Capability, allow a driver to override it.
> + */
> +void pci_sriov_fdl_override(struct pci_dev *dev, u8 fdl)
> +{
> + dev->sriov->link = fdl;
> +}
> +EXPORT_SYMBOL_GPL(pci_sriov_fdl_override);
We usually use quirks to work around problems in config space. That's
a nice mechanism because we don't have to add new PCI core interfaces
and it makes it clear that we're working around a hardware problem.
Can you use a quirk here? We allocate dev->sriov in the
pci_init_capabilities() path, so it looks like a pci_fixup_final quirk
should work.
> +
> +/**
> * pci_disable_sriov - disable the SR-IOV capability
> * @dev: the PCI device
> */
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 2599a98..da8a5b3 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1823,6 +1823,7 @@ int pci_num_vf(struct pci_dev *dev);
> int pci_vfs_assigned(struct pci_dev *dev);
> int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs);
> int pci_sriov_get_totalvfs(struct pci_dev *dev);
> +void pci_sriov_fdl_override(struct pci_dev *dev, u8 fdl);
> resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno);
> #else
> static inline int pci_iov_virtfn_bus(struct pci_dev *dev, int id)
> --
> 1.9.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH] crypto: mxc-scc - check clk_prepare_enable() error
From: Fabio Estevam @ 2016-08-22 2:37 UTC (permalink / raw)
To: herbert; +Cc: s.trumtrar, linux-crypto, Fabio Estevam
From: Fabio Estevam <fabio.estevam@nxp.com>
clk_prepare_enable() may fail, so we should better check its return
value and propagate it in the case of failure.
Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
---
drivers/crypto/mxc-scc.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/crypto/mxc-scc.c b/drivers/crypto/mxc-scc.c
index ff383ef..ee4be1b0 100644
--- a/drivers/crypto/mxc-scc.c
+++ b/drivers/crypto/mxc-scc.c
@@ -668,7 +668,9 @@ static int mxc_scc_probe(struct platform_device *pdev)
return PTR_ERR(scc->clk);
}
- clk_prepare_enable(scc->clk);
+ ret = clk_prepare_enable(scc->clk);
+ if (ret)
+ return ret;
/* clear error status register */
writel(0x0, scc->base + SCC_SCM_ERROR_STATUS);
--
1.9.1
^ permalink raw reply related
* Re: [PATCH 6/7] random: make /dev/urandom scalable for silly userspace programs
From: Theodore Ts'o @ 2016-08-21 11:36 UTC (permalink / raw)
To: Jan Varho
Cc: Linux Kernel Developers List, linux-crypto, smueller, herbert,
andi, sandyinchina, jsd, hpa
In-Reply-To: <CABSDX40G2V9w-OfGU7xP06V5qkreq89CmdaJDc89b-2EskhCQg@mail.gmail.com>
On Sun, Aug 21, 2016 at 12:53:15PM +0300, Jan Varho wrote:
> On Mon, Jun 13, 2016 at 6:48 PM, Theodore Ts'o <tytso@mit.edu> wrote:
> > +static inline void maybe_reseed_primary_crng(void)
> > +{
> > + if (crng_init > 2 &&
> > + time_after(jiffies, primary_crng.init_time + CRNG_RESEED_INTERVAL))
> > + crng_reseed(&primary_crng, &input_pool);
> > +}
>
> Is the above function (which is now in 4.8-rc2) supposed to do
> something? It seems to have no callers and the maximum value of
> crng_init is 2.
It's dead code. Its function got moved into _extra_crng(), and you're
right, these days crng_init never gets above 2. Thanks for pointing
that out. I'll take it out as a cleanup patch.
- Ted
^ permalink raw reply
* Re: [PATCH 6/7] random: make /dev/urandom scalable for silly userspace programs
From: Jan Varho @ 2016-08-21 9:53 UTC (permalink / raw)
To: Theodore Ts'o
Cc: Linux Kernel Developers List, linux-crypto, smueller, herbert,
andi, sandyinchina, jsd, hpa
In-Reply-To: <1465832919-11316-7-git-send-email-tytso@mit.edu>
On Mon, Jun 13, 2016 at 6:48 PM, Theodore Ts'o <tytso@mit.edu> wrote:
> +static inline void maybe_reseed_primary_crng(void)
> +{
> + if (crng_init > 2 &&
> + time_after(jiffies, primary_crng.init_time + CRNG_RESEED_INTERVAL))
> + crng_reseed(&primary_crng, &input_pool);
> +}
Hi,
Is the above function (which is now in 4.8-rc2) supposed to do
something? It seems to have no callers and the maximum value of
crng_init is 2.
--
Jan Varho
^ permalink raw reply
* Attention Beneficially
From: Robert David @ 2016-08-21 6:38 UTC (permalink / raw)
In-Reply-To: <855696991.417467.1471761525032.ref@mail.yahoo.com>
Attention Beneficially
WESTERN UNION
This is very urgent Our Operation manager has sent your first payment of $5000.00 to you. Here is what we need from you to complete the
transfer, Your Name, Your Address,A Copy Of Your ID and Your Telephone Number: Noted That Only Fee Request from You Is to
Reactivate Transfer Files which is Sum Of $65Only, No More Fee again after that.
Western Union Agent: Mr. Peterson Godwin
Direct phone line is: + 229 98782817
E-mail ::(westernunion8087@gmail.com)
Bellow is your first payment for $5000usd sent today in your name.
Sender Name: Mr.
MTCN:
Question
Answer
Amount Sent: $5000.00
You can use this link to confirm the payment,
Best Regards,
Mr.Joseph Ezo
^ permalink raw reply
* Entropy sources (was: /dev/random - a new approach)
From: Jeffrey Walton @ 2016-08-21 5:37 UTC (permalink / raw)
To: H. Peter Anvin; +Cc: linux-crypto, linux-kernel
On Fri, Aug 19, 2016 at 1:20 PM, H. Peter Anvin <hpa@linux.intel.com> wrote:
> On 08/18/16 22:56, Herbert Xu wrote:
>> On Thu, Aug 18, 2016 at 10:49:47PM -0400, Theodore Ts'o wrote:
>>>
>>> That really depends on the system. We can't assume that people are
>>> using systems with a 100Hz clock interrupt. More often than not
>>> people are using tickless kernels these days. That's actually the
>>> problem with changing /dev/urandom to block until things are
>>> initialized.
>>
>> Couldn't we disable tickless until urandom has been seeded? In fact
>> perhaps we should accelerate the timer interrupt rate until it has
>> been seeded?
>>
>
> The biggest problem there is that the timer interrupt adds *no* entropy
> unless there is a source of asynchronicity in the system. On PCs,
> traditionally the timer has been run from a completely different crystal
> (14.31818 MHz) than the CPU, which is the ideal situation, but if they
> are run off the same crystal and run in lockstep, there is very little
> if anything there. On some systems, the timer may even *be* the only
> source of time, and the entropy truly is zero.
It seems like a networked computer should have an abundance on entropy
available from the network stack. Every common case I can come up with
includes a networked computer. If a handheld is outside of coverage,
then it probably does not have the randomness demands because it can't
communicate (i.e., TCP sequence numbers, key agreement, etc).
In fact, there are at least two papers that use bits from the network stack:
* When Good Randomness Goes Bad: Virtual Machine Reset Vulnerabilities
and Hedging Deployed Cryptography,
http://pages.cs.wisc.edu/~rist/papers/sslhedge.pdf
* When Virtual is Harder than Real: Security Challenges in Virtual
Machine Based Computing Environments,
http://www.usenix.org/legacy/event/hotos05/final_papers/full_papers/garfinkel/garfinkel.pdf
As IoT gains traction the entropy available locally should increase
because these devices are chatty. I also expect gossip protocols to
play more of a role in the future. A network based attacker cannot
possibly monitor every conversation, especially when devices pair and
form adhoc networks. The network attacker probably won't see the
traffic on a local LAN segment either for headless servers.
When using network bits, it seems like the remaining problem is
extracting the entropy. I think Krawczyk (et al) have done a lot of
work in this area:
* Leftover Hash Lemma, Revisited, http://eprint.iacr.org/2011/088.pdf
* Cryptographic Extraction and Key Derivation: The HKDF Scheme,
http://eprint.iacr.org/2010/264.pdf
Jeff
^ permalink raw reply
* Re: [PATCH v6 0/5] /dev/random - a new approach
From: Herbert Xu @ 2016-08-21 3:14 UTC (permalink / raw)
To: H. Peter Anvin
Cc: Theodore Ts'o, Pavel Machek, Stephan Mueller, sandyinchina,
Jason Cooper, John Denker, Joe Perches, George Spelvin,
linux-crypto, linux-kernel
In-Reply-To: <605855f7-2990-f118-c07c-ef20cfcc43fb@linux.intel.com>
On Fri, Aug 19, 2016 at 10:20:18AM -0700, H. Peter Anvin wrote:
> On 08/18/16 22:56, Herbert Xu wrote:
> > On Thu, Aug 18, 2016 at 10:49:47PM -0400, Theodore Ts'o wrote:
> >>
> >> That really depends on the system. We can't assume that people are
> >> using systems with a 100Hz clock interrupt. More often than not
> >> people are using tickless kernels these days. That's actually the
> >> problem with changing /dev/urandom to block until things are
> >> initialized.
> >
> > Couldn't we disable tickless until urandom has been seeded? In fact
> > perhaps we should accelerate the timer interrupt rate until it has
> > been seeded?
> >
>
> The biggest problem there is that the timer interrupt adds *no* entropy
> unless there is a source of asynchronicity in the system. On PCs,
> traditionally the timer has been run from a completely different crystal
> (14.31818 MHz) than the CPU, which is the ideal situation, but if they
> are run off the same crystal and run in lockstep, there is very little
> if anything there. On some systems, the timer may even *be* the only
> source of time, and the entropy truly is zero.
Sure, but that's orthorgonal to what Ted was talking about above.
Thanks,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [PATCH -next] crypto: drbg - fix error return code
From: Stephan Mueller @ 2016-08-20 19:13 UTC (permalink / raw)
To: Wei Yongjun; +Cc: Herbert Xu, linux-crypto
In-Reply-To: <1471705611-19309-1-git-send-email-weiyj.lk@gmail.com>
Am Samstag, 20. August 2016, 15:06:51 CEST schrieb Wei Yongjun:
Hi Wei,
> Fix to return a negative error code from the error handling
> case instead of 0.
>
> Signed-off-by: Wei Yongjun <weiyj.lk@gmail.com>
Acked-by: Stephan Mueller <smueller@chronox.de>
Ciao
Stephan
^ permalink raw reply
* [PATCH] hw_random: omap3-rom-rng.c: Remove obsoleted functions
From: PrasannaKumar Muralidharan @ 2016-08-20 16:01 UTC (permalink / raw)
To: linux-crypto, aaro.koskinen, mpm, herbert, linux-kernel
Cc: PrasannaKumar Muralidharan
Remove omap3_rom_rng_data_present method as it was returning 1 always.
Use .read callback instead of .data_read callback. This avoids use of
obsolete callbacks.
This patch is not tested with hardware as I don't have access to it.
Signed-off-by: PrasannaKumar Muralidharan <prasannatsmkumar@gmail.com>
---
drivers/char/hw_random/omap3-rom-rng.c | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/drivers/char/hw_random/omap3-rom-rng.c b/drivers/char/hw_random/omap3-rom-rng.c
index 8da14f1..37a58d7 100644
--- a/drivers/char/hw_random/omap3-rom-rng.c
+++ b/drivers/char/hw_random/omap3-rom-rng.c
@@ -71,12 +71,7 @@ static int omap3_rom_rng_get_random(void *buf, unsigned int count)
return 0;
}
-static int omap3_rom_rng_data_present(struct hwrng *rng, int wait)
-{
- return 1;
-}
-
-static int omap3_rom_rng_data_read(struct hwrng *rng, u32 *data)
+static int omap3_rom_rng_read(struct hwrng *rng, void *data, size_t max, bool w)
{
int r;
@@ -88,8 +83,7 @@ static int omap3_rom_rng_data_read(struct hwrng *rng, u32 *data)
static struct hwrng omap3_rom_rng_ops = {
.name = "omap3-rom",
- .data_present = omap3_rom_rng_data_present,
- .data_read = omap3_rom_rng_data_read,
+ .read = omap3_rom_rng_read,
};
static int omap3_rom_rng_probe(struct platform_device *pdev)
--
2.5.0
^ permalink raw reply related
* [PATCH -next] crypto: drbg - fix error return code
From: Wei Yongjun @ 2016-08-20 15:06 UTC (permalink / raw)
To: Herbert Xu, Stephan Mueller; +Cc: Wei Yongjun, linux-crypto
Fix to return a negative error code from the error handling
case instead of 0.
Signed-off-by: Wei Yongjun <weiyj.lk@gmail.com>
---
crypto/drbg.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index edf3ce0..fb33f7d 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -1178,12 +1178,16 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
goto err;
drbg->Vbuf = kmalloc(drbg_statelen(drbg) + ret, GFP_KERNEL);
- if (!drbg->Vbuf)
+ if (!drbg->Vbuf) {
+ ret = -ENOMEM;
goto fini;
+ }
drbg->V = PTR_ALIGN(drbg->Vbuf, ret + 1);
drbg->Cbuf = kmalloc(drbg_statelen(drbg) + ret, GFP_KERNEL);
- if (!drbg->Cbuf)
+ if (!drbg->Cbuf) {
+ ret = -ENOMEM;
goto fini;
+ }
drbg->C = PTR_ALIGN(drbg->Cbuf, ret + 1);
/* scratchpad is only generated for CTR and Hash */
if (drbg->core->flags & DRBG_HMAC)
@@ -1199,8 +1203,10 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
if (0 < sb_size) {
drbg->scratchpadbuf = kzalloc(sb_size + ret, GFP_KERNEL);
- if (!drbg->scratchpadbuf)
+ if (!drbg->scratchpadbuf) {
+ ret = -ENOMEM;
goto fini;
+ }
drbg->scratchpad = PTR_ALIGN(drbg->scratchpadbuf, ret + 1);
}
@@ -1999,7 +2005,7 @@ static int __init drbg_init(void)
{
unsigned int i = 0; /* pointer to drbg_algs */
unsigned int j = 0; /* pointer to drbg_cores */
- int ret = -EFAULT;
+ int ret;
ret = drbg_healthcheck_sanity();
if (ret)
@@ -2009,7 +2015,7 @@ static int __init drbg_init(void)
pr_info("DRBG: Cannot register all DRBG types"
"(slots needed: %zu, slots available: %zu)\n",
ARRAY_SIZE(drbg_cores) * 2, ARRAY_SIZE(drbg_algs));
- return ret;
+ return -EFAULT;
}
/*
^ permalink raw reply related
* [PATCH -next v2] crypto: sun4i-ss - fix missing unlock on error in sun4i_hash()
From: Wei Yongjun @ 2016-08-20 10:48 UTC (permalink / raw)
To: Corentin Labbe, Herbert Xu, David S. Miller, Maxime Ripard,
Chen-Yu Tsai
Cc: Wei Yongjun, linux-crypto, linux-arm-kernel
In-Reply-To: <1471560130-5265-1-git-send-email-weiyj.lk@gmail.com>
Add the missing unlock before return from function sun4i_hash()
in the error handling case.
Fixes: 477d9b2e591b ("crypto: sun4i-ss - unify update/final function")
Signed-off-by: Wei Yongjun <weiyj.lk@gmail.com>
---
v1 -> v2: goto release_ss as LABBE Corentin's suggestion
---
drivers/crypto/sunxi-ss/sun4i-ss-hash.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-hash.c b/drivers/crypto/sunxi-ss/sun4i-ss-hash.c
index 2ee3b59..1afeb8e 100644
--- a/drivers/crypto/sunxi-ss/sun4i-ss-hash.c
+++ b/drivers/crypto/sunxi-ss/sun4i-ss-hash.c
@@ -245,7 +245,8 @@ int sun4i_hash(struct ahash_request *areq)
if (end > areq->nbytes || areq->nbytes - end > 63) {
dev_err(ss->dev, "ERROR: Bound error %u %u\n",
end, areq->nbytes);
- return -EINVAL;
+ err = -EINVAL;
+ goto release_ss;
}
} else {
/* Since we have the flag final, we can go up to modulo 4 */
^ permalink raw reply related
* Re: [PATCH 2/2] crypto: marvell - Don't break chain for computable last ahash requests
From: Boris Brezillon @ 2016-08-20 7:17 UTC (permalink / raw)
To: Romain Perier
Cc: Arnaud Ebalard, David S. Miller, Herbert Xu, Gregory Clement,
Thomas Petazzoni, Russell King, linux-crypto, linux-arm-kernel
In-Reply-To: <1471522334-24839-3-git-send-email-romain.perier@free-electrons.com>
On Thu, 18 Aug 2016 14:12:14 +0200
Romain Perier <romain.perier@free-electrons.com> wrote:
> Currently, the driver breaks chain for all kind of hash requests in order
> to don't override intermediate states of partial ahash updates. However,
> some final ahash requests can be directly processed by the engine, and
> so without intermediate state. This is typically the case for most for
> the HMAC requests processed via IPSec.
>
> This commits adds a TDMA descriptor to copy outer results for thise kind
> of request into the "result" dma pool, then it allow to chain these
> requests at the DMA level. The 'complete' operation is also updated to
> retrieve the MAC digest from the right location.
>
> Signed-off-by: Romain Perier <romain.perier@free-electrons.com>
> ---
> drivers/crypto/marvell/hash.c | 69 +++++++++++++++++++++++++++++++++----------
> 1 file changed, 54 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/crypto/marvell/hash.c b/drivers/crypto/marvell/hash.c
> index 9f28468..1a91662 100644
> --- a/drivers/crypto/marvell/hash.c
> +++ b/drivers/crypto/marvell/hash.c
> @@ -312,24 +312,48 @@ static void mv_cesa_ahash_complete(struct crypto_async_request *req)
> int i;
>
> digsize = crypto_ahash_digestsize(crypto_ahash_reqtfm(ahashreq));
> - for (i = 0; i < digsize / 4; i++)
> - creq->state[i] = readl_relaxed(engine->regs + CESA_IVDIG(i));
>
> - if (creq->last_req) {
> + if (mv_cesa_req_get_type(&creq->base) == CESA_DMA_REQ &&
> + !(creq->base.chain.last->flags & CESA_TDMA_BREAK_CHAIN)) {
> + struct mv_cesa_tdma_desc *tdma = NULL;
> +
> + for (tdma = creq->base.chain.first; tdma; tdma = tdma->next) {
> + u32 type = tdma->flags & CESA_TDMA_TYPE_MSK;
> + if (type == CESA_TDMA_RESULT)
> + break;
> + }
> +
> + BUG_ON(!tdma);
Let's try to use BUG_ON() only when we can't recover from a failure.
This is not the case here, just print an error message, or even better,
move this check in ->process() where you can return an error code
(note that this requires changing a bit the way you are handling
errors in mv_cesa_tdma_process()).
> +
> /*
> - * Hardware's MD5 digest is in little endian format, but
> - * SHA in big endian format
> + * Result is already in the correct endianess when the SA is
> + * used
> */
> - if (creq->algo_le) {
> - __le32 *result = (void *)ahashreq->result;
> + __le32 *data = tdma->data + 0x40;
> + for (i = 0; i < digsize / 4; i++)
> + creq->state[i] = cpu_to_le32(data[i]);
>
> - for (i = 0; i < digsize / 4; i++)
> - result[i] = cpu_to_le32(creq->state[i]);
> - } else {
> - __be32 *result = (void *)ahashreq->result;
> + memcpy(ahashreq->result, data, digsize);
Is it safe to do that when you're in big endian (that's not a
rhetorical question, I always have a hard time figuring when endianess
conversion should be done)?
> + } else {
> + for (i = 0; i < digsize / 4; i++)
> + creq->state[i] = readl_relaxed(engine->regs +
> + CESA_IVDIG(i));
> + if (creq->last_req) {
> + /*
> + * Hardware's MD5 digest is in little endian format, but
> + * SHA in big endian format
> + */
> + if (creq->algo_le) {
> + __le32 *result = (void *)ahashreq->result;
> +
> + for (i = 0; i < digsize / 4; i++)
> + result[i] = cpu_to_le32(creq->state[i]);
> + } else {
> + __be32 *result = (void *)ahashreq->result;
>
> - for (i = 0; i < digsize / 4; i++)
> - result[i] = cpu_to_be32(creq->state[i]);
> + for (i = 0; i < digsize / 4; i++)
> + result[i] = cpu_to_be32(creq->state[i]);
> + }
> }
> }
>
> @@ -504,6 +528,11 @@ mv_cesa_ahash_dma_last_req(struct mv_cesa_tdma_chain *chain,
> CESA_SA_DESC_CFG_LAST_FRAG,
> CESA_SA_DESC_CFG_FRAG_MSK);
>
> + ret = mv_cesa_dma_add_result_op(chain,
> + CESA_SA_MAC_IIV_SRAM_OFFSET, 96,
> + CESA_TDMA_SRC_IN_SRAM, flags);
> + if (ret)
> + return ERR_PTR(-ENOMEM);
> return op;
> }
>
> @@ -564,6 +593,7 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
> struct mv_cesa_op_ctx *op = NULL;
> unsigned int frag_len;
> int ret;
> + u32 type;
How about naming this variable break_chain? This would be clearer IMO.
bool break_chain = false;
>
> basereq->chain.first = NULL;
> basereq->chain.last = NULL;
> @@ -635,6 +665,8 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
> goto err_free_tdma;
> }
>
> + type = basereq->chain.last->flags & CESA_TDMA_TYPE_MSK;
> +
if (basereq->chain.last->flags & CESA_TDMA_TYPE_MSK)
break_chain = true;
> if (op) {
> /* Add dummy desc to wait for crypto operation end */
> ret = mv_cesa_dma_add_dummy_end(&basereq->chain, flags);
> @@ -648,8 +680,15 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
> else
> creq->cache_ptr = 0;
>
> - basereq->chain.last->flags |= (CESA_TDMA_END_OF_REQ |
> - CESA_TDMA_BREAK_CHAIN);
> + basereq->chain.last->flags |= CESA_TDMA_END_OF_REQ;
> + /*
> + * If results are copied via DMA, this means that this
> + * request can be directly processed by the engine,
> + * without partial updates. So we can chain it at the
> + * DMA level with other requests.
> + */
Move the comment where you're assigning break_chain to true.
> + if (type != CESA_TDMA_RESULT)
if (break_chain)
> + basereq->chain.last->flags |= CESA_TDMA_BREAK_CHAIN;
>
> return 0;
>
^ permalink raw reply
* Re: [PATCH 1/2] crypto: marvell - Use an unique pool to copy results of requests
From: Boris Brezillon @ 2016-08-20 6:26 UTC (permalink / raw)
To: Romain Perier
Cc: Arnaud Ebalard, David S. Miller, Herbert Xu, Gregory Clement,
Thomas Petazzoni, Russell King, linux-crypto, linux-arm-kernel
In-Reply-To: <1471522334-24839-2-git-send-email-romain.perier@free-electrons.com>
Hi Romain,
On Thu, 18 Aug 2016 14:12:13 +0200
Romain Perier <romain.perier@free-electrons.com> wrote:
> So far, we used a dedicated dma pool to copy the result of outer IV for
> cipher requests. Instead of using a dma pool per outer data, we prefer
> use a common dma pool that contains the part of the SRAM that is likely
> to be used by the 'complete' operation, later. In this way, any type of
> result can be retrieved by DMA for cipher or ahash requests.
Can't we just re-use the op_pool (and drop the cesa_iv/result pool)? It
may be suboptimal in term of memory usage, but adding more pools also
adds some overhead.
>
> Signed-off-by: Romain Perier <romain.perier@free-electrons.com>
> ---
> drivers/crypto/marvell/cesa.c | 4 ++--
> drivers/crypto/marvell/cesa.h | 6 +++---
> drivers/crypto/marvell/cipher.c | 2 +-
> drivers/crypto/marvell/tdma.c | 16 ++++++++--------
> 4 files changed, 14 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/crypto/marvell/cesa.c b/drivers/crypto/marvell/cesa.c
> index 37dadb2..4d308ad 100644
> --- a/drivers/crypto/marvell/cesa.c
> +++ b/drivers/crypto/marvell/cesa.c
> @@ -375,8 +375,8 @@ static int mv_cesa_dev_dma_init(struct mv_cesa_dev *cesa)
> if (!dma->padding_pool)
> return -ENOMEM;
>
> - dma->iv_pool = dmam_pool_create("cesa_iv", dev, 16, 1, 0);
> - if (!dma->iv_pool)
> + dma->result_pool = dmam_pool_create("cesa_result", dev, 96, 1, 0);
It's better to use a sizeof(xxx) here to avoid bugs if the context size
grows.
The rest looks good.
Thanks,
Boris
> + if (!dma->result_pool)
> return -ENOMEM;
>
> cesa->dma = dma;
> diff --git a/drivers/crypto/marvell/cesa.h b/drivers/crypto/marvell/cesa.h
> index e423d33..3be1aa3 100644
> --- a/drivers/crypto/marvell/cesa.h
> +++ b/drivers/crypto/marvell/cesa.h
> @@ -277,7 +277,7 @@ struct mv_cesa_op_ctx {
> #define CESA_TDMA_DUMMY 0
> #define CESA_TDMA_DATA 1
> #define CESA_TDMA_OP 2
> -#define CESA_TDMA_IV 3
> +#define CESA_TDMA_RESULT 3
>
> /**
> * struct mv_cesa_tdma_desc - TDMA descriptor
> @@ -393,7 +393,7 @@ struct mv_cesa_dev_dma {
> struct dma_pool *op_pool;
> struct dma_pool *cache_pool;
> struct dma_pool *padding_pool;
> - struct dma_pool *iv_pool;
> + struct dma_pool *result_pool;
> };
>
> /**
> @@ -839,7 +839,7 @@ mv_cesa_tdma_desc_iter_init(struct mv_cesa_tdma_chain *chain)
> memset(chain, 0, sizeof(*chain));
> }
>
> -int mv_cesa_dma_add_iv_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src,
> +int mv_cesa_dma_add_result_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src,
> u32 size, u32 flags, gfp_t gfp_flags);
>
> struct mv_cesa_op_ctx *mv_cesa_dma_add_op(struct mv_cesa_tdma_chain *chain,
> diff --git a/drivers/crypto/marvell/cipher.c b/drivers/crypto/marvell/cipher.c
> index d19dc96..bd575b1 100644
> --- a/drivers/crypto/marvell/cipher.c
> +++ b/drivers/crypto/marvell/cipher.c
> @@ -373,7 +373,7 @@ static int mv_cesa_ablkcipher_dma_req_init(struct ablkcipher_request *req,
>
> /* Add output data for IV */
> ivsize = crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(req));
> - ret = mv_cesa_dma_add_iv_op(&basereq->chain, CESA_SA_CRYPT_IV_SRAM_OFFSET,
> + ret = mv_cesa_dma_add_result_op(&basereq->chain, CESA_SA_CRYPT_IV_SRAM_OFFSET,
> ivsize, CESA_TDMA_SRC_IN_SRAM, flags);
>
> if (ret)
> diff --git a/drivers/crypto/marvell/tdma.c b/drivers/crypto/marvell/tdma.c
> index 9fd7a5f..499a1d3 100644
> --- a/drivers/crypto/marvell/tdma.c
> +++ b/drivers/crypto/marvell/tdma.c
> @@ -69,8 +69,8 @@ void mv_cesa_dma_cleanup(struct mv_cesa_req *dreq)
> if (type == CESA_TDMA_OP)
> dma_pool_free(cesa_dev->dma->op_pool, tdma->op,
> le32_to_cpu(tdma->src));
> - else if (type == CESA_TDMA_IV)
> - dma_pool_free(cesa_dev->dma->iv_pool, tdma->data,
> + else if (type == CESA_TDMA_RESULT)
> + dma_pool_free(cesa_dev->dma->result_pool, tdma->data,
> le32_to_cpu(tdma->dst));
>
> tdma = tdma->next;
> @@ -209,29 +209,29 @@ mv_cesa_dma_add_desc(struct mv_cesa_tdma_chain *chain, gfp_t flags)
> return new_tdma;
> }
>
> -int mv_cesa_dma_add_iv_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src,
> +int mv_cesa_dma_add_result_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src,
> u32 size, u32 flags, gfp_t gfp_flags)
> {
>
> struct mv_cesa_tdma_desc *tdma;
> - u8 *iv;
> + u8 *result;
> dma_addr_t dma_handle;
>
> tdma = mv_cesa_dma_add_desc(chain, gfp_flags);
> if (IS_ERR(tdma))
> return PTR_ERR(tdma);
>
> - iv = dma_pool_alloc(cesa_dev->dma->iv_pool, gfp_flags, &dma_handle);
> - if (!iv)
> + result = dma_pool_alloc(cesa_dev->dma->result_pool, gfp_flags, &dma_handle);
> + if (!result)
> return -ENOMEM;
>
> tdma->byte_cnt = cpu_to_le32(size | BIT(31));
> tdma->src = src;
> tdma->dst = cpu_to_le32(dma_handle);
> - tdma->data = iv;
> + tdma->data = result;
>
> flags &= (CESA_TDMA_DST_IN_SRAM | CESA_TDMA_SRC_IN_SRAM);
> - tdma->flags = flags | CESA_TDMA_IV;
> + tdma->flags = flags | CESA_TDMA_RESULT;
> return 0;
> }
>
^ permalink raw reply
* Re: [PATCH 2/2] hwrng: thunderx: Add Cavium HWRNG driver for ThunderX SoC.
From: Corentin LABBE @ 2016-08-20 5:41 UTC (permalink / raw)
To: Omer Khaliq, linux-kernel, linux-pci, linux-crypto,
linux-arm-kernel, bhelgaas, mpm, herbert, Ananth.Jasty,
david.daney
In-Reply-To: <1471645933-3643-3-git-send-email-okhaliq@caviumnetworks.com>
Hello
I have some minor comments below
On 20/08/2016 00:32, Omer Khaliq wrote:
> The Cavium ThunderX SoC has a hardware random number generator.
> This driver provides support using the HWRNG framework.
>
> Signed-off-by: Omer Khaliq <okhaliq@caviumnetworks.com>
> Signed-off-by: Ananth Jasty <Ananth.Jasty@cavium.com>
> Acked-by: David Daney <david.daney@cavium.com>
> ---
> drivers/char/hw_random/Kconfig | 13 +++++
> drivers/char/hw_random/Makefile | 1 +
> drivers/char/hw_random/cavium-rng-vf.c | 102 ++++++++++++++++++++++++++++++++
> drivers/char/hw_random/cavium-rng.c | 103 +++++++++++++++++++++++++++++++++
> 4 files changed, 219 insertions(+)
> create mode 100644 drivers/char/hw_random/cavium-rng-vf.c
> create mode 100644 drivers/char/hw_random/cavium-rng.c
>
> diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
> index 56ad5a5..fb9c7ad 100644
> --- a/drivers/char/hw_random/Kconfig
> +++ b/drivers/char/hw_random/Kconfig
> @@ -410,6 +410,19 @@ config HW_RANDOM_MESON
>
> If unsure, say Y.
>
> +config HW_RANDOM_CAVIUM
> + tristate "Cavium ThunderX Random Number Generator support"
> + depends on HW_RANDOM && PCI && (ARM64 || (COMPILE_TEST && 64BIT))
> + default HW_RANDOM
> + ---help---
> + This driver provides kernel-side support for the Random Number
> + Generator hardware found on Cavium SoCs.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called cavium_rng.
> +
> + If unsure, say Y.
> +
> endif # HW_RANDOM
>
> config UML_RANDOM
> diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
> index 04bb0b0..5f52b1e 100644
> --- a/drivers/char/hw_random/Makefile
> +++ b/drivers/char/hw_random/Makefile
> @@ -35,3 +35,4 @@ obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o
> obj-$(CONFIG_HW_RANDOM_STM32) += stm32-rng.o
> obj-$(CONFIG_HW_RANDOM_PIC32) += pic32-rng.o
> obj-$(CONFIG_HW_RANDOM_MESON) += meson-rng.o
> +obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o
> diff --git a/drivers/char/hw_random/cavium-rng-vf.c b/drivers/char/hw_random/cavium-rng-vf.c
> new file mode 100644
> index 0000000..8e80bce
> --- /dev/null
> +++ b/drivers/char/hw_random/cavium-rng-vf.c
> @@ -0,0 +1,102 @@
> +/*
> + * Hardware Random Number Generator support for Cavium, Inc.
> + * Thunder processor family.
> + *
> + * This file is subject to the terms and conditions of the GNU General Public
> + * License. See the file "COPYING" in the main directory of this archive
> + * for more details.
> + *
> + * Copyright (C) 2016 Cavium, Inc.
> + */
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/device.h>
> +#include <linux/hw_random.h>
> +#include <linux/io.h>
> +#include <linux/pci_ids.h>
> +#include <linux/gfp.h>
> +#include <linux/pci.h>
> +#include <linux/init.h>
Please alphabetize headers, and check if there are necessary, clearly platform_device.h is unnecessary.
> +
> +struct cavium_rng {
> + struct hwrng ops;
> + void __iomem *result;
> +};
> +
> +/* Read data from the RNG unit */
> +static int cavium_rng_read(struct hwrng *rng, void *dat, size_t max, bool wait)
> +{
> + struct cavium_rng *p = container_of(rng, struct cavium_rng, ops);
> + unsigned int size = max;
> +
> + while (size >= 8) {
> + *((u64 *)dat) = readq(p->result);
> + size -= 8;
> + dat += 8;
> + }
> + while (size > 0) {
> + *((u8 *)dat) = readb(p->result);
> + size--;
> + dat++;
> + }
> + return max;
> +}
> +
> +/* Map Cavium RNG to an HWRNG object */
> +static int cavium_rng_probe_vf(struct pci_dev *pdev,
> + const struct pci_device_id *id)
> +{
> + struct cavium_rng *rng;
> + int ret;
> +
> + rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
> + if (!rng)
> + return -ENOMEM;
> +
> + /* Map the RNG result */
> + rng->result = pcim_iomap(pdev, 0, 0);
> + if (!rng->result) {
> + dev_err(&pdev->dev, "Error iomap failed retrieving result.\n");
> + return -ENOMEM;
> + }
> +
> + rng->ops.name = "cavium rng";
> + rng->ops.read = cavium_rng_read;
> + rng->ops.quality = 1000;
> +
> + pci_set_drvdata(pdev, rng);
> +
> + ret = hwrng_register(&rng->ops);
> + if (ret) {
> + dev_err(&pdev->dev, "Error registering device as HWRNG.\n");
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +/* Remove the VF */
> +void cavium_rng_remove_vf(struct pci_dev *pdev)
> +{
> + struct cavium_rng *rng;
> +
> + rng = pci_get_drvdata(pdev);
> + hwrng_unregister(&rng->ops);
> +}
> +
> +static const struct pci_device_id cavium_rng_vf_id_table[] = {
> + { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xa033), 0, 0, 0},
> + {0,},
> +};
> +MODULE_DEVICE_TABLE(pci, cavium_rng_vf_id_table);
> +
> +static struct pci_driver cavium_rng_vf_driver = {
> + .name = "cavium_rng_vf",
> + .id_table = cavium_rng_vf_id_table,
> + .probe = cavium_rng_probe_vf,
> + .remove = cavium_rng_remove_vf,
> +};
> +module_pci_driver(cavium_rng_vf_driver);
> +
> +MODULE_AUTHOR("Omer Khaliq");
You could add your email address.
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/char/hw_random/cavium-rng.c b/drivers/char/hw_random/cavium-rng.c
> new file mode 100644
> index 0000000..7f09ee4
> --- /dev/null
> +++ b/drivers/char/hw_random/cavium-rng.c
> @@ -0,0 +1,103 @@
> +/*
> + * Hardware Random Number Generator support for Cavium Inc.
> + * Thunder processor family.
> + *
> + * This file is subject to the terms and conditions of the GNU General Public
> + * License. See the file "COPYING" in the main directory of this archive
> + * for more details.
> + *
> + * Copyright (C) 2016 Cavium, Inc.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/device.h>
> +#include <linux/hw_random.h>
> +#include <linux/io.h>
> +#include <linux/pci_ids.h>
> +#include <linux/gfp.h>
> +#include <linux/pci.h>
> +#include <linux/init.h>
> +#include <linux/pci-ats.h>
Same comment for headers
> +
> +#define THUNDERX_RNM_ENT_EN 0x1
> +#define THUNDERX_RNM_RNG_EN 0x2
> +
> +struct cavium_rng_pf {
> + void __iomem *control_status;
> +};
> +
> +
Do you have run checkpatch.pl ?
No more than one blank line.
> +/* Enable the RNG hardware and activate the VF */
> +static int cavium_rng_probe(struct pci_dev *pdev,
> + const struct pci_device_id *id)
> +{
> + struct cavium_rng_pf *rng;
> + int iov_err;
> +
> +
Same problem
> + rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
> + if (!rng)
> + return -ENOMEM;
> +
> + /*Map the RNG control */
> + rng->control_status = pcim_iomap(pdev, 0, 0);
> + if (!rng->control_status) {
> + dev_err(&pdev->dev,
> + "Error iomap failed retrieving control_status.\n");
> + return -ENOMEM;
> + }
> +
> + /* Enable the RNG hardware and entropy source */
> + writeq(THUNDERX_RNM_RNG_EN | THUNDERX_RNM_ENT_EN,
> + rng->control_status);
> +
> + pci_set_drvdata(pdev, rng);
> +
> + /* Fix for improper link id reported for cn88XX */
> + if (pdev->subsystem_device == 0xa118)
> + pci_sriov_fdl_override(pdev, pdev->devfn);
> +
> + /* Enable the Cavium RNG as a VF */
> + iov_err = pci_enable_sriov(pdev, 1);
> + if (iov_err != 0) {
> + dev_err(&pdev->dev,
> + "Error initializing RNG virtual function,(%i).\n",
> + iov_err);
> + return iov_err;
You return without disabling the RNG
> + }
> +
> + return 0;
> +}
> +
> +/* Disable VF and RNG Hardware */
> +void cavium_rng_remove(struct pci_dev *pdev)
> +{
> + struct cavium_rng_pf *rng;
> +
> + rng = pci_get_drvdata(pdev);
> +
> + /* Remove the VF */
> + pci_disable_sriov(pdev);
> +
> + /* Disable the RNG hardware and entropy source */
> + writeq(0, rng->control_status);
> +}
> +
> +static const struct pci_device_id cavium_rng_pf_id_table[] = {
> + { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xa018), 0, 0, 0}, /* Thunder RNM */
> + {0,},
> +};
> +
> +MODULE_DEVICE_TABLE(pci, cavium_rng_pf_id_table);
> +
> +static struct pci_driver cavium_rng_pf_driver = {
> + .name = "cavium_rng_pf",
> + .id_table = cavium_rng_pf_id_table,
> + .probe = cavium_rng_probe,
> + .remove = cavium_rng_remove,
> +};
> +
> +module_pci_driver(cavium_rng_pf_driver);
> +MODULE_AUTHOR("Omer Khaliq");
> +MODULE_LICENSE("GPL");
>
Regards
^ permalink raw reply
* [PATCH 2/2] hwrng: thunderx: Add Cavium HWRNG driver for ThunderX SoC.
From: Omer Khaliq @ 2016-08-19 22:32 UTC (permalink / raw)
To: linux-kernel, linux-pci, linux-crypto, linux-arm-kernel, bhelgaas,
mpm, herbert, Ananth.Jasty, david.daney
Cc: Omer Khaliq
In-Reply-To: <1471645933-3643-1-git-send-email-okhaliq@caviumnetworks.com>
The Cavium ThunderX SoC has a hardware random number generator.
This driver provides support using the HWRNG framework.
Signed-off-by: Omer Khaliq <okhaliq@caviumnetworks.com>
Signed-off-by: Ananth Jasty <Ananth.Jasty@cavium.com>
Acked-by: David Daney <david.daney@cavium.com>
---
drivers/char/hw_random/Kconfig | 13 +++++
drivers/char/hw_random/Makefile | 1 +
drivers/char/hw_random/cavium-rng-vf.c | 102 ++++++++++++++++++++++++++++++++
drivers/char/hw_random/cavium-rng.c | 103 +++++++++++++++++++++++++++++++++
4 files changed, 219 insertions(+)
create mode 100644 drivers/char/hw_random/cavium-rng-vf.c
create mode 100644 drivers/char/hw_random/cavium-rng.c
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 56ad5a5..fb9c7ad 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -410,6 +410,19 @@ config HW_RANDOM_MESON
If unsure, say Y.
+config HW_RANDOM_CAVIUM
+ tristate "Cavium ThunderX Random Number Generator support"
+ depends on HW_RANDOM && PCI && (ARM64 || (COMPILE_TEST && 64BIT))
+ default HW_RANDOM
+ ---help---
+ This driver provides kernel-side support for the Random Number
+ Generator hardware found on Cavium SoCs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cavium_rng.
+
+ If unsure, say Y.
+
endif # HW_RANDOM
config UML_RANDOM
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index 04bb0b0..5f52b1e 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -35,3 +35,4 @@ obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o
obj-$(CONFIG_HW_RANDOM_STM32) += stm32-rng.o
obj-$(CONFIG_HW_RANDOM_PIC32) += pic32-rng.o
obj-$(CONFIG_HW_RANDOM_MESON) += meson-rng.o
+obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o
diff --git a/drivers/char/hw_random/cavium-rng-vf.c b/drivers/char/hw_random/cavium-rng-vf.c
new file mode 100644
index 0000000..8e80bce
--- /dev/null
+++ b/drivers/char/hw_random/cavium-rng-vf.c
@@ -0,0 +1,102 @@
+/*
+ * Hardware Random Number Generator support for Cavium, Inc.
+ * Thunder processor family.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2016 Cavium, Inc.
+ */
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/hw_random.h>
+#include <linux/io.h>
+#include <linux/pci_ids.h>
+#include <linux/gfp.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+struct cavium_rng {
+ struct hwrng ops;
+ void __iomem *result;
+};
+
+/* Read data from the RNG unit */
+static int cavium_rng_read(struct hwrng *rng, void *dat, size_t max, bool wait)
+{
+ struct cavium_rng *p = container_of(rng, struct cavium_rng, ops);
+ unsigned int size = max;
+
+ while (size >= 8) {
+ *((u64 *)dat) = readq(p->result);
+ size -= 8;
+ dat += 8;
+ }
+ while (size > 0) {
+ *((u8 *)dat) = readb(p->result);
+ size--;
+ dat++;
+ }
+ return max;
+}
+
+/* Map Cavium RNG to an HWRNG object */
+static int cavium_rng_probe_vf(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ struct cavium_rng *rng;
+ int ret;
+
+ rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
+ if (!rng)
+ return -ENOMEM;
+
+ /* Map the RNG result */
+ rng->result = pcim_iomap(pdev, 0, 0);
+ if (!rng->result) {
+ dev_err(&pdev->dev, "Error iomap failed retrieving result.\n");
+ return -ENOMEM;
+ }
+
+ rng->ops.name = "cavium rng";
+ rng->ops.read = cavium_rng_read;
+ rng->ops.quality = 1000;
+
+ pci_set_drvdata(pdev, rng);
+
+ ret = hwrng_register(&rng->ops);
+ if (ret) {
+ dev_err(&pdev->dev, "Error registering device as HWRNG.\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+/* Remove the VF */
+void cavium_rng_remove_vf(struct pci_dev *pdev)
+{
+ struct cavium_rng *rng;
+
+ rng = pci_get_drvdata(pdev);
+ hwrng_unregister(&rng->ops);
+}
+
+static const struct pci_device_id cavium_rng_vf_id_table[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xa033), 0, 0, 0},
+ {0,},
+};
+MODULE_DEVICE_TABLE(pci, cavium_rng_vf_id_table);
+
+static struct pci_driver cavium_rng_vf_driver = {
+ .name = "cavium_rng_vf",
+ .id_table = cavium_rng_vf_id_table,
+ .probe = cavium_rng_probe_vf,
+ .remove = cavium_rng_remove_vf,
+};
+module_pci_driver(cavium_rng_vf_driver);
+
+MODULE_AUTHOR("Omer Khaliq");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/cavium-rng.c b/drivers/char/hw_random/cavium-rng.c
new file mode 100644
index 0000000..7f09ee4
--- /dev/null
+++ b/drivers/char/hw_random/cavium-rng.c
@@ -0,0 +1,103 @@
+/*
+ * Hardware Random Number Generator support for Cavium Inc.
+ * Thunder processor family.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2016 Cavium, Inc.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/hw_random.h>
+#include <linux/io.h>
+#include <linux/pci_ids.h>
+#include <linux/gfp.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/pci-ats.h>
+
+#define THUNDERX_RNM_ENT_EN 0x1
+#define THUNDERX_RNM_RNG_EN 0x2
+
+struct cavium_rng_pf {
+ void __iomem *control_status;
+};
+
+
+/* Enable the RNG hardware and activate the VF */
+static int cavium_rng_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ struct cavium_rng_pf *rng;
+ int iov_err;
+
+
+ rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
+ if (!rng)
+ return -ENOMEM;
+
+ /*Map the RNG control */
+ rng->control_status = pcim_iomap(pdev, 0, 0);
+ if (!rng->control_status) {
+ dev_err(&pdev->dev,
+ "Error iomap failed retrieving control_status.\n");
+ return -ENOMEM;
+ }
+
+ /* Enable the RNG hardware and entropy source */
+ writeq(THUNDERX_RNM_RNG_EN | THUNDERX_RNM_ENT_EN,
+ rng->control_status);
+
+ pci_set_drvdata(pdev, rng);
+
+ /* Fix for improper link id reported for cn88XX */
+ if (pdev->subsystem_device == 0xa118)
+ pci_sriov_fdl_override(pdev, pdev->devfn);
+
+ /* Enable the Cavium RNG as a VF */
+ iov_err = pci_enable_sriov(pdev, 1);
+ if (iov_err != 0) {
+ dev_err(&pdev->dev,
+ "Error initializing RNG virtual function,(%i).\n",
+ iov_err);
+ return iov_err;
+ }
+
+ return 0;
+}
+
+/* Disable VF and RNG Hardware */
+void cavium_rng_remove(struct pci_dev *pdev)
+{
+ struct cavium_rng_pf *rng;
+
+ rng = pci_get_drvdata(pdev);
+
+ /* Remove the VF */
+ pci_disable_sriov(pdev);
+
+ /* Disable the RNG hardware and entropy source */
+ writeq(0, rng->control_status);
+}
+
+static const struct pci_device_id cavium_rng_pf_id_table[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xa018), 0, 0, 0}, /* Thunder RNM */
+ {0,},
+};
+
+MODULE_DEVICE_TABLE(pci, cavium_rng_pf_id_table);
+
+static struct pci_driver cavium_rng_pf_driver = {
+ .name = "cavium_rng_pf",
+ .id_table = cavium_rng_pf_id_table,
+ .probe = cavium_rng_probe,
+ .remove = cavium_rng_remove,
+};
+
+module_pci_driver(cavium_rng_pf_driver);
+MODULE_AUTHOR("Omer Khaliq");
+MODULE_LICENSE("GPL");
--
1.9.1
^ permalink raw reply related
* [PATCH 1/2] PCI/IOV: Add function to allow Function Dependency Link override.
From: Omer Khaliq @ 2016-08-19 22:32 UTC (permalink / raw)
To: linux-kernel, linux-pci, linux-crypto, linux-arm-kernel, bhelgaas,
mpm, herbert, Ananth.Jasty, david.daney
Cc: Omer Khaliq
In-Reply-To: <1471645933-3643-1-git-send-email-okhaliq@caviumnetworks.com>
From: David Daney <david.daney@cavium.com>
Some hardware presents an incorrect SR-IOV Function Dependency Link,
add a function to allow this to be overridden in the PF driver for
such devices.
Signed-off-by: David Daney <david.daney@cavium.com>
Signed-off-by: Omer Khaliq <okhaliq@caviumnetworks.com>
---
drivers/pci/iov.c | 14 ++++++++++++++
include/linux/pci.h | 1 +
2 files changed, 15 insertions(+)
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 2194b44..81f0672 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -640,6 +640,20 @@ int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn)
EXPORT_SYMBOL_GPL(pci_enable_sriov);
/**
+ * pci_sriov_fdl_override - fix incorrect Function Dependency Link
+ * @dev: the PCI device
+ * @fdl: the corrected Function Dependency Link value
+ *
+ * For hardware presenting an incorrect Function Dependency Link in
+ * the SR-IOV Extended Capability, allow a driver to override it.
+ */
+void pci_sriov_fdl_override(struct pci_dev *dev, u8 fdl)
+{
+ dev->sriov->link = fdl;
+}
+EXPORT_SYMBOL_GPL(pci_sriov_fdl_override);
+
+/**
* pci_disable_sriov - disable the SR-IOV capability
* @dev: the PCI device
*/
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 2599a98..da8a5b3 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1823,6 +1823,7 @@ int pci_num_vf(struct pci_dev *dev);
int pci_vfs_assigned(struct pci_dev *dev);
int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs);
int pci_sriov_get_totalvfs(struct pci_dev *dev);
+void pci_sriov_fdl_override(struct pci_dev *dev, u8 fdl);
resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno);
#else
static inline int pci_iov_virtfn_bus(struct pci_dev *dev, int id)
--
1.9.1
^ permalink raw reply related
* [PATCH 0/2] hwrng/PCI/IOV: Add driver for Cavium Thunder RNG
From: Omer Khaliq @ 2016-08-19 22:32 UTC (permalink / raw)
To: linux-kernel, linux-pci, linux-crypto, linux-arm-kernel, bhelgaas,
mpm, herbert, Ananth.Jasty, david.daney
Cc: Omer Khaliq
There is a hardware error rendering the FDL field incorrect for the some Thunder RNG devices. The first patch adds infrastructure to fix the problem.
The second patch adds the driver.
David Daney (1):
PCI/IOV: Add function to allow Function Dependency Link override.
Omer Khaliq (1):
hwrng: thunderx: Add Cavium HWRNG driver for ThunderX SoC.
drivers/char/hw_random/Kconfig | 13 +++++
drivers/char/hw_random/Makefile | 1 +
drivers/char/hw_random/cavium-rng-vf.c | 102 ++++++++++++++++++++++++++++++++
drivers/char/hw_random/cavium-rng.c | 103 +++++++++++++++++++++++++++++++++
drivers/pci/iov.c | 14 +++++
include/linux/pci.h | 1 +
6 files changed, 234 insertions(+)
create mode 100644 drivers/char/hw_random/cavium-rng-vf.c
create mode 100644 drivers/char/hw_random/cavium-rng.c
--
1.9.1
^ permalink raw reply
* Git bisected regression for ipsec/aead
From: Sowmini Varadhan @ 2016-08-19 19:21 UTC (permalink / raw)
To: herbert, linux-crypto; +Cc: joshua.a.hay, steffen.klassert
Hi Herbert,
In the process of testing ipsec I ran into panics (details below)
with the algorithm
"aead rfc4106(gcm(aes)) 0x1234567890123456789012345678901234567890 64"
git-bisect analyzed this down to
7271b33cb87e80f3a416fb031ad3ca87f0bea80a is the first bad commit
commit 7271b33cb87e80f3a416fb031ad3ca87f0bea80a
Author: Herbert Xu <herbert@gondor.apana.org.au>
Date: Tue Jun 21 16:55:16 2016 +0800
crypto: ghash-clmulni - Fix cryptd reordering
:
Could you please take a look? here are additional details:
To reproduce the panic, I set up ipsec as follows, on 2 test machines
# #set up laddr to be local interface address, faddr as peer's addres.
# ip x p add dir out src $laddr dst $faddr proto tcp \
tmpl proto esp src $laddr dst $faddr spi 0x00000001 \
mode transport reqid 1
# ip x p add dir in src $laddr dst $faddr proto tcp \
tmpl proto esp dst $laddr src $faddr spi 0x00000001 \
mode transport reqid 1
# ip x s add proto esp src $laddr dst $faddr spi 0x00000001 \
mode transport reqid 1 replay-window 32 \
aead 'rfc4106(gcm(aes))' 0x1234567890123456789012345678901234567890 64 \
sel src $laddr dst $faddr proto tcp
# ip x s add proto esp dst $laddr src $faddr spi 0x00000001 \
mode transport reqid 1 replay-window 32 \
aead 'rfc4106(gcm(aes))' 0x1234567890123456789012345678901234567890 64 \
sel src $laddr dst $faddr proto tcp
Then run iperf i.e., start "iperf -s" on one node (server), and
"iperf -c $faddr -P 1" on the on the other (client). The client will
panic with something like this in the dmesg:
[ 124.627594] BUG: unable to handle kernel paging request at 00000001000000c5
[ 124.627612] ------------[ cut here ]------------
[ 124.627620] WARNING: CPU: 3 PID: 0 at lib/list_debug.c:62 __list_del_entry+0x
86/0xd0
[ 124.627621] list_del corruption. next->prev should be ffff88085cebd168, but w
as 00000000ffffff8d
[ 124.627622] Modules linked in:
:
:
[ 124.627650] CPU: 3 PID: 0 Comm: swapper/3 Tainted: G E 4.7.0-rc1-ipsec-offload-api2+ #15
[ 124.627651] Hardware name: Intel Corporation S2600WTT/S2600WTT, BIOS GRNDSDP1.86B.0046.R00.1502111331 02/11/2015
[ 124.627666] [<ffffffff812df929>] dump_stack+0x51/0x78
[ 124.627667] [<ffffffff812fd1c6>] ? __list_del_entry+0x86/0xd0
[ 124.627673] [<ffffffff8106711d>] __warn+0xfd/0x120
[ 124.627676] [<ffffffff810671f9>] warn_slowpath_fmt+0x49/0x50
[ 124.627677] [<ffffffff812fd1c6>] __list_del_entry+0x86/0xd0
[ 124.627683] [<ffffffff8109906b>] detach_tasks+0x1ab/0x280
[ 124.627685] [<ffffffff8109d58b>] load_balance+0x32b/0x860
[ 124.627691] [<ffffffff810cf219>] ? enqueue_hrtimer+0x49/0xa0
[ 124.627693] [<ffffffff810cddbc>] ? run_timer_softirq+0x4c/0x300
[ 124.627695] [<ffffffff8109e064>] rebalance_domains+0x144/0x290
[ 124.627696] [<ffffffff8109e3e9>] run_rebalance_domains+0x49/0x60
[ 124.627701] [<ffffffff816234bb>] __do_softirq+0xeb/0x2d8
[ 124.627703] [<ffffffff810cfa38>] ? hrtimer_interrupt+0xb8/0x170
[ 124.627706] [<ffffffff8106c755>] irq_exit+0xa5/0xb0
[ 124.627708] [<ffffffff816232b6>] smp_apic_timer_interrupt+0x46/0x60
[ 124.627709] [<ffffffff8162198f>] apic_timer_interrupt+0x7f/0x90
[ 124.627709] <EOI>
[ 124.627716] [<ffffffff814fe369>] ? cpuidle_enter_state+0xc9/0x2d0
[ 124.627718] [<ffffffff814fe35b>] ? cpuidle_enter_state+0xbb/0x2d0
[ 124.627719] [<ffffffff814ff833>] ? menu_select+0x103/0x3a0
[ 124.627721] [<ffffffff814fe587>] cpuidle_enter+0x17/0x20
[ 124.627723] [<ffffffff810a600e>] call_cpuidle+0x2e/0x40
[ 124.627724] [<ffffffff810a6088>] cpuidle_idle_call+0x68/0x100
[ 124.627725] [<ffffffff810a6275>] cpu_idle_loop+0x155/0x240
[ 124.627726] [<ffffffff810a6381>] cpu_startup_entry+0x21/0x30
[ 124.627732] [<ffffffff810441c3>] start_secondary+0x73/0x80
[ 124.627733] ---[ end trace d9352c1808e65391 ]---
[ 124.640240] paging request
[ 124.640557] at 00000001000000c5
:
[ 124.640809] IP: [<ffffffff810975a6>] account_system_time+0x66/0x130
[ 124.641146] PGD 85a8c3067 PUD 0
[ 124.641533] Thread overran stack, or stack corrupted
[ 124.641795] Oops: 0000 [#1] SMP
[ 124.642049] Modules linked in: seqiv esp4 xfrm4_mode_transport sha256_generic drbg ansi_cprng ctr ghash_generic gf128mul ghash_clmulni_intel cryptd gcm autofs4 8021q garp stp llc sunrpc cpufreq_ondemand ipv6 iTCO_wdt iTCO_vendor_support pcspkr i40e i2c_i801 i2c_core sg lpc_ich mfd_core xhci_pci xhci_hcd ixgbe dca hwmon mdio hed wmi ipmi_si ipmi_msghandler acpi_cpufreq acpi_pad ext4(E) mbcache(E) jbd2(E) sd_mod(E) sr_mod(E) cdrom(E) ahci(E) libahci(E) dm_mirror(E) dm_region_hash(E) dm_log(E) dm_mod(E)
[ 124.647568] Hardware name: Intel Corporation S2600WTT/S2600WTT, BIOS GRNDSDP1
.86B.0046.R00.1502111331 02/11/2015
[ 124.648027] task: ffff88085f344100 ti: ffff88085f348000 task.ti: ffff880855cb
b2e0
[ 124.648293] RIP: 0010:[<ffffffff810975a6>] [<ffffffff810975a6>] account_system_time+0x66/0x130
[ 124.648814] RSP: 0018:ffff88087ec03d68 EFLAGS: 00010086
[ 124.649075] RAX: 0000000000010000 RBX: ffff88085f344100 RCX: 00000000ffffff8d
[ 124.649342] RDX: 0000000000000001 RSI: 0000000000000002 RDI: 0000000000000000
[ 124.649609] RBP: ffff88087ec03d88 R08: 0000000000010000 R09: ffff880855cbb2a8
[ 124.649877] R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000000
[ 124.650143] R13: ffff88085f32edd8 R14: ffff88087ec0fc80 R15: 0000001cdb6654dd
[ 124.650409] FS: 0000000000000000(0000) GS:ffff88087ec00000(0000) knlGS:0000000000000000
[ 124.650676] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 124.650939] CR2: 00000001000000c5 CR3: 00000008564c3000 CR4: 00000000001406f0
[ 124.651204] Stack:
[ 124.651452] 0000000000000000 ffff88087ec03d70 ffff88087ec03d70 ffff88085f344100
[ 124.651983] ffff88087ec03da8 ffffffff81097730 ffff88087ec03dc8 ffff88087ec03e48
[ 124.653046] Call Trace:
[ 124.653296] <IRQ>
[ 124.653368] [<ffffffff81097730>] account_process_tick+0x40/0xa0
[ 124.653878] [<ffffffff810cc84c>] update_process_times+0x2c/0x70
[ 124.654143] [<ffffffff810de2d7>] tick_sched_handle+0x37/0x70
[ 124.654405] [<ffffffff810ded52>] tick_sched_timer+0x52/0xa0
[ 124.654666] [<ffffffff810cf685>] __run_hrtimer+0x85/0x210
[ 124.654926] [<ffffffff810ded00>] ? tick_nohz_handler+0xc0/0xc0
[ 124.655193] [<ffffffff810bbff8>] ? handle_irq_event_percpu+0xb8/0x1f0
[ 124.655459] [<ffffffff810cf877>] __hrtimer_run_queues+0x67/0x90
[ 124.655724] [<ffffffff810cfa1b>] hrtimer_interrupt+0x9b/0x170
[ 124.655987] [<ffffffff810451e9>] local_apic_timer_interrupt+0x39/0x60
[ 124.656252] [<ffffffff816232b1>] smp_apic_timer_interrupt+0x41/0x60
[ 124.656516] [<ffffffff8162198f>] apic_timer_interrupt+0x7f/0x90
[ 124.656777] <EOI>
:
^ permalink raw reply
* [PATCH v5] KEYS: add SP800-56A KDF support for DH
From: Stephan Mueller @ 2016-08-19 18:39 UTC (permalink / raw)
To: herbert, mathew.j.martineau, dhowells; +Cc: linux-crypto, keyrings
Hi,
This patch now folds the KDF into the keys support as requested by
Herbert. The caller can only supply the hash name used for the KDF.
Note, the KDF implementation is identical to the kdf_ctr() support in
the now unneeded KDF patches to the kernel crypto API.
The new patch also changes the variable name from kdfname to hashname.
Also, the patch adds a missing semicolon.
Finally, the patch adds a guard against compiling the compat code
if the general Linux kernel configuration does not have the compat
code enabled. Without that guard, compilation warnings are seen.
---8<---
SP800-56A defines the use of DH with key derivation function based on a
counter. The input to the KDF is defined as (DH shared secret || other
information). The value for the "other information" is to be provided by
the caller.
The KDF is implemented using the hash support from the kernel crypto API.
The implementation uses the symmetric hash support as the input to the
hash operation is usually very small. The caller is allowed to specify
the hash name that he wants to use to derive the key material allowing
the use of all supported hashes provided with the kernel crypto API.
As the KDF implements the proper truncation of the DH shared secret to
the requested size, this patch fills the caller buffer up to its size.
The patch is tested with a new test added to the keyutils user space
code which uses a CAVS test vector testing the compliance with
SP800-56A.
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
Documentation/security/keys.txt | 34 ++++--
include/linux/compat.h | 7 ++
include/uapi/linux/keyctl.h | 7 ++
security/keys/Kconfig | 1 +
security/keys/Makefile | 3 +-
security/keys/compat.c | 5 +-
security/keys/compat_dh.c | 38 +++++++
security/keys/dh.c | 222 +++++++++++++++++++++++++++++++++++++---
security/keys/internal.h | 24 ++++-
security/keys/keyctl.c | 2 +-
10 files changed, 317 insertions(+), 26 deletions(-)
create mode 100644 security/keys/compat_dh.c
diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt
index 3849814..58fcae7 100644
--- a/Documentation/security/keys.txt
+++ b/Documentation/security/keys.txt
@@ -827,7 +827,7 @@ The keyctl syscall functions are:
long keyctl(KEYCTL_DH_COMPUTE, struct keyctl_dh_params *params,
char *buffer, size_t buflen,
- void *reserved);
+ struct keyctl_kdf_params *kdf);
The params struct contains serial numbers for three keys:
@@ -844,18 +844,36 @@ The keyctl syscall functions are:
public key. If the base is the remote public key, the result is
the shared secret.
- The reserved argument must be set to NULL.
+ If the parameter kdf is NULL, the following applies:
- The buffer length must be at least the length of the prime, or zero.
+ - The buffer length must be at least the length of the prime, or zero.
- If the buffer length is nonzero, the length of the result is
- returned when it is successfully calculated and copied in to the
- buffer. When the buffer length is zero, the minimum required
- buffer length is returned.
+ - If the buffer length is nonzero, the length of the result is
+ returned when it is successfully calculated and copied in to the
+ buffer. When the buffer length is zero, the minimum required
+ buffer length is returned.
+
+ The kdf parameter allows the caller to apply a key derivation function
+ (KDF) on the Diffie-Hellman computation where only the result
+ of the KDF is returned to the caller. The KDF is characterized with
+ struct keyctl_kdf_params as follows:
+
+ - char *hashname specifies the NUL terminated string identifying
+ the hash used from the kernel crypto API and applied for the KDF
+ operation. The KDF implemenation complies with SP800-56A as well
+ as with SP800-108 (the counter KDF).
+
+ - char *otherinfo specifies the OtherInfo data as documented in
+ SP800-56A section 5.8.1.2. The length of the buffer is given with
+ otherinfolen. The format of OtherInfo is defined by the caller.
+ The otherinfo pointer may be NULL if no OtherInfo shall be used.
This function will return error EOPNOTSUPP if the key type is not
supported, error ENOKEY if the key could not be found, or error
- EACCES if the key is not readable by the caller.
+ EACCES if the key is not readable by the caller. In addition, the
+ function will return EMSGSIZE when the parameter kdf is non-NULL
+ and either the buffer length or the OtherInfo length exceeds the
+ allowed length.
===============
KERNEL SERVICES
diff --git a/include/linux/compat.h b/include/linux/compat.h
index f964ef7..f6979d5 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -295,6 +295,13 @@ struct compat_old_sigaction {
};
#endif
+struct compat_keyctl_kdf_params {
+ compat_uptr_t hashname;
+ compat_uptr_t otherinfo;
+ __u32 otherinfolen;
+ __u32 __spare[8];
+};
+
struct compat_statfs;
struct compat_statfs64;
struct compat_old_linux_dirent;
diff --git a/include/uapi/linux/keyctl.h b/include/uapi/linux/keyctl.h
index 86eddd6..2102822 100644
--- a/include/uapi/linux/keyctl.h
+++ b/include/uapi/linux/keyctl.h
@@ -68,4 +68,11 @@ struct keyctl_dh_params {
__s32 base;
};
+struct keyctl_kdf_params {
+ char *hashname;
+ char *otherinfo;
+ __u32 otherinfolen;
+ __u32 __spare[8];
+};
+
#endif /* _LINUX_KEYCTL_H */
diff --git a/security/keys/Kconfig b/security/keys/Kconfig
index f826e87..00723a8 100644
--- a/security/keys/Kconfig
+++ b/security/keys/Kconfig
@@ -90,6 +90,7 @@ config KEY_DH_OPERATIONS
bool "Diffie-Hellman operations on retained keys"
depends on KEYS
select MPILIB
+ select CRYPTO_HASH
help
This option provides support for calculating Diffie-Hellman
public keys and shared secrets using values stored as keys
diff --git a/security/keys/Makefile b/security/keys/Makefile
index 1fd4a16..57dff0c 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -15,7 +15,8 @@ obj-y := \
request_key.o \
request_key_auth.o \
user_defined.o
-obj-$(CONFIG_KEYS_COMPAT) += compat.o
+compat-obj-$(CONFIG_KEY_DH_OPERATIONS) += compat_dh.o
+obj-$(CONFIG_KEYS_COMPAT) += compat.o $(compat-obj-y)
obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_SYSCTL) += sysctl.o
obj-$(CONFIG_PERSISTENT_KEYRINGS) += persistent.o
diff --git a/security/keys/compat.c b/security/keys/compat.c
index 36c80bf..b674886 100644
--- a/security/keys/compat.c
+++ b/security/keys/compat.c
@@ -133,8 +133,9 @@ COMPAT_SYSCALL_DEFINE5(keyctl, u32, option,
return keyctl_get_persistent(arg2, arg3);
case KEYCTL_DH_COMPUTE:
- return keyctl_dh_compute(compat_ptr(arg2), compat_ptr(arg3),
- arg4, compat_ptr(arg5));
+ return compat_keyctl_dh_compute(compat_ptr(arg2),
+ compat_ptr(arg3),
+ arg4, compat_ptr(arg5));
default:
return -EOPNOTSUPP;
diff --git a/security/keys/compat_dh.c b/security/keys/compat_dh.c
new file mode 100644
index 0000000..a6a659b
--- /dev/null
+++ b/security/keys/compat_dh.c
@@ -0,0 +1,38 @@
+/* 32-bit compatibility syscall for 64-bit systems for DH operations
+ *
+ * Copyright (C) 2016 Stephan Mueller <smueller@chronox.de>
+ *
+ * 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/uaccess.h>
+
+#include "internal.h"
+
+/*
+ * Perform the DH computation or DH based key derivation.
+ *
+ * If successful, 0 will be returned.
+ */
+long compat_keyctl_dh_compute(struct keyctl_dh_params __user *params,
+ char __user *buffer, size_t buflen,
+ struct compat_keyctl_kdf_params __user *kdf)
+{
+ struct keyctl_kdf_params kdfcopy;
+ struct compat_keyctl_kdf_params compat_kdfcopy;
+
+ if (!kdf)
+ return __keyctl_dh_compute(params, buffer, buflen, NULL);
+
+ if (copy_from_user(&compat_kdfcopy, kdf, sizeof(compat_kdfcopy)) != 0)
+ return -EFAULT;
+
+ kdfcopy.hashname = compat_ptr(compat_kdfcopy.hashname);
+ kdfcopy.otherinfo = compat_ptr(compat_kdfcopy.otherinfo);
+ kdfcopy.otherinfolen = compat_kdfcopy.otherinfolen;
+
+ return __keyctl_dh_compute(params, buffer, buflen, &kdfcopy);
+}
diff --git a/security/keys/dh.c b/security/keys/dh.c
index 531ed2e..51ca787 100644
--- a/security/keys/dh.c
+++ b/security/keys/dh.c
@@ -12,6 +12,10 @@
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <keys/user-type.h>
+
+#include <linux/crypto.h>
+#include <crypto/hash.h>
+
#include "internal.h"
/*
@@ -77,9 +81,146 @@ error:
return ret;
}
-long keyctl_dh_compute(struct keyctl_dh_params __user *params,
- char __user *buffer, size_t buflen,
- void __user *reserved)
+struct kdf_sdesc {
+ struct shash_desc shash;
+ char ctx[];
+};
+
+static int kdf_alloc(struct kdf_sdesc **sdesc_ret, char *hashname)
+{
+ struct crypto_shash *tfm;
+ struct kdf_sdesc *sdesc;
+ int size;
+
+ /* allocate synchronous hash */
+ tfm = crypto_alloc_shash(hashname, 0, 0);
+ if (IS_ERR(tfm)) {
+ pr_info("could not allocate digest TFM handle %s\n", hashname);
+ return PTR_ERR(tfm);
+ }
+
+ size = sizeof(struct shash_desc) + crypto_shash_descsize(tfm);
+ sdesc = kmalloc(size, GFP_KERNEL);
+ if (!sdesc)
+ return -ENOMEM;
+ sdesc->shash.tfm = tfm;
+ sdesc->shash.flags = 0x0;
+
+ *sdesc_ret = sdesc;
+
+ return 0;
+}
+
+static void kdf_dealloc(struct kdf_sdesc *sdesc)
+{
+ if (!sdesc)
+ return;
+
+ if (sdesc->shash.tfm)
+ crypto_free_shash(sdesc->shash.tfm);
+
+ kzfree(sdesc);
+}
+
+/* convert 32 bit integer into its string representation */
+static inline void crypto_kw_cpu_to_be32(u32 val, u8 *buf)
+{
+ __be32 *a = (__be32 *)buf;
+
+ *a = cpu_to_be32(val);
+}
+
+/*
+ * Implementation of the KDF in counter mode according to SP800-108 section 5.1
+ * as well as SP800-56A section 5.8.1 (Single-step KDF).
+ *
+ * SP800-56A:
+ * The src pointer is defined as Z || other info where Z is the shared secret
+ * from DH and other info is an arbitrary string (see SP800-56A section
+ * 5.8.1.2).
+ */
+static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int dlen)
+{
+ struct shash_desc *desc = &sdesc->shash;
+ unsigned int h = crypto_shash_digestsize(desc->tfm);
+ int err = 0;
+ u8 *dst_orig = dst;
+ u32 i = 1;
+ u8 iteration[sizeof(u32)];
+
+ while (dlen) {
+ err = crypto_shash_init(desc);
+ if (err)
+ goto err;
+
+ crypto_kw_cpu_to_be32(i, iteration);
+ err = crypto_shash_update(desc, iteration, sizeof(u32));
+ if (err)
+ goto err;
+
+ if (src && slen) {
+ err = crypto_shash_update(desc, src, slen);
+ if (err)
+ goto err;
+ }
+
+ if (dlen < h) {
+ u8 tmpbuffer[h];
+
+ err = crypto_shash_final(desc, tmpbuffer);
+ if (err)
+ goto err;
+ memcpy(dst, tmpbuffer, dlen);
+ memzero_explicit(tmpbuffer, h);
+ return 0;
+ } else {
+ err = crypto_shash_final(desc, dst);
+ if (err)
+ goto err;
+
+ dlen -= h;
+ dst += h;
+ i++;
+ }
+ }
+
+ return 0;
+
+err:
+ memzero_explicit(dst_orig, dlen);
+ return err;
+}
+
+static int keyctl_dh_compute_kdf(struct kdf_sdesc *sdesc,
+ char __user *buffer, size_t buflen,
+ uint8_t *kbuf, size_t kbuflen)
+{
+ uint8_t *outbuf = NULL;
+ int ret;
+
+ outbuf = kmalloc(buflen, GFP_KERNEL);
+ if (!outbuf) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ ret = kdf_ctr(sdesc, kbuf, kbuflen, outbuf, buflen);
+ if (ret)
+ goto err;
+
+ ret = buflen;
+ if (copy_to_user(buffer, outbuf, buflen) != 0)
+ ret = -EFAULT;
+
+err:
+ kzfree(outbuf);
+ return ret;
+}
+
+long __keyctl_dh_compute(struct keyctl_dh_params __user *params,
+ char __user *buffer, size_t buflen,
+ struct keyctl_kdf_params *kdfcopy)
{
long ret;
MPI base, private, prime, result;
@@ -88,6 +229,7 @@ long keyctl_dh_compute(struct keyctl_dh_params __user *params,
uint8_t *kbuf;
ssize_t keylen;
size_t resultlen;
+ struct kdf_sdesc *sdesc = NULL;
if (!params || (!buffer && buflen)) {
ret = -EINVAL;
@@ -98,12 +240,34 @@ long keyctl_dh_compute(struct keyctl_dh_params __user *params,
goto out;
}
- if (reserved) {
- ret = -EINVAL;
- goto out;
+ if (kdfcopy) {
+ char *hashname;
+
+ if (buflen > KEYCTL_KDF_MAX_OUTPUT_LEN ||
+ kdfcopy->otherinfolen > KEYCTL_KDF_MAX_OI_LEN) {
+ ret = -EMSGSIZE;
+ goto out;
+ }
+
+ /* get KDF name string */
+ hashname = strndup_user(kdfcopy->hashname, CRYPTO_MAX_ALG_NAME);
+ if (IS_ERR(hashname)) {
+ ret = PTR_ERR(hashname);
+ goto out;
+ }
+
+ /* allocate KDF from the kernel crypto API */
+ ret = kdf_alloc(&sdesc, hashname);
+ kfree(hashname);
+ if (ret)
+ goto out;
}
- keylen = mpi_from_key(pcopy.prime, buflen, &prime);
+ /*
+ * If the caller requests postprocessing with a KDF, allow an
+ * arbitrary output buffer size since the KDF ensures proper truncation.
+ */
+ keylen = mpi_from_key(pcopy.prime, kdfcopy ? SIZE_MAX : buflen, &prime);
if (keylen < 0 || !prime) {
/* buflen == 0 may be used to query the required buffer size,
* which is the prime key length.
@@ -133,12 +297,25 @@ long keyctl_dh_compute(struct keyctl_dh_params __user *params,
goto error3;
}
- kbuf = kmalloc(resultlen, GFP_KERNEL);
+ /* allocate space for DH shared secret and SP800-56A otherinfo */
+ kbuf = kmalloc(kdfcopy ? (resultlen + kdfcopy->otherinfolen) : resultlen,
+ GFP_KERNEL);
if (!kbuf) {
ret = -ENOMEM;
goto error4;
}
+ /*
+ * Concatenate SP800-56A otherinfo past DH shared secret -- the
+ * input to the KDF is (DH shared secret || otherinfo)
+ */
+ if (kdfcopy && kdfcopy->otherinfo &&
+ copy_from_user(kbuf + resultlen, kdfcopy->otherinfo,
+ kdfcopy->otherinfolen) != 0) {
+ ret = -EFAULT;
+ goto error5;
+ }
+
ret = do_dh(result, base, private, prime);
if (ret)
goto error5;
@@ -147,12 +324,17 @@ long keyctl_dh_compute(struct keyctl_dh_params __user *params,
if (ret != 0)
goto error5;
- ret = nbytes;
- if (copy_to_user(buffer, kbuf, nbytes) != 0)
- ret = -EFAULT;
+ if (kdfcopy) {
+ ret = keyctl_dh_compute_kdf(sdesc, buffer, buflen, kbuf,
+ resultlen + kdfcopy->otherinfolen);
+ } else {
+ ret = nbytes;
+ if (copy_to_user(buffer, kbuf, nbytes) != 0)
+ ret = -EFAULT;
+ }
error5:
- kfree(kbuf);
+ kzfree(kbuf);
error4:
mpi_free(result);
error3:
@@ -162,5 +344,21 @@ error2:
error1:
mpi_free(prime);
out:
+ kdf_dealloc(sdesc);
return ret;
}
+
+long keyctl_dh_compute(struct keyctl_dh_params __user *params,
+ char __user *buffer, size_t buflen,
+ struct keyctl_kdf_params __user *kdf)
+{
+ struct keyctl_kdf_params kdfcopy;
+
+ if (!kdf)
+ return __keyctl_dh_compute(params, buffer, buflen, NULL);
+
+ if (copy_from_user(&kdfcopy, kdf, sizeof(kdfcopy)) != 0)
+ return -EFAULT;
+
+ return __keyctl_dh_compute(params, buffer, buflen, &kdfcopy);
+}
diff --git a/security/keys/internal.h b/security/keys/internal.h
index a705a7d..c0f1adf 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -16,6 +16,7 @@
#include <linux/key-type.h>
#include <linux/task_work.h>
#include <linux/keyctl.h>
+#include <linux/compat.h>
struct iovec;
@@ -260,15 +261,34 @@ static inline long keyctl_get_persistent(uid_t uid, key_serial_t destring)
#ifdef CONFIG_KEY_DH_OPERATIONS
extern long keyctl_dh_compute(struct keyctl_dh_params __user *, char __user *,
- size_t, void __user *);
+ size_t, struct keyctl_kdf_params __user *);
+extern long __keyctl_dh_compute(struct keyctl_dh_params __user *, char __user *,
+ size_t, struct keyctl_kdf_params *);
+#ifdef CONFIG_KEYS_COMPAT
+extern long compat_keyctl_dh_compute(struct keyctl_dh_params __user *params,
+ char __user *buffer, size_t buflen,
+ struct compat_keyctl_kdf_params __user *kdf);
+#endif
+#define KEYCTL_KDF_MAX_OUTPUT_LEN 1024 /* max length of KDF output */
+#define KEYCTL_KDF_MAX_OI_LEN 64 /* max length of otherinfo */
#else
static inline long keyctl_dh_compute(struct keyctl_dh_params __user *params,
char __user *buffer, size_t buflen,
- void __user *reserved)
+ struct keyctl_kdf_params __user *kdf)
+{
+ return -EOPNOTSUPP;
+}
+
+#ifdef CONFIG_KEYS_COMPAT
+static inline long compat_keyctl_dh_compute(
+ struct keyctl_dh_params __user *params,
+ char __user *buffer, size_t buflen,
+ struct keyctl_kdf_params __user *kdf)
{
return -EOPNOTSUPP;
}
#endif
+#endif
/*
* Debugging key validation
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index d580ad0..b106898 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -1689,7 +1689,7 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3,
case KEYCTL_DH_COMPUTE:
return keyctl_dh_compute((struct keyctl_dh_params __user *) arg2,
(char __user *) arg3, (size_t) arg4,
- (void __user *) arg5);
+ (struct keyctl_kdf_params __user *) arg5);
default:
return -EOPNOTSUPP;
--
2.7.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox