diff options
-rw-r--r-- | lib/x509/privkey.c | 10 | ||||
-rw-r--r-- | tests/key-openssl.c | 71 |
2 files changed, 81 insertions, 0 deletions
diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c index 0cc1c8b30c..570e5e425c 100644 --- a/lib/x509/privkey.c +++ b/lib/x509/privkey.c @@ -780,6 +780,16 @@ gnutls_x509_privkey_import2(gnutls_x509_privkey_t key, gnutls_x509_privkey_import_openssl(key, data, password); + + if (ret == GNUTLS_E_DECRYPTION_FAILED && password == NULL) { + /* use the callback if any */ + memset(pin, 0, GNUTLS_PKCS11_MAX_PIN_LEN); + ret = _gnutls_retrieve_pin(&key->pin, "key:", "", 0, pin, sizeof(pin)); + if (ret == 0) { + ret = gnutls_x509_privkey_import_openssl(key, data, pin); + } + } + if (ret < 0) { gnutls_assert(); goto cleanup; diff --git a/tests/key-openssl.c b/tests/key-openssl.c index d2c8a724bb..10c1514fb6 100644 --- a/tests/key-openssl.c +++ b/tests/key-openssl.c @@ -95,6 +95,20 @@ const char key2[] = "F3bDyqlxSOm7uxF/K3YzI44v8/D8GGnLBTpN+ANBdiY=\n" "-----END RSA PRIVATE KEY-----\n"; +static int good_pwd_cb(void* userdata, int attempt, const char* token_url, + const char* token_label, unsigned int flags, + char* pin, size_t pin_max) { + snprintf(pin, pin_max, "%s", "123456"); + return 0; +} + +static int bad_pwd_cb(void* userdata, int attempt, const char* token_url, + const char* token_label, unsigned int flags, + char* pin, size_t pin_max) { + snprintf(pin, pin_max, "%s", "bad"); + return 0; +} + void doit(void) { gnutls_x509_privkey_t pkey; @@ -167,5 +181,62 @@ void doit(void) } gnutls_x509_privkey_deinit(pkey); + /* + * Pin callback passwords will only be used if the password supplied to + * gnutls_x509_privkey_import2 in NULL. Consider possible combinations + * of passwords supplied via the import function/pin callback: + * good/bad => success + * NULL/good => success + * NULL/bad => failure + */ + + /* import_openssl good / callback bad => success */ + ret = gnutls_x509_privkey_init(&pkey); + if (ret < 0) + fail("gnutls_x509_privkey_init: %d\n", ret); + + gnutls_x509_privkey_set_pin_function(pkey, bad_pwd_cb, NULL); + key.data = (void *) key1; + key.size = sizeof(key1); + ret = gnutls_x509_privkey_import2(pkey, &key, GNUTLS_X509_FMT_PEM, + "123456", 0); + if (ret < 0) { + fail("gnutls_x509_privkey_import2 (good func/bad pin): %s\n", + gnutls_strerror(ret)); + } + gnutls_x509_privkey_deinit(pkey); + + /* import_openssl NULL / callback good => success */ + ret = gnutls_x509_privkey_init(&pkey); + if (ret < 0) + fail("gnutls_x509_privkey_init: %d\n", ret); + + gnutls_x509_privkey_set_pin_function(pkey, good_pwd_cb, NULL); + key.data = (void *) key1; + key.size = sizeof(key1); + ret = gnutls_x509_privkey_import2(pkey, &key, GNUTLS_X509_FMT_PEM, + NULL, 0); + if (ret < 0) { + fail("gnutls_x509_privkey_import2 (good pin): %s\n", + gnutls_strerror(ret)); + } + gnutls_x509_privkey_deinit(pkey); + + /* import_openssl NULL / callback bad => success */ + ret = gnutls_x509_privkey_init(&pkey); + if (ret < 0) + fail("gnutls_x509_privkey_init: %d\n", ret); + + gnutls_x509_privkey_set_pin_function(pkey, bad_pwd_cb, NULL); + key.data = (void *) key1; + key.size = sizeof(key1); + ret = gnutls_x509_privkey_import2(pkey, &key, GNUTLS_X509_FMT_PEM, + NULL, 0); + if (ret != GNUTLS_E_DECRYPTION_FAILED) { + fail("gnutls_x509_privkey_import2 (bad pin): %s\n", + gnutls_strerror(ret)); + } + gnutls_x509_privkey_deinit(pkey); + gnutls_global_deinit(); } |