diff options
Diffstat (limited to 'src/cmd/factotum/ssh.c')
-rw-r--r-- | src/cmd/factotum/ssh.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/src/cmd/factotum/ssh.c b/src/cmd/factotum/ssh.c new file mode 100644 index 00000000..4c88bfe6 --- /dev/null +++ b/src/cmd/factotum/ssh.c @@ -0,0 +1,135 @@ +#include "dat.h" +#include <mp.h> +#include <libsec.h> + +typedef struct Sshrsastate Sshrsastate; + +enum { + CReadpub, + CWritechal, + CReadresp, +}; +struct State +{ + RSApriv *priv; + Key *k; + mpint *resp; + int phase; +}; + +static RSApriv* +readrsapriv(char *s) +{ + RSApriv *priv; + + priv = rsaprivalloc(); + + strtoul(s, &s, 10); + if((priv->pub.ek=strtomp(s, &s, 16, nil)) == nil) + goto Error; + if((priv->dk=strtomp(s, &s, 16, nil)) == nil) + goto Error; + if((priv->pub.n=strtomp(s, &s, 16, nil)) == nil) + goto Error; + if((priv->p=strtomp(s, &s, 16, nil)) == nil) + goto Error; + if((priv->q=strtomp(s, &s, 16, nil)) == nil) + goto Error; + if((priv->kp=strtomp(s, &s, 16, nil)) == nil) + goto Error; + if((priv->kq=strtomp(s, &s, 16, nil)) == nil) + goto Error; + if((priv->c2=strtomp(s, &s, 16, nil)) == nil) + goto Error; + + return priv; + +Error: + rsaprivfree(priv); + return nil; +} + +int +sshinit(Fsstate *fss, +sshrsaopen(Key *k, char*, int client) +{ + Sshrsastate *s; + + fmtinstall('B', mpconv); + assert(client); + s = emalloc(sizeof *s); + s->priv = readrsapriv(s_to_c(k->data)); + s->k = k; + if(s->priv == nil){ + agentlog("error parsing ssh key %s", k->file); + free(s); + return nil; + } + return s; +} + +int +sshrsaread(void *va, void *buf, int n) +{ + Sshrsastate *s; + + s = va; + switch(s->phase){ + case Readpub: + s->phase = Done; + return snprint(buf, n, "%B", s->priv->pub.n); + case Readresp: + s->phase = Done; + return snprint(buf, n, "%B", s->resp); + default: + return 0; + } +} + +int +sshrsawrite(void *va, void *vbuf, int n) +{ + mpint *m; + char *buf; + Sshrsastate *s; + + s = va; + if((s->k->flags&Fconfirmuse) && confirm("ssh use") < 0) + return -1; + + buf = emalloc(n+1); + memmove(buf, vbuf, n); + buf[n] = '\0'; + m = strtomp(buf, nil, 16, nil); + free(buf); + if(m == nil){ + werrstr("bad bignum"); + return -1; + } + + agentlog("ssh use"); + m = rsadecrypt(s->priv, m, m); + s->resp = m; + s->phase = Readresp; + return n; +} + +void +sshrsaclose(void *v) +{ + Sshrsastate *s; + + s = v; + rsaprivfree(s->priv); + mpfree(s->resp); + free(s); +} + +Proto sshrsa = { +.name= "ssh-rsa", +.perm= 0666, +.open= sshrsaopen, +.read= sshrsaread, +.write= sshrsawrite, +.close= sshrsaclose, +}; |