diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2014-11-13 12:06:32 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2014-11-13 12:11:05 +0100 |
commit | 88289f4402d1f3b2063c007fb7029996bd97b987 (patch) | |
tree | 0994bbbf876e8cb210c876e450871a2b08313041 | |
parent | 305103b65f5b476daa0e84539128550de552281d (diff) | |
download | gnutls-88289f4402d1f3b2063c007fb7029996bd97b987.tar.gz |
added the notion of preferred sign algorithm in a private key
This can be set for keys imported with gnutls_privkey_import_ext3()
with the info callback. It is only considered for client side keys
in TLS sessions.
-rw-r--r-- | lib/abstract_int.h | 6 | ||||
-rw-r--r-- | lib/gnutls_privkey.c | 39 | ||||
-rw-r--r-- | lib/gnutls_sig.c | 13 | ||||
-rw-r--r-- | lib/includes/gnutls/abstract.h | 11 |
4 files changed, 54 insertions, 15 deletions
diff --git a/lib/abstract_int.h b/lib/abstract_int.h index fc78f1cad9..273585a778 100644 --- a/lib/abstract_int.h +++ b/lib/abstract_int.h @@ -41,12 +41,13 @@ struct gnutls_privkey_st { gnutls_privkey_sign_func sign_func; gnutls_privkey_decrypt_func decrypt_func; gnutls_privkey_deinit_func deinit_func; - gnutls_privkey_pk_func pk_func; + gnutls_privkey_info_func info_func; void *userdata; } ext; } key; unsigned int flags; + gnutls_sign_algorithm_t preferred_sign_algo; struct pin_info_st pin; }; @@ -111,4 +112,7 @@ const mac_entry_st *_gnutls_dsa_q_to_hash(gnutls_pk_algorithm_t algo, int _gnutls_privkey_get_mpis(gnutls_privkey_t key, gnutls_pk_params_st * params); +gnutls_sign_algorithm_t +_gnutls_privkey_get_preferred_sign_algo(gnutls_privkey_t key); + #endif diff --git a/lib/gnutls_privkey.c b/lib/gnutls_privkey.c index 054ac629d4..ab419ae544 100644 --- a/lib/gnutls_privkey.c +++ b/lib/gnutls_privkey.c @@ -89,8 +89,8 @@ int gnutls_privkey_get_pk_algorithm(gnutls_privkey_t key, unsigned int *bits) case GNUTLS_PRIVKEY_EXT: if (bits) *bits = 0; - if (key->key.ext.pk_func) - return key->key.ext.pk_func(key, key->key.ext.userdata); + if (key->key.ext.info_func) + return key->key.ext.info_func(key, GNUTLS_PRIVKEY_INFO_PK_ALGO, key->key.ext.userdata); else return key->pk_algorithm; default: @@ -558,12 +558,11 @@ gnutls_privkey_import_ext2(gnutls_privkey_t pkey, /** * gnutls_privkey_import_ext3: * @pkey: The private key - * @pk: The public key algorithm, when @pk_func isn't provided * @userdata: private data to be provided to the callbacks * @sign_fn: callback for signature operations * @decrypt_fn: callback for decryption operations * @deinit_fn: a deinitialization function - * @pk_fn: returns the public key algorithm (may be %NULL; if set @pk will be ignored) + * @info_fn: returns info about the public key algorithm (should not be %NULL) * @flags: Flags for the import * * This function will associate the given callbacks with the @@ -576,6 +575,9 @@ gnutls_privkey_import_ext2(gnutls_privkey_t pkey, * will be provided, and the signing function is expected to do the PKCS #1 * 1.5 padding and the exponentiation. * + * The @info_fn must provide information on %GNUTLS_PRIVKEY_INFO_PK_ALGO and + * %GNUTLS_PRIVKEY_INFO_PK_ALGO, and should return -1 on unknown flags. + * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * @@ -588,7 +590,7 @@ gnutls_privkey_import_ext3(gnutls_privkey_t pkey, gnutls_privkey_sign_func sign_fn, gnutls_privkey_decrypt_func decrypt_fn, gnutls_privkey_deinit_func deinit_fn, - gnutls_privkey_pk_func pk_fn, + gnutls_privkey_info_func info_fn, unsigned int flags) { int ret; @@ -602,13 +604,15 @@ gnutls_privkey_import_ext3(gnutls_privkey_t pkey, if (sign_fn == NULL && decrypt_fn == NULL) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + if (info_fn == NULL) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + pkey->key.ext.sign_func = sign_fn; pkey->key.ext.decrypt_func = decrypt_fn; pkey->key.ext.deinit_func = deinit_fn; - pkey->key.ext.pk_func = pk_fn; + pkey->key.ext.info_func = info_fn; pkey->key.ext.userdata = userdata; pkey->type = GNUTLS_PRIVKEY_EXT; - pkey->pk_algorithm = pk; pkey->flags = flags; /* Ensure gnutls_privkey_deinit() calls the deinit_func */ @@ -1337,3 +1341,24 @@ int gnutls_privkey_verify_params(gnutls_privkey_t key) return 0; } +/*- + * _gnutls_privkey_get_preferred_sign_algo: + * @key: should contain a #gnutls_privkey_t structure + * + * This function returns the preferred signature algorithm for this + * private key. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a + * negative error value. + * + * Since: 3.4.0 + -*/ +gnutls_sign_algorithm_t +_gnutls_privkey_get_preferred_sign_algo(gnutls_privkey_t key) +{ + if (key->type == GNUTLS_PRIVKEY_EXT) { + if (key->key.ext.info_func) + return key->key.ext.info_func(key, GNUTLS_PRIVKEY_INFO_SIGN_ALGO, key->key.ext.userdata); + } + return key->preferred_sign_algo; +} diff --git a/lib/gnutls_sig.c b/lib/gnutls_sig.c index 5c5f4f3b30..97f463d33d 100644 --- a/lib/gnutls_sig.c +++ b/lib/gnutls_sig.c @@ -570,10 +570,15 @@ _gnutls_handshake_sign_crt_vrfy12(gnutls_session_t session, gnutls_sign_algorithm_t sign_algo; const mac_entry_st *me; - sign_algo = _gnutls_session_get_sign_algo(session, cert); - if (sign_algo == GNUTLS_SIGN_UNKNOWN) { - gnutls_assert(); - return GNUTLS_E_UNKNOWN_PK_ALGORITHM; + sign_algo = _gnutls_privkey_get_preferred_sign_algo(pkey); + if (sign_algo == GNUTLS_SIGN_UNKNOWN || + _gnutls_session_sign_algo_enabled(session, sign_algo) < 0) { + + sign_algo = _gnutls_session_get_sign_algo(session, cert); + if (sign_algo == GNUTLS_SIGN_UNKNOWN) { + gnutls_assert(); + return GNUTLS_E_UNKNOWN_PK_ALGORITHM; + } } gnutls_sign_algorithm_set_client(session, sign_algo); diff --git a/lib/includes/gnutls/abstract.h b/lib/includes/gnutls/abstract.h index d3a33e3362..0c5353e124 100644 --- a/lib/includes/gnutls/abstract.h +++ b/lib/includes/gnutls/abstract.h @@ -68,8 +68,13 @@ typedef int (*gnutls_privkey_decrypt_func) (gnutls_privkey_t key, typedef void (*gnutls_privkey_deinit_func) (gnutls_privkey_t key, void *userdata); -/* returns the public key algorithm associated with userdata */ -typedef gnutls_pk_algorithm_t (*gnutls_privkey_pk_func) (gnutls_privkey_t key, void *userdata); +/* Should return the public key algorithm (gnutls_pk_algorithm_t) */ +#define GNUTLS_PRIVKEY_INFO_PK_ALGO 1 + +/* Should return the preferred signature algorithm (gnutls_sign_algorithm_t) or 0. */ +#define GNUTLS_PRIVKEY_INFO_SIGN_ALGO (1<<1) +/* returns information on the public key associated with userdata */ +typedef int (*gnutls_privkey_info_func) (gnutls_privkey_t key, unsigned int flags, void *userdata); int gnutls_pubkey_init(gnutls_pubkey_t * key); void gnutls_pubkey_deinit(gnutls_pubkey_t key); @@ -354,7 +359,7 @@ gnutls_privkey_import_ext3(gnutls_privkey_t pkey, gnutls_privkey_sign_func sign_func, gnutls_privkey_decrypt_func decrypt_func, gnutls_privkey_deinit_func deinit_func, - gnutls_privkey_pk_func pk_func, + gnutls_privkey_info_func info_func, unsigned int flags); int gnutls_privkey_import_dsa_raw(gnutls_privkey_t key, |