/* Key.cpp : defines the key object. This file contains the routines that allow a key to store and restore itself */ #include "stdafx.h" #include "resource.h" #include "KeyObjs.h" #include "cmnkey.h" #include "W3Key.h" #define KEY_VERSION 0x102 /*======== The scheme here is to create a handle that contains all the data necessary to restore the key object. The data contained in that handle is then stored as a secret on the target machine. This does require that the size of the handle be less than 65000 bytes, which should be no problem. */ //------------------------------------------------------------------------------ // generate a handle containing data that gets stored and then is used to restore // the key object at a later date. Restore this key by passing this dereferenced // handle back into the FInitKey routine above. HANDLE CW3Key::HGenerateDataHandle( BOOL fIncludePassword ) { DWORD cbSize; DWORD cbChar = sizeof(TCHAR); PUCHAR p; HANDLE h; CString szReserved; // save an empty string so that one can be added later szReserved.Empty(); // calculate the size of the handle cbSize = 2*sizeof(DWORD) + sizeof(BOOL); cbSize += sizeof(DWORD); // reserved dword cbSize += sizeof(DWORD) + szReserved.GetLength() * cbChar + cbChar; cbSize += sizeof(DWORD) + m_szName.GetLength() * cbChar + cbChar; cbSize += sizeof(DWORD) + m_szPassword.GetLength() * cbChar + cbChar; // no longer need to store all the distinguishing info now that crack certificate works cbSize += (sizeof(DWORD) + szReserved.GetLength() * cbChar + cbChar) * 6; /* cbSize += sizeof(DWORD) + m_szOrganization.GetLength() * cbChar + cbChar; cbSize += sizeof(DWORD) + m_szUnit.GetLength() * cbChar + cbChar; cbSize += sizeof(DWORD) + m_szNetAddress.GetLength() * cbChar + cbChar; cbSize += sizeof(DWORD) + m_szCountry.GetLength() * cbChar + cbChar; cbSize += sizeof(DWORD) + m_szStateProvince.GetLength() * cbChar + cbChar; cbSize += sizeof(DWORD) + m_szLocality.GetLength() * cbChar + cbChar; */ cbSize += sizeof(DWORD) + m_szIPAddress.GetLength() * cbChar + cbChar; cbSize += sizeof(BOOL); //m_fDefault cbSize += sizeof(DWORD) + m_cbPrivateKey; cbSize += sizeof(DWORD) + m_cbCertificate; cbSize += sizeof(DWORD) + m_cbCertificateRequest; cbSize += sizeof(FILETIME); // no longer used // create the new handle and lock it h = GlobalAlloc( GHND, cbSize ); if ( !h ) { AfxThrowMemoryException(); return NULL; } p = (PUCHAR)GlobalLock( h ); // put in the version, fComplete, and nBits *((UNALIGNED DWORD*)p) = KEY_VERSION; p += sizeof(DWORD); *((UNALIGNED DWORD*)p) = 0; // no longer used p += sizeof(DWORD); *((UNALIGNED BOOL*)p) = (m_pCertificate != NULL); // no longer used p += sizeof(BOOL); // add in a reserved dword for future use. *((UNALIGNED DWORD*)p) = 0L; p += sizeof(DWORD); // now the strings...... // for each string, first write out the size of the string, then the string data. // save the reserved string. If you need to add one later and don't want to // invalidate the older keys on a machine, replace this string. cbSize = szReserved.GetLength() * cbChar + cbChar; *((UNALIGNED DWORD*)p) = cbSize; p += sizeof(DWORD); CopyMemory( p, LPCTSTR(szReserved), cbSize ); p += cbSize; // save the name cbSize = m_szName.GetLength() * cbChar + cbChar; *((UNALIGNED DWORD*)p) = cbSize; p += sizeof(DWORD); CopyMemory( p, LPCTSTR(m_szName), cbSize ); p += cbSize; // save the password if ( fIncludePassword ) { cbSize = m_szPassword.GetLength() * cbChar + cbChar; *((UNALIGNED DWORD*)p) = cbSize; p += sizeof(DWORD); CopyMemory( p, LPCTSTR(m_szPassword), cbSize ); p += cbSize; } else // do not include the password - just put in an empty field { *((UNALIGNED DWORD*)p) = 0; p += sizeof(DWORD); } // no longer need to store all the distinguishing info now that crack certificate works for ( WORD i = 0; i < 6; i++ ) { cbSize = szReserved.GetLength() * cbChar + cbChar; *((UNALIGNED DWORD*)p) = cbSize; p += sizeof(DWORD); CopyMemory( p, LPCTSTR(szReserved), cbSize ); p += cbSize; } // save the ip address it is attached to cbSize = m_szIPAddress.GetLength() * cbChar + cbChar; *((UNALIGNED DWORD*)p) = cbSize; p += sizeof(DWORD); CopyMemory( p, LPCTSTR(m_szIPAddress), cbSize ); p += cbSize; // put in the m_fDefault flag *((UNALIGNED BOOL*)p) = m_fDefault; p += sizeof(BOOL); // now put in the number of bytes in the private key *((UNALIGNED DWORD*)p) = m_cbPrivateKey; p += sizeof(DWORD); // put in the private key CopyMemory( p, m_pPrivateKey, m_cbPrivateKey ); p += m_cbPrivateKey; // now put in the number of bytes in the certificate *((UNALIGNED DWORD*)p) = m_cbCertificate; p += sizeof(DWORD); // put in the certificate key CopyMemory( p, m_pCertificate, m_cbCertificate ); p += m_cbCertificate; // now put in the number of bytes in the certificate request *((UNALIGNED DWORD*)p) = m_cbCertificateRequest; p += sizeof(DWORD); // put in the certificate request CopyMemory( p, m_pCertificateRequest, m_cbCertificateRequest ); p += m_cbCertificateRequest; // and finally, add the timestamp FILETIME ft; memset( &ft, 0, sizeof(ft) ); *((UNALIGNED FILETIME*)p) = ft; p += sizeof(FILETIME); // unlock the handle GlobalUnlock( h ); // all done return h; } //------------------------------------------------------------------------------ // Given a pointer to a block of data originally created by the above routine, fill // in the key object BOOL CW3Key::InitializeFromPointer( PUCHAR pSrc, DWORD cbSrc ) { DWORD dword, version; DWORD cbChar = sizeof(TCHAR); PUCHAR p = pSrc; ASSERT(pSrc && cbSrc); // get the version of the data - just put it into dword for now version = *((UNALIGNED DWORD*)p); // check the version for validity if ( version > KEY_VERSION ) { return FALSE; } p += sizeof(DWORD); // anything below version 0x101 is BAD. Do not accept it if ( version < 0x101 ) { AfxMessageBox( IDS_INVALID_KEY, MB_OK|MB_ICONINFORMATION ); return FALSE; } // get the bits and the complete flag // no longer used p += sizeof(DWORD); p += sizeof(BOOL); ASSERT( p < (pSrc + cbSrc) ); // get the reserved dword - (acutally, just skip over it) p += sizeof(DWORD); // now the strings...... // for each string, first get the size of the string, then the data from the string // get the reserved string - (actually, just skip over it) dword = *((UNALIGNED DWORD*)p); p += sizeof(DWORD); p += dword; // get the name dword = *((UNALIGNED DWORD*)p); p += sizeof(DWORD); m_szName= p; p += dword; ASSERT( p < (pSrc + cbSrc) ); // get the password dword = *((UNALIGNED DWORD*)p); p += sizeof(DWORD); // if there is no password, don't worry, just skip it if ( dword ) { m_szPassword = p; p += dword; ASSERT( p < (pSrc + cbSrc) ); } // get the organization // no longer used - skip the DN info for ( WORD i = 0; i < 6; i++ ) { dword = *((UNALIGNED DWORD*)p); p += sizeof(DWORD); p += dword; ASSERT( p < (pSrc + cbSrc) ); } // get the ip addres it is attached to dword = *((UNALIGNED DWORD*)p); p += sizeof(DWORD); m_szIPAddress = p; p += dword; ASSERT( p < (pSrc + cbSrc) ); // get the default flag m_fDefault = *((UNALIGNED BOOL*)p); p += sizeof(BOOL); // now put get the number of bytes in the private key m_cbPrivateKey = *((UNALIGNED DWORD*)p); p += sizeof(DWORD); ASSERT( p < (pSrc + cbSrc) ); // if the private key already exists, kill it. Then make a new pointer for it if ( m_pPrivateKey ) GlobalFree( (HANDLE)m_pPrivateKey ); m_pPrivateKey = (PVOID)GlobalAlloc( GPTR, m_cbPrivateKey ); if ( !m_pPrivateKey ) return FALSE; // put in the private key CopyMemory( m_pPrivateKey, p, m_cbPrivateKey ); p += m_cbPrivateKey; ASSERT( p < (pSrc + cbSrc) ); // now put get the number of bytes in the certificate m_cbCertificate = *((UNALIGNED DWORD*)p); p += sizeof(DWORD); ASSERT( p < (pSrc + cbSrc) ); // if the private key already exists, kill it. Then make a new pointer for it if ( m_pCertificate ) GlobalFree( (HANDLE)m_pCertificate ); m_pCertificate = NULL; // only make a certificate pointer if m_cbCertificate is greater than zero if ( m_cbCertificate ) { m_pCertificate = (PVOID)GlobalAlloc( GPTR, m_cbCertificate ); if ( !m_pCertificate ) return FALSE; // put in the private key CopyMemory( m_pCertificate, p, m_cbCertificate ); p += m_cbCertificate; if ( version >= KEY_VERSION ) ASSERT( p < (pSrc + cbSrc) ); else ASSERT( p == (pSrc + cbSrc) ); } // added near the end if ( version >= KEY_VERSION ) { // now put get the number of bytes in the certificte request m_cbCertificateRequest = *((UNALIGNED DWORD*)p); p += sizeof(DWORD); ASSERT( p < (pSrc + cbSrc) ); // if the private key already exists, kill it. Then make a new pointer for it if ( m_pCertificateRequest ) GlobalFree( (HANDLE)m_pCertificateRequest ); m_pCertificateRequest = NULL; // only make a certificate pointer if m_cbCertificate is greater than zero if ( m_cbCertificateRequest ) { m_pCertificateRequest = (PVOID)GlobalAlloc( GPTR, m_cbCertificateRequest ); if ( !m_pCertificateRequest ) return FALSE; // put in the private key CopyMemory( m_pCertificateRequest, p, m_cbCertificateRequest ); p += m_cbCertificateRequest; ASSERT( p < (pSrc + cbSrc) ); } // finally read in the expiration timestamp // m_tsExpires = *((UNALIGNED FILETIME*)p); p += sizeof(FILETIME); } else { m_cbCertificateRequest = 0; if ( m_pCertificateRequest ) GlobalFree( (HANDLE)m_pCertificateRequest ); m_pCertificateRequest = NULL; // m_tsExpires.dwLowDateTime = 0; // m_tsExpires.dwHighDateTime = 0; } // all done return TRUE; }