Fix CVE-2017-6891 in minitasn1 code
[platform/upstream/gnutls.git] / lib / pkcs11_privkey.c
index 9df4594..dcffe5f 100644 (file)
@@ -28,7 +28,6 @@
 #include <gnutls_sig.h>
 #include <gnutls_pk.h>
 #include <fips.h>
-#include "urls.h"
 #include <p11-kit/uri.h>
 
 /* In case of a fork, it will invalidate the open session
@@ -76,7 +75,7 @@ struct gnutls_pkcs11_privkey_st {
 
 /**
  * gnutls_pkcs11_privkey_init:
- * @key: A pointer to the type to be initialized
+ * @key: The structure to be initialized
  *
  * This function will initialize an private key structure.
  *
@@ -104,28 +103,8 @@ int gnutls_pkcs11_privkey_init(gnutls_pkcs11_privkey_t * key)
 }
 
 /**
- * gnutls_pkcs11_privkey_cpy:
- * @dst: The destination key, which should be initialized.
- * @src: The source key
- *
- * This function will copy a private key from source to destination
- * key. Destination has to be initialized.
- *
- * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
- *   negative error value.
- *
- * Since: 3.4.0
- **/
-int
-gnutls_pkcs11_privkey_cpy(gnutls_pkcs11_privkey_t dst,
-                         gnutls_pkcs11_privkey_t src)
-{
-       return gnutls_pkcs11_privkey_import_url(dst, src->url, src->flags);
-}
-
-/**
  * gnutls_pkcs11_privkey_deinit:
- * @key: the key to be deinitialized
+ * @key: The structure to be initialized
  *
  * This function will deinitialize a private key structure.
  **/
@@ -140,7 +119,7 @@ void gnutls_pkcs11_privkey_deinit(gnutls_pkcs11_privkey_t key)
 
 /**
  * gnutls_pkcs11_privkey_get_pk_algorithm:
- * @key: should contain a #gnutls_pkcs11_privkey_t type
+ * @key: should contain a #gnutls_pkcs11_privkey_t structure
  * @bits: if bits is non null it will hold the size of the parameters' in bits
  *
  * This function will return the public key algorithm of a private
@@ -160,7 +139,7 @@ gnutls_pkcs11_privkey_get_pk_algorithm(gnutls_pkcs11_privkey_t key,
 
 /**
  * gnutls_pkcs11_privkey_get_info:
- * @pkey: should contain a #gnutls_pkcs11_privkey_t type
+ * @pkey: should contain a #gnutls_pkcs11_privkey_t structure
  * @itype: Denotes the type of information requested
  * @output: where output will be stored
  * @output_size: contains the maximum size of the output and will be overwritten with actual
@@ -255,6 +234,17 @@ _gnutls_pkcs11_privkey_sign_hash(gnutls_pkcs11_privkey_t key,
 
        PKCS11_CHECK_INIT_PRIVKEY(key);
 
+       if (key->reauth) {
+               ret =
+                   pkcs11_login(&key->sinfo, &key->pin,
+                                key->uinfo, 0, 1);
+               if (ret < 0) {
+                       gnutls_assert();
+                       _gnutls_debug_log("PKCS #11 login failed, trying operation anyway\n");
+                       /* let's try the operation anyway */
+               }
+       }
+
        sinfo = &key->sinfo;
 
        mech.mechanism = pk_to_mech(key->pk_algorithm);
@@ -270,17 +260,6 @@ _gnutls_pkcs11_privkey_sign_hash(gnutls_pkcs11_privkey_t key,
                goto cleanup;
        }
 
-       if (key->reauth) {
-               ret =
-                   pkcs11_login(&key->sinfo, &key->pin,
-                                key->uinfo, 0, 1);
-               if (ret < 0) {
-                       gnutls_assert();
-                       _gnutls_debug_log("PKCS #11 login failed, trying operation anyway\n");
-                       /* let's try the operation anyway */
-               }
-       }
-
        /* Work out how long the signature must be: */
        rv = pkcs11_sign(sinfo->module, sinfo->pks, hash->data, hash->size,
                         NULL, &siglen);
@@ -377,12 +356,12 @@ int gnutls_pkcs11_privkey_status(gnutls_pkcs11_privkey_t key)
 
 /**
  * gnutls_pkcs11_privkey_import_url:
- * @pkey: The private key
+ * @pkey: The structure to store the parsed key
  * @url: a PKCS 11 url identifying the key
  * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags
  *
  * This function will "import" a PKCS 11 URL identifying a private
- * key to the #gnutls_pkcs11_privkey_t type. In reality since
+ * key to the #gnutls_pkcs11_privkey_t structure. In reality since
  * in most cases keys cannot be exported, the private key structure
  * is being associated with the available operations on the token.
  *
@@ -408,19 +387,14 @@ gnutls_pkcs11_privkey_import_url(gnutls_pkcs11_privkey_t pkey,
                pkey->url = NULL;
        }
 
-       if (pkey->uinfo) {
-               p11_kit_uri_free(pkey->uinfo);
-               pkey->uinfo = NULL;
-       }
-
        pkey->url = gnutls_strdup(url);
        if (pkey->url == NULL)
                return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
 
-       ret = pkcs11_url_to_info(pkey->url, &pkey->uinfo, flags|GNUTLS_PKCS11_OBJ_FLAG_EXPECT_PRIVKEY);
+       ret = pkcs11_url_to_info(url, &pkey->uinfo, flags|GNUTLS_PKCS11_OBJ_FLAG_EXPECT_PRIVKEY);
        if (ret < 0) {
                gnutls_assert();
-               goto cleanup;
+               return ret;
        }
 
        pkey->flags = flags;
@@ -429,8 +403,7 @@ gnutls_pkcs11_privkey_import_url(gnutls_pkcs11_privkey_t pkey,
        if (!attr || attr->value_len != sizeof(ck_object_class_t) ||
            *(ck_object_class_t *) attr->value != CKO_PRIVATE_KEY) {
                gnutls_assert();
-               ret = GNUTLS_E_INVALID_REQUEST;
-               goto cleanup;
+               return GNUTLS_E_INVALID_REQUEST;
        }
 
        attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_ID);
@@ -438,8 +411,7 @@ gnutls_pkcs11_privkey_import_url(gnutls_pkcs11_privkey_t pkey,
                attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_LABEL);
                if (!attr) {
                        gnutls_assert();
-                       ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
-                       goto cleanup;
+                       return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
                }
        }
 
@@ -451,7 +423,7 @@ gnutls_pkcs11_privkey_import_url(gnutls_pkcs11_privkey_t pkey,
 
        if (pkcs11_get_attribute_value(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, a, 1)
            == CKR_OK) {
-               pkey->pk_algorithm = key_type_to_pk(key_type);
+               pkey->pk_algorithm = mech_to_pk(key_type);
                if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN) {
                        _gnutls_debug_log
                            ("Cannot determine PKCS #11 key algorithm\n");
@@ -474,12 +446,7 @@ gnutls_pkcs11_privkey_import_url(gnutls_pkcs11_privkey_t pkey,
        return ret;
 
       cleanup:
-       if (pkey->uinfo != NULL) {
-               p11_kit_uri_free(pkey->uinfo);
-               pkey->uinfo = NULL;
-       }
-       gnutls_free(pkey->url);
-       pkey->url = NULL;
+       pkcs11_close_session(&pkey->sinfo);
 
        return ret;
 }
@@ -513,6 +480,17 @@ _gnutls_pkcs11_privkey_decrypt_data(gnutls_pkcs11_privkey_t key,
        if (key->pk_algorithm != GNUTLS_PK_RSA)
                return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
 
+       if (key->reauth) {
+               ret =
+                   pkcs11_login(&key->sinfo, &key->pin,
+                                key->uinfo, 0, 1);
+               if (ret < 0) {
+                       gnutls_assert();
+                       _gnutls_debug_log("PKCS #11 login failed, trying operation anyway\n");
+                       /* let's try the operation anyway */
+               }
+       }
+
        mech.mechanism = CKM_RSA_PKCS;
        mech.parameter = NULL;
        mech.parameter_len = 0;
@@ -526,17 +504,6 @@ _gnutls_pkcs11_privkey_decrypt_data(gnutls_pkcs11_privkey_t key,
                goto cleanup;
        }
 
-       if (key->reauth) {
-               ret =
-                   pkcs11_login(&key->sinfo, &key->pin,
-                                key->uinfo, 0, 1);
-               if (ret < 0) {
-                       gnutls_assert();
-                       _gnutls_debug_log("PKCS #11 login failed, trying operation anyway\n");
-                       /* let's try the operation anyway */
-               }
-       }
-
        /* Work out how long the plaintext must be: */
        rv = pkcs11_decrypt(key->sinfo.module, key->sinfo.pks, ciphertext->data,
                            ciphertext->size, NULL, &siglen);
@@ -593,7 +560,6 @@ gnutls_pkcs11_privkey_export_url(gnutls_pkcs11_privkey_t key,
        return 0;
 }
 
-#if 0
 /**
  * gnutls_pkcs11_privkey_generate:
  * @url: a token URL
@@ -616,7 +582,7 @@ gnutls_pkcs11_privkey_generate(const char *url, gnutls_pk_algorithm_t pk,
                               unsigned int bits, const char *label,
                               unsigned int flags)
 {
-       int x;
+       return gnutls_pkcs11_privkey_generate2(url, pk, bits, label, 0, NULL, flags);
 }
 
 /**
@@ -651,60 +617,7 @@ gnutls_pkcs11_privkey_generate2(const char *url, gnutls_pk_algorithm_t pk,
                                gnutls_datum_t * pubkey,
                                unsigned int flags)
 {
-       int x;
-}
-#endif
-
-struct dsa_params {
-       /* FIPS 186-3 maximal size for L and N length pair is (3072,256). */
-       uint8_t prime[384];
-       uint8_t subprime[32];
-       uint8_t generator[384];
-};
-
-static int
-_dsa_params_generate(struct ck_function_list *module, ck_session_handle_t session,
-                    unsigned long bits, struct dsa_params *params,
-                    struct ck_attribute *a, int *a_val)
-{
-       struct ck_mechanism mech = { CKM_DSA_PARAMETER_GEN };
-       struct ck_attribute attr = { CKA_PRIME_BITS, &bits, sizeof(bits) };
-       ck_object_handle_t key;
-       ck_rv_t rv;
-
-       /* Generate DSA parameters from prime length. */
-
-       rv = pkcs11_generate_key(module, session, &mech, &attr, 1, &key);
-       if (rv != CKR_OK) {
-               gnutls_assert();
-               _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
-               return pkcs11_rv_to_err(rv);
-       }
-
-       /* Retrieve generated parameters to be used with the new key pair. */
-
-       a[*a_val + 0].type = CKA_PRIME;
-       a[*a_val + 0].value = params->prime;
-       a[*a_val + 0].value_len = sizeof(params->prime);
-
-       a[*a_val + 1].type = CKA_SUBPRIME;
-       a[*a_val + 1].value = params->subprime;
-       a[*a_val + 1].value_len = sizeof(params->subprime);
-
-       a[*a_val + 2].type = CKA_BASE;
-       a[*a_val + 2].value = params->generator;
-       a[*a_val + 2].value_len = sizeof(params->generator);
-
-       rv = pkcs11_get_attribute_value(module, session, key, &a[*a_val], 3);
-       if (rv != CKR_OK) {
-               gnutls_assert();
-               _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
-               return pkcs11_rv_to_err(rv);
-       }
-
-       *a_val += 3;
-
-       return 0;
+       return gnutls_pkcs11_privkey_generate3(url, pk, bits, label, NULL, fmt, pubkey, flags);
 }
 
 /**
@@ -716,7 +629,6 @@ _dsa_params_generate(struct ck_function_list *module, ck_session_handle_t sessio
  * @cid: The CKA_ID to use for the new object
  * @fmt: the format of output params. PEM or DER
  * @pubkey: will hold the public key (may be %NULL)
- * @key_usage: One of GNUTLS_KEY_*
  * @flags: zero or an OR'ed sequence of %GNUTLS_PKCS11_OBJ_FLAGs
  *
  * This function will generate a private key in the specified
@@ -732,7 +644,7 @@ _dsa_params_generate(struct ck_function_list *module, ck_session_handle_t sessio
  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
  *   negative error value.
  *
- * Since: 3.4.0
+ * Since: 3.3.26
  **/
 int
 gnutls_pkcs11_privkey_generate3(const char *url, gnutls_pk_algorithm_t pk,
@@ -740,7 +652,6 @@ gnutls_pkcs11_privkey_generate3(const char *url, gnutls_pk_algorithm_t pk,
                                const gnutls_datum_t *cid,
                                gnutls_x509_crt_fmt_t fmt,
                                gnutls_datum_t * pubkey,
-                               unsigned int key_usage,
                                unsigned int flags)
 {
        int ret;
@@ -760,10 +671,8 @@ gnutls_pkcs11_privkey_generate3(const char *url, gnutls_pk_algorithm_t pk,
        ck_key_type_t key_type;
        char pubEx[3] = { 1,0,1 }; // 65537 = 0x10001
        uint8_t id[20];
-       struct dsa_params dsa_params;
 
        PKCS11_CHECK_INIT;
-       FIX_KEY_USAGE(pk, key_usage);
 
        memset(&sinfo, 0, sizeof(sinfo));
 
@@ -827,23 +736,13 @@ gnutls_pkcs11_privkey_generate3(const char *url, gnutls_pk_algorithm_t pk,
        switch (pk) {
        case GNUTLS_PK_RSA:
                p[p_val].type = CKA_DECRYPT;
-               if (key_usage & (GNUTLS_KEY_DECIPHER_ONLY|GNUTLS_KEY_ENCIPHER_ONLY)) {
-                       p[p_val].value = (void *) &tval;
-                       p[p_val].value_len = sizeof(tval);
-               } else {
-                       p[p_val].value = (void *) &fval;
-                       p[p_val].value_len = sizeof(fval);
-               }
+               p[p_val].value = (void *) &tval;
+               p[p_val].value_len = sizeof(tval);
                p_val++;
 
                p[p_val].type = CKA_SIGN;
-               if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
-                       p[p_val].value = (void *) &tval;
-                       p[p_val].value_len = sizeof(tval);
-               } else {
-                       p[p_val].value = (void *) &fval;
-                       p[p_val].value_len = sizeof(fval);
-               }
+               p[p_val].value = (void *) &tval;
+               p[p_val].value_len = sizeof(tval);
                p_val++;
 
                a[a_val].type = CKA_ENCRYPT;
@@ -869,13 +768,8 @@ gnutls_pkcs11_privkey_generate3(const char *url, gnutls_pk_algorithm_t pk,
                break;
        case GNUTLS_PK_DSA:
                p[p_val].type = CKA_SIGN;
-               if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
-                       p[p_val].value = (void *) &tval;
-                       p[p_val].value_len = sizeof(tval);
-               } else {
-                       p[p_val].value = (void *) &fval;
-                       p[p_val].value_len = sizeof(fval);
-               }
+               p[p_val].value = (void *) &tval;
+               p[p_val].value_len = sizeof(tval);
                p_val++;
 
                a[a_val].type = CKA_VERIFY;
@@ -883,22 +777,15 @@ gnutls_pkcs11_privkey_generate3(const char *url, gnutls_pk_algorithm_t pk,
                a[a_val].value_len = sizeof(tval);
                a_val++;
 
-               ret = _dsa_params_generate(sinfo.module, sinfo.pks, _bits,
-                                          &dsa_params, a, &a_val);
-               if (ret < 0) {
-                       goto cleanup;
-               }
-
+               a[a_val].type = CKA_MODULUS_BITS;
+               a[a_val].value = &_bits;
+               a[a_val].value_len = sizeof(_bits);
+               a_val++;
                break;
        case GNUTLS_PK_EC:
                p[p_val].type = CKA_SIGN;
-               if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
-                       p[p_val].value = (void *) &tval;
-                       p[p_val].value_len = sizeof(tval);
-               } else {
-                       p[p_val].value = (void *) &fval;
-                       p[p_val].value_len = sizeof(fval);
-               }
+               p[p_val].value = (void *) &tval;
+               p[p_val].value_len = sizeof(tval);
                p_val++;
 
                a[a_val].type = CKA_VERIFY;
@@ -1069,7 +956,7 @@ static int load_pubkey_obj(gnutls_pkcs11_privkey_t pkey, gnutls_pubkey_t pub)
 
        gnutls_x509_crt_set_pin_function(crt, pkey->pin.cb, pkey->pin.data);
 
-       ret = gnutls_x509_crt_import_url(crt, pkey->url, pkey->flags);
+       ret = gnutls_x509_crt_import_pkcs11_url(crt, pkey->url, pkey->flags);
        if (ret < 0) {
                ret = iret;
                goto cleanup;