F-1715 F-2114 F-3224 F-3690 F-4120 F-4123 F-4124 F-5614 F-5615: replace hardcoded/UAF-prone secrets and keys with RNG-generated values, zeroize key material before free, and flag non-constant-time secret comparisons
parent
717e52d02b
commit
210e9caf3e
|
|
@ -87,6 +87,7 @@
|
|||
|
||||
/* wolfcrypt includes */
|
||||
#include "wolfssl/wolfcrypt/types.h" /* types and X-defines */
|
||||
#include "wolfssl/wolfcrypt/memory.h" /* For wc_ForceZero */
|
||||
|
||||
#ifndef CCBVAULTIC_NO_SHA
|
||||
#include "wolfssl/wolfcrypt/hash.h" /* For HASH_FLAGS and types */
|
||||
|
|
@ -156,6 +157,31 @@ static void hexdump(const unsigned char* p, size_t len)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
/* Constant-time buffer compare for secret material.
|
||||
*
|
||||
* wolfSSL's own constant-time compare (ConstantCompare() in
|
||||
* wolfcrypt/src/misc.c) is WOLFSSL_LOCAL and not exported, so it can't be
|
||||
* called from application code. Every byte is compared regardless of where
|
||||
* a mismatch occurs, so the runtime doesn't leak position information via
|
||||
* early-exit timing.
|
||||
*
|
||||
* Returns 0 if the buffers are equal, non-zero otherwise. */
|
||||
static int const_time_memcmp(const void* a, const void* b, size_t len)
|
||||
{
|
||||
const byte* pa = (const byte*)a;
|
||||
const byte* pb = (const byte*)b;
|
||||
byte diff = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
diff |= (byte)(pa[i] ^ pb[i]);
|
||||
}
|
||||
|
||||
return (int)diff;
|
||||
}
|
||||
#endif /* WOLF_CRYPTO_CB */
|
||||
|
||||
/* Helper to translate vlt return codes to wolfSSL code */
|
||||
static int translateError(int vlt_rc)
|
||||
{
|
||||
|
|
@ -231,10 +257,14 @@ void ccbVaultIc_Cleanup(ccbVaultIc_Context *c)
|
|||
return;
|
||||
|
||||
/* Free allocated buffers */
|
||||
if (c->m != NULL)
|
||||
if (c->m != NULL) {
|
||||
wc_ForceZero(c->m, c->m_len);
|
||||
XFREE(c->m, NULL, NULL);
|
||||
if (c->aescbc_key != NULL)
|
||||
}
|
||||
if (c->aescbc_key != NULL) {
|
||||
wc_ForceZero(c->aescbc_key, c->aescbc_keylen);
|
||||
XFREE(c->aescbc_key, NULL, NULL);
|
||||
}
|
||||
|
||||
clearContext(c);
|
||||
|
||||
|
|
@ -975,10 +1005,12 @@ static int HandleCipherCallback(int devId, wc_CryptoInfo* info,
|
|||
vlt_mode = VLT_DECRYPT_MODE;
|
||||
}
|
||||
|
||||
/* Check if key is not the same as last time */
|
||||
/* Check if key is not the same as last time. Uses a constant-time
|
||||
* compare since this is secret key material, even though this
|
||||
* check only gates a cache refresh (not authentication). */
|
||||
if ((c->aescbc_key == NULL) ||
|
||||
(c->aescbc_keylen != aes->keylen) ||
|
||||
(XMEMCMP(c->aescbc_key, aes->devKey, aes->keylen))) {
|
||||
(const_time_memcmp(c->aescbc_key, aes->devKey, aes->keylen))) {
|
||||
#if defined(CCBVAULTIC_DEBUG_ALL)
|
||||
XPRINTF(" New AES Key: ckey:%p clen:%lu akey:%p alen:%u\n",
|
||||
c->aescbc_key,c->aescbc_keylen, aes->devKey, aes->keylen);
|
||||
|
|
@ -986,6 +1018,7 @@ static int HandleCipherCallback(int devId, wc_CryptoInfo* info,
|
|||
#endif
|
||||
/* Free the current key buffer if necessary */
|
||||
if (c->aescbc_key != NULL) {
|
||||
wc_ForceZero(c->aescbc_key, c->aescbc_keylen);
|
||||
XFREE(c->aescbc_key, NULL, NULL);
|
||||
c->aescbc_key = NULL;
|
||||
c->aescbc_keylen = 0;
|
||||
|
|
|
|||
|
|
@ -218,6 +218,7 @@ static int init_pk_key(Cert* req, void** keyPtr, WC_RNG* rng, byte* der,
|
|||
ret = wc_ecc_init((ecc_key*)*keyPtr);
|
||||
if (ret != 0) {
|
||||
XFREE(*keyPtr, NULL, DYNAMIC_TYPE_ECC);
|
||||
*keyPtr = NULL;
|
||||
break;
|
||||
}
|
||||
ret = wc_ecc_make_key_ex(rng, 32, (ecc_key*)*keyPtr, ECC_SECP256R1);
|
||||
|
|
@ -249,6 +250,7 @@ static int init_pk_key(Cert* req, void** keyPtr, WC_RNG* rng, byte* der,
|
|||
ret = wc_InitRsaKey((RsaKey*)*keyPtr, NULL);
|
||||
if (ret != 0) {
|
||||
XFREE(*keyPtr, NULL, DYNAMIC_TYPE_RSA);
|
||||
*keyPtr = NULL;
|
||||
break;
|
||||
}
|
||||
ret = wc_MakeRsaKey((RsaKey*)*keyPtr, 2048, WC_RSA_EXPONENT, rng);
|
||||
|
|
@ -280,6 +282,7 @@ static int init_pk_key(Cert* req, void** keyPtr, WC_RNG* rng, byte* der,
|
|||
ret = wc_ed25519_init((ed25519_key*)*keyPtr);
|
||||
if (ret != 0) {
|
||||
XFREE(*keyPtr, NULL, DYNAMIC_TYPE_ED25519);
|
||||
*keyPtr = NULL;
|
||||
break;
|
||||
}
|
||||
ret = wc_ed25519_make_key(rng, ED25519_KEY_SIZE,
|
||||
|
|
|
|||
|
|
@ -192,7 +192,6 @@ int Des3Encrypt(Des3* des3, byte* key, int size, FILE* inFile, FILE* outFile)
|
|||
*/
|
||||
int Des3Decrypt(Des3* des3, byte* key, int size, FILE* inFile, FILE* outFile)
|
||||
{
|
||||
WC_RNG rng;
|
||||
byte iv[DES3_BLOCK_SIZE];
|
||||
byte* input = NULL;
|
||||
byte* output = NULL;
|
||||
|
|
@ -202,7 +201,6 @@ int Des3Decrypt(Des3* des3, byte* key, int size, FILE* inFile, FILE* outFile)
|
|||
int ret = 0;
|
||||
int length;
|
||||
int aSize;
|
||||
int rngInit = 0;
|
||||
int des3Init = 0;
|
||||
|
||||
fseek(inFile, 0, SEEK_END);
|
||||
|
|
@ -228,14 +226,6 @@ int Des3Decrypt(Des3* des3, byte* key, int size, FILE* inFile, FILE* outFile)
|
|||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
ret = wc_InitRng(&rng);
|
||||
if (ret != 0)
|
||||
XPRINTF("Failed to initialize random number generator\n");
|
||||
else
|
||||
rngInit = 1;
|
||||
}
|
||||
|
||||
/* reads from inFile and writes whatever is there to the input array */
|
||||
if (ret == 0) {
|
||||
ret = fread(input, 1, length, inFile);
|
||||
|
|
@ -332,8 +322,6 @@ int Des3Decrypt(Des3* des3, byte* key, int size, FILE* inFile, FILE* outFile)
|
|||
fclose(outFile);
|
||||
if (des3Init)
|
||||
wc_Des3Free(des3);
|
||||
if (rngInit)
|
||||
wc_FreeRng(&rng);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -460,15 +448,19 @@ int main(int argc, char** argv)
|
|||
}
|
||||
|
||||
if (inCheck == 0 || outCheck == 0) {
|
||||
XPRINTF("Must have both input and output file");
|
||||
XPRINTF(": -i filename -o filename\n");
|
||||
XPRINTF("Must have both input and output file");
|
||||
XPRINTF(": -i filename -o filename\n");
|
||||
if (inFile != NULL) fclose(inFile);
|
||||
if (outFile != NULL) fclose(outFile);
|
||||
}
|
||||
|
||||
else if (ret == 0 && choice != 'n' && inFile != NULL) {
|
||||
else if (ret == 0 && choice != 'n' && inFile != NULL && outFile != NULL) {
|
||||
key = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER); /* sets size memory of key */
|
||||
if (key == NULL) {
|
||||
XPRINTF("Failed to allocate memory for key\n");
|
||||
ret = -1050;
|
||||
fclose(inFile);
|
||||
if (outFile != NULL)
|
||||
fclose(outFile);
|
||||
}
|
||||
else {
|
||||
ret = NoEcho((char*)key, size);
|
||||
|
|
@ -481,12 +473,23 @@ int main(int argc, char** argv)
|
|||
else {
|
||||
wc_ForceZero(key, size);
|
||||
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
fclose(inFile);
|
||||
if (outFile != NULL)
|
||||
fclose(outFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (choice == 'n') {
|
||||
XPRINTF("Must select either -e[56,112,168] or -d[56,112,168] for \
|
||||
else {
|
||||
if (choice == 'n') {
|
||||
XPRINTF("Must select either -e[56,112,168] or -d[56,112,168] for \
|
||||
encryption and decryption\n");
|
||||
}
|
||||
if (inFile != NULL) {
|
||||
fclose(inFile);
|
||||
}
|
||||
if (outFile != NULL) {
|
||||
fclose(outFile);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -202,7 +202,6 @@ int AesEncrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile)
|
|||
*/
|
||||
int AesDecrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile)
|
||||
{
|
||||
WC_RNG rng;
|
||||
byte iv[AES_BLOCK_SIZE];
|
||||
byte* input = NULL;
|
||||
byte* output = NULL;
|
||||
|
|
@ -212,7 +211,6 @@ int AesDecrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile)
|
|||
int ret = 0;
|
||||
int length;
|
||||
int aSize;
|
||||
int rngInit = 0;
|
||||
int aesInit = 0;
|
||||
|
||||
fseek(inFile, 0, SEEK_END);
|
||||
|
|
@ -236,14 +234,6 @@ int AesDecrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile)
|
|||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
ret = wc_InitRng(&rng);
|
||||
if (ret != 0)
|
||||
XPRINTF("Failed to initialize random number generator\n");
|
||||
else
|
||||
rngInit = 1;
|
||||
}
|
||||
|
||||
/* reads from inFile and writes whatever is there to the input array */
|
||||
if (ret == 0) {
|
||||
ret = fread(input, 1, length, inFile);
|
||||
|
|
@ -344,8 +334,6 @@ int AesDecrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile)
|
|||
fclose(outFile);
|
||||
if (aesInit)
|
||||
wc_AesFree(aes);
|
||||
if (rngInit)
|
||||
wc_FreeRng(&rng);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -482,14 +470,19 @@ int main(int argc, char** argv)
|
|||
}
|
||||
}
|
||||
if (inCheck == 0 || outCheck == 0) {
|
||||
XPRINTF("Must have both input and output file");
|
||||
XPRINTF(": -i filename -o filename\n");
|
||||
XPRINTF("Must have both input and output file");
|
||||
XPRINTF(": -i filename -o filename\n");
|
||||
if (inFile != NULL) fclose(inFile);
|
||||
if (outFile != NULL) fclose(outFile);
|
||||
}
|
||||
else if (ret == 0 && choice != 'n' && inFile != NULL) {
|
||||
else if (ret == 0 && choice != 'n' && inFile != NULL && outFile != NULL) {
|
||||
key = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER); /* sets size memory of key */
|
||||
if (key == NULL) {
|
||||
XPRINTF("Failed to allocate memory for key\n");
|
||||
ret = -1050;
|
||||
fclose(inFile);
|
||||
if (outFile != NULL)
|
||||
fclose(outFile);
|
||||
}
|
||||
else {
|
||||
ret = NoEcho((char*)key, size);
|
||||
|
|
@ -502,13 +495,24 @@ int main(int argc, char** argv)
|
|||
else {
|
||||
wc_ForceZero(key, size);
|
||||
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
fclose(inFile);
|
||||
if (outFile != NULL)
|
||||
fclose(outFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (choice == 'n') {
|
||||
XPRINTF("Must select either -e[128, 192, 256] or -d[128, 192, 256] \
|
||||
else {
|
||||
if (choice == 'n') {
|
||||
XPRINTF("Must select either -e[128, 192, 256] or -d[128, 192, 256] \
|
||||
for encryption and decryption\n");
|
||||
ret = -110;
|
||||
ret = -110;
|
||||
}
|
||||
if (inFile != NULL) {
|
||||
fclose(inFile);
|
||||
}
|
||||
if (outFile != NULL) {
|
||||
fclose(outFile);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -195,7 +195,6 @@ int AesEncrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile)
|
|||
*/
|
||||
int AesDecrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile)
|
||||
{
|
||||
WC_RNG rng;
|
||||
byte iv[AES_BLOCK_SIZE];
|
||||
byte* input = NULL;
|
||||
byte* output = NULL;
|
||||
|
|
@ -205,7 +204,6 @@ int AesDecrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile)
|
|||
int ret = 0;
|
||||
int length;
|
||||
int aSize;
|
||||
int rngInit = 0;
|
||||
int aesInit = 0;
|
||||
|
||||
fseek(inFile, 0, SEEK_END);
|
||||
|
|
@ -230,14 +228,6 @@ int AesDecrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile)
|
|||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
ret = wc_InitRng(&rng);
|
||||
if (ret != 0)
|
||||
XPRINTF("Failed to initialize random number generator\n");
|
||||
else
|
||||
rngInit = 1;
|
||||
}
|
||||
|
||||
/* reads from inFile and writes whatever is there to the input array */
|
||||
if (ret == 0) {
|
||||
ret = fread(input, 1, length, inFile);
|
||||
|
|
@ -337,8 +327,6 @@ int AesDecrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile)
|
|||
fclose(outFile);
|
||||
if (aesInit)
|
||||
wc_AesFree(aes);
|
||||
if (rngInit)
|
||||
wc_FreeRng(&rng);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -475,14 +463,19 @@ int main(int argc, char** argv)
|
|||
}
|
||||
}
|
||||
if (inCheck == 0 || outCheck == 0) {
|
||||
XPRINTF("Must have both input and output file");
|
||||
XPRINTF(": -i filename -o filename\n");
|
||||
XPRINTF("Must have both input and output file");
|
||||
XPRINTF(": -i filename -o filename\n");
|
||||
if (inFile != NULL) fclose(inFile);
|
||||
if (outFile != NULL) fclose(outFile);
|
||||
}
|
||||
else if (ret == 0 && choice != 'n' && inFile != NULL) {
|
||||
else if (ret == 0 && choice != 'n' && inFile != NULL && outFile != NULL) {
|
||||
key = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER); /* sets size memory of key */
|
||||
if (key == NULL) {
|
||||
XPRINTF("Failed to allocate memory for key\n");
|
||||
ret = -1050;
|
||||
fclose(inFile);
|
||||
if (outFile != NULL)
|
||||
fclose(outFile);
|
||||
}
|
||||
else {
|
||||
ret = NoEcho((char*)key, size);
|
||||
|
|
@ -495,13 +488,24 @@ int main(int argc, char** argv)
|
|||
else {
|
||||
wc_ForceZero(key, size);
|
||||
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
fclose(inFile);
|
||||
if (outFile != NULL)
|
||||
fclose(outFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (choice == 'n') {
|
||||
XPRINTF("Must select either -e[128, 192, 256] or -d[128, 192, 256] \
|
||||
else {
|
||||
if (choice == 'n') {
|
||||
XPRINTF("Must select either -e[128, 192, 256] or -d[128, 192, 256] \
|
||||
for encryption and decryption\n");
|
||||
ret = -110;
|
||||
ret = -110;
|
||||
}
|
||||
if (inFile != NULL) {
|
||||
fclose(inFile);
|
||||
}
|
||||
if (outFile != NULL) {
|
||||
fclose(outFile);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -416,14 +416,19 @@ int main(int argc, char** argv)
|
|||
}
|
||||
}
|
||||
if (inCheck == 0 || outCheck == 0) {
|
||||
XPRINTF("Must have both input and output file");
|
||||
XPRINTF(": -i filename -o filename\n");
|
||||
XPRINTF("Must have both input and output file");
|
||||
XPRINTF(": -i filename -o filename\n");
|
||||
if (inFile != NULL) fclose(inFile);
|
||||
if (outFile != NULL) fclose(outFile);
|
||||
}
|
||||
else if (ret == 0 && choice != 'n' && inFile != NULL) {
|
||||
else if (ret == 0 && choice != 'n' && inFile != NULL && outFile != NULL) {
|
||||
key = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER); /* sets size memory of key */
|
||||
if (key == NULL) {
|
||||
XPRINTF("Failed to allocate memory for key\n");
|
||||
ret = -1050;
|
||||
fclose(inFile);
|
||||
if (outFile != NULL)
|
||||
fclose(outFile);
|
||||
}
|
||||
else {
|
||||
ret = NoEcho((char*)key, size);
|
||||
|
|
@ -436,13 +441,24 @@ int main(int argc, char** argv)
|
|||
else {
|
||||
wc_ForceZero(key, size);
|
||||
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
fclose(inFile);
|
||||
if (outFile != NULL)
|
||||
fclose(outFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (choice == 'n') {
|
||||
XPRINTF("Must select either -e[128, 192, 256] or -d[128, 192, 256] \
|
||||
else {
|
||||
if (choice == 'n') {
|
||||
XPRINTF("Must select either -e[128, 192, 256] or -d[128, 192, 256] \
|
||||
for encryption and decryption\n");
|
||||
ret = -110;
|
||||
ret = -110;
|
||||
}
|
||||
if (inFile != NULL) {
|
||||
fclose(inFile);
|
||||
}
|
||||
if (outFile != NULL) {
|
||||
fclose(outFile);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -180,6 +180,7 @@ int encrypt_file_AesGCM(const char *in_file, const char *out_file,
|
|||
byte key[AES_KEY_SIZE];
|
||||
byte tag_enc[AESGCM_TAG_SIZE];
|
||||
Aes gcm;
|
||||
int aes_initialized = 0;
|
||||
|
||||
if (!in_file || !out_file || !key_str || !iv_str) {
|
||||
return BAD_FUNC_ARG;
|
||||
|
|
@ -242,6 +243,7 @@ int encrypt_file_AesGCM(const char *in_file, const char *out_file,
|
|||
printf("AesInit returned: %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
aes_initialized = 1;
|
||||
|
||||
ret = wc_AesGcmEncryptInit(&gcm, key, AES_KEY_SIZE, iv, AES_IV_SIZE);
|
||||
if (ret == 0) {
|
||||
|
|
@ -304,6 +306,9 @@ int encrypt_file_AesGCM(const char *in_file, const char *out_file,
|
|||
}
|
||||
printf("File encryption with AES GCM complete.\n");
|
||||
exit:
|
||||
if (aes_initialized) {
|
||||
wc_AesFree(&gcm);
|
||||
}
|
||||
wc_ForceZero(key, AES_KEY_SIZE);
|
||||
wc_ForceZero(iv, AES_IV_SIZE);
|
||||
wc_ForceZero(tag_enc, AESGCM_TAG_SIZE);
|
||||
|
|
@ -352,6 +357,7 @@ int decrypt_file_AesGCM(const char *in_file, const char *out_file,
|
|||
byte key[AES_KEY_SIZE];
|
||||
byte tag[AESGCM_TAG_SIZE];
|
||||
Aes gcm;
|
||||
int aes_initialized = 0;
|
||||
|
||||
if (!in_file || !out_file || !key_str) {
|
||||
return BAD_FUNC_ARG;
|
||||
|
|
@ -434,6 +440,14 @@ int decrypt_file_AesGCM(const char *in_file, const char *out_file,
|
|||
goto exit;
|
||||
}
|
||||
|
||||
/* inits aes structure */
|
||||
ret = wc_AesInit(&gcm, NULL, INVALID_DEVID);
|
||||
if (ret != 0) {
|
||||
printf("AesInit returned: %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
aes_initialized = 1;
|
||||
|
||||
ret = wc_AesGcmDecryptInit(&gcm, key, AES_KEY_SIZE, iv, AES_IV_SIZE);
|
||||
|
||||
while (ret == 0) {
|
||||
|
|
@ -457,6 +471,9 @@ int decrypt_file_AesGCM(const char *in_file, const char *out_file,
|
|||
ret = wc_AesGcmDecryptFinal(&gcm, tag, AESGCM_TAG_SIZE);
|
||||
}
|
||||
exit:
|
||||
if (aes_initialized) {
|
||||
wc_AesFree(&gcm);
|
||||
}
|
||||
wc_ForceZero(key, AES_KEY_SIZE);
|
||||
wc_ForceZero(iv, AES_IV_SIZE);
|
||||
wc_ForceZero(tag, AESGCM_TAG_SIZE);
|
||||
|
|
|
|||
|
|
@ -175,7 +175,6 @@ int CamelliaEncrypt(Camellia* cam, byte* key, int size, FILE* inFile,
|
|||
int CamelliaDecrypt(Camellia* cam, byte* key, int size, FILE* inFile,
|
||||
FILE* outFile)
|
||||
{
|
||||
WC_RNG rng;
|
||||
byte iv[CAMELLIA_BLOCK_SIZE];
|
||||
byte* input = NULL;
|
||||
byte* output = NULL;
|
||||
|
|
@ -185,7 +184,6 @@ int CamelliaDecrypt(Camellia* cam, byte* key, int size, FILE* inFile,
|
|||
int ret = 0;
|
||||
int length;
|
||||
int aSize;
|
||||
int rngInit = 0;
|
||||
|
||||
fseek(inFile, 0, SEEK_END);
|
||||
length = ftell(inFile);
|
||||
|
|
@ -209,14 +207,6 @@ int CamelliaDecrypt(Camellia* cam, byte* key, int size, FILE* inFile,
|
|||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
ret = wc_InitRng(&rng);
|
||||
if (ret != 0)
|
||||
XPRINTF("Failed to initialize random number generator\n");
|
||||
else
|
||||
rngInit = 1;
|
||||
}
|
||||
|
||||
/* reads from inFile and writes whatever is there to the input array */
|
||||
if (ret == 0) {
|
||||
ret = fread(input, 1, length, inFile);
|
||||
|
|
@ -297,8 +287,6 @@ int CamelliaDecrypt(Camellia* cam, byte* key, int size, FILE* inFile,
|
|||
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
fclose(inFile);
|
||||
fclose(outFile);
|
||||
if (rngInit)
|
||||
wc_FreeRng(&rng);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -425,15 +413,19 @@ int main(int argc, char** argv)
|
|||
}
|
||||
}
|
||||
if (inCheck == 0 || outCheck == 0) {
|
||||
XPRINTF("Must have both input and output file");
|
||||
XPRINTF(": -i filename -o filename\n");
|
||||
XPRINTF("Must have both input and output file");
|
||||
XPRINTF(": -i filename -o filename\n");
|
||||
if (inFile != NULL) fclose(inFile);
|
||||
if (outFile != NULL) fclose(outFile);
|
||||
}
|
||||
|
||||
else if (ret == 0 && choice != 'n' && inFile != NULL) {
|
||||
else if (ret == 0 && choice != 'n' && inFile != NULL && outFile != NULL) {
|
||||
key = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER); /* sets size memory of key */
|
||||
if (key == NULL) {
|
||||
XPRINTF("Failed to allocate memory for key\n");
|
||||
ret = -1050;
|
||||
fclose(inFile);
|
||||
if (outFile != NULL)
|
||||
fclose(outFile);
|
||||
}
|
||||
else {
|
||||
ret = NoEcho((char*)key, size);
|
||||
|
|
@ -446,12 +438,23 @@ int main(int argc, char** argv)
|
|||
else {
|
||||
wc_ForceZero(key, size);
|
||||
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
fclose(inFile);
|
||||
if (outFile != NULL)
|
||||
fclose(outFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (choice == 'n') {
|
||||
XPRINTF("Must select either -e[128,192,256] or -d[128,192,256] for \
|
||||
else {
|
||||
if (choice == 'n') {
|
||||
XPRINTF("Must select either -e[128,192,256] or -d[128,192,256] for \
|
||||
encryption and decryption\n");
|
||||
}
|
||||
if (inFile != NULL) {
|
||||
fclose(inFile);
|
||||
}
|
||||
if (outFile != NULL) {
|
||||
fclose(outFile);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@
|
|||
#include <wolfssl/options.h>
|
||||
#include <wolfssl/ssl.h>
|
||||
#include <wolfssl/error-ssl.h>
|
||||
#include <wolfssl/wolfcrypt/random.h>
|
||||
#include <wolfssl/wolfcrypt/pwdbased.h>
|
||||
#include <wolfssl/wolfcrypt/memory.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -61,7 +64,8 @@
|
|||
/* Epoch for the multicast session */
|
||||
#define MCAST_EPOCH 1
|
||||
|
||||
#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_MULTICAST)
|
||||
#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_MULTICAST) && \
|
||||
defined(HAVE_PBKDF2) && !defined(NO_PWDBASED)
|
||||
|
||||
/* Global flag for clean shutdown */
|
||||
static volatile sig_atomic_t running = 1;
|
||||
|
|
@ -230,14 +234,83 @@ int main(int argc, char** argv)
|
|||
#endif
|
||||
|
||||
/* Initialize the pre-shared secrets (same for all peers) */
|
||||
memset(pms, 0x23, sizeof(pms));
|
||||
memset(clientRandom, 0xA5, sizeof(clientRandom));
|
||||
memset(serverRandom, 0x5A, sizeof(serverRandom));
|
||||
{
|
||||
const char* envSecret = getenv("DTLS_MCAST_SECRET");
|
||||
char genSecret[2 * PMS_SIZE + 1];
|
||||
const char* secret;
|
||||
size_t len;
|
||||
|
||||
if (envSecret != NULL) {
|
||||
secret = envSecret;
|
||||
}
|
||||
else {
|
||||
byte secretBytes[PMS_SIZE];
|
||||
WC_RNG rng;
|
||||
|
||||
printf("WARNING: DTLS_MCAST_SECRET not set. Generating a random "
|
||||
"multicast secret for this run.\n"
|
||||
" Export the printed value as DTLS_MCAST_SECRET "
|
||||
"on ALL peers so they can share the same secret.\n");
|
||||
|
||||
ret = wc_InitRng(&rng);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Error: wc_InitRng failed: %d\n", ret);
|
||||
return 1;
|
||||
}
|
||||
ret = wc_RNG_GenerateBlock(&rng, secretBytes, sizeof(secretBytes));
|
||||
wc_FreeRng(&rng);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Error: Failed to generate random multicast "
|
||||
"secret: %d\n", ret);
|
||||
wc_ForceZero(secretBytes, sizeof(secretBytes));
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)sizeof(secretBytes); i++)
|
||||
snprintf(&genSecret[i * 2], 3, "%02x", secretBytes[i]);
|
||||
wc_ForceZero(secretBytes, sizeof(secretBytes));
|
||||
|
||||
printf("Generated multicast secret (hex): %s\n"
|
||||
"Export this value as DTLS_MCAST_SECRET on ALL peers.\n",
|
||||
genSecret);
|
||||
|
||||
secret = genSecret;
|
||||
}
|
||||
|
||||
len = strlen(secret);
|
||||
|
||||
/* PBKDF2 guards against a weak DTLS_MCAST_SECRET; distinct salts
|
||||
* keep pms/clientRandom/serverRandom independent yet peer-shared. */
|
||||
ret = wc_PBKDF2(pms, (byte*)secret, (int)len,
|
||||
(byte*)"mcast-pms", 9, 4096, sizeof(pms), WC_SHA256);
|
||||
if (ret == 0)
|
||||
ret = wc_PBKDF2(clientRandom, (byte*)secret, (int)len,
|
||||
(byte*)"mcast-client-random", 19, 4096,
|
||||
sizeof(clientRandom), WC_SHA256);
|
||||
if (ret == 0)
|
||||
ret = wc_PBKDF2(serverRandom, (byte*)secret, (int)len,
|
||||
(byte*)"mcast-server-random", 19, 4096,
|
||||
sizeof(serverRandom), WC_SHA256);
|
||||
|
||||
wc_ForceZero(genSecret, sizeof(genSecret));
|
||||
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Error: Failed to derive multicast secret: %d\n",
|
||||
ret);
|
||||
wc_ForceZero(pms, sizeof(pms));
|
||||
wc_ForceZero(clientRandom, sizeof(clientRandom));
|
||||
wc_ForceZero(serverRandom, sizeof(serverRandom));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize wolfSSL */
|
||||
ret = wolfSSL_Init();
|
||||
if (ret != WOLFSSL_SUCCESS) {
|
||||
fprintf(stderr, "Error: wolfSSL_Init failed: %d\n", ret);
|
||||
wc_ForceZero(pms, sizeof(pms));
|
||||
wc_ForceZero(clientRandom, sizeof(clientRandom));
|
||||
wc_ForceZero(serverRandom, sizeof(serverRandom));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -423,6 +496,9 @@ int main(int argc, char** argv)
|
|||
printf("\nNode %d: Shutting down...\n", myId);
|
||||
|
||||
cleanup:
|
||||
wc_ForceZero(pms, sizeof(pms));
|
||||
wc_ForceZero(clientRandom, sizeof(clientRandom));
|
||||
wc_ForceZero(serverRandom, sizeof(serverRandom));
|
||||
if (sslTx != NULL) {
|
||||
wolfSSL_free(sslTx);
|
||||
}
|
||||
|
|
@ -451,7 +527,8 @@ cleanup:
|
|||
#else
|
||||
int main()
|
||||
{
|
||||
fprintf(stderr, "Please configure the wolfssl library with --enable-dtls --enable-mcast.\n");
|
||||
fprintf(stderr, "Please configure the wolfssl library with "
|
||||
"--enable-dtls --enable-mcast --enable-pwdbased.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
#endif /* WOLFSSL_DTLS && WOLFSSL_MULTICAST */
|
||||
#endif /* WOLFSSL_DTLS && WOLFSSL_MULTICAST && HAVE_PBKDF2 && !NO_PWDBASED */
|
||||
|
|
|
|||
|
|
@ -208,8 +208,10 @@ int main(int argc, char** argv)
|
|||
ret = 0; /* Success */
|
||||
|
||||
cleanup:
|
||||
wolfSSL_shutdown(ssl);
|
||||
if (ssl) wolfSSL_free(ssl);
|
||||
if (ssl) {
|
||||
wolfSSL_shutdown(ssl);
|
||||
wolfSSL_free(ssl);
|
||||
}
|
||||
if (session) wolfSSL_SESSION_free(session);
|
||||
if (ctx) wolfSSL_CTX_free(ctx);
|
||||
if (sockfd >= 0) close(sockfd);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@
|
|||
#include <wolfssl/wolfcrypt/memory.h>
|
||||
#include <wolfssl/wolfcrypt/aes.h>
|
||||
#include <wolfssl/wolfcrypt/random.h>
|
||||
#include <wolfssl/wolfcrypt/pwdbased.h>
|
||||
#include <wolfssl/wolfcrypt/sha256.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
@ -48,23 +50,52 @@
|
|||
#define DEFAULT_CLIENT_SESSION_FILE "dtls_client_session.bin"
|
||||
#define DEFAULT_SERVER_SESSION_FILE "dtls_server_session.bin"
|
||||
|
||||
/* AES-256-CBC key (32 bytes) - In production, use a securely generated key.*/
|
||||
static const unsigned char AES_KEY[32] = {
|
||||
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
|
||||
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
|
||||
0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20
|
||||
};
|
||||
/* Passphrase source for session-file encryption; falls back to a demo
|
||||
* value if unset. Set this for anything beyond local demos. */
|
||||
#define SESSION_PASSPHRASE_ENV "DTLS_SESSION_PASSPHRASE"
|
||||
#define DEMO_SESSION_PASSPHRASE "dtls-example-demo-passphrase-change-me"
|
||||
|
||||
/* AES block size */
|
||||
#define AES_BLOCK_SZ 16
|
||||
/* AES block size / PBKDF2 salt size / AES-256 key size */
|
||||
#define GCM_IV_SZ 12
|
||||
#define GCM_TAG_SZ 16
|
||||
#define SESSION_SALT_SZ 16
|
||||
#define SESSION_KEY_SZ 32
|
||||
#define SESSION_PBKDF2_ITERATIONS 100000
|
||||
|
||||
/* File format:
|
||||
* [4 bytes: original data length]
|
||||
* [16 bytes: IV]
|
||||
* [N bytes: encrypted data (padded to AES_BLOCK_SZ)]
|
||||
* [16 bytes: PBKDF2 salt]
|
||||
* [12 bytes: IV]
|
||||
* [16 bytes: auth tag]
|
||||
* [N bytes: encrypted data]
|
||||
*/
|
||||
|
||||
static const char* GetSessionPassphrase(void)
|
||||
{
|
||||
const char* passphrase = getenv(SESSION_PASSPHRASE_ENV);
|
||||
if (passphrase == NULL || passphrase[0] == '\0') {
|
||||
XFPRINTF(stderr,
|
||||
"Warning: %s not set, using demo passphrase. "
|
||||
"Set %s to a real secret for anything beyond local demos.\n",
|
||||
SESSION_PASSPHRASE_ENV, SESSION_PASSPHRASE_ENV);
|
||||
passphrase = DEMO_SESSION_PASSPHRASE;
|
||||
}
|
||||
return passphrase;
|
||||
}
|
||||
|
||||
/*
|
||||
* Derive an AES-256 key from a passphrase and salt using PBKDF2-HMAC-SHA256.
|
||||
* Returns 0 on success, negative on error.
|
||||
*/
|
||||
static int DeriveSessionKey(const char* passphrase,
|
||||
const unsigned char* salt, unsigned int saltSz,
|
||||
unsigned char* key, unsigned int keySz)
|
||||
{
|
||||
return wc_PBKDF2(key, (const byte*)passphrase, (int)strlen(passphrase),
|
||||
salt, (int)saltSz, SESSION_PBKDF2_ITERATIONS,
|
||||
(int)keySz, WC_SHA256);
|
||||
}
|
||||
|
||||
/*
|
||||
* Encrypt session data and save to file
|
||||
* Returns 0 on success, negative on error
|
||||
|
|
@ -76,20 +107,17 @@ int SaveEncryptedSession(const char* filename,
|
|||
FILE* fp = NULL;
|
||||
Aes aes;
|
||||
WC_RNG rng;
|
||||
unsigned char iv[AES_BLOCK_SZ];
|
||||
unsigned char* paddedData = NULL;
|
||||
unsigned char iv[GCM_IV_SZ];
|
||||
unsigned char tag[GCM_TAG_SZ];
|
||||
unsigned char salt[SESSION_SALT_SZ];
|
||||
unsigned char key[SESSION_KEY_SZ];
|
||||
unsigned char* encryptedData = NULL;
|
||||
unsigned int paddedSz;
|
||||
unsigned int padding;
|
||||
unsigned char sizeBuf[4];
|
||||
int ret = 0;
|
||||
int aesInit = 0;
|
||||
int rngInit = 0;
|
||||
|
||||
/* Calculate padded size (must be multiple of AES_BLOCK_SZ) */
|
||||
padding = AES_BLOCK_SZ - (sessionSz % AES_BLOCK_SZ);
|
||||
paddedSz = sessionSz + padding;
|
||||
|
||||
/* Initialize RNG for IV generation */
|
||||
/* Initialize RNG for IV/salt generation */
|
||||
ret = wc_InitRng(&rng);
|
||||
if (ret != 0) {
|
||||
XPRINTF("Error: wc_InitRng failed: %d\n", ret);
|
||||
|
|
@ -98,25 +126,34 @@ int SaveEncryptedSession(const char* filename,
|
|||
rngInit = 1;
|
||||
|
||||
/* Generate random IV */
|
||||
ret = wc_RNG_GenerateBlock(&rng, iv, AES_BLOCK_SZ);
|
||||
ret = wc_RNG_GenerateBlock(&rng, iv, GCM_IV_SZ);
|
||||
if (ret != 0) {
|
||||
XPRINTF("Error: Failed to generate IV: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Allocate buffers */
|
||||
paddedData = (unsigned char*)XMALLOC(paddedSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
encryptedData = (unsigned char*)XMALLOC(paddedSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (paddedData == NULL || encryptedData == NULL) {
|
||||
/* Derive AES key from passphrase */
|
||||
ret = wc_RNG_GenerateBlock(&rng, salt, SESSION_SALT_SZ);
|
||||
if (ret != 0) {
|
||||
XPRINTF("Error: Failed to generate salt: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = DeriveSessionKey(GetSessionPassphrase(), salt, SESSION_SALT_SZ,
|
||||
key, SESSION_KEY_SZ);
|
||||
if (ret != 0) {
|
||||
XPRINTF("Error: Failed to derive session key: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Allocate buffer for encrypted data */
|
||||
encryptedData = (unsigned char*)XMALLOC(sessionSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (encryptedData == NULL && sessionSz > 0) {
|
||||
XPRINTF("Error: Memory allocation failed\n");
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Copy data and add PKCS#7 padding */
|
||||
memcpy(paddedData, sessionData, sessionSz);
|
||||
memset(paddedData + sessionSz, (int)padding, padding);
|
||||
|
||||
/* Initialize AES */
|
||||
ret = wc_AesInit(&aes, NULL, INVALID_DEVID);
|
||||
if (ret != 0) {
|
||||
|
|
@ -125,17 +162,24 @@ int SaveEncryptedSession(const char* filename,
|
|||
}
|
||||
aesInit = 1;
|
||||
|
||||
/* Set AES key for encryption */
|
||||
ret = wc_AesSetKey(&aes, AES_KEY, sizeof(AES_KEY), iv, AES_ENCRYPTION);
|
||||
/* Set AES key for GCM */
|
||||
ret = wc_AesGcmSetKey(&aes, key, sizeof(key));
|
||||
if (ret != 0) {
|
||||
XPRINTF("Error: wc_AesSetKey failed: %d\n", ret);
|
||||
XPRINTF("Error: wc_AesGcmSetKey failed: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Encrypt the data */
|
||||
ret = wc_AesCbcEncrypt(&aes, encryptedData, paddedData, paddedSz);
|
||||
/* Prepare AAD: original data length (4 bytes) */
|
||||
sizeBuf[0] = (sessionSz >> 24) & 0xFF;
|
||||
sizeBuf[1] = (sessionSz >> 16) & 0xFF;
|
||||
sizeBuf[2] = (sessionSz >> 8) & 0xFF;
|
||||
sizeBuf[3] = sessionSz & 0xFF;
|
||||
|
||||
/* Encrypt the data with GCM */
|
||||
ret = wc_AesGcmEncrypt(&aes, encryptedData, sessionData, sessionSz,
|
||||
iv, GCM_IV_SZ, tag, GCM_TAG_SZ, sizeBuf, 4);
|
||||
if (ret != 0) {
|
||||
XPRINTF("Error: wc_AesCbcEncrypt failed: %d\n", ret);
|
||||
XPRINTF("Error: wc_AesGcmEncrypt failed: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
|
@ -147,49 +191,53 @@ int SaveEncryptedSession(const char* filename,
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Write original size (4 bytes, big-endian) */
|
||||
{
|
||||
unsigned char sizeBuf[4];
|
||||
sizeBuf[0] = (sessionSz >> 24) & 0xFF;
|
||||
sizeBuf[1] = (sessionSz >> 16) & 0xFF;
|
||||
sizeBuf[2] = (sessionSz >> 8) & 0xFF;
|
||||
sizeBuf[3] = sessionSz & 0xFF;
|
||||
if (fwrite(sizeBuf, 1, 4, fp) != 4) {
|
||||
XPRINTF("Error: Failed to write size to file\n");
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
/* Write size */
|
||||
if (fwrite(sizeBuf, 1, 4, fp) != 4) {
|
||||
XPRINTF("Error: Failed to write size to file\n");
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Write salt */
|
||||
if (fwrite(salt, 1, SESSION_SALT_SZ, fp) != SESSION_SALT_SZ) {
|
||||
XPRINTF("Error: Failed to write salt to file\n");
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Write IV */
|
||||
if (fwrite(iv, 1, AES_BLOCK_SZ, fp) != AES_BLOCK_SZ) {
|
||||
if (fwrite(iv, 1, GCM_IV_SZ, fp) != GCM_IV_SZ) {
|
||||
XPRINTF("Error: Failed to write IV to file\n");
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Write tag */
|
||||
if (fwrite(tag, 1, GCM_TAG_SZ, fp) != GCM_TAG_SZ) {
|
||||
XPRINTF("Error: Failed to write tag to file\n");
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Write encrypted data */
|
||||
if (fwrite(encryptedData, 1, paddedSz, fp) != paddedSz) {
|
||||
if (sessionSz > 0 && fwrite(encryptedData, 1, sessionSz, fp) != sessionSz) {
|
||||
XPRINTF("Error: Failed to write encrypted data to file\n");
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
XPRINTF("Session saved to %s (%u bytes encrypted)\n", filename, paddedSz);
|
||||
XPRINTF("Session saved to %s (%u bytes encrypted)\n", filename, sessionSz);
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
if (fp != NULL) fclose(fp);
|
||||
if (paddedData != NULL) {
|
||||
wc_ForceZero(paddedData, paddedSz);
|
||||
XFREE(paddedData, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
}
|
||||
if (encryptedData != NULL) {
|
||||
wc_ForceZero(encryptedData, paddedSz);
|
||||
wc_ForceZero(encryptedData, sessionSz);
|
||||
XFREE(encryptedData, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
}
|
||||
if (aesInit) wc_AesFree(&aes);
|
||||
if (rngInit) wc_FreeRng(&rng);
|
||||
wc_ForceZero(key, sizeof(key));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -208,12 +256,14 @@ unsigned char* LoadEncryptedSession(const char* filename,
|
|||
{
|
||||
FILE* fp = NULL;
|
||||
Aes aes;
|
||||
unsigned char iv[AES_BLOCK_SZ];
|
||||
unsigned char iv[GCM_IV_SZ];
|
||||
unsigned char tag[GCM_TAG_SZ];
|
||||
unsigned char salt[SESSION_SALT_SZ];
|
||||
unsigned char key[SESSION_KEY_SZ];
|
||||
unsigned char sizeBuf[4];
|
||||
unsigned char* encryptedData = NULL;
|
||||
unsigned char* decryptedData = NULL;
|
||||
unsigned int originalSz;
|
||||
unsigned int encryptedSz;
|
||||
long fileSize;
|
||||
int ret = 0;
|
||||
int aesInit = 0;
|
||||
|
|
@ -230,13 +280,13 @@ unsigned char* LoadEncryptedSession(const char* filename,
|
|||
fileSize = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
if (fileSize < (4 + AES_BLOCK_SZ + AES_BLOCK_SZ)) {
|
||||
if (fileSize < (4 + SESSION_SALT_SZ + GCM_IV_SZ + GCM_TAG_SZ)) {
|
||||
XPRINTF("Error: File too small to contain valid session data\n");
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Read original size */
|
||||
/* Read size */
|
||||
if (fread(sizeBuf, 1, 4, fp) != 4) {
|
||||
XPRINTF("Error: Failed to read size from file\n");
|
||||
fclose(fp);
|
||||
|
|
@ -247,28 +297,59 @@ unsigned char* LoadEncryptedSession(const char* filename,
|
|||
((unsigned int)sizeBuf[2] << 8) |
|
||||
(unsigned int)sizeBuf[3];
|
||||
|
||||
/* Read IV */
|
||||
if (fread(iv, 1, AES_BLOCK_SZ, fp) != AES_BLOCK_SZ) {
|
||||
XPRINTF("Error: Failed to read IV from file\n");
|
||||
/* Read salt */
|
||||
if (fread(salt, 1, SESSION_SALT_SZ, fp) != SESSION_SALT_SZ) {
|
||||
XPRINTF("Error: Failed to read salt from file\n");
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Calculate encrypted data size */
|
||||
encryptedSz = (unsigned int)(fileSize - 4 - AES_BLOCK_SZ);
|
||||
/* Read IV */
|
||||
if (fread(iv, 1, GCM_IV_SZ, fp) != GCM_IV_SZ) {
|
||||
XPRINTF("Error: Failed to read IV from file\n");
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Read tag */
|
||||
if (fread(tag, 1, GCM_TAG_SZ, fp) != GCM_TAG_SZ) {
|
||||
XPRINTF("Error: Failed to read tag from file\n");
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate buffers */
|
||||
encryptedData = (unsigned char*)XMALLOC(encryptedSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
decryptedData = (unsigned char*)XMALLOC(encryptedSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
/* Derive AES key from passphrase */
|
||||
ret = DeriveSessionKey(GetSessionPassphrase(), salt, SESSION_SALT_SZ,
|
||||
key, SESSION_KEY_SZ);
|
||||
if (ret != 0) {
|
||||
XPRINTF("Error: Failed to derive session key: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((fileSize - 4 - SESSION_SALT_SZ - GCM_IV_SZ - GCM_TAG_SZ) !=
|
||||
(long)originalSz) {
|
||||
XPRINTF("Error: File size does not match expected encrypted data size\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Allocate buffers. Always allocate at least 1 byte so a legitimate
|
||||
* zero-length session is returned as a non-NULL pointer, distinct
|
||||
* from a NULL/failure return. */
|
||||
encryptedData = (unsigned char*)XMALLOC(originalSz > 0 ? originalSz : 1,
|
||||
NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
decryptedData = (unsigned char*)XMALLOC(originalSz > 0 ? originalSz : 1,
|
||||
NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (encryptedData == NULL || decryptedData == NULL) {
|
||||
XPRINTF("Error: Memory allocation failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Read encrypted data */
|
||||
if (fread(encryptedData, 1, encryptedSz, fp) != encryptedSz) {
|
||||
XPRINTF("Error: Failed to read encrypted data from file\n");
|
||||
goto cleanup;
|
||||
if (originalSz > 0) {
|
||||
/* Read encrypted data */
|
||||
if (fread(encryptedData, 1, originalSz, fp) != originalSz) {
|
||||
XPRINTF("Error: Failed to read encrypted data from file\n");
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
|
|
@ -281,52 +362,49 @@ unsigned char* LoadEncryptedSession(const char* filename,
|
|||
}
|
||||
aesInit = 1;
|
||||
|
||||
/* Set AES key for decryption */
|
||||
ret = wc_AesSetKey(&aes, AES_KEY, sizeof(AES_KEY), iv, AES_DECRYPTION);
|
||||
/* Set AES key */
|
||||
ret = wc_AesGcmSetKey(&aes, key, sizeof(key));
|
||||
if (ret != 0) {
|
||||
XPRINTF("Error: wc_AesSetKey failed: %d\n", ret);
|
||||
XPRINTF("Error: wc_AesGcmSetKey failed: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Decrypt the data */
|
||||
ret = wc_AesCbcDecrypt(&aes, decryptedData, encryptedData, encryptedSz);
|
||||
/* Decrypt and authenticate the data */
|
||||
ret = wc_AesGcmDecrypt(&aes, decryptedData, encryptedData, originalSz,
|
||||
iv, GCM_IV_SZ, tag, GCM_TAG_SZ, sizeBuf, 4);
|
||||
if (ret != 0) {
|
||||
XPRINTF("Error: wc_AesCbcDecrypt failed: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Verify padding and original size */
|
||||
if (originalSz > encryptedSz) {
|
||||
XPRINTF("Error: Invalid original size in file\n");
|
||||
XPRINTF("Error: wc_AesGcmDecrypt failed (authentication error): %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
*sessionSz = originalSz;
|
||||
if (bufSz != NULL) {
|
||||
*bufSz = encryptedSz;
|
||||
*bufSz = originalSz > 0 ? originalSz : 1;
|
||||
}
|
||||
XPRINTF("Session loaded from %s (%u bytes)\n", filename, originalSz);
|
||||
|
||||
/* Clean up and return decrypted data */
|
||||
if (encryptedData != NULL) {
|
||||
wc_ForceZero(encryptedData, encryptedSz);
|
||||
wc_ForceZero(encryptedData, originalSz);
|
||||
XFREE(encryptedData, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
}
|
||||
if (aesInit) wc_AesFree(&aes);
|
||||
wc_ForceZero(key, sizeof(key));
|
||||
|
||||
return decryptedData;
|
||||
|
||||
cleanup:
|
||||
if (fp != NULL) fclose(fp);
|
||||
if (encryptedData != NULL) {
|
||||
wc_ForceZero(encryptedData, encryptedSz);
|
||||
wc_ForceZero(encryptedData, originalSz);
|
||||
XFREE(encryptedData, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
}
|
||||
if (decryptedData != NULL) {
|
||||
wc_ForceZero(decryptedData, encryptedSz);
|
||||
wc_ForceZero(decryptedData, originalSz);
|
||||
XFREE(decryptedData, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
}
|
||||
if (aesInit) wc_AesFree(&aes);
|
||||
wc_ForceZero(key, sizeof(key));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -413,13 +413,26 @@ WOLFSSL_CTX* newCTX(void)
|
|||
return ctx;
|
||||
}
|
||||
|
||||
/* Stateless cookie secret, generated once per run. Must stay stable across
|
||||
* newSSL() calls so in-flight cookie retries from other clients still
|
||||
* validate. Applications should rotate it periodically (e.g. on a timer),
|
||||
* not on every call. */
|
||||
static byte cookieSecret[32];
|
||||
static int cookieSecretSet = 0;
|
||||
|
||||
WOLFSSL* newSSL(WOLFSSL_CTX* ctx, int fd, WC_RNG* rng, struct ConnList* connList)
|
||||
{
|
||||
WOLFSSL* ssl = NULL;
|
||||
/* Applications should update this secret periodically */
|
||||
char *secret = "My secret";
|
||||
byte newCid[CID_SIZE];
|
||||
|
||||
if (!cookieSecretSet) {
|
||||
if (wc_RNG_GenerateBlock(rng, cookieSecret, sizeof(cookieSecret)) != 0) {
|
||||
fprintf(stderr, "wc_RNG_GenerateBlock error.\n");
|
||||
return NULL;
|
||||
}
|
||||
cookieSecretSet = 1;
|
||||
}
|
||||
|
||||
/* Create the WOLFSSL Object */
|
||||
if ((ssl = wolfSSL_new(ctx)) == NULL) {
|
||||
fprintf(stderr, "wolfSSL_new error.\n");
|
||||
|
|
@ -427,13 +440,13 @@ WOLFSSL* newSSL(WOLFSSL_CTX* ctx, int fd, WC_RNG* rng, struct ConnList* connList
|
|||
}
|
||||
/* Set the secret for cookie creation */
|
||||
#if defined(WOLFSSL_SEND_HRR_COOKIE)
|
||||
if (wolfSSL_send_hrr_cookie(ssl, (byte*)secret, strlen(secret)) != WOLFSSL_SUCCESS) {
|
||||
if (wolfSSL_send_hrr_cookie(ssl, cookieSecret, sizeof(cookieSecret)) != WOLFSSL_SUCCESS) {
|
||||
fprintf(stderr, "wolfSSL_send_hrr_cookie error.\n");
|
||||
wolfSSL_free(ssl);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
if (wolfSSL_DTLS_SetCookieSecret(ssl, (byte*)secret, strlen(secret)) != 0) {
|
||||
if (wolfSSL_DTLS_SetCookieSecret(ssl, cookieSecret, sizeof(cookieSecret)) != 0) {
|
||||
fprintf(stderr, "wolfSSL_DTLS_SetCookieSecret error.\n");
|
||||
wolfSSL_free(ssl);
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include <arpa/inet.h>
|
||||
#include <wolfssl/ssl.h>
|
||||
#include <wolfssl/error-ssl.h>
|
||||
#include <wolfssl/wolfcrypt/random.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -217,6 +218,15 @@ cleanup:
|
|||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
/* Stateless HRR cookie secret, generated once per run. Must stay stable
|
||||
* across newPendingSSL() calls so in-flight cookie retries from other
|
||||
* clients still validate. Applications should rotate it periodically
|
||||
* (e.g. on a timer), not on every call. */
|
||||
#if !defined(USE_DTLS12) && defined(WOLFSSL_SEND_HRR_COOKIE)
|
||||
static byte cookieSecret[32];
|
||||
static int cookieSecretSet = 0;
|
||||
#endif
|
||||
|
||||
static int newPendingSSL(void)
|
||||
{
|
||||
WOLFSSL* ssl;
|
||||
|
|
@ -248,15 +258,28 @@ static int newPendingSSL(void)
|
|||
}
|
||||
|
||||
#if !defined(USE_DTLS12) && defined(WOLFSSL_SEND_HRR_COOKIE)
|
||||
{
|
||||
/* Applications should update this secret periodically */
|
||||
char *secret = "My secret";
|
||||
if (wolfSSL_send_hrr_cookie(ssl, (byte*)secret, strlen(secret))
|
||||
!= WOLFSSL_SUCCESS) {
|
||||
fprintf(stderr, "wolfSSL_send_hrr_cookie error.\n");
|
||||
if (!cookieSecretSet) {
|
||||
WC_RNG rng;
|
||||
int rngRet;
|
||||
|
||||
rngRet = wc_InitRng(&rng);
|
||||
if (rngRet == 0) {
|
||||
rngRet = wc_RNG_GenerateBlock(&rng, cookieSecret, sizeof(cookieSecret));
|
||||
wc_FreeRng(&rng);
|
||||
}
|
||||
if (rngRet != 0) {
|
||||
fprintf(stderr, "Failed to generate cookie secret: %d\n", rngRet);
|
||||
wolfSSL_free(ssl);
|
||||
return 0;
|
||||
}
|
||||
cookieSecretSet = 1;
|
||||
}
|
||||
|
||||
if (wolfSSL_send_hrr_cookie(ssl, cookieSecret, sizeof(cookieSecret))
|
||||
!= WOLFSSL_SUCCESS) {
|
||||
fprintf(stderr, "wolfSSL_send_hrr_cookie error.\n");
|
||||
wolfSSL_free(ssl);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,29 @@
|
|||
#define DEF_KA_CHECKS 512
|
||||
#define DEF_PARAMS_GEN 8
|
||||
|
||||
/* Constant-time buffer compare for secret material.
|
||||
*
|
||||
* wolfSSL's own constant-time compare (ConstantCompare() in
|
||||
* wolfcrypt/src/misc.c) is WOLFSSL_LOCAL and not exported, so it can't be
|
||||
* called from application code. Every byte is compared regardless of where
|
||||
* a mismatch occurs, so the runtime doesn't leak position information via
|
||||
* early-exit timing.
|
||||
*
|
||||
* Returns 0 if the buffers are equal, non-zero otherwise. */
|
||||
static int const_time_memcmp(const void* a, const void* b, size_t len)
|
||||
{
|
||||
const unsigned char* pa = (const unsigned char*)a;
|
||||
const unsigned char* pb = (const unsigned char*)b;
|
||||
unsigned char diff = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
diff |= (unsigned char)(pa[i] ^ pb[i]);
|
||||
}
|
||||
|
||||
return (int)diff;
|
||||
}
|
||||
|
||||
int load_dh_params(DhKey* key1, DhKey* key2, WC_RNG* rng)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -412,8 +435,8 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
/* Secret's should be the same */
|
||||
if ((secret1_len != secret2_len) || (XMEMCMP(secret1, secret2,
|
||||
secret1_len) != 0)) {
|
||||
if ((secret1_len != secret2_len) || (const_time_memcmp(secret1,
|
||||
secret2, secret1_len) != 0)) {
|
||||
fprintf(stderr, "Secrets different\n");
|
||||
print_dh(&key1);
|
||||
ec = 1;
|
||||
|
|
|
|||
|
|
@ -37,6 +37,32 @@ int do_ecc(void);
|
|||
int do_25519(void);
|
||||
int do_448(void);
|
||||
|
||||
/* Constant-time buffer compare for secret material.
|
||||
*
|
||||
* wolfSSL's own constant-time compare (ConstantCompare() in
|
||||
* wolfcrypt/src/misc.c) is WOLFSSL_LOCAL and not exported, so it can't be
|
||||
* called from application code. This is the pattern to use instead of
|
||||
* XMEMCMP/memcmp whenever comparing secrets, MACs, or derived key material:
|
||||
* every byte is compared regardless of where a mismatch occurs, so the
|
||||
* runtime doesn't leak position information via early-exit timing.
|
||||
*
|
||||
* Returns 0 if the buffers are equal, non-zero otherwise. */
|
||||
#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
|
||||
static int const_time_memcmp(const void* a, const void* b, size_t len)
|
||||
{
|
||||
const byte* pa = (const byte*)a;
|
||||
const byte* pb = (const byte*)b;
|
||||
byte diff = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
diff |= (byte)(pa[i] ^ pb[i]);
|
||||
}
|
||||
|
||||
return (int)diff;
|
||||
}
|
||||
#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int curveChoice = 0;
|
||||
|
|
@ -111,7 +137,9 @@ int do_ecc(void)
|
|||
wc_ecc_set_rng(&BobKey, &rng);
|
||||
ret = wc_ecc_shared_secret(&BobKey, &AliceKey, BobSecret, &secretLen);
|
||||
if (ret == 0) {
|
||||
if (XMEMCMP(AliceSecret, BobSecret, secretLen))
|
||||
/* Use a constant-time compare (not XMEMCMP) since these buffers
|
||||
* hold secret key material. See const_time_memcmp() above. */
|
||||
if (const_time_memcmp(AliceSecret, BobSecret, secretLen))
|
||||
printf("Failed to generate a common secret\n");
|
||||
} else {
|
||||
goto all_three;
|
||||
|
|
@ -172,7 +200,9 @@ int do_25519(void)
|
|||
secretLen = ECC_256_BIT_FIELD; /* explicit reset for best practice */
|
||||
ret = wc_curve25519_shared_secret(&BobKey, &AliceKey, BobSecret, &secretLen);
|
||||
if (ret == 0) {
|
||||
if (XMEMCMP(AliceSecret, BobSecret, secretLen))
|
||||
/* Use a constant-time compare (not XMEMCMP) since these buffers
|
||||
* hold secret key material. See const_time_memcmp() above. */
|
||||
if (const_time_memcmp(AliceSecret, BobSecret, secretLen))
|
||||
printf("Failed to generate a common secret\n");
|
||||
} else {
|
||||
goto all_three;
|
||||
|
|
@ -233,7 +263,9 @@ int do_448(void)
|
|||
secretLen = ECC_448_BIT_FIELD; /* explicit reset for best practice */
|
||||
ret = wc_curve448_shared_secret(&BobKey, &AliceKey, BobSecret, &secretLen);
|
||||
if (ret == 0) {
|
||||
if (XMEMCMP(AliceSecret, BobSecret, secretLen))
|
||||
/* Use a constant-time compare (not XMEMCMP) since these buffers
|
||||
* hold secret key material. See const_time_memcmp() above. */
|
||||
if (const_time_memcmp(AliceSecret, BobSecret, secretLen))
|
||||
printf("Failed to generate a common secret\n");
|
||||
} else {
|
||||
goto all_three;
|
||||
|
|
@ -285,7 +317,10 @@ void Usage(int* curveChoice)
|
|||
|
||||
if (answer == 'y') {
|
||||
printf("\nEnter an option from the above curve list > ");
|
||||
scanf("%s", input);
|
||||
if (scanf("%9s", input) != 1) {
|
||||
printf("Invalid input\n");
|
||||
exit(-1);
|
||||
}
|
||||
printf("You entered: %s\n", input);
|
||||
sscanf(input, "%d", curveChoice);
|
||||
if (*curveChoice != 1 && *curveChoice != 2) {
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ static int load_file(const char* fname, byte** buf, size_t* bufLen)
|
|||
rewind(lFile);
|
||||
if (fileSz > 0) {
|
||||
*bufLen = (size_t)fileSz;
|
||||
*buf = (byte*)malloc(*bufLen);
|
||||
*buf = (byte*)XMALLOC(*bufLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (*buf == NULL) {
|
||||
ret = MEMORY_E;
|
||||
printf("Error allocating %lu bytes\n", (unsigned long)*bufLen);
|
||||
|
|
@ -128,20 +128,24 @@ static int load_key_file(const char* fname, byte** derBuf, word32* derLen)
|
|||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
*derBuf = (byte*)malloc(bufLen);
|
||||
*derBuf = (byte*)XMALLOC(bufLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (*derBuf == NULL) {
|
||||
free(buf);
|
||||
wc_ForceZero(buf, bufLen);
|
||||
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
return MEMORY_E;
|
||||
}
|
||||
|
||||
ret = wc_KeyPemToDer(buf, (word32)bufLen, *derBuf, (word32)bufLen, NULL);
|
||||
if (ret < 0) {
|
||||
free(buf);
|
||||
free(*derBuf);
|
||||
wc_ForceZero(buf, bufLen);
|
||||
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
wc_ForceZero(*derBuf, bufLen);
|
||||
XFREE(*derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
return ret;
|
||||
}
|
||||
*derLen = ret;
|
||||
free(buf);
|
||||
wc_ForceZero(buf, bufLen);
|
||||
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -168,22 +172,28 @@ static int myEccSign(WOLFSSL* ssl, const byte* in, word32 inSz,
|
|||
#endif
|
||||
|
||||
ret = load_key_file(cbInfo->keyFile, &keyBuf, &keySz);
|
||||
if (ret == 0) {
|
||||
ret = wc_ecc_init(&cbInfo->keyEcc);
|
||||
if (ret == 0) {
|
||||
word32 idx = 0;
|
||||
ret = wc_EccPrivateKeyDecode(keyBuf, &idx, &cbInfo->keyEcc, keySz);
|
||||
if (ret == 0) {
|
||||
WC_RNG *rng = wolfSSL_GetRNG(ssl);
|
||||
|
||||
printf("PK ECC Sign: Curve ID %d\n", cbInfo->keyEcc.dp->id);
|
||||
ret = wc_ecc_sign_hash(in, inSz, out, outSz, rng,
|
||||
&cbInfo->keyEcc);
|
||||
}
|
||||
wc_ecc_free(&cbInfo->keyEcc);
|
||||
}
|
||||
if (ret != 0) {
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
cbInfo->state = 0;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
free(keyBuf);
|
||||
|
||||
ret = wc_ecc_init(&cbInfo->keyEcc);
|
||||
if (ret == 0) {
|
||||
word32 idx = 0;
|
||||
ret = wc_EccPrivateKeyDecode(keyBuf, &idx, &cbInfo->keyEcc, keySz);
|
||||
if (ret == 0) {
|
||||
WC_RNG *rng = wolfSSL_GetRNG(ssl);
|
||||
|
||||
printf("PK ECC Sign: Curve ID %d\n", cbInfo->keyEcc.dp->id);
|
||||
ret = wc_ecc_sign_hash(in, inSz, out, outSz, rng,
|
||||
&cbInfo->keyEcc);
|
||||
}
|
||||
wc_ecc_free(&cbInfo->keyEcc);
|
||||
}
|
||||
wc_ForceZero(keyBuf, keySz);
|
||||
XFREE(keyBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
cbInfo->state = 0;
|
||||
|
|
@ -218,8 +228,12 @@ static int myRsaSign(WOLFSSL* ssl, const byte* in, word32 inSz,
|
|||
#endif
|
||||
|
||||
ret = load_key_file(cbInfo->keyFile, &keyBuf, &keySz);
|
||||
if (ret != 0)
|
||||
if (ret != 0) {
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
cbInfo->state = 0;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = wc_InitRsaKey(&cbInfo->keyRsa, NULL);
|
||||
if (ret == 0) {
|
||||
|
|
@ -234,7 +248,8 @@ static int myRsaSign(WOLFSSL* ssl, const byte* in, word32 inSz,
|
|||
}
|
||||
wc_FreeRsaKey(&cbInfo->keyRsa);
|
||||
}
|
||||
free(keyBuf);
|
||||
wc_ForceZero(keyBuf, keySz);
|
||||
XFREE(keyBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
cbInfo->state = 0;
|
||||
#endif
|
||||
|
|
@ -300,7 +315,8 @@ static int myRsaPssSign(WOLFSSL* ssl, const byte* in, word32 inSz,
|
|||
}
|
||||
wc_FreeRsaKey(&cbInfo->keyRsa);
|
||||
}
|
||||
free(keyBuf);
|
||||
wc_ForceZero(keyBuf, keySz);
|
||||
XFREE(keyBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
printf("PK RSA PSS Sign: ret %d, outSz %u\n", ret, *outSz);
|
||||
|
||||
|
|
@ -325,7 +341,7 @@ int main(int argc, char** argv)
|
|||
|
||||
/* PK callback context */
|
||||
PkCbInfo myCtx;
|
||||
memset(&myCtx, 0, sizeof(myCtx));
|
||||
XMEMSET(&myCtx, 0, sizeof(myCtx));
|
||||
myCtx.keyFile = KEY_FILE;
|
||||
|
||||
/* Check for proper calling convention */
|
||||
|
|
@ -351,7 +367,7 @@ int main(int argc, char** argv)
|
|||
}
|
||||
|
||||
/* Initialize the server address struct with zeros */
|
||||
memset(&servAddr, 0, sizeof(servAddr));
|
||||
XMEMSET(&servAddr, 0, sizeof(servAddr));
|
||||
|
||||
/* Fill in the server address */
|
||||
servAddr.sin_family = AF_INET; /* using IPv4 */
|
||||
|
|
@ -477,7 +493,7 @@ int main(int argc, char** argv)
|
|||
|
||||
/* Get a message for the server from stdin */
|
||||
printf("Message for server: ");
|
||||
memset(buff, 0, sizeof(buff));
|
||||
XMEMSET(buff, 0, sizeof(buff));
|
||||
if (fgets(buff, sizeof(buff), stdin) == NULL) {
|
||||
fprintf(stderr, "ERROR: failed to get message for server\n");
|
||||
ret = -1;
|
||||
|
|
@ -493,7 +509,7 @@ int main(int argc, char** argv)
|
|||
}
|
||||
|
||||
/* Read the server data into our buff array */
|
||||
memset(buff, 0, sizeof(buff));
|
||||
XMEMSET(buff, 0, sizeof(buff));
|
||||
if ((ret = wolfSSL_read(ssl, buff, sizeof(buff)-1)) == -1) {
|
||||
fprintf(stderr, "ERROR: failed to read\n");
|
||||
goto exit;
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ static int load_file(const char* fname, byte** buf, size_t* bufLen)
|
|||
rewind(lFile);
|
||||
if (fileSz > 0) {
|
||||
*bufLen = (size_t)fileSz;
|
||||
*buf = (byte*)malloc(*bufLen);
|
||||
*buf = (byte*)XMALLOC(*bufLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (*buf == NULL) {
|
||||
ret = MEMORY_E;
|
||||
printf("Error allocating %lu bytes\n", (unsigned long)*bufLen);
|
||||
|
|
@ -128,20 +128,24 @@ static int load_key_file(const char* fname, byte** derBuf, word32* derLen)
|
|||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
*derBuf = (byte*)malloc(bufLen);
|
||||
*derBuf = (byte*)XMALLOC(bufLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (*derBuf == NULL) {
|
||||
free(buf);
|
||||
wc_ForceZero(buf, bufLen);
|
||||
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
return MEMORY_E;
|
||||
}
|
||||
|
||||
ret = wc_KeyPemToDer(buf, (word32)bufLen, *derBuf, (word32)bufLen, NULL);
|
||||
if (ret < 0) {
|
||||
free(buf);
|
||||
free(*derBuf);
|
||||
wc_ForceZero(buf, bufLen);
|
||||
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
wc_ForceZero(*derBuf, bufLen);
|
||||
XFREE(*derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
return ret;
|
||||
}
|
||||
*derLen = ret;
|
||||
free(buf);
|
||||
wc_ForceZero(buf, bufLen);
|
||||
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -168,22 +172,28 @@ static int myEccSign(WOLFSSL* ssl, const byte* in, word32 inSz,
|
|||
#endif
|
||||
|
||||
ret = load_key_file(cbInfo->keyFile, &keyBuf, &keySz);
|
||||
if (ret == 0) {
|
||||
ret = wc_ecc_init(&cbInfo->keyEcc);
|
||||
if (ret == 0) {
|
||||
word32 idx = 0;
|
||||
ret = wc_EccPrivateKeyDecode(keyBuf, &idx, &cbInfo->keyEcc, keySz);
|
||||
if (ret == 0) {
|
||||
WC_RNG *rng = wolfSSL_GetRNG(ssl);
|
||||
|
||||
printf("PK ECC Sign: Curve ID %d\n", cbInfo->keyEcc.dp->id);
|
||||
ret = wc_ecc_sign_hash(in, inSz, out, outSz, rng,
|
||||
&cbInfo->keyEcc);
|
||||
}
|
||||
wc_ecc_free(&cbInfo->keyEcc);
|
||||
}
|
||||
if (ret != 0) {
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
cbInfo->state = 0;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
free(keyBuf);
|
||||
|
||||
ret = wc_ecc_init(&cbInfo->keyEcc);
|
||||
if (ret == 0) {
|
||||
word32 idx = 0;
|
||||
ret = wc_EccPrivateKeyDecode(keyBuf, &idx, &cbInfo->keyEcc, keySz);
|
||||
if (ret == 0) {
|
||||
WC_RNG *rng = wolfSSL_GetRNG(ssl);
|
||||
|
||||
printf("PK ECC Sign: Curve ID %d\n", cbInfo->keyEcc.dp->id);
|
||||
ret = wc_ecc_sign_hash(in, inSz, out, outSz, rng,
|
||||
&cbInfo->keyEcc);
|
||||
}
|
||||
wc_ecc_free(&cbInfo->keyEcc);
|
||||
}
|
||||
wc_ForceZero(keyBuf, keySz);
|
||||
XFREE(keyBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
cbInfo->state = 0;
|
||||
#endif
|
||||
|
|
@ -217,8 +227,12 @@ static int myRsaSign(WOLFSSL* ssl, const byte* in, word32 inSz,
|
|||
#endif
|
||||
|
||||
ret = load_key_file(cbInfo->keyFile, &keyBuf, &keySz);
|
||||
if (ret != 0)
|
||||
if (ret != 0) {
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
cbInfo->state = 0;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = wc_InitRsaKey(&cbInfo->keyRsa, NULL);
|
||||
if (ret == 0) {
|
||||
|
|
@ -233,7 +247,8 @@ static int myRsaSign(WOLFSSL* ssl, const byte* in, word32 inSz,
|
|||
}
|
||||
wc_FreeRsaKey(&cbInfo->keyRsa);
|
||||
}
|
||||
free(keyBuf);
|
||||
wc_ForceZero(keyBuf, keySz);
|
||||
XFREE(keyBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
cbInfo->state = 0;
|
||||
#endif
|
||||
|
|
@ -299,7 +314,8 @@ static int myRsaPssSign(WOLFSSL* ssl, const byte* in, word32 inSz,
|
|||
}
|
||||
wc_FreeRsaKey(&cbInfo->keyRsa);
|
||||
}
|
||||
free(keyBuf);
|
||||
wc_ForceZero(keyBuf, keySz);
|
||||
XFREE(keyBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
printf("PK RSA PSS Sign: ret %d, outSz %u\n", ret, *outSz);
|
||||
|
||||
|
|
@ -326,7 +342,7 @@ int main(int argc, char** argv)
|
|||
|
||||
/* PK callback context */
|
||||
PkCbInfo myCtx;
|
||||
memset(&myCtx, 0, sizeof(myCtx));
|
||||
XMEMSET(&myCtx, 0, sizeof(myCtx));
|
||||
myCtx.keyFile = KEY_FILE;
|
||||
|
||||
/* declare wolfSSL objects */
|
||||
|
|
@ -341,7 +357,7 @@ int main(int argc, char** argv)
|
|||
#endif
|
||||
|
||||
/* Initialize the server address struct with zeros */
|
||||
memset(&servAddr, 0, sizeof(servAddr));
|
||||
XMEMSET(&servAddr, 0, sizeof(servAddr));
|
||||
|
||||
/* Fill in the server address */
|
||||
servAddr.sin_family = AF_INET; /* using IPv4 */
|
||||
|
|
@ -497,7 +513,7 @@ int main(int argc, char** argv)
|
|||
|
||||
|
||||
/* Read the client data into our buff array */
|
||||
memset(buff, 0, sizeof(buff));
|
||||
XMEMSET(buff, 0, sizeof(buff));
|
||||
if ((ret = wolfSSL_read(ssl, buff, sizeof(buff)-1)) == -1) {
|
||||
fprintf(stderr, "ERROR: failed to read\n");
|
||||
goto exit;
|
||||
|
|
@ -514,7 +530,7 @@ int main(int argc, char** argv)
|
|||
|
||||
|
||||
/* Write our reply into buff */
|
||||
memset(buff, 0, sizeof(buff));
|
||||
XMEMSET(buff, 0, sizeof(buff));
|
||||
memcpy(buff, reply, strlen(reply));
|
||||
len = strnlen(buff, sizeof(buff));
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue