CryptoAPI and Cryptographic Service Providers

When the folks at Microsoft decided how they were going to build this cryptographic functionality into the operating system, they chose to make it very flexible and expandable. They realized that different applications would need different types and strengths of encryption. They also knew that new types of encryption would be released on a regular basis.

The question was how to make the API able to continuously expand and adapt as the state of the art for encryption changes, while not requiring constant changing and updating of all the applications that use the API. Microsoft's solution to this question was to make the API a front end that applications could use and call, while the back end was an open API for any encryption vendor to plug in its own encryption engine, as illustrated in Figure 2.1.

These plug-in encryption engines are called Cryptographic Service Providers (CSPs). Windows is shipped with some default CSPs that serve most basic encryption needs. Even if your application needs require a CSP that is not shipped with Windows, you build your appli cation no differently than if you could use a default one.

Note

The construction of Cryptographic Service Providers (CSP) is not covered in this book. This book covers only how to build applications that use the API.


Figure 2.1. The CryptoAPI passes messages between applications and Cryptographic Service Providers.


With this design, the CryptoAPI does little more than pass messages back and forth between the applications using it and the CSPs being used by those applications. Consequently, all the responsibility for performing the encryption and decryption is placed on the CSP, not your application. You therefore can change what type of encryption you are using as the need arises. It also places the need to employ those number-speaking mathematicians on the vendors creating the CSPs.

Opening the CSP

One of the first steps that you have to take in an application that uses the CryptoAPI is to open a context handle to the appropriate CSP. The CSP context is opened with the CryptAcquireContext function. The declaration for the CryptAcquireContext function is as follows:

Context Handle

A context handle is an ID for a resource that has been opened and is being maintained by the operating system. A context handle is different from a pointer in that a pointer contains an actual memory address where the object can be found, whereas a handle contains an ID number that is used to identify the object. Context handles are typically used with resources that are made available for use by the operating system.


Public Declare Function CryptAcquireContext Lib "advapi32.dll" _
     Alias "CryptAcquireContextA" (phProv As Long, _
     ByVal pszContainer As String, ByVal pszProvider As String, _
     ByVal dwProvType As Long, ByVal dwFlags As Long) As Long

Note

Microsoft has not packaged the CryptoAPI in an ActiveX or COM control (despite a lot of documentation from Microsoft mentioning such a control). As a result, all the function declarations in this book are given in the form of their API declarations so that Visual Basic can use the function.


Tip

In this and other function declarations that have string parameters, you have the option of declaring the alias with a trailing "W" instead of the trailing "A" if you know that you will be running on NT or Windows 2000. This will call the UNICODE versions of these functions, allowing you to use UNICODE strings. The other option that you have available to you is to declare all "ByVal String" parameters as "ByRef Byte" parameters, and pass in the first position in a byte array that you have copied the string into. If you will be working only with character sets that fit within the ANSI character set, or will be needing your applications to run on Windows 95/98, then leave all of the function alias declarations as they are specified in this book, using the ANSI version of the functions.


The first parameter to this function (phProv) is a long variable into which the handle for the CSP context will be placed. This variable will be used throughout your application.

The second variable (pszContainer) is the name of the key container to be opened. If you are using the default Microsoft CSP and pass a string consisting only of the NULL string (vbNullString), the CSP will use the login name of the current user for the name of the key container.

Note

If your application stores private key information in the key store, it is recommended that you do not use the default key store, no matter which CSP you are using. The reason for this is that it would be very easy for any other application to write over or otherwise alter the key information in the default key store. By creating an application-specific key store, you can store keys in it without worrying about other applications modifying them.


Key Store

A key store is a CSP-maintained database in which encryption keys are kept for use over multiple application sessions. Normally, session encryption keys are not kept in a key store, whereas public/private key pairs are usually kept in one. Some CSPs maintain their key store in the Registry database, whereas others maintain it in other locations, such as in Smart Cards or encrypted, hidden files.


The third variable (pszProvider) is the name of the CSP to be used. Constant definitions can be used for any of the Microsoft CSPs. These constants are listed in Table 2.1. If you pass the NULL string (vbNullString) as the provider name, the default provider for the specified CSP type (see the next parameter) will be used.

Table 2.1. Constant Definitions for Microsoft CSPs
Constant Value
MS_DEF_PROV Microsoft Base Cryptographic Provider v1.0
MS_ENHANCED_PROV Microsoft Enhanced Cryptographic Provider v1.0
MS_DEF_RSA_SIG_PROV Microsoft RSA Signature Cryptographic Provider
MS_DEF_RSA_SCHANNEL_PROV Microsoft Base RSA SChannel Cryptographic Provider
MS_ENHANCED_RSA_SCHANNEL_PROV Microsoft Enhanced RSA SChannel Cryptographic Provider
MS_DEF_DSS_PROV Microsoft Base DSS Cryptographic Provider
MS_DEF_DSS_DH_PROV Microsoft Base DSS and Diffie-Hellman Cryptographic Provider

The fourth parameter (dwProvType) is the provider type. A series of constants is defined for use with this parameter, as listed in Table 2.2. This list of types will expand as new encryption methods and formulas are introduced. It is important to choose a provider type that is supported by the provider selected in the previous parameter.

Table 2.2. Constant Definitions for Microsoft CSP Types
Constant Value Description
PROV_RSA_FULL 1 This general-purpose type supports both digital signatures and encryption.
PROV_RSA_SIG 2 A subset of the PROV_RSA_FULL type, this type is for hashes and digital signatures only.
PROV_DSS 3 This type implements the Digital Signature Algorithm (DSA) for hashes and digital signatures only.
PROV_FORTEZZA 4 This type implements a series of National Institute of Standards and Technology (NIST) algorithms.
PROV_MS_EXCHANGE 5 This provider type is designed for use with Microsoft Exchange and other MS Mail-compatible applications.
PROV_SSL 6 This provider type supports the Secure Sockets Layer (SSL) protocol.
PROV_RSA_SCHANNEL 12 This general-purpose type supports both the RSA and SChannel protocols.
PROV_DSS_DH 13 A superset of the PROV_DSS type, this type is for both digital signatures and encryption.

The fifth and final parameter (dwFlags) is used to specify options on how the CSP context needs to be opened. These options can be used to create a new key container or to prevent the application from having access to private keys. The available values that can be used in this flag are listed in Table 2.3. More often than not, you'll want to pass 0 for this parameter. Passing 0 signals that you want to open an existing keyset.

Table 2.3. CryptAcquireContext Flags
Flag Value Description
CRYPT_VERIFYCONTEXT &HF0000000 This option is for use by applications that do not use private keys. When this option is used, the key container parameter (the second parameter) should be just the NULL character.
CRYPT_NEWKEYSET &H8 A new key container will be created with the name in the key container parameter (the second parameter).
CRYPT_MACHINE_KEYSET 1&H20 This option tells the CSP that the key container is a machine container (the default is a user container, associated with the currently logged-on user). This option must be used if the application is running as a service.
CRYPT_DELETEKEYSET &H10 The key container specified will be deleted. If the key container parameter is the NULL character, then the default key container will be deleted.
CRYPT_SILENT &H40 The CSP will not display any user interface elements to the user.

The CryptAcquireContext function returns a C language Boolean, which you cast as a Visual Basic Boolean by using the CBool function. You can check the resulting Boolean value, as follows, to determine whether the function was successful:

Dim sContainer As String
Dim sProvider As String
Dim lHCryptProv as Long

'--- Prepare string buffers
sContainer = vbNullChar
sProvider = MS_DEF_PROV & vbNullChar

'--- Attempt to acquire a handle to the default key container.
If CBool(CryptAcquireContext(lHCryptProv, vbNullString, sProvider, _
        PROV_RSA_FULL, 0)) Then
   '--- We were successful, continue on...
					

Closing the CSP

After you have finished all the encryption that your application needs to do, you need to close the key container context by using the CryptReleaseContext function. This function is defined as follows:

 Public Declare Function CryptReleaseContext Lib "advapi32.dll" ( _
      ByVal hProv As Long, ByVal dwFlags As Long) As Long


Calling this function is simple because it has only one parameter of any importance. The first parameter (hProv) is the handle to the key context that you received in the CryptAcquireContext function (the first parameter in that function). This parameter tells the CryptReleaseContext function which key container context to close. The second parameter (dwFlags) is always zero (0). Therefore, you can call this function as you are closing your application, as in the following code:

Dim lResult As Long

'--- Do we have an open key context? If so, release it.
If (lHCryptProv <> 0) Then _
        lResult = CryptReleaseContext(lHCryptProv, 0)

The CryptReleaseContext function does return a Boolean result, but the only reason it might fail is if you pass it an invalid key container handle (or pass it something other than 0 for the second parameter).

Listing the Available CSPs

So what do you do if you need a particular CSP, and you don't know whether it's available on the user's computer? In this case, you can enumerate the CSPs on the system by using the CryptEnumProviders function. This function is defined as follows:

Public Declare Function CryptEnumProviders Lib "advapi32.dll" _
    Alias "CryptEnumProvidersA" (ByVal dwIndex As Long, _
    ByVal pdwReserved As Long, ByVal dwFlags As Long, _
    pdwProvType As Long, ByVal pszProvName As String, _
    pcbProvName As Long) As Long

The first parameter (dwIndex) to this function is the index number of the CSP to list. The index starts with zero (0) for the first CSP and increments from there. So, as you are looping through all the available CSPs, you need to have a counter variable that you can increment for each CSP you enumerate.

The second (pdwReserved) and third (dwFlags) parameters should always be zero (0). These parameters are "reserved for future use," so at some point, this use may change, but for now, just pass 0 for both of them.

The fourth parameter (pdwProvType) is a variable into which the provider type will be placed. For a list of the current provider types, see Table 2.2.

The fifth parameter (pszProvName) is a string variable into which the name of the provider will be placed. You can pass the NULL string (vbNullString) in this parameter to determine the length of the string needed to hold the provider name. The length of the provider name will be copied into the variable passed as the sixth parameter (pcbProvName). After you have sized the string for the fifth parameter, the sixth parameter should be populated with the length of the string being passed for the fifth parameter.

As with most CryptoAPI functions, this one returns a Boolean value that can be checked (after passing through the CBool function) to determine whether the function succeeded. You might use this function as follows:

Dim lResult As Long
Dim lIndex As Long
Dim sNameBuffer As String
Dim lNameLength As Long
Dim lProvType As Long

lIndex = 0
'--- Determine the size of the buffer needed
lResult = CryptEnumProviders(lIndex, 0, 0, lProvType, vbNullString, _
        lNameLength)
'--- We expect the preceding function call to fail, so we don't need to
'--- check the return value

'--- Prepare a string buffer for the CryptEncrypt function
sNameBuffer = String(lNameLength, vbNullChar)

'--- Get the provider name
If CBool(CryptEnumProviders(lIndex, 0, 0, lProvType, sNameBuffer, _
        lNameLength)) Then
    '--- Continue on
					

Listing the CSP Types

If you want to know what the available provider types are on a particular system, you can use the CryptEnumProviderTypes function. This function looks basically the same as the CryptEnumProviders function, as in the following definition:

Public Declare Function CryptEnumProviderTypes Lib "advapi32.dll" _
    Alias "CryptEnumProviderTypesA" (ByVal dwIndex As Long, _
    ByVal pdwReserved As Long, ByVal dwFlags As Long, _
    pdwProvType As Long, ByVal pszTypeName As String, _
    pcbTypeName As Long) As Long

The only difference between this function and the CryptEnumProviders function is that the name of the provider type is returned in the fifth parameter (pszTypeName). Otherwise, all the parameters are the same, and the two functions work the same.

Getting the Default CSP

When you want to determine which CSP is the default provider for a specific CSP type, you can use the CryptGetDefaultProvider function. This function is defined as follows:

Public Declare Function CryptGetDefaultProvider Lib "advapi32.dll" _
    Alias "CryptGetDefaultProviderA" (ByVal dwProvType As Long, _
    ByVal pdwReserved As Long, ByVal dwFlags As Long, _
    ByVal pszProvName As String, pcbProvName As Long) As Long

The first parameter (dwProvType) for this function is the CSP type for which you want to know the default CSP. These types are listed in Table 2.2. The second parameter (pdwReserved) is "reserved for future use" and should always be zero (0).

The third parameter (dwFlags) specifies whether to look up the user or machine default CSP. The available values are listed in Table 2.4.

Table 2.4. CryptGetDefaultProvider Flags
Flag Value Description
CRYPT_MACHINE_DEFAULT &H1 Returns the computer default CSP for the specified CSP type
CRYPT_USER_DEFAULT &H2 Returns the user default CSP for the specified CSP type

The fourth parameter (pszProvName) is a string into which the name of the default provider will be copied. The fifth parameter (pcbProvName) is the size of the string into which the name will be copied and the length of the CSP name after it is copied into the string.

As with most CryptoAPI functions, the CryptGetDefaultProvider function returns a Boolean value that you can check by using the CBool function.

Setting the Default CSP

To set the default CSP, you have two options, depending on which platform your application runs. The first option is the CryptSetProvider function, defined as follows:

Public Declare Function CryptSetProvider Lib "advapi32.dll" _
    Alias "CryptSetProviderA" (ByVal pszProvName As String, _
    ByVal dwProvType As Long) As Long

This function takes two parameters. The first parameter (pszProvName) is the name of the CSP to be the default for the CSP type. The second parameter (dwProvType) is the CSP type for which to make the CSP specified as the default.

Note

Remember that if the NULL string is passed as the CSP name to the CryptAcquireContext function to open a CSP and key container, the default CSP is used.


The second option is the CryptSetProviderEx function, which is defined as follows:

Public Declare Function CryptSetProviderEx Lib "advapi32.dll" _
    Alias "CryptSetProviderExA" (ByVal pszProvName As String, _
    ByVal dwProvType As Long, ByVal pdwReserved As Long, _
    ByVal dwFlags As Long) As Long

In this version, the first two parameters are the same as with the CryptSetProvider version. The first (pszProvName) is the name of the CSP to be used, and the second (dwProvType) is the CSP type to make it the default. The third parameter (pdwReserved) is reserved and should always be zero (0).

The fourth parameter (dwFlags) is the real difference between these two versions. This parameter is used to specify whether you want to set the user or machine default CSP. You can also specify to delete (unset) the current default CSP for a particular type. The possible values for this parameter are listed in Table 2.5. You can use OR to combine these values to delete either the user or machine default.

Table 2.5. CryptSetProviderEx Flags
Flag Value Description
CRYPT_MACHINE_DEFAULT &H1 Sets the computer default CSP for the specified CSP type
CRYPT_USER_DEFAULT &H2 Sets the user default CSP for the specified CSP type
CRYPT_DELETE_DEFAULT &H4 Deletes (unsets) the default CSP for the specified type

As usual, you can check the Boolean return value to determine whether these functions were successful by using the CBool function.

CSP Types and Encryption Algorithms

The various CSP types implement certain encryption algorithms for performing their various tasks. If you need to use a specific algorithm, you need to check which CSP type supports it. The current CSP types and the algorithms they support are listed in Table 2.6.

Table 2.6. CSP Types and the Algorithms Implemented
Type Key Exchange Signature Encryption Hashing
PROV_RSA_FULL RSA RSA RC2 MD5
   RC4 SHA
PROV_RSA_SIG  RSA  MD5
    SHA
PROV_DSS  DSS  MD5
    SHA
PROV_FORTEZZA KEA DSS Skipjack SHA
PROV_MS_EXCHANGE RSA RSA CAST MD5
PROV_SSL RSA RSA Varies Varies
PROV_RSA_SCHANNEL RSA RSA CYLINK_MEK MD5
    SHA
PROV_DSS_DH DH DSS CYLINK_MEK MD5
    SHA
PROV_DH_SCHANNEL DH DSS RC2 RC4 MD5
   RC4SHA
   CYLINK_MEK 

Note

Not all the CSP types listed in Table 2.6 may be present, or have the same capabilities as listed, if you are working with an older version of the CryptoAPI. If you are working with the CryptoAPI 1.0 version, you might want to check the documentation to see which CSP types are supported, and what capabilities they have.


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset