Merge pull request #1523 from SparkiDev/ed25519_key

Allow Ed25519 private-only keys to work in TLS
This commit is contained in:
toddouska 2018-05-24 09:56:17 -07:00 committed by GitHub
commit 453daee965
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 435 additions and 152 deletions

Binary file not shown.

View File

@ -0,0 +1,3 @@
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIBGdNYxa3ommO8aYO1oGaGSRQBqDYB0sKOdR3bqejqIQ
-----END PRIVATE KEY-----

Binary file not shown.

View File

@ -0,0 +1,3 @@
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEINjpdrI/H/eIdfXd+HrGSTBu6Z/LnR4rwBjvu3WJ5ndn
-----END PRIVATE KEY-----

View File

@ -72,6 +72,8 @@ EXTRA_DIST += \
certs/ed25519/client-ed25519-key.der \
certs/ed25519/client-ed25519-key.pem \
certs/ed25519/client-ed25519.pem \
certs/ed25519/client-ed25519-priv.pem \
certs/ed25519/client-ed25519-priv.pem \
certs/ed25519/root-ed25519.der \
certs/ed25519/root-ed25519-key.der \
certs/ed25519/root-ed25519-key.pem \
@ -79,7 +81,9 @@ EXTRA_DIST += \
certs/ed25519/server-ed25519.der \
certs/ed25519/server-ed25519-key.der \
certs/ed25519/server-ed25519-key.pem \
certs/ed25519/server-ed25519.pem
certs/ed25519/server-ed25519.pem \
certs/ed25519/server-ed25519-priv.der \
certs/ed25519/server-ed25519-priv.pem
# ECC CA prime256v1
EXTRA_DIST += \

View File

@ -874,7 +874,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
int err = 0;
int scr = 0; /* allow secure renegotiation */
int forceScr = 0; /* force client initiaed scr */
#ifndef WOLFSSL_NO_CLIENT_AUTH
int useClientCert = 1;
#else
int useClientCert = 0;
#endif
int fewerPackets = 0;
int atomicUser = 0;
#ifdef HAVE_PK_CALLBACKS

View File

@ -405,6 +405,9 @@ static void Usage(void)
printf("-n Use NTRU key (needed for NTRU suites)\n");
#endif
printf("-B <num> Benchmark throughput using <num> bytes and print stats\n");
#ifdef HAVE_CRL
printf("-V Disable CRL\n");
#endif
#ifdef WOLFSSL_TRUST_PEER_CERT
printf("-E <file> Path to load trusted peer cert\n");
#endif
@ -462,7 +465,14 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
char input[80];
int ch;
int version = SERVER_DEFAULT_VERSION;
#ifndef WOLFSSL_NO_CLIENT_AUTH
int doCliCertCheck = 1;
#else
int doCliCertCheck = 0;
#endif
#ifdef HAVE_CRL
int disableCRL = 0;
#endif
int useAnyAddr = 0;
word16 port = wolfSSLPort;
int usePsk = 0;
@ -601,7 +611,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
/* Not Used: h, m, z, F, M, T, V, W, X */
while ((ch = mygetopt(argc, argv, "?"
"abc:defgijk:l:nop:q:rstuv:wxy"
"A:B:C:D:E:GH:IJKL:NO:PQR:S:TUYZ:"
"A:B:C:D:E:GH:IJKL:NO:PQR:S:TUVYZ:"
"03:")) != -1) {
switch (ch) {
case '?' :
@ -616,6 +626,12 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
doCliCertCheck = 0;
break;
case 'V' :
#ifdef HAVE_CRL
disableCRL = 1;
#endif
break;
case 'b' :
useAnyAddr = 1;
break;
@ -1286,6 +1302,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
wolfSSL_SetHsDoneCb(ssl, myHsDoneCb, NULL);
#endif
#ifdef HAVE_CRL
if (!disableCRL) {
#ifdef HAVE_CRL_MONITOR
crlFlags = CYASSL_CRL_MONITOR | CYASSL_CRL_START_MON;
#endif
@ -1296,6 +1313,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
err_sys_ex(runWithErrors, "unable to load CRL");
if (CyaSSL_SetCRL_Cb(ssl, CRL_CallBack) != WOLFSSL_SUCCESS)
err_sys_ex(runWithErrors, "unable to set CRL callback url");
}
#endif
#ifdef HAVE_OCSP
if (useOcsp) {
@ -1567,17 +1585,19 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
if (postHandAuth) {
SSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER |
((usePskPlus)? WOLFSSL_VERIFY_FAIL_EXCEPT_PSK :
WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT),0);
((usePskPlus) ? WOLFSSL_VERIFY_FAIL_EXCEPT_PSK :
WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT), 0);
if (SSL_CTX_load_verify_locations(ctx, verifyCert, 0)
!= WOLFSSL_SUCCESS) {
err_sys_ex(runWithErrors, "can't load ca file, Please run from wolfSSL home dir");
!= WOLFSSL_SUCCESS) {
err_sys_ex(runWithErrors, "can't load ca file, Please run from "
"wolfSSL home dir");
}
#ifdef WOLFSSL_TRUST_PEER_CERT
if (trustCert) {
if ((ret = wolfSSL_CTX_trust_peer_cert(ctx, trustCert,
WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) {
err_sys_ex(runWithErrors, "can't load trusted peer cert file");
WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) {
err_sys_ex(runWithErrors, "can't load trusted peer cert "
"file");
}
}
#endif /* WOLFSSL_TRUST_PEER_CERT */

View File

@ -103,7 +103,8 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS
#ifndef NO_WOLFSSL_SERVER
static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32*, word32);
#if !defined(NO_RSA) || defined(HAVE_ECC)
#if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)) && \
!defined(WOLFSSL_NO_CLIENT_AUTH)
static int DoCertificateVerify(WOLFSSL* ssl, byte*, word32*, word32);
#endif
#ifdef WOLFSSL_DTLS
@ -2692,7 +2693,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
*
* input The encoded signature algorithm.
* hashalgo The hash algorithm.
* hsType The signature type.
* hsType The signature type.
*/
static INLINE void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType)
{
@ -2888,35 +2889,37 @@ static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output)
(void)output;
}
#if !defined(WOLFSSL_NO_CLIENT_AUTH)
static void SetDigest(WOLFSSL* ssl, int hashAlgo)
{
switch (hashAlgo) {
#ifndef NO_SHA
#ifndef NO_SHA
case sha_mac:
ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha;
ssl->buffers.digest.length = WC_SHA_DIGEST_SIZE;
break;
#endif /* !NO_SHA */
#ifndef NO_SHA256
#endif /* !NO_SHA */
#ifndef NO_SHA256
case sha256_mac:
ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256;
ssl->buffers.digest.length = WC_SHA256_DIGEST_SIZE;
break;
#endif /* !NO_SHA256 */
#ifdef WOLFSSL_SHA384
#endif /* !NO_SHA256 */
#ifdef WOLFSSL_SHA384
case sha384_mac:
ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384;
ssl->buffers.digest.length = WC_SHA384_DIGEST_SIZE;
break;
#endif /* WOLFSSL_SHA384 */
#ifdef WOLFSSL_SHA512
#endif /* WOLFSSL_SHA384 */
#ifdef WOLFSSL_SHA512
case sha512_mac:
ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512;
ssl->buffers.digest.length = WC_SHA512_DIGEST_SIZE;
break;
#endif /* WOLFSSL_SHA512 */
#endif /* WOLFSSL_SHA512 */
} /* switch */
}
#endif /* !WOLFSSL_NO_CLIENT_AUTH */
#endif /* !NO_CERTS */
#ifndef NO_RSA
@ -3632,6 +3635,43 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer)
#endif /* HAVE_ECC */
#ifdef HAVE_ED25519
/* Check whether the key contains a public key.
* If not then pull it out of the leaf certificate.
*
* ssl SSL/TLS object.
* returns MEMORY_E when unable to allocate memory, a parsing error, otherwise
* 0 on success.
*/
int Ed25519CheckPubKey(WOLFSSL* ssl)
{
ed25519_key* key = (ed25519_key*)ssl->hsKey;
int ret = 0;
/* Public key required for signing. */
if (!key->pubKeySet) {
DerBuffer* leaf = ssl->buffers.certificate;
DecodedCert* cert = (DecodedCert*)XMALLOC(sizeof(*cert),
ssl->heap, DYNAMIC_TYPE_DCERT);
if (cert == NULL)
ret = MEMORY_E;
if (ret == 0) {
InitDecodedCert(cert, leaf->buffer, leaf->length, ssl->heap);
ret = DecodeToKey(cert, 0);
}
if (ret == 0) {
ret = wc_ed25519_import_public(cert->publicKey, cert->pubKeySize,
key);
}
if (cert != NULL) {
FreeDecodedCert(cert);
XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
}
}
return ret;
}
/* Sign the data using EdDSA and key using X25519.
*
* ssl SSL object.
@ -4138,6 +4178,12 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
ssl->buffers.keyType = ctx->privateKeyType;
ssl->buffers.keySz = ctx->privateKeySz;
#endif
#if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
!defined(NO_ED25519_CLIENT_AUTH)
ssl->options.cacheMessages = ssl->options.side == WOLFSSL_SERVER_END ||
ssl->buffers.keyType == ed25519_sa_algo;
#endif
#ifdef WOLFSSL_ASYNC_CRYPT
ssl->devId = ctx->devId;
@ -4287,6 +4333,12 @@ void FreeHandshakeHashes(WOLFSSL* ssl)
#ifdef WOLFSSL_SHA512
wc_Sha512Free(&ssl->hsHashes->hashSha512);
#endif
#if defined(HAVE_ED25519) && !defined(WOLFSSL_NO_CLIENT_AUTH)
if (ssl->hsHashes->messages != NULL) {
XFREE(ssl->hsHashes->messages, ssl->heap, DYNAMIC_TYPE_HASHES);
ssl->hsHashes->messages = NULL;
}
#endif
XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES);
ssl->hsHashes = NULL;
@ -5994,7 +6046,37 @@ ProtocolVersion MakeDTLSv1_2(void)
return (word32)XTIME(0);
}
#endif
#if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
!defined(NO_ED25519_CLIENT_AUTH)
/* Store the message for use with CertificateVerify using Ed25519.
*
* ssl SSL/TLS object.
* data Message to store.
* sz Size of message to store.
* returns MEMORY_E if not able to reallocate, otherwise 0.
*/
static int Ed25519Update(WOLFSSL* ssl, const byte* data, int sz)
{
int ret = 0;
byte* msgs;
if (ssl->options.cacheMessages) {
msgs = (byte*)XREALLOC(ssl->hsHashes->messages,
ssl->hsHashes->length + sz,
ssl->heap, DYNAMIC_TYPE_HASHES);
if (msgs == NULL)
ret = MEMORY_E;
if (ret == 0) {
ssl->hsHashes->messages = msgs;
XMEMCPY(msgs + ssl->hsHashes->length, data, sz);
ssl->hsHashes->prevLen = ssl->hsHashes->length;
ssl->hsHashes->length += sz;
}
}
return ret;
}
#endif /* HAVE_ED25519 && !WOLFSSL_NO_CLIENT_AUTH */
#ifndef NO_CERTS
int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz)
@ -6012,30 +6094,36 @@ int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz)
ssl->fuzzerCb(ssl, output, sz, FUZZ_HASH, ssl->fuzzerCtx);
#endif
#ifndef NO_OLD_TLS
#ifndef NO_SHA
wc_ShaUpdate(&ssl->hsHashes->hashSha, output, sz);
#endif
#ifndef NO_MD5
wc_Md5Update(&ssl->hsHashes->hashMd5, output, sz);
#endif
#ifndef NO_SHA
wc_ShaUpdate(&ssl->hsHashes->hashSha, output, sz);
#endif
#ifndef NO_MD5
wc_Md5Update(&ssl->hsHashes->hashMd5, output, sz);
#endif
#endif /* NO_OLD_TLS */
if (IsAtLeastTLSv1_2(ssl)) {
#ifndef NO_SHA256
#ifndef NO_SHA256
ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, output, sz);
if (ret != 0)
return ret;
#endif
#ifdef WOLFSSL_SHA384
#endif
#ifdef WOLFSSL_SHA384
ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, output, sz);
if (ret != 0)
return ret;
#endif
#ifdef WOLFSSL_SHA512
#endif
#ifdef WOLFSSL_SHA512
ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, output, sz);
if (ret != 0)
return ret;
#endif
#endif
#if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
!defined(NO_ED25519_CLIENT_AUTH)
ret = Ed25519Update(ssl, output, sz);
if (ret != 0)
return ret;
#endif
}
return ret;
@ -6063,30 +6151,36 @@ int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz)
}
#endif
#ifndef NO_OLD_TLS
#ifndef NO_SHA
wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz);
#endif
#ifndef NO_MD5
wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz);
#endif
#ifndef NO_SHA
wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz);
#endif
#ifndef NO_MD5
wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz);
#endif
#endif
if (IsAtLeastTLSv1_2(ssl)) {
#ifndef NO_SHA256
#ifndef NO_SHA256
ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, adj, sz);
if (ret != 0)
return ret;
#endif
#ifdef WOLFSSL_SHA384
#endif
#ifdef WOLFSSL_SHA384
ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, adj, sz);
if (ret != 0)
return ret;
#endif
#ifdef WOLFSSL_SHA512
#endif
#ifdef WOLFSSL_SHA512
ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, adj, sz);
if (ret != 0)
return ret;
#endif
#endif
#if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
!defined(NO_ED25519_CLIENT_AUTH)
ret = Ed25519Update(ssl, adj, sz);
if (ret != 0)
return ret;
#endif
}
return ret;
@ -6116,30 +6210,36 @@ int HashInput(WOLFSSL* ssl, const byte* input, int sz)
}
#ifndef NO_OLD_TLS
#ifndef NO_SHA
wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz);
#endif
#ifndef NO_MD5
wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz);
#endif
#ifndef NO_SHA
wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz);
#endif
#ifndef NO_MD5
wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz);
#endif
#endif
if (IsAtLeastTLSv1_2(ssl)) {
#ifndef NO_SHA256
#ifndef NO_SHA256
ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, adj, sz);
if (ret != 0)
return ret;
#endif
#ifdef WOLFSSL_SHA384
#endif
#ifdef WOLFSSL_SHA384
ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, adj, sz);
if (ret != 0)
return ret;
#endif
#ifdef WOLFSSL_SHA512
#endif
#ifdef WOLFSSL_SHA512
ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, adj, sz);
if (ret != 0)
return ret;
#endif
#endif
#if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
!defined(NO_ED25519_CLIENT_AUTH)
ret = Ed25519Update(ssl, adj, sz);
if (ret != 0)
return ret;
#endif
}
return ret;
@ -9185,7 +9285,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
}
break;
}
#endif /* HAVE_ECC */
#endif /* HAVE_ED25519 */
default:
break;
}
@ -9408,7 +9508,7 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx,
int ret;
WOLFSSL_START(WC_FUNC_CERTIFICATE_DO);
WOLFSSL_ENTER("DoCertificateVerify");
WOLFSSL_ENTER("DoCertificate");
ret = ProcessPeerCerts(ssl, input, inOutIdx, size);
@ -9416,7 +9516,7 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx,
ssl->options.serverState = SERVER_CERT_COMPLETE;
#endif
WOLFSSL_LEAVE("DoCertificateVerify", ret);
WOLFSSL_LEAVE("DoCertificate", ret);
WOLFSSL_END(WC_FUNC_CERTIFICATE_DO);
return ret;
@ -10163,6 +10263,13 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
case server_hello:
WOLFSSL_MSG("processing server hello");
ret = DoServerHello(ssl, input, inOutIdx, size);
#if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
!defined(NO_ED25519_CLIENT_AUTH)
if (ssl->options.resuming || !IsAtLeastTLSv1_2(ssl) ||
IsAtLeastTLSv1_3(ssl->version)) {
ssl->options.cacheMessages = 0;
}
#endif
break;
#ifndef NO_CERTS
@ -10224,6 +10331,13 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
case client_hello:
WOLFSSL_MSG("processing client hello");
ret = DoClientHello(ssl, input, inOutIdx, size);
#if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
!defined(NO_ED25519_CLIENT_AUTH)
if (ssl->options.resuming || !ssl->options.verifyPeer || \
!IsAtLeastTLSv1_2(ssl) || IsAtLeastTLSv1_3(ssl->version)) {
ssl->options.cacheMessages = 0;
}
#endif
break;
case client_key_exchange:
@ -10231,12 +10345,13 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
ret = DoClientKeyExchange(ssl, input, inOutIdx, size);
break;
#if !defined(NO_RSA) || defined(HAVE_ECC)
#if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)) && \
!defined(WOLFSSL_NO_CLIENT_AUTH)
case certificate_verify:
WOLFSSL_MSG("processing certificate verify");
ret = DoCertificateVerify(ssl, input, inOutIdx, size);
break;
#endif /* !NO_RSA || HAVE_ECC */
#endif /* (!NO_RSA || HAVE_ECC || HAVE_ED25519) && !WOLFSSL_NO_CLIENT_AUTH */
#endif /* !NO_WOLFSSL_SERVER */
@ -13582,6 +13697,7 @@ int SendFinished(WOLFSSL* ssl)
#ifndef NO_CERTS
#if !defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH)
/* handle generation of certificate (11) */
int SendCertificate(WOLFSSL* ssl)
{
@ -13845,6 +13961,7 @@ int SendCertificate(WOLFSSL* ssl)
return ret;
}
#endif /* !NO_WOLFSSL_SERVER || !WOLFSSL_NO_CLIENT_AUTH */
/* handle generation of certificate_request (13) */
int SendCertificateRequest(WOLFSSL* ssl)
@ -17743,7 +17860,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
break;
}
#endif /* HAVE_ECC */
#ifdef HAVE_ED25519
#if defined(HAVE_ED25519)
case ed25519_sa_algo:
{
if (!ssl->peerEd25519KeyPresent) {
@ -17751,7 +17868,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
}
break;
}
#endif /* HAVE_ECC */
#endif /* HAVE_ED25519 */
default:
ret = ALGO_ID_E;
@ -17853,7 +17970,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
break;
}
#endif /* HAVE_ECC */
#ifdef HAVE_ED25519
#if defined(HAVE_ED25519)
case ed25519_sa_algo:
{
ret = Ed25519Verify(ssl,
@ -17871,7 +17988,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
break;
}
#endif /* HAVE_ECC */
#endif /* HAVE_ED25519 */
default:
ret = ALGO_ID_E;
@ -17981,11 +18098,11 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
/* Nothing to do in this algo */
break;
#endif /* HAVE_ECC */
#ifdef HAVE_ED25519
#if defined(HAVE_ED25519)
case ed25519_sa_algo:
/* Nothing to do in this algo */
break;
#endif /* HAVE_ECC */
#endif /* HAVE_ED25519 */
default:
ret = ALGO_ID_E;
} /* switch (sigAlgo) */
@ -19627,9 +19744,9 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
}
#endif
#ifdef HAVE_ED25519
#if !defined(NO_RSA) || defined(HAVE_ECC)
FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey);
#endif
#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);
@ -19637,13 +19754,13 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
goto exit_dpk;
}
#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
#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
/* Set start of data to beginning of buffer. */
idx = 0;
@ -19665,7 +19782,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
goto exit_dpk;
}
#endif
#endif /* HAVE_ED25519 */
(void)idx;
(void)keySz;
@ -19675,6 +19792,7 @@ exit_dpk:
}
#ifndef WOLFSSL_NO_CLIENT_AUTH
typedef struct ScvArgs {
byte* output; /* not allocated */
#ifndef NO_RSA
@ -19883,6 +20001,13 @@ int SendCertificateVerify(WOLFSSL* ssl)
c16toa(args->length, args->verify + args->extraSz);
}
#endif /* !NO_RSA */
#if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
if (args->sigAlgo == ed25519_sa_algo) {
ret = Ed25519CheckPubKey(ssl);
if (ret != 0)
goto exit_scv;
}
#endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
/* Advance state and proceed */
ssl->options.asyncState = TLS_ASYNC_DO;
@ -19908,12 +20033,12 @@ int SendCertificateVerify(WOLFSSL* ssl)
);
}
#endif /* HAVE_ECC */
#ifdef HAVE_ED25519
#if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
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->hsHashes->messages, ssl->hsHashes->length,
ssl->buffers.sig.buffer, &ssl->buffers.sig.length,
key,
#ifdef HAVE_PK_CALLBACKS
@ -19924,7 +20049,7 @@ int SendCertificateVerify(WOLFSSL* ssl)
#endif
);
}
#endif /* HAVE_ECC */
#endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
#ifndef NO_RSA
if (ssl->hsType == DYNAMIC_TYPE_RSA) {
RsaKey* key = (RsaKey*)ssl->hsKey;
@ -20133,6 +20258,7 @@ exit_scv:
return ret;
}
#endif /* WOLFSSL_NO_CLIENT_AUTH */
#endif /* NO_CERTS */
@ -21330,13 +21456,17 @@ 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;
}
#ifdef HAVE_ED25519
case ed25519_sa_algo:
ret = Ed25519CheckPubKey(ssl);
if (ret != 0)
goto exit_sske;
break;
#endif /* HAVE_ED25519 */
} /* switch(ssl->specs.sig_algo) */
break;
}
@ -21796,18 +21926,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
}
#endif
case ecc_dsa_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;
}
#ifdef HAVE_ED25519
case ed25519_sa_algo:
#endif
{
/* Now that we know the real sig size, write it. */
c16toa((word16)args->sigSz,
@ -21818,7 +21939,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
args->sendSz += args->sigSz - args->tmpSigSz;
break;
}
#endif
default:
ERROR_OUT(ALGO_ID_E, exit_sske); /* unsupported type */
} /* switch(ssl->specs.sig_algo) */
@ -22977,7 +23097,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
}
#if !defined(NO_RSA) || defined(HAVE_ECC)
#if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)) && \
!defined(WOLFSSL_NO_CLIENT_AUTH)
typedef struct DcvArgs {
byte* output; /* not allocated */
@ -23072,10 +23193,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
#if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
else if (ssl->peerEd25519KeyPresent)
args->sigAlgo = ed25519_sa_algo;
#endif
#endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
ERROR_OUT(BUFFER_ERROR, exit_dcv);
@ -23116,7 +23237,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
}
}
#endif /* HAVE_ECC */
#ifdef HAVE_ED25519
#if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
if (ssl->peerEd25519KeyPresent) {
WOLFSSL_MSG("Doing ED25519 peer cert verify");
if (IsAtLeastTLSv1_2(ssl) &&
@ -23125,7 +23246,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
"Oops, peer sent ED25519 key but not in verify");
}
}
#endif /* HAVE_ED25519 */
#endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
/* Advance state and proceed */
ssl->options.asyncState = TLS_ASYNC_DO;
@ -23179,6 +23300,23 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
);
}
#endif /* HAVE_ECC */
#if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
if (ssl->peerEd25519KeyPresent) {
WOLFSSL_MSG("Doing Ed25519 peer cert verify");
ret = Ed25519Verify(ssl,
input + args->idx, args->sz,
ssl->hsHashes->messages, ssl->hsHashes->prevLen,
ssl->peerEd25519Key,
#ifdef HAVE_PK_CALLBACKS
&ssl->buffers.peerEd25519Key,
ssl->Ed25519VerifyCtx
#else
NULL, NULL
#endif
);
}
#endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
/* Check for error */
if (ret != 0) {
@ -23311,7 +23449,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
return ret;
}
#endif /* !NO_RSA || HAVE_ECC */
#endif /* (!NO_RSA || HAVE_ECC || HAVE_ED25519) && !WOLFSSL_NO_CLIENT_AUTH */
/* handle generation of server_hello_done (14) */
int SendServerHelloDone(WOLFSSL* ssl)

View File

@ -8678,11 +8678,11 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
FALL_THROUGH;
case FIRST_REPLY_DONE :
#ifdef WOLFSSL_TLS13
if (ssl->options.tls1_3)
return wolfSSL_connect_TLSv13(ssl);
#endif
#ifndef NO_CERTS
#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH)
#ifdef WOLFSSL_TLS13
if (ssl->options.tls1_3)
return wolfSSL_connect_TLSv13(ssl);
#endif
if (ssl->options.sendVerify) {
if ( (ssl->error = SendCertificate(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
@ -8714,7 +8714,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
FALL_THROUGH;
case FIRST_REPLY_SECOND :
#ifndef NO_CERTS
#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH)
if (ssl->options.sendVerify) {
if ( (ssl->error = SendCertificateVerify(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
@ -8722,7 +8722,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
}
WOLFSSL_MSG("sent: certificate verify");
}
#endif
#endif /* !NO_CERTS && !WOLFSSL_NO_CLIENT_AUTH */
ssl->options.connectState = FIRST_REPLY_THIRD;
WOLFSSL_MSG("connect state: FIRST_REPLY_THIRD");
FALL_THROUGH;

View File

@ -5252,7 +5252,10 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl)
#endif /* HAVE_ECC */
#ifdef HAVE_ED25519
if (ssl->hsType == DYNAMIC_TYPE_ED25519) {
/* Nothing to do */
ret = Ed25519CheckPubKey(ssl);
if (ret < 0) {
ERROR_OUT(ret, exit_scv);
}
sig->length = ED25519_SIG_SIZE;
}
#endif /* HAVE_ECC */

View File

@ -10,21 +10,22 @@
-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
-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
-V
# Remove -V when CRL for ED25519 certificates available.
# 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
-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
@ -40,16 +41,19 @@
# 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
-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
-V
# Remove -V when CRL for ED25519 certificates available.
# 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
-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

View File

@ -12296,29 +12296,38 @@ int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx,
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 (GetSequence(input, inOutIdx, &length, inSz) >= 0) {
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 (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;
}
else {
if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0)
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;
priv = input + *inOutIdx;
*inOutIdx += privSz;
endKeyIdx = *inOutIdx;
}
if (endKeyIdx == (int)*inOutIdx) {
ret = wc_ed25519_import_private_only(priv, privSz, key);

View File

@ -90,6 +90,8 @@ int wc_ed25519_make_key(WC_RNG* rng, int keySz, ed25519_key* key)
/* put public key after private key, on the same buffer */
XMEMMOVE(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE);
key->pubKeySet = 1;
return ret;
}
@ -121,6 +123,8 @@ int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out,
/* sanity check on arguments */
if (in == NULL || out == NULL || outLen == NULL || key == NULL)
return BAD_FUNC_ARG;
if (!key->pubKeySet)
return BAD_FUNC_ARG;
/* check and set up out length */
if (*outLen < ED25519_SIG_SIZE) {
@ -370,6 +374,7 @@ int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key)
pubKey.Y = key->pointY;
LTC_PKHA_Ed25519_PointDecompress(key->p, ED25519_PUB_KEY_SIZE, &pubKey);
#endif
key->pubKeySet = 1;
return 0;
}
@ -389,6 +394,8 @@ int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key)
ret = ge_compress_key(key->p, in+1,
in+1+ED25519_PUB_KEY_SIZE, ED25519_PUB_KEY_SIZE);
#endif /* FREESCALE_LTC_ECC */
if (ret == 0)
key->pubKeySet = 1;
return ret;
}
@ -403,6 +410,7 @@ int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key)
pubKey.Y = key->pointY;
LTC_PKHA_Ed25519_PointDecompress(key->p, ED25519_PUB_KEY_SIZE, &pubKey);
#endif
key->pubKeySet = 1;
return 0;
}

View File

@ -17115,6 +17115,38 @@ int ed25519_test(void)
0 /*sizeof(msg1)*/,
sizeof(msg4)
};
static byte privateEd25519[] = {
0x30,0x2e,0x02,0x01,0x00,0x30,0x05,0x06,
0x03,0x2b,0x65,0x70,0x04,0x22,0x04,0x20,
0x9d,0x61,0xb1,0x9d,0xef,0xfd,0x5a,0x60,
0xba,0x84,0x4a,0xf4,0x92,0xec,0x2c,0xc4,
0x44,0x49,0xc5,0x69,0x7b,0x32,0x69,0x19,
0x70,0x3b,0xac,0x03,0x1c,0xae,0x7f,0x60
};
static byte publicEd25519[] = {
0x30,0x2a,0x30,0x05,0x06,0x03,0x2b,0x65,
0x70,0x03,0x21,0x00,0xd7,0x5a,0x98,0x01,
0x82,0xb1,0x0a,0xb7,0xd5,0x4b,0xfe,0xd3,
0xc9,0x64,0x07,0x3a,0x0e,0xe1,0x72,0xf3,
0xda,0xa6,0x23,0x25,0xaf,0x02,0x1a,0x68,
0xf7,0x07,0x51,0x1a
};
static byte privPubEd25519[] = {
0x30,0x52,0x02,0x01,0x00,0x30,0x05,0x06,
0x03,0x2b,0x65,0x70,0x04,0x22,0x04,0x20,
0x9d,0x61,0xb1,0x9d,0xef,0xfd,0x5a,0x60,
0xba,0x84,0x4a,0xf4,0x92,0xec,0x2c,0xc4,
0x44,0x49,0xc5,0x69,0x7b,0x32,0x69,0x19,
0x70,0x3b,0xac,0x03,0x1c,0xae,0x7f,0x60,
0xa1,0x22,0x04,0x20,0xd7,0x5a,0x98,0x01,
0x82,0xb1,0x0a,0xb7,0xd5,0x4b,0xfe,0xd3,
0xc9,0x64,0x07,0x3a,0x0e,0xe1,0x72,0xf3,
0xda,0xa6,0x23,0x25,0xaf,0x02,0x1a,0x68,
0xf7,0x07,0x51,0x1a
};
word32 idx;
ed25519_key key3;
#endif /* HAVE_ED25519_SIGN && HAVE_ED25519_KEY_EXPORT && HAVE_ED25519_KEY_IMPORT */
/* create ed25519 keys */
@ -17128,6 +17160,7 @@ int ed25519_test(void)
wc_ed25519_init(&key);
wc_ed25519_init(&key2);
wc_ed25519_init(&key3);
wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key);
wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key2);
@ -17145,8 +17178,7 @@ int ed25519_test(void)
pKeySz[i], &key) != 0)
return -8901 - i;
if (wc_ed25519_sign_msg(msgs[i], msgSz[i], out, &outlen, &key)
!= 0)
if (wc_ed25519_sign_msg(msgs[i], msgSz[i], out, &outlen, &key) != 0)
return -8911 - i;
if (XMEMCMP(out, sigs[i], 64))
@ -17196,6 +17228,50 @@ int ed25519_test(void)
return -9011 - i;
#endif /* HAVE_ED25519_VERIFY */
}
/* Try ASN.1 encoded private-only key and public key. */
idx = 0;
if (wc_Ed25519PrivateKeyDecode(privateEd25519, &idx, &key3,
sizeof(privateEd25519)) != 0)
return -7230 - i;
if (wc_ed25519_sign_msg(msgs[0], msgSz[0], out, &outlen, &key3)
!= BAD_FUNC_ARG)
return -7231 - i;
idx = 0;
if (wc_Ed25519PublicKeyDecode(publicEd25519, &idx, &key3,
sizeof(publicEd25519)) != 0)
return -7232 - i;
if (wc_ed25519_sign_msg(msgs[0], msgSz[0], out, &outlen, &key3) != 0)
return -7233 - i;
if (XMEMCMP(out, sigs[0], 64))
return -7234 - i;
#if defined(HAVE_ED25519_VERIFY)
/* test verify on good msg */
if (wc_ed25519_verify_msg(out, outlen, msgs[0], msgSz[0], &verify, &key3)
!= 0 || verify != 1)
return -7233 - i;
#endif /* HAVE_ED25519_VERIFY */
wc_ed25519_free(&key3);
wc_ed25519_init(&key3);
idx = 0;
if (wc_Ed25519PrivateKeyDecode(privPubEd25519, &idx, &key3,
sizeof(privPubEd25519)) != 0)
return -7230 - i;
if (wc_ed25519_sign_msg(msgs[0], msgSz[0], out, &outlen, &key3) != 0)
return -7233 - i;
if (XMEMCMP(out, sigs[0], 64))
return -7234 - i;
wc_ed25519_free(&key3);
#endif /* HAVE_ED25519_SIGN && HAVE_ED25519_KEY_EXPORT && HAVE_ED25519_KEY_IMPORT */
/* clean up keys when done */

View File

@ -3075,6 +3075,10 @@ typedef struct Options {
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
word16 sentChangeCipher:1; /* Change Cipher Spec sent */
#endif
#if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
!defined(NO_ED25519_CLIENT_AUTH)
word16 cacheMessages:1; /* Cache messages for sign/verify */
#endif
/* need full byte values for this section */
byte processReply; /* nonblocking resume */
@ -3369,6 +3373,11 @@ typedef struct HS_Hashes {
#ifdef WOLFSSL_SHA512
wc_Sha512 hashSha512; /* sha512 hash of handshake msgs */
#endif
#if defined(HAVE_ED25519) && !defined(WOLFSSL_NO_CLIENT_AUTH)
byte* messages; /* handshake messages */
int length; /* length of handhsake messages' data */
int prevLen; /* length of messages but last */
#endif
} HS_Hashes;
@ -3895,6 +3904,7 @@ WOLFSSL_LOCAL int wolfSSL_GetMaxRecordSize(WOLFSSL* ssl, int maxFragment);
word32* outlen, int side, void* ctx);
#endif /* HAVE_ECC */
#ifdef HAVE_ED25519
WOLFSSL_LOCAL int Ed25519CheckPubKey(WOLFSSL* ssl);
WOLFSSL_LOCAL int Ed25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz,
byte* out, word32* outSz, ed25519_key* key, DerBuffer* keyBufInfo,
void* ctx);

View File

@ -77,6 +77,7 @@ struct ed25519_key {
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
int pubKeySet:1;
#ifdef WOLFSSL_ASYNC_CRYPT
WC_ASYNC_DEV asyncDev;
#endif