diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2015-09-12 15:47:38 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2015-09-12 16:22:48 +0200 |
commit | 6c8702587943c426e06d5b545af4f143ae17c670 (patch) | |
tree | 8a8184b82ccd40564456390f4ab580970a431763 | |
parent | 9b89f76fc789fd8f8e3bb3c418f25b97b9e71920 (diff) | |
download | gnutls-6c8702587943c426e06d5b545af4f143ae17c670.tar.gz |
Added API to generate private keys from a given seed
Currently it is restricted to RSA and FIPS 186-4 key generation with SHA384.
Relates to #34
-rw-r--r-- | lib/crypto-backend.h | 8 | ||||
-rw-r--r-- | lib/gnutls.asn | 12 | ||||
-rw-r--r-- | lib/gnutls_int.h | 3 | ||||
-rw-r--r-- | lib/includes/gnutls/abstract.h | 9 | ||||
-rw-r--r-- | lib/includes/gnutls/x509.h | 7 | ||||
-rw-r--r-- | lib/libgnutls.map | 4 | ||||
-rw-r--r-- | lib/nettle/Makefile.am | 6 | ||||
-rw-r--r-- | lib/nettle/int/dsa-fips.h | 2 | ||||
-rw-r--r-- | lib/nettle/int/rsa-fips.h | 2 | ||||
-rw-r--r-- | lib/nettle/int/rsa-keygen-fips186.c | 23 | ||||
-rw-r--r-- | lib/nettle/pk.c | 37 | ||||
-rw-r--r-- | lib/pk.c | 7 | ||||
-rw-r--r-- | lib/privkey.c | 64 | ||||
-rw-r--r-- | lib/x509/key_encode.c | 33 | ||||
-rw-r--r-- | lib/x509/privkey.c | 108 |
15 files changed, 293 insertions, 32 deletions
diff --git a/lib/crypto-backend.h b/lib/crypto-backend.h index 5f6c228fb4..3aba11a842 100644 --- a/lib/crypto-backend.h +++ b/lib/crypto-backend.h @@ -173,6 +173,11 @@ typedef struct { bigint_t params[GNUTLS_MAX_PK_PARAMS]; unsigned int params_nr; /* the number of parameters */ unsigned int flags; + + unsigned int seed_size; + uint8_t seed[MAX_PVP_SEED_SIZE]; + gnutls_digest_algorithm_t palgo; + gnutls_pk_algorithm_t algo; } gnutls_pk_params_st; @@ -183,7 +188,8 @@ typedef struct { * Enumeration of public-key flag. */ typedef enum { - GNUTLS_PK_FLAG_NONE = 0 + GNUTLS_PK_FLAG_NONE = 0, + GNUTLS_PK_FLAG_PROVABLE = 1 } gnutls_pk_flag_t; diff --git a/lib/gnutls.asn b/lib/gnutls.asn index 9eaae4e158..5a68d8067c 100644 --- a/lib/gnutls.asn +++ b/lib/gnutls.asn @@ -26,7 +26,17 @@ RSAPrivateKey ::= SEQUENCE { exponent1 INTEGER, -- (Usually large) d mod (p-1) exponent2 INTEGER, -- (Usually large) d mod (q-1) coefficient INTEGER, -- (Usually large) (inverse of q) mod p - otherPrimeInfos OtherPrimeInfos OPTIONAL + otherInfo RSAOtherInfo OPTIONAL +} + +RSASeed ::= SEQUENCE { + algorithm OBJECT IDENTIFIER, + seed OCTET STRING +} + +RSAOtherInfo ::= CHOICE { + otherPrimeInfos OtherPrimeInfos, -- the hash algorithm OID used for FIPS186-4 generation + seed [1] RSASeed } OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 49dcd575f3..fbdee50691 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -178,6 +178,9 @@ typedef enum record_flush_t { #define HANDSHAKE_HEADER_SIZE(session) (IS_DTLS(session) ? DTLS_HANDSHAKE_HEADER_SIZE : TLS_HANDSHAKE_HEADER_SIZE) #define MAX_HANDSHAKE_HEADER_SIZE DTLS_HANDSHAKE_HEADER_SIZE +/* Maximum seed size for provable parameters */ +#define MAX_PVP_SEED_SIZE 256 + /* This is the maximum handshake message size we send without fragmentation. This currently ignores record layer overhead. */ #define DTLS_DEFAULT_MTU 1200 diff --git a/lib/includes/gnutls/abstract.h b/lib/includes/gnutls/abstract.h index c915d7a035..6ebd2ea3bd 100644 --- a/lib/includes/gnutls/abstract.h +++ b/lib/includes/gnutls/abstract.h @@ -244,6 +244,12 @@ int gnutls_privkey_generate (gnutls_privkey_t key, gnutls_pk_algorithm_t algo, unsigned int bits, unsigned int flags); +int +gnutls_privkey_generate2(gnutls_privkey_t pkey, + gnutls_pk_algorithm_t algo, unsigned int bits, + unsigned int flags, void *seed, unsigned 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); @@ -270,7 +276,8 @@ typedef enum gnutls_privkey_flags { GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE = 1, GNUTLS_PRIVKEY_IMPORT_COPY = 1 << 1, GNUTLS_PRIVKEY_DISABLE_CALLBACKS = 1 << 2, - GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA = 1 << 4 + GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA = 1 << 4, + GNUTLS_PRIVKEY_FLAG_PROVABLE = 1 << 5 } gnutls_privkey_flags_t; int gnutls_privkey_import_pkcs11(gnutls_privkey_t pkey, diff --git a/lib/includes/gnutls/x509.h b/lib/includes/gnutls/x509.h index 73b98e85a9..beb619522e 100644 --- a/lib/includes/gnutls/x509.h +++ b/lib/includes/gnutls/x509.h @@ -1055,6 +1055,13 @@ int gnutls_x509_privkey_get_key_id(gnutls_x509_privkey_t key, int gnutls_x509_privkey_generate(gnutls_x509_privkey_t key, gnutls_pk_algorithm_t algo, unsigned int bits, unsigned int flags); +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); + +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); int gnutls_x509_privkey_export(gnutls_x509_privkey_t key, diff --git a/lib/libgnutls.map b/lib/libgnutls.map index a4f9a3d57b..f17f2bdd14 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -1056,6 +1056,10 @@ 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; local: *; }; diff --git a/lib/nettle/Makefile.am b/lib/nettle/Makefile.am index e84ed1f6f4..eaaae17fc5 100644 --- a/lib/nettle/Makefile.am +++ b/lib/nettle/Makefile.am @@ -40,10 +40,10 @@ noinst_LTLIBRARIES = libcrypto.la libcrypto_la_SOURCES = pk.c mpi.c mac.c cipher.c init.c egd.c egd.h \ gnettle.h rnd-common.h rnd-common.c \ - rnd.c + rnd.c int/rsa-fips.h int/rsa-keygen-fips186.c int/provable-prime.c if ENABLE_FIPS140 libcrypto_la_SOURCES += rnd-fips.c int/drbg-aes-self-test.c \ - int/dsa-fips.h int/dsa-keygen-fips186.c int/dsa-validate.c int/provable-prime.c \ - int/drbg-aes.c int/drbg-aes.h int/rsa-fips.h int/rsa-keygen-fips186.c + int/dsa-fips.h int/dsa-keygen-fips186.c int/dsa-validate.c \ + int/drbg-aes.c int/drbg-aes.h endif diff --git a/lib/nettle/int/dsa-fips.h b/lib/nettle/int/dsa-fips.h index e1edfb5125..9d1e4c06d4 100644 --- a/lib/nettle/int/dsa-fips.h +++ b/lib/nettle/int/dsa-fips.h @@ -29,8 +29,6 @@ #include <nettle/sha2.h> #include <fips.h> -#define MAX_PVP_SEED_SIZE 256 - #define div_ceil(x,y) ((x+(y)-1)/(y)) struct dss_params_validation_seeds { diff --git a/lib/nettle/int/rsa-fips.h b/lib/nettle/int/rsa-fips.h index 6f349909fa..7b1cf701d2 100644 --- a/lib/nettle/int/rsa-fips.h +++ b/lib/nettle/int/rsa-fips.h @@ -41,6 +41,8 @@ rsa_generate_fips186_4_keypair(struct rsa_public_key *pub, void *random_ctx, nettle_random_func * random, void *progress_ctx, nettle_progress_func * progress, + unsigned *rseed_size, + void *rseed, /* Desired size of modulo, in bits */ unsigned n_size); diff --git a/lib/nettle/int/rsa-keygen-fips186.c b/lib/nettle/int/rsa-keygen-fips186.c index 624aa36535..711c2004ea 100644 --- a/lib/nettle/int/rsa-keygen-fips186.c +++ b/lib/nettle/int/rsa-keygen-fips186.c @@ -270,12 +270,17 @@ _rsa_generate_fips186_4_keypair(struct rsa_public_key *pub, if (n_size == 2048) { if (seed_length != 14 * 2) { + _gnutls_debug_log("Seed length must be 28 bytes\n"); return 0; } - } else { + } else if (n_size == 3072) { if (seed_length != 16 * 2) { + _gnutls_debug_log("Seed length must be 32 bytes\n"); return 0; } + } else { + _gnutls_debug_log("Unsupported size for modulus\n"); + return 0; } if (!mpz_tstbit(pub->e, 0)) { @@ -333,7 +338,6 @@ _rsa_generate_fips186_4_keypair(struct rsa_public_key *pub, } while (mpz_cmp(t, r) <= 0); memset(&cert, 0, sizeof(cert)); - memset(seed, 0, seed_length); mpz_mul(pub->n, key->p, key->q); @@ -385,11 +389,14 @@ rsa_generate_fips186_4_keypair(struct rsa_public_key *pub, void *random_ctx, nettle_random_func * random, void *progress_ctx, nettle_progress_func * progress, + unsigned *rseed_size, + void *rseed, /* Desired size of modulo, in bits */ unsigned n_size) { uint8_t seed[32]; unsigned seed_length; + int ret; if (n_size != 2048 && n_size != 3072) { return 0; @@ -402,6 +409,16 @@ rsa_generate_fips186_4_keypair(struct rsa_public_key *pub, random(random_ctx, seed_length, seed); - return _rsa_generate_fips186_4_keypair(pub, key, seed_length, seed, + if (rseed && rseed_size) { + if (*rseed_size < seed_length) { + return 0; + } + memcpy(rseed, seed, seed_length); + *rseed_size = seed_length; + } + + ret = _rsa_generate_fips186_4_keypair(pub, key, seed_length, seed, progress_ctx, progress, n_size); + gnutls_memset(seed, 0, seed_length); + return ret; } diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c index 98621ec87b..0d9869a300 100644 --- a/lib/nettle/pk.c +++ b/lib/nettle/pk.c @@ -40,8 +40,8 @@ #include <nettle/dsa.h> #ifdef ENABLE_FIPS140 # include <dsa-fips.h> -# include <rsa-fips.h> #endif +#include <rsa-fips.h> #include <nettle/rsa.h> #include <gnutls/crypto.h> #include <nettle/bignum.h> @@ -1132,6 +1132,9 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo, switch (algo) { case GNUTLS_PK_DSA: + if (params->flags & GNUTLS_PK_FLAG_PROVABLE) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + #ifdef ENABLE_FIPS140 if (_gnutls_fips_mode_enabled() != 0) { struct dsa_params pub; @@ -1176,6 +1179,9 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo, } #endif case GNUTLS_PK_DH: + if (params->flags & GNUTLS_PK_FLAG_PROVABLE) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + { struct dsa_params pub; mpz_t r; @@ -1258,15 +1264,23 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo, mpz_set_ui(pub.e, 65537); -#ifdef ENABLE_FIPS140 - if (_gnutls_fips_mode_enabled() != 0) { - ret = - rsa_generate_fips186_4_keypair(&pub, &priv, NULL, - rnd_func, NULL, NULL, - level); - } else -#endif - { + if ((params->flags & GNUTLS_PK_FLAG_PROVABLE) || _gnutls_fips_mode_enabled() != 0) { + params->flags |= GNUTLS_PK_FLAG_PROVABLE; + params->palgo = GNUTLS_DIG_SHA384; + + if (params->seed_size) { + ret = _rsa_generate_fips186_4_keypair(&pub, &priv, + params->seed_size, params->seed, + NULL, NULL, level); + } else { + params->seed_size = sizeof(params->seed); + ret = + rsa_generate_fips186_4_keypair(&pub, &priv, NULL, + rnd_func, NULL, NULL, + ¶ms->seed_size, params->seed, + level); + } + } else { ret = rsa_generate_keypair(&pub, &priv, NULL, rnd_func, NULL, NULL, @@ -1309,6 +1323,9 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo, break; } case GNUTLS_PK_EC: + if (params->flags & GNUTLS_PK_FLAG_PROVABLE) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + { struct ecc_scalar key; struct ecc_point pub; @@ -186,6 +186,11 @@ int _gnutls_pk_params_copy(gnutls_pk_params_st * dst, dst->params_nr++; } + if (src->seed_size) { + dst->seed_size = src->seed_size; + memcpy(dst->seed, src->seed, src->seed_size); + } + return 0; fail: @@ -215,6 +220,8 @@ void gnutls_pk_params_clear(gnutls_pk_params_st * p) if (p->params[i] != NULL) _gnutls_mpi_clear(p->params[i]); } + gnutls_memset(p->seed, 0, p->seed_size); + p->seed_size = 0; } /* Writes the digest information and the digest in a DER encoded diff --git a/lib/privkey.c b/lib/privkey.c index 6394a9000e..cb1b88c43a 100644 --- a/lib/privkey.c +++ b/lib/privkey.c @@ -62,6 +62,29 @@ gnutls_privkey_type_t gnutls_privkey_get_type(gnutls_privkey_t key) } /** + * gnutls_privkey_get_seed: + * @key: should contain a #gnutls_privkey_t type + * @digest: if non-NULL it will contain the digest algorithm used for key generation (if applicable) + * @seed: where seed will be copied to + * @seed_size: originally holds the size of @seed, will be updated with actual size + * + * This function will return the seed that was used to generate the + * given private key. That function will succeed only if the key was generated + * as a provable key. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a + * negative error value. + * + * Since: 3.5.0 + **/ +int gnutls_privkey_get_seed(gnutls_privkey_t key, gnutls_digest_algorithm_t *digest, void *seed, size_t *seed_size) +{ + if (key->type != GNUTLS_PRIVKEY_X509) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + return gnutls_x509_privkey_get_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) @@ -735,10 +758,12 @@ gnutls_privkey_export_x509(gnutls_privkey_t pkey, * @pkey: The private key * @algo: is one of the algorithms in #gnutls_pk_algorithm_t. * @bits: the size of the modulus - * @flags: unused for now. Must be 0. + * @flags: Must be zero or flags from #gnutls_privkey_flags_t. * * This function will generate a random private key. Note that this - * function must be called on an empty private key. + * function must be called on an empty private key. The flag %GNUTLS_PRIVKEY_FLAG_PROVABLE + * instructs the key generation process to use algorithms which generate + * provable parameters out of a seed. * * Note that when generating an elliptic curve key, the curve * can be substituted in the place of the bits parameter using the @@ -756,13 +781,46 @@ gnutls_privkey_generate(gnutls_privkey_t pkey, gnutls_pk_algorithm_t algo, unsigned int bits, unsigned int flags) { + return gnutls_privkey_generate2(pkey, algo, bits, flags, NULL, 0); +} + +/** + * gnutls_privkey_generate2: + * @pkey: The private key + * @algo: is one of the algorithms in #gnutls_pk_algorithm_t. + * @bits: the size of the modulus + * @flags: Must be zero or flags from #gnutls_privkey_flags_t. + * @seed: The seed to be used in case of %GNUTLS_PRIVKEY_FLAG_PROVABLE flag + * @seed_size: The size of the seed + * + * This function will generate a random private key. Note that this + * function must be called on an empty private key. The flag %GNUTLS_PRIVKEY_FLAG_PROVABLE + * instructs the key generation process to use algorithms which generate + * provable parameters out of a seed. + * + * Note that when generating an elliptic curve key, the curve + * can be substituted in the place of the bits parameter using the + * GNUTLS_CURVE_TO_BITS() macro. + * + * Do not set the number of bits directly, use gnutls_sec_param_to_pk_bits(). + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a + * negative error value. + * + * Since: 3.5.0 + **/ +int +gnutls_privkey_generate2(gnutls_privkey_t pkey, + gnutls_pk_algorithm_t algo, unsigned int bits, + unsigned int flags, void *seed, unsigned seed_size) +{ int ret; ret = gnutls_x509_privkey_init(&pkey->key.x509); if (ret < 0) return gnutls_assert_val(ret); - ret = gnutls_x509_privkey_generate(pkey->key.x509, algo, bits, flags); + ret = gnutls_x509_privkey_generate2(pkey->key.x509, algo, bits, flags, seed, seed_size); if (ret < 0) { gnutls_x509_privkey_deinit(pkey->key.x509); pkey->key.x509 = NULL; diff --git a/lib/x509/key_encode.c b/lib/x509/key_encode.c index 7da4cbef2d..99490b0be5 100644 --- a/lib/x509/key_encode.c +++ b/lib/x509/key_encode.c @@ -442,11 +442,34 @@ _gnutls_asn1_encode_rsa(ASN1_TYPE * c2, gnutls_pk_params_st * params) goto cleanup; } - if ((result = asn1_write_value(*c2, "otherPrimeInfos", - NULL, 0)) != ASN1_SUCCESS) { - gnutls_assert(); - ret = _gnutls_asn2err(result); - goto cleanup; + if (params->flags & GNUTLS_PK_FLAG_PROVABLE && params->seed_size > 0) { + if ((result = asn1_write_value(*c2, "otherInfo", + "seed", 1)) != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(result); + goto cleanup; + } + + if ((result = asn1_write_value(*c2, "otherInfo.seed.seed", + params->seed, params->seed_size)) != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(result); + goto cleanup; + } + + if ((result = asn1_write_value(*c2, "otherInfo.seed.algorithm", + gnutls_digest_get_oid(params->palgo), 1)) != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(result); + goto cleanup; + } + } else { + if ((result = asn1_write_value(*c2, "otherInfo", + NULL, 0)) != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(result); + goto cleanup; + } } if ((result = diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c index f97477cf9c..9af576cd3c 100644 --- a/lib/x509/privkey.c +++ b/lib/x509/privkey.c @@ -134,6 +134,8 @@ _gnutls_privkey_decode_pkcs1_rsa_key(const gnutls_datum_t * raw_key, { int result; ASN1_TYPE pkey_asn; + char tmp[64]; + int tmp_size; gnutls_pk_params_init(&pkey->params); @@ -228,6 +230,29 @@ _gnutls_privkey_decode_pkcs1_rsa_key(const gnutls_datum_t * raw_key, pkey->params.params_nr = RSA_PRIVATE_PARAMS; + tmp_size = sizeof(tmp); + result = asn1_read_value(pkey_asn, "otherInfo", tmp, &tmp_size); + if (result == ASN1_SUCCESS && strcmp(tmp, "seed") == 0) { + gnutls_datum_t v; + char oid[MAX_OID_SIZE]; + int oid_size; + + oid_size = sizeof(oid); + result = asn1_read_value(pkey_asn, "otherInfo.seed.algorithm", oid, &oid_size); + if (result >= 0) { + pkey->params.palgo = gnutls_oid_to_digest(oid); + } + + result = _gnutls_x509_read_value(pkey_asn, "otherInfo.seed.seed", &v); + if (result >= 0) { + if (v.size <= sizeof(pkey->params.seed)) { + memcpy(pkey->params.seed, v.data, v.size); + pkey->params.seed_size = v.size; + } + gnutls_free(v.data); + } + } + return pkey_asn; error: @@ -1482,10 +1507,12 @@ cleanup: * @key: a key * @algo: is one of the algorithms in #gnutls_pk_algorithm_t. * @bits: the size of the modulus - * @flags: unused for now. Must be 0. + * @flags: Must be zero or flags from #gnutls_privkey_flags_t. * * This function will generate a random private key. Note that this - * function must be called on an empty private key. + * function must be called on an empty private key. The flag %GNUTLS_PRIVKEY_FLAG_PROVABLE + * instructs the key generation process to use algorithms which generate + * provable parameters out of a seed. * * Note that when generating an elliptic curve key, the curve * can be substituted in the place of the bits parameter using the @@ -1504,6 +1531,40 @@ gnutls_x509_privkey_generate(gnutls_x509_privkey_t key, gnutls_pk_algorithm_t algo, unsigned int bits, unsigned int flags) { + return gnutls_x509_privkey_generate2(key, algo, bits, flags, NULL, 0); +} + +/** + * gnutls_x509_privkey_generate2: + * @key: a key + * @algo: is one of the algorithms in #gnutls_pk_algorithm_t. + * @bits: the size of the modulus + * @flags: Must be zero or flags from #gnutls_privkey_flags_t. + * @seed: The seed to be used in case of %GNUTLS_PRIVKEY_FLAG_PROVABLE flag + * @seed_size: The size of the seed + * + * This function will generate a random private key. Note that this + * function must be called on an empty private key. The flag %GNUTLS_PRIVKEY_FLAG_PROVABLE + * instructs the key generation process to use algorithms which generate + * provable parameters out of a seed. + * + * Note that when generating an elliptic curve key, the curve + * can be substituted in the place of the bits parameter using the + * GNUTLS_CURVE_TO_BITS() macro. + * + * For DSA keys, if the subgroup size needs to be specified check + * the GNUTLS_SUBGROUP_TO_BITS() macro. + * + * Do not set the number of bits directly, use gnutls_sec_param_to_pk_bits(). + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a + * negative error value. + **/ +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) +{ int ret; if (key == NULL) { @@ -1520,6 +1581,14 @@ gnutls_x509_privkey_generate(gnutls_x509_privkey_t key, bits = _gnutls_ecc_bits_to_curve(bits); } + if (flags & GNUTLS_PRIVKEY_FLAG_PROVABLE) { + key->params.flags |= GNUTLS_PK_FLAG_PROVABLE; + if (seed && seed_size < sizeof(key->params.seed)) { + key->params.seed_size = seed_size; + memcpy(key->params.seed, seed, seed_size); + } + } + ret = _gnutls_pk_generate_params(algo, bits, &key->params); if (ret < 0) { gnutls_assert(); @@ -1531,7 +1600,6 @@ gnutls_x509_privkey_generate(gnutls_x509_privkey_t key, gnutls_assert(); goto cleanup; } - #ifndef ENABLE_FIPS140 ret = _gnutls_pk_verify_priv_params(algo, &key->params); #else @@ -1560,6 +1628,40 @@ gnutls_x509_privkey_generate(gnutls_x509_privkey_t key, } /** + * gnutls_x509_privkey_get_seed: + * @key: should contain a #gnutls_x509_privkey_t type + * @digest: if non-NULL it will contain the digest algorithm used for key generation (if applicable) + * @seed: where seed will be copied to + * @seed_size: originally holds the size of @seed, will be updated with actual size + * + * This function will return the seed that was used to generate the + * given private key. That function will succeed only if the key was generated + * as a provable key. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a + * negative error value. + * + * Since: 3.5.0 + **/ +int gnutls_x509_privkey_get_seed(gnutls_x509_privkey_t key, gnutls_digest_algorithm_t *digest, void *seed, size_t *seed_size) +{ + if (key->params.seed_size == 0) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + if (*seed_size < key->params.seed_size) { + *seed_size = key->params.seed_size; + return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); + } + + if (digest) + *digest = key->params.palgo; + + memcpy(seed, key->params.seed, key->params.seed_size); + *seed_size = key->params.seed_size; + return 0; +} + +/** * gnutls_x509_privkey_verify_params: * @key: a key * |