mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-22 16:29:09 +01:00
Add logging for decryption failures (#11683)
* Add logging to decryption routines * Fix case of uknown encryption type * Remove enum to string mapping
This commit is contained in:
parent
9b471e6633
commit
b3b311e164
@ -8,6 +8,14 @@ export enum EncryptionType {
|
|||||||
Rsa2048_OaepSha1_HmacSha256_B64 = 6,
|
Rsa2048_OaepSha1_HmacSha256_B64 = 6,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function encryptionTypeToString(encryptionType: EncryptionType): string {
|
||||||
|
if (encryptionType in EncryptionType) {
|
||||||
|
return EncryptionType[encryptionType];
|
||||||
|
} else {
|
||||||
|
return "Unknown encryption type " + encryptionType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** The expected number of parts to a serialized EncString of the given encryption type.
|
/** The expected number of parts to a serialized EncString of the given encryption type.
|
||||||
* For example, an EncString of type AesCbc256_B64 will have 2 parts, and an EncString of type
|
* For example, an EncString of type AesCbc256_B64 will have 2 parts, and an EncString of type
|
||||||
* AesCbc128_HmacSha256_B64 will have 3 parts.
|
* AesCbc128_HmacSha256_B64 will have 3 parts.
|
||||||
|
@ -2,7 +2,7 @@ import { Utils } from "../../../platform/misc/utils";
|
|||||||
import { CryptoFunctionService } from "../../abstractions/crypto-function.service";
|
import { CryptoFunctionService } from "../../abstractions/crypto-function.service";
|
||||||
import { EncryptService } from "../../abstractions/encrypt.service";
|
import { EncryptService } from "../../abstractions/encrypt.service";
|
||||||
import { LogService } from "../../abstractions/log.service";
|
import { LogService } from "../../abstractions/log.service";
|
||||||
import { EncryptionType } from "../../enums";
|
import { EncryptionType, encryptionTypeToString as encryptionTypeName } from "../../enums";
|
||||||
import { Decryptable } from "../../interfaces/decryptable.interface";
|
import { Decryptable } from "../../interfaces/decryptable.interface";
|
||||||
import { Encrypted } from "../../interfaces/encrypted";
|
import { Encrypted } from "../../interfaces/encrypted";
|
||||||
import { InitializerMetadata } from "../../interfaces/initializer-metadata.interface";
|
import { InitializerMetadata } from "../../interfaces/initializer-metadata.interface";
|
||||||
@ -70,13 +70,24 @@ export class EncryptServiceImplementation implements EncryptService {
|
|||||||
|
|
||||||
key = this.resolveLegacyKey(key, encString);
|
key = this.resolveLegacyKey(key, encString);
|
||||||
|
|
||||||
|
// 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) {
|
if (key.macKey != null && encString?.mac == null) {
|
||||||
this.logService.error("MAC required but not provided.");
|
this.logService.error(
|
||||||
|
"[Encrypt service] Key has mac key but payload is missing mac bytes. Key type " +
|
||||||
|
encryptionTypeName(key.encType) +
|
||||||
|
" Payload type " +
|
||||||
|
encryptionTypeName(encString.encryptionType),
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key.encType !== encString.encryptionType) {
|
if (key.encType !== encString.encryptionType) {
|
||||||
this.logService.error("Key encryption type does not match payload encryption type.");
|
this.logService.error(
|
||||||
|
"[Encrypt service] Key encryption type does not match payload encryption type. Key type " +
|
||||||
|
encryptionTypeName(key.encType) +
|
||||||
|
" Payload type " +
|
||||||
|
encryptionTypeName(encString.encryptionType),
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +105,12 @@ export class EncryptServiceImplementation implements EncryptService {
|
|||||||
);
|
);
|
||||||
const macsEqual = await this.cryptoFunctionService.compareFast(fastParams.mac, computedMac);
|
const macsEqual = await this.cryptoFunctionService.compareFast(fastParams.mac, computedMac);
|
||||||
if (!macsEqual) {
|
if (!macsEqual) {
|
||||||
this.logMacFailed("MAC comparison failed. Key or payload has changed.");
|
this.logMacFailed(
|
||||||
|
"[Encrypt service] MAC comparison failed. Key or payload has changed. Key type " +
|
||||||
|
encryptionTypeName(key.encType) +
|
||||||
|
" Payload type " +
|
||||||
|
encryptionTypeName(encString.encryptionType),
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,13 +129,24 @@ export class EncryptServiceImplementation implements EncryptService {
|
|||||||
|
|
||||||
key = this.resolveLegacyKey(key, encThing);
|
key = this.resolveLegacyKey(key, encThing);
|
||||||
|
|
||||||
|
// 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) {
|
if (key.macKey != null && encThing.macBytes == null) {
|
||||||
this.logService.error("MAC required but not provided.");
|
this.logService.error(
|
||||||
|
"[Encrypt service] Key has mac key but payload is missing mac bytes. Key type " +
|
||||||
|
encryptionTypeName(key.encType) +
|
||||||
|
" Payload type " +
|
||||||
|
encryptionTypeName(encThing.encryptionType),
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key.encType !== encThing.encryptionType) {
|
if (key.encType !== encThing.encryptionType) {
|
||||||
this.logService.error("Key encryption type does not match payload encryption type.");
|
this.logService.error(
|
||||||
|
"[Encrypt service] Key encryption type does not match payload encryption type. Key type " +
|
||||||
|
encryptionTypeName(key.encType) +
|
||||||
|
" Payload type " +
|
||||||
|
encryptionTypeName(encThing.encryptionType),
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,13 +156,25 @@ export class EncryptServiceImplementation implements EncryptService {
|
|||||||
macData.set(new Uint8Array(encThing.dataBytes), encThing.ivBytes.byteLength);
|
macData.set(new Uint8Array(encThing.dataBytes), encThing.ivBytes.byteLength);
|
||||||
const computedMac = await this.cryptoFunctionService.hmac(macData, key.macKey, "sha256");
|
const computedMac = await this.cryptoFunctionService.hmac(macData, key.macKey, "sha256");
|
||||||
if (computedMac === null) {
|
if (computedMac === null) {
|
||||||
this.logMacFailed("Failed to compute MAC.");
|
this.logMacFailed(
|
||||||
|
"[Encrypt service] Failed to compute MAC." +
|
||||||
|
" Key type " +
|
||||||
|
encryptionTypeName(key.encType) +
|
||||||
|
" Payload type " +
|
||||||
|
encryptionTypeName(encThing.encryptionType),
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const macsMatch = await this.cryptoFunctionService.compare(encThing.macBytes, computedMac);
|
const macsMatch = await this.cryptoFunctionService.compare(encThing.macBytes, computedMac);
|
||||||
if (!macsMatch) {
|
if (!macsMatch) {
|
||||||
this.logMacFailed("MAC comparison failed. Key or payload has changed.");
|
this.logMacFailed(
|
||||||
|
"[Encrypt service] MAC comparison failed. Key or payload has changed." +
|
||||||
|
" Key type " +
|
||||||
|
encryptionTypeName(key.encType) +
|
||||||
|
" Payload type " +
|
||||||
|
encryptionTypeName(encThing.encryptionType),
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,7 +203,7 @@ export class EncryptServiceImplementation implements EncryptService {
|
|||||||
|
|
||||||
async rsaDecrypt(data: EncString, privateKey: Uint8Array): Promise<Uint8Array> {
|
async rsaDecrypt(data: EncString, privateKey: Uint8Array): Promise<Uint8Array> {
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
throw new Error("No data provided for decryption.");
|
throw new Error("[Encrypt service] rsaDecrypt: No data provided for decryption.");
|
||||||
}
|
}
|
||||||
|
|
||||||
let algorithm: "sha1" | "sha256";
|
let algorithm: "sha1" | "sha256";
|
||||||
@ -182,7 +221,7 @@ export class EncryptServiceImplementation implements EncryptService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (privateKey == null) {
|
if (privateKey == null) {
|
||||||
throw new Error("No private key provided for decryption.");
|
throw new Error("[Encrypt service] rsaDecrypt: No private key provided for decryption.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.cryptoFunctionService.rsaDecrypt(data.dataBytes, privateKey, algorithm);
|
return this.cryptoFunctionService.rsaDecrypt(data.dataBytes, privateKey, algorithm);
|
||||||
|
Loading…
Reference in New Issue
Block a user