Skip to content

Commit

Permalink
crypto: ccp - CCP versioning support
Browse files Browse the repository at this point in the history
Future hardware may introduce new algorithms wherein the
driver will need to manage resources for different versions
of the cryptographic coprocessor. This precursor patch
determines the version of the available device, and marks
and registers algorithms accordingly. A structure is added
which manages the version-specific data.

Signed-off-by: Gary R Hook <[email protected]>
Acked-by: Tom Lendacky <[email protected]>
Signed-off-by: Herbert Xu <[email protected]>
  • Loading branch information
garyrhook authored and herbertx committed Mar 11, 2016
1 parent 553d237 commit c7019c4
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 5 deletions.
12 changes: 11 additions & 1 deletion drivers/crypto/ccp/ccp-crypto-aes.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* AMD Cryptographic Coprocessor (CCP) AES crypto API support
*
* Copyright (C) 2013 Advanced Micro Devices, Inc.
* Copyright (C) 2013,2016 Advanced Micro Devices, Inc.
*
* Author: Tom Lendacky <[email protected]>
*
Expand Down Expand Up @@ -259,6 +259,7 @@ static struct crypto_alg ccp_aes_rfc3686_defaults = {

struct ccp_aes_def {
enum ccp_aes_mode mode;
unsigned int version;
const char *name;
const char *driver_name;
unsigned int blocksize;
Expand All @@ -269,6 +270,7 @@ struct ccp_aes_def {
static struct ccp_aes_def aes_algs[] = {
{
.mode = CCP_AES_MODE_ECB,
.version = CCP_VERSION(3, 0),
.name = "ecb(aes)",
.driver_name = "ecb-aes-ccp",
.blocksize = AES_BLOCK_SIZE,
Expand All @@ -277,6 +279,7 @@ static struct ccp_aes_def aes_algs[] = {
},
{
.mode = CCP_AES_MODE_CBC,
.version = CCP_VERSION(3, 0),
.name = "cbc(aes)",
.driver_name = "cbc-aes-ccp",
.blocksize = AES_BLOCK_SIZE,
Expand All @@ -285,6 +288,7 @@ static struct ccp_aes_def aes_algs[] = {
},
{
.mode = CCP_AES_MODE_CFB,
.version = CCP_VERSION(3, 0),
.name = "cfb(aes)",
.driver_name = "cfb-aes-ccp",
.blocksize = AES_BLOCK_SIZE,
Expand All @@ -293,6 +297,7 @@ static struct ccp_aes_def aes_algs[] = {
},
{
.mode = CCP_AES_MODE_OFB,
.version = CCP_VERSION(3, 0),
.name = "ofb(aes)",
.driver_name = "ofb-aes-ccp",
.blocksize = 1,
Expand All @@ -301,6 +306,7 @@ static struct ccp_aes_def aes_algs[] = {
},
{
.mode = CCP_AES_MODE_CTR,
.version = CCP_VERSION(3, 0),
.name = "ctr(aes)",
.driver_name = "ctr-aes-ccp",
.blocksize = 1,
Expand All @@ -309,6 +315,7 @@ static struct ccp_aes_def aes_algs[] = {
},
{
.mode = CCP_AES_MODE_CTR,
.version = CCP_VERSION(3, 0),
.name = "rfc3686(ctr(aes))",
.driver_name = "rfc3686-ctr-aes-ccp",
.blocksize = 1,
Expand Down Expand Up @@ -357,8 +364,11 @@ static int ccp_register_aes_alg(struct list_head *head,
int ccp_register_aes_algs(struct list_head *head)
{
int i, ret;
unsigned int ccpversion = ccp_version();

for (i = 0; i < ARRAY_SIZE(aes_algs); i++) {
if (aes_algs[i].version > ccpversion)
continue;
ret = ccp_register_aes_alg(head, &aes_algs[i]);
if (ret)
return ret;
Expand Down
9 changes: 8 additions & 1 deletion drivers/crypto/ccp/ccp-crypto-sha.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* AMD Cryptographic Coprocessor (CCP) SHA crypto API support
*
* Copyright (C) 2013 Advanced Micro Devices, Inc.
* Copyright (C) 2013,2016 Advanced Micro Devices, Inc.
*
* Author: Tom Lendacky <[email protected]>
*
Expand Down Expand Up @@ -341,6 +341,7 @@ static void ccp_hmac_sha_cra_exit(struct crypto_tfm *tfm)
}

struct ccp_sha_def {
unsigned int version;
const char *name;
const char *drv_name;
enum ccp_sha_type type;
Expand All @@ -350,20 +351,23 @@ struct ccp_sha_def {

static struct ccp_sha_def sha_algs[] = {
{
.version = CCP_VERSION(3, 0),
.name = "sha1",
.drv_name = "sha1-ccp",
.type = CCP_SHA_TYPE_1,
.digest_size = SHA1_DIGEST_SIZE,
.block_size = SHA1_BLOCK_SIZE,
},
{
.version = CCP_VERSION(3, 0),
.name = "sha224",
.drv_name = "sha224-ccp",
.type = CCP_SHA_TYPE_224,
.digest_size = SHA224_DIGEST_SIZE,
.block_size = SHA224_BLOCK_SIZE,
},
{
.version = CCP_VERSION(3, 0),
.name = "sha256",
.drv_name = "sha256-ccp",
.type = CCP_SHA_TYPE_256,
Expand Down Expand Up @@ -480,8 +484,11 @@ static int ccp_register_sha_alg(struct list_head *head,
int ccp_register_sha_algs(struct list_head *head)
{
int i, ret;
unsigned int ccpversion = ccp_version();

for (i = 0; i < ARRAY_SIZE(sha_algs); i++) {
if (sha_algs[i].version > ccpversion)
continue;
ret = ccp_register_sha_alg(head, &sha_algs[i]);
if (ret)
return ret;
Expand Down
27 changes: 27 additions & 0 deletions drivers/crypto/ccp/ccp-dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,29 @@ int ccp_present(void)
}
EXPORT_SYMBOL_GPL(ccp_present);

/**
* ccp_version - get the version of the CCP device
*
* Returns the version from the first unit on the list;
* otherwise a zero if no CCP device is present
*/
unsigned int ccp_version(void)
{
struct ccp_device *dp;
unsigned long flags;
int ret = 0;

read_lock_irqsave(&ccp_unit_lock, flags);
if (!list_empty(&ccp_units)) {
dp = list_first_entry(&ccp_units, struct ccp_device, entry);
ret = dp->vdata->version;
}
read_unlock_irqrestore(&ccp_unit_lock, flags);

return ret;
}
EXPORT_SYMBOL_GPL(ccp_version);

/**
* ccp_enqueue_cmd - queue an operation for processing by the CCP
*
Expand Down Expand Up @@ -664,6 +687,10 @@ bool ccp_queues_suspended(struct ccp_device *ccp)
}
#endif

struct ccp_vdata ccpv3 = {
.version = CCP_VERSION(3, 0),
};

static int __init ccp_mod_init(void)
{
#ifdef CONFIG_X86
Expand Down
8 changes: 8 additions & 0 deletions drivers/crypto/ccp/ccp-dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@
#define CCP_ECC_RESULT_OFFSET 60
#define CCP_ECC_RESULT_SUCCESS 0x0001

/* Structure to hold CCP version-specific values */
struct ccp_vdata {
unsigned int version;
};

extern struct ccp_vdata ccpv3;

struct ccp_device;
struct ccp_cmd;

Expand Down Expand Up @@ -187,6 +194,7 @@ struct ccp_cmd_queue {
struct ccp_device {
struct list_head entry;

struct ccp_vdata *vdata;
unsigned int ord;
char name[MAX_CCP_NAME_LEN];
char rngname[MAX_CCP_NAME_LEN];
Expand Down
8 changes: 7 additions & 1 deletion drivers/crypto/ccp/ccp-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,12 @@ static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto e_err;

ccp->dev_specific = ccp_pci;
ccp->vdata = (struct ccp_vdata *)id->driver_data;
if (!ccp->vdata || !ccp->vdata->version) {
ret = -ENODEV;
dev_err(dev, "missing driver data\n");
goto e_err;
}
ccp->get_irq = ccp_get_irqs;
ccp->free_irq = ccp_free_irqs;

Expand Down Expand Up @@ -313,7 +319,7 @@ static int ccp_pci_resume(struct pci_dev *pdev)
#endif

static const struct pci_device_id ccp_pci_table[] = {
{ PCI_VDEVICE(AMD, 0x1537), },
{ PCI_VDEVICE(AMD, 0x1537), (kernel_ulong_t)&ccpv3 },
/* Last entry must be zero */
{ 0, }
};
Expand Down
39 changes: 37 additions & 2 deletions drivers/crypto/ccp/ccp-platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,33 @@ struct ccp_platform {
int coherent;
};

static const struct acpi_device_id ccp_acpi_match[];
static const struct of_device_id ccp_of_match[];

static struct ccp_vdata *ccp_get_of_version(struct platform_device *pdev)
{
#ifdef CONFIG_OF
const struct of_device_id *match;

match = of_match_node(ccp_of_match, pdev->dev.of_node);
if (match && match->data)
return (struct ccp_vdata *)match->data;
#endif
return 0;
}

static struct ccp_vdata *ccp_get_acpi_version(struct platform_device *pdev)
{
#ifdef CONFIG_ACPI
const struct acpi_device_id *match;

match = acpi_match_device(ccp_acpi_match, &pdev->dev);
if (match && match->driver_data)
return (struct ccp_vdata *)match->driver_data;
#endif
return 0;
}

static int ccp_get_irq(struct ccp_device *ccp)
{
struct device *dev = ccp->dev;
Expand Down Expand Up @@ -106,6 +133,13 @@ static int ccp_platform_probe(struct platform_device *pdev)
goto e_err;

ccp->dev_specific = ccp_platform;
ccp->vdata = pdev->dev.of_node ? ccp_get_of_version(pdev)
: ccp_get_acpi_version(pdev);
if (!ccp->vdata || !ccp->vdata->version) {
ret = -ENODEV;
dev_err(dev, "missing driver data\n");
goto e_err;
}
ccp->get_irq = ccp_get_irqs;
ccp->free_irq = ccp_free_irqs;

Expand Down Expand Up @@ -214,15 +248,16 @@ static int ccp_platform_resume(struct platform_device *pdev)

#ifdef CONFIG_ACPI
static const struct acpi_device_id ccp_acpi_match[] = {
{ "AMDI0C00", 0 },
{ "AMDI0C00", (kernel_ulong_t)&ccpv3 },
{ },
};
MODULE_DEVICE_TABLE(acpi, ccp_acpi_match);
#endif

#ifdef CONFIG_OF
static const struct of_device_id ccp_of_match[] = {
{ .compatible = "amd,ccp-seattle-v1a" },
{ .compatible = "amd,ccp-seattle-v1a",
.data = (const void *)&ccpv3 },
{ },
};
MODULE_DEVICE_TABLE(of, ccp_of_match);
Expand Down
17 changes: 17 additions & 0 deletions include/linux/ccp.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ struct ccp_cmd;
*/
int ccp_present(void);

#define CCP_VSIZE 16
#define CCP_VMASK ((unsigned int)((1 << CCP_VSIZE) - 1))
#define CCP_VERSION(v, r) ((unsigned int)((v << CCP_VSIZE) \
| (r & CCP_VMASK)))

/**
* ccp_version - get the version of the CCP
*
* Returns a positive version number, or zero if no CCP
*/
unsigned int ccp_version(void);

/**
* ccp_enqueue_cmd - queue an operation for processing by the CCP
*
Expand Down Expand Up @@ -65,6 +77,11 @@ static inline int ccp_present(void)
return -ENODEV;
}

static inline unsigned int ccp_version(void)
{
return 0;
}

static inline int ccp_enqueue_cmd(struct ccp_cmd *cmd)
{
return -ENODEV;
Expand Down

0 comments on commit c7019c4

Please sign in to comment.