diff options
author | Jakub Jelen <jjelen@redhat.com> | 2017-11-27 17:25:34 +0100 |
---|---|---|
committer | Daiki Ueno <dueno@src.gnome.org> | 2017-11-29 17:22:17 +0100 |
commit | 35a01f8c6eaf3c991aaeb3f66449f41d3f0580bc (patch) | |
tree | aede6c9492a3b8444bbc4e58e31a443a92cb1613 | |
parent | f87699bc53a70b63423e7bf122ade29ed6d113e3 (diff) | |
download | gnome-keyring-35a01f8c6eaf3c991aaeb3f66449f41d3f0580bc.tar.gz |
ssh-agent: Support SHA2 extension for RSA signatures
* Includes the test adjustments
IETF draft:
https://tools.ietf.org/html/draft-ietf-curdle-rsa-sha2-12
This will be most probably needed for OpenSSH 7.7p1:
https://bugzilla.mindrot.org/show_bug.cgi?id=2799
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
https://bugzilla.gnome.org/show_bug.cgi?id=790910
-rw-r--r-- | daemon/ssh-agent/gkd-ssh-agent-ops.c | 63 | ||||
-rw-r--r-- | daemon/ssh-agent/gkd-ssh-agent-private.h | 11 | ||||
-rw-r--r-- | daemon/ssh-agent/gkd-ssh-agent-proto.c | 72 | ||||
-rw-r--r-- | daemon/ssh-agent/test-keytypes.c | 47 |
4 files changed, 129 insertions, 64 deletions
diff --git a/daemon/ssh-agent/gkd-ssh-agent-ops.c b/daemon/ssh-agent/gkd-ssh-agent-ops.c index ab4becaf..e1cba2d5 100644 --- a/daemon/ssh-agent/gkd-ssh-agent-ops.c +++ b/daemon/ssh-agent/gkd-ssh-agent-ops.c @@ -884,6 +884,17 @@ op_v1_request_identities (GkdSshAgentCall *call) return TRUE; } +/* XXX we should create it using asn1x ... */ +static const guchar SHA512_ASN[] = /* Object ID is 2.16.840.1.101.3.4.2.3 */ + { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, + 0x40 }; + +static const guchar SHA256_ASN[] = /* Object ID is 2.16.840.1.101.3.4.2.1 */ + { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, + 0x20 }; + static const guchar SHA1_ASN[15] = /* Object ID is 1.3.14.3.2.26 */ { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 }; @@ -910,9 +921,17 @@ make_pkcs1_sign_hash (GChecksumType algo, const guchar *data, gsize n_data, if (algo == G_CHECKSUM_SHA1) { asn = SHA1_ASN; n_asn = sizeof (SHA1_ASN); + } else if (algo == G_CHECKSUM_SHA256) { + asn = SHA256_ASN; + n_asn = sizeof (SHA256_ASN); + } else if (algo == G_CHECKSUM_SHA512) { + asn = SHA512_ASN; + n_asn = sizeof (SHA512_ASN); } else if (algo == G_CHECKSUM_MD5) { asn = MD5_ASN; n_asn = sizeof (MD5_ASN); + } else { + g_assert_not_reached(); } n_hash = n_algo + n_asn; @@ -1013,6 +1032,7 @@ op_sign_request (GkdSshAgentCall *call) GChecksumType halgo; gsize n_hash = 0; GQuark oid = 0; + gint rv; offset = 5; @@ -1056,21 +1076,44 @@ op_sign_request (GkdSshAgentCall *call) return TRUE; } - if (mech == CKM_ECDSA) { + /* Usually we hash the data with SHA1 */ + halgo = G_CHECKSUM_SHA1; + if (flags & GKD_SSH_FLAG_OLD_SIGNATURE) { + halgo = G_CHECKSUM_MD5; + } + switch (algo) { + case CKK_RSA: + /* draft-ietf-curdle-rsa-sha2-12 */ + if (flags & GKD_SSH_FLAG_RSA_SHA2_256) { + halgo = G_CHECKSUM_SHA256; + } else if (flags & GKD_SSH_FLAG_RSA_SHA2_512) { + halgo = G_CHECKSUM_SHA512; + } + salgo = gkd_ssh_agent_proto_rsa_algo_to_keytype (halgo); + break; + + case CKK_EC: /* ECDSA is using SHA-2 hash algorithms based on key size */ - gint ret = gkd_ssh_agent_proto_curve_oid_to_hash_algo (oid); - if (ret == -1) { + rv = gkd_ssh_agent_proto_curve_oid_to_hash_algo (oid); + if (rv == -1) { egg_buffer_add_byte (call->resp, GKD_SSH_RES_FAILURE); return FALSE; } - halgo = (GChecksumType) ret; - } else if (flags & GKD_SSH_FLAG_OLD_SIGNATURE) { - halgo = G_CHECKSUM_MD5; - } else { - /* Usually we hash the data with SHA1 */ - halgo = G_CHECKSUM_SHA1; + halgo = (GChecksumType) rv; + salgo = gkd_ssh_agent_proto_ecc_algo_to_keytype (oid); + break; + + case CKK_DSA: + /* DSA is using default values */ + salgo = gkd_ssh_agent_proto_dsa_algo_to_keytype (); + break; + + default: + g_assert_not_reached (); } + g_assert (salgo); + /* Build the hash */ if (mech == CKM_RSA_PKCS) hash = make_pkcs1_sign_hash (halgo, data, n_data, &n_hash); @@ -1101,8 +1144,6 @@ op_sign_request (GkdSshAgentCall *call) blobpos = call->resp->len; egg_buffer_add_uint32 (call->resp, 0); - salgo = gkd_ssh_agent_proto_algo_to_keytype (algo, oid); - g_assert (salgo); egg_buffer_add_string (call->resp, salgo); switch (algo) { diff --git a/daemon/ssh-agent/gkd-ssh-agent-private.h b/daemon/ssh-agent/gkd-ssh-agent-private.h index 28a1faf2..a6c35a44 100644 --- a/daemon/ssh-agent/gkd-ssh-agent-private.h +++ b/daemon/ssh-agent/gkd-ssh-agent-private.h @@ -79,6 +79,8 @@ typedef struct _GkdSshAgentCall { #define GKD_SSH_DSA_SIGNATURE_PADDING 20 #define GKD_SSH_FLAG_OLD_SIGNATURE 0x01 +#define GKD_SSH_FLAG_RSA_SHA2_256 0x02 +#define GKD_SSH_FLAG_RSA_SHA2_512 0x04 /* ----------------------------------------------------------------------------- * gkd-ssh-agent-ops.c @@ -103,8 +105,11 @@ void gkd_ssh_agent_checkin_main_session (GckSession* gulong gkd_ssh_agent_proto_keytype_to_algo (const gchar *salgo); -const gchar* gkd_ssh_agent_proto_algo_to_keytype (gulong algo, - GQuark oid); +const gchar* gkd_ssh_agent_proto_rsa_algo_to_keytype (GChecksumType halgo); + +const gchar* gkd_ssh_agent_proto_dsa_algo_to_keytype (void); + +const gchar* gkd_ssh_agent_proto_ecc_algo_to_keytype (GQuark oid); GQuark gkd_ssh_agent_proto_curve_to_oid (const gchar *salgo); @@ -112,8 +117,6 @@ const gchar* gkd_ssh_agent_proto_oid_to_curve (GQuark oid) gint gkd_ssh_agent_proto_curve_oid_to_hash_algo (GQuark oid); -const gchar* gkd_ssh_agent_proto_curve_oid_to_keytype (GQuark oid); - GQuark gkd_ssh_agent_proto_find_curve_oid (GckAttributes *attrs); gboolean gkd_ssh_agent_proto_read_mpi (EggBuffer *req, diff --git a/daemon/ssh-agent/gkd-ssh-agent-proto.c b/daemon/ssh-agent/gkd-ssh-agent-proto.c index 034bfb9a..522733d1 100644 --- a/daemon/ssh-agent/gkd-ssh-agent-proto.c +++ b/daemon/ssh-agent/gkd-ssh-agent-proto.c @@ -66,7 +66,9 @@ gulong gkd_ssh_agent_proto_keytype_to_algo (const gchar *salgo) { g_return_val_if_fail (salgo, G_MAXULONG); - if (strcmp (salgo, "ssh-rsa") == 0) + if (strcmp (salgo, "ssh-rsa") == 0 || + strcmp (salgo, "rsa-sha2-256") == 0 || + strcmp (salgo, "rsa-sha2-512") == 0) return CKK_RSA; else if (strcmp (salgo, "ssh-dss") == 0) return CKK_DSA; @@ -130,9 +132,26 @@ gkd_ssh_agent_proto_curve_oid_to_hash_algo (GQuark oid) } const gchar* -gkd_ssh_agent_proto_curve_oid_to_keytype (GQuark oid) +gkd_ssh_agent_proto_dsa_algo_to_keytype (void) { - g_return_val_if_fail (oid, NULL); + return "ssh-dss"; +} + +const gchar* +gkd_ssh_agent_proto_rsa_algo_to_keytype (GChecksumType halgo) +{ + if (halgo == G_CHECKSUM_SHA256) + return "rsa-sha2-256"; + else if (halgo == G_CHECKSUM_SHA512) + return "rsa-sha2-512"; + + return "ssh-rsa"; +} + +const gchar* +gkd_ssh_agent_proto_ecc_algo_to_keytype (GQuark oid) +{ + g_return_val_if_fail (oid != 0, NULL); init_quarks (); @@ -146,24 +165,6 @@ gkd_ssh_agent_proto_curve_oid_to_keytype (GQuark oid) return NULL; } -const gchar* -gkd_ssh_agent_proto_algo_to_keytype (gulong algo, GQuark curve_oid) -{ - if (algo == CKK_RSA) { - g_return_val_if_fail (curve_oid == 0, NULL); - return "ssh-rsa"; - } else if (algo == CKK_DSA) { - g_return_val_if_fail (curve_oid == 0, NULL); - return "ssh-dss"; - } else if (algo == CKK_EC) { - g_return_val_if_fail (curve_oid != 0, NULL); - return gkd_ssh_agent_proto_curve_oid_to_keytype (curve_oid); - } - - return NULL; -} - - GQuark gkd_ssh_agent_proto_find_curve_oid (GckAttributes *attrs) { @@ -660,8 +661,6 @@ gboolean gkd_ssh_agent_proto_write_public (EggBuffer *resp, GckAttributes *attrs) { gboolean ret = FALSE; - const gchar *salgo; - GQuark oid = 0; gulong algo; g_assert (resp); @@ -669,15 +668,6 @@ gkd_ssh_agent_proto_write_public (EggBuffer *resp, GckAttributes *attrs) if (!gck_attributes_find_ulong (attrs, CKA_KEY_TYPE, &algo)) g_return_val_if_reached (FALSE); - if (algo == CKK_EC) { - oid = gkd_ssh_agent_proto_find_curve_oid (attrs); - if (!oid) - return FALSE; - } - - salgo = gkd_ssh_agent_proto_algo_to_keytype (algo, oid); - g_assert (salgo); - egg_buffer_add_string (resp, salgo); switch (algo) { case CKK_RSA: @@ -704,10 +694,16 @@ gboolean gkd_ssh_agent_proto_write_public_rsa (EggBuffer *resp, GckAttributes *attrs) { const GckAttribute *attr; + const gchar *salgo; g_assert (resp); g_assert (attrs); + /* write algorithm identification */ + salgo = gkd_ssh_agent_proto_rsa_algo_to_keytype (G_CHECKSUM_SHA1); + g_assert (salgo); + egg_buffer_add_string (resp, salgo); + attr = gck_attributes_find (attrs, CKA_PUBLIC_EXPONENT); g_return_val_if_fail (attr, FALSE); @@ -727,10 +723,16 @@ gboolean gkd_ssh_agent_proto_write_public_dsa (EggBuffer *resp, GckAttributes *attrs) { const GckAttribute *attr; + const gchar *salgo; g_assert (resp); g_assert (attrs); + /* write algorithm identification */ + salgo = gkd_ssh_agent_proto_dsa_algo_to_keytype (); + g_assert (salgo); + egg_buffer_add_string (resp, salgo); + attr = gck_attributes_find (attrs, CKA_PRIME); g_return_val_if_fail (attr, FALSE); @@ -769,6 +771,7 @@ gkd_ssh_agent_proto_write_public_ecdsa (EggBuffer *resp, GckAttributes *attrs) GBytes *bytes, *q; gboolean rv; gsize q_len; + const gchar *salgo; g_assert (resp); g_assert (attrs); @@ -777,6 +780,11 @@ gkd_ssh_agent_proto_write_public_ecdsa (EggBuffer *resp, GckAttributes *attrs) oid = gkd_ssh_agent_proto_find_curve_oid (attrs); g_return_val_if_fail (oid, FALSE); + /* write algorithm identification */ + salgo = gkd_ssh_agent_proto_ecc_algo_to_keytype (oid); + g_assert (salgo); + egg_buffer_add_string (resp, salgo); + curve = gkd_ssh_agent_proto_oid_to_curve (oid); g_return_val_if_fail (curve != NULL, FALSE); diff --git a/daemon/ssh-agent/test-keytypes.c b/daemon/ssh-agent/test-keytypes.c index 0c315b43..e8ed127b 100644 --- a/daemon/ssh-agent/test-keytypes.c +++ b/daemon/ssh-agent/test-keytypes.c @@ -39,15 +39,18 @@ struct alg { gchar *name; CK_KEY_TYPE id; gchar *curve_oid; + GChecksumType hash; }; /* known algorithms */ static struct alg algs_known[] = { - { "ssh-rsa", CKK_RSA, NULL }, - { "ssh-dss", CKK_DSA, NULL }, - { "ecdsa-sha2-nistp256", CKK_EC, GKD_SSH_OID_ANSI_SECP256R1 }, - { "ecdsa-sha2-nistp384", CKK_EC, GKD_SSH_OID_ANSI_SECP384R1 }, - { "ecdsa-sha2-nistp521", CKK_EC, GKD_SSH_OID_ANSI_SECP521R1 }, + { "ssh-rsa", CKK_RSA, NULL, 0 }, + { "rsa-sha2-256", CKK_RSA, NULL, G_CHECKSUM_SHA256 }, + { "rsa-sha2-512", CKK_RSA, NULL, G_CHECKSUM_SHA512 }, + { "ssh-dss", CKK_DSA, NULL, 0}, + { "ecdsa-sha2-nistp256", CKK_EC, GKD_SSH_OID_ANSI_SECP256R1, 0 }, + { "ecdsa-sha2-nistp384", CKK_EC, GKD_SSH_OID_ANSI_SECP384R1, 0 }, + { "ecdsa-sha2-nistp521", CKK_EC, GKD_SSH_OID_ANSI_SECP521R1, 0 }, /* terminator */ { NULL, 0, 0 } @@ -56,16 +59,14 @@ static struct alg algs_known[] = { /* unknown algorithms */ static struct alg algs_parse_unknown[] = { /* no certificates */ - { "ssh-rsa-cert-v01@openssh.com", G_MAXULONG, NULL }, - { "ssh-dss-cert-v01@openssh.com", G_MAXULONG, NULL }, - { "ecdsa-sha2-nistp256-cert-v01@openssh.com", G_MAXULONG, NULL }, - { "ecdsa-sha2-nistp384-cert-v01@openssh.com", G_MAXULONG, NULL }, - { "ecdsa-sha2-nistp521-cert-v01@openssh.com", G_MAXULONG, NULL }, + { "ssh-rsa-cert-v01@openssh.com", G_MAXULONG, NULL, 0 }, + { "ssh-dss-cert-v01@openssh.com", G_MAXULONG, NULL, 0 }, + { "ecdsa-sha2-nistp256-cert-v01@openssh.com", G_MAXULONG, NULL, 0 }, + { "ecdsa-sha2-nistp384-cert-v01@openssh.com", G_MAXULONG, NULL, 0 }, + { "ecdsa-sha2-nistp521-cert-v01@openssh.com", G_MAXULONG, NULL, 0 }, /* no new signatures/algorithms */ - { "rsa-sha2-256", G_MAXULONG, NULL }, - { "rsa-sha2-512", G_MAXULONG, NULL }, - { "ssh-ed25519", G_MAXULONG, NULL }, - { "ssh-ed25519-cert-v01@openssh.com", G_MAXULONG, NULL }, + { "ssh-ed25519", G_MAXULONG, NULL, 0 }, + { "ssh-ed25519-cert-v01@openssh.com", G_MAXULONG, NULL, 0 }, /* terminator */ { NULL, 0, 0 } @@ -128,8 +129,20 @@ test_generate (Test *test, gconstpointer unused) const struct alg *a; for (a = test->algs_known; a->name != NULL; a++) { - GQuark oid = g_quark_from_string (a->curve_oid); - const gchar *alg_name = gkd_ssh_agent_proto_algo_to_keytype (a->id, oid); + const gchar *alg_name = NULL; + GQuark oid; + switch (a->id) { + case CKK_RSA: + alg_name = gkd_ssh_agent_proto_rsa_algo_to_keytype (a->hash); + break; + case CKK_EC: + oid = g_quark_from_string (a->curve_oid); + alg_name = gkd_ssh_agent_proto_ecc_algo_to_keytype (oid); + break; + case CKK_DSA: + alg_name = gkd_ssh_agent_proto_dsa_algo_to_keytype (); + break; + } g_assert_cmpstr (a->name, ==, alg_name); } } @@ -143,7 +156,7 @@ test_curve_from_ssh (Test *test, gconstpointer unused) /* known */ for (a = test->curves; a->name != NULL; a++) { GQuark oid = g_quark_from_string (a->curve_oid); - alg_name = gkd_ssh_agent_proto_curve_oid_to_keytype (oid); + alg_name = gkd_ssh_agent_proto_ecc_algo_to_keytype (oid); g_assert_cmpstr (a->name, ==, alg_name); } } |