3.2.4.1 Client Side Processing

The Group Key Distribution Protocol client receives requests from a higher layer. The caller requests the retrieval of a key for a given security descriptor, while optionally specifying a root key identifier and group key identifier. The caller also specifies the name of the Active Directory domain from which to retrieve keys and provides valid user credentials for authenticating in a specific domain.

Upon receiving such a request, the client SHOULD attempt to locate a matching key in the cache, as follows:

  1. If the caller specified a group key identifier but did not specify a root key identifier, then do not attempt to locate a key in the cache.

  2. If the caller specified a root key identifier, the client must first check if a group key identifier was also specified. If the caller did not specify a group key identifier, the client converts the current time to the group key identifier, as specified in section 3.1.4.1, and uses that as the requested group key identifier. The client then attempts to find a group seed key in the cache that has the same domain and security descriptor, and whose group key identifier is the same as the requested group key identifier, or whose group key identifier is newer than the requested group key identifier but has the same L0 index field value. If such a key is found in the cache, the client uses it to derive the desired key, as specified in section 3.2.4.3, and returns the result to the caller.

  3. If the caller specified neither a root key identifier nor a group key identifier (for example, the group key identifier was (-1, -1, -1)), the client first converts the current time to a group key identifier, as specified in section 3.1.4.1. The client then attempts to find a group key in the cache that has the same domain and security descriptor, which is marked as current, and whose group key identifier is no older than the group key identifier just computed. If such a key is found in the cache, the client uses it to compute the desired key, as specified in section 3.2.4.3, and returns the result to the caller.

If no key is found in the cache, the client MUST attempt to connect to a server and retrieve a key as specified in section 3.2.4.2.

If the client fails to retrieve a key from the server, and if the caller had not specified a root key identifier, the client SHOULD attempt to find a cached group key with the same domain and security descriptor that is marked as current and whose group key identifier is no more than 32 L2 periods older than the current time. If such a key is found, the client SHOULD return it to the caller.

In all other cases, if the client fails to retrieve a key from the server, the client MUST return an error to the caller.

If the client successfully retrieves a key from the server, it will have received a group key in the format specified in section 2.2.4. The client MUST parse this format as follows:

  1. If bit 31 of the dwFlags field of the returned Group Key Envelope is set to 1, the value in the L2 key field is a public key with group key identifier (L0 field, L1 field, L2 field).

  2. If bit 31 of the dwFlags field of the returned Group Key Envelope is set to 0 and the L2 Key field is present, the value in the L2 key field is an L2 seed key with group key identifier (L0 field, L1 field, L2 field).

  3. If bit 31 of the dwFlags field of the returned Group Key Envelope is set to 0 and the L1 Key field is present, then:

    • If the value in the L2 index field is 31, the value in the L1 Key field is an L1 seed key with group key identifier (L0 field, L1 field, -1).

    • If the value in the L2 index field is not 31, the value in the L1 Key field is an L1 seed key with group key identifier (L0 field, L1 field - 1, -1).

The client SHOULD then update its group key cache as follows.

  1. If the server returned a public key, then:

    • Check the cache for a group seed key for the same domain, the same security descriptor, the same root key identifier, and the same or newer group key identifier. If such a key is found, do not update the cache.

    • Check the cache for a group public key with the same domain, the same security descriptor, and an older group key identifier or different root key identifier. If such a key exists, replace it with the retrieved group public key.

    • If neither of the preceding cases apply, add the retrieved group public key to the cache.

  2. If the server returned a seed key, then:

    • Check the cache for a group public key with the same domain, the same security descriptor, the same root key identifier, and same or older group key identifier. If such a key exists, remove it from the cache and add the retrieved seed key to the cache.

    • Check the cache for a seed key with the same domain, the same security descriptor, and the same root key identifier. If such a key is found and it has an older group key identifier than the retrieved key, replace it with the retrieved key. If such a key is found but it has a newer group key identifier than the retrieved key, do not update the cache.

    • If neither of the preceding cases apply, add the retrieved seed key to the cache.

  3. If the caller for this request specified neither a root key identifier nor a group key identifier, then mark the above key with the current attribute.

Lastly, the client MUST compute the requested key, as specified in section 3.2.4.3, and return the result to the caller.