shithub: riscv

Download patch

ref: 85216d3d95505c19a57d3bbe74e8a7eca109a8e6
parent: 7bb1a9a18566ea9c8ae7f6c2fa99e448026521d2
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Fri Aug 30 03:34:35 EDT 2019

auth/rsa2asn1: implement private key export with -a flag (thanks kvik)

kvik writes:

I needed to convert the RSA private key that was laying around in
secstore into a format understood by UNIX® tools like SSH.

With asn12rsa(8) we can go from the ASN.1/DER to Plan 9 format, but not
back - so I wrote the libsec function asn1encodeRSApriv(2) and used it in
rsa2asn1(8) by adding the -a flag which causes the full private key to be
encoded and output.

--- a/sys/include/ape/libsec.h
+++ b/sys/include/ape/libsec.h
@@ -380,6 +380,7 @@
 mpint*		pkcs1padbuf(uchar *buf, int len, mpint *modulus, int blocktype);
 int		pkcs1unpadbuf(uchar *buf, int len, mpint *modulus, int blocktype);
 int		asn1encodeRSApub(RSApub *pk, uchar *buf, int len);
+int		asn1encodeRSApriv(RSApriv *k, uchar *buf, int len);
 int		asn1encodedigest(DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*),
 			uchar *digest, uchar *buf, int len);
 
--- a/sys/include/libsec.h
+++ b/sys/include/libsec.h
@@ -372,6 +372,7 @@
 mpint*		pkcs1padbuf(uchar *buf, int len, mpint *modulus, int blocktype);
 int		pkcs1unpadbuf(uchar *buf, int len, mpint *modulus, int blocktype);
 int		asn1encodeRSApub(RSApub *pk, uchar *buf, int len);
+int		asn1encodeRSApriv(RSApriv *k, uchar *buf, int len);
 int		asn1encodedigest(DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*),
 			uchar *digest, uchar *buf, int len);
 
--- a/sys/man/8/rsa
+++ b/sys/man/8/rsa
@@ -28,6 +28,9 @@
 .PP
 .B rsa2asn1
 [
+-a
+]
+[
 .I file
 ]
 .PP
@@ -182,6 +185,9 @@
 is like
 .I rsa2pub
 but outputs the public key in ASN.1/DER format.
+With the
+.I -a
+flag a private key is read and encoded in ANS.1/DER format.
 .PP
 .I Rsa2ssh
 reads a Plan 9 RSA public or private key and prints the public portion 
--- a/sys/src/cmd/auth/rsa2asn1.c
+++ b/sys/src/cmd/auth/rsa2asn1.c
@@ -5,10 +5,12 @@
 #include <libsec.h>
 #include "rsa2any.h"
 
+int privatekey = 0;
+
 void
 usage(void)
 {
-	fprint(2, "usage: auth/rsa2asn1 [file]\n");
+	fprint(2, "usage: auth/rsa2asn1 [-a] [file]\n");
 	exits("usage");
 }
 
@@ -20,6 +22,9 @@
 	int n;
 
 	ARGBEGIN{
+	case 'a':
+		privatekey = 1;
+		break;
 	default:
 		usage();
 	}ARGEND
@@ -27,10 +32,15 @@
 	if(argc > 1)
 		usage();
 
-	if((k = getrsakey(argc, argv, 0, nil)) == nil)
+	if((k = getrsakey(argc, argv, privatekey, nil)) == nil)
 		sysfatal("%r");
-	if((n = asn1encodeRSApub(&k->pub, buf, sizeof(buf))) < 0)
-		sysfatal("asn1encodeRSApub: %r");
+	if(privatekey){
+		if((n = asn1encodeRSApriv(k, buf, sizeof(buf))) < 0)
+			sysfatal("asn1encodeRSApriv: %r");
+	}else{
+		if((n = asn1encodeRSApub(&k->pub, buf, sizeof(buf))) < 0)
+			sysfatal("asn1encodeRSApub: %r");
+	}
 	if(write(1, buf, n) != n)
 		sysfatal("write: %r");
 	exits(nil);
--- a/sys/src/libsec/port/x509.c
+++ b/sys/src/libsec/port/x509.c
@@ -2689,10 +2689,48 @@
 	return b;
 }
 
+static Bytes*
+encode_rsaprivkey(RSApriv *k)
+{
+	Bytes *b = nil;
+	RSApub *pk = &k->pub;
+	Elem e = mkseq(
+		mkel(mkint(0),
+		mkel(mkbigint(pk->n),
+		mkel(mpsignif(pk->ek)<32 ? mkint(mptoi(pk->ek)) : mkbigint(pk->ek),
+		mkel(mkbigint(k->dk),
+		mkel(mkbigint(k->p),
+		mkel(mkbigint(k->q),
+		mkel(mkbigint(k->kp),
+		mkel(mkbigint(k->kq),
+		mkel(mkbigint(k->c2),
+		nil))))))))));
+	encode(e, &b);
+	freevalfields(&e.val);
+	return b;
+}
+
 int
 asn1encodeRSApub(RSApub *pk, uchar *buf, int len)
 {
 	Bytes *b = encode_rsapubkey(pk);
+	if(b == nil)
+		return -1;
+	if(b->len > len){
+		freebytes(b);
+		werrstr("buffer too small");
+		return -1;
+	}
+	memmove(buf, b->data, len = b->len);
+	freebytes(b);
+	return len;
+}
+
+int
+asn1encodeRSApriv(RSApriv *k, uchar *buf, int len)
+{
+	Bytes *b;
+	b = encode_rsaprivkey(k);
 	if(b == nil)
 		return -1;
 	if(b->len > len){