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.
This commit is contained in:
cinap_lenrek 2015-09-23 17:33:52 +02:00
parent 5639f9504b
commit 6641548938

View file

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