blob: ced10355f3d448107392334c409b238979779bb4 [file] [log] [blame]
#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
};