ADVISOR DETAILS

RECENT BLOG POSTS

Utilizing AES New Instructions (AES-NI) in a Windows* 8 C# App

AES-NI is a new security feature available on the latest Intel® Atom™ Z3000 processors (codename Bay Trail).  AES-NI provides a set of hardware instructions onboard the processor that implement some of the intensive sub-steps of the AES algorithm.  This yields additional performance when performing AES cryptographic operations.  This blog discusses a method of adding encryption and decryption that utilizes AES-NI in a Windows 8 C# app.

To learn more about AES-NI, please see the link below.
http://www.intel.com/content/www/us/en/architecture-and-technology/advanced-encryption-standard–aes-/data-protection-aes-general-technology.html

An easy way to take advantage of AES-NI under the hood in a Windows 8 app is to use the Microsoft Cryptography API:  Next Generation (CNG) library.  The CNG library was developed in C++ and is available to use in other languages by importing the Bcrypt.dll file. 

To learn more about the CNG library and API’s, please see the link below.
http://msdn.microsoft.com/en-us/library/aa376210(v=vs.85).aspx

To use the Bcrypt.dll in your C# application, import the functions using the System.Runtime.Interop Services.  The following code below are example DllImport statements.

[DllImport("Bcrypt.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern uint BCryptOpenAlgorithmProvider(
            [In] [Out] ref IntPtr phAlgorithm,
            [In] String pszAlgId,
            [In] String pszImplementation,
            [In] int dwFlags
        );

[DllImport("Bcrypt.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern uint BCryptGetProperty(
            [In] IntPtr hObject,
            [In] String pszProperty,
            [Out] byte[] pbOutput,
            [In] int cbOutput,
            [In] [Out] ref int pcbResult,
            [In] int dwFlags);

 [DllImport("Bcrypt.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern uint BCryptGenerateSymmetricKey(
            [In]  IntPtr hAlgorithm,
            [In] [Out] ref IntPtr phKey,
            [Out] byte[] pbKeyObject,
            [In] int cbKeyObject,
            [In] byte[] pbSecret,
            [In] int cbSecret,
            [In] int dwFlags
        );

[DllImport("Bcrypt.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern uint BCryptEncrypt(
            [In][Out] IntPtr hKey,
            [In] byte[] pbInput,
            [In] int cbInput,
            [In] IntPtr pPaddingInfo,
            [In] byte[] pbIV,
            [In] int cbIV,
            [Out] byte[] pbOutput,
            [In] int cbOutput,
            [In] [Out] ref int pcbResult,
            [In] int dwFlags
        );

[DllImport("Bcrypt.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern uint BCryptDecrypt(
            [In][Out] IntPtr hKey,
            [In] byte[] pbInput,
            [In] int cbInput,
            [In] IntPtr pPaddingInfo,
            [In] byte[] pbIV,
            [In] int cbIV,
            [Out] byte[] pbOutput,
            [In] int cbOutput,
            [In] [Out] ref int pcbResult,
            [In] int dwFlags
        );

[DllImport("Bcrypt.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern uint BCryptCloseAlgorithmProvider(
            [In] IntPtr phAlgorithm,
            [In] int dwFlags
        );

The following six steps below show an example on how to use the CNG library functions to perform AES encryption & decryption.  The CNG library function calls are shown in bold.

1. Open the Algorithm Provider

//Initialize Status
uint status = 0;

//Initialize AlgHandle
IntPtr pAlgHandle = IntPtr.Zero;

//Open Algorithm Provider
status = BCryptOpenAlgorithmProvider(
       ref pAlgHandle,
       “AES”,
       “Microsoft Primitive Provider”,
       0); 

2. Get Algorithm Properties

//Allocate DWORD for ObjectLength
byte[] pbObjectLength = new byte[4];

//Initialize ObjectLength Byte Count
int pcbObjectLength = 0;

//Get Algorithm Properties(BCRYPT_OBJECT_LENGTH)
status = BCryptGetProperty(
       pAlgHandle,
       “ObjectLength”,
       pbObjectLength,
       pbObjectLength.Length,
       ref pcbObjectLength,
       0);

3. Generate the Key Object

//Initialize KeyHandle
IntPtr pKeyHandle = IntPtr.Zero;

//Initialize Key Object Size with ObjectLength
int keyObjectSize = pbObjectLength[3]<<24 | pbObjectLength[2]<<16 | pbObjectLength[1]<<8 | pbObjectLength[0];
           
//Initialize AES Key
byte[] pbKey = { 0×00, 0×01, 0×02, 0×03, 0×04, 0×05, 0×06, 0×07, 0×08, 0×09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
          
//Allocate KeyObject With Key Object Size
byte[] pbKeyObject = new byte[keyObjectSize];
           
//Generate Symmetric Key Object
status = BCryptGenerateSymmetricKey(
       pAlgHandle,
       ref pKeyHandle,
       pbKeyObject,
       keyObjectSize,
       pbKey,
       pbKey.Length,
       0);

4. Encrypt the Plain Text Data

//Initialize Data To Encrypt
byte[] pbData = { 0×00, 0×01, 0×02, 0×03, 0×04, 0×05, 0×06, 0×07, 0×08, 0×09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };

//Initialize Initialization Vector
byte[] pbIV = { 0×00, 0×01, 0×02, 0×03, 0×04, 0×05, 0×06, 0×07, 0×08, 0×09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; 
//Initialize PaddingInfo
IntPtr pPaddingInfo = IntPtr.Zero;

//Initialize Cipher Text Byte Count
int pcbCipherText = 0;

//Get Cipher Text Byte Count
status = BCryptEncrypt(
       pKeyHandle,
       pbData,
       pbData.Length,
       pPaddingInfo,
       pbIV,
       pbIV.Length,
       null,
       0,
       ref pcbCipherText,
       0);

//Allocate Cipher Text Buffer
byte[] pbCipherText = new byte[pcbCipherText]; 
               
//Encrypt The Data
status = BCryptEncrypt(
       pKeyHandle,
       pbData,
       pbData.Length,
       pPaddingInfo,
       pbIV,
       pbIV.Length,
       pbCipherText,
       pcbCipherText,
       ref pcbCipherText,
       0);

  
5. Decrypt the Cipher Text

//Initialize Initialization Vector
byte[] pbIV2 = { 0×00, 0×01, 0×02, 0×03, 0×04, 0×05, 0×06, 0×07, 0×08, 0×09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; 

//Initialize Plain Text Byte Count
int pcbPlainText = 0;

//Get Plain Text Byte Count
status = BCryptDecrypt(
       pKeyHandle,
       pbCipherText,
       pcbCipherText,
       pPaddingInfo,
       pbIV2,
       pbIV2.Length,
       null,
       0,
       ref pcbPlainText,
       0);

//Allocate Plain Text Buffer
byte[] pbPlainText = new byte[pcbPlainText]; 

//Decrypt The Data
status = BCryptDecrypt(
       pKeyHandle,
       pbCipherText,
       pcbCipherText,
       pPaddingInfo,
       pbIV2,
       pbIV2.Length,
       pbPlainText,
       pbPlainText.Length,
       ref pcbPlainText,
       0);

6. Close the Algorithm Provider
status = BCryptCloseAlgorithmProvider(pAlgHandle, 0);

 

***This sample source code is released under the Microsoft Limited Public License (MS-LPL)

 

Read more >