From: Nikos Mavrogiannopoulos Date: Fri, 7 Oct 2011 15:47:09 +0000 (+0200) Subject: Added new signing callback in gnutls_privkey_t. X-Git-Tag: gnutls_3_0_4~28 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8128354e41015c15e27a0bf7c4eb785fff51d08c;p=thirdparty%2Fgnutls.git Added new signing callback in gnutls_privkey_t. --- diff --git a/NEWS b/NEWS index b240191cf3..b01bbb4bc6 100644 --- a/NEWS +++ b/NEWS @@ -24,8 +24,13 @@ Used to get the PKIX Authority Information Access (AIA) field. ** libgnutls: gnutls_x509_crt_print supports printing AIA fields. +** libgnutls: Added ability to gnutls_privkey_t to operate with +signing callback function. + ** API and ABI modifications: gnutls_x509_crt_get_authority_info_access (x509.h): Added function. +gnutls_privkey_import_ext: Added function. +gnutls_certificate_set_key: Added function. gnutls_info_access_what_t (x509.h): Added enum. GNUTLS_OID_AIA (x509.h): Added symbol. GNUTLS_OID_AD_OCSP (x509.h): Added symbol. diff --git a/doc/cha-auth.texi b/doc/cha-auth.texi index 1cfa08d595..fcbe26bce1 100644 --- a/doc/cha-auth.texi +++ b/doc/cha-auth.texi @@ -83,7 +83,8 @@ certificate certifies the one before it. The trusted authority's certificate need not to be included, since the peer should possess it already. -@showfuncE{gnutls_certificate_set_x509_key,gnutls_certificate_set_x509_key_mem,gnutls_certificate_set_openpgp_key,gnutls_certificate_set_openpgp_key_file,gnutls_certificate_set_openpgp_key_mem} +@showfuncD{gnutls_certificate_set_x509_key_mem,gnutls_certificate_set_openpgp_key,gnutls_certificate_set_openpgp_key_file,gnutls_certificate_set_openpgp_key_mem} +@showfuncB{gnutls_certificate_set_x509_key,gnutls_certificate_set_key} @showfuncdesc{gnutls_certificate_set_x509_key_file} diff --git a/doc/cha-cert-auth.texi b/doc/cha-cert-auth.texi index f1309bd720..26a23e7eb1 100644 --- a/doc/cha-cert-auth.texi +++ b/doc/cha-cert-auth.texi @@ -588,7 +588,7 @@ are not extractable. @showfuncdesc{gnutls_privkey_import_x509} -@showfuncB{gnutls_privkey_import_openpgp,gnutls_privkey_import_pkcs11} +@showfuncC{gnutls_privkey_import_openpgp,gnutls_privkey_import_pkcs11,gnutls_privkey_import_ext} @showfuncdesc{gnutls_privkey_get_pk_algorithm} @showfuncdesc{gnutls_privkey_get_type} diff --git a/lib/auth/cert.c b/lib/auth/cert.c index 2deb5e2b64..fddc10249a 100644 --- a/lib/auth/cert.c +++ b/lib/auth/cert.c @@ -620,6 +620,10 @@ call_get_cert_callback (gnutls_session_t session, } } break; + default: + gnutls_assert(); + ret = GNUTLS_E_INVALID_REQUEST; + goto cleanup; } _gnutls_selected_certs_set (session, local_certs, diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c index e72a662e43..802f671672 100644 --- a/lib/gnutls_cert.c +++ b/lib/gnutls_cert.c @@ -790,7 +790,7 @@ gnutls_certificate_activation_time_peers (gnutls_session_t session) * can be used to store application-specific data needed in the * callback function. See also gnutls_sign_callback_get(). * - * Deprecated: Use the PKCS 11 interfaces instead. + * Deprecated: Use the PKCS 11 or #gnutls_privkey_t interfacess instead. */ void gnutls_sign_callback_set (gnutls_session_t session, diff --git a/lib/gnutls_privkey.c b/lib/gnutls_privkey.c index 87ed1c17fe..f572ce5e92 100644 --- a/lib/gnutls_privkey.c +++ b/lib/gnutls_privkey.c @@ -47,6 +47,11 @@ struct gnutls_privkey_st #ifdef ENABLE_OPENPGP gnutls_openpgp_privkey_t openpgp; #endif + struct { + gnutls_privkey_sign_func sign_func; + gnutls_privkey_decrypt_func decrypt_func; + void* userdata; + } ext; } key; unsigned int flags; @@ -101,6 +106,10 @@ gnutls_privkey_get_pk_algorithm (gnutls_privkey_t key, unsigned int *bits) if (bits) *bits = _gnutls_mpi_get_nbits (key->key.x509->params.params[0]); return gnutls_x509_privkey_get_pk_algorithm (key->key.x509); + case GNUTLS_PRIVKEY_EXT: + if (bits) + *bits = 0; + return key->pk_algorithm; default: gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; @@ -359,6 +368,54 @@ int ret; #endif /* ENABLE_PKCS11 */ +/** + * gnutls_privkey_import_ext: + * @pkey: The private key + * @pk: The public key algorithm + * @userdata: private data to be provided to the callbacks + * @sign_func: callback for signature operations + * @decrypt_func: callback for decryption operations + * @flags: Flags for the import + * + * This function will associate the given callbacks with the + * #gnutls_privkey_t structure. At least one of the two callbacks + * must be non-null. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a + * negative error value. + * + * Since: 3.0.0 + **/ +int +gnutls_privkey_import_ext (gnutls_privkey_t pkey, + gnutls_pk_algorithm_t pk, + void* userdata, + gnutls_privkey_sign_func sign_func, + gnutls_privkey_decrypt_func decrypt_func, + unsigned int flags) +{ +int ret; + + ret = check_if_clean(pkey); + if (ret < 0) + { + gnutls_assert(); + return ret; + } + + if (sign_func == NULL && decrypt_func == NULL) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + pkey->key.ext.sign_func = sign_func; + pkey->key.ext.decrypt_func = decrypt_func; + pkey->key.ext.userdata = userdata; + pkey->type = GNUTLS_PRIVKEY_EXT; + pkey->pk_algorithm = pk; + pkey->flags = flags; + + return 0; +} + /** * gnutls_privkey_import_x509: * @pkey: The private key @@ -646,6 +703,10 @@ _gnutls_privkey_sign_hash (gnutls_privkey_t key, return _gnutls_soft_sign (key->key.x509->pk_algorithm, &key->key.x509->params, hash, signature); + case GNUTLS_PRIVKEY_EXT: + if (key->key.ext.sign_func == NULL) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + return key->key.ext.sign_func(key, key->key.ext.userdata, hash, signature); default: gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; @@ -696,6 +757,11 @@ gnutls_privkey_decrypt_data (gnutls_privkey_t key, flags, ciphertext, plaintext); #endif + case GNUTLS_PRIVKEY_EXT: + if (key->key.ext.decrypt_func == NULL) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + return key->key.ext.decrypt_func(key, key->key.ext.userdata, ciphertext, plaintext); default: gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c index 1d4ed53010..025456364f 100644 --- a/lib/gnutls_x509.c +++ b/lib/gnutls_x509.c @@ -1099,6 +1099,83 @@ cleanup: return ret; } +/** + * gnutls_certificate_set_key: + * @res: is a #gnutls_certificate_credentials_t structure. + * @name: is the DNS name of the certificate (NULL if none) + * @pcert_list: contains a certificate list (path) for the specified private key + * @pcert_list_size: holds the size of the certificate list + * @key: is a gnutls_x509_privkey_t key + * + * This function sets a certificate/private key pair in the + * gnutls_certificate_credentials_t structure. This function may be + * called more than once, in case multiple keys/certificates exist for + * the server. For clients that wants to send more than its own end + * entity certificate (e.g., also an intermediate CA cert) then put + * the certificate chain in @pcert_list. The @pcert_list and @key will + * become part of the credentials structure and must not + * be deallocated. They will be automatically deallocated when + * @res is deinitialized. + * + * Returns: %GNUTLS_E_SUCCESS (0) on success, or a negative error code. + * + * Since: 3.0.0 + **/ +int +gnutls_certificate_set_key (gnutls_certificate_credentials_t res, + const char** names, + int names_size, + gnutls_pcert_st * pcert_list, + int pcert_list_size, + gnutls_privkey_t key) +{ + int ret, i; + gnutls_str_array_t str_names; + + _gnutls_str_array_init(&str_names); + + if (names != NULL && names_size > 0) + { + for (i=0;incerts++; + + if ((ret = _gnutls_check_key_cert_match (res)) < 0) + { + gnutls_assert (); + return ret; + } + + return 0; + +cleanup: + _gnutls_str_array_clear(&str_names); + return ret; +} + /** * gnutls_certificate_set_x509_key_file: * @res: is a #gnutls_certificate_credentials_t structure. diff --git a/lib/includes/gnutls/abstract.h b/lib/includes/gnutls/abstract.h index 2d570798a6..7644e18025 100644 --- a/lib/includes/gnutls/abstract.h +++ b/lib/includes/gnutls/abstract.h @@ -37,6 +37,15 @@ typedef struct gnutls_pubkey_st *gnutls_pubkey_t; struct gnutls_privkey_st; typedef struct gnutls_privkey_st *gnutls_privkey_t; +typedef int (*gnutls_privkey_sign_func) (gnutls_privkey_t key, + void *userdata, + const gnutls_datum_t * raw_data, + gnutls_datum_t * signature); +typedef int (*gnutls_privkey_decrypt_func) (gnutls_privkey_t key, + void *userdata, + const gnutls_datum_t * ciphertext, + gnutls_datum_t * plaintext); + int gnutls_pubkey_init (gnutls_pubkey_t * key); void gnutls_pubkey_deinit (gnutls_pubkey_t key); int gnutls_pubkey_get_pk_algorithm (gnutls_pubkey_t key, unsigned int *bits); @@ -157,6 +166,13 @@ int gnutls_privkey_import_x509 (gnutls_privkey_t pkey, int gnutls_privkey_import_openpgp (gnutls_privkey_t pkey, gnutls_openpgp_privkey_t key, unsigned int flags); +int +gnutls_privkey_import_ext (gnutls_privkey_t pkey, + gnutls_pk_algorithm_t pk, + void* userdata, + gnutls_privkey_sign_func sign_func, + gnutls_privkey_decrypt_func decrypt_func, + unsigned int flags); int gnutls_privkey_sign_data (gnutls_privkey_t signer, gnutls_digest_algorithm_t hash, @@ -252,9 +268,16 @@ void gnutls_pcert_deinit (gnutls_pcert_st* pcert); gnutls_privkey_t *privkey); - void gnutls_certificate_set_retrieve_function2 - (gnutls_certificate_credentials_t cred, - gnutls_certificate_retrieve_function2 * func); +void gnutls_certificate_set_retrieve_function2 + (gnutls_certificate_credentials_t cred, + gnutls_certificate_retrieve_function2 * func); +int +gnutls_certificate_set_key (gnutls_certificate_credentials_t res, + const char** name, + int name_size, + gnutls_pcert_st * pcert_list, + int pcert_list_size, + gnutls_privkey_t key); #endif diff --git a/lib/includes/gnutls/compat.h b/lib/includes/gnutls/compat.h index becf98bb12..d18424b34f 100644 --- a/lib/includes/gnutls/compat.h +++ b/lib/includes/gnutls/compat.h @@ -192,7 +192,7 @@ void func) _GNUTLS_GCC_ATTR_DEPRECATED; /* External signing callback. No longer supported because it - * was deprecated by the PKCS #11 API. */ + * was deprecated by the PKCS #11 API and gnutls_privkey_t. */ typedef int (*gnutls_sign_func) (gnutls_session_t session, void *userdata, gnutls_certificate_type_t cert_type, diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index 83d4743ef0..77ee1f49be 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -1468,6 +1468,7 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get(gnutls_session_t session); * @GNUTLS_PRIVKEY_X509: X.509 private key, #gnutls_x509_privkey_t. * @GNUTLS_PRIVKEY_OPENPGP: OpenPGP private key, #gnutls_openpgp_privkey_t. * @GNUTLS_PRIVKEY_PKCS11: PKCS11 private key, #gnutls_pkcs11_privkey_t. + * @GNUTLS_PRIVKEY_EXT: External private key, operating using callbacks. * * Enumeration of different private key types. */ @@ -1475,7 +1476,8 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get(gnutls_session_t session); { GNUTLS_PRIVKEY_X509, GNUTLS_PRIVKEY_OPENPGP, - GNUTLS_PRIVKEY_PKCS11 + GNUTLS_PRIVKEY_PKCS11, + GNUTLS_PRIVKEY_EXT } gnutls_privkey_type_t; typedef struct gnutls_retr2_st diff --git a/lib/libgnutls.map b/lib/libgnutls.map index b80f7bc0f8..4d3ba84b9b 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -718,6 +718,8 @@ GNUTLS_3_0_0 { gnutls_pubkey_import_ecc_raw2; gnutls_record_get_discarded; gnutls_x509_crt_get_authority_info_access; + gnutls_privkey_import_ext; + gnutls_certificate_set_key; } GNUTLS_2_12; GNUTLS_PRIVATE {