1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-07 20:24:01 +00:00

[PM-27486] Remove feature flag PM25174_DisableType0Decryption (#18413)

This commit is contained in:
Thomas Avery
2026-01-23 11:09:59 -06:00
committed by GitHub
parent 6cf434cf11
commit bc8c925cd0
9 changed files with 26 additions and 73 deletions

View File

@@ -1565,7 +1565,6 @@ export default class MainBackground {
await this.sdkLoadService.loadAndInit();
// Only the "true" background should run migrations
await this.migrationRunner.run();
this.encryptService.init(this.configService);
// This is here instead of in the InitService b/c we don't plan for
// side effects to run in the Browser InitService.

View File

@@ -2,8 +2,6 @@ import { inject, Inject, Injectable, DOCUMENT } from "@angular/core";
import { AbstractThemingService } from "@bitwarden/angular/platform/services/theming/theming.service.abstraction";
import { TwoFactorService } from "@bitwarden/common/auth/two-factor";
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService as LogServiceAbstraction } from "@bitwarden/common/platform/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@@ -30,8 +28,6 @@ export class InitService {
private sdkLoadService: SdkLoadService,
private viewCacheService: PopupViewCacheService,
private readonly migrationRunner: MigrationRunner,
private configService: ConfigService,
private encryptService: EncryptService,
@Inject(DOCUMENT) private document: Document,
) {}
@@ -43,7 +39,6 @@ export class InitService {
this.twoFactorService.init();
await this.viewCacheService.init();
await this.sizeService.init();
this.encryptService.init(this.configService);
const htmlEl = window.document.documentElement;
this.themingService.applyThemeChangesTo(this.document);

View File

@@ -1058,7 +1058,6 @@ export class ServiceContainer {
this.containerService.attachToGlobal(global);
await this.i18nService.init();
this.twoFactorService.init();
this.encryptService.init(this.configService);
// If a user has a BW_SESSION key stored in their env (not process.env.BW_SESSION),
// this should set the user key to unlock the vault on init.

View File

@@ -8,7 +8,6 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv
import { TwoFactorService } from "@bitwarden/common/auth/two-factor";
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
import { DefaultVaultTimeoutService } from "@bitwarden/common/key-management/vault-timeout";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service";
@@ -54,7 +53,6 @@ export class InitService {
private autotypeService: DesktopAutotypeService,
private sdkLoadService: SdkLoadService,
private biometricMessageHandlerService: BiometricMessageHandlerService,
private configService: ConfigService,
@Inject(DOCUMENT) private document: Document,
private readonly migrationRunner: MigrationRunner,
) {}
@@ -65,7 +63,6 @@ export class InitService {
await this.sshAgentService.init();
this.nativeMessagingService.init();
await this.migrationRunner.waitForCompletion(); // Desktop will run migrations in the main process
this.encryptService.init(this.configService);
const accounts = await firstValueFrom(this.accountService.accounts$);
const setUserKeyInMemoryPromises = [];

View File

@@ -8,7 +8,6 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv
import { TwoFactorService } from "@bitwarden/common/auth/two-factor";
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
import { DefaultVaultTimeoutService } from "@bitwarden/common/key-management/vault-timeout";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platform/abstractions/i18n.service";
import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service";
import { IpcService } from "@bitwarden/common/platform/ipc";
@@ -40,7 +39,6 @@ export class InitService {
private ipcService: IpcService,
private sdkLoadService: SdkLoadService,
private taskService: TaskService,
private configService: ConfigService,
private readonly migrationRunner: MigrationRunner,
@Inject(DOCUMENT) private document: Document,
) {}
@@ -49,7 +47,6 @@ export class InitService {
return async () => {
await this.sdkLoadService.loadAndInit();
await this.migrationRunner.run();
this.encryptService.init(this.configService);
const activeAccount = await firstValueFrom(this.accountService.activeAccount$);
if (activeAccount) {

View File

@@ -40,7 +40,6 @@ export enum FeatureFlag {
PrivateKeyRegeneration = "pm-12241-private-key-regeneration",
EnrollAeadOnKeyRotation = "enroll-aead-on-key-rotation",
ForceUpdateKDFSettings = "pm-18021-force-update-kdf-settings",
PM25174_DisableType0Decryption = "pm-25174-disable-type-0-decryption",
LinuxBiometricsV2 = "pm-26340-linux-biometrics-v2",
NoLogoutOnKdfChange = "pm-23995-no-logout-on-kdf-change",
DataRecoveryTool = "pm-28813-data-recovery-tool",
@@ -150,7 +149,6 @@ export const DefaultFeatureFlagValue = {
[FeatureFlag.PrivateKeyRegeneration]: FALSE,
[FeatureFlag.EnrollAeadOnKeyRotation]: FALSE,
[FeatureFlag.ForceUpdateKDFSettings]: FALSE,
[FeatureFlag.PM25174_DisableType0Decryption]: FALSE,
[FeatureFlag.LinuxBiometricsV2]: FALSE,
[FeatureFlag.NoLogoutOnKdfChange]: FALSE,
[FeatureFlag.DataRecoveryTool]: FALSE,

View File

@@ -1,16 +1,8 @@
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { EncArrayBuffer } from "../../../platform/models/domain/enc-array-buffer";
import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key";
import { EncString } from "../models/enc-string";
export abstract class EncryptService {
/**
* A temporary init method to make the encrypt service listen to feature-flag changes.
* This will be removed once the feature flag has been rolled out.
*/
abstract init(configService: ConfigService): void;
/**
* Encrypts a string to an EncString
* @param plainValue - The value to encrypt

View File

@@ -1,9 +1,7 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { CryptoFunctionService } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service";
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service";
import { EncryptionType } from "@bitwarden/common/platform/enums";
@@ -15,28 +13,12 @@ import { PureCrypto } from "@bitwarden/sdk-internal";
import { EncryptService } from "../abstractions/encrypt.service";
export class EncryptServiceImplementation implements EncryptService {
private disableType0Decryption = false;
constructor(
protected cryptoFunctionService: CryptoFunctionService,
protected logService: LogService,
protected logMacFailures: boolean,
) {}
init(configService: ConfigService): void {
configService.serverConfig$.subscribe((newConfig) => {
if (newConfig != null) {
this.setDisableType0Decryption(
newConfig.featureStates[FeatureFlag.PM25174_DisableType0Decryption] === true,
);
}
});
}
setDisableType0Decryption(disable: boolean): void {
this.disableType0Decryption = disable;
}
async encryptString(plainValue: string, key: SymmetricCryptoKey): Promise<EncString> {
if (plainValue == null) {
this.logService.warning(
@@ -60,7 +42,7 @@ export class EncryptServiceImplementation implements EncryptService {
}
async decryptString(encString: EncString, key: SymmetricCryptoKey): Promise<string> {
if (this.disableType0Decryption && encString.encryptionType === EncryptionType.AesCbc256_B64) {
if (encString.encryptionType === EncryptionType.AesCbc256_B64) {
throw new Error("Decryption of AesCbc256_B64 encrypted data is disabled.");
}
await SdkLoadService.Ready;
@@ -68,7 +50,7 @@ export class EncryptServiceImplementation implements EncryptService {
}
async decryptBytes(encString: EncString, key: SymmetricCryptoKey): Promise<Uint8Array> {
if (this.disableType0Decryption && encString.encryptionType === EncryptionType.AesCbc256_B64) {
if (encString.encryptionType === EncryptionType.AesCbc256_B64) {
throw new Error("Decryption of AesCbc256_B64 encrypted data is disabled.");
}
await SdkLoadService.Ready;
@@ -76,7 +58,7 @@ export class EncryptServiceImplementation implements EncryptService {
}
async decryptFileData(encBuffer: EncArrayBuffer, key: SymmetricCryptoKey): Promise<Uint8Array> {
if (this.disableType0Decryption && encBuffer.encryptionType === EncryptionType.AesCbc256_B64) {
if (encBuffer.encryptionType === EncryptionType.AesCbc256_B64) {
throw new Error("Decryption of AesCbc256_B64 encrypted data is disabled.");
}
await SdkLoadService.Ready;
@@ -148,10 +130,7 @@ export class EncryptServiceImplementation implements EncryptService {
throw new Error("No wrappingKey provided for unwrapping.");
}
if (
this.disableType0Decryption &&
wrappedDecapsulationKey.encryptionType === EncryptionType.AesCbc256_B64
) {
if (wrappedDecapsulationKey.encryptionType === EncryptionType.AesCbc256_B64) {
throw new Error("Decryption of AesCbc256_B64 encrypted data is disabled.");
}
@@ -171,10 +150,7 @@ export class EncryptServiceImplementation implements EncryptService {
if (wrappingKey == null) {
throw new Error("No wrappingKey provided for unwrapping.");
}
if (
this.disableType0Decryption &&
wrappedEncapsulationKey.encryptionType === EncryptionType.AesCbc256_B64
) {
if (wrappedEncapsulationKey.encryptionType === EncryptionType.AesCbc256_B64) {
throw new Error("Decryption of AesCbc256_B64 encrypted data is disabled.");
}
@@ -194,10 +170,7 @@ export class EncryptServiceImplementation implements EncryptService {
if (wrappingKey == null) {
throw new Error("No wrappingKey provided for unwrapping.");
}
if (
this.disableType0Decryption &&
keyToBeUnwrapped.encryptionType === EncryptionType.AesCbc256_B64
) {
if (keyToBeUnwrapped.encryptionType === EncryptionType.AesCbc256_B64) {
throw new Error("Decryption of AesCbc256_B64 encrypted data is disabled.");
}

View File

@@ -163,7 +163,7 @@ describe("EncryptService", () => {
describe("decryptString", () => {
it("is a proxy to PureCrypto", async () => {
const key = new SymmetricCryptoKey(makeStaticByteArray(64));
const encString = new EncString("encrypted_string");
const encString = new EncString(EncryptionType.AesCbc256_HmacSha256_B64, "encrypted_string");
const result = await encryptService.decryptString(encString, key);
expect(result).toEqual("decrypted_string");
expect(PureCrypto.symmetric_decrypt_string).toHaveBeenCalledWith(
@@ -172,8 +172,7 @@ describe("EncryptService", () => {
);
});
it("throws if disableType0Decryption is enabled and type is AesCbc256_B64", async () => {
encryptService.setDisableType0Decryption(true);
it("throws if type is AesCbc256_B64", async () => {
const key = new SymmetricCryptoKey(makeStaticByteArray(64));
const encString = new EncString(EncryptionType.AesCbc256_B64, "encrypted_string");
await expect(encryptService.decryptString(encString, key)).rejects.toThrow(
@@ -185,7 +184,7 @@ describe("EncryptService", () => {
describe("decryptBytes", () => {
it("is a proxy to PureCrypto", async () => {
const key = new SymmetricCryptoKey(makeStaticByteArray(64));
const encString = new EncString("encrypted_bytes");
const encString = new EncString(EncryptionType.AesCbc256_HmacSha256_B64, "encrypted_bytes");
const result = await encryptService.decryptBytes(encString, key);
expect(result).toEqual(new Uint8Array(3));
expect(PureCrypto.symmetric_decrypt_bytes).toHaveBeenCalledWith(
@@ -194,8 +193,7 @@ describe("EncryptService", () => {
);
});
it("throws if disableType0Decryption is enabled and type is AesCbc256_B64", async () => {
encryptService.setDisableType0Decryption(true);
it("throws if type is AesCbc256_B64", async () => {
const key = new SymmetricCryptoKey(makeStaticByteArray(64));
const encString = new EncString(EncryptionType.AesCbc256_B64, "encrypted_bytes");
await expect(encryptService.decryptBytes(encString, key)).rejects.toThrow(
@@ -216,8 +214,7 @@ describe("EncryptService", () => {
);
});
it("throws if disableType0Decryption is enabled and type is AesCbc256_B64", async () => {
encryptService.setDisableType0Decryption(true);
it("throws if type is AesCbc256_B64", async () => {
const key = new SymmetricCryptoKey(makeStaticByteArray(64));
const encBuffer = EncArrayBuffer.fromParts(
EncryptionType.AesCbc256_B64,
@@ -234,7 +231,10 @@ describe("EncryptService", () => {
describe("unwrapDecapsulationKey", () => {
it("is a proxy to PureCrypto", async () => {
const key = new SymmetricCryptoKey(makeStaticByteArray(64));
const encString = new EncString("wrapped_decapsulation_key");
const encString = new EncString(
EncryptionType.AesCbc256_HmacSha256_B64,
"wrapped_decapsulation_key",
);
const result = await encryptService.unwrapDecapsulationKey(encString, key);
expect(result).toEqual(new Uint8Array(4));
expect(PureCrypto.unwrap_decapsulation_key).toHaveBeenCalledWith(
@@ -242,8 +242,7 @@ describe("EncryptService", () => {
key.toEncoded(),
);
});
it("throws if disableType0Decryption is enabled and type is AesCbc256_B64", async () => {
encryptService.setDisableType0Decryption(true);
it("throws if type is AesCbc256_B64", async () => {
const key = new SymmetricCryptoKey(makeStaticByteArray(64));
const encString = new EncString(EncryptionType.AesCbc256_B64, "wrapped_decapsulation_key");
await expect(encryptService.unwrapDecapsulationKey(encString, key)).rejects.toThrow(
@@ -267,7 +266,10 @@ describe("EncryptService", () => {
describe("unwrapEncapsulationKey", () => {
it("is a proxy to PureCrypto", async () => {
const key = new SymmetricCryptoKey(makeStaticByteArray(64));
const encString = new EncString("wrapped_encapsulation_key");
const encString = new EncString(
EncryptionType.AesCbc256_HmacSha256_B64,
"wrapped_encapsulation_key",
);
const result = await encryptService.unwrapEncapsulationKey(encString, key);
expect(result).toEqual(new Uint8Array(5));
expect(PureCrypto.unwrap_encapsulation_key).toHaveBeenCalledWith(
@@ -275,8 +277,7 @@ describe("EncryptService", () => {
key.toEncoded(),
);
});
it("throws if disableType0Decryption is enabled and type is AesCbc256_B64", async () => {
encryptService.setDisableType0Decryption(true);
it("throws if type is AesCbc256_B64", async () => {
const key = new SymmetricCryptoKey(makeStaticByteArray(64));
const encString = new EncString(EncryptionType.AesCbc256_B64, "wrapped_encapsulation_key");
await expect(encryptService.unwrapEncapsulationKey(encString, key)).rejects.toThrow(
@@ -300,7 +301,10 @@ describe("EncryptService", () => {
describe("unwrapSymmetricKey", () => {
it("is a proxy to PureCrypto", async () => {
const key = new SymmetricCryptoKey(makeStaticByteArray(64));
const encString = new EncString("wrapped_symmetric_key");
const encString = new EncString(
EncryptionType.AesCbc256_HmacSha256_B64,
"wrapped_symmetric_key",
);
const result = await encryptService.unwrapSymmetricKey(encString, key);
expect(result).toEqual(new SymmetricCryptoKey(new Uint8Array(64)));
expect(PureCrypto.unwrap_symmetric_key).toHaveBeenCalledWith(
@@ -308,8 +312,7 @@ describe("EncryptService", () => {
key.toEncoded(),
);
});
it("throws if disableType0Decryption is enabled and type is AesCbc256_B64", async () => {
encryptService.setDisableType0Decryption(true);
it("throws if type is AesCbc256_B64", async () => {
const key = new SymmetricCryptoKey(makeStaticByteArray(64));
const encString = new EncString(EncryptionType.AesCbc256_B64, "wrapped_symmetric_key");
await expect(encryptService.unwrapSymmetricKey(encString, key)).rejects.toThrow(