shithub: riscv

Download patch

ref: 78808ca314949f40d9f6aa7abd4aa0e3f6e4b88d
parent: cc8e8c978cb48955417db592b799c4c65881c2b8
author: cinap_lenrek <[email protected]>
date: Tue Feb 2 23:18:54 EST 2016

libsec: refactor asn1 encoding of digest for rsa signatures, fix memory leak in ecverify

--- a/sys/src/libsec/port/ecc.c
+++ b/sys/src/libsec/port/ecc.c
@@ -476,6 +476,7 @@
 		mpmod(R.x, dom->n, t);
 		ret = mpcmp(r, t) == 0;
 	}
+	mpfree(E);
 	mpfree(t);
 	mpfree(u1);
 	mpfree(u2);
--- a/sys/src/libsec/port/tlshand.c
+++ b/sys/src/libsec/port/tlshand.c
@@ -432,7 +432,7 @@
 
 /* x509.c */
 extern mpint*	pkcs1padbuf(uchar *buf, int len, mpint *modulus);
-extern int	X509encodesignature_sha256(uchar digest[SHA2_256dlen], uchar *buf, int len);
+extern int	asn1encodedigest(DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*), uchar *digest, uchar *buf, int len);
 
 //================= client/server ========================
 
@@ -1298,7 +1298,7 @@
 
 			m.u.certificateVerify.sigalg = 0x0401;	/* RSA SHA256 */
 			sha2_256(nil, 0, digest, &c->handhash.sha2_256);
-			buflen = X509encodesignature_sha256(digest, buf, sizeof(buf));
+			buflen = asn1encodedigest(sha2_256, digest, buf, sizeof(buf));
 		} else {
 			md5(nil, 0, buf, &c->handhash.md5);
 			sha1(nil, 0, buf+MD5dlen, &c->handhash.sha1);
@@ -1305,6 +1305,11 @@
 			buflen = MD5dlen+SHA1dlen;
 		}
 		c->handhash = hsave;
+
+		if(buflen <= 0){
+			tlsError(c, EInternalError, "can't encode handshake hashes");
+			goto Err;
+		}
 		
 		paddedHashes = pkcs1padbuf(buf, buflen, c->sec->rsapub->n);
 		signedMP = factotum_rsa_decrypt(c->sec->rpc, paddedHashes);
--- a/sys/src/libsec/port/x509.c
+++ b/sys/src/libsec/port/x509.c
@@ -1896,7 +1896,7 @@
 }
 
 /*
- *	RSAPublickKey :: SEQUENCE {
+ *	RSAPublickKey ::= SEQUENCE {
  *		modulus INTEGER,
  *		publicExponent INTEGER
  *	}
@@ -2552,32 +2552,54 @@
 	return mkseq(el);
 }
 
-int
-X509encodesignature_sha256(uchar digest[SHA2_256dlen], uchar *buf, int len)
+/*
+ * DigestInfo ::= SEQUENCE {
+ *	digestAlgorithm AlgorithmIdentifier,
+ *	digest OCTET STRING }
+ */
+static Bytes*
+encode_digest(DigestAlg *da, uchar *digest)
 {
-	Bytes *sigbytes;
-	Elem sig;
+	Bytes *ans;
 	int err;
+	Elem e;
 
-	sig = mkseq(
-		mkel(mkalg(ALG_sha256),
-		mkel(mkoctet(digest, SHA2_256dlen),
+	e = mkseq(
+		mkel(mkalg(da->alg),
+		mkel(mkoctet(digest, da->len),
 		nil)));
-	err = encode(sig, &sigbytes);
-	freevalfields(&sig.val);
+	err = encode(e, &ans);
+	freevalfields(&e.val);
 	if(err != ASN_OK)
-		return -1;
-	if(len < sigbytes->len){
-		freebytes(sigbytes);
-		return -1;
-	}
-	len = sigbytes->len;
-	memmove(buf, sigbytes->data, len);
-	freebytes(sigbytes);
+		return nil;
 
-	return len;
+	return ans;
 }
 
+int
+asn1encodedigest(DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*), uchar *digest, uchar *buf, int len)
+{
+	Bytes *bytes;
+	DigestAlg **dp;
+
+	for(dp = digestalg; *dp != nil; dp++){
+		if((*dp)->fun != fun)
+			continue;
+		bytes = encode_digest(*dp, digest);
+		if(bytes == nil)
+			break;
+		if(bytes->len > len){
+			freebytes(bytes);
+			break;
+		}
+		len = bytes->len;
+		memmove(buf, bytes->data, len);
+		freebytes(bytes);
+		return len;
+	}
+	return -1;
+}
+
 uchar*
 X509rsagen(RSApriv *priv, char *subj, ulong valid[2], int *certlen)
 {
@@ -2612,21 +2634,18 @@
 	freebytes(pkbytes);
 	if(encode(e, &certinfobytes) != ASN_OK)
 		goto errret;
+
 	da = digestalg[sigalg];
 	(*da->fun)(certinfobytes->data, certinfobytes->len, digest, 0);
 	freebytes(certinfobytes);
 	certinfo = e;
-	e = mkseq(
-		mkel(mkalg(da->alg),
-		mkel(mkoctet(digest, da->len),
-		nil)));
-	if(encode(e, &sigbytes) != ASN_OK){
-		freevalfields(&certinfo.val);
+
+	sigbytes = encode_digest(da, digest);
+	if(sigbytes == nil)
 		goto errret;
-	}
-	freevalfields(&e.val);
 	pkcs1 = pkcs1pad(sigbytes, pk->n);
 	freebytes(sigbytes);
+
 	rsadecrypt(priv, pkcs1, pkcs1);
 	buflen = mptobe(pkcs1, nil, 0, &buf);
 	mpfree(pkcs1);
@@ -2682,16 +2701,13 @@
 	(*da->fun)(certinfobytes->data, certinfobytes->len, digest, 0);
 	freebytes(certinfobytes);
 	certinfo = e;
-	e = mkseq(
-		mkel(mkalg(da->alg),
-		mkel(mkoctet(digest, da->len),
-		nil)));
-	if(encode(e, &sigbytes) != ASN_OK){
-		freevalfields(&certinfo.val);
+
+	sigbytes = encode_digest(da, digest);
+	if(sigbytes == nil)
 		goto errret;
-	}
 	pkcs1 = pkcs1pad(sigbytes, pk->n);
 	freebytes(sigbytes);
+
 	rsadecrypt(priv, pkcs1, pkcs1);
 	buflen = mptobe(pkcs1, nil, 0, &buf);
 	mpfree(pkcs1);