Windows: CTR mode with Crypto API

Introduction

CTR mode turns a block cipher into a stream cipher. The concept was proposed by Whitfield Diffie and Martin Hellman in their 1979 publication, Privacy and Authentication: An Introduction to Cryptography.

Unfortunately, CTR mode isn’t supported out of the box by Microsoft Crypto API but can be implemented with some additional code using ECB mode.

The question was already asked on stackoverflow while I was searching for some code to perform this.

Maybe someone know, does Microsoft’s CryptoAPI supports AES-128 in CTR Mode?

In MSDN docs I have just find that we might set only following modes CBC ECB OFB CFB and CTS modes. Which we might set with CryptSetKeyParam function. Is it possible to use CTR mode in some way? Combine ECB + IV? Maybe someone know such details for both encryption and decryption processes?

Example in C

CTR mode only requires encryption because we xor the plaintext with ciphertext.

ctr_enc

To recover the plaintext, perform the same operation on the ciphertext generated from nonce and counter.

ctr_dec

So the steps using Crypto API are:

  • Acquire a crypto provider.
  • Initialize a plaintext key blob and copy raw key.
  • Import blob into key object
  • Encrypt the CTR (initialization vector or nonce/counter) with bFinalize set to FALSE
  • XOR plaintext with ciphertext result
  • Update CTR (increment by 1)

Here I use the last test vector from NIST publication and that’s why you see update_ctr(ctr) called 3 times before encryption.

The following is simple example using AES-256 CTR test vectors from Recommendation for Block Cipher Modes of Operation

char key_tv[] = "603deb1015ca71be2b73aef0857d7781"
                "1f352c073b6108d72d9810a30914dff4";
char ctr_tv[]  = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
char pt_tv[]  = "f69f2445df4f9b17ad2b417be66c3710";
char ct_tv[]  = "dfc9c58db67aada613c2dd08457941a6";

typedef struct _key_hdr_t {
  PUBLICKEYSTRUC hdr;            // info about key
  DWORD          len;            // key length in bytes
  BYTE           key[32];        // for AES-256
} key_hdr;

void update_ctr (uint8_t *ctr)
{
  int i;
  
  for (i=16-1; i>=0; i--) {
    ctr[i]++;
    if (ctr[i]) {
      break;
    }
  }
}

int main (int argc, char *argv[])
{
  BOOL       r;
  HCRYPTPROV hProv;
  HCRYPTKEY  hSession;
  key_hdr    key;
  BYTE       ctr[64], pt[64], ct[64];
  DWORD      ctr_len, pt_len, ct_len, i;
  
  r=CryptAcquireContext (&hProv, NULL, NULL, 
      PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
  
  if (!r) {
    xstrerror ("CryptAcquireContext");
    return 0;
  }
  key.hdr.bType    = PLAINTEXTKEYBLOB;
  key.hdr.bVersion = CUR_BLOB_VERSION;
  key.hdr.reserved = 0;
  key.hdr.aiKeyAlg = CALG_AES_256;
  key.len          = hex2bin (key.key, key_tv);
  
  r=CryptImportKey (hProv, (PBYTE)&key, sizeof(key), 
    0, CRYPT_NO_SALT, &hSession);
    
  if (r)
  {
    // encrypt test vector
    pt_len=hex2bin (pt, pt_tv);
    ct_len=hex2bin (ct, ct_tv);
    ctr_len=hex2bin (ctr, ctr_tv);
    
    // update 3 times (only for test vector)
    update_ctr(ctr);
    update_ctr(ctr);
    update_ctr(ctr);
    
    // encrypt the counter
    r=CryptEncrypt (hSession, 0, FALSE, 0, 
      ctr, &ctr_len, sizeof(ctr));
    
    if (r)
    {
      // xor plaintext with ciphertext
      for (i=0; i<pt_len; i++) {
        pt[i] ^= ctr[i];
      }
      // compare with ciphertext result
      if (memcmp (pt, ct, pt_len)==0) {
        printf ("CTR test passed");
      }
    } else xstrerror("CryptEncrypt");
    CryptDestroyKey (hSession);
  } else {
    xstrerror ("CryptImportKey");
  }
  CryptReleaseContext (hProv, 0);
  return 0;
}
Advertisements
This entry was posted in cryptography, programming, windows and tagged , , , . Bookmark the permalink.

2 Responses to Windows: CTR mode with Crypto API

  1. Pingback: Windows: Interactive shells Part 4 |

  2. Pingback: Windows: Interactive shells Part 4 | modexp

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s