shithub: drawterm

Download patch

ref: 1cb0ad40de5c6b8232432705d45aa71029d7df12
parent: f5683254d71662c2dc536dba1d2f6fbf5bf10af3
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Feb 6 16:51:02 EST 2017

libsec: import x509 and rsagen changes from 9front

--- a/libsec/rsagen.c
+++ b/libsec/rsagen.c
@@ -26,9 +26,13 @@
 	// find an e relatively prime to phi
 	t1 = mpnew(0);
 	t2 = mpnew(0);
-	mprand(elen, genrandom, e);
-	if(mpcmp(e,mptwo) <= 0)
-		itomp(3, e);
+	if(elen == 0)
+		itomp(65537, e);
+	else {
+		mprand(elen, genrandom, e);
+		if(mpcmp(e,mptwo) <= 0)
+			itomp(3, e);
+	}
 	// See Menezes et al. p.291 "8.8 Note (selecting primes)" for discussion
 	// of the merits of various choices of primes and exponents.  e=3 is a
 	// common and recommended exponent, but doesn't necessarily work here
--- a/libsec/x509.c
+++ b/libsec/x509.c
@@ -1885,7 +1885,7 @@
  	esubj = &el->hd;
  	el = el->tl;
  	epubkey = &el->hd;
- 	if(!is_int(eserial, &c->serial)) {
+	if(!is_int(eserial, &c->serial)) {
 		if(!is_bigint(eserial, &b))
 			goto errret;
 		c->serial = -1;	/* else we have to change cert struct */
@@ -2129,8 +2129,12 @@
 
 	if(is_int(e, &v))
 		return itomp(v, nil);
-	if(is_bigint(e, &b))
-		return betomp(b->data, b->len, nil);
+	if(is_bigint(e, &b)){
+		mpint *s = betomp(b->data, b->len, nil);
+		if(b->len > 0 && (b->data[0] & 0x80) != 0)
+			mpxtend(s, b->len*8, s);
+		return s;
+	}
 	return nil;
 }
 
@@ -2143,6 +2147,10 @@
 	mpint *mp;
 
 	pm1 = n - 1 - len;
+	if(pm1 <= 2){
+		werrstr("pkcs1padbuf: modulus too small");
+		return nil;
+	}
 	p = (uchar*)emalloc(n);
 	p[0] = 0;
 	p[1] = 1;
@@ -2457,15 +2465,20 @@
 mkbigint(mpint *p)
 {
 	Elem e;
-	uchar *buf;
-	int buflen;
 
 	e.tag.class = Universal;
 	e.tag.num = INTEGER;
 	e.val.tag = VBigInt;
-	buflen = mptobe(p, nil, 0, &buf);
-	e.val.u.bigintval = makebytes(buf, buflen);
-	free(buf);
+	e.val.u.bigintval = newbytes((mpsignif(p)+8)/8);
+	if(p->sign < 0){
+		mpint *s = mpnew(e.val.u.bigintval->len*8+1);
+		mpleft(mpone, e.val.u.bigintval->len*8, s);
+		mpadd(p, s, s);
+		mptober(s, e.val.u.bigintval->data, e.val.u.bigintval->len);
+		mpfree(s);
+	} else {
+		mptober(p, e.val.u.bigintval->data, e.val.u.bigintval->len);
+	}
 	return e;
 }
 
@@ -2675,6 +2688,107 @@
 	return -1;
 }
 
+static Elem
+mkcont(Elem e, int num)
+{
+	e = mkseq(mkel(e, nil));
+	e.tag.class = Context;
+	e.tag.num = num;
+	return e;
+}
+
+static Elem
+mkaltname(char *s)
+{
+	Elem e;
+	int i;
+
+	for(i=0; i<nelem(DN_oid); i++){
+		if(strstr(s, DN_oid[i].prefix) != nil)
+			return mkcont(mkDN(s), 4); /* DN */
+	}
+	e = mkstring(s, IA5String);
+	e.tag.class = Context;
+	e.tag.num = strchr(s, '@') != nil ? 1 : 2; /* email : DNS */
+	return e;
+}
+
+static Elist*
+mkaltnames(char *alts)
+{
+	Elist *el;
+	char *s, *p;
+
+	if(alts == nil)
+		return nil;
+
+	el = nil;
+	alts = estrdup(alts);
+	for(s = alts; s != nil; s = p){
+		while(*s == ' ')
+			s++;
+		if(*s == '\0')
+			break;
+		if((p = strchr(s, ',')) != nil)
+			*p++ = 0;
+		el = mkel(mkaltname(s), el);
+	}
+	free(alts);
+	return el;
+}
+
+static Elist*
+mkextel(Elem e, Ints *oid, Elist *el)
+{
+	Bytes *b = nil;
+
+	if(encode(e, &b) == ASN_OK){
+		el = mkel(mkseq(
+			mkel(mkoid(oid),
+			mkel(mkoctet(b->data, b->len),
+			nil))), el);
+		freebytes(b);
+	}
+	freevalfields(&e.val);
+	return el;
+}
+
+static Ints15 oid_subjectAltName = {4, 2, 5, 29, 17 };
+static Ints15 oid_extensionRequest = { 7, 1, 2, 840, 113549, 1, 9, 14};
+
+static Elist*
+mkextensions(char *alts, int req)
+{
+	Elist *sl, *xl;
+
+	xl = nil;
+	if((sl = mkaltnames(alts)) != nil)
+		xl = mkextel(mkseq(sl), (Ints*)&oid_subjectAltName, xl);
+	if(xl != nil){
+		if(req) return mkel(mkcont(mkseq(
+			mkel(mkoid((Ints*)&oid_extensionRequest),
+			mkel(mkset(mkel(mkseq(xl), nil)), nil))), 0), nil);
+		return mkel(mkcont(mkseq(xl), 3), nil);
+	}
+	return nil;
+}
+
+static char*
+splitalts(char *s)
+{
+	int q;
+
+	for(q = 0; *s != '\0'; s++){
+		if(*s == '\'')
+			q ^= 1;
+		else if(q == 0 && *s == ','){
+			*s++ = 0;
+			return s;
+		}
+	}
+	return nil;
+}
+
 uchar*
 X509rsagen(RSApriv *priv, char *subj, ulong valid[2], int *certlen)
 {
@@ -2687,12 +2801,18 @@
 	uchar digest[MAXdlen], *buf;
 	int buflen;
 	mpint *pkcs1;
+	char *alts;
 
+	subj = estrdup(subj);
+	alts = splitalts(subj);
+
 	e = mkseq(mkel(mkbigint(pk->n),mkel(mkint(mptoi(pk->ek)),nil)));
 	if(encode(e, &pkbytes) != ASN_OK)
 		goto errret;
 	freevalfields(&e.val);
+
 	e = mkseq(
+		mkel(mkcont(mkint(2), 0),
 		mkel(mkint(serial),
 		mkel(mkalg(sigalg),
 		mkel(mkDN(subj),
@@ -2705,7 +2825,7 @@
 			mkel(mkalg(ALG_rsaEncryption),
 			mkel(mkbits(pkbytes->data, pkbytes->len),
 			nil))),
-		nil)))))));
+		mkextensions(alts, 0)))))))));
 	freebytes(pkbytes);
 	if(encode(e, &certinfobytes) != ASN_OK)
 		goto errret;
@@ -2720,6 +2840,8 @@
 		goto errret;
 	pkcs1 = pkcs1pad(sigbytes, pk->n);
 	freebytes(sigbytes);
+	if(pkcs1 == nil)
+		goto errret;
 
 	rsadecrypt(priv, pkcs1, pkcs1);
 	buflen = mptobe(pkcs1, nil, 0, &buf);
@@ -2740,6 +2862,7 @@
 	freebytes(certbytes);
 errret:
 	freevalfields(&e.val);
+	free(subj);
 	return cert;
 }
 
@@ -2756,7 +2879,11 @@
 	uchar digest[MAXdlen], *buf;
 	int buflen;
 	mpint *pkcs1;
+	char *alts;
 
+	subj = estrdup(subj);
+	alts = splitalts(subj);
+
 	e = mkseq(mkel(mkbigint(pk->n),mkel(mkint(mptoi(pk->ek)),nil)));
 	if(encode(e, &pkbytes) != ASN_OK)
 		goto errret;
@@ -2768,7 +2895,7 @@
 			mkel(mkalg(ALG_rsaEncryption),
 			mkel(mkbits(pkbytes->data, pkbytes->len),
 			nil))),
-		nil))));
+		mkextensions(alts, 1)))));
 	freebytes(pkbytes);
 	if(encode(e, &certinfobytes) != ASN_OK)
 		goto errret;
@@ -2782,6 +2909,8 @@
 		goto errret;
 	pkcs1 = pkcs1pad(sigbytes, pk->n);
 	freebytes(sigbytes);
+	if(pkcs1 == nil)
+		goto errret;
 
 	rsadecrypt(priv, pkcs1, pkcs1);
 	buflen = mptobe(pkcs1, nil, 0, &buf);
@@ -2802,6 +2931,7 @@
 	freebytes(certbytes);
 errret:
 	freevalfields(&e.val);
+	free(subj);
 	return cert;
 }
 
@@ -2808,8 +2938,12 @@
 static char*
 tagdump(Tag tag)
 {
-	if(tag.class != Universal)
-		return smprint("class%d,num%d", tag.class, tag.num);
+	static char buf[32];
+
+	if(tag.class != Universal){
+		snprint(buf, sizeof(buf), "class%d,num%d", tag.class, tag.num);
+		return buf;
+	}
 	switch(tag.num){
 	case BOOLEAN: return "BOOLEAN";
 	case INTEGER: return "INTEGER";
@@ -2838,7 +2972,8 @@
 	case UniversalString: return "UniversalString";
 	case BMPString: return "BMPString";
 	default:
-		return smprint("Universal,num%d", tag.num);
+		snprint(buf, sizeof(buf), "Universal,num%d", tag.num);
+		return buf;
 	}
 }
 
@@ -2858,7 +2993,7 @@
 	case VBigInt: print("BigInt[%d] %.2x%.2x...",v.u.bigintval->len,v.u.bigintval->data[0],v.u.bigintval->data[1]); break;
 	case VReal: print("Real..."); break;
 	case VOther: print("Other..."); break;
-	case VBitString: print("BitString..."); break;
+	case VBitString: print("BitString[%d]...", v.u.bitstringval->len*8 - v.u.bitstringval->unusedbits); break;
 	case VNull: print("Null"); break;
 	case VEOC: print("EOC..."); break;
 	case VObjId: print("ObjId");
@@ -2922,7 +3057,6 @@
 	print("issuer %s\n", c->issuer);
 	print("validity %s %s\n", c->validity_start, c->validity_end);
 	print("subject %s\n", c->subject);
-
 	print("sigalg=%d digest=%.*H\n", c->signature_alg, digestlen, digest);
 	print("publickey_alg=%d pubkey[%d] %.*H\n", c->publickey_alg, c->publickey->len,
 		c->publickey->len, c->publickey->data);