Skip to content

Commit

Permalink
Handle userGroupKeyRotation as admin
Browse files Browse the repository at this point in the history
When performing a user group key rotation after another admin already
performed the admin group key rotation, each admin must validate the
authenticity of the newly received admin group key and then encrypt it
with their new user group key.

tutadb#1909
  • Loading branch information
bedhub authored and vitoreiji committed Dec 17, 2024
1 parent a941ea5 commit 6725f5d
Show file tree
Hide file tree
Showing 13 changed files with 501 additions and 291 deletions.
20 changes: 20 additions & 0 deletions packages/tutanota-crypto/lib/encryption/KeyEncryption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ import type { PQKeyPairs } from "./PQKeyPairs.js"

export type EncryptedKeyPairs = EncryptedPqKeyPairs | EncryptedRsaKeyPairs | EncryptedRsaEccKeyPairs

export type AbstractEncryptedKeyPair = {
pubEccKey: null | Uint8Array
pubKyberKey: null | Uint8Array
pubRsaKey: null | Uint8Array
symEncPrivEccKey: null | Uint8Array
symEncPrivKyberKey: null | Uint8Array
symEncPrivRsaKey: null | Uint8Array
}

export type EncryptedPqKeyPairs = {
pubEccKey: Uint8Array
pubKyberKey: Uint8Array
Expand Down Expand Up @@ -38,6 +47,17 @@ export type EncryptedRsaEccKeyPairs = {
symEncPrivRsaKey: Uint8Array
}

export function isEncryptedPqKeyPairs(keyPair: AbstractEncryptedKeyPair): keyPair is EncryptedPqKeyPairs {
return (
keyPair.pubEccKey != null &&
keyPair.pubKyberKey != null &&
keyPair.symEncPrivEccKey != null &&
keyPair.symEncPrivKyberKey != null &&
keyPair.pubRsaKey == null &&
keyPair.symEncPrivRsaKey == null
)
}

export function encryptKey(encryptionKey: AesKey, keyToBeEncrypted: AesKey): Uint8Array {
const keyLength = getKeyLengthBytes(encryptionKey)
if (keyLength === KEY_LENGTH_BYTES_AES_128) {
Expand Down
2 changes: 2 additions & 0 deletions packages/tutanota-crypto/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,12 @@ export {
} from "./hashes/Argon2id/Argon2id.js"
export { KeyLength, EntropySource, HkdfKeyDerivationDomains } from "./misc/Constants.js"
export {
AbstractEncryptedKeyPair,
EncryptedKeyPairs,
EncryptedPqKeyPairs,
EncryptedRsaKeyPairs,
EncryptedRsaEccKeyPairs,
isEncryptedPqKeyPairs,
encryptKey,
decryptKey,
encryptRsaKey,
Expand Down
16 changes: 13 additions & 3 deletions schemas/sys.json
Original file line number Diff line number Diff line change
Expand Up @@ -495,9 +495,9 @@
"info": "RenameAttribute KeyRotation: adminGroupKeyAuthenticationData -> userEncAdminPubKeyHash."
},
{
"name": "AddValue",
"name": "AddAssociation",
"sourceType": "KeyRotation",
"info": "AddValue KeyRotation/distEncAdminGroupSymKey/2505."
"info": "AddAssociation KeyRotation/distEncAdminGroupSymKey/AGGREGATION/2505."
},
{
"name": "AddAssociation",
Expand All @@ -517,7 +517,17 @@
{
"name": "AddValue",
"sourceType": "UserGroupKeyRotationData",
"info": "AddValue UserGroupKeyRotationData/userGroupEncAdminGroupKey/2537."
"info": "AddValue UserGroupKeyRotationData/userGroupEncAdminGroupKey/2529."
},
{
"name": "AddValue",
"sourceType": "PubEncKeyData",
"info": "AddValue PubEncKeyData/senderIdentifier/2530."
},
{
"name": "AddValue",
"sourceType": "PubEncKeyData",
"info": "AddValue PubEncKeyData/senderIdentifierType/2531."
}
]
}
Expand Down
1 change: 1 addition & 0 deletions src/common/api/common/TutanotaConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1230,6 +1230,7 @@ export const DEFAULT_ERROR = "defaultError"
export enum PublicKeyIdentifierType {
MAIL_ADDRESS = "0",
GROUP_ID = "1",
KEY_ROTATION_ID = "2",
}

export function asPublicKeyIdentifier(maybe: NumberString): PublicKeyIdentifierType {
Expand Down
133 changes: 36 additions & 97 deletions src/common/api/entities/sys/TypeModels.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,18 +238,19 @@ export const typeModels = {
"type": "CustomId",
"cardinality": "One",
"encrypted": false
},
}
},
"associations": {
"distEncAdminGroupKey": {
"final": false,
"name": "distEncAdminGroupKey",
"id": 2512,
"since": 116,
"type": "Bytes",
"type": "AGGREGATION",
"cardinality": "One",
"encrypted": false
}
},
"associations": {
"refType": "PubEncKeyData",
"dependency": null
},
"userEncAdminSymKeyHash": {
"final": false,
"name": "userEncAdminSymKeyHash",
Expand Down Expand Up @@ -426,77 +427,6 @@ export const typeModels = {
"app": "sys",
"version": "116"
},
"AdminMembershipUpdateData": {
"name": "AdminMembershipUpdateData",
"since": 116,
"type": "AGGREGATED_TYPE",
"id": 2529,
"rootId": "A3N5cwAJ4Q",
"versioned": false,
"encrypted": false,
"values": {
"_id": {
"final": true,
"name": "_id",
"id": 2530,
"since": 116,
"type": "CustomId",
"cardinality": "One",
"encrypted": false
},
"adminGroupKeyVersion": {
"final": false,
"name": "adminGroupKeyVersion",
"id": 2533,
"since": 116,
"type": "Number",
"cardinality": "One",
"encrypted": false
},
"userEncAdminGroupKey": {
"final": false,
"name": "userEncAdminGroupKey",
"id": 2531,
"since": 116,
"type": "Bytes",
"cardinality": "One",
"encrypted": false
},
"userGroupKeyVersion": {
"final": false,
"name": "userGroupKeyVersion",
"id": 2532,
"since": 116,
"type": "Number",
"cardinality": "One",
"encrypted": false
}
},
"associations": {
"adminGroup": {
"final": false,
"name": "adminGroup",
"id": 2535,
"since": 116,
"type": "ELEMENT_ASSOCIATION",
"cardinality": "One",
"refType": "Group",
"dependency": null
},
"userGroup": {
"final": false,
"name": "userGroup",
"id": 2534,
"since": 116,
"type": "ELEMENT_ASSOCIATION",
"cardinality": "One",
"refType": "Group",
"dependency": null
}
},
"app": "sys",
"version": "116"
},
"AdministratedGroup": {
"name": "AdministratedGroup",
"since": 27,
Expand Down Expand Up @@ -7851,15 +7781,6 @@ export const typeModels = {
"cardinality": "One",
"encrypted": false
},
"distEncAdminGroupSymKey": {
"final": false,
"name": "distEncAdminGroupSymKey",
"id": 2505,
"since": 116,
"type": "Bytes",
"cardinality": "ZeroOrOne",
"encrypted": false
},
"groupKeyRotationType": {
"final": true,
"name": "groupKeyRotationType",
Expand Down Expand Up @@ -7900,6 +7821,16 @@ export const typeModels = {
"refType": "EncryptedKeyHash",
"dependency": null
},
"distEncAdminGroupSymKey": {
"final": false,
"name": "distEncAdminGroupSymKey",
"id": 2505,
"since": 116,
"type": "AGGREGATION",
"cardinality": "ZeroOrOne",
"refType": "PubEncKeyData",
"dependency": null
},
"userEncAdminPubKeyHash": {
"final": false,
"name": "userEncAdminPubKeyHash",
Expand Down Expand Up @@ -10295,6 +10226,24 @@ export const typeModels = {
"cardinality": "One",
"encrypted": false
},
"senderIdentifier": {
"final": true,
"name": "senderIdentifier",
"id": 2530,
"since": 116,
"type": "String",
"cardinality": "ZeroOrOne",
"encrypted": false
},
"senderIdentifierType": {
"final": true,
"name": "senderIdentifierType",
"id": 2531,
"since": 116,
"type": "Number",
"cardinality": "ZeroOrOne",
"encrypted": false
},
"senderKeyVersion": {
"final": true,
"name": "senderKeyVersion",
Expand Down Expand Up @@ -14193,7 +14142,7 @@ export const typeModels = {
"userGroupEncAdminGroupKey": {
"final": false,
"name": "userGroupEncAdminGroupKey",
"id": 2537,
"id": 2529,
"since": 116,
"type": "Bytes",
"cardinality": "ZeroOrOne",
Expand Down Expand Up @@ -14283,16 +14232,6 @@ export const typeModels = {
}
},
"associations": {
"adminMembershipUpdateData": {
"final": false,
"name": "adminMembershipUpdateData",
"id": 2536,
"since": 116,
"type": "AGGREGATION",
"cardinality": "ZeroOrOne",
"refType": "AdminMembershipUpdateData",
"dependency": null
},
"userGroupKeyData": {
"final": false,
"name": "userGroupKeyData",
Expand Down
26 changes: 5 additions & 21 deletions src/common/api/entities/sys/TypeRefs.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { create, StrippedEntity } from "../../common/utils/EntityUtils.js"
import { create, Stripped, StrippedEntity } from "../../common/utils/EntityUtils.js"
import { TypeRef } from "@tutao/tutanota-utils"
import { typeModels } from "./TypeModels.js"

Expand Down Expand Up @@ -47,8 +47,8 @@ export type AdminGroupKeyDistributionElement = {
_type: TypeRef<AdminGroupKeyDistributionElement>;

_id: Id;
distEncAdminGroupKey: Uint8Array;

distEncAdminGroupKey: PubEncKeyData;
userEncAdminSymKeyHash: EncryptedKeyHash;
userGroupId: Id;
}
Expand Down Expand Up @@ -96,23 +96,6 @@ export type AdminGroupKeyRotationPutIn = {
adminDistKeyPair: KeyPair;
adminEncDistKeyHash: EncryptedKeyHash;
}
export const AdminMembershipUpdateDataTypeRef: TypeRef<AdminMembershipUpdateData> = new TypeRef("sys", "AdminMembershipUpdateData")

export function createAdminMembershipUpdateData(values: StrippedEntity<AdminMembershipUpdateData>): AdminMembershipUpdateData {
return Object.assign(create(typeModels.AdminMembershipUpdateData, AdminMembershipUpdateDataTypeRef), values)
}

export type AdminMembershipUpdateData = {
_type: TypeRef<AdminMembershipUpdateData>;

_id: Id;
adminGroupKeyVersion: NumberString;
userEncAdminGroupKey: Uint8Array;
userGroupKeyVersion: NumberString;

adminGroup: Id;
userGroup: Id;
}
export const AdministratedGroupTypeRef: TypeRef<AdministratedGroup> = new TypeRef("sys", "AdministratedGroup")

export function createAdministratedGroup(values: StrippedEntity<AdministratedGroup>): AdministratedGroup {
Expand Down Expand Up @@ -1879,12 +1862,12 @@ export type KeyRotation = {
_id: IdTuple;
_ownerGroup: null | Id;
_permissions: Id;
distEncAdminGroupSymKey: null | Uint8Array;
groupKeyRotationType: NumberString;
targetKeyVersion: NumberString;

adminDistKeyPair: null | KeyPair;
adminEncDistKeyHash: null | EncryptedKeyHash;
distEncAdminGroupSymKey: null | PubEncKeyData;
userEncAdminPubKeyHash: null | EncryptedKeyHash;
userEncAdminSymKeyHash: null | EncryptedKeyHash;
}
Expand Down Expand Up @@ -2512,6 +2495,8 @@ export type PubEncKeyData = {
recipientIdentifier: string;
recipientIdentifierType: NumberString;
recipientKeyVersion: NumberString;
senderIdentifier: null | string;
senderIdentifierType: null | NumberString;
senderKeyVersion: null | NumberString;
}
export const PublicKeyGetInTypeRef: TypeRef<PublicKeyGetIn> = new TypeRef("sys", "PublicKeyGetIn")
Expand Down Expand Up @@ -3503,7 +3488,6 @@ export type UserGroupKeyRotationPostIn = {

_format: NumberString;

adminMembershipUpdateData: null | AdminMembershipUpdateData;
userGroupKeyData: UserGroupKeyRotationData;
}
export const UserGroupRootTypeRef: TypeRef<UserGroupRoot> = new TypeRef("sys", "UserGroupRoot")
Expand Down
Loading

0 comments on commit 6725f5d

Please sign in to comment.