Merge changes from topic "certtool-memleak" into integration

* changes:
  Use preallocated parts of the HASH struct
  Free arguments copied with strdup
  Free keys after use
  Free X509_EXTENSIONs
diff --git a/tools/cert_create/src/ext.c b/tools/cert_create/src/ext.c
index d9a92bb..65dd3e5 100644
--- a/tools/cert_create/src/ext.c
+++ b/tools/cert_create/src/ext.c
@@ -158,51 +158,36 @@
 		unsigned char *buf, size_t len)
 {
 	X509_EXTENSION *ex;
-	ASN1_OCTET_STRING *octet;
 	HASH *hash;
 	ASN1_OBJECT *algorithm;
-	X509_ALGOR *x509_algor;
 	unsigned char *p = NULL;
 	int sz;
 
-	/* OBJECT_IDENTIFIER with hash algorithm */
-	algorithm = OBJ_nid2obj(EVP_MD_type(md));
-	if (algorithm == NULL) {
-		return NULL;
-	}
-
-	/* Create X509_ALGOR */
-	x509_algor = X509_ALGOR_new();
-	if (x509_algor == NULL) {
-		return NULL;
-	}
-	x509_algor->algorithm = algorithm;
-	x509_algor->parameter = ASN1_TYPE_new();
-	ASN1_TYPE_set(x509_algor->parameter, V_ASN1_NULL, NULL);
-
-	/* OCTET_STRING with the actual hash */
-	octet = ASN1_OCTET_STRING_new();
-	if (octet == NULL) {
-		X509_ALGOR_free(x509_algor);
-		return NULL;
-	}
-	ASN1_OCTET_STRING_set(octet, buf, len);
-
 	/* HASH structure containing algorithm + hash */
 	hash = HASH_new();
 	if (hash == NULL) {
-		ASN1_OCTET_STRING_free(octet);
-		X509_ALGOR_free(x509_algor);
 		return NULL;
 	}
-	hash->hashAlgorithm = x509_algor;
-	hash->dataHash = octet;
+
+	/* OBJECT_IDENTIFIER with hash algorithm */
+	algorithm = OBJ_nid2obj(EVP_MD_type(md));
+	if (algorithm == NULL) {
+		HASH_free(hash);
+		return NULL;
+	}
+
+	/* Create X509_ALGOR */
+	hash->hashAlgorithm->algorithm = algorithm;
+	hash->hashAlgorithm->parameter = ASN1_TYPE_new();
+	ASN1_TYPE_set(hash->hashAlgorithm->parameter, V_ASN1_NULL, NULL);
+
+	/* OCTET_STRING with the actual hash */
+	ASN1_OCTET_STRING_set(hash->dataHash, buf, len);
 
 	/* DER encoded HASH */
 	sz = i2d_HASH(hash, &p);
 	if ((sz <= 0) || (p == NULL)) {
 		HASH_free(hash);
-		X509_ALGOR_free(x509_algor);
 		return NULL;
 	}
 
diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c
index 2ba1101..d5abe49 100644
--- a/tools/cert_create/src/main.c
+++ b/tools/cert_create/src/main.c
@@ -539,6 +539,11 @@
 			exit(1);
 		}
 
+		for (cert_ext = sk_X509_EXTENSION_pop(sk); cert_ext != NULL;
+				cert_ext = sk_X509_EXTENSION_pop(sk)) {
+			X509_EXTENSION_free(cert_ext);
+		}
+
 		sk_X509_EXTENSION_free(sk);
 	}
 
@@ -576,10 +581,44 @@
 		}
 	}
 
+	/* If we got here, then we must have filled the key array completely.
+	 * We can then safely call free on all of the keys in the array
+	 */
+	for (i = 0; i < num_keys; i++) {
+		EVP_PKEY_free(keys[i].key);
+	}
+
 #ifndef OPENSSL_NO_ENGINE
 	ENGINE_cleanup();
 #endif
 	CRYPTO_cleanup_all_ex_data();
 
+
+	/* We allocated strings through strdup, so now we have to free them */
+	for (i = 0; i < num_keys; i++) {
+		if (keys[i].fn != NULL) {
+			void *ptr = keys[i].fn;
+
+			keys[i].fn = NULL;
+			free(ptr);
+		}
+	}
+	for (i = 0; i < num_extensions; i++) {
+		if (extensions[i].arg != NULL) {
+			void *ptr = (void *)extensions[i].arg;
+
+			extensions[i].arg = NULL;
+			free(ptr);
+		}
+	}
+	for (i = 0; i < num_certs; i++) {
+		if (certs[i].fn != NULL) {
+			void *ptr = (void *)certs[i].fn;
+
+			certs[i].fn = NULL;
+			free(ptr);
+		}
+	}
+
 	return 0;
 }