Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignore subkeys that are expired or cannot be used for signing #1911

Closed
DemiMarie opened this issue Feb 6, 2022 · 11 comments · Fixed by #1938
Closed

Ignore subkeys that are expired or cannot be used for signing #1911

DemiMarie opened this issue Feb 6, 2022 · 11 comments · Fixed by #1938

Comments

@DemiMarie
Copy link
Contributor

Such keys should be ignored by RPM.

@DemiMarie
Copy link
Contributor Author

@pmatilai @ffesti is it okay if I make a PR for this? It is a somewhat substantial change.

@pmatilai
Copy link
Member

We don't look at expiry dates on main keys, on purpose. How are subkeys different?
Ignoring keys that can't be used for signing seems reasonable though, I guess.

@teythoon
Copy link

We don't look at expiry dates on main keys, on purpose. How are subkeys different?

I suppose you do that so that old signatures still check out even after the issuing certificate expires, e.g. old distribution certificates.

Note that outright ignoring expiration times is not the best way to accomplish this.

A consequence of ignoring expiration times is that expired certificates can still issue new signatures. Imagine an old distribution signing key being exfiltrated after it is expired. Now, all installations that still have that old certificate in their set of trusted certificates will consider newly created signatures valid, even though their copy of the certificate says it is expired.

A better way is to look at the creation time of the signature you want to verify, then ask the question whether the certificate and its signing subkeys are valid at that point in time.

@pmatilai
Copy link
Member

The problem with expiration is that people have software installed and it doesn't get uninstalled or inaccessible by a clock ticking someplace (similar issue with revocation). But "valid at the time of signing" is indeed a much better way to look at it.

@DemiMarie
Copy link
Contributor Author

A consequence of ignoring expiration times is that expired certificates can still issue new signatures. Imagine an old distribution signing key being exfiltrated after it is expired. Now, all installations that still have that old certificate in their set of trusted certificates will consider newly created signatures valid, even though their copy of the certificate says it is expired.

A better way is to look at the creation time of the signature you want to verify, then ask the question whether the certificate and its signing subkeys are valid at that point in time.

This alone isn’t sufficient for primary keys. The person with a copy of the secret key can just make a signature that claims to be from when the key was still valid. They could also create a new self-signature that makes the key no longer expired.
A better solution is for distributions to generate their signing keys on smart cards, so that they can securely erase them once they are no longer in use. Cryptographic Message Syntax, which is used by Windows for its code signing, solves the problem by means of a third-party time-stamping countersignature, which proves that the signature was actually made before a certain point in time.

That said, RPM needs to be able to handle expired signatures in the rpmdb. Could RPMRC_NOTTRUSTED be used for that?

We don't look at expiry dates on main keys, on purpose. How are subkeys different?
Ignoring keys that can't be used for signing seems reasonable though, I guess.

Subkeys are different because they provide a mechanism for key rotation. Someone in possession of a subkey cannot simply increase the subkey’s validity arbitrarily, as only the primary key can create a new subkey binding signature. One should also be able to revoke a subkey and mark signatures made by the subkey after a certain point as no longer valid. This requires that RPM support subkey revocation. I might be able to implement this, but I would need to know where to store the data. @pmatilai any suggestions?

@pmatilai
Copy link
Member

From rpm POV, the revocation problem is exactly the same as expiry: software doesn't get uninstalled or become inaccessible by somebody somewhere revoking something. Rpm would need to use a different policy for installed packages to make that possible, and it all spins out of hand real fast.

The sanest thing for rpm to do would be dropping support for subkeys because that opens up all manner of complications that just don't exist with primary keys. When subkey parsing support was added in 355c9b0 , I doubt the complexities were considered at all.

The other thing to keep in mind wrt rpm key support is that rpm's imported == trusted key model means that you only feed very curated material into rpm. It doesn't generally need to handle arbitrary key data off the net, like a general purpose OpenPGP implementation does.

@DemiMarie
Copy link
Contributor Author

The sanest thing for rpm to do would be dropping support for subkeys because that opens up all manner of complications that just don't exist with primary keys. When subkey parsing support was added in 355c9b0 , I doubt the complexities were considered at all.

That isn’t an option because it would break packages used in the wild, sadly. But I can submit a patch that will ignore subkeys that cannot be used for signing.

The other thing to keep in mind wrt rpm key support is that rpm's imported == trusted key model means that you only feed very curated material into rpm. It doesn't generally need to handle arbitrary key data off the net, like a general purpose OpenPGP implementation does.

My assumption is that gpg --export --armor -o key.asc -- fingerprint-of-trusted-key && rpmkeys --import key.asc should be safe. That means that RPM needs to at least safely ignore third-party certifications and direct-key signatures, as well as subkeys that cannot be used for signing.

@mlschroe
Copy link
Contributor

IMHO Rpm should just behave like gpgv in regards to subkeys, key expiration, and revokations.

@teythoon
Copy link

This alone isn’t sufficient for primary keys. The person with a copy of the secret key can just make a signature that claims to be from when the key was still valid. They could also create a new self-signature that makes the key no longer expired.

While that is true, I would assume that the set of trusted OpenPGP certificates on old installations is fixed and won't be updated. Under this assumptions, the attacker can not extend the expiration time. Thus, honoring the expiration closes an attack vector by invalidating newer signatures.

There is the caveat that an attacker can backdate the signature creation time. To protect against that, the creation time must be corroborated by other means, the OpenPGP implementation cannot do that alone, one needs to consider context.

Invalidation of cryptographic material, either via expiration or revocation, is tricky. But, ignoring expiration times certainly doesn't help.

DemiMarie added a commit to DemiMarie/rpm that referenced this issue Feb 25, 2022
This ensures that a signature is only accepted if the key in question
can actually be used for signing.  Tests 265 and 266 verify that RPM
completely ignores keys that are not capable of signing.

Fixes rpm-software-management#1911.
DemiMarie added a commit to DemiMarie/rpm that referenced this issue Feb 26, 2022
This ensures that a signature is only accepted if the key in question
can actually be used for signing.  Tests 265 and 266 verify that RPM
completely ignores keys that are not capable of signing.

Fixes rpm-software-management#1911.
DemiMarie added a commit to DemiMarie/rpm that referenced this issue Feb 26, 2022
This ensures that a signature is only accepted if the key in question
can actually be used for signing.  Tests 265 and 266 verify that RPM
completely ignores keys that are not capable of signing.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  No signature, regardless of type, is permitted to have
more than one hashed key flags subpacket.  Unhashed key flags subpackets
are ignored.  The presence of a hashed key flags subpacket is specified
by the flag PGPDIG_SAVED_KEY_FLAGS in struct pgpDigParams_s::saved.  A
new `hashed` parameter is added to pgpPrtSubType() to allow hashed and
unhashed subpackets to be distinguished.

Since PGPDIG_SAVED_KEY_FLAGS must not be inherited from a previous use
of this `struct pgpDigParams_s`, it is cleared by pgpPrtSig() whenever
it processes a new signature.  All other saved flags, with the exception
of PGPDIG_SAVED_ID and PGPDIG_SAVED_TIME, are also cleared.  This allows
for future changes to store per-key state without worrying that it will
be inherited from a previously used key.  The key usage flags are
cleared too, although this is not strictly necessary.

RFC4880 requires that a subkey binding signature be v4 if the subkey is
capable of signing.  Requiring a hashed key flags subpacket for such
signatures enforces this requirement implicitly, as v3 signatures do not
have subpackets.  RFC4880 also requires that primary key binding
signatures be present and checked.  This is not implemented in this
commit, but may be implemented in a future commit.

To avoid a performance penalty, pgpPrtSig() is changed to ignore the
MPIs of a signature if its `tag` parameter is 0.  The only caller that
sets `tag` to 0 is pgpPrtParamSubkeys(), which does not actually check
any cryptographic signatures.  The subkey binding signature has been
checked earlier in pgpPrtParams().

Fixes rpm-software-management#1911.
DemiMarie added a commit to DemiMarie/rpm that referenced this issue Mar 3, 2022
This ensures that a signature is only accepted if the key in question
can actually be used for signing.  Tests 265 and 266 verify that RPM
completely ignores keys that are not capable of signing.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  No signature, regardless of type, is permitted to have
more than one hashed key flags subpacket.  Unhashed key flags subpackets
are ignored.  The presence of a hashed key flags subpacket is specified
by the flag PGPDIG_HAS_KEY_FLAGS in struct pgpDigParams_s::saved.  A new
`hashed` parameter is added to pgpPrtSubType() to allow hashed and
unhashed subpackets to be distinguished.

Since PGPDIG_HAS_KEY_FLAGS must not be inherited from a previous use of
this `struct pgpDigParams_s`, it is cleared by pgpPrtSig() whenever it
processes a new signature.  All other saved flags, with the exception of
PGPDIG_SAVED_ID and PGPDIG_SAVED_TIME, are also cleared.  This allows
for future changes to store per-key state without worrying that it will
be inherited from a previously used key.  The key usage flags are
cleared too, although this is not strictly necessary.

RFC4880 requires that a subkey binding signature be v4 if the subkey is
capable of signing.  Requiring a hashed key flags subpacket for such
signatures enforces this requirement implicitly, as v3 signatures do not
have subpackets.  RFC4880 also requires that primary key binding
signatures be present and checked.  This is not implemented in this
commit, but may be implemented in a future commit.

To avoid a performance penalty, pgpPrtSig() is changed to ignore the
MPIs of a signature if its `tag` parameter is 0.  The only caller that
sets `tag` to 0 is pgpPrtParamSubkeys(), which does not actually check
any cryptographic signatures.  The subkey binding signature has been
checked earlier in pgpPrtParams().

Fixes rpm-software-management#1911.
DemiMarie added a commit to DemiMarie/rpm that referenced this issue Mar 5, 2022
This ensures that a signature is only accepted if the key in question
can actually be used for signing.  Tests 265 and 266 verify that RPM
completely ignores keys that are not capable of signing.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  No signature, regardless of type, is permitted to have
more than one hashed key flags subpacket.  Unhashed key flags subpackets
are ignored.  The presence of a hashed key flags subpacket is specified
by the flag PGPDIG_HAS_KEY_FLAGS in struct pgpDigParams_s::saved.  A new
`hashed` parameter is added to pgpPrtSubType() to allow hashed and
unhashed subpackets to be distinguished.

Since PGPDIG_HAS_KEY_FLAGS must not be inherited from a previous use of
this `struct pgpDigParams_s`, it is cleared by pgpPrtSig() whenever it
processes a new signature.  All other saved flags, with the exception of
PGPDIG_SAVED_ID and PGPDIG_SAVED_TIME, are also cleared.  This allows
for future changes to store per-key state without worrying that it will
be inherited from a previously used key.  The key usage flags are
cleared too, although this is not strictly necessary.

RFC4880 requires that a subkey binding signature be v4 if the subkey is
capable of signing.  Requiring a hashed key flags subpacket for such
signatures enforces this requirement implicitly, as v3 signatures do not
have subpackets.  RFC4880 also requires that primary key binding
signatures be present and checked.  This is not implemented in this
commit, but may be implemented in a future commit.

To avoid a performance penalty, pgpPrtSig() is changed to ignore the
MPIs of a signature if its `tag` parameter is 0.  The only caller that
sets `tag` to 0 is pgpPrtParamSubkeys(), which does not actually check
any cryptographic signatures.  The subkey binding signature has been
checked earlier in pgpPrtParams().

Fixes rpm-software-management#1911.
DemiMarie added a commit to DemiMarie/rpm that referenced this issue Mar 11, 2022
This ensures that a signature is only accepted if the key in question
can actually be used for signing.  Tests 265 and 266 verify that RPM
completely ignores keys that are not capable of signing.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  No signature, regardless of type, is permitted to have
more than one hashed key flags subpacket.  Unhashed key flags subpackets
are ignored.  The presence of a hashed key flags subpacket is specified
by the flag PGPDIG_HAS_KEY_FLAGS in struct pgpDigParams_s::saved.  A new
`hashed` parameter is added to pgpPrtSubType() to allow hashed and
unhashed subpackets to be distinguished.

Since PGPDIG_HAS_KEY_FLAGS must not be inherited from a previous use of
this `struct pgpDigParams_s`, it is cleared by pgpPrtSig() whenever it
processes a new signature.  All other saved flags, with the exception of
PGPDIG_SAVED_ID and PGPDIG_SAVED_TIME, are also cleared.  This allows
for future changes to store per-key state without worrying that it will
be inherited from a previously used key.  The key usage flags are
cleared too, although this is not strictly necessary.

RFC4880 requires that a subkey binding signature be v4 if the subkey is
capable of signing.  Requiring a hashed key flags subpacket for such
signatures enforces this requirement implicitly, as v3 signatures do not
have subpackets.  RFC4880 also requires that primary key binding
signatures be present and checked.  This is not implemented in this
commit, but may be implemented in a future commit.

To avoid a performance penalty, pgpPrtSig() is changed to ignore the
MPIs of a signature if its `tag` parameter is 0.  The only caller that
sets `tag` to 0 is pgpPrtParamSubkeys(), which does not actually check
any cryptographic signatures.  The subkey binding signature has been
checked earlier in pgpPrtParams().

Fixes rpm-software-management#1911.
DemiMarie added a commit to DemiMarie/rpm that referenced this issue Mar 18, 2022
This ensures that a signature is only accepted if the key in question
can actually be used for signing.  Tests 265 and 266 verify that RPM
completely ignores keys that are not capable of signing.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  No signature, regardless of type, is permitted to have
more than one hashed key flags subpacket.  Unhashed key flags subpackets
are ignored.  The presence of a hashed key flags subpacket is specified
by the flag PGPDIG_HAS_KEY_FLAGS in struct pgpDigParams_s::saved.  A new
`hashed` parameter is added to pgpPrtSubType() to allow hashed and
unhashed subpackets to be distinguished.

Since PGPDIG_HAS_KEY_FLAGS must not be inherited from a previous use of
this `struct pgpDigParams_s`, it is cleared by pgpPrtSig() whenever it
processes a new signature.  All other saved flags, with the exception of
PGPDIG_SAVED_ID and PGPDIG_SAVED_TIME, are also cleared.  This allows
for future changes to store per-key state without worrying that it will
be inherited from a previously used key.  The key usage flags are
cleared too, although this is not strictly necessary.

RFC4880 requires that a subkey binding signature be v4 if the subkey is
capable of signing.  Requiring a hashed key flags subpacket for such
signatures enforces this requirement implicitly, as v3 signatures do not
have subpackets.  RFC4880 also requires that primary key binding
signatures be present and checked.  This is not implemented in this
commit, but may be implemented in a future commit.

To avoid a performance penalty, pgpPrtSig() is changed to ignore the
MPIs of a signature if its `tag` parameter is 0.  The only caller that
sets `tag` to 0 is pgpPrtParamSubkeys(), which does not actually check
any cryptographic signatures.  The subkey binding signature has been
checked earlier in pgpPrtParams().

Fixes rpm-software-management#1911.
DemiMarie added a commit to DemiMarie/rpm that referenced this issue Mar 18, 2022
This ensures that a signature is only accepted if the key in question
can actually be used for signing.  Tests 265 and 266 verify that RPM
completely ignores keys that are not capable of signing.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  No signature, regardless of type, is permitted to have
more than one hashed key flags subpacket.  Unhashed key flags subpackets
are ignored.  The presence of a hashed key flags subpacket is specified
by the flag PGPDIG_HAS_KEY_FLAGS in struct pgpDigParams_s::saved.  A new
`hashed` parameter is added to pgpPrtSubType() to allow hashed and
unhashed subpackets to be distinguished.

Since PGPDIG_HAS_KEY_FLAGS must not be inherited from a previous use of
this `struct pgpDigParams_s`, it is cleared by pgpPrtSig() whenever it
processes a new signature.  All other saved flags, with the exception of
PGPDIG_SAVED_ID and PGPDIG_SAVED_TIME, are also cleared.  This allows
for future changes to store per-key state without worrying that it will
be inherited from a previously used key.  The key usage flags are
cleared too, although this is not strictly necessary.

RFC4880 requires that a subkey binding signature be v4 if the subkey is
capable of signing.  Requiring a hashed key flags subpacket for such
signatures enforces this requirement implicitly, as v3 signatures do not
have subpackets.  RFC4880 also requires that primary key binding
signatures be present and checked.  This is not implemented in this
commit, but may be implemented in a future commit.

To avoid a performance penalty, pgpPrtSig() is changed to ignore the
MPIs of a signature if its `tag` parameter is 0.  The only caller that
sets `tag` to 0 is pgpPrtParamSubkeys(), which does not actually check
any cryptographic signatures.  The subkey binding signature has been
checked earlier in pgpPrtParams().

Fixes rpm-software-management#1911.
DemiMarie added a commit to DemiMarie/rpm that referenced this issue Mar 18, 2022
This ensures that a signature is only accepted if the key in question
can actually be used for signing.  Tests 265 and 266 verify that RPM
completely ignores keys that are not capable of signing.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  No signature, regardless of type, is permitted to have
more than one hashed key flags subpacket.  Unhashed key flags subpackets
are ignored.  The presence of a hashed key flags subpacket is specified
by the flag PGPDIG_HAS_KEY_FLAGS in struct pgpDigParams_s::saved.  A new
`hashed` parameter is added to pgpPrtSubType() to allow hashed and
unhashed subpackets to be distinguished.

Since PGPDIG_HAS_KEY_FLAGS must not be inherited from a previous use of
this `struct pgpDigParams_s`, it is cleared by pgpPrtSig() whenever it
processes a new signature.  All other saved flags, with the exception of
PGPDIG_SAVED_ID and PGPDIG_SAVED_TIME, are also cleared.  This allows
for future changes to store per-key state without worrying that it will
be inherited from a previously used key.  The key usage flags are
cleared too, although this is not strictly necessary.

RFC4880 requires that a subkey binding signature be v4 if the subkey is
capable of signing.  Requiring a hashed key flags subpacket for such
signatures enforces this requirement implicitly, as v3 signatures do not
have subpackets.  RFC4880 also requires that primary key binding
signatures be present and checked.  This is not implemented in this
commit, but may be implemented in a future commit.

To avoid a performance penalty, pgpPrtSig() is changed to ignore the
MPIs of a signature if its `tag` parameter is 0.  The only caller that
sets `tag` to 0 is pgpPrtParamSubkeys(), which does not actually check
any cryptographic signatures.  The subkey binding signature has been
checked earlier in pgpPrtParams().

Fixes rpm-software-management#1911.
DemiMarie added a commit to DemiMarie/rpm that referenced this issue Mar 18, 2022
This ensures that a signature is only accepted if the key in question
can actually be used for signing.  Tests 265 and 266 verify that RPM
completely ignores keys that are not capable of signing.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  No signature, regardless of type, is permitted to have
more than one hashed key flags subpacket.  Unhashed key flags subpackets
are ignored.  The presence of a hashed key flags subpacket is specified
by the flag PGPDIG_HAS_KEY_FLAGS in struct pgpDigParams_s::saved.  A new
`hashed` parameter is added to pgpPrtSubType() to allow hashed and
unhashed subpackets to be distinguished.

Since PGPDIG_HAS_KEY_FLAGS must not be inherited from a previous use of
this `struct pgpDigParams_s`, it is cleared by pgpPrtSig() whenever it
processes a new signature.  All other saved flags, with the exception of
PGPDIG_SAVED_ID and PGPDIG_SAVED_TIME, are also cleared.  This allows
for future changes to store per-key state without worrying that it will
be inherited from a previously used key.  The key usage flags are
cleared too, although this is not strictly necessary.

RFC4880 requires that a subkey binding signature be v4 if the subkey is
capable of signing.  Requiring a hashed key flags subpacket for such
signatures enforces this requirement implicitly, as v3 signatures do not
have subpackets.  RFC4880 also requires that primary key binding
signatures be present and checked.  This is not implemented in this
commit, but may be implemented in a future commit.

To avoid a performance penalty, pgpPrtSig() is changed to ignore the
MPIs of a signature if its `tag` parameter is 0.  The only caller that
sets `tag` to 0 is pgpPrtParamSubkeys(), which does not actually check
any cryptographic signatures.  The subkey binding signature has been
checked earlier in pgpPrtParams().

Fixes rpm-software-management#1911.
DemiMarie added a commit to DemiMarie/rpm that referenced this issue Mar 18, 2022
This ensures that a signature is only accepted if the key in question
can actually be used for signing.  Tests 265 and 266 verify that RPM
completely ignores keys that are not capable of signing.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  No signature, regardless of type, is permitted to have
more than one hashed key flags subpacket.  Unhashed key flags subpackets
are ignored.  The presence of a hashed key flags subpacket is specified
by the flag PGPDIG_HAS_KEY_FLAGS in struct pgpDigParams_s::saved.  A new
`hashed` parameter is added to pgpPrtSubType() to allow hashed and
unhashed subpackets to be distinguished.

Since PGPDIG_HAS_KEY_FLAGS must not be inherited from a previous use of
this `struct pgpDigParams_s`, it is cleared by pgpPrtSig() whenever it
processes a new signature.  All other saved flags, with the exception of
PGPDIG_SAVED_ID and PGPDIG_SAVED_TIME, are also cleared.  This allows
for future changes to store per-key state without worrying that it will
be inherited from a previously used key.  The key usage flags are
cleared too, although this is not strictly necessary.

RFC4880 requires that a subkey binding signature be v4 if the subkey is
capable of signing.  Requiring a hashed key flags subpacket for such
signatures enforces this requirement implicitly, as v3 signatures do not
have subpackets.  RFC4880 also requires that primary key binding
signatures be present and checked.  This is not implemented in this
commit, but may be implemented in a future commit.

To avoid a performance penalty, pgpPrtSig() is changed to ignore the
MPIs of a signature if its `tag` parameter is 0.  The only caller that
sets `tag` to 0 is pgpPrtParamSubkeys(), which does not actually check
any cryptographic signatures.  The subkey binding signature has been
checked earlier in pgpPrtParams().

Finally, use the new `hashed` parameter to pgpPrtSubType() to reject
*all* creation time subpackets in the unhashed section, even those that
are of a length RPM does not know about.

Fixes rpm-software-management#1911.
DemiMarie added a commit to DemiMarie/rpm that referenced this issue Mar 18, 2022
This ensures that a signature is only accepted if the key in question
can actually be used for signing.  Tests 265 and 266 verify that RPM
completely ignores keys that are not capable of signing.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  No signature, regardless of type, is permitted to have
more than one hashed key flags subpacket.  Unhashed key flags subpackets
are ignored.  The presence of a hashed key flags subpacket is specified
by the flag PGPDIG_HAS_KEY_FLAGS in struct pgpDigParams_s::saved.  A new
`hashed` parameter is added to pgpPrtSubType() to allow hashed and
unhashed subpackets to be distinguished.

Since PGPDIG_HAS_KEY_FLAGS must not be inherited from a previous use of
this `struct pgpDigParams_s`, it is cleared by pgpPrtSig() whenever it
processes a new signature.  All other saved flags, with the exception of
PGPDIG_SAVED_ID and PGPDIG_SAVED_TIME, are also cleared.  This allows
for future changes to store per-key state without worrying that it will
be inherited from a previously used key.  The key usage flags are
cleared too, although this is not strictly necessary.

RFC4880 requires that a subkey binding signature be v4 if the subkey is
capable of signing.  Requiring a hashed key flags subpacket for such
signatures enforces this requirement implicitly, as v3 signatures do not
have subpackets.  RFC4880 also requires that primary key binding
signatures be present and checked.  This is not implemented in this
commit, but may be implemented in a future commit.

To avoid a performance penalty, pgpPrtSig() is changed to ignore the
MPIs of a signature if its `tag` parameter is 0.  The only caller that
sets `tag` to 0 is pgpPrtParamSubkeys(), which does not actually check
any cryptographic signatures.  The subkey binding signature has been
checked earlier in pgpPrtParams().

Finally, use the new `hashed` parameter to pgpPrtSubType() to reject
*all* creation time subpackets in the unhashed section, even those that
are of a length RPM does not know about.

Fixes rpm-software-management#1911.
DemiMarie added a commit to DemiMarie/rpm that referenced this issue Mar 19, 2022
This ensures that a signature is only accepted if the key in question
can actually be used for signing.  Tests 265 and 266 verify that RPM
completely ignores keys that are not capable of signing.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  No signature, regardless of type, is permitted to have
more than one hashed key flags subpacket.  Unhashed key flags subpackets
are ignored.  The presence of a hashed key flags subpacket is specified
by the flag PGPDIG_HAS_KEY_FLAGS in struct pgpDigParams_s::saved.  A new
`hashed` parameter is added to pgpPrtSubType() to allow hashed and
unhashed subpackets to be distinguished.

Since PGPDIG_HAS_KEY_FLAGS must not be inherited from a previous use of
this `struct pgpDigParams_s`, it is cleared by pgpPrtSig() whenever it
processes a new signature.  All other saved flags, with the exception of
PGPDIG_SAVED_ID and PGPDIG_SAVED_TIME, are also cleared.  This allows
for future changes to store per-key state without worrying that it will
be inherited from a previously used key.  The key usage flags are
cleared too, although this is not strictly necessary.

RFC4880 requires that a subkey binding signature be v4 if the subkey is
capable of signing.  Requiring a hashed key flags subpacket for such
signatures enforces this requirement implicitly, as v3 signatures do not
have subpackets.  RFC4880 also requires that primary key binding
signatures be present and checked.  This is not implemented in this
commit, but may be implemented in a future commit.

To avoid a performance penalty, pgpPrtSig() is changed to ignore the
MPIs of a signature if its `tag` parameter is 0.  The only caller that
sets `tag` to 0 is pgpPrtParamSubkeys(), which does not actually check
any cryptographic signatures.  The subkey binding signature has been
checked earlier in pgpPrtParams().

Finally, use the new `hashed` parameter to pgpPrtSubType() to reject
*all* creation time subpackets in the unhashed section, even those that
are of a length RPM does not know about.

Fixes rpm-software-management#1911.
DemiMarie added a commit to DemiMarie/rpm that referenced this issue Mar 24, 2022
This ensures that a signature is only accepted if the key in question
can actually be used for signing.  Tests 265 and 266 verify that RPM
completely ignores keys that are not capable of signing.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  No signature, regardless of type, is permitted to have
more than one hashed key flags subpacket.  Unhashed key flags subpackets
are ignored.  The presence of a hashed key flags subpacket is specified
by the flag PGPDIG_HAS_KEY_FLAGS in struct pgpDigParams_s::saved.  A new
`hashed` parameter is added to pgpPrtSubType() to allow hashed and
unhashed subpackets to be distinguished.

Since PGPDIG_HAS_KEY_FLAGS must not be inherited from a previous use of
this `struct pgpDigParams_s`, it is cleared by pgpPrtSig() whenever it
processes a new signature.  All other saved flags, with the exception of
PGPDIG_SAVED_ID and PGPDIG_SAVED_TIME, are also cleared.  This allows
for future changes to store per-key state without worrying that it will
be inherited from a previously used key.  The key usage flags are
cleared too, although this is not strictly necessary.

RFC4880 requires that a subkey binding signature be v4 if the subkey is
capable of signing.  Requiring a hashed key flags subpacket for such
signatures enforces this requirement implicitly, as v3 signatures do not
have subpackets.  RFC4880 also requires that primary key binding
signatures be present and checked.  This is not implemented in this
commit, but may be implemented in a future commit.

To avoid a performance penalty, pgpPrtSig() is changed to ignore the
MPIs of a signature if its `tag` parameter is 0.  The only caller that
sets `tag` to 0 is pgpPrtParamSubkeys(), which does not actually check
any cryptographic signatures.  The subkey binding signature has been
checked earlier in pgpPrtParams().

Finally, use the new `hashed` parameter to pgpPrtSubType() to reject
*all* creation time subpackets in the unhashed section, even those that
are of a length RPM does not know about.

Fixes rpm-software-management#1911.
DemiMarie added a commit to DemiMarie/rpm that referenced this issue Mar 24, 2022
This ensures that a signature is only accepted if the key in question
can actually be used for signing.  Tests 265 and 266 verify that RPM
completely ignores keys that are not capable of signing.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  No signature, regardless of type, is permitted to have
more than one hashed key flags subpacket.  Unhashed key flags subpackets
are ignored.  The presence of a hashed key flags subpacket is specified
by the flag PGPDIG_HAS_KEY_FLAGS in struct pgpDigParams_s::saved.  A new
`hashed` parameter is added to pgpPrtSubType() to allow hashed and
unhashed subpackets to be distinguished.

Since PGPDIG_HAS_KEY_FLAGS must not be inherited from a previous use of
this `struct pgpDigParams_s`, it is cleared by pgpPrtSig() whenever it
processes a new signature.  All other saved flags, with the exception of
PGPDIG_SAVED_ID and PGPDIG_SAVED_TIME, are also cleared.  This allows
for future changes to store per-key state without worrying that it will
be inherited from a previously used key.  The key usage flags are
cleared too, although this is not strictly necessary.

RFC4880 requires that a subkey binding signature be v4 if the subkey is
capable of signing.  Requiring a hashed key flags subpacket for such
signatures enforces this requirement implicitly, as v3 signatures do not
have subpackets.  RFC4880 also requires that primary key binding
signatures be present and checked.  This is not implemented in this
commit, but may be implemented in a future commit.

To avoid a performance penalty, pgpPrtSig() is changed to ignore the
MPIs of a signature if its `tag` parameter is 0.  The only caller that
sets `tag` to 0 is pgpPrtParamSubkeys(), which does not actually check
any cryptographic signatures.  The subkey binding signature has been
checked earlier in pgpPrtParams().

Finally, use the new `hashed` parameter to pgpPrtSubType() to reject
*all* creation time subpackets in the unhashed section, even those that
are of a length RPM does not know about.

Fixes rpm-software-management#1911.
DemiMarie added a commit to DemiMarie/rpm that referenced this issue Mar 25, 2022
This ensures that a signature is only accepted if the key in question
can actually be used for signing.  Tests 265 and 266 verify that RPM
completely ignores keys that are not capable of signing.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  No signature, regardless of type, is permitted to have
more than one hashed key flags subpacket.  Unhashed key flags subpackets
are ignored.  The presence of a hashed key flags subpacket is specified
by the flag PGPDIG_HAS_KEY_FLAGS in struct pgpDigParams_s::saved.  A new
`hashed` parameter is added to pgpPrtSubType() to allow hashed and
unhashed subpackets to be distinguished.

Since PGPDIG_HAS_KEY_FLAGS must not be inherited from a previous use of
this `struct pgpDigParams_s`, it is cleared by pgpPrtSig() whenever it
processes a new signature.  All other saved flags, with the exception of
PGPDIG_SAVED_ID and PGPDIG_SAVED_TIME, are also cleared.  This allows
for future changes to store per-key state without worrying that it will
be inherited from a previously used key.  The key usage flags are
cleared too, although this is not strictly necessary.

RFC4880 requires that a subkey binding signature be v4 if the subkey is
capable of signing.  Requiring a hashed key flags subpacket for such
signatures enforces this requirement implicitly, as v3 signatures do not
have subpackets.  RFC4880 also requires that primary key binding
signatures be present and checked.  This is not implemented in this
commit, but may be implemented in a future commit.

To avoid a performance penalty, pgpPrtSig() is changed to ignore the
MPIs of a signature if its `tag` parameter is 0.  The only caller that
sets `tag` to 0 is pgpPrtParamSubkeys(), which does not actually check
any cryptographic signatures.  The subkey binding signature has been
checked earlier in pgpPrtParams().

Finally, use the new `hashed` parameter to pgpPrtSubType() to reject
*all* creation time subpackets in the unhashed section, even those that
are of a length RPM does not know about.

Fixes rpm-software-management#1911.
DemiMarie added a commit to DemiMarie/rpm that referenced this issue Mar 26, 2022
This ensures that a signature is only accepted if the key in question
can actually be used for signing.  Tests 265 and 266 verify that RPM
completely ignores keys that are not capable of signing.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  No signature, regardless of type, is permitted to have
more than one hashed key flags subpacket.  Unhashed key flags subpackets
are ignored.  The presence of a hashed key flags subpacket is specified
by the flag PGPDIG_HAS_KEY_FLAGS in struct pgpDigParams_s::saved.  A new
`hashed` parameter is added to pgpPrtSubType() to allow hashed and
unhashed subpackets to be distinguished.

Since PGPDIG_HAS_KEY_FLAGS must not be inherited from a previous use of
this `struct pgpDigParams_s`, it is cleared by pgpPrtSig() whenever it
processes a new signature.  All other saved flags, with the exception of
PGPDIG_SAVED_ID and PGPDIG_SAVED_TIME, are also cleared.  This allows
for future changes to store per-key state without worrying that it will
be inherited from a previously used key.  The key usage flags are
cleared too, although this is not strictly necessary.

RFC4880 requires that a subkey binding signature be v4 if the subkey is
capable of signing.  Requiring a hashed key flags subpacket for such
signatures enforces this requirement implicitly, as v3 signatures do not
have subpackets.  RFC4880 also requires that primary key binding
signatures be present and checked.  This is not implemented in this
commit, but may be implemented in a future commit.

To avoid a performance penalty, pgpPrtSig() is changed to ignore the
MPIs of a signature if its `tag` parameter is 0.  The only caller that
sets `tag` to 0 is pgpPrtParamSubkeys(), which does not actually check
any cryptographic signatures.  The subkey binding signature has been
checked earlier in pgpPrtParams().

Finally, use the new `hashed` parameter to pgpPrtSubType() to reject
*all* creation time subpackets in the unhashed section, even those that
are of a length RPM does not know about.

Fixes rpm-software-management#1911.
DemiMarie added a commit to DemiMarie/rpm that referenced this issue Mar 26, 2022
This ensures that a signature is only accepted if the key in question
can actually be used for signing.  Tests 265 and 266 verify that RPM
completely ignores keys that are not capable of signing.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  No signature, regardless of type, is permitted to have
more than one hashed key flags subpacket.  Unhashed key flags subpackets
are ignored.  The presence of a hashed key flags subpacket is specified
by the flag PGPDIG_HAS_KEY_FLAGS in struct pgpDigParams_s::saved.  A new
`hashed` parameter is added to pgpPrtSubType() to allow hashed and
unhashed subpackets to be distinguished.

Since PGPDIG_HAS_KEY_FLAGS must not be inherited from a previous use of
this `struct pgpDigParams_s`, it is cleared by pgpPrtSig() whenever it
processes a new signature.  All other saved flags, with the exception of
PGPDIG_SAVED_ID and PGPDIG_SAVED_TIME, are also cleared.  This allows
for future changes to store per-key state without worrying that it will
be inherited from a previously used key.  The key usage flags are
cleared too, although this is not strictly necessary.

RFC4880 requires that a subkey binding signature be v4 if the subkey is
capable of signing.  Requiring a hashed key flags subpacket for such
signatures enforces this requirement implicitly, as v3 signatures do not
have subpackets.  RFC4880 also requires that primary key binding
signatures be present and checked.  This is not implemented in this
commit, but may be implemented in a future commit.

To avoid a performance penalty, pgpPrtSig() is changed to ignore the
MPIs of a signature if its `tag` parameter is 0.  The only caller that
sets `tag` to 0 is pgpPrtParamSubkeys(), which does not actually check
any cryptographic signatures.  The subkey binding signature has been
checked earlier in pgpPrtParams().

Finally, use the new `hashed` parameter to pgpPrtSubType() to explicitly
ignore *all* creation time subpackets in the unhashed section, even
those that are of a length RPM does not know about.

Fixes rpm-software-management#1911.
DemiMarie added a commit to DemiMarie/rpm that referenced this issue Mar 26, 2022
This ensures that a signature is only accepted if the key in question
can actually be used for signing.  Tests 265 and 266 verify that RPM
completely ignores keys that are not capable of signing.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  No signature, regardless of type, is permitted to have
more than one hashed key flags subpacket.  Unhashed key flags subpackets
are ignored.  The presence of a hashed key flags subpacket is specified
by the flag PGPDIG_SIG_HAS_KEY_FLAGS in struct pgpDigParams_s::saved.
As with all PGPDIG_SIG_HAS_* flags, this is reset for each signature.
A new `hashed` parameter is added to pgpPrtSubType() to allow hashed and
unhashed subpackets to be distinguished.

RFC4880 requires that a subkey binding signature be v4 if the subkey is
capable of signing.  Requiring a hashed key flags subpacket for such
signatures enforces this requirement implicitly, as v3 signatures do not
have subpackets.  RFC4880 also requires that primary key binding
signatures be present and checked.  This is not implemented in this
commit, but may be implemented in a future commit.

To avoid a performance penalty, pgpPrtSig() is changed to ignore the
MPIs of a signature if its `tag` parameter is 0.  The only caller that
sets `tag` to 0 is pgpPrtParamSubkeys(), which does not actually check
any cryptographic signatures.  The subkey binding signature has been
checked earlier in pgpPrtParams().  To ensure that pgpPrtSig() will
overwrite data from old signatures when needed, the checks for
‘_digp->pubkey_algo == 0’ are replaced with checks for
‘_digp->alg == NULL’.  Otherwise, later subkey signatures would not have
the signature type updated, causing revocation signatures to be treated
as binding signatures (oops!).  pubkey_algo is also set to 0 to catch
this case.

The previous ‘pgpVerifySelf()’ code was clumsy: the type of the
self-signature should be determined by the type of the data it is a
signature of, not the other way around.  The new code is much cleaner,
which makes adding the revocation check much simpler.

Finally, use the new `hashed` parameter to pgpPrtSubType() to explicitly
ignore *all* creation time subpackets in the unhashed section, even
those that are of a length RPM does not know about.

Fixes rpm-software-management#1911.
DemiMarie added a commit to DemiMarie/rpm that referenced this issue Mar 26, 2022
This ensures that a signature is only accepted if the key in question
can actually be used for signing.  Tests 265 and 266 verify that RPM
completely ignores keys that are not capable of signing.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  No signature, regardless of type, is permitted to have
more than one hashed key flags subpacket.  Unhashed key flags subpackets
are ignored.  The presence of a hashed key flags subpacket is specified
by the flag PGPDIG_SIG_HAS_KEY_FLAGS in struct pgpDigParams_s::saved.
As with all PGPDIG_SIG_HAS_* flags, this is reset for each signature.
A new `hashed` parameter is added to pgpPrtSubType() to allow hashed and
unhashed subpackets to be distinguished.

RFC4880 requires that a subkey binding signature be v4 if the subkey is
capable of signing.  Requiring a hashed key flags subpacket for such
signatures enforces this requirement implicitly, as v3 signatures do not
have subpackets.  RFC4880 also requires that primary key binding
signatures be present and checked.  This is not implemented in this
commit, but may be implemented in a future commit.

To avoid a performance penalty, pgpPrtSig() is changed to ignore the
MPIs of a signature if its `tag` parameter is 0.  The only caller that
sets `tag` to 0 is pgpPrtParamSubkeys(), which does not actually check
any cryptographic signatures.  The subkey binding signature has been
checked earlier in pgpPrtParams().  To ensure that pgpPrtSig() will
overwrite data from old signatures when needed, the checks for
‘_digp->pubkey_algo == 0’ are replaced with checks for
‘_digp->alg == NULL’.  Otherwise, later subkey signatures would not have
the signature type updated, causing revocation signatures to be treated
as binding signatures (oops!).  pubkey_algo is also set to 0 to catch
this case.

The previous ‘pgpVerifySelf()’ code was clumsy: the type of the
self-signature should be determined by the type of the data it is a
signature of, not the other way around.  The new code is much cleaner,
which makes adding the revocation check much simpler.

Finally, use the new `hashed` parameter to pgpPrtSubType() to explicitly
ignore *all* creation time subpackets in the unhashed section, even
those that are of a length RPM does not know about.

Fixes rpm-software-management#1911.
DemiMarie added a commit to DemiMarie/rpm that referenced this issue Mar 27, 2022
This ensures that a signature is only accepted if the subkey that made
it is actually allowed to sign.  Test 265 verifies that RPM ignores
subkeys that cannot sign.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  RFC4880 requires that the subkey binding signature be
v4, which this requirement enforces implicitly.  RFC4880 also requires
that primary key binding signatures be present and checked.  This is not
yet implemented, but may be implemented later.

Fixes rpm-software-management#1911.
DemiMarie added a commit to DemiMarie/rpm that referenced this issue Mar 27, 2022
This ensures that a signature is only accepted if the subkey that made
it is actually allowed to sign.  Test 265 verifies that RPM ignores
subkeys that cannot sign.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  RFC4880 requires that the subkey binding signature be
v4, which this requirement enforces implicitly.  RFC4880 also requires
that primary key binding signatures be present and checked.  This is not
yet implemented, but may be implemented later.

Fixes rpm-software-management#1911.
@nwalfield
Copy link
Contributor

A better way is to look at the creation time of the signature you want to verify, then ask the question whether the certificate and its signing subkeys are valid at that point in time.

FWIW, this is the policy that I chose in the Sequoia backend for rpm. The signature is check at the current time. And a view of the certificate is create as of the signature's time.

@DemiMarie
Copy link
Contributor Author

A better way is to look at the creation time of the signature you want to verify, then ask the question whether the certificate and its signing subkeys are valid at that point in time.

FWIW, this is the policy that I chose in the Sequoia backend for rpm. The signature is check at the current time. And a view of the certificate is create as of the signature's time.

That’s valid, thanks!

DemiMarie added a commit to DemiMarie/rpm that referenced this issue Mar 30, 2022
This ensures that a signature is only accepted if the subkey that made
it is actually allowed to sign.  Test 265 verifies that RPM ignores
subkeys that cannot sign.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  RFC4880 requires that the subkey binding signature be
v4, which this requirement enforces implicitly.  RFC4880 also requires
that primary key binding signatures be present and checked.  This is not
yet implemented, but may be implemented later.

Fixes rpm-software-management#1911.
pmatilai pushed a commit that referenced this issue Mar 31, 2022
This ensures that a signature is only accepted if the subkey that made
it is actually allowed to sign.  Test 265 verifies that RPM ignores
subkeys that cannot sign.

A subkey is considered to be capable of signing if, and only if, its
subkey binding signature has a hashed key flags subpacket that contains
the flag 0x02.  RFC4880 requires that the subkey binding signature be
v4, which this requirement enforces implicitly.  RFC4880 also requires
that primary key binding signatures be present and checked.  This is not
yet implemented, but may be implemented later.

Fixes #1911.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants