diff --git a/src/internal.c b/src/internal.c index d62c24a56..d4a0b437a 100644 --- a/src/internal.c +++ b/src/internal.c @@ -14200,9 +14200,6 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case NOT_READY_ERROR : return "handshake layer not ready yet, complete first"; - case PMS_VERSION_ERROR : - return "premaster secret version mismatch error"; - case VERSION_ERROR : return "record layer version error"; @@ -18770,8 +18767,10 @@ int SendClientKeyExchange(WOLFSSL* ssl) #ifndef NO_RSA case rsa_kea: { + /* build PreMasterSecret with RNG data */ ret = wc_RNG_GenerateBlock(ssl->rng, - ssl->arrays->preMasterSecret, SECRET_LEN); + &ssl->arrays->preMasterSecret[VERSION_SZ], + SECRET_LEN - VERSION_SZ); if (ret != 0) { goto exit_scke; } @@ -23569,6 +23568,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 idx; word32 begin; word32 sigSz; + #ifndef NO_RSA + int lastErr; + #endif } DckeArgs; static void FreeDckeArgs(WOLFSSL* ssl, void* pArgs) @@ -23794,6 +23796,14 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ERROR_OUT(BUFFER_ERROR, exit_dcke); } + /* pre-load PreMasterSecret with RNG data */ + ret = wc_RNG_GenerateBlock(ssl->rng, + &ssl->arrays->preMasterSecret[VERSION_SZ], + SECRET_LEN - VERSION_SZ); + if (ret != 0) { + goto exit_dcke; + } + args->output = NULL; break; } /* rsa_kea */ @@ -24258,6 +24268,20 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, NULL, 0, NULL #endif ); + + /* Errors that can occur here that should be + * indistinguishable: + * RSA_BUFFER_E, RSA_PAD_E and RSA_PRIVATE_ERROR + */ + if (ret < 0 && ret != BAD_FUNC_ARG) { + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + goto exit_dcke; + #endif + /* store error code for handling below */ + args->lastErr = ret; + ret = 0; + } break; } /* rsa_kea */ #endif /* !NO_RSA */ @@ -24404,16 +24428,42 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Add the signature length to idx */ args->idx += args->length; - if (args->sigSz == SECRET_LEN && args->output != NULL) { - XMEMCPY(ssl->arrays->preMasterSecret, args->output, SECRET_LEN); - if (ssl->arrays->preMasterSecret[0] != ssl->chVersion.major || - ssl->arrays->preMasterSecret[1] != ssl->chVersion.minor) { - ERROR_OUT(PMS_VERSION_ERROR, exit_dcke); + #ifdef DEBUG_WOLFSSL + /* check version (debug warning message only) */ + if (args->output != NULL) { + if (args->output[0] != ssl->chVersion.major || + args->output[1] != ssl->chVersion.minor) { + WOLFSSL_MSG("preMasterSecret version mismatch"); } } - else { - ERROR_OUT(RSA_PRIVATE_ERROR, exit_dcke); + #endif + + /* RFC5246 7.4.7.1: + * Treat incorrectly formatted message blocks and/or + * mismatched version numbers in a manner + * indistinguishable from correctly formatted RSA blocks + */ + + ret = args->lastErr; + args->lastErr = 0; /* reset */ + + /* build PreMasterSecret */ + ssl->arrays->preMasterSecret[0] = ssl->chVersion.major; + ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor; + if (ret == 0 && args->sigSz == SECRET_LEN && + args->output != NULL) { + XMEMCPY(&ssl->arrays->preMasterSecret[VERSION_SZ], + &args->output[VERSION_SZ], + SECRET_LEN - VERSION_SZ); } + else { + /* preMasterSecret has RNG and version set */ + /* return proper length and ignore error */ + /* error will be caught as decryption error */ + args->sigSz = SECRET_LEN; + ret = 0; + } + break; } /* rsa_kea */ #endif /* !NO_RSA */ diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index ff1bb0b71..facab69a9 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -57,7 +57,7 @@ enum wolfSSL_ErrorCodes { DOMAIN_NAME_MISMATCH = -322, /* peer subject name mismatch */ WANT_READ = -323, /* want read, call again */ NOT_READY_ERROR = -324, /* handshake layer not ready */ - PMS_VERSION_ERROR = -325, /* pre m secret version error */ + VERSION_ERROR = -326, /* record layer version error */ WANT_WRITE = -327, /* want write, call again */ BUFFER_ERROR = -328, /* malformed buffer input */