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);
|
||||
uchar* decodePEM(char *s, char *type, int *len, char **new_s);
|
||||
PEMChain* decodepemchain(char *s, char *type);
|
||||
uchar* X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen);
|
||||
uchar* X509req(RSApriv *priv, char *subj, int *certlen);
|
||||
char* X509verifydigest(uchar *sig, int siglen, uchar *edigest, int edigestlen, RSApub *pk);
|
||||
char* X509verifydata(uchar *sig, int siglen, uchar *data, int datalen, RSApub *pk);
|
||||
char* X509verify(uchar *cert, int ncert, RSApub *pk);
|
||||
uchar* X509rsagen(RSApriv *priv, char *subj, ulong valid[2], int *certlen);
|
||||
uchar* X509rsareq(RSApriv *priv, char *subj, int *certlen);
|
||||
char* X509rsaverifydigest(uchar *sig, int siglen, uchar *edigest, int edigestlen, RSApub *pk);
|
||||
char* X509rsaverify(uchar *cert, int ncert, RSApub *pk);
|
||||
|
||||
void X509dump(uchar *cert, int ncert);
|
||||
|
||||
/*
|
||||
|
@ -487,11 +487,14 @@ typedef struct ECdomain{
|
|||
mpint *p;
|
||||
mpint *a;
|
||||
mpint *b;
|
||||
ECpoint *G;
|
||||
ECpoint G;
|
||||
mpint *n;
|
||||
mpint *h;
|
||||
} 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 ecadd(ECdomain *, ECpoint *a, ECpoint *b, 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);
|
||||
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 *);
|
||||
|
||||
/*
|
||||
|
|
19
sys/man/2/ec
19
sys/man/2/ec
|
@ -19,6 +19,12 @@ ecdsaverify \- elliptic curve cryptography
|
|||
.B #include <libsec.h>
|
||||
.PP
|
||||
.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);
|
||||
.PP
|
||||
.B
|
||||
|
@ -54,6 +60,19 @@ Points on the curve are represented by
|
|||
.B ECpoint
|
||||
structs.
|
||||
.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
|
||||
are analogous to their counterparts in
|
||||
.IR mp (2).
|
||||
|
|
|
@ -12,8 +12,9 @@ rsaprivtopub,
|
|||
rsapuballoc,
|
||||
rsapubfree,
|
||||
X509toRSApub,
|
||||
X509gen,
|
||||
X509verify \- RSA encryption algorithm
|
||||
X509rsagen,
|
||||
X509rsareq,
|
||||
X509rsaverify \- RSA encryption algorithm
|
||||
.SH SYNOPSIS
|
||||
.B #include <u.h>
|
||||
.br
|
||||
|
@ -61,13 +62,13 @@ void asn1dump(uchar *der, int len)
|
|||
uchar* decodePEM(char *s, char *type, int *len, char **new_s)
|
||||
.PP
|
||||
.B
|
||||
uchar* X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen);
|
||||
uchar* X509rsagen(RSApriv *priv, char *subj, ulong valid[2], int *certlen);
|
||||
.PP
|
||||
.B
|
||||
uchar* X509req(RSApriv *priv, char *subj, int *certlen);
|
||||
uchar* X509rsareq(RSApriv *priv, char *subj, int *certlen);
|
||||
.PP
|
||||
.B
|
||||
char* X509verify(uchar *cert, int ncert, RSApub *pk)
|
||||
char* X509rsaverify(uchar *cert, int ncert, RSApub *pk)
|
||||
.DT
|
||||
.SH DESCRIPTION
|
||||
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
|
||||
certificates signed by a known trusted key
|
||||
(in a single step, without certificate chains),
|
||||
.I X509verify
|
||||
.I X509rsaverify
|
||||
checks the signature on
|
||||
.IR cert .
|
||||
It returns nil if successful, else an error string.
|
||||
.PP
|
||||
.I X509gen
|
||||
.I X509rsagen
|
||||
creates a self-signed X.509 certificate, given an RSA keypair
|
||||
.IR priv ,
|
||||
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.x = 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;
|
||||
}
|
||||
|
||||
|
@ -56,14 +56,8 @@ ecdsainit(Proto *, Fsstate *fss)
|
|||
char *key, *password;
|
||||
Attr *attr;
|
||||
|
||||
if(dom.p == nil){
|
||||
dom.p = strtomp("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", nil, 16, nil);
|
||||
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);
|
||||
}
|
||||
if(dom.p == nil)
|
||||
ecdominit(&dom, secp256k1);
|
||||
fss->ps = nil;
|
||||
if((iscli = isclient(_strfindattr(fss->attr, "role"))) < 0)
|
||||
return failure(fss, nil);
|
||||
|
|
|
@ -34,7 +34,7 @@ main(int argc, char **argv)
|
|||
if((key = getkey(argc-1, argv+1, 1, nil)) == nil)
|
||||
sysfatal("%r");
|
||||
|
||||
cert = X509req(key, argv[0], &len);
|
||||
cert = X509rsareq(key, argv[0], &len);
|
||||
if(cert == nil)
|
||||
sysfatal("X509req: %r");
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ main(int argc, char **argv)
|
|||
if((key = getkey(argc-1, argv+1, 1, nil)) == nil)
|
||||
sysfatal("%r");
|
||||
|
||||
cert = X509gen(key, argv[0], valid, &len);
|
||||
cert = X509rsagen(key, argv[0], valid, &len);
|
||||
if(cert == nil)
|
||||
sysfatal("X509gen: %r");
|
||||
|
||||
|
|
|
@ -407,7 +407,7 @@ ecgen(ECdomain *dom, ECpriv *p)
|
|||
if(mpcmp(p->d, mpzero) > 0 && mpcmp(p->d, dom->n) < 0)
|
||||
break;
|
||||
}
|
||||
ecmul(dom, dom->G, p->d, p);
|
||||
ecmul(dom, &dom->G, p->d, 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);
|
||||
mpmul(r, t, u2);
|
||||
mpmod(u2, dom->n, u2);
|
||||
ecmul(dom, dom->G, u1, &R);
|
||||
ecmul(dom, &dom->G, u1, &R);
|
||||
ecmul(dom, pub, u2, &S);
|
||||
ecadd(dom, &R, &S, &R);
|
||||
ret = 0;
|
||||
|
@ -540,3 +540,79 @@ base58dec(char *src, uchar *dst, int len)
|
|||
mpfree(b);
|
||||
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\
|
||||
ccpoly.c\
|
||||
tsmemcmp.c\
|
||||
secp256r1.c\
|
||||
secp256k1.c\
|
||||
|
||||
CLEANFILES=secp256r1.c secp256k1.c
|
||||
|
||||
ALLOFILES=${CFILES:%.c=%.$O}
|
||||
|
||||
|
@ -46,6 +50,12 @@ UPDATE=mkfile\
|
|||
|
||||
</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
|
||||
$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,
|
||||
MaxKeyData = 160, // amount of secret we may need
|
||||
MaxChunk = 1<<15,
|
||||
MAXdlen = SHA2_512dlen,
|
||||
RandomSize = 32,
|
||||
SidSize = 32,
|
||||
MasterSecretSize = 48,
|
||||
|
@ -48,14 +49,7 @@ typedef struct Algs{
|
|||
|
||||
typedef struct Namedcurve{
|
||||
int tlsid;
|
||||
char *name;
|
||||
|
||||
char *p;
|
||||
char *a;
|
||||
char *b;
|
||||
char *G;
|
||||
char *n;
|
||||
char *h;
|
||||
void (*init)(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h);
|
||||
} Namedcurve;
|
||||
|
||||
typedef struct Finished{
|
||||
|
@ -279,11 +273,14 @@ enum {
|
|||
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0XC013,
|
||||
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0XC014,
|
||||
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_ECDSA_WITH_CHACHA20_POLY1305 = 0xCCA9,
|
||||
TLS_DHE_RSA_WITH_CHACHA20_POLY1305 = 0xCCAA,
|
||||
|
||||
GOOGLE_ECDHE_RSA_WITH_CHACHA20_POLY1305 = 0xCC13,
|
||||
GOOGLE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 = 0xCC14,
|
||||
GOOGLE_DHE_RSA_WITH_CHACHA20_POLY1305 = 0xCC15,
|
||||
|
||||
TLS_PSK_WITH_CHACHA20_POLY1305 = 0xCCAB,
|
||||
|
@ -299,11 +296,14 @@ enum {
|
|||
|
||||
static Algs cipherAlgs[] = {
|
||||
{"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},
|
||||
|
||||
{"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},
|
||||
|
||||
{"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", "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},
|
||||
|
@ -328,21 +328,32 @@ static uchar compressors[] = {
|
|||
};
|
||||
|
||||
static Namedcurve namedcurves[] = {
|
||||
{0x0017, "secp256r1",
|
||||
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
|
||||
"5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
|
||||
"046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
|
||||
"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
|
||||
"1"}
|
||||
0x0017, secp256r1,
|
||||
};
|
||||
|
||||
static uchar pointformats[] = {
|
||||
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[] = {
|
||||
0x0603, /* SHA512 ECDSA */
|
||||
0x0503, /* SHA384 ECDSA */
|
||||
0x0403, /* SHA256 ECDSA */
|
||||
0x0203, /* SHA1 ECDSA */
|
||||
|
||||
0x0601, /* SHA512 RSA */
|
||||
0x0501, /* SHA384 RSA */
|
||||
0x0401, /* SHA256 RSA */
|
||||
|
@ -421,7 +432,6 @@ 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 ========================
|
||||
|
@ -869,11 +879,16 @@ static int
|
|||
isECDHE(int 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_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 0;
|
||||
|
@ -932,47 +947,14 @@ Out:
|
|||
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*
|
||||
tlsSecECDHEc(TlsSec *sec, uchar *srandom, int vers, int curve, Bytes *Ys)
|
||||
{
|
||||
Namedcurve *nc, *enc;
|
||||
Bytes *epm;
|
||||
ECdomain dom;
|
||||
ECpoint G, K, Y;
|
||||
ECpub *pub;
|
||||
ECpoint K;
|
||||
ECpriv Q;
|
||||
|
||||
if(Ys == nil)
|
||||
|
@ -990,18 +972,12 @@ tlsSecECDHEc(TlsSec *sec, uchar *srandom, int vers, int curve, Bytes *Ys)
|
|||
if(setVers(sec, vers) < 0)
|
||||
return nil;
|
||||
|
||||
epm = nil;
|
||||
|
||||
memset(&dom, 0, sizeof(dom));
|
||||
dom.p = mpfield(strtomp(nc->p, nil, 16, nil));
|
||||
dom.a = strtomp(nc->a, nil, 16, 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);
|
||||
ecdominit(&dom, nc->init);
|
||||
pub = ecdecodepub(&dom, Ys->data, Ys->len);
|
||||
if(pub == nil){
|
||||
ecdomfree(&dom);
|
||||
return nil;
|
||||
}
|
||||
|
||||
memset(&Q, 0, sizeof(Q));
|
||||
Q.x = mpnew(0);
|
||||
|
@ -1012,48 +988,22 @@ tlsSecECDHEc(TlsSec *sec, uchar *srandom, int vers, int curve, Bytes *Ys)
|
|||
K.x = mpnew(0);
|
||||
K.y = mpnew(0);
|
||||
|
||||
memset(&Y, 0, sizeof(Y));
|
||||
Y.x = mpnew(0);
|
||||
Y.y = mpnew(0);
|
||||
|
||||
if(dom.p == nil || dom.a == nil || dom.b == nil || dom.n == nil || dom.h == nil)
|
||||
goto Out;
|
||||
|
||||
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);
|
||||
epm = nil;
|
||||
if(ecgen(&dom, &Q) != nil){
|
||||
ecmul(&dom, pub, Q.d, &K);
|
||||
setMasterSecret(sec, mptobytes(K.x));
|
||||
|
||||
/* 0x04 = uncompressed public key */
|
||||
epm = ectobytes(0x04, &Q);
|
||||
|
||||
Out:
|
||||
mpfree(Y.x);
|
||||
mpfree(Y.y);
|
||||
epm = newbytes(1 + 2*((mpsignif(dom.p)+7)/8));
|
||||
epm->len = ecencodepub(&dom, &Q, epm->data, epm->len);
|
||||
}
|
||||
|
||||
mpfree(K.x);
|
||||
mpfree(K.y);
|
||||
|
||||
mpfree(Q.x);
|
||||
mpfree(Q.y);
|
||||
mpfree(Q.d);
|
||||
|
||||
mpfree(G.x);
|
||||
mpfree(G.y);
|
||||
|
||||
mpfree(dom.p);
|
||||
mpfree(dom.a);
|
||||
mpfree(dom.b);
|
||||
mpfree(dom.n);
|
||||
mpfree(dom.h);
|
||||
ecpubfree(pub);
|
||||
ecdomfree(&dom);
|
||||
|
||||
return epm;
|
||||
}
|
||||
|
@ -1061,9 +1011,12 @@ Out:
|
|||
static char*
|
||||
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;
|
||||
RSApub *pk;
|
||||
char *err;
|
||||
|
||||
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(c->sec->psklen > 0)
|
||||
return nil;
|
||||
|
||||
return "no signature";
|
||||
}
|
||||
|
||||
if(c->cert == nil)
|
||||
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);
|
||||
memmove(blob->data+0*RandomSize, c->crandom, RandomSize);
|
||||
memmove(blob->data+1*RandomSize, c->srandom, RandomSize);
|
||||
memmove(blob->data+2*RandomSize, par->data, par->len);
|
||||
if(c->version >= TLS12Version) {
|
||||
if((sigalg & 0xFF) == 1)
|
||||
err = X509verifydata(sig->data, sig->len, blob->data, blob->len, pk);
|
||||
else
|
||||
err = "signaure algorithm not RSA";
|
||||
if(c->version < TLS12Version){
|
||||
digestlen = MD5dlen + SHA1dlen;
|
||||
md5(blob->data, blob->len, digest, nil);
|
||||
sha1(blob->data, blob->len, digest+MD5dlen, nil);
|
||||
} else {
|
||||
err = nil;
|
||||
if(pkcs1decryptsignature(sig->data, sig->len, pk, &buf) != sizeof(hashes))
|
||||
err = "bad signature";
|
||||
else {
|
||||
md5(blob->data, blob->len, hashes, nil);
|
||||
sha1(blob->data, blob->len, hashes+MD5dlen, nil);
|
||||
if(tsmemcmp(buf, hashes, sizeof(hashes)) != 0)
|
||||
err = "digests did not match";
|
||||
int hashalg = (sigalg>>8) & 0xFF;
|
||||
digestlen = -1;
|
||||
if(hashalg < nelem(hashfun) && hashfun[hashalg].fun != nil){
|
||||
digestlen = hashfun[hashalg].len;
|
||||
(*hashfun[hashalg].fun)(blob->data, blob->len, digest, nil);
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -134,8 +134,7 @@ static int encode(Elem e, Bytes** pbytes);
|
|||
static int oid_lookup(Ints* o, Ints** tab);
|
||||
static void freevalfields(Value* v);
|
||||
static mpint *asn1mpint(Elem *e);
|
||||
|
||||
|
||||
static void edump(Elem);
|
||||
|
||||
#define TAG_MASK 0x1F
|
||||
#define CONSTR_MASK 0x20
|
||||
|
@ -223,6 +222,7 @@ ber_decode(uchar** pp, uchar* pend, Elem* pelem)
|
|||
Tag tag;
|
||||
Value val;
|
||||
|
||||
memset(pelem, 0, sizeof(*pelem));
|
||||
err = tag_decode(pp, pend, &tag, &isconstr);
|
||||
if(err == ASN_OK) {
|
||||
err = length_decode(pp, pend, &length);
|
||||
|
@ -1159,21 +1159,8 @@ is_int(Elem* pe, int* pint)
|
|||
static int
|
||||
is_bigint(Elem* pe, Bytes** pbigint)
|
||||
{
|
||||
int v, n, i;
|
||||
|
||||
if(pe->tag.class == Universal && pe->tag.num == INTEGER) {
|
||||
if(pe->val.tag == VBigInt)
|
||||
if(pe->tag.class == Universal && pe->tag.num == INTEGER && 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 0;
|
||||
|
@ -1536,6 +1523,7 @@ typedef struct CertX509 {
|
|||
Bytes* publickey;
|
||||
int signature_alg;
|
||||
Bytes* signature;
|
||||
int curve;
|
||||
} CertX509;
|
||||
|
||||
/* Algorithm object-ids */
|
||||
|
@ -1553,6 +1541,12 @@ enum {
|
|||
ALG_sha512WithRSAEncryption,
|
||||
ALG_sha224WithRSAEncryption,
|
||||
|
||||
ALG_ecPublicKey,
|
||||
ALG_sha1WithECDSA,
|
||||
ALG_sha256WithECDSA,
|
||||
ALG_sha384WithECDSA,
|
||||
ALG_sha512WithECDSA,
|
||||
|
||||
ALG_md5,
|
||||
ALG_sha1,
|
||||
ALG_sha256,
|
||||
|
@ -1587,6 +1581,7 @@ enum {
|
|||
};
|
||||
|
||||
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_md4WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 3 };
|
||||
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_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_sha1 = {6, 1, 3, 14, 3, 2, 26 };
|
||||
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_sha224WithRSAEncryption,
|
||||
|
||||
(Ints*)&oid_ecPublicKey,
|
||||
(Ints*)&oid_sha1WithECDSA,
|
||||
(Ints*)&oid_sha256WithECDSA,
|
||||
(Ints*)&oid_sha384WithECDSA,
|
||||
(Ints*)&oid_sha512WithECDSA,
|
||||
|
||||
(Ints*)&oid_md5,
|
||||
(Ints*)&oid_sha1,
|
||||
(Ints*)&oid_sha256,
|
||||
|
@ -1631,10 +1638,22 @@ static DigestAlg *digestalg[NUMALGS+1] = {
|
|||
&alg_md5, &alg_md5, &alg_md5, &alg_md5,
|
||||
&alg_sha1, &alg_sha1,
|
||||
&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,
|
||||
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
|
||||
freecert(CertX509* c)
|
||||
{
|
||||
|
@ -1726,6 +1745,17 @@ parse_alg(Elem* e)
|
|||
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*
|
||||
decode_cert(Bytes* a)
|
||||
{
|
||||
|
@ -1836,6 +1866,12 @@ decode_cert(Bytes* a)
|
|||
c->publickey_alg = parse_alg(&elpubkey->hd);
|
||||
if(c->publickey_alg < 0)
|
||||
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))
|
||||
goto errret;
|
||||
if(bits->unusedbits != 0)
|
||||
|
@ -1869,32 +1905,23 @@ static RSApub*
|
|||
decode_rsapubkey(Bytes* a)
|
||||
{
|
||||
Elem e;
|
||||
Elist *el, *l;
|
||||
mpint *mp;
|
||||
Elist *el;
|
||||
RSApub* key;
|
||||
|
||||
l = nil;
|
||||
key = rsapuballoc();
|
||||
if(decode(a->data, a->len, &e) != ASN_OK)
|
||||
goto errret;
|
||||
if(!is_seq(&e, &el) || elistlen(el) != 2)
|
||||
goto errret;
|
||||
|
||||
l = el;
|
||||
|
||||
key->n = mp = asn1mpint(&el->hd);
|
||||
if(mp == nil)
|
||||
if((key->n = asn1mpint(&el->hd)) == nil)
|
||||
goto errret;
|
||||
|
||||
el = el->tl;
|
||||
key->ek = mp = asn1mpint(&el->hd);
|
||||
if(mp == nil)
|
||||
if((key->ek = asn1mpint(&el->hd)) == nil)
|
||||
goto errret;
|
||||
|
||||
freeelist(l);
|
||||
freevalfields(&e.val);
|
||||
return key;
|
||||
errret:
|
||||
freeelist(l);
|
||||
freevalfields(&e.val);
|
||||
rsapubfree(key);
|
||||
return nil;
|
||||
}
|
||||
|
@ -1917,7 +1944,6 @@ decode_rsaprivkey(Bytes* a)
|
|||
int version;
|
||||
Elem e;
|
||||
Elist *el;
|
||||
mpint *mp;
|
||||
RSApriv* key;
|
||||
|
||||
key = rsaprivalloc();
|
||||
|
@ -1929,47 +1955,41 @@ decode_rsaprivkey(Bytes* a)
|
|||
goto errret;
|
||||
|
||||
el = el->tl;
|
||||
key->pub.n = mp = asn1mpint(&el->hd);
|
||||
if(mp == nil)
|
||||
if((key->pub.n = asn1mpint(&el->hd)) == nil)
|
||||
goto errret;
|
||||
|
||||
el = el->tl;
|
||||
key->pub.ek = mp = asn1mpint(&el->hd);
|
||||
if(mp == nil)
|
||||
if((key->pub.ek = asn1mpint(&el->hd)) == nil)
|
||||
goto errret;
|
||||
|
||||
el = el->tl;
|
||||
key->dk = mp = asn1mpint(&el->hd);
|
||||
if(mp == nil)
|
||||
if((key->dk = asn1mpint(&el->hd)) == nil)
|
||||
goto errret;
|
||||
|
||||
el = el->tl;
|
||||
key->q = mp = asn1mpint(&el->hd);
|
||||
if(mp == nil)
|
||||
if((key->q = asn1mpint(&el->hd)) == nil)
|
||||
goto errret;
|
||||
|
||||
el = el->tl;
|
||||
key->p = mp = asn1mpint(&el->hd);
|
||||
if(mp == nil)
|
||||
if((key->p = asn1mpint(&el->hd)) == nil)
|
||||
goto errret;
|
||||
|
||||
el = el->tl;
|
||||
key->kq = mp = asn1mpint(&el->hd);
|
||||
if(mp == nil)
|
||||
if((key->kq = asn1mpint(&el->hd)) == nil)
|
||||
goto errret;
|
||||
|
||||
el = el->tl;
|
||||
key->kp = mp = asn1mpint(&el->hd);
|
||||
if(mp == nil)
|
||||
if((key->kp = asn1mpint(&el->hd)) == nil)
|
||||
goto errret;
|
||||
|
||||
el = el->tl;
|
||||
key->c2 = mp = asn1mpint(&el->hd);
|
||||
if(mp == nil)
|
||||
if((key->c2 = asn1mpint(&el->hd)) == nil)
|
||||
goto errret;
|
||||
|
||||
freevalfields(&e.val);
|
||||
return key;
|
||||
errret:
|
||||
freevalfields(&e.val);
|
||||
rsaprivfree(key);
|
||||
return nil;
|
||||
}
|
||||
|
@ -1990,7 +2010,6 @@ decode_dsaprivkey(Bytes* a)
|
|||
int version;
|
||||
Elem e;
|
||||
Elist *el;
|
||||
mpint *mp;
|
||||
DSApriv* key;
|
||||
|
||||
key = dsaprivalloc();
|
||||
|
@ -2003,32 +2022,29 @@ decode_dsaprivkey(Bytes* a)
|
|||
goto errret;
|
||||
|
||||
el = el->tl;
|
||||
key->pub.p = mp = asn1mpint(&el->hd);
|
||||
if(mp == nil)
|
||||
if((key->pub.p = asn1mpint(&el->hd)) == nil)
|
||||
goto errret;
|
||||
|
||||
el = el->tl;
|
||||
key->pub.q = mp = asn1mpint(&el->hd);
|
||||
if(mp == nil)
|
||||
if((key->pub.q = asn1mpint(&el->hd)) == nil)
|
||||
goto errret;
|
||||
|
||||
el = el->tl;
|
||||
key->pub.alpha = mp = asn1mpint(&el->hd);
|
||||
if(mp == nil)
|
||||
if((key->pub.alpha = asn1mpint(&el->hd)) == nil)
|
||||
goto errret;
|
||||
|
||||
el = el->tl;
|
||||
key->pub.key = mp = asn1mpint(&el->hd);
|
||||
if(mp == nil)
|
||||
if((key->pub.key = asn1mpint(&el->hd)) == nil)
|
||||
goto errret;
|
||||
|
||||
el = el->tl;
|
||||
key->secret = mp = asn1mpint(&el->hd);
|
||||
if(mp == nil)
|
||||
if((key->secret = asn1mpint(&el->hd)) == nil)
|
||||
goto errret;
|
||||
|
||||
freevalfields(&e.val);
|
||||
return key;
|
||||
errret:
|
||||
freevalfields(&e.val);
|
||||
dsaprivfree(key);
|
||||
return nil;
|
||||
}
|
||||
|
@ -2037,16 +2053,12 @@ static mpint*
|
|||
asn1mpint(Elem *e)
|
||||
{
|
||||
Bytes *b;
|
||||
mpint *mp;
|
||||
int v;
|
||||
|
||||
if(is_int(e, &v))
|
||||
return itomp(v, nil);
|
||||
if(is_bigint(e, &b)) {
|
||||
mp = betomp(b->data, b->len, nil);
|
||||
freebytes(b);
|
||||
return mp;
|
||||
}
|
||||
if(is_bigint(e, &b))
|
||||
return betomp(b->data, b->len, nil);
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
@ -2134,7 +2146,7 @@ digest_certinfo(Bytes *cert, DigestAlg *da, uchar *digest)
|
|||
return da->len;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
pkcs1decryptsignature(uchar *sig, int siglen, RSApub *pk, uchar **pbuf)
|
||||
{
|
||||
int nlen, buflen;
|
||||
|
@ -2169,34 +2181,41 @@ bad:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static char*
|
||||
verify_digestinfo(uchar *sig, int siglen, RSApub *pk, uchar *pdigest, int *psigalg)
|
||||
char*
|
||||
X509rsaverifydigest(uchar *sig, int siglen, uchar *edigest, int edigestlen, RSApub *pk)
|
||||
{
|
||||
Elem e;
|
||||
Elist *el;
|
||||
Bytes *digest;
|
||||
uchar *buf;
|
||||
int buflen;
|
||||
int alg, buflen;
|
||||
char *err;
|
||||
|
||||
buflen = pkcs1decryptsignature(sig, siglen, pk, &buf);
|
||||
if(buflen == edigestlen && tsmemcmp(buf, edigest, edigestlen) == 0){
|
||||
free(buf);
|
||||
return nil;
|
||||
}
|
||||
el = nil;
|
||||
memset(&e, 0, sizeof(e));
|
||||
buflen = pkcs1decryptsignature(sig, siglen, pk, &buf);
|
||||
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;
|
||||
}
|
||||
*psigalg = parse_alg(&el->hd);
|
||||
if(*psigalg < 0){
|
||||
alg = parse_alg(&el->hd);
|
||||
if(alg < 0){
|
||||
err = "unknown signature algorithm";
|
||||
goto end;
|
||||
}
|
||||
if(digest->len != digestalg[*psigalg]->len){
|
||||
if(digest->len != edigestlen || digest->len != digestalg[alg]->len){
|
||||
err = "bad digest length";
|
||||
goto end;
|
||||
}
|
||||
memmove(pdigest, digest->data, digest->len);
|
||||
if(tsmemcmp(digest->data, edigest, edigestlen) != 0){
|
||||
err = "digest did not match";
|
||||
goto end;
|
||||
}
|
||||
err = nil;
|
||||
end:
|
||||
freevalfields(&e.val);
|
||||
|
@ -2205,64 +2224,60 @@ end:
|
|||
}
|
||||
|
||||
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];
|
||||
int sigalg;
|
||||
char *e;
|
||||
Elem e;
|
||||
Elist *el;
|
||||
mpint *r, *s;
|
||||
char *err;
|
||||
|
||||
e = verify_digestinfo(sig, siglen, pk, digest, &sigalg);
|
||||
if(e != nil)
|
||||
return e;
|
||||
if(digestalg[sigalg]->len != edigestlen)
|
||||
return "bad digest length";
|
||||
if(tsmemcmp(digest, edigest, edigestlen) != 0)
|
||||
return "digests did not match";
|
||||
return nil;
|
||||
r = s = nil;
|
||||
err = "bad signature";
|
||||
if(decode(sig, siglen, &e) != ASN_OK)
|
||||
goto end;
|
||||
if(!is_seq(&e, &el) || elistlen(el) != 2)
|
||||
goto end;
|
||||
r = asn1mpint(&el->hd);
|
||||
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*
|
||||
X509verifydata(uchar *sig, int siglen, uchar *data, int datalen, RSApub *pk)
|
||||
ECpub*
|
||||
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;
|
||||
RSApub *pk;
|
||||
ECpub *pub;
|
||||
Bytes *b;
|
||||
|
||||
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_ecPublicKey){
|
||||
ecdominit(dom, namedcurves[c->curve]);
|
||||
pub = ecdecodepub(dom, c->publickey->data, c->publickey->len);
|
||||
if(pub == nil)
|
||||
ecdomfree(dom);
|
||||
}
|
||||
pk = decode_rsapubkey(c->publickey);
|
||||
freecert(c);
|
||||
return pk;
|
||||
return pub;
|
||||
}
|
||||
|
||||
char*
|
||||
X509verify(uchar *cert, int ncert, RSApub *pk)
|
||||
X509ecdsaverify(uchar *cert, int ncert, ECdomain *dom, ECpub *pk)
|
||||
{
|
||||
char *e;
|
||||
Bytes *b;
|
||||
|
@ -2282,7 +2297,59 @@ X509verify(uchar *cert, int ncert, RSApub *pk)
|
|||
freecert(c);
|
||||
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);
|
||||
return e;
|
||||
}
|
||||
|
@ -2512,7 +2579,7 @@ X509encodesignature_sha256(uchar digest[SHA2_256dlen], uchar *buf, int len)
|
|||
}
|
||||
|
||||
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;
|
||||
uchar *cert = nil;
|
||||
|
@ -2583,7 +2650,7 @@ errret:
|
|||
}
|
||||
|
||||
uchar*
|
||||
X509req(RSApriv *priv, char *subj, int *certlen)
|
||||
X509rsareq(RSApriv *priv, char *subj, int *certlen)
|
||||
{
|
||||
/* RFC 2314, PKCS #10 Certification Request Syntax */
|
||||
int version = 0, sigalg = ALG_sha256WithRSAEncryption;
|
||||
|
@ -2738,7 +2805,9 @@ X509dump(uchar *cert, int ncert)
|
|||
char *e;
|
||||
Bytes *b;
|
||||
CertX509 *c;
|
||||
RSApub *pk;
|
||||
RSApub *rsapub;
|
||||
ECpub *ecpub;
|
||||
ECdomain ecdom;
|
||||
int digestlen;
|
||||
uchar digest[MAXdlen];
|
||||
|
||||
|
@ -2762,16 +2831,36 @@ X509dump(uchar *cert, int ncert)
|
|||
print("issuer %s\n", c->issuer);
|
||||
print("validity %s %s\n", c->validity_start, c->validity_end);
|
||||
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);
|
||||
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,
|
||||
c->publickey->len, c->publickey->data);
|
||||
|
||||
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 X509verifydigest returns: %s\n", e);
|
||||
|
||||
rsapubfree(pk);
|
||||
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);
|
||||
print("end X509dump\n");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue