aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/factotum/ssh.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/factotum/ssh.c')
-rw-r--r--src/cmd/factotum/ssh.c135
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,
+};