Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

399 lines
9.5 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995.
//
// File: keys.c
//
// Contents: Well known keys for certificate validation
//
// Classes:
//
// Functions:
//
// History: 9-21-95 RichardW Created
//
//----------------------------------------------------------------------------
#include "pctsspi.h"
#include "encode.h"
#include "bulk.h"
#define PRIVATE_KEY_TEXT "private-key"
UCHAR RsaSecureServer[] = {
0x00, 0x00, 0x00, 0x00, // Magic
0x00, 0x00, 0x00, 0x00, // Key len
0x00, 0x00, 0x00, 0x00, // bitlen
0x00, 0x00, 0x00, 0x00, // datalen
0x01, 0x00, 0x01, 0x00, // exponent
0x7b, 0x1e, 0xc8, 0xd6, 0x2d, 0xdd, 0xe5, 0x48,
0x67, 0x70, 0x6d, 0x9c, 0x39, 0x97, 0xb1, 0x82,
0x69, 0x3a, 0x73, 0x2c, 0x54, 0x49, 0xd5, 0x15,
0x1e, 0x9c, 0x59, 0x11, 0x4a, 0x2e, 0x13, 0x1a,
0x29, 0xa7, 0x1d, 0xb9, 0x48, 0x98, 0x56, 0x89,
0x50, 0xe3, 0x4c, 0x77, 0x9b, 0x3e, 0x76, 0x71,
0x13, 0x70, 0x65, 0x07, 0x84, 0x6d, 0x59, 0x81,
0xf7, 0x8f, 0x07, 0x88, 0x6c, 0x56, 0x22, 0x66,
0x25, 0x4b, 0xc9, 0x4b, 0xa2, 0x05, 0x9a, 0x81,
0x68, 0x76, 0xad, 0x02, 0x21, 0xb1, 0xe9, 0x55,
0x37, 0x86, 0x16, 0xd2, 0x08, 0x82, 0x8a, 0xe2,
0x08, 0x8f, 0xbf, 0xc9, 0x51, 0x40, 0x84, 0xe5,
0x03, 0x54, 0x64, 0x78, 0x35, 0xeb, 0xce, 0x37,
0x2c, 0x8e, 0xae, 0xad, 0x0c, 0x76, 0x01, 0x25,
0xac, 0x57, 0x83, 0x89, 0xaa, 0x5a, 0x3e, 0x83,
0xae, 0xc1, 0x7a, 0xce, 0x92, 0x00, 0x00, 0x00
};
UCHAR NetscapeTestKey[] = {
0x00, 0x00, 0x00, 0x00, // Magic
0x00, 0x00, 0x00, 0x00, // Key len
0x00, 0x00, 0x00, 0x00, // bitlen
0x00, 0x00, 0x00, 0x00, // datalen
0x03, 0x00, 0x00, 0x00, // exponent
0x63, 0x16, 0xcc, 0xd3, 0x9c, 0x5f, 0x3e, 0x1a,
0x40, 0xd2, 0x4e, 0x77, 0xe0, 0x00, 0x09, 0xfd,
0x68, 0x15, 0x87, 0x68, 0x0b, 0x2d, 0x29, 0x2a,
0x3f, 0x40, 0xcb, 0x1f, 0x61, 0x33, 0x8e, 0xd5,
0x96, 0xb3, 0x28, 0xcf, 0x94, 0x58, 0xde, 0xfc,
0x74, 0xbd, 0x33, 0xdb, 0xb9, 0x09, 0x3e, 0x67,
0x36, 0xa7, 0xdd, 0xdd, 0x16, 0xe0, 0xbd, 0x16,
0x0e, 0x52, 0xcb, 0xb8, 0xe1, 0xb7, 0x16, 0xa0,
0x45, 0xa7, 0xff, 0x65, 0xc9, 0xb8, 0x8a, 0x59,
0x12, 0x37, 0x6b, 0x7d, 0x21, 0x4a, 0x4a, 0x48,
0x21, 0xbf, 0x4e, 0x6a, 0xa3, 0x95, 0x34, 0xa0,
0xc1, 0x32, 0xa7, 0xf0, 0xde, 0x56, 0x15, 0xad,
0x60, 0xc3, 0x14, 0xe6, 0x07, 0x51, 0x7c, 0xfe,
0x2a, 0x02, 0x50, 0x13, 0x5b, 0x82, 0xb2, 0x9b,
0xdf, 0x2d, 0x15, 0x81, 0xe9, 0xcb, 0x3c, 0xa1,
0x72, 0x7b, 0x18, 0xba, 0xec, 0x8a, 0x6c, 0xb4,
0x00, 0x00, 0x00, 0x00
};
BSAFE_PUB_KEY * pRsaSecureServer;
BSAFE_PUB_KEY * pNetscapeTestKey;
typedef struct _KnownKey {
PSTR pszIssuer;
BSAFE_PUB_KEY * pKey;
} KnownKey, * PKnownKey;
KnownKey PctKnownKeys[] = { {"C=US, O=RSA Data Security, Inc., OU=Secure Server Certification Authority",
NULL },
{"C=US, OU=Test CA, O=Netscape Communications Corp.", NULL}
};
VOID
InitializeWellKnownKeys( VOID )
{
pRsaSecureServer = (BSAFE_PUB_KEY *) RsaSecureServer;
pRsaSecureServer->magic = RSA1;
pRsaSecureServer->bitlen = 16 * 8 * 8;
pRsaSecureServer->keylen = 16 * 8 + 8;
pRsaSecureServer->datalen = 16 * 8 - 1;
PctKnownKeys[0].pKey = pRsaSecureServer;
pNetscapeTestKey = (BSAFE_PUB_KEY *) NetscapeTestKey;
pNetscapeTestKey->magic = RSA1;
pNetscapeTestKey->bitlen = 16 * 8 * 8;
pNetscapeTestKey->keylen = 16 * 8 + 8;
pNetscapeTestKey->datalen = 16 * 8 - 1;
PctKnownKeys[1].pKey = pNetscapeTestKey;
}
BSAFE_PUB_KEY *
FindIssuerKey(
PSTR pszIssuer)
{
DWORD i;
for (i = 0; i < sizeof(PctKnownKeys) / sizeof(KnownKey) ; i++ )
{
if (_stricmp(pszIssuer, PctKnownKeys[i].pszIssuer) == 0)
{
return(PctKnownKeys[i].pKey);
}
}
return( NULL );
}
BOOL
PctpEncodePrivateKey(
BSAFE_PRV_KEY * pKey,
DWORD InitialSize,
PSTR pszPassword,
PUCHAR * ppBuffer,
DWORD * pcbBuffer )
{
BSAFE_KEY_PARTS parts;
PUCHAR pBuffer;
PUCHAR pbEncoded;
PUCHAR pSave;
int Result;
DWORD Zero;
DWORD BigLen;
DWORD ShortLen;
PUCHAR pSequence;
DWORD Length;
PUCHAR pSave2;
long Delta2;
PStateBuffer pState;
PCheckSumBuffer pCheck;
UCHAR Key[16];
BSafeGetPrvKeyParts( pKey, &parts );
pBuffer = LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, InitialSize );
if (!pBuffer)
{
return( FALSE );
}
pbEncoded = pBuffer;
BigLen = pKey->bitlen / 8;
ShortLen = BigLen / 2;
//
// We just do the key now, and then we'll add the other stuff later
//
//
// Encode the maximum length for now. We'll patch this up later
//
Result = EncodeHeader(pbEncoded, InitialSize, TRUE );
pbEncoded += Result;
pSave = pbEncoded;
Zero = 0;
Result = EncodeInteger(pbEncoded, (PBYTE) &Zero, 1, TRUE );
pbEncoded += Result;
Result = EncodeInteger( pbEncoded, parts.modulus, BigLen, TRUE );
pbEncoded += Result;
Result = EncodeInteger( pbEncoded, (PBYTE) &pKey->pubexp, sizeof(DWORD), TRUE );
pbEncoded += Result;
Result = EncodeInteger( pbEncoded, parts.prvexp, BigLen, TRUE );
pbEncoded += Result;
Result = EncodeInteger( pbEncoded, parts.prime1, ShortLen, TRUE );
pbEncoded += Result;
Result = EncodeInteger( pbEncoded, parts.prime2, ShortLen, TRUE );
pbEncoded += Result;
Result = EncodeInteger( pbEncoded, parts.exp1, ShortLen, TRUE );
pbEncoded += Result;
Result = EncodeInteger( pbEncoded, parts.exp2, ShortLen, TRUE );
pbEncoded += Result;
Result = EncodeInteger( pbEncoded, parts.coef, ShortLen, TRUE );
pbEncoded += Result;
Length = pbEncoded - pSave;
Result = EncodeHeader( pBuffer, Length, TRUE );
Length += Result;
pSequence = LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, Length + 64 );
if (!pSequence)
{
LocalFree( pBuffer );
return( FALSE );
}
pbEncoded = pSequence;
Result = EncodeHeader( pbEncoded, Length + 64, TRUE );
pbEncoded += Result;
pSave = pbEncoded;
Result = EncodeInteger( pbEncoded, (PBYTE) &Zero, 1, TRUE );
pbEncoded += Result;
Result = EncodeAlgorithm( pbEncoded, BASIC_RSA, TRUE );
pbEncoded += Result;
Result = EncodeOctetString( pbEncoded, pBuffer, Length, TRUE );
pbEncoded += Result;
ZeroMemory( pBuffer, Length );
Length = pbEncoded - pSave;
Result = EncodeHeader( pSequence, Length, TRUE );
Length += Result;
LocalFree( pBuffer );
pBuffer = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, Length + 128);
if (!pBuffer)
{
LocalFree( pSequence );
return( FALSE );
}
pbEncoded = pBuffer;
Result = EncodeHeader( pBuffer, Length + 128, TRUE );
pbEncoded += Result;
pSave = pbEncoded;
Result = EncodeOctetString( pbEncoded, PRIVATE_KEY_TEXT,
strlen(PRIVATE_KEY_TEXT), TRUE );
pbEncoded += Result;
Result = EncodeHeader( pbEncoded, Length + 64, TRUE );
pbEncoded += Result;
pSave2 = pbEncoded;
Delta2 = Result;
Result = EncodeAlgorithm( pbEncoded, RC4_STREAM, TRUE );
pbEncoded += Result;
//
// Encrypt the data with the password
//
ckMD5.Initialize(0, &pCheck);
ckMD5.Sum(pCheck, strlen(pszPassword), pszPassword);
ckMD5.Finalize(pCheck, Key);
ckMD5.Finish(&pCheck);
csRC4.Initialize(Key, 16, &pState);
csRC4.Encrypt(pState, pSequence, pSequence, Length);
csRC4.Discard( &pState );
Result = EncodeOctetString( pbEncoded, pSequence, Length, TRUE );
LocalFree( pSequence );
pbEncoded += Result;
//
// Now, back up and fill in the correct lengths:
//
Result = EncodeHeader( pSave2-Delta2, pbEncoded - pSave2, TRUE );
Result = EncodeHeader( pBuffer, pbEncoded - pSave2, TRUE );
DebugLog((DEB_TRACE, "Encoded private key\n"));
return( TRUE );
}
BOOL
PctGenerateKeyPair(
PPCT_CREDENTIAL_CERTIFICATE pCerts,
PSTR pszDN,
PSTR pszPassword,
DWORD Bits )
{
DWORD BitsCopy;
DWORD dwPrivateSize;
DWORD dwPublicSize;
BSAFE_PRV_KEY * pPrivate;
BSAFE_PUB_KEY * pPublic;
BitsCopy = Bits;
BSafeComputeKeySizes( &dwPublicSize, &dwPrivateSize, &BitsCopy );
pPrivate = LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, dwPrivateSize );
pPublic = LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, dwPublicSize );
if (!pPrivate || !pPublic)
{
if (pPrivate)
{
LocalFree( pPrivate );
}
if (pPublic)
{
LocalFree( pPublic );
}
return( FALSE );
}
if (!BSafeMakeKeyPair(pPublic, pPrivate, Bits ) )
{
LocalFree( pPrivate );
LocalFree( pPublic );
return( FALSE );
}
//
// Ah yes, now to encode them...
//
//
// First, the private key. Why? Well, it's at least straight-forward
//
if (!PctpEncodePrivateKey(pPrivate, dwPrivateSize, pszPassword,
&pCerts->pPrivateKey, &pCerts->cbPrivateKey ) )
{
LocalFree( pPrivate );
LocalFree( pPublic );
return( FALSE );
}
}