Files
base/drivers/source/crypto/mailbox/sdrv_crypto_mailbox_eccp.c
2025-11-07 09:57:14 +08:00

458 lines
15 KiB
C

/**
* @file sdrv_crypto_mailbox_eccp.c
* @brief SemiDrive CRYPTO mailbox eccp api source file.
*
* @copyright Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*/
#include <sdrv_crypto_mailbox_eccp.h>
/**
* @brief eccp point doubling.
*
* This function get eccp point doubling.
*
* @param[in] curve_id curve_id.
* @param[in] G_x_y curve xy buff.
* @param[out] output_x_y out buff.
* @return CMD_RETURN_SUCCESS or error code.
*/
sdrv_crypto_error_status_e cmd_eccp_point_doubling(uint8_t curve_id,
uint8_t *G_x_y,
uint8_t *output_x_y)
{
uint32_t cmd_buf[8] = {0};
uint32_t ret = 0;
cmd_eccp_pointdoubling_t *cmd_eccp_dbl = NULL;
/*********** point dbl ***********/
cmd_eccp_dbl = (cmd_eccp_pointdoubling_t *)cmd_buf;
cmd_eccp_dbl->cmd_id = ECCP_POINT_DOUBLING;
cmd_eccp_dbl->curve_id = curve_id;
set_big_endian_4byte((uint8_t *)cmd_eccp_dbl->inputPoint_ptr,
(uint32_t)G_x_y);
set_big_endian_4byte((uint8_t *)cmd_eccp_dbl->outputPoint_ptr,
(uint32_t)output_x_y);
ret = send_cmd_and_wait_response((uint32_t *)cmd_buf);
if (SEIP_SUCCESS == ret) {
printf("ECCP_POINT_DOUBLING success \n");
} else {
printf("ECCP_POINT_DOUBLING error, ret = 0x%x \n", ret);
return CMD_RETURN_FAIL;
}
return CMD_RETURN_SUCCESS;
}
/**
* @brief eccp point addition.
*
* This function get eccp point addition.
*
* @param[in] curve_id curve_id.
* @param[in] kG_x_y kG_x_y buff.
* @param[in] dblG_x_y dblG_x_y buff.
* @param[out] output_x_y out buff.
* @return CMD_RETURN_SUCCESS or error code.
*/
sdrv_crypto_error_status_e cmd_eccp_point_addition(uint8_t curve_id,
uint8_t *kG_x_y,
uint8_t *dblG_x_y,
uint8_t *output_x_y)
{
uint32_t cmd_buf[8] = {0};
uint32_t ret = 0;
cmd_eccp_pointaddition_t *cmd_eccp_add = NULL;
/*********** point add ***********/
cmd_eccp_add = (cmd_eccp_pointaddition_t *)cmd_buf;
cmd_eccp_add->cmd_id = ECCP_POINT_ADDITION;
cmd_eccp_add->curve_id = curve_id;
set_big_endian_4byte((uint8_t *)cmd_eccp_add->inputPoint1_ptr,
(uint32_t)kG_x_y);
set_big_endian_4byte((uint8_t *)cmd_eccp_add->inputPoint2_ptr,
(uint32_t)dblG_x_y);
set_big_endian_4byte((uint8_t *)cmd_eccp_add->outputPoint_ptr,
(uint32_t)output_x_y);
ret = send_cmd_and_wait_response((uint32_t *)cmd_buf);
if (SEIP_SUCCESS == ret) {
printf("ECCP_POINT_ADDITION success \n");
} else {
printf("ECCP_POINT_ADDITION error, ret = 0x%x \n", ret);
return CMD_RETURN_FAIL;
}
return CMD_RETURN_SUCCESS;
}
/**
* @brief eccp point multplication.
*
* This function get eccp point multplication.
*
* @param[in] curve_id curved id.
* @param[in] G_x_y point value.
* @param[in] k scalar value.
* @param[out] output_x_y out buff.
* @return CMD_RETURN_SUCCESS or error code.
*/
sdrv_crypto_error_status_e cmd_eccp_point_multiplication(uint8_t curve_id,
uint8_t *G_x_y,
uint8_t *k,
uint8_t *output_x_y)
{
uint32_t cmd_buf[8] = {0};
uint32_t ret = 0;
cmd_eccp_pointmultiplication_t *cmd_eccp_mul = NULL;
/*********** point mul ***********/
cmd_eccp_mul = (cmd_eccp_pointmultiplication_t *)cmd_buf;
cmd_eccp_mul->cmd_id = ECCP_POINT_MULTIPLICATION;
cmd_eccp_mul->curve_id = curve_id;
set_big_endian_4byte((uint8_t *)cmd_eccp_mul->inputScalar_ptr, (uint32_t)k);
set_big_endian_4byte((uint8_t *)cmd_eccp_mul->inputPoint_ptr,
(uint32_t)G_x_y);
set_big_endian_4byte((uint8_t *)cmd_eccp_mul->outputPoint_ptr,
(uint32_t)output_x_y);
ret = send_cmd_and_wait_response((uint32_t *)cmd_buf);
if (SEIP_SUCCESS == ret) {
printf("ECCP_POINT_MULTIPLICATION success \n");
} else {
printf("ECCP_POINT_MULTIPLICATION error, ret = 0x%x \n", ret);
return CMD_RETURN_FAIL;
}
return CMD_RETURN_SUCCESS;
}
/**
* @brief eccp point verify.
*
* This function verify eccp point.
*
* @param[in] curve_id curved id.
* @param[in] G_x_y point value.
* @return CMD_RETURN_SUCCESS or error code.
*/
sdrv_crypto_error_status_e cmd_eccp_point_verify(uint8_t curve_id,
uint8_t *G_x_y)
{
uint32_t cmd_buf[8] = {0};
uint32_t ret = 0;
cmd_eccp_pointverifying_t *cmd_eccp_verify = NULL;
/*********** point verify ***********/
cmd_eccp_verify = (cmd_eccp_pointverifying_t *)cmd_buf;
cmd_eccp_verify->cmd_id = ECCP_POINT_VERIFY;
cmd_eccp_verify->curve_id = curve_id;
set_big_endian_4byte((uint8_t *)cmd_eccp_verify->inputPoint_ptr,
(uint32_t)G_x_y);
ret = send_cmd_and_wait_response((uint32_t *)cmd_buf);
if (SEIP_SUCCESS == ret) {
printf("ECCP_POINT_VERIFY success \n");
} else {
printf("ECCP_POINT_VERIFY error , ret = 0x%x \n", ret);
return CMD_RETURN_FAIL;
}
return CMD_RETURN_SUCCESS;
}
/**
* @brief eccp generate ecdh keypair.
*
* This function generate ecdh keypair.
*
* @param[in] curve_id curved id.
* @param[out] prikey prikey buff.
* @param[out] pubkey pubkey buff.
* @param[in] generate_key_type pri and pub key output type.
* @param[in] generate_key_id for enc key.
* @param[in] mac_buf key_id mac buf.
* @return CMD_RETURN_SUCCESS or error code.
*/
sdrv_crypto_error_status_e cmd_eccp_ecdh_generate_keypair(
uint8_t curve_id, uint8_t *prikey, uint8_t *pubkey,
cmd_key_type_e generate_key_type, uint16_t generate_key_id,
uint8_t *mac_buf)
{
sdrv_crypto_error_status_e RetVal = CMD_RETURN_FAIL;
uint16_t key_id_array[2];
uint32_t cmd_buf[8] = {0};
uint32_t ret = 0;
uint8_t count;
cmd_eccp_generatekey_t *cmd_eccp_get_key = NULL;
/*********** get key pair ***********/
cmd_eccp_get_key = (cmd_eccp_generatekey_t *)cmd_buf;
cmd_eccp_get_key->cmd_id = ECCP_GENERATE_KEY;
if (CMD_KEY_EXTERNAL_PLAINTEXT == generate_key_type) {
key_id_array[0] = 0;
} else if (CMD_KEY_EXTERNAL_CIPHERTEXT == generate_key_type) {
key_id_array[0] = generate_key_id;
} else {
key_id_array[0] = 0;
}
set_big_endian_2byte((uint8_t *)cmd_eccp_get_key->key_id, key_id_array[0]);
cmd_eccp_get_key->curve_id = curve_id;
set_big_endian_4byte((uint8_t *)cmd_eccp_get_key->pubKey_ptr,
(uint32_t)pubkey);
set_big_endian_4byte((uint8_t *)cmd_eccp_get_key->priKey_ptr,
(uint32_t)prikey);
set_big_endian_4byte((uint8_t *)cmd_eccp_get_key->aut_info_ptr,
(uint32_t)mac_buf);
get_otp_key_aut_mac(key_id_array, 1, (uint8_t *)cmd_buf, mac_buf);
count = RETRY_COUNT;
do {
ret = send_cmd_and_wait_response((uint32_t *)cmd_buf);
if (SEIP_SUCCESS == ret) {
RetVal = CMD_RETURN_SUCCESS;
break;
} else if (SEIP_ERROR_ECC_GET_KEY_FAIL == ret) {
RetVal = CMD_RETURN_FAIL;
/* retry */
} else {
RetVal = CMD_RETURN_FAIL;
break;
}
count--;
} while (count);
return RetVal;
}
/**
* @brief ecdh exchange key.
*
* This function for ecdh exchange key.
*
* @param[in] curve_id curved id.
* @param[in] key_len key len.
* @param[out] KA key buff.
* @param[in] pubkey_B PeerPubKey buff.
* @param[in] prikey_A selfPrikey buff.
* @param[in] ecdh_key_type selfPrikey type.
* @param[in] ecdh_key_id for enc key.
* @param[in] output_key_type output key type.
* @param[in] output_key_id for enc key.
* @param[in] mac_buf key_id mac buf.
* @return CMD_RETURN_SUCCESS or error code.
*/
sdrv_crypto_error_status_e cmd_eccp_ecdh_exchange_key(
uint8_t curve_id, uint8_t key_len, uint8_t *KA, uint8_t *pubkey_B,
uint8_t *prikey_A, cmd_key_type_e ecdh_key_type, uint16_t ecdh_key_id,
cmd_key_type_e output_key_type, uint16_t output_key_id, uint8_t *mac_buf)
{
uint16_t key_id_array[3];
uint32_t cmd_buf[8] = {0};
uint32_t ret = 0;
cmd_ecdh_exchangekey_t *cmd_eccp_exc_key = NULL;
/*********** calc ***********/
cmd_eccp_exc_key = (cmd_ecdh_exchangekey_t *)cmd_buf;
cmd_eccp_exc_key->cmd_id = ECDH_EXCHANGE_KEY;
cmd_eccp_exc_key->curve_id = curve_id;
set_big_endian_4byte((uint8_t *)cmd_eccp_exc_key->PeerPubKey_ptr,
(uint32_t)pubkey_B);
set_big_endian_4byte((uint8_t *)cmd_eccp_exc_key->aut_info_ptr,
(uint32_t)mac_buf);
if (CMD_KEY_EXTERNAL_PLAINTEXT == ecdh_key_type) {
set_big_endian_4byte((uint8_t *)cmd_eccp_exc_key->selfPrikey_ptr,
(uint32_t)prikey_A);
key_id_array[0] = 0;
key_id_array[1] = 0;
} else if (CMD_KEY_EXTERNAL_CIPHERTEXT == ecdh_key_type) {
set_big_endian_4byte((uint8_t *)cmd_eccp_exc_key->selfPrikey_ptr,
(uint32_t)prikey_A);
key_id_array[0] = 0;
key_id_array[1] = ecdh_key_id;
} else if (CMD_KEY_INTERNAL == ecdh_key_type) {
set_big_endian_4byte((uint8_t *)cmd_eccp_exc_key->selfPrikey_ptr, 0);
key_id_array[0] = ecdh_key_id;
key_id_array[1] = 0;
} else {
return CMD_RETURN_FAIL;
}
set_big_endian_2byte((uint8_t *)cmd_eccp_exc_key->key_id0, key_id_array[0]);
set_big_endian_2byte((uint8_t *)cmd_eccp_exc_key->key_id1, key_id_array[1]);
cmd_eccp_exc_key->key_len = key_len;
set_big_endian_4byte((uint8_t *)cmd_eccp_exc_key->key_ptr, (uint32_t)KA);
if (CMD_KEY_EXTERNAL_PLAINTEXT == output_key_type) {
key_id_array[2] = 0;
} else if (CMD_KEY_EXTERNAL_CIPHERTEXT == output_key_type) {
key_id_array[2] = output_key_id;
} else {
key_id_array[2] = 0;
}
set_big_endian_2byte((uint8_t *)cmd_eccp_exc_key->key_id2, key_id_array[2]);
uint32_clear((uint32_t *)mac_buf, 4 * 2);
get_otp_key_aut_mac(key_id_array, 3, (uint8_t *)cmd_buf, mac_buf);
ret = send_cmd_and_wait_response((uint32_t *)cmd_buf);
if (SEIP_SUCCESS == ret) {
} else {
printf("calc error, ret = 0x%x \n", ret);
return CMD_RETURN_FAIL;
}
return CMD_RETURN_SUCCESS;
}
/**
* @brief eccp ecdsa gen signature.
*
* This function for ecdsa gen signature.
*
* @param[in] curve_id curved id.
* @param[in] e e value.
* @param[out] e_len e len.
* @param[in] sign_key_type sign key type.
* @param[in] sign_key_id sign key id.
* @param[in] prikey prikey value.
* @param[out] signature signature value.
* @param[in] mac_buf key_id mac buf.
* @return CMD_RETURN_SUCCESS or error code.
*/
sdrv_crypto_error_status_e cmd_eccp_ecdsa_gen_signature(
uint8_t curve_id, uint8_t *e, uint32_t e_len,
cmd_key_type_e sign_key_type, uint16_t sign_key_id,
uint8_t *prikey, uint8_t *signature, uint8_t *mac_buf)
{
sdrv_crypto_error_status_e RetVal = CMD_RETURN_FAIL;
uint8_t count;
uint16_t key_id_array[2];
uint32_t cmd_buf[8] = {0};
uint32_t ret = 0;
cmd_ecdsa_generatesignature_t *cmd_ecdsa_sign = NULL;
/*********** ecdsa sign ***********/
cmd_ecdsa_sign = (cmd_ecdsa_generatesignature_t *)cmd_buf;
cmd_ecdsa_sign->cmd_id = ECDSA_GENERATE_SIGNATURE;
cmd_ecdsa_sign->curve_id = curve_id;
cmd_ecdsa_sign->e_len = e_len;
set_big_endian_4byte((uint8_t *)cmd_ecdsa_sign->e_ptr, (uint32_t)e);
set_big_endian_4byte((uint8_t *)cmd_ecdsa_sign->aut_info_ptr,
(uint32_t)mac_buf);
if (CMD_KEY_EXTERNAL_PLAINTEXT == sign_key_type) {
key_id_array[0] = 0;
key_id_array[1] = 0;
set_big_endian_4byte((uint8_t *)cmd_ecdsa_sign->priKey_ptr,
(uint32_t)prikey);
} else if (CMD_KEY_EXTERNAL_CIPHERTEXT == sign_key_type) {
key_id_array[0] = 0;
key_id_array[1] = sign_key_id;
set_big_endian_4byte((uint8_t *)cmd_ecdsa_sign->priKey_ptr,
(uint32_t)prikey);
} else if (CMD_KEY_INTERNAL == sign_key_type) {
set_big_endian_4byte((uint8_t *)cmd_ecdsa_sign->priKey_ptr, 0);
key_id_array[0] = sign_key_id;
key_id_array[1] = 0;
} else {
return CMD_RETURN_FAIL;
}
set_big_endian_2byte((uint8_t *)cmd_ecdsa_sign->key_id0, key_id_array[0]);
set_big_endian_2byte((uint8_t *)cmd_ecdsa_sign->key_id1, key_id_array[1]);
set_big_endian_4byte((uint8_t *)cmd_ecdsa_sign->signature_ptr,
(uint32_t)signature);
get_otp_key_aut_mac(key_id_array, 2, (uint8_t *)cmd_buf, mac_buf);
count = RETRY_COUNT;
do {
ret = send_cmd_and_wait_response((uint32_t *)cmd_buf);
if (SEIP_SUCCESS == ret) {
RetVal = CMD_RETURN_SUCCESS;
break;
} else if (SEIP_ERROR_ECDSA_VERIFY_FAIL == ret) {
RetVal = CMD_RETURN_FAIL;
/* retry */
} else {
RetVal = CMD_RETURN_FAIL;
break;
}
count--;
} while (count);
return RetVal;
}
/**
* @brief eccp point verify.
*
* This function verify eccp point.
*
* @param[in] curve_id curved id.
* @param[in] e e value.
* @param[out] e_len e len.
* @param[in] pubkey pubkey value.
* @param[in] signature signature value.
* @return CMD_RETURN_SUCCESS or error code.
*/
sdrv_crypto_error_status_e cmd_eccp_ecdsa_verify_signature(uint8_t curve_id,
uint8_t *e,
uint32_t e_len,
uint8_t *pubkey,
uint8_t *signature)
{
uint32_t cmd_buf[8] = {0};
uint32_t ret = 0;
cmd_ecdsa_verifysignature_t *cmd_ecdsa_verify = NULL;
/*********** ecdsa verify ***********/
cmd_ecdsa_verify = (cmd_ecdsa_verifysignature_t *)cmd_buf;
cmd_ecdsa_verify->cmd_id = ECDSA_VERIFY_SIGNATURE;
cmd_ecdsa_verify->curve_id = curve_id;
cmd_ecdsa_verify->e_len = e_len;
set_big_endian_4byte((uint8_t *)cmd_ecdsa_verify->e_ptr, (uint32_t)e);
set_big_endian_4byte((uint8_t *)cmd_ecdsa_verify->pubKey_ptr,
(uint32_t)pubkey);
set_big_endian_4byte((uint8_t *)cmd_ecdsa_verify->signature_ptr,
(uint32_t)signature);
ret = send_cmd_and_wait_response((uint32_t *)cmd_buf);
if (SEIP_SUCCESS == ret) {
printf("ecdsa verify pass \n");
} else {
printf("ecdsa verify error, ret = 0x%x \n", ret);
return CMD_RETURN_FAIL;
}
return CMD_RETURN_SUCCESS;
}