shithub: drawterm

Download patch

ref: 6f175d289e57bf447640255d484f411f631195be
parent: 1cb0ad40de5c6b8232432705d45aa71029d7df12
author: cinap_lenrek <[email protected]>
date: Thu Feb 9 19:21:28 EST 2017

libsec: import changed from 9front

--- a/libsec/tlshand.c
+++ b/libsec/tlshand.c
@@ -430,8 +430,8 @@
 static int	digestDHparams(TlsSec *sec, Bytes *par, uchar digest[MAXdlen], int sigalg);
 static char*	verifyDHparams(TlsSec *sec, Bytes *par, Bytes *cert, Bytes *sig, int sigalg);
 
-static Bytes*	pkcs1_encrypt(Bytes* data, RSApub* key, int blocktype);
-static Bytes*	pkcs1_decrypt(TlsSec *sec, Bytes *cipher);
+static Bytes*	pkcs1_encrypt(Bytes* data, RSApub* key);
+static Bytes*	pkcs1_decrypt(TlsSec *sec, Bytes *data);
 static Bytes*	pkcs1_sign(TlsSec *sec, uchar *digest, int digestlen, int sigalg);
 
 static void* emalloc(int);
@@ -451,7 +451,8 @@
 static int lookupid(Ints* b, int id);
 
 /* x509.c */
-extern mpint*	pkcs1padbuf(uchar *buf, int len, mpint *modulus);
+extern mpint*	pkcs1padbuf(uchar *buf, int len, mpint *modulus, int blocktype);
+extern int	pkcs1unpadbuf(uchar *buf, int len, mpint *modulus, int blocktype);
 extern int	asn1encodedigest(DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*), uchar *digest, uchar *buf, int len);
 
 //================= client/server ========================
@@ -2322,6 +2323,8 @@
 	char *p;
 	int rv;
 
+	if(cipher == nil)
+		return nil;
 	p = mptoa(cipher, 16, nil, 0);
 	mpfree(cipher);
 	if(p == nil)
@@ -2659,7 +2662,7 @@
 	pm = newbytes(MasterSecretSize);
 	put16(pm->data, sec->clientVers);
 	genrandom(pm->data+2, MasterSecretSize - 2);
-	epm = pkcs1_encrypt(pm, pub, 2);
+	epm = pkcs1_encrypt(pm, pub);
 	setMasterSecret(sec, pm);
 	rsapubfree(pub);
 	return epm;
@@ -2832,105 +2835,40 @@
 	return err;
 }
 
-
-// Do RSA computation on block according to key, and pad
-// result on left with zeros to make it modlen long.
+// encrypt data according to PKCS#1, /lib/rfc/rfc2437 9.1.2.1
 static Bytes*
-rsacomp(Bytes* block, RSApub* key, int modlen)
+pkcs1_encrypt(Bytes* data, RSApub* key)
 {
 	mpint *x, *y;
-	Bytes *a, *ybytes;
-	int ylen;
 
-	x = bytestomp(block);
+	x = pkcs1padbuf(data->data, data->len, key->n, 2);
+	if(x == nil)
+		return nil;
 	y = rsaencrypt(key, x, nil);
 	mpfree(x);
-	ybytes = mptobytes(y);
-	ylen = ybytes->len;
+	data = newbytes((mpsignif(key->n)+7)/8);
+	mptober(y, data->data, data->len);
 	mpfree(y);
-
-	if(ylen < modlen) {
-		a = newbytes(modlen);
-		memset(a->data, 0, modlen-ylen);
-		memmove(a->data+modlen-ylen, ybytes->data, ylen);
-		freebytes(ybytes);
-		ybytes = a;
-	}
-	else if(ylen > modlen) {
-		// assume it has leading zeros (mod should make it so)
-		a = newbytes(modlen);
-		memmove(a->data, ybytes->data, modlen);
-		freebytes(ybytes);
-		ybytes = a;
-	}
-	return ybytes;
+	return data;
 }
 
-// encrypt data according to PKCS#1, /lib/rfc/rfc2437 9.1.2.1
-static Bytes*
-pkcs1_encrypt(Bytes* data, RSApub* key, int blocktype)
-{
-	Bytes *pad, *eb, *ans;
-	int i, dlen, padlen, modlen;
-
-	modlen = (mpsignif(key->n)+7)/8;
-	dlen = data->len;
-	if(modlen < 12 || dlen > modlen - 11)
-		return nil;
-	padlen = modlen - 3 - dlen;
-	pad = newbytes(padlen);
-	genrandom(pad->data, padlen);
-	for(i = 0; i < padlen; i++) {
-		if(blocktype == 0)
-			pad->data[i] = 0;
-		else if(blocktype == 1)
-			pad->data[i] = 255;
-		else if(pad->data[i] == 0)
-			pad->data[i] = 1;
-	}
-	eb = newbytes(modlen);
-	eb->data[0] = 0;
-	eb->data[1] = blocktype;
-	memmove(eb->data+2, pad->data, padlen);
-	eb->data[padlen+2] = 0;
-	memmove(eb->data+padlen+3, data->data, dlen);
-	ans = rsacomp(eb, key, modlen);
-	freebytes(eb);
-	freebytes(pad);
-	return ans;
-}
-
 // decrypt data according to PKCS#1, with given key.
-// expect a block type of 2.
 static Bytes*
-pkcs1_decrypt(TlsSec *sec, Bytes *cipher)
+pkcs1_decrypt(TlsSec *sec, Bytes *data)
 {
-	Bytes *eb;
-	int i, modlen;
-	mpint *x, *y;
+	mpint *y;
 
-	modlen = (mpsignif(sec->rsapub->n)+7)/8;
-	if(cipher->len != modlen)
+	if(data->len != (mpsignif(sec->rsapub->n)+7)/8)
 		return nil;
-	x = bytestomp(cipher);
-	y = factotum_rsa_decrypt(sec->rpc, x);
+	y = factotum_rsa_decrypt(sec->rpc, bytestomp(data));
 	if(y == nil)
 		return nil;
-	eb = newbytes(modlen);
-	mptober(y, eb->data, eb->len);
-	mpfree(y);
-	if(eb->data[0] == 0 && eb->data[1] == 2) {
-		for(i = 2; i < eb->len; i++)
-			if(eb->data[i] == 0)
-				break;
-		if(++i < eb->len){
-			eb->len -= i;
-			memmove(eb->data, eb->data+i, eb->len);
-			return eb;
-		}
+	data = mptobytes(y);
+	if((data->len = pkcs1unpadbuf(data->data, data->len, sec->rsapub->n, 2)) < 0){
+		freebytes(data);
+		return nil;
 	}
-	freebytes(eb);
-	return nil;
+	return data;
 }
 
 static Bytes*
@@ -2951,7 +2889,7 @@
 		werrstr("bad digest algorithm");
 		return nil;
 	}
-	signedMP = factotum_rsa_decrypt(sec->rpc, pkcs1padbuf(buf, digestlen, sec->rsapub->n));
+	signedMP = factotum_rsa_decrypt(sec->rpc, pkcs1padbuf(buf, digestlen, sec->rsapub->n, 1));
 	if(signedMP == nil)
 		return nil;
 	signature = mptobytes(signedMP);
--- a/libsec/x509.c
+++ b/libsec/x509.c
@@ -1492,6 +1492,19 @@
 	}
 }
 
+static mpint*
+asn1mpint(Elem *e)
+{
+	Bytes *b;
+	int v;
+
+	if(is_int(e, &v))
+		return itomp(v, nil);
+	if(is_bigint(e, &b))
+		return betomp(b->data, b->len, nil);
+	return nil;
+}
+
 /* end of general ASN1 functions */
 
 
@@ -1695,6 +1708,8 @@
 	nil
 };
 
+static Bytes* encode_digest(DigestAlg *da, uchar *digest);
+
 static Ints15 oid_secp256r1 = {7, 1, 2, 840, 10045, 3, 1, 7};
 static Ints15 oid_secp384r1 = {5, 1, 3, 132, 0, 34};
 
@@ -2121,54 +2136,6 @@
 	return nil;
 }
 
-static mpint*
-asn1mpint(Elem *e)
-{
-	Bytes *b;
-	int v;
-
-	if(is_int(e, &v))
-		return itomp(v, 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;
-}
-
-mpint*
-pkcs1padbuf(uchar *buf, int len, mpint *modulus)
-{
-	int n = (mpsignif(modulus)+7)/8;
-	int pm1, i;
-	uchar *p;
-	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;
-	for(i = 2; i < pm1; i++)
-		p[i] = 0xFF;
-	p[pm1] = 0;
-	memcpy(&p[pm1+1], buf, len);
-	mp = betomp(p, n, nil);
-	free(p);
-	return mp;
-}
-
-static mpint*
-pkcs1pad(Bytes *b, mpint *modulus)
-{
-	return pkcs1padbuf(b->data, b->len, modulus);
-}
-
 RSApriv*
 asn1toRSApriv(uchar *kd, int kn)
 {
@@ -2226,79 +2193,92 @@
 	return da->len;
 }
 
-static int
-pkcs1decryptsignature(uchar *sig, int siglen, RSApub *pk, uchar **pbuf)
+mpint*
+pkcs1padbuf(uchar *buf, int len, mpint *modulus, int blocktype)
 {
-	int nlen, buflen;
-	mpint *pkcs1;
-	uchar *buf;
+	int i, n = (mpsignif(modulus)-1)/8;
+	int pad = n - 2 - len;
+	uchar *p;
+	mpint *mp;
 
-	*pbuf = nil;
+	if(pad < 8){
+		werrstr("rsa modulus too small");
+		return nil;
+	}
+	if((p = malloc(n)) == nil)
+		return nil;
+	p[0] = blocktype;
+	switch(blocktype){
+	default:
+	case 1:
+		memset(p+1, 0xFF, pad);
+		break;
+	case 2:
+		for(i=1; i <= pad; i++)
+			p[i] = 1 + nfastrand(255);
+		break;
+	}
+	p[1+pad] = 0;
+	memmove(p+2+pad, buf, len);
+	mp = betomp(p, n, nil);
+	free(p);
+	return mp;
+}
 
-	/* one less than the byte length of the modulus */
-	nlen = (mpsignif(pk->n)-1)/8;
+int
+pkcs1unpadbuf(uchar *buf, int len, mpint *modulus, int blocktype)
+{
+	uchar *p = buf + 1, *e = buf + len;
 
-	/* see 9.2.1 of rfc2437 */
-	pkcs1 = betomp(sig, siglen, nil);
-	mpexp(pkcs1, pk->ek, pk->n, pkcs1);
-	buflen = mptobe(pkcs1, nil, 0, pbuf);
-	mpfree(pkcs1);
-
-	buf = *pbuf;
-	if(buflen != nlen || buf[0] != 1)
-		goto bad;
-	buf++, buflen--;
-	while(buflen > 0 && buf[0] == 0xff)
-		buf++, buflen--;
-	if(buflen < 1 || buf[0] != 0)
-		goto bad;
-	buf++, buflen--;
-	memmove(*pbuf, buf, buflen);
-	return buflen;
-bad:
-	free(*pbuf);
-	*pbuf = nil;
-	return -1;
+	if(len < 1 || len != (mpsignif(modulus)-1)/8 || buf[0] != blocktype)
+		return -1;
+	switch(blocktype){
+	default:
+	case 1:
+		while(p < e && *p == 0xFF)
+			p++;
+		break;
+	case 2:
+		while(p < e && *p != 0x00)
+			p++;
+		break;
+	}
+	if(p - buf <= 8 || p >= e || *p++ != 0x00)
+		return -1;
+	memmove(buf, p, len = e - p);
+	return len;
 }
 
+static char Ebadsig[] = "bad signature";
+
 char*
 X509rsaverifydigest(uchar *sig, int siglen, uchar *edigest, int edigestlen, RSApub *pk)
 {
-	Elem e;
-	Elist *el;
+	mpint *x, *y;
+	DigestAlg **dp;
 	Bytes *digest;
 	uchar *buf;
-	int alg, buflen;
+	int len;
 	char *err;
 
-	buflen = pkcs1decryptsignature(sig, siglen, pk, &buf);
-	if(buflen == edigestlen && tsmemcmp(buf, edigest, edigestlen) == 0){
-		free(buf);
-		return nil;
+	x = betomp(sig, siglen, nil);
+	y = rsaencrypt(pk, x, nil);
+	mpfree(x);
+	len = mptobe(y, nil, 0, &buf);
+	mpfree(y);	
+
+	err = Ebadsig;
+	len = pkcs1unpadbuf(buf, len, pk->n, 1);
+	if(len == edigestlen && tsmemcmp(buf, edigest, edigestlen) == 0)
+		err = nil;
+	for(dp = digestalg; err != nil && *dp != nil; dp++){
+		if((*dp)->len != edigestlen)
+			continue;
+		digest = encode_digest(*dp, edigest);
+		if(digest->len == len && tsmemcmp(digest->data, buf, len) == 0)
+			err = nil;
+		freebytes(digest);
 	}
-	el = nil;
-	memset(&e, 0, sizeof(e));
-	if(buflen < 0 || decode(buf, buflen, &e) != ASN_OK
-	|| !is_seq(&e, &el) || elistlen(el) != 2 || !is_octetstring(&el->tl->hd, &digest)) {
-		err = "signature parse error";
-		goto end;
-	}
-	alg = parse_alg(&el->hd);
-	if(alg < 0){
-		err = "unknown signature algorithm";
-		goto end;
-	}
-	if(digest->len != edigestlen || digest->len != digestalg[alg]->len){
-		err = "bad digest length";
-		goto end;
-	}
-	if(tsmemcmp(digest->data, edigest, edigestlen) != 0){
-		err = "digest did not match";
-		goto end;
-	}
-	err = nil;
-end:
-	freevalfields(&e.val);
 	free(buf);
 	return err;
 }
@@ -2312,7 +2292,7 @@
 	char *err;
 
 	r = s = nil;
-	err = "bad signature";
+	err = Ebadsig;
 	if(decode(sig, siglen, &e) != ASN_OK)
 		goto end;
 	if(!is_seq(&e, &el) || elistlen(el) != 2)
@@ -2838,7 +2818,7 @@
 	sigbytes = encode_digest(da, digest);
 	if(sigbytes == nil)
 		goto errret;
-	pkcs1 = pkcs1pad(sigbytes, pk->n);
+	pkcs1 = pkcs1padbuf(sigbytes->data, sigbytes->len, pk->n, 1);
 	freebytes(sigbytes);
 	if(pkcs1 == nil)
 		goto errret;
@@ -2907,7 +2887,7 @@
 	sigbytes = encode_digest(da, digest);
 	if(sigbytes == nil)
 		goto errret;
-	pkcs1 = pkcs1pad(sigbytes, pk->n);
+	pkcs1 = pkcs1padbuf(sigbytes->data, sigbytes->len, pk->n, 1);
 	freebytes(sigbytes);
 	if(pkcs1 == nil)
 		goto errret;