libsec: add q parameter to dh_new() for subgroup support, sanitize dh parameters

This commit is contained in:
cinap_lenrek 2015-08-26 05:59:42 +02:00
parent 844bbecadb
commit 3bb0b9f4ea
3 changed files with 60 additions and 25 deletions

View file

@ -447,15 +447,16 @@ struct DHstate
{ {
mpint *g; /* base g */ mpint *g; /* base g */
mpint *p; /* large prime */ mpint *p; /* large prime */
mpint *q; /* subgroup prime */
mpint *x; /* random secret */ mpint *x; /* random secret */
mpint *y; /* public key y = g ^ x % p */ mpint *y; /* public key y = g**x % p */
}; };
/* generate new public key: y = g ^ x % p */ /* generate new public key: y = g**x % p */
mpint* dh_new(DHstate *dh, mpint *p, mpint *g); mpint* dh_new(DHstate *dh, mpint *p, mpint *q, mpint *g);
/* calculate shared key: k = pub ^ x % p */ /* calculate shared key: k = y**x % p */
mpint* dh_finish(DHstate *dh, mpint *pub); mpint* dh_finish(DHstate *dh, mpint *y);
/* password-based key derivation function 2 (RFC 2898) */ /* password-based key derivation function 2 (RFC 2898) */
void pbkdf2_hmac_sha1(uchar *p, ulong plen, uchar *s, ulong slen, ulong rounds, uchar *d, ulong dlen); void pbkdf2_hmac_sha1(uchar *p, ulong plen, uchar *s, ulong slen, ulong rounds, uchar *d, ulong dlen);

View file

@ -3,38 +3,72 @@
#include <libsec.h> #include <libsec.h>
mpint* mpint*
dh_new(DHstate *dh, mpint *p, mpint *g) dh_new(DHstate *dh, mpint *p, mpint *q, mpint *g)
{ {
mpint *pm1;
int n;
memset(dh, 0, sizeof(*dh)); memset(dh, 0, sizeof(*dh));
dh->g = mpcopy(g); if(mpcmp(g, mpone) <= 0)
return nil;
n = mpsignif(p);
pm1 = mpnew(n);
mpsub(p, mpone, pm1);
dh->p = mpcopy(p); dh->p = mpcopy(p);
if(dh->g != nil && dh->p != nil){ dh->g = mpcopy(g);
dh->x = mprand(mpsignif(dh->p), genrandom, nil); dh->q = mpcopy(q != nil ? q : pm1);
dh->y = mpnew(0); dh->x = mpnew(mpsignif(dh->q));
if(dh->x != nil && dh->y != nil){ dh->y = mpnew(n);
mpexp(dh->g, dh->x, dh->p, dh->y); for(;;){
return dh->y; mpnrand(dh->q, genrandom, dh->x);
} mpexp(dh->g, dh->x, dh->p, dh->y);
if(mpcmp(dh->y, mpone) > 0 && mpcmp(dh->y, pm1) < 0)
break;
} }
dh_finish(dh, nil); mpfree(pm1);
return nil;
return dh->y;
} }
mpint* mpint*
dh_finish(DHstate *dh, mpint *pub) dh_finish(DHstate *dh, mpint *y)
{ {
mpint *k; mpint *k = nil;
k = nil; if(y == nil || dh->x == nil || dh->p == nil || dh->q == nil)
if(pub != nil && dh->x != nil && dh->p != nil){ goto Out;
if((k = mpnew(0)) != nil)
mpexp(pub, dh->x, dh->p, k); /* y > 1 */
if(mpcmp(y, mpone) <= 0)
goto Out;
k = mpnew(mpsignif(dh->p));
/* y < p-1 */
mpsub(dh->p, mpone, k);
if(mpcmp(y, k) >= 0){
Bad:
mpfree(k);
k = nil;
goto Out;
} }
mpfree(dh->g);
/* y**q % p == 1 if q < p-1 */
if(mpcmp(dh->q, k) < 0){
mpexp(y, dh->q, dh->p, k);
if(mpcmp(k, mpone) != 0)
goto Bad;
}
mpexp(y, dh->x, dh->p, k);
Out:
mpfree(dh->p); mpfree(dh->p);
mpfree(dh->q);
mpfree(dh->g);
mpfree(dh->x); mpfree(dh->x);
mpfree(dh->y); mpfree(dh->y);
memset(dh, 0, sizeof(*dh)); memset(dh, 0, sizeof(*dh));
return k; return k;
} }

View file

@ -797,7 +797,7 @@ tlsSecDHEc(TlsSec *sec, uchar *srandom, int vers,
Y = bytestomp(Ys); Y = bytestomp(Ys);
K = nil; K = nil;
if(P == nil || G == nil || Y == nil || dh_new(&dh, P, G) == nil) if(P == nil || G == nil || Y == nil || dh_new(&dh, P, nil, G) == nil)
goto Out; goto Out;
epm = mptobytes(dh.y); epm = mptobytes(dh.y);
K = dh_finish(&dh, Y); K = dh_finish(&dh, Y);