From 4beda52dcd83543e6363f96305961203231219ce Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Thu, 25 May 2017 09:04:05 +1000 Subject: [PATCH 1/6] Ed25519 Certificates --- wolfcrypt/src/asn.c | 839 +++++++++++++++++++++++++++------ wolfcrypt/src/ed25519.c | 29 +- wolfssl/wolfcrypt/asn.h | 19 +- wolfssl/wolfcrypt/asn_public.h | 43 +- wolfssl/wolfcrypt/ed25519.h | 17 +- wolfssl/wolfcrypt/types.h | 1 + 6 files changed, 783 insertions(+), 165 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index f615728d8..e3e647e07 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -87,6 +87,10 @@ ASN Options: #include #endif +#ifdef HAVE_ED25519 + #include +#endif + #ifndef NO_RSA #include #endif @@ -1113,6 +1117,9 @@ static const byte hashSha512hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 3}; static const byte sigSha384wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 3}; static const byte sigSha512wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 4}; #endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + static const byte sigEd25519Oid[] = {43, 101, 112}; +#endif /* HAVE_ED25519 */ /* keyType */ #ifndef NO_DSA @@ -1127,6 +1134,9 @@ static const byte hashSha512hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 3}; #ifdef HAVE_ECC static const byte keyEcdsaOid[] = {42, 134, 72, 206, 61, 2, 1}; #endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + static const byte keyEd25519Oid[] = {43, 101, 112}; +#endif /* HAVE_ED25519 */ /* curveType */ #ifdef HAVE_ECC @@ -1292,6 +1302,12 @@ static const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(sigSha512wEcdsaOid); break; #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case CTC_ED25519: + oid = sigEd25519Oid; + *oidSz = sizeof(sigEd25519Oid); + break; + #endif default: break; } @@ -1323,6 +1339,12 @@ static const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(keyEcdsaOid); break; #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + oid = keyEd25519Oid; + *oidSz = sizeof(keyEd25519Oid); + break; + #endif /* HAVE_ED25519 */ default: break; } @@ -2140,6 +2162,41 @@ int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der) } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + { + int ret = 0; + word32 keyIdx = 0; + ed25519_key key_pair; + + if (der->keyOID == ED25519k) { + if ((ret = wc_ed25519_init(&key_pair)) == 0 && + wc_Ed25519PrivateKeyDecode(key, &keyIdx, &key_pair, keySz) + == 0) { + WOLFSSL_MSG("Checking ED25519 key pair"); + keyIdx = 0; + if ((ret = wc_ed25519_import_public(der->publicKey, + der->pubKeySize, &key_pair)) == 0) { + /* public and private extracted successfuly no check if is + * a pair and also do sanity checks on key. wc_ecc_check_key + * checks that private * base generator equals pubkey */ + if ((ret = wc_ed25519_check_key(&key_pair)) == 0) { + /* found a match */ + wc_ed25519_free(&key_pair); + return 1; + } + + } + } + wc_ed25519_free(&key_pair); + } + + /* error on attempt to match */ + if (ret != 0) { + return ret; + } + } + #endif + /* no match found */ return 0; } @@ -2390,6 +2447,9 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, #ifndef NO_RSA RsaKey rsa; #endif +#ifdef HAVE_ED25519 + ed25519_key ed25519; +#endif if (algoID == NULL) { return BAD_FUNC_ARG; @@ -2441,6 +2501,23 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, } } #endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + if (*algoID != RSAk && *algoId != ECDSAk) { + if (wc_ed25519_init(&ed25519) == 0) { + if (wc_Ed25519PrivateKeyDecode(key, &tmpIdx, &ed25519, keySz) + == 0) { + *algoID = ED25519k; + } + else { + WOLFSSL_MSG("Not ED25519 DER key"); + } + wc_ed25519_free(&ed25519); + } + else { + WOLFSSL_MSG("GetKeyOID wc_ed25519_init failed"); + } + } +#endif /* if flag is not set then is neither RSA or ECC key that could be * found */ @@ -3348,6 +3425,29 @@ static int GetKey(DecodedCert* cert) return ECC_CURVE_OID_E; /* key header */ + ret = CheckBitString(cert->source, &cert->srcIdx, &length, + cert->maxIdx, 1, NULL); + if (ret != 0) + return ret; + + cert->publicKey = (byte*)XMALLOC(length, cert->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (cert->publicKey == NULL) + return MEMORY_E; + XMEMCPY(cert->publicKey, &cert->source[cert->srcIdx], length); + cert->pubKeyStored = 1; + cert->pubKeySize = length; + + cert->srcIdx += length; + + return 0; + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + { + int ret; + ret = CheckBitString(cert->source, &cert->srcIdx, &length, cert->maxIdx, 1, NULL); if (ret != 0) @@ -3365,7 +3465,7 @@ static int GetKey(DecodedCert* cert) return 0; } - #endif /* HAVE_ECC */ + #endif /* HAVE_ED25519 */ default: return ASN_UNKNOWN_OID_E; } @@ -4318,7 +4418,8 @@ WOLFSSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz) byte seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */ tagSz = (type == oidHashType || - (type == oidSigType && !IsSigAlgoECDSA(algoOID)) || + (type == oidSigType && !IsSigAlgoECDSA(algoOID) && + algoOID != ED25519k) || (type == oidKeyType && algoOID == RSAk)) ? 2 : 0; algoName = OidFromId(algoOID, type, &algoSz); @@ -4436,6 +4537,12 @@ void FreeSignatureCtx(SignatureCtx* sigCtx) XFREE(sigCtx->key.ecc, sigCtx->heap, DYNAMIC_TYPE_ECC); break; #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + wc_ed25519_free(sigCtx->key.ed25519); + XFREE(sigCtx->key.ed25519, sigCtx->heap, DYNAMIC_TYPE_ED25519); + break; + #endif /* HAVE_ED25519 */ default: break; } /* switch (keyOID) */ @@ -4446,6 +4553,93 @@ void FreeSignatureCtx(SignatureCtx* sigCtx) sigCtx->state = SIG_STATE_BEGIN; } +static int HashForSignature(const byte* buf, word32 bufSz, word32 sigOID, + byte* digest, int* typeH, int* digestSz, int verify) +{ + int ret = 0; + + (void)verify; + + switch (sigOID) { + #if defined(WOLFSSL_MD2) + case CTC_MD2wRSA: + if (!verify) { + ret = HASH_TYPE_E; + WOLFSSL_MSG("MD2 not supported for signing"); + } + else if ((ret = wc_Md2Hash(buf, bufSz, digest)) == 0) { + *typeH = MD2h; + *digestSz = MD2_DIGEST_SIZE; + } + break; + #endif + #ifndef NO_MD5 + case CTC_MD5wRSA: + if ((ret = wc_Md5Hash(buf, bufSz, digest)) == 0) { + *typeH = MD5h; + *digestSz = MD5_DIGEST_SIZE; + } + break; + #endif + #ifndef NO_SHA + case CTC_SHAwRSA: + case CTC_SHAwDSA: + case CTC_SHAwECDSA: + if ((ret = wc_ShaHash(buf, bufSz, digest)) == 0) { + *typeH = SHAh; + *digestSz = SHA_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA224 + case CTC_SHA224wRSA: + case CTC_SHA224wECDSA: + if ((ret = wc_Sha224Hash(buf, bufSz, digest)) == 0) { + *typeH = SHA224h; + *digestSz = SHA224_DIGEST_SIZE; + } + break; + #endif + #ifndef NO_SHA256 + case CTC_SHA256wRSA: + case CTC_SHA256wECDSA: + if ((ret = wc_Sha256Hash(buf, bufSz, digest)) == 0) { + *typeH = SHA256h; + *digestSz = SHA256_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA384 + case CTC_SHA384wRSA: + case CTC_SHA384wECDSA: + if ((ret = wc_Sha384Hash(buf, bufSz, digest)) == 0) { + *typeH = SHA384h; + *digestSz = SHA384_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA512 + case CTC_SHA512wRSA: + case CTC_SHA512wECDSA: + if ((ret = wc_Sha512Hash(buf, bufSz, digest)) == 0) { + *typeH = SHA512h; + *digestSz = SHA512_DIGEST_SIZE; + } + break; + #endif + case CTC_ED25519: + /* Hashes done in signing operation. + * Two dependent hashes with prefixes performed. + */ + break; + default: + ret = HASH_TYPE_E; + WOLFSSL_MSG("Hash for Signature has unsupported type"); + } + + return 0; +} + /* Return codes: 0=Success, Negative (see error-crypt.h), ASN_SIG_CONFIRM_E */ static int ConfirmSignature(SignatureCtx* sigCtx, const byte* buf, word32 bufSz, @@ -4481,74 +4675,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx, case SIG_STATE_HASH: { - switch (sigOID) { - #ifndef NO_MD5 - case CTC_MD5wRSA: - if ((ret = wc_Md5Hash(buf, bufSz, sigCtx->digest)) == 0) { - sigCtx->typeH = MD5h; - sigCtx->digestSz = MD5_DIGEST_SIZE; - } - break; - #endif - #if defined(WOLFSSL_MD2) - case CTC_MD2wRSA: - if ((ret = wc_Md2Hash(buf, bufSz, sigCtx->digest)) == 0) { - sigCtx->typeH = MD2h; - sigCtx->digestSz = MD2_DIGEST_SIZE; - } - break; - #endif - #ifndef NO_SHA - case CTC_SHAwRSA: - case CTC_SHAwDSA: - case CTC_SHAwECDSA: - if ((ret = wc_ShaHash(buf, bufSz, sigCtx->digest)) == 0) { - sigCtx->typeH = SHAh; - sigCtx->digestSz = SHA_DIGEST_SIZE; - } - break; - #endif - #ifdef WOLFSSL_SHA224 - case CTC_SHA224wRSA: - case CTC_SHA224wECDSA: - if ((ret = wc_Sha224Hash(buf, bufSz, sigCtx->digest)) == 0) { - sigCtx->typeH = SHA224h; - sigCtx->digestSz = SHA224_DIGEST_SIZE; - } - break; - #endif - #ifndef NO_SHA256 - case CTC_SHA256wRSA: - case CTC_SHA256wECDSA: - if ((ret = wc_Sha256Hash(buf, bufSz, sigCtx->digest)) == 0) { - sigCtx->typeH = SHA256h; - sigCtx->digestSz = SHA256_DIGEST_SIZE; - } - break; - #endif - #ifdef WOLFSSL_SHA512 - case CTC_SHA512wRSA: - case CTC_SHA512wECDSA: - if ((ret = wc_Sha512Hash(buf, bufSz, sigCtx->digest)) == 0) { - sigCtx->typeH = SHA512h; - sigCtx->digestSz = SHA512_DIGEST_SIZE; - } - break; - #endif - #ifdef WOLFSSL_SHA384 - case CTC_SHA384wRSA: - case CTC_SHA384wECDSA: - if ((ret = wc_Sha384Hash(buf, bufSz, sigCtx->digest)) == 0) { - sigCtx->typeH = SHA384h; - sigCtx->digestSz = SHA384_DIGEST_SIZE; - } - break; - #endif - default: - ret = HASH_TYPE_E; - WOLFSSL_MSG("Verify Signature has unsupported type"); - } - + ret = HashForSignature(buf, bufSz, sigOID, sigCtx->digest, + &sigCtx->typeH, &sigCtx->digestSz, 1); if (ret != 0) { goto exit_cs; } @@ -4618,6 +4746,28 @@ static int ConfirmSignature(SignatureCtx* sigCtx, break; } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + { + sigCtx->verify = 0; + sigCtx->key.ed25519 = (ed25519_key*)XMALLOC( + sizeof(ed25519_key), sigCtx->heap, + DYNAMIC_TYPE_ED25519); + if (sigCtx->key.ed25519 == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + + if ((ret = wc_ed25519_init(sigCtx->key.ed25519)) < 0) { + goto exit_cs; + } + if ((ret = wc_ed25519_import_public(key, keySz, + sigCtx->key.ed25519)) < 0) { + WOLFSSL_MSG("ASN Key import error ED25519"); + goto exit_cs; + } + break; + } + #endif default: WOLFSSL_MSG("Verify Key type unknown"); ret = ASN_UNKNOWN_OID_E; @@ -4659,6 +4809,18 @@ static int ConfirmSignature(SignatureCtx* sigCtx, break; } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + { + ret = wc_ed25519_verify_msg(sig, sigSz, buf, bufSz, + &sigCtx->verify, sigCtx->key.ed25519); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + sigCtx->asyncDev = &sigCtx->key.ecc->asyncDev; + #endif + break; + } + #endif default: break; } /* switch (keyOID) */ @@ -4724,6 +4886,19 @@ static int ConfirmSignature(SignatureCtx* sigCtx, break; } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + { + if (sigCtx->verify == 1) { + ret = 0; + } + else { + WOLFSSL_MSG("ED25519 Verify didn't match"); + ret = ASN_SIG_CONFIRM_E; + } + break; + } + #endif /* HAVE_ED25519 */ default: break; } /* switch (keyOID) */ @@ -7106,6 +7281,110 @@ int wc_EccPublicKeyToDer(ecc_key* key, byte* output, word32 inLen, return SetEccPublicKey(output, key, with_AlgCurve); } #endif /* HAVE_ECC && (WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN) */ +#if defined(HAVE_ED25519) && (defined(WOLFSSL_CERT_GEN) || \ + defined(WOLFSSL_KEY_GEN)) + +/* Write a public ECC key to output */ +static int SetEd25519PublicKey(byte* output, ed25519_key* key, int with_header) +{ + byte bitString[1 + MAX_LENGTH_SZ + 1]; + int algoSz; + int bitStringSz; + int idx; + word32 pubSz = ED25519_PUB_KEY_SIZE; +#ifdef WOLFSSL_SMALL_STACK + byte* algo = NULL; + byte* pub = NULL; +#else + byte algo[MAX_ALGO_SZ]; + byte pub[ED25519_PUB_KEY_SIZE]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + pub = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pub == NULL) + return MEMORY_E; +#endif + + int ret = wc_ed25519_export_public(key, pub, &pubSz); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + /* headers */ + if (with_header) { +#ifdef WOLFSSL_SMALL_STACK + algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (algo == NULL) { + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + algoSz = SetAlgoID(ED25519k, algo, oidKeyType, 0); + + bitStringSz = SetBitString(pubSz, 0, bitString); + + idx = SetSequence(pubSz + bitStringSz + algoSz, output); + /* algo */ + XMEMCPY(output + idx, algo, algoSz); + idx += algoSz; + /* bit string */ + XMEMCPY(output + idx, bitString, bitStringSz); + idx += bitStringSz; + } + else + idx = 0; + + /* pub */ + XMEMCPY(output + idx, pub, pubSz); + idx += pubSz; + +#ifdef WOLFSSL_SMALL_STACK + if (with_header) { + XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return idx; +} + +int wc_Ed25519PublicKeyToDer(ed25519_key* key, byte* output, word32 inLen, + int withAlg) +{ + word32 infoSz = 0; + word32 keySz = 0; + int ret; + + if (output == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + if (withAlg) { + /* buffer space for algorithm */ + infoSz += MAX_SEQ_SZ; + infoSz += MAX_ALGO_SZ; + + /* buffer space for public key sequence */ + infoSz += MAX_SEQ_SZ; + infoSz += TRAILING_ZERO; + } + + if ((ret = wc_ed25519_export_public(key, output, &keySz)) != BUFFER_E) { + WOLFSSL_MSG("Error in getting ECC public key size"); + return ret; + } + + if (inLen < keySz + infoSz) { + return BUFFER_E; + } + + return SetEd25519PublicKey(output, key, withAlg); +} +#endif /* HAVE_ED25519 && (WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN) */ #if defined(WOLFSSL_CERT_GEN) && !defined(NO_RSA) static INLINE byte itob(int number) @@ -7866,13 +8145,15 @@ int SetName(byte* output, word32 outputSz, CertName* name) /* encode info from cert into DER encoded format */ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, - WC_RNG* rng, const byte* ntruKey, word16 ntruSz) + WC_RNG* rng, const byte* ntruKey, word16 ntruSz, + ed25519_key* ed25519Key) { int ret; (void)eccKey; (void)ntruKey; (void)ntruSz; + (void)ed25519Key; if (cert == NULL || der == NULL || rng == NULL) return BAD_FUNC_ARG; @@ -7916,6 +8197,16 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, } #endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + if (cert->keyType == ED25519_KEY) { + if (ed25519Key == NULL) + return PUBLIC_KEY_E; + der->publicKeySz = SetEd25519PublicKey(der->publicKey, ed25519Key, 1); + if (der->publicKeySz <= 0) + return PUBLIC_KEY_E; + } +#endif + #ifdef HAVE_NTRU if (cert->keyType == NTRU_KEY) { word32 rc; @@ -8174,8 +8465,8 @@ static int WriteCertBody(DerCert* der, byte* buffer) /* Make RSA signature from buffer (sz), write to sig (sigSz) */ static int MakeSignature(CertSignCtx* certSignCtx, const byte* buffer, int sz, - byte* sig, int sigSz, RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng, - int sigAlgoType, void* heap) + byte* sig, int sigSz, RsaKey* rsaKey, ecc_key* eccKey, + ed25519_key* ed25519Key, WC_RNG* rng, int sigAlgoType, void* heap) { int digestSz = 0, typeH = 0, ret = 0; @@ -8187,6 +8478,7 @@ static int MakeSignature(CertSignCtx* certSignCtx, const byte* buffer, int sz, (void)sigSz; (void)rsaKey; (void)eccKey; + (void)ed25519Key; (void)rng; switch (certSignCtx->state) { @@ -8200,65 +8492,8 @@ static int MakeSignature(CertSignCtx* certSignCtx, const byte* buffer, int sz, ret = MEMORY_E; goto exit_ms; } - switch (sigAlgoType) { - #ifndef NO_MD5 - case CTC_MD5wRSA: - if ((ret = wc_Md5Hash(buffer, sz, certSignCtx->digest)) == 0) { - typeH = MD5h; - digestSz = MD5_DIGEST_SIZE; - } - break; - #endif - #ifndef NO_SHA - case CTC_SHAwRSA: - case CTC_SHAwECDSA: - if ((ret = wc_ShaHash(buffer, sz, certSignCtx->digest)) == 0) { - typeH = SHAh; - digestSz = SHA_DIGEST_SIZE; - } - break; - #endif - #ifdef WOLFSSL_SHA224 - case CTC_SHA224wRSA: - case CTC_SHA224wECDSA: - if ((ret = wc_Sha224Hash(buffer, sz, certSignCtx->digest)) == 0) { - typeH = SHA224h; - digestSz = SHA224_DIGEST_SIZE; - } - break; - #endif - #ifndef NO_SHA256 - case CTC_SHA256wRSA: - case CTC_SHA256wECDSA: - if ((ret = wc_Sha256Hash(buffer, sz, certSignCtx->digest)) == 0) { - typeH = SHA256h; - digestSz = SHA256_DIGEST_SIZE; - } - break; - #endif - #ifdef WOLFSSL_SHA384 - case CTC_SHA384wRSA: - case CTC_SHA384wECDSA: - if ((ret = wc_Sha384Hash(buffer, sz, certSignCtx->digest)) == 0) { - typeH = SHA384h; - digestSz = SHA384_DIGEST_SIZE; - } - break; - #endif - #ifdef WOLFSSL_SHA512 - case CTC_SHA512wRSA: - case CTC_SHA512wECDSA: - if ((ret = wc_Sha512Hash(buffer, sz, certSignCtx->digest)) == 0) { - typeH = SHA512h; - digestSz = SHA512_DIGEST_SIZE; - } - break; - #endif - default: - WOLFSSL_MSG("MakeSignautre called with unsupported type"); - ret = ALGO_ID_E; - } - + ret = HashForSignature(buffer, sz, sigAlgoType, certSignCtx->digest, + &typeH, &digestSz, 0); /* set next state, since WC_PENDING rentry for these are not "call again" */ certSignCtx->state = CERTSIGN_STATE_ENCODE; if (ret != 0) { @@ -8304,6 +8539,16 @@ static int MakeSignature(CertSignCtx* certSignCtx, const byte* buffer, int sz, ret = outSz; } #endif /* HAVE_ECC */ + + #ifdef HAVE_ED25519 + if (!rsaKey && !eccKey && ed25519Key) { + word32 outSz = sigSz; + + ret = wc_ed25519_sign_msg(buffer, sz, sig, &outSz, ed25519Key); + if (ret == 0) + ret = outSz; + } + #endif /* HAVE_ECC */ break; } @@ -8357,7 +8602,8 @@ static int AddSignature(byte* buffer, int bodySz, const byte* sig, int sigSz, /* Make an x509 Certificate v3 any key type from cert input, write to buffer */ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng, - const byte* ntruKey, word16 ntruSz) + const byte* ntruKey, word16 ntruSz, + ed25519_key* ed25519Key) { int ret; #ifdef WOLFSSL_SMALL_STACK @@ -8366,7 +8612,8 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, DerCert der[1]; #endif - cert->keyType = eccKey ? ECC_KEY : (rsaKey ? RSA_KEY : NTRU_KEY); + cert->keyType = eccKey ? ECC_KEY : (rsaKey ? RSA_KEY : + (ed25519Key ? ED25519_KEY : NTRU_KEY)); #ifdef WOLFSSL_SMALL_STACK der = (DerCert*)XMALLOC(sizeof(DerCert), NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -8374,7 +8621,8 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, return MEMORY_E; #endif - ret = EncodeCert(cert, der, rsaKey, eccKey, rng, ntruKey, ntruSz); + ret = EncodeCert(cert, der, rsaKey, eccKey, rng, ntruKey, ntruSz, + ed25519Key); if (ret == 0) { if (der->total + MAX_SEQ_SZ * 2 > (int)derSz) ret = BUFFER_E; @@ -8390,11 +8638,30 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, } +/* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */ +int wc_MakeCert_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType, + void* key, WC_RNG* rng) +{ + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + + if (keyType == RSA_TYPE) + rsaKey = (RsaKey*)key; + else if (keyType == ECC_TYPE) + eccKey = (ecc_key*)key; + else if (keyType == ED25519_TYPE) + ed25519Key = (ed25519_key*)key; + + return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0, + ed25519Key); +} /* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */ int wc_MakeCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng) { - return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0); + return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0, + NULL); } @@ -8483,10 +8750,11 @@ static int SetReqAttrib(byte* output, char* pw, int extSz) /* encode info from cert into DER encoded format */ -static int EncodeCertReq(Cert* cert, DerCert* der, - RsaKey* rsaKey, ecc_key* eccKey) +static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey, + ecc_key* eccKey, ed25519_key* ed25519Key) { (void)eccKey; + (void)ed25519Key; if (cert == NULL || der == NULL) return BAD_FUNC_ARG; @@ -8522,6 +8790,16 @@ static int EncodeCertReq(Cert* cert, DerCert* der, } #endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + if (cert->keyType == ED25519_KEY) { + if (ed25519Key == NULL) + return PUBLIC_KEY_E; + der->publicKeySz = SetEd25519PublicKey(der->publicKey, ed25519Key, 1); + if (der->publicKeySz <= 0) + return PUBLIC_KEY_E; + } +#endif /* HAVE_ED25519 */ + /* set the extensions */ der->extensionsSz = 0; @@ -8657,8 +8935,8 @@ static int WriteCertReqBody(DerCert* der, byte* buffer) } -int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, - RsaKey* rsaKey, ecc_key* eccKey) +static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, + RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key) { int ret; #ifdef WOLFSSL_SMALL_STACK @@ -8667,7 +8945,7 @@ int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, DerCert der[1]; #endif - cert->keyType = eccKey ? ECC_KEY : RSA_KEY; + cert->keyType = eccKey ? ECC_KEY : (ed25519Key ? ED25519_KEY : RSA_KEY); #ifdef WOLFSSL_SMALL_STACK der = (DerCert*)XMALLOC(sizeof(DerCert), NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -8675,7 +8953,7 @@ int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, return MEMORY_E; #endif - ret = EncodeCertReq(cert, der, rsaKey, eccKey); + ret = EncodeCertReq(cert, der, rsaKey, eccKey, ed25519Key); if (ret == 0) { if (der->total + MAX_SEQ_SZ * 2 > (int)derSz) @@ -8691,11 +8969,34 @@ int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, return ret; } +int wc_MakeCertReq_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType, + void* key) +{ + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + + if (keyType == RSA_TYPE) + rsaKey = (RsaKey*)key; + else if (keyType == ECC_TYPE) + eccKey = (ecc_key*)key; + else if (keyType == ED25519_TYPE) + ed25519Key = (ed25519_key*)key; + + return MakeCertReq(cert, derBuffer, derSz, rsaKey, eccKey, ed25519Key); +} + +int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, + RsaKey* rsaKey, ecc_key* eccKey) +{ + return MakeCertReq(cert, derBuffer, derSz, rsaKey, eccKey, NULL); +} #endif /* WOLFSSL_CERT_REQ */ -int wc_SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, - RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng) +static int SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, + RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key, + WC_RNG* rng) { int sigSz = 0; void* heap = NULL; @@ -8737,7 +9038,7 @@ int wc_SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, } sigSz = MakeSignature(certSignCtx, buffer, requestSz, certSignCtx->sig, - MAX_ENCODED_SIG_SZ, rsaKey, eccKey, rng, sType, heap); + MAX_ENCODED_SIG_SZ, rsaKey, eccKey, ed25519Key, rng, sType, heap); if (sigSz == WC_PENDING_E) return sigSz; @@ -8754,6 +9055,30 @@ int wc_SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, return sigSz; } +int wc_SignCert_ex(int requestSz, int sType, byte* buffer, word32 buffSz, + int keyType, void* key, WC_RNG* rng) +{ + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + + if (keyType == RSA_TYPE) + rsaKey = (RsaKey*)key; + else if (keyType == ECC_TYPE) + eccKey = (ecc_key*)key; + else if (keyType == ED25519_TYPE) + ed25519Key = (ed25519_key*)key; + + return SignCert(requestSz, sType, buffer, buffSz, rsaKey, eccKey, + ed25519Key, rng); +} + +int wc_SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, + RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng) +{ + return SignCert(requestSz, sType, buffer, buffSz, rsaKey, eccKey, NULL, + rng); +} int wc_MakeSelfCert(Cert* cert, byte* buffer, word32 buffSz, RsaKey* key, WC_RNG* rng) @@ -8773,7 +9098,8 @@ int wc_MakeSelfCert(Cert* cert, byte* buffer, word32 buffSz, /* Set KID from RSA or ECC public key */ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, - byte *ntruKey, word16 ntruKeySz, int kid_type) + byte *ntruKey, word16 ntruKeySz, + ed25519_key* ed25519Key, int kid_type) { byte *buffer; int bufferSz, ret; @@ -8782,7 +9108,9 @@ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, (void)ntruKeySz; #endif - if (cert == NULL || (rsakey == NULL && eckey == NULL && ntruKey == NULL) || + if (cert == NULL || + (rsakey == NULL && eckey == NULL && ntruKey == NULL && + ed25519Key == NULL) || (rsakey != NULL && eckey != NULL) || (rsakey != NULL && ntruKey != NULL) || (ntruKey != NULL && eckey != NULL) || @@ -8812,6 +9140,11 @@ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, bufferSz = -1; } #endif +#ifdef HAVE_ED25519 + /* ED25519 public key */ + else if (ed25519Key != NULL) + bufferSz = SetEd25519PublicKey(buffer, ed25519Key, 0); +#endif /* HAVE_ECC */ else bufferSz = -1; @@ -8849,10 +9182,27 @@ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, return ret; } +int wc_SetSubjectKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key) +{ + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + + if (keyType == RSA_TYPE) + rsaKey = (RsaKey*)key; + else if (keyType == ECC_TYPE) + eccKey = (ecc_key*)key; + else if (keyType == ED25519_TYPE) + ed25519Key = (ed25519_key*)key; + + return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, NULL, 0, ed25519Key, + SKID_TYPE); +} + /* Set SKID from RSA or ECC public key */ int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey) { - return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, SKID_TYPE); + return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, NULL, SKID_TYPE); } #ifdef HAVE_NTRU @@ -8860,14 +9210,32 @@ int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey) int wc_SetSubjectKeyIdFromNtruPublicKey(Cert *cert, byte *ntruKey, word16 ntruKeySz) { - return SetKeyIdFromPublicKey(cert, NULL,NULL,ntruKey, ntruKeySz, SKID_TYPE); + return SetKeyIdFromPublicKey(cert, NULL,NULL,ntruKey, ntruKeySz, NULL, + SKID_TYPE); } #endif +int wc_SetAuthKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key) +{ + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + + if (keyType == RSA_TYPE) + rsaKey = (RsaKey*)key; + else if (keyType == ECC_TYPE) + eccKey = (ecc_key*)key; + else if (keyType == ED25519_TYPE) + ed25519Key = (ed25519_key*)key; + + return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, NULL, 0, ed25519Key, + AKID_TYPE); +} + /* Set SKID from RSA or ECC public key */ int wc_SetAuthKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey) { - return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, AKID_TYPE); + return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, NULL, AKID_TYPE); } @@ -9847,6 +10215,177 @@ int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, word32 inLen) #endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + +int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx, + ed25519_key* key, word32 inSz) +{ + word32 oid; + int ret, version, length, endKeyIdx, privSz, pubSz; + const byte* priv; + const byte* pub; + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) + return BAD_FUNC_ARG; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + endKeyIdx = *inOutIdx + length; + + if (GetMyVersion(input, inOutIdx, &version, inSz) < 0) + return ASN_PARSE_E; + if (version != 0) { + WOLFSSL_MSG("Unrecognized version of ED25519 private key"); + return ASN_PARSE_E; + } + + if (GetAlgoId(input, inOutIdx, &oid, oidKeyType, inSz) < 0) + return ASN_PARSE_E; + if (oid != ED25519k) + return ASN_PARSE_E; + + if (GetOctetString(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0) + return ASN_PARSE_E; + priv = input + *inOutIdx; + *inOutIdx += privSz; + + if (endKeyIdx == (int)*inOutIdx) { + ret = wc_ed25519_import_private_only(priv, privSz, key); + } + else { + if (GetASNHeader(input, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1, + inOutIdx, &length, inSz) < 0) { + return ASN_PARSE_E; + } + if (GetOctetString(input, inOutIdx, &pubSz, inSz) < 0) + return ASN_PARSE_E; + pub = input + *inOutIdx; + *inOutIdx += pubSz; + + ret = wc_ed25519_import_private_key(priv, privSz, pub, pubSz, key); + } + if (ret == 0 && endKeyIdx != (int)*inOutIdx) + return ASN_PARSE_E; + + return ret; +} + + +int wc_Ed25519PublicKeyDecode(const byte* input, word32* inOutIdx, + ed25519_key* key, word32 inSz) +{ + int length; + int ret; +#ifdef ECC_CHECK_PUBLIC_KEY_OID + word32 oidSum; +#endif + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) + return BAD_FUNC_ARG; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + ret = SkipObjectId(input, inOutIdx, inSz); + if (ret != 0) + return ret; + + /* key header */ + ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL); + if (ret != 0) + return ret; + + /* This is the raw point data compressed or uncompressed. */ + if (wc_ed25519_import_public(input + *inOutIdx, inSz - *inOutIdx, key) != 0) + return ASN_ECC_KEY_E; + + return 0; +} + + +#ifdef WOLFSSL_KEY_GEN + +/* build DER formatted ED25519 key, + * return length on success, negative on error */ +static int wc_BuildEd25519KeyDer(ed25519_key* key, byte* output, word32 inLen, + int pubOut) +{ + byte algoArray[MAX_ALGO_SZ]; + byte ver[MAX_VERSION_SZ]; + byte seq[MAX_SEQ_SZ]; + int ret; + word32 idx = 0, seqSz, verSz, algoSz, privSz, pubSz = 0; + + if (key == NULL || output == NULL || inLen == 0) + return BAD_FUNC_ARG; + + if (pubOut) + pubSz = 2 + 2 + ED25519_PUB_KEY_SIZE; + privSz = 2 + 2 + ED25519_KEY_SIZE; + algoSz = SetAlgoID(ED25519k, algoArray, oidKeyType, 0); + verSz = SetMyVersion(0, ver, FALSE); + seqSz = SetSequence(verSz + algoSz + privSz + pubSz, seq); + + if (seqSz + verSz + algoSz + privSz + pubSz > inLen) + return BAD_FUNC_ARG; + + /* write out */ + /* seq */ + XMEMCPY(output + idx, seq, seqSz); + idx = seqSz; + /* ver */ + XMEMCPY(output + idx, ver, verSz); + idx += verSz; + /* algo */ + XMEMCPY(output + idx, algoArray, algoSz); + idx += algoSz; + /* privKey */ + idx += SetOctetString(2 + ED25519_KEY_SIZE, output + idx); + idx += SetOctetString(ED25519_KEY_SIZE, output + idx); + ret = wc_ed25519_export_private_only(key, output + idx, &privSz); + if (ret != 0) + return ret; + idx += privSz; + /* pubKey */ + if (pubOut) { + idx += SetExplicit(1, 2 + ED25519_PUB_KEY_SIZE, output + idx); + idx += SetOctetString(ED25519_KEY_SIZE, output + idx); + ret = wc_ed25519_export_public(key, output + idx, &pubSz); + if (ret != 0) + return ret; + idx += pubSz; + } + + return idx; +} + +/* Write a Private ecc key, including public to DER format, + * length on success else < 0 */ +int wc_Ed25519KeyToDer(ed25519_key* key, byte* output, word32 inLen) +{ + return wc_BuildEd25519KeyDer(key, output, inLen, 1); +} + + + +/* Write only private ecc key to DER format, + * length on success else < 0 */ +int wc_Ed25519PrivateKeyToDer(ed25519_key* key, byte* output, word32 inLen) +{ + return wc_BuildEd25519KeyDer(key, output, inLen, 0); +} + +#endif /* WOLFSSL_KEY_GEN */ + +#endif /* HAVE_ED25519 */ + + #if defined(HAVE_OCSP) || defined(HAVE_CRL) /* Get raw Date only, no processing, 0 on success */ diff --git a/wolfcrypt/src/ed25519.c b/wolfcrypt/src/ed25519.c index 258631b00..22ced3d1b 100644 --- a/wolfcrypt/src/ed25519.c +++ b/wolfcrypt/src/ed25519.c @@ -210,7 +210,7 @@ int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out, res will be 1 on successful verify and 0 on unsuccessful return 0 and res of 1 on success */ -int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg, +int wc_ed25519_verify_msg(const byte* sig, word32 siglen, const byte* msg, word32 msglen, int* res, ed25519_key* key) { byte rcheck[ED25519_KEY_SIZE]; @@ -407,6 +407,25 @@ int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key) } +/* + For importing a private key. + */ +int wc_ed25519_import_private_only(const byte* priv, word32 privSz, + ed25519_key* key) +{ + /* sanity check on arguments */ + if (priv == NULL || key == NULL) + return BAD_FUNC_ARG; + + /* key size check */ + if (privSz < ED25519_KEY_SIZE) + return BAD_FUNC_ARG; + + XMEMCPY(key->k, priv, ED25519_KEY_SIZE); + + return 0; +} + /* For importing a private key and its associated public key. */ @@ -508,6 +527,14 @@ int wc_ed25519_export_key(ed25519_key* key, #endif /* HAVE_ED25519_KEY_EXPORT */ +/* check the private and public keys match */ +int wc_ed25519_check_key(ed25519_key* key) +{ + /* TODO: Perform check of private and public key */ + (void)key; + + return 0; +} /* returns the private key size (secret only) in bytes */ int wc_ed25519_size(ed25519_key* key) diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index a6ef14fa2..42be1f71c 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -239,10 +239,11 @@ enum Block_Sum { enum Key_Sum { - DSAk = 515, - RSAk = 645, - NTRUk = 274, - ECDSAk = 518 + DSAk = 515, + RSAk = 645, + NTRUk = 274, + ECDSAk = 518, + ED25519k = 256 }; @@ -434,10 +435,13 @@ struct SignatureCtx { #endif union { #ifndef NO_RSA - struct RsaKey* rsa; + struct RsaKey* rsa; #endif #ifdef HAVE_ECC - struct ecc_key* ecc; + struct ecc_key* ecc; + #endif + #ifdef HAVE_ED25519 + struct ed25519_key* ed25519; #endif void* ptr; } key; @@ -814,7 +818,8 @@ enum cert_enums { EMAIL_JOINT_LEN = 9, RSA_KEY = 10, NTRU_KEY = 11, - ECC_KEY = 12 + ECC_KEY = 12, + ED25519_KEY = 13 }; #ifndef WOLFSSL_PEMCERT_TODER_DEFINED diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 1fdfa61ef..9adf13cf5 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -35,6 +35,10 @@ typedef struct ecc_key ecc_key; #define WC_ECCKEY_TYPE_DEFINED #endif +#ifndef WC_ED25519KEY_TYPE_DEFINED + typedef struct ed25519_key ed25519_key; + #define WC_ED25519KEY_TYPE_DEFINED +#endif #ifndef WC_RSAKEY_TYPE_DEFINED typedef struct RsaKey RsaKey; #define WC_RSAKEY_TYPE_DEFINED @@ -61,7 +65,8 @@ enum CertType { PUBLICKEY_TYPE, RSA_PUBLICKEY_TYPE, ECC_PUBLICKEY_TYPE, - TRUSTED_PEER_TYPE + TRUSTED_PEER_TYPE, + ED25519_TYPE }; @@ -79,7 +84,8 @@ enum Ctc_SigType { CTC_SHA384wRSA = 656, CTC_SHA384wECDSA = 525, CTC_SHA512wRSA = 657, - CTC_SHA512wECDSA = 526 + CTC_SHA512wECDSA = 526, + CTC_ED25519 = 256 }; enum Ctc_Encoding { @@ -174,14 +180,21 @@ typedef struct Cert { keyType = RSA_KEY (default) */ WOLFSSL_API void wc_InitCert(Cert*); +WOLFSSL_API int wc_MakeCert_ex(Cert* cert, byte* derBuffer, word32 derSz, + int keyType, void* key, WC_RNG* rng); WOLFSSL_API int wc_MakeCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, - ecc_key*, WC_RNG*); + ecc_key*, WC_RNG*); #ifdef WOLFSSL_CERT_REQ + WOLFSSL_API int wc_MakeCertReq_ex(Cert*, byte* derBuffer, word32 derSz, + int, void*); WOLFSSL_API int wc_MakeCertReq(Cert*, byte* derBuffer, word32 derSz, RsaKey*, ecc_key*); #endif +WOLFSSL_API int wc_SignCert_ex(int requestSz, int sType, byte* buffer, + word32 buffSz, int keyType, void* key, + WC_RNG* rng); WOLFSSL_API int wc_SignCert(int requestSz, int sigType, byte* derBuffer, - word32 derSz, RsaKey*, ecc_key*, WC_RNG*); + word32 derSz, RsaKey*, ecc_key*, WC_RNG*); WOLFSSL_API int wc_MakeSelfCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, WC_RNG*); WOLFSSL_API int wc_SetIssuer(Cert*, const char*); @@ -195,10 +208,14 @@ WOLFSSL_API int wc_SetAltNamesBuffer(Cert*, const byte*, int); WOLFSSL_API int wc_SetDatesBuffer(Cert*, const byte*, int); #ifdef WOLFSSL_CERT_EXT +WOLFSSL_API int wc_SetAuthKeyIdFromPublicKey_ex(Cert *cert, int keyType, + void* key); WOLFSSL_API int wc_SetAuthKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey); WOLFSSL_API int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz); WOLFSSL_API int wc_SetAuthKeyId(Cert *cert, const char* file); +WOLFSSL_API int wc_SetSubjectKeyIdFromPublicKey_ex(Cert *cert, int keyType, + void* key); WOLFSSL_API int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey); WOLFSSL_API int wc_SetSubjectKeyId(Cert *cert, const char* file); @@ -267,6 +284,24 @@ WOLFSSL_API int wc_SetKeyUsage(Cert *cert, const char *value); #endif #endif +#ifdef HAVE_ED25519 + /* private key helpers */ + WOLFSSL_API int wc_Ed25519PrivateKeyDecode(const byte*, word32*, + ed25519_key*, word32); + WOLFSSL_API int wc_Ed25519KeyToDer(ed25519_key* key, byte* output, + word32 inLen); + WOLFSSL_API int wc_Ed25519PrivateKeyToDer(ed25519_key* key, byte* output, + word32 inLen); + + /* public key helper */ + WOLFSSL_API int wc_Ed25519PublicKeyDecode(const byte*, word32*, + ed25519_key*, word32); + #if (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)) + WOLFSSL_API int wc_Ed25519PublicKeyToDer(ed25519_key*, byte* output, + word32 inLen, int with_AlgCurve); + #endif +#endif + /* DER encode signature */ WOLFSSL_API word32 wc_EncodeSignature(byte* out, const byte* digest, word32 digSz, int hashOID); diff --git a/wolfssl/wolfcrypt/ed25519.h b/wolfssl/wolfcrypt/ed25519.h index ea88603a3..f806785aa 100644 --- a/wolfssl/wolfcrypt/ed25519.h +++ b/wolfssl/wolfcrypt/ed25519.h @@ -54,8 +54,14 @@ /* both private and public key */ #define ED25519_PRV_KEY_SIZE (ED25519_PUB_KEY_SIZE+ED25519_KEY_SIZE) + +#ifndef WC_ED25519KEY_TYPE_DEFINED + typedef struct ed25519_key ed25519_key; + #define WC_ED25519KEY_TYPE_DEFINED +#endif + /* An ED25519 Key */ -typedef struct { +struct ed25519_key { byte p[ED25519_PUB_KEY_SIZE]; /* compressed public key */ byte k[ED25519_PRV_KEY_SIZE]; /* private key : 32 secret -- 32 public */ #ifdef FREESCALE_LTC_ECC @@ -63,7 +69,7 @@ typedef struct { byte pointX[ED25519_KEY_SIZE]; /* recovered X coordinate */ byte pointY[ED25519_KEY_SIZE]; /* Y coordinate is the public key with The most significant bit of the final octet always zero. */ #endif -} ed25519_key; +}; WOLFSSL_API @@ -72,7 +78,7 @@ WOLFSSL_API int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out, word32 *outlen, ed25519_key* key); WOLFSSL_API -int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg, +int wc_ed25519_verify_msg(const byte* sig, word32 siglen, const byte* msg, word32 msglen, int* stat, ed25519_key* key); WOLFSSL_API int wc_ed25519_init(ed25519_key* key); @@ -81,6 +87,9 @@ void wc_ed25519_free(ed25519_key* key); WOLFSSL_API int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key); WOLFSSL_API +int wc_ed25519_import_private_only(const byte* priv, word32 privSz, + ed25519_key* key); +WOLFSSL_API int wc_ed25519_import_private_key(const byte* priv, word32 privSz, const byte* pub, word32 pubSz, ed25519_key* key); WOLFSSL_API @@ -94,6 +103,8 @@ int wc_ed25519_export_key(ed25519_key* key, byte* priv, word32 *privSz, byte* pub, word32 *pubSz); +int wc_ed25519_check_key(ed25519_key* key); + /* size helper */ WOLFSSL_API int wc_ed25519_size(ed25519_key* key); diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 044fcfd06..5b23efeb2 100755 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -416,6 +416,7 @@ DYNAMIC_TYPE_ASYNC_NUMA = 67, DYNAMIC_TYPE_ASYNC_NUMA64 = 68, DYNAMIC_TYPE_CURVE25519 = 69, + DYNAMIC_TYPE_ED25519 = 70, }; /* max error buffer string size */ From 613d30bcae2734ea802701f34bcee36a45198a16 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Tue, 30 May 2017 16:04:24 +1000 Subject: [PATCH 2/6] ED25519 TLS support --- certs/ed25519/ca-ed25519-key.der | Bin 0 -> 84 bytes certs/ed25519/ca-ed25519-key.pem | 4 + certs/ed25519/ca-ed25519.der | Bin 0 -> 605 bytes certs/ed25519/ca-ed25519.pem | 15 + certs/ed25519/client-ed25519-key.der | Bin 0 -> 84 bytes certs/ed25519/client-ed25519-key.pem | 4 + certs/ed25519/client-ed25519.der | Bin 0 -> 597 bytes certs/ed25519/client-ed25519.pem | 15 + certs/ed25519/root-ed25519-key.der | Bin 0 -> 84 bytes certs/ed25519/root-ed25519-key.pem | 4 + certs/ed25519/root-ed25519.der | Bin 0 -> 607 bytes certs/ed25519/root-ed25519.pem | 15 + certs/ed25519/server-ed25519-key.der | Bin 0 -> 84 bytes certs/ed25519/server-ed25519-key.pem | 4 + certs/ed25519/server-ed25519.der | Bin 0 -> 591 bytes certs/ed25519/server-ed25519.pem | 30 ++ src/internal.c | 546 +++++++++++++++++++++++---- src/ssl.c | 179 ++++++++- src/tls.c | 112 +++--- src/tls13.c | 91 ++++- tests/suites.c | 10 + tests/test-ed25519.conf | 56 +++ tests/test-tls13.conf | 12 + tests/test.conf | 12 + wolfcrypt/src/asn.c | 15 +- wolfssl/internal.h | 40 +- wolfssl/ssl.h | 21 ++ wolfssl/test.h | 59 ++- wolfssl/wolfcrypt/asn.h | 1 + 29 files changed, 1091 insertions(+), 154 deletions(-) create mode 100644 certs/ed25519/ca-ed25519-key.der create mode 100644 certs/ed25519/ca-ed25519-key.pem create mode 100644 certs/ed25519/ca-ed25519.der create mode 100644 certs/ed25519/ca-ed25519.pem create mode 100644 certs/ed25519/client-ed25519-key.der create mode 100644 certs/ed25519/client-ed25519-key.pem create mode 100644 certs/ed25519/client-ed25519.der create mode 100644 certs/ed25519/client-ed25519.pem create mode 100644 certs/ed25519/root-ed25519-key.der create mode 100644 certs/ed25519/root-ed25519-key.pem create mode 100644 certs/ed25519/root-ed25519.der create mode 100644 certs/ed25519/root-ed25519.pem create mode 100644 certs/ed25519/server-ed25519-key.der create mode 100644 certs/ed25519/server-ed25519-key.pem create mode 100644 certs/ed25519/server-ed25519.der create mode 100644 certs/ed25519/server-ed25519.pem create mode 100644 tests/test-ed25519.conf diff --git a/certs/ed25519/ca-ed25519-key.der b/certs/ed25519/ca-ed25519-key.der new file mode 100644 index 0000000000000000000000000000000000000000..01156fec2949fb7c50ca359e52a69a5386fd10bf GIT binary patch literal 84 zcmV-a0IUBnQUU=0Fa-t!D`jv5A_O2!#L1OW{s!oN^&ld^p12M2XVE(iw9v(F$1pY! qg}h~d7ZKRI~^5UJRL&78|n0~D15+F7J literal 0 HcmV?d00001 diff --git a/certs/ed25519/ca-ed25519-key.pem b/certs/ed25519/ca-ed25519-key.pem new file mode 100644 index 000000000..a78c396f7 --- /dev/null +++ b/certs/ed25519/ca-ed25519-key.pem @@ -0,0 +1,4 @@ +-----BEGIN RSA PRIVATE KEY----- +MFICAQAwBQYDK2VwBCIEIE3EyZVR/gbofvUgIsCeuA3yZ9E7DbTQxW7HMDYQhbxl +oSIEIEEH7HUMaHISPASCB24Wb0BBbaSPCPLinadDwiQomH6s +-----END RSA PRIVATE KEY----- diff --git a/certs/ed25519/ca-ed25519.der b/certs/ed25519/ca-ed25519.der new file mode 100644 index 0000000000000000000000000000000000000000..fd6f31d1d8517b5f991fd05ce1de26065becfb5a GIT binary patch literal 605 zcmXqLVv00qV&Y!F%*4pV#KHLOq1~R!g{=mxY|PrJ1qO}t4Y>_C*_cCF*o2uvgAD}? z_&^*E9(LdSypqJcM3@LW54%%-RcdZxo*}ORH%JW&4@*#fehEwg7Y}=Reok6&un$ax zn}^-i#mLmu(9%%CKn$dXnTNl;yj%~YuDCcyFF8NgP~Je6jZ>@5qwPB{BPXMnKxSTA zz5|j110@N5BLhQo15+alBV!{oBg-hTfF)4C5-MQOIG1!^K)ubv!{qD;b1|*_pal(X zW<>@^_BW+G8AU=iEKTfrV)+h^xl8&vK0TVd-1(4-#*Df(ixUmv4S0ZoB`eIrYQW6M z_#YTRKpr297>mfHtK7FfvUKlU*v-r|KZ3#3jJ@ilfjmfBnFScc4I*s^)L+i~)q3#n z_C*_cCF*o2uvgAD}? z_&^*E9(LdSypqJcM3@LW54%%-RcdZxo*};hFGvjw4_k6hW@=suObHhcdwG6NT5zxr zOoW?<-POg&)YQ<@P{KeAq=}h_zr4I$52UWRI7crzKi5#+K$eYDtIebBJ1-+AqnJQu zURu5bk^%!I34S93LvsUDBMT#ABQqn*D6oJfP{0x@FeLn;1r2m&MFun5z3>M~4Sw0pq7LjGs3ns^8PS&1gB-dVT zwrlb%&G3%~@*rtt7GS_OU{}BoQozs1_@9N9nThQH1I&6yhAE57Za5A5dySyj|tE8D+BHB(G4DdmqLC literal 0 HcmV?d00001 diff --git a/certs/ed25519/root-ed25519-key.pem b/certs/ed25519/root-ed25519-key.pem new file mode 100644 index 000000000..be922d961 --- /dev/null +++ b/certs/ed25519/root-ed25519-key.pem @@ -0,0 +1,4 @@ +-----BEGIN RSA PRIVATE KEY----- +MFICAQAwBQYDK2VwBCIEIFwOftlJ9QL4yEBIBh9UmTRwCu+A6puPK9OFmVk0A19P +oSIEIKZgKbt92EfL1B7QbQ9XANgqH1BqQrxd5bgZZbLfJK9Q +-----END RSA PRIVATE KEY----- diff --git a/certs/ed25519/root-ed25519.der b/certs/ed25519/root-ed25519.der new file mode 100644 index 0000000000000000000000000000000000000000..f4da216c4f44dcba10db9f1767a80bb3ffce814a GIT binary patch literal 607 zcmXqLVv06sV&YxE%*4pV#KCyf@ZAev3poQ;HfHVA0)xi+hTI06Y|No7Y{E>T!G;0` zd>{@754&%EUP)qJB20vxhutZ^Dm6DT&yd%E8>EJXhb1UKzXYa$i-)~DKPN3X*as%U z&BN~MVq|J+XlW>6AO_OH%)?(^UakjHS6rNPUy-|z z%OB2gLrXp&%V|&S(;bqjo9?Tu4_KUN5O2T(3@%w=7FGjhM#lfZAOiCESj1RF+776{ zocF8s;NQpje?lUQ%#RyS+HD{Yl2&E`266*-1^gfd{6LdfSb@pl7z4~Pjto+^WnbJY zW|nVu>~3Q@bFV3Q?Vjk*cfI;`1Sh-n**2}(aQka|SnJRGsrjuh-<;5Ta{qVWv=^lZ OPTrg2qB{5Feog@FP_5Gd literal 0 HcmV?d00001 diff --git a/certs/ed25519/root-ed25519.pem b/certs/ed25519/root-ed25519.pem new file mode 100644 index 000000000..1356b21cc --- /dev/null +++ b/certs/ed25519/root-ed25519.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICWzCCAg2gAwIBAgIIAcUx7uhNOB4wBQYDK2VwMIGfMQswCQYDVQQGEwJVUzEQ +MA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjENMAsGA1UEBAwEUm9v +dDEQMA4GA1UECgwHd29sZlNTTDEQMA4GA1UECwwHRUQyNTUxOTEYMBYGA1UEAwwP +d3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t +MCIYDzIwMTcwNTI4MjMyNjI5WhgPMjAxOTA1MjkyMzI2MjlaMIGfMQswCQYDVQQG +EwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjENMAsGA1UE +BAwEUm9vdDEQMA4GA1UECgwHd29sZlNTTDEQMA4GA1UECwwHRUQyNTUxOTEYMBYG +A1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZz +c2wuY29tMCowBQYDK2VwAyEApmApu33YR8vUHtBtD1cA2CofUGpCvF3luBllst8k +r1CjYTBfMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFIbAJ+me+oXB/eNv/FRZcjfH +M5K7MB8GA1UdIwQYMBaAFIbAJ+me+oXB/eNv/FRZcjfHM5K7MA8GA1UdDwEB/wQF +AwIBxgAwBQYDK2VwA0EAGj129Ed4mXezQYuGBMzeglOtvFvz3UqPLBGTRI49gqqw +2/VnVoX532VvhensyCrk3/tRluh1wMnenEQlncm/CQ== +-----END CERTIFICATE----- diff --git a/certs/ed25519/server-ed25519-key.der b/certs/ed25519/server-ed25519-key.der new file mode 100644 index 0000000000000000000000000000000000000000..3c966a31b58677514764749a87ddc9a60e39283e GIT binary patch literal 84 zcmV-a0IUBnQUU=0Fa-t!D`jv5A_O4V>2|U|ANPoL_1*Y-#z`=4>7UD;9xK2Y@4I!0 q=67eIA_O2BFo+mOFPGW`^rYjxYz!8;NWsxU*N&2epmZujo(?I5QX}60 literal 0 HcmV?d00001 diff --git a/certs/ed25519/server-ed25519-key.pem b/certs/ed25519/server-ed25519-key.pem new file mode 100644 index 000000000..5699e0a7c --- /dev/null +++ b/certs/ed25519/server-ed25519-key.pem @@ -0,0 +1,4 @@ +-----BEGIN RSA PRIVATE KEY----- +MFICAQAwBQYDK2VwBCIEINjpdrI/H/eIdfXd+HrGSTBu6Z/LnR4rwBjvu3WJ5ndn +oSIEIBowiBhHL5faBPSk471sDBa5SMHRQteOkoSgdCpDng4p +-----END RSA PRIVATE KEY----- diff --git a/certs/ed25519/server-ed25519.der b/certs/ed25519/server-ed25519.der new file mode 100644 index 0000000000000000000000000000000000000000..9dc76898affb4b6c704ab2f524b9310a53c0885a GIT binary patch literal 591 zcmXqLV)8aT!G;0` zd>{@754&%EUP)qJB20vxhutZ^Dm6DT52k^IhsoIyCe6jeUY?(m798vY6XE7zcXcr` zH8r#}lrRtj8OqGVUtV6W2U1sDoTHbVpKB;@Aj`(7)#lOmotKf5QA{8+FD>5zNr8cq z1iz7ip}B#nk%f`5k(rTY6j;C#C}0T{Fld|)a}x1>;5Fa|If;db#V0i}4d!NA`9cdC z+{}s$QU)Co?)uYjv3yzbcyA7m*iMgw7oD#6O=?+CqUAh~PjhjwK_D4AusbNmsdVePrq0xv-m=X?_HQsTq6K zNdtb60)9ru|17M`Ol$`jVAeY_2!)mNOmmuX>!fIopT|^I*$Wj$Kib@8xy?@LHrybY nT|Tq>{~snZR_;vm_N3BV0Xn*|K~wA*=1REcn+x@QdBOkyhashSigAlgo[idx++] = sha_mac; suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo; #endif + #ifdef HAVE_ED25519 + suites->hashSigAlgo[idx++] = ED25519_SA_MAJOR; + suites->hashSigAlgo[idx++] = ED25519_SA_MINOR; + #endif } if (haveRSAsig) { @@ -2652,17 +2656,24 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, static INLINE void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType) { switch (input[0]) { + case NEW_SA_MAJOR: #ifdef WC_RSA_PSS - case rsa_pss_sa_algo: - /* PSS signatures: 0x080[4-6] */ - if (input[1] <= sha512_mac) { - *hsType = input[0]; - *hashAlgo = input[1]; - } - break; + /* PSS signatures: 0x080[4-6] */ + if (input[1] <= sha512_mac) { + *hsType = input[0]; + *hashAlgo = input[1]; + } #endif - /* ED25519: 0x0807 */ - /* ED448: 0x0808 */ + #ifdef HAVE_ED25519 + /* ED25519: 0x0807 */ + if (input[1] == ED25519_SA_MINOR) { + *hsType = ed25519_sa_algo; + /* Hash performed as part of sign/verify operation. */ + *hashAlgo = sha512_mac; + } + #endif + /* ED448: 0x0808 */ + break; default: *hashAlgo = input[0]; *hsType = input[1]; @@ -2828,6 +2839,12 @@ static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) output[0] = hashAlgo; output[1] = ecc_dsa_sa_algo; break; + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + output[0] = ED25519_SA_MAJOR; + output[1] = ED25519_SA_MINOR; + break; + #endif #endif #ifndef NO_RSA case rsa_sa_algo: @@ -2842,7 +2859,6 @@ static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) break; #endif #endif - /* ED25519: 0x0807 */ /* ED448: 0x0808 */ } } @@ -3420,6 +3436,108 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer) return ret; } +#ifdef HAVE_ED25519 +/* Sign the data using EdDSA and key using X25519. + * + * ssl SSL object. + * in Data or message to sign. + * inSz Length of the data. + * out Buffer to hold signature. + * outSz On entry, size of the buffer. On exit, the size of the signature. + * key The private X25519 key data. + * keySz The length of the private key data in bytes. + * ctx The callback context. + * returns 0 on succes, otherwise the valus is an error. + */ +int Ed25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, + word32* outSz, ed25519_key* key, byte* keyBuf, word32 keySz, + void* ctx) +{ + int ret; + + (void)ssl; + (void)keyBuf; + (void)keySz; + (void)ctx; + + WOLFSSL_ENTER("Ed25519Sign"); + +#if defined(HAVE_PK_CALLBACKS) + if (ssl->ctx->Ed25519SignCb) { + ret = ssl->ctx->Ed25519SignCb(ssl, in, inSz, out, outSz, keyBuf, + keySz, ctx); + } + else +#endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_ed25519_sign_msg(in, inSz, out, outSz, key); + } + + /* Handle async pending response */ +#if defined(WOLFSSL_ASYNC_CRYPT) + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("Ed25519Sign", ret); + + return ret; +} + +/* Verify the data using EdDSA and key using X25519. + * + * ssl SSL object. + * in Signature data. + * inSz Length of the signature data in bytes. + * msg Message to verify. + * outSz Length of message in bytes. + * key The public X25519 key data. + * keySz The length of the private key data in bytes. + * ctx The callback context. + * returns 0 on succes, otherwise the valus is an error. + */ +int Ed25519Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg, + word32 msgSz, ed25519_key* key, byte* keyBuf, word32 keySz, + void* ctx) +{ + int ret; + + (void)ssl; + (void)keyBuf; + (void)keySz; + (void)ctx; + + WOLFSSL_ENTER("Ed25519Verify"); + +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->Ed25519VerifyCb) { + ret = ssl->ctx->Ed25519VerifyCb(ssl, in, inSz, msg, msgSz, keyBuf, + keySz, &ssl->eccVerifyRes, ctx); + } + else +#endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_ed25519_verify_msg(in, inSz, msg, msgSz, + &ssl->eccVerifyRes, key); + } + + /* Handle async pending response */ +#if defined(WOLFSSL_ASYNC_CRYPT) + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + } + else +#endif /* WOLFSSL_ASYNC_CRYPT */ + { + ret = (ret != 0 || ssl->eccVerifyRes == 0) ? VERIFY_SIGN_ERROR : 0; + } + + WOLFSSL_LEAVE("Ed25519Verify", ret); + + return ret; +} +#endif /* HAVE_ED25519 */ #ifdef HAVE_CURVE25519 #ifdef HAVE_PK_CALLBACKS @@ -4179,6 +4297,11 @@ void FreeKey(WOLFSSL* ssl, int type, void** pKey) wc_ecc_free((ecc_key*)*pKey); break; #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case DYNAMIC_TYPE_ED25519: + wc_ed25519_free((ed25519_key*)*pKey); + break; + #endif /* HAVE_CURVE25519 */ #ifdef HAVE_CURVE25519 case DYNAMIC_TYPE_CURVE25519: wc_curve25519_free((curve25519_key*)*pKey); @@ -4216,26 +4339,31 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey) /* Determine size */ switch (type) { - #ifndef NO_RSA + #ifndef NO_RSA case DYNAMIC_TYPE_RSA: sz = sizeof(RsaKey); break; - #endif /* ! NO_RSA */ - #ifdef HAVE_ECC + #endif /* ! NO_RSA */ + #ifdef HAVE_ECC case DYNAMIC_TYPE_ECC: sz = sizeof(ecc_key); break; - #endif /* HAVE_ECC */ - #ifdef HAVE_CURVE25519 + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case DYNAMIC_TYPE_ED25519: + sz = sizeof(ed25519_key); + break; + #endif /* HAVE_ED25519 */ + #ifdef HAVE_CURVE25519 case DYNAMIC_TYPE_CURVE25519: sz = sizeof(curve25519_key); break; - #endif /* HAVE_CURVE25519 */ - #ifndef NO_DH + #endif /* HAVE_CURVE25519 */ + #ifndef NO_DH case DYNAMIC_TYPE_DH: sz = sizeof(DhKey); break; - #endif /* !NO_DH */ + #endif /* !NO_DH */ default: return BAD_FUNC_ARG; } @@ -4262,6 +4390,12 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey) ret = wc_ecc_init_ex((ecc_key*)*pKey, ssl->heap, ssl->devId); break; #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case DYNAMIC_TYPE_ED25519: + wc_ed25519_init((ed25519_key*)*pKey); + ret = 0; + break; + #endif /* HAVE_CURVE25519 */ #ifdef HAVE_CURVE25519 case DYNAMIC_TYPE_CURVE25519: wc_curve25519_init((curve25519_key*)*pKey); @@ -4303,6 +4437,12 @@ static int ReuseKey(WOLFSSL* ssl, int type, void* pKey) ret = wc_ecc_init_ex((ecc_key*)pKey, ssl->heap, ssl->devId); break; #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case DYNAMIC_TYPE_ED25519: + wc_ed25519_free((ed25519_key*)pKey); + wc_ed25519_init((ed25519_key*)pKey); + break; + #endif /* HAVE_CURVE25519 */ #ifdef HAVE_CURVE25519 case DYNAMIC_TYPE_CURVE25519: wc_curve25519_free((curve25519_key*)pKey); @@ -4447,6 +4587,10 @@ void SSL_ResourceFree(WOLFSSL* ssl) ssl->peerX25519KeyPresent = 0; #endif #endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + FreeKey(ssl, DYNAMIC_TYPE_ED25519, (void**)&ssl->peerEd25519Key); + ssl->peerEd25519KeyPresent = 0; +#endif #ifdef HAVE_PK_CALLBACKS #ifdef HAVE_ECC XFREE(ssl->buffers.peerEccDsaKey.buffer, ssl->heap, DYNAMIC_TYPE_ECC); @@ -7640,6 +7784,17 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz } break; #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + if (ssl->options.minEccKeySz < 0 || + ED25519_KEY_SIZE < + (word16)ssl->options.minEccKeySz) { + WOLFSSL_MSG( + "ECC key size in cert chain error"); + ret = ECC_KEY_SIZE_E; + } + break; + #endif /* HAVE_ED25519 */ default: WOLFSSL_MSG("Key size not checked"); /* key not being checked for size if not in @@ -8098,7 +8253,6 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz else { ssl->peerEccDsaKeyPresent = 1; #ifdef HAVE_PK_CALLBACKS - #ifdef HAVE_ECC ssl->buffers.peerEccDsaKey.buffer = (byte*)XMALLOC(args->dCert->pubKeySize, ssl->heap, DYNAMIC_TYPE_ECC); @@ -8112,7 +8266,6 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz ssl->buffers.peerEccDsaKey.length = args->dCert->pubKeySize; } - #endif /* HAVE_ECC */ #endif /*HAVE_PK_CALLBACKS */ } @@ -8126,6 +8279,56 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz } break; } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + { + int keyRet = 0; + if (ssl->peerEd25519Key == NULL) { + /* alloc/init on demand */ + keyRet = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEd25519Key); + } else if (ssl->peerEd25519KeyPresent) { + keyRet = ReuseKey(ssl, DYNAMIC_TYPE_ECC, + ssl->peerEd25519Key); + ssl->peerEd25519KeyPresent = 0; + } + + if (keyRet != 0 || + wc_ed25519_import_public(args->dCert->publicKey, + args->dCert->pubKeySize, + ssl->peerEd25519Key) + != 0) { + ret = PEER_KEY_ERROR; + } + else { + ssl->peerEd25519KeyPresent = 1; + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerEd25519Key.buffer = + (byte*)XMALLOC(args->dCert->pubKeySize, + ssl->heap, DYNAMIC_TYPE_ECC); + if (ssl->buffers.peerEd25519Key.buffer == NULL) { + ERROR_OUT(MEMORY_ERROR, exit_ppc); + } + else { + XMEMCPY(ssl->buffers.peerEd25519Key.buffer, + args->dCert->publicKey, + args->dCert->pubKeySize); + ssl->buffers.peerEd25519Key.length = + args->dCert->pubKeySize; + } + #endif /*HAVE_PK_CALLBACKS */ + } + + /* check size of peer ECC key */ + if (ret == 0 && ssl->peerEd25519KeyPresent && + !ssl->options.verifyNone && + ED25519_KEY_SIZE < ssl->options.minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Peer ECC key is too small"); + } + break; + } #endif /* HAVE_ECC */ default: break; @@ -15177,6 +15380,17 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, byte hashAlgo = 0, sigAlgo = 0; DecodeSigAlg(&hashSigAlgo[i], &hashAlgo, &sigAlgo); + #ifdef HAVE_ECC + if (ssl->pkCurveOID == ECC_ED25519_OID && sigAlgo != ed25519_sa_algo) + continue; + + if (sigAlgo == ed25519_sa_algo && + ssl->specs.sig_algo == ecc_dsa_sa_algo) { + ssl->suites->sigAlgo = sigAlgo; + ssl->suites->hashAlgo = sha512_mac; + break; + } + #endif if (sigAlgo == ssl->specs.sig_algo || (sigAlgo == rsa_pss_sa_algo && ssl->specs.sig_algo == rsa_sa_algo)) { if (hashAlgo == sha_mac) { @@ -16756,15 +16970,6 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } ssl->buffers.sig.length = SEED_LEN + verifySz; - /* buffer for hash */ - ssl->buffers.digest.length = wc_HashGetDigestSize(hashType); - ssl->buffers.digest.buffer = (byte*)XMALLOC( - ssl->buffers.digest.length, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (ssl->buffers.digest.buffer == NULL) { - ERROR_OUT(MEMORY_E, exit_dske); - } - /* build message to hash */ XMEMCPY(ssl->buffers.sig.buffer, ssl->arrays->clientRandom, RAN_LEN); @@ -16773,12 +16978,25 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, XMEMCPY(&ssl->buffers.sig.buffer[RAN_LEN * 2], input + args->begin, verifySz); /* message */ - /* Perform hash */ - ret = wc_Hash(hashType, - ssl->buffers.sig.buffer, ssl->buffers.sig.length, - ssl->buffers.digest.buffer, ssl->buffers.digest.length); - if (ret != 0) { - goto exit_dske; + if (args->sigAlgo != ed25519_sa_algo) { + /* buffer for hash */ + ssl->buffers.digest.length = + wc_HashGetDigestSize(hashType); + ssl->buffers.digest.buffer = (byte*)XMALLOC( + ssl->buffers.digest.length, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (ssl->buffers.digest.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_dske); + } + + /* Perform hash */ + ret = wc_Hash(hashType, ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + ssl->buffers.digest.buffer, + ssl->buffers.digest.length); + if (ret != 0) { + goto exit_dske; + } } switch (args->sigAlgo) @@ -16805,6 +17023,15 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, break; } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + { + if (!ssl->peerEd25519KeyPresent) { + ERROR_OUT(NO_PEER_KEY, exit_dske); + } + break; + } + #endif /* HAVE_ECC */ default: ret = ALGO_ID_E; @@ -16908,6 +17135,26 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, break; } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + { + ret = Ed25519Verify(ssl, + args->verifySig, args->verifySigSz, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + ssl->peerEd25519Key, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerEccDsaKey.buffer, + ssl->buffers.peerEccDsaKey.length, + ssl->Ed25519VerifyCtx + #else + NULL, 0, NULL + #endif + ); + + break; + } + #endif /* HAVE_ECC */ default: ret = ALGO_ID_E; @@ -17016,6 +17263,11 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, case ecc_dsa_sa_algo: /* Nothing to do in this algo */ break; + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + /* Nothing to do in this algo */ + break; #endif /* HAVE_ECC */ default: ret = ALGO_ID_E; @@ -18582,22 +18834,61 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx, (ecc_key*)ssl->hsKey, ssl->buffers.key->length); + if (ret == 0) { + WOLFSSL_MSG("Using ECC private key"); + + /* Check it meets the minimum ECC key size requirements. */ + keySz = wc_ecc_size((ecc_key*)ssl->hsKey); + if (keySz < ssl->options.minEccKeySz) { + WOLFSSL_MSG("ECC key size too small"); + ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk); + } + + /* Return the maximum signature length. */ + *length = wc_ecc_sig_size((ecc_key*)ssl->hsKey); + + goto exit_dpk; + } +#endif +#ifdef HAVE_ED25519 +#if !defined(NO_RSA) || defined(HAVE_ECC) + FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey); +#endif + + ssl->hsType = DYNAMIC_TYPE_ED25519; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { - WOLFSSL_MSG("Bad client cert type"); goto exit_dpk; } - WOLFSSL_MSG("Using ECC private key"); +#ifdef HAVE_ECC + WOLFSSL_MSG("Trying ED25519 private key, ECC didn't work"); +#elif !defined(NO_RSA) + WOLFSSL_MSG("Trying ED25519 private key, RSA didn't work"); +#else + WOLFSSL_MSG("Trying ED25519 private key"); +#endif - /* Check it meets the minimum ECC key size requirements. */ - keySz = wc_ecc_size((ecc_key*)ssl->hsKey); - if (keySz < ssl->options.minEccKeySz) { - WOLFSSL_MSG("ECC key size too small"); - ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk); + /* Set start of data to beginning of buffer. */ + idx = 0; + /* Decode the key assuming it is an ED25519 private key. */ + ret = wc_Ed25519PrivateKeyDecode(ssl->buffers.key->buffer, &idx, + (ed25519_key*)ssl->hsKey, + ssl->buffers.key->length); + if (ret == 0) { + WOLFSSL_MSG("Using ED25519 private key"); + + /* Check it meets the minimum ECC key size requirements. */ + if (ED25519_KEY_SIZE < ssl->options.minEccKeySz) { + WOLFSSL_MSG("ED25519 key size too small"); + ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk); + } + + /* Return the maximum signature length. */ + *length = ED25519_SIG_SIZE; + + goto exit_dpk; } - - /* Return the maximum signature length. */ - *length = wc_ecc_sig_size((ecc_key*)ssl->hsKey); #endif exit_dpk: @@ -18755,6 +19046,8 @@ int SendCertificateVerify(WOLFSSL* ssl) } else if (ssl->hsType == DYNAMIC_TYPE_ECC) args->sigAlgo = ecc_dsa_sa_algo; + else if (ssl->hsType == DYNAMIC_TYPE_ED25519) + args->sigAlgo = ed25519_sa_algo; if (IsAtLeastTLSv1_2(ssl)) { EncodeSigAlg(ssl->suites->hashAlgo, args->sigAlgo, @@ -18821,6 +19114,24 @@ int SendCertificateVerify(WOLFSSL* ssl) ); } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (ssl->hsType == DYNAMIC_TYPE_ED25519) { + ed25519_key* key = (ed25519_key*)ssl->hsKey; + + ret = Ed25519Sign(ssl, + ssl->buffers.digest.buffer, ssl->buffers.digest.length, + ssl->buffers.sig.buffer, &ssl->buffers.sig.length, + key, + #if defined(HAVE_PK_CALLBACKS) + ssl->buffers.key->buffer, + ssl->buffers.key->length, + ssl->Ed25519SignCtx + #else + NULL, 0, NULL + #endif + ); + } + #endif /* HAVE_ECC */ #ifndef NO_RSA if (ssl->hsType == DYNAMIC_TYPE_RSA) { RsaKey* key = (RsaKey*)ssl->hsKey; @@ -18867,6 +19178,16 @@ int SendCertificateVerify(WOLFSSL* ssl) ssl->buffers.sig.buffer, ssl->buffers.sig.length); } #endif /* HAVE_ECC */ + #ifdef HAVE_ECC + if (ssl->hsType == DYNAMIC_TYPE_ED25519) { + args->length = ssl->buffers.sig.length; + /* prepend hdr */ + c16toa((word16)ssl->buffers.sig.length, args->verify + + args->extraSz); + XMEMCPY(args->verify + args->extraSz + VERIFY_HEADER, + ssl->buffers.sig.buffer, ssl->buffers.sig.length); + } + #endif /* HAVE_ECC */ #ifndef NO_RSA if (ssl->hsType == DYNAMIC_TYPE_RSA) { RsaKey* key = (RsaKey*)ssl->hsKey; @@ -19991,6 +20312,38 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } break; } + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + { + word32 i = 0; + + ssl->hsType = DYNAMIC_TYPE_ED25519; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_sske; + } + + ret = wc_Ed25519PrivateKeyDecode( + ssl->buffers.key->buffer, + &i, + (ed25519_key*)ssl->hsKey, + ssl->buffers.key->length); + if (ret != 0) { + goto exit_sske; + } + /* worst case estimate */ + args->tmpSigSz = ED25519_SIG_SIZE; + + /* check the minimum ECC key size */ + if (ED25519_KEY_SIZE < + ssl->options.minEccKeySz) { + WOLFSSL_MSG("Ed25519 key size too small"); + ret = ECC_KEY_SIZE_E; + goto exit_sske; + } + break; + } + #endif default: ERROR_OUT(ALGO_ID_E, exit_sske); /* unsupported type */ } /* switch(ssl->specs.sig_algo) */ @@ -20091,20 +20444,24 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, XMEMCPY(args->sigDataBuf+RAN_LEN+RAN_LEN, args->output + preSigIdx, preSigSz); - ssl->buffers.sig.length = wc_HashGetDigestSize(hashType); - ssl->buffers.sig.buffer = (byte*)XMALLOC( + if (ssl->suites->sigAlgo != ed25519_sa_algo) { + ssl->buffers.sig.length = + wc_HashGetDigestSize(hashType); + ssl->buffers.sig.buffer = (byte*)XMALLOC( ssl->buffers.sig.length, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (ssl->buffers.sig.buffer == NULL) { - ERROR_OUT(MEMORY_E, exit_sske); - } + if (ssl->buffers.sig.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } - /* Perform hash */ - ret = wc_Hash(hashType, - args->sigDataBuf, args->sigDataSz, - ssl->buffers.sig.buffer, ssl->buffers.sig.length); - if (ret != 0) { - goto exit_sske; + /* Perform hash */ + ret = wc_Hash(hashType, args->sigDataBuf, + args->sigDataSz, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length); + if (ret != 0) { + goto exit_sske; + } } args->sigSz = args->tmpSigSz; @@ -20151,6 +20508,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, break; #endif #endif /* !NO_RSA */ + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + #endif case ecc_dsa_sa_algo: { break; @@ -20321,20 +20681,24 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, XMEMCPY(args->sigDataBuf+RAN_LEN+RAN_LEN, args->output + preSigIdx, preSigSz); - ssl->buffers.sig.length = wc_HashGetDigestSize(hashType); - ssl->buffers.sig.buffer = (byte*)XMALLOC( + if (ssl->suites->sigAlgo != ed25519_sa_algo) { + ssl->buffers.sig.length = + wc_HashGetDigestSize(hashType); + ssl->buffers.sig.buffer = (byte*)XMALLOC( ssl->buffers.sig.length, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (ssl->buffers.sig.buffer == NULL) { - ERROR_OUT(MEMORY_E, exit_sske); - } + if (ssl->buffers.sig.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } - /* Perform hash */ - ret = wc_Hash(hashType, - args->sigDataBuf, args->sigDataSz, - ssl->buffers.sig.buffer, ssl->buffers.sig.length); - if (ret != 0) { - goto exit_sske; + /* Perform hash */ + ret = wc_Hash(hashType, args->sigDataBuf, + args->sigDataSz, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length); + if (ret != 0) { + goto exit_sske; + } } args->sigSz = args->tmpSigSz; @@ -20458,6 +20822,27 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ); break; } + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + { + ed25519_key* key = (ed25519_key*)ssl->hsKey; + + ret = Ed25519Sign(ssl, + args->sigDataBuf, args->sigDataSz, + args->output + LENGTH_SZ + args->idx, + &args->sigSz, + key, + #if defined(HAVE_PK_CALLBACKS) + ssl->buffers.key->buffer, + ssl->buffers.key->length, + ssl->Ed25519SignCtx + #else + NULL, 0, NULL + #endif + ); + break; + } + #endif } /* switch(ssl->specs.sig_algo) */ break; } @@ -20589,6 +20974,19 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, args->sendSz += args->sigSz - args->tmpSigSz; break; } + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + { + /* Now that we know the real sig size, write it. */ + c16toa((word16)args->sigSz, + args->output + args->idx); + + /* And adjust length and sendSz from estimates */ + args->length += args->sigSz - args->tmpSigSz; + args->sendSz += args->sigSz - args->tmpSigSz; + break; + } + #endif default: ERROR_OUT(ALGO_ID_E, exit_sske); /* unsupported type */ } /* switch(ssl->specs.sig_algo) */ @@ -21714,6 +22112,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, else if (ssl->peerEccDsaKeyPresent) args->sigAlgo = ecc_dsa_sa_algo; #endif + #ifdef HAVE_ED25519 + else if (ssl->peerEd25519KeyPresent) + args->sigAlgo = ed25519_sa_algo; + #endif if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcv); @@ -21754,6 +22156,16 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (ssl->peerEd25519KeyPresent) { + WOLFSSL_MSG("Doing ED25519 peer cert verify"); + if (IsAtLeastTLSv1_2(ssl) && + args->sigAlgo != ed25519_sa_algo) { + WOLFSSL_MSG( + "Oops, peer sent ED25519 key but not in verify"); + } + } + #endif /* HAVE_ED25519 */ /* Advance state and proceed */ ssl->options.asyncState = TLS_ASYNC_DO; diff --git a/src/ssl.c b/src/ssl.c index eceafd442..59a18ec42 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -3635,6 +3635,15 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) } break; #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + if (cm->minEccKeySz < 0 || + ED25519_KEY_SIZE < (word16)cm->minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("\tCA ECC key size error"); + } + break; + #endif /* HAVE_ED25519 */ default: WOLFSSL_MSG("\tNo key size check done on CA"); @@ -4375,6 +4384,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, DerBuffer* der = NULL; /* holds DER or RAW (for NTRU) */ int ret = 0; int eccKey = 0; + int ed25519Key = 0; int rsaKey = 0; int resetSuites = 0; void* heap = ctx ? ctx->heap : ((ssl) ? ssl->heap : NULL); @@ -4574,7 +4584,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, if (type == PRIVATEKEY_TYPE && format != SSL_FILETYPE_RAW) { #ifndef NO_RSA - if (!eccKey) { + if (!eccKey && !ed25519Key) { /* make sure RSA key can be used */ word32 idx = 0; #ifdef WOLFSSL_SMALL_STACK @@ -4638,40 +4648,83 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } #endif #ifdef HAVE_ECC - if (!rsaKey) { + if (!rsaKey && !ed25519Key) { /* make sure ECC key can be used */ word32 idx = 0; ecc_key key; - ret = wc_ecc_init_ex(&key, heap, devId); + if (wc_ecc_init_ex(&key, heap, devId) == 0) { + if (wc_EccPrivateKeyDecode(der->buffer, &idx, &key, + der->length) == 0) { + + /* check for minimum ECC key size and then free */ + if (ssl) { + if (wc_ecc_size(&key) < ssl->options.minEccKeySz) { + wc_ecc_free(&key); + WOLFSSL_MSG("ECC private key too small"); + return ECC_KEY_SIZE_E; + } + } + else if (ctx) { + if (wc_ecc_size(&key) < ctx->minEccKeySz) { + wc_ecc_free(&key); + WOLFSSL_MSG("ECC private key too small"); + return ECC_KEY_SIZE_E; + } + } + + eccKey = 1; + if (ssl) { + ssl->options.haveStaticECC = 1; + } + else if (ctx) { + ctx->haveStaticECC = 1; + } + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + resetSuites = 1; + } + } + + wc_ecc_free(&key); + } + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (!rsaKey && !eccKey) { + /* make sure Ed25519 key can be used */ + word32 idx = 0; + ed25519_key key; + + ret = wc_ed25519_init(&key); if (ret != 0) { return ret; } - if (wc_EccPrivateKeyDecode(der->buffer, &idx, &key, - der->length) != 0) { - wc_ecc_free(&key); + if (wc_Ed25519PrivateKeyDecode(der->buffer, &idx, &key, + der->length) != 0) { + wc_ed25519_free(&key); return SSL_BAD_FILE; } /* check for minimum ECC key size and then free */ if (ssl) { - if (wc_ecc_size(&key) < ssl->options.minEccKeySz) { - wc_ecc_free(&key); - WOLFSSL_MSG("ECC private key too small"); + if (ED25519_KEY_SIZE < ssl->options.minEccKeySz) { + wc_ed25519_free(&key); + WOLFSSL_MSG("ED25519 private key too small"); return ECC_KEY_SIZE_E; } } else if (ctx) { - if (wc_ecc_size(&key) < ctx->minEccKeySz) { - wc_ecc_free(&key); - WOLFSSL_MSG("ECC private key too small"); + if (ED25519_KEY_SIZE < ctx->minEccKeySz) { + wc_ed25519_free(&key); + WOLFSSL_MSG("ED25519 private key too small"); return ECC_KEY_SIZE_E; } } - wc_ecc_free(&key); - eccKey = 1; + wc_ed25519_free(&key); + ed25519Key = 1; if (ssl) { ssl->options.haveStaticECC = 1; } @@ -4683,7 +4736,12 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, resetSuites = 1; } } - #endif /* HAVE_ECC */ + #endif + + if (!rsaKey && !eccKey && !ed25519Key) + return SSL_BAD_FILE; + + (void)ed25519Key; } else if (type == CERT_TYPE) { #ifdef WOLFSSL_SMALL_STACK @@ -4730,6 +4788,13 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, else if (ctx) ctx->haveECDSAsig = 1; break; + case CTC_ED25519: + WOLFSSL_MSG("ED25519 cert signature"); + if (ssl) + ssl->options.haveECDSAsig = 1; + else if (ctx) + ctx->haveECDSAsig = 1; + break; default: WOLFSSL_MSG("Not ECDSA cert signature"); break; @@ -4742,6 +4807,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, if (cert->keyOID == ECDSAk) { ssl->options.haveECC = 1; } + #ifdef HAVE_ED25519 + else if (cert->keyOID == ED25519k) { + ssl->options.haveECC = 1; + } + #endif #else ssl->options.haveECC = ssl->options.haveECDSAsig; #endif @@ -4752,6 +4822,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, if (cert->keyOID == ECDSAk) { ctx->haveECC = 1; } + #ifdef HAVE_ED25519 + else if (cert->keyOID == ED25519k) { + ctx->haveECC = 1; + } + #endif #else ctx->haveECC = ctx->haveECDSAsig; #endif @@ -4777,7 +4852,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } } break; - #endif /* !NO_RSA */ + #endif /* !NO_RSA */ #ifdef HAVE_ECC case ECDSAk: if (ssl && !ssl->options.verifyNone) { @@ -4795,7 +4870,25 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } } break; - #endif /* HAVE_ECC */ + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + if (ssl && !ssl->options.verifyNone) { + if (ssl->options.minEccKeySz < 0 || + ED25519_KEY_SIZE < (word16)ssl->options.minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Certificate Ed key size error"); + } + } + else if (ctx && !ctx->verifyNone) { + if (ctx->minEccKeySz < 0 || + ED25519_KEY_SIZE < (word16)ctx->minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Certificate ECC key size error"); + } + } + break; + #endif /* HAVE_ED25519 */ default: WOLFSSL_MSG("No key size check done on certificate"); @@ -22022,6 +22115,54 @@ void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl) return NULL; } +#endif /* HAVE_ECC */ + +#ifdef HAVE_ED25519 +void wolfSSL_CTX_SetEd25519SignCb(WOLFSSL_CTX* ctx, CallbackEd25519Sign cb) +{ + if (ctx) + ctx->Ed25519SignCb = cb; +} + + +void wolfSSL_SetEd25519SignCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->Ed25519SignCtx = ctx; +} + + +void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->Ed25519SignCtx; + + return NULL; +} + + +void wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX* ctx, CallbackEd25519Verify cb) +{ + if (ctx) + ctx->Ed25519VerifyCb = cb; +} + + +void wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->Ed25519VerifyCtx = ctx; +} + + +void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->Ed25519VerifyCtx; + + return NULL; +} +#endif #ifdef HAVE_CURVE25519 void wolfSSL_CTX_SetX25519SharedSecretCb(WOLFSSL_CTX* ctx, @@ -22046,7 +22187,6 @@ void* wolfSSL_GetX25519SharedSecretCtx(WOLFSSL* ssl) return NULL; } #endif -#endif /* HAVE_ECC */ #ifndef NO_RSA @@ -22365,6 +22505,9 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) case RSAk: ctx->haveRSA = 1; break; + #ifdef HAVE_ED25519 + case ED25519k: + #endif case ECDSAk: ctx->haveECC = 1; ctx->pkCurveOID = x->pkCurveOID; diff --git a/src/tls.c b/src/tls.c index 5e5c47148..4a713d0c9 100755 --- a/src/tls.c +++ b/src/tls.c @@ -2985,6 +2985,7 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { : NULL; EllipticCurve* curve = NULL; word32 oid = 0; + word32 pkOid = 0; word32 defOid = 0; word32 defSz = 80; /* Maximum known curve size is 66. */ word32 nextOid = 0; @@ -3009,19 +3010,19 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP case WOLFSSL_ECC_SECP160R1: - oid = ECC_SECP160R1_OID; + pkOid = oid = ECC_SECP160R1_OID; octets = 20; break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_SECPR2 case WOLFSSL_ECC_SECP160R2: - oid = ECC_SECP160R2_OID; + pkOid = oid = ECC_SECP160R2_OID; octets = 20; break; #endif /* HAVE_ECC_SECPR2 */ #ifdef HAVE_ECC_KOBLITZ case WOLFSSL_ECC_SECP160K1: - oid = ECC_SECP160K1_OID; + pkOid = oid = ECC_SECP160K1_OID; octets = 20; break; #endif /* HAVE_ECC_KOBLITZ */ @@ -3029,13 +3030,13 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP case WOLFSSL_ECC_SECP192R1: - oid = ECC_SECP192R1_OID; + pkOid = oid = ECC_SECP192R1_OID; octets = 24; break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_KOBLITZ case WOLFSSL_ECC_SECP192K1: - oid = ECC_SECP192K1_OID; + pkOid = oid = ECC_SECP192K1_OID; octets = 24; break; #endif /* HAVE_ECC_KOBLITZ */ @@ -3043,13 +3044,13 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP case WOLFSSL_ECC_SECP224R1: - oid = ECC_SECP224R1_OID; + pkOid = oid = ECC_SECP224R1_OID; octets = 28; break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_KOBLITZ case WOLFSSL_ECC_SECP224K1: - oid = ECC_SECP224K1_OID; + pkOid = oid = ECC_SECP224K1_OID; octets = 28; break; #endif /* HAVE_ECC_KOBLITZ */ @@ -3057,25 +3058,30 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP case WOLFSSL_ECC_SECP256R1: - oid = ECC_SECP256R1_OID; + pkOid = oid = ECC_SECP256R1_OID; octets = 32; break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_CURVE25519 case WOLFSSL_ECC_X25519: oid = ECC_X25519_OID; + #ifdef HAVE_ED25519 + pkOid = ECC_ED25519_OID; + #else + pkOid = ECC_X25519_OID; + #endif octets = 32; break; #endif /* HAVE_CURVE25519 */ #ifdef HAVE_ECC_KOBLITZ case WOLFSSL_ECC_SECP256K1: - oid = ECC_SECP256K1_OID; + pkOid = oid = ECC_SECP256K1_OID; octets = 32; break; #endif /* HAVE_ECC_KOBLITZ */ #ifdef HAVE_ECC_BRAINPOOL case WOLFSSL_ECC_BRAINPOOLP256R1: - oid = ECC_BRAINPOOLP256R1_OID; + pkOid = oid = ECC_BRAINPOOLP256R1_OID; octets = 32; break; #endif /* HAVE_ECC_BRAINPOOL */ @@ -3083,13 +3089,13 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP case WOLFSSL_ECC_SECP384R1: - oid = ECC_SECP384R1_OID; + pkOid = oid = ECC_SECP384R1_OID; octets = 48; break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_BRAINPOOL case WOLFSSL_ECC_BRAINPOOLP384R1: - oid = ECC_BRAINPOOLP384R1_OID; + pkOid = oid = ECC_BRAINPOOLP384R1_OID; octets = 48; break; #endif /* HAVE_ECC_BRAINPOOL */ @@ -3097,7 +3103,7 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) #ifdef HAVE_ECC_BRAINPOOL case WOLFSSL_ECC_BRAINPOOLP512R1: - oid = ECC_BRAINPOOLP512R1_OID; + pkOid = oid = ECC_BRAINPOOLP512R1_OID; octets = 64; break; #endif /* HAVE_ECC_BRAINPOOL */ @@ -3105,7 +3111,7 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP case WOLFSSL_ECC_SECP521R1: - oid = ECC_SECP521R1_OID; + pkOid = oid = ECC_SECP521R1_OID; octets = 66; break; #endif /* !NO_ECC_SECP */ @@ -3139,7 +3145,7 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: - sig |= ssl->pkCurveOID == oid; + sig |= ssl->pkCurveOID == pkOid; key |= ssl->ecdhCurveOID == oid; ephmSuite = 1; break; @@ -3158,7 +3164,7 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { defOid = 0; defSz = 80; } - sig |= ssl->pkCurveOID == oid; + sig |= ssl->pkCurveOID == pkOid; key |= ssl->pkCurveOID == oid; break; #endif /* WOLFSSL_STATIC_DH */ @@ -3192,7 +3198,7 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { defSz = 80; } sig = 1; - key |= ssl->pkCurveOID == oid; + key |= ssl->pkCurveOID == pkOid; break; #endif /* WOLFSSL_STATIC_DH */ #endif @@ -3214,7 +3220,7 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { /* ECDHE_ECDSA */ case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 : case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : - sig |= ssl->pkCurveOID == oid; + sig |= ssl->pkCurveOID == pkOid; key |= ssl->ecdhCurveOID == oid; ephmSuite = 1; break; @@ -6969,9 +6975,9 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) WOLFSSL_ECC_SECP256R1, ssl->heap); if (ret != SSL_SUCCESS) return ret; #endif - #ifdef HAVE_CURVE25519 + #if defined(HAVE_CURVE25519) ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_ECC_X25519, ssl->heap); + WOLFSSL_ECC_X25519, ssl->heap); if (ret != SSL_SUCCESS) return ret; #endif #ifdef HAVE_ECC_KOBLITZ @@ -7028,38 +7034,40 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) ssl->heap)) != 0) return ret; - /* Add FFDHE supported groups. */ - #ifdef HAVE_FFDHE_2048 - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_FFDHE_2048, ssl->heap); - if (ret != SSL_SUCCESS) - return ret; - #endif - #ifdef HAVE_FFDHE_3072 - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_FFDHE_3072, ssl->heap); - if (ret != SSL_SUCCESS) - return ret; - #endif - #ifdef HAVE_FFDHE_4096 - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_FFDHE_4096, ssl->heap); - if (ret != SSL_SUCCESS) - return ret; - #endif - #ifdef HAVE_FFDHE_6144 - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_FFDHE_6144, ssl->heap); - if (ret != SSL_SUCCESS) - return ret; - #endif - #ifdef HAVE_FFDHE_8192 - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_FFDHE_8192, ssl->heap); - if (ret != SSL_SUCCESS) - return ret; - #endif - ret = 0; + if (!ssl->options.userCurves && !ssl->ctx->userCurves) { + /* Add FFDHE supported groups. */ + #ifdef HAVE_FFDHE_2048 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_2048, ssl->heap); + if (ret != SSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_3072 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_3072, ssl->heap); + if (ret != SSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_4096 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_4096, ssl->heap); + if (ret != SSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_6144 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_6144, ssl->heap); + if (ret != SSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_8192 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_8192, ssl->heap); + if (ret != SSL_SUCCESS) + return ret; + #endif + ret = 0; + } if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) { #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && \ diff --git a/src/tls13.c b/src/tls13.c index 852b30f80..3679c06d0 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -3087,6 +3087,13 @@ static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) output[0] = hashAlgo; output[1] = ecc_dsa_sa_algo; break; + #ifdef HAVE_ED25519 + /* ED25519: 0x0807 */ + case ed25519_sa_algo: + output[0] = ED25519_SA_MAJOR; + output[1] = ED25519_SA_MINOR; + break; + #endif #endif #ifndef NO_RSA case rsa_sa_algo: @@ -3101,7 +3108,6 @@ static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) break; #endif #endif - /* ED25519: 0x0807 */ /* ED448: 0x0808 */ } } @@ -3115,17 +3121,24 @@ static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) static INLINE void DecodeSigAlg(byte* input, byte* hashAlgo, byte* hsType) { switch (input[0]) { + case NEW_SA_MAJOR: #ifdef WC_RSA_PSS - case 0x08: - /* PSS signatures: 0x080[4-6] */ - if (input[1] <= 0x06) { - *hsType = input[0]; - *hashAlgo = input[1]; - } - break; + /* PSS signatures: 0x080[4-6] */ + if (input[1] <= sha512_mac) { + *hsType = input[0]; + *hashAlgo = input[1]; + } #endif - /* ED25519: 0x0807 */ - /* ED448: 0x0808 */ + #ifdef HAVE_ED25519 + /* ED25519: 0x0807 */ + if (input[1] == ED25519_SA_MINOR) { + *hsType = ed25519_sa_algo; + /* Hash performed as part of sign/verify operation. */ + *hashAlgo = sha512_mac; + } + #endif + /* ED448: 0x0808 */ + break; default: *hashAlgo = input[0]; *hsType = input[1]; @@ -3825,6 +3838,8 @@ int SendTls13CertificateVerify(WOLFSSL* ssl) } else if (ssl->hsType == DYNAMIC_TYPE_ECC) args->sigAlgo = ecc_dsa_sa_algo; + else if (ssl->hsType == DYNAMIC_TYPE_ED25519) + args->sigAlgo = ed25519_sa_algo; EncodeSigAlg(ssl->suites->hashAlgo, args->sigAlgo, args->verify); /* Create the data to be signed. */ @@ -3869,6 +3884,12 @@ int SendTls13CertificateVerify(WOLFSSL* ssl) ret = 0; } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (ssl->hsType == DYNAMIC_TYPE_ED25519) { + /* Nothing to do */ + sig->length = ED25519_SIG_SIZE; + } + #endif /* HAVE_ECC */ /* Advance state and proceed */ ssl->options.asyncState = TLS_ASYNC_DO; @@ -3892,6 +3913,21 @@ int SendTls13CertificateVerify(WOLFSSL* ssl) args->length = sig->length; } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (ssl->hsType == DYNAMIC_TYPE_ED25519) { + ret = Ed25519Sign(ssl, args->sigData, args->sigDataSz, + args->verify + HASH_SIG_SIZE + VERIFY_HEADER, + &sig->length, (ed25519_key*)ssl->hsKey, + #if defined(HAVE_PK_CALLBACKS) + ssl->buffers.key->buffer, ssl->buffers.key->length, + ssl->Ed25519SignCtx + #else + NULL, 0, NULL + #endif + ); + args->length = sig->length; + } + #endif #ifndef NO_RSA if (ssl->hsType == DYNAMIC_TYPE_RSA) { /* restore verify pointer */ @@ -4154,6 +4190,10 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, } /* Check for public key of required type. */ + if (args->sigAlgo == ed25519_sa_algo && + !ssl->peerEd25519KeyPresent) { + WOLFSSL_MSG("Oops, peer sent ED25519 key but not in verify"); + } if (args->sigAlgo == ecc_dsa_sa_algo && !ssl->peerEccDsaKeyPresent) { WOLFSSL_MSG("Oops, peer sent ECC key but not in verify"); @@ -4191,6 +4231,20 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, ret = 0; } #endif + #ifdef HAVE_ED25519 + if (ssl->peerEd25519KeyPresent) { + WOLFSSL_MSG("Doing ED25519 peer cert verify"); + + args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (args->sigData == NULL) { + ERROR_OUT(MEMORY_E, exit_dcv); + } + + CreateSigData(ssl, args->sigData, &args->sigDataSz, 1); + ret = 0; + } + #endif /* Advance state and proceed */ ssl->options.asyncState = TLS_ASYNC_DO; @@ -4237,6 +4291,23 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, ); } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (ssl->peerEd25519KeyPresent) { + WOLFSSL_MSG("Doing ED25519 peer cert verify"); + + ret = Ed25519Verify(ssl, input + args->idx, args->sz, + args->sigData, args->sigDataSz, + ssl->peerEd25519Key, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerEd25519Key.buffer, + ssl->buffers.peerEd25519Key.length, + ssl->Ed25519VerifyCtx + #else + NULL, 0, NULL + #endif + ); + } + #endif /* Check for error */ if (ret != 0) { diff --git a/tests/suites.c b/tests/suites.c index 289c5ef46..cb37e203f 100644 --- a/tests/suites.c +++ b/tests/suites.c @@ -574,6 +574,16 @@ int SuiteTest(void) exit(EXIT_FAILURE); } #endif +#if defined(HAVE_CURVE25519) && defined(HAVE_ED25519) + /* add ED25519 certificate cipher suite tests */ + strcpy(argv0[1], "tests/test-ed25519.conf"); + printf("starting ED25519 extra cipher suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + exit(EXIT_FAILURE); + } +#endif #ifdef WOLFSSL_DTLS /* add dtls extra suites */ strcpy(argv0[1], "tests/test-dtls.conf"); diff --git a/tests/test-ed25519.conf b/tests/test-ed25519.conf new file mode 100644 index 000000000..cdd3ade35 --- /dev/null +++ b/tests/test-ed25519.conf @@ -0,0 +1,56 @@ +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-c ./certs/ed25519/server-ed25519.pem +-k ./certs/ed25519/server-ed25519-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ed25519/root-ed25519.pem +-C + +# Enable when CRL for ED25519 certificates available. +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +#-v 3 +#-l ECDHE-ECDSA-AES128-GCM-SHA256 +#-c ./certs/ed25519/server-ed25519.pem +#-k ./certs/ed25519/server-ed25519-key.pem +#-A ./certs/ed25519/client-ed25519.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +#-v 3 +#-l ECDHE-ECDSA-AES128-GCM-SHA256 +#-c ./certs/ed25519/client-ed25519.pem +#-k ./certs/ed25519/client-ed25519-key.pem +#-A ./certs/ed25519/root-ed25519.pem +#-C + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-c ./certs/ed25519/server-ed25519.pem +-k ./certs/ed25519/server-ed25519-key.pem + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ed25519/root-ed25519.pem +-C + +# Enable when CRL for ED25519 certificates available. +# server TLSv1.3 TLS13-AES128-GCM-SHA256 +#-v 4 +#-l TLS13-AES128-GCM-SHA256 +#-c ./certs/ed25519/server-ed25519.pem +#-k ./certs/ed25519/server-ed25519-key.pem +#-A ./certs/ed25519/client-ed25519.pem + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 +#-v 4 +#-l TLS13-AES128-GCM-SHA256 +#-c ./certs/ed25519/client-ed25519.pem +#-k ./certs/ed25519/client-ed25519-key.pem +#-A ./certs/ed25519/root-ed25519.pem +#-C + diff --git a/tests/test-tls13.conf b/tests/test-tls13.conf index cf1e9f7f9..b0c2aa92f 100644 --- a/tests/test-tls13.conf +++ b/tests/test-tls13.conf @@ -93,3 +93,15 @@ -l TLS13-AES128-CCM-8-SHA256 -A ./certs/server-ecc.pem +# server TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/server-ecc.pem +-t + diff --git a/tests/test.conf b/tests/test.conf index 933d001fd..e8223797e 100644 --- a/tests/test.conf +++ b/tests/test.conf @@ -2178,3 +2178,15 @@ -l ECDHE-RSA-AES128-SHA256 -j +# server TLSv1.2 ECDHE-EDCSA-CHACHA20-POLY1305 +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305 +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-A ./certs/server-ecc.pem +-t + diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index e3e647e07..51df86d6b 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -2502,7 +2502,7 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, } #endif /* HAVE_ECC */ #ifdef HAVE_ED25519 - if (*algoID != RSAk && *algoId != ECDSAk) { + if (*algoID != RSAk && *algoID != ECDSAk) { if (wc_ed25519_init(&ed25519) == 0) { if (wc_Ed25519PrivateKeyDecode(key, &tmpIdx, &ed25519, keySz) == 0) { @@ -3448,6 +3448,8 @@ static int GetKey(DecodedCert* cert) { int ret; + cert->pkCurveOID = ED25519k; + ret = CheckBitString(cert->source, &cert->srcIdx, &length, cert->maxIdx, 1, NULL); if (ret != 0) @@ -4637,7 +4639,7 @@ static int HashForSignature(const byte* buf, word32 bufSz, word32 sigOID, WOLFSSL_MSG("Hash for Signature has unsupported type"); } - return 0; + return ret; } /* Return codes: 0=Success, Negative (see error-crypt.h), ASN_SIG_CONFIRM_E */ @@ -10228,6 +10230,15 @@ int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx, if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) return BAD_FUNC_ARG; + if (GetOctetString(input, inOutIdx, &privSz, inSz) >= 0) { + priv = input + *inOutIdx; + *inOutIdx += privSz; + + if (*inOutIdx != inSz) + return ASN_PARSE_E; + return wc_ed25519_import_private_only(priv, privSz, key); + } + if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; endKeyIdx = *inOutIdx + length; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 9487a7947..4293dd873 100755 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -72,6 +72,9 @@ #ifdef HAVE_ECC #include #endif +#ifdef HAVE_ED25519 + #include +#endif #ifdef HAVE_CURVE25519 #include #endif @@ -909,7 +912,7 @@ enum Misc { ECC_BYTE = 0xC0, /* ECC first cipher suite byte */ QSH_BYTE = 0xD0, /* Quantum-safe Handshake cipher suite */ CHACHA_BYTE = 0xCC, /* ChaCha first cipher suite */ - TLS13_BYTE = 0x13, /* TLS v.13 first byte of cipher suite */ + TLS13_BYTE = 0x13, /* TLS v1.3 first byte of cipher suite */ SEND_CERT = 1, SEND_BLANK_CERT = 2, @@ -1093,6 +1096,12 @@ enum Misc { ECDHE_SIZE = 32, /* ECHDE server size defaults to 256 bit */ MAX_EXPORT_ECC_SZ = 256, /* Export ANS X9.62 max future size */ + NEW_SA_MAJOR = 8, /* Most signicant byte used with new sig algos */ + ED25519_SA_MAJOR = 8, /* Most significant byte for ED25519 */ + ED25519_SA_MINOR = 7, /* Least significant byte for ED25519 */ + ED448_SA_MAJOR = 8, /* Most significant byte for ED448 */ + ED448_SA_MINOR = 8, /* Least significant byte for ED448 */ + #ifdef HAVE_QSH /* qsh handshake sends 600+ size keys over hello extensions */ MAX_HELLO_SZ = 2048, /* max client or server hello */ @@ -2263,6 +2272,12 @@ struct WOLFSSL_CTX { CallbackEccSign EccSignCb; /* User EccSign Callback handler */ CallbackEccVerify EccVerifyCb; /* User EccVerify Callback handler */ CallbackEccSharedSecret EccSharedSecretCb; /* User EccVerify Callback handler */ + #ifdef HAVE_ED25519 + /* User Ed25519Sign Callback handler */ + CallbackEd25519Sign Ed25519SignCb; + /* User Ed25519Verify Callback handler */ + CallbackEd25519Verify Ed25519VerifyCb; + #endif #ifdef HAVE_CURVE25519 /* User EccSharedSecret Callback handler */ CallbackX25519SharedSecret X25519SharedSecretCb; @@ -2374,7 +2389,8 @@ enum SignatureAlgorithm { rsa_sa_algo = 1, dsa_sa_algo = 2, ecc_dsa_sa_algo = 3, - rsa_pss_sa_algo = 8 + rsa_pss_sa_algo = 8, + ed25519_sa_algo = 9 }; @@ -2637,6 +2653,9 @@ typedef struct Buffers { #ifdef HAVE_ECC buffer peerEccDsaKey; /* we own for Ecc Verify Callbacks */ #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + buffer peerEd25519Key; /* for Ed25519 Verify Callbacks */ + #endif /* HAVE_ED25519 */ #ifndef NO_RSA buffer peerRsaKey; /* we own for Rsa Verify Callbacks */ #endif /* NO_RSA */ @@ -3134,6 +3153,10 @@ struct WOLFSSL { byte peerEccKeyPresent; byte peerEccDsaKeyPresent; byte eccTempKeyPresent; +#ifdef HAVE_ED25519 + ed25519_key* peerEd25519Key; + byte peerEd25519KeyPresent; +#endif #ifdef HAVE_CURVE25519 curve25519_key* peerX25519Key; byte peerX25519KeyPresent; @@ -3241,6 +3264,10 @@ struct WOLFSSL { void* EccSignCtx; /* Ecc Sign Callback Context */ void* EccVerifyCtx; /* Ecc Verify Callback Context */ void* EccSharedSecretCtx; /* Ecc Pms Callback Context */ + #ifdef HAVE_ED25519 + void* Ed25519SignCtx; /* ED25519 Sign Callback Context */ + void* Ed25519VerifyCtx; /* ED25519 Verify Callback Context */ + #endif #ifdef HAVE_CURVE25519 void* X25519SharedSecretCtx; /* X25519 Pms Callback Context */ #endif @@ -3472,6 +3499,15 @@ WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl); ecc_key* pub_key, byte* pubKeyDer, word32* pubKeySz, byte* out, word32* outlen, int side, void* ctx); #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + WOLFSSL_LOCAL int Ed25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, ed25519_key* key, byte* keyBuf, + word32 keySz, void* ctx); + WOLFSSL_LOCAL int Ed25519Verify(WOLFSSL* ssl, const byte* in, + word32 inSz, const byte* msg, word32 msgSz, ed25519_key* key, + byte* keyBuf, word32 keySz, void* ctx); + #endif /* HAVE_ED25519 */ + #ifdef WOLFSSL_TRUST_PEER_CERT diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 9ae8cd9f5..7e573a398 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1506,6 +1506,27 @@ WOLFSSL_API void wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX*, CallbackEccShar WOLFSSL_API void wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx); WOLFSSL_API void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl); +struct ed25519_key; +typedef int (*CallbackEd25519Sign)(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, unsigned int* outSz, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetEd25519SignCb(WOLFSSL_CTX*, + CallbackEd25519Sign); +WOLFSSL_API void wolfSSL_SetEd25519SignCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl); + +typedef int (*CallbackEd25519Verify)(WOLFSSL* ssl, + const unsigned char* sig, unsigned int sigSz, + const unsigned char* msg, unsigned int msgSz, + const unsigned char* keyDer, unsigned int keySz, + int* result, void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX*, + CallbackEd25519Verify); +WOLFSSL_API void wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl); + struct curve25519_key; typedef int (*CallbackX25519SharedSecret)(WOLFSSL* ssl, struct curve25519_key* otherKey, diff --git a/wolfssl/test.h b/wolfssl/test.h index aab51b4e6..7535465af 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -24,6 +24,9 @@ #ifdef HAVE_ECC #include #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + #include + #endif /* HAVE_ED25519 */ #ifdef HAVE_CURVE25519 #include #endif /* HAVE_ECC */ @@ -1828,6 +1831,52 @@ static INLINE int myEccSharedSecret(WOLFSSL* ssl, ecc_key* otherKey, return ret; } +#ifdef HAVE_ED25519 +static INLINE int myEd25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx) +{ + int ret; + word32 idx = 0; + ed25519_key myKey; + + (void)ssl; + (void)ctx; + + ret = wc_ed25519_init(&myKey); + if (ret == 0) { + ret = wc_Ed25519PrivateKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) + ret = wc_ed25519_sign_msg(in, inSz, out, outSz, &myKey); + wc_ed25519_free(&myKey); + } + + return ret; +} + + +static INLINE int myEd25519Verify(WOLFSSL* ssl, const byte* sig, word32 sigSz, + const byte* msg, word32 msgSz, const byte* key, word32 keySz, + int* result, void* ctx) +{ + int ret; + ed25519_key myKey; + + (void)ssl; + (void)ctx; + + ret = wc_ed25519_init(&myKey); + if (ret == 0) { + ret = wc_ed25519_import_public(key, keySz, &myKey); + if (ret == 0) { + ret = wc_ed25519_verify_msg(sig, sigSz, msg, msgSz, result, &myKey); + } + wc_ed25519_free(&myKey); + } + + return ret; +} +#endif /* HAVE_ED25519 */ + #ifdef HAVE_CURVE25519 static INLINE int myX25519SharedSecret(WOLFSSL* ssl, curve25519_key* otherKey, unsigned char* pubKeyDer, unsigned int* pubKeySz, @@ -2121,10 +2170,14 @@ static INLINE void SetupPkCallbacks(WOLFSSL_CTX* ctx, WOLFSSL* ssl) wolfSSL_CTX_SetEccSignCb(ctx, myEccSign); wolfSSL_CTX_SetEccVerifyCb(ctx, myEccVerify); wolfSSL_CTX_SetEccSharedSecretCb(ctx, myEccSharedSecret); - #ifdef HAVE_CURVE25519 - wolfSSL_CTX_SetX25519SharedSecretCb(ctx, myX25519SharedSecret); - #endif #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + wolfSSL_CTX_SetEd25519SignCb(ctx, myEd25519Sign); + wolfSSL_CTX_SetEd25519VerifyCb(ctx, myEd25519Verify); + #endif + #ifdef HAVE_CURVE25519 + wolfSSL_CTX_SetX25519SharedSecretCb(ctx, myX25519SharedSecret); + #endif #ifndef NO_RSA wolfSSL_CTX_SetRsaSignCb(ctx, myRsaSign); wolfSSL_CTX_SetRsaVerifyCb(ctx, myRsaVerify); diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 42be1f71c..f2c5c9aa5 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -287,6 +287,7 @@ enum Ecc_Sum { ECC_SECP256K1_OID = 186, ECC_BRAINPOOLP256R1_OID = 104, ECC_X25519_OID = 365, + ECC_ED25519_OID = 256, ECC_BRAINPOOLP320R1_OID = 106, ECC_SECP384R1_OID = 210, ECC_BRAINPOOLP384R1_OID = 108, From 1bc862ae249b0a8b25bd96be19fdbf0a0c1b8dfb Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Wed, 31 May 2017 10:35:55 +1000 Subject: [PATCH 3/6] Ed25519 testing in test.c --- wolfcrypt/test/test.c | 226 ++++++++++++++++++++++++++++++++++++++++++ wolfssl/certs_test.h | 153 ++++++++++++++++++++++++++++ 2 files changed, 379 insertions(+) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 4bf48891b..86d1e3b01 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -5712,6 +5712,14 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) static const char* eccCaKeyPubFile = CERT_ROOT "ecc-keyPub.der"; #endif #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + #ifdef WOLFSSL_TEST_CERT + static const char* serverEd25519Cert = + CERT_ROOT "ed25519/server-ed25519.der"; + static const char* caEd25519Cert = + CERT_ROOT "ed25519/ca-ed25519.der"; + #endif + #endif #endif /* !USE_CERT_BUFFER_* */ #ifndef NO_WRITE_TEMP_FILES @@ -11442,6 +11450,213 @@ int curve25519_test(void) #ifdef HAVE_ED25519 +#ifdef WOLFSSL_TEST_CERT +static int ed25519_test_cert(void) +{ + DecodedCert cert[2]; + DecodedCert* serverCert = NULL; + DecodedCert* caCert = NULL; +#ifdef HAVE_ED25519_VERIFY + ed25519_key key; + ed25519_key* pubKey = NULL; + int verify; +#endif /* HAVE_ED25519_VERIFY */ + int ret; + byte* tmp; + int bytes; + FILE* file; + + tmp = XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + ret = -7200; + goto done; + } + +#ifdef USE_CERT_BUFFERS_256 + XMEMCPY(tmp, ca_ed25519_cert, sizeof_ca_ed25519_cert); + bytes = sizeof_ca_ed25519_cert; +#elif !defined(NO_FILESYSTEM) + file = fopen(caEd25519Cert, "rb"); + if (file == NULL) { + ret = -7201; + goto done; + } + bytes = fread(tmp, 1, FOURK_BUF, file); + fclose(file); +#else + /* No certificate to use. */ + ret = -7202; + goto done; +#endif + + InitDecodedCert(&cert[0], tmp, (word32)bytes, 0); + caCert = &cert[0]; + ret = ParseCert(caCert, CERT_TYPE, NO_VERIFY, NULL); + if (ret != 0) { + ret = -7203; + goto done; + } + +#ifdef USE_CERT_BUFFERS_256 + XMEMCPY(tmp, server_ed25519_cert, sizeof_server_ed25519_cert); + bytes = sizeof_server_ed25519_cert; +#elif !defined(NO_FILESYSTEM) + file = fopen(serverEd25519Cert, "rb"); + if (file == NULL) { + ret = -7204; + goto done; + } + bytes = fread(tmp, 1, FOURK_BUF, file); + fclose(file); +#else + /* No certificate to use. */ + ret = -7205; + goto done; +#endif + + InitDecodedCert(&cert[1], tmp, (word32)bytes, 0); + serverCert = &cert[1]; + ret = ParseCert(serverCert, CERT_TYPE, NO_VERIFY, NULL); + if (ret != 0) { + ret = -7206; + goto done; + } + +#ifdef HAVE_ED25519_VERIFY + ret = wc_ed25519_init(&key); + if (ret < 0) { + ret = -7207; + goto done; + } + pubKey = &key; + ret = wc_ed25519_import_public(caCert->publicKey, caCert->pubKeySize, + pubKey); + if (ret < 0) { + ret = -7208; + goto done; + } + + if (wc_ed25519_verify_msg(serverCert->signature, serverCert->sigLength, + serverCert->source + serverCert->certBegin, + serverCert->sigIndex - serverCert->certBegin, + &verify, pubKey) < 0 || verify != 1) { + ret = -7209; + goto done; + } +#endif /* HAVE_ED25519_VERIFY */ + +done: + if (tmp != NULL) + XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef HAVE_ED25519_VERIFY + wc_ed25519_free(pubKey); +#endif /* HAVE_ED25519_VERIFY */ + if (caCert != NULL) + FreeDecodedCert(caCert); + if (serverCert != NULL) + FreeDecodedCert(serverCert); + + return ret; +} + +#ifdef WOLFSSL_CERT_GEN +static const CertName defaultName = { + "US", CTC_PRINTABLE, + "Montana", CTC_UTF8, + "Bozeman", CTC_UTF8, + "Test", CTC_UTF8, + "wolfSSL", CTC_UTF8, + "ED25519", CTC_UTF8, + "www.wolfssl.com", CTC_UTF8, + "info@wolfssl.com" +}; +#ifdef WOLFSSL_CERT_EXT +static const char leafKeyUsage[] = "digitalSignature,nonRepudiation"; +#endif + +static int ed25519_test_make_cert(void) +{ + WC_RNG rng; + Cert cert; + DecodedCert decode; + ed25519_key key; + ed25519_key* privKey = NULL; + int ret = 0; + byte* tmp = NULL; + + wc_InitCert(&cert); + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) + return -7220; + + wc_ed25519_init(&key); + privKey = &key; + wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, privKey); + + cert.daysValid = 365 * 2; + cert.selfSigned = 1; + XMEMCPY(&cert.issuer, &defaultName, sizeof(CertName)); + XMEMCPY(&cert.subject, &defaultName, sizeof(CertName)); + cert.isCA = 0; +#ifdef WOLFSSL_CERT_EXT + ret = wc_SetKeyUsage(&cert, leafKeyUsage); + if (ret < 0) { + ret = -7221; + goto done; + } + ret = wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ED25519_TYPE, privKey); + if (ret < 0) { + ret = -7222; + goto done; + } + ret = wc_SetAuthKeyIdFromPublicKey_ex(&cert, ED25519_TYPE, privKey); + if (ret < 0) { + ret = -7223; + goto done; + } +#endif + tmp = XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + ret = -7224; + goto done; + } + + cert.sigType = CTC_ED25519; + ret = wc_MakeCert_ex(&cert, tmp, FOURK_BUF, ED25519_TYPE, privKey, &rng); + if (ret < 0) { + ret = -7225; + goto done; + } + ret = wc_SignCert_ex(cert.bodySz, cert.sigType, tmp, FOURK_BUF, + ED25519_TYPE, privKey, &rng); + if (ret < 0) { + ret = -7226; + goto done; + } + + InitDecodedCert(&decode, tmp, ret, HEAP_HINT); + ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); + FreeDecodedCert(&decode); + if (ret != 0) { + ret = -7227; + goto done; + } + +done: + if (tmp != NULL) + XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_ed25519_free(privKey); + wc_FreeRng(&rng); + return ret; +} +#endif /* WOLFSSL_CERT_GEN */ +#endif /* WOLFSSL_TEST_CERT */ + int ed25519_test(void) { WC_RNG rng; @@ -11871,6 +12086,17 @@ int ed25519_test(void) (void)keySz; (void)sigSz; +#ifdef WOLFSSL_TEST_CERT + ret = ed25519_test_cert(); + if (ret < 0) + return ret; +#ifdef WOLFSSL_CERT_GEN + ret = ed25519_test_make_cert(); + if (ret < 0) + return ret; +#endif /* WOLFSSL_CERT_GEN */ +#endif /* WOLFSSL_TEST_CERT */ + return 0; } #endif /* HAVE_ED25519 */ diff --git a/wolfssl/certs_test.h b/wolfssl/certs_test.h index 64d10e50d..621936c00 100644 --- a/wolfssl/certs_test.h +++ b/wolfssl/certs_test.h @@ -2183,5 +2183,158 @@ static const unsigned char dh_g[] = 0x02, }; +#ifdef HAVE_ED25519 +/* + * Subject: /C=US/ST=Montana/L=Bozeman/SN=Leaf/O=wolfSSL/OU=ED25519/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + * Issuer: /C=US/ST=Montana/L=Bozeman/SN=CA/O=wolfSSL/OU=ED25519/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + */ +static const unsigned char server_ed25519_pkey[44] = { + 0x30, 0x2A, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, 0x03, + 0x21, 0x00, 0x1A, 0x30, 0x88, 0x18, 0x47, 0x2F, 0x97, 0xDA, + 0x04, 0xF4, 0xA4, 0xE3, 0xBD, 0x6C, 0x0C, 0x16, 0xB9, 0x48, + 0xC1, 0xD1, 0x42, 0xD7, 0x8E, 0x92, 0x84, 0xA0, 0x74, 0x2A, + 0x43, 0x9E, 0x0E, 0x29 +}; +static const int sizeof_server_ed25519_pkey = sizeof(server_ed25519_pkey); + +static const unsigned char server_ed25519_cert[591] = { + 0x30, 0x82, 0x02, 0x4B, 0x30, 0x82, 0x01, 0xFD, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x08, 0x01, 0xD0, 0x92, 0x10, 0x6A, + 0x5A, 0x46, 0x57, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, + 0x30, 0x81, 0x9D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, + 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, + 0x61, 0x6E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x04, 0x0C, 0x02, 0x43, 0x41, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, + 0x53, 0x53, 0x4C, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x0C, 0x07, 0x45, 0x44, 0x32, 0x35, 0x35, 0x31, + 0x39, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, + 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37, 0x30, 0x35, + 0x32, 0x38, 0x32, 0x33, 0x32, 0x36, 0x32, 0x39, 0x5A, 0x18, + 0x0F, 0x32, 0x30, 0x31, 0x39, 0x30, 0x35, 0x32, 0x39, 0x32, + 0x33, 0x32, 0x36, 0x32, 0x39, 0x5A, 0x30, 0x81, 0x9F, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, + 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x0D, + 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x04, 0x0C, 0x04, 0x4C, + 0x65, 0x61, 0x66, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, + 0x4C, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x0C, 0x07, 0x45, 0x44, 0x32, 0x35, 0x35, 0x31, 0x39, 0x31, + 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, + 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, + 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, + 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, + 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x2A, + 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, 0x03, 0x21, 0x00, + 0x1A, 0x30, 0x88, 0x18, 0x47, 0x2F, 0x97, 0xDA, 0x04, 0xF4, + 0xA4, 0xE3, 0xBD, 0x6C, 0x0C, 0x16, 0xB9, 0x48, 0xC1, 0xD1, + 0x42, 0xD7, 0x8E, 0x92, 0x84, 0xA0, 0x74, 0x2A, 0x43, 0x9E, + 0x0E, 0x29, 0xA3, 0x53, 0x30, 0x51, 0x30, 0x1D, 0x06, 0x03, + 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xF6, 0xB2, 0x84, + 0x1A, 0x95, 0xB4, 0x70, 0x32, 0x53, 0xFE, 0xD9, 0xEB, 0x9B, + 0x29, 0x80, 0x4B, 0xD6, 0xB5, 0xF1, 0xC0, 0x30, 0x1F, 0x06, + 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0x92, 0xD5, 0x0B, 0xDA, 0xF1, 0x04, 0x8B, 0xB9, 0xA1, 0x8B, + 0x03, 0x02, 0x9F, 0x58, 0x00, 0x35, 0x36, 0x07, 0x7A, 0xC9, + 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, + 0x04, 0x05, 0x03, 0x02, 0x06, 0xC0, 0x00, 0x30, 0x05, 0x06, + 0x03, 0x2B, 0x65, 0x70, 0x03, 0x41, 0x00, 0x12, 0x56, 0x77, + 0x0C, 0x96, 0x42, 0x98, 0xDA, 0xC9, 0x15, 0x6C, 0x4E, 0x48, + 0x95, 0x05, 0x1D, 0xD0, 0x78, 0x32, 0xF8, 0x86, 0x46, 0x9A, + 0x46, 0x9B, 0x64, 0x8B, 0x31, 0xB0, 0x19, 0x6B, 0x77, 0x99, + 0x8B, 0xFF, 0xFC, 0x02, 0x36, 0x05, 0x0B, 0x69, 0x37, 0x87, + 0x62, 0x75, 0xDA, 0x50, 0x2C, 0x2D, 0x5D, 0x52, 0x94, 0x3F, + 0x00, 0x9D, 0x18, 0x45, 0x6F, 0x37, 0x12, 0x8E, 0xF4, 0xE4, + 0x00 +}; +static const int sizeof_server_ed25519_cert = sizeof(server_ed25519_cert); + +static const unsigned char ca_ed25519_pkey[44] = { + 0x30, 0x2A, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, 0x03, + 0x21, 0x00, 0x41, 0x07, 0xEC, 0x75, 0x0C, 0x68, 0x72, 0x12, + 0x3C, 0x04, 0x82, 0x07, 0x6E, 0x16, 0x6F, 0x40, 0x41, 0x6D, + 0xA4, 0x8F, 0x08, 0xF2, 0xE2, 0x9D, 0xA7, 0x43, 0xC2, 0x24, + 0x28, 0x98, 0x7E, 0xAC +}; +static const int sizeof_ca_ed25519_pkey = sizeof(ca_ed25519_pkey); + +static const unsigned char ca_ed25519_cert[605] = { + 0x30, 0x82, 0x02, 0x59, 0x30, 0x82, 0x02, 0x0B, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x08, 0x01, 0xF6, 0xE1, 0x3E, 0xBC, + 0x79, 0xA1, 0x85, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, + 0x30, 0x81, 0x9F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, + 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, + 0x61, 0x6E, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, + 0x04, 0x0C, 0x04, 0x52, 0x6F, 0x6F, 0x74, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, + 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x45, 0x44, 0x32, 0x35, + 0x35, 0x31, 0x39, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, + 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, + 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, + 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, + 0x6F, 0x6D, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37, + 0x30, 0x35, 0x32, 0x38, 0x32, 0x33, 0x32, 0x36, 0x32, 0x39, + 0x5A, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x39, 0x30, 0x35, 0x32, + 0x39, 0x32, 0x33, 0x32, 0x36, 0x32, 0x39, 0x5A, 0x30, 0x81, + 0x9D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, + 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, + 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x04, 0x0C, + 0x02, 0x43, 0x41, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, + 0x4C, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x0C, 0x07, 0x45, 0x44, 0x32, 0x35, 0x35, 0x31, 0x39, 0x31, + 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, + 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, + 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, + 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, + 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x2A, + 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, 0x03, 0x21, 0x00, + 0x41, 0x07, 0xEC, 0x75, 0x0C, 0x68, 0x72, 0x12, 0x3C, 0x04, + 0x82, 0x07, 0x6E, 0x16, 0x6F, 0x40, 0x41, 0x6D, 0xA4, 0x8F, + 0x08, 0xF2, 0xE2, 0x9D, 0xA7, 0x43, 0xC2, 0x24, 0x28, 0x98, + 0x7E, 0xAC, 0xA3, 0x61, 0x30, 0x5F, 0x30, 0x0C, 0x06, 0x03, + 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, + 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, + 0x14, 0x92, 0xD5, 0x0B, 0xDA, 0xF1, 0x04, 0x8B, 0xB9, 0xA1, + 0x8B, 0x03, 0x02, 0x9F, 0x58, 0x00, 0x35, 0x36, 0x07, 0x7A, + 0xC9, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0x86, 0xC0, 0x27, 0xE9, 0x9E, 0xFA, + 0x85, 0xC1, 0xFD, 0xE3, 0x6F, 0xFC, 0x54, 0x59, 0x72, 0x37, + 0xC7, 0x33, 0x92, 0xBB, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, + 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x03, 0x02, 0x01, 0xC6, + 0x00, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, 0x03, 0x41, + 0x00, 0x22, 0x1B, 0x06, 0x17, 0xC0, 0x11, 0x74, 0x1F, 0x64, + 0xD1, 0xA3, 0xF6, 0x7B, 0x06, 0x00, 0x1A, 0x0B, 0x50, 0x8E, + 0xEB, 0xB1, 0x63, 0x92, 0x45, 0xBA, 0xDC, 0xE2, 0xC1, 0x68, + 0x14, 0x23, 0x0C, 0x6E, 0x2C, 0x95, 0x3C, 0xB1, 0x1C, 0x19, + 0x27, 0x98, 0x50, 0x3E, 0x55, 0x51, 0xCC, 0xC4, 0x49, 0x58, + 0xAF, 0xB9, 0x46, 0x4F, 0xED, 0x9C, 0x57, 0x38, 0x04, 0x29, + 0xD4, 0xA9, 0x12, 0xFE, 0x08 +}; +static const int sizeof_ca_ed25519_cert = sizeof(ca_ed25519_cert); +#endif + #endif /* WOLFSSL_CERTS_TEST_H */ From a30e8eb4ade7aa67ff83db519b1dd0eef72fba28 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Wed, 31 May 2017 11:44:43 +1000 Subject: [PATCH 4/6] Fix for benchmarking X25519 --- examples/client/client.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index 6b81d3430..284f21e83 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -156,7 +156,7 @@ static void ShowVersions(void) /* Measures average time to create, connect and disconnect a connection (TPS). Benchmark = number of connections. */ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, - int dtlsUDP, int dtlsSCTP, int benchmark, int resumeSession) + int dtlsUDP, int dtlsSCTP, int benchmark, int resumeSession, int useX25519) { /* time passed in number of connects give average */ int times = benchmark; @@ -171,6 +171,7 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, #endif (void)resumeSession; + (void)useX25519; while (loops--) { #ifndef NO_SESSION_CACHE @@ -190,6 +191,16 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, #ifndef NO_SESSION_CACHE if (benchResume) wolfSSL_set_session(ssl, benchSession); + #endif + #ifdef WOLFSSL_TLS13 + #ifdef HAVE_CURVE25519 + else if (useX25519) { + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) + != SSL_SUCCESS) { + err_sys("unable to use curve secp256r1"); + } + } + #endif #endif if (wolfSSL_set_fd(ssl, sockfd) != SSL_SUCCESS) { err_sys("error in setting fd"); @@ -247,7 +258,7 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, /* Measures throughput in kbps. Throughput = number of bytes */ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, - int dtlsUDP, int dtlsSCTP, int throughput) + int dtlsUDP, int dtlsSCTP, int throughput, int useX25519) { double start, conn_time = 0, tx_time = 0, rx_time = 0; SOCKET_T sockfd; @@ -264,6 +275,18 @@ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, err_sys("error in setting fd"); } + (void)useX25519; + #ifdef WOLFSSL_TLS13 + #ifdef HAVE_CURVE25519 + if (useX25519) { + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) + != SSL_SUCCESS) { + err_sys("unable to use curve secp256r1"); + } + } + #endif + #endif + do { err = 0; /* reset error */ ret = wolfSSL_connect(ssl); @@ -735,9 +758,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) int useOcsp = 0; char* ocspUrl = NULL; #endif -#ifdef HAVE_CURVE25519 int useX25519 = 0; -#endif #ifdef HAVE_WNR const char* wnrConfigFile = wnrConfig; @@ -771,6 +792,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) (void)alpnList; (void)alpn_opt; (void)updateKeysIVs; + (void)useX25519; StackTrap(); @@ -1479,7 +1501,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (benchmark) { ((func_args*)args)->return_code = ClientBenchmarkConnections(ctx, host, port, dtlsUDP, dtlsSCTP, - benchmark, resumeSession); + benchmark, resumeSession, useX25519); wolfSSL_CTX_free(ctx); exit(EXIT_SUCCESS); } @@ -1487,7 +1509,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if(throughput) { ((func_args*)args)->return_code = ClientBenchmarkThroughput(ctx, host, port, dtlsUDP, dtlsSCTP, - throughput); + throughput, useX25519); wolfSSL_CTX_free(ctx); exit(EXIT_SUCCESS); } From 1db52f0c0448d1d7afeb564d49ad6eb4d9320aae Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Tue, 6 Jun 2017 10:52:48 +1000 Subject: [PATCH 5/6] Fix to use different PEM header for EDDSA keys Include new cert and key files in distribution Fix compile issue when only doing TLS13. --- certs/ed25519/ca-ed25519-key.pem | 4 +-- certs/ed25519/client-ed25519-key.pem | 4 +-- certs/ed25519/root-ed25519-key.pem | 4 +-- certs/ed25519/server-ed25519-key.pem | 4 +-- certs/include.am | 17 +++++++++++ src/ssl.c | 44 +++++++++++++++++----------- src/tls13.c | 2 ++ wolfcrypt/src/asn.c | 20 +++++++------ wolfssl/wolfcrypt/asn.h | 2 ++ wolfssl/wolfcrypt/asn_public.h | 1 + 10 files changed, 68 insertions(+), 34 deletions(-) diff --git a/certs/ed25519/ca-ed25519-key.pem b/certs/ed25519/ca-ed25519-key.pem index a78c396f7..e21c1100c 100644 --- a/certs/ed25519/ca-ed25519-key.pem +++ b/certs/ed25519/ca-ed25519-key.pem @@ -1,4 +1,4 @@ ------BEGIN RSA PRIVATE KEY----- +-----BEGIN EDDSA PRIVATE KEY----- MFICAQAwBQYDK2VwBCIEIE3EyZVR/gbofvUgIsCeuA3yZ9E7DbTQxW7HMDYQhbxl oSIEIEEH7HUMaHISPASCB24Wb0BBbaSPCPLinadDwiQomH6s ------END RSA PRIVATE KEY----- +-----END EDDSA PRIVATE KEY----- diff --git a/certs/ed25519/client-ed25519-key.pem b/certs/ed25519/client-ed25519-key.pem index b35d30898..fc4eef62f 100644 --- a/certs/ed25519/client-ed25519-key.pem +++ b/certs/ed25519/client-ed25519-key.pem @@ -1,4 +1,4 @@ ------BEGIN RSA PRIVATE KEY----- +-----BEGIN EDDSA PRIVATE KEY----- MFICAQAwBQYDK2VwBCIEIBGdNYxa3ommO8aYO1oGaGSRQBqDYB0sKOdR3bqejqIQ oSIEIDY9UZ60w5FgsDoJuIdapQUPW1PlZBc+cLkNZhKk5fFR ------END RSA PRIVATE KEY----- +-----END EDDSA PRIVATE KEY----- diff --git a/certs/ed25519/root-ed25519-key.pem b/certs/ed25519/root-ed25519-key.pem index be922d961..2db2a669e 100644 --- a/certs/ed25519/root-ed25519-key.pem +++ b/certs/ed25519/root-ed25519-key.pem @@ -1,4 +1,4 @@ ------BEGIN RSA PRIVATE KEY----- +-----BEGIN EDDSA PRIVATE KEY----- MFICAQAwBQYDK2VwBCIEIFwOftlJ9QL4yEBIBh9UmTRwCu+A6puPK9OFmVk0A19P oSIEIKZgKbt92EfL1B7QbQ9XANgqH1BqQrxd5bgZZbLfJK9Q ------END RSA PRIVATE KEY----- +-----END EDDSA PRIVATE KEY----- diff --git a/certs/ed25519/server-ed25519-key.pem b/certs/ed25519/server-ed25519-key.pem index 5699e0a7c..1f1e769ce 100644 --- a/certs/ed25519/server-ed25519-key.pem +++ b/certs/ed25519/server-ed25519-key.pem @@ -1,4 +1,4 @@ ------BEGIN RSA PRIVATE KEY----- +-----BEGIN EDDSA PRIVATE KEY----- MFICAQAwBQYDK2VwBCIEINjpdrI/H/eIdfXd+HrGSTBu6Z/LnR4rwBjvu3WJ5ndn oSIEIBowiBhHL5faBPSk471sDBa5SMHRQteOkoSgdCpDng4p ------END RSA PRIVATE KEY----- +-----END EDDSA PRIVATE KEY----- diff --git a/certs/include.am b/certs/include.am index e9b8e5c5d..72ef15232 100644 --- a/certs/include.am +++ b/certs/include.am @@ -55,6 +55,23 @@ EXTRA_DIST += \ certs/server-ecc.der \ certs/server-ecc-rsa.der \ certs/server-cert-chain.der +EXTRA_DIST += \ + certs/ed25519/ca-ed25519.der \ + certs/ed25519/ca-ed25519-key.der \ + certs/ed25519/ca-ed25519-key.pem \ + certs/ed25519/ca-ed25519.pem \ + certs/ed25519/client-ed25519.der \ + certs/ed25519/client-ed25519-key.der \ + certs/ed25519/client-ed25519-key.pem \ + certs/ed25519/client-ed25519.pem \ + certs/ed25519/root-ed25519.der \ + certs/ed25519/root-ed25519-key.der \ + certs/ed25519/root-ed25519-key.pem \ + certs/ed25519/root-ed25519.pem \ + certs/ed25519/server-ed25519.der \ + certs/ed25519/server-ed25519-key.der \ + certs/ed25519/server-ed25519-key.pem \ + certs/ed25519/server-ed25519.pem dist_doc_DATA+= certs/taoCert.txt diff --git a/src/ssl.c b/src/ssl.c index 59a18ec42..23d7bce00 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -4035,16 +4035,28 @@ int PemToDer(const unsigned char* buff, long longSz, int type, switch (type) { case CA_TYPE: /* same as below */ case TRUSTED_PEER_TYPE: - case CERT_TYPE: header=BEGIN_CERT; footer=END_CERT; break; - case CRL_TYPE: header=BEGIN_X509_CRL; footer=END_X509_CRL; break; - case DH_PARAM_TYPE: header=BEGIN_DH_PARAM; footer=END_DH_PARAM; break; - case DSA_PARAM_TYPE: header=BEGIN_DSA_PARAM; footer=END_DSA_PARAM; break; - case CERTREQ_TYPE: header=BEGIN_CERT_REQ; footer=END_CERT_REQ; break; - case DSA_TYPE: header=BEGIN_DSA_PRIV; footer=END_DSA_PRIV; break; - case ECC_TYPE: header=BEGIN_EC_PRIV; footer=END_EC_PRIV; break; - case RSA_TYPE: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; break; - case PUBLICKEY_TYPE: header=BEGIN_PUB_KEY; footer=END_PUB_KEY; break; - default: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; break; + case CERT_TYPE: header=BEGIN_CERT; footer=END_CERT; + break; + case CRL_TYPE: header=BEGIN_X509_CRL; footer=END_X509_CRL; + break; + case DH_PARAM_TYPE: header=BEGIN_DH_PARAM; footer=END_DH_PARAM; + break; + case DSA_PARAM_TYPE: header=BEGIN_DSA_PARAM; footer=END_DSA_PARAM; + break; + case CERTREQ_TYPE: header=BEGIN_CERT_REQ; footer=END_CERT_REQ; + break; + case DSA_TYPE: header=BEGIN_DSA_PRIV; footer=END_DSA_PRIV; + break; + case ECC_TYPE: header=BEGIN_EC_PRIV; footer=END_EC_PRIV; + break; + case RSA_TYPE: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; + break; + case ED25519_TYPE: header=BEGIN_EDDSA_PRIV; footer=END_EDDSA_PRIV; + break; + case PUBLICKEY_TYPE: header=BEGIN_PUB_KEY; footer=END_PUB_KEY; + break; + default: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; + break; } /* find header */ @@ -4061,6 +4073,8 @@ int PemToDer(const unsigned char* buff, long longSz, int type, header = BEGIN_EC_PRIV; footer = END_EC_PRIV; } else if (header == BEGIN_EC_PRIV) { header = BEGIN_DSA_PRIV; footer = END_DSA_PRIV; + } else if (header == BEGIN_DSA_PRIV) { + header = BEGIN_EDDSA_PRIV; footer = END_EDDSA_PRIV; } else break; } @@ -4685,6 +4699,8 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, resetSuites = 1; } } + else + eccKey = 0; wc_ecc_free(&key); } @@ -4707,7 +4723,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, return SSL_BAD_FILE; } - /* check for minimum ECC key size and then free */ + /* check for minimum key size and then free */ if (ssl) { if (ED25519_KEY_SIZE < ssl->options.minEccKeySz) { wc_ed25519_free(&key); @@ -4725,12 +4741,6 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, wc_ed25519_free(&key); ed25519Key = 1; - if (ssl) { - ssl->options.haveStaticECC = 1; - } - else if (ctx) { - ctx->haveStaticECC = 1; - } if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { resetSuites = 1; diff --git a/src/tls13.c b/src/tls13.c index 3679c06d0..e649bc467 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -4190,10 +4190,12 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, } /* Check for public key of required type. */ + #ifdef HAVE_ED25519 if (args->sigAlgo == ed25519_sa_algo && !ssl->peerEd25519KeyPresent) { WOLFSSL_MSG("Oops, peer sent ED25519 key but not in verify"); } + #endif if (args->sigAlgo == ecc_dsa_sa_algo && !ssl->peerEccDsaKeyPresent) { WOLFSSL_MSG("Oops, peer sent ECC key but not in verify"); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 51df86d6b..180179eff 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -6550,6 +6550,8 @@ const char* BEGIN_DSA_PRIV = "-----BEGIN DSA PRIVATE KEY-----"; const char* END_DSA_PRIV = "-----END DSA PRIVATE KEY-----"; const char* BEGIN_PUB_KEY = "-----BEGIN PUBLIC KEY-----"; const char* END_PUB_KEY = "-----END PUBLIC KEY-----"; +const char* BEGIN_EDDSA_PRIV = "-----BEGIN EDDSA PRIVATE KEY-----"; +const char* END_EDDSA_PRIV = "-----END EDDSA PRIVATE KEY-----"; #if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) || defined(OPENSSL_EXTRA) @@ -6625,6 +6627,15 @@ int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz, XSTRNCAT(footer, "\n", 1); } #endif +#ifdef HAVE_ED25519 + else if (type == EDDSA_PRIVATEKEY_TYPE) { + XSTRNCPY(header, BEGIN_EDDSA_PRIV, headerLen); + XSTRNCAT(header, "\n", 1); + + XSTRNCPY(footer, END_EDDSA_PRIV, footerLen); + XSTRNCAT(footer, "\n", 1); + } +#endif #ifdef WOLFSSL_CERT_REQ else if (type == CERTREQ_TYPE) { @@ -10230,15 +10241,6 @@ int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx, if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) return BAD_FUNC_ARG; - if (GetOctetString(input, inOutIdx, &privSz, inSz) >= 0) { - priv = input + *inOutIdx; - *inOutIdx += privSz; - - if (*inOutIdx != inSz) - return ASN_PARSE_E; - return wc_ed25519_import_private_only(priv, privSz, key); - } - if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; endKeyIdx = *inOutIdx + length; diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index f2c5c9aa5..1b732fa55 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -660,6 +660,8 @@ extern const char* BEGIN_DSA_PRIV; extern const char* END_DSA_PRIV; extern const char* BEGIN_PUB_KEY; extern const char* END_PUB_KEY; +extern const char* BEGIN_EDDSA_PRIV; +extern const char* END_EDDSA_PRIV; #ifdef NO_SHA #define SIGNER_DIGEST_SIZE SHA256_DIGEST_SIZE diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 9adf13cf5..0b4a8653b 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -66,6 +66,7 @@ enum CertType { RSA_PUBLICKEY_TYPE, ECC_PUBLICKEY_TYPE, TRUSTED_PEER_TYPE, + EDDSA_PRIVATEKEY_TYPE, ED25519_TYPE }; From 3429b5a3b5bd736f302b89d93528de5464aa106b Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Thu, 8 Jun 2017 09:24:39 +1000 Subject: [PATCH 6/6] Rework CheckPrivateKey --- wolfcrypt/src/asn.c | 163 +++++++++++++++++++------------------------- 1 file changed, 69 insertions(+), 94 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 180179eff..1863c2b81 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -2073,132 +2073,107 @@ int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz, * der : a initialized and parsed DecodedCert holding a certificate */ int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der) { + int ret; + if (key == NULL || der == NULL) { return BAD_FUNC_ARG; } #if !defined(NO_RSA) - { + /* test if RSA key */ + if (der->keyOID == RSAk) { RsaKey a, b; word32 keyIdx = 0; - int ret = 0; - /* test if RSA key */ - if (der->keyOID == RSAk) { - if (wc_InitRsaKey(&a, NULL) == 0 && - wc_RsaPrivateKeyDecode(key, &keyIdx, &a, keySz) == 0) { - WOLFSSL_MSG("Checking RSA key pair"); - keyIdx = 0; /* reset to 0 for parsing public key */ - - if (wc_InitRsaKey(&b, NULL) == 0) { - if ((ret = wc_RsaPublicKeyDecode(der->publicKey, &keyIdx, - &b, der->pubKeySize)) == 0) { - /* limit for user RSA crypto because of RsaKey - * dereference. */ - #if defined(HAVE_USER_RSA) - WOLFSSL_MSG("Cannot verify RSA pair with user RSA"); - wc_FreeRsaKey(&b); - wc_FreeRsaKey(&a); - return 1; /* return first RSA cert as match */ - #else - /* both keys extracted successfully now check n and e - * values are the same. This is dereferencing RsaKey */ - if (mp_cmp(&(a.n), &(b.n)) != MP_EQ || - mp_cmp(&(a.e), &(b.e)) != MP_EQ) { - ret = MP_CMP_E; - } - else { - /* match found, free keys and return success */ - wc_FreeRsaKey(&b); - wc_FreeRsaKey(&a); - return 1; - } - #endif - } - wc_FreeRsaKey(&b); - } - } + if ((ret = wc_InitRsaKey(&a, NULL)) < 0) + return ret; + if ((ret = wc_InitRsaKey(&b, NULL)) < 0) { wc_FreeRsaKey(&a); - } - - /* if ret is not 0 then there was a failed comparision attempt */ - if (ret != 0) { return ret; } + if ((ret = wc_RsaPrivateKeyDecode(key, &keyIdx, &a, keySz)) == 0) { + WOLFSSL_MSG("Checking RSA key pair"); + keyIdx = 0; /* reset to 0 for parsing public key */ + + if ((ret = wc_RsaPublicKeyDecode(der->publicKey, &keyIdx, &b, + der->pubKeySize)) == 0) { + /* limit for user RSA crypto because of RsaKey + * dereference. */ + #if defined(HAVE_USER_RSA) + WOLFSSL_MSG("Cannot verify RSA pair with user RSA"); + ret = 1; /* return first RSA cert as match */ + #else + /* both keys extracted successfully now check n and e + * values are the same. This is dereferencing RsaKey */ + if (mp_cmp(&(a.n), &(b.n)) != MP_EQ || + mp_cmp(&(a.e), &(b.e)) != MP_EQ) { + ret = MP_CMP_E; + } + else + ret = 1; + #endif + } + } + wc_FreeRsaKey(&b); + wc_FreeRsaKey(&a); } + else #endif /* NO_RSA */ #ifdef HAVE_ECC - { - int ret = 0; + if (der->keyOID == ECDSAk) { word32 keyIdx = 0; ecc_key key_pair; - if (der->keyOID == ECDSAk) { - if ((ret = wc_ecc_init(&key_pair)) == 0 && - wc_EccPrivateKeyDecode(key, &keyIdx, &key_pair, keySz) == 0) { - WOLFSSL_MSG("Checking ECC key pair"); - keyIdx = 0; - if ((ret = wc_ecc_import_x963(der->publicKey, der->pubKeySize, - &key_pair)) == 0) { - /* public and private extracted successfuly no check if is - * a pair and also do sanity checks on key. wc_ecc_check_key - * checks that private * base generator equals pubkey */ - if ((ret = wc_ecc_check_key(&key_pair)) == 0) { - /* found a match */ - wc_ecc_free(&key_pair); - return 1; - } - - } - } - wc_ecc_free(&key_pair); - } - - /* error on attempt to match */ - if (ret != 0) { + if ((ret = wc_ecc_init(&key_pair)) < 0) return ret; + if ((ret = wc_EccPrivateKeyDecode(key, &keyIdx, &key_pair, + keySz)) == 0) { + WOLFSSL_MSG("Checking ECC key pair"); + keyIdx = 0; + if ((ret = wc_ecc_import_x963(der->publicKey, der->pubKeySize, + &key_pair)) == 0) { + /* public and private extracted successfuly no check if is + * a pair and also do sanity checks on key. wc_ecc_check_key + * checks that private * base generator equals pubkey */ + if ((ret = wc_ecc_check_key(&key_pair)) == 0) + ret = 1; + } } + wc_ecc_free(&key_pair); } + else #endif /* HAVE_ECC */ #ifdef HAVE_ED25519 - { - int ret = 0; + if (der->keyOID == ED25519k) { word32 keyIdx = 0; ed25519_key key_pair; - if (der->keyOID == ED25519k) { - if ((ret = wc_ed25519_init(&key_pair)) == 0 && - wc_Ed25519PrivateKeyDecode(key, &keyIdx, &key_pair, keySz) - == 0) { - WOLFSSL_MSG("Checking ED25519 key pair"); - keyIdx = 0; - if ((ret = wc_ed25519_import_public(der->publicKey, - der->pubKeySize, &key_pair)) == 0) { - /* public and private extracted successfuly no check if is - * a pair and also do sanity checks on key. wc_ecc_check_key - * checks that private * base generator equals pubkey */ - if ((ret = wc_ed25519_check_key(&key_pair)) == 0) { - /* found a match */ - wc_ed25519_free(&key_pair); - return 1; - } - - } - } - wc_ed25519_free(&key_pair); - } - - /* error on attempt to match */ - if (ret != 0) { + if ((ret = wc_ed25519_init(&key_pair)) < 0) return ret; + if ((ret = wc_Ed25519PrivateKeyDecode(key, &keyIdx, &key_pair, + keySz)) == 0) { + WOLFSSL_MSG("Checking ED25519 key pair"); + keyIdx = 0; + if ((ret = wc_ed25519_import_public(der->publicKey, der->pubKeySize, + &key_pair)) == 0) { + /* public and private extracted successfuly no check if is + * a pair and also do sanity checks on key. wc_ecc_check_key + * checks that private * base generator equals pubkey */ + if ((ret = wc_ed25519_check_key(&key_pair)) == 0) + ret = 1; + } } + wc_ed25519_free(&key_pair); } + else #endif + { + ret = 0; + } - /* no match found */ - return 0; + return ret; } #ifndef NO_PWDBASED