shithub: riscv

Download patch

ref: 582d2e664f85819f56599c8b632a04b4bd4dddc7
parent: e3cad82680aaf115ff179637fa67f32ca606b6d1
author: cinap_lenrek <[email protected]>
date: Fri Dec 29 21:36:47 EST 2017

libsec: avoid unneccesary memory copies and redundant code in x509

getting rid of some functions that take Byte* and instead
pass uchar* and length.

keeping the signature and public key fields in CertX509
as Bits* allows ownership transfer by swapping pointers.

use common code to copy CN from subject field.

--- a/sys/src/libsec/port/x509.c
+++ b/sys/src/libsec/port/x509.c
@@ -1474,8 +1474,7 @@
 		freeints(v->u.objidval);
 		break;
 	case VString:
-		if(v->u.stringval)
-			free(v->u.stringval);
+		free(v->u.stringval);
 		break;
 	case VSeq:
 		el = v->u.seqval;
@@ -1490,6 +1489,7 @@
 		freeelist(el);
 		break;
 	}
+	memset(v, 0, sizeof(*v));
 }
 
 static mpint*
@@ -1585,9 +1585,9 @@
 	char*	validity_end;
 	char*	subject;
 	int	publickey_alg;
-	Bytes*	publickey;
+	Bits*	publickey;
 	int	signature_alg;
-	Bytes*	signature;
+	Bits*	signature;
 	int	curve;
 } CertX509;
 
@@ -1733,8 +1733,8 @@
 	free(c->validity_start);
 	free(c->validity_end);
 	free(c->subject);
-	freebytes(c->publickey);
-	freebytes(c->signature);
+	freebits(c->publickey);
+	freebits(c->signature);
 	free(c);
 }
 
@@ -1827,11 +1827,10 @@
 }
 
 static CertX509*
-decode_cert(Bytes* a)
+decode_cert(uchar *buf, int len)
 {
 	int ok = 0;
 	int n;
-	CertX509* c = nil;
 	Elem  ecert;
 	Elem* ecertinfo;
 	Elem* esigalg;
@@ -1849,8 +1848,9 @@
 	Bits* bits = nil;
 	Bytes* b;
 	Elem* e;
+	CertX509* c = nil;
 
-	if(decode(a->data, a->len, &ecert) != ASN_OK)
+	if(decode(buf, len, &ecert) != ASN_OK)
 		goto errret;
 
 	c = (CertX509*)emalloc(sizeof(CertX509));
@@ -1942,18 +1942,19 @@
 		if(c->curve < 0)
 			goto errret;
 	}
-  	if(!is_bitstring(&elpubkey->tl->hd, &bits))
+	elpubkey = elpubkey->tl;
+	if(!is_bitstring(&elpubkey->hd, &bits))
 		goto errret;
-	if(bits->unusedbits != 0)
-		goto errret;
- 	c->publickey = makebytes(bits->data, bits->len);
+	elpubkey->hd.val.u.bitstringval = nil;	/* transfer ownership */
+	c->publickey = bits;
 
 	/*resume Certificate */
 	if(c->signature_alg < 0)
 		goto errret;
- 	if(!is_bitstring(esig, &bits))
+	if(!is_bitstring(esig, &bits))
 		goto errret;
- 	c->signature = makebytes(bits->data, bits->len);
+	esig->val.u.bitstringval = nil;	/* transfer ownership */
+	c->signature = bits;
 	ok = 1;
 
 errret:
@@ -2000,12 +2001,6 @@
 
 }
 
-static RSApub*
-decode_rsapubkey(Bytes* a)
-{
-	return asn1toRSApub(a->data, a->len);
-}
-
 /*
  *	RSAPrivateKey ::= SEQUENCE {
  *		version Version,
@@ -2018,16 +2013,16 @@
  *		exponent2 INTEGER, -- d mod (q-1)
  *		coefficient INTEGER -- (inverse of q) mod p }
  */
-static RSApriv*
-decode_rsaprivkey(Bytes* a)
+RSApriv*
+asn1toRSApriv(uchar *buf, int len)
 {
 	int version;
 	Elem e;
 	Elist *el;
-	RSApriv* key;
+	Bytes *b;
+	RSApriv* key = nil;
 
-	key = nil;
-	if(decode(a->data, a->len, &e) != ASN_OK)
+	if(decode(buf, len, &e) != ASN_OK)
 		goto errret;
 	if(!is_seq(&e, &el))
 		goto errret;
@@ -2038,8 +2033,8 @@
 	if(elistlen(el) != 9){
 		if(elistlen(el) == 3
 		&& parse_alg(&el->tl->hd) == ALG_rsaEncryption
-		&& is_octetstring(&el->tl->tl->hd, &a)){
-			key = decode_rsaprivkey(a);
+		&& is_octetstring(&el->tl->tl->hd, &b)){
+			key = asn1toRSApriv(b->data, b->len);
 			if(key != nil)
 				goto done;
 		}
@@ -2098,16 +2093,15 @@
  *		priv_key INTEGER, -- secret
  *	}
  */
-static DSApriv*
-decode_dsaprivkey(Bytes* a)
+DSApriv*
+asn1toDSApriv(uchar *buf, int len)
 {
 	int version;
 	Elem e;
 	Elist *el;
-	DSApriv* key;
+	DSApriv* key = nil;
 
-	key = dsaprivalloc();
-	if(decode(a->data, a->len, &e) != ASN_OK)
+	if(decode(buf, len, &e) != ASN_OK)
 		goto errret;
 	if(!is_seq(&e, &el) || elistlen(el) != 6)
 		goto errret;
@@ -2115,6 +2109,7 @@
 	if(!is_int(&el->hd, &version) || version != 0)
 		goto errret;
 
+	key = dsaprivalloc();
 	el = el->tl;
 	if((key->pub.p = asn1mpint(&el->hd)) == nil)
 		goto errret;
@@ -2143,30 +2138,6 @@
 	return nil;
 }
 
-RSApriv*
-asn1toRSApriv(uchar *kd, int kn)
-{
-	Bytes *b;
-	RSApriv *key;
-
-	b = makebytes(kd, kn);
-	key = decode_rsaprivkey(b);
-	freebytes(b);
-	return key;
-}
-
-DSApriv*
-asn1toDSApriv(uchar *kd, int kn)
-{
-	Bytes *b;
-	DSApriv *key;
-
-	b = makebytes(kd, kn);
-	key = decode_dsaprivkey(b);
-	freebytes(b);
-	return key;
-}
-
 /*
  * digest(CertificateInfo)
  * Our ASN.1 library doesn't return pointers into the original
@@ -2173,16 +2144,15 @@
  * data array, so we need to do a little hand decoding.
  */
 static int
-digest_certinfo(Bytes *cert, DigestAlg *da, uchar *digest)
+digest_certinfo(uchar *cert, int ncert, DigestAlg *da, uchar *digest)
 {
 	uchar *info, *p, *pend;
-	ulong infolen;
 	int isconstr, length;
 	Tag tag;
 	Elem elem;
 
-	p = cert->data;
-	pend = cert->data + cert->len;
+	p = cert;
+	pend = cert + ncert;
 	if(tag_decode(&p, pend, &tag, &isconstr) != ASN_OK ||
 	   tag.class != Universal || tag.num != SEQUENCE ||
 	   length_decode(&p, pend, &length) != ASN_OK ||
@@ -2195,8 +2165,7 @@
 	freevalfields(&elem.val);
 	if(elem.tag.num != SEQUENCE)
 		return -1;
-	infolen = p - info;
-	(*da->fun)(info, infolen, digest, nil);
+	(*da->fun)(info, p - info, digest, nil);
 	return da->len;
 }
 
@@ -2320,27 +2289,32 @@
 	return err;
 }
 
+static void
+copysubject(char *name, int nname, char *subject)
+{
+	char *e;
+
+	if(name == nil)
+		return;
+	memset(name, 0, nname);
+	if(subject == nil)
+		return;
+	strncpy(name, subject, nname-1);
+	e = strnchr(name, ',');
+	if(e != nil)
+		*e = 0;	/* take just CN part of Distinguished Name */
+}
+
 ECpub*
 X509toECpub(uchar *cert, int ncert, char *name, int nname, ECdomain *dom)
 {
 	CertX509 *c;
 	ECpub *pub;
-	Bytes *b;
 
-	if(name != nil)
-		memset(name, 0, nname);
-
-	b = makebytes(cert, ncert);
-	c = decode_cert(b);
-	freebytes(b);
+	c = decode_cert(cert, ncert);
 	if(c == nil)
 		return nil;
-	if(name != nil && c->subject != nil){
-		char *e = strchr(c->subject, ',');
-		if(e != nil)
-			*e = 0;	/* take just CN part of Distinguished Name */
-		strncpy(name, c->subject, nname);
-	}
+	copysubject(name, nname, c->subject);
 	pub = nil;
 	if(c->publickey_alg == ALG_ecPublicKey){
 		ecdominit(dom, namedcurves[c->curve]);
@@ -2356,19 +2330,14 @@
 X509ecdsaverify(uchar *cert, int ncert, ECdomain *dom, ECpub *pk)
 {
 	char *e;
-	Bytes *b;
 	CertX509 *c;
 	int digestlen;
 	uchar digest[MAXdlen];
 
-	b = makebytes(cert, ncert);
-	c = decode_cert(b);
-	if(c == nil){
-		freebytes(b);
+	c = decode_cert(cert, ncert);
+	if(c == nil)
 		return "cannot decode cert";
-	}
-	digestlen = digest_certinfo(b, digestalg[c->signature_alg], digest);
-	freebytes(b);
+	digestlen = digest_certinfo(cert, ncert, digestalg[c->signature_alg], digest);
 	if(digestlen <= 0){
 		freecert(c);
 		return "cannot decode certinfo";
@@ -2381,27 +2350,16 @@
 RSApub*
 X509toRSApub(uchar *cert, int ncert, char *name, int nname)
 {
-	Bytes *b;
 	CertX509 *c;
 	RSApub *pub;
 
-	if(name != nil)
-		memset(name, 0, nname);
-
-	b = makebytes(cert, ncert);
-	c = decode_cert(b);
-	freebytes(b);
+	c = decode_cert(cert, ncert);
 	if(c == nil)
 		return nil;
-	if(name != nil && c->subject != nil){
-		char *e = strchr(c->subject, ',');
-		if(e != nil)
-			*e = 0;	/* take just CN part of Distinguished Name */
-		strncpy(name, c->subject, nname);
-	}
+	copysubject(name, nname, c->subject);
 	pub = nil;
 	if(c->publickey_alg == ALG_rsaEncryption)
-		pub = decode_rsapubkey(c->publickey);
+		pub = asn1toRSApub(c->publickey->data, c->publickey->len);
 	freecert(c);
 	return pub;
 }
@@ -2410,19 +2368,14 @@
 X509rsaverify(uchar *cert, int ncert, RSApub *pk)
 {
 	char *e;
-	Bytes *b;
 	CertX509 *c;
 	int digestlen;
 	uchar digest[MAXdlen];
 
-	b = makebytes(cert, ncert);
-	c = decode_cert(b);
-	if(c == nil){
-		freebytes(b);
+	c = decode_cert(cert, ncert);
+	if(c == nil)
 		return "cannot decode cert";
-	}
-	digestlen = digest_certinfo(b, digestalg[c->signature_alg], digest);
-	freebytes(b);
+	digestlen = digest_certinfo(cert, ncert, digestalg[c->signature_alg], digest);
 	if(digestlen <= 0){
 		freecert(c);
 		return "cannot decode certinfo";
@@ -2643,20 +2596,14 @@
 static Bytes*
 encode_digest(DigestAlg *da, uchar *digest)
 {
-	Bytes *ans;
-	int err;
-	Elem e;
-
-	e = mkseq(
+	Bytes *b = nil;
+	Elem e = mkseq(
 		mkel(mkalg(da->alg),
 		mkel(mkoctet(digest, da->len),
 		nil)));
-	err = encode(e, &ans);
+	encode(e, &b);
 	freevalfields(&e.val);
-	if(err != ASN_OK)
-		return nil;
-
-	return ans;
+	return b;
 }
 
 int
@@ -2875,12 +2822,10 @@
 	free(buf);
 	if(encode(e, &certbytes) != ASN_OK)
 		goto errret;
-	if(certlen)
+	if(certlen != nil)
 		*certlen = certbytes->len;
-	cert = malloc(certbytes->len);
-	if(cert != nil)
-		memmove(cert, certbytes->data, certbytes->len);
-	freebytes(certbytes);
+	cert = (uchar*)certbytes;
+	memmove(cert, certbytes->data, certbytes->len);
 errret:
 	freevalfields(&e.val);
 	free(subj);
@@ -2942,12 +2887,10 @@
 	free(buf);
 	if(encode(e, &certbytes) != ASN_OK)
 		goto errret;
-	if(certlen)
+	if(certlen != nil)
 		*certlen = certbytes->len;
-	cert = malloc(certbytes->len);
-	if(cert != nil)
-		memmove(cert, certbytes->data, certbytes->len);
-	freebytes(certbytes);
+	cert = (uchar*)certbytes;
+	memmove(cert, certbytes->data, certbytes->len);
 errret:
 	freevalfields(&e.val);
 	free(subj);
@@ -3048,7 +2991,6 @@
 X509dump(uchar *cert, int ncert)
 {
 	char *e;
-	Bytes *b;
 	CertX509 *c;
 	RSApub *rsapub;
 	ECpub *ecpub;
@@ -3057,15 +2999,13 @@
 	uchar digest[MAXdlen];
 
 	print("begin X509dump\n");
-	b = makebytes(cert, ncert);
-	c = decode_cert(b);
+	c = decode_cert(cert, ncert);
 	if(c == nil){
-		freebytes(b);
 		print("cannot decode cert\n");
 		return;
 	}
-	digestlen = digest_certinfo(b, digestalg[c->signature_alg], digest);
-	freebytes(b);
+
+	digestlen = digest_certinfo(cert, ncert, digestalg[c->signature_alg], digest);
 	if(digestlen <= 0){
 		freecert(c);
 		print("cannot decode certinfo\n");
@@ -3082,10 +3022,11 @@
 
 	switch(c->publickey_alg){
 	case ALG_rsaEncryption:
-		rsapub = decode_rsapubkey(c->publickey);
+		rsapub = asn1toRSApub(c->publickey->data, c->publickey->len);
 		if(rsapub != nil){
 			print("rsa pubkey e=%B n(%d)=%B\n", rsapub->ek, mpsignif(rsapub->n), rsapub->n);
-			e = X509rsaverifydigest(c->signature->data, c->signature->len, digest, digestlen, rsapub);
+			e = X509rsaverifydigest(c->signature->data, c->signature->len,
+				digest, digestlen, rsapub);
 			if(e==nil)
 				e = "nil (meaning ok)";
 			print("self-signed X509rsaverifydigest returns: %s\n", e);
@@ -3096,7 +3037,8 @@
 		ecdominit(&ecdom, namedcurves[c->curve]);
 		ecpub = ecdecodepub(&ecdom, c->publickey->data, c->publickey->len);
 		if(ecpub != nil){
-			e = X509ecdsaverifydigest(c->signature->data, c->signature->len, digest, digestlen, &ecdom, ecpub);
+			e = X509ecdsaverifydigest(c->signature->data, c->signature->len,
+				digest, digestlen, &ecdom, ecpub);
 			if(e==nil)
 				e = "nil (meaning ok)";
 			print("self-signed X509ecdsaverifydigest returns: %s\n", e);