Skip to content
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

driver: crypto: hisilicon: add rsa algorithm #7123

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

yuzexiyzx
Copy link
Contributor

@yuzexiyzx yuzexiyzx commented Nov 13, 2024

add rsa algorithm

Copy link
Contributor

@jenswi-linaro jenswi-linaro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The commit message needs to be fixed up. It looks like it was removed by mistake.

switch (msg->alg_type) {
case HPRE_ALG_KG_CRT:
memzero_explicit(msg->in, msg->key_bytes << 1);
free(msg->in);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can free_wipe() be used instead of memzero_explicit()+free()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

paddr_t pubkey_dma;
uint8_t *prikey;
paddr_t prikey_dma;
uint8_t *in;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice with a summary of all the expected sizes of these buffers and how they relate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is different in encrypt and decrypt,also in crt and ncrt. Expected size of these buffers and how they relate can be seen in alloc function of every mode, such as hpre_rsa_crt_decrypt_alloc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It sounds like it's even more important since it makes it harder to work out backward.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to describe the buffer layout for HPRE_RSA_CRT_TOTAL_BUF_SIZE() and HPRE_RSA_NCRT_TOTAL_BUF_SIZE() above?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

#include <tee_api_types.h>
#include <types_ext.h>

#define PKCS_V1_5_MSG_MIN_LEN 11
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please align all the values

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

@@ -0,0 +1,47 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (c) 2022, HiSilicon Technologies Co., Ltd.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's 2024 now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

@@ -8,3 +8,5 @@ srcs-$(CFG_HISILICON_ACC_V3) += hpre_main.c
srcs-$(CFG_HISILICON_ACC_V3) += hpre_dh.c
srcs-$(CFG_HISILICON_ACC_V3) += hpre_ecc.c
srcs-$(CFG_HISILICON_ACC_V3) += hpre_montgomery.c
srcs-$(CFG_HISILICON_ACC_V3) += hpre_rsa.c

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary empty line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You missed this review comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

mbedtls_mpi_free(&G);
mbedtls_mpi_free(&L);

return ret;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ret is always 0. Could change this to return 0?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved


if (mbedtls_mpi_bitlen(&rsa.D) <= ((nbits + 1) >> 1))
continue;
break;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion:

		if (mbedtls_mpi_bitlen(&rsa.D) > ((nbits + 1) >> 1))
			break;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

else if (key_bits <= 4096)
size = BITS_TO_BYTES(4096);
else
EMSG("Invalid key_bits[%"PRIu64"]", key_bits);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/%"PRIu64"/%zu/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

#include <string_ext.h>
#include <trace.h>
#include <mbedtls/rsa.h>
#include <tee/tee_cryp_utl.h>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

order

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

return HISI_QM_DRVCRYPT_NO_ERR;
case HPRE_ALG_NC_NCRT:
case HPRE_ALG_NC_CRT:
if (msg->is_private) { /* DECRYPT */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prefer

		if (msg->is_private) {
			/* DECRYPT */
			...
		} else {
			/* ENCRYPT */
			...
		}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

TEE_Result ret = TEE_SUCCESS;

if (rsa_data->message.length > n_bytes) {
EMSG("Invalid msg length[%"PRIu64"]", rsa_data->message.length);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

%zu for size_t type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

struct drvcrypt_rsa_ed rsa_enc_info = { };
TEE_Result ret = TEE_SUCCESS;

memcpy(&rsa_enc_info, rsa_data, sizeof(rsa_enc_info));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prefer rsa_enc_info = *rsa_data;
or simply struct drvcrypt_rsa_ed rsa_enc_info = *rsa_data; at line 717.

Ditto at lines 845, 1191 and 1327.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

if (ret)
return ret;

(void)hw_get_random_bytes(seed, lhash_len);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency, prefer test the return code, even if hw_get_random_bytes() from hi16xx_rng.c always succeeds.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

@yuzexiyzx
Copy link
Contributor Author

@jenswi-linaro @etienne-lms All comments have been solved

Copy link
Contributor

@etienne-lms etienne-lms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you fix the build issues reported by CI / make?

@@ -8,3 +8,5 @@ srcs-$(CFG_HISILICON_ACC_V3) += hpre_main.c
srcs-$(CFG_HISILICON_ACC_V3) += hpre_dh.c
srcs-$(CFG_HISILICON_ACC_V3) += hpre_ecc.c
srcs-$(CFG_HISILICON_ACC_V3) += hpre_montgomery.c
srcs-$(CFG_HISILICON_ACC_V3) += hpre_rsa.c

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You missed this review comment.

@yuzexiyzx
Copy link
Contributor Author

image
@etienne-lms Sorry, I do not know how to deal with this. I can find member P and Q in mbedtls code, and there is no such error when I compile it. Could you please give me some suggestion? Thank you very much

static int32_t hpre_rsa_gen_p_q(size_t nbits, struct rsa_keypair *key)
{
int32_t prime_quality = 0;
mbedtls_rsa_context rsa = { };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should use the crypto API from <crypto/crypto.h> as an abstraction instead of reaching directly into mbedtls. sw_crypto_acipher_gen_rsa_key() might be useful here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I just want to generate p and q here, and then generate rsa_keypair from p and q by hardware.
sw_crypto_acipher_gen_rsa_key() might generate the whole rsa_keypair directly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You've already generated a keypair before calling hpre_rsa_fill_p_q(), only the CRT parameters remain.
The heavy lifting has already been done, even if you decide to throw away D and E. What is hpre_rsa_fill_p_q() supposed to do? Recreate D and E and then deduce the CRT parameters?
By the way, hpre_rsa_gen_p_q() looks like a slightly hacked-up copy of mbedtls_rsa_gen_key().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we call hpre_rsa_gen_keypiar, we already have key->e.
We hope hpre_rsa_keypair _init only generate key->p and key->q,The function of hpre_rsa_fill_p_q is to copy p and q to rsa_keypair.
And then, hpre_rsa_init and hpre_rsa_do_task use hardware to calculate N,D(ncrt mode) or dP,dQ ,qInv,N,D(crt mode).
The input is key->e,key->p and key->q.

Do you mean I can use mbedtls_rsa_gen_key() instead of hpre_rsa_gen_p_q, and just throw away D and E?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we call hpre_rsa_gen_keypiar, we already have key->e.

You're right, that's an input parameter.

We hope hpre_rsa_keypair _init only generate key->p and key->q,The function of hpre_rsa_fill_p_q is to copy p and q to rsa_keypair. And then, hpre_rsa_init and hpre_rsa_do_task use hardware to calculate N,D(ncrt mode) or dP,dQ ,qInv,N,D(crt mode). The input is key->e,key->p and key->q.

The process to generate P and Q involves a few checks to see that the values are good. This is an iterative process that is restarted if any of the tests fail. Checking that the produced D is large enough is one of the checks. So the assumption that you can ask for just two good values for P and Q leaves a few holes.

What is the purpose of using hardware to calculate N, D, and the CRT parameters? Is it more secure? Is it faster?

Without trying to benchmark hpre_rsa_gen_p_q() I believe that most of the time is spent in the calls to mbedtls_mpi_gen_prime() when generating the key.

Do you mean I can use mbedtls_rsa_gen_key() instead of hpre_rsa_gen_p_q, and just throw away D and E?

No, but if that's the best you can do with the hardware when generating an RSA key why bother with the hardware?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I should do rsa_gen_keypair just with software, not implement this mode with hardware?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean I should just not register hpre_rsa_genkeypair or call mbedtls_rsa_gen_key() in hpre_rsa_genkeypair without hardware.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I should do rsa_gen_keypair just with software, not implement this mode with hardware?

Yes, we can do that for now. We can improve that later if someone comes up with something better.

The easiest should be to register .gen_keypair = sw_crypto_acipher_gen_rsa_key. Please look at the other sw_crypto_acipher_*() functions. It looks like for instance sw_crypto_acipher_alloc_rsa_keypair() and sw_crypto_acipher_free_rsa_keypair() does the same thing as hpre_rsa_allocate_keypair() and hpre_rsa_free_keypair().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get it. Thank you very much.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

@yuzexiyzx yuzexiyzx force-pushed the master branch 2 times, most recently from c57b4ca to 3a3e653 Compare December 10, 2024 03:29
Copy link
Contributor

@jenswi-linaro jenswi-linaro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix the build error and the checkpatch warning that isn't about a print.

return drvcrypt_xor_mod_n(&xor_mod);
}

static TEE_Result hpre_rsa_allocate_publickey(struct rsa_public_key *key,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sw_crypto_acipher_alloc_rsa_public_key() can be used instead of this function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

return TEE_SUCCESS;
}

static void hpre_rsa_free_publickey(struct rsa_public_key *key)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sw_crypto_acipher_free_rsa_public_key() can be used instead of this function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

return ret;
}

static int32_t hpre_rsa_is_crt_mod(struct rsa_keypair *key)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use bool instead of int32_t.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

key->dp && crypto_bignum_num_bits(key->dp) &&
key->dq && crypto_bignum_num_bits(key->dq) &&
key->qp && crypto_bignum_num_bits(key->qp))
is_crt = 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return true;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

key->qp && crypto_bignum_num_bits(key->qp))
is_crt = 1;

return is_crt;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return false;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

msg->alg_type = HPRE_ALG_NC_CRT;
ret = hpre_rsa_crt_decrypt_alloc(msg);
if (ret)
return TEE_ERROR_BAD_STATE;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why TEE_ERROR_BAD_STATE and not TEE_ERROR_OUT_OF_MEMORY?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You missed this comment.

msg->pubkey = data;
msg->pubkey_dma = virt_to_phys(msg->pubkey);

msg->in = data + (msg->key_bytes << 1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you use << 1 instead of * 2?
I prefer * 2 since we care about the value here, not the position of the bits.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

@@ -8,3 +8,4 @@ srcs-$(CFG_HISILICON_ACC_V3) += hpre_main.c
srcs-$(CFG_HISILICON_ACC_V3) += hpre_dh.c
srcs-$(CFG_HISILICON_ACC_V3) += hpre_ecc.c
srcs-$(CFG_HISILICON_ACC_V3) += hpre_montgomery.c
srcs-$(CFG_HISILICON_ACC_V3) += hpre_rsa.c
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add the missing newline at the end of the file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

#define OAEP_MAX_HASH_LEN 64
#define OAEP_MAX_DB_LEN 512
#define PRIME_QUALITY_FLAG 1024
#define HPRE_RSA_GEN_TOTAL_BUF_SIZE(kbytes) ((kbytes) * 7)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This macro is unused. Will it be needed in later patches?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

paddr_t pubkey_dma;
uint8_t *prikey;
paddr_t prikey_dma;
uint8_t *in;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to describe the buffer layout for HPRE_RSA_CRT_TOTAL_BUF_SIZE() and HPRE_RSA_NCRT_TOTAL_BUF_SIZE() above?

Copy link
Contributor

@etienne-lms etienne-lms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In commit message header line: s/rsa/RSA/
In commit message body: prefer a more explicit description (even if it rephrases the header line), e.g. Add RSA support in HiSilicon crypto drivers.

*/

#ifndef __TEE_HPRE_RSA_H__
#define __TEE_HPRE_RSA_H__
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer __HPRE_RSA_H__ or __HISILICON_HPRE_RSA_H__ as per header file name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

rsa_qp->parse_sqe = hpre_rsa_parse_sqe;
ret = hisi_qp_send(rsa_qp, msg);
if (ret) {
EMSG("Fail to send task, ret=%d", ret);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ret=%x"PRIx32, ret);
Ditto at line 103

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved


static void hpre_rsa_params_free(struct hpre_rsa_msg *msg)
{
size_t len = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

len is not used (see CI / make (multi-platform) results).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

{
size_t lhash_len = rsa_data->digest_size;
uint8_t db[OAEP_MAX_DB_LEN] = { };
uint8_t seed[OAEP_MAX_HASH_LEN];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

= { }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved


msg->prikey = data;
msg->prikey_dma = virt_to_phys(msg->prikey);
if (!msg->prikey_dma) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

virt_to_phys() cannot fail on a non NULL address returned by calloc().
Ditto at line 614.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

msg_len = db_len - lp_len - 1;
if (msg_len > rsa_data->message.length) {
EMSG("Message space is not enough");
return TEE_ERROR_SHORT_BUFFER;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set *out_len = msg_len to help caller to get to required size.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would replace EMSG() with DMSG() at line 918 since this may not be a error case but an output buffer length query from the caller.

*/
.ssa_sign = NULL,
.ssa_verify = NULL,
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These explicit NULL inits are not required. But maybe you prefer to have them for the reader information.

@yuzexiyzx yuzexiyzx force-pushed the master branch 3 times, most recently from ac80ae4 to 887f761 Compare December 16, 2024 02:48
@yuzexiyzx
Copy link
Contributor Author

@jenswi-linaro @etienne-lms All comments have been solved.
The errors in code style are all about print.
image

add RSA support in Hisilicon crypto drivers

Signed-off-by: yuzexi <[email protected]>
struct hpre_sqe *sqe)
{
switch (msg->alg_type) {
case HPRE_ALG_KG_CRT: /* KEY GEN */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

	case HPRE_ALG_KG_CRT:
		/* KEY GEN */
		(...)

msg->alg_type = HPRE_ALG_NC_CRT;
ret = hpre_rsa_crt_decrypt_alloc(msg);
if (ret)
return TEE_ERROR_BAD_STATE;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You missed this comment.

msg_len = db_len - lp_len - 1;
if (msg_len > rsa_data->message.length) {
EMSG("Message space is not enough");
return TEE_ERROR_SHORT_BUFFER;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would replace EMSG() with DMSG() at line 918 since this may not be a error case but an output buffer length query from the caller.

{
switch (msg->alg_type) {
case HPRE_ALG_KG_CRT:
free_wipe(msg->in);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see where msg->in is an allocated pointer. I think at this stage, msg->in is always NULL.


ret = hpre_rsa_encrypt_alloc(msg);
if (ret)
return TEE_ERROR_BAD_STATE;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TEE_ERROR_OUT_OF_MEMORY?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants