diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2015-09-13 09:06:12 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2015-09-13 09:09:13 +0200 |
commit | d5075bcff6e0c66014ed279248f27f0cdb275a02 (patch) | |
tree | 6bc8b271b2f5b010e2fd347ef025097a6f3b6999 /lib | |
parent | 65a67fd2d3bf568c4ef550612583a47865b648a7 (diff) | |
download | gnutls-d5075bcff6e0c66014ed279248f27f0cdb275a02.tar.gz |
Added API to verify private keys generated with seed
Diffstat (limited to 'lib')
-rw-r--r-- | lib/errors.c | 2 | ||||
-rw-r--r-- | lib/includes/gnutls/abstract.h | 3 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 1 | ||||
-rw-r--r-- | lib/includes/gnutls/x509.h | 3 | ||||
-rw-r--r-- | lib/libgnutls.map | 6 | ||||
-rw-r--r-- | lib/privkey.c | 26 | ||||
-rw-r--r-- | lib/x509/privkey.c | 110 |
7 files changed, 144 insertions, 7 deletions
diff --git a/lib/errors.c b/lib/errors.c index 41b0610f1c..11f8916b3d 100644 --- a/lib/errors.c +++ b/lib/errors.c @@ -156,6 +156,8 @@ static const gnutls_error_entry error_entries[] = { GNUTLS_E_CERTIFICATE_ERROR), ERROR_ENTRY(N_("Error in the certificate verification."), GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR), + ERROR_ENTRY(N_("Error in the private key verification; seed doesn't match."), + GNUTLS_E_PRIVKEY_VERIFICATION_ERROR), ERROR_ENTRY(N_("Could not authenticate peer."), GNUTLS_E_AUTH_ERROR), ERROR_ENTRY(N_ diff --git a/lib/includes/gnutls/abstract.h b/lib/includes/gnutls/abstract.h index 6ebd2ea3bd..6a8b460fba 100644 --- a/lib/includes/gnutls/abstract.h +++ b/lib/includes/gnutls/abstract.h @@ -247,8 +247,9 @@ gnutls_privkey_generate (gnutls_privkey_t key, int gnutls_privkey_generate2(gnutls_privkey_t pkey, gnutls_pk_algorithm_t algo, unsigned int bits, - unsigned int flags, void *seed, unsigned seed_size); + unsigned int flags, const void *seed, unsigned seed_size); +int gnutls_privkey_verify_seed(gnutls_privkey_t key, gnutls_digest_algorithm_t, const void *seed, size_t seed_size); int gnutls_privkey_get_seed(gnutls_privkey_t key, gnutls_digest_algorithm_t*, void *seed, size_t *seed_size); int gnutls_privkey_verify_params(gnutls_privkey_t key); diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index 32e1d67398..691e9d9556 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -2612,6 +2612,7 @@ int gnutls_fips140_mode_enabled(void); #define GNUTLS_E_KEY_IMPORT_FAILED -346 #define GNUTLS_E_INAPPROPRIATE_FALLBACK -347 /*GNUTLS_A_INAPPROPRIATE_FALLBACK*/ #define GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR -348 +#define GNUTLS_E_PRIVKEY_VERIFICATION_ERROR -349 #define GNUTLS_E_SELF_TEST_ERROR -400 #define GNUTLS_E_NO_SELF_TEST -401 diff --git a/lib/includes/gnutls/x509.h b/lib/includes/gnutls/x509.h index beb619522e..5ad771477e 100644 --- a/lib/includes/gnutls/x509.h +++ b/lib/includes/gnutls/x509.h @@ -1058,8 +1058,9 @@ int gnutls_x509_privkey_generate(gnutls_x509_privkey_t key, int gnutls_x509_privkey_generate2(gnutls_x509_privkey_t key, gnutls_pk_algorithm_t algo, unsigned int bits, - unsigned int flags, void *seed, unsigned size_size); + unsigned int flags, const void *seed, unsigned size_size); +int gnutls_x509_privkey_verify_seed(gnutls_x509_privkey_t key, gnutls_digest_algorithm_t, const void *seed, size_t seed_size); int gnutls_x509_privkey_get_seed(gnutls_x509_privkey_t key, gnutls_digest_algorithm_t*, void *seed, size_t *seed_size); int gnutls_x509_privkey_verify_params(gnutls_x509_privkey_t key); diff --git a/lib/libgnutls.map b/lib/libgnutls.map index f17f2bdd14..cec85552fd 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -1056,10 +1056,12 @@ GNUTLS_3_4 gnutls_session_set_verify_cert; gnutls_session_set_verify_cert2; gnutls_session_get_verify_cert_status; - gnutls_privkey_generate2; gnutls_x509_privkey_generate2; - gnutls_privkey_get_seed; gnutls_x509_privkey_get_seed; + gnutls_x509_privkey_verify_seed; + gnutls_privkey_generate2; + gnutls_privkey_get_seed; + gnutls_privkey_verify_seed; local: *; }; diff --git a/lib/privkey.c b/lib/privkey.c index cb1b88c43a..6413d428ff 100644 --- a/lib/privkey.c +++ b/lib/privkey.c @@ -1,7 +1,7 @@ /* * GnuTLS PKCS#11 support * Copyright (C) 2010-2014 Free Software Foundation, Inc. - * Copyright (C) 2012-2014 Nikos Mavrogiannopoulos + * Copyright (C) 2012-2015 Nikos Mavrogiannopoulos * * Author: Nikos Mavrogiannopoulos * @@ -85,6 +85,28 @@ int gnutls_privkey_get_seed(gnutls_privkey_t key, gnutls_digest_algorithm_t *dig } /** + * gnutls_privkey_verify_seed: + * @key: should contain a #gnutls_privkey_t type + * @digest: it contains the digest algorithm used for key generation (if applicable) + * @seed: the seed of the key to be checked with + * @seed_size: holds the size of @seed + * + * This function will verify that the given private key was generated from + * the provided seed. + * + * Returns: In case of a verification failure %GNUTLS_E_PRIVKEY_VERIFICATION_ERROR + * is returned, and zero or positive code on success. + * + * Since: 3.5.0 + **/ +int gnutls_privkey_verify_seed(gnutls_privkey_t key, gnutls_digest_algorithm_t digest, const void *seed, size_t seed_size) +{ + if (key->type != GNUTLS_PRIVKEY_X509) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + return gnutls_x509_privkey_verify_seed(key->key.x509, digest, seed, seed_size); +} + +/** * gnutls_privkey_get_pk_algorithm: * @key: should contain a #gnutls_privkey_t type * @bits: If set will return the number of bits of the parameters (may be NULL) @@ -812,7 +834,7 @@ gnutls_privkey_generate(gnutls_privkey_t pkey, int gnutls_privkey_generate2(gnutls_privkey_t pkey, gnutls_pk_algorithm_t algo, unsigned int bits, - unsigned int flags, void *seed, unsigned seed_size) + unsigned int flags, const void *seed, unsigned seed_size) { int ret; diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c index 9af576cd3c..5a81cf3bd7 100644 --- a/lib/x509/privkey.c +++ b/lib/x509/privkey.c @@ -1563,7 +1563,7 @@ gnutls_x509_privkey_generate(gnutls_x509_privkey_t key, int gnutls_x509_privkey_generate2(gnutls_x509_privkey_t key, gnutls_pk_algorithm_t algo, unsigned int bits, - unsigned int flags, void *seed, unsigned seed_size) + unsigned int flags, const void *seed, unsigned seed_size) { int ret; @@ -1662,6 +1662,114 @@ int gnutls_x509_privkey_get_seed(gnutls_x509_privkey_t key, gnutls_digest_algori } /** + * gnutls_x509_privkey_verify_seed: + * @key: should contain a #gnutls_x509_privkey_t type + * @digest: it contains the digest algorithm used for key generation (if applicable) + * @seed: the seed of the key to be checked with + * @seed_size: holds the size of @seed + * + * This function will verify that the given private key was generated from + * the provided seed. If @seed is %NULL then the seed stored in the @key's structure + * will be used for verification. + * + * Returns: In case of a verification failure %GNUTLS_E_PRIVKEY_VERIFICATION_ERROR + * is returned, and zero or positive code on success. + * + * Since: 3.5.0 + **/ +int gnutls_x509_privkey_verify_seed(gnutls_x509_privkey_t key, gnutls_digest_algorithm_t digest, const void *seed, size_t seed_size) +{ + int ret; + gnutls_x509_privkey_t okey; + unsigned bits; + gnutls_datum_t m1 = {NULL, 0}, e1 = {NULL, 0}, d1 = {NULL, 0}, p1 = {NULL, 0}, q1 = {NULL, 0}; + gnutls_datum_t m2 = {NULL, 0}, e2 = {NULL, 0}, d2 = {NULL, 0}, p2 = {NULL, 0}, q2 = {NULL, 0}; + + if (key == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + if (key->pk_algorithm != GNUTLS_PK_RSA) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + ret = gnutls_x509_privkey_get_pk_algorithm2(key, &bits); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = gnutls_x509_privkey_init(&okey); + if (ret < 0) + return gnutls_assert_val(ret); + + if (seed == NULL) { + seed = key->params.seed; + seed_size = key->params.seed_size; + } + + ret = gnutls_x509_privkey_generate2(okey, key->pk_algorithm, bits, + GNUTLS_PRIVKEY_FLAG_PROVABLE, seed, seed_size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = gnutls_x509_privkey_export_rsa_raw(okey, &m1, &e1, &d1, &p1, &q1, NULL); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = gnutls_x509_privkey_export_rsa_raw(key, &m2, &e2, &d2, &p2, &q2, NULL); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + if (m1.size != m2.size || memcmp(m1.data, m2.data, m1.size) != 0) { + ret = GNUTLS_E_PRIVKEY_VERIFICATION_ERROR; + goto cleanup; + } + + if (d1.size != d2.size || memcmp(d1.data, d2.data, d1.size) != 0) { + ret = GNUTLS_E_PRIVKEY_VERIFICATION_ERROR; + goto cleanup; + } + + if (e1.size != e2.size || memcmp(e1.data, e2.data, e1.size) != 0) { + ret = GNUTLS_E_PRIVKEY_VERIFICATION_ERROR; + goto cleanup; + } + + if (p1.size != p2.size || memcmp(p1.data, p2.data, p1.size) != 0) { + ret = GNUTLS_E_PRIVKEY_VERIFICATION_ERROR; + goto cleanup; + } + + if (q1.size != q2.size || memcmp(q1.data, q2.data, q1.size) != 0) { + ret = GNUTLS_E_PRIVKEY_VERIFICATION_ERROR; + goto cleanup; + } + + ret = 0; + + cleanup: + gnutls_free(m1.data); + gnutls_free(e1.data); + gnutls_free(d1.data); + gnutls_free(p1.data); + gnutls_free(q1.data); + gnutls_free(m2.data); + gnutls_free(e2.data); + gnutls_free(d2.data); + gnutls_free(p2.data); + gnutls_free(q2.data); + gnutls_x509_privkey_deinit(okey); + + return ret; + +} + +/** * gnutls_x509_privkey_verify_params: * @key: a key * |