Skip to content

implement PIN/passphrase generation UI #324

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

Open
wants to merge 134 commits into
base: 15-qpr2
Choose a base branch
from

Conversation

inthewaves
Copy link
Member

@inthewaves inthewaves commented Jan 26, 2025

Closes GrapheneOS/os-issue-tracker#599

Passphrases have been implemented using EFF's Long Wordlist of $6^5$ words. In terms of entropy, an 8-word passphrase would have a search space of $(6^5)^8 \approx 2^{103}$. This wordlist can be easily changed; just make sure to update the various constants in the DicewareWordList class.

Test: Manual (normal user, work profile, and private space)
Test: atest -c SettingsUnitTests:com.android.settings.password.generate (after building with m and running emulator)
Test: SetupWizard2:

adb shell pm enable app.grapheneos.setupwizard
adb shell settings put secure user_setup_complete 0
adb shell am start -a android.intent.action.MAIN -n app.grapheneos.setupwizard/app.grapheneos.setupwizard.view.activity.WelcomeActivity

@inthewaves inthewaves force-pushed the pin-passphrase-gen-2 branch 5 times, most recently from 1fc6572 to 425ecac Compare January 26, 2025 12:57
@thestinger thestinger force-pushed the 15 branch 2 times, most recently from 0cda973 to d3c03c8 Compare January 27, 2025 09:01
@inthewaves inthewaves force-pushed the pin-passphrase-gen-2 branch from 666c89e to 932b760 Compare January 28, 2025 06:34
@inthewaves
Copy link
Member Author

inthewaves commented Jan 28, 2025

Changes since rebase:

  • fix PasswordComplexity parsing & remove flaky test functions
  • allow skip and changing lock type from SetupWizard. I was reading a comment from BiometricUtil about how PIN is used by default, but I didn't realize it launched SetupLockPassword (via class function overrides) which has its own buttons for choosing lock and skipping. Should've compared it with the original SetupWizard flow
  • clarify comments & test password lengths and selections

@inthewaves inthewaves force-pushed the pin-passphrase-gen-2 branch 3 times, most recently from ec4a72d to cf957c9 Compare January 29, 2025 03:28
@inthewaves
Copy link
Member Author

inthewaves commented Jan 29, 2025

Changes since rebase:

  • hide auto-PIN in SetupWizard and other fixes (auto-PIN originally disabled in SetupWizard but generation flow didn't handle that until now; see 4c8ad8f)
  • make a copy of the credential in the save request for Fragment's SaveWorker

empratyush and others added 6 commits March 5, 2025 16:03
many carrier where 5G network options is available (in settings) doesn't really support standalone 5G and in that case setting it to 'NR/5G only' soft fails.

it is disabled for NSA carrier, calling options will be broken on NSA (non standalone 5G).
…animation"

This reverts commit cdfab94fdab8287e47e6a24bb1700a85ee250484.
@inthewaves inthewaves force-pushed the pin-passphrase-gen-2 branch from 9583dfa to 5cff010 Compare March 9, 2025 20:09
@inthewaves inthewaves changed the base branch from 15 to 15-qpr2 March 10, 2025 01:37
@inthewaves inthewaves force-pushed the pin-passphrase-gen-2 branch 3 times, most recently from 8010895 to 7a0d905 Compare March 10, 2025 08:22
@inthewaves
Copy link
Member Author

inthewaves commented Mar 10, 2025

Changes:

  • Delegate final confirmation step to AOSP's ChooseLockPassword activity so that we don't have duplicate validation and saving logic. To facilitate this, the generated password (as a LockscreenCredential) and also original intent extras are passed to ChooseLockPassword (since our generate password Activity intercepts all of the extras originally meant for ChooseLockPassword).

    The select-and-confirm flow now:

    1. Our ShowGeneratedLockPassOptionsFragment: User selects a generated password from a RadioButton list
    2. Our ConfirmGeneratedLockPassFragment: Confirm with password visible
    3. Our ConfirmGeneratedLockPassFragment: Confirm again with password not visible
    4. AOSP's ChooseLockPassword: Confirm one more time, then save the password

    The first two confirmation steps are still handed by our generated password Activity for the following reasons:

    1. AOSP's ChooseLockPassword only has 3 stages: Introduction, NeedToConfirm, ConfirmWrong. The Introduction lets the user for what they want as a password, and the NeedToConfirm / ConfirmWrong stages gets them to confirm the password from Introduction. So, there's essentially only 1 confirmation stage

      We would need to modify ChooseLockPassword even more if we want to add multiple rounds of confirmation (like add a new Stage enum, or keeping track of a number of confirmations). If AOSP ever rewrites ChooseLockPassword, then we would have to do those extra modifications from scratch again. ChooseLockPassword can even be subclassed (e.g. there's a subclass for SetupWizard).

      By delegating only the last confirmation step to AOSP's ChooseLockPassword, all we need to do is simulate the user inputting the generated password as their actual password and display our custom message. This avoids the need to keep track of extra state.

    2. When the user chooses a generated password, we show their selection in the first confirmation stage in plaintext. If we move all of the confirmation stages to ChooseLockPassword, we'd likely have to pass it as a String extra instead of a Parcelable LockscreenCredential (or deal with constructing a String from Charset decoding of the LockscreenCredential) to show it to the user in ChooseLockPassword.

      It's likely better to reduce the number of times the password is stored in String form, since we can't explicitly zero out strings in Java. A String of the password is already stored in the ViewModel in the generate password Activity in case the user wants to go back. (There's probably already Strings from the text input view, though.)

      By delegating only the last confirmation step to AOSP's ChooseLockPassword, we can get away with only passing and using a LockscreenCredential.

  • We stop bypassing sequence errors in password validation. Now that final validation has been delegated to AOSP's ChooseLockPassword, it's possible that their
    activity ends up rejecting a passphrase that we bypassed an error for

  • Use an actual dice icon for diceware

  • Take out changes to show locked notification content settings (should be done as part of consider using Settings app's SetupRedactionInterstitial for notification privacy settings platform_packages_apps_SetupWizard2#38)

  • generalize ChooseLockPassword class selection but limit it to only ChooseLockPassword classes that are known to work since we need to modify it (currently ChooseLockPassword has only 1 subclass, SetupChooseLockPassword, and it works with it)

@inthewaves inthewaves force-pushed the pin-passphrase-gen-2 branch 5 times, most recently from cd9c06b to 58dfee9 Compare March 10, 2025 13:56
@inthewaves
Copy link
Member Author

Changes:

  • Increase the minimum number of words for diceware passphrases from 4 to 6, and the maximum from 8 to 10.

  • Update intro text for passphrases and PINs to be more descriptive with their respective length
    ranges.

  • Change manual passphrase description to a warning, indicating that an overly complex password
    may be less secure than a long passphrase.

  • Remove references to Titan M and just use the general "secure element" wording

  • Add handling for validation errors from AOSP's password activity, showing them in a new section of the UI. This should be very rare and the only reason this would happen if validation code between our code base drifts

  • Add a new AOSPPasswordValidationError class for parceling password validation errors

  • Add early validation of the selected generated passwords against AOSP's validation logic. This is
    achieved by launching the AOSP's ChooseLockPassword in a custom, validation-only mode before
    proceeding to the confirmation steps in our generated password Activity. ChooseLockPassword will be used again for the last step for final confirmation and saving the password

@inthewaves inthewaves force-pushed the pin-passphrase-gen-2 branch from 57120ba to ecc0fae Compare March 11, 2025 01:38
It's already present in Developer options, but they are not available in secondary users.
Both override_desktop_mode_features and enable_freeform_support toggle had the same name UI name:
"Enable freeform windows".
@inthewaves inthewaves force-pushed the pin-passphrase-gen-2 branch from b944939 to bd4524e Compare March 16, 2025 13:17
Passphrases have been implemented using EFF's Long Wordlist of 6^5
words. In terms of entropy, an 8-word passphrase would have a search
space of (6^5)^8 ~= 2^103. This wordlist can be easily changed; just
make sure to update the various constants in the DicewareWordList class

Test: Manual
Test: atest -c SettingsUnitTests:com.android.settings.password.generate
(after building with m and running emulator)
Test: SetupWizard2
- Increase the minimum number of words for diceware passphrases from 4 to 6, and the maximum from
  8 to 10.
- Update intro text for passphrases and PINs to be more descriptive with their respective length
ranges.
- Change manual passphrase description to a warning, indicating that an overly complex password
may be less secure than a long passphrase.
- Remove references to Titan M and just use the general "secure element" wording
- Add handling for validation errors from AOSP's password activity, showing them in a new section of
  the UI. This should be very rare and the only reason this would happen if validation code between
  our code base drifts
- Add a new `AOSPPasswordValidationError` class for parceling password validation errors
Add early validation of the selected generated passwords against AOSP's validation logic. This is
achieved by launching the AOSP's ChooseLockPassword in a custom, validation-only mode before
proceeding to the confirmation steps in our generated password Activity.
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.

provide a UI for generating random PIN/passphrases