libsec: ecdsa client support for tlshand, cleanups
This commit is contained in:
parent
0bfac109a4
commit
a291bbdedd
12 changed files with 467 additions and 278 deletions
|
@ -339,11 +339,11 @@ RSApriv* asn1toRSApriv(uchar*, int);
|
||||||
void asn1dump(uchar *der, int len);
|
void asn1dump(uchar *der, int len);
|
||||||
uchar* decodePEM(char *s, char *type, int *len, char **new_s);
|
uchar* decodePEM(char *s, char *type, int *len, char **new_s);
|
||||||
PEMChain* decodepemchain(char *s, char *type);
|
PEMChain* decodepemchain(char *s, char *type);
|
||||||
uchar* X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen);
|
uchar* X509rsagen(RSApriv *priv, char *subj, ulong valid[2], int *certlen);
|
||||||
uchar* X509req(RSApriv *priv, char *subj, int *certlen);
|
uchar* X509rsareq(RSApriv *priv, char *subj, int *certlen);
|
||||||
char* X509verifydigest(uchar *sig, int siglen, uchar *edigest, int edigestlen, RSApub *pk);
|
char* X509rsaverifydigest(uchar *sig, int siglen, uchar *edigest, int edigestlen, RSApub *pk);
|
||||||
char* X509verifydata(uchar *sig, int siglen, uchar *data, int datalen, RSApub *pk);
|
char* X509rsaverify(uchar *cert, int ncert, RSApub *pk);
|
||||||
char* X509verify(uchar *cert, int ncert, RSApub *pk);
|
|
||||||
void X509dump(uchar *cert, int ncert);
|
void X509dump(uchar *cert, int ncert);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -487,11 +487,14 @@ typedef struct ECdomain{
|
||||||
mpint *p;
|
mpint *p;
|
||||||
mpint *a;
|
mpint *a;
|
||||||
mpint *b;
|
mpint *b;
|
||||||
ECpoint *G;
|
ECpoint G;
|
||||||
mpint *n;
|
mpint *n;
|
||||||
mpint *h;
|
mpint *h;
|
||||||
} ECdomain;
|
} ECdomain;
|
||||||
|
|
||||||
|
void ecdominit(ECdomain *, void (*init)(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h));
|
||||||
|
void ecdomfree(ECdomain *);
|
||||||
|
|
||||||
void ecassign(ECdomain *, ECpoint *old, ECpoint *new);
|
void ecassign(ECdomain *, ECpoint *old, ECpoint *new);
|
||||||
void ecadd(ECdomain *, ECpoint *a, ECpoint *b, ECpoint *s);
|
void ecadd(ECdomain *, ECpoint *a, ECpoint *b, ECpoint *s);
|
||||||
void ecmul(ECdomain *, ECpoint *a, mpint *k, ECpoint *s);
|
void ecmul(ECdomain *, ECpoint *a, mpint *k, ECpoint *s);
|
||||||
|
@ -504,6 +507,18 @@ int ecdsaverify(ECdomain *, ECpub *, uchar *, int, mpint *, mpint *);
|
||||||
void base58enc(uchar *, char *, int);
|
void base58enc(uchar *, char *, int);
|
||||||
int base58dec(char *, uchar *, int);
|
int base58dec(char *, uchar *, int);
|
||||||
|
|
||||||
|
ECpub* ecdecodepub(ECdomain *dom, uchar *, int);
|
||||||
|
int ecencodepub(ECdomain *dom, ECpub *, uchar *, int);
|
||||||
|
void ecpubfree(ECpub *);
|
||||||
|
|
||||||
|
ECpub* X509toECpub(uchar *cert, int ncert, ECdomain *dom);
|
||||||
|
char* X509ecdsaverifydigest(uchar *sig, int siglen, uchar *edigest, int edigestlen, ECdomain *dom, ECpub *pub);
|
||||||
|
char* X509ecdsaverify(uchar *sig, int siglen, ECdomain *dom, ECpub *pub);
|
||||||
|
|
||||||
|
/* curves */
|
||||||
|
void secp256r1(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h);
|
||||||
|
void secp256k1(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h);
|
||||||
|
|
||||||
DigestState* ripemd160(uchar *, ulong, uchar *, DigestState *);
|
DigestState* ripemd160(uchar *, ulong, uchar *, DigestState *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
19
sys/man/2/ec
19
sys/man/2/ec
|
@ -19,6 +19,12 @@ ecdsaverify \- elliptic curve cryptography
|
||||||
.B #include <libsec.h>
|
.B #include <libsec.h>
|
||||||
.PP
|
.PP
|
||||||
.B
|
.B
|
||||||
|
void ecdominit(ECdomain *dom, void (*init)(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h));
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
|
void ecdomfree(ECdomain *dom);
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
void ecassign(ECdomain *dom, ECpoint *old, ECpoint *new);
|
void ecassign(ECdomain *dom, ECpoint *old, ECpoint *new);
|
||||||
.PP
|
.PP
|
||||||
.B
|
.B
|
||||||
|
@ -54,6 +60,19 @@ Points on the curve are represented by
|
||||||
.B ECpoint
|
.B ECpoint
|
||||||
structs.
|
structs.
|
||||||
.PP
|
.PP
|
||||||
|
.B ecdominit
|
||||||
|
initializes a
|
||||||
|
.B ECdomain
|
||||||
|
struct and calls the
|
||||||
|
.B init
|
||||||
|
function such as
|
||||||
|
.B secp256r1
|
||||||
|
which fills in the parameters of the curve.
|
||||||
|
.PP
|
||||||
|
.B ecdomfree
|
||||||
|
frees the parameters of the curve and zeros the struct. It does
|
||||||
|
not free the memory of the struct itself.
|
||||||
|
.PP
|
||||||
.BR ecassign ", " ecadd " and " ecmul
|
.BR ecassign ", " ecadd " and " ecmul
|
||||||
are analogous to their counterparts in
|
are analogous to their counterparts in
|
||||||
.IR mp (2).
|
.IR mp (2).
|
||||||
|
|
|
@ -12,8 +12,9 @@ rsaprivtopub,
|
||||||
rsapuballoc,
|
rsapuballoc,
|
||||||
rsapubfree,
|
rsapubfree,
|
||||||
X509toRSApub,
|
X509toRSApub,
|
||||||
X509gen,
|
X509rsagen,
|
||||||
X509verify \- RSA encryption algorithm
|
X509rsareq,
|
||||||
|
X509rsaverify \- RSA encryption algorithm
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B #include <u.h>
|
.B #include <u.h>
|
||||||
.br
|
.br
|
||||||
|
@ -61,13 +62,13 @@ void asn1dump(uchar *der, int len)
|
||||||
uchar* decodePEM(char *s, char *type, int *len, char **new_s)
|
uchar* decodePEM(char *s, char *type, int *len, char **new_s)
|
||||||
.PP
|
.PP
|
||||||
.B
|
.B
|
||||||
uchar* X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen);
|
uchar* X509rsagen(RSApriv *priv, char *subj, ulong valid[2], int *certlen);
|
||||||
.PP
|
.PP
|
||||||
.B
|
.B
|
||||||
uchar* X509req(RSApriv *priv, char *subj, int *certlen);
|
uchar* X509rsareq(RSApriv *priv, char *subj, int *certlen);
|
||||||
.PP
|
.PP
|
||||||
.B
|
.B
|
||||||
char* X509verify(uchar *cert, int ncert, RSApub *pk)
|
char* X509rsaverify(uchar *cert, int ncert, RSApub *pk)
|
||||||
.DT
|
.DT
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
RSA is a public key encryption algorithm. The owner of a key publishes
|
RSA is a public key encryption algorithm. The owner of a key publishes
|
||||||
|
@ -147,12 +148,12 @@ to convert to binary before computing the fingerprint or calling
|
||||||
For the special case of
|
For the special case of
|
||||||
certificates signed by a known trusted key
|
certificates signed by a known trusted key
|
||||||
(in a single step, without certificate chains),
|
(in a single step, without certificate chains),
|
||||||
.I X509verify
|
.I X509rsaverify
|
||||||
checks the signature on
|
checks the signature on
|
||||||
.IR cert .
|
.IR cert .
|
||||||
It returns nil if successful, else an error string.
|
It returns nil if successful, else an error string.
|
||||||
.PP
|
.PP
|
||||||
.I X509gen
|
.I X509rsagen
|
||||||
creates a self-signed X.509 certificate, given an RSA keypair
|
creates a self-signed X.509 certificate, given an RSA keypair
|
||||||
.IR priv ,
|
.IR priv ,
|
||||||
a issuer/subject string
|
a issuer/subject string
|
||||||
|
|
|
@ -42,7 +42,7 @@ decryptkey(Fsstate *fss, char *key, char *password)
|
||||||
st->p.d = betomp(keyenc + 1, 32, nil);
|
st->p.d = betomp(keyenc + 1, 32, nil);
|
||||||
st->p.x = mpnew(0);
|
st->p.x = mpnew(0);
|
||||||
st->p.y = mpnew(0);
|
st->p.y = mpnew(0);
|
||||||
ecmul(&dom, dom.G, st->p.d, &st->p);
|
ecmul(&dom, &dom.G, st->p.d, &st->p);
|
||||||
return RpcOk;
|
return RpcOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,14 +56,8 @@ ecdsainit(Proto *, Fsstate *fss)
|
||||||
char *key, *password;
|
char *key, *password;
|
||||||
Attr *attr;
|
Attr *attr;
|
||||||
|
|
||||||
if(dom.p == nil){
|
if(dom.p == nil)
|
||||||
dom.p = strtomp("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", nil, 16, nil);
|
ecdominit(&dom, secp256k1);
|
||||||
dom.a = uitomp(0, nil);
|
|
||||||
dom.b = uitomp(7, nil);
|
|
||||||
dom.n = strtomp("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", nil, 16, nil);
|
|
||||||
dom.h = uitomp(1, nil);
|
|
||||||
dom.G = strtoec(&dom, "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", nil, nil);
|
|
||||||
}
|
|
||||||
fss->ps = nil;
|
fss->ps = nil;
|
||||||
if((iscli = isclient(_strfindattr(fss->attr, "role"))) < 0)
|
if((iscli = isclient(_strfindattr(fss->attr, "role"))) < 0)
|
||||||
return failure(fss, nil);
|
return failure(fss, nil);
|
||||||
|
|
|
@ -34,7 +34,7 @@ main(int argc, char **argv)
|
||||||
if((key = getkey(argc-1, argv+1, 1, nil)) == nil)
|
if((key = getkey(argc-1, argv+1, 1, nil)) == nil)
|
||||||
sysfatal("%r");
|
sysfatal("%r");
|
||||||
|
|
||||||
cert = X509req(key, argv[0], &len);
|
cert = X509rsareq(key, argv[0], &len);
|
||||||
if(cert == nil)
|
if(cert == nil)
|
||||||
sysfatal("X509req: %r");
|
sysfatal("X509req: %r");
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ main(int argc, char **argv)
|
||||||
if((key = getkey(argc-1, argv+1, 1, nil)) == nil)
|
if((key = getkey(argc-1, argv+1, 1, nil)) == nil)
|
||||||
sysfatal("%r");
|
sysfatal("%r");
|
||||||
|
|
||||||
cert = X509gen(key, argv[0], valid, &len);
|
cert = X509rsagen(key, argv[0], valid, &len);
|
||||||
if(cert == nil)
|
if(cert == nil)
|
||||||
sysfatal("X509gen: %r");
|
sysfatal("X509gen: %r");
|
||||||
|
|
||||||
|
|
|
@ -407,7 +407,7 @@ ecgen(ECdomain *dom, ECpriv *p)
|
||||||
if(mpcmp(p->d, mpzero) > 0 && mpcmp(p->d, dom->n) < 0)
|
if(mpcmp(p->d, mpzero) > 0 && mpcmp(p->d, dom->n) < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ecmul(dom, dom->G, p->d, p);
|
ecmul(dom, &dom->G, p->d, p);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,7 +468,7 @@ ecdsaverify(ECdomain *dom, ECpub *pub, uchar *dig, int len, mpint *r, mpint *s)
|
||||||
mpmod(u1, dom->n, u1);
|
mpmod(u1, dom->n, u1);
|
||||||
mpmul(r, t, u2);
|
mpmul(r, t, u2);
|
||||||
mpmod(u2, dom->n, u2);
|
mpmod(u2, dom->n, u2);
|
||||||
ecmul(dom, dom->G, u1, &R);
|
ecmul(dom, &dom->G, u1, &R);
|
||||||
ecmul(dom, pub, u2, &S);
|
ecmul(dom, pub, u2, &S);
|
||||||
ecadd(dom, &R, &S, &R);
|
ecadd(dom, &R, &S, &R);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
@ -540,3 +540,79 @@ base58dec(char *src, uchar *dst, int len)
|
||||||
mpfree(b);
|
mpfree(b);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ecdominit(ECdomain *dom, void (*init)(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h))
|
||||||
|
{
|
||||||
|
memset(dom, 0, sizeof(*dom));
|
||||||
|
dom->p = mpnew(0);
|
||||||
|
dom->a = mpnew(0);
|
||||||
|
dom->b = mpnew(0);
|
||||||
|
dom->G.x = mpnew(0);
|
||||||
|
dom->G.y = mpnew(0);
|
||||||
|
dom->n = mpnew(0);
|
||||||
|
dom->h = mpnew(0);
|
||||||
|
if(init){
|
||||||
|
(*init)(dom->p, dom->a, dom->b, dom->G.x, dom->G.y, dom->n, dom->h);
|
||||||
|
dom->p = mpfield(dom->p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ecdomfree(ECdomain *dom)
|
||||||
|
{
|
||||||
|
mpfree(dom->p);
|
||||||
|
mpfree(dom->a);
|
||||||
|
mpfree(dom->b);
|
||||||
|
mpfree(dom->G.x);
|
||||||
|
mpfree(dom->G.y);
|
||||||
|
mpfree(dom->n);
|
||||||
|
mpfree(dom->h);
|
||||||
|
memset(dom, 0, sizeof(*dom));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ecencodepub(ECdomain *dom, ECpub *pub, uchar *data, int len)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = (mpsignif(dom->p)+7)/8;
|
||||||
|
if(len < 1 + 2*n)
|
||||||
|
return 0;
|
||||||
|
len = 1 + 2*n;
|
||||||
|
data[0] = 0x04;
|
||||||
|
mptober(pub->x, data+1, n);
|
||||||
|
mptober(pub->y, data+1+n, n);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
ECpub*
|
||||||
|
ecdecodepub(ECdomain *dom, uchar *data, int len)
|
||||||
|
{
|
||||||
|
ECpub *pub;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = (mpsignif(dom->p)+7)/8;
|
||||||
|
if(len != 1 + 2*n || data[0] != 0x04)
|
||||||
|
return nil;
|
||||||
|
pub = mallocz(sizeof(*pub), 1);
|
||||||
|
if(pub == nil)
|
||||||
|
return nil;
|
||||||
|
pub->x = betomp(data+1, n, nil);
|
||||||
|
pub->y = betomp(data+1+n, n, nil);
|
||||||
|
if(!ecpubverify(dom, pub)){
|
||||||
|
ecpubfree(pub);
|
||||||
|
pub = nil;
|
||||||
|
}
|
||||||
|
return pub;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ecpubfree(ECpub *p)
|
||||||
|
{
|
||||||
|
if(p == nil)
|
||||||
|
return;
|
||||||
|
mpfree(p->x);
|
||||||
|
mpfree(p->y);
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
|
|
@ -30,6 +30,10 @@ CFILES = des.c desmodes.c desECB.c desCBC.c des3ECB.c des3CBC.c\
|
||||||
hkdf.c\
|
hkdf.c\
|
||||||
ccpoly.c\
|
ccpoly.c\
|
||||||
tsmemcmp.c\
|
tsmemcmp.c\
|
||||||
|
secp256r1.c\
|
||||||
|
secp256k1.c\
|
||||||
|
|
||||||
|
CLEANFILES=secp256r1.c secp256k1.c
|
||||||
|
|
||||||
ALLOFILES=${CFILES:%.c=%.$O}
|
ALLOFILES=${CFILES:%.c=%.$O}
|
||||||
|
|
||||||
|
@ -46,6 +50,12 @@ UPDATE=mkfile\
|
||||||
|
|
||||||
</sys/src/cmd/mksyslib
|
</sys/src/cmd/mksyslib
|
||||||
|
|
||||||
|
%.c:D: %.mp
|
||||||
|
echo '#include <u.h>' > $target
|
||||||
|
echo '#include <libc.h>' >> $target
|
||||||
|
echo '#include <mp.h>' >> $target
|
||||||
|
mpc $prereq >> $target
|
||||||
|
|
||||||
$O.rsatest: rsatest.$O
|
$O.rsatest: rsatest.$O
|
||||||
$LD -o $target $prereq
|
$LD -o $target $prereq
|
||||||
|
|
||||||
|
|
10
sys/src/libsec/port/secp256k1.mp
Normal file
10
sys/src/libsec/port/secp256k1.mp
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# E: y² = x³ + ax + b
|
||||||
|
secp256k1(p,a,b,x,y,n,h) {
|
||||||
|
p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1;
|
||||||
|
a = 0;
|
||||||
|
b = 7;
|
||||||
|
x = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798;
|
||||||
|
y = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8;
|
||||||
|
n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141;
|
||||||
|
h = 1;
|
||||||
|
}
|
10
sys/src/libsec/port/secp256r1.mp
Normal file
10
sys/src/libsec/port/secp256r1.mp
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# E: y² = x³ + ax + b
|
||||||
|
secp256r1(p,a,b,x,y,n,h) {
|
||||||
|
p = 2^256 - 2^224 + 2^192 + 2^96 - 1;
|
||||||
|
a = p - 3;
|
||||||
|
b = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B;
|
||||||
|
x = 0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296;
|
||||||
|
y = 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5;
|
||||||
|
n = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551;
|
||||||
|
h = 1;
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ enum {
|
||||||
SSL3FinishedLen = MD5dlen+SHA1dlen,
|
SSL3FinishedLen = MD5dlen+SHA1dlen,
|
||||||
MaxKeyData = 160, // amount of secret we may need
|
MaxKeyData = 160, // amount of secret we may need
|
||||||
MaxChunk = 1<<15,
|
MaxChunk = 1<<15,
|
||||||
|
MAXdlen = SHA2_512dlen,
|
||||||
RandomSize = 32,
|
RandomSize = 32,
|
||||||
SidSize = 32,
|
SidSize = 32,
|
||||||
MasterSecretSize = 48,
|
MasterSecretSize = 48,
|
||||||
|
@ -48,14 +49,7 @@ typedef struct Algs{
|
||||||
|
|
||||||
typedef struct Namedcurve{
|
typedef struct Namedcurve{
|
||||||
int tlsid;
|
int tlsid;
|
||||||
char *name;
|
void (*init)(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h);
|
||||||
|
|
||||||
char *p;
|
|
||||||
char *a;
|
|
||||||
char *b;
|
|
||||||
char *G;
|
|
||||||
char *n;
|
|
||||||
char *h;
|
|
||||||
} Namedcurve;
|
} Namedcurve;
|
||||||
|
|
||||||
typedef struct Finished{
|
typedef struct Finished{
|
||||||
|
@ -279,12 +273,15 @@ enum {
|
||||||
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0XC013,
|
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0XC013,
|
||||||
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0XC014,
|
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0XC014,
|
||||||
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027,
|
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027,
|
||||||
|
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023,
|
||||||
|
|
||||||
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 = 0xCCA8,
|
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 = 0xCCA8,
|
||||||
|
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 = 0xCCA9,
|
||||||
TLS_DHE_RSA_WITH_CHACHA20_POLY1305 = 0xCCAA,
|
TLS_DHE_RSA_WITH_CHACHA20_POLY1305 = 0xCCAA,
|
||||||
|
|
||||||
GOOGLE_ECDHE_RSA_WITH_CHACHA20_POLY1305 = 0xCC13,
|
GOOGLE_ECDHE_RSA_WITH_CHACHA20_POLY1305 = 0xCC13,
|
||||||
GOOGLE_DHE_RSA_WITH_CHACHA20_POLY1305 = 0xCC15,
|
GOOGLE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 = 0xCC14,
|
||||||
|
GOOGLE_DHE_RSA_WITH_CHACHA20_POLY1305 = 0xCC15,
|
||||||
|
|
||||||
TLS_PSK_WITH_CHACHA20_POLY1305 = 0xCCAB,
|
TLS_PSK_WITH_CHACHA20_POLY1305 = 0xCCAB,
|
||||||
TLS_PSK_WITH_AES_128_CBC_SHA256 = 0x00AE,
|
TLS_PSK_WITH_AES_128_CBC_SHA256 = 0x00AE,
|
||||||
|
@ -299,11 +296,14 @@ enum {
|
||||||
|
|
||||||
static Algs cipherAlgs[] = {
|
static Algs cipherAlgs[] = {
|
||||||
{"ccpoly96_aead", "clear", 2*(32+12), TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305},
|
{"ccpoly96_aead", "clear", 2*(32+12), TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305},
|
||||||
|
{"ccpoly96_aead", "clear", 2*(32+12), TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305},
|
||||||
{"ccpoly96_aead", "clear", 2*(32+12), TLS_DHE_RSA_WITH_CHACHA20_POLY1305},
|
{"ccpoly96_aead", "clear", 2*(32+12), TLS_DHE_RSA_WITH_CHACHA20_POLY1305},
|
||||||
|
|
||||||
{"ccpoly64_aead", "clear", 2*32, GOOGLE_ECDHE_RSA_WITH_CHACHA20_POLY1305},
|
{"ccpoly64_aead", "clear", 2*32, GOOGLE_ECDHE_RSA_WITH_CHACHA20_POLY1305},
|
||||||
|
{"ccpoly64_aead", "clear", 2*32, GOOGLE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305},
|
||||||
{"ccpoly64_aead", "clear", 2*32, GOOGLE_DHE_RSA_WITH_CHACHA20_POLY1305},
|
{"ccpoly64_aead", "clear", 2*32, GOOGLE_DHE_RSA_WITH_CHACHA20_POLY1305},
|
||||||
|
|
||||||
|
{"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
|
||||||
{"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
|
{"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
|
||||||
{"aes_128_cbc", "sha1", 2*(16+16+SHA1dlen), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
|
{"aes_128_cbc", "sha1", 2*(16+16+SHA1dlen), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
|
||||||
{"aes_256_cbc", "sha1", 2*(32+16+SHA1dlen), TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
|
{"aes_256_cbc", "sha1", 2*(32+16+SHA1dlen), TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
|
||||||
|
@ -328,21 +328,32 @@ static uchar compressors[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static Namedcurve namedcurves[] = {
|
static Namedcurve namedcurves[] = {
|
||||||
{0x0017, "secp256r1",
|
0x0017, secp256r1,
|
||||||
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
|
|
||||||
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
|
|
||||||
"5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
|
|
||||||
"046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
|
|
||||||
"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
|
|
||||||
"1"}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static uchar pointformats[] = {
|
static uchar pointformats[] = {
|
||||||
CompressionNull /* support of uncompressed point format is mandatory */
|
CompressionNull /* support of uncompressed point format is mandatory */
|
||||||
};
|
};
|
||||||
|
|
||||||
// signature algorithms (only RSA at the moment)
|
static struct {
|
||||||
|
DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*);
|
||||||
|
int len;
|
||||||
|
} hashfun[] = {
|
||||||
|
[0x01] {md5, MD5dlen},
|
||||||
|
[0x02] {sha1, SHA1dlen},
|
||||||
|
[0x03] {sha2_224, SHA2_224dlen},
|
||||||
|
[0x04] {sha2_256, SHA2_256dlen},
|
||||||
|
[0x05] {sha2_384, SHA2_384dlen},
|
||||||
|
[0x06] {sha2_512, SHA2_512dlen},
|
||||||
|
};
|
||||||
|
|
||||||
|
// signature algorithms (only RSA and ECDSA at the moment)
|
||||||
static int sigalgs[] = {
|
static int sigalgs[] = {
|
||||||
|
0x0603, /* SHA512 ECDSA */
|
||||||
|
0x0503, /* SHA384 ECDSA */
|
||||||
|
0x0403, /* SHA256 ECDSA */
|
||||||
|
0x0203, /* SHA1 ECDSA */
|
||||||
|
|
||||||
0x0601, /* SHA512 RSA */
|
0x0601, /* SHA512 RSA */
|
||||||
0x0501, /* SHA384 RSA */
|
0x0501, /* SHA384 RSA */
|
||||||
0x0401, /* SHA256 RSA */
|
0x0401, /* SHA256 RSA */
|
||||||
|
@ -421,7 +432,6 @@ static void freeints(Ints* b);
|
||||||
|
|
||||||
/* x509.c */
|
/* x509.c */
|
||||||
extern mpint* pkcs1padbuf(uchar *buf, int len, mpint *modulus);
|
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);
|
extern int X509encodesignature_sha256(uchar digest[SHA2_256dlen], uchar *buf, int len);
|
||||||
|
|
||||||
//================= client/server ========================
|
//================= client/server ========================
|
||||||
|
@ -869,11 +879,16 @@ static int
|
||||||
isECDHE(int tlsid)
|
isECDHE(int tlsid)
|
||||||
{
|
{
|
||||||
switch(tlsid){
|
switch(tlsid){
|
||||||
|
case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305:
|
||||||
|
case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305:
|
||||||
|
|
||||||
|
case GOOGLE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305:
|
||||||
|
case GOOGLE_ECDHE_RSA_WITH_CHACHA20_POLY1305:
|
||||||
|
|
||||||
|
case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
|
||||||
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
|
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
|
||||||
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
|
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
|
||||||
case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
|
case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
|
||||||
case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305:
|
|
||||||
case GOOGLE_ECDHE_RSA_WITH_CHACHA20_POLY1305:
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -932,47 +947,14 @@ Out:
|
||||||
return epm;
|
return epm;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ECpoint*
|
|
||||||
bytestoec(ECdomain *dom, Bytes *bp, ECpoint *ret)
|
|
||||||
{
|
|
||||||
char *hex = "0123456789ABCDEF";
|
|
||||||
char *s;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
s = emalloc(2*bp->len + 1);
|
|
||||||
for(i=0; i < bp->len; i++){
|
|
||||||
s[2*i] = hex[bp->data[i]>>4 & 15];
|
|
||||||
s[2*i+1] = hex[bp->data[i] & 15];
|
|
||||||
}
|
|
||||||
s[2*bp->len] = '\0';
|
|
||||||
ret = strtoec(dom, s, nil, ret);
|
|
||||||
free(s);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Bytes*
|
|
||||||
ectobytes(int type, ECpoint *p)
|
|
||||||
{
|
|
||||||
Bytes *bx, *by, *bp;
|
|
||||||
|
|
||||||
bx = mptobytes(p->x);
|
|
||||||
by = mptobytes(p->y);
|
|
||||||
bp = newbytes(bx->len + by->len + 1);
|
|
||||||
bp->data[0] = type;
|
|
||||||
memmove(bp->data+1, bx->data, bx->len);
|
|
||||||
memmove(bp->data+1+bx->len, by->data, by->len);
|
|
||||||
freebytes(bx);
|
|
||||||
freebytes(by);
|
|
||||||
return bp;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Bytes*
|
static Bytes*
|
||||||
tlsSecECDHEc(TlsSec *sec, uchar *srandom, int vers, int curve, Bytes *Ys)
|
tlsSecECDHEc(TlsSec *sec, uchar *srandom, int vers, int curve, Bytes *Ys)
|
||||||
{
|
{
|
||||||
Namedcurve *nc, *enc;
|
Namedcurve *nc, *enc;
|
||||||
Bytes *epm;
|
Bytes *epm;
|
||||||
ECdomain dom;
|
ECdomain dom;
|
||||||
ECpoint G, K, Y;
|
ECpub *pub;
|
||||||
|
ECpoint K;
|
||||||
ECpriv Q;
|
ECpriv Q;
|
||||||
|
|
||||||
if(Ys == nil)
|
if(Ys == nil)
|
||||||
|
@ -990,18 +972,12 @@ tlsSecECDHEc(TlsSec *sec, uchar *srandom, int vers, int curve, Bytes *Ys)
|
||||||
if(setVers(sec, vers) < 0)
|
if(setVers(sec, vers) < 0)
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
epm = nil;
|
ecdominit(&dom, nc->init);
|
||||||
|
pub = ecdecodepub(&dom, Ys->data, Ys->len);
|
||||||
memset(&dom, 0, sizeof(dom));
|
if(pub == nil){
|
||||||
dom.p = mpfield(strtomp(nc->p, nil, 16, nil));
|
ecdomfree(&dom);
|
||||||
dom.a = strtomp(nc->a, nil, 16, nil);
|
return nil;
|
||||||
dom.b = strtomp(nc->b, nil, 16, nil);
|
}
|
||||||
dom.n = strtomp(nc->n, nil, 16, nil);
|
|
||||||
dom.h = strtomp(nc->h, nil, 16, nil);
|
|
||||||
|
|
||||||
memset(&G, 0, sizeof(G));
|
|
||||||
G.x = mpnew(0);
|
|
||||||
G.y = mpnew(0);
|
|
||||||
|
|
||||||
memset(&Q, 0, sizeof(Q));
|
memset(&Q, 0, sizeof(Q));
|
||||||
Q.x = mpnew(0);
|
Q.x = mpnew(0);
|
||||||
|
@ -1012,48 +988,22 @@ tlsSecECDHEc(TlsSec *sec, uchar *srandom, int vers, int curve, Bytes *Ys)
|
||||||
K.x = mpnew(0);
|
K.x = mpnew(0);
|
||||||
K.y = mpnew(0);
|
K.y = mpnew(0);
|
||||||
|
|
||||||
memset(&Y, 0, sizeof(Y));
|
epm = nil;
|
||||||
Y.x = mpnew(0);
|
if(ecgen(&dom, &Q) != nil){
|
||||||
Y.y = mpnew(0);
|
ecmul(&dom, pub, Q.d, &K);
|
||||||
|
setMasterSecret(sec, mptobytes(K.x));
|
||||||
if(dom.p == nil || dom.a == nil || dom.b == nil || dom.n == nil || dom.h == nil)
|
epm = newbytes(1 + 2*((mpsignif(dom.p)+7)/8));
|
||||||
goto Out;
|
epm->len = ecencodepub(&dom, &Q, epm->data, epm->len);
|
||||||
|
}
|
||||||
dom.G = strtoec(&dom, nc->G, nil, &G);
|
|
||||||
if(dom.G == nil)
|
|
||||||
goto Out;
|
|
||||||
|
|
||||||
if(bytestoec(&dom, Ys, &Y) == nil)
|
|
||||||
goto Out;
|
|
||||||
|
|
||||||
if(ecgen(&dom, &Q) == nil)
|
|
||||||
goto Out;
|
|
||||||
|
|
||||||
ecmul(&dom, &Y, Q.d, &K);
|
|
||||||
setMasterSecret(sec, mptobytes(K.x));
|
|
||||||
|
|
||||||
/* 0x04 = uncompressed public key */
|
|
||||||
epm = ectobytes(0x04, &Q);
|
|
||||||
|
|
||||||
Out:
|
|
||||||
mpfree(Y.x);
|
|
||||||
mpfree(Y.y);
|
|
||||||
|
|
||||||
mpfree(K.x);
|
mpfree(K.x);
|
||||||
mpfree(K.y);
|
mpfree(K.y);
|
||||||
|
|
||||||
mpfree(Q.x);
|
mpfree(Q.x);
|
||||||
mpfree(Q.y);
|
mpfree(Q.y);
|
||||||
mpfree(Q.d);
|
mpfree(Q.d);
|
||||||
|
|
||||||
mpfree(G.x);
|
ecpubfree(pub);
|
||||||
mpfree(G.y);
|
ecdomfree(&dom);
|
||||||
|
|
||||||
mpfree(dom.p);
|
|
||||||
mpfree(dom.a);
|
|
||||||
mpfree(dom.b);
|
|
||||||
mpfree(dom.n);
|
|
||||||
mpfree(dom.h);
|
|
||||||
|
|
||||||
return epm;
|
return epm;
|
||||||
}
|
}
|
||||||
|
@ -1061,9 +1011,12 @@ Out:
|
||||||
static char*
|
static char*
|
||||||
verifyDHparams(TlsConnection *c, Bytes *par, Bytes *sig, int sigalg)
|
verifyDHparams(TlsConnection *c, Bytes *par, Bytes *sig, int sigalg)
|
||||||
{
|
{
|
||||||
uchar hashes[MD5dlen+SHA1dlen], *buf;
|
uchar digest[MAXdlen];
|
||||||
|
int digestlen;
|
||||||
|
ECdomain dom;
|
||||||
|
ECpub *ecpk;
|
||||||
|
RSApub *rsapk;
|
||||||
Bytes *blob;
|
Bytes *blob;
|
||||||
RSApub *pk;
|
|
||||||
char *err;
|
char *err;
|
||||||
|
|
||||||
if(par == nil || par->len <= 0)
|
if(par == nil || par->len <= 0)
|
||||||
|
@ -1072,40 +1025,52 @@ verifyDHparams(TlsConnection *c, Bytes *par, Bytes *sig, int sigalg)
|
||||||
if(sig == nil || sig->len <= 0){
|
if(sig == nil || sig->len <= 0){
|
||||||
if(c->sec->psklen > 0)
|
if(c->sec->psklen > 0)
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
return "no signature";
|
return "no signature";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(c->cert == nil)
|
if(c->cert == nil)
|
||||||
return "no certificate";
|
return "no certificate";
|
||||||
|
|
||||||
pk = X509toRSApub(c->cert->data, c->cert->len, nil, 0);
|
|
||||||
if(pk == nil)
|
|
||||||
return "bad certificate";
|
|
||||||
|
|
||||||
blob = newbytes(2*RandomSize + par->len);
|
blob = newbytes(2*RandomSize + par->len);
|
||||||
memmove(blob->data+0*RandomSize, c->crandom, RandomSize);
|
memmove(blob->data+0*RandomSize, c->crandom, RandomSize);
|
||||||
memmove(blob->data+1*RandomSize, c->srandom, RandomSize);
|
memmove(blob->data+1*RandomSize, c->srandom, RandomSize);
|
||||||
memmove(blob->data+2*RandomSize, par->data, par->len);
|
memmove(blob->data+2*RandomSize, par->data, par->len);
|
||||||
if(c->version >= TLS12Version) {
|
if(c->version < TLS12Version){
|
||||||
if((sigalg & 0xFF) == 1)
|
digestlen = MD5dlen + SHA1dlen;
|
||||||
err = X509verifydata(sig->data, sig->len, blob->data, blob->len, pk);
|
md5(blob->data, blob->len, digest, nil);
|
||||||
else
|
sha1(blob->data, blob->len, digest+MD5dlen, nil);
|
||||||
err = "signaure algorithm not RSA";
|
|
||||||
} else {
|
} else {
|
||||||
err = nil;
|
int hashalg = (sigalg>>8) & 0xFF;
|
||||||
if(pkcs1decryptsignature(sig->data, sig->len, pk, &buf) != sizeof(hashes))
|
digestlen = -1;
|
||||||
err = "bad signature";
|
if(hashalg < nelem(hashfun) && hashfun[hashalg].fun != nil){
|
||||||
else {
|
digestlen = hashfun[hashalg].len;
|
||||||
md5(blob->data, blob->len, hashes, nil);
|
(*hashfun[hashalg].fun)(blob->data, blob->len, digest, nil);
|
||||||
sha1(blob->data, blob->len, hashes+MD5dlen, nil);
|
|
||||||
if(tsmemcmp(buf, hashes, sizeof(hashes)) != 0)
|
|
||||||
err = "digests did not match";
|
|
||||||
}
|
}
|
||||||
free(buf);
|
|
||||||
}
|
}
|
||||||
freebytes(blob);
|
freebytes(blob);
|
||||||
rsapubfree(pk);
|
|
||||||
|
if(digestlen <= 0)
|
||||||
|
return "unknown signature digest algorithm";
|
||||||
|
|
||||||
|
switch(sigalg & 0xFF){
|
||||||
|
case 0x01:
|
||||||
|
rsapk = X509toRSApub(c->cert->data, c->cert->len, nil, 0);
|
||||||
|
if(rsapk == nil)
|
||||||
|
return "bad certificate";
|
||||||
|
err = X509rsaverifydigest(sig->data, sig->len, digest, digestlen, rsapk);
|
||||||
|
rsapubfree(rsapk);
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
ecpk = X509toECpub(c->cert->data, c->cert->len, &dom);
|
||||||
|
if(ecpk == nil)
|
||||||
|
return "bad certificate";
|
||||||
|
err = X509ecdsaverifydigest(sig->data, sig->len, digest, digestlen, &dom, ecpk);
|
||||||
|
ecdomfree(&dom);
|
||||||
|
ecpubfree(ecpk);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err = "signaure algorithm not RSA or ECDSA";
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,8 +134,7 @@ static int encode(Elem e, Bytes** pbytes);
|
||||||
static int oid_lookup(Ints* o, Ints** tab);
|
static int oid_lookup(Ints* o, Ints** tab);
|
||||||
static void freevalfields(Value* v);
|
static void freevalfields(Value* v);
|
||||||
static mpint *asn1mpint(Elem *e);
|
static mpint *asn1mpint(Elem *e);
|
||||||
|
static void edump(Elem);
|
||||||
|
|
||||||
|
|
||||||
#define TAG_MASK 0x1F
|
#define TAG_MASK 0x1F
|
||||||
#define CONSTR_MASK 0x20
|
#define CONSTR_MASK 0x20
|
||||||
|
@ -223,6 +222,7 @@ ber_decode(uchar** pp, uchar* pend, Elem* pelem)
|
||||||
Tag tag;
|
Tag tag;
|
||||||
Value val;
|
Value val;
|
||||||
|
|
||||||
|
memset(pelem, 0, sizeof(*pelem));
|
||||||
err = tag_decode(pp, pend, &tag, &isconstr);
|
err = tag_decode(pp, pend, &tag, &isconstr);
|
||||||
if(err == ASN_OK) {
|
if(err == ASN_OK) {
|
||||||
err = length_decode(pp, pend, &length);
|
err = length_decode(pp, pend, &length);
|
||||||
|
@ -1159,21 +1159,8 @@ is_int(Elem* pe, int* pint)
|
||||||
static int
|
static int
|
||||||
is_bigint(Elem* pe, Bytes** pbigint)
|
is_bigint(Elem* pe, Bytes** pbigint)
|
||||||
{
|
{
|
||||||
int v, n, i;
|
if(pe->tag.class == Universal && pe->tag.num == INTEGER && pe->val.tag == VBigInt) {
|
||||||
|
*pbigint = pe->val.u.bigintval;
|
||||||
if(pe->tag.class == Universal && pe->tag.num == INTEGER) {
|
|
||||||
if(pe->val.tag == VBigInt)
|
|
||||||
*pbigint = pe->val.u.bigintval;
|
|
||||||
else if(pe->val.tag == VInt){
|
|
||||||
v = pe->val.u.intval;
|
|
||||||
for(n = 1; n < 4; n++)
|
|
||||||
if((1 << (8 * n)) > v)
|
|
||||||
break;
|
|
||||||
*pbigint = newbytes(n);
|
|
||||||
for(i = 0; i < n; i++)
|
|
||||||
(*pbigint)->data[i] = (v >> ((n - 1 - i) * 8));
|
|
||||||
}else
|
|
||||||
return 0;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1536,6 +1523,7 @@ typedef struct CertX509 {
|
||||||
Bytes* publickey;
|
Bytes* publickey;
|
||||||
int signature_alg;
|
int signature_alg;
|
||||||
Bytes* signature;
|
Bytes* signature;
|
||||||
|
int curve;
|
||||||
} CertX509;
|
} CertX509;
|
||||||
|
|
||||||
/* Algorithm object-ids */
|
/* Algorithm object-ids */
|
||||||
|
@ -1553,6 +1541,12 @@ enum {
|
||||||
ALG_sha512WithRSAEncryption,
|
ALG_sha512WithRSAEncryption,
|
||||||
ALG_sha224WithRSAEncryption,
|
ALG_sha224WithRSAEncryption,
|
||||||
|
|
||||||
|
ALG_ecPublicKey,
|
||||||
|
ALG_sha1WithECDSA,
|
||||||
|
ALG_sha256WithECDSA,
|
||||||
|
ALG_sha384WithECDSA,
|
||||||
|
ALG_sha512WithECDSA,
|
||||||
|
|
||||||
ALG_md5,
|
ALG_md5,
|
||||||
ALG_sha1,
|
ALG_sha1,
|
||||||
ALG_sha256,
|
ALG_sha256,
|
||||||
|
@ -1587,6 +1581,7 @@ enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
static Ints15 oid_rsaEncryption = {7, 1, 2, 840, 113549, 1, 1, 1 };
|
static Ints15 oid_rsaEncryption = {7, 1, 2, 840, 113549, 1, 1, 1 };
|
||||||
|
|
||||||
static Ints15 oid_md2WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 2 };
|
static Ints15 oid_md2WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 2 };
|
||||||
static Ints15 oid_md4WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 3 };
|
static Ints15 oid_md4WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 3 };
|
||||||
static Ints15 oid_md5WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 4 };
|
static Ints15 oid_md5WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 4 };
|
||||||
|
@ -1597,6 +1592,12 @@ static Ints15 oid_sha384WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 12 };
|
||||||
static Ints15 oid_sha512WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 13 };
|
static Ints15 oid_sha512WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 13 };
|
||||||
static Ints15 oid_sha224WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 14 };
|
static Ints15 oid_sha224WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 14 };
|
||||||
|
|
||||||
|
static Ints15 oid_ecPublicKey = {6, 1, 2, 840, 10045, 2, 1 };
|
||||||
|
static Ints15 oid_sha1WithECDSA = {6, 1, 2, 840, 10045, 4, 1 };
|
||||||
|
static Ints15 oid_sha256WithECDSA = {7, 1, 2, 840, 10045, 4, 3, 2 };
|
||||||
|
static Ints15 oid_sha384WithECDSA = {7, 1, 2, 840, 10045, 4, 3, 3 };
|
||||||
|
static Ints15 oid_sha512WithECDSA = {7, 1, 2, 840, 10045, 4, 3, 4 };
|
||||||
|
|
||||||
static Ints15 oid_md5 = {6, 1, 2, 840, 113549, 2, 5 };
|
static Ints15 oid_md5 = {6, 1, 2, 840, 113549, 2, 5 };
|
||||||
static Ints15 oid_sha1 = {6, 1, 3, 14, 3, 2, 26 };
|
static Ints15 oid_sha1 = {6, 1, 3, 14, 3, 2, 26 };
|
||||||
static Ints15 oid_sha256= {9, 2, 16, 840, 1, 101, 3, 4, 2, 1 };
|
static Ints15 oid_sha256= {9, 2, 16, 840, 1, 101, 3, 4, 2, 1 };
|
||||||
|
@ -1618,6 +1619,12 @@ static Ints *alg_oid_tab[NUMALGS+1] = {
|
||||||
(Ints*)&oid_sha512WithRSAEncryption,
|
(Ints*)&oid_sha512WithRSAEncryption,
|
||||||
(Ints*)&oid_sha224WithRSAEncryption,
|
(Ints*)&oid_sha224WithRSAEncryption,
|
||||||
|
|
||||||
|
(Ints*)&oid_ecPublicKey,
|
||||||
|
(Ints*)&oid_sha1WithECDSA,
|
||||||
|
(Ints*)&oid_sha256WithECDSA,
|
||||||
|
(Ints*)&oid_sha384WithECDSA,
|
||||||
|
(Ints*)&oid_sha512WithECDSA,
|
||||||
|
|
||||||
(Ints*)&oid_md5,
|
(Ints*)&oid_md5,
|
||||||
(Ints*)&oid_sha1,
|
(Ints*)&oid_sha1,
|
||||||
(Ints*)&oid_sha256,
|
(Ints*)&oid_sha256,
|
||||||
|
@ -1631,10 +1638,22 @@ static DigestAlg *digestalg[NUMALGS+1] = {
|
||||||
&alg_md5, &alg_md5, &alg_md5, &alg_md5,
|
&alg_md5, &alg_md5, &alg_md5, &alg_md5,
|
||||||
&alg_sha1, &alg_sha1,
|
&alg_sha1, &alg_sha1,
|
||||||
&alg_sha256, &alg_sha384, &alg_sha512, &alg_sha224,
|
&alg_sha256, &alg_sha384, &alg_sha512, &alg_sha224,
|
||||||
|
&alg_sha256, &alg_sha1, &alg_sha256, &alg_sha384, &alg_sha512,
|
||||||
&alg_md5, &alg_sha1, &alg_sha256, &alg_sha384, &alg_sha512, &alg_sha224,
|
&alg_md5, &alg_sha1, &alg_sha256, &alg_sha384, &alg_sha512, &alg_sha224,
|
||||||
nil
|
nil
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Ints15 oid_secp256r1 = {7, 1, 2, 840, 10045, 3, 1, 7};
|
||||||
|
|
||||||
|
static Ints *namedcurves_oid_tab[] = {
|
||||||
|
(Ints*)&oid_secp256r1,
|
||||||
|
nil,
|
||||||
|
};
|
||||||
|
static void (*namedcurves[])(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h) = {
|
||||||
|
secp256r1,
|
||||||
|
nil,
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
freecert(CertX509* c)
|
freecert(CertX509* c)
|
||||||
{
|
{
|
||||||
|
@ -1726,6 +1745,17 @@ parse_alg(Elem* e)
|
||||||
return oid_lookup(oid, alg_oid_tab);
|
return oid_lookup(oid, alg_oid_tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
parse_curve(Elem* e)
|
||||||
|
{
|
||||||
|
Elist* el;
|
||||||
|
Ints* oid;
|
||||||
|
|
||||||
|
if(!is_seq(e, &el) || elistlen(el)<2 || !is_oid(&el->tl->hd, &oid))
|
||||||
|
return -1;
|
||||||
|
return oid_lookup(oid, namedcurves_oid_tab);
|
||||||
|
}
|
||||||
|
|
||||||
static CertX509*
|
static CertX509*
|
||||||
decode_cert(Bytes* a)
|
decode_cert(Bytes* a)
|
||||||
{
|
{
|
||||||
|
@ -1828,7 +1858,7 @@ decode_cert(Bytes* a)
|
||||||
goto errret;
|
goto errret;
|
||||||
|
|
||||||
/* SubjectPublicKeyInfo */
|
/* SubjectPublicKeyInfo */
|
||||||
if(!is_seq(epubkey, &elpubkey))
|
if(!is_seq(epubkey, &elpubkey))
|
||||||
goto errret;
|
goto errret;
|
||||||
if(elistlen(elpubkey) != 2)
|
if(elistlen(elpubkey) != 2)
|
||||||
goto errret;
|
goto errret;
|
||||||
|
@ -1836,6 +1866,12 @@ decode_cert(Bytes* a)
|
||||||
c->publickey_alg = parse_alg(&elpubkey->hd);
|
c->publickey_alg = parse_alg(&elpubkey->hd);
|
||||||
if(c->publickey_alg < 0)
|
if(c->publickey_alg < 0)
|
||||||
goto errret;
|
goto errret;
|
||||||
|
c->curve = -1;
|
||||||
|
if(c->publickey_alg == ALG_ecPublicKey){
|
||||||
|
c->curve = parse_curve(&elpubkey->hd);
|
||||||
|
if(c->curve < 0)
|
||||||
|
goto errret;
|
||||||
|
}
|
||||||
if(!is_bitstring(&elpubkey->tl->hd, &bits))
|
if(!is_bitstring(&elpubkey->tl->hd, &bits))
|
||||||
goto errret;
|
goto errret;
|
||||||
if(bits->unusedbits != 0)
|
if(bits->unusedbits != 0)
|
||||||
|
@ -1869,32 +1905,23 @@ static RSApub*
|
||||||
decode_rsapubkey(Bytes* a)
|
decode_rsapubkey(Bytes* a)
|
||||||
{
|
{
|
||||||
Elem e;
|
Elem e;
|
||||||
Elist *el, *l;
|
Elist *el;
|
||||||
mpint *mp;
|
|
||||||
RSApub* key;
|
RSApub* key;
|
||||||
|
|
||||||
l = nil;
|
|
||||||
key = rsapuballoc();
|
key = rsapuballoc();
|
||||||
if(decode(a->data, a->len, &e) != ASN_OK)
|
if(decode(a->data, a->len, &e) != ASN_OK)
|
||||||
goto errret;
|
goto errret;
|
||||||
if(!is_seq(&e, &el) || elistlen(el) != 2)
|
if(!is_seq(&e, &el) || elistlen(el) != 2)
|
||||||
goto errret;
|
goto errret;
|
||||||
|
if((key->n = asn1mpint(&el->hd)) == nil)
|
||||||
l = el;
|
|
||||||
|
|
||||||
key->n = mp = asn1mpint(&el->hd);
|
|
||||||
if(mp == nil)
|
|
||||||
goto errret;
|
goto errret;
|
||||||
|
|
||||||
el = el->tl;
|
el = el->tl;
|
||||||
key->ek = mp = asn1mpint(&el->hd);
|
if((key->ek = asn1mpint(&el->hd)) == nil)
|
||||||
if(mp == nil)
|
|
||||||
goto errret;
|
goto errret;
|
||||||
|
freevalfields(&e.val);
|
||||||
freeelist(l);
|
|
||||||
return key;
|
return key;
|
||||||
errret:
|
errret:
|
||||||
freeelist(l);
|
freevalfields(&e.val);
|
||||||
rsapubfree(key);
|
rsapubfree(key);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
@ -1917,7 +1944,6 @@ decode_rsaprivkey(Bytes* a)
|
||||||
int version;
|
int version;
|
||||||
Elem e;
|
Elem e;
|
||||||
Elist *el;
|
Elist *el;
|
||||||
mpint *mp;
|
|
||||||
RSApriv* key;
|
RSApriv* key;
|
||||||
|
|
||||||
key = rsaprivalloc();
|
key = rsaprivalloc();
|
||||||
|
@ -1929,47 +1955,41 @@ decode_rsaprivkey(Bytes* a)
|
||||||
goto errret;
|
goto errret;
|
||||||
|
|
||||||
el = el->tl;
|
el = el->tl;
|
||||||
key->pub.n = mp = asn1mpint(&el->hd);
|
if((key->pub.n = asn1mpint(&el->hd)) == nil)
|
||||||
if(mp == nil)
|
|
||||||
goto errret;
|
goto errret;
|
||||||
|
|
||||||
el = el->tl;
|
el = el->tl;
|
||||||
key->pub.ek = mp = asn1mpint(&el->hd);
|
if((key->pub.ek = asn1mpint(&el->hd)) == nil)
|
||||||
if(mp == nil)
|
|
||||||
goto errret;
|
goto errret;
|
||||||
|
|
||||||
el = el->tl;
|
el = el->tl;
|
||||||
key->dk = mp = asn1mpint(&el->hd);
|
if((key->dk = asn1mpint(&el->hd)) == nil)
|
||||||
if(mp == nil)
|
|
||||||
goto errret;
|
goto errret;
|
||||||
|
|
||||||
el = el->tl;
|
el = el->tl;
|
||||||
key->q = mp = asn1mpint(&el->hd);
|
if((key->q = asn1mpint(&el->hd)) == nil)
|
||||||
if(mp == nil)
|
|
||||||
goto errret;
|
goto errret;
|
||||||
|
|
||||||
el = el->tl;
|
el = el->tl;
|
||||||
key->p = mp = asn1mpint(&el->hd);
|
if((key->p = asn1mpint(&el->hd)) == nil)
|
||||||
if(mp == nil)
|
|
||||||
goto errret;
|
goto errret;
|
||||||
|
|
||||||
el = el->tl;
|
el = el->tl;
|
||||||
key->kq = mp = asn1mpint(&el->hd);
|
if((key->kq = asn1mpint(&el->hd)) == nil)
|
||||||
if(mp == nil)
|
|
||||||
goto errret;
|
goto errret;
|
||||||
|
|
||||||
el = el->tl;
|
el = el->tl;
|
||||||
key->kp = mp = asn1mpint(&el->hd);
|
if((key->kp = asn1mpint(&el->hd)) == nil)
|
||||||
if(mp == nil)
|
|
||||||
goto errret;
|
goto errret;
|
||||||
|
|
||||||
el = el->tl;
|
el = el->tl;
|
||||||
key->c2 = mp = asn1mpint(&el->hd);
|
if((key->c2 = asn1mpint(&el->hd)) == nil)
|
||||||
if(mp == nil)
|
|
||||||
goto errret;
|
goto errret;
|
||||||
|
|
||||||
|
freevalfields(&e.val);
|
||||||
return key;
|
return key;
|
||||||
errret:
|
errret:
|
||||||
|
freevalfields(&e.val);
|
||||||
rsaprivfree(key);
|
rsaprivfree(key);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
@ -1990,7 +2010,6 @@ decode_dsaprivkey(Bytes* a)
|
||||||
int version;
|
int version;
|
||||||
Elem e;
|
Elem e;
|
||||||
Elist *el;
|
Elist *el;
|
||||||
mpint *mp;
|
|
||||||
DSApriv* key;
|
DSApriv* key;
|
||||||
|
|
||||||
key = dsaprivalloc();
|
key = dsaprivalloc();
|
||||||
|
@ -2003,32 +2022,29 @@ decode_dsaprivkey(Bytes* a)
|
||||||
goto errret;
|
goto errret;
|
||||||
|
|
||||||
el = el->tl;
|
el = el->tl;
|
||||||
key->pub.p = mp = asn1mpint(&el->hd);
|
if((key->pub.p = asn1mpint(&el->hd)) == nil)
|
||||||
if(mp == nil)
|
|
||||||
goto errret;
|
goto errret;
|
||||||
|
|
||||||
el = el->tl;
|
el = el->tl;
|
||||||
key->pub.q = mp = asn1mpint(&el->hd);
|
if((key->pub.q = asn1mpint(&el->hd)) == nil)
|
||||||
if(mp == nil)
|
|
||||||
goto errret;
|
goto errret;
|
||||||
|
|
||||||
el = el->tl;
|
el = el->tl;
|
||||||
key->pub.alpha = mp = asn1mpint(&el->hd);
|
if((key->pub.alpha = asn1mpint(&el->hd)) == nil)
|
||||||
if(mp == nil)
|
|
||||||
goto errret;
|
goto errret;
|
||||||
|
|
||||||
el = el->tl;
|
el = el->tl;
|
||||||
key->pub.key = mp = asn1mpint(&el->hd);
|
if((key->pub.key = asn1mpint(&el->hd)) == nil)
|
||||||
if(mp == nil)
|
|
||||||
goto errret;
|
goto errret;
|
||||||
|
|
||||||
el = el->tl;
|
el = el->tl;
|
||||||
key->secret = mp = asn1mpint(&el->hd);
|
if((key->secret = asn1mpint(&el->hd)) == nil)
|
||||||
if(mp == nil)
|
|
||||||
goto errret;
|
goto errret;
|
||||||
|
|
||||||
|
freevalfields(&e.val);
|
||||||
return key;
|
return key;
|
||||||
errret:
|
errret:
|
||||||
|
freevalfields(&e.val);
|
||||||
dsaprivfree(key);
|
dsaprivfree(key);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
@ -2037,16 +2053,12 @@ static mpint*
|
||||||
asn1mpint(Elem *e)
|
asn1mpint(Elem *e)
|
||||||
{
|
{
|
||||||
Bytes *b;
|
Bytes *b;
|
||||||
mpint *mp;
|
|
||||||
int v;
|
int v;
|
||||||
|
|
||||||
if(is_int(e, &v))
|
if(is_int(e, &v))
|
||||||
return itomp(v, nil);
|
return itomp(v, nil);
|
||||||
if(is_bigint(e, &b)) {
|
if(is_bigint(e, &b))
|
||||||
mp = betomp(b->data, b->len, nil);
|
return betomp(b->data, b->len, nil);
|
||||||
freebytes(b);
|
|
||||||
return mp;
|
|
||||||
}
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2134,7 +2146,7 @@ digest_certinfo(Bytes *cert, DigestAlg *da, uchar *digest)
|
||||||
return da->len;
|
return da->len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
pkcs1decryptsignature(uchar *sig, int siglen, RSApub *pk, uchar **pbuf)
|
pkcs1decryptsignature(uchar *sig, int siglen, RSApub *pk, uchar **pbuf)
|
||||||
{
|
{
|
||||||
int nlen, buflen;
|
int nlen, buflen;
|
||||||
|
@ -2169,34 +2181,41 @@ bad:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char*
|
char*
|
||||||
verify_digestinfo(uchar *sig, int siglen, RSApub *pk, uchar *pdigest, int *psigalg)
|
X509rsaverifydigest(uchar *sig, int siglen, uchar *edigest, int edigestlen, RSApub *pk)
|
||||||
{
|
{
|
||||||
Elem e;
|
Elem e;
|
||||||
Elist *el;
|
Elist *el;
|
||||||
Bytes *digest;
|
Bytes *digest;
|
||||||
uchar *buf;
|
uchar *buf;
|
||||||
int buflen;
|
int alg, buflen;
|
||||||
char *err;
|
char *err;
|
||||||
|
|
||||||
|
buflen = pkcs1decryptsignature(sig, siglen, pk, &buf);
|
||||||
|
if(buflen == edigestlen && tsmemcmp(buf, edigest, edigestlen) == 0){
|
||||||
|
free(buf);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
el = nil;
|
el = nil;
|
||||||
memset(&e, 0, sizeof(e));
|
memset(&e, 0, sizeof(e));
|
||||||
buflen = pkcs1decryptsignature(sig, siglen, pk, &buf);
|
|
||||||
if(buflen < 0 || decode(buf, buflen, &e) != ASN_OK
|
if(buflen < 0 || decode(buf, buflen, &e) != ASN_OK
|
||||||
|| !is_seq(&e, &el) || elistlen(el) != 2 || !is_octetstring(&el->tl->hd, &digest)) {
|
|| !is_seq(&e, &el) || elistlen(el) != 2 || !is_octetstring(&el->tl->hd, &digest)) {
|
||||||
err = "signature parse error";
|
err = "signature parse error";
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
*psigalg = parse_alg(&el->hd);
|
alg = parse_alg(&el->hd);
|
||||||
if(*psigalg < 0){
|
if(alg < 0){
|
||||||
err = "unknown signature algorithm";
|
err = "unknown signature algorithm";
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
if(digest->len != digestalg[*psigalg]->len){
|
if(digest->len != edigestlen || digest->len != digestalg[alg]->len){
|
||||||
err = "bad digest length";
|
err = "bad digest length";
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
memmove(pdigest, digest->data, digest->len);
|
if(tsmemcmp(digest->data, edigest, edigestlen) != 0){
|
||||||
|
err = "digest did not match";
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
err = nil;
|
err = nil;
|
||||||
end:
|
end:
|
||||||
freevalfields(&e.val);
|
freevalfields(&e.val);
|
||||||
|
@ -2205,64 +2224,60 @@ end:
|
||||||
}
|
}
|
||||||
|
|
||||||
char*
|
char*
|
||||||
X509verifydigest(uchar *sig, int siglen, uchar *edigest, int edigestlen, RSApub *pk)
|
X509ecdsaverifydigest(uchar *sig, int siglen, uchar *edigest, int edigestlen, ECdomain *dom, ECpub *pub)
|
||||||
{
|
{
|
||||||
uchar digest[MAXdlen];
|
Elem e;
|
||||||
int sigalg;
|
Elist *el;
|
||||||
char *e;
|
mpint *r, *s;
|
||||||
|
char *err;
|
||||||
|
|
||||||
e = verify_digestinfo(sig, siglen, pk, digest, &sigalg);
|
r = s = nil;
|
||||||
if(e != nil)
|
err = "bad signature";
|
||||||
return e;
|
if(decode(sig, siglen, &e) != ASN_OK)
|
||||||
if(digestalg[sigalg]->len != edigestlen)
|
goto end;
|
||||||
return "bad digest length";
|
if(!is_seq(&e, &el) || elistlen(el) != 2)
|
||||||
if(tsmemcmp(digest, edigest, edigestlen) != 0)
|
goto end;
|
||||||
return "digests did not match";
|
r = asn1mpint(&el->hd);
|
||||||
return nil;
|
if(r == nil)
|
||||||
|
goto end;
|
||||||
|
el = el->tl;
|
||||||
|
s = asn1mpint(&el->hd);
|
||||||
|
if(s == nil)
|
||||||
|
goto end;
|
||||||
|
if(ecdsaverify(dom, pub, edigest, edigestlen, r, s))
|
||||||
|
err = nil;
|
||||||
|
end:
|
||||||
|
freevalfields(&e.val);
|
||||||
|
mpfree(s);
|
||||||
|
mpfree(r);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
char*
|
ECpub*
|
||||||
X509verifydata(uchar *sig, int siglen, uchar *data, int datalen, RSApub *pk)
|
X509toECpub(uchar *cert, int ncert, ECdomain *dom)
|
||||||
{
|
{
|
||||||
uchar digest[MAXdlen], edigest[MAXdlen];
|
|
||||||
int sigalg;
|
|
||||||
char *e;
|
|
||||||
|
|
||||||
e = verify_digestinfo(sig, siglen, pk, digest, &sigalg);
|
|
||||||
if(e != nil)
|
|
||||||
return e;
|
|
||||||
(*digestalg[sigalg]->fun)(data, datalen, edigest, nil);
|
|
||||||
if(tsmemcmp(digest, edigest, digestalg[sigalg]->len) != 0)
|
|
||||||
return "digests did not match";
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
RSApub*
|
|
||||||
X509toRSApub(uchar *cert, int ncert, char *name, int nname)
|
|
||||||
{
|
|
||||||
char *e;
|
|
||||||
Bytes *b;
|
|
||||||
CertX509 *c;
|
CertX509 *c;
|
||||||
RSApub *pk;
|
ECpub *pub;
|
||||||
|
Bytes *b;
|
||||||
|
|
||||||
b = makebytes(cert, ncert);
|
b = makebytes(cert, ncert);
|
||||||
c = decode_cert(b);
|
c = decode_cert(b);
|
||||||
freebytes(b);
|
freebytes(b);
|
||||||
if(c == nil)
|
if(c == nil)
|
||||||
return nil;
|
return nil;
|
||||||
if(name != nil && c->subject != nil){
|
pub = nil;
|
||||||
e = strchr(c->subject, ',');
|
if(c->publickey_alg == ALG_ecPublicKey){
|
||||||
if(e != nil)
|
ecdominit(dom, namedcurves[c->curve]);
|
||||||
*e = 0; /* take just CN part of Distinguished Name */
|
pub = ecdecodepub(dom, c->publickey->data, c->publickey->len);
|
||||||
strncpy(name, c->subject, nname);
|
if(pub == nil)
|
||||||
|
ecdomfree(dom);
|
||||||
}
|
}
|
||||||
pk = decode_rsapubkey(c->publickey);
|
|
||||||
freecert(c);
|
freecert(c);
|
||||||
return pk;
|
return pub;
|
||||||
}
|
}
|
||||||
|
|
||||||
char*
|
char*
|
||||||
X509verify(uchar *cert, int ncert, RSApub *pk)
|
X509ecdsaverify(uchar *cert, int ncert, ECdomain *dom, ECpub *pk)
|
||||||
{
|
{
|
||||||
char *e;
|
char *e;
|
||||||
Bytes *b;
|
Bytes *b;
|
||||||
|
@ -2282,7 +2297,59 @@ X509verify(uchar *cert, int ncert, RSApub *pk)
|
||||||
freecert(c);
|
freecert(c);
|
||||||
return "cannot decode certinfo";
|
return "cannot decode certinfo";
|
||||||
}
|
}
|
||||||
e = X509verifydigest(c->signature->data, c->signature->len, digest, digestlen, pk);
|
e = X509ecdsaverifydigest(c->signature->data, c->signature->len, digest, digestlen, dom, pk);
|
||||||
|
freecert(c);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
RSApub*
|
||||||
|
X509toRSApub(uchar *cert, int ncert, char *name, int nname)
|
||||||
|
{
|
||||||
|
char *e;
|
||||||
|
Bytes *b;
|
||||||
|
CertX509 *c;
|
||||||
|
RSApub *pub;
|
||||||
|
|
||||||
|
b = makebytes(cert, ncert);
|
||||||
|
c = decode_cert(b);
|
||||||
|
freebytes(b);
|
||||||
|
if(c == nil)
|
||||||
|
return nil;
|
||||||
|
if(name != nil && c->subject != nil){
|
||||||
|
e = strchr(c->subject, ',');
|
||||||
|
if(e != nil)
|
||||||
|
*e = 0; /* take just CN part of Distinguished Name */
|
||||||
|
strncpy(name, c->subject, nname);
|
||||||
|
}
|
||||||
|
pub = nil;
|
||||||
|
if(c->publickey_alg == ALG_rsaEncryption)
|
||||||
|
pub = decode_rsapubkey(c->publickey);
|
||||||
|
freecert(c);
|
||||||
|
return pub;
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
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);
|
||||||
|
return "cannot decode cert";
|
||||||
|
}
|
||||||
|
digestlen = digest_certinfo(b, digestalg[c->signature_alg], digest);
|
||||||
|
freebytes(b);
|
||||||
|
if(digestlen <= 0){
|
||||||
|
freecert(c);
|
||||||
|
return "cannot decode certinfo";
|
||||||
|
}
|
||||||
|
e = X509rsaverifydigest(c->signature->data, c->signature->len, digest, digestlen, pk);
|
||||||
freecert(c);
|
freecert(c);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
@ -2512,7 +2579,7 @@ X509encodesignature_sha256(uchar digest[SHA2_256dlen], uchar *buf, int len)
|
||||||
}
|
}
|
||||||
|
|
||||||
uchar*
|
uchar*
|
||||||
X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen)
|
X509rsagen(RSApriv *priv, char *subj, ulong valid[2], int *certlen)
|
||||||
{
|
{
|
||||||
int serial = 0, sigalg = ALG_sha256WithRSAEncryption;
|
int serial = 0, sigalg = ALG_sha256WithRSAEncryption;
|
||||||
uchar *cert = nil;
|
uchar *cert = nil;
|
||||||
|
@ -2583,7 +2650,7 @@ errret:
|
||||||
}
|
}
|
||||||
|
|
||||||
uchar*
|
uchar*
|
||||||
X509req(RSApriv *priv, char *subj, int *certlen)
|
X509rsareq(RSApriv *priv, char *subj, int *certlen)
|
||||||
{
|
{
|
||||||
/* RFC 2314, PKCS #10 Certification Request Syntax */
|
/* RFC 2314, PKCS #10 Certification Request Syntax */
|
||||||
int version = 0, sigalg = ALG_sha256WithRSAEncryption;
|
int version = 0, sigalg = ALG_sha256WithRSAEncryption;
|
||||||
|
@ -2738,7 +2805,9 @@ X509dump(uchar *cert, int ncert)
|
||||||
char *e;
|
char *e;
|
||||||
Bytes *b;
|
Bytes *b;
|
||||||
CertX509 *c;
|
CertX509 *c;
|
||||||
RSApub *pk;
|
RSApub *rsapub;
|
||||||
|
ECpub *ecpub;
|
||||||
|
ECdomain ecdom;
|
||||||
int digestlen;
|
int digestlen;
|
||||||
uchar digest[MAXdlen];
|
uchar digest[MAXdlen];
|
||||||
|
|
||||||
|
@ -2762,16 +2831,36 @@ X509dump(uchar *cert, int ncert)
|
||||||
print("issuer %s\n", c->issuer);
|
print("issuer %s\n", c->issuer);
|
||||||
print("validity %s %s\n", c->validity_start, c->validity_end);
|
print("validity %s %s\n", c->validity_start, c->validity_end);
|
||||||
print("subject %s\n", c->subject);
|
print("subject %s\n", c->subject);
|
||||||
pk = decode_rsapubkey(c->publickey);
|
|
||||||
print("pubkey e=%B n(%d)=%B\n", pk->ek, mpsignif(pk->n), pk->n);
|
|
||||||
|
|
||||||
print("sigalg=%d digest=%.*H\n", c->signature_alg, digestlen, digest);
|
print("sigalg=%d digest=%.*H\n", c->signature_alg, digestlen, digest);
|
||||||
e = X509verifydigest(c->signature->data, c->signature->len, digest, digestlen, pk);
|
print("publickey_alg=%d pubkey[%d] %.*H\n", c->publickey_alg, c->publickey->len,
|
||||||
if(e==nil)
|
c->publickey->len, c->publickey->data);
|
||||||
e = "nil (meaning ok)";
|
|
||||||
print("self-signed X509verifydigest returns: %s\n", e);
|
|
||||||
|
|
||||||
rsapubfree(pk);
|
switch(c->publickey_alg){
|
||||||
|
case ALG_rsaEncryption:
|
||||||
|
rsapub = decode_rsapubkey(c->publickey);
|
||||||
|
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);
|
||||||
|
if(e==nil)
|
||||||
|
e = "nil (meaning ok)";
|
||||||
|
print("self-signed X509rsaverifydigest returns: %s\n", e);
|
||||||
|
rsapubfree(rsapub);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ALG_ecPublicKey:
|
||||||
|
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);
|
||||||
|
if(e==nil)
|
||||||
|
e = "nil (meaning ok)";
|
||||||
|
print("self-signed X509ecdsaverifydigest returns: %s\n", e);
|
||||||
|
ecpubfree(ecpub);
|
||||||
|
}
|
||||||
|
ecdomfree(&ecdom);
|
||||||
|
break;
|
||||||
|
}
|
||||||
freecert(c);
|
freecert(c);
|
||||||
print("end X509dump\n");
|
print("end X509dump\n");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue