diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2018-04-28 11:14:34 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2018-05-03 09:19:57 +0200 |
commit | 333864750739df33020a8b48563051565100ba04 (patch) | |
tree | ed098d666d10feb1dab6ffa483da49bb70d3940f | |
parent | 0ce2a9b327c39a6ef98f411fed5da207091af813 (diff) | |
download | gnutls-333864750739df33020a8b48563051565100ba04.tar.gz |
pkcs11: mark private key objects as sensitive by defaulttmp-pkcs11-sensitive-fix
That is, to prevent accidentally creating objects which can
be exported.
Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>
-rw-r--r-- | NEWS | 6 | ||||
-rw-r--r-- | doc/cha-upgrade.texi | 3 | ||||
-rw-r--r-- | lib/includes/gnutls/pkcs11.h | 4 | ||||
-rw-r--r-- | lib/pkcs11.c | 8 | ||||
-rw-r--r-- | lib/pkcs11_privkey.c | 6 | ||||
-rw-r--r-- | lib/pkcs11_secret.c | 2 | ||||
-rw-r--r-- | lib/pkcs11_write.c | 22 | ||||
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rw-r--r-- | tests/pkcs11/pkcs11-privkey-generate.c | 170 |
9 files changed, 206 insertions, 17 deletions
@@ -40,6 +40,11 @@ See the end for copying conditions. as TLS1.2 requires specific ordering of the groups based on the ciphersuite ordering, making group order unpredictable under TLS1.3. +** libgnutls: gnutls_pkcs11_copy_secret_key, gnutls_pkcs11_copy_x509_privkey2, + gnutls_pkcs11_privkey_generate3 will mark objects as sensitive by default + unless GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE is specified. This is an API + change for these functions which make them err towards safety. + ** API and ABI modifications: gnutls_fips140_set_mode: Added gnutls_session_key_update: Added @@ -56,6 +61,7 @@ gnutls_certificate_get_ocsp_expiration: Added gnutls_record_send2: Added gnutls_ext_raw_parse: Added GNUTLS_PRIVKEY_INFO_PK_ALGO_BITS: Added +GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE: Added * Version 3.6.2 (released 2018-02-16) diff --git a/doc/cha-upgrade.texi b/doc/cha-upgrade.texi index 1db04aa255..337331e356 100644 --- a/doc/cha-upgrade.texi +++ b/doc/cha-upgrade.texi @@ -222,4 +222,7 @@ flag using @funcref{gnutls_certificate_set_flags}. @tab It is replaced by separate key update and re-authentication functionality which can be accessed directly via @funcref{gnutls_session_key_update} and @funcref{gnutls_reauth}. +@item @funcref{gnutls_pkcs11_privkey_generate3}, @funcref{gnutls_pkcs11_copy_secret_key}, @funcref{gnutls_pkcs11_copy_x509_privkey2} +@tab These functions no longer create an exportable key by default; they require the flag @code{GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE} to do so. + @end multitable diff --git a/lib/includes/gnutls/pkcs11.h b/lib/includes/gnutls/pkcs11.h index 52f7898b44..630fb7d014 100644 --- a/lib/includes/gnutls/pkcs11.h +++ b/lib/includes/gnutls/pkcs11.h @@ -95,7 +95,7 @@ void gnutls_pkcs11_obj_set_pin_function(gnutls_pkcs11_obj_t obj, * gnutls_pkcs11_obj_flags: * @GNUTLS_PKCS11_OBJ_FLAG_LOGIN: Force login in the token for the operation (seek+store). * @GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED: object marked as trusted (seek+store). - * @GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE: object marked as sensitive -unexportable (store). + * @GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE: object is explicitly marked as sensitive -unexportable (store). * @GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO: force login as a security officer in the token for the operation (seek+store). * @GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE: marked as private -requires PIN to access (store). * @GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE: marked as not private (store). @@ -117,6 +117,7 @@ void gnutls_pkcs11_obj_set_pin_function(gnutls_pkcs11_obj_t obj, * @GNUTLS_PKCS11_OBJ_FLAG_PUBKEY: When searching, restrict to public key objects only (seek). * @GNUTLS_PKCS11_OBJ_FLAG_PRIVKEY: When searching, restrict to private key objects only (seek). * @GNUTLS_PKCS11_OBJ_FLAG_NO_STORE_PUBKEY: When generating a keypair don't store the public key (store). + * @GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE: object marked as not sensitive -exportable (store). * * Enumeration of different PKCS #11 object flags. Some flags are used * to mark objects when storing, while others are also used while seeking @@ -147,6 +148,7 @@ typedef enum gnutls_pkcs11_obj_flags { GNUTLS_PKCS11_OBJ_FLAG_PUBKEY = (1<<20), GNUTLS_PKCS11_OBJ_FLAG_NO_STORE_PUBKEY = GNUTLS_PKCS11_OBJ_FLAG_PUBKEY, GNUTLS_PKCS11_OBJ_FLAG_PRIVKEY = (1<<21), + GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE = (1<<22), /* flags 1<<29 and later are reserved - see pkcs11_int.h */ } gnutls_pkcs11_obj_flags; diff --git a/lib/pkcs11.c b/lib/pkcs11.c index e4d14f9f4b..395a7e59aa 100644 --- a/lib/pkcs11.c +++ b/lib/pkcs11.c @@ -1922,8 +1922,12 @@ pkcs11_import_object(ck_object_handle_t ctx, ck_object_class_t class, a[0].value_len = sizeof(b); rv = pkcs11_get_attribute_value(sinfo->module, sinfo->pks, ctx, a, 1); - if (rv == CKR_OK && b != 0) - pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE; + if (rv == CKR_OK) { + if (b != 0) + pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE; + else + pobj->flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE; + } a[0].type = CKA_EXTRACTABLE; a[0].value = &b; diff --git a/lib/pkcs11_privkey.c b/lib/pkcs11_privkey.c index 48e4836ab2..b721ed1252 100644 --- a/lib/pkcs11_privkey.c +++ b/lib/pkcs11_privkey.c @@ -880,8 +880,8 @@ _dsa_params_generate(struct ck_function_list *module, ck_session_handle_t sessio * can be substituted in the place of the bits parameter using the * GNUTLS_CURVE_TO_BITS() macro. * - * It is highly recommended flags to contain %GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE - * unless there is a strong reason not to. + * Since 3.6.3 the objects are marked as sensitive by default unless + * %GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE is specified. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. @@ -1127,7 +1127,7 @@ gnutls_pkcs11_privkey_generate3(const char *url, gnutls_pk_algorithm_t pk, a_val++; } - if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE) { + if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE)) { p[p_val].type = CKA_SENSITIVE; p[p_val].value = (void *) &tval; p[p_val].value_len = sizeof(tval); diff --git a/lib/pkcs11_secret.c b/lib/pkcs11_secret.c index b9a88549ee..83cdf58457 100644 --- a/lib/pkcs11_secret.c +++ b/lib/pkcs11_secret.c @@ -119,7 +119,7 @@ gnutls_pkcs11_copy_secret_key(const char *token_url, gnutls_datum_t * key, a_val++; } - if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE) + if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE)) tval = 1; else tval = 0; diff --git a/lib/pkcs11_write.c b/lib/pkcs11_write.c index 4386f727e1..e55bcbeda4 100644 --- a/lib/pkcs11_write.c +++ b/lib/pkcs11_write.c @@ -91,8 +91,8 @@ static void mark_flags(unsigned flags, struct ck_attribute *a, unsigned *a_val, * * This function will copy a certificate into a PKCS #11 token specified by * a URL. Valid flags to mark the certificate: %GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED, - * %GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE, %GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE, - * %GNUTLS_PKCS11_OBJ_FLAG_MARK_CA, %GNUTLS_PKCS11_OBJ_FLAG_MARK_ALWAYS_AUTH. + * %GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE, %GNUTLS_PKCS11_OBJ_FLAG_MARK_CA, + * %GNUTLS_PKCS11_OBJ_FLAG_MARK_ALWAYS_AUTH. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. @@ -374,8 +374,8 @@ static int add_pubkey(gnutls_pubkey_t pubkey, struct ck_attribute *a, unsigned * * * This function will copy a public key object into a PKCS #11 token specified by * a URL. Valid flags to mark the key: %GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED, - * %GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE, %GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE, - * %GNUTLS_PKCS11_OBJ_FLAG_MARK_CA, %GNUTLS_PKCS11_OBJ_FLAG_MARK_ALWAYS_AUTH. + * %GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE, %GNUTLS_PKCS11_OBJ_FLAG_MARK_CA, + * %GNUTLS_PKCS11_OBJ_FLAG_MARK_ALWAYS_AUTH. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. @@ -625,8 +625,10 @@ gnutls_pkcs11_copy_attached_extension(const char *token_url, * @flags: One of GNUTLS_PKCS11_OBJ_* flags * * This function will copy a private key into a PKCS #11 token specified by - * a URL. It is highly recommended flags to contain %GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE - * unless there is a strong reason not to. + * a URL. + * + * Since 3.6.3 the objects are marked as sensitive by default unless + * %GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE is specified. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. @@ -782,7 +784,7 @@ gnutls_pkcs11_copy_x509_privkey2(const char *token_url, a_val++; } - if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE) { + if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE)) { a[a_val].type = CKA_SENSITIVE; a[a_val].value = (void *) &tval; a[a_val].value_len = sizeof(tval); @@ -1356,8 +1358,10 @@ int gnutls_pkcs11_copy_x509_crt(const char *token_url, * @flags: One of GNUTLS_PKCS11_OBJ_* flags * * This function will copy a private key into a PKCS #11 token specified by - * a URL. It is highly recommended flags to contain %GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE - * unless there is a strong reason not to. + * a URL. + * + * Since 3.6.3 the objects are marked as sensitive by default unless + * %GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE is specified. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. diff --git a/tests/Makefile.am b/tests/Makefile.am index 77819a3777..27560204d7 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -321,7 +321,7 @@ ctests += pkcs11-cert-import-url-exts pkcs11-get-exts pkcs11-get-raw-issuer-exts pkcs11-privkey-always-auth pkcs11-privkey-export pkcs11/pkcs11-import-with-pin \ pkcs11/pkcs11-privkey-pthread pkcs11/pkcs11-pin-func pkcs11/pkcs11-obj-import \ pkcs11-privkey-fork-reinit pkcs11-mechanisms pkcs11-privkey-safenet-always-auth \ - pkcs11/pkcs11-rsa-pss-privkey-test pkcs11/tls-neg-pkcs11-key + pkcs11/pkcs11-rsa-pss-privkey-test pkcs11/tls-neg-pkcs11-key pkcs11/pkcs11-privkey-generate endif diff --git a/tests/pkcs11/pkcs11-privkey-generate.c b/tests/pkcs11/pkcs11-privkey-generate.c new file mode 100644 index 0000000000..e831a490d9 --- /dev/null +++ b/tests/pkcs11/pkcs11-privkey-generate.c @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2018 Nikos Mavrogiannopoulos + * + * Author: Nikos Mavrogiannopoulos + * + * This file is part of GnuTLS. + * + * GnuTLS is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuTLS is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> + +#include <gnutls/gnutls.h> +#include <gnutls/x509.h> +#include <gnutls/abstract.h> +#include <gnutls/pkcs11.h> + +#ifdef _WIN32 + +void doit(void) +{ + exit(77); +} + +#else + +#include "../utils.h" +#include "softhsm.h" +#include <assert.h> + +#define CONFIG_NAME "softhsm-generate" +#define CONFIG CONFIG_NAME".config" +#define PIN "1234" +/* Tests whether a gnutls_privkey_generate3 will work generate a key + * which is marked as sensitive. + */ + +static unsigned pin_called = 0; +static const char *_pin = PIN; + +static void tls_log_func(int level, const char *str) +{ + fprintf(stderr, "|<%d>| %s", level, str); +} + +static +int pin_func(void* userdata, int attempt, const char* url, const char *label, + unsigned flags, char *pin, size_t pin_max) +{ + if (_pin == NULL) + return -1; + + strcpy(pin, _pin); + pin_called++; + return 0; +} + +void doit(void) +{ + char buf[128]; + int ret; + const char *lib, *bin; + gnutls_datum_t out; + unsigned flags; + gnutls_pkcs11_obj_t obj; + + ret = global_init(); + if (ret != 0) { + fail("%d: %s\n", ret, gnutls_strerror(ret)); + exit(1); + } + + gnutls_global_set_log_function(tls_log_func); + if (debug) + gnutls_global_set_log_level(4711); + + bin = softhsm_bin(); + + lib = softhsm_lib(); + + set_softhsm_conf(CONFIG); + snprintf(buf, sizeof(buf), "%s --init-token --slot 0 --label test --so-pin "PIN" --pin "PIN, bin); + system(buf); + + ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL); + if (ret != 0) { + fail("%d: %s\n", ret, gnutls_strerror(ret)); + exit(1); + } + + ret = gnutls_pkcs11_add_provider(lib, NULL); + if (ret != 0) { + fail("%d: %s\n", ret, gnutls_strerror(ret)); + exit(1); + } + + gnutls_pkcs11_set_pin_function(pin_func, NULL); + + /* generate sensitive */ + ret = gnutls_pkcs11_privkey_generate3("pkcs11:token=test", GNUTLS_PK_RSA, 2048, + "testkey", NULL, GNUTLS_X509_FMT_DER, + &out, 0, GNUTLS_PKCS11_OBJ_FLAG_LOGIN); + if (ret < 0) { + fail("%d: %s\n", ret, gnutls_strerror(ret)); + exit(1); + } + + assert(gnutls_pkcs11_obj_init(&obj) >= 0); + assert(out.size > 0); + + gnutls_pkcs11_obj_set_pin_function(obj, pin_func, NULL); + assert(gnutls_pkcs11_obj_import_url(obj, "pkcs11:token=test;object=testkey;type=private", GNUTLS_PKCS11_OBJ_FLAG_LOGIN) >= 0); + + assert(gnutls_pkcs11_obj_get_flags(obj, &flags) >= 0); + + assert(!(flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE)); + assert(flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE); + + gnutls_free(out.data); + gnutls_pkcs11_obj_deinit(obj); + + /* generate non-sensitive */ + ret = gnutls_pkcs11_privkey_generate3("pkcs11:token=test", GNUTLS_PK_RSA, 2048, + "testkey2", NULL, GNUTLS_X509_FMT_DER, + &out, 0, GNUTLS_PKCS11_OBJ_FLAG_LOGIN|GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE); + if (ret < 0) { + fail("%d: %s\n", ret, gnutls_strerror(ret)); + exit(1); + } + + assert(gnutls_pkcs11_obj_init(&obj) >= 0); + assert(out.size > 0); + + gnutls_pkcs11_obj_set_pin_function(obj, pin_func, NULL); + assert(gnutls_pkcs11_obj_import_url(obj, "pkcs11:token=test;object=testkey2;type=private", GNUTLS_PKCS11_OBJ_FLAG_LOGIN) >= 0); + + assert(gnutls_pkcs11_obj_get_flags(obj, &flags) >= 0); + + assert(!(flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE)); + assert(flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE); + + gnutls_free(out.data); + gnutls_pkcs11_obj_deinit(obj); + + gnutls_pkcs11_deinit(); + gnutls_global_deinit(); + remove(CONFIG); +} +#endif |