# 3.1.4.1.2 Generating a Group Key

This section specifies the processing rules for generating a group key for a given security descriptor, root key identifier, and group key identifier. The following notational conventions are used in the processing rules in this section:

SD — is used to denote the specified security descriptor, expressed in self-relative form, as specified in [MS-DTYP] section 2.4.6.

RKID — denotes the specified root key identifier, represented in the binary format specified in [MS-DTYP] section 2.3.4.2.

RK — denotes the selected

**root key**object corresponding to the root key identifier RKID. The attributes of the**root key**object are denoted in the form**RK.attributeName**, where attributeName is a particular Active Directory attribute of the**root key**object, as specified in section 3.1.1. For example,**RK.msKds-Version**indicates the version of the**root key**RK.(L0, L1, L2) — refers to the specified group key identifier.

Key(SD, RK, L0, L1, L2) — denotes the

**group seed key**for security descriptor SD,**root key**object RK, and group key identifier (L0, L1, L2).PubKey(SD, RK, L0, L1, L2) — denotes the group public key for security descriptor SD,

**root key**object RK, and group key identifier (L0, L1, L2).PrivKey(SD, RK, L0, L1, L2) — denotes the group private key for security descriptor SD,

**root key**object RK, and group key identifier (L0, L1, L2).KDF(HashAlg, K

_{I}, Label, Context, L) — denotes an execution of the [SP800-108]**KDF**in counter mode ([SP800-108] section 5.1) by using the Hash Message Authentication Code (HMAC) specified in [FIPS198-1], with HashAlg as the underlying hash algorithm (as the PRF), and with K_{I}, Label, Context, and L representing the identically named parameters specified in [SP800-108] section 5.SHA-1, SHA-256, SHA-384, and SHA-512 — denote the hash algorithms of the same names, as specified in [FIPS180-3].

|| — this symbol refers to the concatenation operator.

In addition, the following assumptions apply unless specified otherwise:

Each string constant is assumed to be a null-terminated Unicode string.

All integer constants and variables are assumed to be 32-bit integers in little-endian format.

To generate the group key, the server MUST first check the **root
key** configuration attributes of the RK object.

Check that

**RK.msKds-Version**is equal to 1. Otherwise, return an error.Check that

**RK.msKds-KDF-AlgorithmID**is equal to "SP800_108_CTR_HMAC".Protocol behavior for other values of the KDF algorithm ID is undefined.<1>

Check that

**RK.msKds-KDF-Param**is in the format specified in section 2.2.1, and that the hash algorithm name therein is equal to one of the values that follow.Protocol behavior for other values of the KDF parameter attribute is undefined.<2>

If

**RK.msKds-KDF-Param**is equal to "SHA1", set HashAlg to SHA-1.If

**RK.msKds-KDF-Param**is equal to "SHA256", set HashAlg to SHA-256.If

**RK.msKds-KDF-Param**is equal to "SHA384", set HashAlg to SHA-384.If

**RK.msKds-KDF-Param**is equal to "SHA512", set HashAlg to SHA-512.

To derive an

**L0 seed key**with a group key identifier (L0, -1, -1), the server MUST perform the following computation:Key(SD, RK, L0, -1, -1) = KDF(HashAlg,

**RK.msKds-RootKeyData**, "KDS service", RKID || L0 || 0xffffffff || 0xffffffff, 512)To derive an

**L1 seed key**with a group key identifier (L0, 31, -1), the server MUST proceed as follows:Key(SD, RK, L0, 31, -1) = KDF(HashAlg, Key(SD, RK, L0, -1, -1), "KDS service", RKID || L0 || 31 || 0xffffffff || SD, 512)

To derive an

**L1 seed key**with group key identifier (L0, n, -1), where n is an integer between 0 and 30 inclusive, the server MUST proceed as follows:Key(SD, RK, L0, n, -1) = KDF(HashAlg, Key(SD, RK, L0, n+1, -1), "KDS service", RKID || L0 || n || 0xffffffff, 512)

To derive an

**L2 seed key**with a group key identifier (L0, L1, n), where n is an integer between 0 and 31 inclusive, the server MUST proceed as follows:Key(SD, RK, L0, L1, n) = KDF(HashAlg, Key(SD, RK, L0, L1, n+1), "KDS service", RKID || L0 || L1|| n, 512); where Key(SD, RK, L0, L1, 32) = Key(SD, RK, L0, L1, -1)

To derive a **group public key** with a group key
identifier (L0, L1, L2), the server MUST proceed as follows:

First, the server MUST validate the

**root key**configuration attributes related to public keys:If

**RK.msKds-SecretAgreement-AlgorithmID**is equal to "DH",**RK.msKds-SecretAgreement-Param**MUST be in the format specified in section 2.2.2, and the**Key length**field of**RK.msKds-SecretAgreement-Param**MUST be equal to**RK.msKds-PublicKey-Length**.If

**RK.msKds-SecretAgreement-AlgorithmID**is equal to "ECDH_P256", "ECDH_P384" or "ECDH_P521", the**RK.msKds-SecretAgreement-Param**MUST be NULL.Protocol behavior for other values of the secret agreement algorithm name and parameter attributes is undefined.<3>

Having validated the

**root key**configuration, the server MUST then compute the group private key in the following manner:PrivKey(SD, RK, L0, L1, L2) = KDF(HashAlg, Key(SD, RK, L0, L1, L2), "KDS service",

**RK.msKds-SecretAgreement-AlgorithmID**,**RK.msKds-PrivateKey-Length**)**Note**If**RK.msKds-PrivateKey-Length**is not a multiple of 8, it needs to be rounded up to the next multiple of 8.Lastly, the server MUST compute the

**group public key**PubKey(SD, RK, L0, L1, L2) as follows:If

**RK.msKds-SecretAgreement-AlgorithmID**is equal to "DH", the server MUST compute PubKey(SD, RK, L0, L1, L2) by using the method specified in [SP800-56A] section 5.6.1.1, with the group parameters specified in**RK.msKds-SecretAgreement-Param**, and with PrivKey(SD, RK, L0, L1, L2) as the private key.If

**RK.msKds-SecretAgreement-AlgorithmID**is equal to "ECDH_P256", "ECDH_P384", or "ECDH_P521", the server MUST compute PubKey(SD, RK, L0, L1, L2) by using the method specified in [SP800-56A] section 5.6.1.2, with PrivKey(SD, RK, L0, L1, L2) as the private key d, and by using the domain parameters from [FIPS186] Appendix D.1.2.3, D.1.2.4, or D.1.2.5, respectively.