150 lines
2.5 KiB
C
150 lines
2.5 KiB
C
#include "std.h"
|
|
#include "dat.h"
|
|
|
|
/*
|
|
* DSA signing and verification
|
|
*
|
|
* Sign:
|
|
* start p=xxx q=xxx alpha=xxx key=xxx
|
|
* write msg
|
|
* read signature(msg)
|
|
*
|
|
* Verify: (not implemented)
|
|
* start p=xxx q=xxx alpha=xxx key=xxx
|
|
* write msg
|
|
* write signature(msg)
|
|
* read ok or fail
|
|
*
|
|
* all numbers are hexadecimal bigints parsable with strtomp.
|
|
*/
|
|
|
|
static int
|
|
xdsasign(Conv *c)
|
|
{
|
|
int n;
|
|
mpint *m;
|
|
uchar digest[SHA1dlen], sigblob[20+20];
|
|
DSAsig *sig;
|
|
Key *k;
|
|
|
|
k = keylookup("%A", c->attr);
|
|
if(k == nil)
|
|
return -1;
|
|
|
|
c->state = "read data";
|
|
if((n=convread(c, digest, SHA1dlen)) < 0){
|
|
keyclose(k);
|
|
return -1;
|
|
}
|
|
m = betomp(digest, SHA1dlen, nil);
|
|
if(m == nil){
|
|
keyclose(k);
|
|
return -1;
|
|
}
|
|
sig = dsasign(k->priv, m);
|
|
keyclose(k);
|
|
mpfree(m);
|
|
if(sig == nil)
|
|
return -1;
|
|
if(mpsignif(sig->r) > 20*8 || mpsignif(sig->s) > 20*8){
|
|
werrstr("signature too long");
|
|
return -1;
|
|
}
|
|
mptoberjust(sig->r, sigblob, 20);
|
|
mptoberjust(sig->s, sigblob+20, 20);
|
|
convwrite(c, sigblob, sizeof sigblob);
|
|
dsasigfree(sig);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* convert to canonical form (lower case)
|
|
* for use in attribute matches.
|
|
*/
|
|
static void
|
|
strlwr(char *a)
|
|
{
|
|
for(; *a; a++){
|
|
if('A' <= *a && *a <= 'Z')
|
|
*a += 'a' - 'A';
|
|
}
|
|
}
|
|
|
|
static DSApriv*
|
|
readdsapriv(Key *k)
|
|
{
|
|
char *a;
|
|
DSApriv *priv;
|
|
|
|
priv = dsaprivalloc();
|
|
|
|
if((a=strfindattr(k->attr, "p"))==nil
|
|
|| (priv->pub.p=strtomp(a, nil, 16, nil))==nil)
|
|
goto Error;
|
|
strlwr(a);
|
|
if((a=strfindattr(k->attr, "q"))==nil
|
|
|| (priv->pub.q=strtomp(a, nil, 16, nil))==nil)
|
|
goto Error;
|
|
strlwr(a);
|
|
if(!probably_prime(priv->pub.p, 20) && !probably_prime(priv->pub.q, 20)) {
|
|
werrstr("dsa: p or q not prime");
|
|
goto Error;
|
|
}
|
|
if((a=strfindattr(k->attr, "alpha"))==nil
|
|
|| (priv->pub.alpha=strtomp(a, nil, 16, nil))==nil)
|
|
goto Error;
|
|
strlwr(a);
|
|
if((a=strfindattr(k->attr, "key"))==nil
|
|
|| (priv->pub.key=strtomp(a, nil, 16, nil))==nil)
|
|
goto Error;
|
|
strlwr(a);
|
|
if((a=strfindattr(k->privattr, "!secret"))==nil
|
|
|| (priv->secret=strtomp(a, nil, 16, nil))==nil)
|
|
goto Error;
|
|
strlwr(a);
|
|
return priv;
|
|
|
|
Error:
|
|
dsaprivfree(priv);
|
|
return nil;
|
|
}
|
|
|
|
static int
|
|
dsacheck(Key *k)
|
|
{
|
|
static int first = 1;
|
|
|
|
if(first){
|
|
fmtinstall('B', mpfmt);
|
|
first = 0;
|
|
}
|
|
|
|
if((k->priv = readdsapriv(k)) == nil){
|
|
werrstr("malformed key data");
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
dsaclose(Key *k)
|
|
{
|
|
dsaprivfree(k->priv);
|
|
k->priv = nil;
|
|
}
|
|
|
|
static Role
|
|
dsaroles[] =
|
|
{
|
|
"sign", xdsasign,
|
|
0
|
|
};
|
|
|
|
Proto dsa = {
|
|
"dsa",
|
|
dsaroles,
|
|
nil,
|
|
dsacheck,
|
|
dsaclose
|
|
};
|
|
|