-
Notifications
You must be signed in to change notification settings - Fork 808
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding Crypto support #2477
base: adsp-main
Are you sure you want to change the base?
Adding Crypto support #2477
Conversation
Hashing passes test, cipher untested - Correcting error handling - Changing ahash_algs to ahash_engine_algs Since this is a hardware driven engine, it is more approriate to be using ahash_engine_algs - Removing busy wait While loops now yield while waiting for device status - Changing interrupt handler to threaded context CRC tests now pass (for upto 4KB input) - Changing interrupt to threaded context - Removing unneeded function call Signed-off-by: UtsavAgarwalADI <utsav.agarwal@analog.com>
drivers/crypto/adi/adi-pkte-hash.c
Outdated
{ | ||
u32 i, nLength, SIZE, nPadLength = 0, nTotalSize; | ||
u32 *temp; | ||
u32 temp1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the naming of temp1
and temp
could be improved a bit;
maybe source -> source_offset
and temp1 -> data_offset
?
or something more representative of what they are
drivers/crypto/adi/adi-pkte-hash.c
Outdated
SIZE = (nLength > 128) ? 128 : (nLength); | ||
|
||
if (SIZE % 4) { | ||
for (i = 0; i < 1+SIZE/4; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these 2 for-loop look like it could be condensed into one;
maybe re-used nTotalSize = !!(SIZE % 4) + (SIZE / 4)
here?
drivers/crypto/adi/adi-pkte-hash.c
Outdated
break; | ||
} | ||
|
||
pkte->pPkteList.pSource += SIZE/(u32)4; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
explicit casts are discouraged in kernel code (in most cases);
drivers/crypto/adi/adi-pkte-hash.c
Outdated
|
||
void adi_write_packet(struct adi_dev *pkte_dev, u32 *source) | ||
{ | ||
u32 i, nLength, SIZE, nPadLength = 0, nTotalSize; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the naming of variables is a mix of camel-case or C-style (with underscores);
if this needs to be upstreamed, C-style is preferred for the naming;
u32 *temp; | ||
u32 temp1 = 0, temp2 = 0; | ||
u8 pos; | ||
struct ADI_PKTE_DEVICE *pkte; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some upstream people prefer reverse-christmas-tree ordering for variable names;
and IIRC, initialization-on-declaration is not preferred;
|
||
static int adi_crypt_aes_cbc_decrypt(struct skcipher_request *req) | ||
{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: remove these empty lines at the start of these functions?
drivers/crypto/adi/adi-pkte.c
Outdated
u32 Key[8] = {0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0}; | ||
u32 IV[4] = {0x0, 0x0, 0x0, 0x0}; | ||
u32 IDigest[8] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; | ||
u32 ODigest[8] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these look like global;
should they be static const
?
if they are device-state-specific, then malloc-ing is preferred, in case there are 2 similar devices in the same system
drivers/crypto/adi/adi-pkte.c
Outdated
|
||
void adi_init_ring(struct adi_dev *pkte_dev) | ||
{ | ||
u32 temp; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
u32 temp
-> u32 addr
?
drivers/crypto/adi/adi-pkte-hash.c
Outdated
{ | ||
u32 i = 0; | ||
u32 nLength = 0, SIZE = 0; | ||
uint8_t iBufIncrement = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there's a mix of uintXX_t
and uXX
types;
it's preferred to have one of the 2;
drivers/crypto/adi/adi_crc.c
Outdated
#include <crypto/algapi.h> | ||
#include <crypto/hash.h> | ||
#include <crypto/internal/hash.h> | ||
#include <asm/unaligned.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are all headers needed?
it's preferred to use the minimum required
drivers/crypto/adi/adi_crc.c
Outdated
|
||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
crc->regs = devm_ioremap_resource(dev, res); | ||
if (IS_ERR((void *)crc->regs)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
casting here is redundant
Signed-off-by: UtsavAgarwalADI <utsav.agarwal@analog.com>
c70f836
to
77c8307
Compare
Thank you for your review. I have made the requested changes in addition to some indentation for the source files - to allow it being more in line with the kernel coding style(used gnu indent with kernel specific settings). Please let me know if there are any further changes that you feel may be necessary. |
@UtsavAgarwalADI For upstream kernel (review level), quite a bit more work would be required (to review, and re-spin). The initial review (which I did) was a bit more late-Friday quick-scan. |
@@ -21,7 +21,7 @@ config CRYPTO_DEV_PADLOCK | |||
(so called VIA PadLock ACE, Advanced Cryptography Engine) | |||
that provides instructions for very fast cryptographic | |||
operations with supported algorithms. | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this change looks like patch noise;
maybe remove it?
drivers/crypto/adi/adi-pkte-hash.c
Outdated
@@ -0,0 +1,1196 @@ | |||
//#define DEBUG |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
left over debug;
remove?
drivers/crypto/adi/adi-pkte-hash.c
Outdated
static int adi_one_request(struct crypto_engine *engine, void *areq); | ||
static int adi_prepare_req(struct crypto_engine *engine, void *areq); | ||
|
||
void adi_write_packet(struct adi_dev *pkte_dev, u32 * source) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this adi_write_packet()
function looks like it does a lot of work;
is there a way to make this return error codes?
(just asking; no need to change if this is not doable)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
usually with both read & write function (in C), it's a good idea to provide the length of the buffer;
to be able to do some checks, in case the caller may goof something
void adi_write_packet(struct adi_dev *pkte_dev, u32 * source, u32 source_len)
drivers/crypto/adi/adi-pkte-hash.c
Outdated
n_length = pkte_dev->src_bytes_available; | ||
SIZE = (n_length > 128) ? 128 : (n_length); | ||
|
||
for (i = 0; i < (!!(SIZE % 4) + SIZE / 4); i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i would use an intermediate variable here;
``(!!(SIZE % 4) + SIZE / 4)` looks a bit quirky;
but feel free to disregard here; it may be just my preference
Ideally these files(this and a series of others before - these are basically ports of a non-upstream LTS branch to the current kernel version) are intended to be eventually submitted to the kernel mailing list. As you had correctly mentioned, there is a lot of work needed for re-spinning it in addition to feedback from the kernel maintainers. Hence, if possible, I would request an upstream review, however, any feedback at all would be appreciated. |
drivers/crypto/adi/adi-pkte-hash.c
Outdated
data_offset += DATAIO_BUF_OFFSET; | ||
|
||
n_length = pkte_dev->src_bytes_available; | ||
SIZE = (n_length > 128) ? 128 : (n_length); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
usually upper-case names are constants or macros;
also, this looks like a min()
function;
could this re-use a macro or generic min()
function from the kernel?
drivers/crypto/adi/adi-pkte-hash.c
Outdated
default: | ||
//Pad to 16 byte alignment/boundaries | ||
if (SIZE % 16 != 0) { | ||
nTotalSize = ((SIZE / 16) + 1) * 16; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nPadLength, nTotalSize are used here;
they could be declared in this scope (since it's a new scope), to reduce the number of variables declared in the function;
drivers/crypto/adi/adi-pkte-hash.c
Outdated
imsk_stat_offset = adi_read(pkte_dev, IMSK_STAT_OFFSET); | ||
pos = | ||
pkte_dev->flags & PKTE_AUTONOMOUS_MODE ? pkte_dev-> | ||
ring_pos_consume : 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ternary operators aren't preferred too often;
also, in this case, this looks more preferred:
if (pkte_dev->flags & PKTE_AUTONOMOUS_MODE)
pos = pkte_dev->ring_pos_consume;
else
pos = 0;
drivers/crypto/adi/adi-pkte-hash.c
Outdated
pkte-> | ||
pPkteList. | ||
pDestination)); | ||
SIZE = (n_length > 128) ? 128 : n_length; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
min()
function?
drivers/crypto/adi/adi-pkte-hash.c
Outdated
if (pkte->pPkteList.pCommand.hash == hash_sha256) | ||
SIZE = 8 * 4; /* Destination will be 8 word hash value */ | ||
|
||
if (SIZE % 4) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a way this could happen? i.e. (SIZE % 4) != 0
for a valid hash command?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if this could only happen for an invalid command, then maybe convert this to a switch statement?
or use the get_hash_command_params()
or get_hash_command_size()
approach?
drivers/crypto/adi/adi-pkte-hash.c
Outdated
SIZE = (n_length > 128) ? 128 : n_length; | ||
|
||
if (pkte->pPkteList.pCommand.opcode == opcode_hash) { | ||
if (pkte->pPkteList.pCommand.hash == hash_md5) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could this become a lookup table?
struct hash_command_param {
uint8_t hash_cmd;
uint32_t size;
}
then
static const struct hash_command_param hash_command_params[] = {
{ hash_md5, 4 * 4 } ,
{ hash_sha1, 5 * 4 } ,
{ hash_sha224, 7 * 4 },
{ hash_sha256, 8 * 4 },
};
then have a lookup table
static struct hash_command_param* get_hash_command_params(int hash_cmd) {
for (i = 0; i < ARARY_SIZE(hash_command_params); i++) {
struct hash_command_param *p = &hash_command_params[i];
if (p->cmd == hash_cmd)
return p;
}
return NULL;
}
the get_hash_command_params()
function could also just be a get_has_command_size()
function if there will be no other per-command parameter;
Changing implementation for a more efficient and modular approach. adi_read_packet() now calls adi_read_hash_to_dest() for handling various opcode and algorithm combinations. This also allows reusing code and increasing readibility. Signed-off-by: UtsavAgarwalADI <utsav.agarwal@analog.com>
Adding a check to adi_read_hash_to_dest() for making sure an invalid memory address is not written to Signed-off-by: UtsavAgarwalADI <utsav.agarwal@analog.com>
Added more variables for improved readability and removed unnecessary conditional statements for more code reuse Signed-off-by: UtsavAgarwalADI <utsav.agarwal@analog.com>
Changing how code waits for pkte device by introducing adi_wait_for_bit() - it can now timeout rather than waiting indefinitely, which then returns an error - code is now reused Changing implementation for adi_write_packet(). - now packet alignment to 16B, if required, is handled by a dedicated function. Changing implementation for adi_process_packet(). - added a dedicated debug function which can be enabled during compile time - added a dedicated function to handle resuming a previous packet processing operation - added checks which can return an error value Adding some general comments for increased readability All hash and CRC tests pass Signed-off-by: UtsavAgarwalADI <utsav.agarwal@analog.com>
Changing adi_wait_for_bit() to a common function between multiple kernel modules for increased code reuse - now used in adi-pkte-skcipher.c as well Modularising implementation of adi_crypt_configure_pkte - Replaced multiple if statements with LUT and switch statements for more efficient and compact code - Split function into multiple parts for code reuse and better readability Adding dedicated debug print functions Changing variable names for consistency with other modules - changed crypt to pkte_dev, as it is represented in adi-pkte-hash.c Signed-off-by: UtsavAgarwalADI <utsav.agarwal@analog.com>
I have tried addressing all of the above-mentioned concerns/suggestions. In addition, I have also attempted to try and remove any other redundant code and added checks for long/complex functions which previously could never fail. |
Signed-off-by: UtsavAgarwalADI <utsav.agarwal@analog.com>
04f6a49
to
f9c4dd9
Compare
Signed-off-by: UtsavAgarwalADI <utsav.agarwal@analog.com>
drivers/crypto/adi/adi-pkte-hash.c
Outdated
{ | ||
u32 i, n_pad_len = 0; | ||
|
||
if (packet_size % 16 != 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
early returns are preferred in kernel code;
if (packet_size % 16 == 0)
return 0;
the rationale is, that it creates less indentation
drivers/crypto/adi/adi-pkte-hash.c
Outdated
if((hash_type < ARRAY_SIZE(hash_params)) && (hash_type > 0)) | ||
return hash_params[hash_type].packet_size; | ||
|
||
//invalid hash command |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this comment is redundant;
but feel free to keep it;
drivers/crypto/adi/adi-pkte-hash.c
Outdated
|
||
pkte = pkte_dev->pkte_device; | ||
imsk_stat_offset = adi_read(pkte_dev, IMSK_STAT_OFFSET); | ||
if(pkte_dev->flags & PKTE_AUTONOMOUS_MODE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some kernel guidelines are also covered by the ./scripts/checkpatch.pl
script;
drivers/crypto/adi/adi-pkte-hash.c
Outdated
else | ||
pos = 0; | ||
|
||
if ((imsk_stat_offset & BITM_PKTE_IMSK_EN_OPDN) != |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inverting this conditio, also for an early return;
and can be moved right after reading imsk_stat_offset = adi_read(pkte_dev, IMSK_STAT_OFFSET);
so
imsk_stat_offset = adi_read(pkte_dev, IMSK_STAT_OFFSET);
imsk_stat_offset &= BITM_PKTE_IMSK_EN_OPDN;
if (imsk_stat_offset == BITM_PKTE_IMSK_EN_OPDN)
return 0;
```
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, and obviously, less indentation in the next block :)
drivers/crypto/adi/adi-pkte-hash.c
Outdated
*dev_final_hash |= | ||
hash_source_state << BITP_PKTE_SA_CMD0_HASHSRC; | ||
sa_record->SA_Para.SA_CMD0 = *dev_final_hash; | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not that it makes much difference here, but coming back to early returns:
if (pkte_dev->flags & PKTE_AUTONOMOUS_MODE) {
pos = pkte_dev->ring_pos_consume;
sa_record = &pkte_dev->pkte_device->pPkteDescriptor.SARecord[pos];
*dev_final_hash = sa_record->SA_Para.SA_CMD0;
*dev_final_hash &= ~BITM_PKTE_SA_CMD0_HASHSRC;
*dev_final_hash |=
hash_source_state << BITP_PKTE_SA_CMD0_HASHSRC;
sa_record->SA_Para.SA_CMD0 = *dev_final_hash;
+ return;
}
then the rest of the block can be un-indented one-level
} else { | ||
dev_err(pkte_dev->dev, "Key length exceeds limit!\n"); | ||
return -ENOMEM; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here:
if (keylen > PKTE_MAX_KEY_SIZE) {
dev_err(pkte_dev->dev, "Key length exceeds limit!\n");
return -ENOMEM;
}
then more code can be un-indented one level
|
||
//Endian Swap! | ||
if (pkte->pPkteList.pCommand.hash == hash_md5) { | ||
memcpy(hash, pkte->pPkteList.pDestination, rctx->digcnt); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a return
here can allow the un-indentation of the else block;
then hash[i] = __builtin_bswap32(pkte->pPkteList.pDestination[i]);
this may fit on one line
drivers/crypto/adi/adi-pkte-hash.c
Outdated
dev_dbg(pkte_dev->dev, "%s flags %lx\n", __func__, pkte_dev->flags); | ||
pkte = pkte_dev->pkte_device; | ||
|
||
if (!err && (PKTE_FLAGS_FINAL & pkte_dev->flags)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
especially here it looks useful
if (err || (PKTE_FLAGS_FINAL & pkte_dev->flags))
return:
and all the rest can be un-indented
drivers/crypto/adi/adi-pkte-hash.c
Outdated
adi_finish_req(req, err); | ||
|
||
return err; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: empty line
drivers/crypto/adi/adi_crc.c
Outdated
|
||
ret = dmaengine_slave_config(crc->dma_ch, &dma_config); | ||
if (ret) { | ||
dev_err(crc->dev, "Error configuring DMA channel\n"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it may be useful to also print the ret
value in the error message;
for debugging
drivers/crypto/adi/adi_crc.c
Outdated
if (!req->nbytes) | ||
return 0; | ||
|
||
if (ctx->total + req->nbytes <= BUFLEN) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (ctx->total + req->nbytes > BUFLEN)
return -ENOBUFS;
#define POLYMIRR 0x00200000 /* CRC poly register is mirrored. */ | ||
#define POLYMIRR_OFFSET 21 /* Mirror CRC poly offset. */ | ||
#define CMPMIRR 0x00400000 /* CRC compare register is mirrored. */ | ||
#define CMPMIRR_OFFSET 22 /* Mirror CRC compare offset. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as a note: in the kernel, there are some neat macros for bits/mask
for example
#define CMPMIRR BIT(22)
; or if it's a mask (bit-range) it would be (for example) #define CMPMIRR_MASK GETMASK(22, 20)
(in this example, bits 22 and 20 are pare of the mask);
then they can be used to mask values with the FIELD_PREP()
macro
Signed-off-by: UtsavAgarwalADI <utsav.agarwal@analog.com>
Adding Early returns for functions where possible Adding more variables to avoid long pointer strings Replacing ternary operators with if else statements for simplicity/readibility Signed-off-by: UtsavAgarwalADI <utsav.agarwal@analog.com>
Adding better indentation Adding early returns where possible Signed-off-by: UtsavAgarwalADI <utsav.agarwal@analog.com>
drivers/crypto/adi/adi-pkte.c
Outdated
const u32 IDigest[8] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; | ||
const u32 ODigest[8] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; | ||
|
||
u32 IV[4] = { 0x0, 0x0, 0x0, 0x0 }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are these global variables, state variables for the chip?
if yes, it is recommended to make part of the struct adi_dev
or some instance struct;
the reason being: in some cases there could be more than 1 chip in the system;
then 1 chip state-info would overwrite the state info for all chips;
Adding Key, Idigest, Odigest, IV as members of adi_dev. - Allows managing multiple devices by assigning each one a separate context Signed-off-by: UtsavAgarwalADI <utsav.agarwal@analog.com>
Making minor changes in accordance with kernel guidelines(checkpatch) Signed-off-by: UtsavAgarwalADI <utsav.agarwal@analog.com>
PR Description
necessary to understand them. List any dependencies required for this change.
any space), or simply check them after publishing the PR.
description and try to push all related PRs simultaneously.
PR Type
PR Checklist
NOTE: hardware cryptographic functions were not tested at the moment due to absence of the devcrypto engine userspace library