/*----------------------------------------------------------------------------- * Copyright (C) Microsoft Corporation, 1995 - 1996. * All rights reserved. * * Owner : ramas * Date : 5/03/97 * description : Main Crypto functions for TLS1 *----------------------------------------------------------------------------*/ #include #define DEB_TLS1KEYS 0x01000000 //+--------------------------------------------------------------------------- // // Function: Tls1MakeWriteSessionKeys // // Synopsis: // // Arguments: [pContext] -- Schannel context. // // History: 10-10-97 jbanes Added server-side CAPI integration. // // Notes: // //---------------------------------------------------------------------------- SP_STATUS Tls1MakeWriteSessionKeys(PSPContext pContext) { BOOL fClient; // Determine if we're a client or a server. fClient = (0 != (pContext->RipeZombie->fProtocol & SP_PROT_TLS1_CLIENT)); if(pContext->hWriteKey) { if(!SchCryptDestroyKey(pContext->hWriteKey, pContext->RipeZombie->dwCapiFlags)) { SP_LOG_RESULT(GetLastError()); } } pContext->hWriteProv = pContext->RipeZombie->hMasterProv; pContext->hWriteKey = pContext->hPendingWriteKey; pContext->hPendingWriteKey = 0; if(pContext->hWriteMAC) { if(!SchCryptDestroyKey(pContext->hWriteMAC, pContext->RipeZombie->dwCapiFlags)) { SP_LOG_RESULT(GetLastError()); } } pContext->hWriteMAC = pContext->hPendingWriteMAC; pContext->hPendingWriteMAC = 0; return PCT_ERR_OK; } //+--------------------------------------------------------------------------- // // Function: Tls1MakeReadSessionKeys // // Synopsis: // // Arguments: [pContext] -- Schannel context. // // History: 10-10-97 jbanes Added server-side CAPI integration. // // Notes: // //---------------------------------------------------------------------------- SP_STATUS Tls1MakeReadSessionKeys(PSPContext pContext) { BOOL fClient; // Determine if we're a client or a server. fClient = (0 != (pContext->RipeZombie->fProtocol & SP_PROT_TLS1_CLIENT)); if(pContext->hReadKey) { if(!SchCryptDestroyKey(pContext->hReadKey, pContext->RipeZombie->dwCapiFlags)) { SP_LOG_RESULT(GetLastError()); } } pContext->hReadProv = pContext->RipeZombie->hMasterProv; pContext->hReadKey = pContext->hPendingReadKey; pContext->hPendingReadKey = 0; if(pContext->hReadMAC) { if(!SchCryptDestroyKey(pContext->hReadMAC, pContext->RipeZombie->dwCapiFlags)) { SP_LOG_RESULT(GetLastError()); } } pContext->hReadMAC = pContext->hPendingReadMAC; pContext->hPendingReadMAC = 0; return PCT_ERR_OK; } //+--------------------------------------------------------------------------- // // Function: Tls1ComputeMac // // Synopsis: // // Arguments: [pContext] -- // [hSecret] -- // [dwSequence] -- // [pClean] -- // [cContentType] -- // [pbMac] -- // [cbMac] // // History: 10-03-97 jbanes Created. // // Notes: // //---------------------------------------------------------------------------- SP_STATUS Tls1ComputeMac( PSPContext pContext, BOOL fReadMac, PSPBuffer pClean, CHAR cContentType, PBYTE pbMac, DWORD cbMac) { HCRYPTHASH hHash; HMAC_INFO HmacInfo; PBYTE pbData; DWORD cbData; DWORD cbDataReverse; DWORD dwReverseSequence; UCHAR rgbData1[15]; PUCHAR pbData1; DWORD cbData1; HCRYPTPROV hProv; HCRYPTKEY hSecret; DWORD dwSequence; DWORD dwCapiFlags; PHashInfo pHashInfo; pbData = pClean->pvBuffer; cbData = pClean->cbData; if(cbData & 0xFFFF0000) { return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR); } if(fReadMac) { hProv = pContext->hReadProv; hSecret = pContext->hReadMAC; dwSequence = pContext->ReadCounter; pHashInfo = pContext->pReadHashInfo; } else { hProv = pContext->hWriteProv; hSecret = pContext->hWriteMAC; dwSequence = pContext->WriteCounter; pHashInfo = pContext->pWriteHashInfo; } dwCapiFlags = pContext->RipeZombie->dwCapiFlags; if(!hProv) { return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR); } // Create hash object. if(!SchCryptCreateHash(hProv, CALG_HMAC, hSecret, 0, &hHash, dwCapiFlags)) { SP_LOG_RESULT(GetLastError()); return PCT_INT_INTERNAL_ERROR; } // Specify hash algorithm. ZeroMemory(&HmacInfo, sizeof(HMAC_INFO)); HmacInfo.HashAlgid = pHashInfo->aiHash; if(!SchCryptSetHashParam(hHash, HP_HMAC_INFO, (PBYTE)&HmacInfo, 0, dwCapiFlags)) { SP_LOG_RESULT(GetLastError()); SchCryptDestroyHash(hHash, dwCapiFlags); return PCT_INT_INTERNAL_ERROR; } // Build data to be hashed. cbData1 = 2 * sizeof(DWORD) + // sequence number (64-bit) 1 + // content type 2 + // protocol version 2; // message length SP_ASSERT(cbData1 <= sizeof(rgbData1)); pbData1 = rgbData1; ZeroMemory(pbData1, sizeof(DWORD)); pbData1 += sizeof(DWORD); dwReverseSequence = htonl(dwSequence); CopyMemory(pbData1, &dwReverseSequence, sizeof(DWORD)); pbData1 += sizeof(DWORD); *pbData1++ = cContentType; *pbData1++ = SSL3_CLIENT_VERSION_MSB; *pbData1++ = TLS1_CLIENT_VERSION_LSB; cbDataReverse = (cbData >> 8) | (cbData << 8); CopyMemory(pbData1, &cbDataReverse, 2); // Hash data. if(!SchCryptHashData(hHash, rgbData1, cbData1, 0, dwCapiFlags)) { SP_LOG_RESULT(GetLastError()); SchCryptDestroyHash(hHash, dwCapiFlags); return PCT_INT_INTERNAL_ERROR; } if(!SchCryptHashData(hHash, pbData, cbData, 0, dwCapiFlags)) { SP_LOG_RESULT(GetLastError()); SchCryptDestroyHash(hHash, dwCapiFlags); return PCT_INT_INTERNAL_ERROR; } // Get hash value. if(!SchCryptGetHashParam(hHash, HP_HASHVAL, pbMac, &cbMac, 0, dwCapiFlags)) { SP_LOG_RESULT(GetLastError()); SchCryptDestroyHash(hHash, dwCapiFlags); return PCT_INT_INTERNAL_ERROR; } SP_ASSERT(cbMac == pHashInfo->cbCheckSum); #if DBG DebugLog((DEB_TLS1KEYS, " TLS1 MAC Output")); DBG_HEX_STRING(DEB_TLS1KEYS, pbMac, cbMac); #endif SchCryptDestroyHash(hHash, dwCapiFlags); return PCT_ERR_OK; } #define HMAC_K_PADSIZE 64 BOOL MyPrimitiveSHA( PBYTE pbData, DWORD cbData, BYTE rgbHash[A_SHA_DIGEST_LEN]) { BOOL fRet = FALSE; A_SHA_CTX sSHAHash; A_SHAInit(&sSHAHash); A_SHAUpdate(&sSHAHash, (BYTE *) pbData, cbData); A_SHAFinal(&sSHAHash, rgbHash); fRet = TRUE; //Ret: return fRet; } BOOL MyPrimitiveMD5( PBYTE pbData, DWORD cbData, BYTE rgbHash[MD5DIGESTLEN]) { BOOL fRet = FALSE; MD5_CTX sMD5Hash; MD5Init(&sMD5Hash); MD5Update(&sMD5Hash, (BYTE *) pbData, cbData); MD5Final(&sMD5Hash); memcpy(rgbHash, sMD5Hash.digest, MD5DIGESTLEN); fRet = TRUE; //Ret: return fRet; } BOOL MyPrimitiveHMACParam( PBYTE pbKeyMaterial, DWORD cbKeyMaterial, PBYTE pbData, DWORD cbData, ALG_ID Algid, BYTE rgbHMAC[A_SHA_DIGEST_LEN]) { BYTE rgbFirstHash[A_SHA_DIGEST_LEN]; BYTE rgbHMACTmp[HMAC_K_PADSIZE+A_SHA_DIGEST_LEN]; BOOL fRet = FALSE; BYTE rgbKipad[HMAC_K_PADSIZE]; BYTE rgbKopad[HMAC_K_PADSIZE]; DWORD dwBlock; // truncate if (cbKeyMaterial > HMAC_K_PADSIZE) cbKeyMaterial = HMAC_K_PADSIZE; ZeroMemory(rgbKipad, HMAC_K_PADSIZE); CopyMemory(rgbKipad, pbKeyMaterial, cbKeyMaterial); ZeroMemory(rgbKopad, HMAC_K_PADSIZE); CopyMemory(rgbKopad, pbKeyMaterial, cbKeyMaterial); // Kipad, Kopad are padded sMacKey. Now XOR across... for(dwBlock=0; dwBlock