Goal

Today's goal is to add support for OpenPGP hardware card credentials.

Roadmap

roadmap

Changes from last time:

  • marked "create credential when init repo" and "initialize chunk repository" as finished
  • picked "OpenPGP card credential" as next task

Plan

  • Implement a new credential using the rsoct program by Heiko Schaefer. Testing with hardware can be tricky to automate, but test at least manually.
    • Implement a CredentialKind::OpenPgpCard variant.
    • Implement an obnam credential openpgp-card command.

Notes

  • First change actually needs to be to change obnam sop to support rsoct. I've done this before in sopass by using rsop for most things, but rsoct for things that require the key on the card.
  • The jist of it is to have two commands, both defaulting to rsop, but allowing the other command to be set to rsoct to support an OpenPGP card.
  • I split Sop so it knows two commands. Also changed all call sites for constructing a Sop.
  • This allows me to run obnam sop decrypt rsoct CERT MSG to decrypt a message encrypted with rsop encrypt. However, I can't encrypt with obnam sop encrypt is it wants to extract the certificate from the file given as a key, and for cards that's not a key, it's a certificate. I'll live with this, for now.
  • Added a CredentialKind::OpenPgpCard variant, and implemented it using software keys, for now.
  • Hm, Sop::decrypt also wants an OpenPgpKey, but we don't have that for cards. Changing that will result in messy changes. I need a re-think.
  • OK, I'll throw away all I did in this branch (read: I'll start a new branch off main), and split Sop into Sop and SopCard.
  • There may be a need for SopLike trait. But not now.
  • Changed obnam sop decrypt to support SopCard if --sop-card option is used. obnam sop encrypt doesn't need that, for now, but will need the same treatment later.
  • Interesting problem: now that I have two credential method variants, the CredentialSpec::method method can't return an impl CredentialMethod, because it can only return one concrete type that implements a credential mehtod. If I change the return type to be Box<dyn CredentialMethod>, then Config::credential_method also needs to return a vector of that type, which means when src/bin/cmd/credential.rs uses them, there's a problem: "the trait bound std::boxed::Box<dyn obnam::credential::CredentialMethod>: obnam::credential::CredentialMethod is not satisfied". There's also a warning about multiple versions of the obnam crate in use.
  • I can work around this by putting all use of credential methods created from the configuration into src/config.rs, at least for now.
  • Hm, no, that's not good enough. It would require src/config.rs to know about how to encrypt different kinds of credentials. Tricky.
  • I'll change CredentialMethod to be an enum instead of a trait.
  • I'd prefer a trait based approach, as it keeps types and their impls smaller, but if I can't get that to work, then I'll do this.
  • I can refactor this once I learn how to achieve this in Rust with traits.
  • Now I realize I haven't actually implemented creating a first credential when initializing a client, oops. That means I can't test this.
  • I'll tidy up the branch and continue next time.

Summary

I ran a little over time today, and found out that I hadn't actually implemented some things I thought I had, but I did make progress. I can now create an OpenPGP card credential, and can continue from here next time. I'll need to fix up store and client initialization so that at least one credential chunk is actually created, and then I'll be able to test the card credentials, manually.

Comments?

If you have feedback on this development session, please use the following fediverse thread: https://toot.liw.fi/@liw/115201974511602854.