diff --git a/ctaocrypt/src/asn.c b/ctaocrypt/src/asn.c index 56b420298..6629f8e66 100644 --- a/ctaocrypt/src/asn.c +++ b/ctaocrypt/src/asn.c @@ -4240,7 +4240,7 @@ static int DecodeSingleResponse(byte* source, if (GetBasicDate(source, &idx, cs->thisDate, &cs->thisDateFormat, size) < 0) return ASN_PARSE_E; - if (!ValidateDate(cs->thisDate, cs->thisDateFormat, BEFORE)) + if (!XVALIDATE_DATE(cs->thisDate, cs->thisDateFormat, BEFORE)) return ASN_BEFORE_DATE_E; /* The following items are optional. Only check for them if there is more @@ -4374,8 +4374,6 @@ static int DecodeResponseData(byte* source, if (GetBasicDate(source, &idx, resp->producedDate, &resp->producedDateFormat, size) < 0) return ASN_PARSE_E; - if (!ValidateDate(resp->producedDate, resp->producedDateFormat, BEFORE)) - return ASN_BEFORE_DATE_E; if (DecodeSingleResponse(source, &idx, resp, size) < 0) return ASN_PARSE_E; @@ -4635,7 +4633,6 @@ int EncodeOcspRequest(OcspRequest* req) byte snArray[MAX_SN_SZ]; byte extArray[MAX_OCSP_EXT_SZ]; byte* output = req->dest; - RNG rng; word32 seqSz[5], algoSz, issuerSz, issuerKeySz, snSz, extSz, totalSz; int i; @@ -4653,14 +4650,17 @@ int EncodeOcspRequest(OcspRequest* req) req->serialSz = req->cert->serialSz; snSz = SetSerialNumber(req->cert->serial, req->cert->serialSz, snArray); - if (InitRng(&rng) != 0) { - CYASSL_MSG("\tCannot initialize RNG. Skipping the OSCP Nonce."); - extSz = 0; - } else { - req->nonceSz = MAX_OCSP_NONCE_SZ; - RNG_GenerateBlock(&rng, req->nonce, req->nonceSz); - extSz = SetOcspReqExtensions(MAX_OCSP_EXT_SZ, extArray, - req->nonce, req->nonceSz); + extSz = 0; + if (req->useNonce) { + RNG rng; + if (InitRng(&rng) != 0) { + CYASSL_MSG("\tCannot initialize RNG. Skipping the OSCP Nonce."); + } else { + req->nonceSz = MAX_OCSP_NONCE_SZ; + RNG_GenerateBlock(&rng, req->nonce, req->nonceSz); + extSz = SetOcspReqExtensions(MAX_OCSP_EXT_SZ, extArray, + req->nonce, req->nonceSz); + } } totalSz = algoSz + issuerSz + issuerKeySz + snSz; @@ -4692,12 +4692,13 @@ int EncodeOcspRequest(OcspRequest* req) } -void InitOcspRequest(OcspRequest* req, DecodedCert* cert, +void InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce, byte* dest, word32 destSz) { CYASSL_ENTER("InitOcspRequest"); req->cert = cert; + req->useNonce = useNonce; req->nonceSz = 0; req->issuerHash = NULL; req->issuerKeyHash = NULL; @@ -4725,18 +4726,20 @@ int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp) return 1; } - cmp = req->nonceSz - resp->nonceSz; - if (cmp != 0) - { - CYASSL_MSG("\tnonceSz mismatch"); - return cmp; - } - - cmp = XMEMCMP(req->nonce, resp->nonce, req->nonceSz); - if (cmp != 0) - { - CYASSL_MSG("\tnonce mismatch"); - return cmp; + if (req->useNonce) { + cmp = req->nonceSz - resp->nonceSz; + if (cmp != 0) + { + CYASSL_MSG("\tnonceSz mismatch"); + return cmp; + } + + cmp = XMEMCMP(req->nonce, resp->nonce, req->nonceSz); + if (cmp != 0) + { + CYASSL_MSG("\tnonce mismatch"); + return cmp; + } } cmp = XMEMCMP(req->issuerHash, resp->issuerHash, SHA_DIGEST_SIZE); diff --git a/ctaocrypt/src/ecc.c b/ctaocrypt/src/ecc.c index 1976b3d12..ef35477f2 100644 --- a/ctaocrypt/src/ecc.c +++ b/ctaocrypt/src/ecc.c @@ -1266,17 +1266,17 @@ int ecc_verify_hash(const byte* sig, word32 siglen, byte* hash, word32 hashlen, } /* allocate ints */ - if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2)) != MP_OKAY) { + if ((err = mp_init_multi(&v, &w, &u1, &u2, &p, &e)) != MP_OKAY) { return MEMORY_E; } - if ((err = mp_init_multi(&p, &e, &m, NULL, NULL, NULL)) != MP_OKAY) { - mp_clear(&r); - mp_clear(&s); + if ((err = mp_init(&m)) != MP_OKAY) { mp_clear(&v); mp_clear(&w); mp_clear(&u1); mp_clear(&u2); + mp_clear(&p); + mp_clear(&e); return MEMORY_E; } @@ -1286,6 +1286,12 @@ int ecc_verify_hash(const byte* sig, word32 siglen, byte* hash, word32 hashlen, if (mQ == NULL || mG == NULL) err = MEMORY_E; + /* Note, DecodeECC_DSA_Sig() calls mp_init() on r and s. + * If either of those don't allocate correctly, none of + * the rest of this function will execute, and everything + * gets cleaned up at the end. */ + XMEMSET(&r, 0, sizeof(r)); + XMEMSET(&s, 0, sizeof(s)); if (err == MP_OKAY) err = DecodeECC_DSA_Sig(sig, siglen, &r, &s); diff --git a/ctaocrypt/src/integer.c b/ctaocrypt/src/integer.c index 388c4f0d5..000669db5 100644 --- a/ctaocrypt/src/integer.c +++ b/ctaocrypt/src/integer.c @@ -3792,8 +3792,10 @@ int mp_add_d (mp_int* a, mp_digit b, mp_int* c) *tmpc++ &= MP_MASK; } /* set final carry */ - ix++; - *tmpc++ = mu; + if (mu != 0 && ix < c->alloc) { + ix++; + *tmpc++ = mu; + } /* setup size */ c->used = a->used + 1; diff --git a/cyassl/ctaocrypt/asn.h b/cyassl/ctaocrypt/asn.h index eab0dd2e3..cc3d8a4f0 100644 --- a/cyassl/ctaocrypt/asn.h +++ b/cyassl/ctaocrypt/asn.h @@ -417,6 +417,7 @@ struct OcspResponse { struct OcspRequest { DecodedCert* cert; + byte useNonce; byte nonce[MAX_OCSP_NONCE_SZ]; int nonceSz; @@ -433,7 +434,8 @@ struct OcspRequest { CYASSL_LOCAL void InitOcspResponse(OcspResponse*, CertStatus*, byte*, word32); CYASSL_LOCAL int OcspResponseDecode(OcspResponse*); -CYASSL_LOCAL void InitOcspRequest(OcspRequest*, DecodedCert*, byte*, word32); +CYASSL_LOCAL void InitOcspRequest(OcspRequest*, DecodedCert*, + byte, byte*, word32); CYASSL_LOCAL int EncodeOcspRequest(OcspRequest*); CYASSL_LOCAL int CompareOcspReqResp(OcspRequest*, OcspResponse*); diff --git a/cyassl/ctaocrypt/types.h b/cyassl/ctaocrypt/types.h index 286280abb..083a87621 100644 --- a/cyassl/ctaocrypt/types.h +++ b/cyassl/ctaocrypt/types.h @@ -224,7 +224,8 @@ enum { DYNAMIC_TYPE_ARRAYS = 33, DYNAMIC_TYPE_DTLS_POOL = 34, DYNAMIC_TYPE_SOCKADDR = 35, - DYNAMIC_TYPE_LIBZ = 36 + DYNAMIC_TYPE_LIBZ = 36, + DYNAMIC_TYPE_ECC = 37 }; /* stack protection */ diff --git a/cyassl/internal.h b/cyassl/internal.h index d2decb1a7..1c43774be 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -781,6 +781,7 @@ struct OCSP_Entry { struct CYASSL_OCSP { byte enabled; byte useOverrideUrl; + byte useNonce; char overrideName[80]; char overridePath[80]; int overridePort; @@ -1355,10 +1356,10 @@ struct CYASSL { byte peerNtruKeyPresent; #endif #ifdef HAVE_ECC - ecc_key peerEccKey; /* peer's ECDHE key */ - ecc_key peerEccDsaKey; /* peer's ECDSA key */ - ecc_key eccTempKey; /* private ECDHE key */ - ecc_key eccDsaKey; /* private ECDSA key */ + ecc_key* peerEccKey; /* peer's ECDHE key */ + ecc_key* peerEccDsaKey; /* peer's ECDSA key */ + ecc_key* eccTempKey; /* private ECDHE key */ + ecc_key* eccDsaKey; /* private ECDSA key */ word16 eccTempKeySz; /* in octets 20 - 66 */ byte peerEccKeyPresent; byte peerEccDsaKeyPresent; diff --git a/cyassl/ssl.h b/cyassl/ssl.h index 2bbbfa054..0035e1341 100644 --- a/cyassl/ssl.h +++ b/cyassl/ssl.h @@ -885,6 +885,7 @@ CYASSL_API int CyaSSL_CTX_OCSP_set_override_url(CYASSL_CTX*, const char*); #define CYASSL_OCSP_ENABLE 0x0001 /* Enable OCSP lookups */ #define CYASSL_OCSP_URL_OVERRIDE 0x0002 /* Use the override URL instead of URL * in certificate */ +#define CYASSL_OCSP_NO_NONCE 0x0004 /* Disables the request nonce. */ #ifdef __cplusplus diff --git a/src/internal.c b/src/internal.c index b9dafc787..42905d1c6 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1004,10 +1004,10 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx) ssl->peerEccDsaKeyPresent = 0; ssl->eccDsaKeyPresent = 0; ssl->eccTempKeyPresent = 0; - ecc_init(&ssl->peerEccKey); - ecc_init(&ssl->peerEccDsaKey); - ecc_init(&ssl->eccDsaKey); - ecc_init(&ssl->eccTempKey); + ssl->peerEccKey = NULL; + ssl->peerEccDsaKey = NULL; + ssl->eccDsaKey = NULL; + ssl->eccTempKey = NULL; #endif ssl->timeout = ctx->timeout; @@ -1228,6 +1228,36 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx) return NO_PRIVATE_KEY; } #endif +#ifdef HAVE_ECC + ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), + ctx->heap, DYNAMIC_TYPE_ECC); + if (ssl->peerEccKey == NULL) { + CYASSL_MSG("PeerEccKey Memory error"); + return MEMORY_E; + } + ssl->peerEccDsaKey = (ecc_key*)XMALLOC(sizeof(ecc_key), + ctx->heap, DYNAMIC_TYPE_ECC); + if (ssl->peerEccDsaKey == NULL) { + CYASSL_MSG("PeerEccDsaKey Memory error"); + return MEMORY_E; + } + ssl->eccDsaKey = (ecc_key*)XMALLOC(sizeof(ecc_key), + ctx->heap, DYNAMIC_TYPE_ECC); + if (ssl->eccDsaKey == NULL) { + CYASSL_MSG("EccDsaKey Memory error"); + return MEMORY_E; + } + ssl->eccTempKey = (ecc_key*)XMALLOC(sizeof(ecc_key), + ctx->heap, DYNAMIC_TYPE_ECC); + if (ssl->eccTempKey == NULL) { + CYASSL_MSG("EccTempKey Memory error"); + return MEMORY_E; + } + ecc_init(ssl->peerEccKey); + ecc_init(ssl->peerEccDsaKey); + ecc_init(ssl->eccDsaKey); + ecc_init(ssl->eccTempKey); +#endif /* make sure server has DH parms, and add PSK if there, add NTRU too */ if (ssl->options.side == SERVER_END) @@ -1312,10 +1342,26 @@ void SSL_ResourceFree(CYASSL* ssl) FreeStreams(ssl); #endif #ifdef HAVE_ECC - ecc_free(&ssl->peerEccKey); - ecc_free(&ssl->peerEccDsaKey); - ecc_free(&ssl->eccTempKey); - ecc_free(&ssl->eccDsaKey); + if (ssl->peerEccKey) { + if (ssl->peerEccKeyPresent) + ecc_free(ssl->peerEccKey); + XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC); + } + if (ssl->peerEccDsaKey) { + if (ssl->peerEccDsaKeyPresent) + ecc_free(ssl->peerEccDsaKey); + XFREE(ssl->peerEccDsaKey, ssl->heap, DYNAMIC_TYPE_ECC); + } + if (ssl->eccTempKey) { + if (ssl->eccTempKeyPresent) + ecc_free(ssl->eccTempKey); + XFREE(ssl->eccTempKey, ssl->heap, DYNAMIC_TYPE_ECC); + } + if (ssl->eccDsaKey) { + if (ssl->eccDsaKeyPresent) + ecc_free(ssl->eccDsaKey); + XFREE(ssl->eccDsaKey, ssl->heap, DYNAMIC_TYPE_ECC); + } #endif } @@ -1358,6 +1404,45 @@ void FreeHandshakeResources(CYASSL* ssl) ssl->peerRsaKey = NULL; } #endif + +#ifdef HAVE_ECC + if (ssl->peerEccKey) + { + if (ssl->peerEccKeyPresent) { + ecc_free(ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + } + XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC); + ssl->peerEccKey = NULL; + } + if (ssl->peerEccDsaKey) + { + if (ssl->peerEccDsaKeyPresent) { + ecc_free(ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; + } + XFREE(ssl->peerEccDsaKey, ssl->heap, DYNAMIC_TYPE_ECC); + ssl->peerEccDsaKey = NULL; + } + if (ssl->eccTempKey) + { + if (ssl->eccTempKeyPresent) { + ecc_free(ssl->eccTempKey); + ssl->eccTempKeyPresent = 0; + } + XFREE(ssl->eccTempKey, ssl->heap, DYNAMIC_TYPE_ECC); + ssl->eccTempKey = NULL; + } + if (ssl->eccDsaKey) + { + if (ssl->eccDsaKeyPresent) { + ecc_free(ssl->eccDsaKey); + ssl->eccDsaKeyPresent = 0; + } + XFREE(ssl->eccDsaKey, ssl->heap, DYNAMIC_TYPE_ECC); + ssl->eccDsaKey = NULL; + } +#endif } @@ -2418,7 +2503,7 @@ static int DoCertificate(CYASSL* ssl, byte* input, word32* inOutIdx) case ECDSAk: { if (ecc_import_x963(dCert.publicKey, dCert.pubKeySize, - &ssl->peerEccDsaKey) != 0) { + ssl->peerEccDsaKey) != 0) { ret = PEER_KEY_ERROR; } else @@ -5913,7 +5998,7 @@ int SetCipherList(Suites* s, const char* list) length = input[*inOutIdx]; *inOutIdx += 1; - if (ecc_import_x963(&input[*inOutIdx], length, &ssl->peerEccKey) != 0) + if (ecc_import_x963(&input[*inOutIdx], length, ssl->peerEccKey) != 0) return ECC_PEERKEY_ERROR; *inOutIdx += length; @@ -6007,7 +6092,7 @@ int SetCipherList(Suites* s, const char* list) return NO_PEER_KEY; ret = ecc_verify_hash(signature, sigLen, &hash[MD5_DIGEST_SIZE], - SHA_DIGEST_SIZE, &verify, &ssl->peerEccDsaKey); + SHA_DIGEST_SIZE, &verify, ssl->peerEccDsaKey); if (ret != 0 || verify == 0) return VERIFY_SIGN_ERROR; } @@ -6157,14 +6242,14 @@ int SetCipherList(Suites* s, const char* list) if (ssl->specs.static_ecdh) { /* TODO: EccDsa is really fixed Ecc change naming */ - if (!ssl->peerEccDsaKeyPresent || !ssl->peerEccDsaKey.dp) + if (!ssl->peerEccDsaKeyPresent || !ssl->peerEccDsaKey->dp) return NO_PEER_KEY; - peerKey = &ssl->peerEccDsaKey; + peerKey = ssl->peerEccDsaKey; } else { - if (!ssl->peerEccKeyPresent || !ssl->peerEccKey.dp) + if (!ssl->peerEccKeyPresent || !ssl->peerEccKey->dp) return NO_PEER_KEY; - peerKey = &ssl->peerEccKey; + peerKey = ssl->peerEccKey; } ecc_init(&myKey); @@ -6620,7 +6705,7 @@ int SetCipherList(Suites* s, const char* list) length = ENUM_LEN + CURVE_LEN + ENUM_LEN; /* pub key size */ CYASSL_MSG("Using ephemeral ECDH"); - if (ecc_export_x963(&ssl->eccTempKey, exportBuf, &expSz) != 0) + if (ecc_export_x963(ssl->eccTempKey, exportBuf, &expSz) != 0) return ECC_EXPORT_ERROR; length += expSz; @@ -6690,7 +6775,7 @@ int SetCipherList(Suites* s, const char* list) /* key exchange data */ output[idx++] = named_curve; output[idx++] = 0x00; /* leading zero */ - output[idx++] = SetCurveId(ecc_size(&ssl->eccTempKey)); + output[idx++] = SetCurveId(ecc_size(ssl->eccTempKey)); output[idx++] = (byte)expSz; XMEMCPY(output + idx, exportBuf, expSz); idx += expSz; @@ -7823,7 +7908,7 @@ int SetCipherList(Suites* s, const char* list) CYASSL_MSG("Doing ECC peer cert verify"); err = ecc_verify_hash(sig, sz, ssl->certHashes.sha, SHA_DIGEST_SIZE, - &verify, &ssl->peerEccDsaKey); + &verify, ssl->peerEccDsaKey); if (err == 0 && verify == 1) ret = 0; /* verified */ @@ -8066,7 +8151,8 @@ int SetCipherList(Suites* s, const char* list) word32 bLength = input[*inOutIdx]; /* one byte length */ *inOutIdx += 1; - ret = ecc_import_x963(&input[*inOutIdx], bLength, &ssl->peerEccKey); + ret = ecc_import_x963(&input[*inOutIdx], + bLength, ssl->peerEccKey); if (ret != 0) return ECC_PEERKEY_ERROR; *inOutIdx += bLength; @@ -8079,14 +8165,14 @@ int SetCipherList(Suites* s, const char* list) ecc_init(&staticKey); ret = EccPrivateKeyDecode(ssl->buffers.key.buffer, &i, - &staticKey, ssl->buffers.key.length); + &staticKey, ssl->buffers.key.length); if (ret == 0) - ret = ecc_shared_secret(&staticKey, &ssl->peerEccKey, - ssl->arrays->preMasterSecret, &size); + ret = ecc_shared_secret(&staticKey, ssl->peerEccKey, + ssl->arrays->preMasterSecret, &size); ecc_free(&staticKey); } else - ret = ecc_shared_secret(&ssl->eccTempKey, &ssl->peerEccKey, + ret = ecc_shared_secret(ssl->eccTempKey, ssl->peerEccKey, ssl->arrays->preMasterSecret, &size); if (ret != 0) return ECC_SHARED_ERROR; diff --git a/src/ocsp.c b/src/ocsp.c index 343b98c5b..c012f27e5 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -64,6 +64,7 @@ int CyaSSL_OCSP_Init(CYASSL_OCSP* ocsp) { if (ocsp != NULL) { XMEMSET(ocsp, 0, sizeof(*ocsp)); + ocsp->useNonce = 1; return 0; } @@ -454,7 +455,7 @@ static int xstat2err(int stat) int CyaSSL_OCSP_Lookup_Cert(CYASSL_OCSP* ocsp, DecodedCert* cert) { - byte ocspReqBuf[SCRATCH_BUFFER_SIZE]; + byte* ocspReqBuf = NULL; int ocspReqSz = SCRATCH_BUFFER_SIZE; byte* ocspRespBuf = NULL; OcspRequest ocspRequest; @@ -501,30 +502,37 @@ int CyaSSL_OCSP_Lookup_Cert(CYASSL_OCSP* ocsp, DecodedCert* cert) } } - InitOcspRequest(&ocspRequest, cert, ocspReqBuf, ocspReqSz); + ocspReqBuf = (byte*)XMALLOC(ocspReqSz, NULL, DYNAMIC_TYPE_IN_BUFFER); + if (ocspReqBuf == NULL) { + CYASSL_MSG("\talloc OCSP request buffer failed"); + return MEMORY_ERROR; + } + InitOcspRequest(&ocspRequest, cert, ocsp->useNonce, ocspReqBuf, ocspReqSz); ocspReqSz = EncodeOcspRequest(&ocspRequest); result = http_ocsp_transaction(ocsp, cert, ocspReqBuf, ocspReqSz, &ocspRespBuf); - if (result < 0) return result; - /* If the transaction failed, return that result. */ - - InitOcspResponse(&ocspResponse, certStatus, ocspRespBuf, result); - OcspResponseDecode(&ocspResponse); - - if (ocspResponse.responseStatus != OCSP_SUCCESSFUL) { - CYASSL_MSG("OCSP Responder failure"); - result = OCSP_LOOKUP_FAIL; - } else { - if (CompareOcspReqResp(&ocspRequest, &ocspResponse) == 0) - { - result = xstat2err(ocspResponse.status->status); - } - else - { - CYASSL_MSG("OCSP Response incorrect for Request"); + if (result >= 0) { + InitOcspResponse(&ocspResponse, certStatus, ocspRespBuf, result); + OcspResponseDecode(&ocspResponse); + + if (ocspResponse.responseStatus != OCSP_SUCCESSFUL) { + CYASSL_MSG("OCSP Responder failure"); result = OCSP_LOOKUP_FAIL; + } else { + if (CompareOcspReqResp(&ocspRequest, &ocspResponse) == 0) + { + result = xstat2err(ocspResponse.status->status); + } + else + { + CYASSL_MSG("OCSP Response incorrect for Request"); + result = OCSP_LOOKUP_FAIL; + } } } + if (ocspReqBuf != NULL) { + XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_IN_BUFFER); + } if (ocspRespBuf != NULL) { XFREE(ocspRespBuf, NULL, DYNAMIC_TYPE_IN_BUFFER); } diff --git a/src/ssl.c b/src/ssl.c index 1baa80dab..673fc72cb 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -2786,7 +2786,7 @@ int CyaSSL_dtls_got_timeout(CYASSL* ssl) /* in case used set_accept_state after init */ if (ssl->eccTempKeyPresent == 0) { if (ecc_make_key(ssl->rng, ssl->eccTempKeySz, - &ssl->eccTempKey) != 0) { + ssl->eccTempKey) != 0) { ssl->error = ECC_MAKEKEY_ERROR; CYASSL_ERROR(ssl->error); return SSL_FATAL_ERROR; @@ -8220,6 +8220,7 @@ long CyaSSL_CTX_OCSP_set_options(CYASSL_CTX* ctx, long options) if (ctx != NULL) { ctx->ocsp.enabled = (options & CYASSL_OCSP_ENABLE) != 0; ctx->ocsp.useOverrideUrl = (options & CYASSL_OCSP_URL_OVERRIDE) != 0; + ctx->ocsp.useNonce = (options & CYASSL_OCSP_NO_NONCE) == 0; return 1; } return 0;