-
-
Notifications
You must be signed in to change notification settings - Fork 11.1k
Description
If you use EVP_CIPHER_CTX_copy() on a an existing EVP_CIPHER_CTX that was initialised using a cipher from the dasync ENGINE, then subsequently freeing the source and destination EVP_CIPHER_CTX objects results in a double free.
The reason is that, by default, the copy operation simply does a memcpy on the internal cipher data:
Lines 1396 to 1412 in d5d95da
| if (in->cipher_data && in->cipher->ctx_size) { | |
| out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size); | |
| if (out->cipher_data == NULL) { | |
| out->cipher = NULL; | |
| ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); | |
| return 0; | |
| } | |
| memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size); | |
| } | |
| if (in->cipher->flags & EVP_CIPH_CUSTOM_COPY) | |
| if (!in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY, 0, out)) { | |
| out->cipher = NULL; | |
| ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); | |
| return 0; | |
| } | |
| return 1; |
Unfortunately, for the dasync engine, this internal cipher data contains pointers to other data which is managed internally to the daysnc engine. When the source and destination EVP_CIPHER_CTX objects subsequently get freed the internal pointers (which are identical) are also freed twice - and hence a double free occurs.
To avoid this problem, engines that need to are supposed to use the EVP_CIPH_CUSTOM_COPY flag, but the dasync engine does not do this.