diff --git a/.gitignore b/.gitignore index 2eb356d20..f1145d74d 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,8 @@ ntru-cert.pem ntru-key.raw key.der key.pem +ecc-key.der +ecc-key.pem certreq.der certreq.pem pkcs7cert.der diff --git a/ctaocrypt/src/asn.c b/ctaocrypt/src/asn.c index c836db064..ad3f35026 100644 --- a/ctaocrypt/src/asn.c +++ b/ctaocrypt/src/asn.c @@ -2545,7 +2545,7 @@ CYASSL_LOCAL word32 SetExplicit(byte number, word32 len, byte* output) } -#if defined(HAVE_ECC) && defined(CYASSL_CERT_GEN) +#if defined(HAVE_ECC) && (defined(CYASSL_CERT_GEN) || defined(CYASSL_KEY_GEN)) static word32 SetCurve(ecc_key* key, byte* output) { @@ -4766,6 +4766,7 @@ static int SetSerial(const byte* serial, byte* output) #ifdef HAVE_ECC + /* Write a public ECC key to output */ static int SetEccPublicKey(byte* output, ecc_key* key) { @@ -6554,6 +6555,96 @@ int EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, return ret; } + +#ifdef CYASSL_KEY_GEN + +/* Write a Private ecc key to DER format, length on success else < 0 */ +int EccKeyToDer(ecc_key* key, byte* output, word32 inLen) +{ + byte curve[MAX_ALGO_SZ]; + byte ver[MAX_VERSION_SZ]; + byte seq[MAX_SEQ_SZ]; + int ret; + int curveSz; + int verSz; + int privHdrSz = ASN_ECC_HEADER_SZ; + int pubHdrSz = ASN_ECC_CONTEXT_SZ + ASN_ECC_HEADER_SZ; + int curveHdrSz = ASN_ECC_CONTEXT_SZ; + word32 seqSz; + word32 idx = 0; + word32 pubSz = ECC_BUFSIZE; + word32 privSz; + word32 totalSz; + + if (key == NULL || output == NULL || inLen == 0) + return BAD_FUNC_ARG; + + ret = ecc_export_x963(key, NULL, &pubSz); + if (ret != LENGTH_ONLY_E) { + return ret; + } + curveSz = SetCurve(key, curve); + if (curveSz < 0) { + return curveSz; + } + + privSz = key->dp->size; + + verSz = SetMyVersion(1, ver, FALSE); + if (verSz < 0) { + return verSz; + } + + totalSz = verSz + privSz + privHdrSz + curveSz + curveHdrSz + + pubSz + pubHdrSz + 1; /* plus null byte b4 public */ + seqSz = SetSequence(totalSz, seq); + totalSz += seqSz; + + if (totalSz > inLen) { + return BUFFER_E; + } + + /* write it out */ + /* seq */ + XMEMCPY(output + idx, seq, seqSz); + idx += seqSz; + + /* ver */ + XMEMCPY(output + idx, ver, verSz); + idx += verSz; + + /* private */ + output[idx++] = ASN_OCTET_STRING; + output[idx++] = (byte)privSz; + ret = ecc_export_private_only(key, output + idx, &privSz); + if (ret < 0) { + return ret; + } + idx += privSz; + + /* curve */ + output[idx++] = ECC_PREFIX_0; + output[idx++] = (byte)curveSz; + XMEMCPY(output + idx, curve, curveSz); + idx += curveSz; + + /* public */ + output[idx++] = ECC_PREFIX_1; + output[idx++] = (byte)pubSz + ASN_ECC_CONTEXT_SZ + 1; /* plus null byte */ + output[idx++] = ASN_BIT_STRING; + output[idx++] = (byte)pubSz + 1; /* plus null byte */ + output[idx++] = (byte)0; /* null byte */ + ret = ecc_export_x963(key, output + idx, &pubSz); + if (ret != 0) { + return ret; + } + /* idx += pubSz if do more later */ + + return totalSz; +} + +#endif /* CYASSL_KEY_GEN */ + #endif /* HAVE_ECC */ diff --git a/ctaocrypt/src/ecc.c b/ctaocrypt/src/ecc.c index c81f7871b..d13cb58c5 100644 --- a/ctaocrypt/src/ecc.c +++ b/ctaocrypt/src/ecc.c @@ -2162,8 +2162,15 @@ int ecc_export_x963(ecc_key* key, byte* out, word32* outLen) word32 numlen; int ret = MP_OKAY; + /* return length needed only */ + if (key != NULL && out == NULL && outLen != NULL) { + numlen = key->dp->size; + *outLen = 1 + 2*numlen; + return LENGTH_ONLY_E; + } + if (key == NULL || out == NULL || outLen == NULL) - return ECC_BAD_ARG_E; + return ECC_BAD_ARG_E; if (ecc_is_valid_idx(key->idx) == 0) { return ECC_BAD_ARG_E; diff --git a/ctaocrypt/src/error.c b/ctaocrypt/src/error.c index be625ad16..f8d6a9e2f 100644 --- a/ctaocrypt/src/error.c +++ b/ctaocrypt/src/error.c @@ -283,6 +283,9 @@ const char* CTaoCryptGetErrorString(int error) case RSA_PAD_E: return "Rsa Padding error"; + case LENGTH_ONLY_E: + return "Output length only set, not for other use error"; + default: return "unknown error number"; diff --git a/ctaocrypt/test/test.c b/ctaocrypt/test/test.c index 59b16db3e..4e2cc655b 100644 --- a/ctaocrypt/test/test.c +++ b/ctaocrypt/test/test.c @@ -193,12 +193,9 @@ int pbkdf2_test(void); static void err_sys(const char* msg, int es) + { printf("%s error = %d\n", msg, es); - #if !defined(THREADX) && !defined(CYASSL_MDK_ARM) - if (msg) - exit(es); - #endif return; } @@ -219,74 +216,75 @@ void ctaocrypt_test(void* args) #if !defined(NO_BIG_INT) if (CheckCtcSettings() != 1) - err_sys("Build vs runtime math mismatch\n", -1234); + return err_sys("Build vs runtime math mismatch\n", -1234); #ifdef USE_FAST_MATH if (CheckFastMathSettings() != 1) - err_sys("Build vs runtime fastmath FP_MAX_BITS mismatch\n", -1235); + return err_sys("Build vs runtime fastmath FP_MAX_BITS mismatch\n", + -1235); #endif /* USE_FAST_MATH */ #endif /* !NO_BIG_INT */ #ifndef NO_MD5 if ( (ret = md5_test()) != 0) - err_sys("MD5 test failed!\n", ret); + return err_sys("MD5 test failed!\n", ret); else printf( "MD5 test passed!\n"); #endif #ifdef CYASSL_MD2 if ( (ret = md2_test()) != 0) - err_sys("MD2 test failed!\n", ret); + return err_sys("MD2 test failed!\n", ret); else printf( "MD2 test passed!\n"); #endif #ifndef NO_MD4 if ( (ret = md4_test()) != 0) - err_sys("MD4 test failed!\n", ret); + return err_sys("MD4 test failed!\n", ret); else printf( "MD4 test passed!\n"); #endif #ifndef NO_SHA if ( (ret = sha_test()) != 0) - err_sys("SHA test failed!\n", ret); + return err_sys("SHA test failed!\n", ret); else printf( "SHA test passed!\n"); #endif #ifndef NO_SHA256 if ( (ret = sha256_test()) != 0) - err_sys("SHA-256 test failed!\n", ret); + return err_sys("SHA-256 test failed!\n", ret); else printf( "SHA-256 test passed!\n"); #endif #ifdef CYASSL_SHA384 if ( (ret = sha384_test()) != 0) - err_sys("SHA-384 test failed!\n", ret); + return err_sys("SHA-384 test failed!\n", ret); else printf( "SHA-384 test passed!\n"); #endif #ifdef CYASSL_SHA512 if ( (ret = sha512_test()) != 0) - err_sys("SHA-512 test failed!\n", ret); + return err_sys("SHA-512 test failed!\n", ret); else printf( "SHA-512 test passed!\n"); #endif #ifdef CYASSL_RIPEMD if ( (ret = ripemd_test()) != 0) - err_sys("RIPEMD test failed!\n", ret); + return err_sys("RIPEMD test failed!\n", ret); else printf( "RIPEMD test passed!\n"); #endif #ifdef HAVE_BLAKE2 if ( (ret = blake2b_test()) != 0) - err_sys("BLAKE2b test failed!\n", ret); + return err_sys("BLAKE2b test failed!\n", ret); else printf( "BLAKE2b test passed!\n"); #endif @@ -294,49 +292,49 @@ void ctaocrypt_test(void* args) #ifndef NO_HMAC #ifndef NO_MD5 if ( (ret = hmac_md5_test()) != 0) - err_sys("HMAC-MD5 test failed!\n", ret); + return err_sys("HMAC-MD5 test failed!\n", ret); else printf( "HMAC-MD5 test passed!\n"); #endif #ifndef NO_SHA if ( (ret = hmac_sha_test()) != 0) - err_sys("HMAC-SHA test failed!\n", ret); + return err_sys("HMAC-SHA test failed!\n", ret); else printf( "HMAC-SHA test passed!\n"); #endif #ifndef NO_SHA256 if ( (ret = hmac_sha256_test()) != 0) - err_sys("HMAC-SHA256 test failed!\n", ret); + return err_sys("HMAC-SHA256 test failed!\n", ret); else printf( "HMAC-SHA256 test passed!\n"); #endif #ifdef CYASSL_SHA384 if ( (ret = hmac_sha384_test()) != 0) - err_sys("HMAC-SHA384 test failed!\n", ret); + return err_sys("HMAC-SHA384 test failed!\n", ret); else printf( "HMAC-SHA384 test passed!\n"); #endif #ifdef CYASSL_SHA512 if ( (ret = hmac_sha512_test()) != 0) - err_sys("HMAC-SHA512 test failed!\n", ret); + return err_sys("HMAC-SHA512 test failed!\n", ret); else printf( "HMAC-SHA512 test passed!\n"); #endif #ifdef HAVE_BLAKE2 if ( (ret = hmac_blake2b_test()) != 0) - err_sys("HMAC-BLAKE2 test failed!\n", ret); + return err_sys("HMAC-BLAKE2 test failed!\n", ret); else printf( "HMAC-BLAKE2 test passed!\n"); #endif #ifdef HAVE_HKDF if ( (ret = hkdf_test()) != 0) - err_sys("HMAC-KDF test failed!\n", ret); + return err_sys("HMAC-KDF test failed!\n", ret); else printf( "HMAC-KDF test passed!\n"); #endif @@ -345,76 +343,76 @@ void ctaocrypt_test(void* args) #ifdef HAVE_AESGCM if ( (ret = gmac_test()) != 0) - err_sys("GMAC test passed!\n", ret); + return err_sys("GMAC test passed!\n", ret); else printf( "GMAC test passed!\n"); #endif #ifndef NO_RC4 if ( (ret = arc4_test()) != 0) - err_sys("ARC4 test failed!\n", ret); + return err_sys("ARC4 test failed!\n", ret); else printf( "ARC4 test passed!\n"); #endif #ifndef NO_HC128 if ( (ret = hc128_test()) != 0) - err_sys("HC-128 test failed!\n", ret); + return err_sys("HC-128 test failed!\n", ret); else printf( "HC-128 test passed!\n"); #endif #ifndef NO_RABBIT if ( (ret = rabbit_test()) != 0) - err_sys("Rabbit test failed!\n", ret); + return err_sys("Rabbit test failed!\n", ret); else printf( "Rabbit test passed!\n"); #endif #ifdef HAVE_CHACHA if ( (ret = chacha_test()) != 0) - err_sys("Chacha test failed!\n", ret); + return err_sys("Chacha test failed!\n", ret); else printf( "Chacha test passed!\n"); #endif #ifndef NO_DES3 if ( (ret = des_test()) != 0) - err_sys("DES test failed!\n", ret); + return err_sys("DES test failed!\n", ret); else printf( "DES test passed!\n"); #endif #ifndef NO_DES3 if ( (ret = des3_test()) != 0) - err_sys("DES3 test failed!\n", ret); + return err_sys("DES3 test failed!\n", ret); else printf( "DES3 test passed!\n"); #endif #ifndef NO_AES if ( (ret = aes_test()) != 0) - err_sys("AES test failed!\n", ret); + return err_sys("AES test failed!\n", ret); else printf( "AES test passed!\n"); #ifdef HAVE_POLY1305 if ( (ret = poly1305_test()) != 0) - err_sys("POLY1305 test failed!\n", ret); + return err_sys("POLY1305 test failed!\n", ret); else printf( "POLY1305 test passed!\n"); #endif #ifdef HAVE_AESGCM if ( (ret = aesgcm_test()) != 0) - err_sys("AES-GCM test failed!\n", ret); + return err_sys("AES-GCM test failed!\n", ret); else printf( "AES-GCM test passed!\n"); #endif #ifdef HAVE_AESCCM if ( (ret = aesccm_test()) != 0) - err_sys("AES-CCM test failed!\n", ret); + return err_sys("AES-CCM test failed!\n", ret); else printf( "AES-CCM test passed!\n"); #endif @@ -422,59 +420,59 @@ void ctaocrypt_test(void* args) #ifdef HAVE_CAMELLIA if ( (ret = camellia_test()) != 0) - err_sys("CAMELLIA test failed!\n", ret); + return err_sys("CAMELLIA test failed!\n", ret); else printf( "CAMELLIA test passed!\n"); #endif if ( (ret = random_test()) != 0) - err_sys("RANDOM test failed!\n", ret); + return err_sys("RANDOM test failed!\n", ret); else printf( "RANDOM test passed!\n"); #ifndef NO_RSA if ( (ret = rsa_test()) != 0) - err_sys("RSA test failed!\n", ret); + return err_sys("RSA test failed!\n", ret); else printf( "RSA test passed!\n"); #endif #ifndef NO_DH if ( (ret = dh_test()) != 0) - err_sys("DH test failed!\n", ret); + return err_sys("DH test failed!\n", ret); else printf( "DH test passed!\n"); #endif #ifndef NO_DSA if ( (ret = dsa_test()) != 0) - err_sys("DSA test failed!\n", ret); + return err_sys("DSA test failed!\n", ret); else printf( "DSA test passed!\n"); #endif #ifndef NO_PWDBASED if ( (ret = pwdbased_test()) != 0) - err_sys("PWDBASED test failed!\n", ret); + return err_sys("PWDBASED test failed!\n", ret); else printf( "PWDBASED test passed!\n"); #endif #ifdef OPENSSL_EXTRA if ( (ret = openssl_test()) != 0) - err_sys("OPENSSL test failed!\n", ret); + return err_sys("OPENSSL test failed!\n", ret); else printf( "OPENSSL test passed!\n"); #endif #ifdef HAVE_ECC if ( (ret = ecc_test()) != 0) - err_sys("ECC test failed!\n", ret); + return err_sys("ECC test failed!\n", ret); else printf( "ECC test passed!\n"); #ifdef HAVE_ECC_ENCRYPT if ( (ret = ecc_encrypt_test()) != 0) - err_sys("ECC Enc test failed!\n", ret); + return err_sys("ECC Enc test failed!\n", ret); else printf( "ECC Enc test passed!\n"); #endif @@ -482,19 +480,19 @@ void ctaocrypt_test(void* args) #ifdef HAVE_LIBZ if ( (ret = compress_test()) != 0) - err_sys("COMPRESS test failed!\n", ret); + return err_sys("COMPRESS test failed!\n", ret); else printf( "COMPRESS test passed!\n"); #endif #ifdef HAVE_PKCS7 if ( (ret = pkcs7enveloped_test()) != 0) - err_sys("PKCS7enveloped test failed!\n", ret); + return err_sys("PKCS7enveloped test failed!\n", ret); else printf( "PKCS7enveloped test passed!\n"); if ( (ret = pkcs7signed_test()) != 0) - err_sys("PKCS7signed test failed!\n", ret); + return err_sys("PKCS7signed test failed!\n", ret); else printf( "PKCS7signed test passed!\n"); #endif @@ -538,8 +536,10 @@ static int OpenNitroxDevice(int dma_mode,int dev_id) #ifdef HAVE_CAVIUM int ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID); - if (ret != 0) + if (ret != 0) { err_sys("Cavium OpenNitroxDevice failed", -1236); + return -1236; + } #endif /* HAVE_CAVIUM */ args.argc = argc; @@ -3004,9 +3004,11 @@ int rsa_test(void) #else file = fopen(clientKey, "rb"); - if (!file) + if (!file) { err_sys("can't open ./certs/client-key.der, " "Please run from CyaSSL home dir", -40); + return -40; + } bytes = fread(tmp, 1, FOURK_BUF, file); fclose(file); @@ -4616,6 +4618,47 @@ int ecc_test(void) } } + +#ifdef CYASSL_KEY_GEN + { + int derSz, pemSz; + byte der[FOURK_BUF]; + byte pem[FOURK_BUF]; + FILE* keyFile; + FILE* pemFile; + + derSz = EccKeyToDer(&userB, der, FOURK_BUF); + if (derSz < 0) { + return -1024; + } + + keyFile = fopen("./ecc-key.der", "wb"); + if (!keyFile) { + return -1025; + } + ret = (int)fwrite(der, 1, derSz, keyFile); + fclose(keyFile); + if (ret != derSz) { + return -1026; + } + + pemSz = DerToPem(der, derSz, pem, FOURK_BUF, ECC_PRIVATEKEY_TYPE); + if (pemSz < 0) { + return -1027; + } + + pemFile = fopen("./ecc-key.pem", "wb"); + if (!pemFile) { + return -1028; + } + ret = (int)fwrite(pem, 1, pemSz, pemFile); + fclose(pemFile); + if (ret != pemSz) { + return -1029; + } + } +#endif /* CYASSL_KEY_GEN */ + ecc_free(&pubKey); ecc_free(&userB); ecc_free(&userA); @@ -4915,6 +4958,7 @@ int pkcs7enveloped_test(void) free(privKey); err_sys("can't open ./certs/client-cert.der, " "Please run from CyaSSL home dir", -42); + return -42; } certSz = fread(cert, 1, FOURK_BUF, certFile); @@ -4926,6 +4970,7 @@ int pkcs7enveloped_test(void) free(privKey); err_sys("can't open ./certs/client-key.der, " "Please run from CyaSSL home dir", -43); + return -43; } privKeySz = fread(privKey, 1, FOURK_BUF, keyFile); @@ -5047,6 +5092,7 @@ int pkcs7signed_test(void) free(out); err_sys("can't open ./certs/client-cert.der, " "Please run from CyaSSL home dir", -44); + return -44; } certDerSz = (word32)fread(certDer, 1, FOURK_BUF, file); fclose(file); @@ -5058,6 +5104,7 @@ int pkcs7signed_test(void) free(out); err_sys("can't open ./certs/client-key.der, " "Please run from CyaSSL home dir", -45); + return -45; } keyDerSz = (word32)fread(keyDer, 1, FOURK_BUF, file); fclose(file); diff --git a/cyassl/ctaocrypt/asn.h b/cyassl/ctaocrypt/asn.h index 25d6fbc06..ff0c3f6b4 100644 --- a/cyassl/ctaocrypt/asn.h +++ b/cyassl/ctaocrypt/asn.h @@ -118,6 +118,8 @@ enum Misc_ASN { PKCS12 = 12, /* PKCS #12 */ MAX_UNICODE_SZ = 256, ASN_BOOL_SIZE = 2, /* including type */ + ASN_ECC_HEADER_SZ = 2, /* String type + 1 byte len */ + ASN_ECC_CONTEXT_SZ = 2, /* Content specific type + 1 byte len */ SHA_SIZE = 20, RSA_INTS = 8, /* RSA ints in private key */ MIN_DATE_SIZE = 13, diff --git a/cyassl/ctaocrypt/asn_public.h b/cyassl/ctaocrypt/asn_public.h index 34c899dc0..eca28db23 100644 --- a/cyassl/ctaocrypt/asn_public.h +++ b/cyassl/ctaocrypt/asn_public.h @@ -178,6 +178,7 @@ CYASSL_API int SetDatesBuffer(Cert*, const byte*, int); /* private key helpers */ CYASSL_API int EccPrivateKeyDecode(const byte* input,word32* inOutIdx, ecc_key*,word32); + CYASSL_API int EccKeyToDer(ecc_key*, byte* output, word32 inLen); #endif diff --git a/cyassl/ctaocrypt/error-crypt.h b/cyassl/ctaocrypt/error-crypt.h index 31489958d..7ec1e96a1 100644 --- a/cyassl/ctaocrypt/error-crypt.h +++ b/cyassl/ctaocrypt/error-crypt.h @@ -128,6 +128,7 @@ enum { RNG_FAILURE_E = -199, /* RNG Failed, Reinitialize */ HMAC_MIN_KEYLEN_E = -200, /* FIPS Mode HMAC Minimum Key Length error */ RSA_PAD_E = -201, /* RSA Padding Error */ + LENGTH_ONLY_E = -202, /* Returning output length only */ MIN_CODE_E = -300 /* errors -101 - -299 */ };