diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2018-10-15 15:59:48 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2018-10-24 11:04:25 +0200 |
commit | f68a86202bd1aaeb3988566def4374359b211875 (patch) | |
tree | aeeaabaf6a12c9f35315e3a0f4f5f99afb5d3af7 /lib | |
parent | 1d5e93dbd69358fe7d66a3a6dd461d7fbb0738ee (diff) | |
download | gnutls-f68a86202bd1aaeb3988566def4374359b211875.tar.gz |
p11tool: fix initialization of security officer's PINtmp-initialize-so-pin-fix
Previously we would call gnutls_pkcs11_token_set_pin() without an
old PIN provided, which will result to the use of C_InitPIN() on the
underlying module. The C_InitPIN() in contrast with C_SetPIN() will
only work for the user and not for the administrator. As such, we
always provide the oldpin for when we change the admin's PIN.
Resolves #561
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pkcs11.c | 14 | ||||
-rw-r--r-- | lib/pkcs11_int.h | 7 | ||||
-rw-r--r-- | lib/pkcs11_write.c | 40 |
3 files changed, 47 insertions, 14 deletions
diff --git a/lib/pkcs11.c b/lib/pkcs11.c index 9909127903..1a335ea959 100644 --- a/lib/pkcs11.c +++ b/lib/pkcs11.c @@ -35,9 +35,7 @@ #include <pin.h> #include <pkcs11_int.h> -#include <p11-kit/p11-kit.h> #include "pkcs11x.h" -#include <p11-kit/pin.h> #include <system-keys.h> #include "x509/x509_int.h" @@ -2781,10 +2779,10 @@ retrieve_pin_from_callback(const struct pin_info_st *pin_info, return 0; } -static int -retrieve_pin(struct pin_info_st *pin_info, struct p11_kit_uri *info, - struct ck_token_info *token_info, int attempts, - ck_user_type_t user_type, struct p11_kit_pin **pin) +int +pkcs11_retrieve_pin(struct pin_info_st *pin_info, struct p11_kit_uri *info, + struct ck_token_info *token_info, int attempts, + ck_user_type_t user_type, struct p11_kit_pin **pin) { const char *pinfile; int ret = GNUTLS_E_PKCS11_PIN_ERROR; @@ -2930,8 +2928,8 @@ pkcs11_login(struct pkcs11_session_info *sinfo, } ret = - retrieve_pin(pin_info, info, &tinfo, attempt++, - user_type, &pin); + pkcs11_retrieve_pin(pin_info, info, &tinfo, attempt++, + user_type, &pin); if (ret < 0) { gnutls_assert(); goto cleanup; diff --git a/lib/pkcs11_int.h b/lib/pkcs11_int.h index f52db0780c..76c09b460a 100644 --- a/lib/pkcs11_int.h +++ b/lib/pkcs11_int.h @@ -31,6 +31,8 @@ #define PKCS11_ID_SIZE 128 #define PKCS11_LABEL_SIZE 128 +#include <p11-kit/p11-kit.h> +#include <p11-kit/pin.h> #include <p11-kit/uri.h> typedef unsigned char ck_bool_t; @@ -269,6 +271,11 @@ static inline int pk_to_genmech(gnutls_pk_algorithm_t pk, ck_key_type_t *type) } } +int +pkcs11_retrieve_pin(struct pin_info_st *pin_info, struct p11_kit_uri *info, + struct ck_token_info *token_info, int attempts, + ck_user_type_t user_type, struct p11_kit_pin **pin); + ck_object_class_t pkcs11_type_to_class(gnutls_pkcs11_obj_type_t type); ck_rv_t diff --git a/lib/pkcs11_write.c b/lib/pkcs11_write.c index 35207d5543..cb5b65d508 100644 --- a/lib/pkcs11_write.c +++ b/lib/pkcs11_write.c @@ -1193,6 +1193,8 @@ gnutls_pkcs11_token_init(const char *token_url, } +#define L(x) ((x==NULL)?0:strlen(x)) + /** * gnutls_pkcs11_token_set_pin: * @token_url: A PKCS #11 URL specifying a token @@ -1200,9 +1202,11 @@ gnutls_pkcs11_token_init(const char *token_url, * @newpin: new user's PIN * @flags: one of #gnutls_pin_flag_t. * - * This function will modify or set a user's PIN for the given token. - * If it is called to set a user pin for first time the oldpin must - * be NULL. + * This function will modify or set a user or administrator's PIN for + * the given token. If it is called to set a PIN for first time + * the oldpin must be %NULL. When setting the admin's PIN with the + * %GNUTLS_PIN_SO flag, the @oldpin value must be provided (this requirement + * is relaxed after GnuTLS 3.6.5 since which the PIN will be requested if missing). * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. @@ -1240,7 +1244,8 @@ gnutls_pkcs11_token_set_pin(const char *token_url, return ret; } - if (oldpin == NULL) { + if (oldpin == NULL && !(flags & GNUTLS_PIN_SO)) { + /* This changes only the user PIN */ rv = pkcs11_init_pin(sinfo.module, sinfo.pks, (uint8_t *) newpin, strlen(newpin)); if (rv != CKR_OK) { @@ -1251,9 +1256,32 @@ gnutls_pkcs11_token_set_pin(const char *token_url, goto finish; } } else { + struct p11_kit_pin *pin; + unsigned oldpin_size; + + oldpin_size = L(oldpin); + + if (!(sinfo.tinfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH)) { + if (newpin == NULL) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + if (oldpin == NULL) { + struct pin_info_st pin_info; + memset(&pin_info, 0, sizeof(pin_info)); + + ret = pkcs11_retrieve_pin(&pin_info, info, &sinfo.tinfo, 0, CKU_SO, &pin); + if (ret < 0) { + gnutls_assert(); + goto finish; + } + oldpin = (const char*)p11_kit_pin_get_value(pin, NULL); + oldpin_size = p11_kit_pin_get_length(pin); + } + } + rv = pkcs11_set_pin(sinfo.module, sinfo.pks, - oldpin, strlen(oldpin), - newpin, strlen(newpin)); + oldpin, oldpin_size, + newpin, L(newpin)); if (rv != CKR_OK) { gnutls_assert(); _gnutls_debug_log("p11: %s\n", |