mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-31 19:24:42 +02:00
add basic ecc encrypt/decrypt
This commit is contained in:
27
configure.ac
27
configure.ac
@@ -595,10 +595,35 @@ AC_ARG_ENABLE([fpecc],
|
||||
|
||||
if test "$ENABLED_FPECC" = "yes"
|
||||
then
|
||||
if test "$ENABLED_ECC" = "no"
|
||||
then
|
||||
AC_MSG_ERROR([cannot enable fpecc without enabling ecc.])
|
||||
fi
|
||||
AM_CFLAGS="$AM_CFLAGS -DFP_ECC"
|
||||
fi
|
||||
|
||||
|
||||
# ECC encrypt
|
||||
AC_ARG_ENABLE([eccencrypt],
|
||||
[ --enable-eccencrypt Enable ECC encrypt (default: disabled)],
|
||||
[ ENABLED_ECC_ENCRYPT=$enableval ],
|
||||
[ ENABLED_ECC_ENCRYPT=no ]
|
||||
)
|
||||
|
||||
if test "$ENABLED_ECC_ENCRYPT" = "yes"
|
||||
then
|
||||
if test "$ENABLED_ECC" = "no"
|
||||
then
|
||||
AC_MSG_ERROR([cannot enable eccencrypt without enabling ecc.])
|
||||
fi
|
||||
if test "$ENABLED_HKDF" = "no"
|
||||
then
|
||||
AC_MSG_ERROR([cannot enable eccencrypt without enabling hkdf.])
|
||||
fi
|
||||
AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC_ENCRYPT"
|
||||
fi
|
||||
|
||||
|
||||
# PSK
|
||||
AC_ARG_ENABLE([psk],
|
||||
[ --enable-psk Enable PSK (default: disabled)],
|
||||
@@ -1522,6 +1547,7 @@ echo " * certgen: $ENABLED_CERTGEN"
|
||||
echo " * HC-128: $ENABLED_HC128"
|
||||
echo " * RABBIT: $ENABLED_RABBIT"
|
||||
echo " * PWDBASED: $ENABLED_PWDBASED"
|
||||
echo " * HKDF: $ENABLED_HKDF"
|
||||
echo " * MD4: $ENABLED_MD4"
|
||||
echo " * PSK: $ENABLED_PSK"
|
||||
echo " * LEANPSK: $ENABLED_LEANPSK"
|
||||
@@ -1530,6 +1556,7 @@ echo " * DSA: $ENABLED_DSA"
|
||||
echo " * DH: $ENABLED_DH"
|
||||
echo " * ECC: $ENABLED_ECC"
|
||||
echo " * FPECC: $ENABLED_FPECC"
|
||||
echo " * ECC_ENCRYPT: $ENABLED_ECC_ENCRYPT"
|
||||
echo " * ASN: $ENABLED_ASN"
|
||||
echo " * CODING: $ENABLED_CODING"
|
||||
echo " * MEMORY: $ENABLED_MEMORY"
|
||||
|
@@ -33,6 +33,11 @@
|
||||
#include <cyassl/ctaocrypt/asn.h>
|
||||
#include <cyassl/ctaocrypt/error.h>
|
||||
|
||||
#ifdef HAVE_ECC_ENCRYPT
|
||||
#include <cyassl/ctaocrypt/hmac.h>
|
||||
#include <cyassl/ctaocrypt/aes.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* map
|
||||
|
||||
@@ -3484,6 +3489,269 @@ void ecc_fp_free(void)
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* FP_ECC */
|
||||
|
||||
#ifdef HAVE_ECC_ENCRYPT
|
||||
|
||||
/* init and set defaults, just holders */
|
||||
void ecc_encrypt_init_options(ecEncOptions* options)
|
||||
{
|
||||
if (options) {
|
||||
XMEMSET(options, 0, sizeof(ecEncOptions));
|
||||
|
||||
options->encAlgo = ecAES_128_CBC;
|
||||
options->kdfAlgo = ecHKDF_SHA256;
|
||||
options->macAlgo = ecHMAC_SHA256;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* free any resources, clear any keys */
|
||||
void ecc_encrypt_free_options(ecEncOptions* options)
|
||||
{
|
||||
if (options) {
|
||||
XMEMSET(options, 0, sizeof(ecEncOptions));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int ecc_get_key_sizes(ecEncOptions* options, int* encKeySz, int* ivSz,
|
||||
int* keysLen, word32* digestSz, word32* blockSz)
|
||||
{
|
||||
if (options) {
|
||||
switch (options->encAlgo) {
|
||||
case ecAES_128_CBC:
|
||||
*encKeySz = KEY_SIZE_128;
|
||||
*ivSz = IV_SIZE_64;
|
||||
*blockSz = AES_BLOCK_SIZE;
|
||||
break;
|
||||
default:
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
switch (options->macAlgo) {
|
||||
case ecHMAC_SHA256:
|
||||
*digestSz = SHA256_DIGEST_SIZE;
|
||||
break;
|
||||
default:
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
} else
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
*keysLen = *encKeySz + *ivSz + *digestSz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ecc encrypt with shared secret run through kdf
|
||||
options holds non default algos and inputs
|
||||
msgSz should be the right size for encAlgo, i.e., already padded
|
||||
return 0 on success */
|
||||
int ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
||||
word32 msgSz, byte* out, word32* outSz, ecEncOptions* opts)
|
||||
{
|
||||
int ret;
|
||||
word32 blockSz;
|
||||
word32 digestSz;
|
||||
ecEncOptions options;
|
||||
byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */
|
||||
byte keys[ECC_BUFSIZE]; /* max size */
|
||||
word32 sharedSz = sizeof(sharedSecret);
|
||||
int keysLen;
|
||||
int encKeySz;
|
||||
int ivSz;
|
||||
byte* encKey;
|
||||
byte* encIv;
|
||||
byte* macKey;
|
||||
|
||||
if (privKey == NULL || pubKey == NULL || msg == NULL || out == NULL ||
|
||||
outSz == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (opts)
|
||||
options = *opts;
|
||||
else {
|
||||
ecc_encrypt_init_options(&options); /* defaults */
|
||||
}
|
||||
|
||||
ret = ecc_get_key_sizes(&options, &encKeySz, &ivSz, &keysLen, &digestSz,
|
||||
&blockSz);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if ( (msgSz%blockSz) != 0)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (*outSz < (msgSz + digestSz))
|
||||
return BUFFER_E;
|
||||
|
||||
ret = ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
switch (options.kdfAlgo) {
|
||||
case ecHKDF_SHA256 :
|
||||
ret = HKDF(SHA256, sharedSecret, sharedSz, options.kdfSalt,
|
||||
options.kdfSaltSz, options.kdfInfo,
|
||||
options.kdfInfoSz, keys, keysLen);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
break;
|
||||
|
||||
default:
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
encKey = keys;
|
||||
encIv = encKey + encKeySz;
|
||||
macKey = encKey + encKeySz + ivSz;
|
||||
|
||||
switch (options.encAlgo) {
|
||||
case ecAES_128_CBC:
|
||||
{
|
||||
Aes aes;
|
||||
ret = AesSetKey(&aes, encKey,KEY_SIZE_128,encIv,AES_ENCRYPTION);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
ret = AesCbcEncrypt(&aes, out, msg, msgSz);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
switch (options.macAlgo) {
|
||||
case ecHMAC_SHA256:
|
||||
{
|
||||
Hmac hmac;
|
||||
ret = HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
HmacUpdate(&hmac, out, msgSz);
|
||||
HmacUpdate(&hmac, options.macSalt, options.macSaltSz);
|
||||
HmacFinal(&hmac, out+msgSz);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
*outSz = msgSz + digestSz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
||||
word32 msgSz, byte* out, word32* outSz, ecEncOptions* opts)
|
||||
{
|
||||
int ret;
|
||||
word32 blockSz;
|
||||
word32 digestSz;
|
||||
ecEncOptions options;
|
||||
byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */
|
||||
byte keys[ECC_BUFSIZE]; /* max size */
|
||||
word32 sharedSz = sizeof(sharedSecret);
|
||||
int keysLen;
|
||||
int encKeySz;
|
||||
int ivSz;
|
||||
byte* encKey;
|
||||
byte* encIv;
|
||||
byte* macKey;
|
||||
|
||||
if (privKey == NULL || pubKey == NULL || msg == NULL || out == NULL ||
|
||||
outSz == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (opts)
|
||||
options = *opts;
|
||||
else {
|
||||
ecc_encrypt_init_options(&options); /* defaults */
|
||||
}
|
||||
|
||||
ret = ecc_get_key_sizes(&options, &encKeySz, &ivSz, &keysLen, &digestSz,
|
||||
&blockSz);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if ( ((msgSz-digestSz) % blockSz) != 0)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (*outSz < (msgSz - digestSz))
|
||||
return BUFFER_E;
|
||||
|
||||
ret = ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
switch (options.kdfAlgo) {
|
||||
case ecHKDF_SHA256 :
|
||||
ret = HKDF(SHA256, sharedSecret, sharedSz, options.kdfSalt,
|
||||
options.kdfSaltSz, options.kdfInfo,
|
||||
options.kdfInfoSz, keys, keysLen);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
break;
|
||||
|
||||
default:
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
encKey = keys;
|
||||
encIv = encKey + encKeySz;
|
||||
macKey = encKey + encKeySz + ivSz;
|
||||
|
||||
switch (options.macAlgo) {
|
||||
case ecHMAC_SHA256:
|
||||
{
|
||||
byte verify[SHA256_DIGEST_SIZE];
|
||||
Hmac hmac;
|
||||
ret = HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
HmacUpdate(&hmac, msg, msgSz-digestSz);
|
||||
HmacUpdate(&hmac, options.macSalt, options.macSaltSz);
|
||||
HmacFinal(&hmac, verify);
|
||||
|
||||
if (memcmp(verify, msg + msgSz - digestSz, digestSz) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
switch (options.encAlgo) {
|
||||
case ecAES_128_CBC:
|
||||
{
|
||||
Aes aes;
|
||||
ret = AesSetKey(&aes, encKey,KEY_SIZE_128,encIv,AES_DECRYPTION);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
ret = AesCbcDecrypt(&aes, out, msg, msgSz-digestSz);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
*outSz = msgSz - digestSz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif /* HAVE_ECC_ENCRYPT */
|
||||
|
||||
#endif /* HAVE_ECC */
|
||||
|
@@ -158,6 +158,9 @@ int pkcs12_test(void);
|
||||
int pbkdf2_test(void);
|
||||
#ifdef HAVE_ECC
|
||||
int ecc_test(void);
|
||||
#ifdef HAVE_ECC_ENCRYPT
|
||||
int ecc_encrypt_test(void);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef HAVE_BLAKE2
|
||||
int blake2b_test(void);
|
||||
@@ -434,6 +437,12 @@ void ctaocrypt_test(void* args)
|
||||
err_sys("ECC test failed!\n", ret);
|
||||
else
|
||||
printf( "ECC test passed!\n");
|
||||
#ifdef HAVE_ECC_ENCRYPT
|
||||
if ( (ret = ecc_encrypt_test()) != 0)
|
||||
err_sys("ECC Enc test failed!\n", ret);
|
||||
else
|
||||
printf( "ECC Enc test passed!\n");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
@@ -3583,6 +3592,56 @@ int ecc_test(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ECC_ENCRYPT
|
||||
|
||||
int ecc_encrypt_test(void)
|
||||
{
|
||||
RNG rng;
|
||||
int ret;
|
||||
ecc_key userA, userB;
|
||||
byte msg[48];
|
||||
byte plain[48];
|
||||
byte out[80];
|
||||
word32 outSz = sizeof(out);
|
||||
word32 plainSz = sizeof(plain);
|
||||
int i;
|
||||
|
||||
ret = InitRng(&rng);
|
||||
if (ret != 0)
|
||||
return -3001;
|
||||
|
||||
ecc_init(&userA);
|
||||
ecc_init(&userB);
|
||||
|
||||
ret = ecc_make_key(&rng, 32, &userA);
|
||||
ret += ecc_make_key(&rng, 32, &userB);
|
||||
|
||||
if (ret != 0)
|
||||
return -3002;
|
||||
|
||||
for (i = 0; i < 48; i++)
|
||||
msg[i] = i;
|
||||
|
||||
/* send encrypted msg to B */
|
||||
ret = ecc_encrypt(&userA, &userB, msg, sizeof(msg), out, &outSz, NULL);
|
||||
if (ret != 0)
|
||||
return -3003;
|
||||
|
||||
/* decrypted msg to B */
|
||||
ret = ecc_decrypt(&userB, &userA, out, outSz, plain, &plainSz, NULL);
|
||||
if (ret != 0)
|
||||
return -3004;
|
||||
|
||||
if (memcmp(plain, msg, sizeof(msg)) != 0)
|
||||
return -3005;
|
||||
|
||||
ecc_free(&userB);
|
||||
ecc_free(&userA);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* HAVE_ECC_ENCRYPT */
|
||||
#endif /* HAVE_ECC */
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
|
@@ -119,6 +119,53 @@ CYASSL_API
|
||||
int ecc_sig_size(ecc_key* key);
|
||||
|
||||
|
||||
/* ecc encrypt */
|
||||
|
||||
enum ecEncAlgo {
|
||||
ecAES_128_CBC = 1, /* default */
|
||||
ecAES_256_CBC = 2
|
||||
};
|
||||
|
||||
enum ecKdfAlgo {
|
||||
ecHKDF_SHA256 = 1, /* default */
|
||||
ecHKDF_SHA1 = 2
|
||||
};
|
||||
|
||||
enum ecMacAlgo {
|
||||
ecHMAC_SHA256 = 1, /* default */
|
||||
ecHMAC_SHA1 = 2
|
||||
};
|
||||
|
||||
enum {
|
||||
KEY_SIZE_128 = 16,
|
||||
KEY_SIZE_256 = 32,
|
||||
IV_SIZE_64 = 8
|
||||
};
|
||||
|
||||
typedef struct ecEncOptions {
|
||||
byte encAlgo; /* which encryption type */
|
||||
byte kdfAlgo; /* which key derivation function type */
|
||||
byte macAlgo; /* which mac function type */
|
||||
byte* kdfSalt; /* optional salt for kdf */
|
||||
byte* kdfInfo; /* optional info for kdf */
|
||||
byte* macSalt; /* optional salt for mac */
|
||||
word32 kdfSaltSz; /* size of kdfSalt */
|
||||
word32 kdfInfoSz; /* size of kdfInfo */
|
||||
word32 macSaltSz; /* size of macSalt */
|
||||
} ecEncOptions;
|
||||
|
||||
CYASSL_API
|
||||
void ecc_encrypt_init_options(ecEncOptions*); /* init and set to defaults */
|
||||
CYASSL_API
|
||||
void ecc_encrypt_free_options(ecEncOptions*); /* release/clear options */
|
||||
|
||||
CYASSL_API
|
||||
int ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
||||
word32 msgSz, byte* out, word32* outSz, ecEncOptions* options);
|
||||
CYASSL_API
|
||||
int ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
||||
word32 msgSz, byte* out, word32* outSz, ecEncOptions* options);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user