2025-11-28 00:35:46 +09:00

218 lines
7.0 KiB
C++

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// File: KeyDerivation.cpp
//
// Contents: This sample shows how to derive bytes from a secret
// using BCryptKeyDerivation API.
//
//
#define WIN32_NO_STATUS
#include <windows.h>
#undef WIN32_NO_STATUS
#include <winternl.h>
#include <ntstatus.h>
#include <winerror.h>
#include <stdio.h>
#include <sal.h>
#include "KeyDerivation.h"
//
// Utilities and helper functions
//
//----------------------------------------------------------------------------
//
// ReportError
// Prints error information to the console
//
//----------------------------------------------------------------------------
void
ReportError(
_In_ DWORD dwErrCode
)
{
wprintf( L"Error: 0x%08x (%d)\n", dwErrCode, dwErrCode );
}
//----------------------------------------------------------------------------
//
// PerformKeyDerivation
//
//----------------------------------------------------------------------------
NTSTATUS
PeformKeyDerivation(
_In_ DWORD ArrayIndex
)
{
NTSTATUS Status;
BCRYPT_ALG_HANDLE KdfAlgHandle = NULL;
BCRYPT_KEY_HANDLE SecretKeyHandle = NULL;
DWORD ResultLength = 0;
PBYTE DerivedKey = NULL;
DWORD DerivedKeyLength = 0;
Status = BCryptOpenAlgorithmProvider(
&KdfAlgHandle, // Alg Handle pointer
KdfAlgorithmNameArray[ArrayIndex],
// Cryptographic Algorithm name (null terminated unicode string)
NULL, // Provider name; if null, the default provider is loaded
0); // Flags
if( !NT_SUCCESS(Status) )
{
ReportError(Status);
goto cleanup;
}
Status = BCryptGenerateSymmetricKey(
KdfAlgHandle, // Algorithm Handle
&SecretKeyHandle, // A pointer to a key handle
NULL, // Buffer that recieves the key object;NULL implies memory is allocated and freed by the function
0, // Size of the buffer in bytes
(PBYTE) Secret, // Buffer that contains the key material
sizeof(Secret), // Size of the buffer in bytes
0); // Flags
if( !NT_SUCCESS(Status) )
{
ReportError(Status);
goto cleanup;
}
//
// Derive the key
//
DerivedKeyLength = DERIVED_KEY_LEN;
DerivedKey = (PBYTE)HeapAlloc(GetProcessHeap(), 0, DerivedKeyLength);
if( NULL == DerivedKey )
{
Status = STATUS_NO_MEMORY;
ReportError(Status);
goto cleanup;
}
// Generic parameters:
// KDF_GENERIC_PARAMETER and KDF_HASH_ALGORITHM are the generic parameters that can be passed for the following KDF algorithms:
// BCRYPT_SP800108_CTR_HMAC_ALGORITHM
// KDF_GENERIC_PARAMETER = KDF_LABEL||0x00||KDF_CONTEXT
// BCRYPT_SP80056A_CONCAT_ALGORITHM
// KDF_GENERIC_PARAMETER = KDF_ALGORITHMID || KDF_PARTYUINFO || KDF_PARTYVINFO {|| KDF_SUPPPUBINFO } {|| KDF_SUPPPRIVINFO }
// BCRYPT_PBKDF2_ALGORITHM
// KDF_GENERIC_PARAMETER = KDF_SALT
// BCRYPT_CAPI_KDF_ALGORITHM
// KDF_GENERIC_PARAMETER = Not used
//
// Alternatively, KDF specific parameters can be passed.
// For BCRYPT_SP800108_CTR_HMAC_ALGORITHM:
// KDF_HASH_ALGORITHM, KDF_LABEL and KDF_CONTEXT are required
// For BCRYPT_SP80056A_CONCAT_ALGORITHM:
// KDF_HASH_ALGORITHM, KDF_ALGORITHMID, KDF_PARTYUINFO, KDF_PARTYVINFO are required
// KDF_SUPPPUBINFO, KDF_SUPPPRIVINFO are optional
// For BCRYPT_PBKDF2_ALGORITHM
// KDF_HASH_ALGORITHM is required
// KDF_ITERATION_COUNT, KDF_SALT are optional
// Iteration count, (if not specified) will default to 10,000
// For BCRYPT_CAPI_KDF_ALGORITHM
// KDF_HASH_ALGORITHM is required
//
//
// This sample uses KDF specific parameters defined in KeyDerivation.h
//
Status = BCryptKeyDerivation(
SecretKeyHandle, // Handle to the password key
&ParamList[ArrayIndex], // Parameters to the KDF algorithm
DerivedKey, // Address of the buffer which recieves the derived bytes
DerivedKeyLength, // Size of the buffer in bytes
&ResultLength, // Variable that recieves number of bytes copied to above buffer
0); // Flags
if( !NT_SUCCESS(Status) )
{
ReportError(Status);
goto cleanup;
}
//
// DerivedKeyLength bytes have been derived
//
cleanup:
if( NULL != DerivedKey )
{
HeapFree( GetProcessHeap(), 0, DerivedKey);
DerivedKey = NULL;
}
if( NULL != SecretKeyHandle )
{
Status = BCryptDestroyKey(SecretKeyHandle);
if( !NT_SUCCESS(Status) )
{
ReportError(Status);
}
SecretKeyHandle = NULL;
}
if( NULL != KdfAlgHandle )
{
Status = BCryptCloseAlgorithmProvider(KdfAlgHandle,0);
if( !NT_SUCCESS(Status) )
{
ReportError(Status);
}
KdfAlgHandle = NULL;
}
return Status;
}
//-----------------------------------------------------------------------------
//
// wmain
//
//-----------------------------------------------------------------------------
DWORD
__cdecl
wmain(
_In_ int argc,
_In_reads_(argc) LPWSTR argv[]
)
{
NTSTATUS Status = STATUS_SUCCESS;
DWORD i = 0 ;
for( i=0; i<ARRAYSIZE(KdfAlgorithmNameArray); i++ )
{
Status = PeformKeyDerivation(i);
if( !NT_SUCCESS(Status) )
{
ReportError(Status);
goto exit;
}
} // for loop
exit:
return (DWORD)Status;
UNREFERENCED_PARAMETER( argc );
UNREFERENCED_PARAMETER( argv );
}