Don't leak memory on error in i2b_PVK
authorMatt Caswell <matt@openssl.org>
Wed, 27 Apr 2016 13:00:37 +0000 (14:00 +0100)
committerMatt Caswell <matt@openssl.org>
Thu, 28 Apr 2016 12:13:09 +0000 (13:13 +0100)
The i2b_PVK function leaked a number of different memory allocations on
error paths (and even some non-error paths).

Reviewed-by: Richard Levitte <levitte@openssl.org>
crypto/pem/pvkfmt.c

index 85ab677..e7ee6dd 100644 (file)
@@ -807,26 +807,29 @@ static int i2b_PVK(unsigned char **out, EVP_PKEY *pk, int enclevel,
 {
     int outlen = 24, pklen;
     unsigned char *p, *salt = NULL;
 {
     int outlen = 24, pklen;
     unsigned char *p, *salt = NULL;
-    EVP_CIPHER_CTX *cctx = EVP_CIPHER_CTX_new();
+    EVP_CIPHER_CTX *cctx = NULL;
     if (enclevel)
         outlen += PVK_SALTLEN;
     pklen = do_i2b(NULL, pk, 0);
     if (pklen < 0)
         return -1;
     outlen += pklen;
     if (enclevel)
         outlen += PVK_SALTLEN;
     pklen = do_i2b(NULL, pk, 0);
     if (pklen < 0)
         return -1;
     outlen += pklen;
-    if (!out)
+    if (out == NULL)
         return outlen;
         return outlen;
-    if (*out)
+    if (*out != NULL) {
         p = *out;
         p = *out;
-    else {
+    else {
         p = OPENSSL_malloc(outlen);
         if (p == NULL) {
             PEMerr(PEM_F_I2B_PVK, ERR_R_MALLOC_FAILURE);
             return -1;
         }
         p = OPENSSL_malloc(outlen);
         if (p == NULL) {
             PEMerr(PEM_F_I2B_PVK, ERR_R_MALLOC_FAILURE);
             return -1;
         }
-        *out = p;
     }
 
     }
 
+    cctx = EVP_CIPHER_CTX_new();
+    if (cctx == NULL)
+        return -1;
+
     write_ledword(&p, MS_PVKMAGIC);
     write_ledword(&p, 0);
     if (EVP_PKEY_id(pk) == EVP_PKEY_DSA)
     write_ledword(&p, MS_PVKMAGIC);
     write_ledword(&p, 0);
     if (EVP_PKEY_id(pk) == EVP_PKEY_DSA)
@@ -843,9 +846,7 @@ static int i2b_PVK(unsigned char **out, EVP_PKEY *pk, int enclevel,
         p += PVK_SALTLEN;
     }
     do_i2b(&p, pk, 0);
         p += PVK_SALTLEN;
     }
     do_i2b(&p, pk, 0);
-    if (enclevel == 0)
-        return outlen;
-    else {
+    if (enclevel != 0) {
         char psbuf[PEM_BUFSIZE];
         unsigned char keybuf[20];
         int enctmplen, inlen;
         char psbuf[PEM_BUFSIZE];
         unsigned char keybuf[20];
         int enctmplen, inlen;
@@ -871,7 +872,12 @@ static int i2b_PVK(unsigned char **out, EVP_PKEY *pk, int enclevel,
         if (!EVP_DecryptFinal_ex(cctx, p + enctmplen, &enctmplen))
             goto error;
     }
         if (!EVP_DecryptFinal_ex(cctx, p + enctmplen, &enctmplen))
             goto error;
     }
+
     EVP_CIPHER_CTX_free(cctx);
     EVP_CIPHER_CTX_free(cctx);
+
+    if (*out == NULL)
+        *out = p;
+
     return outlen;
 
  error:
     return outlen;
 
  error: