Files
E3/e3_176_ref/drivers/source/crypto/cacc/pke/x25519.c
2025-10-21 19:40:27 +08:00

270 lines
6.8 KiB
C

/*****************************************************************************
*
*
*Copyright (c) 2021-2029 Semidrive Incorporated. All rights reserved.
*Software License Agreement
*
******************************************************************************
*/
#include <pke.h>
#include <trng.h>
#include <x25519.h>
#ifdef SUPPORT_C25519
/*Curve25519 parameters*/
uint32_t const curve25519_p[8] = {
0xFFFFFFED, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF,
};
uint32_t const curve25519_p_h[8] = {
0x000005A4, 0, 0, 0, 0, 0, 0, 0,
};
uint32_t const curve25519_a24[8] = {
0x0001DB41, 0, 0, 0, 0, 0, 0, 0,
};
uint32_t const curve25519_u[] = {
0x00000009, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
};
uint32_t const curve25519_v[] = {
0x7ECED3D9, 0x29E9C5A2, 0x6D7C61B2, 0x923D4D7E,
0x7748D14C, 0xE01EDD2C, 0xB8A086B4, 0x20AE19A1,
};
uint32_t const curve25519_n[] = {
0x5CF5D3ED, 0x5812631A, 0xA2F79CD6, 0x14DEF9DE,
0x00000000, 0x00000000, 0x00000000, 0x10000000,
};
uint32_t const curve25519_n_h[8] = {
0x449C0F01, 0xA40611E3, 0x68859347, 0xD00E1BA7,
0x17F5BE65, 0xCEEC73D2, 0x7C309A3D, 0x0399411B,
};
uint32_t const curve25519_h = 8;
const mont_curve_t c25519[1] = {
{
255,
(uint32_t *)curve25519_p,
(uint32_t *)curve25519_p_h,
(uint32_t *)curve25519_a24,
(uint32_t *)curve25519_u,
(uint32_t *)curve25519_v,
(uint32_t *)curve25519_n,
(uint32_t *)curve25519_n_h,
(uint32_t *)&curve25519_h,
},
};
/* Function: decode X25519 scalar for point multiplication
* Parameters:
* k -------------------------- input,
* out ------------------------ output, big scalar in little-endian
* bytes ---------------------- input, byte length of k and out
* Return: none
* Caution:
* 1.
*/
void x25519_decode_scalar(uint8_t *k, uint8_t *out, uint32_t bytes)
{
if (k != out) {
memcpy_(out, k, bytes);
} else {
;
}
/*clear lowest 3 bits*/
out[0] &= 0xF8;
/*clear highest 1 bit*/
out[bytes - 1] &= 0x7F;
/*set second highest bit as 1*/
out[bytes - 1] |= 0x40;
}
/* Function: decode X25519 u coordinate for point multiplication
* Parameters:
* u -------------------------- input,
* p -------------------------- input, modulus in little-endian
* out ------------------------ output, big scalar in little-endian
* bytes ---------------------- input, byte length of u, p and out
* Return: none
* Caution:
* 1.
*/
uint32_t x25519_decode_u(uint8_t *u, uint32_t *p, uint8_t *out, uint32_t bytes)
{
uint8_t ret;
if (u != out) {
memcpy_(out, u, bytes);
} else {
;
}
/*clear highest bit*/
out[bytes - 1] &= 0x7F;
/*mod p*/
if (uint32_bignumcmp((uint32_t *)out, (bytes + 3) / 4, p,
(bytes + 3) / 4) >= 0) {
ret = pke_sub((uint32_t *)out, p, (uint32_t *)out, (bytes + 3) / 4);
if (PKE_SUCCESS != ret) {
return ret;
} else {
;
}
} else {
;
}
return PKE_SUCCESS;
}
/* Function: get X25519 public key from private key
* Parameters:
* prikey --------------------- input, private key, 32 bytes, little-endian
* pubkey --------------------- output, public key, 32 bytes, little-endian
* Return: X25519_SUCCESS(success); other(error)
* Caution:
* 1.
*/
uint32_t x25519_get_pubkey_from_prikey(uint8_t prikey[32], uint8_t pubkey[32])
{
uint32_t t[C25519_WORD_LEN];
uint32_t ret;
if (NULL == prikey || NULL == pubkey) {
return X25519_POINTER_NULL;
} else {
;
}
x25519_decode_scalar(prikey, (uint8_t *)t, C25519_BYTE_LEN);
/*it could be proved that here t is not multiple of c25519->n, so no need to
* compare*/
/*(t mod c25519->n) with c25519->n*/
ret = x25519_pointMul((mont_curve_t *)c25519, t, c25519->u, t);
if (PKE_SUCCESS != ret) {
return ret;
} else {
;
}
memcpy_(pubkey, t, C25519_BYTE_LEN);
return X25519_SUCCESS;
}
/* Function: get x25519 random key pair
* Parameters:
* prikey --------------------- output, private key, 32 bytes, little-endian
* pubkey --------------------- output, public key, 32 bytes, little-endian
* Return: X25519_SUCCESS(success); other(error)
* Caution:
* 1.
*/
uint32_t x25519_getkey(uint8_t prikey[32], uint8_t pubkey[32])
{
uint32_t ret;
if (NULL == prikey || NULL == pubkey) {
return X25519_POINTER_NULL;
} else {
;
}
ret = get_rand(prikey, C25519_BYTE_LEN);
if (TRNG_SUCCESS != ret) {
return ret;
} else {
return x25519_get_pubkey_from_prikey(prikey, pubkey);
}
}
/* Function: X25519 key agreement
* Parameters:
* local_prikey --------------- input, local private key, 32 bytes,
* little-endian peer_pubkey ---------------- input, peer Public key, 32 bytes,
* little-endian key ------------------------ output, derived key keyByteLen
* ----------------- input, byte length of output key kdf
* ------------------------ input, KDF function Return: X25519_SUCCESS(success);
* other(error) Caution:
* 1. if no KDF function, please set kdf to be NULL
*/
uint32_t x25519_compute_key(uint8_t local_prikey[32], uint8_t peer_pubkey[32],
uint8_t *key, uint32_t keyByteLen, KDF_FUNC kdf)
{
uint32_t k[C25519_WORD_LEN], u[C25519_WORD_LEN];
uint32_t ret;
if (NULL == local_prikey || NULL == peer_pubkey || NULL == key) {
return X25519_POINTER_NULL;
} else if (0 == keyByteLen) {
return X25519_INVALID_INPUT;
} else {
;
}
/*decode u*/
ret =
x25519_decode_u(peer_pubkey, c25519->p, (uint8_t *)u, C25519_BYTE_LEN);
if (PKE_SUCCESS != ret) {
return ret;
} else {
;
}
/*u could not be zero, otherwise it will return PKE_NO_MODINV no matter what
* the scalar is.*/
if (uint32_bignum_check_zero(u, C25519_WORD_LEN)) {
return X25519_INVALID_INPUT;
} else {
;
}
/*decode scalar*/
x25519_decode_scalar(local_prikey, (uint8_t *)k, C25519_BYTE_LEN);
ret = x25519_pointMul((mont_curve_t *)c25519, k, u, u);
if (PKE_SUCCESS != ret) {
return ret;
} else {
;
}
/*make sure u is not zero*/
k[0] = 0;
for (ret = 0; ret < C25519_WORD_LEN; ret++) {
k[0] |= u[ret];
}
if (0 == k[0]) {
return X25519_ZERO_ALL;
} else {
;
}
if (kdf) {
kdf(u, C25519_BYTE_LEN, key, keyByteLen);
} else {
if (keyByteLen > C25519_BYTE_LEN) {
keyByteLen = C25519_BYTE_LEN;
} else {
;
}
memcpy_(key, u, keyByteLen);
}
return X25519_SUCCESS;
}
#endif