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

Add Key Fingerprints to rpmsinfoMsg() #3321

Merged
merged 7 commits into from
Oct 3, 2024

Conversation

ffesti
Copy link
Contributor

@ffesti ffesti commented Sep 20, 2024

This does not yet adjust the test cases. So 198 209 216 217 220 221 222 223 226 227 are failing due to unexpected key finger prints.

Can probably be used in combination with #3292 as this does not touch the keyid output. Although we might want to skip the key id for verified signatures.

Related: #2403

@ffesti ffesti added RFE crypto Signatures, keys, hashes and their verification labels Sep 20, 2024
@ffesti ffesti marked this pull request as draft September 20, 2024 12:52
@pmatilai
Copy link
Member

pmatilai commented Sep 23, 2024

Fishing out an example output from the CI run to make it easier to discuss:

 /tmp/hello-2.0-1.x86_64.rpm:
-    Header V4 ECDSA/SHA256 Signature, key ID 5f65bbe8: OK
+    Header V4 ECDSA/SHA256 Signature, key ID 5f65bbe8: OK, Key Fingerprint: e8a62c0512b06b5d2183ba207f1c21f95f65bbe8

The :OK (or whatever the result) should continue to be the very last thing on this line to make it trivial to see/parse what the TLDR outcome of each part is.

The keyid becomes redundant if the fingerprint is there, so I guess we should just go with what @nwalfield suggested in #3292 (comment) and show either the fingerprint or if not available, the long keyid. Some programs split up the fingerprint a bit to make it easier for humans to consume (eg split by space so the keyid is easy to see), but I don't know if there's a "best practise" on that.

Just FWIW, we're in no way married to using pgpIdentItem() for the rest of our days. That dumb thing never should've been a public API but the rpmio/lib split and lack of other APIs forced the issue at the time - it was supposedly the lesser evil compared leaving all the structs wide open. If we want to dynamically decide on fingerprint/keyid we'll need to ditch it anyhow it seems.

include/rpm/rpmkeyring.h Outdated Show resolved Hide resolved
@mlschroe
Copy link
Contributor

Maybe it's a good idea to also return the pubkey version with the fingerprint if you're adding a new API function.

@ffesti
Copy link
Contributor Author

ffesti commented Sep 23, 2024

OK, put #3292 underneath, adjusted the message and the name of rpmPubkeyFingerprint and make the test cases pass.

For now I have not remove the key IDs from the messages. I wonder if keeping them is more backward compatible. While they are technical redundant figuring out the key IDs from the fingerprints is kinda annoying for anyone parsing the output. But I agree that the messages are getting overly long. Any other opinions? @nwalfield ?

@ffesti ffesti marked this pull request as ready for review September 23, 2024 09:43
@ffesti ffesti requested a review from a team as a code owner September 23, 2024 09:43
@ffesti ffesti requested review from pmatilai and removed request for a team September 23, 2024 09:43
@pmatilai
Copy link
Member

For now I have not remove the key IDs from the messages. I wonder if keeping them is more backward compatible. While they are technical redundant figuring out the key IDs from the fingerprints is kinda annoying for anyone parsing the output.

See my point about splitting the fingerprint up a bit, that way you could make the keyid part stand out.

lib/rpmvs.c Outdated Show resolved Hide resolved
lib/rpmvs.c Outdated Show resolved Hide resolved
if (key == NULL)
return -1;
key = key->mainkey;
pthread_rwlock_rdlock(&key->lock);
Copy link
Member

@pmatilai pmatilai Sep 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lock should be taken one line earlier, above the key assignment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not quite sure about that. To be fair may be I should just use an new variable for that.
But right now we are locking the main key. The one we are actually processing. For sub keys we might need to lock that, too, if the assignment needs a lock around it. Ofc we'd need to be more careful for main keys to not lock them twice.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see it's a bit different than the average key member, and it's indeed trickier than that. But mainkey can go away between the assignment and the locking, so that's not safe as it is.

Subkeys can become separated from the main key (call rpmGetSubkeys() and then free the main key), so the mainkey needs to be reference counted instead. And then you here take a reference to the mainkey.

Also, it's indeed better to use a new variable than reuse an argument, such reuse doesn't save anything at all and makes the code less obvious.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW now that #3302 got merged, you'll need to rebase this and switch to the C++ locking instead of pthread_*.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, now that the locking is completely different I have re-done this.

rpmio/rpmkeyring.c Outdated Show resolved Hide resolved
tests/rpmsigdig.at Outdated Show resolved Hide resolved
rpmio/rpmkeyring.c Outdated Show resolved Hide resolved
@nwalfield
Copy link
Contributor

OK, put #3292 underneath, adjusted the message and the name of rpmPubkeyFingerprint and make the test cases pass.

For now I have not remove the key IDs from the messages.

I think when the fingerprint is available, we should strictly prefer it.

I wonder if keeping them is more backward compatible.

What are you thinking of here? Are you imaging a script breaking because it matches on the key ID? Will those scripts still work when we add the fingerprint to the output?

figuring out the key IDs from the fingerprints is kinda annoying

In what cases does one need a key ID, but a fingerprint is rejected? In other words, why would anyone ever need to derive the key ID?

@nwalfield
Copy link
Contributor

Maybe it's a good idea to also return the pubkey version with the fingerprint if you're adding a new API function.

How do you imagine rpm or an application that uses the library using this information?

@mlschroe
Copy link
Contributor

How do you imagine rpm or an application that uses the library using this information?

Lets say you want to put the key in a database so that you can find it if you want to check a signature. In that case you need to use pubkey version plus fingerprint as a key.

@nwalfield
Copy link
Contributor

How do you imagine rpm or an application that uses the library using this information?

Lets say you want to put the key in a database so that you can find it if you want to check a signature. In that case you need to use pubkey version plus fingerprint as a key.

Why do you need to use the version as part of the key? Are you worried about collisions? Fingerprints don't require collision resistance, because the attacker doesn't control the key material. As such, both SHA-1 and MD5 are safe. See, for instance, this wikipedia article.

@mlschroe
Copy link
Contributor

Are you really arguing that the keyid would have been enough in the signature and switching to the fingerprint was a mistake? Note that the fingerprint subpackage does include the version of the key.

@nwalfield
Copy link
Contributor

Are you really arguing that the keyid would have been enough in the signature and switching to the fingerprint was a mistake? Note that the fingerprint subpackage does include the version of the key.

I really don't understand you. Sure, the issuer fingerprint subpacket includes the version, in which case you have the fingerprint and don't need the key ID. But in the case of the issuer subpacket, you don't have a version. Also, the issuer is self-authenticating. So if multiple key IDs match, then you (should) try them all.

@ffesti ffesti force-pushed the fingerprint branch 2 times, most recently from 0a63303 to a927b9d Compare September 25, 2024 15:22
@ffesti
Copy link
Contributor Author

ffesti commented Sep 25, 2024

I wonder what's the deal with upper verses lower case hex strings. I split the fingerprints into groups of four and in lowercase this looks very wrong to me for some reason. Any opinions on that topic? Looks like RPM has always used lowercase in one continuous string.

@ffesti
Copy link
Contributor Author

ffesti commented Sep 26, 2024

From my POV this is now complete.

include/rpm/rpmkeyring.h Outdated Show resolved Hide resolved
@pmatilai
Copy link
Member

As for the upper/lowercase thing: lets leave it at lowercase here - like it is in the PR now. We'll want to revisit that when we deal with #3313 but there's no need to mess with that here just now.

Copy link
Member

@pmatilai pmatilai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some unresolved review remarks still. Marking as request changes to make it stand out, the main conversation is getting crowded to the point where its hard to see what's still relevant.

@@ -319,15 +319,15 @@ done
[0],
[nopls
/data/RPMS/hello-2.0-1.x86_64-signed.rpm:
Header V4 RSA/SHA256 Signature, key ID 1964c5fc: OK
Header V4 RSA/SHA256 Signature, key ID 4344591e1964c5fc, key fingerprint: 771b18d3d7baa28734333c424344591e1964c5fc: OK
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I realize now why you originally put the fingerprint after the OK: the "key ID" part belongs to the signature. "key fingerprint" after that seems just repetitive, until you realize it comes from a different source entirely.

The message should probably make this clear somehow 🤔

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On a related note, this is also why you should really decide what to output first, and once that is agreed upon, go and implement. You don't need a single line of code to mock up various versions of such messages, and concrete examples are always easier to discuss than highlevel this or that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you really want to keep both, then perhaps:

... signing subkey 4344591e1964c5fc, certificate: 771b18d3d7baa28734333c424344591e1964c5fc

But I'd rather just show the certificate as users don't need to know about this detail.

tests/rpmi.at Show resolved Hide resolved
if (key == NULL)
return -1;
key = key->mainkey;
pthread_rwlock_rdlock(&key->lock);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see it's a bit different than the average key member, and it's indeed trickier than that. But mainkey can go away between the assignment and the locking, so that's not safe as it is.

Subkeys can become separated from the main key (call rpmGetSubkeys() and then free the main key), so the mainkey needs to be reference counted instead. And then you here take a reference to the mainkey.

Also, it's indeed better to use a new variable than reuse an argument, such reuse doesn't save anything at all and makes the code less obvious.

if (key == NULL)
return -1;
key = key->mainkey;
pthread_rwlock_rdlock(&key->lock);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW now that #3302 got merged, you'll need to rebase this and switch to the C++ locking instead of pthread_*.

lib/rpmvs.c Outdated Show resolved Hide resolved
rpmio/rpmkeyring.c Outdated Show resolved Hide resolved
rpmio/rpmkeyring.c Outdated Show resolved Hide resolved
include/rpm/rpmkeyring.h Outdated Show resolved Hide resolved
include/rpm/rpmkeyring.h Outdated Show resolved Hide resolved
rpmio/rpmkeyring.c Outdated Show resolved Hide resolved
rpmio/rpmkeyring.c Outdated Show resolved Hide resolved
rpmio/rpmkeyring.c Outdated Show resolved Hide resolved
Short (4 bytes) PGP Key IDs or insecure and prone to collisions.
Long Key IDs (8 bytes) are still not as good as full Fingerprints with
20 to 32 bytes but a huge step up.

Related: rpm-software-management#2403
Store pointer to primarykey and use it to get the Fingerprint of the primary
key for sub keys.
Add the key to rpmsinfo_s so we have the key available with the verified
signature and can print the key's finger print when desired
The Key IDs may only be confusing when subkeys are used and the key ID
won't match up with the finger print of the main key.
Even if a signature fails giving the fingerprint of the public key that
is involved has some value. The key can no longer be trusted for various
reasons or the package was tempered with. In both cases it might be of
interest which key is outdated or attacked.
{
rpmPubkey key = new rpmPubkey_s {};
/* Packets with all subkeys already stored in main key */
/* Packets with all subkeys already stored in primary key */
key->primarykey = primarykey;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose it should actually take the reference here already, might simplify the rest of stuff as well.
But l agree, lets take another look at the whole in #3350/#3351, it should be easier to see the big picture when this is already in place. We're both getting battle-weary on this PR.

Copy link
Member

@pmatilai pmatilai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I think this is pretty nice now.

The issues with the subkey refcounts and locking were there to begin with, and its quite impossible to reason about those things if one of the places doesn't honor the rules at all. Would've probably been easier if we'd spotted the subkey handling doesn't make much sense to begin and address that first, but it is what it is.

@pmatilai pmatilai merged commit 332edb7 into rpm-software-management:master Oct 3, 2024
1 check passed
@ffesti ffesti deleted the fingerprint branch October 7, 2024 09:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
crypto Signatures, keys, hashes and their verification RFE
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

4 participants