diff options
author | Jacob Moody <moody@posixcafe.org> | 2023-04-19 14:57:14 +0000 |
---|---|---|
committer | Jacob Moody <moody@posixcafe.org> | 2023-04-19 14:57:14 +0000 |
commit | 6118f598e0caff4cba0d5838afa98631b1acf0e1 (patch) | |
tree | 987bd6f3d31b662306e080a42c346e1af1240c99 /sys/src/cmd/auth | |
parent | 56970a285fcc90b4c0418b0653ff7fcae377d7c7 (diff) |
auth/ssh2rsa: convert Unix ssh private keys to Plan 9 format.
Diffstat (limited to 'sys/src/cmd/auth')
-rw-r--r-- | sys/src/cmd/auth/mkfile | 1 | ||||
-rw-r--r-- | sys/src/cmd/auth/ssh2rsa.c | 199 |
2 files changed, 200 insertions, 0 deletions
diff --git a/sys/src/cmd/auth/mkfile b/sys/src/cmd/auth/mkfile index 1dbc46941..25c4fe2d3 100644 --- a/sys/src/cmd/auth/mkfile +++ b/sys/src/cmd/auth/mkfile @@ -34,6 +34,7 @@ TARG=\ rsa2x509\ rsafill\ rsagen\ + ssh2rsa\ uniq\ userpasswd\ warning\ diff --git a/sys/src/cmd/auth/ssh2rsa.c b/sys/src/cmd/auth/ssh2rsa.c new file mode 100644 index 000000000..1dbee57c9 --- /dev/null +++ b/sys/src/cmd/auth/ssh2rsa.c @@ -0,0 +1,199 @@ +#include <u.h> +#include <libc.h> +#include <auth.h> +#include <mp.h> +#include <libsec.h> + +#define GET4(p) (u32int)(p)[3] | (u32int)(p)[2]<<8 | (u32int)(p)[1]<<16 | (u32int)(p)[0]<<24 + +static char *magic = "openssh-key-v1"; + +static uchar *pubkey; +static uchar *pubend; + +static uchar *privkey; +static uchar *privend; + +static void* +emalloc(ulong size, int clr) +{ + void *p; + if((p = mallocz(size, clr)) == nil) + sysfatal("emalloc: %r"); + return p; +} + +static long +ereadn(int fd, void *buf, long nbytes) +{ + long n; + if((n = readn(fd, buf, nbytes)) != nbytes) + sysfatal("ereadn: %r"); + return n; +} + +static uchar* +slurp(int fd, int alloc, u32int *np) +{ + u32int n; + uchar buf[4], trash[1024]; + uchar *p; + + ereadn(fd, buf, sizeof buf); + n = GET4(buf); + if(alloc){ + *np = n; + p = emalloc(n, 0); + ereadn(fd, p, n); + return p; + } + if(n >= sizeof trash) + sysfatal("key component too large"); + ereadn(fd, trash, n); + return nil; +} + +static u32int +decode(int fd) +{ + uchar buf[4]; + u32int ret, n; + + /* ciphername */ + slurp(fd, 0, nil); + /* kdfname */ + slurp(fd, 0, nil); + /* kdfoptions */ + slurp(fd, 0, nil); + + ereadn(fd, buf, 4); + ret = GET4(buf); + + pubkey = slurp(fd, 1, &n); + pubend = pubkey + n; + + privkey = slurp(fd, 1, &n); + privend = privkey + n; + + return ret; +} + +static u32int +scan(uchar **p, uchar *e) +{ + u32int n; + + if(*p + 4 > e) + sysfatal("unexpected end of key"); + n = GET4(*p); *p += 4; + if(*p + n > e) + sysfatal("unexpected end of key"); + return n; +} + +static mpint* +scanmp(uchar **p, uchar *e) +{ + mpint *m; + u32int n; + + n = scan(p, e); + if(n == 0) + sysfatal("required key component has zero length"); + m = betomp(*p, n, nil); + if(m == nil) + sysfatal("betomp: %r"); + *p += n; + return m; +} + +static RSApriv* +fill(void) +{ + char *rsa = "ssh-rsa"; + u32int n, a, b; + uchar *p, *e; + mpint *ek, *mod, *dk, *p0, *q0; + + p = pubkey; + e = pubend; + if(scan(&p, e) != 7 || memcmp(rsa, p, 7) != 0) + sysfatal("not a RSA key"); + p += 7; + + ek = scanmp(&p, e); + mod = scanmp(&p, e); + + p = privkey; + e = privend; + if(p + 8 >= e) + sysfatal("unexpected end of key"); + a = GET4(p); p += 4; + b = GET4(p); p += 4; + if(a != b) + sysfatal("private key seems encrypted"); + + if(scan(&p, e) != 7 || memcmp(rsa, p, 7) != 0) + sysfatal("not a RSA key"); + p += 7; + + /* public components are repeated */ + n = scan(&p, e); p += n; + n = scan(&p, e); p += n; + dk = scanmp(&p, e); + /* iq */ + n = scan(&p, e); p += n; + p0 = scanmp(&p, e); + q0 = scanmp(&p, e); + + return rsafill(mod, ek, dk, p0, q0); +} + +void +usage(void) +{ + fprint(2, "usage: auth/ssh2rsa [file]\n"); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + int fd; + RSApriv *p; + uchar buf[64]; + + fd = 0; + fmtinstall('B', mpfmt); + ARGBEGIN{ + default: + usage(); + }ARGEND + switch(argc){ + default: + usage(); + case 1: + fd = open(argv[0], OREAD); + if(fd < 0) + sysfatal("open: %r"); + case 0: + break; + } + + ereadn(fd, buf, strlen(magic)+1); + if(memcmp(buf, magic, strlen(magic)+1) != 0) + sysfatal("bad magic"); + + if(decode(fd) != 1) + sysfatal("invalid key"); + if((p = fill()) == nil) + sysfatal("fill: %r"); + + print("%s size=%d ek=%B !dk=%B n=%B !p=%B !q=%B !kp=%B !kq=%B !c2=%B\n", + "key service=ssh proto=rsa", + mpsignif(p->pub.n), p->pub.ek, + p->dk, p->pub.n, p->p, p->q, + p->kp, p->kq, p->c2); + + exits(nil); +} |