283 lines
8.2 KiB
C
283 lines
8.2 KiB
C
/////////////////////////////////////////////////////////////////////////////
|
|
// FILE : swnt_pk.c //
|
|
// DESCRIPTION : //
|
|
// Software nametag public key management functions. These functions //
|
|
// isolate the peculiarities of public key management without a token //
|
|
// //
|
|
// AUTHOR : //
|
|
// HISTORY : //
|
|
// Jan 25 1995 larrys Changed from Nametag //
|
|
// Mar 01 1995 terences Fixed key pair handle creation //
|
|
// Mar 08 1995 larrys Fixed warning //
|
|
// Mar 23 1995 larrys Added variable key length //
|
|
// Apr 17 1995 larrys Added 1024 key gen //
|
|
// Apr 19 1995 larrys Changed CRYPT_EXCH_PUB to AT_KEYEXCHANGE //
|
|
// Aug 16 1995 larrys Removed exchange key stuff //
|
|
// Sep 12 1995 larrys Removed 2 DWORDS from exported keys //
|
|
// Sep 28 1995 larrys Changed format of PKCS //
|
|
// Oct 04 1995 larrys Fixed problem with PKCS format //
|
|
// Oct 27 1995 rajeshk RandSeed Stuff added hUID to PKCS2Encrypt //
|
|
// Nov 3 1995 larrys Merge for NT checkin //
|
|
// Dec 11 1995 larrys Added check for error return from RSA routine //
|
|
// May 15 1996 larrys Changed NTE_NO_MEMORY to ERROR_NOT_ENOUGHT... //
|
|
// //
|
|
// Copyright (C) 1993 Microsoft Corporation All Rights Reserved //
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "precomp.h"
|
|
#include "swnt_pk.h"
|
|
|
|
BOOL PKCS2Encrypt(HCRYPTPROV hUID,
|
|
BSAFE_PUB_KEY *pKey,
|
|
BYTE *InBuf,
|
|
DWORD InBufLen,
|
|
BYTE *OutBuf)
|
|
{
|
|
DWORD i;
|
|
BYTE *pScratch;
|
|
BYTE *pScratch2;
|
|
BYTE *pLocal;
|
|
DWORD temp;
|
|
DWORD z;
|
|
|
|
if ((pScratch = (BYTE *)_nt_malloc(pKey->keylen)) == NULL)
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
if ((pScratch2 = (BYTE *)_nt_malloc(pKey->keylen)) == NULL)
|
|
{
|
|
_nt_free(pScratch, pKey->keylen);
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
memset(pScratch, 0, pKey->keylen);
|
|
|
|
pScratch[pKey->datalen - 1] = PKCS_BLOCKTYPE_2;
|
|
GenRandom(hUID, pScratch+InBufLen+1, (pKey->datalen)-InBufLen-2);
|
|
|
|
pLocal = pScratch + InBufLen + 1;
|
|
|
|
// Need to insure that none of the padding bytes are zero.
|
|
temp = pKey->datalen - InBufLen - 2;
|
|
while (temp)
|
|
{
|
|
if (*pLocal == 0)
|
|
{
|
|
GenRandom(hUID, pLocal , 1);
|
|
}
|
|
else
|
|
{
|
|
pLocal++;
|
|
temp--;
|
|
}
|
|
}
|
|
|
|
// Reverse the session key bytes
|
|
for (z = 0; z < InBufLen; ++z) pScratch[z] = InBuf[InBufLen - z - 1];
|
|
|
|
if (BSafeEncPublic(pKey, pScratch, pScratch2) == FALSE)
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
_nt_free(pScratch, pKey->keylen);
|
|
_nt_free(pScratch2, pKey->keylen);
|
|
return NTF_FAILED;
|
|
}
|
|
|
|
memcpy(OutBuf, pScratch2, pKey->keylen - 2*sizeof(DWORD));
|
|
|
|
memnuke(pScratch, pKey->keylen);
|
|
_nt_free(pScratch, pKey->keylen);
|
|
memnuke(pScratch2, pKey->keylen);
|
|
_nt_free(pScratch2, pKey->keylen);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL PKCS2Decrypt(BSAFE_PRV_KEY *pKey,
|
|
BYTE *InBuf,
|
|
BYTE *OutBuf,
|
|
DWORD *OutBufLen)
|
|
{
|
|
DWORD i;
|
|
BYTE *pScratch;
|
|
BYTE *pScratch2;
|
|
DWORD z;
|
|
|
|
if ((pScratch = (BYTE *)_nt_malloc(pKey->keylen)) == NULL)
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
if ((pScratch2 = (BYTE *)_nt_malloc(pKey->keylen)) == NULL)
|
|
{
|
|
_nt_free(pScratch, pKey->keylen);
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
memset(pScratch2, 0, pKey->keylen);
|
|
memcpy(pScratch2, InBuf, pKey->keylen - 2*sizeof(DWORD));
|
|
|
|
BSafeDecPrivate(pKey, pScratch2, pScratch);
|
|
|
|
if (pScratch[pKey->datalen - 1] != PKCS_BLOCKTYPE_2)
|
|
{
|
|
SetLastError((DWORD) NTE_BAD_DATA);
|
|
memnuke(pScratch, pKey->keylen);
|
|
_nt_free(pScratch, pKey->keylen);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
i = pKey->datalen - 2;
|
|
|
|
while((i > 0) && (pScratch[i]))
|
|
i--;
|
|
|
|
if (i > *OutBufLen)
|
|
{
|
|
SetLastError((DWORD) NTE_BAD_DATA);
|
|
memnuke(pScratch, pKey->keylen);
|
|
_nt_free(pScratch, pKey->keylen);
|
|
memnuke(pScratch2, pKey->keylen);
|
|
_nt_free(pScratch2, pKey->keylen);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
*OutBufLen = i;
|
|
|
|
// Reverse the session key bytes
|
|
for (z = 0; z < i; ++z) OutBuf[z] = pScratch[i - z - 1];
|
|
|
|
memnuke(pScratch, pKey->keylen);
|
|
_nt_free(pScratch, pKey->keylen);
|
|
memnuke(pScratch2, pKey->keylen);
|
|
_nt_free(pScratch2, pKey->keylen);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
#ifndef ACT_BUILD
|
|
|
|
BOOL ReGenKey(HCRYPTPROV hUser,
|
|
DWORD dwWhichKey,
|
|
HCRYPTKEY *phKey,
|
|
DWORD bits)
|
|
{
|
|
BYTE **ThisPubKey, **ThisPrivKey;
|
|
size_t *pThisPubLen, *pThisPrivLen;
|
|
BYTE *pNewPubKey, *pNewPrivKey;
|
|
DWORD PrivateKeySize, PublicKeySize;
|
|
DWORD localbits;
|
|
PNTAGUserList pOurUser;
|
|
|
|
// ## MTS: No user structure locking
|
|
if ((pOurUser = (PNTAGUserList) NTLCheckList(hUser, USER_HANDLE)) == NULL)
|
|
{
|
|
SetLastError((DWORD) NTE_BAD_UID);
|
|
return NTF_FAILED;
|
|
}
|
|
|
|
localbits = bits;
|
|
|
|
if (!BSafeComputeKeySizes(&PublicKeySize, &PrivateKeySize, &localbits))
|
|
{
|
|
SetLastError((DWORD) NTE_FAIL);
|
|
return NTF_FAILED;
|
|
}
|
|
|
|
if ((pNewPubKey = (BYTE *)_nt_malloc(PublicKeySize)) == NULL)
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return NTF_FAILED;
|
|
}
|
|
|
|
// allocate space for the new key exchange public key
|
|
if ((pNewPrivKey = (BYTE *)_nt_malloc(PrivateKeySize)) == NULL)
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return NTF_FAILED;
|
|
}
|
|
|
|
// generate the key exchange key pair
|
|
if (!BSafeMakeKeyPair((BSAFE_PUB_KEY *) pNewPubKey,
|
|
(BSAFE_PRV_KEY *) pNewPrivKey,
|
|
bits))
|
|
{
|
|
_nt_free(pNewPrivKey, PrivateKeySize);
|
|
_nt_free(pNewPubKey, PublicKeySize);
|
|
SetLastError((DWORD) NTE_FAIL);
|
|
return NTF_FAILED;
|
|
}
|
|
|
|
if (dwWhichKey == NTPK_USE_SIG)
|
|
{
|
|
ThisPubKey = &pOurUser->pSigPubKey;
|
|
ThisPrivKey = &pOurUser->pSigPrivKey;
|
|
pThisPubLen = &pOurUser->SigPubLen;
|
|
pThisPrivLen = &pOurUser->SigPrivLen;
|
|
}
|
|
else
|
|
{
|
|
ThisPubKey = &pOurUser->pExchPubKey;
|
|
ThisPrivKey = &pOurUser->pExchPrivKey;
|
|
pThisPubLen = &pOurUser->ExchPubLen;
|
|
pThisPrivLen = &pOurUser->ExchPrivLen;
|
|
}
|
|
|
|
if (*ThisPubKey)
|
|
{
|
|
ASSERT(*pThisPubLen);
|
|
ASSERT(*pThisPrivLen);
|
|
ASSERT(*ThisPrivKey);
|
|
|
|
memnuke(*ThisPubKey, *pThisPubLen);
|
|
_nt_free (*ThisPubKey, *pThisPubLen);
|
|
|
|
memnuke(*ThisPrivKey, *pThisPrivLen);
|
|
_nt_free (*ThisPrivKey, *pThisPrivLen);
|
|
}
|
|
#ifdef NTAGDEBUG
|
|
else
|
|
{
|
|
ASSERT(*pThisPrivLen == 0);
|
|
ASSERT(*pThisPubLen == 0);
|
|
ASSERT(*ThisPrivKey == 0);
|
|
ASSERT(*ThisPubKey == 0);
|
|
}
|
|
#endif
|
|
|
|
*pThisPrivLen = PrivateKeySize;
|
|
*pThisPubLen = PublicKeySize;
|
|
*ThisPrivKey = pNewPrivKey;
|
|
*ThisPubKey = pNewPubKey;
|
|
|
|
// write the new keys to the user storage file
|
|
if (SaveUserKeys (pOurUser) == NTF_FAILED)
|
|
{
|
|
// ## NOTE: keys are changed, but not persistent
|
|
return NTF_FAILED; // error already set
|
|
}
|
|
|
|
if (dwWhichKey == NTPK_USE_SIG)
|
|
{
|
|
if (!CPGetUserKey(hUser, AT_SIGNATURE, phKey))
|
|
return NTF_FAILED;
|
|
}
|
|
else
|
|
{
|
|
if (!CPGetUserKey(hUser, AT_KEYEXCHANGE, phKey))
|
|
return NTF_FAILED;
|
|
}
|
|
|
|
return NTF_SUCCEED;
|
|
}
|
|
|
|
#endif // ACT_BUILD
|