5.1.2 Secret Encryption and Decryption

This cipher is used to provide confidentiality of wire traffic for operations that reference this section.

The encrypt_secret routine is used to encrypt a cleartext value into ciphertext prior to transmission. The decrypt_secret routine is used to decrypt a ciphertext value into cleartext after receipt. The appropriate mode is selected based on the requirements of the interface.

The definitions of des_ecb_lm_dec and des_ecb_lm_enc are specified in section 5.1.3.

 encrypt_secret(input : LSA_UNICODE_STRING, sessionkey : byte[16], 
 output : LSA_UNICODE_STRING)
 {
     LET blocklen be 8
     LET keyindex be 0
  
     // Set version, length
     // temporary buffer.
     LET buffer be an array of blocklen bytes
     DECLEARE  Version as ULONG
     SET Version to 1
     SET buffer to input->length
     SET (buffer + 4) to Version
  
     CALL des_ecb_lm_enc(buffer, sessionkey[keyindex],
                         output->buffer)
  
     INCREMENT output->buffer by blocklen
     INCREMENT output->length by blocklen
  
     SET keyindex to AdvanceKey(keyindex)
  
     LET remaining be input->length
     WHILE remaining > blocklen
         CALL des_ecb_lm_enc(input->buffer,
             sessionkey[keyindex], output->buffer)
  
         INCREMENT input->buffer by blocklen
         INCREMENT output->buffer by blocklen
         INCREMENT output->length by blocklen
  
         SET keyindex to AdvanceKey(keyindex)
  
         DECREMENT remaining by blocklen
     ENDWHILE
  
     IF (remaining > 0) THEN
         // zero pad the last block.
         SET bytes in buffer to 0
         COPY remaining bytes from input->buffer to buffer
         
         CALL des_ecb_lm_enc(buffer, sessionkey[keyindex],
                             output->buffer)
  
         INCREMENT output->length by blocklen
     ENDIF
 }
  
  
 decrypt_secret(input : LSA_UNICODE_STRING, sessionkey : byte[16], 
 output : LSA_UNICODE_STRING)
 {
     LET keyindex be 0
     LET blocklen be 8
  
     // Check version, get clear length.
     CALL des_ecb_lm_dec(input->buffer, sessionkey[keyindex],
                         output->buffer)
  
     LET outputlength be output[0]
     LET version be output[1]
  
     IF (version ≠ 1) THEN // version check
         FAIL
     ENDIF
     
     INCREMENT input->buffer by blocklen
  
     SET keyindex to AdvanceKey(keyindex)
  
     LET remaining be outputlength
  
     WHILE remaining > blocklen
         CALL des_ecb_lm_dec(input->buffer,
                  sessionkey[keyindex], output->buffer)
         
         INCREMENT input->buffer by blocklen
         INCREMENT output->buffer by blocklen
  
         SET keyindex to AdvanceKey(keyindex)
  
         DECREMENT remaining by blocklen
     ENDWHILE
  
     IF (remaining > 0) THEN
         CALL des_ecb_lm_dec(input->buffer,
                  sessionkey[keyindex], output->buffer)
     ENDIF
  
     SET output->length to outputlength
 }
  
  
 ULONG AdvanceKey(pos : ULONG)
 {
     LET KeyBlockLen be 7;
     DECLARE overrun as ULONG
     DECLARE currpos as ULONG;
     DECLARE nextpos as ULONG;
  
     LET pos = pos + KeyBlockLen;
     LET currpos = pos;
     LET nextpos = pos + KeyBlockLen;
  
     IF (nextpos > sizeof(sessionKey)) THEN
       LET overrun = nextpos- sizeof(sessionKey);
       LET currpos = (KeyBlockLen - overrun);
     ENDIF
     RETURN currpos;
 }