shithub: riscv

Download patch

ref: a788f2000dcba29d5cbb37b74550907b00f1c554
parent: 5f7d769a02f0d6045ac844b40111a789996c58bc
author: cinap_lenrek <[email protected]>
date: Wed May 27 15:52:06 EDT 2015

libsec/x509: fix verify_signature(), digest_certinfo(), X509dump()

make digest_certinfo() return the digest length, otherwise
return -1 as an error and handle it in the callers.

pass expected digest length to verify_signature() and
check digest length from certificate! make sure we wont
run off the buffer.

fix newlines in error prints of X509dump().

--- a/sys/src/libsec/port/x509.c
+++ b/sys/src/libsec/port/x509.c
@@ -2145,7 +2145,7 @@
  * Our ASN.1 library doesn't return pointers into the original
  * data array, so we need to do a little hand decoding.
  */
-static void
+static int
 digest_certinfo(Bytes *cert, DigestAlg *da, uchar *digest)
 {
 	uchar *info, *p, *pend;
@@ -2161,19 +2161,20 @@
 	   length_decode(&p, pend, &length) != ASN_OK ||
 	   p+length > pend ||
 	   p+length < p)
-		return;
+		return -1;
 	info = p;
 	if(ber_decode(&p, pend, &elem) != ASN_OK)
-		return;
+		return -1;
 	freevalfields(&elem.val);
 	if(elem.tag.num != SEQUENCE)
-		return;
+		return -1;
 	infolen = p - info;
 	(*da->fun)(info, infolen, digest, nil);
+	return da->len;
 }
 
 static char*
-verify_signature(Bytes* signature, RSApub *pk, uchar *edigest, Elem **psigalg)
+verify_signature(Bytes* signature, RSApub *pk, uchar *edigest, int edigestlen, Elem **psigalg)
 {
 	Elem e;
 	Elist *el;
@@ -2199,15 +2200,14 @@
 		err = "expected 1";
 		goto end;
 	}
-	buf++;
-	while(buf[0] == 0xff)
-		buf++;
-	if(buf[0] != 0) {
+	buf++, buflen--;
+	while(buflen > 0 && buf[0] == 0xff)
+		buf++, buflen--;
+	if(buflen < 1 || buf[0] != 0) {
 		err = "expected 0";
 		goto end;
 	}
-	buf++;
-	buflen -= buf-pkcs1buf;
+	buf++, buflen--;
 	if(decode(buf, buflen, &e) != ASN_OK || !is_seq(&e, &el) || elistlen(el) != 2 ||
 			!is_octetstring(&el->tl->hd, &digest)) {
 		err = "signature parse error";
@@ -2214,9 +2214,12 @@
 		goto end;
 	}
 	*psigalg = &el->hd;
-	if(memcmp(digest->data, edigest, digest->len) == 0)
+	if(digest->len != edigestlen) {
+		err = "bad digest length";
 		goto end;
-	err = "digests did not match";
+	}
+	if(memcmp(digest->data, edigest, edigestlen) != 0)
+		err = "digests did not match";
 
 end:
 	if(pkcs1 != nil)
@@ -2256,17 +2259,23 @@
 	char *e;
 	Bytes *b;
 	CertX509 *c;
-	uchar digest[256];
+	int digestlen;
+	uchar digest[MAXdlen];
 	Elem *sigalg;
 
 	b = makebytes(cert, ncert);
 	c = decode_cert(b);
-	if(c != nil)
-		digest_certinfo(b, digestalg[c->signature_alg], digest);
-	freebytes(b);
-	if(c == nil)
+	if(c == nil){
+		freebytes(b);
 		return "cannot decode cert";
-	e = verify_signature(c->signature, pk, digest, &sigalg);
+	}
+	digestlen = digest_certinfo(b, digestalg[c->signature_alg], digest);
+	freebytes(b);
+	if(digestlen <= 0){
+		freecert(c);
+		return "cannot decode certinfo";
+	}
+	e = verify_signature(c->signature, pk, digest, digestlen, &sigalg);
 	freecert(c);
 	return e;
 }
@@ -2671,7 +2680,7 @@
 	Bytes *b;
 	CertX509 *c;
 	RSApub *pk;
-	DigestAlg *da;
+	int digestlen;
 	uchar digest[MAXdlen];
 	Elem *sigalg;
 
@@ -2680,12 +2689,16 @@
 	c = decode_cert(b);
 	if(c == nil){
 		freebytes(b);
-		print("cannot decode cert");
+		print("cannot decode cert\n");
 		return;
 	}
-	da = digestalg[c->signature_alg];
-	digest_certinfo(b, da, digest);
+	digestlen = digest_certinfo(b, digestalg[c->signature_alg], digest);
 	freebytes(b);
+	if(digestlen <= 0){
+		freecert(c);
+		print("cannot decode certinfo\n");
+		return;
+	}
 
 	print("serial %d\n", c->serial);
 	print("issuer %s\n", c->issuer);
@@ -2694,8 +2707,8 @@
 	pk = decode_rsapubkey(c->publickey);
 	print("pubkey e=%B n(%d)=%B\n", pk->ek, mpsignif(pk->n), pk->n);
 
-	print("sigalg=%d digest=%.*H\n", c->signature_alg, da->len, digest);
-	e = verify_signature(c->signature, pk, digest, &sigalg);
+	print("sigalg=%d digest=%.*H\n", c->signature_alg, digestlen, digest);
+	e = verify_signature(c->signature, pk, digest, digestlen, &sigalg);
 	if(e==nil){
 		e = "nil (meaning ok)";
 		print("sigalg=\n");