3.2.4.1 Performing Client-Side Wrapping of Secrets
When requested by a higher layer to perform client-side wrapping of a client secret against a given Active Directory domain, a BackupKey Remote Protocol client that supports the ClientWrap subprotocol MUST proceed as follows.
If the client does not possess a cached copy of a ClientWrap public key of the specified domain, the client MUST locate a BackupKey server for that domain by using the DC Locator functionality as specified in [MS-ADTS] section 6.3.6 to locate a writable domain controller in that domain. It must then send a BackuprKey message to this server with the pguidActionAgent parameter set to BACKUPKEY_RETRIEVE_BACKUP_KEY_GUID. The pDataIn parameter SHOULD be set to NULL, and the cbDataIn parameter SHOULD be set to zero.
If the BACKUPKEY_RETRIEVE_BACKUP_KEY_GUID request fails, the client MAY attempt to perform server-side wrapping by sending a BACKUPKEY_BACKUP_GUID instead.<19>
If the BACKUPKEY_RETRIEVE_BACKUP_KEY_GUID request is successful, the client MUST validate that the data returned from the server is formatted as specified in section 2.2.1. Specifically, it MUST verify that it is able to parse out the fields listed in section 2.2.1 from the certificate. If this validation fails, the client MUST discard the received data and return an error to the caller. For details on the X.509 certificate format, see [X509] section 2 and [RFC5280]. DER encoding is specified in [X690].
Having obtained the server's ClientWrap public key, the client MUST construct a wrapped secret as specified in section 2.2.2 by using the following procedure, and store the secret as desired.
Select whether to use the version 2 wrapping format or the version 3 wrapping format (specified as dwVersion in section 2.2.2). Clients MUST use version 2 unless explicitly configured to use version 3.<20> If version 2 is chosen and the length of the RSA modulus of the server's ClientWrap public key does not exceed the length of the client secret by at least 51 bytes, stop processing and return an error to the caller. If version 3 is chosen and the length of the RSA modulus of the server's ClientWrap public key does not exceed the length of the client secret by at least 75 bytes, stop processing and return an error to the caller.
Retrieve the SID of the calling user.
Using a cryptographically strong random number generator, generate a nonce for use in this wrapping operation. The nonce MUST be at least 32 bytes long.
Construct a version 2 or version 3 AccessCheck structure (specified in section 2.2.2.3 and section 2.2.2.4 respectively) based on the choice of wrapping format in step 1. Choose the length of the Pad field in the AccessCheck structure such that the length of the AccessCheck structure is an integral multiple of 8 bytes. Place the result of step 2 in the SID field, and populate the cbNonce and Nonce fields based on the results of step 3. Fill the Pad field with random data, and then compute and populate the Hash field.
Depending on the choice of wrapping format in step 1, generate an encryption key (denoted EncKey) and initialization vector (denoted EncIV) as follows:
If the version 2 wrapping format was chosen, generate a 3DES [SP800-67] key for EncKey and a cryptographically random 8-byte value for EncIV.
If the version 3 wrapping format was chosen, generate a 256-bit AES [FIPS197] key for EncKey and a cryptographically random 16-byte value for EncIV.
Based on the choice of wrapping format in step 1, encrypt the AccessCheck structure constructed in step 4 as follows:
If the version 2 wrapping format was chosen, encrypt the AccessCheck structure using the 3DES algorithm as specified in [SP800-67], with EncKey as the key and EncIV as the initialization vector.
If the version 3 wrapping format was chosen, encrypt the AccessCheck structure using the AES algorithm as specified in [FIPS197], with EncKey as the key and EncIV as the initialization vector.
Construct a version 2 or version 3 EncryptedSecret structure (specified in section 2.2.2.1 and section 2.2.2.2 respectively) based on the choice of wrapping format in step 1. Copy the client secret to Secret, and copy its length to cbSecret. Concatenate EncKey and EncIV (generated in step 5) and place the result in the PayloadKey field.
Encrypt the EncryptedSecret structure created in step 7, using the server's ClientWrap public key and using the RSA algorithm PKCS1 v1.5 padding as specified in [RFC8017], and then reverse the byte order of the result.
Construct the client-side wrapped secret as specified in section 2.2.2. Populate the dwVersion field based on the result of step 1, the cbEncryptedSecret and EncryptedSecret fields based on the result of step 8, and the cbAccessCheck and AccessCheck fields based on the result of step 7.
Retrieve the GUID of the server public key from the SubjectUniqueID field of the server's ClientWrap public key certificate, as specified in section 2.2.1, and place it in the guidKey field of the wrapped secret constructed in step 10.