|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1996
//
// File: oidenc.c
//
// Contents: SCHANNEL encode/decode functions
//
// ASN.1 implementation uses the Asn1 compiler.
//
// Functions: InitSchannelAsn1
// ShutdownSchannelAsn1
//
// History: 03-Dec-98 philh changed to use msasn1
//
//--------------------------------------------------------------------------
#include <spbase.h>
#include <pkiasn1.h>
#include <crypttls.h>
#include <oidenc.h>
#include "asn1enc.h"
// Nonstandard extension, function/data pointer conversion in expression
#pragma warning (disable: 4152)
VOID ReverseMemCopy( PUCHAR Dest, PUCHAR Source, ULONG Size) ;
#define PRIVATE_KEY_TAG "private-key"
// All the *pvInfo extra stuff needs to be aligned
#define INFO_LEN_ALIGN(Len) ((Len + 7) & ~7)
static HCRYPTASN1MODULE hAsn1Module;
//+-------------------------------------------------------------------------
// Function: GetEncoder/GetDecoder
//
// Synopsis: Initialize thread local storage for the asn libs
//
// Returns: pointer to an initialized Asn1 encoder/decoder data
// structures
//--------------------------------------------------------------------------
static ASN1encoding_t GetEncoder(void) { return I_CryptGetAsn1Encoder(hAsn1Module); } static ASN1decoding_t GetDecoder(void) { return I_CryptGetAsn1Decoder(hAsn1Module); }
//+-------------------------------------------------------------------------
// Asn1 SCHANNEL Private Encode/Decode functions
//--------------------------------------------------------------------------
BOOL WINAPI Asn1RSAPublicEncode( IN DWORD dwCertEncodingType, IN LPCSTR lpszStructType, IN PUBLICKEYSTRUC *pbKeyStruc, OUT BYTE *pbEncoded, IN OUT DWORD *pcbEncoded );
BOOL WINAPI Asn1PrivateKeyFileEncode( IN DWORD dwCertEncodingType, IN LPCSTR lpszStructType, IN PPRIVATE_KEY_FILE_ENCODE pKey, OUT BYTE *pbEncoded, IN OUT DWORD *pcbEncoded );
BOOL WINAPI Asn1PrivateKeyFileDecode( IN DWORD dwCertEncodingType, IN LPCSTR lpszStructType, IN const BYTE *pbEncoded, IN DWORD cbEncoded, IN DWORD dwFlags, OUT PPRIVATE_KEY_FILE_ENCODE pKey, IN OUT DWORD *pcbKey );
BOOL WINAPI Asn1PrivateKeyInfoEncode( IN DWORD dwCertEncodingType, IN LPCSTR lpszStructType, IN BLOBHEADER * pKey, OUT BYTE *pbEncoded, IN OUT DWORD *pcbEncoded );
BOOL WINAPI Asn1PrivateKeyInfoDecode( IN DWORD dwCertEncodingType, IN LPCSTR lpszStructType, IN const BYTE *pbEncoded, IN DWORD cbEncoded, IN DWORD dwFlags, OUT BLOBHEADER * pKey, IN OUT DWORD *pcbKey );
static BOOL WINAPI Asn1X509CtlUsageDecode( IN DWORD dwCertEncodingType, IN LPCSTR lpszStructType, IN const BYTE *pbEncoded, IN DWORD cbEncoded, IN DWORD dwFlags, OUT PCTL_USAGE pInfo, IN OUT DWORD *pcbInfo );
static const CRYPT_OID_FUNC_ENTRY SchannelEncodeFuncTable[] = { szPrivateKeyFileEncode, Asn1PrivateKeyFileEncode, szPrivateKeyInfoEncode, Asn1PrivateKeyInfoEncode, szOID_RSA_RSA_Public, Asn1RSAPublicEncode };
#define SCHANNEL_ENCODE_FUNC_COUNT (sizeof(SchannelEncodeFuncTable) / \
sizeof(SchannelEncodeFuncTable[0]))
static const CRYPT_OID_FUNC_ENTRY SchannelDecodeFuncTable[] = { szPrivateKeyFileEncode, Asn1PrivateKeyFileDecode, szPrivateKeyInfoEncode, Asn1PrivateKeyInfoDecode, X509_ENHANCED_KEY_USAGE, Asn1X509CtlUsageDecode };
#define SCHANNEL_DECODE_FUNC_COUNT (sizeof(SchannelDecodeFuncTable) / \
sizeof(SchannelDecodeFuncTable[0]))
//+-------------------------------------------------------------------------
// Dll initialization
//--------------------------------------------------------------------------
BOOL WINAPI InitSchannelAsn1( HMODULE hModule) { ASN1ENC_Module_Startup(); if (0 == (hAsn1Module = I_CryptInstallAsn1Module(ASN1ENC_Module, 0, NULL))) { return FALSE; }
if (!CryptInstallOIDFunctionAddress( hModule, X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC, SCHANNEL_DECODE_FUNC_COUNT, SchannelDecodeFuncTable, 0)) { return FALSE; }
if (!CryptInstallOIDFunctionAddress( hModule, X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC, SCHANNEL_ENCODE_FUNC_COUNT, SchannelEncodeFuncTable, 0)) { return FALSE; } return TRUE; }
BOOL WINAPI ShutdownSchannelAsn1() { if (hAsn1Module) { I_CryptUninstallAsn1Module(hAsn1Module); ASN1ENC_Module_Cleanup(); hAsn1Module = 0; }
return TRUE; }
//+-------------------------------------------------------------------------
// Encode an Asn1 formatted info structure
//
// Called by the Asn1X509*Encode() functions.
//--------------------------------------------------------------------------
static BOOL Asn1InfoEncode( IN int pdunum, IN void *pAsn1Info, OUT BYTE *pbEncoded, IN OUT DWORD *pcbEncoded ) { ASN1encoding_t Encoder; if((Encoder = GetEncoder()) == NULL) { return FALSE; }
return PkiAsn1EncodeInfo( Encoder, pdunum, pAsn1Info, pbEncoded, pcbEncoded); }
//+-------------------------------------------------------------------------
// Encode an Asn1 formatted info structure
//
// Called by the Asn1X509*Encode() functions.
//--------------------------------------------------------------------------
static BOOL Asn1InfoEncodeAndAlloc( IN int pdunum, IN void *pAsn1Info, OUT BYTE **ppEncoded, IN OUT DWORD *pcbEncoded ) { ASN1encoding_t Encoder; if((Encoder = GetEncoder()) == NULL) { return FALSE; }
if(!PkiAsn1EncodeInfo( Encoder, pdunum, pAsn1Info, NULL, pcbEncoded)) { return FALSE; } *ppEncoded = SPExternalAlloc(*pcbEncoded); if(*ppEncoded == NULL) { return FALSE; } if(!PkiAsn1EncodeInfo( Encoder, pdunum, pAsn1Info, *ppEncoded, pcbEncoded)) { SPExternalFree(*ppEncoded); return FALSE; } return TRUE;
}
//+-------------------------------------------------------------------------
// Decode into an allocated, Asn1 formatted info structure
//
// Called by the Asn1X509*Decode() functions.
//--------------------------------------------------------------------------
static BOOL Asn1InfoDecodeAndAlloc( IN int pdunum, IN const BYTE *pbEncoded, IN DWORD cbEncoded, OUT void **ppAsn1Info ) { ASN1decoding_t Decoder; if((Decoder = GetDecoder()) == NULL) { return FALSE; }
return PkiAsn1DecodeAndAllocInfo( Decoder, pdunum, pbEncoded, cbEncoded, ppAsn1Info); }
//+-------------------------------------------------------------------------
// Free an allocated, Asn1 formatted info structure
//
// Called by the Asn1X509*Decode() functions.
//--------------------------------------------------------------------------
static void Asn1InfoFree( IN int pdunum, IN void *pAsn1Info ) { ASN1decoding_t Decoder; if((Decoder = GetDecoder()) == NULL) { return; }
if (pAsn1Info) { DWORD dwErr = GetLastError();
// TlsGetValue globbers LastError
PkiAsn1FreeInfo(Decoder, pdunum, pAsn1Info);
SetLastError(dwErr); } }
SP_STATUS RsaPublicKeyFromCert( PCERT_PUBLIC_KEY_INFO pPublicKeyInfo, BLOBHEADER *pBlob, PDWORD pcbBlob) { SP_STATUS pctRet;
if(!CryptDecodeObject(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB, pPublicKeyInfo->PublicKey.pbData, pPublicKeyInfo->PublicKey.cbData, 0, pBlob, pcbBlob)) { pctRet = GetLastError(); return SP_LOG_RESULT(pctRet); }
return PCT_ERR_OK; }
/*****************************************************************************/ SP_STATUS DssPublicKeyFromCert( PCERT_PUBLIC_KEY_INFO pPublicKeyInfo, BLOBHEADER *pBlob, PDWORD pcbBlob) { CRYPT_UINT_BLOB *pPublic = NULL; DWORD cbPublic; CERT_DSS_PARAMETERS *pParams = NULL; DWORD cbParams; DSSPUBKEY *pDssPubKey = NULL; DSSSEED *pSeed = NULL; PBYTE pbData = NULL; DWORD cbBlob; DWORD cbRequired; DWORD cbPadding; SP_STATUS pctRet;
//
// Estimate size of DSS public key blob.
//
if(!CryptDecodeObject(X509_ASN_ENCODING, X509_DSS_PUBLICKEY, pPublicKeyInfo->PublicKey.pbData, pPublicKeyInfo->PublicKey.cbData, 0, NULL, &cbPublic)) { pctRet = GetLastError(); return SP_LOG_RESULT(pctRet); }
if(!CryptDecodeObject(X509_ASN_ENCODING, X509_DSS_PARAMETERS, pPublicKeyInfo->Algorithm.Parameters.pbData, pPublicKeyInfo->Algorithm.Parameters.cbData, 0, NULL, &cbParams)) { pctRet = GetLastError(); return SP_LOG_RESULT(pctRet); }
cbBlob = sizeof(BLOBHEADER) + sizeof(DSSPUBKEY) + cbPublic + cbParams + sizeof(DSSSEED);
if(pBlob == NULL) { *pcbBlob = cbBlob; return PCT_ERR_OK; } if(*pcbBlob < cbBlob) { *pcbBlob = cbBlob; return SP_LOG_RESULT(PCT_INT_BUFF_TOO_SMALL); }
//
// Decode public key info.
//
pPublic = SPExternalAlloc(cbPublic + cbParams); if(pPublic == NULL) { return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY); } pParams = (CERT_DSS_PARAMETERS *)((PBYTE)pPublic + cbPublic);
if(!CryptDecodeObject(X509_ASN_ENCODING, X509_DSS_PUBLICKEY, pPublicKeyInfo->PublicKey.pbData, pPublicKeyInfo->PublicKey.cbData, 0, pPublic, &cbPublic)) { pctRet = SP_LOG_RESULT(GetLastError()); goto cleanup; }
if(!CryptDecodeObject(X509_ASN_ENCODING, X509_DSS_PARAMETERS, pPublicKeyInfo->Algorithm.Parameters.pbData, pPublicKeyInfo->Algorithm.Parameters.cbData, 0, pParams, &cbParams)) { pctRet = SP_LOG_RESULT(GetLastError()); goto cleanup; }
//
// Double check size of memory allocated for blob. The G and Y
// components may need to be padded out a little bit, but this
// should always be less than the overhead in the params structure.
// It doesn't hurt to make sure, though.
//
cbRequired = sizeof(BLOBHEADER) + sizeof(DSSPUBKEY) + pParams->p.cbData + pParams->q.cbData + max(pParams->p.cbData, pParams->g.cbData) + max(pParams->p.cbData, pPublic->cbData) + sizeof(DSSSEED);
if(cbBlob < cbRequired) { *pcbBlob = cbRequired; return SP_LOG_RESULT(PCT_INT_BUFF_TOO_SMALL); }
//
// Build PUBLICKEYBLOB
//
pBlob->bType = PUBLICKEYBLOB; pBlob->bVersion = CUR_BLOB_VERSION; pBlob->reserved = 0; pBlob->aiKeyAlg = CALG_DSS_SIGN;
pDssPubKey = (DSSPUBKEY *)(pBlob + 1); pDssPubKey->magic = MAGIC_DSS1; pDssPubKey->bitlen = pPublic->cbData * 8;
pbData = (PBYTE)(pDssPubKey + 1);
CopyMemory(pbData, pParams->p.pbData, pParams->p.cbData); pbData += pParams->p.cbData;
CopyMemory(pbData, pParams->q.pbData, pParams->q.cbData); pbData += pParams->q.cbData;
CopyMemory(pbData, pParams->g.pbData, pParams->g.cbData); pbData += pParams->g.cbData;
if(pParams->g.cbData < pParams->p.cbData) { cbPadding = pParams->p.cbData - pParams->g.cbData; ZeroMemory(pbData, cbPadding); pbData += cbPadding; }
CopyMemory(pbData, pPublic->pbData, pPublic->cbData); pbData += pPublic->cbData;
if(pPublic->cbData < pParams->p.cbData) { cbPadding = pParams->p.cbData - pPublic->cbData; ZeroMemory(pbData, cbPadding); pbData += cbPadding; }
pSeed = (DSSSEED *)pbData; pSeed->counter = 0xffffffff; ZeroMemory(pSeed->seed, sizeof(pSeed->seed)); pbData += sizeof(DSSSEED);
*pcbBlob = (DWORD)((PBYTE)pbData - (PBYTE)pBlob);
pctRet = PCT_ERR_OK;
cleanup:
if(pPublic) SPExternalFree(pPublic);
return pctRet; }
#define my_isdigit(ch) ((ch >= '0') && (ch <= '9'))
//+-------------------------------------------------------------------------
// Convert the ascii string ("1.2.9999") to Asn1's Object Identifier
// represented as an array of unsigned longs.
//
// Returns TRUE for a successful conversion.
//--------------------------------------------------------------------------
BOOL WINAPI OIDFromString( IN LPCSTR pszObjId, IN OUT unsigned short *pCount, OUT unsigned long rgulValue[] ) { BOOL fResult = TRUE; unsigned short c = 0; LPSTR psz = (LPSTR) pszObjId; if (psz) { unsigned short cMax = *pCount; unsigned long *pul = rgulValue; while (*psz != '\0' && c++ < cMax) { *pul = 0; while (my_isdigit(*psz)) { *pul = ((*pul) * 10) + (*psz++) - '0'; } pul++; if (*psz != '.') break; psz++; } if (*psz != '\0') fResult = FALSE; } *pCount = c; return fResult; }
BOOL WINAPI Asn1PrivateKeyInfoEncode( IN DWORD dwCertEncodingType, IN LPCSTR lpszStructType, IN BLOBHEADER * pKey, OUT BYTE *pbEncoded, IN OUT DWORD *pcbEncoded ) { PrivateKeyInfo KeyInfo; BOOL fRet;
UNREFERENCED_PARAMETER(dwCertEncodingType); UNREFERENCED_PARAMETER(lpszStructType);
// First encode the private key data, depending on
// the algorithm.
switch(pKey->aiKeyAlg) { case CALG_RSA_SIGN: case CALG_RSA_KEYX: { RSAPUBKEY *pRsaPub = (RSAPUBKEY *)(pKey+1); RSAPrivateKey RsaPrivate; PBYTE pbRsaBlob, pbRsaBlobSav; PBYTE pbDataBlob = NULL, pbDataBlobSav; DWORD dwDataBlob = 0;
// Covert the RSA key into the RSAPrivateKey structure
RsaPrivate.version = 0; dwDataBlob = (9 * (pRsaPub->bitlen/16)) + 7 ; pbDataBlobSav = pbDataBlob = SPExternalAlloc(dwDataBlob); if(pbDataBlob == NULL) { return FALSE; }
//Copy Modulus
*pbDataBlob = 0; pbRsaBlobSav = pbRsaBlob = (PBYTE)(pRsaPub+1); CopyMemory(pbDataBlob+1, pbRsaBlob, pRsaPub->bitlen/8); PkiAsn1ReverseBytes(pbDataBlob + 1, pRsaPub->bitlen/8);
RsaPrivate.modulus.value = pbDataBlob; RsaPrivate.modulus.length = (pRsaPub->bitlen/8) + 1; pbDataBlob += (pRsaPub->bitlen/8) + 1; pbRsaBlob += (pRsaPub->bitlen/8);
RsaPrivate.publicExponent = pRsaPub->pubexp;
//Copy Prime1
*pbDataBlob = 0; CopyMemory(pbDataBlob+1, pbRsaBlob, pRsaPub->bitlen/16); PkiAsn1ReverseBytes(pbDataBlob + 1, pRsaPub->bitlen/16);
RsaPrivate.prime1.value = pbDataBlob; RsaPrivate.prime1.length = (pRsaPub->bitlen/16) + 1; pbDataBlob += (pRsaPub->bitlen/16) + 1; pbRsaBlob += (pRsaPub->bitlen/16);
//Copy Prime2
*pbDataBlob = 0; CopyMemory(pbDataBlob+1, pbRsaBlob, pRsaPub->bitlen/16); PkiAsn1ReverseBytes(pbDataBlob + 1, pRsaPub->bitlen/16);
RsaPrivate.prime2.value = pbDataBlob; RsaPrivate.prime2.length = (pRsaPub->bitlen/16) + 1; pbDataBlob += (pRsaPub->bitlen/16) + 1; pbRsaBlob += (pRsaPub->bitlen/16);
//Copy exponent1
*pbDataBlob = 0; CopyMemory(pbDataBlob+1, pbRsaBlob, pRsaPub->bitlen/16); PkiAsn1ReverseBytes(pbDataBlob + 1, pRsaPub->bitlen/16);
RsaPrivate.exponent1.value = pbDataBlob; RsaPrivate.exponent1.length = (pRsaPub->bitlen/16) + 1; pbDataBlob += (pRsaPub->bitlen/16) + 1; pbRsaBlob += (pRsaPub->bitlen/16);
//Copy exponent2
*pbDataBlob = 0; CopyMemory(pbDataBlob+1, pbRsaBlob, pRsaPub->bitlen/16); PkiAsn1ReverseBytes(pbDataBlob + 1, pRsaPub->bitlen/16);
RsaPrivate.exponent2.value = pbDataBlob; RsaPrivate.exponent2.length = (pRsaPub->bitlen/16) + 1; pbDataBlob += (pRsaPub->bitlen/16) + 1; pbRsaBlob += (pRsaPub->bitlen/16);
//Copy coefficient
*pbDataBlob = 0; CopyMemory(pbDataBlob+1, pbRsaBlob, pRsaPub->bitlen/16); PkiAsn1ReverseBytes(pbDataBlob + 1, pRsaPub->bitlen/16);
RsaPrivate.coefficient.value = pbDataBlob; RsaPrivate.coefficient.length = (pRsaPub->bitlen/16) + 1; pbDataBlob += (pRsaPub->bitlen/16) + 1; pbRsaBlob += (pRsaPub->bitlen/16);
//Copy privateExponent
*pbDataBlob = 0; CopyMemory(pbDataBlob+1, pbRsaBlob, pRsaPub->bitlen/8); PkiAsn1ReverseBytes(pbDataBlob + 1, pRsaPub->bitlen/8);
RsaPrivate.privateExponent.value = pbDataBlob; RsaPrivate.privateExponent.length = (pRsaPub->bitlen/8) + 1; pbDataBlob += (pRsaPub->bitlen/8) + 1; pbRsaBlob += (pRsaPub->bitlen/8);
fRet = Asn1InfoEncodeAndAlloc(RSAPrivateKey_PDU, &RsaPrivate, &KeyInfo.privateKey.value, &KeyInfo.privateKey.length); SPExternalFree(pbDataBlobSav); if(!fRet) { return FALSE; } KeyInfo.privateKeyAlgorithm.bit_mask = 0; KeyInfo.privateKeyAlgorithm.algorithm.count =sizeof(KeyInfo.privateKeyAlgorithm.algorithm.value)/sizeof(KeyInfo.privateKeyAlgorithm.algorithm.value[0]);
fRet = OIDFromString( szOID_RSA_RSA, &KeyInfo.privateKeyAlgorithm.algorithm.count, KeyInfo.privateKeyAlgorithm.algorithm.value); if(!fRet) { SPExternalFree(KeyInfo.privateKey.value); return FALSE; }
break; }
default: return FALSE; }
// Set up the KeyInfo struct
KeyInfo.bit_mask = 0; KeyInfo.version = 0;
fRet = Asn1InfoEncode( PrivateKeyInfo_PDU, &KeyInfo, pbEncoded, pcbEncoded );
SPExternalFree(KeyInfo.privateKey.value); return fRet; }
BOOL WINAPI Asn1PrivateKeyFileEncode( IN DWORD dwCertEncodingType, IN LPCSTR lpszStructType, IN PPRIVATE_KEY_FILE_ENCODE pKey, OUT BYTE *pbEncoded, IN OUT DWORD *pcbEncoded ) {
PrivateKeyFile File; BOOL fRet;
UNREFERENCED_PARAMETER(dwCertEncodingType); UNREFERENCED_PARAMETER(lpszStructType);
File.privateKey.privateKey.value = pKey->EncryptedBlob.pbData; File.privateKey.privateKey.length = pKey->EncryptedBlob.cbData;
File.privateKey.privateKeyAlgorithm.bit_mask = 0; File.privateKey.privateKeyAlgorithm.algorithm.count = sizeof(File.privateKey.privateKeyAlgorithm.algorithm.value)/sizeof(File.privateKey.privateKeyAlgorithm.algorithm.value[0]);
OIDFromString( pKey->Alg.pszObjId, &File.privateKey.privateKeyAlgorithm.algorithm.count, File.privateKey.privateKeyAlgorithm.algorithm.value);
File.name.value = (ASN1octet_t *)PRIVATE_KEY_TAG; File.name.length = lstrlen(PRIVATE_KEY_TAG);
fRet = Asn1InfoEncode( PrivateKeyFile_PDU, &File, pbEncoded, pcbEncoded );
return fRet;
}
BOOL WINAPI Asn1PrivateKeyInfoDecode( IN DWORD dwCertEncodingType, IN LPCSTR lpszStructType, IN const BYTE *pbEncoded, IN DWORD cbEncoded, IN DWORD dwFlags, OUT BLOBHEADER *pKey, IN OUT DWORD *pcbKey )
{ PrivateKeyInfo *pKeyInfo = NULL; DWORD cbKey; DWORD cbMod;
BOOL fResult = FALSE;
UNREFERENCED_PARAMETER(dwCertEncodingType); UNREFERENCED_PARAMETER(lpszStructType); UNREFERENCED_PARAMETER(dwFlags);
// Now crack the key info
fResult = Asn1InfoDecodeAndAlloc(PrivateKeyInfo_PDU, pbEncoded, cbEncoded, (void **)&pKeyInfo); if(!fResult) { return FALSE; }
fResult = FALSE; do { USHORT cbOID; DWORD psOID[16];
cbOID = sizeof(psOID)/sizeof(psOID[0]);
OIDFromString( szOID_RSA_RSA, &cbOID, psOID);
if((cbOID == pKeyInfo->privateKeyAlgorithm.algorithm.count) && (memcmp(pKeyInfo->privateKeyAlgorithm.algorithm.value, psOID, cbOID*sizeof(psOID[0]))==0)) { RSAPUBKEY * pRsaPub; RSAPrivateKey * pRsaPrivate = NULL; PBYTE pbCurrent; RSAPrivateKey RsaPrivate;
fResult = Asn1InfoDecodeAndAlloc(RSAPrivateKey_PDU, pKeyInfo->privateKey.value, pKeyInfo->privateKey.length, (void **)&pRsaPrivate); if(!fResult) { break; }
RsaPrivate = *pRsaPrivate;
// We successfully decrypted an RSA Private Key,
// so now turn it into a pRsaPub;
// Make some adjustmenst to the lengths of things if we have leading zeros
if(RsaPrivate.modulus.length && (0 == *(PBYTE)RsaPrivate.modulus.value)) { RsaPrivate.modulus.value++; RsaPrivate.modulus.length--; } if(RsaPrivate.prime1.length && (0 == *(PBYTE)RsaPrivate.prime1.value)) { RsaPrivate.prime1.value++; RsaPrivate.prime1.length--; } if(RsaPrivate.prime2.length && (0 == *(PBYTE)RsaPrivate.prime2.value)) { RsaPrivate.prime2.value++; RsaPrivate.prime2.length--; }
if(RsaPrivate.exponent1.length && (0 == *(PBYTE)RsaPrivate.exponent1.value)) { RsaPrivate.exponent1.value++; RsaPrivate.exponent1.length--; } if(RsaPrivate.exponent2.length && (0 == *(PBYTE)RsaPrivate.exponent2.value)) { RsaPrivate.exponent2.value++; RsaPrivate.exponent2.length--; }
if(RsaPrivate.coefficient.length && (0 == *(PBYTE)RsaPrivate.coefficient.value)) { RsaPrivate.coefficient.value++; RsaPrivate.coefficient.length--; } if(RsaPrivate.privateExponent.length && (0 == *(PBYTE)RsaPrivate.privateExponent.value)) { RsaPrivate.privateExponent.value++; RsaPrivate.privateExponent.length--; }
cbMod = (RsaPrivate.modulus.length + sizeof(DWORD) - 1) & ~(sizeof(DWORD)-1); cbKey = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + (cbMod*9)/2; if(pKey == NULL) { *pcbKey = cbKey; fResult = TRUE; Asn1InfoFree(RSAPrivateKey_PDU, pRsaPrivate); break; }
// we're actually unpacking this key.
if(*pcbKey < cbKey) { fResult = FALSE; Asn1InfoFree(RSAPrivateKey_PDU, pRsaPrivate); break; }
pKey->bType = PRIVATEKEYBLOB; pKey->bVersion = 2; pKey->reserved = 0; pKey->aiKeyAlg = CALG_RSA_KEYX;
pRsaPub = (RSAPUBKEY *)(pKey+1); pRsaPub->magic = ((DWORD)'R'+((DWORD)'S'<<8)+((DWORD)'A'<<16)+((DWORD)'2'<<24)); pRsaPub->bitlen = cbMod*8; pRsaPub->pubexp = RsaPrivate.publicExponent; pbCurrent = (PBYTE)(pRsaPub + 1); ReverseMemCopy(pbCurrent, RsaPrivate.modulus.value, RsaPrivate.modulus.length); pbCurrent += cbMod;
ReverseMemCopy(pbCurrent, RsaPrivate.prime1.value, RsaPrivate.prime1.length); pbCurrent += cbMod/2;
ReverseMemCopy(pbCurrent, RsaPrivate.prime2.value, RsaPrivate.prime2.length); pbCurrent += cbMod/2;
ReverseMemCopy(pbCurrent, RsaPrivate.exponent1.value, RsaPrivate.exponent1.length); pbCurrent += cbMod/2;
ReverseMemCopy(pbCurrent, RsaPrivate.exponent2.value, RsaPrivate.exponent2.length); pbCurrent += cbMod/2;
ReverseMemCopy(pbCurrent, RsaPrivate.coefficient.value, RsaPrivate.coefficient.length); pbCurrent += cbMod/2;
ReverseMemCopy(pbCurrent, RsaPrivate.privateExponent.value, RsaPrivate.privateExponent.length); pbCurrent += cbMod; *pcbKey = cbKey; Asn1InfoFree(RSAPrivateKey_PDU, pRsaPrivate);
}
}while(FALSE);
Asn1InfoFree(PrivateKeyInfo_PDU, pKeyInfo); return fResult; }
BOOL WINAPI Asn1PrivateKeyFileDecode( IN DWORD dwCertEncodingType, IN LPCSTR lpszStructType, IN const BYTE *pbEncoded, IN DWORD cbEncoded, IN DWORD dwFlags, OUT PPRIVATE_KEY_FILE_ENCODE pKey, IN OUT DWORD *pcbKey )
{ PrivateKeyFile *pFile = NULL; DWORD cbPrivateKeyStruct;
BOOL fResult = FALSE;
UNREFERENCED_PARAMETER(dwCertEncodingType); UNREFERENCED_PARAMETER(lpszStructType); UNREFERENCED_PARAMETER(dwFlags);
// Decode the file
if(!Asn1InfoDecodeAndAlloc(PrivateKeyFile_PDU, pbEncoded, cbEncoded, (void **)&pFile)) { return FALSE; }
cbPrivateKeyStruct = pFile->privateKey.privateKey.length + sizeof(PRIVATE_KEY_FILE_ENCODE); if(pKey == NULL) { *pcbKey = cbPrivateKeyStruct; fResult = TRUE; } else { if(*pcbKey < cbPrivateKeyStruct) { fResult = FALSE; } else { pKey->EncryptedBlob.cbData = pFile->privateKey.privateKey.length; pKey->EncryptedBlob.pbData = (PBYTE)(pKey + 1); pKey->EncryptedBlob.cUnusedBits = 0; CopyMemory(pKey->EncryptedBlob.pbData, pFile->privateKey.privateKey.value, pKey->EncryptedBlob.cbData); fResult = TRUE; } }
Asn1InfoFree(PrivateKeyFile_PDU, pFile); return fResult;
}
BOOL WINAPI Asn1RSAPublicEncode( IN DWORD dwCertEncodingType, IN LPCSTR lpszStructType, IN PUBLICKEYSTRUC *pbKeyStruc, OUT BYTE *pbEncoded, IN OUT DWORD *pcbEncoded ) { UNREFERENCED_PARAMETER(lpszStructType);
return CryptEncodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB, pbKeyStruc, pbEncoded, pcbEncoded); }
static void Asn1X509GetObjId( IN ObjectID *pAsn1, IN DWORD dwFlags, OUT LPSTR *ppszObjId, IN OUT BYTE **ppbExtra, IN OUT LONG *plRemainExtra ) { LONG lRemainExtra = *plRemainExtra; BYTE *pbExtra = *ppbExtra; LONG lAlignExtra; DWORD cbObjId;
UNREFERENCED_PARAMETER(dwFlags);
cbObjId = lRemainExtra > 0 ? lRemainExtra : 0; PkiAsn1FromObjectIdentifier( pAsn1->count, pAsn1->value, (LPSTR) pbExtra, &cbObjId );
lAlignExtra = INFO_LEN_ALIGN(cbObjId); lRemainExtra -= lAlignExtra; if (lRemainExtra >= 0) { if(cbObjId) { *ppszObjId = (LPSTR) pbExtra; } else *ppszObjId = NULL; pbExtra += lAlignExtra; }
*plRemainExtra = lRemainExtra; *ppbExtra = pbExtra; }
static void Asn1X509GetCtlUsage( IN EnhancedKeyUsage *pAsn1, IN DWORD dwFlags, OUT PCTL_USAGE pUsage, IN OUT BYTE **ppbExtra, IN OUT LONG *plRemainExtra ) { LONG lRemainExtra = *plRemainExtra; BYTE *pbExtra = *ppbExtra; LONG lAlignExtra;
DWORD cId; UsageIdentifier *pAsn1Id; LPSTR *ppszId;
cId = pAsn1->count; lAlignExtra = INFO_LEN_ALIGN(cId * sizeof(LPSTR)); lRemainExtra -= lAlignExtra; if (lRemainExtra >= 0) { pUsage->cUsageIdentifier = cId; ppszId = (LPSTR *) pbExtra; pUsage->rgpszUsageIdentifier = ppszId; pbExtra += lAlignExtra; } else ppszId = NULL;
pAsn1Id = pAsn1->value; for ( ; cId > 0; cId--, pAsn1Id++, ppszId++) Asn1X509GetObjId(pAsn1Id, dwFlags, ppszId, &pbExtra, &lRemainExtra);
*plRemainExtra = lRemainExtra; *ppbExtra = pbExtra; }
//+-------------------------------------------------------------------------
// CTL Usage (Enhanced Key Usage) Decode (Asn1 X509)
//--------------------------------------------------------------------------
static BOOL WINAPI Asn1X509CtlUsageDecode( IN DWORD dwCertEncodingType, IN LPCSTR lpszStructType, IN const BYTE *pbEncoded, IN DWORD cbEncoded, IN DWORD dwFlags, OUT PCTL_USAGE pInfo, IN OUT DWORD *pcbInfo ) { BOOL fResult; EnhancedKeyUsage *pAsn1Info = NULL; BYTE *pbExtra; LONG lRemainExtra;
UNREFERENCED_PARAMETER(dwCertEncodingType); UNREFERENCED_PARAMETER(lpszStructType);
if (pInfo == NULL) *pcbInfo = 0;
if (!Asn1InfoDecodeAndAlloc( EnhancedKeyUsage_PDU, pbEncoded, cbEncoded, (void **) &pAsn1Info)) goto ErrorReturn;
// for lRemainExtra < 0, LENGTH_ONLY calculation
lRemainExtra = (LONG) *pcbInfo - sizeof(CTL_USAGE); if (lRemainExtra < 0) { pbExtra = NULL; } else pbExtra = (BYTE *) pInfo + sizeof(CTL_USAGE);
Asn1X509GetCtlUsage(pAsn1Info, dwFlags, pInfo, &pbExtra, &lRemainExtra);
if (lRemainExtra >= 0) *pcbInfo = *pcbInfo - (DWORD) lRemainExtra; else { *pcbInfo = *pcbInfo + (DWORD) -lRemainExtra; if (pInfo) goto LengthError; }
fResult = TRUE; goto CommonReturn;
LengthError: SetLastError((DWORD) ERROR_MORE_DATA); fResult = FALSE; goto CommonReturn; ErrorReturn: *pcbInfo = 0; fResult = FALSE; CommonReturn: Asn1InfoFree(EnhancedKeyUsage_PDU, pAsn1Info); return fResult; }
|