Ejemplo n.º 1
0
/**
 * gnutls_pkcs11_privkey_import_url:
 * @pkey: The structure to store the parsed key
 * @url: a PKCS 11 url identifying the key
 * @flags: sequence of GNUTLS_PKCS_PRIVKEY_*
 *
 * This function will "import" a PKCS 11 URL identifying a private
 * 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.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_pkcs11_privkey_import_url(gnutls_pkcs11_privkey_t pkey,
				 const char *url, unsigned int flags)
{
	int ret;
	struct ck_attribute *attr;
	ck_object_handle_t obj;
	struct ck_attribute a[4];
	ck_key_type_t key_type;
	struct pkcs11_session_info sinfo;

	PKCS11_CHECK_INIT;

	memset(&sinfo, 0, sizeof(sinfo));

	ret = pkcs11_url_to_info(url, &pkey->info);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	pkey->flags = flags;

	attr = p11_kit_uri_get_attribute(pkey->info, CKA_CLASS);
	if (!attr || attr->value_len != sizeof(ck_object_class_t) ||
	    *(ck_object_class_t *) attr->value != CKO_PRIVATE_KEY) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	attr = p11_kit_uri_get_attribute(pkey->info, CKA_ID);
	if (!attr || !attr->value_len) {
		attr = p11_kit_uri_get_attribute(pkey->info, CKA_LABEL);
		if (!attr || !attr->value_len) {
			gnutls_assert();
			return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
		}
	}

	FIND_OBJECT(&sinfo, &pkey->pin, obj, pkey);

	a[0].type = CKA_KEY_TYPE;
	a[0].value = &key_type;
	a[0].value_len = sizeof(key_type);

	if (pkcs11_get_attribute_value(sinfo.module, sinfo.pks, obj, a, 1)
	    == CKR_OK) {
		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");
			ret = GNUTLS_E_UNKNOWN_ALGORITHM;
			goto cleanup;
		}
	}

	ret = 0;

	if (pkey->sinfo.init)
		pkcs11_close_session(&pkey->sinfo);

	if (sinfo.tinfo.max_session_count != 1) {
		/* We do not keep the session open in tokens that can 
		 * only support a single session.
		 */
		memcpy(&pkey->sinfo, &sinfo, sizeof(pkey->sinfo));
		pkey->obj = obj;
		return ret;
	}

      cleanup:
	pkcs11_close_session(&sinfo);

	return ret;
}
/**
 * gnutls_pkcs11_privkey_import_url:
 * @pkey: The structure to store the parsed key
 * @url: a PKCS 11 url identifying the key
 * @flags: sequence of GNUTLS_PKCS_PRIVKEY_*
 *
 * This function will "import" a PKCS 11 URL identifying a private
 * 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.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_pkcs11_privkey_import_url (gnutls_pkcs11_privkey_t pkey,
                                  const char *url, unsigned int flags)
{
  int ret;
  struct ck_function_list *module;
  struct ck_attribute *attr;
  ck_session_handle_t pks;
  ck_object_handle_t obj;
  struct ck_attribute a[4];
  ck_key_type_t key_type;

  ret = pkcs11_url_to_info (url, &pkey->info);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  pkey->flags = flags;

  attr = p11_kit_uri_get_attribute (pkey->info, CKA_CLASS);
  if (!attr || attr->value_len != sizeof (ck_object_class_t) ||
      *(ck_object_class_t*)attr->value != CKO_PRIVATE_KEY)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  attr = p11_kit_uri_get_attribute (pkey->info, CKA_ID);
  if (!attr || !attr->value_len)
    {
      attr = p11_kit_uri_get_attribute (pkey->info, CKA_LABEL);
      if (!attr || !attr->value_len)
        {
          gnutls_assert ();
          return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
        }
    }

  FIND_OBJECT (module, pks, obj, pkey);
  a[0].type = CKA_KEY_TYPE;
  a[0].value = &key_type;
  a[0].value_len = sizeof (key_type);

  if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
    {
      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");
          ret = GNUTLS_E_UNKNOWN_ALGORITHM;
          goto cleanup;
        }
    }

  ret = 0;

cleanup:
  pkcs11_close_session (module, pks);

  return ret;
}