From a7bcca84c3bb714c6810dbe641ca45368d3e1334 Mon Sep 17 00:00:00 2001 From: toddouska Date: Thu, 14 Nov 2013 15:00:22 -0800 Subject: [PATCH] add ecdsa cert signing --- .gitignore | 2 + ctaocrypt/src/asn.c | 95 ++++++++++++++++++++++------ ctaocrypt/test/test.c | 114 ++++++++++++++++++++++++++++++++-- cyassl/ctaocrypt/asn.h | 3 - cyassl/ctaocrypt/asn_public.h | 14 ++++- src/ssl.c | 87 +++++++++++++------------- 6 files changed, 243 insertions(+), 72 deletions(-) diff --git a/.gitignore b/.gitignore index e4c4d2d48..9ef608923 100644 --- a/.gitignore +++ b/.gitignore @@ -46,6 +46,8 @@ testsuite/*.pem testsuite/*.raw cert.der cert.pem +certecc.der +certecc.pem othercert.der othercert.pem key.der diff --git a/ctaocrypt/src/asn.c b/ctaocrypt/src/asn.c index 65ff0a660..13f0b0c87 100644 --- a/ctaocrypt/src/asn.c +++ b/ctaocrypt/src/asn.c @@ -2241,7 +2241,7 @@ static word32 SetAlgoID(int algoOID, byte* output, int type) static const byte md2AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x02, 0x05, 0x00}; - /* sigTypes */ + /* RSA sigTypes */ #ifndef NO_RSA static const byte md5wRSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00}; @@ -2255,12 +2255,29 @@ static word32 SetAlgoID(int algoOID, byte* output, int type) 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00}; #endif /* NO_RSA */ - /* keyTypes */ + /* ECDSA sigTypes */ + #ifdef HAVE_ECC + static const byte shawECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d, + 0x04, 0x01, 0x05, 0x00}; + static const byte sha256wECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE,0x3d, + 0x04, 0x03, 0x02, 0x05, 0x00}; + static const byte sha384wECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE,0x3d, + 0x04, 0x03, 0x03, 0x05, 0x00}; + static const byte sha512wECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE,0x3d, + 0x04, 0x03, 0x04, 0x05, 0x00}; + #endif /* HAVE_ECC */ + + /* RSA keyType */ #ifndef NO_RSA static const byte RSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00}; #endif /* NO_RSA */ + #ifdef HAVE_ECC + static const byte ECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d, + 0x04, 0x02, 0x05, 0x00}; + #endif /* HAVE_ECC */ + int algoSz = 0; word32 idSz, seqSz; const byte* algoName = 0; @@ -2332,6 +2349,27 @@ static word32 SetAlgoID(int algoOID, byte* output, int type) algoName = sha512wRSA_AlgoID; break; #endif /* NO_RSA */ + #ifdef HAVE_ECC + case CTC_SHAwECDSA: + algoSz = sizeof(shawECDSA_AlgoID); + algoName = shawECDSA_AlgoID; + break; + + case CTC_SHA256wECDSA: + algoSz = sizeof(sha256wECDSA_AlgoID); + algoName = sha256wECDSA_AlgoID; + break; + + case CTC_SHA384wECDSA: + algoSz = sizeof(sha384wECDSA_AlgoID); + algoName = sha384wECDSA_AlgoID; + break; + + case CTC_SHA512wECDSA: + algoSz = sizeof(sha512wECDSA_AlgoID); + algoName = sha512wECDSA_AlgoID; + break; + #endif /* HAVE_ECC */ default: CYASSL_MSG("Unknown Signature Algo"); return 0; @@ -2345,6 +2383,12 @@ static word32 SetAlgoID(int algoOID, byte* output, int type) algoName = RSA_AlgoID; break; #endif /* NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + algoSz = sizeof(ECDSA_AlgoID); + algoName = ECDSA_AlgoID; + break; + #endif /* HAVE_ECC */ default: CYASSL_MSG("Unknown Key Algo"); return 0; @@ -3995,13 +4039,8 @@ static int SetName(byte* output, CertName* name) } /* encode info from cert into DER enocder format */ -static int EncodeCert( -Cert* cert, -DerCert* der, -RsaKey* rsaKey, -RNG* rng, - const byte* ntruKey, -word16 ntruSz) +static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, RNG* rng, + const byte* ntruKey, word16 ntruSz) { (void)ntruKey; (void)ntruSz; @@ -4153,12 +4192,15 @@ static int WriteCertBody(DerCert* der, byte* buffer) /* Make RSA signature from buffer (sz), write to sig (sigSz) */ static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz, - RsaKey* key, RNG* rng, int sigAlgoType) + RsaKey* rsaKey, ecc_key* eccKey, RNG* rng, + int sigAlgoType) { byte digest[SHA256_DIGEST_SIZE]; /* max size */ byte encSig[MAX_ENCODED_DIG_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ]; int encSigSz, digestSz, typeH; + (void)eccKey; + if (sigAlgoType == CTC_MD5wRSA) { Md5 md5; InitMd5(&md5); @@ -4167,7 +4209,7 @@ static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz, digestSz = MD5_DIGEST_SIZE; typeH = MD5h; } - else if (sigAlgoType == CTC_SHAwRSA) { + else if (sigAlgoType == CTC_SHAwRSA || sigAlgoType == CTC_SHAwECDSA) { Sha sha; InitSha(&sha); ShaUpdate(&sha, buffer, sz); @@ -4175,7 +4217,7 @@ static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz, digestSz = SHA_DIGEST_SIZE; typeH = SHAh; } - else if (sigAlgoType == CTC_SHA256wRSA) { + else if (sigAlgoType == CTC_SHA256wRSA || sigAlgoType == CTC_SHA256wECDSA) { Sha256 sha256; InitSha256(&sha256); Sha256Update(&sha256, buffer, sz); @@ -4186,9 +4228,23 @@ static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz, else return ALGO_ID_E; - /* signature */ - encSigSz = EncodeSignature(encSig, digest, digestSz, typeH); - return RsaSSL_Sign(encSig, encSigSz, sig, sigSz, key, rng); + if (rsaKey) { + /* signature */ + encSigSz = EncodeSignature(encSig, digest, digestSz, typeH); + return RsaSSL_Sign(encSig, encSigSz, sig, sigSz, rsaKey, rng); + } +#ifdef HAVE_ECC + else if (eccKey) { + word32 outSz = sigSz; + int ret = ecc_sign_hash(digest, digestSz, sig, &outSz, rng, eccKey); + + if (ret != 0) + return ret; + return outSz; + } +#endif /* HAVE_ECC */ + + return ALGO_ID_E; } @@ -4257,7 +4313,8 @@ int MakeNtruCert(Cert* cert, byte* derBuffer, word32 derSz, #endif /* HAVE_NTRU */ -int SignCert(Cert* cert, byte* buffer, word32 buffSz, RsaKey* key, RNG* rng) +int SignCert(Cert* cert, byte* buffer, word32 buffSz, RsaKey* rsaKey, + ecc_key* eccKey, RNG* rng) { byte sig[MAX_ENCODED_SIG_SZ]; int sigSz; @@ -4266,8 +4323,8 @@ int SignCert(Cert* cert, byte* buffer, word32 buffSz, RsaKey* key, RNG* rng) if (bodySz < 0) return bodySz; - sigSz = MakeSignature(buffer, bodySz, sig, sizeof(sig), key, rng, - cert->sigType); + sigSz = MakeSignature(buffer, bodySz, sig, sizeof(sig), rsaKey, eccKey, + rng, cert->sigType); if (sigSz < 0) return sigSz; @@ -4285,7 +4342,7 @@ int MakeSelfCert(Cert* cert, byte* buffer, word32 buffSz, RsaKey* key, RNG* rng) if (ret < 0) return ret; - return SignCert(cert, buffer, buffSz, key, rng); + return SignCert(cert, buffer, buffSz, key, NULL, rng); } diff --git a/ctaocrypt/test/test.c b/ctaocrypt/test/test.c index c62b4daeb..928b63d21 100644 --- a/ctaocrypt/test/test.c +++ b/ctaocrypt/test/test.c @@ -2487,17 +2487,27 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) #ifdef CYASSL_CERT_GEN static const char* caKeyFile = "a:\\certs\\ca-key.der"; static const char* caCertFile = "a:\\certs\\ca-cert.pem"; + #ifdef HAVE_ECC + static const char* eccCaKeyFile = "a:\\certs\\ecc-key.der"; + static const char* eccCaCertFile = "a:\\certs\\server-ecc.pem"; + #endif #endif #elif defined(CYASSL_MKD_SHELL) static char* clientKey = "certs/client-key.der"; static char* clientCert = "certs/client-cert.der"; - void set_clientKey(char *key) { clientKey = key ; } /* set by shell command */ - void set_clientCert(char *cert) { clientCert = cert ; } /* set by shell command */ + void set_clientKey(char *key) { clientKey = key ; } + void set_clientCert(char *cert) { clientCert = cert ; } #ifdef CYASSL_CERT_GEN static char* caKeyFile = "certs/ca-key.der"; static char* caCertFile = "certs/ca-cert.pem"; - void set_caKeyFile (char * key) { caKeyFile = key ; } /* set by shell command */ - void set_caCertFile(char * cert) { caCertFile = cert ; } /* set by shell command */ + void set_caKeyFile (char * key) { caKeyFile = key ; } + void set_caCertFile(char * cert) { caCertFile = cert ; } + #ifdef HAVE_ECC + static const char* eccCaKeyFile = "certs/ecc-key.der"; + static const char* eccCaCertFile = "certs/server-ecc.pem"; + void set_eccCaKeyFile (char * key) { eccCaKeyFile = key ; } + void set_eccCaCertFile(char * cert) { eccCaCertFile = cert ; } + #endif #endif #else static const char* clientKey = "./certs/client-key.der"; @@ -2505,6 +2515,10 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) #ifdef CYASSL_CERT_GEN static const char* caKeyFile = "./certs/ca-key.der"; static const char* caCertFile = "./certs/ca-cert.pem"; + #ifdef HAVE_ECC + static const char* eccCaKeyFile = "./certs/ecc-key.der"; + static const char* eccCaCertFile = "./certs/server-ecc.pem"; + #endif #endif #endif #endif @@ -2788,7 +2802,7 @@ int rsa_test(void) if (certSz < 0) return -407; - certSz = SignCert(&myCert, derCert, FOURK_BUF, &caKey, &rng); + certSz = SignCert(&myCert, derCert, FOURK_BUF, &caKey, NULL, &rng); if (certSz < 0) return -408; @@ -2820,6 +2834,94 @@ int rsa_test(void) free(derCert); FreeRsaKey(&caKey); } +#ifdef HAVE_ECC + /* ECC CA style */ + { + ecc_key caKey; + Cert myCert; + byte* derCert; + byte* pem; + FILE* derFile; + FILE* pemFile; + int certSz; + int pemSz; + size_t bytes3; + word32 idx3 = 0; + FILE* file3 ; +#ifdef CYASSL_TEST_CERT + DecodedCert decode; +#endif + + derCert = (byte*)malloc(FOURK_BUF); + if (derCert == NULL) + return -5311; + pem = (byte*)malloc(FOURK_BUF); + if (pem == NULL) + return -5312; + + file3 = fopen(eccCaKeyFile, "rb"); + + if (!file3) + return -5412; + + bytes3 = fread(tmp, 1, FOURK_BUF, file3); + fclose(file3); + + ecc_init(&caKey); + ret = EccPrivateKeyDecode(tmp, &idx3, &caKey, (word32)bytes3); + if (ret != 0) return -5413; + + InitCert(&myCert); + myCert.sigType = CTC_SHA256wECDSA; + + strncpy(myCert.subject.country, "US", CTC_NAME_SIZE); + strncpy(myCert.subject.state, "OR", CTC_NAME_SIZE); + strncpy(myCert.subject.locality, "Portland", CTC_NAME_SIZE); + strncpy(myCert.subject.org, "wolfSSL", CTC_NAME_SIZE); + strncpy(myCert.subject.unit, "Development", CTC_NAME_SIZE); + strncpy(myCert.subject.commonName, "www.wolfssl.com", CTC_NAME_SIZE); + strncpy(myCert.subject.email, "info@wolfssl.com", CTC_NAME_SIZE); + + ret = SetIssuer(&myCert, eccCaCertFile); + if (ret < 0) + return -5405; + + certSz = MakeCert(&myCert, derCert, FOURK_BUF, &key, &rng); + if (certSz < 0) + return -5407; + + certSz = SignCert(&myCert, derCert, FOURK_BUF, NULL, &caKey, &rng); + if (certSz < 0) + return -5408; + +#ifdef CYASSL_TEST_CERT + InitDecodedCert(&decode, derCert, certSz, 0); + ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); + if (ret != 0) + return -5409; + FreeDecodedCert(&decode); +#endif + + derFile = fopen("./certecc.der", "wb"); + if (!derFile) + return -5410; + ret = (int)fwrite(derCert, certSz, 1, derFile); + fclose(derFile); + + pemSz = DerToPem(derCert, certSz, pem, FOURK_BUF, CERT_TYPE); + if (pemSz < 0) + return -5411; + + pemFile = fopen("./certecc.pem", "wb"); + if (!pemFile) + return -5412; + ret = (int)fwrite(pem, pemSz, 1, pemFile); + fclose(pemFile); + free(pem); + free(derCert); + ecc_free(&caKey); + } +#endif /* HAVE_ECC */ #ifdef HAVE_NTRU { RsaKey caKey; @@ -2900,7 +3002,7 @@ int rsa_test(void) if (certSz < 0) return -456; - certSz = SignCert(&myCert, derCert, FOURK_BUF, &caKey, &rng); + certSz = SignCert(&myCert, derCert, FOURK_BUF, &caKey, NULL, &rng); if (certSz < 0) return -457; diff --git a/cyassl/ctaocrypt/asn.h b/cyassl/ctaocrypt/asn.h index 70dbfbe09..737f594f1 100644 --- a/cyassl/ctaocrypt/asn.h +++ b/cyassl/ctaocrypt/asn.h @@ -391,9 +391,6 @@ CYASSL_LOCAL int ValidateDate(const byte* date, byte format, int dateType); mp_int* s); CYASSL_LOCAL int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s); - /* private key helpers */ - CYASSL_API int EccPrivateKeyDecode(const byte* input,word32* inOutIdx, - ecc_key*,word32); #endif #ifdef CYASSL_CERT_GEN diff --git a/cyassl/ctaocrypt/asn_public.h b/cyassl/ctaocrypt/asn_public.h index f824fbb36..a9d5fb7a9 100644 --- a/cyassl/ctaocrypt/asn_public.h +++ b/cyassl/ctaocrypt/asn_public.h @@ -24,6 +24,7 @@ #define CTAO_CRYPT_ASN_PUBLIC_H #include +#include #ifdef CYASSL_CERT_GEN #include #endif @@ -63,6 +64,10 @@ enum Ctc_SigType { #ifdef CYASSL_CERT_GEN +#ifndef HAVE_ECC + typedef struct ecc_key ecc_key; +#endif + enum Ctc_Misc { CTC_NAME_SIZE = 64, CTC_DATE_SIZE = 32, @@ -121,7 +126,8 @@ typedef struct Cert { */ CYASSL_API void InitCert(Cert*); CYASSL_API int MakeCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, RNG*); -CYASSL_API int SignCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, RNG*); +CYASSL_API int SignCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, + ecc_key*, RNG*); CYASSL_API int MakeSelfCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, RNG*); CYASSL_API int SetIssuer(Cert*, const char*); @@ -147,6 +153,12 @@ CYASSL_API int SetDatesBuffer(Cert*, const byte*, int); word32 outputSz, int type); #endif +#ifdef HAVE_ECC + /* private key helpers */ + CYASSL_API int EccPrivateKeyDecode(const byte* input,word32* inOutIdx, + ecc_key*,word32); +#endif + #ifdef __cplusplus } /* extern "C" */ diff --git a/src/ssl.c b/src/ssl.c index f17449376..7da7f2224 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1045,6 +1045,50 @@ int CyaSSL_CertManagerUnloadCAs(CYASSL_CERT_MANAGER* cm) } +/* Return bytes written to buff or < 0 for error */ +int CyaSSL_KeyPemToDer(const unsigned char* pem, int pemSz, unsigned char* buff, + int buffSz, const char* pass) +{ + EncryptedInfo info; + int eccKey = 0; + int ret; + buffer der; + + (void)pass; + + CYASSL_ENTER("CyaSSL_KeyPemToDer"); + + if (pem == NULL || buff == NULL || buffSz <= 0) { + CYASSL_MSG("Bad pem der args"); + return BAD_FUNC_ARG; + } + + info.set = 0; + info.ctx = NULL; + info.consumed = 0; + der.buffer = NULL; + + ret = PemToDer(pem, pemSz, PRIVATEKEY_TYPE, &der, NULL, &info, &eccKey); + if (ret < 0) { + CYASSL_MSG("Bad Pem To Der"); + } + else { + if (der.length <= (word32)buffSz) { + XMEMCPY(buff, der.buffer, der.length); + ret = der.length; + } + else { + CYASSL_MSG("Bad der length"); + ret = BAD_FUNC_ARG; + } + } + + XFREE(der.buffer, NULL, DYNAMIC_TYPE_KEY); + + return ret; +} + + #endif /* !NO_CERTS */ @@ -10430,49 +10474,6 @@ static int initGlobalRNG = 0; -/* Return bytes written to buff or < 0 for error */ -int CyaSSL_KeyPemToDer(const unsigned char* pem, int pemSz, unsigned char* buff, - int buffSz, const char* pass) -{ - EncryptedInfo info; - int eccKey = 0; - int ret; - buffer der; - - (void)pass; - - CYASSL_ENTER("CyaSSL_KeyPemToDer"); - - if (pem == NULL || buff == NULL || buffSz <= 0) { - CYASSL_MSG("Bad pem der args"); - return BAD_FUNC_ARG; - } - - info.set = 0; - info.ctx = NULL; - info.consumed = 0; - der.buffer = NULL; - - ret = PemToDer(pem, pemSz, PRIVATEKEY_TYPE, &der, NULL, &info, &eccKey); - if (ret < 0) { - CYASSL_MSG("Bad Pem To Der"); - } - else { - if (der.length <= (word32)buffSz) { - XMEMCPY(buff, der.buffer, der.length); - ret = der.length; - } - else { - CYASSL_MSG("Bad der length"); - ret = BAD_FUNC_ARG; - } - } - - XFREE(der.buffer, NULL, DYNAMIC_TYPE_KEY); - - return ret; -} - /* Load RSA from Der, SSL_SUCCESS on success < 0 on error */ int CyaSSL_RSA_LoadDer(CYASSL_RSA* rsa, const unsigned char* der, int derSz)