diff --git a/source/windows/secure_channel_tls_handler.c b/source/windows/secure_channel_tls_handler.c index 7e9e52a56..2591a5451 100644 --- a/source/windows/secure_channel_tls_handler.c +++ b/source/windows/secure_channel_tls_handler.c @@ -59,6 +59,7 @@ struct secure_channel_ctx { HCRYPTPROV crypto_provider; HCRYPTKEY private_key; bool verify_peer; + bool should_free_pcerts; }; struct secure_channel_handler { @@ -1841,7 +1842,15 @@ static void s_secure_channel_ctx_destroy(struct secure_channel_ctx *secure_chann } if (secure_channel_ctx->pcerts) { - CertFreeCertificateContext(secure_channel_ctx->pcerts); + /** + * Only free the private certificate context if the private key is NOT + * from the certificate context because freeing the private key + * using CryptDestroyKey frees the certificate context and then + * trying to access it leads to a access violation. + */ + if (secure_channel_ctx->should_free_pcerts == true) { + CertFreeCertificateContext(secure_channel_ctx->pcerts); + } } if (secure_channel_ctx->cert_store) { @@ -1887,6 +1896,7 @@ struct aws_tls_ctx *s_ctx_new( secure_channel_ctx->verify_peer = options->verify_peer; secure_channel_ctx->credentials.dwVersion = SCHANNEL_CRED_VERSION; + secure_channel_ctx->should_free_pcerts = true; secure_channel_ctx->credentials.grbitEnabledProtocols = 0; @@ -2015,6 +2025,7 @@ struct aws_tls_ctx *s_ctx_new( secure_channel_ctx->credentials.paCred = &secure_channel_ctx->pcerts; secure_channel_ctx->credentials.cCreds = 1; + secure_channel_ctx->should_free_pcerts = false; } return &secure_channel_ctx->ctx;