diff options
Diffstat (limited to 'usr.bin/ssh/sshkey.c')
-rw-r--r-- | usr.bin/ssh/sshkey.c | 96 |
1 files changed, 75 insertions, 21 deletions
diff --git a/usr.bin/ssh/sshkey.c b/usr.bin/ssh/sshkey.c index f41b0a1d0a1..e9c641ad3f7 100644 --- a/usr.bin/ssh/sshkey.c +++ b/usr.bin/ssh/sshkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.c,v 1.64 2018/03/22 07:05:48 markus Exp $ */ +/* $OpenBSD: sshkey.c,v 1.65 2018/07/03 11:39:54 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * Copyright (c) 2008 Alexander von Gernler. All rights reserved. @@ -79,38 +79,48 @@ static int sshkey_from_blob_internal(struct sshbuf *buf, struct keytype { const char *name; const char *shortname; + const char *sigalg; int type; int nid; int cert; int sigonly; }; static const struct keytype keytypes[] = { - { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0, 0 }, - { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", + { "ssh-ed25519", "ED25519", NULL, KEY_ED25519, 0, 0, 0 }, + { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", NULL, KEY_ED25519_CERT, 0, 1, 0 }, #ifdef WITH_XMSS - { "ssh-xmss@openssh.com", "XMSS", KEY_XMSS, 0, 0, 0 }, - { "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT", + { "ssh-xmss@openssh.com", "XMSS", NULL, KEY_XMSS, 0, 0, 0 }, + { "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT", NULL, KEY_XMSS_CERT, 0, 1, 0 }, #endif /* WITH_XMSS */ #ifdef WITH_OPENSSL - { "ssh-rsa", "RSA", KEY_RSA, 0, 0, 0 }, - { "rsa-sha2-256", "RSA", KEY_RSA, 0, 0, 1 }, - { "rsa-sha2-512", "RSA", KEY_RSA, 0, 0, 1 }, - { "ssh-dss", "DSA", KEY_DSA, 0, 0, 0 }, - { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0, 0 }, - { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0, 0 }, - { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0, 0 }, - { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1, 0 }, - { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1, 0 }, - { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", + { "ssh-rsa", "RSA", NULL, KEY_RSA, 0, 0, 0 }, + { "rsa-sha2-256", "RSA", NULL, KEY_RSA, 0, 0, 1 }, + { "rsa-sha2-512", "RSA", NULL, KEY_RSA, 0, 0, 1 }, + { "ssh-dss", "DSA", NULL, KEY_DSA, 0, 0, 0 }, + { "ecdsa-sha2-nistp256", "ECDSA", NULL, + KEY_ECDSA, NID_X9_62_prime256v1, 0, 0 }, + { "ecdsa-sha2-nistp384", "ECDSA", NULL, + KEY_ECDSA, NID_secp384r1, 0, 0 }, + { "ecdsa-sha2-nistp521", "ECDSA", NULL, + KEY_ECDSA, NID_secp521r1, 0, 0 }, + { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL, + KEY_RSA_CERT, 0, 1, 0 }, + { "rsa-sha2-256-cert-v01@openssh.com", "RSA-CERT", + "ssh-rsa-sha2-256", KEY_RSA_CERT, 0, 1, 1 }, + { "rsa-sha2-512-cert-v01@openssh.com", "RSA-CERT", + "ssh-rsa-sha2-512", KEY_RSA_CERT, 0, 1, 1 }, + { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", NULL, + KEY_DSA_CERT, 0, 1, 0 }, + { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", NULL, KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1, 0 }, - { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", + { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", NULL, KEY_ECDSA_CERT, NID_secp384r1, 1, 0 }, - { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", - KEY_ECDSA_CERT, NID_secp521r1, 1, 0 }, + { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", NULL, + KEY_ECDSA_CERT, NID_secp521r1, 1, 0 }, #endif /* WITH_OPENSSL */ - { NULL, NULL, -1, -1, 0, 0 } + { NULL, NULL, NULL, -1, -1, 0, 0 } }; const char * @@ -2160,8 +2170,8 @@ sshkey_froms(struct sshbuf *buf, struct sshkey **keyp) return r; } -int -sshkey_sigtype(const u_char *sig, size_t siglen, char **sigtypep) +static int +get_sigtype(const u_char *sig, size_t siglen, char **sigtypep) { int r; struct sshbuf *b = NULL; @@ -2185,6 +2195,50 @@ sshkey_sigtype(const u_char *sig, size_t siglen, char **sigtypep) return r; } +/* + * Returns the expected signature algorithm for a given public key algorithm. + */ +static const char * +sigalg_by_name(const char *name) +{ + const struct keytype *kt; + + for (kt = keytypes; kt->type != -1; kt++) { + if (strcmp(kt->name, name) != 0) + continue; + if (kt->sigalg != NULL) + return kt->sigalg; + if (!kt->cert) + return kt->name; + return sshkey_ssh_name_from_type_nid( + sshkey_type_plain(kt->type), kt->nid); + } + return NULL; +} + +/* + * Verifies that the signature algorithm appearing inside the signature blob + * matches that which was requested. + */ +int +sshkey_check_sigtype(const u_char *sig, size_t siglen, + const char *requested_alg) +{ + const char *expected_alg; + char *sigtype = NULL; + int r; + + if (requested_alg == NULL) + return 0; + if ((expected_alg = sigalg_by_name(requested_alg)) == NULL) + return SSH_ERR_INVALID_ARGUMENT; + if ((r = get_sigtype(sig, siglen, &sigtype)) != 0) + return r; + r = strcmp(expected_alg, sigtype) == 0; + free(sigtype); + return r ? 0 : SSH_ERR_SIGN_ALG_UNSUPPORTED; +} + int sshkey_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, |