Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Next Generation of Cryptography for Microsoft Windows Vista

0.00/5 (No votes)
30 Apr 2007 1  
Cryptography API: Next Generation (CNG) is the latest cryptographic infrastructure in Windows Vista� which supports new APIs, unified user and kernel mode, agile cryptography, new cipher suits and improved auditing

Screenshot - main.jpg

Introduction

The Cryptography API: Next Generation(CNG) is a new and agile framework in Windows Vista�, which implements an extensible provider model that allows you to load a provider by specifying the required cryptographic algorithm rather than having to hardcode a specific provider.

The advantage is that an algorithm provider can be replaced or upgraded and you will not have to change your code in any way to use the new provider. Also, if some algorithm is determined to be unsafe in the future, a more secure version of that algorithm can be installed with no effect to your code. To facilitate this, you load a CNG provider by identifying the cryptographic algorithm that you require, not the specific provider. Most of the CNG APIs require a provider or an object created by a provider.

In this article, I try to describe the new security feature Cryptography API: Next Generation(CNG) and compare it with an RSA and AES samples, both managed and unmanaged, using "Crypto API" (CAPI before Vista) and how it can be implemented using CNG in Windows Vista. Managed version of CNG is yet to come, if you feel like you want more, wait for the next release of Visual Studio "Orcas".

Background

About RSA

RSA is the established standard for public key encryption. The name RSA is derived from the names of the inventors of this algorithm, which are: Ron Rivest, Adi Shamir and Leonard Adleman. The principle and security of RSA is based on the fact that with today's knowledge, it is not possible to find the prime factors of a big number (n=pq, where p and q are prime numbers) in suitable time.

Short details

  • Public Key: n=pq (p and q are big prime numbers)
  • e relative prime to (p-1)(q-1)
  • Private Key: d e-1 mod ((p-1)(q-1))
  • Encryption: c = me mod n
  • Decryption: m = cd mod n

About AES

Advanced Encryption Standard (AES), also known as Rijndael, is a symmetric 128-bit block cipher adopted as an encryption standard by the US government.

Short details

  • AES operates on a 4�4 array of bytes.
  • For encryption, each round of AES (except the last round) consists of four stages: AddRoundKey, Subbytes, Shift rows and Mix columns.
  • At each stage, the bytes are manipulated and processed for the next level.

Crytography API: Next Generation(CNG)

CNG provides a set of APIs that are used for performing basic cryptographic operations, such as creating hashes, encrypting, and decrypting data.

Each algorithm class in CNG is represented by a primitive router. Applications making use of the primitive APIs will link to the router binary (Bcrypt.dll in user mode, or Ksecdd.sys in kernel mode), and make calls to the various CNG primitive functions. All of the algorithm primitives are managed by various router components. These routers keep track of each algorithm implementation that has been installed on the system. The router will route each function call to the appropriate primitive provider module.

The following illustration shows the design and function of the CNG cryptographic primitives.

Screenshot - cng1.gif

CNG provides primitives for the following classes of algorithms:

  • Random Number Generator: This class is used to represent pluggable random number generation (RNG).
  • Hashing: This class represents algorithms used for hashing, such as SHA1 and SHA2.
  • Symmetric encryption: This class represents algorithms used for symmetric encryption. Some examples are AES, 3DES, and RC4.
  • Asymmetric encryption: This class represents asymmetric (public key) algorithms that support encryption, like RSA.
  • Signature: This class represents signature algorithms such as DSA and ECDSA. This class can also be used with RSA.
  • Secret Agreement: This class represents secret agreement algorithms such as Diffie-Hellman (DH) and elliptical curve Diffie-Hellman (ECDH).

Using the code

Using a RSA CryptoService Provider (CAPI)

In CAPI, all cryptographic algorithms are predefined in wincrypt.h which makes it very difficult to extend cryptographic functionality to suit your application's need. Adding a custom symmetric algorithm is not easy. Secondly the CAPI requires Microsoft to sign the implementation, so that it can be a part of a security namespace.

Encrypt and Decrypt in a traditional way, with RSACryptoServiceProvider.

RSACryptoServiceProvider MyAsymmetricAlgorithm = new RSACryptoServiceProvider();
byte[] PlainTextBytes;
byte[] CipherTextBytes;

private void Encrypt()
{
    PlainTextBytes = System.Text.Encoding.UTF8.GetBytes(TextBoxOriginal.Text);
    CipherTextBytes = MyAsymmetricAlgorithm.Encrypt(PlainTextBytes, true);
    TextBoxEncrypted.Text = TextBoxEncrypted.Text +
    + Convert.ToBase64String(CipherTextBytes);
                ShowPublicPrivate();
    // rest of the code removed for brevity

}

private void Decrypt()
{
    PlainTextBytes = MyAsymmetricAlgorithm.Decrypt(CipherTextBytes, true);
    TextBoxOriginal.Text = System.Text.Encoding.UTF8.GetString
    (PlainTextBytes);
}

private void ShowPublicPrivate()
{
   RSAParameters MyParameters = new RSAParameters();
   MyParameters = MyAsymmetricAlgorithm.ExportParameters(true);
   TextBoxPrivateKey.Text = Convert.ToBase64String(MyParameters.D);
   TextBoxPublicKey.Text = Convert.ToBase64String(MyParameters.Modulus);
   // rest of the code removed for brevity

}

Using the CryptoService Provider with CNG

In CNG, all cryptographic constants are "strings" rather than numeric constants. And since you can use any string constant you want to define your algorithm, when your application attempts to use the algorithm, CNG will load the crypto-provider that registered the name. You can also plug in custom cipher-suits for SSL and TLS. The core function that adds a new add-in is BCryptAddContextFunctionProvider2.

The typical steps involved in using the CNG API for cryptographic primitive operations are:

  1. Open the Algorithm Provider
  2. Get or Set Algorithm Properties
  3. Create or Import a Key
  4. Perform Cryptographic Operations
  5. Close the Algorithm Provider

The code for "encrypting data", the string for RSA encryption is BCRYPT_RSA_ALGORITHM. The following shows a pseudocode for the algorithm.

Encrypt pseudocode

BCryptOpenAlgorithmProvider(&hAlg...)
BCryptGetProperty(hAlg,BCRYPT_BLOCK_LENGTH,&dwBlockSize...)
//allocate buffer , rounding up to next block size


BCryptGetProperty(hAlg,BCRYPT_OBJECT_LENGTH,&cbKeyObjectLen...)
//allocate buffer for key object


BCryptGenerateSymmetricKey(hAlg,&hKey...)
BCryptEncrypt(hKey,...)
//data is now encrypted


BCryptDestroyKey(hKey)
BCryptCloseAlgorithmProvider(hAlg,0)
//deallocate buffers

Portion of Encrypt code, key generation

I have added this example of CNG for AES, and not for RSA for simplicity and reference only.
BCRYPT_RSA_ALGORITHM can also be implemented in a similar fashion. A complete sample program for AES-CBC encryption using CNG comes with the CNG3 SDK.

Here BCRYPT_AES_ALGORITHM is the string variable which gives the handle to the actual algorithm. So later if this algorithm needs to be changed, all we will need to do is change the implementation of AES, keeping the existing code.

#include "stdafx.h"

using namespace std;
#pragma comment(lib, "bcrypt")

wchar_t *GetEncryptionAlg() 
{
    return BCRYPT_AES_ALGORITHM;
}

LPBYTE GetPwd() 
{
    static const BYTE key[] = {1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,0};
    return (LPBYTE)key;
}

LPBYTE GetIV() 
{
    static const BYTE iv[] = {1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8};
    return (LPBYTE)iv;
}

int _tmain(int argc, _TCHAR* argv[]) 
{
    BCRYPT_ALG_HANDLE hAlg = NULL;
    if (BCryptOpenAlgorithmProvider(
        &hAlg,
        GetEncryptionAlg(),
        NULL,
        0) == STATUS_SUCCESS) 
        {
            BCRYPT_KEY_HANDLE hKey = NULL;
            DWORD cbKey = 0;
            DWORD cbData = 0;
            if (BCryptGetProperty(
                    hAlg,
                    BCRYPT_OBJECT_LENGTH,
                    reinterpret_cast(&cbKey),
                    sizeof cbKey,
                    &cbData,
                    0) == STATUS_SUCCESS) 
            {
                LPBYTE pbKey = new (nothrow)BYTE[cbKey];
                if (pbKey) 
                {
                        BCRYPT_KEY_HANDLE hKey = NULL;
                        LPCSTR szPwd = (LPCSTR)GetPwd();
                        if (BCryptGenerateSymmetricKey(
                                    hAlg,
                                    &hKey,
                                    pbKey,
                                    cbKey,
                                    (PUCHAR)szPwd,
                                    (ULONG)strlen(szPwd),
                                    0) == STATUS_SUCCESS) 
                        {
                                printf("!!!");
                        }
                }
            }
        }

    return 0;
}

Decrypting Data

Same as above, except for BCryptDecrypt

BCryptOpenAlgorithmProvider(&hAlg...)
BCryptGetProperty(hAlg,BCRYPT_BLOCK_LENGTH,&dwBlockSize...)
//allocate buffer , rounding up to next block size


BCryptGetProperty(hAlg,BCRYPT_OBJECT_LENGTH,&cbKeyObjectLen...)
//allocate buffer for key object


BCryptGenerateSymmetricKey(hAlg,&hKey...)
BCryptDecrypt(hKey,...)
//data is now encrypted


BCryptDestroyKey(hKey)
BCryptCloseAlgorithmProvider(hAlg,0)
// deallocate buffers

Hashing Data

BCryptOpenAlgorithmProvider(&hAlg...)
BCryptGetProperty(hAlg,BCRYPT_OBJECT_LENGTH,&cbHash...)
//allocate buffer for hash


BCryptCreateHash(hAlg,&hHash,...)
BCryptHashData(hHash,...)
// use the hash data

// your code here


BCryptDestroyHash(hHash)
BCryptCloseAlgorithmProvider(hAlg,0)
//deallocate buffers

With CNG, a cryptographer can create his own cryptographic provider, with all the needed interfaces and functionality for the provider and plug in the CNG framework. The core function which is required for this is BCryptAddContextFunctionProvider.

Here is the basic structure which will be required to add a test algorithm BCRYPT_MYTEST_ALGORITHM, for details please refer to the steps to install and register "CNG add-ins" in the CNG SDK3.
#define BCRYPT_MYTEST_ALGORITHM
status = BCryptAddContextFunctionProvider(
         CRYPT_LOCAL,
         NULL,  //default

         BCRYPT_CIPHER_INTERFACE,
         BCRYPT_MYTEST_ALGORITHM,
         L"MyTest Provider",
         CRYPT_PRIORITY_TOP);

A CNG also allows you to query for all supported algorithms using the function BCryptResolveProviders.

#include "stdafx.h"

#pragma comment(lib, "bcrypt")
#ifndef NT_SUCCESS
#   define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#endif

int  __cdecl main(int argc, __in_ecount(argc) LPWSTR *wargv) 
{
    argc;
    wargv;

    BOOLEAN bFipsEnabled = FALSE;
    if (NT_SUCCESS(BCryptGetFipsAlgorithmMode(&bFipsEnabled)))
        printf("FIPS is %Senabled.\n",bFipsEnabled ? L"" : L"not ");

    PCRYPT_PROVIDER_REFS pProviders = NULL;
    DWORD dwBufSize = 0;
    const DWORD dwFlags = CRYPT_ALL_FUNCTIONS | CRYPT_ALL_PROVIDERS;

    for (DWORD i = BCRYPT_CIPHER_INTERFACE; i <= BCRYPT_RNG_INTERFACE; i++) 
    {
        NTSTATUS ret = BCryptResolveProviders(
                            NULL,
                            i,
                            NULL,
                            NULL,
                            CRYPT_UM,
                            dwFlags,
                            &dwBufSize,
                            &pProviders);
        if (NT_SUCCESS(ret) && pProviders) 
        {
            printf("dwInterface = %d\n", i);

            for (DWORD k=0; k < pProviders->cProviders; k++) 
            {
                PCRYPT_PROVIDER_REF pProv = pProviders->rgpProviders[k];

                printf("\tFunction = %S\n", pProv->pszFunction);
                printf("\tProvider = %S\n", pProv->pszProvider);

            // print property names

            for ( DWORD j = 0; j < pProv->cProperties; j++)
            printf("\tProperty %d = %S\n", j, 
            pProv->rgpProperties[j]->pszProperty);

                printf("\n");
            }

            BCryptFreeBuffer(pProviders);
            pProviders = NULL;
            dwBufSize = 0;
        }
    }

    return 0;
}

Managed library for CNG is coming with the next version of Visual Studio "Orcas" and is not available right now in Visual Studio 2005. You can download the unmanaged version of the CNG SDK3 to develop for Windows Vista.

CNG also has access to all the CAPI keys used by Microsoft Cryptographic Service providers.

List of CNG Cryptographic Primitive Functions

Here is a the list of functions defined by the Cryptographic Next Generation (CNG) API that are used for performing cryptographic operations.

  • BCryptCloseAlgorithmProvider
  • BCryptCreateHash
  • BCryptDecrypt
  • BCryptDeriveKey
  • BCryptDestroyHash
  • BCryptDestroyKey
  • BCryptDestroySecret
  • BCryptDuplicateHash
  • BCryptDuplicateKey
  • BCryptEncrypt
  • BCryptExportKey
  • BCryptFinalizeKeyPair
  • BCryptFinishHash
  • BCryptFreeBuffer
  • BCryptGenerateKeyPair
  • BCryptGenerateSymmetricKey
  • BCryptGenRandom
  • BCryptGetProperty
  • BCryptHashData
  • BCryptImportKey
  • BCryptImportKeyPair
  • BCryptOpenAlgorithmProvider
  • BCryptSecretAgreement
  • BCryptSetProperty
  • BCryptSignHash
  • BCryptVerifySignature

Look for details on each of these functions in MSDN.

New Crypto Algorithms in Orcas

The January CTP of Orcas, has the first set of managed wrappers around the new CNG APIs in Windows Vista5, which will use the "Cng suffix" on the implementation classes.

Hash Algorithms

Algorithm Class OS Required
MD5 MD5Cng Windows Vista
SHA-1 SHA1Cng Windows Vista
SHA-256 SHA256CryptoServiceProvider
SHA256Cng
Windows 2003
Windows Vista
SHA-384 SHA384CryptoServiceProvider
SHA384Cng
Windows 2003
Windows Vista
SHA-512 SHA512CryptoServiceProvider
SHA512Cng
Windows 2003
Windows Vista

For applications targeting Vista which must use CNG, this set of algorithms also provides CNG wrappers for all of our hashing algorithms.

Asymmetric Algorithms

Algorithm Class OS Required
Elliptic Curve DSA ECDSACng Windows Vista
Elliptic Curve Diffie-Hellman ECDiffieHellmanCng Windows Vista

Check Microsoft security5 blogs for the latest information on CNG.

Points of Interest

  • Windows Vista supports the following four user modes cryptographic interfaces; CNG, Cryptographic API 1.0 (CAPI 1.0), Cryptographic API 2.0 (CAPI 2.0) and .NET Framework Cryptography
  • CNG also includes kernel mode along with the user mode. In prior versions of Windows, technologies like CAPI were user mode only and kernel mode cryptography required totally different set of APIs. Now with the Next Generation Cryptography (CNG) there is a unified set of APIs for both
  • CNG is highly flexible, enabling new algorithms to be added to Windows Vista for use in Secure Socket Layer/Transport Layer Security SSL/TLS and Internet Protocol Security IPSec
  • CNG includes Elliptic Curve Cryptography, an emerging standard among cryptographic algorithms.
  • Windows Vista includes a Base Smart Card Cryptographic Service Provider (Base CSP) in the platform. This will make smart cards more accessible, as vendors will no longer have to deal with writing complex CSPs. There will also be a smart card Key Storage Provider in the new CNG infrastructure.
  • Only administrator can install a CNG Provider

References

  1. Encryption and Cryptography
  2. Writing Secure Code for Windows Vista
  3. Download CNG SDK for use in C++
  4. Orcas January CTP with Managed library for CNG
  5. CNG Reference, MSDN Security blog
  6. List Cryptographic algorithms available in your computer

History

  • Apr 29, 2007: First Published
  • May 02, 2007: CNG Enumerator & portion of AES encrypt

And thanks

For coming so far, I hope this article will help demystify some of the new security concepts in Windows Vista, and you will find it useful. Adios!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here