Skip to content

FXCM-2273: Refactor login/encryption code into a new support crate - #7542

Merged
jo merged 1 commit into
mozilla:mainfrom
oskirby:fxcm-2274-add-encryption-crate
Sep 22, 2026
Merged

jo merged 1 commit into
mozilla:mainfrom
oskirby:fxcm-2274-add-encryption-crate

Conversation

@oskirby

@oskirby oskirby commented Aug 13, 2026 •

Copy link
Copy Markdown
Collaborator

This attempts to refactor the credential encryption code and move it into it's own support crate so that it can be re-used by other modules in the a-s ecosystem, and is a prerequisite for supporting encrypted autofill (eg: to store things like payment details).

There were some changes made to the uniffi API to enable this work, but logically there should be no meaningful changes to the API, and it should be compatible with no changes to the consumers of this code. It's a bit unclear to me how serious these changes are, and whether they constitute an API change. The changes include:

  • The encryption-related types and traits are moved out of logins.udl and into a new crate encryption.udl.
  • The encryption-related types and traits that were moved, are re-export by logins.udl as external types.
  • The return type is changed from a LoginsApiError to an EncryptionApiError.
  • The constructor for the NSSKeyManager type now takes a key_name parameter, though as far as I can tell, the NSSKeyManager was never acually exposed by uniffi.

Downstream, when merged into Firefox, this will require the following changes to be made:

  • The UniFFI bindings will need to be re-generated.
  • Android: The methods createKey(), checkCanary() and createCanary() have been moved from mozilla.appservices.logins to mozilla.appservices.db_crypto
  • The import of PrimaryPasswordAuthenticator will need to be moved from RustLogins.sys.mjs to RustDbCrypto.sys.mjs

Related JIRA Issues:

Pull Request checklist

  • Breaking changes: This PR follows our breaking change policy
    • This PR follows the breaking change policy:
      • This PR has no breaking API changes, or
      • There are corresponding PRs for our consumer applications that resolve the breaking changes and have been approved
  • Quality: This PR builds and tests run cleanly
    • Note:
      • For changes that need extra cross-platform testing, consider adding [ci full] to the PR title.
      • If this pull request includes a breaking change, consider cutting a new release after merging.
  • Tests: This PR includes thorough tests or an explanation of why it does not
  • Changelog: This PR includes a changelog entry in CHANGELOG.md or an explanation of why it does not need one
    • Any breaking changes to Swift or Kotlin binding APIs are noted explicitly
  • Dependencies: This PR follows our dependency management guidelines
    • Any new dependencies are accompanied by a summary of the due diligence applied in selecting them.

@oskirby
oskirby force-pushed the fxcm-2274-add-encryption-crate branch 3 times, most recently from 27fea06 to 042d197 Compare August 14, 2026 00:13
@oskirby
oskirby marked this pull request as ready for review August 14, 2026 23:19
@oskirby
oskirby force-pushed the fxcm-2274-add-encryption-crate branch from aa20b6c to 26697cb Compare August 17, 2026 08:26
jo
jo previously requested changes Aug 17, 2026

@jo jo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thank you very much for this work!

I think that - contrary to our expectations - this represents a breaking change for Android and Swift users, since error handling has changed and the moved import. Therefore, accompanying pull requests for mobile applications would be necessary 😬 see https://github.com/mozilla/application-services/blob/main/docs/howtos/breaking-changes.md

And could you add a CHANGELOG entry?

Comment thread examples/sync-pass/src/sync-pass.rs Outdated
Comment thread megazords/full/src/lib.rs Outdated
Comment thread components/support/encryption/uniffi.toml Outdated
Comment thread components/support/encryption/android/build.gradle Outdated
Comment thread components/support/encryption/android/build.gradle Outdated
Comment thread components/logins/src/logins.udl Outdated
Comment thread components/logins/src/logins.udl Outdated
Comment on lines +160 to +161
[External = "encryption"]
typedef interface StaticKeyManager;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can go, too afaik, ...

Comment thread components/logins/src/logins.udl Outdated
Comment thread components/logins/src/logins.udl Outdated
bytes decrypt(bytes ciphertext);
};
[External = "encryption"]
typedef trait EncryptorDecryptor;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I am not sure but this might be

typedef trait_with_foreign EncryptorDecryptor;

Comment thread components/logins/src/logins.udl Outdated
bytes get_key();
};
[External = "encryption"]
typedef trait KeyManager;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

and this

typedef trait_with_foreign KeyManager;

@jo

jo commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

@oskirby #7535 has landed, which introduces a key cache - could you port this in here as well?

@oskirby

oskirby commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator Author

@oskirby #7535 has landed, which introduces a key cache - could you port this in here as well?

Yep, I'll rebase my work to pick that up.

@mergify
mergify Bot dismissed jo’s stale review August 18, 2026 14:04

The pull request has been modified, dismissing previous reviews.

@oskirby
oskirby force-pushed the fxcm-2274-add-encryption-crate branch 4 times, most recently from 88f8453 to 51cb1fa Compare August 19, 2026 08:47

@mhammond mhammond left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

just a quick driveby, but this looks great!

Comment thread components/logins/src/lib.rs Outdated
Ok(encryption::create_canary(text, key)?)
}

pub fn check_canary(canary: &str, text: &str, key: &str) -> ApiResult<bool> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

#[handle_error(Error)] here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The original code didn't have it before this PR, but I also don't see a reason why not to add it.

@@ -0,0 +1,30 @@
[package]
name = "encryption"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't like this name, it's too generic and kinda competes with rc_crypto for things generically called "encryption". I think we need some qualification here. Not sure what it might be - something likelogins-encryption, but clearly you are intending to make it more generic than that. I've no great ideas but maybe we can bike-shed?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I agree, and I am open to suggestions as well.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I think something along the lines of 'credential-cryptography` would better represent the intended purpose of this crate, but that is a bit of a lengthy name.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

still a fan of enc_dec and renaming EncryptorDecryptor to EncDec

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm good with either of those options. enc_dec has the advantage of matching exactly how it is used. Happy to leave this decision to y'all!

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I'm not a huge fan of enc_dec for two reasons:

  • It's not really any more specific than encryption
  • Could also be confused with encoder/decoder (a.k.a codecs).

Reading through comments in this area of the code a bit closer suggest that it's really intended for encrypting database records, which by their nature a need to take the form of text both in their plaintext and ciphertext forms (otherwise, I would expect the DB schema to run into problems). And as I understand it, this is also going to be the same case later down the line when autofill starts to use it.

So, how about the name db-crypto, short for Database Cryptography?

issammani
issammani previously approved these changes Sep 2, 2026

@issammani issammani left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Great work @oskirby. We need to remove create_key, check_canary, and create_canary from logins.udl to avoid duplicate method definitions. With that change, it builds on iOS and login operations work as expected. r+

@mergify
mergify Bot dismissed issammani’s stale review September 2, 2026 20:21

The pull request has been modified, dismissing previous reviews.

@oskirby
oskirby force-pushed the fxcm-2274-add-encryption-crate branch from 983e0d9 to 1df7392 Compare September 2, 2026 21:14
@oskirby
oskirby force-pushed the fxcm-2274-add-encryption-crate branch 2 times, most recently from b50d133 to 616d37a Compare September 10, 2026 00:22
@jo
jo force-pushed the fxcm-2274-add-encryption-crate branch 2 times, most recently from c371c6e to a49511a Compare September 10, 2026 09:34
bendk
bendk previously requested changes Sep 17, 2026

@bendk bendk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This looks good to me overall, it's a fairly straightforward refactor that moves the functionality to a new crate. The only questions I have is around the error handling after the refactor. I think some of it can be removed and if so, I think it should be. It's also very possible that I'm missing something and we actually do need the error conversions that I flagged, so feel free to push back on this.

Comment thread components/logins/src/error.rs Outdated
Comment thread components/logins/src/error.rs Outdated
Comment thread components/support/db-crypto/src/error.rs Outdated
impl GetErrorHandling for Error {
type ExternalError = DbCryptoApiError;

fn get_error_handling(&self) -> ErrorHandling<Self::ExternalError> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

When we designed the GetErrorHandling trait, the intended use was for converting errors in top-level API methods that are called in the application. This isn't exactly that, since the db-crypto crate is used by other components and all of this happens below that highest layer. Still, I think it makes sense to report these errors and it seems nice that we can define the logic once here.

Another way of looking at this is the public API of db-crypto is essentially the same as the public API of logins and other components. The fact that db-crypto gets consumed by logins and logins gets consumed by the Firefox application isn't relevant.

I'm not 100% sure what's right, but I'm feeling like the best course is to merge this and see how it works in practice.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

we have found a couple spots in the Firefox codebase that directly reference the types that got moved as a part of this refactoring (specifically toolkit/components/passwordmgr/storage-rust.sys.mjs). So it is not true that the db-crypto crate is exclusively private to this repository.

I must admit I am not enough of an expert on the Firefox side of things to know how this affects the error handling requirements here, and as such I opted to preserve as much of the original error handling traits as was possible.

@mhammond mhammond Sep 19, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I agree with Ben here - this crate shouldn't need to have a "public" error with its own error handling. I haven't thought about options here but it does seem wrong, the consumer crates exposing this as their own variant seems all we need?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

In this sense, db-crypto does two things:

  1. It provides APIs internal to Application Services (EncryptorDecryptor, etc.)
  2. It exposes the PrimaryPasswordAuthenticator to the application

Actually, the PrimaryPasswordAuthenticator should provide the appropriate "public" error handling. And all internal traits (the rest: EncryptorDecryptor, KeyManager) should provide low-level ones. Right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I feel like we're in new territory here with this refactor.

Maybe PrimaryPasswordAuthenticator could have it's own error enum. It's a callback interface, so it would make sense that it has a different error hierarchy than the normal API. I'm not sure how this would look in practice, but it could be worth a try.

For the rest of the API, I'm not really sure if how we should be conceptualizing it. Like I said in that first comment, I can see it both ways. The one thing I like about having the error handling is this crate, is that I think it makes more sense to define what gets reported as an error in db-crypto rather than in every crate that depends on db-crypto.

Comment thread components/support/db-crypto/src/error.rs Outdated
@mergify
mergify Bot dismissed bendk’s stale review September 18, 2026 22:45

The pull request has been modified, dismissing previous reviews.

@oskirby
oskirby force-pushed the fxcm-2274-add-encryption-crate branch from 187938f to 78f5a03 Compare September 18, 2026 23:03

@mhammond mhammond left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this looks great to me, I'll let Ben finish any thoughts on the errors, but :shipit:

@@ -0,0 +1,81 @@
/* This Source Code Form is subject to the terms of the Mozilla Public

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

fyi, we are kinda moving away from UDL, so this is fine. But optionally here or in followup it can die and use uniffi macros.

impl GetErrorHandling for Error {
type ExternalError = DbCryptoApiError;

fn get_error_handling(&self) -> ErrorHandling<Self::ExternalError> {

@mhammond mhammond Sep 19, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I agree with Ben here - this crate shouldn't need to have a "public" error with its own error handling. I haven't thought about options here but it does seem wrong, the consumer crates exposing this as their own variant seems all we need?

@bendk bendk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The code changes look good to me and I like the name db-crypto. It looks like the last thing to figure out is the error handling. I'm okay with the current system so I'm going to hit the approve button. However, I think it would be good to discuss it some more in that comment thread before merging.

@jo
jo added this pull request to the merge queue Sep 22, 2026
Merged via the queue into mozilla:main with commit 6eb36a9 Sep 22, 2026
15 checks passed
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 this pull request may close these issues.

5 participants