Add SSH export for RSA public key
This commit is contained in:
+1
-1
@@ -51,7 +51,7 @@ option "pin-retries" - "Number of retries before the pin code is blocked" int op
|
|||||||
option "puk-retries" - "Number of retries before the puk code is blocked" int optional dependon="pin-retries"
|
option "puk-retries" - "Number of retries before the puk code is blocked" int optional dependon="pin-retries"
|
||||||
option "input" i "Filename to use as input, - for stdin" string optional default="-"
|
option "input" i "Filename to use as input, - for stdin" string optional default="-"
|
||||||
option "output" o "Filename to use as output, - for stdout" string optional default="-"
|
option "output" o "Filename to use as output, - for stdout" string optional default="-"
|
||||||
option "key-format" K "Format of the key being read/written" values="PEM","PKCS12","GZIP","DER" enum optional default="PEM"
|
option "key-format" K "Format of the key being read/written" values="PEM","PKCS12","GZIP","DER","SSH" enum optional default="PEM"
|
||||||
option "password" p "Password for decryption of private key file" string optional
|
option "password" p "Password for decryption of private key file" string optional
|
||||||
option "subject" S "The subject to use for certificate request" string optional
|
option "subject" S "The subject to use for certificate request" string optional
|
||||||
text "
|
text "
|
||||||
|
|||||||
+70
@@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
|
#include <openssl/rsa.h>
|
||||||
|
|
||||||
#include <ykpiv.h>
|
#include <ykpiv.h>
|
||||||
|
|
||||||
@@ -611,3 +612,72 @@ unsigned char get_touch_policy(enum enum_touch_policy policy) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SSH_write_X509(FILE *fp, X509 *x) {
|
||||||
|
|
||||||
|
EVP_PKEY *pkey = NULL;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
pkey = X509_get_pubkey(x);
|
||||||
|
|
||||||
|
if (pkey == NULL) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (pkey->type) {
|
||||||
|
case EVP_PKEY_RSA:
|
||||||
|
case EVP_PKEY_RSA2: {
|
||||||
|
RSA *rsa;
|
||||||
|
unsigned char n[256];
|
||||||
|
|
||||||
|
char rsa_id[] = "\x00\x00\x00\x07ssh-rsa";
|
||||||
|
char rsa_f4[] = "\x00\x00\x00\x03\x01\x00\x01";
|
||||||
|
|
||||||
|
rsa = EVP_PKEY_get1_RSA(pkey);
|
||||||
|
|
||||||
|
set_component(n, rsa->n, RSA_size(rsa));
|
||||||
|
|
||||||
|
uint32_t bytes = BN_num_bytes(rsa->n);
|
||||||
|
char len_buf[5];
|
||||||
|
int len = 4;
|
||||||
|
|
||||||
|
len_buf[0] = (bytes >> 24) & 0x000000ff;
|
||||||
|
len_buf[1] = (bytes << 16) & 0x000000ff;
|
||||||
|
len_buf[2] = (bytes >> 8) & 0x000000ff;
|
||||||
|
len_buf[3] = (bytes) & 0x000000ff;
|
||||||
|
|
||||||
|
if (n[0] >= 0x80) {
|
||||||
|
// High bit set, need an extra byte
|
||||||
|
len++;
|
||||||
|
len_buf[3]++;
|
||||||
|
len_buf[4] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fp, "ssh-rsa ");
|
||||||
|
|
||||||
|
BIO *b64 = BIO_new(BIO_f_base64());
|
||||||
|
BIO *bio = BIO_new_fp(fp, BIO_NOCLOSE);
|
||||||
|
|
||||||
|
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
|
||||||
|
BIO_push(b64, bio);
|
||||||
|
|
||||||
|
BIO_write(b64, rsa_id, sizeof(rsa_id) - 1);
|
||||||
|
BIO_write(b64, rsa_f4, sizeof(rsa_f4) - 1);
|
||||||
|
BIO_write(b64, len_buf, len);
|
||||||
|
BIO_write(b64, n, RSA_size(rsa));
|
||||||
|
BIO_flush(b64);
|
||||||
|
BIO_free_all(b64);
|
||||||
|
|
||||||
|
ret = 1;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case EVP_PKEY_EC:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -58,5 +58,6 @@ int get_hashnid(enum enum_hash, unsigned char);
|
|||||||
unsigned char get_piv_algorithm(enum enum_algorithm);
|
unsigned char get_piv_algorithm(enum enum_algorithm);
|
||||||
unsigned char get_pin_policy(enum enum_pin_policy);
|
unsigned char get_pin_policy(enum enum_pin_policy);
|
||||||
unsigned char get_touch_policy(enum enum_touch_policy);
|
unsigned char get_touch_policy(enum enum_touch_policy);
|
||||||
|
int SSH_write_X509(FILE *fp, X509 *x);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+18
-5
@@ -1058,8 +1058,10 @@ static bool read_certificate(ykpiv_state *state, enum enum_slot slot,
|
|||||||
bool ret = false;
|
bool ret = false;
|
||||||
X509 *x509 = NULL;
|
X509 *x509 = NULL;
|
||||||
|
|
||||||
if(key_format != key_format_arg_PEM && key_format != key_format_arg_DER) {
|
if(key_format != key_format_arg_PEM &&
|
||||||
fprintf(stderr, "Only PEM and DER format are supported for read-certificate.\n");
|
key_format != key_format_arg_DER &&
|
||||||
|
key_format != key_format_arg_SSH) {
|
||||||
|
fprintf(stderr, "Only PEM, DER and SSH format are supported for read-certificate.\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1075,7 +1077,8 @@ static bool read_certificate(ykpiv_state *state, enum enum_slot slot,
|
|||||||
|
|
||||||
if(*ptr++ == 0x70) {
|
if(*ptr++ == 0x70) {
|
||||||
ptr += get_length(ptr, &cert_len);
|
ptr += get_length(ptr, &cert_len);
|
||||||
if(key_format == key_format_arg_PEM) {
|
if(key_format == key_format_arg_PEM ||
|
||||||
|
key_format == key_format_arg_SSH) {
|
||||||
x509 = X509_new();
|
x509 = X509_new();
|
||||||
if(!x509) {
|
if(!x509) {
|
||||||
fprintf(stderr, "Failed allocating x509 structure.\n");
|
fprintf(stderr, "Failed allocating x509 structure.\n");
|
||||||
@@ -1086,8 +1089,18 @@ static bool read_certificate(ykpiv_state *state, enum enum_slot slot,
|
|||||||
fprintf(stderr, "Failed parsing x509 information.\n");
|
fprintf(stderr, "Failed parsing x509 information.\n");
|
||||||
goto read_cert_out;
|
goto read_cert_out;
|
||||||
}
|
}
|
||||||
PEM_write_X509(output_file, x509);
|
|
||||||
ret = true;
|
if (key_format == key_format_arg_PEM) {
|
||||||
|
PEM_write_X509(output_file, x509);
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!SSH_write_X509(output_file, x509)) {
|
||||||
|
fprintf(stderr, "Unable to extract public key or not an RSA key.\n");
|
||||||
|
goto read_cert_out;
|
||||||
|
}
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
} else { /* key_format_arg_DER */
|
} else { /* key_format_arg_DER */
|
||||||
/* XXX: This will just dump the raw data in tag 0x70.. */
|
/* XXX: This will just dump the raw data in tag 0x70.. */
|
||||||
fwrite(ptr, (size_t)cert_len, 1, output_file);
|
fwrite(ptr, (size_t)cert_len, 1, output_file);
|
||||||
|
|||||||
Reference in New Issue
Block a user