version 1.334, 2019/07/05 04:55:40 |
version 1.337, 2019/07/16 13:18:39 |
|
|
/* Load key from this PKCS#11 provider */ |
/* Load key from this PKCS#11 provider */ |
static char *pkcs11provider = NULL; |
static char *pkcs11provider = NULL; |
|
|
/* Use new OpenSSH private key format when writing SSH2 keys instead of PEM */ |
/* Format for writing private keys */ |
static int use_new_format = 1; |
static int private_key_format = SSHKEY_PRIVATE_OPENSSH; |
|
|
/* Cipher for new-format private keys */ |
/* Cipher for new-format private keys */ |
static char *new_format_cipher = NULL; |
static char *openssh_format_cipher = NULL; |
|
|
/* |
/* |
* Number of KDF rounds to derive new format keys / |
* Number of KDF rounds to derive new format keys / |
|
|
static void |
static void |
do_convert_to_ssh2(struct passwd *pw, struct sshkey *k) |
do_convert_to_ssh2(struct passwd *pw, struct sshkey *k) |
{ |
{ |
size_t len; |
struct sshbuf *b; |
u_char *blob; |
char comment[61], *b64; |
char comment[61]; |
|
int r; |
int r; |
|
|
if ((r = sshkey_to_blob(k, &blob, &len)) != 0) |
if ((b = sshbuf_new()) == NULL) |
|
fatal("%s: sshbuf_new failed", __func__); |
|
if ((r = sshkey_putb(k, b)) != 0) |
fatal("key_to_blob failed: %s", ssh_err(r)); |
fatal("key_to_blob failed: %s", ssh_err(r)); |
|
if ((b64 = sshbuf_dtob64_string(b, 1)) == NULL) |
|
fatal("%s: sshbuf_dtob64_string failed", __func__); |
|
|
/* Comment + surrounds must fit into 72 chars (RFC 4716 sec 3.3) */ |
/* Comment + surrounds must fit into 72 chars (RFC 4716 sec 3.3) */ |
snprintf(comment, sizeof(comment), |
snprintf(comment, sizeof(comment), |
"%u-bit %s, converted by %s@%s from OpenSSH", |
"%u-bit %s, converted by %s@%s from OpenSSH", |
sshkey_size(k), sshkey_type(k), |
sshkey_size(k), sshkey_type(k), |
pw->pw_name, hostname); |
pw->pw_name, hostname); |
|
|
|
sshkey_free(k); |
|
sshbuf_free(b); |
|
|
fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN); |
fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN); |
fprintf(stdout, "Comment: \"%s\"\n", comment); |
fprintf(stdout, "Comment: \"%s\"\n%s", comment, b64); |
dump_base64(stdout, blob, len); |
|
fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END); |
fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END); |
sshkey_free(k); |
free(b64); |
free(blob); |
|
exit(0); |
exit(0); |
} |
} |
|
|
|
|
} |
} |
|
|
static struct sshkey * |
static struct sshkey * |
do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) |
do_convert_private_ssh2(struct sshbuf *b) |
{ |
{ |
struct sshbuf *b; |
|
struct sshkey *key = NULL; |
struct sshkey *key = NULL; |
char *type, *cipher; |
char *type, *cipher; |
u_char e1, e2, e3, *sig = NULL, data[] = "abcde12345"; |
u_char e1, e2, e3, *sig = NULL, data[] = "abcde12345"; |
|
|
BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL; |
BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL; |
BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL; |
BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL; |
BIGNUM *rsa_p = NULL, *rsa_q = NULL, *rsa_iqmp = NULL; |
BIGNUM *rsa_p = NULL, *rsa_q = NULL, *rsa_iqmp = NULL; |
if ((b = sshbuf_from(blob, blen)) == NULL) |
|
fatal("%s: sshbuf_from failed", __func__); |
|
if ((r = sshbuf_get_u32(b, &magic)) != 0) |
if ((r = sshbuf_get_u32(b, &magic)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
|
|
if (magic != SSH_COM_PRIVATE_KEY_MAGIC) { |
if (magic != SSH_COM_PRIVATE_KEY_MAGIC) { |
error("bad magic 0x%x != 0x%x", magic, |
error("bad magic 0x%x != 0x%x", magic, |
SSH_COM_PRIVATE_KEY_MAGIC); |
SSH_COM_PRIVATE_KEY_MAGIC); |
sshbuf_free(b); |
|
return NULL; |
return NULL; |
} |
} |
if ((r = sshbuf_get_u32(b, &i1)) != 0 || |
if ((r = sshbuf_get_u32(b, &i1)) != 0 || |
|
|
if (strcmp(cipher, "none") != 0) { |
if (strcmp(cipher, "none") != 0) { |
error("unsupported cipher %s", cipher); |
error("unsupported cipher %s", cipher); |
free(cipher); |
free(cipher); |
sshbuf_free(b); |
|
free(type); |
free(type); |
return NULL; |
return NULL; |
} |
} |
|
|
} else if (strstr(type, "rsa")) { |
} else if (strstr(type, "rsa")) { |
ktype = KEY_RSA; |
ktype = KEY_RSA; |
} else { |
} else { |
sshbuf_free(b); |
|
free(type); |
free(type); |
return NULL; |
return NULL; |
} |
} |
|
|
fatal("%s: BN_new", __func__); |
fatal("%s: BN_new", __func__); |
if (!BN_set_word(rsa_e, e)) { |
if (!BN_set_word(rsa_e, e)) { |
BN_clear_free(rsa_e); |
BN_clear_free(rsa_e); |
sshbuf_free(b); |
|
sshkey_free(key); |
sshkey_free(key); |
return NULL; |
return NULL; |
} |
} |
|
|
} |
} |
rlen = sshbuf_len(b); |
rlen = sshbuf_len(b); |
if (rlen != 0) |
if (rlen != 0) |
error("do_convert_private_ssh2_from_blob: " |
error("%s: remaining bytes in key blob %d", __func__, rlen); |
"remaining bytes in key blob %d", rlen); |
|
sshbuf_free(b); |
|
|
|
/* try the key */ |
/* try the key */ |
if (sshkey_sign(key, &sig, &slen, data, sizeof(data), NULL, 0) != 0 || |
if (sshkey_sign(key, &sig, &slen, data, sizeof(data), NULL, 0) != 0 || |
|
|
int r, blen, escaped = 0; |
int r, blen, escaped = 0; |
u_int len; |
u_int len; |
char line[1024]; |
char line[1024]; |
u_char blob[8096]; |
struct sshbuf *buf; |
char encoded[8096]; |
char encoded[8096]; |
FILE *fp; |
FILE *fp; |
|
|
|
if ((buf = sshbuf_new()) == NULL) |
|
fatal("sshbuf_new failed"); |
if ((fp = fopen(identity_file, "r")) == NULL) |
if ((fp = fopen(identity_file, "r")) == NULL) |
fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); |
fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); |
encoded[0] = '\0'; |
encoded[0] = '\0'; |
|
|
(encoded[len-2] == '=') && |
(encoded[len-2] == '=') && |
(encoded[len-3] == '=')) |
(encoded[len-3] == '=')) |
encoded[len-3] = '\0'; |
encoded[len-3] = '\0'; |
blen = uudecode(encoded, blob, sizeof(blob)); |
if ((r = sshbuf_b64tod(buf, encoded)) != 0) |
if (blen < 0) |
fatal("%s: base64 decoding failed: %s", __func__, ssh_err(r)); |
fatal("uudecode failed."); |
|
if (*private) |
if (*private) |
*k = do_convert_private_ssh2_from_blob(blob, blen); |
*k = do_convert_private_ssh2(buf); |
else if ((r = sshkey_from_blob(blob, blen, k)) != 0) |
else if ((r = sshkey_fromb(buf, k)) != 0) |
fatal("decode blob failed: %s", ssh_err(r)); |
fatal("decode blob failed: %s", ssh_err(r)); |
fclose(fp); |
fclose(fp); |
} |
} |
|
|
snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, |
snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, |
hostname); |
hostname); |
if ((r = sshkey_save_private(private, prv_tmp, "", |
if ((r = sshkey_save_private(private, prv_tmp, "", |
comment, use_new_format, new_format_cipher, rounds)) != 0) { |
comment, private_key_format, openssh_format_cipher, |
|
rounds)) != 0) { |
error("Saving key \"%s\" failed: %s", |
error("Saving key \"%s\" failed: %s", |
prv_tmp, ssh_err(r)); |
prv_tmp, ssh_err(r)); |
goto failnext; |
goto failnext; |
|
|
|
|
/* Save the file using the new passphrase. */ |
/* Save the file using the new passphrase. */ |
if ((r = sshkey_save_private(private, identity_file, passphrase1, |
if ((r = sshkey_save_private(private, identity_file, passphrase1, |
comment, use_new_format, new_format_cipher, rounds)) != 0) { |
comment, private_key_format, openssh_format_cipher, rounds)) != 0) { |
error("Saving key \"%s\" failed: %s.", |
error("Saving key \"%s\" failed: %s.", |
identity_file, ssh_err(r)); |
identity_file, ssh_err(r)); |
explicit_bzero(passphrase1, strlen(passphrase1)); |
explicit_bzero(passphrase1, strlen(passphrase1)); |
|
|
} |
} |
|
|
if (private->type != KEY_ED25519 && private->type != KEY_XMSS && |
if (private->type != KEY_ED25519 && private->type != KEY_XMSS && |
!use_new_format) { |
private_key_format != SSHKEY_PRIVATE_OPENSSH) { |
error("Comments are only supported for keys stored in " |
error("Comments are only supported for keys stored in " |
"the new format (-o)."); |
"the new format (-o)."); |
explicit_bzero(passphrase, strlen(passphrase)); |
explicit_bzero(passphrase, strlen(passphrase)); |
|
|
|
|
/* Save the file using the new passphrase. */ |
/* Save the file using the new passphrase. */ |
if ((r = sshkey_save_private(private, identity_file, passphrase, |
if ((r = sshkey_save_private(private, identity_file, passphrase, |
new_comment, use_new_format, new_format_cipher, rounds)) != 0) { |
new_comment, private_key_format, openssh_format_cipher, |
|
rounds)) != 0) { |
error("Saving key \"%s\" failed: %s", |
error("Saving key \"%s\" failed: %s", |
identity_file, ssh_err(r)); |
identity_file, ssh_err(r)); |
explicit_bzero(passphrase, strlen(passphrase)); |
explicit_bzero(passphrase, strlen(passphrase)); |
|
|
} |
} |
if (n > SSHKEY_CERT_MAX_PRINCIPALS) |
if (n > SSHKEY_CERT_MAX_PRINCIPALS) |
fatal("Too many certificate principals specified"); |
fatal("Too many certificate principals specified"); |
|
|
tmp = tilde_expand_filename(argv[i], pw->pw_uid); |
tmp = tilde_expand_filename(argv[i], pw->pw_uid); |
if ((r = sshkey_load_public(tmp, &public, &comment)) != 0) |
if ((r = sshkey_load_public(tmp, &public, &comment)) != 0) |
fatal("%s: unable to open \"%s\": %s", |
fatal("%s: unable to open \"%s\": %s", |
|
|
} |
} |
if (strcasecmp(optarg, "PKCS8") == 0) { |
if (strcasecmp(optarg, "PKCS8") == 0) { |
convert_format = FMT_PKCS8; |
convert_format = FMT_PKCS8; |
|
private_key_format = SSHKEY_PRIVATE_PKCS8; |
break; |
break; |
} |
} |
if (strcasecmp(optarg, "PEM") == 0) { |
if (strcasecmp(optarg, "PEM") == 0) { |
convert_format = FMT_PEM; |
convert_format = FMT_PEM; |
use_new_format = 0; |
private_key_format = SSHKEY_PRIVATE_PEM; |
break; |
break; |
} |
} |
fatal("Unsupported conversion format \"%s\"", optarg); |
fatal("Unsupported conversion format \"%s\"", optarg); |
|
|
add_cert_option(optarg); |
add_cert_option(optarg); |
break; |
break; |
case 'Z': |
case 'Z': |
new_format_cipher = optarg; |
openssh_format_cipher = optarg; |
break; |
break; |
case 'C': |
case 'C': |
identity_comment = optarg; |
identity_comment = optarg; |
|
|
|
|
/* Save the key with the given passphrase and comment. */ |
/* Save the key with the given passphrase and comment. */ |
if ((r = sshkey_save_private(private, identity_file, passphrase1, |
if ((r = sshkey_save_private(private, identity_file, passphrase1, |
comment, use_new_format, new_format_cipher, rounds)) != 0) { |
comment, private_key_format, openssh_format_cipher, rounds)) != 0) { |
error("Saving key \"%s\" failed: %s", |
error("Saving key \"%s\" failed: %s", |
identity_file, ssh_err(r)); |
identity_file, ssh_err(r)); |
explicit_bzero(passphrase1, strlen(passphrase1)); |
explicit_bzero(passphrase1, strlen(passphrase1)); |