⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 randlib.c

📁 windows的加密api源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++

Copyright (c) 1993, 1998  Microsoft Corporation

Module Name:

    randlib.c

Abstract:

    This module implements the core cryptographic random number generator
    for use by system components.

    The #define KMODE_RNG affects whether the file is built in a way
    suitable for kernel mode usage.  if KMODE_RNG is not defined, the file
    is built in a way suitable for user mode usage.

Author:

    Scott Field (sfield)    27-Nov-96
    Jeff Spelman (jeffspel) 14-Oct-96

--*/

#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <zwapi.h>

#ifdef KMODE_RNG
#include <ntos.h>
#ifdef USE_HW_RNG
#ifdef _M_IX86
#include <io.h>
#include "deftypes.h"   //ISD typedefs and constants
#include "ioctldef.h"   //ISD ioctl definitions
#endif  // _M_IX86
#endif  // USE_HW_RNG
#endif  // KMODE_RNG

#include <windows.h>
#include <winioctl.h>
#include <lmcons.h>

#include <rc4.h>
#include <sha.h>
#include <md4.h>

#include <ntddksec.h>   // IOCTL_
#include <randlib.h>

#include "vlhash.h"
#include "circhash.h"
#include "cpu.h"
#include "seed.h"


#ifdef KMODE_RNG
#include <ntos.h>
#ifdef USE_HW_RNG
#ifdef _M_IX86
static DWORD g_dwHWDriver = 0;
static PFILE_OBJECT   g_pFileObject = NULL;
static PDEVICE_OBJECT g_pDeviceObject = NULL;
#endif  // _M_IX86
#endif  // USE_HW_RNG
#endif  // KMODE_RNG


#include "umkm.h"

//
// note: RAND_CTXT_LEN dictates the maximum input quantity for re-seed entropy
// is.  We make this fairly large, so that we can take all the entropy generated
// during the GatherRandomBits().  Since the lifetime of the RandContext structure
// is very short, and it lives on the stack, this larger than necessary size
// is ok.  The last few items processed during GatherRandomBits() are of
// variable size, up to a maximum of of UNLEN for the username.
//

#define RAND_CTXT_LEN           (256)
#define RC4_REKEY_PARAM_NT      (16384) // rekey less often on NT

#ifndef KMODE_RNG
#define RC4_REKEY_PARAM_DEFAULT (512)   // rekey every 512 bytes by default
#else
#define RC4_REKEY_PARAM_DEFAULT RC4_REKEY_PARAM_NT
#endif


static unsigned int     g_dwRC4RekeyParam = RC4_REKEY_PARAM_DEFAULT;

static CircularHash     g_CircularHashCtx;
static BYTE             g_VeryLargeHash[A_SHA_DIGEST_LEN*4];

static void *           g_RC4SafeCtx;

#ifndef KMODE_RNG

typedef NTSYSAPI NTSTATUS (NTAPI *NTQUERYSYSTEMINFORMATION) (
    IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
    OUT PVOID SystemInformation,
    IN ULONG SystemInformationLength,
    OUT PULONG ReturnLength OPTIONAL
    );

typedef NTSYSAPI NTSTATUS (NTAPI *NTOPENFILE) (
    OUT PHANDLE FileHandle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_ATTRIBUTES ObjectAttributes,
    OUT PIO_STATUS_BLOCK IoStatusBlock,
    IN ULONG ShareAccess,
    IN ULONG OpenOptions
    );

typedef NTSYSAPI VOID (NTAPI *RTLINITUNICODESTRING) (
    PUNICODE_STRING DestinationString,
    PCWSTR SourceString
    );

typedef BOOL (WINAPI *GETCURSORPOS)(
    LPPOINT lpPoint
    );

typedef LONG (WINAPI *GETMESSAGETIME)(
    VOID
    );

NTQUERYSYSTEMINFORMATION    ___NtQuerySystemInformationRNG = NULL;
NTOPENFILE                  ___NtOpenFileRNG = NULL;
RTLINITUNICODESTRING        ___RtlInitUnicodeStringRNG = NULL;

GETCURSORPOS                ___GetCursorPosRNG = NULL;
GETMESSAGETIME              ___GetMessageTimeRNG = NULL;

HANDLE g_hKsecDD = NULL;


#define _NtQuerySystemInformation   ___NtQuerySystemInformationRNG
#define _NtOpenFile                 ___NtOpenFileRNG
#define _RtlInitUnicodeString       ___RtlInitUnicodeStringRNG
#define _GetCursorPos               ___GetCursorPosRNG
#define _GetMessageTime             ___GetMessageTimeRNG

#else

#define _NtQuerySystemInformation ZwQuerySystemInformation

#endif // !KMODE_RNG

/// TODO: cache hKeySeed later.
///extern HKEY g_hKeySeed;



//
// private function prototypes.
//


BOOL
GenRandom (
    IN      PVOID           hUID,
        OUT BYTE            *pbBuffer,
    IN      size_t          dwLength
    );


BOOL
RandomFillBuffer(
        OUT BYTE            *pbBuffer,
    IN      DWORD           *pdwLength
    );

BOOL
GatherRandomKey(
    IN      BYTE            *pbUserSeed,
    IN      DWORD           cbUserSeed,
    IN  OUT BYTE            *pbRandomKey,
    IN  OUT DWORD           *pcbRandomKey
    );

BOOL
GatherRandomKeyFastUserMode(
    IN      BYTE            *pbUserSeed,
    IN      DWORD           cbUserSeed,
    IN  OUT BYTE            *pbRandomKey,
    IN  OUT DWORD           *pcbRandomKey
    );


BOOL
IsRNGWinNT(
    VOID
    );


#ifdef _M_IX86
unsigned int
QueryForHWRandomBits(
    IN      DWORD *pdwRandom,
    IN  OUT DWORD cdwRandom
    );
#endif //_M_IX86


#ifdef KMODE_RNG

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, NewGenRandom)
#pragma alloc_text(PAGE, NewGenRandomEx)
#pragma alloc_text(PAGE, GenRandom)
#pragma alloc_text(PAGE, RandomFillBuffer)
#pragma alloc_text(PAGE, InitializeRNG)
#pragma alloc_text(PAGE, ShutdownRNG)
#ifdef _M_IX86
#pragma alloc_text(PAGE, QueryForHWRandomBits)
#endif //_M_IX86
#pragma alloc_text(PAGE, GatherRandomKey)

#endif  // ALLOC_PRAGMA
#endif  // KMODE_RNG



/************************************************************************/
/* NewGenRandom generates a specified number of random bytes and places */
/* them into the specified buffer.                                      */
/************************************************************************/
/*                                                                      */
/* Pseudocode logic flow:                                               */
/*                                                                      */
/* if (bits streamed >= threshold)                                      */
/* {                                                                    */
/*  Gather_Bits()                                                       */
/*  SHAMix_Bits(User, Gathered, Static -> Static)                       */
/*  RC4Key(Static -> newRC4Key)                                         */
/*  SaveToRegistry(Static)                                              */
/* }                                                                    */
/* else                                                                 */
/* {                                                                    */
/*  Mix_Bits(User, Static -> Static)                                    */
/* }                                                                    */
/*                                                                      */
/* RC4(newRC4Key -> outbuf)                                             */
/* bits streamed += sizeof(outbuf)                                      */
/*                                                                      */
/************************************************************************/


unsigned int
RSA32API
NewGenRandomEx(
    IN      RNG_CONTEXT *pRNGContext,
    IN  OUT unsigned char *pbRandBuffer,
    IN      unsigned long cbRandBuffer
    )
{
    unsigned char **ppbRandSeed;
    unsigned long *pcbRandSeed;
    unsigned int fRet;

#ifdef KMODE_RNG
    PAGED_CODE();
#endif  // KMODE_RNG

    fRet = TRUE;

    if( pRNGContext->cbSize != sizeof( RNG_CONTEXT ) )
        return FALSE;

    if( pRNGContext->pbRandSeed && pRNGContext->cbRandSeed ) {

        ppbRandSeed = &pRNGContext->pbRandSeed;
        pcbRandSeed = &pRNGContext->cbRandSeed;

    } else {

        ppbRandSeed = NULL;
        pcbRandSeed = NULL;
    }

    InitRand( ppbRandSeed, pcbRandSeed );
    InitializeRNG( NULL );

    if( pRNGContext->Flags & RNG_FLAG_REKEY_ONLY ) {

        //
        // caller wants REKEY only.
        //

        fRet = GatherRandomKey( NULL, 0, pbRandBuffer, &cbRandBuffer );

    } else {

        //
        // standard RNG request.
        //

        fRet = GenRandom(0, pbRandBuffer, cbRandBuffer);
    }

    if( ppbRandSeed && pcbRandSeed ) {
        DeInitRand( *ppbRandSeed, *pcbRandSeed);
    }

    return fRet;
}

unsigned int
RSA32API
NewGenRandom (
    IN  OUT unsigned char **ppbRandSeed,
    IN      unsigned long *pcbRandSeed,
    IN  OUT unsigned char *pbBuffer,
    IN      unsigned long dwLength
    )
{
    RNG_CONTEXT RNGContext;

#ifdef KMODE_RNG
    PAGED_CODE();
#endif  // KMODE_RNG


    ZeroMemory( &RNGContext, sizeof(RNGContext) );
    RNGContext.cbSize = sizeof(RNGContext);

    if( ppbRandSeed && pcbRandSeed ) {
        BOOL fRet;

        RNGContext.pbRandSeed = *ppbRandSeed;
        RNGContext.cbRandSeed = *pcbRandSeed;

        fRet = NewGenRandomEx( &RNGContext, pbBuffer, dwLength );
        *pcbRandSeed = RNGContext.cbRandSeed;

        return fRet;
    }

    return NewGenRandomEx( &RNGContext, pbBuffer, dwLength );
}

unsigned int
RSA32API
InitRand(
    IN  OUT unsigned char **ppbRandSeed,
    IN      unsigned long *pcbRandSeed
    )
{

    static BOOL fInitialized = FALSE;

#ifdef KMODE_RNG
    PAGED_CODE();
#endif  // KMODE_RNG

    if( !fInitialized ) {

        InitCircularHash(
                    &g_CircularHashCtx,
                    7,
                    CH_ALG_MD4,
                    0   // CH_MODE_FEEDBACK
                    );

        //
        // get prior seed.
        //

        ReadSeed( g_VeryLargeHash, sizeof( g_VeryLargeHash ) );

        fInitialized = TRUE;
    }

    if( ppbRandSeed != NULL && pcbRandSeed != NULL && *pcbRandSeed != 0 )
        UpdateCircularHash( &g_CircularHashCtx, *ppbRandSeed, *pcbRandSeed );

    return TRUE;
}

unsigned int
RSA32API
DeInitRand(
    IN  OUT unsigned char *pbRandSeed,
    IN      unsigned long cbRandSeed
    )
{
    PBYTE       pbCircularHash;
    DWORD       cbCircularHash;

#ifdef KMODE_RNG
    PAGED_CODE();
#endif  // KMODE_RNG

    if( pbRandSeed == NULL || cbRandSeed == 0 )
        return TRUE;

    if(GetCircularHashValue( &g_CircularHashCtx, &pbCircularHash, &cbCircularHash )) {

        unsigned long cbToCopy;

        if( cbRandSeed > cbCircularHash ) {
            cbToCopy = cbCircularHash;
        } else {
            cbToCopy = cbRandSeed;
        }

        memcpy(pbRandSeed, pbCircularHash, cbToCopy);
    }

    return TRUE;
}

unsigned int
RSA32API
InitializeRNG(
    VOID *pvReserved
    )
{
    void *pvCtx;
    void *pvOldCtx;

#ifdef KMODE_RNG
    PAGED_CODE();
#endif  // KMODE_RNG

    if( g_RC4SafeCtx ) {
        return TRUE;
    }

    if(!rc4_safe_startup( &pvCtx )) {
        return FALSE;
    }

    pvOldCtx = INTERLOCKEDCOMPAREEXCHANGEPOINTER( &g_RC4SafeCtx, pvCtx, NULL );

    if( pvOldCtx ) {

        //
        // race condition occured during init.
        //

        rc4_safe_shutdown( pvCtx );
    }

    return TRUE;
}

void
RSA32API
ShutdownRNG(
    VOID *pvReserved
    )
{
    void *pvCtx;
    HKEY hKey;

#ifdef KMODE_RNG
    PAGED_CODE();
#endif  // KMODE_RNG

    pvCtx = InterlockedExchangePointer( &g_RC4SafeCtx, NULL );

    if( pvCtx ) {
        rc4_safe_shutdown( pvCtx );
    }

#ifndef KMODE_RNG
{
    HANDLE hFile;
    hFile = InterlockedExchangePointer( &g_hKsecDD, NULL );

    if( hFile ) {
        CloseHandle( hFile );
    }
}
#endif

#if 0
    // TODO later: finish logic for caching registry key.
    hKey = InterlockedExchangePointer( &g_hKeySeed, NULL );

    if( hKey ) {
        REGCLOSEKEY( hKey );
    }
#endif

}

BOOL
GenRandom (
    IN      PVOID hUID,
        OUT BYTE *pbBuffer,
    IN      size_t dwLength
    )
{
    DWORD           dwBytesThisPass;
    DWORD           dwFilledBytes;

#ifdef KMODE_RNG
    PAGED_CODE();
#endif  // KMODE_RNG

    dwFilledBytes = 0;

    // break request into chunks that we rekey between
    while(dwFilledBytes < dwLength)
    {
        dwBytesThisPass = dwLength - dwFilledBytes;

        if(!RandomFillBuffer(
                pbBuffer + dwFilledBytes,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -