Struct parsec_client::core::basic_client::BasicClient[][src]

pub struct BasicClient { /* fields omitted */ }
Expand description

Core client for the Parsec service

The client exposes low-level functionality for using the Parsec service. Below you can see code examples for a few of the operations supported.

Providers are abstracted representations of the secure elements that Parsec offers abstraction over. Providers are the ones to execute the cryptographic operations requested by the user.

For all cryptographic operations an implicit provider is used which can be changed between operations. The client starts with the default provider, the first one returned by the ListProviders operation.

For crypto operations, if the implicit client provider is ProviderId::Core, a client error of InvalidProvider type is returned. See the operation-specific response codes returned by the service in the operation’s page here.

Implementations

Main client functionality.

Create a new Parsec client.

The client will be initialised with default values obtained from the service for the implicit provider and for application identity.

  • app_name is the application name to be used if direct authentication is the default authentication choice

This client will use the default configuration. That includes using a Protobuf converter for message bodies and a Unix Domain Socket IPC handler. The default timeout length is 60 seconds.

Example

use parsec_client::BasicClient;

let client: BasicClient = BasicClient::new(None)?;

Create a client that can initially only be used with Core operations not necessitating authentication (eg ping).

Setting an authentication method and an implicit provider is needed before calling crypto operations.

Example

use parsec_client::BasicClient;
let client = BasicClient::new_naked();
let (major, minor) = client.ping()?;

Query the service for the list of authenticators provided and use the first one as default

  • app_name is to be used if direct authentication is the default choice

Errors

If no authenticator is reported by the service, a NoAuthenticator error kind is returned.

If the default authenticator is DirectAuthenticator and app_name was set to None, an error of type MissingParam is returned.

If none of the authenticators returned by the service is supported, NoAuthenticator is returned.

Example

use parsec_client::BasicClient;
use parsec_client::core::interface::requests::ProviderId;
let mut client = BasicClient::new_naked();
client.set_implicit_provider(ProviderId::Pkcs11);
client.set_default_auth(Some("main_client".to_string()))?;

Update the authentication data of the client.

This is useful if you want to use a different authentication method than the default one.

Example

See [set_default_provider].

Retrieve authentication data of the client.

Example

use parsec_client::BasicClient;
use parsec_client::auth::Authentication;
let mut client = BasicClient::new_naked();
client.set_auth_data(Authentication::UnixPeerCredentials);
assert_eq!(Authentication::UnixPeerCredentials, client.auth_data());

Query for the service provider list and set the default one as implicit

Errors

If no provider is returned by the service, an client error of NoProvider type is returned.

Example

use parsec_client::BasicClient;
use parsec_client::auth::Authentication;
let mut client = BasicClient::new_naked();
client.set_default_provider()?;
client.set_auth_data(Authentication::UnixPeerCredentials);

Set the provider that the client will be implicitly working with.

Example

See [set_default_auth].

Retrieve client’s implicit provider.

Example

use parsec_client::BasicClient;
use parsec_client::core::interface::requests::ProviderId;
let mut client = BasicClient::new_naked();
client.set_implicit_provider(ProviderId::Pkcs11);
assert_eq!(ProviderId::Pkcs11, client.implicit_provider());

[Core Operation] List the opcodes supported by the specified provider.

Example

use parsec_client::BasicClient;
use parsec_client::core::interface::requests::{Opcode, ProviderId};

let client: BasicClient = BasicClient::new(None)?;
let opcodes = client.list_opcodes(ProviderId::Pkcs11)?;
if opcodes.contains(&Opcode::PsaGenerateRandom) {
    let random_bytes = client.psa_generate_random(10)?;
}

[Core Operation] List the providers that are supported by the service.

Example

use parsec_client::BasicClient;

let mut client: BasicClient = BasicClient::new_naked();
let providers = client.list_providers()?;
client.set_implicit_provider(providers[1].id);

[Core Operation] List the authenticators that are supported by the service.

Example

use parsec_client::BasicClient;

let client: BasicClient = BasicClient::new(None)?;
let opcodes = client.list_authenticators()?;

[Core Operation] List all keys belonging to the application.

Example

use parsec_client::BasicClient;

let client: BasicClient = BasicClient::new(None)?;
let keys = client.list_keys()?;

Get the key attributes.

This is a convenience method that uses list_keys underneath.

Errors

Returns NotFound if a key with this name does not exist.

Example

use parsec_client::BasicClient;

let client: BasicClient = BasicClient::new(None)?;
let attributes = client.key_attributes("my_key")?;

[Core Operation, Admin Operation] Lists all clients currently having data in the service.

Example

use parsec_client::BasicClient;

let client: BasicClient = BasicClient::new(None)?;
let clients = client.list_clients()?;

[Core Operation, Admin Operation] Delete all data a client has in the service.

Example

use parsec_client::BasicClient;

let client: BasicClient = BasicClient::new(None)?;
client.delete_client("main_client")?;

[Core Operation] Send a ping request to the service.

This operation is intended for testing connectivity to the service and for retrieving the maximum wire protocol version it supports.

Example

See [new_naked].

[Cryptographic Operation] Generate a key.

Creates a new key with the given name within the namespace of the implicit client provider. Any UTF-8 string is considered a valid key name, however names must be unique per provider.

Persistence of keys is implemented at provider level, and currently all providers persist all the keys users create.

If this method returns an error, no key will have been generated and the name used will still be available for another key.

Example

use parsec_client::BasicClient;
use parsec_client::core::interface::operations::psa_key_attributes::{Attributes, Lifetime, Policy, Type, UsageFlags};
use parsec_client::core::interface::operations::psa_algorithm::{AsymmetricSignature, Hash};

let client: BasicClient = BasicClient::new(None)?;
let key_attrs = Attributes {
    lifetime: Lifetime::Persistent,
    key_type: Type::RsaKeyPair,
    bits: 2048,
    policy: Policy {
        usage_flags: UsageFlags::default(),
        permitted_algorithms: AsymmetricSignature::RsaPkcs1v15Sign {
            hash_alg: Hash::Sha256.into(),
        }.into(),
    },
};
client.psa_generate_key("my_key", key_attrs)?;

[Cryptographic Operation] Destroy a key.

Given that keys are namespaced at a provider level, it is important to call psa_destroy_key on the correct combination of implicit client provider and key_name.

Example

use parsec_client::BasicClient;

let client: BasicClient = BasicClient::new(None)?;
client.psa_destroy_key("my_key")?;

[Cryptographic Operation] Import a key.

Creates a new key with the given name within the namespace of the implicit client provider using the user-provided data. Any UTF-8 string is considered a valid key name, however names must be unique per provider.

The key material should follow the appropriate binary format expressed here. Several crates (e.g. picky-asn1) can greatly help in dealing with binary encodings.

If this method returns an error, no key will have been imported and the name used will still be available for another key.

Example

use parsec_client::BasicClient;
use parsec_client::core::interface::operations::psa_key_attributes::{Attributes, Lifetime, Policy, Type, UsageFlags, EccFamily};
use parsec_client::core::interface::operations::psa_algorithm::{AsymmetricSignature, Hash};

let client: BasicClient = BasicClient::new(None)?;
let ecc_private_key = vec![
    0x26, 0xc8, 0x82, 0x9e, 0x22, 0xe3, 0x0c, 0xa6, 0x3d, 0x29, 0xf5, 0xf7, 0x27, 0x39, 0x58, 0x47,
    0x41, 0x81, 0xf6, 0x57, 0x4f, 0xdb, 0xcb, 0x4d, 0xbb, 0xdd, 0x52, 0xff, 0x3a, 0xc0, 0xf6, 0x0d,
];
let key_attrs = Attributes {
    lifetime: Lifetime::Persistent,
    key_type: Type::EccKeyPair {
        curve_family: EccFamily::SecpR1,
    },
    bits: 256,
    policy: Policy {
        usage_flags: UsageFlags::default(),
        permitted_algorithms: AsymmetricSignature::RsaPkcs1v15Sign {
            hash_alg: Hash::Sha256.into(),
        }.into(),
    },
};
client.psa_import_key("my_key", &ecc_private_key, key_attrs)?;

[Cryptographic Operation] Export a public key or the public part of a key pair.

The returned key material will follow the appropriate binary format expressed here. Several crates (e.g. picky-asn1) can greatly help in dealing with binary encodings.

Example

use parsec_client::BasicClient;

let client: BasicClient = BasicClient::new(None)?;
let public_key_data = client.psa_export_public_key("my_key");

[Cryptographic Operation] Export a key.

The returned key material will follow the appropriate binary format expressed here. Several crates (e.g. picky-asn1) can greatly help in dealing with binary encodings.

Example

use parsec_client::BasicClient;

let client: BasicClient = BasicClient::new(None)?;
let key_data = client.psa_export_key("my_key");

[Cryptographic Operation] Create an asymmetric signature on a pre-computed message digest.

The key intended for signing must have its sign_hash flag set to true in its key policy.

The signature will be created with the algorithm defined in sign_algorithm, but only after checking that the key policy and type conform with it.

hash must be a hash pre-computed over the message of interest with the algorithm specified within sign_algorithm.

Example

use parsec_client::BasicClient;
use parsec_client::core::interface::operations::psa_key_attributes::{Attributes, Lifetime, Policy, Type, UsageFlags};
use parsec_client::core::interface::operations::psa_algorithm::{AsymmetricSignature, Hash};

let client: BasicClient = BasicClient::new(None)?;
let hash = vec![
  0x69, 0x3E, 0xDB, 0x1B, 0x22, 0x79, 0x03, 0xF4, 0xC0, 0xBF, 0xD6, 0x91, 0x76, 0x37, 0x84, 0xA2,
  0x94, 0x8E, 0x92, 0x50, 0x35, 0xC2, 0x8C, 0x5C, 0x3C, 0xCA, 0xFE, 0x18, 0xE8, 0x81, 0x37, 0x78,
];
let signature = client.psa_sign_hash("my_key", &hash, AsymmetricSignature::RsaPkcs1v15Sign {
hash_alg: Hash::Sha256.into(),
})?;

[Cryptographic Operation] Verify an existing asymmetric signature over a pre-computed message digest.

The key intended for signing must have its verify_hash flag set to true in its key policy.

The signature will be verifyied with the algorithm defined in sign_algorithm, but only after checking that the key policy and type conform with it.

hash must be a hash pre-computed over the message of interest with the algorithm specified within sign_algorithm.

Example

use parsec_client::BasicClient;
use parsec_client::core::interface::operations::psa_key_attributes::{Attributes, Lifetime, Policy, Type, UsageFlags};
use parsec_client::core::interface::operations::psa_algorithm::{AsymmetricSignature, Hash};

let client: BasicClient = BasicClient::new(None)?;
let hash = vec![
    0x69, 0x3E, 0xDB, 0x1B, 0x22, 0x79, 0x03, 0xF4, 0xC0, 0xBF, 0xD6, 0x91, 0x76, 0x37, 0x84, 0xA2,
    0x94, 0x8E, 0x92, 0x50, 0x35, 0xC2, 0x8C, 0x5C, 0x3C, 0xCA, 0xFE, 0x18, 0xE8, 0x81, 0x37, 0x78,
];
let alg = AsymmetricSignature::RsaPkcs1v15Sign {
    hash_alg: Hash::Sha256.into(),
};
let signature = client.psa_sign_hash("my_key", &hash, alg)?;
client.psa_verify_hash("my_key", &hash, alg, &signature)?;

[Cryptographic Operation] Create an asymmetric signature on a message.

The key intended for signing must have its sign_message flag set to true in its key policy.

The signature will be created with the algorithm defined in sign_algorithm, but only after checking that the key policy and type conform with it.

Example

use parsec_client::BasicClient;
use parsec_client::core::interface::operations::psa_key_attributes::{Attributes, Lifetime, Policy, Type, UsageFlags};
use parsec_client::core::interface::operations::psa_algorithm::{AsymmetricSignature, Hash};

let client: BasicClient = BasicClient::new(None)?;
let message = "This is the message to sign which can be of any size!".as_bytes();
let signature = client.psa_sign_message(
    "my_key",
    message,
    AsymmetricSignature::RsaPkcs1v15Sign {
        hash_alg: Hash::Sha256.into(),
    }
)?;

[Cryptographic Operation] Verify an existing asymmetric signature over a message.

The key intended for signing must have its verify_message flag set to true in its key policy.

The signature will be verifyied with the algorithm defined in sign_algorithm, but only after checking that the key policy and type conform with it.

Example

use parsec_client::BasicClient;
use parsec_client::core::interface::operations::psa_key_attributes::{Attributes, Lifetime, Policy, Type, UsageFlags};
use parsec_client::core::interface::operations::psa_algorithm::{AsymmetricSignature, Hash};

let client: BasicClient = BasicClient::new(None)?;
let message = "This is the message to sign which can be of any size!".as_bytes();
let alg = AsymmetricSignature::RsaPkcs1v15Sign {
    hash_alg: Hash::Sha256.into(),
};
let signature = client.psa_sign_message("my_key", message, alg)?;
client.psa_verify_message("my_key", message, alg, &signature)?;

[Cryptographic Operation] Encrypt a short message.

The key intended for encrypting must have its encrypt flag set to true in its key policy.

The encryption will be performed with the algorithm defined in alg, but only after checking that the key policy and type conform with it.

salt can be provided if supported by the algorithm. If the algorithm does not support salt, pass an empty vector. If the algorithm supports optional salt, pass an empty vector to indicate no salt. For RSA PKCS#1 v1.5 encryption, no salt is supported.

[Cryptographic Operation] Decrypt a short message.

The key intended for decrypting must have its decrypt flag set to true in its key policy.

salt can be provided if supported by the algorithm. If the algorithm does not support salt, pass an empty vector. If the algorithm supports optional salt, pass an empty vector to indicate no salt. For RSA PKCS#1 v1.5 encryption, no salt is supported.

The decryption will be performed with the algorithm defined in alg, but only after checking that the key policy and type conform with it.

[Cryptographic Operation] Compute hash of a message.

The hash computation will be performed with the algorithm defined in alg.

[Cryptographic Operation] Compute hash of a message and compare it with a reference value.

The hash computation will be performed with the algorithm defined in alg.

If this operation returns no error, the hash was computed successfully and it matches the reference value.

[Cryptographic Operation] Authenticate and encrypt a short message.

The key intended for decrypting must have its encrypt flag set to true in its key policy.

The encryption will be performed with the algorithm defined in alg, but only after checking that the key policy and type conform with it.

nonce must be appropriate for the selected alg.

For algorithms where the encrypted data and the authentication tag are defined as separate outputs, the returned buffer will contain the encrypted data followed by the authentication data.

[Cryptographic Operation] Decrypt and authenticate a short message.

The key intended for decrypting must have its decrypt flag set to true in its key policy.

The decryption will be performed with the algorithm defined in alg, but only after checking that the key policy and type conform with it.

nonce must be appropriate for the selected alg.

For algorithms where the encrypted data and the authentication tag are defined as separate inputs, ciphertext must contain the encrypted data followed by the authentication data.

[Cryptographic Operation] Perform a raw key agreement.

The provided private key must have its derive flag set to true in its key policy.

The raw_key_agreement will be performed with the algorithm defined in alg, but only after checking that the key policy and type conform with it.

peer_key must be the peer public key to use in the raw key derivation. It must be in a format supported by PsaImportKey.

[Cryptographic Operation] Generate some random bytes.

Generates a sequence of random bytes and returns them to the user.

If this method returns an error, no bytes will have been generated.

Example

See [list_opcodes].

Configuration methods for controlling communication with the service.

Set the converter used for request bodies handled by this client.

By default Protobuf will be used for this.

Set the converter used for response bodies handled by this client.

By default Protobuf will be used for this.

Configuration methods for controlling IPC-level options.

Set the maximum body size allowed for requests.

Defaults to the maximum value of usize.

Set the IPC handler used for communication with the service.

By default the Unix domain socket client is used.

Set the timeout for operations on the IPC stream.

The value defaults to 1 second.

Trait Implementations

Formats the value using the given formatter. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Performs the conversion.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.