diff --git a/src/genkey/clu_genkey.c b/src/genkey/clu_genkey.c index b3986533..add1a9a8 100644 --- a/src/genkey/clu_genkey.c +++ b/src/genkey/clu_genkey.c @@ -39,7 +39,7 @@ int wolfCLU_genKey_ED25519(WC_RNG* rng, char* fOutNm, int directive, int format) int ret; /* return value */ int fOutNmSz; /* file name without append */ int fOutNmAppendSz = 6; /* # of bytes to append to file name */ - int flagOutputPub = 0; /* set if outputting both priv/pub */ + int flagOutputPub = 0; /* set if outputting both priv/pub */ char privAppend[6] = ".priv\0"; /* last part of the priv file name */ char pubAppend[6] = ".pub\0\0"; /* last part of the pub file name*/ byte privKeyBuf[ED25519_KEY_SIZE*2]; /* will hold public & private parts */ @@ -47,112 +47,276 @@ int wolfCLU_genKey_ED25519(WC_RNG* rng, char* fOutNm, int directive, int format) word32 privKeySz; /* size of private key */ word32 pubKeySz; /* size of public key */ ed25519_key edKeyOut; /* the ed25519 key structure */ - char* finalOutFNm; /* file name + append */ - XFILE file; /* file stream */ + char* finalOutFNm = NULL; /* file name + append */ + XFILE file = NULL; /* file stream */ + byte* derBuf = NULL; /* buffer for DER format */ + byte* pemBuf = NULL; /* buffer for PEM format */ + int derSz; /* size of DER buffer */ + int pemSz; /* size of PEM buffer */ + + /* initialize ed25519 key */ + ret = wc_ed25519_init(&edKeyOut); + if (ret != 0) { + wolfCLU_LogError("Failed to initialize ed25519 key.\nRET: %d", ret); + } + /* make ed25519 key */ + if (ret == 0) { + ret = wc_ed25519_make_key(rng, ED25519_KEY_SIZE, &edKeyOut); + if (ret != 0) { + wolfCLU_LogError("Failed to make ed25519 key.\nRET: %d", ret); + } + } - WOLFCLU_LOG(WOLFCLU_L0, "fOutNm = %s", fOutNm); - fOutNmSz = (int)XSTRLEN(fOutNm); + if (ret == 0) { + if (fOutNm == NULL) { + ret = BAD_FUNC_ARG; + } + else { + WOLFCLU_LOG(WOLFCLU_L0, "fOutNm = %s", fOutNm); + fOutNmSz = (int)XSTRLEN(fOutNm); + } + } - /*--------------- INIT ---------------------*/ - ret = wc_ed25519_init(&edKeyOut); - if (ret != 0) - return ret; - /*--------------- MAKE KEY ---------------------*/ - ret = wc_ed25519_make_key(rng, ED25519_KEY_SIZE, &edKeyOut); - if (ret != 0) - return ret; - /*--------------- GET KEY SIZES ---------------------*/ - privKeySz = wc_ed25519_priv_size(&edKeyOut); - if (privKeySz <= 0) - return WC_KEY_SIZE_E; - - pubKeySz = wc_ed25519_pub_size(&edKeyOut); - if (pubKeySz <= 0) - return WC_KEY_SIZE_E; - /*--------------- EXPORT KEYS TO BUFFERS ---------------------*/ - ret = wc_ed25519_export_key(&edKeyOut, privKeyBuf, &privKeySz, pubKeyBuf, - &pubKeySz); - if (ret != 0) - return ret; + if (format == RAW_FORM && ret == 0) { + /* get key size */ + privKeySz = wc_ed25519_priv_size(&edKeyOut); + if (privKeySz <= 0) + ret = WC_KEY_SIZE_E; - /*--------------- CONVERT TO PEM IF APPLICABLE ---------------------*/ - if (format == PEM_FORM) { - wolfCLU_LogError("Der to Pem for ed25519 key not yet implemented"); - WOLFCLU_LOG(WOLFCLU_L0, "FEATURE COMING SOON!"); - return FEATURE_COMING_SOON; + pubKeySz = wc_ed25519_pub_size(&edKeyOut); + if (pubKeySz <= 0) + ret = WC_KEY_SIZE_E; + + /* export keys to buffers */ + ret = wc_ed25519_export_key(&edKeyOut, privKeyBuf, &privKeySz, + pubKeyBuf, &pubKeySz); } - /*--------------- OUTPUT KEYS TO FILE(S) ---------------------*/ - finalOutFNm = (char*) XMALLOC( (fOutNmSz + fOutNmAppendSz), HEAP_HINT, - DYNAMIC_TYPE_TMP_BUFFER); - if (finalOutFNm == NULL) - return MEMORY_E; - /* get the first part of the file name setup */ - XMEMSET(finalOutFNm, 0, fOutNmSz + fOutNmAppendSz); - XMEMCPY(finalOutFNm, fOutNm, fOutNmSz); + /* set up the file name output buffer */ + if (ret == 0) { + finalOutFNm = (char*) XMALLOC( (fOutNmSz + fOutNmAppendSz), HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (finalOutFNm == NULL) { + ret = MEMORY_E; + } else { + /* get the first part of the file name setup */ + XMEMSET(finalOutFNm, 0, fOutNmSz + fOutNmAppendSz); + XMEMCPY(finalOutFNm, fOutNm, fOutNmSz); + } + } - switch(directive) { + if (ret == 0) { + switch(directive) { case PRIV_AND_PUB_FILES: flagOutputPub = 1; - /* Fall through to PRIV_ONLY_FILE */ + + /* fall through to PRIV_ONLY_FILE */ FALL_THROUGH; case PRIV_ONLY_FILE: /* add on the final part of the file name ".priv" */ - XMEMCPY(finalOutFNm+fOutNmSz, privAppend, fOutNmAppendSz); + XMEMCPY(finalOutFNm + fOutNmSz, privAppend, fOutNmAppendSz); WOLFCLU_LOG(WOLFCLU_L0, "finalOutFNm = %s", finalOutFNm); - file = XFOPEN(finalOutFNm, "wb"); - if (!file) { - XFREE(finalOutFNm, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return OUTPUT_FILE_ERROR; + /* open the file for writing the private key */ + if (ret == 0) { + file = XFOPEN(finalOutFNm, "wb"); + if (!file) { + ret = OUTPUT_FILE_ERROR; + } } - ret = (int)XFWRITE(privKeyBuf, 1, privKeySz, file); - if (ret <= 0) { - XFCLOSE(file); - XFREE(finalOutFNm, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return OUTPUT_FILE_ERROR; + /* write RAW format to the file */ + if (format == RAW_FORM && ret == 0) { + if (XFWRITE(privKeyBuf, 1, privKeySz, file) != privKeySz) { + ret = OUTPUT_FILE_ERROR; + } } - fclose(file); + else { /* DER and PEM */ + /* determine size for buffer */ + if (ret == 0) { + derSz = wc_Ed25519PrivateKeyToDer(&edKeyOut, NULL, 0); + if (derSz <= 0) { + ret = MEMORY_E; + } + } + + /* allocate DER buffer */ + if (ret == 0) { + derBuf = (byte*)XMALLOC(derSz, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + ret = MEMORY_E; + } + } + /* convert Key to DER */ + if (ret == 0) { + derSz = wc_Ed25519PrivateKeyToDer(&edKeyOut, derBuf, derSz); + if (derSz < 0) { + ret = derSz; + } + } + if (ret != 0) + break; + + /* convert DER to PEM if necessary */ + if (format == PEM_FORM) { + if (ret == 0) { + pemSz = wolfCLU_KeyDerToPem(derBuf, derSz, &pemBuf, + PRIVATEKEY_TYPE, DYNAMIC_TYPE_TMP_BUFFER); + if (pemSz < 0) { + ret = pemSz; + } + } + /* write PEM format to the file */ + if (ret == 0) { + ret = (int)XFWRITE(pemBuf, 1, pemSz, file); + if (ret != pemSz) { + ret = OUTPUT_FILE_ERROR; + } + else { + ret = 0; + } + } + } + else { + /* write DER format to the file */ + if (ret == 0) { + ret = (int)XFWRITE(derBuf, 1, derSz, file); + if (ret != derSz) { + ret = OUTPUT_FILE_ERROR; + } + else { + ret = 0; + } + } + } + } + if (ret != 0) { + break; + } if (flagOutputPub == 0) { break; - } /* else fall through to PUB_ONLY_FILE if flagOutputPub == 1*/ + } /* else fall through to PUB_ONLY_FILE if flagOutputPub == 1 */ + + XFCLOSE(file); + file = NULL; + XFREE(derBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + derBuf = NULL; + XFREE(pemBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + pemBuf = NULL; + FALL_THROUGH; case PUB_ONLY_FILE: /* add on the final part of the file name ".pub" */ - XMEMCPY(finalOutFNm+fOutNmSz, pubAppend, fOutNmAppendSz); + XMEMCPY(finalOutFNm + fOutNmSz, pubAppend, fOutNmAppendSz); WOLFCLU_LOG(WOLFCLU_L0, "finalOutFNm = %s", finalOutFNm); - file = XFOPEN(finalOutFNm, "wb"); - if (!file) { - XFREE(finalOutFNm, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return OUTPUT_FILE_ERROR; + /* open the file for writing the public key */ + if (ret == 0) { + file = XFOPEN(finalOutFNm, "wb"); + if (!file) { + ret = OUTPUT_FILE_ERROR; + } } - ret = (int)XFWRITE(pubKeyBuf, 1, pubKeySz, file); - if (ret <= 0) { - XFCLOSE(file); - XFREE(finalOutFNm, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return OUTPUT_FILE_ERROR; + /* write RAW format to the file */ + if (format == RAW_FORM && ret == 0) { + if (XFWRITE(pubKeyBuf, 1, pubKeySz, file) != pubKeySz) { + ret = OUTPUT_FILE_ERROR; + } + } + else { /* DER and PEM */ + /* determine size for buffer */ + if (ret == 0) { + derSz = wc_Ed25519PublicKeyToDer(&edKeyOut, NULL, 0, 1); + if (derSz <= 0) { + ret = MEMORY_E; + } + } + + /* allocate DER buffer */ + if (ret == 0) { + derBuf = (byte*)XMALLOC(derSz, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + ret = MEMORY_E; + } + } + + /* convert Key to DER */ + if (ret == 0) { + derSz = wc_Ed25519PublicKeyToDer(&edKeyOut, derBuf, derSz, 1); + if (derSz < 0) { + ret = derSz; + } + } + + if (ret != 0) + break; + + /* convert DER to PEM if necessary */ + if (format == PEM_FORM) { + if (ret == 0) { + pemSz = wolfCLU_KeyDerToPem(derBuf, derSz, &pemBuf, + PUBLICKEY_TYPE, DYNAMIC_TYPE_TMP_BUFFER); + if (pemSz < 0) { + ret = pemSz; + } + } + /* write PEM format to the file */ + if (ret == 0) { + ret = (int)XFWRITE(pemBuf, 1, pemSz, file); + if (ret != pemSz) { + ret = OUTPUT_FILE_ERROR; + } else { + ret = 0; + } + } + } + else { + /* write DER format to the file */ + if (ret == 0) { + ret = (int)XFWRITE(derBuf, 1, derSz, file); + if (ret != derSz) { + ret = OUTPUT_FILE_ERROR; + } + else { + ret = 0; + } + } + } + } + + if (ret != 0) { + ret = OUTPUT_FILE_ERROR; } - XFCLOSE(file); break; default: wolfCLU_LogError("Invalid directive"); - XFREE(finalOutFNm, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return BAD_FUNC_ARG; + ret = BAD_FUNC_ARG; + } /* switch */ } - XFREE(finalOutFNm, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - - if (ret > 0) { - /* ret > 0 indicates a successful file write, set to zero for return */ - ret = WOLFCLU_SUCCESS; + /* cleanup allocated resources */ + if (finalOutFNm != NULL) { + XFREE(finalOutFNm, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + finalOutFNm = NULL; + } + if (derBuf != NULL) { + XFREE(derBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } + if (pemBuf != NULL) { + XFREE(pemBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } + if (file != NULL) { + XFCLOSE(file); + file = NULL; } - return ret; + /* expected ret == WOLFCLU_SUCCESS */ + return (ret >= 0) ? WOLFCLU_SUCCESS : ret; } #endif /* HAVE_ED25519 */ @@ -579,7 +743,7 @@ int wolfCLU_GenAndOutput_ECC(WC_RNG* rng, char* fName, int directive, } -#ifndef NO_RSA +#if !defined(NO_RSA) || defined(HAVE_ED25519) /* helper function to convert a key to PEM format. Creates new 'out' buffer on * success. * returns size of PEM buffer created on success @@ -613,7 +777,7 @@ int wolfCLU_KeyDerToPem(const byte* der, int derSz, byte** out, int pemType, *out = pemBuf; return pemBufSz; } -#endif /* !NO_RSA */ +#endif /* !NO_RSA || HAVE_ED25519*/ /* return WOLFCLU_SUCCESS on success */ @@ -621,169 +785,240 @@ int wolfCLU_genKey_RSA(WC_RNG* rng, char* fName, int directive, int fmt, int keySz, long exp) { #ifndef NO_RSA - RsaKey key; - XFILE file; - int ret = WOLFCLU_SUCCESS; - - int fNameSz; - int fExtSz = 6; - char fExtPriv[6] = ".priv\0"; - char fExtPub[6] = ".pub\0\0"; - char* fOutNameBuf = NULL; - - #ifdef NO_AES - /* use 16 bytes for AES block size */ - size_t maxDerBufSz = 4 * keySz * 16; - #else - size_t maxDerBufSz = 4 * keySz * AES_BLOCK_SIZE; - #endif - byte* derBuf = NULL; - byte* pemBuf = NULL; - byte* outBuf = NULL; - int derBufSz = -1; - int pemBufSz = 0; - int outBufSz = 0; + RsaKey key; /* the RSA key structure */ + XFILE file = NULL; /* file stream */ + int ret = WOLFCLU_SUCCESS; /* return value */ + int fNameSz; /* file name without append */ + int fExtSz = 6; /* number of bytes to append to file name */ + char fExtPriv[6] = ".priv\0"; /* last part of the priv file name */ + char fExtPub[6] = ".pub\0\0"; /* last part of the pub file name*/ + char* fOutNameBuf = NULL; /* file name + fExt */ + int flagOutputPub = 0; /* set if outputting both priv/pub */ + byte* derBuf = NULL; /* buffer for DER format */ + byte* pemBuf = NULL; /* buffer for PEM format */ + int derBufSz = -1; /* size of DER buffer */ + int pemBufSz = 0; /* size of PEM buffer */ if (rng == NULL || fName == NULL) return BAD_FUNC_ARG; + WOLFCLU_LOG(WOLFCLU_L0, "fOutNm = %s", fName); + fNameSz = (int)XSTRLEN(fName); + + /* init RSA key */ if (wc_InitRsaKey(&key, HEAP_HINT) != 0) { return WOLFCLU_FAILURE; } + /* make RSA key */ if (wc_MakeRsaKey(&key, keySz, exp, rng) != 0) { - ret = WOLFCLU_FAILURE; + wc_FreeRsaKey(&key); + return WOLFCLU_FAILURE; } /* set up the file name output buffer */ - if (ret == WOLFCLU_SUCCESS) { - fNameSz = (int)XSTRLEN(fName); - fOutNameBuf = (char*)XMALLOC(fNameSz + fExtSz, HEAP_HINT, - DYNAMIC_TYPE_TMP_BUFFER); - if (fOutNameBuf == NULL) - ret = MEMORY_E; + fOutNameBuf = (char*) XMALLOC( (fNameSz + fExtSz), HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (fOutNameBuf == NULL) { + wc_FreeRsaKey(&key); + return MEMORY_E; } - - if (ret == WOLFCLU_SUCCESS) { + else { + /* get the first part of the file name setup */ XMEMSET(fOutNameBuf, 0, fNameSz + fExtSz); XMEMCPY(fOutNameBuf, fName, fNameSz); - derBuf = (byte*) XMALLOC(maxDerBufSz, HEAP_HINT, - DYNAMIC_TYPE_TMP_BUFFER); - if (derBuf == NULL) { - ret = MEMORY_E; - } } if (ret == WOLFCLU_SUCCESS) { switch (directive) { - case PRIV_AND_PUB_FILES: - /* Fall through to PRIV_ONLY_FILE */ - FALL_THROUGH; - case PRIV_ONLY_FILE: - /* add on the final part of the file name ".priv" */ - XMEMCPY(fOutNameBuf + fNameSz, fExtPriv, fExtSz); - WOLFCLU_LOG(WOLFCLU_L0, "fOutNameBuf = %s", fOutNameBuf); + case PRIV_AND_PUB_FILES: + flagOutputPub = 1; - derBufSz = wc_RsaKeyToDer(&key, derBuf, (word32)maxDerBufSz); + /* Fall through to PRIV_ONLY_FILE */ + FALL_THROUGH; + case PRIV_ONLY_FILE: + /* add on the final part of the file name ".priv" */ + XMEMCPY(fOutNameBuf + fNameSz, fExtPriv, fExtSz); + WOLFCLU_LOG(WOLFCLU_L0, "fOutNameBuf = %s", fOutNameBuf); + + /* open the file for writing the private key */ + if (ret == WOLFCLU_SUCCESS) { + file = XFOPEN(fOutNameBuf, "wb"); + if (!file) { + ret = OUTPUT_FILE_ERROR; + } + } + + /* determine size for buffer */ + if (ret == WOLFCLU_SUCCESS) { + derBufSz = wc_RsaKeyToDer(&key, NULL, 0); + if (derBufSz < 0) { + ret = MEMORY_E; + } + } + + /* allocate DER buffer */ + if (ret == WOLFCLU_SUCCESS) { + derBuf = (byte*)XMALLOC(derBufSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + ret = MEMORY_E; + } + } + + /* convert Key to DER */ + if (ret == WOLFCLU_SUCCESS) { + derBufSz = wc_RsaKeyToDer(&key, derBuf, derBufSz); if (derBufSz < 0) { ret = derBufSz; } - outBuf = derBuf; - outBufSz = derBufSz; + } + if (ret != WOLFCLU_SUCCESS) + break; - /* check if should convert to PEM format */ - if (ret == WOLFCLU_SUCCESS && fmt == PEM_FORM) { + /* convert DER to PEM if necessary */ + if (fmt == PEM_FORM) { + if (ret == WOLFCLU_SUCCESS) { pemBufSz = wolfCLU_KeyDerToPem(derBuf, derBufSz, &pemBuf, - PRIVATEKEY_TYPE, DYNAMIC_TYPE_PRIVATE_KEY); - if (pemBufSz <= 0 || pemBuf == NULL) { - ret = WOLFCLU_FAILURE; + PRIVATEKEY_TYPE, DYNAMIC_TYPE_TMP_BUFFER); + if (pemBufSz < 0) { + ret = pemBufSz; } - outBuf = pemBuf; - outBufSz = pemBufSz; } - if (ret == WOLFCLU_SUCCESS) { - file = XFOPEN(fOutNameBuf, "wb"); - if (file == XBADFILE) { + ret = (int)XFWRITE(pemBuf, 1, pemBufSz, file); + if (ret != pemBufSz) { ret = OUTPUT_FILE_ERROR; } + else { + ret = WOLFCLU_SUCCESS; + } } - + } + else { + /* write DER format to the file */ if (ret == WOLFCLU_SUCCESS) { - if ((int)XFWRITE(outBuf, 1, outBufSz, file) <= 0) { + ret = (int)XFWRITE(derBuf, 1, derBufSz, file); + if (ret != derBufSz) { ret = OUTPUT_FILE_ERROR; } - XFCLOSE(file); + else { + ret = WOLFCLU_SUCCESS; + } } + } + if (ret != WOLFCLU_SUCCESS) { + break; + } + if (flagOutputPub == 0) { + break; + } /* else fall through to PUB_ONLY_FILE if flagOutputPub == 1 */ - if (pemBuf != NULL) { - wolfCLU_ForceZero(pemBuf, pemBufSz); - XFREE(pemBuf, HEAP_HINT, DYNAMIC_TYPE_PRIVATE_KEY); + XFCLOSE(file); + file = NULL; + XFREE(derBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + derBuf = NULL; + XFREE(pemBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + pemBuf = NULL; + + FALL_THROUGH; + case PUB_ONLY_FILE: + /* add on the final part of the file name ".pub" */ + XMEMCPY(fOutNameBuf + fNameSz, fExtPub, fExtSz); + WOLFCLU_LOG(WOLFCLU_L0, "fOutNameBuf = %s", fOutNameBuf); + + /* open the file for writing the public key */ + if (ret == WOLFCLU_SUCCESS) { + file = XFOPEN(fOutNameBuf, "wb"); + if (!file) { + ret = OUTPUT_FILE_ERROR; } + } - if (directive != PRIV_AND_PUB_FILES) { - break; + /* determine size for buffer */ + if (ret == WOLFCLU_SUCCESS) { + derBufSz = wc_RsaKeyToPublicDer(&key, NULL, 0); + if (derBufSz < 0) { + ret = MEMORY_E; } - FALL_THROUGH; - case PUB_ONLY_FILE: - /* add on the final part of the file name ".pub" */ - if (ret == WOLFCLU_SUCCESS) { - XMEMCPY(fOutNameBuf + fNameSz, fExtPub, fExtSz); - WOLFCLU_LOG(WOLFCLU_L0, "fOutNameBuf = %s", fOutNameBuf); + } - derBufSz = wc_RsaKeyToPublicDer(&key, derBuf, - (word32)maxDerBufSz); - if (derBufSz < 0) { - ret = derBufSz; - } - outBuf = derBuf; - outBufSz = derBufSz; + /* allocate DER buffer */ + if (ret == WOLFCLU_SUCCESS) { + derBuf = (byte*)XMALLOC(derBufSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + ret = MEMORY_E; + } + } + + /* convert Key to DER */ + if (ret == WOLFCLU_SUCCESS) { + derBufSz = wc_RsaKeyToPublicDer(&key, derBuf, derBufSz); + if (derBufSz < 0) { + ret = derBufSz; } + } + if (ret != WOLFCLU_SUCCESS) + break; - /* check if should convert to PEM format */ - if (ret == WOLFCLU_SUCCESS && fmt == PEM_FORM) { + /* convert DER to PEM if necessary */ + if (fmt == PEM_FORM) { + if (ret == WOLFCLU_SUCCESS) { pemBufSz = wolfCLU_KeyDerToPem(derBuf, derBufSz, &pemBuf, - PUBLICKEY_TYPE, DYNAMIC_TYPE_PUBLIC_KEY); - if (pemBufSz <= 0 || pemBuf == NULL) { - ret = WOLFCLU_FAILURE; + PUBLICKEY_TYPE, DYNAMIC_TYPE_TMP_BUFFER); + if (pemBufSz < 0) { + ret = pemBufSz; } - outBuf = pemBuf; - outBufSz = pemBufSz; } - if (ret == WOLFCLU_SUCCESS) { - file = XFOPEN(fOutNameBuf, "wb"); - if (file == XBADFILE) { + ret = (int)XFWRITE(pemBuf, 1, pemBufSz, file); + if (ret != pemBufSz) { ret = OUTPUT_FILE_ERROR; } + else { + ret = WOLFCLU_SUCCESS; + } } - + } + else { + /* write DER format to the file */ if (ret == WOLFCLU_SUCCESS) { - if ((int)XFWRITE(outBuf, 1, outBufSz, file) <= 0) { + ret = (int)XFWRITE(derBuf, 1, derBufSz, file); + if (ret != derBufSz) { ret = OUTPUT_FILE_ERROR; } - XFCLOSE(file); - } - - if (pemBuf != NULL) { - XFREE(pemBuf, HEAP_HINT, DYNAMIC_TYPE_PUBLIC_KEY); + else { + ret = WOLFCLU_SUCCESS; + } } + } - break; - default: - wolfCLU_LogError("Invalid directive"); - ret = BAD_FUNC_ARG; - } + if (ret != WOLFCLU_SUCCESS) { + ret = OUTPUT_FILE_ERROR; + } + break; + default: + wolfCLU_LogError("Invalid directive"); + ret = BAD_FUNC_ARG; + } /* switch */ } + /* cleanup allocated resources */ + if (fOutNameBuf != NULL) { + XFREE(fOutNameBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + fOutNameBuf = NULL; + } if (derBuf != NULL) { - wolfCLU_ForceZero(derBuf, (unsigned int)maxDerBufSz); XFREE(derBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); } - if (fOutNameBuf != NULL) { - XFREE(fOutNameBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (pemBuf != NULL) { + XFREE(pemBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } + if (file != NULL) { + XFCLOSE(file); + file = NULL; } + wc_FreeRsaKey(&key); return ret; diff --git a/src/genkey/clu_genkey_setup.c b/src/genkey/clu_genkey_setup.c index 644f1b26..957062d3 100644 --- a/src/genkey/clu_genkey_setup.c +++ b/src/genkey/clu_genkey_setup.c @@ -79,8 +79,12 @@ int wolfCLU_genKeySetup(int argc, char** argv) format = argv[ret+1]; } ret = wolfCLU_checkOutform(format); - if (ret == PEM_FORM || ret == DER_FORM) { - WOLFCLU_LOG(WOLFCLU_L0, "OUTPUT A %s FILE", (ret == PEM_FORM)? "PEM": "DER"); + if (ret == PEM_FORM || ret == DER_FORM || ret == RAW_FORM) { + const char* formatStr = (ret == PEM_FORM) ? "PEM" : + (ret == DER_FORM) ? "DER" : + "RAW"; + + WOLFCLU_LOG(WOLFCLU_L0, "OUTPUT A %s FILE", formatStr); formatArg = ret; } else { diff --git a/src/sign-verify/clu_sign.c b/src/sign-verify/clu_sign.c index 296d9bc8..bc11ee15 100644 --- a/src/sign-verify/clu_sign.c +++ b/src/sign-verify/clu_sign.c @@ -22,10 +22,65 @@ #include #include #include +#include #ifndef WOLFCLU_NO_FILESYSTEM -int wolfCLU_sign_data(char* in, char* out, char* privKey, int keyType) +int wolfCLU_KeyPemToDer(unsigned char** pkeyBuf, int pkeySz, int pubIn) { + int ret = 0; + byte* der = NULL; + const unsigned char* keyBuf = *pkeyBuf; + + if (pubIn == 0) { + ret = wc_KeyPemToDer(keyBuf, pkeySz, NULL, 0, NULL); + if (ret > 0) { + int derSz = ret; + der = (byte*)XMALLOC(derSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ret = MEMORY_E; + } + else { + ret = wc_KeyPemToDer(keyBuf, pkeySz, der, derSz, NULL); + if (ret > 0) { + /* replace incoming pkeyBuf with new der buf */ + XFREE(*pkeyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + *pkeyBuf = der; + } + else { + /* failure, so cleanup */ + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } + } + } + } + else { + ret = wc_PubKeyPemToDer(keyBuf, pkeySz, NULL, 0); + if (ret > 0) { + int derSz = ret; + der = (byte*)XMALLOC(derSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ret = MEMORY_E; + } + else { + ret = wc_PubKeyPemToDer(keyBuf, pkeySz, der, derSz); + if (ret > 0) { + /* replace incoming pkeyBuf with new der buf */ + XFREE(*pkeyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + *pkeyBuf = der; + } + else { + /* failure, so cleanup */ + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } + } + } + } + + return ret; +} + +int wolfCLU_sign_data(char* in, char* out, char* privKey, int keyType, + int inForm) { int ret; int fSz; @@ -55,15 +110,15 @@ int wolfCLU_sign_data(char* in, char* out, char* privKey, int keyType) switch(keyType) { case RSA_SIG_VER: - ret = wolfCLU_sign_data_rsa(data, out, fSz, privKey); + ret = wolfCLU_sign_data_rsa(data, out, fSz, privKey, inForm); break; case ECC_SIG_VER: - ret = wolfCLU_sign_data_ecc(data, out, fSz, privKey); + ret = wolfCLU_sign_data_ecc(data, out, fSz, privKey, inForm); break; case ED25519_SIG_VER: - ret = wolfCLU_sign_data_ed25519(data, out, fSz, privKey); + ret = wolfCLU_sign_data_ed25519(data, out, fSz, privKey, inForm); break; default: @@ -75,14 +130,15 @@ int wolfCLU_sign_data(char* in, char* out, char* privKey, int keyType) return ret; } -int wolfCLU_sign_data_rsa(byte* data, char* out, word32 dataSz, char* privKey) +int wolfCLU_sign_data_rsa(byte* data, char* out, word32 dataSz, char* privKey, + int inForm) { #ifndef NO_RSA int ret; int privFileSz; word32 index = 0; - XFILE privKeyFile; + XFILE privKeyFile = NULL; byte* keyBuf = NULL; RsaKey key; @@ -94,93 +150,128 @@ int wolfCLU_sign_data_rsa(byte* data, char* out, word32 dataSz, char* privKey) XMEMSET(&rng, 0, sizeof(rng)); XMEMSET(&key, 0, sizeof(key)); - /* init the RsaKey */ + /* initialize the RSA key */ ret = wc_InitRsaKey(&key, NULL); if (ret != 0) { wolfCLU_LogError("Failed to initialize RsaKey\nRET: %d", ret); - return ret; } - /* read in and store private key */ - privKeyFile = XFOPEN(privKey, "rb"); - if (privKeyFile == NULL) { - wolfCLU_LogError("unable to open file %s", privKey); - return BAD_FUNC_ARG; + /* initialize RNG */ + if (ret == 0) { + ret = wc_InitRng(&rng); + if (ret != 0) { + wolfCLU_LogError("Failed to initialize rng.\nRET: %d", ret); + } } - XFSEEK(privKeyFile, 0, SEEK_END); - privFileSz = (int)XFTELL(privKeyFile); - keyBuf = (byte*)XMALLOC(privFileSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (keyBuf == NULL) { - XFCLOSE(privKeyFile); - return MEMORY_E; + /* initialize RNG RSA_BLINDING */ + if (ret == 0) { +#ifdef WC_RSA_BLINDING + ret = wc_RsaSetRNG(&key, &rng); + if (ret < 0) { + wolfCLU_LogError("Failed to initialize rng.\nRET: %d", ret); + } +#endif } - if (XFSEEK(privKeyFile, 0, SEEK_SET) != 0 || (int)XFREAD(keyBuf, 1, privFileSz, privKeyFile) != privFileSz) { - XFCLOSE(privKeyFile); - return WOLFCLU_FATAL_ERROR; + + /* open, read, and store RSA key */ + if (ret == 0) { + privKeyFile = XFOPEN(privKey, "rb"); + if (privKeyFile == NULL) { + wolfCLU_LogError("unable to open file %s", privKey); + ret = BAD_FUNC_ARG; + } + } + if (ret == 0) { + XFSEEK(privKeyFile, 0, SEEK_END); + privFileSz = (int)XFTELL(privKeyFile); + keyBuf = (byte*)XMALLOC(privFileSz+1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (keyBuf == NULL) { + ret = MEMORY_E; + } + } + if (ret == 0) { + XMEMSET(keyBuf, 0, privFileSz+1); + if (XFSEEK(privKeyFile, 0, SEEK_SET) != 0 || + (int)XFREAD(keyBuf, 1, privFileSz, privKeyFile) != privFileSz) { + ret = WOLFCLU_FATAL_ERROR; + } + } + + /* convert PEM to DER if necessary */ + if (inForm == PEM_FORM && ret == 0) { + ret = wolfCLU_KeyPemToDer(&keyBuf, privFileSz, 0); + if (ret < 0) { + wolfCLU_LogError("Failed to convert PEM to DER.\nRET: %d", ret); + } + else { + privFileSz = ret; + ret = 0; + } } - XFCLOSE(privKeyFile); /* retrieving private key and storing in the RsaKey */ - ret = wc_RsaPrivateKeyDecode(keyBuf, &index, &key, privFileSz); - XFREE(keyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (ret != 0 ) { - wolfCLU_LogError("Failed to decode private key.\nRET: %d", ret); - return ret; + if (ret == 0) { + ret = wc_RsaPrivateKeyDecode(keyBuf, &index, &key, privFileSz); + if (privFileSz < 0) { + wolfCLU_LogError("Failed to decode private key.\nRET: %d", ret); + ret = privFileSz; + } } /* setting up output buffer based on key size */ - outBufSz = wc_RsaEncryptSize(&key); - outBuf = (byte*)XMALLOC(outBufSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (outBuf == NULL) { - return MEMORY_E; - } - XMEMSET(outBuf, 0, outBufSz); - - ret = wc_InitRng(&rng); - if (ret != 0) { - wolfCLU_LogError("Failed to initialize rng.\nRET: %d", ret); - XFREE(outBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return ret; - } + if (ret == 0) { + outBufSz = wc_RsaEncryptSize(&key); + if (outBufSz <= 0) { + wolfCLU_LogError("Invalid output buffer size: %d", outBufSz); + ret = WOLFCLU_FATAL_ERROR; + } + } + if (ret == 0) { + outBuf = (byte*)XMALLOC(outBufSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (outBuf == NULL) { + ret = MEMORY_E; + } + } + if (ret == 0) { + XMEMSET(outBuf, 0, outBufSz); + + + /* signing input with RSA priv key to produce signature */ + ret = wc_RsaSSL_Sign(data, dataSz, outBuf, (word32)outBufSz, &key, &rng); + if (ret >= 0) { + XFILE s; + s = XFOPEN(out, "wb"); + XFWRITE(outBuf, 1, outBufSz, s); + XFCLOSE(s); + } + else { + wolfCLU_LogError("Failed to sign data with RSA private key.\nRET: %d", ret); + } + } + + /* cleanup allocated resources */ + XFCLOSE(privKeyFile); -#ifdef WC_RSA_BLINDING - ret = wc_RsaSetRNG(&key, &rng); - if (ret < 0) { - wolfCLU_LogError("Failed to initialize rng.\nRET: %d", ret); - XFREE(outBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return ret; + if (keyBuf!= NULL) { + XFREE(keyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); } -#endif - - ret = wc_RsaSSL_Sign(data, dataSz, outBuf, (word32)outBufSz, &key, - &rng); - if (ret < 0) { - wolfCLU_LogError("Failed to sign data with RSA private key.\nRET: %d", ret); + if (outBuf!= NULL) { XFREE(outBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - wc_FreeRsaKey(&key); - return ret; - } - else { - XFILE s; - s = XFOPEN(out, "wb"); - XFWRITE(outBuf, 1, outBufSz, s); - XFCLOSE(s); } - XFREE(outBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); wc_FreeRsaKey(&key); - (void)index; - return WOLFCLU_SUCCESS; + wc_FreeRng(&rng); + + /* expected ret == WOLFCLU_SUCCESS */ + return (ret >= 0) ? WOLFCLU_SUCCESS : ret; #else return NOT_COMPILED_IN; #endif } -int wolfCLU_sign_data_ecc(byte* data, char* out, word32 fSz, char* privKey) +int wolfCLU_sign_data_ecc(byte* data, char* out, word32 fSz, char* privKey, + int inForm) { #ifdef HAVE_ECC int ret; @@ -189,7 +280,7 @@ int wolfCLU_sign_data_ecc(byte* data, char* out, word32 fSz, char* privKey) word32 outLen; byte* keyBuf = NULL; - XFILE privKeyFile; + XFILE privKeyFile = NULL; ecc_key key; WC_RNG rng; @@ -200,84 +291,112 @@ int wolfCLU_sign_data_ecc(byte* data, char* out, word32 fSz, char* privKey) XMEMSET(&rng, 0, sizeof(rng)); XMEMSET(&key, 0, sizeof(key)); - /* init the ecc key */ + /* initialize ecc key */ ret = wc_ecc_init(&key); if (ret != 0) { - wolfCLU_LogError("Failed to initialize ecc key\nRET: %d", ret); - return ret; - } - - ret = wc_InitRng(&rng); - if (ret != 0) { - wolfCLU_LogError("Failed to initialize rng.\nRET: %d", ret); - return ret; + wolfCLU_LogError("Failed to initialize ecc key.\nRET: %d", ret); + } + + /* initialize RNG */ + if (ret == 0) { + ret = wc_InitRng(&rng); + if (ret != 0) { + wolfCLU_LogError("Failed to initialize rng.\nRET: %d", ret); + } + } + + /* open, read, and store ecc key */ + if (ret == 0) { + privKeyFile = XFOPEN(privKey, "rb"); + if (privKeyFile == NULL) { + wolfCLU_LogError("unable to open file %s", privKey); + ret = BAD_FUNC_ARG; + } + } + if (ret == 0) { + XFSEEK(privKeyFile, 0, SEEK_END); + privFileSz = (int)XFTELL(privKeyFile); + keyBuf = (byte*)XMALLOC(privFileSz+1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (keyBuf == NULL) { + ret = MEMORY_E; + } + } + if (ret == 0) { + XMEMSET(keyBuf, 0, privFileSz+1); + if (XFSEEK(privKeyFile, 0, SEEK_SET) != 0 || + (int)XFREAD(keyBuf, 1, privFileSz, privKeyFile) != privFileSz) { + ret = WOLFCLU_FATAL_ERROR; + } + } + + /* convert PEM to DER if necessary */ + if (inForm == PEM_FORM && ret == 0) { + ret = wolfCLU_KeyPemToDer(&keyBuf, privFileSz, 0); + if (ret < 0) { + wolfCLU_LogError("Failed to convert PEM to DER.\nRET: %d", ret); + } + else { + privFileSz = ret; + ret = 0; + } } - /* read in and store private key */ - privKeyFile = XFOPEN(privKey, "rb"); - if (privKeyFile == NULL) { - wolfCLU_LogError("unable to open file %s", privKey); - wc_FreeRng(&rng); - return BAD_FUNC_ARG; - } - - XFSEEK(privKeyFile, 0, SEEK_END); - privFileSz = (int)XFTELL(privKeyFile); - keyBuf = (byte*)XMALLOC(privFileSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (keyBuf == NULL) { - wc_FreeRng(&rng); - return MEMORY_E; - } - if (XFSEEK(privKeyFile, 0, SEEK_SET) != 0 || (int)XFREAD(keyBuf, 1, privFileSz, privKeyFile) != privFileSz) { - XFCLOSE(privKeyFile); - return WOLFCLU_FATAL_ERROR; - } - XFCLOSE(privKeyFile); - /* retrieving private key and storing in the Ecc Key */ - ret = wc_EccPrivateKeyDecode(keyBuf, &index, &key, privFileSz); - XFREE(keyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (ret != 0 ) { - wolfCLU_LogError("Failed to decode private key.\nRET: %d", ret); - wc_FreeRng(&rng); - return ret; + if (ret == 0) { + ret = wc_EccPrivateKeyDecode(keyBuf, &index, &key, privFileSz); + if (privFileSz < 0) { + wolfCLU_LogError("Failed to decode Ecc private key.\nRET: %d", ret); + ret = privFileSz; + } } /* setting up output buffer based on key size */ - outBufSz = wc_ecc_sig_size(&key); - outBuf = (byte*)XMALLOC(outBufSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (outBuf == NULL) { - wc_FreeRng(&rng); - return MEMORY_E; - } - XMEMSET(outBuf, 0, outBufSz); - outLen = (word32)outBufSz; + if (ret == 0) { + outBufSz = wc_ecc_sig_size(&key); + outBuf = (byte*)XMALLOC(outBufSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (outBuf == NULL) { + ret = MEMORY_E; + } + } + if (ret == 0) { + XMEMSET(outBuf, 0, outBufSz); + + /* signing input with ecc priv key to produce signature */ + outLen = (word32)outBufSz; + ret = wc_ecc_sign_hash(data, fSz, outBuf, &outLen, &rng, &key); + if (ret >= 0) { + XFILE s; + s = XFOPEN(out, "wb"); + XFWRITE(outBuf, 1, outLen, s); + XFCLOSE(s); + } + else { + wolfCLU_LogError("Failed to sign data with Ecc private key.\nRET: %d", ret); + } + } + + /* cleanup allocated resources */ + XFCLOSE(privKeyFile); - /* signing input with ecc priv key to produce signature */ - ret = wc_ecc_sign_hash(data, fSz, outBuf, &outLen, &rng, &key); - if (ret < 0) { - wolfCLU_LogError("Failed to sign data with Ecc private key.\nRET: %d", ret); - XFREE(outBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return ret; + if (keyBuf!= NULL) { + XFREE(keyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); } - else { - XFILE s; - s = XFOPEN(out, "wb"); - XFWRITE(outBuf, 1, outLen, s); - XFCLOSE(s); + if (outBuf!= NULL) { + XFREE(outBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); } - XFREE(outBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + wc_ecc_free(&key); wc_FreeRng(&rng); - (void)index; - return WOLFCLU_SUCCESS; + /* expected ret == WOLFCLU_SUCCESS */ + return (ret >= 0) ? WOLFCLU_SUCCESS : ret; #else return NOT_COMPILED_IN; #endif } -int wolfCLU_sign_data_ed25519 (byte* data, char* out, word32 fSz, char* privKey) +int wolfCLU_sign_data_ed25519 (byte* data, char* out, word32 fSz, char* privKey, + int inForm) { #ifdef HAVE_ED25519 int ret; @@ -285,7 +404,7 @@ int wolfCLU_sign_data_ed25519 (byte* data, char* out, word32 fSz, char* privKey) word32 index = 0; word32 outLen; - XFILE privKeyFile; + XFILE privKeyFile = NULL; byte* keyBuf = NULL; byte* outBuf = NULL; int outBufSz = 0; @@ -296,82 +415,123 @@ int wolfCLU_sign_data_ed25519 (byte* data, char* out, word32 fSz, char* privKey) XMEMSET(&rng, 0, sizeof(rng)); XMEMSET(&key, 0, sizeof(key)); - /* init the ED25519 key */ + /* initialize ED25519 key */ ret = wc_ed25519_init(&key); if (ret != 0) { wolfCLU_LogError("Failed to initialize ed25519 key\nRET: %d", ret); - return ret; } - ret = wc_InitRng(&rng); - if (ret != 0) { - wolfCLU_LogError("Failed to initialize rng.\nRET: %d", ret); - return ret; + /* initialize RNG */ + if (ret == 0) { + ret = wc_InitRng(&rng); + if (ret != 0) { + wolfCLU_LogError("Failed to initialize rng.\nRET: %d", ret); + } + } + + /* open, read, and store ED25519 key */ + if (ret == 0) { + privKeyFile = XFOPEN(privKey, "rb"); + if (privKeyFile == NULL) { + wolfCLU_LogError("unable to open file %s", privKey); + ret = BAD_FUNC_ARG; + } + } + if (ret == 0) { + XFSEEK(privKeyFile, 0, SEEK_END); + privFileSz = (int)XFTELL(privKeyFile); + keyBuf = (byte*)XMALLOC(privFileSz+1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (keyBuf == NULL) { + ret = MEMORY_E; + } + } + if (ret == 0) { + XMEMSET(keyBuf, 0, privFileSz+1); + if (XFSEEK(privKeyFile, 0, SEEK_SET) != 0 || + (int)XFREAD(keyBuf, 1, privFileSz, privKeyFile) != privFileSz) { + ret = WOLFCLU_FATAL_ERROR; + } + } + + /* convert PEM to DER if necessary */ + if (inForm == PEM_FORM && ret == 0) { + ret = wolfCLU_KeyPemToDer(&keyBuf, privFileSz, 0); + if (ret < 0) { + wolfCLU_LogError("Failed to convert PEM to DER.\nRET: %d", ret); + } + else { + privFileSz = ret; + ret = 0; + } + } + + /* retrieve RAW private key and store in the ED25519 Key */ + if (inForm == RAW_FORM && ret == 0) { + ret = wc_ed25519_import_private_key(keyBuf, + ED25519_KEY_SIZE, + keyBuf + ED25519_KEY_SIZE, + ED25519_KEY_SIZE, &key); + if (ret != 0 ) { + wolfCLU_LogError("Failed to import RAW private key.\nRET: %d", ret); + } } - - /* read in and store private key */ - privKeyFile = XFOPEN(privKey, "rb"); - if (privKeyFile == NULL) { - wolfCLU_LogError("unable to open file %s", privKey); - wc_FreeRng(&rng); - return BAD_FUNC_ARG; + else { + /* decode the private key from the DER-encoded input */ + if (ret == 0) { + ret = wc_Ed25519PrivateKeyDecode(keyBuf, &index, &key, privFileSz); + if (ret == 0) { + /* Calculate the public key */ + ret = wc_ed25519_make_public(&key, key.p, ED25519_PUB_KEY_SIZE); + if (ret == 0) { + key.pubKeySet = 1; + } + } + else { + wolfCLU_LogError("Failed to import private key.\nRET: %d", ret); + } + } } - XFSEEK(privKeyFile, 0, SEEK_END); - privFileSz = (int)XFTELL(privKeyFile); - keyBuf = (byte*)XMALLOC(privFileSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (keyBuf == NULL) { - XFCLOSE(privKeyFile); - wc_FreeRng(&rng); - return MEMORY_E; - } - if (XFSEEK(privKeyFile, 0, SEEK_SET) != 0 || (int)XFREAD(keyBuf, 1, privFileSz, privKeyFile) != privFileSz) { - XFCLOSE(privKeyFile); - return WOLFCLU_FATAL_ERROR; - } + /* setting up output buffer based on key size */ + if (ret == 0) { + outBufSz = ED25519_SIG_SIZE; + outBuf = (byte*)XMALLOC(outBufSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (outBuf == NULL) { + ret = MEMORY_E; + } + } + if (ret == 0) { + XMEMSET(outBuf, 0, outBufSz); + outLen = outBufSz; + + /* signing input with ED25519 priv key to produce signature */ + ret = wc_ed25519_sign_msg(data, fSz, outBuf, &outLen, &key); + if (ret >= 0) { + XFILE s; + s = XFOPEN(out, "wb"); + XFWRITE(outBuf, 1, outBufSz, s); + XFCLOSE(s); + } + else { + wolfCLU_LogError("Failed to sign data with ED25519 private key.\nRET: %d", ret); + } + } + + /* cleanup allocated resources */ XFCLOSE(privKeyFile); - /* retrieving private key and storing in the ED25519 Key */ - ret = wc_ed25519_import_private_key(keyBuf, - ED25519_KEY_SIZE, - keyBuf + ED25519_KEY_SIZE, - ED25519_KEY_SIZE, &key); - XFREE(keyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (ret != 0 ) { - wolfCLU_LogError("Failed to import private key.\nRET: %d", ret); - wc_FreeRng(&rng); - return ret; + if (keyBuf!= NULL) { + XFREE(keyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); } - - /* setting up output buffer based on key size */ - outBufSz = ED25519_SIG_SIZE; - outBuf = (byte*)XMALLOC(outBufSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (outBuf == NULL) { - wc_FreeRng(&rng); - return MEMORY_E; - } - XMEMSET(outBuf, 0, outBufSz); - outLen = outBufSz; - - /* signing input with ED25519 priv key to produce signature */ - ret = wc_ed25519_sign_msg(data, fSz, outBuf, &outLen, &key); - if (ret < 0) { - wolfCLU_LogError("Failed to sign data with ED25519 private key.\nRET: %d", ret); + if (outBuf!= NULL) { XFREE(outBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return ret; - } - else { - XFILE s; - s = XFOPEN(out, "wb"); - XFWRITE(outBuf, 1, outBufSz, s); - XFCLOSE(s); } - XFREE(outBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - (void)index; + wc_ed25519_free(&key); wc_FreeRng(&rng); - return WOLFCLU_SUCCESS; + + /* expected ret == WOLFCLU_SUCCESS */ + return (ret >= 0) ? WOLFCLU_SUCCESS : ret; #else return NOT_COMPILED_IN; #endif diff --git a/src/sign-verify/clu_sign_verify_setup.c b/src/sign-verify/clu_sign_verify_setup.c index a0232cdd..1bad0972 100644 --- a/src/sign-verify/clu_sign_verify_setup.c +++ b/src/sign-verify/clu_sign_verify_setup.c @@ -24,6 +24,7 @@ #include #include #include +#include int wolfCLU_sign_verify_setup(int argc, char** argv) { @@ -39,6 +40,7 @@ int wolfCLU_sign_verify_setup(int argc, char** argv) int signCheck = 0; int verifyCheck = 0; int pubInCheck = 0; + int inForm = DER_FORM; /* the key input format */ /* checkForArg doesn't look for "-" here, as it would have been * removed in clu_main.c if present */ @@ -107,6 +109,17 @@ int wolfCLU_sign_verify_setup(int argc, char** argv) return ret; } + ret = wolfCLU_checkForArg("-inform", 7, argc, argv); + if (ret > 0) { + inForm = wolfCLU_checkInform(argv[ret+1]); + if (inForm == USER_INPUT_ERROR) { + ret = WOLFCLU_FATAL_ERROR; + if (priv) + XFREE(priv, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + } + ret = wolfCLU_checkForArg("-pubin", 6, argc, argv); if (ret > 0) { /* output file */ @@ -226,10 +239,10 @@ int wolfCLU_sign_verify_setup(int argc, char** argv) } if (signCheck == 1) { - ret = wolfCLU_sign_data(in, out, priv, algCheck); + ret = wolfCLU_sign_data(in, out, priv, algCheck, inForm); } else if (verifyCheck == 1) { - ret = wolfCLU_verify_signature(sig, in, out, priv, algCheck, pubInCheck); + ret = wolfCLU_verify_signature(sig, in, out, priv, algCheck, pubInCheck, inForm); } if (priv) diff --git a/src/sign-verify/clu_verify.c b/src/sign-verify/clu_verify.c index 834961ad..351547e0 100644 --- a/src/sign-verify/clu_verify.c +++ b/src/sign-verify/clu_verify.c @@ -22,146 +22,119 @@ #include #include #include +#include #include /* for RSA_SIG_VER, ECC_SIG_VER, - ED25519_SIG_VER */ + * and ED25519_SIG_VER */ #ifndef WOLFCLU_NO_FILESYSTEM -static byte* wolfCLU_generate_public_key_rsa(char* privKey, byte* outBuf, - int* outBufSz) +# if 0 +static int wolfCLU_generate_public_key_ed25519(char* privKey, int inForm, byte* outBuf, + word32 outLen) { -#ifndef NO_RSA +#ifdef HAVE_ED25519 int ret; int privFileSz; word32 index = 0; - XFILE privKeyFile; - RsaKey key; - WC_RNG rng; - byte* keyBuf; - if (outBufSz == NULL) { - wolfCLU_LogError("Unexpected null output size variable"); - return NULL; - } + XFILE privKeyFile = NULL; + byte* keyBuf = NULL; + ed25519_key key; - XMEMSET(&rng, 0, sizeof(rng)); XMEMSET(&key, 0, sizeof(key)); - ret = wc_InitRsaKey(&key, NULL); + /* initialize ED25519 key */ + ret = wc_ed25519_init(&key); if (ret != 0) { - wolfCLU_LogError("Failed to initialize RsaKey.\nRet: %d", ret); - *outBufSz = ret; - return outBuf; + wolfCLU_LogError("Failed to initialize ed25519 key\nRET: %d", ret); } - - /* read in and store private key */ - - privKeyFile = XFOPEN(privKey, "rb"); - if (privKeyFile == NULL) { - wolfCLU_LogError("Unable to open file %s", privKey); - wc_FreeRsaKey(&key); - return NULL; + /* open, read, and store ED25519 key */ + if (ret == 0) { + privKeyFile = XFOPEN(privKey, "rb"); + if (privKeyFile == NULL) { + wolfCLU_LogError("unable to open file %s", privKey); + ret = BAD_FUNC_ARG; + } } - XFSEEK(privKeyFile, 0, SEEK_END); - privFileSz = (int)XFTELL(privKeyFile); - keyBuf = (byte*)XMALLOC(privFileSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (keyBuf != NULL) { - if (XFSEEK(privKeyFile, 0, SEEK_SET) != 0 || (int)XFREAD(keyBuf, 1, privFileSz, privKeyFile) != privFileSz) { - XFCLOSE(privKeyFile); - return NULL; + if (ret == 0) { + XFSEEK(privKeyFile, 0, SEEK_END); + privFileSz = (int)XFTELL(privKeyFile); + keyBuf = (byte*)XMALLOC(privFileSz+1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (keyBuf == NULL) { + ret = MEMORY_E; } } - XFCLOSE(privKeyFile); - - /* retrieving private key and storing in the RsaKey */ - ret = wc_RsaPrivateKeyDecode(keyBuf, &index, &key, privFileSz); - XFREE(keyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (ret < 0 ) { - wolfCLU_LogError("Failed to decode private key.\nRET: %d", ret); - *outBufSz = ret; - wc_FreeRsaKey(&key); - return outBuf; + if (ret == 0) { + XMEMSET(keyBuf, 0, privFileSz+1); + if (XFSEEK(privKeyFile, 0, SEEK_SET) != 0 || + (int)XFREAD(keyBuf, 1, privFileSz, privKeyFile) != privFileSz) { + ret = WOLFCLU_FATAL_ERROR; + } } - /* set output buffer to twice the private key size to ensure enough space */ - *outBufSz = 2*wc_RsaEncryptSize(&key); - - /* setting up output buffer based on privateKeyFile size */ - outBuf = (byte*)XMALLOC(*outBufSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (outBuf == NULL) { - wc_FreeRsaKey(&key); - return NULL; + /* convert PEM to DER if necessary */ + if (inForm == PEM_FORM && ret == 0) { + ret = wolfCLU_KeyPemToDer(&keyBuf, privFileSz, 0); + if (ret < 0) { + wolfCLU_LogError("Failed to convert PEM to DER.\nRET: %d", ret); + } + else { + privFileSz = ret; + ret = 0; + } } - XMEMSET(outBuf, 0, *outBufSz); - ret = wc_RsaKeyToPublicDer(&key, outBuf, *outBufSz); - if (ret < 0) { - wolfCLU_LogError("Failed to create RSA public key.\nBuf size: %d\nRET: %d", - *outBufSz, ret); - *outBufSz = ret; - wc_FreeRsaKey(&key); - return outBuf; + /* decode the private key from the DER-encoded input */ + if (ret == 0) { + ret = wc_Ed25519PrivateKeyDecode(keyBuf, &index, &key, privFileSz); + if (ret == 0) { + /* Calculate the public key */ + ret = wc_ed25519_make_public(&key, key.p, ED25519_PUB_KEY_SIZE); + if (ret == 0) { + key.pubKeySet = 1; + } + } + else { + wolfCLU_LogError("Failed to import private key.\nRET: %d", ret); + } } - *outBufSz = ret; - wc_FreeRsaKey(&key); - return outBuf; -#else - return NOT_COMPILED_IN; -#endif -} - -static int wolfCLU_generate_public_key_ed25519(char* privKey, byte* outBuf) -{ -#ifdef HAVE_ED25519 - int ret; - word32 outLen = ED25519_KEY_SIZE; - XFILE privKeyFile; - ed25519_key key; - byte privBuf[ED25519_SIG_SIZE]; - XMEMSET(&key, 0, sizeof(key)); - XMEMSET(privBuf, 0, ED25519_SIG_SIZE); - - ret = wc_ed25519_init(&key); - if (ret != 0) { - wolfCLU_LogError("Failed to initialize ED25519.\nRet: %d", ret); - return ret; + /* export public key */ + if (ret == 0) { + if (outLen < ED25519_PUB_KEY_SIZE) { + wolfCLU_LogError("Output buffer too small. Required: %d, Provided: %d", + ED25519_PUB_KEY_SIZE, outLen); + ret = BUFFER_E; + } + else { + outLen = ED25519_PUB_KEY_SIZE; + ret = wc_ed25519_export_public(&key, outBuf, &outLen); + if (ret != 0) { + wolfCLU_LogError("Failed to export ED25519 public key.\nRET: %d", ret); + } + } } - /* read in and store private key */ - privKeyFile = XFOPEN(privKey, "rb"); - if ((int)XFREAD(privBuf, 1, ED25519_SIG_SIZE, privKeyFile) != ED25519_SIG_SIZE) { - XFCLOSE(privKeyFile); - return WOLFCLU_FATAL_ERROR; - } + /* cleanup allocated resources */ XFCLOSE(privKeyFile); - /* retrieving private key and storing in the ED25519 */ - ret = wc_ed25519_import_private_key(privBuf, - ED25519_KEY_SIZE, - privBuf + ED25519_KEY_SIZE, - ED25519_KEY_SIZE, - &key); - if (ret < 0 ) { - wolfCLU_LogError("Failed to decode private key.\nRET: %d", ret); - return ret; + if (keyBuf!= NULL) { + XFREE(keyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); } - /* retrive public key from private */ - ret = wc_ed25519_export_public(&key, outBuf, &outLen); - if (ret != 0) { - wolfCLU_LogError("Failed to create ED25519 public key.\nRET: %d", ret); - return ret; - } - return WOLFCLU_SUCCESS; + wc_ed25519_free(&key); + + /* expected ret == WOLFCLU_SUCCESS */ + return (ret >= 0) ? WOLFCLU_SUCCESS : ret; #else return NOT_COMPILED_IN; #endif } - +#endif int wolfCLU_verify_signature(char* sig, char* hashFile, char* out, - char* keyPath, int keyType, int pubIn) + char* keyPath, int keyType, int pubIn, + int inForm) { int hSz = 0; int fSz; @@ -198,7 +171,7 @@ int wolfCLU_verify_signature(char* sig, char* hashFile, char* out, switch(keyType) { case RSA_SIG_VER: - ret = wolfCLU_verify_signature_rsa(data, out, fSz, keyPath, pubIn); + ret = wolfCLU_verify_signature_rsa(data, out, fSz, keyPath, pubIn, inForm); break; case ECC_SIG_VER: @@ -225,7 +198,7 @@ int wolfCLU_verify_signature(char* sig, char* hashFile, char* out, } XFCLOSE(h); ret = wolfCLU_verify_signature_ecc(data, fSz, hash, hSz, keyPath, - pubIn); + pubIn, inForm); break; case ED25519_SIG_VER: @@ -253,7 +226,7 @@ int wolfCLU_verify_signature(char* sig, char* hashFile, char* out, } XFCLOSE(h); ret = wolfCLU_verify_signature_ed25519(data, fSz, hash, hSz, - keyPath, pubIn); + keyPath, pubIn, inForm); #endif break; @@ -273,91 +246,108 @@ int wolfCLU_verify_signature(char* sig, char* hashFile, char* out, } int wolfCLU_verify_signature_rsa(byte* sig, char* out, int sigSz, char* keyPath, - int pubIn) -{ + int pubIn, int inForm) { + #ifndef NO_RSA int ret; int keyFileSz = 0; word32 index = 0; - XFILE keyPathFile; + XFILE keyPathFile = NULL; RsaKey key; - WC_RNG rng; byte* keyBuf = NULL; byte* outBuf = NULL; int outBufSz = 0; - XMEMSET(&rng, 0, sizeof(rng)); XMEMSET(&key, 0, sizeof(key)); + /* initialize RSA key */ ret = wc_InitRsaKey(&key, NULL); if (ret != 0) { wolfCLU_LogError("Failed to initialize RsaKey.\nRet: %d", ret); - return ret; } - if (pubIn == 1) { - /* read in and store rsa key */ + /* open, read, and store RSA key */ + if (ret == 0) { keyPathFile = XFOPEN(keyPath, "rb"); if (keyPathFile == NULL) { wolfCLU_LogError("unable to open file %s", keyPath); - wc_FreeRsaKey(&key); - return BAD_FUNC_ARG; + ret = BAD_FUNC_ARG; } - + } + if (ret == 0) { XFSEEK(keyPathFile, 0, SEEK_END); keyFileSz = (int)XFTELL(keyPathFile); - keyBuf = (byte*)XMALLOC(keyFileSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (keyBuf != NULL) { - if (XFSEEK(keyPathFile, 0, SEEK_SET) != 0 || - (int)XFREAD(keyBuf, 1, keyFileSz, keyPathFile) != keyFileSz) { - XFCLOSE(keyPathFile); - return WOLFCLU_FATAL_ERROR; - } + keyBuf = (byte*)XMALLOC(keyFileSz+1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (keyBuf == NULL) { + ret = MEMORY_E; } - XFCLOSE(keyPathFile); } - else { - keyBuf = wolfCLU_generate_public_key_rsa(keyPath, keyBuf, &keyFileSz); - if (keyFileSz < 0) { - wolfCLU_LogError("Failed to derive public key from private key."); - wc_FreeRsaKey(&key); - return ret; + if (ret == 0) { + XMEMSET(keyBuf, 0, keyFileSz+1); + if (XFSEEK(keyPathFile, 0, SEEK_SET) != 0 || + (int)XFREAD(keyBuf, 1, keyFileSz, keyPathFile) != keyFileSz) { + ret = WOLFCLU_FATAL_ERROR; } } - /* retrieving public key and storing in the RsaKey */ - ret = wc_RsaPublicKeyDecode(keyBuf, &index, &key, keyFileSz); - if (keyBuf != NULL) { - XFREE(keyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + /* convert PEM to DER if necessary */ + if (inForm == PEM_FORM && ret == 0) { + ret = wolfCLU_KeyPemToDer(&keyBuf, keyFileSz, pubIn); + if (ret < 0) { + wolfCLU_LogError("Failed to convert PEM to DER.\nRET: %d", ret); + } + else { + keyFileSz = ret; + ret = 0; + } } - if (ret < 0 ) { - wolfCLU_LogError("Failed to decode public key.\nRET: %d", ret); - wc_FreeRsaKey(&key); - return ret; + if (pubIn == 1) { + /* decode public key from DER-encoded input */ + if (ret == 0) { + ret = wc_RsaPublicKeyDecode(keyBuf, &index, &key, keyFileSz); + if (ret != 0) { + wolfCLU_LogError("Failed to decode public key from DER.\nRET: %d", ret); + } + } } - - /* setting up output buffer based on key size */ - outBufSz = wc_RsaEncryptSize(&key); - outBuf = (byte*)XMALLOC(outBufSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (outBuf == NULL) { - wolfCLU_LogError("Failed to malloc output buffer"); - wc_FreeRsaKey(&key); - return MEMORY_E; + else { + /* retrieve private key and store in the RsaKey */ + if (ret == 0) { + ret = wc_RsaPrivateKeyDecode(keyBuf, &index, &key, keyFileSz); + if (ret != 0) { + wolfCLU_LogError("Failed to decode private key.\nRET: %d", ret); + } + } } - XMEMSET(outBuf, 0, outBufSz); - ret = wc_RsaSSL_Verify(sig, sigSz, outBuf, (word32)outBufSz, &key); - if (ret < 0) { - wolfCLU_LogError("Failed to verify data with RSA public key.\nRET: %d", ret); - XFREE(outBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&key); - return ret; + /* set up output buffer based on key size */ + if (ret == 0) { + outBufSz = wc_RsaEncryptSize(&key); + if (outBufSz <= 0) { + wolfCLU_LogError("Invalid output buffer size: %d", outBufSz); + ret = WOLFCLU_FATAL_ERROR; + } } - else { + if (ret == 0) { + outBuf = (byte*)XMALLOC(outBufSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (outBuf == NULL) { + ret = MEMORY_E; + } + } + if (ret == 0) { + XMEMSET(outBuf, 0, outBufSz); + + /* verify the RSA signature */ + ret = wc_RsaSSL_Verify(sig, sigSz, outBuf, (word32)outBufSz, &key); + if (ret < 0) { + wolfCLU_LogError("Failed to verify data with pub key.\nRET: %d", ret); + } + + /* write the output to the specified file */ XFILE s = XFOPEN(out, "wb"); if (s == NULL) { - wolfCLU_LogError("unable to open file %s", out); + wolfCLU_LogError("Unable to open file %s", out); ret = BAD_FUNC_ARG; } else { @@ -366,169 +356,278 @@ int wolfCLU_verify_signature_rsa(byte* sig, char* out, int sigSz, char* keyPath, } } + /* Cleanup allocated resources */ + XFCLOSE(keyPathFile); + if (outBuf != NULL) { XFREE(outBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); } + if (keyBuf != NULL) { + XFREE(keyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } + wc_FreeRsaKey(&key); - return (ret < 0)? ret : WOLFCLU_SUCCESS; + + /* expected ret == WOLFCLU_SUCCESS */ + return (ret >= 0) ? WOLFCLU_SUCCESS : ret; #else return NOT_COMPILED_IN; #endif } int wolfCLU_verify_signature_ecc(byte* sig, int sigSz, byte* hash, int hashSz, - char* keyPath, int pubIn) { + char* keyPath, int pubIn, int inForm) +{ #ifdef HAVE_ECC int ret; - int keyFileSz; + int keyFileSz = 0; int stat = 0; word32 index = 0; - XFILE keyPathFile; + XFILE keyPathFile = NULL; ecc_key key; - WC_RNG rng; - byte* keyBuf; + byte* keyBuf = NULL; + byte* outBuf = NULL; + int outBufSz = 0; - XMEMSET(&rng, 0, sizeof(rng)); XMEMSET(&key, 0, sizeof(key)); + /* initialize Ecc key */ ret = wc_ecc_init(&key); if (ret != 0) { wolfCLU_LogError("Failed to initialize ecc key.\nRet: %d", ret); - return ret; } - /* read in and store ecc key */ - keyPathFile = XFOPEN(keyPath, "rb"); - if (keyPathFile == NULL) { - wolfCLU_LogError("unable to open file %s", keyPath); - return BAD_FUNC_ARG; + /* open, read, and store Ecc key */ + if (ret == 0) { + keyPathFile = XFOPEN(keyPath, "rb"); + if (keyPathFile == NULL) { + wolfCLU_LogError("unable to open file %s", keyPath); + ret = BAD_FUNC_ARG; + } } - - XFSEEK(keyPathFile, 0, SEEK_END); - keyFileSz = (int)XFTELL(keyPathFile); - keyBuf = (byte*)XMALLOC(keyFileSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (keyBuf != NULL) { + if (ret == 0) { + XFSEEK(keyPathFile, 0, SEEK_END); + keyFileSz = (int)XFTELL(keyPathFile); + keyBuf = (byte*)XMALLOC(keyFileSz+1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (keyBuf == NULL) { + ret = MEMORY_E; + } + } + if (ret == 0) { + XMEMSET(keyBuf, 0, keyFileSz+1); if (XFSEEK(keyPathFile, 0, SEEK_SET) != 0 || - (int)XFREAD(keyBuf, 1, keyFileSz, keyPathFile) != keyFileSz) { - XFCLOSE(keyPathFile); - return WOLFCLU_FATAL_ERROR; - } + (int)XFREAD(keyBuf, 1, keyFileSz, keyPathFile) != keyFileSz) { + ret = WOLFCLU_FATAL_ERROR; + } + } + + /* convert PEM to DER if necessary */ + if (inForm == PEM_FORM && ret == 0) { + ret = wolfCLU_KeyPemToDer(&keyBuf, keyFileSz, pubIn); + if (ret < 0) { + wolfCLU_LogError("Failed to convert PEM to DER.\nRET: %d", ret); + } + else { + keyFileSz = ret; + ret = 0; + } } - XFCLOSE(keyPathFile); if (pubIn == 1) { - /* retrieving public key and storing in the ecc key */ - ret = wc_EccPublicKeyDecode(keyBuf, &index, &key, keyFileSz); - if (ret < 0 ) { - wolfCLU_LogError("Failed to decode public key.\nRET: %d", ret); - XFREE(keyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return ret; + /* retrieve public key and store in the Ecc key */ + if (ret == 0) { + ret = wc_EccPublicKeyDecode(keyBuf, &index, &key, keyFileSz); + if (ret < 0 ) { + wolfCLU_LogError("Failed to decode public key.\nRET: %d", ret); + } } } else { - /* retrieving private key and storing in the Ecc Key */ - ret = wc_EccPrivateKeyDecode(keyBuf, &index, &key, keyFileSz); - if (ret != 0 ) { - wolfCLU_LogError("Failed to decode private key.\nRET: %d", ret); - XFREE(keyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return ret; + /* retrieve private key and store in the Ecc Key */ + if (ret == 0) { + ret = wc_EccPrivateKeyDecode(keyBuf, &index, &key, keyFileSz); + if (ret != 0 ) { + wolfCLU_LogError("Failed to decode Ecc private key.\nRET: %d", ret); + } } } - if (keyBuf) - XFREE(keyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + /* setting up output buffer based on key size */ + if (ret == 0) { + outBufSz = wc_ecc_sig_size(&key); + if (outBufSz <= 0) { + wolfCLU_LogError("Invalid output buffer size: %d", outBufSz); + ret = WOLFCLU_FATAL_ERROR; + } + } + if (ret == 0) { + outBuf = (byte*)XMALLOC(outBufSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (outBuf == NULL) { + ret = MEMORY_E; + } + } + if (ret == 0) { + XMEMSET(outBuf, 0, outBufSz); - ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, &stat, &key); - if (ret < 0) { - wolfCLU_LogError("Failed to verify data with Ecc public key.\nRET: %d", ret); - return ret; + /* verify data with Ecc public key */ + ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, &stat, &key); + if (ret < 0) { + wolfCLU_LogError("Failed to verify data with pub key.\nRET: %d", ret); + } + else if (stat == 1) { + WOLFCLU_LOG(WOLFCLU_L0, "Valid Signature."); + } + else { + wolfCLU_LogError("Invalid Signature."); + } } - else if (stat == 1) { - WOLFCLU_LOG(WOLFCLU_L0, "Valid Signature."); + + /* cleanup allocated resources */ + XFCLOSE(keyPathFile); + + if (outBuf != NULL) { + XFREE(outBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); } - else { - wolfCLU_LogError("Invalid Signature."); + if (keyBuf != NULL) { + XFREE(keyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); } - return WOLFCLU_SUCCESS; + wc_ecc_free(&key); + + /* expected ret == WOLFCLU_SUCCESS */ + return (ret >= 0) ? WOLFCLU_SUCCESS : ret; #else return NOT_COMPILED_IN; #endif } int wolfCLU_verify_signature_ed25519(byte* sig, int sigSz, - byte* hash, int hashSz, char* keyPath, int pubIn) { + byte* hash, int hashSz, char* keyPath, int pubIn, int inForm) { #ifdef HAVE_ED25519 int ret; int stat = 0; + word32 index = 0; + int keyFileSz = 0; - XFILE keyPathFile; + XFILE keyPathFile = NULL; ed25519_key key; - byte* keyBuf = (byte*)XMALLOC(ED25519_KEY_SIZE, HEAP_HINT, - DYNAMIC_TYPE_TMP_BUFFER); - if (keyBuf == NULL) { - wolfCLU_LogError("malloc failed"); - return MEMORY_E; - } + byte* keyBuf = NULL; XMEMSET(&key, 0, sizeof(key)); - XMEMSET(keyBuf, 0, ED25519_KEY_SIZE); + /* initialize ED25519 key */ ret = wc_ed25519_init(&key); if (ret != 0) { wolfCLU_LogError("Failed to initialize ED25519 key.\nRet: %d", ret); - XFREE(keyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return ret; } - /* retrieving public key and storing in the ED25519 key */ - if (pubIn == 1) { - /* read in and store ED25519 key */ + /* open, read, and store ED25519 key */ + if (ret == 0) { keyPathFile = XFOPEN(keyPath, "rb"); if (keyPathFile == NULL) { - XFREE(keyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return BAD_FUNC_ARG; + wolfCLU_LogError("unable to open file %s", keyPath); + ret = BAD_FUNC_ARG; } - if ((int)XFREAD(keyBuf, 1, ED25519_KEY_SIZE, keyPathFile) != ED25519_KEY_SIZE) { - XFCLOSE(keyPathFile); - return WOLFCLU_FATAL_ERROR; + } + if (ret == 0) { + XFSEEK(keyPathFile, 0, SEEK_END); + keyFileSz = (int)XFTELL(keyPathFile); + keyBuf = (byte*)XMALLOC(keyFileSz+1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (keyBuf == NULL) { + ret = MEMORY_E; } - XFCLOSE(keyPathFile); - } - else { - ret = wolfCLU_generate_public_key_ed25519(keyPath, keyBuf); - if (ret != 0) { - wolfCLU_LogError("Failed to derive public key from private key."); - XFREE(keyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return ret; + if (ret == 0) { + XMEMSET(keyBuf, 0, keyFileSz+1); + if (XFSEEK(keyPathFile, 0, SEEK_SET) != 0 || + (int)XFREAD(keyBuf, 1, keyFileSz, keyPathFile) != keyFileSz) { + ret = WOLFCLU_FATAL_ERROR; } } - ret = wc_ed25519_import_public(keyBuf, ED25519_KEY_SIZE, &key); - if (ret != 0 ) { - wolfCLU_LogError("Failed to decode public key.\nRET: %d", ret); - XFREE(keyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return ret; + /* convert PEM to DER if necessary */ + if (inForm == PEM_FORM && ret == 0) { + ret = wolfCLU_KeyPemToDer(&keyBuf, keyFileSz, pubIn); + if (ret < 0) { + wolfCLU_LogError("Failed to convert PEM to DER.\nRET: %d", ret); + } + else { + keyFileSz = ret; + ret = 0; + } } - XFREE(keyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - ret = wc_ed25519_verify_msg(sig, sigSz, hash, hashSz, &stat, &key); - if (ret != 0) { - wolfCLU_LogError("Failed to verify data with ED25519 public key.\nRET: %d", ret); - return ret; + if (pubIn == 1 && ret == 0) { + /* decode public key from RAW-encoded input */ + if (inForm == RAW_FORM) { + ret = wc_ed25519_import_public(keyBuf, ED25519_KEY_SIZE, &key); + if (ret != 0) { + wolfCLU_LogError("Failed to import raw public key.\nRET: %d", ret); + } + } + /* decode public key from DER-encoded input */ + else { + ret = wc_Ed25519PublicKeyDecode(keyBuf, &index, &key, keyFileSz); + if (ret != 0) { + wolfCLU_LogError("Failed to decode public key from DER.\nRET: %d", ret); + } + } } - else if (stat == 1) { - WOLFCLU_LOG(WOLFCLU_L0, "Valid Signature."); + else if (ret == 0) { + /* handle private key decoding and public key derivation */ + if (inForm == RAW_FORM) { + ret = wc_ed25519_import_private_key(keyBuf, + ED25519_KEY_SIZE, + keyBuf + ED25519_KEY_SIZE, + ED25519_KEY_SIZE, &key); + if (ret < 0) { + wolfCLU_LogError("Failed to decode private key.\nRET: %d", ret); + } + } + else { + ret = wc_Ed25519PrivateKeyDecode(keyBuf, &index, &key, keyFileSz); + if (ret != 0) { + wolfCLU_LogError("Failed to import private key.\nRET: %d", ret); + } + } + + /* calculate the public key */ + if (ret == 0) { + ret = wc_ed25519_make_public(&key, key.p, ED25519_PUB_KEY_SIZE); + if (ret == 0) { + key.pubKeySet = 1; + } + } } - else { - wolfCLU_LogError("Invalid Signature."); + + /* verify data with ED25519 public key */ + if (ret == 0) { + ret = wc_ed25519_verify_msg(sig, sigSz, hash, hashSz, &stat, &key); + if (ret < 0) { + wolfCLU_LogError("Failed to verify data with ED25519 public key.\nRET: %d", ret); + } + else if (stat == 1) { + WOLFCLU_LOG(WOLFCLU_L0, "Valid Signature."); + } + else { + wolfCLU_LogError("Invalid Signature."); + } } - return WOLFCLU_SUCCESS; + /* cleanup allocated resources */ + XFCLOSE(keyPathFile); + + if (keyBuf != NULL) { + XFREE(keyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } + + wc_ed25519_free(&key); + + /* expected ret == WOLFCLU_SUCCESS */ + return (ret >= 0) ? WOLFCLU_SUCCESS : ret; #else return NOT_COMPILED_IN; #endif diff --git a/src/tools/clu_funcs.c b/src/tools/clu_funcs.c index 2fb49be0..02a45669 100644 --- a/src/tools/clu_funcs.c +++ b/src/tools/clu_funcs.c @@ -1100,7 +1100,7 @@ int wolfCLU_checkForArg(const char* searchTerm, int length, int argc, int wolfCLU_checkOutform(char* outform) { if (outform == NULL) { - WOLFCLU_LOG(WOLFCLU_L0, "Usage: -outform [PEM/DER]"); + WOLFCLU_LOG(WOLFCLU_L0, "Usage: -outform [PEM/DER/RAW]"); WOLFCLU_LOG(WOLFCLU_L0, "missing outform required argument"); return USER_INPUT_ERROR; } @@ -1112,8 +1112,11 @@ int wolfCLU_checkOutform(char* outform) else if (XSTRNCMP(outform, "der", 3) == 0) { return DER_FORM; } + else if (XSTRNCMP(outform, "raw", 3) == 0) { + return RAW_FORM; + } else { - WOLFCLU_LOG(WOLFCLU_L0, "Usage: -outform [PEM/DER]"); + WOLFCLU_LOG(WOLFCLU_L0, "Usage: -outform [PEM/DER/RAW]"); WOLFCLU_LOG(WOLFCLU_L0, "\"%s\" is not a valid output format", outform); } return USER_INPUT_ERROR; @@ -1122,7 +1125,7 @@ int wolfCLU_checkOutform(char* outform) int wolfCLU_checkInform(char* inform) { if (inform == NULL) { - WOLFCLU_LOG(WOLFCLU_L0, "Usage: -inform [PEM/DER]"); + WOLFCLU_LOG(WOLFCLU_L0, "Usage: -inform [PEM/DER/RAW]"); WOLFCLU_LOG(WOLFCLU_L0, "missing inform required argument"); return USER_INPUT_ERROR; } @@ -1134,8 +1137,11 @@ int wolfCLU_checkInform(char* inform) else if (XSTRNCMP(inform, "der", 3) == 0) { return DER_FORM; } + else if (XSTRNCMP(inform, "raw", 3) == 0) { + return RAW_FORM; + } else { - WOLFCLU_LOG(WOLFCLU_L0, "Usage: -inform [PEM/DER]"); + WOLFCLU_LOG(WOLFCLU_L0, "Usage: -inform [PEM/DER/RAW]"); WOLFCLU_LOG(WOLFCLU_L0, "\"%s\" is not a valid input format", inform); } return USER_INPUT_ERROR; diff --git a/tests/genkey_sign_ver/genkey-sign-ver-test.sh b/tests/genkey_sign_ver/genkey-sign-ver-test.sh index 3f79dd5a..b869d8ae 100755 --- a/tests/genkey_sign_ver/genkey-sign-ver-test.sh +++ b/tests/genkey_sign_ver/genkey-sign-ver-test.sh @@ -66,7 +66,7 @@ rsa_compare_decrypted(){ gen_key_sign_ver_test(){ # generate a key pair for signing - ./wolfssl -genkey $1 -out $2 -outform der KEYPAIR + ./wolfssl -genkey $1 -out $2 -outform $4 KEYPAIR RESULT=$? printf '%s\n' "genkey RESULT - $RESULT" [ $RESULT -ne 0 ] && printf '%s\n' "Failed $1 genkey" && \ @@ -74,40 +74,40 @@ gen_key_sign_ver_test(){ printf '%s\n' "--enable-keygen" && exit -1 # test signing with priv key - ./wolfssl -$1 -sign -inkey $2.priv -in sign-this.txt -out $3 + ./wolfssl -$1 -sign -inkey $2.priv -inform $4 -in sign-this.txt -out $3 RESULT=$? printf '%s\n' "sign RESULT - $RESULT" [ $RESULT -ne 0 ] && printf '%s\n' "Failed $1 sign" && exit -1 # test verifying with priv key if [ "${1}" = "rsa" ]; then - ./wolfssl -$1 -verify -inkey $2.priv -sigfile $3 -in sign-this.txt \ - -out $4.private_result + ./wolfssl -$1 -verify -inkey $2.priv -inform $4 -sigfile $3 -in sign-this.txt \ + -out $5.private_result else - ./wolfssl -$1 -verify -inkey $2.priv -sigfile $3 -in sign-this.txt + ./wolfssl -$1 -verify -inkey $2.priv -inform $4 -sigfile $3 -in sign-this.txt fi RESULT=$? printf '%s\n' "private verify RESULT - $RESULT" - [ $RESULT -ne 0 ] && printf '%s\n' "Failed $1 sign" && exit -1 + [ $RESULT -ne 0 ] && printf '%s\n' "Failed $1 private verify" && exit -1 # test verifying with pub key if [ "${1}" = "rsa" ]; then - ./wolfssl -$1 -verify -inkey $2.pub -sigfile $3 -in sign-this.txt \ - -out $4.public_result -pubin + ./wolfssl -$1 -verify -inkey $2.pub -inform $4 -sigfile $3 -in sign-this.txt \ + -out $5.public_result -pubin else - ./wolfssl -$1 -verify -inkey $2.pub -sigfile $3 -in sign-this.txt -pubin + ./wolfssl -$1 -verify -inkey $2.pub -inform $4 -sigfile $3 -in sign-this.txt -pubin fi RESULT=$? printf '%s\n' "public verify RESULT - $RESULT" - [ $RESULT -ne 0 ] && printf '%s\n' "Failed $1 sign" && exit -1 + [ $RESULT -ne 0 ] && printf '%s\n' "Failed $1 public verify " && exit -1 if [ $1 = "rsa" ]; then ORIGINAL=`cat -A sign-this.txt` - DECRYPTED=`cat -A $4.private_result` + DECRYPTED=`cat -A $5.private_result` rsa_compare_decrypted "${DECRYPTED}" "${ORIGINAL}" - DECRYPTED=`cat -A $4.public_result` + DECRYPTED=`cat -A $5.public_result` rsa_compare_decrypted "${DECRYPTED}" "${ORIGINAL}" fi @@ -118,17 +118,45 @@ create_sign_data_file ALGORITHM="ed25519" KEYFILENAME="edkey" SIGOUTNAME="ed-signed.sig" -gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} +DERPEMRAW="der" +gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} ALGORITHM="ecc" KEYFILENAME="ecckey" SIGOUTNAME="ecc-signed.sig" -gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} +DERPEMRAW="der" +gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} ALGORITHM="rsa" KEYFILENAME="rsakey" SIGOUTNAME="rsa-signed.sig" +DERPEMRAW="der" VERIFYOUTNAME="rsa-sigout" -gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${VERIFYOUTNAME} +gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} ${VERIFYOUTNAME} + +ALGORITHM="ed25519" +KEYFILENAME="edkey" +SIGOUTNAME="ed-signed.sig" +DERPEMRAW="pem" +gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} + +ALGORITHM="ecc" +KEYFILENAME="ecckey" +SIGOUTNAME="ecc-signed.sig" +DERPEMRAW="pem" +gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} + +ALGORITHM="rsa" +KEYFILENAME="rsakey" +SIGOUTNAME="rsa-signed.sig" +DERPEMRAW="pem" +VERIFYOUTNAME="rsa-sigout" +gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} ${VERIFYOUTNAME} + +ALGORITHM="ed25519" +KEYFILENAME="edkey" +SIGOUTNAME="ed-signed.sig" +DERPEMRAW="raw" +gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} exit 0 diff --git a/wolfclu/sign-verify/clu_sign.h b/wolfclu/sign-verify/clu_sign.h index a86223f2..d7dac5de 100644 --- a/wolfclu/sign-verify/clu_sign.h +++ b/wolfclu/sign-verify/clu_sign.h @@ -39,11 +39,12 @@ enum { ED25519_SIG_VER, }; -int wolfCLU_sign_data(char*, char*, char*, int); +int wolfCLU_sign_data(char*, char*, char*, int, int); -int wolfCLU_sign_data_rsa(byte*, char*, word32, char*); -int wolfCLU_sign_data_ecc(byte*, char*, word32, char*); -int wolfCLU_sign_data_ed25519(byte*, char*, word32, char*); +int wolfCLU_sign_data_rsa(byte*, char*, word32, char*, int); +int wolfCLU_sign_data_ecc(byte*, char*, word32, char*, int); +int wolfCLU_sign_data_ed25519(byte*, char*, word32, char*, int); +int wolfCLU_KeyPemToDer(unsigned char** pkeyBuf, int pkeySz, int pubIn); diff --git a/wolfclu/sign-verify/clu_verify.h b/wolfclu/sign-verify/clu_verify.h index dd826029..a3a50826 100644 --- a/wolfclu/sign-verify/clu_verify.h +++ b/wolfclu/sign-verify/clu_verify.h @@ -36,8 +36,8 @@ int wolfCLU_x509Verify(int argc, char** argv); int wolfCLU_CRLVerify(int argc, char** argv); -int wolfCLU_verify_signature(char* , char*, char*, char*, int, int); +int wolfCLU_verify_signature(char* , char*, char*, char*, int, int, int); -int wolfCLU_verify_signature_rsa(byte* , char*, int, char*, int); -int wolfCLU_verify_signature_ecc(byte*, int, byte*, int, char*, int); -int wolfCLU_verify_signature_ed25519(byte*, int, byte*, int, char*, int); +int wolfCLU_verify_signature_rsa(byte* , char*, int, char*, int, int); +int wolfCLU_verify_signature_ecc(byte*, int, byte*, int, char*, int, int); +int wolfCLU_verify_signature_ed25519(byte*, int, byte*, int, char*, int, int); diff --git a/wolfclu/x509/clu_cert.h b/wolfclu/x509/clu_cert.h index feda6371..79f5fee3 100644 --- a/wolfclu/x509/clu_cert.h +++ b/wolfclu/x509/clu_cert.h @@ -24,6 +24,7 @@ #define PEM_FORM 1 #define DER_FORM 2 +#define RAW_FORM 3 /* handles incoming arguments for certificate generation */ int wolfCLU_certSetup(int argc, char** argv);