new auth
This commit is contained in:
191
src/cmd/auth/factotum/rsa.c
Normal file
191
src/cmd/auth/factotum/rsa.c
Normal file
@@ -0,0 +1,191 @@
|
||||
#include "std.h"
|
||||
#include "dat.h"
|
||||
|
||||
/*
|
||||
* RSA authentication.
|
||||
*
|
||||
* Client:
|
||||
* start n=xxx ek=xxx
|
||||
* write msg
|
||||
* read decrypt(msg)
|
||||
*
|
||||
* Sign (PKCS #1 using hash=sha1 or hash=md5)
|
||||
* start n=xxx ek=xxx
|
||||
* write hash(msg)
|
||||
* read signature(hash(msg))
|
||||
*
|
||||
* all numbers are hexadecimal biginits parsable with strtomp.
|
||||
* must be lower case for attribute matching in start.
|
||||
*/
|
||||
|
||||
static int
|
||||
rsaclient(Conv *c)
|
||||
{
|
||||
char *chal;
|
||||
mpint *m;
|
||||
Key *k;
|
||||
|
||||
k = keylookup("%A", c->attr);
|
||||
if(k == nil)
|
||||
return -1;
|
||||
c->state = "read challenge";
|
||||
if(convreadm(c, &chal) < 0){
|
||||
keyclose(k);
|
||||
return -1;
|
||||
}
|
||||
if(strlen(chal) < 32){
|
||||
badchal:
|
||||
free(chal);
|
||||
convprint(c, "bad challenge");
|
||||
keyclose(k);
|
||||
return -1;
|
||||
}
|
||||
m = strtomp(chal, nil, 16, nil);
|
||||
if(m == nil)
|
||||
goto badchal;
|
||||
free(chal);
|
||||
m = rsadecrypt(k->priv, m, m);
|
||||
convprint(c, "%B", m);
|
||||
mpfree(m);
|
||||
keyclose(k);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
xrsasign(Conv *c)
|
||||
{
|
||||
char *hash;
|
||||
int dlen, n;
|
||||
DigestAlg *hashfn;
|
||||
Key *k;
|
||||
uchar sig[1024], digest[64];
|
||||
|
||||
k = keylookup("%A", c->attr);
|
||||
if(k == nil)
|
||||
return -1;
|
||||
hash = strfindattr(k->attr, "hash");
|
||||
if(hash == nil)
|
||||
hash = "sha1";
|
||||
if(strcmp(hash, "sha1") == 0){
|
||||
hashfn = sha1;
|
||||
dlen = SHA1dlen;
|
||||
}else if(strcmp(hash, "md5") == 0){
|
||||
hashfn = md5;
|
||||
dlen = MD5dlen;
|
||||
}else{
|
||||
werrstr("unknown hash function %s", hash);
|
||||
return -1;
|
||||
}
|
||||
c->state = "read data";
|
||||
if((n=convread(c, digest, dlen)) < 0){
|
||||
keyclose(k);
|
||||
return -1;
|
||||
}
|
||||
memset(sig, 0xAA, sizeof sig);
|
||||
n = rsasign(k->priv, hashfn, digest, dlen, sig, sizeof sig);
|
||||
keyclose(k);
|
||||
if(n < 0)
|
||||
return -1;
|
||||
convwrite(c, sig, n);
|
||||
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 RSApriv*
|
||||
readrsapriv(Key *k)
|
||||
{
|
||||
char *a;
|
||||
RSApriv *priv;
|
||||
|
||||
priv = rsaprivalloc();
|
||||
|
||||
if((a=strfindattr(k->attr, "ek"))==nil
|
||||
|| (priv->pub.ek=strtomp(a, nil, 16, nil))==nil)
|
||||
goto Error;
|
||||
strlwr(a);
|
||||
if((a=strfindattr(k->attr, "n"))==nil
|
||||
|| (priv->pub.n=strtomp(a, nil, 16, nil))==nil)
|
||||
goto Error;
|
||||
strlwr(a);
|
||||
if((a=strfindattr(k->privattr, "!p"))==nil
|
||||
|| (priv->p=strtomp(a, nil, 16, nil))==nil)
|
||||
goto Error;
|
||||
strlwr(a);
|
||||
if((a=strfindattr(k->privattr, "!q"))==nil
|
||||
|| (priv->q=strtomp(a, nil, 16, nil))==nil)
|
||||
goto Error;
|
||||
strlwr(a);
|
||||
if((a=strfindattr(k->privattr, "!kp"))==nil
|
||||
|| (priv->kp=strtomp(a, nil, 16, nil))==nil)
|
||||
goto Error;
|
||||
strlwr(a);
|
||||
if((a=strfindattr(k->privattr, "!kq"))==nil
|
||||
|| (priv->kq=strtomp(a, nil, 16, nil))==nil)
|
||||
goto Error;
|
||||
strlwr(a);
|
||||
if((a=strfindattr(k->privattr, "!c2"))==nil
|
||||
|| (priv->c2=strtomp(a, nil, 16, nil))==nil)
|
||||
goto Error;
|
||||
strlwr(a);
|
||||
if((a=strfindattr(k->privattr, "!dk"))==nil
|
||||
|| (priv->dk=strtomp(a, nil, 16, nil))==nil)
|
||||
goto Error;
|
||||
strlwr(a);
|
||||
return priv;
|
||||
|
||||
Error:
|
||||
rsaprivfree(priv);
|
||||
return nil;
|
||||
}
|
||||
|
||||
static int
|
||||
rsacheck(Key *k)
|
||||
{
|
||||
static int first = 1;
|
||||
|
||||
if(first){
|
||||
fmtinstall('B', mpfmt);
|
||||
first = 0;
|
||||
}
|
||||
|
||||
if((k->priv = readrsapriv(k)) == nil){
|
||||
werrstr("malformed key data");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rsaclose(Key *k)
|
||||
{
|
||||
rsaprivfree(k->priv);
|
||||
k->priv = nil;
|
||||
}
|
||||
|
||||
static Role
|
||||
rsaroles[] =
|
||||
{
|
||||
"client", rsaclient,
|
||||
"sign", xrsasign,
|
||||
0
|
||||
};
|
||||
|
||||
Proto rsa = {
|
||||
"rsa",
|
||||
rsaroles,
|
||||
nil,
|
||||
rsacheck,
|
||||
rsaclose
|
||||
};
|
||||
Reference in New Issue
Block a user