summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/src/cmd/auth/rsa2csr.c2
-rw-r--r--sys/src/cmd/auth/rsa2x509.c2
-rw-r--r--sys/src/libsec/port/tlshand.c50
-rw-r--r--sys/src/libsec/port/x509.c116
4 files changed, 110 insertions, 60 deletions
diff --git a/sys/src/cmd/auth/rsa2csr.c b/sys/src/cmd/auth/rsa2csr.c
index cba3f2d35..ebf3ab8b8 100644
--- a/sys/src/cmd/auth/rsa2csr.c
+++ b/sys/src/cmd/auth/rsa2csr.c
@@ -9,7 +9,7 @@
void
usage(void)
{
- fprint(2, "usage: aux/rsa2csr 'C=US ...CN=xxx' [key]");
+ fprint(2, "usage: aux/rsa2csr 'C=US ...CN=xxx' [key]\n");
exits("usage");
}
diff --git a/sys/src/cmd/auth/rsa2x509.c b/sys/src/cmd/auth/rsa2x509.c
index a2bd67ccc..476e09b46 100644
--- a/sys/src/cmd/auth/rsa2x509.c
+++ b/sys/src/cmd/auth/rsa2x509.c
@@ -9,7 +9,7 @@
void
usage(void)
{
- fprint(2, "usage: auth/rsa2x509 [-e expireseconds] 'C=US ...CN=xxx' [key]");
+ fprint(2, "usage: auth/rsa2x509 [-e expireseconds] 'C=US ...CN=xxx' [key]\n");
exits("usage");
}
diff --git a/sys/src/libsec/port/tlshand.c b/sys/src/libsec/port/tlshand.c
index 4a2e4f481..bc6506704 100644
--- a/sys/src/libsec/port/tlshand.c
+++ b/sys/src/libsec/port/tlshand.c
@@ -130,6 +130,7 @@ typedef struct Msg{
} certificate;
struct {
Bytes *types;
+ Ints *sigalgs;
int nca;
Bytes **cas;
} certificateRequest;
@@ -146,6 +147,7 @@ typedef struct Msg{
int curve;
} serverKeyExchange;
struct {
+ int sigalg;
Bytes *signature;
} certificateVerify;
Finished finished;
@@ -387,6 +389,7 @@ static void freeints(Ints* b);
/* x509.c */
extern mpint* pkcs1padbuf(uchar *buf, int len, mpint *modulus);
extern int pkcs1decryptsignature(uchar *sig, int siglen, RSApub *pk, uchar **pbuf);
+extern int X509encodesignature_sha256(uchar digest[SHA2_256dlen], uchar *buf, int len);
//================= client/server ========================
@@ -1024,7 +1027,6 @@ tlsClient2(int ctl, int hand, uchar *csid, int ncsid, uchar *cert, int certlen,
uchar kd[MaxKeyData];
char *secrets;
int creq, dhx, rv, cipher;
- mpint *signedMP, *paddedHashes;
Bytes *epm;
if(!initCiphers())
@@ -1033,10 +1035,6 @@ tlsClient2(int ctl, int hand, uchar *csid, int ncsid, uchar *cert, int certlen,
c = emalloc(sizeof(TlsConnection));
c->version = ProtocolVersion;
- // client certificate signature not implemented for TLS1.2
- if(cert != nil && certlen > 0 && c->version >= TLS12Version)
- c->version = TLS11Version;
-
c->ctl = ctl;
c->hand = hand;
c->trace = trace;
@@ -1201,14 +1199,10 @@ tlsClient2(int ctl, int hand, uchar *csid, int ncsid, uchar *cert, int certlen,
/* certificate verify */
if(creq && cert != nil && certlen > 0) {
- uchar hshashes[MD5dlen+SHA1dlen]; /* content of signature */
+ mpint *signedMP, *paddedHashes;
HandshakeHash hsave;
-
- /* save the state for the Finish message */
- hsave = c->handhash;
- md5(nil, 0, hshashes, &c->handhash.md5);
- sha1(nil, 0, hshashes+MD5dlen, &c->handhash.sha1);
- c->handhash = hsave;
+ uchar buf[512];
+ int buflen;
c->sec->rpc = factotum_rsa_open(cert, certlen);
if(c->sec->rpc == nil){
@@ -1221,7 +1215,22 @@ tlsClient2(int ctl, int hand, uchar *csid, int ncsid, uchar *cert, int certlen,
goto Err;
}
- paddedHashes = pkcs1padbuf(hshashes, MD5dlen+SHA1dlen, c->sec->rsapub->n);
+ /* save the state for the Finish message */
+ hsave = c->handhash;
+ if(c->version >= TLS12Version){
+ uchar digest[SHA2_256dlen];
+
+ m.u.certificateVerify.sigalg = 0x0401; /* RSA SHA256 */
+ sha2_256(nil, 0, digest, &c->handhash.sha2_256);
+ buflen = X509encodesignature_sha256(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;
+
+ paddedHashes = pkcs1padbuf(buf, buflen, c->sec->rsapub->n);
signedMP = factotum_rsa_decrypt(c->sec->rpc, paddedHashes);
if(signedMP == nil){
tlsError(c, EHandshakeFailure, "factotum_rsa_decrypt: %r");
@@ -1410,6 +1419,10 @@ msgSend(TlsConnection *c, Msg *m, int act)
}
break;
case HCertificateVerify:
+ if(m->u.certificateVerify.sigalg != 0){
+ put16(p, m->u.certificateVerify.sigalg);
+ p += 2;
+ }
put16(p, m->u.certificateVerify.signature->len);
p += 2;
memmove(p, m->u.certificateVerify.signature->data, m->u.certificateVerify.signature->len);
@@ -1684,14 +1697,16 @@ msgRecv(TlsConnection *c, Msg *m)
p += nn;
n -= nn;
if(c->version >= TLS12Version){
- /* skip supported_signature_algorithms */
if(n < 2)
goto Short;
nn = get16(p);
p += 2;
n -= 2;
- if(nn > n)
+ if(nn & 1)
goto Short;
+ m->u.certificateRequest.sigalgs = newints(nn>>1);
+ for(i = 0; i < nn; i += 2)
+ m->u.certificateRequest.sigalgs->data[i >> 1] = get16(&p[i]);
p += nn;
n -= nn;
@@ -1861,6 +1876,7 @@ msgClear(Msg *m)
break;
case HCertificateRequest:
freebytes(m->u.certificateRequest.types);
+ freeints(m->u.certificateRequest.sigalgs);
for(i=0; i<m->u.certificateRequest.nca; i++)
freebytes(m->u.certificateRequest.cas[i]);
free(m->u.certificateRequest.cas);
@@ -1969,12 +1985,16 @@ msgPrint(char *buf, int n, Msg *m)
case HCertificateRequest:
bs = seprint(bs, be, "CertificateRequest\n");
bs = bytesPrint(bs, be, "\ttypes: ", m->u.certificateRequest.types, "\n");
+ if(m->u.certificateRequest.sigalgs != nil)
+ bs = intsPrint(bs, be, "\tsigalgs: ", m->u.certificateRequest.sigalgs, "\n");
bs = seprint(bs, be, "\tcertificateauthorities\n");
for(i=0; i<m->u.certificateRequest.nca; i++)
bs = bytesPrint(bs, be, "\t\t", m->u.certificateRequest.cas[i], "\n");
break;
case HCertificateVerify:
bs = seprint(bs, be, "HCertificateVerify\n");
+ if(m->u.certificateVerify.sigalg != 0)
+ bs = seprint(bs, be, "\tsigalg: %.4x\n", m->u.certificateVerify.sigalg);
bs = bytesPrint(bs, be, "\tsignature: ", m->u.certificateVerify.signature,"\n");
break;
case HServerHelloDone:
diff --git a/sys/src/libsec/port/x509.c b/sys/src/libsec/port/x509.c
index b70ed2689..4e0bf2a9c 100644
--- a/sys/src/libsec/port/x509.c
+++ b/sys/src/libsec/port/x509.c
@@ -2496,6 +2496,31 @@ mkDN(char *dn)
return mkseq(el);
}
+int
+X509encodesignature_sha256(uchar digest[SHA2_256dlen], uchar *buf, int len)
+{
+ Bytes *sigbytes;
+ Elem sig;
+ int err;
+
+ sig = mkseq(
+ mkel(mkalg(ALG_sha256),
+ mkel(mkoctet(digest, SHA2_256dlen),
+ nil)));
+ err = encode(sig, &sigbytes);
+ freevalfields(&sig.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 len;
+}
uchar*
X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen)
@@ -2504,47 +2529,46 @@ X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen)
uchar *cert = nil;
RSApub *pk = rsaprivtopub(priv);
Bytes *certbytes, *pkbytes, *certinfobytes, *sigbytes;
- Elem e, certinfo, issuer, subject, pubkey, validity, sig;
+ Elem e, certinfo;
DigestAlg *da;
uchar digest[MAXdlen], *buf;
int buflen;
mpint *pkcs1;
- e.val.tag = VInt; /* so freevalfields at errret is no-op */
- issuer = mkDN(subj);
- subject = mkDN(subj);
- pubkey = mkseq(mkel(mkbigint(pk->n),mkel(mkint(mptoi(pk->ek)),nil)));
- if(encode(pubkey, &pkbytes) != ASN_OK)
+ e = mkseq(mkel(mkbigint(pk->n),mkel(mkint(mptoi(pk->ek)),nil)));
+ if(encode(e, &pkbytes) != ASN_OK)
goto errret;
- freevalfields(&pubkey.val);
- pubkey = mkseq(
- mkel(mkalg(ALG_rsaEncryption),
- mkel(mkbits(pkbytes->data, pkbytes->len),
- nil)));
- freebytes(pkbytes);
- validity = mkseq(
- mkel(mkutc(valid[0]),
- mkel(mkutc(valid[1]),
- nil)));
- certinfo = mkseq(
+ freevalfields(&e.val);
+ e = mkseq(
mkel(mkint(serial),
mkel(mkalg(sigalg),
- mkel(issuer,
- mkel(validity,
- mkel(subject,
- mkel(pubkey,
+ mkel(mkDN(subj),
+ mkel(mkseq(
+ mkel(mkutc(valid[0]),
+ mkel(mkutc(valid[1]),
+ nil))),
+ mkel(mkDN(subj),
+ mkel(mkseq(
+ mkel(mkalg(ALG_rsaEncryption),
+ mkel(mkbits(pkbytes->data, pkbytes->len),
+ nil))),
nil)))))));
- if(encode(certinfo, &certinfobytes) != ASN_OK)
+ freebytes(pkbytes);
+ if(encode(e, &certinfobytes) != ASN_OK)
goto errret;
da = digestalg[sigalg];
(*da->fun)(certinfobytes->data, certinfobytes->len, digest, 0);
freebytes(certinfobytes);
- sig = mkseq(
+ certinfo = e;
+ e = mkseq(
mkel(mkalg(da->alg),
mkel(mkoctet(digest, da->len),
nil)));
- if(encode(sig, &sigbytes) != ASN_OK)
+ if(encode(e, &sigbytes) != ASN_OK){
+ freevalfields(&certinfo.val);
goto errret;
+ }
+ freevalfields(&e.val);
pkcs1 = pkcs1pad(sigbytes, pk->n);
freebytes(sigbytes);
rsadecrypt(priv, pkcs1, pkcs1);
@@ -2560,7 +2584,10 @@ X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen)
goto errret;
if(certlen)
*certlen = certbytes->len;
- cert = certbytes->data;
+ cert = malloc(certbytes->len);
+ if(cert != nil)
+ memmove(cert, certbytes->data, certbytes->len);
+ freebytes(certbytes);
errret:
freevalfields(&e.val);
return cert;
@@ -2574,39 +2601,39 @@ X509req(RSApriv *priv, char *subj, int *certlen)
uchar *cert = nil;
RSApub *pk = rsaprivtopub(priv);
Bytes *certbytes, *pkbytes, *certinfobytes, *sigbytes;
- Elem e, certinfo, subject, pubkey, sig;
+ Elem e, certinfo;
DigestAlg *da;
uchar digest[MAXdlen], *buf;
int buflen;
mpint *pkcs1;
- e.val.tag = VInt; /* so freevalfields at errret is no-op */
- subject = mkDN(subj);
- pubkey = mkseq(mkel(mkbigint(pk->n),mkel(mkint(mptoi(pk->ek)),nil)));
- if(encode(pubkey, &pkbytes) != ASN_OK)
+ e = mkseq(mkel(mkbigint(pk->n),mkel(mkint(mptoi(pk->ek)),nil)));
+ if(encode(e, &pkbytes) != ASN_OK)
goto errret;
- freevalfields(&pubkey.val);
- pubkey = mkseq(
- mkel(mkalg(ALG_rsaEncryption),
- mkel(mkbits(pkbytes->data, pkbytes->len),
- nil)));
- freebytes(pkbytes);
- certinfo = mkseq(
+ freevalfields(&e.val);
+ e = mkseq(
mkel(mkint(version),
- mkel(subject,
- mkel(pubkey,
+ mkel(mkDN(subj),
+ mkel(mkseq(
+ mkel(mkalg(ALG_rsaEncryption),
+ mkel(mkbits(pkbytes->data, pkbytes->len),
+ nil))),
nil))));
- if(encode(certinfo, &certinfobytes) != ASN_OK)
+ freebytes(pkbytes);
+ if(encode(e, &certinfobytes) != ASN_OK)
goto errret;
da = digestalg[sigalg];
(*da->fun)(certinfobytes->data, certinfobytes->len, digest, 0);
freebytes(certinfobytes);
- sig = mkseq(
+ certinfo = e;
+ e = mkseq(
mkel(mkalg(da->alg),
mkel(mkoctet(digest, da->len),
nil)));
- if(encode(sig, &sigbytes) != ASN_OK)
+ if(encode(e, &sigbytes) != ASN_OK){
+ freevalfields(&certinfo.val);
goto errret;
+ }
pkcs1 = pkcs1pad(sigbytes, pk->n);
freebytes(sigbytes);
rsadecrypt(priv, pkcs1, pkcs1);
@@ -2622,7 +2649,10 @@ X509req(RSApriv *priv, char *subj, int *certlen)
goto errret;
if(certlen)
*certlen = certbytes->len;
- cert = certbytes->data;
+ cert = malloc(certbytes->len);
+ if(cert != nil)
+ memmove(cert, certbytes->data, certbytes->len);
+ freebytes(certbytes);
errret:
freevalfields(&e.val);
return cert;