summaryrefslogtreecommitdiffstats
path: root/crypto/openssh/key.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/openssh/key.c')
-rw-r--r--crypto/openssh/key.c510
1 files changed, 444 insertions, 66 deletions
diff --git a/crypto/openssh/key.c b/crypto/openssh/key.c
index 55ee789..9142338 100644
--- a/crypto/openssh/key.c
+++ b/crypto/openssh/key.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: key.c,v 1.104 2013/05/19 02:42:42 djm Exp $ */
+/* $OpenBSD: key.c,v 1.115 2014/01/09 23:20:00 djm Exp $ */
/*
* read_bignum():
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -39,6 +39,8 @@
#include <sys/param.h>
#include <sys/types.h>
+#include "crypto_api.h"
+
#include <openssl/evp.h>
#include <openbsd-compat/openssl-compat.h>
@@ -54,8 +56,10 @@
#include "log.h"
#include "misc.h"
#include "ssh2.h"
+#include "digest.h"
static int to_blob(const Key *, u_char **, u_int *, int);
+static Key *key_from_blob2(const u_char *, u_int, int);
static struct KeyCert *
cert_new(void)
@@ -85,6 +89,8 @@ key_new(int type)
k->dsa = NULL;
k->rsa = NULL;
k->cert = NULL;
+ k->ed25519_sk = NULL;
+ k->ed25519_pk = NULL;
switch (k->type) {
case KEY_RSA1:
case KEY_RSA:
@@ -119,6 +125,10 @@ key_new(int type)
/* Cannot do anything until we know the group */
break;
#endif
+ case KEY_ED25519:
+ case KEY_ED25519_CERT:
+ /* no need to prealloc */
+ break;
case KEY_UNSPEC:
break;
default:
@@ -163,6 +173,10 @@ key_add_private(Key *k)
case KEY_ECDSA_CERT:
/* Cannot do anything until we know the group */
break;
+ case KEY_ED25519:
+ case KEY_ED25519_CERT:
+ /* no need to prealloc */
+ break;
case KEY_UNSPEC:
break;
default:
@@ -225,6 +239,19 @@ key_free(Key *k)
k->ecdsa = NULL;
break;
#endif
+ case KEY_ED25519:
+ case KEY_ED25519_CERT:
+ if (k->ed25519_pk) {
+ memset(k->ed25519_pk, 0, ED25519_PK_SZ);
+ free(k->ed25519_pk);
+ k->ed25519_pk = NULL;
+ }
+ if (k->ed25519_sk) {
+ memset(k->ed25519_sk, 0, ED25519_SK_SZ);
+ free(k->ed25519_sk);
+ k->ed25519_sk = NULL;
+ }
+ break;
case KEY_UNSPEC:
break;
default:
@@ -306,6 +333,10 @@ key_equal_public(const Key *a, const Key *b)
BN_CTX_free(bnctx);
return 1;
#endif /* OPENSSL_HAS_ECC */
+ case KEY_ED25519:
+ case KEY_ED25519_CERT:
+ return a->ed25519_pk != NULL && b->ed25519_pk != NULL &&
+ memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0;
default:
fatal("key_equal: bad key type %d", a->type);
}
@@ -328,30 +359,26 @@ u_char*
key_fingerprint_raw(const Key *k, enum fp_type dgst_type,
u_int *dgst_raw_length)
{
- const EVP_MD *md = NULL;
- EVP_MD_CTX ctx;
u_char *blob = NULL;
u_char *retval = NULL;
u_int len = 0;
- int nlen, elen;
+ int nlen, elen, hash_alg = -1;
*dgst_raw_length = 0;
+ /* XXX switch to DIGEST_* directly? */
switch (dgst_type) {
case SSH_FP_MD5:
- md = EVP_md5();
+ hash_alg = SSH_DIGEST_MD5;
break;
case SSH_FP_SHA1:
- md = EVP_sha1();
+ hash_alg = SSH_DIGEST_SHA1;
break;
-#ifdef HAVE_EVP_SHA256
case SSH_FP_SHA256:
- md = EVP_sha256();
+ hash_alg = SSH_DIGEST_SHA256;
break;
-#endif
default:
- fatal("key_fingerprint_raw: bad digest type %d",
- dgst_type);
+ fatal("%s: bad digest type %d", __func__, dgst_type);
}
switch (k->type) {
case KEY_RSA1:
@@ -365,6 +392,7 @@ key_fingerprint_raw(const Key *k, enum fp_type dgst_type,
case KEY_DSA:
case KEY_ECDSA:
case KEY_RSA:
+ case KEY_ED25519:
key_to_blob(k, &blob, &len);
break;
case KEY_DSA_CERT_V00:
@@ -372,24 +400,26 @@ key_fingerprint_raw(const Key *k, enum fp_type dgst_type,
case KEY_DSA_CERT:
case KEY_ECDSA_CERT:
case KEY_RSA_CERT:
+ case KEY_ED25519_CERT:
/* We want a fingerprint of the _key_ not of the cert */
to_blob(k, &blob, &len, 1);
break;
case KEY_UNSPEC:
return retval;
default:
- fatal("key_fingerprint_raw: bad key type %d", k->type);
+ fatal("%s: bad key type %d", __func__, k->type);
break;
}
if (blob != NULL) {
- retval = xmalloc(EVP_MAX_MD_SIZE);
- EVP_DigestInit(&ctx, md);
- EVP_DigestUpdate(&ctx, blob, len);
- EVP_DigestFinal(&ctx, retval, dgst_raw_length);
+ retval = xmalloc(SSH_DIGEST_MAX_LENGTH);
+ if ((ssh_digest_memory(hash_alg, blob, len,
+ retval, SSH_DIGEST_MAX_LENGTH)) != 0)
+ fatal("%s: digest_memory failed", __func__);
memset(blob, 0, len);
free(blob);
+ *dgst_raw_length = ssh_digest_bytes(hash_alg);
} else {
- fatal("key_fingerprint_raw: blob is null");
+ fatal("%s: blob is null", __func__);
}
return retval;
}
@@ -698,11 +728,13 @@ key_read(Key *ret, char **cpp)
case KEY_RSA:
case KEY_DSA:
case KEY_ECDSA:
+ case KEY_ED25519:
case KEY_DSA_CERT_V00:
case KEY_RSA_CERT_V00:
case KEY_DSA_CERT:
case KEY_ECDSA_CERT:
case KEY_RSA_CERT:
+ case KEY_ED25519_CERT:
space = strchr(cp, ' ');
if (space == NULL) {
debug3("key_read: missing whitespace");
@@ -804,6 +836,14 @@ key_read(Key *ret, char **cpp)
#endif
}
#endif
+ if (key_type_plain(ret->type) == KEY_ED25519) {
+ free(ret->ed25519_pk);
+ ret->ed25519_pk = k->ed25519_pk;
+ k->ed25519_pk = NULL;
+#ifdef DEBUG_PK
+ /* XXX */
+#endif
+ }
success = 1;
/*XXXX*/
key_free(k);
@@ -867,6 +907,11 @@ key_write(const Key *key, FILE *f)
return 0;
break;
#endif
+ case KEY_ED25519:
+ case KEY_ED25519_CERT:
+ if (key->ed25519_pk == NULL)
+ return 0;
+ break;
case KEY_RSA:
case KEY_RSA_CERT_V00:
case KEY_RSA_CERT:
@@ -914,10 +959,13 @@ static const struct keytype keytypes[] = {
{ NULL, "RSA1", KEY_RSA1, 0, 0 },
{ "ssh-rsa", "RSA", KEY_RSA, 0, 0 },
{ "ssh-dss", "DSA", KEY_DSA, 0, 0 },
+ { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0 },
#ifdef OPENSSL_HAS_ECC
{ "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0 },
{ "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0 },
+# ifdef OPENSSL_HAS_NISTP521
{ "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0 },
+# endif
#endif /* OPENSSL_HAS_ECC */
{ "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1 },
{ "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1 },
@@ -926,13 +974,17 @@ static const struct keytype keytypes[] = {
KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1 },
{ "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT",
KEY_ECDSA_CERT, NID_secp384r1, 1 },
+# ifdef OPENSSL_HAS_NISTP521
{ "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT",
KEY_ECDSA_CERT, NID_secp521r1, 1 },
+# endif
#endif /* OPENSSL_HAS_ECC */
{ "ssh-rsa-cert-v00@openssh.com", "RSA-CERT-V00",
KEY_RSA_CERT_V00, 0, 1 },
{ "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00",
KEY_DSA_CERT_V00, 0, 1 },
+ { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT",
+ KEY_ED25519_CERT, 0, 1 },
{ NULL, NULL, -1, -1, 0 }
};
@@ -1004,7 +1056,7 @@ key_ecdsa_nid_from_name(const char *name)
}
char *
-key_alg_list(void)
+key_alg_list(int certs_only, int plain_only)
{
char *ret = NULL;
size_t nlen, rlen = 0;
@@ -1013,6 +1065,8 @@ key_alg_list(void)
for (kt = keytypes; kt->type != -1; kt++) {
if (kt->name == NULL)
continue;
+ if ((certs_only && !kt->cert) || (plain_only && kt->cert))
+ continue;
if (ret != NULL)
ret[rlen++] = '\n';
nlen = strlen(kt->name);
@@ -1023,6 +1077,32 @@ key_alg_list(void)
return ret;
}
+int
+key_type_is_cert(int type)
+{
+ const struct keytype *kt;
+
+ for (kt = keytypes; kt->type != -1; kt++) {
+ if (kt->type == type)
+ return kt->cert;
+ }
+ return 0;
+}
+
+static int
+key_type_is_valid_ca(int type)
+{
+ switch (type) {
+ case KEY_RSA:
+ case KEY_DSA:
+ case KEY_ECDSA:
+ case KEY_ED25519:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
u_int
key_size(const Key *k)
{
@@ -1036,6 +1116,8 @@ key_size(const Key *k)
case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
return BN_num_bits(k->dsa->p);
+ case KEY_ED25519:
+ return 256; /* XXX */
#ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
case KEY_ECDSA_CERT:
@@ -1087,8 +1169,10 @@ key_ecdsa_bits_to_nid(int bits)
return NID_X9_62_prime256v1;
case 384:
return NID_secp384r1;
+# ifdef OPENSSL_HAS_NISTP521
case 521:
return NID_secp521r1;
+# endif
#endif
default:
return -1;
@@ -1103,7 +1187,9 @@ key_ecdsa_key_to_nid(EC_KEY *k)
int nids[] = {
NID_X9_62_prime256v1,
NID_secp384r1,
+# ifdef OPENSSL_HAS_NISTP521
NID_secp521r1,
+# endif
-1
};
int nid;
@@ -1175,6 +1261,11 @@ key_generate(int type, u_int bits)
case KEY_RSA1:
k->rsa = rsa_generate_private_key(bits);
break;
+ case KEY_ED25519:
+ k->ed25519_pk = xmalloc(ED25519_PK_SZ);
+ k->ed25519_sk = xmalloc(ED25519_SK_SZ);
+ crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk);
+ break;
case KEY_RSA_CERT_V00:
case KEY_DSA_CERT_V00:
case KEY_RSA_CERT:
@@ -1268,6 +1359,14 @@ key_from_private(const Key *k)
(BN_copy(n->rsa->e, k->rsa->e) == NULL))
fatal("key_from_private: BN_copy failed");
break;
+ case KEY_ED25519:
+ case KEY_ED25519_CERT:
+ n = key_new(k->type);
+ if (k->ed25519_pk != NULL) {
+ n->ed25519_pk = xmalloc(ED25519_PK_SZ);
+ memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
+ }
+ break;
default:
fatal("key_from_private: unknown type %d", k->type);
break;
@@ -1387,14 +1486,12 @@ cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen)
}
buffer_clear(&tmp);
- if ((key->cert->signature_key = key_from_blob(sig_key,
- sklen)) == NULL) {
+ if ((key->cert->signature_key = key_from_blob2(sig_key, sklen, 0))
+ == NULL) {
error("%s: Signature key invalid", __func__);
goto out;
}
- if (key->cert->signature_key->type != KEY_RSA &&
- key->cert->signature_key->type != KEY_DSA &&
- key->cert->signature_key->type != KEY_ECDSA) {
+ if (!key_type_is_valid_ca(key->cert->signature_key->type)) {
error("%s: Invalid signature key type %s (%d)", __func__,
key_type(key->cert->signature_key),
key->cert->signature_key->type);
@@ -1425,12 +1522,14 @@ cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen)
return ret;
}
-Key *
-key_from_blob(const u_char *blob, u_int blen)
+static Key *
+key_from_blob2(const u_char *blob, u_int blen, int allow_cert)
{
Buffer b;
int rlen, type;
+ u_int len;
char *ktype = NULL, *curve = NULL;
+ u_char *pk = NULL;
Key *key = NULL;
#ifdef OPENSSL_HAS_ECC
EC_POINT *q = NULL;
@@ -1452,7 +1551,10 @@ key_from_blob(const u_char *blob, u_int blen)
if (key_type_plain(type) == KEY_ECDSA)
nid = key_ecdsa_nid_from_name(ktype);
#endif
-
+ if (!allow_cert && key_type_is_cert(type)) {
+ error("key_from_blob: certificate not allowed in this context");
+ goto out;
+ }
switch (type) {
case KEY_RSA_CERT:
(void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
@@ -1526,6 +1628,23 @@ key_from_blob(const u_char *blob, u_int blen)
#endif
break;
#endif /* OPENSSL_HAS_ECC */
+ case KEY_ED25519_CERT:
+ (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
+ /* FALLTHROUGH */
+ case KEY_ED25519:
+ if ((pk = buffer_get_string_ret(&b, &len)) == NULL) {
+ error("key_from_blob: can't read ed25519 key");
+ goto badkey;
+ }
+ if (len != ED25519_PK_SZ) {
+ error("key_from_blob: ed25519 len %d != %d",
+ len, ED25519_PK_SZ);
+ goto badkey;
+ }
+ key = key_new(type);
+ key->ed25519_pk = pk;
+ pk = NULL;
+ break;
case KEY_UNSPEC:
key = key_new(type);
break;
@@ -1543,6 +1662,7 @@ key_from_blob(const u_char *blob, u_int blen)
out:
free(ktype);
free(curve);
+ free(pk);
#ifdef OPENSSL_HAS_ECC
if (q != NULL)
EC_POINT_free(q);
@@ -1551,12 +1671,22 @@ key_from_blob(const u_char *blob, u_int blen)
return key;
}
+Key *
+key_from_blob(const u_char *blob, u_int blen)
+{
+ return key_from_blob2(blob, blen, 1);
+}
+
static int
to_blob(const Key *key, u_char **blobp, u_int *lenp, int force_plain)
{
Buffer b;
int len, type;
+ if (blobp != NULL)
+ *blobp = NULL;
+ if (lenp != NULL)
+ *lenp = 0;
if (key == NULL) {
error("key_to_blob: key == NULL");
return 0;
@@ -1569,6 +1699,7 @@ to_blob(const Key *key, u_char **blobp, u_int *lenp, int force_plain)
case KEY_DSA_CERT:
case KEY_ECDSA_CERT:
case KEY_RSA_CERT:
+ case KEY_ED25519_CERT:
/* Use the existing blob */
buffer_append(&b, buffer_ptr(&key->cert->certblob),
buffer_len(&key->cert->certblob));
@@ -1596,6 +1727,11 @@ to_blob(const Key *key, u_char **blobp, u_int *lenp, int force_plain)
buffer_put_bignum2(&b, key->rsa->e);
buffer_put_bignum2(&b, key->rsa->n);
break;
+ case KEY_ED25519:
+ buffer_put_cstring(&b,
+ key_ssh_name_from_type_nid(type, key->ecdsa_nid));
+ buffer_put_string(&b, key->ed25519_pk, ED25519_PK_SZ);
+ break;
default:
error("key_to_blob: unsupported key type %d", key->type);
buffer_free(&b);
@@ -1639,6 +1775,9 @@ key_sign(
case KEY_RSA_CERT:
case KEY_RSA:
return ssh_rsa_sign(key, sigp, lenp, data, datalen);
+ case KEY_ED25519:
+ case KEY_ED25519_CERT:
+ return ssh_ed25519_sign(key, sigp, lenp, data, datalen);
default:
error("key_sign: invalid key type %d", key->type);
return -1;
@@ -1672,6 +1811,9 @@ key_verify(
case KEY_RSA_CERT:
case KEY_RSA:
return ssh_rsa_verify(key, signature, signaturelen, data, datalen);
+ case KEY_ED25519:
+ case KEY_ED25519_CERT:
+ return ssh_ed25519_verify(key, signature, signaturelen, data, datalen);
default:
error("key_verify: invalid key type %d", key->type);
return -1;
@@ -1691,6 +1833,8 @@ key_demote(const Key *k)
pk->dsa = NULL;
pk->ecdsa = NULL;
pk->rsa = NULL;
+ pk->ed25519_pk = NULL;
+ pk->ed25519_sk = NULL;
switch (k->type) {
case KEY_RSA_CERT_V00:
@@ -1734,8 +1878,17 @@ key_demote(const Key *k)
fatal("key_demote: EC_KEY_set_public_key failed");
break;
#endif
+ case KEY_ED25519_CERT:
+ key_cert_copy(k, pk);
+ /* FALLTHROUGH */
+ case KEY_ED25519:
+ if (k->ed25519_pk != NULL) {
+ pk->ed25519_pk = xmalloc(ED25519_PK_SZ);
+ memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
+ }
+ break;
default:
- fatal("key_free: bad key type %d", k->type);
+ fatal("key_demote: bad key type %d", k->type);
break;
}
@@ -1747,16 +1900,7 @@ key_is_cert(const Key *k)
{
if (k == NULL)
return 0;
- switch (k->type) {
- case KEY_RSA_CERT_V00:
- case KEY_DSA_CERT_V00:
- case KEY_RSA_CERT:
- case KEY_DSA_CERT:
- case KEY_ECDSA_CERT:
- return 1;
- default:
- return 0;
- }
+ return key_type_is_cert(k->type);
}
/* Return the cert-less equivalent to a certified key type */
@@ -1772,12 +1916,14 @@ key_type_plain(int type)
return KEY_DSA;
case KEY_ECDSA_CERT:
return KEY_ECDSA;
+ case KEY_ED25519_CERT:
+ return KEY_ED25519;
default:
return type;
}
}
-/* Convert a KEY_RSA or KEY_DSA to their _CERT equivalent */
+/* Convert a plain key to their _CERT equivalent */
int
key_to_certified(Key *k, int legacy)
{
@@ -1797,41 +1943,34 @@ key_to_certified(Key *k, int legacy)
k->cert = cert_new();
k->type = KEY_ECDSA_CERT;
return 0;
+ case KEY_ED25519:
+ if (legacy)
+ fatal("%s: legacy ED25519 certificates are not "
+ "supported", __func__);
+ k->cert = cert_new();
+ k->type = KEY_ED25519_CERT;
+ return 0;
default:
error("%s: key has incorrect type %s", __func__, key_type(k));
return -1;
}
}
-/* Convert a KEY_RSA_CERT or KEY_DSA_CERT to their raw key equivalent */
+/* Convert a certificate to its raw key equivalent */
int
key_drop_cert(Key *k)
{
- switch (k->type) {
- case KEY_RSA_CERT_V00:
- case KEY_RSA_CERT:
- cert_free(k->cert);
- k->type = KEY_RSA;
- return 0;
- case KEY_DSA_CERT_V00:
- case KEY_DSA_CERT:
- cert_free(k->cert);
- k->type = KEY_DSA;
- return 0;
- case KEY_ECDSA_CERT:
- cert_free(k->cert);
- k->type = KEY_ECDSA;
- return 0;
- default:
+ if (!key_type_is_cert(k->type)) {
error("%s: key has incorrect type %s", __func__, key_type(k));
return -1;
}
+ cert_free(k->cert);
+ k->cert = NULL;
+ k->type = key_type_plain(k->type);
+ return 0;
}
-/*
- * Sign a KEY_RSA_CERT, KEY_DSA_CERT or KEY_ECDSA_CERT, (re-)generating
- * the signed certblob
- */
+/* Sign a certified key, (re-)generating the signed certblob. */
int
key_certify(Key *k, Key *ca)
{
@@ -1850,8 +1989,7 @@ key_certify(Key *k, Key *ca)
return -1;
}
- if (ca->type != KEY_RSA && ca->type != KEY_DSA &&
- ca->type != KEY_ECDSA) {
+ if (!key_type_is_valid_ca(ca->type)) {
error("%s: CA key has unsupported type %s", __func__,
key_type(ca));
return -1;
@@ -1867,6 +2005,7 @@ key_certify(Key *k, Key *ca)
if (!key_cert_is_legacy(k))
buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
+ /* XXX this substantially duplicates to_blob(); refactor */
switch (k->type) {
case KEY_DSA_CERT_V00:
case KEY_DSA_CERT:
@@ -1889,6 +2028,10 @@ key_certify(Key *k, Key *ca)
buffer_put_bignum2(&k->cert->certblob, k->rsa->e);
buffer_put_bignum2(&k->cert->certblob, k->rsa->n);
break;
+ case KEY_ED25519_CERT:
+ buffer_put_string(&k->cert->certblob,
+ k->ed25519_pk, ED25519_PK_SZ);
+ break;
default:
error("%s: key has incorrect type %s", __func__, key_type(k));
buffer_clear(&k->cert->certblob);
@@ -2018,8 +2161,10 @@ key_curve_name_to_nid(const char *name)
return NID_X9_62_prime256v1;
else if (strcmp(name, "nistp384") == 0)
return NID_secp384r1;
+# ifdef OPENSSL_HAS_NISTP521
else if (strcmp(name, "nistp521") == 0)
return NID_secp521r1;
+# endif
#endif
debug("%s: unsupported EC curve name \"%.100s\"", __func__, name);
@@ -2035,8 +2180,10 @@ key_curve_nid_to_bits(int nid)
return 256;
case NID_secp384r1:
return 384;
+# ifdef OPENSSL_HAS_NISTP521
case NID_secp521r1:
return 521;
+# endif
#endif
default:
error("%s: unsupported EC curve nid %d", __func__, nid);
@@ -2052,16 +2199,18 @@ key_curve_nid_to_name(int nid)
return "nistp256";
else if (nid == NID_secp384r1)
return "nistp384";
+# ifdef OPENSSL_HAS_NISTP521
else if (nid == NID_secp521r1)
return "nistp521";
+# endif
#endif
error("%s: unsupported EC curve nid %d", __func__, nid);
return NULL;
}
#ifdef OPENSSL_HAS_ECC
-const EVP_MD *
-key_ec_nid_to_evpmd(int nid)
+int
+key_ec_nid_to_hash_alg(int nid)
{
int kbits = key_curve_nid_to_bits(nid);
@@ -2069,11 +2218,11 @@ key_ec_nid_to_evpmd(int nid)
fatal("%s: invalid nid %d", __func__, nid);
/* RFC5656 section 6.2.1 */
if (kbits <= 256)
- return EVP_sha256();
+ return SSH_DIGEST_SHA256;
else if (kbits <= 384)
- return EVP_sha384();
+ return SSH_DIGEST_SHA384;
else
- return EVP_sha512();
+ return SSH_DIGEST_SHA512;
}
int
@@ -2245,3 +2394,232 @@ key_dump_ec_key(const EC_KEY *key)
}
#endif /* defined(DEBUG_KEXECDH) || defined(DEBUG_PK) */
#endif /* OPENSSL_HAS_ECC */
+
+void
+key_private_serialize(const Key *key, Buffer *b)
+{
+ buffer_put_cstring(b, key_ssh_name(key));
+ switch (key->type) {
+ case KEY_RSA:
+ buffer_put_bignum2(b, key->rsa->n);
+ buffer_put_bignum2(b, key->rsa->e);
+ buffer_put_bignum2(b, key->rsa->d);
+ buffer_put_bignum2(b, key->rsa->iqmp);
+ buffer_put_bignum2(b, key->rsa->p);
+ buffer_put_bignum2(b, key->rsa->q);
+ break;
+ case KEY_RSA_CERT_V00:
+ case KEY_RSA_CERT:
+ if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
+ fatal("%s: no cert/certblob", __func__);
+ buffer_put_string(b, buffer_ptr(&key->cert->certblob),
+ buffer_len(&key->cert->certblob));
+ buffer_put_bignum2(b, key->rsa->d);
+ buffer_put_bignum2(b, key->rsa->iqmp);
+ buffer_put_bignum2(b, key->rsa->p);
+ buffer_put_bignum2(b, key->rsa->q);
+ break;
+ case KEY_DSA:
+ buffer_put_bignum2(b, key->dsa->p);
+ buffer_put_bignum2(b, key->dsa->q);
+ buffer_put_bignum2(b, key->dsa->g);
+ buffer_put_bignum2(b, key->dsa->pub_key);
+ buffer_put_bignum2(b, key->dsa->priv_key);
+ break;
+ case KEY_DSA_CERT_V00:
+ case KEY_DSA_CERT:
+ if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
+ fatal("%s: no cert/certblob", __func__);
+ buffer_put_string(b, buffer_ptr(&key->cert->certblob),
+ buffer_len(&key->cert->certblob));
+ buffer_put_bignum2(b, key->dsa->priv_key);
+ break;
+#ifdef OPENSSL_HAS_ECC
+ case KEY_ECDSA:
+ buffer_put_cstring(b, key_curve_nid_to_name(key->ecdsa_nid));
+ buffer_put_ecpoint(b, EC_KEY_get0_group(key->ecdsa),
+ EC_KEY_get0_public_key(key->ecdsa));
+ buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa));
+ break;
+ case KEY_ECDSA_CERT:
+ if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
+ fatal("%s: no cert/certblob", __func__);
+ buffer_put_string(b, buffer_ptr(&key->cert->certblob),
+ buffer_len(&key->cert->certblob));
+ buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa));
+ break;
+#endif /* OPENSSL_HAS_ECC */
+ case KEY_ED25519:
+ buffer_put_string(b, key->ed25519_pk, ED25519_PK_SZ);
+ buffer_put_string(b, key->ed25519_sk, ED25519_SK_SZ);
+ break;
+ case KEY_ED25519_CERT:
+ if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
+ fatal("%s: no cert/certblob", __func__);
+ buffer_put_string(b, buffer_ptr(&key->cert->certblob),
+ buffer_len(&key->cert->certblob));
+ buffer_put_string(b, key->ed25519_pk, ED25519_PK_SZ);
+ buffer_put_string(b, key->ed25519_sk, ED25519_SK_SZ);
+ break;
+ }
+}
+
+Key *
+key_private_deserialize(Buffer *blob)
+{
+ char *type_name;
+ Key *k = NULL;
+ u_char *cert;
+ u_int len, pklen, sklen;
+ int type;
+#ifdef OPENSSL_HAS_ECC
+ char *curve;
+ BIGNUM *exponent;
+ EC_POINT *q;
+#endif
+
+ type_name = buffer_get_string(blob, NULL);
+ type = key_type_from_name(type_name);
+ switch (type) {
+ case KEY_DSA:
+ k = key_new_private(type);
+ buffer_get_bignum2(blob, k->dsa->p);
+ buffer_get_bignum2(blob, k->dsa->q);
+ buffer_get_bignum2(blob, k->dsa->g);
+ buffer_get_bignum2(blob, k->dsa->pub_key);
+ buffer_get_bignum2(blob, k->dsa->priv_key);
+ break;
+ case KEY_DSA_CERT_V00:
+ case KEY_DSA_CERT:
+ cert = buffer_get_string(blob, &len);
+ if ((k = key_from_blob(cert, len)) == NULL)
+ fatal("Certificate parse failed");
+ free(cert);
+ key_add_private(k);
+ buffer_get_bignum2(blob, k->dsa->priv_key);
+ break;
+#ifdef OPENSSL_HAS_ECC
+ case KEY_ECDSA:
+ k = key_new_private(type);
+ k->ecdsa_nid = key_ecdsa_nid_from_name(type_name);
+ curve = buffer_get_string(blob, NULL);
+ if (k->ecdsa_nid != key_curve_name_to_nid(curve))
+ fatal("%s: curve names mismatch", __func__);
+ free(curve);
+ k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
+ if (k->ecdsa == NULL)
+ fatal("%s: EC_KEY_new_by_curve_name failed",
+ __func__);
+ q = EC_POINT_new(EC_KEY_get0_group(k->ecdsa));
+ if (q == NULL)
+ fatal("%s: BN_new failed", __func__);
+ if ((exponent = BN_new()) == NULL)
+ fatal("%s: BN_new failed", __func__);
+ buffer_get_ecpoint(blob,
+ EC_KEY_get0_group(k->ecdsa), q);
+ buffer_get_bignum2(blob, exponent);
+ if (EC_KEY_set_public_key(k->ecdsa, q) != 1)
+ fatal("%s: EC_KEY_set_public_key failed",
+ __func__);
+ if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1)
+ fatal("%s: EC_KEY_set_private_key failed",
+ __func__);
+ if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
+ EC_KEY_get0_public_key(k->ecdsa)) != 0)
+ fatal("%s: bad ECDSA public key", __func__);
+ if (key_ec_validate_private(k->ecdsa) != 0)
+ fatal("%s: bad ECDSA private key", __func__);
+ BN_clear_free(exponent);
+ EC_POINT_free(q);
+ break;
+ case KEY_ECDSA_CERT:
+ cert = buffer_get_string(blob, &len);
+ if ((k = key_from_blob(cert, len)) == NULL)
+ fatal("Certificate parse failed");
+ free(cert);
+ key_add_private(k);
+ if ((exponent = BN_new()) == NULL)
+ fatal("%s: BN_new failed", __func__);
+ buffer_get_bignum2(blob, exponent);
+ if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1)
+ fatal("%s: EC_KEY_set_private_key failed",
+ __func__);
+ if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
+ EC_KEY_get0_public_key(k->ecdsa)) != 0 ||
+ key_ec_validate_private(k->ecdsa) != 0)
+ fatal("%s: bad ECDSA key", __func__);
+ BN_clear_free(exponent);
+ break;
+#endif
+ case KEY_RSA:
+ k = key_new_private(type);
+ buffer_get_bignum2(blob, k->rsa->n);
+ buffer_get_bignum2(blob, k->rsa->e);
+ buffer_get_bignum2(blob, k->rsa->d);
+ buffer_get_bignum2(blob, k->rsa->iqmp);
+ buffer_get_bignum2(blob, k->rsa->p);
+ buffer_get_bignum2(blob, k->rsa->q);
+
+ /* Generate additional parameters */
+ rsa_generate_additional_parameters(k->rsa);
+ break;
+ case KEY_RSA_CERT_V00:
+ case KEY_RSA_CERT:
+ cert = buffer_get_string(blob, &len);
+ if ((k = key_from_blob(cert, len)) == NULL)
+ fatal("Certificate parse failed");
+ free(cert);
+ key_add_private(k);
+ buffer_get_bignum2(blob, k->rsa->d);
+ buffer_get_bignum2(blob, k->rsa->iqmp);
+ buffer_get_bignum2(blob, k->rsa->p);
+ buffer_get_bignum2(blob, k->rsa->q);
+ break;
+ case KEY_ED25519:
+ k = key_new_private(type);
+ k->ed25519_pk = buffer_get_string(blob, &pklen);
+ k->ed25519_sk = buffer_get_string(blob, &sklen);
+ if (pklen != ED25519_PK_SZ)
+ fatal("%s: ed25519 pklen %d != %d",
+ __func__, pklen, ED25519_PK_SZ);
+ if (sklen != ED25519_SK_SZ)
+ fatal("%s: ed25519 sklen %d != %d",
+ __func__, sklen, ED25519_SK_SZ);
+ break;
+ case KEY_ED25519_CERT:
+ cert = buffer_get_string(blob, &len);
+ if ((k = key_from_blob(cert, len)) == NULL)
+ fatal("Certificate parse failed");
+ free(cert);
+ key_add_private(k);
+ k->ed25519_pk = buffer_get_string(blob, &pklen);
+ k->ed25519_sk = buffer_get_string(blob, &sklen);
+ if (pklen != ED25519_PK_SZ)
+ fatal("%s: ed25519 pklen %d != %d",
+ __func__, pklen, ED25519_PK_SZ);
+ if (sklen != ED25519_SK_SZ)
+ fatal("%s: ed25519 sklen %d != %d",
+ __func__, sklen, ED25519_SK_SZ);
+ break;
+ default:
+ free(type_name);
+ buffer_clear(blob);
+ return NULL;
+ }
+ free(type_name);
+
+ /* enable blinding */
+ switch (k->type) {
+ case KEY_RSA:
+ case KEY_RSA_CERT_V00:
+ case KEY_RSA_CERT:
+ case KEY_RSA1:
+ if (RSA_blinding_on(k->rsa, NULL) != 1) {
+ error("%s: RSA_blinding_on failed", __func__);
+ key_free(k);
+ return NULL;
+ }
+ break;
+ }
+ return k;
+}
OpenPOWER on IntegriCloud