00001
00009 #include "CAPIUtils.h"
00010 #include "ToolkitUtils.h"
00011 #include "PKIFException.h"
00012 #include "PKIFCryptoErrors.h"
00013 #include "components.h"
00021 void CAC_API ReverseBytes(
00023 unsigned char* buf,
00025 int bufLen)
00026 {
00027 unsigned char tmp;
00028 int top = bufLen - 1;
00029 for(int bottom = 0; bottom < top; ++bottom, --top)
00030 {
00031 tmp = buf[top];
00032 buf[top] = buf[bottom];
00033 buf[bottom] = tmp;
00034 }
00035 }
00036
00037
00038
00039
00040
00041
00053 BOOL CreatePrivateExponentOneKey(
00055 LPTSTR szProvider,
00057 DWORD dwProvType,
00059 LPTSTR szContainer,
00061 DWORD dwKeySpec,
00063 HCRYPTPROV *hProv,
00065 HCRYPTKEY *hPrivateKey)
00066 {
00067 BOOL succ = FALSE;
00068 BOOL fReturn = FALSE;
00069 BOOL fResult;
00070 unsigned int n;
00071 LPBYTE keyblob = NULL;
00072 DWORD dwkeyblob;
00073 DWORD dwBitLen;
00074 BYTE *ptr;
00075
00076 __try
00077 {
00078 *hProv = 0;
00079 *hPrivateKey = 0;
00080
00081 if ((dwKeySpec != AT_KEYEXCHANGE) && (dwKeySpec != AT_SIGNATURE)) __leave;
00082
00083
00084 fResult = CryptAcquireContext(hProv, szContainer, szProvider,
00085 dwProvType, CRYPT_NEWKEYSET);
00086 if (!fResult)
00087 {
00088
00089 if (GetLastError() == NTE_EXISTS)
00090 {
00091
00092 fResult = CryptAcquireContext(hProv, szContainer, szProvider, dwProvType, CRYPT_DELETEKEYSET);
00093 if (!fResult)
00094 {
00095
00096 __leave;
00097 }
00098 fResult = CryptAcquireContext(hProv, szContainer, szProvider,
00099 dwProvType, CRYPT_NEWKEYSET);
00100 if (!fResult)
00101 {
00102
00103 __leave;
00104 }
00105 }
00106 else
00107 {
00108
00109 __leave;
00110 }
00111 }
00112
00113
00114 fResult = CryptGenKey(*hProv, dwKeySpec, CRYPT_EXPORTABLE, hPrivateKey);
00115 if (!fResult) __leave;
00116
00117
00118
00119 fResult = CryptExportKey(*hPrivateKey, 0, PRIVATEKEYBLOB, 0, NULL, &dwkeyblob);
00120 if (!fResult) __leave;
00121
00122
00123 keyblob = new unsigned char[dwkeyblob];
00124 if (!keyblob) __leave;
00125
00126 fResult = CryptExportKey(*hPrivateKey, 0, PRIVATEKEYBLOB, 0, keyblob, &dwkeyblob);
00127 if (!fResult) __leave;
00128
00129
00130 succ = CryptDestroyKey(*hPrivateKey);
00131 *hPrivateKey = 0;
00132
00133
00134 memcpy(&dwBitLen, &keyblob[12], 4);
00135
00136
00137
00138
00139
00140 ptr = &keyblob[16];
00141 for (n = 0; n < 4; n++)
00142 {
00143 if (n == 0) ptr[n] = 1;
00144 else ptr[n] = 0;
00145 }
00146
00147
00148 ptr += 4;
00149
00150 ptr += (dwBitLen/8);
00151 ptr += (dwBitLen/16);
00152 ptr += (dwBitLen/16);
00153
00154
00155 for (n = 0; n < (dwBitLen/16); n++)
00156 {
00157 if (n == 0) ptr[n] = 1;
00158 else ptr[n] = 0;
00159 }
00160
00161
00162 ptr += (dwBitLen/16);
00163
00164
00165 for (n = 0; n < (dwBitLen/16); n++)
00166 {
00167 if (n == 0) ptr[n] = 1;
00168 else ptr[n] = 0;
00169 }
00170
00171
00172 ptr += (dwBitLen/16);
00173 ptr += (dwBitLen/16);
00174
00175
00176 for (n = 0; n < (dwBitLen/8); n++)
00177 {
00178 if (n == 0) ptr[n] = 1;
00179 else ptr[n] = 0;
00180 }
00181
00182
00183 if (!CryptImportKey(*hProv, keyblob, dwkeyblob, 0, 0, hPrivateKey))
00184 {
00185 __leave;
00186 }
00187
00188 fReturn = TRUE;
00189 }
00190 __finally
00191 {
00192
00193 if (keyblob)
00194 {
00195 delete[] keyblob;
00196 keyblob = NULL;
00197 }
00198
00199 if (!fReturn)
00200 {
00201 if (*hPrivateKey) CryptDestroyKey(*hPrivateKey);
00202 if (*hProv) CryptReleaseContext(*hProv, 0);
00203 }
00204 }
00205
00206 return fReturn;
00207 }
00219 BOOL ImportPlainSessionBlob(
00221 HCRYPTPROV hProv,
00223 HCRYPTKEY hPrivateKey,
00225 ALG_ID dwAlgId,
00227 LPBYTE pbKeyMaterial ,
00229 DWORD dwKeyMaterial ,
00231 HCRYPTKEY *hSessionKey)
00232 {
00233 BOOL succ = FALSE;
00234 BOOL fResult;
00235 BOOL fReturn = FALSE;
00236 BOOL fFound = FALSE;
00237 LPBYTE pbSessionBlob = NULL;
00238 DWORD dwSessionBlob, dwSize, n;
00239 DWORD dwPublicKeySize;
00240 DWORD dwProvSessionKeySize;
00241 ALG_ID dwPrivKeyAlg;
00242 LPBYTE pbPtr;
00243 DWORD dwFlags = CRYPT_FIRST;
00244 PROV_ENUMALGS_EX ProvEnum;
00245 HCRYPTKEY hTempKey = 0;
00246
00247 __try
00248 {
00249
00250
00251 do
00252 {
00253 dwSize = sizeof(ProvEnum);
00254 fResult = CryptGetProvParam(hProv, PP_ENUMALGS_EX, (LPBYTE)&ProvEnum,
00255 &dwSize, dwFlags);
00256 if (!fResult) break;
00257
00258 dwFlags = 0;
00259
00260 if (ProvEnum.aiAlgid == dwAlgId) fFound = TRUE;
00261
00262 } while (!fFound);
00263
00264 if (!fFound) __leave;
00265
00266
00267
00268
00269 fResult = CryptGenKey(hProv, dwAlgId, 0, &hTempKey);
00270 if (!fResult) __leave;
00271
00272 dwSize = sizeof(DWORD);
00273 fResult = CryptGetKeyParam(hTempKey, KP_KEYLEN, (LPBYTE)&dwProvSessionKeySize,
00274 &dwSize, 0);
00275 if (!fResult) __leave;
00276 succ = CryptDestroyKey(hTempKey);
00277 hTempKey = 0;
00278
00279
00280 if ((dwKeyMaterial * 8) > dwProvSessionKeySize) __leave;
00281
00282
00283 dwSize = sizeof(ALG_ID);
00284 fResult = CryptGetKeyParam(hPrivateKey, KP_ALGID, (LPBYTE)&dwPrivKeyAlg, &dwSize, 0);
00285 if (!fResult) __leave;
00286
00287
00288 dwSize = sizeof(DWORD);
00289 fResult = CryptGetKeyParam(hPrivateKey, KP_KEYLEN, (LPBYTE)&dwPublicKeySize, &dwSize, 0);
00290 if (!fResult) __leave;
00291
00292
00293 dwSessionBlob = (dwPublicKeySize/8) + sizeof(ALG_ID) + sizeof(BLOBHEADER);
00294
00295
00296
00297 pbSessionBlob = new unsigned char[dwSessionBlob];
00298 if (!pbSessionBlob) __leave;
00299
00300 memset(pbSessionBlob, 0, dwSessionBlob);
00301
00302 pbPtr = pbSessionBlob;
00303
00304
00305
00306 ((BLOBHEADER *)pbPtr)->bType = SIMPLEBLOB;
00307 ((BLOBHEADER *)pbPtr)->bVersion = 2;
00308 ((BLOBHEADER *)pbPtr)->reserved = 0;
00309 ((BLOBHEADER *)pbPtr)->aiKeyAlg = dwAlgId;
00310 pbPtr += sizeof(BLOBHEADER);
00311
00312
00313 *((DWORD *)pbPtr) = dwPrivKeyAlg;
00314 pbPtr += sizeof(ALG_ID);
00315
00316
00317 for (n = 0; n < dwKeyMaterial; n++)
00318 {
00319 pbPtr[n] = pbKeyMaterial[dwKeyMaterial-n-1];
00320 }
00321
00322
00323 dwSize = dwSessionBlob - (sizeof(ALG_ID) + sizeof(BLOBHEADER) + dwKeyMaterial + 3);
00324 pbPtr += (dwKeyMaterial+1);
00325
00326
00327
00328 fResult = CryptGenRandom(hProv, dwSize, pbPtr);
00329 if (!fResult) __leave;
00330
00331 for (n = 0; n < dwSize; n++)
00332 {
00333 if (pbPtr[n] == 0) pbPtr[n] = 1;
00334 }
00335
00336 pbSessionBlob[dwSessionBlob - 2] = 2;
00337
00338 fResult = CryptImportKey(hProv, pbSessionBlob , dwSessionBlob,
00339 hPrivateKey, CRYPT_EXPORTABLE, hSessionKey);
00340 if (!fResult) __leave;
00341
00342 fReturn = TRUE;
00343 }
00344 __finally
00345 {
00346 if (hTempKey) CryptDestroyKey(hTempKey);
00347
00348 if (pbSessionBlob) delete[] pbSessionBlob;
00349 }
00350
00351 return fReturn;
00352 }
00353
00354
00355
00363 bool CertHasKey(
00365 PCCERT_CONTEXT pPrevCertContent)
00366 {
00367 if(NULL == pPrevCertContent)
00368 return false;
00369
00370 DWORD dwPropId = 0;
00371 while(dwPropId = CertEnumCertificateContextProperties(
00372 pPrevCertContent,
00373 dwPropId))
00374
00375 {
00376 if(CERT_KEY_PROV_INFO_PROP_ID == dwPropId)
00377 return true;
00378 }
00379
00380 return false;
00381 }
00395 ALG_ID GetHashAlg(
00397 PKIFCRYPTO::HASH_ALG alg)
00398 {
00399 switch(alg)
00400 {
00401 case PKIFCRYPTO::SHA1:
00402 return CALG_SHA1;
00403 case PKIFCRYPTO::MD5:
00404 return CALG_MD5;
00405 default:
00406 throw CPKIFException(TOOLKIT_CRYPTO, CRYPTO_ALG_NOT_SUPPORTED, "Hashing algorithm not supported");
00407 }
00408 }
00409
00423 wchar_t* GetCNGHashAlg(
00425 PKIFCRYPTO::HASH_ALG alg)
00426 {
00427 switch(alg)
00428 {
00429 case PKIFCRYPTO::SHA1:
00430 return BCRYPT_SHA1_ALGORITHM;
00431 case PKIFCRYPTO::SHA256:
00432 return BCRYPT_SHA256_ALGORITHM;
00433 case PKIFCRYPTO::SHA384:
00434 return BCRYPT_SHA384_ALGORITHM;
00435 case PKIFCRYPTO::SHA512:
00436 return BCRYPT_SHA512_ALGORITHM;
00437 case PKIFCRYPTO::MD5:
00438 return BCRYPT_MD5_ALGORITHM;
00439 default:
00440 throw CPKIFException(TOOLKIT_CRYPTO, CRYPTO_ALG_NOT_SUPPORTED, "Hashing algorithm not supported");
00441 }
00442 }
00450 void StrToName(
00452 const char* dn,
00454 unsigned char** enc,
00456 DWORD* len)
00457 {
00458 int err = 0;
00459 const char* errstr = NULL;
00460
00461
00462 BOOL succ = CertStrToName(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, dn,
00463 CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, NULL, NULL, len, &errstr);
00464 if(!succ)
00465 {
00466 err = GetLastError();
00467 *len = 0;
00468 *enc = NULL;
00469 return;
00470 }
00471 *enc = new unsigned char[(*len) + 1];
00472 succ = CertStrToName(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, dn,
00473 CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, NULL, *enc, len, &errstr);
00474 if(!succ)
00475 {
00476 err = GetLastError();
00477 }
00478 }