diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-02-03 04:18:54 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-02-03 04:18:54 +0100 |
commit | 78808ca314949f40d9f6aa7abd4aa0e3f6e4b88d (patch) | |
tree | 32f7604c0414809b36b79ab4254d877305abe33d /sys | |
parent | cc8e8c978cb48955417db592b799c4c65881c2b8 (diff) |
libsec: refactor asn1 encoding of digest for rsa signatures, fix memory leak in ecverify
Diffstat (limited to 'sys')
-rw-r--r-- | sys/src/libsec/port/ecc.c | 1 | ||||
-rw-r--r-- | sys/src/libsec/port/tlshand.c | 9 | ||||
-rw-r--r-- | sys/src/libsec/port/x509.c | 84 |
3 files changed, 58 insertions, 36 deletions
diff --git a/sys/src/libsec/port/ecc.c b/sys/src/libsec/port/ecc.c index 7d3e32648..e4e4df0fd 100644 --- a/sys/src/libsec/port/ecc.c +++ b/sys/src/libsec/port/ecc.c @@ -476,6 +476,7 @@ ecdsaverify(ECdomain *dom, ECpub *pub, uchar *dig, int len, mpint *r, mpint *s) mpmod(R.x, dom->n, t); ret = mpcmp(r, t) == 0; } + mpfree(E); mpfree(t); mpfree(u1); mpfree(u2); diff --git a/sys/src/libsec/port/tlshand.c b/sys/src/libsec/port/tlshand.c index 8f245625a..695284e24 100644 --- a/sys/src/libsec/port/tlshand.c +++ b/sys/src/libsec/port/tlshand.c @@ -432,7 +432,7 @@ static void freeints(Ints* b); /* 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,13 +1298,18 @@ tlsClient2(int ctl, int hand, 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); 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); diff --git a/sys/src/libsec/port/x509.c b/sys/src/libsec/port/x509.c index 21d8cc948..9f00a9700 100644 --- a/sys/src/libsec/port/x509.c +++ b/sys/src/libsec/port/x509.c @@ -1896,7 +1896,7 @@ errret: } /* - * RSAPublickKey :: SEQUENCE { + * RSAPublickKey ::= SEQUENCE { * modulus INTEGER, * publicExponent INTEGER * } @@ -2552,30 +2552,52 @@ mkDN(char *dn) 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 ans; +} - return len; +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* @@ -2612,21 +2634,18 @@ X509rsagen(RSApriv *priv, char *subj, ulong valid[2], int *certlen) 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 @@ X509rsareq(RSApriv *priv, char *subj, int *certlen) (*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); |