Crate sequoia_policy_config
source ·Expand description
Configures a StandardPolicy
using a configuration file.
Sequoia’s StandardPolicy
can be configured using Rust. As
with most things, Sequoia’s low-level library avoids imposing a
policy on users of the library, like where a configuration file
should be or even what format it should have. When necessary, it
is up to the application to provide an interface, and to configure
the policy appropriately.
This library provides a high-level interface that parses a
configuration file, and returns a configured StandardPolicy
.
§Format
The file format is based on TOML. It contains several sections, one for hash algorithms, one for asymmetric algorithms, etc.
§Forward Compatibility
This parser is strict, but we want the configuration format to be forwards compatible so that the same configuration file can be used with different versions of the parser.
§Dealing with New Keys
Unknown sections and unknown keys cause a parse error. To allow
configuration files a degree of backwards compatibility, it is
possible to set the per-map ignore_invalid
key to the key or the
list of keys that should be ignored if they are not recognized.
For instance, if Sequoia adds support for SHA4
, then you could
do the following to unconditionally reject SHA4
while ensuring
that the configuration is still readable by older versions of
Sequoia that don’t know about SHA4
:
[hash_algorithms]
ignore_invalid = [ "sha4" ]
sha4 = never
(The same principle applies to sections.)
§Dealing with Type Changes
Most keys are string types. In the future, we may want to make a given algorithm or data structure’s configuration more nuanced. A logical way to do this is to change the key from taking a string type to taking a map type.
To support this type of change, all keys that take a string are
also recognized as maps with a single key, default_disposition
.
Thus, if key
is ever extended in this way,
key.default_disposition
can be used to control the configuration
of older versions, and new versions can use the configuration
parameters.
For instance, imagine that AES128 is found to be vulnerable to an
attack called foo
in certain, detectable situations. We could
extend AES128 with a new key (foo
) that is respected when those
conditions are detected. This can be expressed in the following,
backwards compatible manner:
[symmetric_algorithms]
aes128.default_disposition = "always"
aes128.foo = "2023-01-01"
aes128.ignore_invalid = "foo"
§Cutoff Times
Most settings take a so-called cutoff time. The cutoff time is the time at which an algorithm (e.g., the broken SHA-1 hash algorithm) or a data structure (e.g. the obsolete SED packet) should no longer be considered valid. Using a cutoff time provides more nuance than simply marking an algorithm as invalid. In particular, it allows sun setting algorithms that have been weakened, but are not yet completely broken, and using data that has been saved to a trusted medium before its security was broken.
Cutoff times are expressed using TOML’s datetime
datatype, which
is an RFC 3339 formatted timestamp. The following variants are
valid:
Offset datetime:
[hash_algorithms]
sha1 = 2010-01-01T00:00:00Z
Local datetime:
[hash_algorithms]
sha1 = 2010-01-01T00:00:00+00:00
Local date (interpreted as midnight in UTC):
[hash_algorithms]
sha1 = 2010-01-01
The local time format is not supported as it doesn’t make sense in this context.
Two special values are also supported: always
means that the
algorithm or data structure should always be considered valid, and
never
means that the algorithm or data structure should never be
considered valid. These values are checked for in a
case-sensitive manner.
[hash_algorithms]
sha1 = "never"
§Default Disposition
In some situations, it is desirable to only allow a fixed set of algorithms. Using the cutoff mechanism, it is possible to accept or reject each of the known algorithms, but unknown algorithms, i.e., those that Sequoia will add in the future, and will likely enable by default, can’t be rejected in this way, because their name is—by definition—not yet known.
To accommodate this usage, it is possible to set an algorithm
class or data structure class’s default disposition using the
default_disposition
key. Currently, only one value is supported
for this key: never
. If this key is present in a section, then
that key is processed first, and all algorithms are set to be
rejected. The rest of the keys are then processed as usual.
The following example shows how to only allow the SHA256 and SHA512 hash functions. Even if a theoretical SHA4 hash function is added to Sequoia, it will be rejected by this configuration.
[hash_algorithms]
sha256.collision_resistance = "always"
sha256.second_preimage_resistance = "always"
sha512.collision_resistance = "always"
sha512.second_preimage_resistance = "always"
default_disposition = "never"
§Sections
§Hash Functions
Hash algorithms are used to ensure multiple properties. Of particular relevance in the context of OpenPGP are collision resistance, and second preimage resistance. In some contexts like self signatures, only second preimage resistance is required. In other contexts, both properties are required. As collision resistance is much easier to attack, these two properties can be set separately.
You configure just the second preimage resistance cutoff by
setting the ALGO.second_preimage_resistance
key. You configure
just the collision resistance cutoff by setting the
ALGO.collision_resistance
key. Setting the ALGO
key is
shorthand for setting both.
A hash algorithm’s key is the lower-case version of the value
returned by the Display
name. For instance,
SHA1 is sha1
.
[hash_algorithms]
md5 = "never"
sha1.second_preimage_resistance = 2030-01-01
sha1.collision_resistance = 2022-01-01
sha512 = "always"
§Symmetric Algorithms
Like hash algorithms, symmetric algorithms can be rejected
outright or have a cutoff date. They don’t have any subkeys like
collision_resistance
, so there is only one way to set the
cutoff: using the algo
key.
The unencrypted variant, the unknown variants, and the private variants cannot currently be set.
[symmetric_algorithms]
cast5 = "never"
aes128 = "always"
§Asymmetric Algorithms
Like symmetric algorithms, asymmetric algorithms can be rejected outright or have a cutoff date.
The unknown variants, and the private variants cannot currently be set.
[asymmetric_algorithms]
rsa1024 = "never"
rsa2048 = 2028-01-01
§AEAD Algorithms
Like symmetric algorithms, AEAD algorithms can be rejected outright or have a cutoff date.
The unknown variants, and the private variants cannot currently be set.
[aead_algorithms]
eax = "never"
ocb = "always"
§Packets
Packets can be rejected outright or have a cutoff date. The SED packet is, for instance, considered broken, and messages that use it should generally be rejected unless they are known to not be from an attacker, e.g., because they were stored on a trusted medium before the attack was feasible.
It is also possible to reject particular versions of a packet. In
this case, the packet is a map and the fields vX
where X
is a
u8
can be used to set the cutoff for version X
of the packet.
This mechanism is only supported for packets that actually are
versioned, and only for known versions. (Unknown versions can
still be set in a forwards compatible way using the
ignore_invalid
key.)
The packets are named after the names of the Packet variants.
The reserved packet, the unknown variants, and the private variants cannot currently be set.
[packets]
sed = "never"
seip = 2028-01-01
signature.v3 = 2017-01-01
signature.v4 = 2030-01-01
signature.v6 = "always"
# v6 signatures are coming, but not yet recognized.
signature.ignore_invalid = "v6"
§Examples
The following example shows how to use a configuration file to
configure a StandardPolicy
:
use sequoia_openpgp as openpgp;
use openpgp::policy::HashAlgoSecurity;
use openpgp::types::HashAlgorithm;
use sequoia_policy_config::ConfiguredStandardPolicy;
let mut p = ConfiguredStandardPolicy::new();
p.parse_bytes(b"[hash_algorithms]
sha1.collision_resistance = \"never\"")?;
let p = &p.build();
assert_eq!(p.hash_cutoff(HashAlgorithm::SHA1,
HashAlgoSecurity::CollisionResistance),
Some(std::time::UNIX_EPOCH));
Structs§
Enums§
- Controls how
ConfiguredStandardPolicy::dump
emits default values. - Errors used in this crate.