shithub: riscv

Download patch

ref: 664154893811cc73bfa00ef276776b87070d50f5
parent: 5639f9504be2b325c7c041a59b424880cb9e8cf7
author: cinap_lenrek <[email protected]>
date: Wed Sep 23 13:33:52 EDT 2015

libsec: fix memory leaks in X509req() and X509gen() and return malloced pointer

X509req() and X509gen() used to leak memory, and had no way for
the caller to free the allocated certificate/certificate request
buffer returned. this is not critical as these functions are only
used in short lived rsa(2) helper programs. but i prefer to have
library routines not leak memory as one does not know in advance
where the code is going to be used.

--- a/sys/src/libsec/port/x509.c
+++ b/sys/src/libsec/port/x509.c
@@ -2529,47 +2529,46 @@
 	uchar *cert = nil;
 	RSApub *pk = rsaprivtopub(priv);
 	Bytes *certbytes, *pkbytes, *certinfobytes, *sigbytes;
-	Elem e, certinfo, issuer, subject, pubkey, validity, sig;
+	Elem e, certinfo;
 	DigestAlg *da;
 	uchar digest[MAXdlen], *buf;
 	int buflen;
 	mpint *pkcs1;
 
-	e.val.tag = VInt;  /* so freevalfields at errret is no-op */
-	issuer = mkDN(subj);
-	subject = mkDN(subj);
-	pubkey = mkseq(mkel(mkbigint(pk->n),mkel(mkint(mptoi(pk->ek)),nil)));
-	if(encode(pubkey, &pkbytes) != ASN_OK)
+	e = mkseq(mkel(mkbigint(pk->n),mkel(mkint(mptoi(pk->ek)),nil)));
+	if(encode(e, &pkbytes) != ASN_OK)
 		goto errret;
-	freevalfields(&pubkey.val);
-	pubkey = mkseq(
-		mkel(mkalg(ALG_rsaEncryption),
-		mkel(mkbits(pkbytes->data, pkbytes->len),
-		nil)));
-	freebytes(pkbytes);
-	validity = mkseq(
-		mkel(mkutc(valid[0]),
-		mkel(mkutc(valid[1]),
-		nil)));
-	certinfo = mkseq(
+	freevalfields(&e.val);
+	e = mkseq(
 		mkel(mkint(serial),
 		mkel(mkalg(sigalg),
-		mkel(issuer,
-		mkel(validity,
-		mkel(subject,
-		mkel(pubkey,
+		mkel(mkDN(subj),
+		mkel(mkseq(
+			mkel(mkutc(valid[0]),
+			mkel(mkutc(valid[1]),
+			nil))),
+		mkel(mkDN(subj),
+		mkel(mkseq(
+			mkel(mkalg(ALG_rsaEncryption),
+			mkel(mkbits(pkbytes->data, pkbytes->len),
+			nil))),
 		nil)))))));
-	if(encode(certinfo, &certinfobytes) != ASN_OK)
+	freebytes(pkbytes);
+	if(encode(e, &certinfobytes) != ASN_OK)
 		goto errret;
 	da = digestalg[sigalg];
 	(*da->fun)(certinfobytes->data, certinfobytes->len, digest, 0);
 	freebytes(certinfobytes);
-	sig = mkseq(
+	certinfo = e;
+	e = mkseq(
 		mkel(mkalg(da->alg),
 		mkel(mkoctet(digest, da->len),
 		nil)));
-	if(encode(sig, &sigbytes) != ASN_OK)
+	if(encode(e, &sigbytes) != ASN_OK){
+		freevalfields(&certinfo.val);
 		goto errret;
+	}
+	freevalfields(&e.val);
 	pkcs1 = pkcs1pad(sigbytes, pk->n);
 	freebytes(sigbytes);
 	rsadecrypt(priv, pkcs1, pkcs1);
@@ -2585,7 +2584,10 @@
 		goto errret;
 	if(certlen)
 		*certlen = certbytes->len;
-	cert = certbytes->data;
+	cert = malloc(certbytes->len);
+	if(cert != nil)
+		memmove(cert, certbytes->data, certbytes->len);
+	freebytes(certbytes);
 errret:
 	freevalfields(&e.val);
 	return cert;
@@ -2599,39 +2601,39 @@
 	uchar *cert = nil;
 	RSApub *pk = rsaprivtopub(priv);
 	Bytes *certbytes, *pkbytes, *certinfobytes, *sigbytes;
-	Elem e, certinfo, subject, pubkey, sig;
+	Elem e, certinfo;
 	DigestAlg *da;
 	uchar digest[MAXdlen], *buf;
 	int buflen;
 	mpint *pkcs1;
 
-	e.val.tag = VInt;  /* so freevalfields at errret is no-op */
-	subject = mkDN(subj);
-	pubkey = mkseq(mkel(mkbigint(pk->n),mkel(mkint(mptoi(pk->ek)),nil)));
-	if(encode(pubkey, &pkbytes) != ASN_OK)
+	e = mkseq(mkel(mkbigint(pk->n),mkel(mkint(mptoi(pk->ek)),nil)));
+	if(encode(e, &pkbytes) != ASN_OK)
 		goto errret;
-	freevalfields(&pubkey.val);
-	pubkey = mkseq(
-		mkel(mkalg(ALG_rsaEncryption),
-		mkel(mkbits(pkbytes->data, pkbytes->len),
-		nil)));
-	freebytes(pkbytes);
-	certinfo = mkseq(
+	freevalfields(&e.val);
+	e = mkseq(
 		mkel(mkint(version),
-		mkel(subject,
-		mkel(pubkey,
+		mkel(mkDN(subj),
+		mkel(mkseq(
+			mkel(mkalg(ALG_rsaEncryption),
+			mkel(mkbits(pkbytes->data, pkbytes->len),
+			nil))),
 		nil))));
-	if(encode(certinfo, &certinfobytes) != ASN_OK)
+	freebytes(pkbytes);
+	if(encode(e, &certinfobytes) != ASN_OK)
 		goto errret;
 	da = digestalg[sigalg];
 	(*da->fun)(certinfobytes->data, certinfobytes->len, digest, 0);
 	freebytes(certinfobytes);
-	sig = mkseq(
+	certinfo = e;
+	e = mkseq(
 		mkel(mkalg(da->alg),
 		mkel(mkoctet(digest, da->len),
 		nil)));
-	if(encode(sig, &sigbytes) != ASN_OK)
+	if(encode(e, &sigbytes) != ASN_OK){
+		freevalfields(&certinfo.val);
 		goto errret;
+	}
 	pkcs1 = pkcs1pad(sigbytes, pk->n);
 	freebytes(sigbytes);
 	rsadecrypt(priv, pkcs1, pkcs1);
@@ -2647,7 +2649,10 @@
 		goto errret;
 	if(certlen)
 		*certlen = certbytes->len;
-	cert = certbytes->data;
+	cert = malloc(certbytes->len);
+	if(cert != nil)
+		memmove(cert, certbytes->data, certbytes->len);
+	freebytes(certbytes);
 errret:
 	freevalfields(&e.val);
 	return cert;