summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2018-04-28 11:14:34 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2018-05-03 09:19:57 +0200
commit333864750739df33020a8b48563051565100ba04 (patch)
treeed098d666d10feb1dab6ffa483da49bb70d3940f
parent0ce2a9b327c39a6ef98f411fed5da207091af813 (diff)
downloadgnutls-tmp-pkcs11-sensitive-fix.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--NEWS6
-rw-r--r--doc/cha-upgrade.texi3
-rw-r--r--lib/includes/gnutls/pkcs11.h4
-rw-r--r--lib/pkcs11.c8
-rw-r--r--lib/pkcs11_privkey.c6
-rw-r--r--lib/pkcs11_secret.c2
-rw-r--r--lib/pkcs11_write.c22
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/pkcs11/pkcs11-privkey-generate.c170
9 files changed, 206 insertions, 17 deletions
diff --git a/NEWS b/NEWS
index 361df5b64e..4858dab6aa 100644
--- a/NEWS
+++ b/NEWS
@@ -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