added generic curve25519 encode/decode functions that can handle combined keypairs

This commit is contained in:
Brett Nicholas
2024-10-29 15:53:06 -06:00
parent bdd62314f0
commit 97a370ed08
3 changed files with 166 additions and 0 deletions

View File

@ -35661,6 +35661,55 @@ int wc_Curve25519PublicKeyDecode(const byte* input, word32* inOutIdx,
}
return ret;
}
/* Decode Curve25519 key from DER format - can handle private only,
* public only, or private+public key pairs.
* return 0 on success, negative on error */
int wc_Curve25519KeyDecode(const byte* input, word32* inOutIdx,
curve25519_key* key, word32 inSz)
{
int ret;
byte privKey[CURVE25519_KEYSIZE];
byte pubKey[CURVE25519_KEYSIZE];
word32 privKeyLen = CURVE25519_KEYSIZE;
word32 pubKeyLen = CURVE25519_KEYSIZE;
/* sanity check */
if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) {
return BAD_FUNC_ARG;
}
/* Try to decode as private key first (may include public) */
ret = DecodeAsymKey(input, inOutIdx, inSz, privKey, &privKeyLen,
pubKey, &pubKeyLen, X25519k);
if (ret == 0) {
/* Successfully decoded private key */
if (pubKeyLen > 0) {
/* Have both private and public */
ret = wc_curve25519_import_private_raw(privKey, privKeyLen,
pubKey, pubKeyLen, key);
}
else {
/* Private only */
ret = wc_curve25519_import_private(privKey, privKeyLen, key);
}
}
else {
/* Try decoding as public key */
*inOutIdx = 0; /* Reset index */
pubKeyLen = CURVE25519_KEYSIZE;
ret = DecodeAsymKeyPublic(input, inOutIdx, inSz,
pubKey, &pubKeyLen, X25519k);
if (ret == 0) {
/* Successfully decoded public key */
ret = wc_curve25519_import_public(pubKey, pubKeyLen, key);
}
}
return ret;
}
#endif /* HAVE_CURVE25519 && HAVE_ED25519_KEY_IMPORT */
@ -35868,6 +35917,63 @@ int wc_Curve25519PublicKeyToDer(curve25519_key* key, byte* output, word32 inLen,
}
return ret;
}
/* Export Curve25519 key to DER format - handles private only, public only,
* or private+public key pairs based on what's set in the key structure.
* Returns length written on success, negative on error */
int wc_Curve25519KeyToDer(curve25519_key* key, byte* output, word32 inLen, int withAlg)
{
int ret;
byte privKey[CURVE25519_KEYSIZE];
byte pubKey[CURVE25519_KEYSIZE];
word32 privKeyLen = CURVE25519_KEYSIZE;
word32 pubKeyLen = CURVE25519_KEYSIZE;
if (key == NULL) {
return BAD_FUNC_ARG;
}
/* Check what we have in the key structure */
if (key->privSet) {
/* Export private key to buffer */
ret = wc_curve25519_export_private_raw(key, privKey, &privKeyLen);
if (ret != 0) {
return ret;
}
if (key->pubSet) {
/* Export public key if available */
ret = wc_curve25519_export_public(key, pubKey, &pubKeyLen);
if (ret != 0) {
return ret;
}
/* Export both private and public */
ret = SetAsymKeyDer(privKey, privKeyLen,
pubKey, pubKeyLen,
output, inLen, X25519k);
}
else {
/* Export private only */
ret = SetAsymKeyDer(privKey, privKeyLen,
NULL, 0,
output, inLen, X25519k);
}
}
else if (key->pubSet) {
/* Export public key only */
ret = wc_curve25519_export_public(key, pubKey, &pubKeyLen);
if (ret == 0) {
ret = SetAsymKeyDerPublic(pubKey, pubKeyLen,
output, inLen, X25519k, withAlg);
}
}
else {
/* Neither public nor private key is set */
ret = BAD_FUNC_ARG;
}
return ret;
}
#endif /* HAVE_CURVE25519 && HAVE_CURVE25519_KEY_EXPORT */
#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT)

View File

@ -35042,6 +35042,62 @@ static wc_test_ret_t curve255519_der_test(void)
ret = WC_TEST_RET_ENC_NC;
}
/* Test decode/encode of Curve25519 private key (only) using generic API */
if (ret == 0) {
/* clear key, since generic API will try to decode all fields */
XMEMSET(&key, 0, sizeof(key));
idx = 0;
ret = wc_Curve25519KeyDecode(kCurve25519PrivDer, &idx, &key,
(word32)sizeof(kCurve25519PrivDer));
if (ret < 0) {
ret = WC_TEST_RET_ENC_EC(ret);
}
}
if (ret == 0) {
outputSz = (word32)sizeof(output);
ret = wc_Curve25519KeyToDer(&key, output, outputSz, 1);
if (ret >= 0) {
outputSz = (word32)ret;
ret = 0;
}
else {
ret = WC_TEST_RET_ENC_EC(ret);
}
}
if (ret == 0 && (outputSz != (word32)sizeof(kCurve25519PrivDer) ||
XMEMCMP(output, kCurve25519PrivDer, outputSz) != 0)) {
ret = WC_TEST_RET_ENC_NC;
}
/* Test decode/encode of Curve25519 public key (only) using generic API */
if (ret == 0) {
/* clear key, since generic API will try to decode all fields */
XMEMSET(&key, 0, sizeof(key));
idx = 0;
ret = wc_Curve25519KeyDecode(kCurve25519PubDer, &idx, &key,
(word32)sizeof(kCurve25519PubDer));
if (ret < 0) {
ret = WC_TEST_RET_ENC_EC(ret);
}
}
if (ret == 0) {
outputSz = (word32)sizeof(output);
ret = wc_Curve25519KeyToDer(&key, output, outputSz, 1);
if (ret >= 0) {
outputSz = (word32)ret;
ret = 0;
}
else {
ret = WC_TEST_RET_ENC_EC(ret);
}
}
if (ret == 0 && (outputSz != (word32)sizeof(kCurve25519PubDer) ||
XMEMCMP(output, kCurve25519PubDer, outputSz) != 0)) {
ret = WC_TEST_RET_ENC_NC;
}
wc_curve25519_free(&key);
return ret;

View File

@ -841,12 +841,16 @@ WOLFSSL_API int wc_Curve25519PrivateKeyDecode(
const byte* input, word32* inOutIdx, curve25519_key* key, word32 inSz);
WOLFSSL_API int wc_Curve25519PublicKeyDecode(
const byte* input, word32* inOutIdx, curve25519_key* key, word32 inSz);
WOLFSSL_API int wc_Curve25519KeyDecode(const byte *input, word32 *inOutIdx,
curve25519_key *key, word32 inSz);
#endif
#ifdef HAVE_CURVE25519_KEY_EXPORT
WOLFSSL_API int wc_Curve25519PrivateKeyToDer(
curve25519_key* key, byte* output, word32 inLen);
WOLFSSL_API int wc_Curve25519PublicKeyToDer(
curve25519_key* key, byte* output, word32 inLen, int withAlg);
WOLFSSL_API int wc_Curve25519KeyToDer(curve25519_key* key, byte* output,
word32 inLen, int withAlg);
#endif
#endif /* HAVE_CURVE25519 */