mirror of https://github.com/lianthony/NT4.0
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.
301 lines
7.0 KiB
301 lines
7.0 KiB
/*
|
|
* mssfsign.c MSSFSIGN Program
|
|
*
|
|
* Microsoft Confidential
|
|
* Copyright (C) Microsoft Corporation 1995
|
|
* All Rights Reserved.
|
|
*
|
|
* Author:
|
|
* Jeffrey S. Webber
|
|
*
|
|
* History:
|
|
*
|
|
* 03-May-1995 jeffwe Started
|
|
*
|
|
*/
|
|
/*
|
|
* Usage: MSSFSIGN File [Dest]
|
|
*
|
|
* MSSFSIGN File [Dest] - Sign "File". If no dest specified sign
|
|
* in-place else copy to "dest" and sign while
|
|
* keeping original filename in suffix.
|
|
*/
|
|
|
|
|
|
#include "mssfsign.h"
|
|
#pragma hdrstop
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <io.h>
|
|
#include <fcntl.h>
|
|
#include <time.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <memory.h>
|
|
#include <string.h>
|
|
#include "..\cpldebug.h"
|
|
#include "..\mssf.h"
|
|
#include "..\sha.h"
|
|
#include "..\rsa.h"
|
|
#include "mssfchek.h"
|
|
|
|
|
|
#define BUFSIZE 16384
|
|
|
|
|
|
|
|
// Private Key
|
|
extern LPBSAFE_PRV_KEY PrivKey;
|
|
|
|
|
|
BOOL fCopy = FALSE;
|
|
BOOL fForce = FALSE;
|
|
char *pszSrcFile = NULL; // Source File Argument
|
|
char *pszSrcName = NULL; // Final Name Portion only
|
|
char *pszDstFile = NULL; // Destination File Argument
|
|
UCHAR abPlainSig[200];
|
|
UCHAR abCryptSig[200];
|
|
UCHAR abBuffer[BUFSIZE];
|
|
|
|
|
|
|
|
/*
|
|
* MSSFVerify() Callback Function
|
|
*
|
|
* After signing we use the MSSFCHEK Library to
|
|
* verify that the signature is correct. This is
|
|
* the callback function called by MSSFVerify() to
|
|
* report status and problems
|
|
*/
|
|
|
|
CALLBACKFUNC(fnMSSFCallback)
|
|
{
|
|
switch (CallbackType) {
|
|
case CALLBACK_STATUS:
|
|
printf("%d Percent Complete\n", (DWORD) CallbackValue );
|
|
return( 1 );
|
|
break;
|
|
case CALLBACK_DESTEXISTS:
|
|
printf("Unexpected Destination Exists Callback\n");
|
|
return( 0 );
|
|
break;
|
|
default:
|
|
printf("CALLBACK NOT RECOGNIZED\n");
|
|
return( 0 );
|
|
exit(1);
|
|
}
|
|
return( 0 );
|
|
}
|
|
|
|
|
|
/*
|
|
* F i l e E x i s t s ( )
|
|
*
|
|
* Check to see whether specified file exists
|
|
*
|
|
* BUGBUG: Is there a better way to do this?
|
|
*
|
|
* Entry:
|
|
* pszFileName - Name of file to check
|
|
*
|
|
* Exit:
|
|
* TRUE - File Exists
|
|
* FALSE - File does not exist
|
|
*
|
|
*/
|
|
|
|
static
|
|
BOOL
|
|
FileExists( LPCSTR pszFileName )
|
|
{
|
|
HANDLE hFile;
|
|
|
|
ASSERT( pszFileName );
|
|
|
|
hFile = CreateFile( pszFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE);
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
return( FALSE );
|
|
|
|
CloseHandle( hFile );
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* P r o c e s s A r g s
|
|
*
|
|
* Process arguments
|
|
*/
|
|
|
|
static
|
|
BOOL
|
|
ProcessArgs( int cArg, char *apszArg[] )
|
|
{
|
|
char *pchRover;
|
|
char *pchLastPathSep;
|
|
|
|
// Must have at least one argument
|
|
if ((cArg < 2) || (cArg > 3)) {
|
|
printf("Invalid Usage\n");
|
|
return( FALSE );
|
|
}
|
|
|
|
// Source File Argument
|
|
pszSrcFile = apszArg[1];
|
|
if (! FileExists( pszSrcFile )) {
|
|
printf("File %d not found\n", pszSrcFile );
|
|
return( FALSE );
|
|
}
|
|
|
|
// Get Dest if provided
|
|
if (cArg == 3) {
|
|
fCopy = TRUE;
|
|
pszDstFile = apszArg[2];
|
|
|
|
// Point at final name part of source
|
|
pchLastPathSep = pszSrcFile;
|
|
pchRover = pszSrcFile;
|
|
while (*pchRover) {
|
|
if ((*pchRover == '\\') || (*pchRover == ':'))
|
|
pchLastPathSep = pchRover + 1;
|
|
pchRover = CharNext(pchRover);
|
|
}
|
|
pszSrcName = pchLastPathSep;
|
|
} else {
|
|
pszDstFile = pszSrcFile;
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* M A I N
|
|
*
|
|
* Main Program
|
|
*/
|
|
|
|
int __cdecl
|
|
main( int cArg, char *apszArg[] )
|
|
{
|
|
int fdFile;
|
|
int cbReadSize;
|
|
int cbFileSize = 0;
|
|
A_SHA_CTX SHA_Hash;
|
|
UCHAR SHA_Digest[A_SHA_DIGEST_LEN];
|
|
MSSUFFIX suffix;
|
|
MSSFVFY mssfinfo;
|
|
char abNameBuffer[MAX_PATH];
|
|
|
|
|
|
// Parse Command Line - Set following globals
|
|
// pszSrcFile
|
|
// pszDstFile
|
|
// fCopy
|
|
// fForce
|
|
if (ProcessArgs(cArg,apszArg) == FALSE) {
|
|
printf("USAGE: MSSFSIGN File [Dest]\n");
|
|
exit(1);
|
|
}
|
|
// Copy if new name specified and it doesn't exist already
|
|
if (fCopy) {
|
|
if (CopyFile( pszSrcFile, pszDstFile, TRUE ) != TRUE) {
|
|
printf("Can't copy %s to %s\n", pszSrcFile, pszDstFile );
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
// Open File and Get Ready to hash
|
|
fdFile = _open(pszDstFile, _O_RDWR | _O_BINARY | _O_APPEND );
|
|
if (fdFile == -1) {
|
|
printf("Error: File Open Failed: %s\n", pszDstFile );
|
|
exit(1);
|
|
}
|
|
A_SHAInit( &SHA_Hash );
|
|
|
|
|
|
// Hash File Contents
|
|
while ((cbReadSize = _read( fdFile, abBuffer, BUFSIZE)) > 0) {
|
|
A_SHAUpdate( &SHA_Hash, abBuffer, cbReadSize);
|
|
cbFileSize += cbReadSize;
|
|
}
|
|
if (cbReadSize == -1) {
|
|
printf("Error: Read Error at %d\n", _lseek( fdFile, 0, SEEK_CUR));
|
|
exit(1);
|
|
}
|
|
|
|
|
|
// Fill in Suffix
|
|
if (fCopy)
|
|
suffix.cbName = strlen(pszSrcName) + 1;
|
|
else
|
|
suffix.cbName = 0;
|
|
suffix.cbSize = sizeof(suffix) + suffix.cbName;
|
|
suffix.Version = 1;
|
|
suffix.Magic = MSSF_MAGIC;
|
|
|
|
|
|
// Hash the stuff in the suffix
|
|
A_SHAUpdate( &SHA_Hash, (UCHAR *) &(suffix.cbName), sizeof(DWORD) );
|
|
if (suffix.cbName > 0)
|
|
A_SHAUpdate( &SHA_Hash, pszSrcName, strlen(pszSrcName));
|
|
A_SHAUpdate( &SHA_Hash, (UCHAR *) &(suffix.cbSize), sizeof(DWORD) );
|
|
A_SHAUpdate( &SHA_Hash, (UCHAR *) &(suffix.Version), sizeof(DWORD) );
|
|
A_SHAUpdate( &SHA_Hash, (UCHAR *) &(suffix.Magic), sizeof(DWORD) );
|
|
|
|
|
|
// Finalize the Message Digest
|
|
A_SHAFinal( &SHA_Hash, SHA_Digest );
|
|
|
|
// Encrypt the Digest
|
|
// first we clear the buffer
|
|
memset(abPlainSig, 0, sizeof(abPlainSig) );
|
|
// then fill some of it with ff's
|
|
memset(abPlainSig, 0xff, PrivKey->datalen - 1);
|
|
// then copy the hash into the buffer
|
|
memcpy(abPlainSig, SHA_Digest, A_SHA_DIGEST_LEN );
|
|
if (! BSafeDecPrivate( PrivKey, abPlainSig, abCryptSig )) {
|
|
printf("Encryption Failure\n");
|
|
exit(1);
|
|
}
|
|
|
|
// Copy Encrypted Signature into suffix
|
|
memcpy( suffix.DigitalSig, abCryptSig, PrivKey->datalen + 1 );
|
|
|
|
|
|
// Write Filename
|
|
if (fCopy) {
|
|
if (_write( fdFile, pszSrcName, strlen(pszSrcName)+1) != ((int) (strlen(pszSrcName)+1))) {
|
|
printf("Error: Writing Old Filename\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
// Write the suffix
|
|
if (_write( fdFile, &suffix, sizeof(suffix)) != sizeof(suffix)) {
|
|
printf("Error: Writing Suffix\n");
|
|
exit(1);
|
|
}
|
|
_close( fdFile );
|
|
|
|
// Verify Correctness
|
|
mssfinfo.pszFilePath = pszDstFile;
|
|
mssfinfo.pszNewFilePath= abNameBuffer;
|
|
mssfinfo.cbNewFilePath = sizeof( abNameBuffer );
|
|
mssfinfo.dwVerifyFlags = MSSF_VERIFYONLY;
|
|
mssfinfo.pfnCallback = fnMSSFCallback;
|
|
|
|
|
|
if (MSSFVerify( &mssfinfo ) == FALSE) {
|
|
printf("Signature Verification Failed\n");
|
|
exit(1);
|
|
}
|
|
|
|
printf("File Signed and Verified!\n");
|
|
|
|
return(0);
|
|
}
|