From f7ff4da41a9be1082375f38b78807c25bb04d0b3 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Wed, 1 Jan 2025 15:09:16 +0100 Subject: [PATCH] Disable legacy ciphers --- .../migrate-legacy-encryption.component.ts | 5 ++- .../platform/abstractions/encrypt.service.ts | 1 + .../encrypt.service.implementation.ts | 39 +++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/apps/web/src/app/key-management/migrate-encryption/migrate-legacy-encryption.component.ts b/apps/web/src/app/key-management/migrate-encryption/migrate-legacy-encryption.component.ts index bb5a1c511c6..1bde2618521 100644 --- a/apps/web/src/app/key-management/migrate-encryption/migrate-legacy-encryption.component.ts +++ b/apps/web/src/app/key-management/migrate-encryption/migrate-legacy-encryption.component.ts @@ -5,6 +5,7 @@ import { FormControl, FormGroup, Validators } from "@angular/forms"; import { firstValueFrom } from "rxjs"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; @@ -40,6 +41,7 @@ export class MigrateFromLegacyEncryptionComponent { private toastService: ToastService, private dialogService: DialogService, private folderApiService: FolderApiServiceAbstraction, + private encryptService: EncryptService, ) {} submit = async () => { @@ -60,9 +62,10 @@ export class MigrateFromLegacyEncryptionComponent { const masterPassword = this.formGroup.value.masterPassword; try { + this.encryptService.setLegacyCiphersEnabled(true); await this.syncService.fullSync(false, true); - await this.keyRotationService.rotateUserKeyAndEncryptedData(masterPassword, activeUser); + this.encryptService.setLegacyCiphersEnabled(false); this.toastService.showToast({ variant: "success", diff --git a/libs/common/src/platform/abstractions/encrypt.service.ts b/libs/common/src/platform/abstractions/encrypt.service.ts index 5b28b98803b..461e8c16e8b 100644 --- a/libs/common/src/platform/abstractions/encrypt.service.ts +++ b/libs/common/src/platform/abstractions/encrypt.service.ts @@ -35,4 +35,5 @@ export abstract class EncryptService { value: string | Uint8Array, algorithm: "sha1" | "sha256" | "sha512", ): Promise; + abstract setLegacyCiphersEnabled(enabled: boolean): void; } diff --git a/libs/common/src/platform/services/cryptography/encrypt.service.implementation.ts b/libs/common/src/platform/services/cryptography/encrypt.service.implementation.ts index 0a85b34eba8..6525ab63e00 100644 --- a/libs/common/src/platform/services/cryptography/encrypt.service.implementation.ts +++ b/libs/common/src/platform/services/cryptography/encrypt.service.implementation.ts @@ -14,6 +14,8 @@ import { EncryptedObject } from "../../models/domain/encrypted-object"; import { SymmetricCryptoKey } from "../../models/domain/symmetric-crypto-key"; export class EncryptServiceImplementation implements EncryptService { + private legacyCiphersEnabled: boolean = false; + constructor( protected cryptoFunctionService: CryptoFunctionService, protected logService: LogService, @@ -29,6 +31,14 @@ export class EncryptServiceImplementation implements EncryptService { return Promise.resolve(null); } + if ( + !this.legacyCiphersEnabled && + (key.encType === EncryptionType.AesCbc128_HmacSha256_B64 || + key.encType === EncryptionType.AesCbc256_B64) + ) { + throw new Error("Legacy ciphers are disabled."); + } + let plainBuf: Uint8Array; if (typeof plainValue === "string") { plainBuf = Utils.fromUtf8ToArray(plainValue); @@ -48,6 +58,14 @@ export class EncryptServiceImplementation implements EncryptService { throw new Error("No encryption key provided."); } + if ( + !this.legacyCiphersEnabled && + (key.encType === EncryptionType.AesCbc128_HmacSha256_B64 || + key.encType === EncryptionType.AesCbc256_B64) + ) { + throw new Error("Legacy ciphers are disabled."); + } + const encValue = await this.aesEncrypt(plainValue, key); let macLen = 0; if (encValue.mac != null) { @@ -76,6 +94,14 @@ export class EncryptServiceImplementation implements EncryptService { key = this.resolveLegacyKey(key, encString); + if ( + (!this.legacyCiphersEnabled || encString.mac == null) && + (key.encType === EncryptionType.AesCbc128_HmacSha256_B64 || + key.encType === EncryptionType.AesCbc256_B64) + ) { + throw new Error("Legacy ciphers are disabled."); + } + // DO NOT REMOVE OR MOVE. This prevents downgrade to mac-less CBC, which would compromise integrity and confidentiality. if (key.macKey != null && encString?.mac == null) { this.logService.error( @@ -139,6 +165,14 @@ export class EncryptServiceImplementation implements EncryptService { key = this.resolveLegacyKey(key, encThing); + if ( + (!this.legacyCiphersEnabled || encThing.macBytes == null) && + (key.encType === EncryptionType.AesCbc128_HmacSha256_B64 || + key.encType === EncryptionType.AesCbc256_B64) + ) { + throw new Error("Legacy ciphers are disabled."); + } + // DO NOT REMOVE OR MOVE. This prevents downgrade to mac-less CBC, which would compromise integrity and confidentiality. if (key.macKey != null && encThing.macBytes == null) { this.logService.error( @@ -297,4 +331,9 @@ export class EncryptServiceImplementation implements EncryptService { return key; } + + setLegacyCiphersEnabled(enabled: boolean): void { + this.logService.info("[Encrypt service] Legacy ciphers enabled: " + enabled); + this.legacyCiphersEnabled = enabled; + } }