SafeEncryptMessage() static private method

Safely invokes the native EncryptMessage function, making sure that handle ref counting is performed in a proper CER.
static private SafeEncryptMessage ( SafeContextHandle handle, int qualityOfProtection, SecureBufferAdapter bufferAdapter, int sequenceNumber ) : SecurityStatus
handle SafeContextHandle
qualityOfProtection int
bufferAdapter SecureBufferAdapter
sequenceNumber int
return SecurityStatus
        /// <summary>
        /// Encrypts the byte array using the context's session key.
        /// </summary>
        /// <remarks>
        /// The structure of the returned data is as follows:
        ///  - 2 bytes, an unsigned big-endian integer indicating the length of the trailer buffer size
        ///  - 4 bytes, an unsigned big-endian integer indicating the length of the message buffer size.
        ///  - 2 bytes, an unsigned big-endian integer indicating the length of the encryption padding buffer size.
        ///  - The trailer buffer
        ///  - The message buffer
        ///  - The padding buffer.
        /// </remarks>
        /// <param name="input">The raw message to encrypt.</param>
        /// <returns>The packed and encrypted message.</returns>
        public byte[] Encrypt(byte[] input)
        {
            // The message is encrypted in place in the buffer we provide to Win32 EncryptMessage
            SecPkgContext_Sizes sizes;

            SecureBuffer        trailerBuffer;
            SecureBuffer        dataBuffer;
            SecureBuffer        paddingBuffer;
            SecureBufferAdapter adapter;

            SecurityStatus status = SecurityStatus.InvalidHandle;

            byte[] result;

            CheckLifecycle();

            sizes = QueryBufferSizes();

            trailerBuffer = new SecureBuffer(new byte[sizes.SecurityTrailer], BufferType.Token);
            dataBuffer    = new SecureBuffer(new byte[input.Length], BufferType.Data);
            paddingBuffer = new SecureBuffer(new byte[sizes.BlockSize], BufferType.Padding);

            Array.Copy(input, dataBuffer.Buffer, input.Length);

            using (adapter = new SecureBufferAdapter(new[] { trailerBuffer, dataBuffer, paddingBuffer }))
            {
                status = ContextNativeMethods.SafeEncryptMessage(
                    this.ContextHandle,
                    WrapNoEncrypt,
                    adapter,
                    0
                    );
            }

            if (status != SecurityStatus.OK)
            {
                throw new SspiException("Failed to encrypt message", status);
            }

            int position = 0;

            // Return 1 buffer with the 3 buffers joined
            result = new byte[trailerBuffer.Length + dataBuffer.Length + paddingBuffer.Length];

            Array.Copy(trailerBuffer.Buffer, 0, result, position, trailerBuffer.Length);
            position += trailerBuffer.Length;

            Array.Copy(dataBuffer.Buffer, 0, result, position, dataBuffer.Length);
            position += dataBuffer.Length;

            Array.Copy(paddingBuffer.Buffer, 0, result, position, paddingBuffer.Length);

            return(result);
        }
Example #2
0
        /// <summary>
        /// Encrypts the byte array using the context's session key.
        /// </summary>
        /// <remarks>
        /// The structure of the returned data is as follows:
        ///  - 2 bytes, an unsigned big-endian integer indicating the length of the trailer buffer size
        ///  - 4 bytes, an unsigned big-endian integer indicating the length of the message buffer size.
        ///  - 2 bytes, an unsigned big-endian integer indicating the length of the encryption padding buffer size.
        ///  - The trailer buffer
        ///  - The message buffer
        ///  - The padding buffer.
        /// </remarks>
        /// <param name="input">The raw message to encrypt.</param>
        /// <returns>The packed and encrypted message.</returns>
        public byte[] Encrypt(byte[] input)
        {
            // The message is encrypted in place in the buffer we provide to Win32 EncryptMessage
            SecPkgContext_Sizes sizes;

            SecureBuffer        trailerBuffer;
            SecureBuffer        dataBuffer;
            SecureBuffer        paddingBuffer;
            SecureBufferAdapter adapter;

            SecurityStatus status = SecurityStatus.InvalidHandle;

            byte[] result;

            CheckLifecycle();

            sizes = QueryBufferSizes();

            trailerBuffer = new SecureBuffer(new byte[sizes.SecurityTrailer], BufferType.Token);
            dataBuffer    = new SecureBuffer(new byte[input.Length], BufferType.Data);
            paddingBuffer = new SecureBuffer(new byte[sizes.BlockSize], BufferType.Padding);

            Array.Copy(input, dataBuffer.Buffer, input.Length);

            using (adapter = new SecureBufferAdapter(new[] { trailerBuffer, dataBuffer, paddingBuffer }))
            {
                status = ContextNativeMethods.SafeEncryptMessage(
                    this.ContextHandle,
                    0,
                    adapter,
                    0
                    );
            }

            if (status != SecurityStatus.OK)
            {
                throw new SspiException("Failed to encrypt message", status);
            }

            int position = 0;

            // Enough room to fit:
            //  -- 2 bytes for the trailer buffer size
            //  -- 4 bytes for the message size
            //  -- 2 bytes for the padding size.
            //  -- The encrypted message
            result = new byte[2 + 4 + 2 + trailerBuffer.Length + dataBuffer.Length + paddingBuffer.Length];

            ByteWriter.WriteInt16_BE((short)trailerBuffer.Length, result, position);
            position += 2;

            ByteWriter.WriteInt32_BE(dataBuffer.Length, result, position);
            position += 4;

            ByteWriter.WriteInt16_BE((short)paddingBuffer.Length, result, position);
            position += 2;

            Array.Copy(trailerBuffer.Buffer, 0, result, position, trailerBuffer.Length);
            position += trailerBuffer.Length;

            Array.Copy(dataBuffer.Buffer, 0, result, position, dataBuffer.Length);
            position += dataBuffer.Length;

            Array.Copy(paddingBuffer.Buffer, 0, result, position, paddingBuffer.Length);
            position += paddingBuffer.Length;

            return(result);
        }