crypto: msm: Support SHA384 & SHA512

General Purpose Crypto Engine (GPCE) hardware has added SHA/HMAC
384/512 in v5.4.0 and above. Hence adding support for SHA/HMAC
384/512 in kernel crypto drivers.

Change-Id: I540cab6d627008508d01c1c3df3ca36abf0e70e0
Signed-off-by: Monika Singh <monising@codeaurora.org>
This commit is contained in:
Monika Singh
2019-12-09 15:17:18 +05:30
parent daae246165
commit 4931e54045
7 changed files with 390 additions and 69 deletions

View File

@@ -26,6 +26,10 @@
#define AES_CE_BLOCK_SIZE 16
/* SHA1/256 supports 2 AUTH_BYTECNT REGISTER */
/* SHA384/512 supports 4 AUTH_BYTECNT REGISTER */
#define AUTH_BYTECNT_REG_NUMBER 4
/* key size in bytes */
#define HMAC_KEY_SIZE (SHA1_DIGESTSIZE) /* hmac-sha1 */
#define SHA_HMAC_KEY_SIZE 64
@@ -71,6 +75,10 @@ enum qce_hash_alg_enum {
QCE_HASH_SHA1_HMAC = 2,
QCE_HASH_SHA256_HMAC = 3,
QCE_HASH_AES_CMAC = 4,
QCE_HASH_SHA384 = 5,
QCE_HASH_SHA512 = 6,
QCE_HASH_SHA384_HMAC = 7,
QCE_HASH_SHA512_HMAC = 8,
QCE_HASH_LAST
};

View File

@@ -176,6 +176,22 @@ static uint32_t _std_init_vector_sha256[] = {
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
};
/* Standard initialization vector for SHA-384, source: FIPS 180-2 */
static uint32_t _std_init_vector_sha384[] = {
0xCBBB9D5D, 0xC1059ED8, 0x629A292A, 0x367CD507,
0x9159015A, 0x3070DD17, 0x152FECD8, 0xF70E5939,
0x67332667, 0xFFC00B31, 0x8EB44A87, 0x68581511,
0xDB0C2E0D, 0x64F98FA7, 0x47B5481D, 0xBEFA4FA4
};
/* Standard initialization vector for SHA-512, source: FIPS 180-2 */
static uint32_t _std_init_vector_sha512[] = {
0x6A09E667, 0xF3BCC908, 0xBB67AE85, 0x84CAA73B,
0x3C6EF372, 0xFE94F82B, 0xA54FF53A, 0x5F1D36F1,
0x510E527F, 0xADE682D1, 0x9B05688C, 0x2B3E6C1F,
0x1F83D9AB, 0xFB41BD6B, 0x5BE0CD19, 0x137E2179
};
static void _byte_stream_to_net_words(uint32_t *iv, unsigned char *b,
unsigned int len)
{
@@ -225,6 +241,23 @@ static int count_sg(struct scatterlist *sg, int nbytes)
return i;
}
static uint32_t qce_get_block_size(enum qce_hash_alg_enum alg)
{
switch (alg) {
case QCE_HASH_SHA1:
case QCE_HASH_SHA1_HMAC:
return SHA1_BLOCK_SIZE;
case QCE_HASH_SHA256:
case QCE_HASH_SHA256_HMAC:
return SHA256_BLOCK_SIZE;
case QCE_HASH_SHA384:
case QCE_HASH_SHA384_HMAC:
return SHA384_BLOCK_SIZE;
default:
return SHA512_BLOCK_SIZE;
}
}
static int qce_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction direction)
{
@@ -323,10 +356,18 @@ static struct qce_cmdlist_info *_ce_get_hash_cmdlistinfo(
return &cmdlistptr->auth_sha1;
case QCE_HASH_SHA256:
return &cmdlistptr->auth_sha256;
case QCE_HASH_SHA384:
return &cmdlistptr->auth_sha384;
case QCE_HASH_SHA512:
return &cmdlistptr->auth_sha512;
case QCE_HASH_SHA1_HMAC:
return &cmdlistptr->auth_sha1_hmac;
case QCE_HASH_SHA256_HMAC:
return &cmdlistptr->auth_sha256_hmac;
case QCE_HASH_SHA384_HMAC:
return &cmdlistptr->auth_sha384_hmac;
case QCE_HASH_SHA512_HMAC:
return &cmdlistptr->auth_sha512_hmac;
case QCE_HASH_AES_CMAC:
if (sreq->authklen == AES128_KEY_SIZE)
return &cmdlistptr->auth_aes_128_cmac;
@@ -341,12 +382,11 @@ static int _ce_setup_hash(struct qce_device *pce_dev,
struct qce_sha_req *sreq,
struct qce_cmdlist_info *cmdlistinfo)
{
uint32_t auth32[SHA256_DIGEST_SIZE / sizeof(uint32_t)];
uint32_t auth32[SHA512_DIGEST_SIZE / sizeof(uint32_t)];
uint32_t diglen;
int i;
uint32_t mackey32[SHA_HMAC_KEY_SIZE/sizeof(uint32_t)] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
bool sha1 = false;
uint32_t mackey32[SHA_HMAC_KEY_SIZE/sizeof(uint32_t)] = {0};
bool sha1 = false, sha256 = false, sha384 = false, sha512 = false;
struct sps_command_element *pce = NULL;
bool use_hw_key = false;
bool use_pipe_key = false;
@@ -355,6 +395,8 @@ static int _ce_setup_hash(struct qce_device *pce_dev,
if ((sreq->alg == QCE_HASH_SHA1_HMAC) ||
(sreq->alg == QCE_HASH_SHA256_HMAC) ||
(sreq->alg == QCE_HASH_SHA384_HMAC) ||
(sreq->alg == QCE_HASH_SHA512_HMAC) ||
(sreq->alg == QCE_HASH_AES_CMAC)) {
@@ -387,7 +429,7 @@ static int _ce_setup_hash(struct qce_device *pce_dev,
goto go_proc;
/* if not the last, the size has to be on the block boundary */
if (!sreq->last_blk && (sreq->size % SHA256_BLOCK_SIZE))
if (!sreq->last_blk && (sreq->size % qce_get_block_size(sreq->alg)))
return -EIO;
switch (sreq->alg) {
@@ -399,6 +441,17 @@ static int _ce_setup_hash(struct qce_device *pce_dev,
case QCE_HASH_SHA256:
case QCE_HASH_SHA256_HMAC:
diglen = SHA256_DIGEST_SIZE;
sha256 = true;
break;
case QCE_HASH_SHA384:
case QCE_HASH_SHA384_HMAC:
diglen = SHA512_DIGEST_SIZE;
sha384 = true;
break;
case QCE_HASH_SHA512:
case QCE_HASH_SHA512_HMAC:
diglen = SHA512_DIGEST_SIZE;
sha512 = true;
break;
default:
return -EINVAL;
@@ -406,13 +459,18 @@ static int _ce_setup_hash(struct qce_device *pce_dev,
/* write 20/32 bytes, 5/8 words into auth_iv for SHA1/SHA256 */
if (sreq->first_blk) {
if (sha1) {
if (sha1)
for (i = 0; i < 5; i++)
auth32[i] = _std_init_vector_sha1[i];
} else {
if (sha256)
for (i = 0; i < 8; i++)
auth32[i] = _std_init_vector_sha256[i];
}
if (sha384)
for (i = 0; i < 16; i++)
auth32[i] = _std_init_vector_sha384[i];
if (sha512)
for (i = 0; i < 16; i++)
auth32[i] = _std_init_vector_sha512[i];
} else {
_byte_stream_to_net_words(auth32, sreq->digest, diglen);
}
@@ -421,15 +479,18 @@ static int _ce_setup_hash(struct qce_device *pce_dev,
for (i = 0; i < 5; i++, pce++)
pce->data = auth32[i];
if ((sreq->alg == QCE_HASH_SHA256) ||
(sreq->alg == QCE_HASH_SHA256_HMAC)) {
if (sha256)
for (i = 5; i < 8; i++, pce++)
pce->data = auth32[i];
}
if (sha384 || sha512)
for (i = 5; i < 16; i++, pce++)
pce->data = auth32[i];
/* write auth_bytecnt 0/1, start with 0 */
pce = cmdlistinfo->auth_bytecount;
for (i = 0; i < 2; i++, pce++)
for (i = 0; i < 4; i++, pce++)
pce->data = sreq->auth_data[i];
/* Set/reset last bit in CFG register */
@@ -1173,15 +1234,14 @@ static void _qce_dump_descr_fifos_dbg(struct qce_device *pce_dev, int req_info)
static int _ce_setup_hash_direct(struct qce_device *pce_dev,
struct qce_sha_req *sreq)
{
uint32_t auth32[SHA256_DIGEST_SIZE / sizeof(uint32_t)];
uint32_t auth32[SHA512_DIGEST_SIZE / sizeof(uint32_t)];
uint32_t diglen;
bool use_hw_key = false;
bool use_pipe_key = false;
int i;
uint32_t mackey32[SHA_HMAC_KEY_SIZE/sizeof(uint32_t)] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint32_t mackey32[SHA_HMAC_KEY_SIZE / sizeof(uint32_t)] = {0};
uint32_t authk_size_in_word = sreq->authklen/sizeof(uint32_t);
bool sha1 = false;
bool sha1 = false, sha256 = false, sha384 = false, sha512 = false;
uint32_t auth_cfg = 0;
/* clear status */
@@ -1226,6 +1286,8 @@ static int _ce_setup_hash_direct(struct qce_device *pce_dev,
if ((sreq->alg == QCE_HASH_SHA1_HMAC) ||
(sreq->alg == QCE_HASH_SHA256_HMAC) ||
(sreq->alg == QCE_HASH_SHA384_HMAC) ||
(sreq->alg == QCE_HASH_SHA512_HMAC) ||
(sreq->alg == QCE_HASH_AES_CMAC)) {
_byte_stream_to_net_words(mackey32, sreq->authkey,
@@ -1252,7 +1314,7 @@ static int _ce_setup_hash_direct(struct qce_device *pce_dev,
goto go_proc;
/* if not the last, the size has to be on the block boundary */
if (!sreq->last_blk && (sreq->size % SHA256_BLOCK_SIZE))
if (!sreq->last_blk && (sreq->size % qce_get_block_size(sreq->alg)))
return -EIO;
switch (sreq->alg) {
@@ -1269,10 +1331,32 @@ static int _ce_setup_hash_direct(struct qce_device *pce_dev,
case QCE_HASH_SHA256:
auth_cfg = pce_dev->reg.auth_cfg_sha256;
diglen = SHA256_DIGEST_SIZE;
sha256 = true;
break;
case QCE_HASH_SHA256_HMAC:
auth_cfg = pce_dev->reg.auth_cfg_hmac_sha256;
diglen = SHA256_DIGEST_SIZE;
sha256 = true;
break;
case QCE_HASH_SHA384:
auth_cfg = pce_dev->reg.auth_cfg_sha384;
diglen = SHA512_DIGEST_SIZE;
sha384 = true;
break;
case QCE_HASH_SHA384_HMAC:
auth_cfg = pce_dev->reg.auth_cfg_hmac_sha384;
diglen = SHA512_DIGEST_SIZE;
sha384 = true;
break;
case QCE_HASH_SHA512:
auth_cfg = pce_dev->reg.auth_cfg_sha512;
diglen = SHA512_DIGEST_SIZE;
sha512 = true;
break;
case QCE_HASH_SHA512_HMAC:
auth_cfg = pce_dev->reg.auth_cfg_hmac_sha512;
diglen = SHA512_DIGEST_SIZE;
sha512 = true;
break;
default:
return -EINVAL;
@@ -1280,13 +1364,18 @@ static int _ce_setup_hash_direct(struct qce_device *pce_dev,
/* write 20/32 bytes, 5/8 words into auth_iv for SHA1/SHA256 */
if (sreq->first_blk) {
if (sha1) {
if (sha1)
for (i = 0; i < 5; i++)
auth32[i] = _std_init_vector_sha1[i];
} else {
if (sha256)
for (i = 0; i < 8; i++)
auth32[i] = _std_init_vector_sha256[i];
}
if (sha384)
for (i = 0; i < 16; i++)
auth32[i] = _std_init_vector_sha384[i];
if (sha512)
for (i = 0; i < 16; i++)
auth32[i] = _std_init_vector_sha512[i];
} else {
_byte_stream_to_net_words(auth32, sreq->digest, diglen);
}
@@ -1296,16 +1385,17 @@ static int _ce_setup_hash_direct(struct qce_device *pce_dev,
QCE_WRITE_REG(auth32[i], (pce_dev->iobase +
(CRYPTO_AUTH_IV0_REG + i*sizeof(uint32_t))));
if ((sreq->alg == QCE_HASH_SHA256) ||
(sreq->alg == QCE_HASH_SHA256_HMAC)) {
if (sha256)
for (i = 5; i < 8; i++)
QCE_WRITE_REG(auth32[i], (pce_dev->iobase +
(CRYPTO_AUTH_IV0_REG + i*sizeof(uint32_t))));
}
if (sha384 || sha512)
for (i = 5; i < 16; i++)
QCE_WRITE_REG(auth32[i], (pce_dev->iobase +
(CRYPTO_AUTH_IV0_REG + i*sizeof(uint32_t))));
/* write auth_bytecnt 0/1/2/3, start with 0 */
for (i = 0; i < 2; i++)
for (i = 0; i < 4; i++)
QCE_WRITE_REG(sreq->auth_data[i], pce_dev->iobase +
CRYPTO_AUTH_BYTECNT0_REG +
i * sizeof(uint32_t));
@@ -1362,7 +1452,7 @@ static int _ce_setup_aead_direct(struct qce_device *pce_dev,
{
int32_t authk_size_in_word = SHA_HMAC_KEY_SIZE/sizeof(uint32_t);
int i;
uint32_t mackey32[SHA_HMAC_KEY_SIZE/sizeof(uint32_t)] = {0};
uint32_t mackey32[SHA_HMAC_KEY_SIZE / sizeof(uint32_t)] = {0};
uint32_t a_cfg;
uint32_t enckey32[(MAX_CIPHER_KEY_SIZE*2)/sizeof(uint32_t)] = {0};
uint32_t enciv32[MAX_IV_LENGTH/sizeof(uint32_t)] = {0};
@@ -2139,8 +2229,8 @@ static int _aead_complete(struct qce_device *pce_dev, int req_info)
static int _sha_complete(struct qce_device *pce_dev, int req_info)
{
struct ahash_request *areq;
unsigned char digest[SHA256_DIGEST_SIZE];
uint32_t bytecount32[2];
unsigned char digest[SHA512_DIGEST_SIZE];
uint32_t bytecount32[AUTH_BYTECNT_REG_NUMBER];
int32_t result_status = 0;
uint32_t result_dump_status;
struct ce_request_info *preq_info;
@@ -2158,10 +2248,10 @@ static int _sha_complete(struct qce_device *pce_dev, int req_info)
qce_dma_unmap_sg(pce_dev->pdev, areq->src, preq_info->src_nents,
DMA_TO_DEVICE);
memcpy(digest, (char *)(&pce_sps_data->result->auth_iv[0]),
SHA256_DIGEST_SIZE);
SHA512_DIGEST_SIZE);
_byte_stream_to_net_words(bytecount32,
(unsigned char *)pce_sps_data->result->auth_byte_count,
2 * CRYPTO_REG_SIZE);
AUTH_BYTECNT_REG_NUMBER * CRYPTO_REG_SIZE);
if (_qce_unlock_other_pipes(pce_dev, req_info)) {
qce_free_req_info(pce_dev, req_info, true);
@@ -3574,6 +3664,40 @@ static int _setup_auth_cmdlistptrs(struct qce_device *pdev, int cri_index,
qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
0, NULL);
break;
case QCE_HASH_SHA384:
cmdlistptr->auth_sha384.cmdlist = (uintptr_t)ce_vaddr;
pcl_info = &(cmdlistptr->auth_sha384);
auth_cfg = pdev->reg.auth_cfg_sha384;
iv_reg = 16;
/* clear status register */
qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG,
0, NULL);
qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
/* 1 dummy write */
qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
0, NULL);
break;
case QCE_HASH_SHA512:
cmdlistptr->auth_sha512.cmdlist = (uintptr_t)ce_vaddr;
pcl_info = &(cmdlistptr->auth_sha512);
auth_cfg = pdev->reg.auth_cfg_sha512;
iv_reg = 16;
/* clear status register */
qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG,
0, NULL);
qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
/* 1 dummy write */
qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
0, NULL);
break;
case QCE_HASH_SHA1_HMAC:
cmdlistptr->auth_sha1_hmac.cmdlist = (uintptr_t)ce_vaddr;
pcl_info = &(cmdlistptr->auth_sha1_hmac);
@@ -3607,6 +3731,42 @@ static int _setup_auth_cmdlistptrs(struct qce_device *pdev, int cri_index,
qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
0, NULL);
break;
case QCE_HASH_SHA384_HMAC:
cmdlistptr->auth_sha384_hmac.cmdlist = (uintptr_t)ce_vaddr;
pcl_info = &(cmdlistptr->auth_sha384_hmac);
auth_cfg = pdev->reg.auth_cfg_hmac_sha384;
key_reg = 32;
iv_reg = 16;
/* clear status register */
qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG, 0,
NULL);
qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
/* 1 dummy write */
qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
0, NULL);
break;
case QCE_HASH_SHA512_HMAC:
cmdlistptr->auth_sha512_hmac.cmdlist = (uintptr_t)ce_vaddr;
pcl_info = &(cmdlistptr->auth_sha512_hmac);
auth_cfg = pdev->reg.auth_cfg_hmac_sha512;
key_reg = 32;
iv_reg = 16;
/* clear status register */
qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG, 0,
NULL);
qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
/* 1 dummy write */
qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
0, NULL);
break;
case QCE_HASH_AES_CMAC:
if (key_128) {
cmdlistptr->auth_aes_128_cmac.cmdlist =
@@ -3674,6 +3834,8 @@ static int _setup_auth_cmdlistptrs(struct qce_device *pdev, int cri_index,
0, &pcl_info->auth_bytecount);
}
qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_BYTECNT1_REG, 0, NULL);
qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_BYTECNT2_REG, 0, NULL);
qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_BYTECNT3_REG, 0, NULL);
if (key_reg) {
qce_add_cmd_element(pdev, &ce_vaddr,
@@ -4282,11 +4444,19 @@ static int qce_setup_cmdlistptrs(struct qce_device *pdev, int cri_index,
false);
_setup_auth_cmdlistptrs(pdev, cri_index, pvaddr, QCE_HASH_SHA256,
false);
_setup_auth_cmdlistptrs(pdev, cri_index, pvaddr, QCE_HASH_SHA384,
false);
_setup_auth_cmdlistptrs(pdev, cri_index, pvaddr, QCE_HASH_SHA512,
false);
_setup_auth_cmdlistptrs(pdev, cri_index, pvaddr, QCE_HASH_SHA1_HMAC,
false);
_setup_auth_cmdlistptrs(pdev, cri_index, pvaddr, QCE_HASH_SHA256_HMAC,
false);
_setup_auth_cmdlistptrs(pdev, cri_index, pvaddr, QCE_HASH_SHA384_HMAC,
false);
_setup_auth_cmdlistptrs(pdev, cri_index, pvaddr, QCE_HASH_SHA512_HMAC,
false);
_setup_auth_cmdlistptrs(pdev, cri_index, pvaddr, QCE_HASH_AES_CMAC,
true);
@@ -4505,6 +4675,18 @@ static int qce_init_ce_cfg_val(struct qce_device *pce_dev)
(CRYPTO_AUTH_ALG_SHA << CRYPTO_AUTH_ALG) |
(CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS);
pce_dev->reg.auth_cfg_hmac_sha384 =
(CRYPTO_AUTH_MODE_HMAC << CRYPTO_AUTH_MODE)|
(CRYPTO_AUTH_SIZE_SHA384 << CRYPTO_AUTH_SIZE) |
(CRYPTO_AUTH_ALG_SHA << CRYPTO_AUTH_ALG) |
(CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS);
pce_dev->reg.auth_cfg_hmac_sha512 =
(CRYPTO_AUTH_MODE_HMAC << CRYPTO_AUTH_MODE)|
(CRYPTO_AUTH_SIZE_SHA512 << CRYPTO_AUTH_SIZE) |
(CRYPTO_AUTH_ALG_SHA << CRYPTO_AUTH_ALG) |
(CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS);
/* Initialize auth_cfg register for SHA1/256 alg */
pce_dev->reg.auth_cfg_sha1 =
(CRYPTO_AUTH_MODE_HASH << CRYPTO_AUTH_MODE)|
@@ -4518,6 +4700,18 @@ static int qce_init_ce_cfg_val(struct qce_device *pce_dev)
(CRYPTO_AUTH_ALG_SHA << CRYPTO_AUTH_ALG) |
(CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS);
pce_dev->reg.auth_cfg_sha384 =
(CRYPTO_AUTH_MODE_HASH << CRYPTO_AUTH_MODE)|
(CRYPTO_AUTH_SIZE_SHA384 << CRYPTO_AUTH_SIZE) |
(CRYPTO_AUTH_ALG_SHA << CRYPTO_AUTH_ALG) |
(CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS);
pce_dev->reg.auth_cfg_sha512 =
(CRYPTO_AUTH_MODE_HASH << CRYPTO_AUTH_MODE)|
(CRYPTO_AUTH_SIZE_SHA512 << CRYPTO_AUTH_SIZE) |
(CRYPTO_AUTH_ALG_SHA << CRYPTO_AUTH_ALG) |
(CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS);
/* Initialize auth_cfg register for AEAD alg */
pce_dev->reg.auth_cfg_aead_sha1_hmac =
(CRYPTO_AUTH_MODE_HMAC << CRYPTO_AUTH_MODE)|

View File

@@ -126,6 +126,10 @@ struct qce_cmdlistptr_ops {
struct qce_cmdlist_info f9_kasumi;
struct qce_cmdlist_info f9_snow3g;
struct qce_cmdlist_info unlock_all_pipes;
struct qce_cmdlist_info auth_sha384;
struct qce_cmdlist_info auth_sha512;
struct qce_cmdlist_info auth_sha384_hmac;
struct qce_cmdlist_info auth_sha512_hmac;
};
struct qce_ce_cfg_reg_setting {
@@ -170,6 +174,11 @@ struct qce_ce_cfg_reg_setting {
uint32_t auth_cfg_aead_sha256_hmac;
uint32_t auth_cfg_kasumi;
uint32_t auth_cfg_snow3g;
uint32_t auth_cfg_sha384;
uint32_t auth_cfg_sha512;
uint32_t auth_cfg_hmac_sha384;
uint32_t auth_cfg_hmac_sha512;
};
struct ce_bam_info {

View File

@@ -50,6 +50,28 @@ static uint8_t _std_init_vector_sha256_uint8[] = {
0x1F, 0x83, 0xD9, 0xAB, 0x5B, 0xE0, 0xCD, 0x19
};
static uint8_t _std_init_vector_sha384_uint8[] = {
0xCB, 0xBB, 0x9D, 0x5D, 0xC1, 0x05, 0x9E, 0xD8,
0x62, 0x9A, 0x29, 0x2A, 0x36, 0x7C, 0xD5, 0x07,
0x91, 0x59, 0x01, 0x5A, 0x30, 0x70, 0xDD, 0x17,
0x15, 0x2F, 0xEC, 0xD8, 0xF7, 0x0E, 0x59, 0x39,
0x67, 0x33, 0x26, 0x67, 0xFF, 0xC0, 0x0B, 0x31,
0x8E, 0xB4, 0x4A, 0x87, 0x68, 0x58, 0x15, 0x11,
0xDB, 0x0C, 0x2E, 0x0D, 0x64, 0xF9, 0x8F, 0xA7,
0x47, 0xB5, 0x48, 0x1D, 0xBE, 0xFA, 0x4F, 0xA4
};
static uint8_t _std_init_vector_sha512_uint8[] = {
0x6A, 0x09, 0xE6, 0x67, 0xF3, 0xBC, 0xC9, 0x08,
0xBB, 0x67, 0xAE, 0x85, 0x84, 0xCA, 0xA7, 0x3B,
0x3C, 0x6E, 0xF3, 0x72, 0xFE, 0x94, 0xF8, 0x2B,
0xA5, 0x4F, 0xF5, 0x3A, 0x5F, 0x1D, 0x36, 0xF1,
0x51, 0x0E, 0x52, 0x7F, 0xAD, 0xE6, 0x82, 0xD1,
0x9B, 0x05, 0x68, 0x8C, 0x2B, 0x3E, 0x6C, 0x1F,
0x1F, 0x83, 0xD9, 0xAB, 0xFB, 0x41, 0xBD, 0x6B,
0x5B, 0xE0, 0xCD, 0x19, 0x13, 0x7E, 0x21, 0x79
};
static DEFINE_MUTEX(send_cmd_lock);
static DEFINE_MUTEX(qcedev_sent_bw_req);
static DEFINE_MUTEX(hash_access_lock);
@@ -66,6 +88,23 @@ static const struct of_device_id qcedev_match[] = {
{}
};
static uint32_t qcedev_get_block_size(enum qcedev_sha_alg_enum alg)
{
switch (alg) {
case QCEDEV_ALG_SHA1:
case QCEDEV_ALG_SHA1_HMAC:
return SHA1_BLOCK_SIZE;
case QCEDEV_ALG_SHA256:
case QCEDEV_ALG_SHA256_HMAC:
return SHA256_BLOCK_SIZE;
case QCEDEV_ALG_SHA384:
case QCEDEV_ALG_SHA384_HMAC:
return SHA384_BLOCK_SIZE;
default:
return SHA512_BLOCK_SIZE;
}
}
static int qcedev_control_clocks(struct qcedev_control *podev, bool enable)
{
unsigned int control_flag;
@@ -340,11 +379,14 @@ void qcedev_sha_req_cb(void *cookie, unsigned char *digest,
pdev = handle->cntl;
if (digest)
memcpy(&handle->sha_ctxt.digest[0], digest, 32);
memcpy(&handle->sha_ctxt.digest[0], digest,
QCEDEV_MAX_SHA_DIGEST);
if (authdata) {
handle->sha_ctxt.auth_data[0] = auth32[0];
handle->sha_ctxt.auth_data[1] = auth32[1];
handle->sha_ctxt.auth_data[2] = auth32[2];
handle->sha_ctxt.auth_data[3] = auth32[3];
}
tasklet_schedule(&pdev->done_tasklet);
@@ -490,12 +532,17 @@ static int start_sha_req(struct qcedev_control *podev)
case QCEDEV_ALG_SHA256:
sreq.alg = QCE_HASH_SHA256;
break;
case QCEDEV_ALG_SHA384:
sreq.alg = QCE_HASH_SHA384;
break;
case QCEDEV_ALG_SHA512:
sreq.alg = QCE_HASH_SHA512;
break;
case QCEDEV_ALG_SHA1_HMAC:
if (podev->ce_support.sha_hmac) {
sreq.alg = QCE_HASH_SHA1_HMAC;
sreq.authkey = &handle->sha_ctxt.authkey[0];
sreq.authklen = QCEDEV_MAX_SHA_BLOCK_SIZE;
sreq.authklen = SHA1_BLOCK_SIZE;
} else {
sreq.alg = QCE_HASH_SHA1;
sreq.authkey = NULL;
@@ -505,12 +552,32 @@ static int start_sha_req(struct qcedev_control *podev)
if (podev->ce_support.sha_hmac) {
sreq.alg = QCE_HASH_SHA256_HMAC;
sreq.authkey = &handle->sha_ctxt.authkey[0];
sreq.authklen = QCEDEV_MAX_SHA_BLOCK_SIZE;
sreq.authklen = SHA256_BLOCK_SIZE;
} else {
sreq.alg = QCE_HASH_SHA256;
sreq.authkey = NULL;
}
break;
case QCEDEV_ALG_SHA384_HMAC:
if (podev->ce_support.sha_hmac) {
sreq.alg = QCE_HASH_SHA384_HMAC;
sreq.authkey = &handle->sha_ctxt.authkey[0];
sreq.authklen = SHA384_BLOCK_SIZE;
} else {
sreq.alg = QCE_HASH_SHA384;
sreq.authkey = NULL;
}
break;
case QCEDEV_ALG_SHA512_HMAC:
if (podev->ce_support.sha_hmac) {
sreq.alg = QCE_HASH_SHA512_HMAC;
sreq.authkey = &handle->sha_ctxt.authkey[0];
sreq.authklen = SHA512_BLOCK_SIZE;
} else {
sreq.alg = QCE_HASH_SHA512;
sreq.authkey = NULL;
}
break;
case QCEDEV_ALG_AES_CMAC:
sreq.alg = QCE_HASH_AES_CMAC;
sreq.authkey = &handle->sha_ctxt.authkey[0];
@@ -623,14 +690,27 @@ static int qcedev_sha_init(struct qcedev_async_req *areq,
memcpy(&sha_ctxt->digest[0],
&_std_init_vector_sha1_uint8[0], SHA1_DIGEST_SIZE);
sha_ctxt->diglen = SHA1_DIGEST_SIZE;
} else {
if ((areq->sha_op_req.alg == QCEDEV_ALG_SHA256) ||
}
if ((areq->sha_op_req.alg == QCEDEV_ALG_SHA256) ||
(areq->sha_op_req.alg == QCEDEV_ALG_SHA256_HMAC)) {
memcpy(&sha_ctxt->digest[0],
&_std_init_vector_sha256_uint8[0],
SHA256_DIGEST_SIZE);
sha_ctxt->diglen = SHA256_DIGEST_SIZE;
}
memcpy(&sha_ctxt->digest[0],
&_std_init_vector_sha256_uint8[0],
SHA256_DIGEST_SIZE);
sha_ctxt->diglen = SHA256_DIGEST_SIZE;
}
if ((areq->sha_op_req.alg == QCEDEV_ALG_SHA384) ||
(areq->sha_op_req.alg == QCEDEV_ALG_SHA384_HMAC)) {
memcpy(&sha_ctxt->digest[0],
&_std_init_vector_sha384_uint8[0],
SHA512_DIGEST_SIZE);
sha_ctxt->diglen = SHA384_DIGEST_SIZE;
}
if ((areq->sha_op_req.alg == QCEDEV_ALG_SHA512) ||
(areq->sha_op_req.alg == QCEDEV_ALG_SHA512_HMAC)) {
memcpy(&sha_ctxt->digest[0],
&_std_init_vector_sha512_uint8[0],
SHA512_DIGEST_SIZE);
sha_ctxt->diglen = SHA512_DIGEST_SIZE;
}
sha_ctxt->init_done = true;
return 0;
@@ -657,10 +737,7 @@ static int qcedev_sha_update_max_xfer(struct qcedev_async_req *qcedev_areq,
total = qcedev_areq->sha_op_req.data_len + t_buf;
if (qcedev_areq->sha_op_req.alg == QCEDEV_ALG_SHA1)
sha_block_size = SHA1_BLOCK_SIZE;
else
sha_block_size = SHA256_BLOCK_SIZE;
sha_block_size = qcedev_get_block_size(qcedev_areq->sha_op_req.alg);
if (total <= sha_block_size) {
uint32_t len = qcedev_areq->sha_op_req.data_len;
@@ -687,7 +764,6 @@ static int qcedev_sha_update_max_xfer(struct qcedev_async_req *qcedev_areq,
return 0;
}
k_buf_src = kmalloc(total + CACHE_LINE_SIZE * 2,
GFP_KERNEL);
if (k_buf_src == NULL)
@@ -727,8 +803,8 @@ static int qcedev_sha_update_max_xfer(struct qcedev_async_req *qcedev_areq,
}
/* get new trailing buffer */
sha_pad_len = ALIGN(total, CE_SHA_BLOCK_SIZE) - total;
trailing_buf_len = CE_SHA_BLOCK_SIZE - sha_pad_len;
sha_pad_len = ALIGN(total, sha_block_size) - total;
trailing_buf_len = sha_block_size - sha_pad_len;
qcedev_areq->sha_req.sreq.src = sg_src;
sg_init_one(qcedev_areq->sha_req.sreq.src, k_align_src,
@@ -738,7 +814,8 @@ static int qcedev_sha_update_max_xfer(struct qcedev_async_req *qcedev_areq,
/* update sha_ctxt trailing buf content to new trailing buf */
if (trailing_buf_len > 0) {
memset(&handle->sha_ctxt.trailing_buf[0], 0, 64);
memset(&handle->sha_ctxt.trailing_buf[0], 0,
QCEDEV_MAX_SHA_BLOCK_SIZE);
memcpy(&handle->sha_ctxt.trailing_buf[0],
(k_src - trailing_buf_len),
trailing_buf_len);
@@ -905,9 +982,11 @@ static int qcedev_sha_final(struct qcedev_async_req *qcedev_areq,
handle->sha_ctxt.last_blk = 0;
handle->sha_ctxt.auth_data[0] = 0;
handle->sha_ctxt.auth_data[1] = 0;
handle->sha_ctxt.auth_data[2] = 0;
handle->sha_ctxt.auth_data[3] = 0;
handle->sha_ctxt.trailing_buf_len = 0;
handle->sha_ctxt.init_done = false;
memset(&handle->sha_ctxt.trailing_buf[0], 0, 64);
memset(&handle->sha_ctxt.trailing_buf[0], 0, QCEDEV_MAX_SHA_BLOCK_SIZE);
memset(k_buf_src, 0, ksize((void *)k_buf_src));
kfree(k_buf_src);
qcedev_areq->sha_req.sreq.src = NULL;
@@ -979,8 +1058,9 @@ static int qcedev_set_hmac_auth_key(struct qcedev_async_req *areq,
struct scatterlist *sg_src)
{
int err = 0;
int qcedev_max_key = qcedev_get_block_size(areq->sha_op_req.alg);
if (areq->sha_op_req.authklen <= QCEDEV_MAX_KEY_SIZE) {
if (areq->sha_op_req.authklen <= qcedev_max_key) {
qcedev_sha_init(areq, handle);
if (copy_from_user(&handle->sha_ctxt.authkey[0],
(void __user *)areq->sha_op_req.authkey,
@@ -1006,6 +1086,10 @@ static int qcedev_set_hmac_auth_key(struct qcedev_async_req *areq,
authkey_areq.sha_op_req.alg = QCEDEV_ALG_SHA1;
if (areq->sha_op_req.alg == QCEDEV_ALG_SHA256_HMAC)
authkey_areq.sha_op_req.alg = QCEDEV_ALG_SHA256;
if (areq->sha_op_req.alg == QCEDEV_ALG_SHA384_HMAC)
authkey_areq.sha_op_req.alg = QCEDEV_ALG_SHA384;
if (areq->sha_op_req.alg == QCEDEV_ALG_SHA512_HMAC)
authkey_areq.sha_op_req.alg = QCEDEV_ALG_SHA512;
authkey_areq.op_type = QCEDEV_CRYPTO_OPER_SHA;
@@ -1034,15 +1118,16 @@ static int qcedev_hmac_get_ohash(struct qcedev_async_req *qcedev_areq,
uint32_t sha_block_size = 0;
uint32_t sha_digest_size = 0;
if (qcedev_areq->sha_op_req.alg == QCEDEV_ALG_SHA1_HMAC) {
sha_block_size = qcedev_get_block_size(qcedev_areq->sha_op_req.alg);
if (qcedev_areq->sha_op_req.alg == QCEDEV_ALG_SHA1_HMAC)
sha_digest_size = SHA1_DIGEST_SIZE;
sha_block_size = SHA1_BLOCK_SIZE;
} else {
if (qcedev_areq->sha_op_req.alg == QCEDEV_ALG_SHA256_HMAC) {
sha_digest_size = SHA256_DIGEST_SIZE;
sha_block_size = SHA256_BLOCK_SIZE;
}
}
if (qcedev_areq->sha_op_req.alg == QCEDEV_ALG_SHA256_HMAC)
sha_digest_size = SHA256_DIGEST_SIZE;
if (qcedev_areq->sha_op_req.alg == QCEDEV_ALG_SHA384_HMAC)
sha_digest_size = SHA384_DIGEST_SIZE;
if (qcedev_areq->sha_op_req.alg == QCEDEV_ALG_SHA512_HMAC)
sha_digest_size = SHA512_DIGEST_SIZE;
k_src = kmalloc(sha_block_size, GFP_KERNEL);
if (k_src == NULL)
return -ENOMEM;
@@ -1076,6 +1161,18 @@ static int qcedev_hmac_get_ohash(struct qcedev_async_req *qcedev_areq,
&_std_init_vector_sha256_uint8[0], SHA256_DIGEST_SIZE);
handle->sha_ctxt.diglen = SHA256_DIGEST_SIZE;
}
if (qcedev_areq->sha_op_req.alg == QCEDEV_ALG_SHA384_HMAC) {
memcpy(&handle->sha_ctxt.digest[0],
&_std_init_vector_sha384_uint8[0], SHA512_DIGEST_SIZE);
handle->sha_ctxt.diglen = SHA384_DIGEST_SIZE;
}
if (qcedev_areq->sha_op_req.alg == QCEDEV_ALG_SHA512_HMAC) {
memcpy(&handle->sha_ctxt.digest[0],
&_std_init_vector_sha512_uint8[0], SHA512_DIGEST_SIZE);
handle->sha_ctxt.diglen = SHA512_DIGEST_SIZE;
}
err = submit_req(qcedev_areq, handle);
handle->sha_ctxt.last_blk = 0;
@@ -1098,10 +1195,7 @@ static int qcedev_hmac_update_iokey(struct qcedev_async_req *areq,
else
constant = 0x5c;
if (areq->sha_op_req.alg == QCEDEV_ALG_SHA1_HMAC)
sha_block_size = SHA1_BLOCK_SIZE;
else
sha_block_size = SHA256_BLOCK_SIZE;
sha_block_size = qcedev_get_block_size(areq->sha_op_req.alg);
memset(&handle->sha_ctxt.trailing_buf[0], 0, sha_block_size);
for (i = 0; i < sha_block_size; i++)
@@ -1151,7 +1245,9 @@ static int qcedev_hash_init(struct qcedev_async_req *areq,
struct scatterlist *sg_src)
{
if ((areq->sha_op_req.alg == QCEDEV_ALG_SHA1) ||
(areq->sha_op_req.alg == QCEDEV_ALG_SHA256))
(areq->sha_op_req.alg == QCEDEV_ALG_SHA256) ||
(areq->sha_op_req.alg == QCEDEV_ALG_SHA384) ||
(areq->sha_op_req.alg == QCEDEV_ALG_SHA512))
return qcedev_sha_init(areq, handle);
else
return qcedev_hmac_init(areq, handle, sg_src);
@@ -1168,7 +1264,9 @@ static int qcedev_hash_final(struct qcedev_async_req *areq,
struct qcedev_handle *handle)
{
if ((areq->sha_op_req.alg == QCEDEV_ALG_SHA1) ||
(areq->sha_op_req.alg == QCEDEV_ALG_SHA256))
(areq->sha_op_req.alg == QCEDEV_ALG_SHA256) ||
(areq->sha_op_req.alg == QCEDEV_ALG_SHA384) ||
(areq->sha_op_req.alg == QCEDEV_ALG_SHA512))
return qcedev_sha_final(areq, handle);
else
return qcedev_hmac_final(areq, handle);
@@ -1635,7 +1733,9 @@ static int qcedev_check_sha_params(struct qcedev_sha_op_req *req,
goto sha_error;
}
if ((req->alg == QCEDEV_ALG_SHA1_HMAC) ||
(req->alg == QCEDEV_ALG_SHA256_HMAC)) {
(req->alg == QCEDEV_ALG_SHA256_HMAC) ||
(req->alg == QCEDEV_ALG_SHA384_HMAC) ||
(req->alg == QCEDEV_ALG_SHA512_HMAC)) {
if (req->authkey == NULL) {
pr_err("%s: Invalid authkey pointer\n", __func__);
goto sha_error;

View File

@@ -41,7 +41,7 @@ struct qcedev_sha_ctxt {
uint32_t auth_data[4];
uint8_t digest[QCEDEV_MAX_SHA_DIGEST];
uint32_t diglen;
uint8_t trailing_buf[64];
uint8_t trailing_buf[QCEDEV_MAX_SHA_BLOCK_SIZE];
uint32_t trailing_buf_len;
uint8_t first_blk;
uint8_t last_blk;

View File

@@ -385,6 +385,8 @@
#define CRYPTO_AUTH_SIZE_MASK (0x1F << CRYPTO_AUTH_SIZE)
#define CRYPTO_AUTH_SIZE_SHA1 0
#define CRYPTO_AUTH_SIZE_SHA256 1
#define CRYPTO_AUTH_SIZE_SHA384 2
#define CRYPTO_AUTH_SIZE_SHA512 3
#define CRYPTO_AUTH_SIZE_ENUM_1_BYTES 0
#define CRYPTO_AUTH_SIZE_ENUM_2_BYTES 1
#define CRYPTO_AUTH_SIZE_ENUM_3_BYTES 2

View File

@@ -10,13 +10,13 @@
#include <linux/ioctl.h>
#include "fips_status.h"
#define QCEDEV_MAX_SHA_BLOCK_SIZE 64
#define QCEDEV_MAX_SHA_BLOCK_SIZE 128
#define QCEDEV_MAX_BEARER 31
#define QCEDEV_MAX_KEY_SIZE 64
#define QCEDEV_MAX_IV_SIZE 32
#define QCEDEV_MAX_BUFFERS 16
#define QCEDEV_MAX_SHA_DIGEST 32
#define QCEDEV_MAX_SHA_DIGEST 64
#define QCEDEV_USE_PMEM 1
#define QCEDEV_NO_PMEM 0
@@ -79,8 +79,12 @@ enum qcedev_cipher_mode_enum {
*enum qcedev_sha_alg_enum : Secure Hashing Algorithm
* @QCEDEV_ALG_SHA1: Digest returned: 20 bytes (160 bits)
* @QCEDEV_ALG_SHA256: Digest returned: 32 bytes (256 bit)
* @QCEDEV_ALG_SHA384: Digest returned: 48 bytes (384 bit)
* @QCEDEV_ALG_SHA512: Digest returned: 64 bytes (512 bit)
* @QCEDEV_ALG_SHA1_HMAC: HMAC returned 20 bytes (160 bits)
* @QCEDEV_ALG_SHA256_HMAC: HMAC returned 32 bytes (256 bit)
* @QCEDEV_ALG_SHA384_HMAC: HMAC returned 48 bytes (384 bit)
* @QCEDEV_ALG_SHA512_HMAC: HMAC returned 64 bytes (512 bit)
* @QCEDEV_ALG_AES_CMAC: Configurable MAC size
*/
enum qcedev_sha_alg_enum {
@@ -89,6 +93,10 @@ enum qcedev_sha_alg_enum {
QCEDEV_ALG_SHA1_HMAC = 2,
QCEDEV_ALG_SHA256_HMAC = 3,
QCEDEV_ALG_AES_CMAC = 4,
QCEDEV_ALG_SHA384 = 5,
QCEDEV_ALG_SHA512 = 6,
QCEDEV_ALG_SHA384_HMAC = 7,
QCEDEV_ALG_SHA512_HMAC = 8,
QCEDEV_ALG_SHA_ALG_LAST
};