2020-09-30 17:12:29 +02:00

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