@0xc996c4872a6820ae;
# This file describes the interface between a client of the keystore
# (e.g., sq) and the keystore. Keystore backends implement the traits
# defined in the sequoia-keystore-backend crate.
interface Keystore {
backends @0 () -> (result: Result(List(Backend)));
# Returns the backends.
decrypt @1 (pkesks: List(Data)) -> (result: Result(DecryptedPkesk));
# Decrypts a PKESK.
#
# If multiple PKESKs are provided, this tries to use the most
# convenient key from the user's perspective. In particular, it
# tries to use an unlocked key before trying a locked key.
#
# If no keys could be used, but there is at least one registered key
# that could be used, this returns `Error::Inaccessible` and the
# list of keys that could be used, and why they can't be used.
struct InaccessibleDecryptionKey {
# Returned by Keystore::decrypt.
keyDescriptor @0: KeyDescriptor;
# The inaccessible key.
pkesk @1: Data;
# The serialized PKESK that triggered this error.
}
struct DecryptedPkesk {
index @0: UInt32;
# The index of the PKESK that was decrypted.
fingerprint @1: Data;
# The fingerprint of the key used to decrypt the data.
algo @2: UInt8;
# The decrypted symmetric algorithm identifier.
#
# See https://datatracker.ietf.org/doc/html/rfc4880#section-5.1
sessionKey @3: Data;
# The decrypted session key.
#
# See https://datatracker.ietf.org/doc/html/rfc4880#section-5.1
}
interface Backend {
id @0 () -> (result: Result(Text));
# Returns the backend's unique identifier.
#
# It should be a well-formed UTF-8 string, which should give a
# curious user a pretty good idea of what backend this is.
list @1 () -> (result: Result(List(Device)));
# List known devices.
# scan @2 () -> (result: VoidResult);
# # Search for devices.
#
# register @3 (description: Text) -> (result: Result(Device));
# # Register a device.
}
interface Device {
id @0 () -> (result: Result(Text));
# Returns a unique device identifier.
#
# It should be a well-formed UTF-8 string, which should give a
# curious user a pretty good idea of what device this is.
list @1 () -> (result: Result(List(KeyDescriptor)));
# List known keys associated with this device.
}
struct KeyDescriptor {
handle @0: Key;
publicKey @1: Data;
# The serialized PublicKey or PublicSubkey packet without OpenPGP framing.
#
# If the creation time is not known, the backend should set the
# creation time to 0.
}
interface Key {
id @0 () -> (result: Result(Text));
# Returns a unique key identifier.
#
# It should be a well-formed UTF-8 string, which should give a
# curious user a pretty good idea of what key this is.
decryptCiphertext @1 (algo: UInt8, ciphertext: Data, plaintextLen: UInt32)
-> (result: Result(Data));
# Decrypts the ciphertext.
#
# The semantics are identical to
# `sequoia_openpgp::crypto::Decryptor::decrypt`.
#
# https://docs.sequoia-pgp.org/sequoia_openpgp/crypto/trait.Decryptor.html#tymethod.decrypt
signMessage @2 (hash_algo: UInt8, digest: Data)
-> (result: Result(SignedData));
# Signs the digest.
unlock @3 (password: Data) -> (result: VoidResult);
# Unlocks the key.
#
# If the key is not available, this first attempts to connect to
# the device (e.g., bring up an ssh tunnel).
#
# If the key is already unlocked, this returns an error.
#
# If the password is wrong, thus returns an error.
#
# If the key can be unlocked, the key remains unlocked until
# the cache flushes unlocked key.
available @4 () -> (result: BoolResult);
# Whether the key is available.
#
# If false, this usually means the device needs to be connected.
locked @5 () -> (result: BoolResult);
# Whether the key is locked.
decryptionCapable @6 () -> (result: BoolResult);
# Whether the key can be used for decryption.
signingCapable @7 () -> (result: BoolResult);
# Whether the key can be used for signing.
}
struct SignedData {
pkAlgo @0 : UInt8;
mpis @1 : Data;
# The serialized mpi::Signature, without OpenPGP framing.
}
struct Unit {}
# Unit struct. Useful with Result.
struct Error {
union {
unspecified @0 :Void;
protocol @1: Void;
eof @2: Void;
inaccessibleDecryptionKey @3: List(InaccessibleDecryptionKey);
# Returned by `KeyStore::decrypt`.
#
# The operation failed, because no keys that could be used to
# complete the operation are accessible. This could be because
# they are locked, or a device that contains a key is
# registered, but not connected.
notDecryptionCapable @4: Text;
# The key cannot be used for decryption.
notSigningCapable @5: Text;
# The key cannot be used for signing.
internalError @6: Text;
# An internal server error occurred.
}
}
struct Result(T) {
union {
ok @0 :T;
err @1 :Error;
}
}
struct VoidResult {
# Generic types can only be pointers. So to return Result<()>, we
# need a different type. See:
#
# 'Kenton Varda' via Cap'n Proto Thu, 30 Apr 2020 15:19:13 -0700
# Subject: Re: [capnproto] Why "Sorry, only pointer types can be used as generic parameters."?
#
# https://www.mail-archive.com/capnproto@googlegroups.com/msg01286.html
union {
ok @0 :Void;
err @1 :Error;
}
}
struct BoolResult {
# Generic types can only be pointers. So to return Result<Bool>, we
# need a different type. See:
#
# 'Kenton Varda' via Cap'n Proto Thu, 30 Apr 2020 15:19:13 -0700
# Subject: Re: [capnproto] Why "Sorry, only pointer types can be used as generic parameters."?
#
# https://www.mail-archive.com/capnproto@googlegroups.com/msg01286.html
union {
ok @0 :Bool;
err @1 :Error;
}
}
}