summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2015-09-13 09:06:12 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2015-09-13 09:09:13 +0200
commitd5075bcff6e0c66014ed279248f27f0cdb275a02 (patch)
tree6bc8b271b2f5b010e2fd347ef025097a6f3b6999 /lib
parent65a67fd2d3bf568c4ef550612583a47865b648a7 (diff)
downloadgnutls-d5075bcff6e0c66014ed279248f27f0cdb275a02.tar.gz
Added API to verify private keys generated with seed
Diffstat (limited to 'lib')
-rw-r--r--lib/errors.c2
-rw-r--r--lib/includes/gnutls/abstract.h3
-rw-r--r--lib/includes/gnutls/gnutls.h.in1
-rw-r--r--lib/includes/gnutls/x509.h3
-rw-r--r--lib/libgnutls.map6
-rw-r--r--lib/privkey.c26
-rw-r--r--lib/x509/privkey.c110
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
*