ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /libkeyring/egalg.c/
#include <lib9.h>
#include <kernel.h>
#include <isa.h>
#include "interp.h"
#include "../libinterp/keyringif.h"
#include "mp.h"
#include "libsec.h"
#include "keys.h"
static char* pkattr[] = { "p", "alpha", "key", nil };
static char* skattr[] = { "p", "alpha", "key", "!secret", nil };
static char* sigattr[] = { "r", "s", nil };
static void*
eg_str2sk(char *str, char **strp)
{
EGpriv *eg;
char *p;
eg = egprivalloc();
eg->pub.p = base64tobig(str, &p);
eg->pub.alpha = base64tobig(p, &p);
eg->pub.key = base64tobig(p, &p);
eg->secret = base64tobig(p, &p);
if(strp)
*strp = p;
if(eg->pub.p == nil || eg->pub.alpha == nil || eg->pub.key == nil || eg->secret == nil){
egprivfree(eg);
return nil;
}
return eg;
}
static void*
eg_str2pk(char *str, char **strp)
{
EGpub *eg;
char *p;
eg = egpuballoc();
eg->p = base64tobig(str, &p);
eg->alpha = base64tobig(p, &p);
eg->key = base64tobig(p, &p);
if(strp)
*strp = p;
if(eg->p == nil || eg->alpha == nil || eg->key == nil){
egpubfree(eg);
return nil;
}
return eg;
}
static void*
eg_str2sig(char *str, char **strp)
{
EGsig *eg;
char *p;
eg = egsigalloc();
eg->r = base64tobig(str, &p);
eg->s = base64tobig(p, &p);
if(strp)
*strp = p;
if(eg->r == nil || eg->s == nil){
egsigfree(eg);
return nil;
}
return eg;
}
static int
eg_sk2str(void *veg, char *buf, int len)
{
EGpriv *eg;
char *cp, *ep;
eg = (EGpriv*)veg;
ep = buf + len - 1;
cp = buf;
cp += snprint(cp, ep - cp, "%U\n", eg->pub.p);
cp += snprint(cp, ep - cp, "%U\n", eg->pub.alpha);
cp += snprint(cp, ep - cp, "%U\n", eg->pub.key);
cp += snprint(cp, ep - cp, "%U\n", eg->secret);
*cp = 0;
return cp - buf;
}
static int
eg_pk2str(void *veg, char *buf, int len)
{
EGpub *eg;
char *cp, *ep;
eg = (EGpub*)veg;
ep = buf + len - 1;
cp = buf;
cp += snprint(cp, ep - cp, "%U\n", eg->p);
cp += snprint(cp, ep - cp, "%U\n", eg->alpha);
cp += snprint(cp, ep - cp, "%U\n", eg->key);
*cp = 0;
return cp - buf;
}
static int
eg_sig2str(void *veg, char *buf, int len)
{
EGsig *eg;
char *cp, *ep;
eg = veg;
ep = buf + len - 1;
cp = buf;
cp += snprint(cp, ep - cp, "%U\n", eg->r);
cp += snprint(cp, ep - cp, "%U\n", eg->s);
*cp = 0;
return cp - buf;
}
static void*
eg_sk2pk(void *vs)
{
return egprivtopub((EGpriv*)vs);
}
/* generate an el gamal secret key with new params */
static void*
eg_gen(int len)
{
return eggen(len, 0);
}
/* generate an el gamal secret key with same params as a public key */
static void*
eg_genfrompk(void *vpub)
{
EGpub *pub;
EGpriv *priv;
int nlen;
pub = vpub;
priv = egprivalloc();
priv->pub.p = mpcopy(pub->p);
priv->pub.alpha = mpcopy(pub->alpha);
nlen = mpsignif(pub->p);
pub = &priv->pub;
pub->key = mpnew(0);
priv->secret = mpnew(0);
mprand(nlen-1, genrandom, priv->secret);
mpexp(pub->alpha, priv->secret, pub->p, pub->key);
return priv;
}
static void*
eg_sign(mpint* mp, void *key)
{
return egsign((EGpriv*)key, mp);
}
static int
eg_verify(mpint* mp, void *sig, void *key)
{
return egverify((EGpub*)key, (EGsig*)sig, mp) == 0;
}
static void
eg_freepub(void *a)
{
egpubfree((EGpub*)a);
}
static void
eg_freepriv(void *a)
{
egprivfree((EGpriv*)a);
}
static void
eg_freesig(void *a)
{
egsigfree((EGsig*)a);
}
SigAlgVec*
elgamalinit(void)
{
SigAlgVec *vec;
vec = malloc(sizeof(SigAlgVec));
if(vec == nil)
return nil;
vec->name = "elgamal";
vec->pkattr = pkattr;
vec->skattr = skattr;
vec->sigattr = sigattr;
vec->str2sk = eg_str2sk;
vec->str2pk = eg_str2pk;
vec->str2sig = eg_str2sig;
vec->sk2str = eg_sk2str;
vec->pk2str = eg_pk2str;
vec->sig2str = eg_sig2str;
vec->sk2pk = eg_sk2pk;
vec->gensk = eg_gen;
vec->genskfrompk = eg_genfrompk;
vec->sign = eg_sign;
vec->verify = eg_verify;
vec->skfree = eg_freepriv;
vec->pkfree = eg_freepub;
vec->sigfree = eg_freesig;
return vec;
}