mirror of https://github.com/wolfSSL/wolfssl
add ecc encrypt secure message exchange, hide ecEncCtx
This commit is contained in:
parent
2e9e372875
commit
cf4230b073
|
@ -3510,33 +3510,189 @@ void ecc_fp_free(void)
|
|||
|
||||
#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;
|
||||
enum ecCliState {
|
||||
ecCLI_INIT = 1,
|
||||
ecCLI_SALT_GET = 2,
|
||||
ecCLI_SALT_SET = 3,
|
||||
ecCLI_SENT_REQ = 4,
|
||||
ecCLI_RECV_RESP = 5,
|
||||
ecCLI_BAD_STATE = 99
|
||||
};
|
||||
|
||||
enum ecSrvState {
|
||||
ecSRV_INIT = 1,
|
||||
ecSRV_SALT_GET = 2,
|
||||
ecSRV_SALT_SET = 3,
|
||||
ecSRV_RECV_REQ = 4,
|
||||
ecSRV_SENT_RESP = 5,
|
||||
ecSRV_BAD_STATE = 99
|
||||
};
|
||||
|
||||
|
||||
struct ecEncCtx {
|
||||
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 */
|
||||
byte clientSalt[EXCHANGE_SALT_SZ]; /* for msg exchange */
|
||||
byte serverSalt[EXCHANGE_SALT_SZ]; /* for msg exchange */
|
||||
byte encAlgo; /* which encryption type */
|
||||
byte kdfAlgo; /* which key derivation function type */
|
||||
byte macAlgo; /* which mac function type */
|
||||
byte protocol; /* are we REQ_RESP client or server ? */
|
||||
byte cliSt; /* protocol state, for sanity checks */
|
||||
byte srvSt; /* protocol state, for sanity checks */
|
||||
};
|
||||
|
||||
|
||||
const byte* ecc_ctx_get_own_salt(ecEncCtx* ctx)
|
||||
{
|
||||
if (ctx == NULL || ctx->protocol == 0)
|
||||
return NULL;
|
||||
|
||||
if (ctx->protocol == REQ_RESP_CLIENT) {
|
||||
if (ctx->cliSt == ecCLI_INIT) {
|
||||
ctx->cliSt = ecCLI_SALT_GET;
|
||||
return ctx->clientSalt;
|
||||
}
|
||||
else {
|
||||
ctx->cliSt = ecCLI_BAD_STATE;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (ctx->protocol == REQ_RESP_SERVER) {
|
||||
if (ctx->srvSt == ecSRV_INIT) {
|
||||
ctx->srvSt = ecSRV_SALT_GET;
|
||||
return ctx->serverSalt;
|
||||
}
|
||||
else {
|
||||
ctx->srvSt = ecSRV_BAD_STATE;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static const char* exchange_info = "Secure Message Exchange";
|
||||
|
||||
int ecc_ctx_set_peer_salt(ecEncCtx* ctx, const byte* salt)
|
||||
{
|
||||
byte tmp[EXCHANGE_SALT_SZ/2];
|
||||
int halfSz = EXCHANGE_SALT_SZ/2;
|
||||
|
||||
if (ctx == NULL || ctx->protocol == 0 || salt == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (ctx->protocol == REQ_RESP_CLIENT) {
|
||||
XMEMCPY(ctx->serverSalt, salt, EXCHANGE_SALT_SZ);
|
||||
if (ctx->cliSt == ecCLI_SALT_GET)
|
||||
ctx->cliSt = ecCLI_SALT_SET;
|
||||
else {
|
||||
ctx->cliSt = ecCLI_BAD_STATE;
|
||||
return BAD_ENC_STATE_E;
|
||||
}
|
||||
}
|
||||
else {
|
||||
XMEMCPY(ctx->clientSalt, salt, EXCHANGE_SALT_SZ);
|
||||
if (ctx->srvSt == ecSRV_SALT_GET)
|
||||
ctx->srvSt = ecSRV_SALT_SET;
|
||||
else {
|
||||
ctx->srvSt = ecSRV_BAD_STATE;
|
||||
return BAD_ENC_STATE_E;
|
||||
}
|
||||
}
|
||||
|
||||
/* mix half and half */
|
||||
/* tmp stores 2nd half of client before overwrite */
|
||||
XMEMCPY(tmp, ctx->clientSalt + halfSz, halfSz);
|
||||
XMEMCPY(ctx->clientSalt + halfSz, ctx->serverSalt, halfSz);
|
||||
XMEMCPY(ctx->serverSalt, tmp, halfSz);
|
||||
|
||||
ctx->kdfSalt = ctx->clientSalt;
|
||||
ctx->kdfSaltSz = EXCHANGE_SALT_SZ;
|
||||
|
||||
ctx->macSalt = ctx->serverSalt;
|
||||
ctx->macSaltSz = EXCHANGE_SALT_SZ;
|
||||
|
||||
ctx->kdfInfo = (byte*)exchange_info;
|
||||
ctx->kdfInfoSz = EXCHANGE_INFO_SZ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ecc_ctx_set_salt(ecEncCtx* ctx, int flags, RNG* rng)
|
||||
{
|
||||
byte* saltBuffer = NULL;
|
||||
|
||||
if (ctx == NULL || rng == NULL || flags == 0)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
saltBuffer = (flags == REQ_RESP_CLIENT) ? ctx->clientSalt : ctx->serverSalt;
|
||||
RNG_GenerateBlock(rng, saltBuffer, EXCHANGE_SALT_SZ);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void ecc_ctx_init(ecEncCtx* ctx, int flags)
|
||||
{
|
||||
if (ctx) {
|
||||
XMEMSET(ctx, 0, sizeof(ecEncCtx));
|
||||
|
||||
ctx->encAlgo = ecAES_128_CBC;
|
||||
ctx->kdfAlgo = ecHKDF_SHA256;
|
||||
ctx->macAlgo = ecHMAC_SHA256;
|
||||
ctx->protocol = (byte)flags;
|
||||
|
||||
if (flags == REQ_RESP_CLIENT)
|
||||
ctx->cliSt = ecCLI_INIT;
|
||||
if (flags == REQ_RESP_SERVER)
|
||||
ctx->srvSt = ecSRV_INIT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* alloc/init and set defaults, return new Context */
|
||||
ecEncCtx* ecc_ctx_new(int flags, RNG* rng)
|
||||
{
|
||||
int ret = 0;
|
||||
ecEncCtx* ctx = (ecEncCtx*)XMALLOC(sizeof(ecEncCtx), 0, DYNAMIC_TYPE_ECC);
|
||||
|
||||
ecc_ctx_init(ctx, flags);
|
||||
|
||||
if (ctx && flags)
|
||||
ret = ecc_ctx_set_salt(ctx, flags, rng);
|
||||
|
||||
if (ret != 0) {
|
||||
ecc_ctx_free(ctx);
|
||||
ctx = NULL;
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
/* free any resources, clear any keys */
|
||||
void ecc_encrypt_free_options(ecEncOptions* options)
|
||||
void ecc_ctx_free(ecEncCtx* ctx)
|
||||
{
|
||||
if (options) {
|
||||
XMEMSET(options, 0, sizeof(ecEncOptions));
|
||||
if (ctx) {
|
||||
XMEMSET(ctx, 0, sizeof(ecEncCtx));
|
||||
XFREE(ctx, 0, DYNAMIC_TYPE_ECC);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int ecc_get_key_sizes(ecEncOptions* options, int* encKeySz, int* ivSz,
|
||||
static int ecc_get_key_sizes(ecEncCtx* ctx, int* encKeySz, int* ivSz,
|
||||
int* keysLen, word32* digestSz, word32* blockSz)
|
||||
{
|
||||
if (options) {
|
||||
switch (options->encAlgo) {
|
||||
if (ctx) {
|
||||
switch (ctx->encAlgo) {
|
||||
case ecAES_128_CBC:
|
||||
*encKeySz = KEY_SIZE_128;
|
||||
*ivSz = IV_SIZE_64;
|
||||
|
@ -3546,7 +3702,7 @@ static int ecc_get_key_sizes(ecEncOptions* options, int* encKeySz, int* ivSz,
|
|||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
switch (options->macAlgo) {
|
||||
switch (ctx->macAlgo) {
|
||||
case ecHMAC_SHA256:
|
||||
*digestSz = SHA256_DIGEST_SIZE;
|
||||
break;
|
||||
|
@ -3563,22 +3719,23 @@ static int ecc_get_key_sizes(ecEncOptions* options, int* encKeySz, int* ivSz,
|
|||
|
||||
|
||||
/* ecc encrypt with shared secret run through kdf
|
||||
options holds non default algos and inputs
|
||||
ctx 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)
|
||||
word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx)
|
||||
{
|
||||
int ret;
|
||||
word32 blockSz;
|
||||
word32 digestSz;
|
||||
ecEncOptions options;
|
||||
ecEncCtx localCtx;
|
||||
byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */
|
||||
byte keys[ECC_BUFSIZE]; /* max size */
|
||||
word32 sharedSz = sizeof(sharedSecret);
|
||||
int keysLen;
|
||||
int encKeySz;
|
||||
int ivSz;
|
||||
int offset; /* keys offset if doing msg exchange */
|
||||
byte* encKey;
|
||||
byte* encIv;
|
||||
byte* macKey;
|
||||
|
@ -3587,19 +3744,37 @@ int ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
|||
outSz == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (opts)
|
||||
options = *opts;
|
||||
else {
|
||||
ecc_encrypt_init_options(&options); /* defaults */
|
||||
if (ctx == NULL) { /* use defaults */
|
||||
ecc_ctx_init(&localCtx, 0);
|
||||
ctx = &localCtx;
|
||||
}
|
||||
|
||||
ret = ecc_get_key_sizes(&options, &encKeySz, &ivSz, &keysLen, &digestSz,
|
||||
ret = ecc_get_key_sizes(ctx, &encKeySz, &ivSz, &keysLen, &digestSz,
|
||||
&blockSz);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if (ctx->protocol == REQ_RESP_SERVER) {
|
||||
offset = keysLen;
|
||||
keysLen *= 2;
|
||||
|
||||
if (ctx->srvSt != ecSRV_RECV_REQ)
|
||||
return BAD_ENC_STATE_E;
|
||||
|
||||
ctx->srvSt = ecSRV_BAD_STATE; /* we're done no more ops allowed */
|
||||
}
|
||||
else if (ctx->protocol == REQ_RESP_CLIENT) {
|
||||
if (ctx->cliSt != ecCLI_SALT_SET)
|
||||
return BAD_ENC_STATE_E;
|
||||
|
||||
ctx->cliSt = ecCLI_SENT_REQ; /* only do this once */
|
||||
}
|
||||
|
||||
if (keysLen > (int)sizeof(keys))
|
||||
return BUFFER_E;
|
||||
|
||||
if ( (msgSz%blockSz) != 0)
|
||||
return BAD_FUNC_ARG;
|
||||
return BAD_PADDING_E;
|
||||
|
||||
if (*outSz < (msgSz + digestSz))
|
||||
return BUFFER_E;
|
||||
|
@ -3608,11 +3783,11 @@ int ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
|||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
switch (options.kdfAlgo) {
|
||||
switch (ctx->kdfAlgo) {
|
||||
case ecHKDF_SHA256 :
|
||||
ret = HKDF(SHA256, sharedSecret, sharedSz, options.kdfSalt,
|
||||
options.kdfSaltSz, options.kdfInfo,
|
||||
options.kdfInfoSz, keys, keysLen);
|
||||
ret = HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
|
||||
ctx->kdfSaltSz, ctx->kdfInfo,
|
||||
ctx->kdfInfoSz, keys, keysLen);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
break;
|
||||
|
@ -3621,11 +3796,11 @@ int ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
|||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
encKey = keys;
|
||||
encKey = keys + offset;
|
||||
encIv = encKey + encKeySz;
|
||||
macKey = encKey + encKeySz + ivSz;
|
||||
|
||||
switch (options.encAlgo) {
|
||||
switch (ctx->encAlgo) {
|
||||
case ecAES_128_CBC:
|
||||
{
|
||||
Aes aes;
|
||||
|
@ -3642,7 +3817,7 @@ int ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
|||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
switch (options.macAlgo) {
|
||||
switch (ctx->macAlgo) {
|
||||
case ecHMAC_SHA256:
|
||||
{
|
||||
Hmac hmac;
|
||||
|
@ -3650,7 +3825,7 @@ int ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
|||
if (ret != 0)
|
||||
return ret;
|
||||
HmacUpdate(&hmac, out, msgSz);
|
||||
HmacUpdate(&hmac, options.macSalt, options.macSaltSz);
|
||||
HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz);
|
||||
HmacFinal(&hmac, out+msgSz);
|
||||
}
|
||||
break;
|
||||
|
@ -3665,19 +3840,23 @@ int ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
|||
}
|
||||
|
||||
|
||||
/* ecc decrypt with shared secret run through kdf
|
||||
ctx holds non default algos and inputs
|
||||
return 0 on success */
|
||||
int ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
||||
word32 msgSz, byte* out, word32* outSz, ecEncOptions* opts)
|
||||
word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx)
|
||||
{
|
||||
int ret;
|
||||
word32 blockSz;
|
||||
word32 digestSz;
|
||||
ecEncOptions options;
|
||||
ecEncCtx localCtx;
|
||||
byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */
|
||||
byte keys[ECC_BUFSIZE]; /* max size */
|
||||
word32 sharedSz = sizeof(sharedSecret);
|
||||
int keysLen;
|
||||
int encKeySz;
|
||||
int ivSz;
|
||||
int offset; /* in case using msg exchange */
|
||||
byte* encKey;
|
||||
byte* encIv;
|
||||
byte* macKey;
|
||||
|
@ -3686,19 +3865,37 @@ int ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
|||
outSz == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (opts)
|
||||
options = *opts;
|
||||
else {
|
||||
ecc_encrypt_init_options(&options); /* defaults */
|
||||
if (ctx == NULL) { /* use defaults */
|
||||
ecc_ctx_init(&localCtx, 0);
|
||||
ctx = &localCtx;
|
||||
}
|
||||
|
||||
ret = ecc_get_key_sizes(&options, &encKeySz, &ivSz, &keysLen, &digestSz,
|
||||
|
||||
ret = ecc_get_key_sizes(ctx, &encKeySz, &ivSz, &keysLen, &digestSz,
|
||||
&blockSz);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if (ctx->protocol == REQ_RESP_CLIENT) {
|
||||
offset = keysLen;
|
||||
keysLen *= 2;
|
||||
|
||||
if (ctx->cliSt != ecCLI_SENT_REQ)
|
||||
return BAD_ENC_STATE_E;
|
||||
|
||||
ctx->cliSt = ecSRV_BAD_STATE; /* we're done no more ops allowed */
|
||||
}
|
||||
else if (ctx->protocol == REQ_RESP_SERVER) {
|
||||
if (ctx->srvSt != ecSRV_SALT_SET)
|
||||
return BAD_ENC_STATE_E;
|
||||
|
||||
ctx->srvSt = ecSRV_RECV_REQ; /* only do this once */
|
||||
}
|
||||
|
||||
if (keysLen > (int)sizeof(keys))
|
||||
return BUFFER_E;
|
||||
|
||||
if ( ((msgSz-digestSz) % blockSz) != 0)
|
||||
return BAD_FUNC_ARG;
|
||||
return BAD_PADDING_E;
|
||||
|
||||
if (*outSz < (msgSz - digestSz))
|
||||
return BUFFER_E;
|
||||
|
@ -3707,11 +3904,11 @@ int ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
|||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
switch (options.kdfAlgo) {
|
||||
switch (ctx->kdfAlgo) {
|
||||
case ecHKDF_SHA256 :
|
||||
ret = HKDF(SHA256, sharedSecret, sharedSz, options.kdfSalt,
|
||||
options.kdfSaltSz, options.kdfInfo,
|
||||
options.kdfInfoSz, keys, keysLen);
|
||||
ret = HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
|
||||
ctx->kdfSaltSz, ctx->kdfInfo,
|
||||
ctx->kdfInfoSz, keys, keysLen);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
break;
|
||||
|
@ -3720,11 +3917,11 @@ int ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
|||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
encKey = keys;
|
||||
encKey = keys + offset;
|
||||
encIv = encKey + encKeySz;
|
||||
macKey = encKey + encKeySz + ivSz;
|
||||
|
||||
switch (options.macAlgo) {
|
||||
switch (ctx->macAlgo) {
|
||||
case ecHMAC_SHA256:
|
||||
{
|
||||
byte verify[SHA256_DIGEST_SIZE];
|
||||
|
@ -3733,7 +3930,7 @@ int ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
|||
if (ret != 0)
|
||||
return ret;
|
||||
HmacUpdate(&hmac, msg, msgSz-digestSz);
|
||||
HmacUpdate(&hmac, options.macSalt, options.macSaltSz);
|
||||
HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz);
|
||||
HmacFinal(&hmac, verify);
|
||||
|
||||
if (memcmp(verify, msg + msgSz - digestSz, digestSz) != 0) {
|
||||
|
@ -3746,7 +3943,7 @@ int ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
|||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
switch (options.encAlgo) {
|
||||
switch (ctx->encAlgo) {
|
||||
case ecAES_128_CBC:
|
||||
{
|
||||
Aes aes;
|
||||
|
|
|
@ -323,6 +323,14 @@ void CTaoCryptErrorString(int error, char* buffer)
|
|||
XSTRNCPY(buffer, "ASN OCSP sig error, confirm failure", max);
|
||||
break;
|
||||
|
||||
case BAD_ENC_STATE_E:
|
||||
XSTRNCPY(buffer, "Bad ecc encrypt state operation", max);
|
||||
break;
|
||||
|
||||
case BAD_PADDING_E:
|
||||
XSTRNCPY(buffer, "Bad padding, message wrong length", max);
|
||||
break;
|
||||
|
||||
default:
|
||||
XSTRNCPY(buffer, "unknown error number", max);
|
||||
|
||||
|
|
|
@ -3628,12 +3628,12 @@ int ecc_encrypt_test(void)
|
|||
for (i = 0; i < 48; i++)
|
||||
msg[i] = i;
|
||||
|
||||
/* send encrypted msg to B */
|
||||
/* encrypt msg to B */
|
||||
ret = ecc_encrypt(&userA, &userB, msg, sizeof(msg), out, &outSz, NULL);
|
||||
if (ret != 0)
|
||||
return -3003;
|
||||
|
||||
/* decrypted msg to B */
|
||||
/* decrypt msg from A */
|
||||
ret = ecc_decrypt(&userB, &userA, out, outSz, plain, &plainSz, NULL);
|
||||
if (ret != 0)
|
||||
return -3004;
|
||||
|
@ -3641,6 +3641,84 @@ int ecc_encrypt_test(void)
|
|||
if (memcmp(plain, msg, sizeof(msg)) != 0)
|
||||
return -3005;
|
||||
|
||||
|
||||
{ /* let's verify message exchange works, A is client, B is server */
|
||||
ecEncCtx* cliCtx = ecc_ctx_new(REQ_RESP_CLIENT, &rng);
|
||||
ecEncCtx* srvCtx = ecc_ctx_new(REQ_RESP_SERVER, &rng);
|
||||
|
||||
byte cliSalt[EXCHANGE_SALT_SZ];
|
||||
byte srvSalt[EXCHANGE_SALT_SZ];
|
||||
const byte* tmpSalt;
|
||||
|
||||
if (cliCtx == NULL || srvCtx == NULL)
|
||||
return -3006;
|
||||
|
||||
/* get salt to send to peer */
|
||||
tmpSalt = ecc_ctx_get_own_salt(cliCtx);
|
||||
if (tmpSalt == NULL)
|
||||
return -3007;
|
||||
memcpy(cliSalt, tmpSalt, EXCHANGE_SALT_SZ);
|
||||
|
||||
tmpSalt = ecc_ctx_get_own_salt(srvCtx);
|
||||
if (tmpSalt == NULL)
|
||||
return -3007;
|
||||
memcpy(srvSalt, tmpSalt, EXCHANGE_SALT_SZ);
|
||||
|
||||
/* in actual use, we'd get the peer's salt over the transport */
|
||||
ret = ecc_ctx_set_peer_salt(cliCtx, srvSalt);
|
||||
ret += ecc_ctx_set_peer_salt(srvCtx, cliSalt);
|
||||
|
||||
if (ret != 0)
|
||||
return -3008;
|
||||
|
||||
/* get encrypted msg (request) to send to B */
|
||||
outSz = sizeof(out);
|
||||
ret = ecc_encrypt(&userA, &userB, msg, sizeof(msg), out, &outSz,cliCtx);
|
||||
if (ret != 0)
|
||||
return -3009;
|
||||
|
||||
/* B decrypts msg (request) from A */
|
||||
plainSz = sizeof(plain);
|
||||
ret = ecc_decrypt(&userB, &userA, out, outSz, plain, &plainSz, srvCtx);
|
||||
if (ret != 0)
|
||||
return -3010;
|
||||
|
||||
if (memcmp(plain, msg, sizeof(msg)) != 0)
|
||||
return -3011;
|
||||
|
||||
{
|
||||
/* msg2 (response) from B to A */
|
||||
byte msg2[48];
|
||||
byte plain2[48];
|
||||
byte out2[80];
|
||||
word32 outSz2 = sizeof(out2);
|
||||
word32 plainSz2 = sizeof(plain2);
|
||||
|
||||
for (i = 0; i < 48; i++)
|
||||
msg2[i] = i+48;
|
||||
|
||||
/* get encrypted msg (response) to send to B */
|
||||
ret = ecc_encrypt(&userB, &userA, msg2, sizeof(msg2), out2,
|
||||
&outSz2, srvCtx);
|
||||
if (ret != 0)
|
||||
return -3012;
|
||||
|
||||
/* A decrypts msg (response) from B */
|
||||
ret = ecc_decrypt(&userA, &userB, out2, outSz2, plain2, &plainSz2,
|
||||
cliCtx);
|
||||
if (ret != 0)
|
||||
return -3013;
|
||||
|
||||
if (memcmp(plain2, msg2, sizeof(msg2)) != 0)
|
||||
return -3014;
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
ecc_ctx_free(srvCtx);
|
||||
ecc_ctx_free(cliCtx);
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
ecc_free(&userB);
|
||||
ecc_free(&userA);
|
||||
|
||||
|
|
|
@ -119,6 +119,7 @@ CYASSL_API
|
|||
int ecc_sig_size(ecc_key* key);
|
||||
|
||||
|
||||
#ifdef HAVE_ECC_ENCRYPT
|
||||
/* ecc encrypt */
|
||||
|
||||
enum ecEncAlgo {
|
||||
|
@ -137,34 +138,39 @@ enum ecMacAlgo {
|
|||
};
|
||||
|
||||
enum {
|
||||
KEY_SIZE_128 = 16,
|
||||
KEY_SIZE_256 = 32,
|
||||
IV_SIZE_64 = 8
|
||||
KEY_SIZE_128 = 16,
|
||||
KEY_SIZE_256 = 32,
|
||||
IV_SIZE_64 = 8,
|
||||
EXCHANGE_SALT_SZ = 16,
|
||||
EXCHANGE_INFO_SZ = 23
|
||||
};
|
||||
|
||||
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;
|
||||
enum ecFlags {
|
||||
REQ_RESP_CLIENT = 1,
|
||||
REQ_RESP_SERVER = 2
|
||||
};
|
||||
|
||||
|
||||
typedef struct ecEncCtx ecEncCtx;
|
||||
|
||||
CYASSL_API
|
||||
void ecc_encrypt_init_options(ecEncOptions*); /* init and set to defaults */
|
||||
ecEncCtx* ecc_ctx_new(int flags, RNG* rng);
|
||||
CYASSL_API
|
||||
void ecc_encrypt_free_options(ecEncOptions*); /* release/clear options */
|
||||
void ecc_ctx_free(ecEncCtx*);
|
||||
|
||||
CYASSL_API
|
||||
const byte* ecc_ctx_get_own_salt(ecEncCtx*);
|
||||
CYASSL_API
|
||||
int ecc_ctx_set_peer_salt(ecEncCtx*, const byte* salt);
|
||||
|
||||
CYASSL_API
|
||||
int ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
||||
word32 msgSz, byte* out, word32* outSz, ecEncOptions* options);
|
||||
word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx);
|
||||
CYASSL_API
|
||||
int ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
||||
word32 msgSz, byte* out, word32* outSz, ecEncOptions* options);
|
||||
word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx);
|
||||
|
||||
#endif /* HAVE_ECC_ENCRYPT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
|
|
@ -114,6 +114,9 @@ enum {
|
|||
ASN_CRL_NO_SIGNER_E = -190, /* ASN CRL no signer to confirm failure */
|
||||
ASN_OCSP_CONFIRM_E = -191, /* ASN OCSP signature confirm failure */
|
||||
|
||||
BAD_ENC_STATE_E = -192, /* Bad ecc enc state operation */
|
||||
BAD_PADDING_E = -193, /* Bad padding, msg not correct length */
|
||||
|
||||
MIN_CODE_E = -200 /* errors -101 - -199 */
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue