예제 #1
0
/*-
 * _gnutls_pkcs11_privkey_decrypt_data:
 * @key: Holds the key
 * @flags: should be 0 for now
 * @ciphertext: holds the data to be signed
 * @plaintext: will contain the plaintext, allocated with gnutls_malloc()
 *
 * This function will decrypt the given data using the public key algorithm
 * supported by the private key. 
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 -*/
int
_gnutls_pkcs11_privkey_decrypt_data(gnutls_pkcs11_privkey_t key,
				    unsigned int flags,
				    const gnutls_datum_t * ciphertext,
				    gnutls_datum_t * plaintext)
{
	ck_rv_t rv;
	int ret;
	struct ck_mechanism mech;
	unsigned long siglen;
	ck_object_handle_t obj;
	struct pkcs11_session_info _sinfo;
	struct pkcs11_session_info *sinfo;

	PKCS11_CHECK_INIT;

	if (key->sinfo.init != 0) {
		sinfo = &key->sinfo;
		obj = key->obj;
	} else {
		sinfo = &_sinfo;
		memset(sinfo, 0, sizeof(*sinfo));
		FIND_OBJECT(sinfo, &key->pin, obj, key);
	}

	if (key->pk_algorithm != GNUTLS_PK_RSA)
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	mech.mechanism = CKM_RSA_PKCS;
	mech.parameter = NULL;
	mech.parameter_len = 0;

	/* Initialize signing operation; using the private key discovered
	 * earlier. */
	rv = pkcs11_decrypt_init(sinfo->module, sinfo->pks, &mech, obj);
	if (rv != CKR_OK) {
		gnutls_assert();
		ret = pkcs11_rv_to_err(rv);
		goto cleanup;
	}

	/* Work out how long the plaintext must be: */
	rv = pkcs11_decrypt(sinfo->module, sinfo->pks, ciphertext->data,
			    ciphertext->size, NULL, &siglen);
	if (rv != CKR_OK) {
		gnutls_assert();
		ret = pkcs11_rv_to_err(rv);
		goto cleanup;
	}

	plaintext->data = gnutls_malloc(siglen);
	plaintext->size = siglen;

	rv = pkcs11_decrypt(sinfo->module, sinfo->pks, ciphertext->data,
			    ciphertext->size, plaintext->data, &siglen);
	if (rv != CKR_OK) {
		gnutls_free(plaintext->data);
		gnutls_assert();
		ret = pkcs11_rv_to_err(rv);
		goto cleanup;
	}

	plaintext->size = siglen;

	ret = 0;

      cleanup:
	if (key->sinfo.init == 0)
		pkcs11_close_session(sinfo);

	return ret;
}
예제 #2
0
/*-
 * _gnutls_pkcs11_privkey_decrypt_data:
 * @key: Holds the key
 * @flags: should be 0 for now
 * @ciphertext: holds the data to be signed
 * @plaintext: will contain the plaintext, allocated with gnutls_malloc()
 *
 * This function will decrypt the given data using the public key algorithm
 * supported by the private key. 
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 -*/
int
_gnutls_pkcs11_privkey_decrypt_data(gnutls_pkcs11_privkey_t key,
				    unsigned int flags,
				    const gnutls_datum_t * ciphertext,
				    gnutls_datum_t * plaintext)
{
	ck_rv_t rv;
	int ret;
	struct ck_mechanism mech;
	unsigned long siglen;
	unsigned req_login = 0;
	unsigned login_flags = SESSION_LOGIN|SESSION_CONTEXT_SPECIFIC;

	PKCS11_CHECK_INIT_PRIVKEY(key);

	if (key->pk_algorithm != GNUTLS_PK_RSA)
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	mech.mechanism = CKM_RSA_PKCS;
	mech.parameter = NULL;
	mech.parameter_len = 0;

	ret = gnutls_mutex_lock(&key->mutex);
	if (ret != 0)
		return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);

	/* Initialize signing operation; using the private key discovered
	 * earlier. */
	REPEAT_ON_INVALID_HANDLE(rv = pkcs11_decrypt_init(key->sinfo.module, key->sinfo.pks, &mech, key->ref));
	if (rv != CKR_OK) {
		gnutls_assert();
		ret = pkcs11_rv_to_err(rv);
		goto cleanup;
	}

 retry_login:
	if (key->reauth || req_login) {
		if (req_login)
			login_flags = SESSION_LOGIN|SESSION_FORCE_LOGIN;

		ret =
		    pkcs11_login(&key->sinfo, &key->pin,
				 key->uinfo, login_flags);
		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);
	if (unlikely(rv == CKR_USER_NOT_LOGGED_IN && req_login == 0)) {
		req_login = 1;
		goto retry_login;
	}

	if (rv != CKR_OK) {
		gnutls_assert();
		ret = pkcs11_rv_to_err(rv);
		goto cleanup;
	}

	plaintext->data = gnutls_malloc(siglen);
	plaintext->size = siglen;

	rv = pkcs11_decrypt(key->sinfo.module, key->sinfo.pks, ciphertext->data,
			    ciphertext->size, plaintext->data, &siglen);
	if (rv != CKR_OK) {
		gnutls_free(plaintext->data);
		gnutls_assert();
		ret = pkcs11_rv_to_err(rv);
		goto cleanup;
	}

	plaintext->size = siglen;

	ret = 0;

      cleanup:
	gnutls_mutex_unlock(&key->mutex);
	return ret;
}
/*-
 * _gnutls_pkcs11_privkey_decrypt_data:
 * @key: Holds the key
 * @flags: should be 0 for now
 * @ciphertext: holds the data to be signed
 * @plaintext: will contain the plaintext, allocated with gnutls_malloc()
 *
 * This function will decrypt the given data using the public key algorithm
 * supported by the private key. 
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 -*/
int
_gnutls_pkcs11_privkey_decrypt_data (gnutls_pkcs11_privkey_t key,
                                    unsigned int flags,
                                    const gnutls_datum_t * ciphertext,
                                    gnutls_datum_t * plaintext)
{
  ck_rv_t rv;
  int ret;
  struct ck_mechanism mech;
  unsigned long siglen;
  struct ck_function_list *module;
  ck_session_handle_t pks;
  ck_object_handle_t obj;

  FIND_OBJECT (module, pks, obj, key);

  if (key->pk_algorithm != GNUTLS_PK_RSA)
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

  mech.mechanism = CKM_RSA_PKCS;
  mech.parameter = NULL;
  mech.parameter_len = 0;

  /* Initialize signing operation; using the private key discovered
   * earlier. */
  rv = pkcs11_decrypt_init (module, pks, &mech, obj);
  if (rv != CKR_OK)
    {
      gnutls_assert ();
      ret = pkcs11_rv_to_err (rv);
      goto cleanup;
    }

  /* Work out how long the plaintext must be: */
  rv = pkcs11_decrypt (module, pks, ciphertext->data, ciphertext->size,
                         NULL, &siglen);
  if (rv != CKR_OK)
    {
      gnutls_assert ();
      ret = pkcs11_rv_to_err (rv);
      goto cleanup;
    }

  plaintext->data = gnutls_malloc (siglen);
  plaintext->size = siglen;

  rv = pkcs11_decrypt (module, pks, ciphertext->data, ciphertext->size,
                         plaintext->data, &siglen);
  if (rv != CKR_OK)
    {
      gnutls_free (plaintext->data);
      gnutls_assert ();
      ret = pkcs11_rv_to_err (rv);
      goto cleanup;
    }

  plaintext->size = siglen;

  ret = 0;

cleanup:
  pkcs11_close_session (module, pks);

  return ret;
}