aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelen <jjelen@redhat.com>2018-11-26 18:10:12 +0100
committerAndreas Schneider <asn@cryptomilk.org>2018-11-30 18:57:39 +0100
commit80d3e10b47b6757b56e8bea9160608296de9b095 (patch)
tree66655a926dc13b067be852cc09f7becec48ca3e4
parent455d495c7441370332835b9123806f3bdccac053 (diff)
downloadlibssh-80d3e10b47b6757b56e8bea9160608296de9b095.tar.gz
libssh-80d3e10b47b6757b56e8bea9160608296de9b095.tar.xz
libssh-80d3e10b47b6757b56e8bea9160608296de9b095.zip
tests: Verify that signatures are sane and can not be verified by non-matching key
Signed-off-by: Jakub Jelen <jjelen@redhat.com> Reviewed-by: Andreas Schneider <asn@cryptomilk.org> (cherry picked from commit 130256c3487d03f5bf07f86c1b809ab67588e121)
-rw-r--r--tests/unittests/torture_pki.c220
1 files changed, 220 insertions, 0 deletions
diff --git a/tests/unittests/torture_pki.c b/tests/unittests/torture_pki.c
index 1aff38ae..f98a3d3b 100644
--- a/tests/unittests/torture_pki.c
+++ b/tests/unittests/torture_pki.c
@@ -9,6 +9,10 @@
#include "torture_pki.h"
#include "pki.c"
+
+const unsigned char HASH[] = "1234567890123456789012345678901234567890"
+ "123456789012345678901234";
+
static void torture_pki_keytype(void **state) {
enum ssh_keytypes_e type;
const char *type_c;
@@ -43,11 +47,227 @@ static void torture_pki_signature(void **state)
ssh_signature_free(sig);
}
+/* Maps to enum ssh_keytypes_e */
+const char *key_types[] = {
+ "", /* UNKNOWN */
+ "ssh-dss",
+ "ssh-rsa",
+ "",/* RSA1 */
+ "ecdsa-sha2-nistp521",
+ "ssh-ed25519",
+};
+
+/* Maps to enum ssh_keytypes_e */
+const int key_sizes[] = {
+ 0, /* UNKNOWN */
+ 1024,
+ 2048,
+ 0, /* RSA1 */
+ 521,
+ 0,
+};
+
+/* Maps to enum ssh_keytypes_e */
+const int sig_lengths[] = {
+ 0, /* UNKNOWN */
+ 20,
+ 20,
+ 0, /* RSA1 */
+ 64,
+ 33,
+};
+
+/* Maps to enum ssh_keytypes_e */
+const char *signature_types[] = {
+ "", /* UNKNOWN */
+ "ssh-dss",
+ "ssh-rsa",
+ "",/* RSA1 */
+ "ecdsa-sha2-nistp521",
+ "ssh-ed25519",
+};
+
+/* Maps to enum ssh_digest_e */
+const char *hash_signatures[] = {
+ "", /* Not used here */
+ "ssh-rsa",
+ "rsa-sha2-256",
+ "rsa-sha2-512",
+};
+
+/* Maps to enum ssh_digest_e */
+int hash_lengths[] = {
+ 0, /* Not used here */
+ 20,
+ 32,
+ 64,
+};
+
+/* This tests all the base types and their signatures against each other */
+static void torture_pki_verify_mismatch(void **state)
+{
+ int rc;
+ int verbosity = torture_libssh_verbosity();
+ ssh_key key = NULL, verify_key = NULL;
+ ssh_signature sign = NULL, import_sig = NULL, new_sig = NULL;
+ ssh_string blob;
+ ssh_session session = ssh_new();
+ enum ssh_keytypes_e key_type, sig_type, first_key;
+ enum ssh_digest_e hash;
+ int hash_length;
+
+ (void) state;
+
+ ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
+
+#ifdef HAVE_DSA
+ first_key = SSH_KEYTYPE_DSS;
+#else
+ first_key = SSH_KEYTYPE_RSA;
+#endif /* HAVE_DSA */
+
+ for (sig_type = first_key;
+ sig_type <= SSH_KEYTYPE_ED25519;
+ sig_type++) {
+ if (sig_type == SSH_KEYTYPE_RSA1) {
+ continue;
+ }
+ rc = ssh_pki_generate(sig_type, key_sizes[sig_type], &key);
+ assert_true(rc == SSH_OK);
+ assert_true(key != NULL);
+ assert_int_equal(key->type, sig_type);
+ assert_string_equal(key->type_c, key_types[sig_type]);
+
+ for (hash = SSH_DIGEST_AUTO;
+ hash <= SSH_DIGEST_SHA512;
+ hash++) {
+ hash_length = ((hash == SSH_DIGEST_AUTO) ?
+ sig_lengths[sig_type] : hash_lengths[hash]);
+
+ SSH_LOG(SSH_LOG_TRACE, "Creating signature %d with hash %d",
+ sig_type, hash);
+
+ /* Create a valid signature using this key */
+ sign = pki_do_sign_hash(key, HASH, hash_length, hash);
+ assert_true(sign != NULL);
+ assert_int_equal(sign->type, key->type);
+ if (hash == SSH_DIGEST_AUTO) {
+ assert_string_equal(sign->type_c, key->type_c);
+ assert_string_equal(sign->type_c, signature_types[sig_type]);
+ } else {
+ assert_string_equal(sign->type_c, hash_signatures[hash]);
+ }
+
+ /* Create a signature blob that can be imported and verified */
+ blob = pki_signature_to_blob(sign);
+ assert_non_null(blob);
+
+ /* Import and verify with current key
+ * (this is not tested anywhere else yet) */
+ import_sig = pki_signature_from_blob(key,
+ blob,
+ sig_type,
+ hash);
+ assert_non_null(import_sig);
+ assert_int_equal(import_sig->type, key->type);
+ if (hash == SSH_DIGEST_AUTO) {
+ assert_string_equal(import_sig->type_c, key->type_c);
+ assert_string_equal(import_sig->type_c, signature_types[sig_type]);
+ } else {
+ assert_string_equal(import_sig->type_c, hash_signatures[hash]);
+ }
+
+ /* Internal API: Should work */
+ rc = pki_signature_verify(session,
+ import_sig,
+ key,
+ HASH,
+ hash_length);
+ assert_true(rc == SSH_OK);
+
+ /* XXX Test all the hash versions only with RSA.
+ * This also skips the cleanup for the last hash so we can use the
+ * created signatures later on
+ */
+ if (sig_type != SSH_KEYTYPE_RSA || hash == SSH_DIGEST_SHA512) {
+ break;
+ }
+ ssh_string_free(blob);
+ ssh_signature_free(sign);
+ ssh_signature_free(import_sig);
+ }
+
+ for (key_type = first_key;
+ key_type <= SSH_KEYTYPE_ED25519;
+ key_type++) {
+ if (key_type == SSH_KEYTYPE_RSA1) {
+ continue;
+ }
+ SSH_LOG(SSH_LOG_TRACE, "Trying key %d with signature %d",
+ key_type, sig_type);
+
+ rc = ssh_pki_generate(key_type, key_sizes[key_type], &verify_key);
+ assert_true(rc == SSH_OK);
+ assert_true(verify_key != NULL);
+
+ /* Should gradefully fail, but not crash */
+ rc = pki_signature_verify(session,
+ sign,
+ verify_key,
+ HASH,
+ hash_length);
+ assert_true(rc != SSH_OK);
+
+ /* Try the same with the imported signature */
+ rc = pki_signature_verify(session,
+ import_sig,
+ verify_key,
+ HASH,
+ hash_length);
+ assert_true(rc != SSH_OK);
+
+ /* Try to import the signature blob with different key */
+ new_sig = pki_signature_from_blob(verify_key,
+ blob,
+ sig_type,
+ SSH_DIGEST_SHA1);
+ if (sig_type != key_type) {
+ assert_true(new_sig == NULL);
+ } else {
+ /* Importing with the same key type should work */
+ assert_true(new_sig != NULL);
+ assert_int_equal(new_sig->type, key->type);
+ assert_string_equal(new_sig->type_c, key->type_c);
+ assert_string_equal(new_sig->type_c, signature_types[sig_type]);
+
+ /* The verificaiton should not work */
+ rc = pki_signature_verify(session,
+ new_sig,
+ verify_key,
+ HASH,
+ hash_length);
+ assert_true(rc != SSH_OK);
+
+ ssh_signature_free(new_sig);
+ }
+ SSH_KEY_FREE(verify_key);
+ }
+ ssh_string_free(blob);
+ ssh_signature_free(sign);
+ ssh_signature_free(import_sig);
+ SSH_KEY_FREE(key);
+ key = NULL;
+ }
+
+ ssh_free(session);
+}
+
int torture_run_tests(void) {
int rc;
struct CMUnitTest tests[] = {
cmocka_unit_test(torture_pki_keytype),
cmocka_unit_test(torture_pki_signature),
+ cmocka_unit_test(torture_pki_verify_mismatch),
};
ssh_init();