Path: blob/master/libs/symcrypt/inc/symcrypt_low_level.h
15010 views
//1// SymCrypt_low_level.h2//3// Copyright (c) Microsoft Corporation. Licensed under the MIT license.4//56#pragma once789#ifdef __cplusplus10extern "C" {11#endif1213//=======================================================================================14// WARNING: The low-level APIs are not stable, and can change from release to release.15// The low-level APIs are only provided for certain exceptional use cases.16// All aspects of the low-level API can change in any release.17// Users are strongly advised to only rely on the API surface defined in symcrypt.h18//=======================================================================================192021//22// Low level asymmetric algorithm API. This is not to be used by external callers.23//2425/**************************************************************************************************26Low-level Integer API27**************************************************************************************************28The low-level API allows manipulation of arbitrarily large integers.2930The internal representation of large integers is not fixed. It depends on CPU architecture and31on the CPU features available on the exact CPU stepping the current software is running on.32In other words, it can change between different executions of the same binary.33Therefore it is critical that callers refrain from making assumptions about the internal34data format used. SymCrypt numbers should only be manipulated through the SymCrypt35API.3637The low-level API allows the caller to allocate the necessary memory for all objects.38This is typically necessary for high-IRQL level callers, callers running in low-memory39environments, and high-performance scenarios where memory has to be pre-allocated.40SymCrypt also provides routines for allocating objects, which makes the API easier41to use. The caller has to provide the allocation functions that SymCrypt uses.4243Internal data representation, and consequently the size of objects, can depend on the44exact CPU stepping the code is running on.45For robustness, the allocation size requirements are compile-time properties;46they vary per CPU architecture but do not depend on the exact available CPU features.4748General rules:49The functions in the low-level API can impose requirements on their inputs. It is imperative that50these requirements are satisfied for every call; failing to satisfy the requirements leads to undefined51behaviour, including bugchecks, access violations, wrong results, or sometimes even the right result.52CHKed versions of the library add more low-level consistency checks; all binaries should be tested53with a CHKed version of the library to detect any errors that might go unnoticed on FRE versions.5455Scratch space:56Many functions in the API require temporary storage for intermediate results.57Some function simply allocate the necessary memory using the caller-provided allocation routines.58Other low-level functions are so fast that the overhead of the allocations would significantly slow59down the computations. These functions require the caller to allocate the memory; this memory60is called the scratch space.6162For each function that requires scratch space, there is a macro that determines how much scratch space63must be provided. This macro is a compile-time function of its arguments; if the parameters to the macro64are compile-time constants, then the result is also a compile-time constant. Therefore that65the macro can be used for statically sizing arrays.66The scratch space macros are all non-decreasing in each argument.67Callers that perform multiple operations can use a single scratch space, sized for the largest68argument(s) used. Note that the SYMCRYPT_C_MAX macro implements a compile-time MAX function suitable69for combining different scratch space sizes at compile time.7071The scratch space is always passed as a pair or arguments: (pbScratch, cbScratch).72cbScratch needs to be at least as large as the macro definition requires, but may be larger.7374Functions that take scratch parameters do not require memory allocation, and will not fail due to75low-memory conditions.76All functions that use memory allocation will return an error indication if a necessary memory77allocation fails. These functions return an error code, or an object pointer which will be NULL if78the allocation fails.79Functions that do not return an error code or object pointer do not use memory allocation.8081SymCrypt uses several implementation techniques to minimize the cost of the scratch space parameters.82This is necessary because the cost of the parameter passing by itself is significant in scenarios83such as elliptic-curve operations.84In a FRE build, some functions will ignore the cbScratch parameter and simply assume they get enough space;85in this case the SymCrypt may provide an inline-able function that allow the compiler to optimize the cbScratch parameter86away, completely removing it from the actual code.87In environments where some functions don't need any scratch space, similar optimizations are possible for the88pbScratch parameter.8990Scratch and object buffers must all be aligned to SYMCRYPT_ALIGN.9192*/9394//95// General flags96//97// SYMCRYPT_FLAG_DATA_PUBLIC is used to signal that the data being processed is public, and does not have98// to be protected from side-channel attacks.99#define SYMCRYPT_FLAG_DATA_PUBLIC (0x01)100101/*102INTEGERS103104Integers are internally represented as a sequence of Digits. An INT object with n digits can store105numbers up to (but not including) R^n where R is the _radix_ of the representation.106107The radix R, as well as the size and format of a Digit, are internal to the library,108and can depend on CPU architecture, CPU stepping and other run-time decisions. Therefore, callers109need to be especially careful not to make any assumptions about the size of a digit, or the number110of digits needed for any particular computation.111112At the same time, most INT operations are defined in terms of Digit sizes, so the caller has to113be aware of digits. This becomes important in the following example. Suppose the radix R =2^256,114and a caller wants to multiply two 384-bit numbers. It takes 2 digits to store a 384-bit number.115The caller knows that the product is 768 bits, which can fit in 3 digits. So the caller might try116to multiply two 2-digit numbers into a 3-digit result, which will not work as the result is 4 digits.117118For an INT object of n digits we call the value R^n the capacity of the object. It is the upper bound of119the values that can be stored in the object.120121Additionally, there is a maximum number of bits for any integer value that the library supports (2^20 bits122in the current version). This bound is used to ensure that no object sizes and scratch space computations123have a value of magnitude more than 32 bits. Note that the computed upper bounds are very loose and the124actual values are much smaller.125126Attempts to create objects larger than this bound will result in NULL being returned. Callers either have127to ensure they do not exceed the bounds, or check that create objects are not NULL before using them. The128rationale behind this approach is to avoid any potential route for malicious inputs to trigger DoS by129taking excessive CPU time which would be indistinguishable from an application hang.130131132Digit size and radix can vary widely; on some CPU steppings the library might use a digit that contains133128 bits are requires 16 bytes of memory, on another CPU stepping it might use a digit that contains134416 bits and uses 64 bytes of memory.135136SAL annotations:137Because the different run-time selected implementations underneath this API might use138different size memory buffers for any one operation, fully accurate SAL annotations are not possible as SAL only139performs static analysis.140Furthermore, adding size parameters to every function would add too much overhead, and sizes are often passed141implicitly. Together with the fact that the same API can be implemented by different implementations, this means142that it isn't possible to write the actual size used in a form that SAL can understand.143Instead we use the following conventions:144- Pointers to SYMCRYPT_* objects can only be created with functions that provide the right memory buffer size.145- We annotate each object-pointer with _In_ our _Out_. The SAL engine treats this as just a read/write to146a single object at the pointer location147- The CHKed version of SymCrypt adds run-time checking that the various size parameters are correct.148This allows us to have both high performance and good checking of our memory management.149150API rationale:151One important choice in this API is whether to pass a (ptr,len) for each INT or just a pointer.152We investigated this issue. The ptr-based API means that there are fewer parameters to pass around,153and generally makes the API simpler. The downside of a ptr-based API is that each INT object has some overhead154and this makes arrays of large integers less efficient, especially since the overhead can be a whole alignment155block.156The problem with the (ptr,len) format is that it isn't clear what length measure to use.157Using the bitsize is inefficient; the internal format might store 29 bits of the number in each 32-bit word,158and that means that the code would have to divide the bitsize by 29 just to find the size of the number.159Division is slow, and therefore this is not a good choice.160Another idea is to have the len parameter be the length of the INT object, in bytes.161But some APIs get really messy. For example, we need an API function to do a multiplication of two same-sized162numbers into a double-sized number. This is such a common operation that we want a separate function for it.163But the storage size of the result might not be twice the storage size of the inputs; if each number has some164fixed overhead then the output object might be smaller than the two times the size of the input objects.165This makes it impossible to write suitable SAL annotations.166For this reason, we use a ptr-based API for integers.167168Most crypto algorithms that wish to store arrays of values actually want to store arrays of elements in a169ring modulo an modulus. And for modular operations the caller is already passing the modulus separately, so170there isn't any need to store per-object size information. The API is designed to allow the ModElement for bitsize171B to be smaller than an INT for bitsize B so that implementations can choose to not store any length information in172a ModElement object.173*/174175//========================================================================176//========================================================================177// Main schema for object creation, deletion, and management (low - level calls).178//179// The following are descriptions of some of the generic functions specifically180// modified for the INT, DIVISOR, MODULUS, and MODELEMENT objects.181182//183// PSYMCRYPT_XXX184// SYMCRYPT_CALL185// SymCryptXxxCreate(186// _Out_writes_bytes_( cbBuffer ) PBYTE pbBuffer,187// SIZE_T cbBuffer,188// UINT32 nDigits );189// Create an XXX object from the provided (pbBuffer, cbBuffer) space.190// The object will be able to store values up to R^nDigits where R is the digit radix.191// Requirement:192// - 1 <= nDigits <= SymCryptDigitsFromBits(SYMCRYPT_INT_MAX_BITS)193// If the value is outside these bounds it will return NULL194// - cbBuffer >= SymCryptSizeofXxxFromDigits( nDigits )195// - (pbBuffer,cbBuffer) memory must be exclusively used by this object.196// The last requirement ensures that all objects are non-overlapping (except for API functions197// that explicitly create overlapping objects).198// All parameters are published.199// It is always safe to choose200// cbBuffer = SYMCRYPT_SIZEOF_XXX_FROM_BITS( nBits )201// nDigits = SymCryptDigitsFromBits( nBits )202// if the caller wants to be able to store numbers up to 2^nBits. However, it is frequently more203// efficient to use cbBuffer = SymCryptSizeofXxxFromDigits( nDigits ) as that gives the exact size for the204// current CPU stepping rather than the compile-time largest size that might be needed on any stepping.205//206// PSYMCRYPT_XXX207// SYMCRYPT_CALL208// SymCryptXxxRetrieveHandle( _In_ PBYTE pbBuffer );209// Retrieve the object's handle from the pointer to the memory space in which the object was created via210// a call to SymCryptXxxCreate. This function allows callers to tightly store arrays of objects without having211// to keep track of each object handle.212// Requirement:213// - A call to SymCryptXxxRetrieveHandle( pbBuffer1 ) must be preceded by at least one call to214// SymCryptXxxCreate( pbBuffer2, cbBuffer2, nDigits ) with ( pbBuffer1 == pbBuffer2 )215// If the requirement is not satisfied the result is undefined.216//217// #define SYMCRYPT_SIZEOF_XXX_FROM_BITS( nBits ) ...218// Returns a memory size that is always sufficient to create an XXX object that can handle219// values of size nBits bits, irrespective of the run-time decision of digit size.220// This is a non-decreasing compile-time function of its inputs, suitable for computing static memory allocations.221// It is always true that222// SYMCRYPT_SIZEOF_XXX_FROM_BITS( n ) >= SymCryptSizeofXxxFromDigits( SymCryptDigitsFromBits( n ) )223// which guarantees that the n-bit XXX can be stored in a memory area of SYMCRYPT_SIZEOF_XXX_FROM_BITS(n) bytes.224// Warning: It is possible that225// SYMCRYPT_SIZEOF_XXX_FROM_BITS( n+m ) < SymCryptSizeofXxxFromDigits( SymCryptDigitsFromBits( n ) + SymCryptDigitsFromBits( m ) )226// for some inputs n and m. This is easy to see if you choose n = m = 1; each represents a 1-digit value, but an n+m bit (i.e. a 2-bit ) value is227// also 1 digit.228// In particular, you cannot use SYMCRYPT_SIZEOF_XXX_FROM_BITS( n + m ) to compute the size229// necessary to store the product of two numbers with bitsize n and m respectively.230// It is guaranteed that231// SymCryptSizeofXxxFromDigits( SymCryptDigitsFromBits( n ) + SymCryptDigitsFromBits( m ) ) <=232// SYMCRYPT_SIZEOF_XXX_FROM_BITS( n ) + SYMCRYPT_SIZEOF_XXX_FROM_BITS( m )233// This is the proper way to statically compute the size needed to store the product of an n- and m-bit value.234//235// UINT32236// SYMCRYPT_CALL237// SymCryptSizeofXxxFromDigits( UINT32 nDigits );238// Memory size that is sufficient to store an XXX object with nDigits digits.239// This is a runtime function as the # digits and size of a digit are run-time decision that depend on the CPU stepping.240// Requirement:241// - 1 <= nDigits <= SymCryptDigitsFromBits(SYMCRYPT_INT_MAX_BITS)242// If the value is outside these bounds the returned value will be 0 indicating failure.243// This function is has the following property:244// SymCryptSizeofXxxFromDigits( a + b ) <= SymCryptSizeofXxxFromDigits( a ) + SymCryptSizeofXxxFromDigits( b )245// for all a and b.246//247// UINT32248// SYMCRYPT_CALL249// SymCryptXxxBitsizeOfObject( PCSYMCRYPT_XXX pObj )250// Return the number of bits of the object.251//252// UINT32253// SYMCRYPT_CALL254// SymCryptXxxDigitsizeOfObject( PCSYMCRYPT_XXX pObj )255// Return the number of digits of the object.256//257258//==============================================================================================259// Object types for low-level API260//261// SYMCRYPT_INT integer in range 0..N for some N262// SYMCRYPT_DIVISOR an integer > 0 that can be used to divide with.263// SYMCRYPT_MODULUS a value M > 1 to use in modulo-M computations264// SYMCRYPT_MODELEMENT An element in a modulo-M ring.265// SYMCRYPT_ECPOINT A point on an elliptic curve.266//267// See symcrypt_internal.h for definitions.268//269270//========================================================================271//========================================================================272// General functions for integers273//274275UINT32276SymCryptDigitsFromBits( UINT32 nBits );277//278// Returns the # digits needed to store values (INT, DIVISOR, MODULUS, MODELEMENT)279// in the range 0..(2^nBits - 1).280//281// Remarks:282// If nBits==0 the returned number is 1.283//284// If nBits exceeds SYMCRYPT_INT_MAX_BITS the function will return 0 to indicate an object with285// this many bits is not supported.286//287// This is a run-time decision; the return value can depend on the exact CPU stepping288// the program is running on, or run-time configurations.289// For a and b in the range 0..SYMCRYPT_INT_MAX_BITS, it is always true that290// SymCryptDigitsFromBits( a + b ) <= SymCryptDigitsFromBits( a ) + SymCryptDigitsFromBits( b )291//292293//========================================================================294// INT objects295//296297PSYMCRYPT_INT298SYMCRYPT_CALL299SymCryptIntAllocate( UINT32 nDigits );300301VOID302SYMCRYPT_CALL303SymCryptIntFree( _Out_ PSYMCRYPT_INT piObj );304305#define SYMCRYPT_SIZEOF_INT_FROM_BITS( _bitsize ) SYMCRYPT_INTERNAL_SIZEOF_INT_FROM_BITS( _bitsize )306307UINT32308SYMCRYPT_CALL309SymCryptSizeofIntFromDigits( UINT32 nDigits );310311PSYMCRYPT_INT312SYMCRYPT_CALL313SymCryptIntCreate(314_Out_writes_bytes_( cbBuffer ) PBYTE pbBuffer,315SIZE_T cbBuffer,316UINT32 nDigits );317318VOID319SYMCRYPT_CALL320SymCryptIntWipe( _Out_ PSYMCRYPT_INT piObj );321322VOID323SYMCRYPT_CALL324SymCryptIntCopy(325_In_ PCSYMCRYPT_INT piSrc,326_Out_ PSYMCRYPT_INT piDst ); // **** Documentation lacking: requires same size327328VOID329SYMCRYPT_CALL330SymCryptIntMaskedCopy(331_In_ PCSYMCRYPT_INT piSrc,332_Inout_ PSYMCRYPT_INT piDst,333UINT32 mask );334335VOID336SYMCRYPT_CALL337SymCryptIntConditionalCopy(338_In_ PCSYMCRYPT_INT piSrc,339_Inout_ PSYMCRYPT_INT piDst,340UINT32 cond );341342VOID343SYMCRYPT_CALL344SymCryptIntConditionalSwap(345_Inout_ PSYMCRYPT_INT piSrc1,346_Inout_ PSYMCRYPT_INT piSrc2,347UINT32 cond );348349UINT32350SYMCRYPT_CALL351SymCryptIntBitsizeOfObject( _In_ PCSYMCRYPT_INT piSrc );352353UINT32354SYMCRYPT_CALL355SymCryptIntDigitsizeOfObject( _In_ PCSYMCRYPT_INT piSrc );356357//========================================================================358// DIVISOR objects359//360361PSYMCRYPT_DIVISOR362SYMCRYPT_CALL363SymCryptDivisorAllocate( UINT32 nDigits );364365VOID366SYMCRYPT_CALL367SymCryptDivisorFree( _Out_ PSYMCRYPT_DIVISOR pdObj );368369#define SYMCRYPT_SIZEOF_DIVISOR_FROM_BITS( _bitsize ) SYMCRYPT_INTERNAL_SIZEOF_DIVISOR_FROM_BITS( _bitsize )370371UINT32372SYMCRYPT_CALL373SymCryptSizeofDivisorFromDigits( UINT32 nDigits );374375PSYMCRYPT_DIVISOR376SYMCRYPT_CALL377SymCryptDivisorCreate(378_Out_writes_bytes_( cbBuffer ) PBYTE pbBuffer,379SIZE_T cbBuffer,380UINT32 nDigits );381382VOID383SYMCRYPT_CALL384SymCryptDivisorWipe( _Out_ PSYMCRYPT_DIVISOR pdObj );385386VOID387SymCryptDivisorCopy(388_In_ PCSYMCRYPT_DIVISOR pdSrc,389_Out_ PSYMCRYPT_DIVISOR pdDst );390391UINT32392SYMCRYPT_CALL393SymCryptDivisorDigitsizeOfObject( _In_ PCSYMCRYPT_DIVISOR pdSrc );394395//========================================================================396// MODULUS objects397//398399PSYMCRYPT_MODULUS400SYMCRYPT_CALL401SymCryptModulusAllocate( UINT32 nDigits );402403VOID404SYMCRYPT_CALL405SymCryptModulusFree( _Out_ PSYMCRYPT_MODULUS pmObj );406407#define SYMCRYPT_SIZEOF_MODULUS_FROM_BITS( _bitsize ) SYMCRYPT_INTERNAL_SIZEOF_MODULUS_FROM_BITS( _bitsize )408409UINT32410SYMCRYPT_CALL411SymCryptSizeofModulusFromDigits( UINT32 nDigits );412413PSYMCRYPT_MODULUS414SYMCRYPT_CALL415SymCryptModulusCreate(416_Out_writes_bytes_( cbBuffer ) PBYTE pbBuffer,417SIZE_T cbBuffer,418UINT32 nDigits );419420VOID421SYMCRYPT_CALL422SymCryptModulusWipe( _Out_ PSYMCRYPT_MODULUS pmObj );423424VOID425SymCryptModulusCopy(426_In_ PCSYMCRYPT_MODULUS pmSrc,427_Out_ PSYMCRYPT_MODULUS pmDst );428429UINT32430SYMCRYPT_CALL431SymCryptModulusDigitsizeOfObject( _In_ PCSYMCRYPT_MODULUS pmSrc );432433//========================================================================434// MODELEMENT objects are treated slightly differently because it does not store its own size.435// This allows a MODELEMENT to be more compact which makes large arrays of ModElements more efficient436// and avoids checking that ModElements have the same size.437// All operations require a modulus to be passed.438//439440PSYMCRYPT_MODELEMENT441SYMCRYPT_CALL442SymCryptModElementAllocate( _In_ PCSYMCRYPT_MODULUS pmMod );443444VOID445SYMCRYPT_CALL446SymCryptModElementFree(447_In_ PCSYMCRYPT_MODULUS pmMod, // only used to determine the digit size of peObj.448_Out_ PSYMCRYPT_MODELEMENT peObj );449450#define SYMCRYPT_SIZEOF_MODELEMENT_FROM_BITS( _bitsize ) SYMCRYPT_INTERNAL_SIZEOF_MODELEMENT_FROM_BITS( _bitsize )451452UINT32453SYMCRYPT_CALL454SymCryptSizeofModElementFromModulus( PCSYMCRYPT_MODULUS pmMod );455456PSYMCRYPT_MODELEMENT457SYMCRYPT_CALL458SymCryptModElementCreate(459_Out_writes_bytes_( cbBuffer ) PBYTE pbBuffer,460SIZE_T cbBuffer,461_In_ PCSYMCRYPT_MODULUS pmMod );462463VOID464SYMCRYPT_CALL465SymCryptModElementWipe(466_In_ PCSYMCRYPT_MODULUS pmMod,467_Out_ PSYMCRYPT_MODELEMENT peDst );468469VOID470SymCryptModElementCopy(471_In_ PCSYMCRYPT_MODULUS pmMod,472_In_ PCSYMCRYPT_MODELEMENT peSrc,473_Out_ PSYMCRYPT_MODELEMENT peDst );474475VOID476SymCryptModElementMaskedCopy(477_In_ PCSYMCRYPT_MODULUS pmMod,478_In_ PCSYMCRYPT_MODELEMENT peSrc,479_Out_ PSYMCRYPT_MODELEMENT peDst,480UINT32 mask );481482VOID483SymCryptModElementConditionalSwap(484_In_ PCSYMCRYPT_MODULUS pmMod,485_Inout_ PSYMCRYPT_MODELEMENT peData1,486_Inout_ PSYMCRYPT_MODELEMENT peData2,487_In_ UINT32 cond );488489//========================================================================490// ECURVE objects491492BOOLEAN493SYMCRYPT_CALL494SymCryptEcurveBufferSizesFromParams(495_In_ PCSYMCRYPT_ECURVE_PARAMS pParams,496_Out_ SIZE_T * pcbCurve,497_Out_ SIZE_T * pcbScratch );498//499// This call computes the memory size necessary to create the ECURVE object described by pParams,500// including the amount of scratch space needed for the operation.501//502// Returns FALSE if the given parameters are deemed invalid.503//504505PSYMCRYPT_ECURVE506SYMCRYPT_CALL507SymCryptEcurveCreate(508_In_ PSYMCRYPT_ECURVE_PARAMS pParams,509_In_ UINT32 flags,510_Out_writes_bytes_( cbCurve ) PBYTE pbCurve,511SIZE_T cbCurve,512_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,513SIZE_T cbScratch );514//515// Use caller-allocated memory to create an ECURVE object which516// is defined by the parameters in pParams.517//518// - pParams: parameters that define the curve519// - flags: Not used, must be zero.520// - pbCurve: caller-allocated memory region to hold the curve object521// - cbCurve: size of memory region to hold the curve object522// - pbScratch: caller-allocated memory region used as scratch space to create the curve523// - cbScratch: size of scratch space memory region524//525// Caller should use SymCryptSizeofEcurveBuffersFromParams to determine the necessary sizes for526// pbCurve and pbScratch. These buffers must be SYMCRYPT_ALIGNed.527//528// Future versions might use the flags to enable different features/tradeoffs.529// There are a number of interesting memory/speed/pre-computation cost trades that can be made.530// For example, pre-computing multiples of the distinguished point, or (parallel?) pre-computation531// of (r, rG) pairs for random r values.532//533// This function applies limited validation of the pParams. The validation is intended to eliminate534// the threat of denial-of-service when hostile parameters are presented. It does not ensure that535// the parameters make sense, define a proper curve, or that any elliptic-curve operations made on536// the curve built from these parameters will fail, succeed or provide any security.537// The only guarantee provided for invalid parameters is that all operations on this curve will538// not crash and will return in some reasonable amount of time.539//540// Returns NULL if the given memory regions are not large enough or the541// parameters are deemed invalid. If the return value is not NULL, then542// pbCurve buffer must later be wiped with SymCryptWipe(). And as with all543// pbScratch buffers, it is the caller's responsibility to wipe after544// completing all operations that require scratch space.545//546547//========================================================================548// ECPOINT objects' API is slightly different than the above API schema in the sense that they549// take as input an ECURVE object pointer instead of the number of digits.550//551552PSYMCRYPT_ECPOINT553SYMCRYPT_CALL554SymCryptEcpointAllocate( _In_ PCSYMCRYPT_ECURVE pCurve );555556VOID557SYMCRYPT_CALL558SymCryptEcpointFree(559_In_ PCSYMCRYPT_ECURVE pCurve,560_Out_ PSYMCRYPT_ECPOINT poDst );561562UINT32563SYMCRYPT_CALL564SymCryptSizeofEcpointFromCurve( PCSYMCRYPT_ECURVE pCurve );565566PSYMCRYPT_ECPOINT567SYMCRYPT_CALL568SymCryptEcpointCreate(569_Out_writes_bytes_( cbBuffer ) PBYTE pbBuffer,570SIZE_T cbBuffer,571_In_ PCSYMCRYPT_ECURVE pCurve );572// The above can take as input a pointer to a curve that has only the FMod, cbModElement, and the573// eformat fields set574575PSYMCRYPT_ECPOINT576SYMCRYPT_CALL577SymCryptEcpointRetrieveHandle( _In_ PBYTE pbBuffer );578579VOID580SYMCRYPT_CALL581SymCryptEcpointWipe(582_In_ PCSYMCRYPT_ECURVE pCurve,583_Out_ PSYMCRYPT_ECPOINT poDst );584585VOID586SymCryptEcpointCopy(587_In_ PCSYMCRYPT_ECURVE pCurve,588_In_ PCSYMCRYPT_ECPOINT poSrc,589_Out_ PSYMCRYPT_ECPOINT poDst );590591VOID592SymCryptEcpointMaskedCopy(593_In_ PCSYMCRYPT_ECURVE pCurve,594_In_ PCSYMCRYPT_ECPOINT poSrc,595_Out_ PSYMCRYPT_ECPOINT poDst,596UINT32 mask );597598599//========================================600// Integer operations601//602603SYMCRYPT_ERROR604SYMCRYPT_CALL605SymCryptIntCopyMixedSize(606_In_ PCSYMCRYPT_INT piSrc,607_Out_ PSYMCRYPT_INT piDst );608//609// Dst = Src, but allows Dst and Src to have different # digits.610//611// Copy the value from piSrc to piDst.612// Returns success if Src < R^Dst.nDigits613// If Src >= R^Dst.nDigits then the value in Src is published and an error is returned.614// Warning: it is not side-channel safe to use this function with a Src value that can't fit in Dst.615// Src and Dst may be the same object.616//617618UINT32619SYMCRYPT_CALL620SymCryptIntBitsizeOfValue( _In_ PCSYMCRYPT_INT piSrc );621//622// Returns the number of bits necessary to store the value of Src.623//624// Let V be the value of Src.625// Then this function returns626// 0 if Src == 0627// 1 + floor( log(Src)/log(2) ) if V > 0628// Note that there is no defined relationship between the result of this function and the bitsize used to allocate Src.629// Digits can be large, so the value Src might be able to store values much larger than 2^b where b is the bitsize630// used when creating Src.631// This function is side-channel safe, and as a result might be slower than expected.632//633634635VOID636SYMCRYPT_CALL637SymCryptIntSetValueUint32(638UINT32 u32Src,639_Out_ PSYMCRYPT_INT piDst );640//641// Dst = Src642// This always succeeds as R >= 2^32 on all implementations.643//644645VOID646SYMCRYPT_CALL647SymCryptIntSetValueUint64(648UINT64 u64Src,649_Out_ PSYMCRYPT_INT piDst );650//651// Dst = Src652// This always succeeds as R >= 2^64 on all implementations.653//654655656//========================================================================================657// Read/write INTegers in defined formats658//659660SYMCRYPT_ERROR661SYMCRYPT_CALL662SymCryptIntSetValue(663_In_reads_bytes_(cbSrc) PCBYTE pbSrc,664SIZE_T cbSrc,665SYMCRYPT_NUMBER_FORMAT format,666_Out_ PSYMCRYPT_INT piDst );667//668// Set the value of an INT object from an array of bytes669//670// (pbSrc,cbSrc): buffer that contains the bytes that encode the value in the specified format.671// format: specifies the format of the pbBytes/cbBytes buffer.672// Dst : INT object that receives the value; must previously have been created/allocated.673//674// Return value:675// If the value encoded in the (pbSrc,cbSrc) buffer fits in Dst, then the676// function succeeds. If the value does not fit, then the function677// returns an error. Note that the error condition is only dependent on the value in the input,678// and not on how many bytes are in the input. Importing a very large (pbSrc,cbSrc) buffer679// into a small piDst is fine as long as the value fits in the number (i.e. enough of the most significant680// bytes in the buffer are zero).681//682// Warning:683// Error return values are always published, so if this function fails it is visible to the attacker.684//685// Rationale:686// Because the size of a digit can be any size (even odd) there are always scenarios in which the687// caller can provide an input that is too large for the INT to store. (Restricting only the size of688// the input buffer is not sufficient.) And if we have to handle this689// in one case, we might as well handle it in all cases.690//691692SYMCRYPT_ERROR693SYMCRYPT_CALL694SymCryptIntGetValue(695_In_ PCSYMCRYPT_INT piSrc,696_Out_writes_bytes_( cbDst) PBYTE pbDst,697SIZE_T cbDst,698SYMCRYPT_NUMBER_FORMAT format );699//700// Convert a value from the internal number representation to a byte array.701//702// Src is the number whose value is to be stored in a byte array703// (pbDst, cbDst) the destination buffer704// format: the destination format.705// Return value: if the value of Src when encoded in the format fits in the output buffer then the function succeeds.706// If the encoded value does not fit, the function returns an error. (Note: All errors are published.)707//708709UINT32710SYMCRYPT_CALL711SymCryptIntGetValueLsbits32( _In_ PCSYMCRYPT_INT piSrc );712//713// Returns Src mod 2^32714//715// Usecase: there are many number-theoretic algorithms where the algorithm716// depends on (n mod 8) or similar values.717//718719UINT64720SYMCRYPT_CALL721SymCryptIntGetValueLsbits64( _In_ PCSYMCRYPT_INT piSrc );722//723// Returns Src mod 2^64724//725// Usecase: RSA public exponents can be 64 bits, and validating that726// a candidate prime is suitable uses this function727//728729UINT32730SYMCRYPT_CALL731SymCryptIntIsEqualUint32(732_In_ PCSYMCRYPT_INT piSrc1,733_In_ UINT32 u32Src2 );734//735// Returns a mask value which is 0xffffffff if Src1 = Src2 and 0 otherwise.736//737738UINT32739SYMCRYPT_CALL740SymCryptIntIsEqual(741_In_ PCSYMCRYPT_INT piSrc1,742_In_ PCSYMCRYPT_INT piSrc2 );743//744// Returns a mask value which is 0xffffffff if Src1 = Src2 and 0 otherwise.745//746// Note that Src1 and Src2 can be of different sizes.747//748749UINT32750SYMCRYPT_CALL751SymCryptIntIsLessThan(752_In_ PCSYMCRYPT_INT piSrc1,753_In_ PCSYMCRYPT_INT piSrc2 );754//755// Returns a mask value which is 0xffffffff if Src1 < Src2 and 0 otherwise.756//757// Note that a <= b is equivalent to NOT( b < a ) so all possible comparisons758// can be made using the < and = comparison primitive.759//760761762//=============================================================763// Addition & subtraction764// For all addition and subtraction operations, the destination may be765// the same object as one of the inputs if the other requirements of the function766// allow that.767//768769UINT32770SYMCRYPT_CALL771SymCryptIntAddUint32(772_In_ PCSYMCRYPT_INT piSrc1,773UINT32 u32Src2,774_Out_ PSYMCRYPT_INT piDst );775//776// Dst = Src1 + Src2.777// Requirement: Dst.nDigits == Src1.nDigits778// If the result is larger than the capacity of Dst, then779// Dst is set to the result minus the capacity and the value 1 is returned.780// Otherwise the Dst is set to the sum and the value 0 is returned.781// The return value is thus a carry output of the addition.782//783784UINT32785SYMCRYPT_CALL786SymCryptIntAddSameSize(787_In_ PCSYMCRYPT_INT piSrc1,788_In_ PCSYMCRYPT_INT piSrc2,789_Out_ PSYMCRYPT_INT piDst );790//791// Dst = Src1 + Src2.792// Requirement: Src1.nDigits == Src2.nDigits == Dst.nDigits793// In more detail:794// if Src1 + Src2 < Dst.capacity:795// Dst = Src1 + Src2796// return 0797// else798// Dst = Src1 + Src2 - Dst.capacity799// return 1800// The return value is a carry output of the addition.801//802// Dst may be the same object as Src1, Src2, or both.803//804805UINT32806SYMCRYPT_CALL807SymCryptIntAddMixedSize(808_In_ PCSYMCRYPT_INT piSrc1,809_In_ PCSYMCRYPT_INT piSrc2,810_Out_ PSYMCRYPT_INT piDst );811//812// Dst = Src1 + Src2.813// Requirement: Dst.nDigits >= max( Src1.nDigits, Src2.nDigits )814// In more detail:815// if Src1 + Src2 < Dst.capacity:816// Dst = Src1 + Src2817// return 0818// else819// Dst = Src1 + Src2 - Dst.capacity820// return 1821// The return value is a carry output of the addition.822//823// Dst may be the same object as Src1, Src2, or both.824//825826//827// Subtraction828// Subtraction functions are the equivalent of addition functions.829// The return value is 1 if an underflow occurred (borrow), and 0 if no underflow/borrow occurred.830// On underflow, the value of the result is the result of the subtraction plus Dst.capacity.831//832// Rationale: For an underflow we could also return (UINT32)-1 or return -1 on a INT32.833// -1 in an unsigned type is actually 2^32 -1 which makes no sense.834// Returning a signed type is somewhat neater, but all other values are unsigned, and mixing835// signed and unsigned types is always error-prone. Furthermore, converting from a signed integer836// to a mask is also error-prone (at least within the behaviour guaranteed by the C standard.)837// Returning an unsigned 1 is therefore preferred.838//839840UINT32841SYMCRYPT_CALL842SymCryptIntSubUint32(843_In_ PCSYMCRYPT_INT piSrc1,844UINT32 Src2,845_Out_ PSYMCRYPT_INT piDst );846847UINT32848SYMCRYPT_CALL849SymCryptIntSubSameSize(850_In_ PCSYMCRYPT_INT piSrc1,851_In_ PCSYMCRYPT_INT piSrc2,852_Out_ PSYMCRYPT_INT piDst );853854UINT32855SYMCRYPT_CALL856SymCryptIntSubMixedSize(857_In_ PCSYMCRYPT_INT piSrc1,858_In_ PCSYMCRYPT_INT piSrc2,859_Out_ PSYMCRYPT_INT piDst );860861VOID862SYMCRYPT_CALL863SymCryptIntNeg(864_In_ PCSYMCRYPT_INT piSrc,865_Out_ PSYMCRYPT_INT piDst );866867//868// Dst = (- Src) mod Dst.Capacity;869// Requirement:870// - Dst.nDigits == Src.nDigits;871// This is a negate modulo the capacity.872// Useful when you want the absolute value of a difference.873// Compute the difference, and if the subtraction yields a carry, negate the result.874//875876//===================================================================877// Shifts878// Note that the shift amount is always published.879// If the need arises, we can define variants that are side-channel safe880// w.r.t. the shift size, but that incurs a significant performance cost.881//882883VOID884SYMCRYPT_CALL885SymCryptIntMulPow2(886_In_ PCSYMCRYPT_INT piSrc,887SIZE_T exp,888_Out_ PSYMCRYPT_INT piDst );889//890// Dst = (Src * 2^Exp ) mod R^n where n = Dst.nDigits.891// Requirement: Dst.nDigits == Src.nDigits, Dst == Src is allowed892// Exp is published.893//894// A variant that keeps Exp private is currently not available, but can be added to the API if needed.895// (A side-channel safe variant might require scratch space.)896//897// Dst may be the same object as Src1.898//899900VOID901SYMCRYPT_CALL902SymCryptIntDivPow2(903_In_ PCSYMCRYPT_INT piSrc,904SIZE_T exp,905_Out_ PSYMCRYPT_INT piDst );906//907// Dst = (Src div 2^Exp )908// Requirement: Dst.nDigits == Src.nDigits, Dst == Src is allowed909// Exp is published910//911// A variant that keeps Exp private is currently not available, but can be added to the API if needed.912// (A side-channel safe variant might require scratch space.)913//914// Dst may be the same object as Src1.915//916917VOID918SYMCRYPT_CALL919SymCryptIntShr1(920UINT32 highestBit,921_In_ PCSYMCRYPT_INT piSrc,922_Out_ PSYMCRYPT_INT piDst );923//924// Dst = (Src + highestBit * Src.Capacity) div 2925//926// Requirements:927// Src.nDigits == Dst.nDigits928// highestBit <= 1929//930// This is the Int equivalent of the 'shift right 1' instruction.931// Shifting by one can be implemented faster than variable sized shifts.932//933934VOID935SYMCRYPT_CALL936SymCryptIntModPow2(937_In_ PCSYMCRYPT_INT piSrc,938SIZE_T exp,939_Out_ PSYMCRYPT_INT piDst );940//941// Dst = Src mod 2^Exp942// Requirement: Dst.nDigits == Src.nDigits, Dst == Src is allowed943// Exp is published944//945// Dst may be the same object as Src1.946//947948UINT32949SYMCRYPT_CALL950SymCryptIntGetBit(951_In_ PCSYMCRYPT_INT piSrc,952UINT32 iBit );953//954// Returns the i-th bit (starting from 0 for the LSB) of piSrc.955// Therefore the only possible return values are 0 and 1.956//957// Requirements:958// - iBit < SymCryptIntBitsizeOfObject( piSrc )959//960961UINT32962SYMCRYPT_CALL963SymCryptIntGetBits(964_In_ PCSYMCRYPT_INT piSrc,965UINT32 iBit,966UINT32 nBits );967//968// Returns the bits from position iBit up to (iBit + nBits - 1)969// (starting from 0 for the LSB). Total of nBits. The 0-th bit of970// the return value corresponds to the iBit-th bit of the source.971//972// Requirements:973// - 1 <= nBits <= 32974// - iBit + nBits <= SymCryptIntBitsizeOfObject( piSrc )975//976// Remarks:977// - The values iBit and nBits are not protected by side-channel attacks,978// therefore they should be treated as published.979// - The bits of the return value after the (nBits)-th bit are zero.980//981982VOID983SYMCRYPT_CALL984SymCryptIntSetBits(985_In_ PSYMCRYPT_INT piDst,986UINT32 value,987UINT32 iBit,988UINT32 nBits );989//990// Sets the bits from position iBit up to (iBit + nBits - 1)991// (starting from 0 for the LSB). Total of nBits. The 0-th bit of992// the input value corresponds to the iBit-th bit of the destination.993//994// Requirements:995// - 1 <= nBits <= 32996// - iBit + nBits <= SymCryptIntBitsizeOfObject( piSrc )997//998// Remarks:999// - The values iBit and nBits are not protected by side-channel attacks,1000// therefore they should be treated as published.1001// - The bits of the value after the (nBits)-th bit are ignored.1002//10031004//===========================================================1005// Mul & div1006//10071008UINT321009SYMCRYPT_CALL1010SymCryptIntMulUint32(1011_In_ PCSYMCRYPT_INT piSrc1,1012UINT32 Src2,1013_Out_ PSYMCRYPT_INT piDst );1014//1015// Dst = Src1 * Src2 mod Dst.capacity; return value = Src1 * Src2 div Dst.capacity1016// Requirement: piDst.nDigits == piSrc1.nDigits, Dst == Src is allowed1017//10181019#define SYMCRYPT_SCRATCH_BYTES_FOR_INT_MUL( _nResultDigits ) SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_INT_MUL( _nResultDigits )10201021VOID1022SYMCRYPT_CALL1023SymCryptIntMulSameSize(1024_In_ PCSYMCRYPT_INT piSrc1,1025_In_ PCSYMCRYPT_INT piSrc2,1026_Out_ PSYMCRYPT_INT piDst,1027_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1028SIZE_T cbScratch );1029//1030// Dst = Src1 * Src2.1031// Requirement:1032// - Src1.nDigits == Src2.nDigits; Dst.nDigits == Src1.nDigits + Src2.nDigits1033// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_INT_MUL( Dst.nDigits )1034//1035// Note that Dst cannot be the same object as Src1 or Src2 because of the size restrictions.1036//10371038VOID1039SYMCRYPT_CALL1040SymCryptIntSquare(1041_In_ PCSYMCRYPT_INT piSrc,1042_Out_ PSYMCRYPT_INT piDst,1043_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1044SIZE_T cbScratch );1045//1046// Dst = Src^21047// Requirement:1048// - Dst.nDigits == 2 * Src.nDigits1049// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_INT_MUL( Dst.nDigits )1050//1051// Note that Dst cannot be the same object as Src1 or Src2 because of the size restrictions.1052//10531054VOID1055SYMCRYPT_CALL1056SymCryptIntMulMixedSize(1057_In_ PCSYMCRYPT_INT piSrc1,1058_In_ PCSYMCRYPT_INT piSrc2,1059_Out_ PSYMCRYPT_INT piDst,1060_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1061SIZE_T cbScratch );1062//1063// Dst = Src1 * Src2.1064// Requirement:1065// - Dst.nDigits >= Src1.nDigits + Src2.nDigits1066// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_INT_MUL( Dst.nDigits )1067//1068// Note that Dst cannot be the same object as Src1 or Src2 because of the size restrictions.1069//107010711072//1073// Division1074// For all division and modulo operations, there are pre-computations that have to be done1075// on the divisor. The pre-computed divisor information is stored in a DIVISOR object.1076// Note that the bitsize of the value of the divisor is published.1077// Therefore, a generic division is not side-channel safe.1078// Rationale: Hiding the bitsize of the value of the divisor is quite expensive,1079// and we have no cryptographic algorithms that require it.1080//108110821083PSYMCRYPT_INT1084SYMCRYPT_CALL1085SymCryptIntFromDivisor( _In_ PSYMCRYPT_DIVISOR pdSrc );1086//1087// Returns the INT object inside the DIVISOR object.1088// Digit size of the INT object is equal to the digit size of the DIVISOR object.1089// This object has two uses:1090// - On an uninitialized DIVISOR object it is a suitable place to put a value before calling1091// SymCryptIntToDivisor.1092// - On an initialized DIVISOR object the function returns a pointer to the INT that contains1093// the divisor value. Modifying the INT value from an initialized DIVISOR value corrupts1094// the divisor value.1095//1096// This is typically a very fast function, with a run-time cost that is zero or only one instruction.1097//10981099#define SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_DIVISOR( _nDigits ) SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_INT_TO_DIVISOR( _nDigits )11001101VOID1102SYMCRYPT_CALL1103SymCryptIntToDivisor(1104_In_ PCSYMCRYPT_INT piSrc,1105_Out_ PSYMCRYPT_DIVISOR pdDst,1106UINT32 totalOperations,1107UINT32 flags,1108_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1109SIZE_T cbScratch );1110//1111// Create a DIVISOR object from an INT.1112// Requirement:1113// - Dst.nDigits == Src.nDigits1114// - Src != 01115// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_DIVISOR( Src.nDigits )1116// SymCryptIntBitsizeOfValue( Src ) is published.1117// Src may be equal to SymCryptIntFromDivisor( Dst ).1118// totalOperations is an estimate of how many divide/modulo operations will be performed with this divisor.1119// An implementation may use this to decide how much pre-computations to do.1120// flags: any combination of the following flag values:1121// - SYMCRYPT_FLAG_DATA_PUBLIC1122// Signals that the Src value is public.1123// Implementations can use this to use more efficient divisor algorithms depending on the actual value of Src.1124// For example, if Src is very close to a power of 2, division can be implemented more efficiently.1125//1126// Once a divisor object has been created, it is immutable.1127// Multiple threads can use the same divisor object for different division operations in parallel.1128//11291130#define SYMCRYPT_SCRATCH_BYTES_FOR_INT_DIVMOD( _nSrcDigits, _nDivisorDigits ) SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_INT_DIVMOD( _nSrcDigits, _nDivisorDigits )11311132VOID1133SYMCRYPT_CALL1134SymCryptIntDivMod(1135_In_ PCSYMCRYPT_INT piSrc,1136_In_ PCSYMCRYPT_DIVISOR pdDivisor,1137_Out_opt_ PSYMCRYPT_INT piQuotient,1138_Out_opt_ PSYMCRYPT_INT piRemainder,1139_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1140SIZE_T cbScratch );1141//1142// Quotient = Src div Divisor1143// Remainder = Src mod Divisor1144// Quotient & Remainder may be NULL in which case that result is not returned.1145// Requirements:1146// - Quotient.nDigits >= Src.nDigits1147// - Remainder.nDigits >= Divisor.nDigits1148// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_INT_DIVMOD( Src.nDigits, Divisor.nDigits )1149// Quotient and Remainder must be different objects.1150// Src may be the same object as either Quotient or Remainder.1151//11521153#define SYMCRYPT_SCRATCH_BYTES_FOR_EXTENDED_GCD( _nDigits ) SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_EXTENDED_GCD( _nDigits )11541155VOID1156SYMCRYPT_CALL1157SymCryptIntExtendedGcd(1158_In_ PCSYMCRYPT_INT piSrc1,1159_In_ PCSYMCRYPT_INT piSrc2,1160UINT32 flags,1161_Out_opt_ PSYMCRYPT_INT piGcd,1162_Out_opt_ PSYMCRYPT_INT piLcm,1163_Out_opt_ PSYMCRYPT_INT piInvSrc1ModSrc2,1164_Out_opt_ PSYMCRYPT_INT piInvSrc2ModSrc1,1165_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1166SIZE_T cbScratch );1167//1168// Compute up to four results from Src1 and Src2.1169// GCD is the greatest common divisor of Src1 and Src2.1170// LCM is the Least Common Multiple of Src1 and Src2.1171// InvSrc1ModSrc2 is the smallest value such that (InvSrc1ModSrc2 * Src1) mod Src2= GCD( Src1, Src2 )1172// UNLESS Src1 is a multiple of Src2, i.e. when Src1 = 0 mod Src2. In this case the result is1173// undefined.1174// InvSrc2ModSrc1 is the smallest value such that (InvSrc2ModSrc1 * Src2) mod Src1= GCD( Src1, Src2 )1175// UNLESS Src2 is a multiple of Src1, i.e. when Src2 = 0 mod Src1. In this case the result is1176// undefined.1177//1178// The last two modular inverse values are not true modular inverses unless GCD( Src1, Src2 ) = 1.1179//1180// Any of the output pointers can be NULL and then that result is not returned.1181// Requirements:1182// - Src1 > 01183// - Src2 > 0 and Src2 odd1184// - Gcd.nDigits >= min( Src1.nDigits, Src2.nDigits )1185// - Lcm.nDigits >= Src1.nDigits + Src2.nDigits1186// - InvSrc1ModSrc2.nDigits >= max(Src1.nDigits, Src2.nDigits) // Future work: Make these bounds Src2 and Src1 respectively.1187// - InvSrc2ModSrc1.nDigits >= max(Src1.nDigits, Src2.nDigits)1188// - if piInvSrc2ModSrc1 is not NULL, max( Src1.nDigits, Src2.nDigits ) * 2 <= SymCryptDigitsFromBits(SYMCRYPT_INT_MAX_BITS)1189// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_EXTENDED_GCD( max( Src1.nDigits, Src2.nDigits ) )1190//1191// If only one inverse value is needed, it is most efficient to use only InvSrc1ModSrc2.1192//1193// The restriction that Src2 must be odd can be removed in a future version.1194// The SYMCRYPT_FLAG_DATA_PUBLIC flag signals that the inputs are public information and do not have1195// to be side-channel protected.1196// The SYMCRYPT_FLAG_GCD_INPUTS_NOT_BOTH_EVEN signals that at least one input is odd. This speeds up the1197// side-channel safe implementation; this flag is not needed if the inputs are signaled as public as the code can then1198// afford to check that condition and change use a optimized algorithm.1199// The SYMCRYPT_FLAG_GCD_PUBLIC signals that the GCD value is public. This can make some computations1200// (of the inverses) more efficient when GCD = 1.1201//12021203#define SYMCRYPT_FLAG_GCD_INPUTS_NOT_BOTH_EVEN (0x02)1204#define SYMCRYPT_FLAG_GCD_PUBLIC (0x04)120512061207UINT641208SYMCRYPT_CALL1209SymCryptUint64Gcd( UINT64 a, UINT64 b, UINT32 flags );1210//1211// Return GCD of two 64-bit integers.1212// a, b : inputs to the GCD1213// flags:1214// - SYMCRYPT_FLAG_DATA_PUBLIC signals that a and b are public values (w.r.t. side-channel safety)1215// This may improve performance.1216// - SYMCRYPT_FLAG_GCD_INPUTS_NOT_BOTH_EVEN: signals that at least one of (a,b) is odd. This1217// simplifies & speeds up the GCD computation.1218//1219// Note:1220// The current implementation requires that the INPUTS_NOT_BOTH_EVEN flag is set (and at least one input be odd).1221// Also note that GCD(x, 0) == GCD(0, x) == x1222//122312241225#define SYMCRYPT_SCRATCH_BYTES_FOR_CRT_GENERATION( _nDigits ) SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_CRT_GENERATION( _nDigits )12261227SYMCRYPT_ERROR1228SYMCRYPT_CALL1229SymCryptCrtGenerateInverses(1230UINT32 nCoprimes,1231_In_reads_( nCoprimes ) PCSYMCRYPT_MODULUS * ppmCoprimes,1232UINT32 flags,1233_Out_writes_( nCoprimes ) PSYMCRYPT_MODELEMENT * ppeCrtInverses,1234_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1235SIZE_T cbScratch );1236//1237// Compute the Chinese Remainder Theorem (CRT) constants for a set of nCoprimes1238// pairwise coprime moduli. Pointers to the input numbers are stored in the array of1239// pointers ppmCoprimes, while the outputs are stored to the locations pointed by1240// ppeCrtInverses.1241//1242// For input numbers Src1, Src2, ..., SrcK where K = nCoprimes, let N = Src1*Src2*...*SrcK.1243// Then this function outputs the constants:1244// (( Src1 / N ) mod Src1), (( Src2 / N ) mod Src2), ..., (( SrcK / N ) mod SrcK)1245//1246// The most common case is for the RSA algorithm where the inputs are 2 prime numbers P and Q1247// and only Q^{-1} mod P is needed (i.e. only the first term of the output array).1248//1249// Any of the output pointers in the ppeCrtInverses can be NULL and then that result1250// is not returned (resulting in a faster total running time).1251//1252// The number of inputs nCoprimes and which outputs are returned is public.1253//1254// Requirements:1255// - nCoprimes >= 21256// - Both ppmCoprimes and ppeCrtInverses must be arrays of pointers of exactly nCoprimes pointers.1257// - ppmCoprimes[i] != NULL for all i in [0, nCoprimes-1].1258// - The input moduli must be pairwise coprime.1259// - The number of digits of all input moduli must match the number of digits of the corresponding1260// output modelements.1261// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_CRT_GENERATION( nDigits ) where nDigits is the maximum number1262// of digits of the inputs and outputs.1263//12641265#define SYMCRYPT_SCRATCH_BYTES_FOR_CRT_SOLUTION( _nDigits ) SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_CRT_SOLUTION( _nDigits )12661267SYMCRYPT_ERROR1268SYMCRYPT_CALL1269SymCryptCrtSolve(1270UINT32 nCoprimes,1271_In_reads_( nCoprimes ) PCSYMCRYPT_MODULUS * ppmCoprimes,1272_In_reads_( nCoprimes ) PCSYMCRYPT_MODELEMENT * ppeCrtInverses,1273_In_reads_( nCoprimes ) PCSYMCRYPT_MODELEMENT * ppeCrtRemainders,1274UINT32 flags,1275_Out_ PSYMCRYPT_INT piSolution,1276_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1277SIZE_T cbScratch );1278//1279// Solve for x the system of nCoprimes congruences of the form1280// x = ppeCrtRemainders[0] (mod ppmCoprimes[0])1281// x = ppeCrtRemainders[1] (mod ppmCoprimes[1])1282// ...1283// x = ppeCrtRemainders[nCoprimes-1] (mod ppmCoprimes[nCoprimes-1])1284//1285// The input array ppeCrtInverses must have been pre-computed by a call to SymCryptCrtGenerateInverses.1286//1287// The number of inputs nCoprimes is public.1288//1289// Requirements:1290// - nCoprimes == 21291// - ppmCoprimes, ppeCrtInverses, and ppeCrtRemainders must be arrays of pointers of exactly nCoprimes elements. All1292// of them non-NULL.1293// - piSolution must be large enough to hold the result modulo the product of all the coprimes.1294// - max( ppmCoprimes[0].nDigits, ppmCoprimes[1].nDigits ) * 2 <= SymCryptDigitsFromBits(SYMCRYPT_INT_MAX_BITS)1295// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_CRT_SOLUTION( nDigits ) where nDigits is the maximum number1296// of digits of the input moduli.1297//129812991300typedef const struct _SYMCRYPT_TRIALDIVISION_CONTEXT *PCSYMCRYPT_TRIALDIVISION_CONTEXT;13011302PCSYMCRYPT_TRIALDIVISION_CONTEXT1303SYMCRYPT_CALL1304SymCryptCreateTrialDivisionContext( UINT32 nDigits );1305//1306// Create a trial division context that can be used for integers up to and including nDigits digits.1307// The Trial division context can be used in multiple threads in parallel.1308// The context should be freed with SymCryptFreeTrialDivisionContext after use.1309// A context can be fairly large (100 kB) so freeing it is important.1310// Returns NULL if out of memory or an invalid digit count is provided.1311//13121313VOID1314SYMCRYPT_CALL1315SymCryptFreeTrialDivisionContext( PCSYMCRYPT_TRIALDIVISION_CONTEXT pContext );1316//1317// Free the trial division context after use.1318//13191320UINT321321SYMCRYPT_CALL1322SymCryptIntFindSmallDivisor(1323_In_ PCSYMCRYPT_TRIALDIVISION_CONTEXT pContext,1324_In_ PCSYMCRYPT_INT piSrc,1325_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1326SIZE_T cbScratch );1327//1328// Returns a divisor of piSrc, or zero.1329// Requirements:1330// Requirement:1331// - pContext is a valid trial division context, and Context.nDigits >= Src.nDigits1332// - Src >= 21333// Note:1334// - Src is published if this function returns a divisor.1335//1336// There is no guarantee that this function finds small divisors;1337// it is valid for the implementation to always return 0.1338// Any nonzero return value is always >= 2 and an actual divisor of Src.1339// Note: this function might not find 2 as a small divisor.1340//13411342#define SYMCRYPT_SCRATCH_BYTES_FOR_INT_IS_PRIME( _nDigits ) SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_INT_IS_PRIME( _nDigits )13431344UINT321345SYMCRYPT_CALL1346SymCryptIntMillerRabinPrimalityTest(1347_In_ PCSYMCRYPT_INT piSrc,1348UINT32 nBitsSrc,1349UINT32 nIterations,1350UINT32 flags,1351_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1352SIZE_T cbScratch );1353//1354// Applies the Miller-Rabin prime testing algorithm using nIterations on the integer1355// piSrc.1356//1357// The maximum bitsize of the value of piSrc is equal to nBitsSrc and it is public.1358// The number of iterations nIterations is also public.1359//1360// If the return value is 0, then Src is guaranteed to be a composite value.1361// In this case, the value of Src is treated as public.1362//1363// If the return value is 0xffffffff, then Src might be prime.1364// In this case, the value of Src is treated as private except when the1365// SYMCRYPT_FLAG_DATA_PUBLIC flag is specified.1366//1367// If the flag SYMCRYPT_FLAG_DATA_PUBLIC is specified the1368// algorithm leaks the number of trailing zeros of Src-1. The reason for1369// not having a fully side-channel safe implementation for arbitrary1370// numbers is that such a function would be prohibitively slow.1371//1372// Requirements:1373// - SymCryptIntBitsizeOfValue( piSrc ) <= nBitsSrc <= SymCryptIntBitsizeOfObject( piSrc )1374// - Src is odd and greater than 3.1375// - If flags == 0 then Src must be 3 modulo 4. (See the comment above for1376// the SYMCRYPT_FLAG_DATA_PUBLIC flag)1377// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_INT_IS_PRIME( Src.nDigits )1378//13791380//13811382#define SYMCRYPT_SCRATCH_BYTES_FOR_INT_PRIME_GEN( _nDigits ) SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_INT_PRIME_GEN( _nDigits )13831384SYMCRYPT_ERROR1385SYMCRYPT_CALL1386SymCryptIntGenerateRandomPrime(1387_In_ PCSYMCRYPT_INT piLow,1388_In_ PCSYMCRYPT_INT piHigh,1389_In_reads_opt_( nPubExp ) PCUINT64 pu64PubExp,1390UINT32 nPubExp,1391UINT32 nTries,1392UINT32 flags,1393_Inout_ PSYMCRYPT_INT piDst,1394_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1395SIZE_T cbScratch );1396//1397// This function generates a random prime Dst such that1398// Dst == 3 mod 4 and1399// Low <= Dst < High1400// for e in PubExp[]: GCD( Dst - 1, e ) == 11401//1402// (pu64PubExp, nPubExp) can be (NULL, 0) if no pubexp restriction is needed.1403// The nTries parameter specifies the maximum number of candidate numbers1404// until a prime number is found satisfying the above restrictions.1405// If the function cannot find one after nTries, it returns SYMCRYPT_INVALID_ARGUMENT1406// (For example, if the caller passes in a Low bound bigger than the High bound,1407// or if there are no primes between Low and High).1408//1409// The values of the pubexps, piLow and piHigh are public.1410//1411// flags: None1412//1413// Requirements:1414// - SymCryptIntBitsizeOfValue( piHigh ) <= SymCryptIntBitsizeOfObject(piDst)1415// - piLow > 31416// - Each public exponent must be greater than 01417// - 0 <= nPubExp <= SYMCRYPT_RSAKEY_MAX_NUMOF_PUBEXPS1418// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_INT_PRIME_GEN( Dst.nDigits )1419//14201421//=====================================================1422// Modular arithmetic1423//1424// To perform modular arithmetic the modulus has to be prepared into a Modulus object.1425// Arithmetic in the ring modulo the modulus can then be done using ModElement objects.1426//14271428PSYMCRYPT_DIVISOR1429SYMCRYPT_CALL1430SymCryptDivisorFromModulus( _In_ PSYMCRYPT_MODULUS pmSrc );1431//1432// Returns the DIVISOR object inside the MODULUS object.1433//1434// Digit size of the DIVISOR object is equal to the digit size of the MODULUS object.1435// This object has one use:1436// - On an initialized MODULUS object the function returns a pointer to the DIVISOR that contains1437// the modulus value. Modifying the DIVISOR value from an initialized MODULUS value corrupts1438// the modulus.1439//1440// This is typically a very fast function, with a run-time cost that is zero or one instruction.1441//14421443PSYMCRYPT_INT1444SYMCRYPT_CALL1445SymCryptIntFromModulus( _In_ PSYMCRYPT_MODULUS pmSrc );1446//1447// Returns the INT object inside the MODULUS object.1448//1449// Digit size of the INT object is equal to the digit size of the MODULUS object.1450// This object has two uses:1451// - On an uninitialized MODULUS object it is a suitable place to put a value before calling1452// SymCryptIntToModulus.1453// - On an initialized MODULUS object the function returns a pointer to the INT that contains1454// the modulus value. Modifying the INT value from an initialized MODULUS value corrupts1455// the modulus.1456//1457// This is typically a very fast function, with a run-time cost that is zero or one instruction.1458//14591460#define SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_MODULUS( _nDigits ) SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_INT_TO_MODULUS( _nDigits )14611462VOID1463SYMCRYPT_CALL1464SymCryptIntToModulus(1465_In_ PCSYMCRYPT_INT piSrc,1466_Out_ PSYMCRYPT_MODULUS pmDst,1467UINT32 averageOperations,1468UINT32 flags,1469_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1470SIZE_T cbScratch );1471//1472// Create a modulus from an INT.1473// Requirements:1474// - Src != 01475// - Dst.nDigits == Src.nDigits1476// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_MODULUS( Src.nDigits )1477// SymCryptIntBitsizeOfValue( Src ) is published.1478// averageOperations is the average number of multiplications that are performed on a ModElement created with this modulus between the time that the value is1479// created as a ModElement and the time it is exported out of modElement form.1480// There are multiple ways of doing modular computations; some of them are faster but have an overhead for converting into and out of modular form.1481// For example, for RSA verification the # operations is small and conversion overhead should be avoided.1482// For RSA signatures, the # operations is large and the fastest per-operation form should be used.1483// This parameter allows the library to select the right kind of modular arithmetic for this modulus.1484// The following flags are supported:1485// SYMCRYPT_FLAG_DATA_PUBLIC1486// Signals the code that the Src value is public. This may improve performance because it allows further optimizations that1487// depend on the value. (For example, if Src is close to a power of 2, the modulo reduction can be made significantly faster.)1488// SYMCRYPT_FLAG_MODULUS_PARITY_PUBLIC1489// Signals that the parity of Src (whether it is even or odd) may be treated as a public value.1490// There are some algorithms that can speed up operations on odd moduli, but their use publishes the fact that the modulus is odd.1491// SYMCRYPT_FLAG_MODULUS_ADDITIVE_ONLY1492// The modulus will only be used for addition and subtraction, not for multiplication or division.1493// This can significantly reduce the cost of this function as there is no need to pre-compute the divisor information.1494// SYMCRYPT_FLAG_MODULUS_PRIME1495// Signals that the modulus is a prime. Some algorithms can be more efficient for prime moduli. Note that setting this flag1496// for a non-prime modulus can result in incorrect answers.1497// The flags and averageOperations parameters are published.1498//14991500#define SYMCRYPT_FLAG_MODULUS_PARITY_PUBLIC (0x02)1501#define SYMCRYPT_FLAG_MODULUS_ADDITIVE_ONLY (0x04)1502#define SYMCRYPT_FLAG_MODULUS_PRIME (0x08)15031504#define SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( _nDigits ) SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( _nDigits )150515061507VOID1508SYMCRYPT_CALL1509SymCryptIntToModElement(1510_In_ PCSYMCRYPT_INT piSrc,1511_In_ PCSYMCRYPT_MODULUS pmMod,1512_Out_ PSYMCRYPT_MODELEMENT peDst,1513_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1514SIZE_T cbScratch );1515//1516// Dst = Src mod Mod1517// Requirements:1518// - Dst.nDigits == Mod.nDigits1519// - piSrc.nDigits <= 2 * Mod.nDigits1520// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( Mod.nDigits )1521//1522// Note: the input is limited in size to be no more than twice the modulus size (in digits).1523// This should be a rare case, and it simplifies the scratch space handling significantly.1524//15251526VOID1527SYMCRYPT_CALL1528SymCryptModElementToInt(1529_In_ PCSYMCRYPT_MODULUS pmMod,1530_In_ PCSYMCRYPT_MODELEMENT peSrc,1531_Out_ PSYMCRYPT_INT piDst,1532_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1533SIZE_T cbScratch );1534//1535// Dst = Src1536//1537// Requirement:1538// - Dst.nDigits >= Mod.nDigits1539// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( Mod.nDigits )1540//1541// Convert a ModElement to an Int.1542// The internal format in which a ModElement is stored might be different1543// from the format of an Int; this function converts the value to the INT format.1544//154515461547SYMCRYPT_ERROR1548SYMCRYPT_CALL1549SymCryptModElementSetValue(1550_In_reads_bytes_( cbSrc ) PCBYTE pbSrc,1551SIZE_T cbSrc,1552SYMCRYPT_NUMBER_FORMAT format,1553PCSYMCRYPT_MODULUS pmMod,1554_Out_ PSYMCRYPT_MODELEMENT peDst,1555_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1556SIZE_T cbScratch );1557//1558// Dst = decode( pbSrc, cbSrc, format ) mod Mod1559// Requirement:1560// - SymCryptDigitsFromBits( 8 * cbSrc ) <= Mod.nDigits1561// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( Mod.nDigits )1562//1563// This is a separate function as it is frequently used, and does not require the allocation of an INT object.1564//15651566VOID1567SYMCRYPT_CALL1568SymCryptModElementSetValueUint32(1569UINT32 value,1570_In_ PCSYMCRYPT_MODULUS pmMod,1571_Out_ PSYMCRYPT_MODELEMENT peDst,1572_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1573SIZE_T cbScratch );1574//1575// Dst = value mod Mod1576// value is published.1577// Requirement:1578// - value < Mod1579// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( Mod.nDigits )1580// Note: this function does NOT hide the value.1581// Rationale: typically the value parameter is known, either 0 or 1.1582//15831584VOID1585SYMCRYPT_CALL1586SymCryptModElementSetValueNegUint32(1587UINT32 value,1588_In_ PCSYMCRYPT_MODULUS pmMod,1589_Out_ PSYMCRYPT_MODELEMENT peDst,1590_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1591SIZE_T cbScratch );1592//1593// Dst = -value mod Mod1594// value is published.1595// Requirement:1596// - 0 < value < Mod1597// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( Mod.nDigits )1598// Note: this function does NOT hide the value.1599// Rationale: typically the value parameter is known, either 0 or 1.1600//160116021603SYMCRYPT_ERROR1604SYMCRYPT_CALL1605SymCryptModElementGetValue(1606PCSYMCRYPT_MODULUS pmMod,1607_In_ PCSYMCRYPT_MODELEMENT peSrc,1608_Out_writes_bytes_( cbDst ) PBYTE pbDst,1609SIZE_T cbDst,1610SYMCRYPT_NUMBER_FORMAT format,1611_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1612SIZE_T cbScratch );1613//1614// (pbDst, cbDst) = encode( format, cbDst, Src )1615// Requirement:1616// - SymCryptDigitsFromBits( 8 * cbDst ) <= Mod.nDigits1617// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( Mod.nDigits )1618//1619// Retrieve the value of a ModElement as an array of bytes1620//16211622UINT321623SYMCRYPT_CALL1624SymCryptModElementIsEqual(1625_In_ PCSYMCRYPT_MODULUS pmMod,1626_In_ PCSYMCRYPT_MODELEMENT peSrc1,1627_In_ PCSYMCRYPT_MODELEMENT peSrc2 );1628//1629// Returns a mask value which is 0xffffffff if Src1 = Src2 and 0 otherwise.1630//1631// Both SYMCRYPT_MODELEMENTs should have been created using the modulus pmMod. Otherwise1632// the result is undefined.1633//16341635UINT321636SYMCRYPT_CALL1637SymCryptModElementIsZero(1638_In_ PCSYMCRYPT_MODULUS pmMod,1639_In_ PCSYMCRYPT_MODELEMENT peSrc );1640//1641// Returns a mask value which is 0xffffffff if Src = 0 and 0 otherwise.1642//1643// Useful for quickly checking if a ModElement is 0.1644//164516461647//===============================1648// Modular arithmetic.1649//16501651VOID1652SYMCRYPT_CALL1653SymCryptModSetRandom(1654_In_ PCSYMCRYPT_MODULUS pmMod,1655_Out_ PSYMCRYPT_MODELEMENT peDst,1656UINT32 flags,1657_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1658SIZE_T cbScratch );1659//1660// Dst = random value modulus Mod.1661// Requirement:1662// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( Mod.nDigits )1663//1664// Random value is chosen uniformly from the set of allowed values.1665// By default this function does not return the values 0, 1, or -1 (see below NOTE for small moduli exception)1666// Flags parameter can signal that these special values are allowed.1667// flags parameter is published.1668//1669// Rationale: these values cause problems in many situations, and for all commonly used cryptographic modulo sizes1670// the absence of these values is statistically undetectable even if they are allowed.1671// For completeness of the API, the flags parameter can be used to allow these three values.1672// flags is a bitmask containing a combination of the following bit values:1673// SYMCRYPT_FLAG_MODRANDOM_ALLOW_ZERO1674// SYMCRYPT_FLAG_MODRANDOM_ALLOW_ONE1675// SYMCRYPT_FLAG_MODRANDOM_ALLOW_MINUSONE1676// Specifying ALLOW_ZERO implies ALLOW_ONE, there is no way to allow 0 and disallow 1.1677//1678// NOTE:1679// For very small moduli (1, 2, and 3), not allowing 0, 1, or -1 by default does not make sense because this would1680// exclude all possible values! Instead the default behavior is to allow -1 for these moduli.1681// Modulo 1 => return 0 by default1682// Modulo 2 => return 1 by default1683// may also return 0 if SYMCRYPT_FLAG_MODRANDOM_ALLOW_ZERO is specified1684// Modulo 3 => return 2 by default1685// may also return 1 if SYMCRYPT_FLAG_MODRANDOM_ALLOW_ONE is specified, and1686// may also return 0 or 1 if SYMCRYPT_FLAG_MODRANDOM_ALLOW_ZERO is specified,1687//1688// Callers relying on not having 0, 1, or -1 are required to pass a larger modulus.16891690#define SYMCRYPT_FLAG_MODRANDOM_ALLOW_ZERO (0x01)1691#define SYMCRYPT_FLAG_MODRANDOM_ALLOW_ONE (0x02)1692#define SYMCRYPT_FLAG_MODRANDOM_ALLOW_MINUSONE (0x04)169316941695VOID1696SYMCRYPT_CALL1697SymCryptModNeg(1698_In_ PCSYMCRYPT_MODULUS pmMod,1699_In_ PCSYMCRYPT_MODELEMENT peSrc,1700_Out_ PSYMCRYPT_MODELEMENT peDst,1701_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1702SIZE_T cbScratch );1703//1704// Dst = -Src mod Mod1705// Requirements:1706// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( Mod.nDigits )1707//17081709VOID1710SYMCRYPT_CALL1711SymCryptModAdd(1712_In_ PCSYMCRYPT_MODULUS pmMod,1713_In_ PCSYMCRYPT_MODELEMENT peSrc1,1714_In_ PCSYMCRYPT_MODELEMENT peSrc2,1715_Out_ PSYMCRYPT_MODELEMENT peDst,1716_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1717SIZE_T cbScratch );1718//1719// Dst = Src1 + Src2 mod Mod1720// Requirement:1721// - Src1.modulus == Src2.modulus == Mod.1722// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( Mod.nDigits )1723// Dst == Src1, Dst == Src2, and Src1 == Src2 are all allowed.1724// Rationale:1725// scratch space can make the mod-add faster for side-channel safe implementations.1726// It allows:1727// Dst = Src1 + Src2;1728// Tmp = Dst - Mod;1729// Dst = choose( Dst, Tmp, carry_bits )1730// And the choose() operation is fast because it does not require carry propagation.1731//173217331734VOID1735SYMCRYPT_CALL1736SymCryptModSub(1737_In_ PCSYMCRYPT_MODULUS pmMod,1738_In_ PCSYMCRYPT_MODELEMENT peSrc1,1739_In_ PCSYMCRYPT_MODELEMENT peSrc2,1740_Out_ PSYMCRYPT_MODELEMENT peDst,1741_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1742SIZE_T cbScratch );1743//1744// Dst = Src1 - Src2 mod Mod1745// Requirement:1746// Same as SymCryptModAdd1747//174817491750VOID1751SYMCRYPT_CALL1752SymCryptModMul(1753_In_ PCSYMCRYPT_MODULUS pmMod,1754_In_ PCSYMCRYPT_MODELEMENT peSrc1,1755_In_ PCSYMCRYPT_MODELEMENT peSrc2,1756_Out_ PSYMCRYPT_MODELEMENT peDst,1757_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1758SIZE_T cbScratch );1759//1760// Dst = Src1 * Src2 mod Mod1761// Requirement:1762// - Src1.modulus == Src2.modulus == Mod.1763// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( Mod.nDigits )1764//17651766VOID1767SYMCRYPT_CALL1768SymCryptModSquare(1769_In_ PCSYMCRYPT_MODULUS pmMod,1770_In_ PCSYMCRYPT_MODELEMENT peSrc,1771_Out_ PSYMCRYPT_MODELEMENT peDst,1772_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1773SIZE_T cbScratch );1774//1775// Dst = Src1^2 mod Mod1776// Requirement:1777// - Src.modulus == Mod.1778// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( Mod.nDigits )1779//17801781VOID1782SYMCRYPT_CALL1783SymCryptModDivPow2(1784_In_ PCSYMCRYPT_MODULUS pmMod,1785_In_ PCSYMCRYPT_MODELEMENT peSrc,1786UINT32 exp,1787_Out_ PSYMCRYPT_MODELEMENT peDst,1788_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1789SIZE_T cbScratch );1790//1791// Dst = Src / 2^exp mod Mod1792// Requirements:1793// - Mod is odd.1794// - Src.modulus == Dst.modulus == Mod.1795// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( Mod.nDigits )1796//1797// Remarks:1798// - The value exp is *** public ***; hence it should be treated as known to the attacker.1799// - This function may write intermediate values to peDst and read them back, violating the1800// read-once/write-once rule, so the caller must ensure that the peDst buffer is trusted.1801//18021803#define SYMCRYPT_SCRATCH_BYTES_FOR_MODINV( _nDigits ) SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_MODINV( _nDigits )18041805// SYMCRYPT_FLAG_DATA_PUBLIC signals that the Src element is public and does not have to be protected1806// against side-channel attacks. The public-ness of the Modulus is part of the Modulus object, specified when the1807// modulus value was set.1808// Marking the source value as public has very little effect on performance, but it removes the random blinding used.1809// The main goal of this flag is to allow ECDSA verification without a source of random numbers.18101811SYMCRYPT_ERROR1812SYMCRYPT_CALL1813SymCryptModInv(1814_In_ PCSYMCRYPT_MODULUS pmMod,1815_In_ PCSYMCRYPT_MODELEMENT peSrc,1816_Out_ PSYMCRYPT_MODELEMENT peDst,1817UINT32 flags,1818_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1819SIZE_T cbScratch );1820//1821// Dst = 1/Src mod Mod.1822//1823// - pmMod: Modulus, must have the SYMCRYPT_FLAG_MODULUS_PRIME and SYMCRYPT_FLAG_DATA_PUBLIC flag set.1824// Non-prime or non-public moduli are currently not supported.1825// - peSrc: Source value, modulo pmMod1826// - peDst: Destination value, mod element modulo pmMod1827// - flags: SYMCRYPT_FLAG_DATA_PUBLIC signals that peSrc is a public value.1828// - pbScratch/cbScratch: scratch space >= SYMCRYPT_SCRATCH_BYTES_FOR_MODINV( nDigits( pmMod ) )1829//1830// Returns an error if1831// - GCD( Src, Mod ) != 11832//18331834#define SYMCRYPT_SCRATCH_BYTES_FOR_MODEXP( _nDigits ) SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_MODEXP( _nDigits )18351836VOID1837SYMCRYPT_CALL1838SymCryptModExp(1839_In_ PCSYMCRYPT_MODULUS pmMod,1840_In_ PCSYMCRYPT_MODELEMENT peBase,1841_In_ PCSYMCRYPT_INT piExp,1842UINT32 nBitsExp,1843UINT32 flags,1844_Out_ PSYMCRYPT_MODELEMENT peDst,1845_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1846SIZE_T cbScratch );1847//1848// Dst = Base ^ Exp mod Mod1849// where only the least significant (nBitsExp) bits of the exponent are used.1850//1851// Requirements:1852// - nBitsExp != 01853// - Mod > 11854// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_MODEXP( Mod.nDigits )1855//1856// Allowed flags:1857// SYMCRYPT_FLAG_DATA_PUBLIC: If set then the algorithm1858// is not side-channel safe (For use in RSA encryption - exponentiation1859// with a public exponent). The default behaviour is side channel safety.1860//1861// Remarks:1862// - The undefined operation 0^0 will return 1.1863// - The value nBitsExp is *** public ***; hence it should be treated as known to the attacker.1864// Examples:1865// - nBitsExp = SymCryptIntBitsizeOfObject( piExp ) => This processes all the1866// bits of the exponent object.1867// - nBitsExp = number of bits of modulus ==> This processes the same1868// number of bits (even leading zeros) as the modulus. In this case1869// the exponent should have a value with bitsize less or equal to the1870// bitsize of the modulus.1871// - nBitsExp = max(1, SymCryptIntBitsizeOfValue( piExp )) => This processes1872// the bits of the exponent ignoring the leading zeros. Therefore, this1873// option leaks the bitsize of the value of the exponent.1874//18751876// SYMCRYPT_MODMULTIEXP_MAX_NBASES, _NBITSEXP: The maximum number of bases1877// and exponent bits allowed for the multi-exponentiation operation.1878#define SYMCRYPT_MODMULTIEXP_MAX_NBASES (8)1879#define SYMCRYPT_MODMULTIEXP_MAX_NBITSEXP (SYMCRYPT_INT_MAX_BITS)18801881#define SYMCRYPT_SCRATCH_BYTES_FOR_MODMULTIEXP( _nDigits, _nBases, _nBitsExp ) SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_MODMULTIEXP( _nDigits, _nBases, _nBitsExp )18821883SYMCRYPT_ERROR1884SYMCRYPT_CALL1885SymCryptModMultiExp(1886_In_ PCSYMCRYPT_MODULUS pmMod,1887_In_reads_( nBases ) PCSYMCRYPT_MODELEMENT * peBaseArray,1888_In_reads_( nBases ) PCSYMCRYPT_INT * piExpArray,1889UINT32 nBases,1890UINT32 nBitsExp,1891UINT32 flags,1892_Out_ PSYMCRYPT_MODELEMENT peDst,1893_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,1894SIZE_T cbScratch );1895//1896// Dst = ( peBaseArray[0]^piExpArray[0] * peBaseArray[1]^piExpArray[1] * ... *1897// peBaseArray[nBases-1]^piExpArray[nBases-1] ) mod Mod1898// where only the least significant (nBitsExp) bits of the exponents are used.1899//1900// Requirements:1901// - 1<= nBitsExp <= SYMCRYPT_MODMULTIEXP_MAX_NBITSEXP1902// - Mod > 11903// - 1<= nBases <= SYMCRYPT_MODMULTIEXP_MAX_NBASES1904// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_MODMULTIEXP( Mod.nDigits, nBases, nBitsExp )1905//1906// Allowed flags:1907// SYMCRYPT_FLAG_DATA_PUBLIC: If set then the algorithm1908// is not side-channel safe (For use in DSA verification).1909// The default behaviour is side channel safety.1910//19111912// =========================================1913// Tools for side-channel safety1914// ========================================19151916//1917//Side-channel safe lookup table1918//19191920typedef struct _SYMCRYPT_SCSTABLE {1921UINT32 groupSize;1922UINT32 interleaveSize;1923UINT32 nElements; // must be multiple of groupSize1924UINT32 elementSize; // # bytes in each element, note: limited to UINT32 for efficiency1925PBYTE pbTableData;1926UINT32 cbTableData;1927} SYMCRYPT_SCSTABLE, *PSYMCRYPT_SCSTABLE;19281929UINT321930SYMCRYPT_CALL1931SymCryptScsTableInit(1932_Out_ PSYMCRYPT_SCSTABLE pScsTable,1933UINT32 nElements,1934UINT32 elementSize );1935// Initializes an ScsTable for nElements elements each of elementSize bytes.1936// nElements and elementSize are limited to less than 2^16.1937// Return value is the size of the buffer that the caller needs to provide.1938//1939// Requirements:1940// - nElements must be a multiple of groupSize and elementSize must be a1941// multiple of interleaveSize. Currently all implementations have as1942// defaults1943// groupSize = 41944// interleaveSize = 81945//19461947VOID1948SYMCRYPT_CALL1949SymCryptScsTableSetBuffer(1950_Inout_ PSYMCRYPT_SCSTABLE pScsTable,1951_Inout_updates_bytes_( cbBuffer ) PBYTE pbBuffer,1952UINT32 cbBuffer );1953// Sets the caller-provided buffer on the ScsTable.1954// cbBuffer should be >= the size returned by the SymCryptScsTableInit function19551956VOID1957SYMCRYPT_CALL1958SymCryptScsTableStore(1959_Inout_ PSYMCRYPT_SCSTABLE pScsTable,1960UINT32 iIndex,1961_In_reads_bytes_( cbData ) PCBYTE pbData,1962UINT32 cbData );1963// Not side-channel safe; publishes iIndex.1964// cbData must match the elementSize i.e. the size of a single element.19651966VOID1967SYMCRYPT_CALL1968SymCryptScsTableLoad(1969_In_ PSYMCRYPT_SCSTABLE pScsTable,1970UINT32 iIndex,1971_Out_writes_bytes_(cbData) PBYTE pbData,1972UINT32 cbData );1973// Side-channel safe fetching of data; iIndex is kept secret.1974// cbData must match the elementSize i.e. the size of a single element.19751976VOID1977SYMCRYPT_CALL1978SymCryptScsTableWipe(1979_Inout_ PSYMCRYPT_SCSTABLE pScsTable );1980// Wipes the part of the buffer that the table used19811982// Other Side-channel safety tools19831984VOID1985SYMCRYPT_CALL1986SymCryptScsRotateBuffer(1987_Inout_updates_( cbBuffer ) PBYTE pbBuffer,1988SIZE_T cbBuffer,1989SIZE_T lshift );1990// Rotates buffer left by lshift without revealing lshift1991// through side channels.1992// - pbBuffer/cbBuffer: buffer to rotate1993// pbBuffer must be aligned to the native integer of the platform (4 or 8 bytes)1994// cbBuffer must be a power of two >= 321995// - lshift: # bytes to left rotate the buffer1996// pbBuffer[0] will get the value pbBuffer[ lshift % cbBuffer ]19971998VOID1999SYMCRYPT_CALL2000SymCryptScsCopy(2001_In_reads_( cbDst ) PCBYTE pbSrc,2002SIZE_T cbSrc,2003_Out_writes_( cbDst ) PBYTE pbDst,2004SIZE_T cbDst );2005// Copy cbSrc bytes of pbSrc into pbDst without revealing cbSrc2006// through side channels.2007//2008// WARNING: pbSrc buffer must be at least cbDst bytes long; not cbSrc!2009//2010// - pbSrc pointer to buffer to copy data from2011// This buffer must be at least cbDst bytes long2012// - cbSrc number of bytes to be copied, must be <= 2^312013// - pbDst destination buffer2014// - pbDst size of the destination buffer, must be <= 2^312015// Equivalent to:2016// n = min( cbSrc, cbDst )2017// pbDst[ 0.. n-1 ] = pbSrc[ 0 .. n - 1 ]2018// cbSrc is protected from side-channels; cbDst is public.201920202021//2022// Mask generation functions.2023// All these functions are side-channel safe in all parameters.2024// Naming convention:2025// SymCrypt <MaskType> <Op> <ParameterType>2026// <MaskType> is the type of the function result:2027// Mask32 UINT32 mask that is 0 or -12028// Mask64 UINT64 mask that is 0 or -12029// <Op> is the boolean operation performed on the parameters2030// IsZero v == 02031// IsNonzero v != 02032// Eq a == b2033// Neq a != b2034// <ParameterType> is an indication of the parameter type supported.2035// U31 UINT32 which is limited to values < 2^312036// This allows more efficient masking functions.2037// U32 UINT322038// Other mask types, operations, and parameter types may be defined in future.2039//20402041UINT322042SYMCRYPT_CALL2043SymCryptMask32IsZeroU31( UINT32 v );20442045UINT322046SYMCRYPT_CALL2047SymCryptMask32IsNonzeroU31( UINT32 v );204820492050UINT322051SYMCRYPT_CALL2052SymCryptMask32EqU32( UINT32 a, UINT32 b );20532054UINT322055SYMCRYPT_CALL2056SymCryptMask32NeqU31( UINT32 a, UINT32 b );20572058UINT322059SYMCRYPT_CALL2060SymCryptMask32LtU31( UINT32 a, UINT32 b );206120622063//2064// Other helper functions2065//2066SIZE_T2067SYMCRYPT_CALL2068SymCryptRoundUpPow2Sizet( SIZE_T v );2069// Round up to the next power of 22070//2071// Requirements:2072// v <= (SIZE_T_MAX / 2) + 12073// i.e. rounding v up to the next power of 2 fits within SIZE_T, so v is2074// less than or equal to the maximum power of 2 representable in SIZE_T207520762077//=====================================================2078//=====================================================2079// RSA padding operations2080//=====================================================2081//=====================================================20822083SYMCRYPT_ERROR2084SYMCRYPT_CALL2085SymCryptRsaPkcs1ApplyEncryptionPadding(2086_In_reads_bytes_( cbPlaintext ) PCBYTE pbPlaintext,2087SIZE_T cbPlaintext,2088_Out_writes_bytes_( cbPkcs1Format ) PBYTE pbPkcs1Format,2089SIZE_T cbPkcs1Format );2090//2091// Applies the RSA PKCS1 v1.5 encryption padding to the plaintext buffer.2092// - Plaintext buffer containing plaintext to be encoded2093// - Pkcs1Format Output buffer, typically the size of the RSA modulus2094// Requirement: cbPkcs1Format >= cbPlaintext + 11 due to the PKCS1 overhead.2095//20962097SYMCRYPT_ERROR2098SYMCRYPT_CALL2099SymCryptRsaPkcs1RemoveEncryptionPadding(2100_Inout_updates_bytes_( cbPkcs1Buffer ) PBYTE pbPkcs1Format,2101SIZE_T cbPkcs1Format,2102SIZE_T cbPkcs1Buffer,2103_Out_writes_bytes_opt_( cbPlaintext ) PBYTE pbPlaintext,2104SIZE_T cbPlaintext,2105_Out_ SIZE_T *pcbPlaintext );2106//2107// Remove the PKCS1 encryption padding and extract the message plaintext.2108// This function is side-channel safe w.r.t. the data in the Pkcs1Format buffer.2109// - pbPkcs1Format points to a buffer containing the raw RSA decrypted data.2110// This buffer will be modified by this function.2111// - cbPkcs1Format is the # bytes of the buffer that were decrypted with raw RSA2112// - cbPkcs1Buffer is the size of the buffer that pbPkcs1Format points to2113// cbPkcs1Buffer must be a power of 2 and >= cbPkcs1Format and >= 322114// cbPkcs1Buffer must be <= 2^302115// - pbPlaintext/cbPlaintext is the output buffer that will receive the data.2116// if pbPlaintext == NULL no message is output, but *pcbPlaintext is still set.2117// - pcbPlaintext receives the # bytes in the actual decrypted message.2118// set to 0 if an error occurred.2119//21202121#define SYMCRYPT_SCRATCH_BYTES_FOR_RSA_OAEP( _hashAlgorithm, _nBytesOAEP ) SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_RSA_OAEP( _hashAlgorithm, _nBytesOAEP )21222123SYMCRYPT_ERROR2124SYMCRYPT_CALL2125SymCryptRsaOaepApplyEncryptionPadding(2126_In_reads_bytes_( cbPlaintext ) PCBYTE pbPlaintext,2127SIZE_T cbPlaintext,2128_In_ PCSYMCRYPT_HASH hashAlgorithm,2129_In_reads_bytes_( cbLabel ) PCBYTE pbLabel,2130SIZE_T cbLabel,2131_In_reads_bytes_opt_( cbSeed ) PCBYTE pbSeed,2132SIZE_T cbSeed,2133_Out_writes_bytes_( cbOaepFormat ) PBYTE pbOaepFormat,2134SIZE_T cbOaepFormat,2135_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,2136SIZE_T cbScratch );2137//2138// Apply the RSA OAEP encryption padding to the plaintext buffer.2139// - Plaintext Plaintext to be encoded2140// - hashAlgorithm Hash algorithm to use during padding2141// - Label Label input for OAEP2142// - Seed Specified seed value. 0 <= cbSeed < hash size2143// - OaepFormat Output buffer, typically the size of the RSA modulus2144//2145// Remarks:2146// - If pbSeed == NULL and cbSeed != 0, then the function picks2147// a uniformly random seed of size cbSeed bytes.2148//2149// Requirements:2150// cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_RSA_OAEP( hashAlgorithm, cbOAEPFormat )2151//21522153SYMCRYPT_ERROR2154SYMCRYPT_CALL2155SymCryptRsaOaepRemoveEncryptionPadding(2156_In_reads_bytes_( cbOAEPFormat )2157PCBYTE pbOAEPFormat,2158SIZE_T cbOAEPFormat,2159_In_ PCSYMCRYPT_HASH hashAlgorithm,2160_In_reads_bytes_( cbLabel ) PCBYTE pbLabel,2161SIZE_T cbLabel,2162UINT32 flags,2163_Out_writes_bytes_( cbPlaintext )2164PBYTE pbPlaintext,2165SIZE_T cbPlaintext,2166_Out_ SIZE_T *pcbPlaintext,2167_Out_writes_bytes_( cbScratch )2168PBYTE pbScratch,2169SIZE_T cbScratch );2170//2171// Removes the RSA OAEP encryption padding from the OAEP formatted buffer2172// after it checks the validity of the format.2173//2174// *pcbPlaintext is the number of bytes output. If pbPlaintext == NULL then this2175// is the only output value.2176//2177// Allowed flags:2178// None2179//2180// Requirements:2181// cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_RSA_OAEP( hashAlgorithm, cbOAEPFormat )2182//21832184#define SYMCRYPT_SCRATCH_BYTES_FOR_RSA_PKCS1( _nBytesPKCS1 ) SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_RSA_PKCS1( _nBytesPKCS1 )21852186SYMCRYPT_ERROR2187SYMCRYPT_CALL2188SymCryptRsaPkcs1ApplySignaturePadding(2189_In_reads_bytes_( cbHash ) PCBYTE pbHash,2190SIZE_T cbHash,2191_In_reads_bytes_( cbHashOid )2192PCBYTE pbHashOid,2193SIZE_T cbHashOid,2194UINT32 flags,2195_Out_writes_bytes_( cbPKCS1Format )2196PBYTE pbPKCS1Format,2197SIZE_T cbPKCS1Format );2198//2199// Applies the RSA PKCS1 v1.5 signature padding to the source buffer, which typically contains the2200// hash of the message.2201//2202// Allowed flags:2203// SYMCRYPT_FLAG_RSA_PKCS1_NO_ASN12204//22052206SYMCRYPT_ERROR2207SYMCRYPT_CALL2208SymCryptRsaPkcs1VerifySignaturePadding(2209_In_reads_bytes_( cbHash ) PCBYTE pbHash,2210SIZE_T cbHash,2211_In_reads_( nOIDCount ) PCSYMCRYPT_OID pHashOIDs,2212_In_ SIZE_T nOIDCount,2213_In_reads_bytes_( cbPKCS1Format )2214PCBYTE pbPKCS1Format,2215SIZE_T cbPKCS1Format,2216UINT32 flags,2217_Out_writes_bytes_( cbScratch )2218PBYTE pbScratch,2219SIZE_T cbScratch );2220//2221// Verifies that the RSA PKCS1 v1.5 signature padding is valid.2222//2223// It returns SYMCRYPT_NO_ERROR if the verification succeeded or SYMCRYPT_VERIFICATION_FAIL2224// if it failed.2225//2226// Allowed flags:2227// SYMCRYPT_FLAG_RSA_PKCS1_OPTIONAL_HASH_OID2228//2229// Requirements:2230// cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_RSA_PKCS1( cbPKCS1Format )2231//22322233#define SYMCRYPT_SCRATCH_BYTES_FOR_RSA_PSS( _hashAlgorithm, _nBytesMessage, _nBytesPSS ) SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_RSA_PSS( _hashAlgorithm, _nBytesMessage, _nBytesPSS )22342235SYMCRYPT_ERROR2236SYMCRYPT_CALL2237SymCryptRsaPssApplySignaturePadding(2238_In_reads_bytes_( cbHash ) PCBYTE pbHash,2239SIZE_T cbHash,2240_In_ PCSYMCRYPT_HASH hashAlgorithm,2241_In_reads_bytes_opt_( cbSalt )2242PCBYTE pbSalt,2243_In_range_(0, cbPSSFormat) SIZE_T cbSalt,2244UINT32 nBitsOfModulus,2245UINT32 flags,2246_Out_writes_bytes_( cbPSSFormat )2247PBYTE pbPSSFormat,2248SIZE_T cbPSSFormat,2249_Out_writes_bytes_( cbScratch )2250PBYTE pbScratch,2251SIZE_T cbScratch );2252//2253// Applies the RSA PSS signature padding to the source buffer, which typically contains the2254// hash of the message.2255//2256// Remarks:2257// - If pbSalt == NULL and cbSalt != 0, then the function picks2258// a uniformly random salt of size cbSalt bytes.2259//2260// Allowed flags:2261// None2262//2263// Requirements:2264// cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_RSA_PSS( hashAlgorithm, cbHash, cbPSSFormat )2265//22662267SYMCRYPT_ERROR2268SYMCRYPT_CALL2269SymCryptRsaPssVerifySignaturePadding(2270_In_reads_bytes_( cbHash ) PCBYTE pbHash,2271SIZE_T cbHash,2272_In_ PCSYMCRYPT_HASH hashAlgorithm,2273_In_range_(0, cbPSSFormat) SIZE_T cbSalt,2274_In_reads_bytes_( cbPSSFormat )2275PCBYTE pbPSSFormat,2276SIZE_T cbPSSFormat,2277UINT32 nBitsOfModulus,2278UINT32 flags,2279_Out_writes_bytes_( cbScratch )2280PBYTE pbScratch,2281SIZE_T cbScratch );2282//2283// Verifies that the RSA PSS signature padding is valid.2284//2285// It returns SYMCRYPT_NO_ERROR if the verification succeeded or SYMCRYPT_VERIFICATION_FAIL2286// if it failed.2287//2288// Allowed flags:2289// SYMCRYPT_FLAG_RSA_PSS_VERIFY_WITH_MINIMUM_SALT2290//2291// When the flag is set, this function will do signature verification using the cbSalt parameter as2292// a minimum value for the salt length, rather than using it as an exact value. Specifying this and2293// setting cbSalt = 0 allows callers to verify a signature which has a valid encoding with any salt2294// length using a single call.2295//2296//2297// Requirements:2298// cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_RSA_PSS( hashAlgorithm, cbHash, cbPSSFormat )2299//23002301//=====================================================2302//=====================================================2303// EC point operations2304//=====================================================2305//=====================================================23062307PCSYMCRYPT_MODULUS2308SYMCRYPT_CALL2309SymCryptEcurveGroupOrder( _In_ PCSYMCRYPT_ECURVE pCurve );2310//2311// This function returns a pointer to the group order of the curve's subgroup.2312//23132314UINT322315SYMCRYPT_CALL2316SymCryptEcurveDigitsofScalarMultiplier( _In_ PCSYMCRYPT_ECURVE pCurve );2317//2318// This function returns the number of digits of a scalar that is big enough to2319// store a multiplier of an elliptic curve point.2320// See also, SymCryptEcurveSizeofScalarMultiplier.2321//23222323UINT322324SYMCRYPT_CALL2325SymCryptEcurveDigitsofFieldElement( _In_ PCSYMCRYPT_ECURVE pCurve );2326//2327// This function returns the number of digits for one coordinate of the public key.2328//23292330//=====================================================2331// GETSET_VALUE_ECURVE_OPERATIONS2332//23332334#define SYMCRYPT_SCRATCH_BYTES_FOR_GETSET_VALUE_ECURVE_OPERATIONS( _pCurve ) SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_GETSET_VALUE_ECURVE_OPERATIONS( _pCurve )23352336SYMCRYPT_ERROR2337SYMCRYPT_CALL2338SymCryptEcpointSetValue(2339_In_ PCSYMCRYPT_ECURVE pCurve,2340_In_reads_bytes_(cbSrc) PCBYTE pbSrc,2341SIZE_T cbSrc,2342SYMCRYPT_NUMBER_FORMAT nformat,2343SYMCRYPT_ECPOINT_FORMAT eformat,2344_Out_ PSYMCRYPT_ECPOINT poDst,2345UINT32 flags,2346_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,2347SIZE_T cbScratch );2348//2349// Set the value of an ECPOINT object from a source buffer pbSrc of size cbSrc. The buffer2350// will contain the necessary coordinates of the ECPOINT in the format specified by nformat2351// and eformat. The nformat determines the format of the integers in the buffer while the2352// eformat determines the layout (and the number) of the coordinates.2353//2354// Requirements:2355// - cbSrc = X * SymCryptEcurveSizeofFieldElement( pCurve ) where X depends on the2356// eformat specified and denotes the number of coordinates. For example, for2357// SYMCRYPT_ECPOINT_FORMAT_XY it is equal to 2.2358// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_GETSET_VALUE_ECURVE_OPERATIONS( pCurve )2359//2360// Flag values:2361// SYMCRYPT_FLAG_DATA_PUBLIC data is public (no side-channel protection needed)2362//2363// Rationale:2364// Scratch space provides room for conversion of point representations.2365//2366// Example:2367// Set an ECPOINT to (X,Y) point in affine coordinates where the size of each coordinate2368// is t = SymCryptEcurveSizeofFieldElement( pCurve ) bytes. The coordinates are2369// X=(X_(t-1), ... , X_1, X_0) and Y=(Y_(t-1), ... , Y_1, Y_0) with t-1 the2370// most significant byte. Then the function can be called with2371// pbSrc = { X_(t-1), ... , X_1, X_0, Y_(t-1), ... , Y_1, Y_0 }2372// cbSrc = 2 * t2373// nformat = SYMCRYPT_NUMBER_FORMAT_MSB_FIRST2374// eformat = SYMCRYPT_ECPOINT_FORMAT_XY2375//23762377SYMCRYPT_ERROR2378SYMCRYPT_CALL2379SymCryptEcpointGetValue(2380_In_ PCSYMCRYPT_ECURVE pCurve,2381_In_ PCSYMCRYPT_ECPOINT poSrc,2382SYMCRYPT_NUMBER_FORMAT nformat,2383SYMCRYPT_ECPOINT_FORMAT eformat,2384_Out_writes_bytes_(cbDst) PBYTE pbDst,2385SIZE_T cbDst,2386UINT32 flags,2387_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,2388SIZE_T cbScratch );2389//2390// Retrieve the value of an ECPOINT object into a destination buffer pbDst of size cbDst. The buffer2391// will contain the necessary coordinates of the ECPOINT in the format specified by nformat2392// and eformat. The nformat determines the format of the integers in the buffer while the2393// eformat determines the layout (and the number) of the coordinates.2394//2395// Flag values:2396// SYMCRYPT_FLAG_DATA_PUBLIC data is public (no side-channel protection needed)2397//2398// Remarks:2399// - If the source point is the "zero" point and it cannot be exported into the2400// required ECPOINT_FORMAT (XY or X), the function fails with SYMCRYPT_INCOMPATIBLE_FORMAT.2401//2402// Requirements:2403// - cbDst = X * SymCryptEcurveSizeofFieldElement( pCurve ) where X depends on the2404// eformat specified and denotes the number of coordinates. For example for SYMCRYPT_ECPOINT_FORMAT_XY it is equal to 2.2405// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_GETSET_VALUE_ECURVE_OPERATIONS( pCurve )2406//2407// Rationale:2408// Scratch space provides room for conversion of point representations.2409//24102411//2412// Low-level flags for ECC operations2413//2414// SYMCRYPT_FLAG_DATA_PUBLIC: When set, the operation will not be side-channel safe.2415// It is used to speed up operation on public data. (default: side-channel safe)2416//2417// SYMCRYPT_FLAG_ECC_LL_COFACTOR_MUL: When set, the underlying operation will multiply2418// by the cofactor of the curve. (default: no multiplication by the cofactor)2419// Remark: **Notice that the default behaviour is the opposite of the higher-level2420// functions in symcrypt.h.**2421#define SYMCRYPT_FLAG_ECC_LL_COFACTOR_MUL (0x20)24222423//=====================================================2424// COMMON_ECURVE_OPERATIONS2425//24262427#define SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_ECURVE_OPERATIONS( _pCurve ) SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_COMMON_ECURVE_OPERATIONS( _pCurve )24282429VOID2430SYMCRYPT_CALL2431SymCryptEcpointSetZero(2432_In_ PCSYMCRYPT_ECURVE pCurve,2433_Out_ PSYMCRYPT_ECPOINT poDst,2434_Out_writes_bytes_opt_( cbScratch )2435PBYTE pbScratch,2436SIZE_T cbScratch );2437//2438// Set the destination point poDst to the zero2439// element of the additive group defined by the2440// elliptic curve addition rule.2441//2442// Requirements:2443// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_ECURVE_OPERATIONS( pCurve ).2444//24452446VOID2447SYMCRYPT_CALL2448SymCryptEcpointSetDistinguishedPoint(2449_In_ PCSYMCRYPT_ECURVE pCurve,2450_Out_ PSYMCRYPT_ECPOINT poDst,2451_Out_writes_bytes_opt_( cbScratch )2452PBYTE pbScratch,2453SIZE_T cbScratch );2454//2455// Set the destination point poDst to the2456// distinguished point of the curve.2457//2458// Requirements:2459// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_ECURVE_OPERATIONS( pCurve ).2460//24612462#define SYMCRYPT_FLAG_ECPOINT_EQUAL (0x01)2463#define SYMCRYPT_FLAG_ECPOINT_NEG_EQUAL (0x02)24642465UINT322466SYMCRYPT_CALL2467SymCryptEcpointIsEqual(2468_In_ PCSYMCRYPT_ECURVE pCurve,2469_In_ PCSYMCRYPT_ECPOINT poSrc1,2470_In_ PCSYMCRYPT_ECPOINT poSrc2,2471UINT32 flags,2472_Out_writes_bytes_opt_( cbScratch )2473PBYTE pbScratch,2474SIZE_T cbScratch );2475//2476// If the flags argument is equal to 0 (default) or SYMCRYPT_FLAG_ECPOINT_EQUAL, it returns a mask value which is2477// 0xffffffff if poSrc1 = poSrc2 and 0 otherwise.2478// If the flags argument is equal to SYMCRYPT_FLAG_ECPOINT_NEG_EQUAL, it returns a mask value which is2479// 0xffffffff if poSrc1 = -poSrc2 and 0 otherwise.2480// If the flags argument is equal to SYMCRYPT_FLAG_ECPOINT_EQUAL | SYMCRYPT_FLAG_ECPOINT_NEG_EQUAL,2481// it returns a mask value which is 0xffffffff if (poSrc1 = poSrc2) or (poSrc1 = -poSrc2) and 0 otherwise.2482//2483// The points should have been created with the same curve pCurve. Otherwise the result is undefined.2484//2485// Requirements:2486// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_ECURVE_OPERATIONS( pCurve ).2487//24882489UINT322490SYMCRYPT_CALL2491SymCryptEcpointIsZero(2492_In_ PCSYMCRYPT_ECURVE pCurve,2493_In_ PCSYMCRYPT_ECPOINT poSrc,2494_Out_writes_bytes_opt_( cbScratch )2495PBYTE pbScratch,2496SIZE_T cbScratch );2497//2498// Returns a mask value which is 0xffffffff if the point is the zero point of the group.2499//2500// Requirements:2501// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_ECURVE_OPERATIONS( pCurve ).2502//25032504UINT322505SYMCRYPT_CALL2506SymCryptEcpointOnCurve(2507_In_ PCSYMCRYPT_ECURVE pCurve,2508_In_ PCSYMCRYPT_ECPOINT poSrc,2509_Out_writes_bytes_opt_( cbScratch )2510PBYTE pbScratch,2511SIZE_T cbScratch );2512//2513// Returns a mask value which is 0xffffffff if the point is on curve.2514//2515// Requirements:2516// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_ECURVE_OPERATIONS( pCurve ).2517//25182519VOID2520SYMCRYPT_CALL2521SymCryptEcpointAdd(2522_In_ PCSYMCRYPT_ECURVE pCurve,2523_In_ PCSYMCRYPT_ECPOINT poSrc1,2524_In_ PCSYMCRYPT_ECPOINT poSrc2,2525_Out_ PSYMCRYPT_ECPOINT poDst,2526UINT32 flags,2527_Out_writes_bytes_opt_( cbScratch )2528PBYTE pbScratch,2529SIZE_T cbScratch );2530//2531// Point addition over the curve pCurve.2532// poDst = poSrc1 + poSrc22533//2534// Allowed flags:2535// SYMCRYPT_FLAG_DATA_PUBLIC: If set then the algorithm2536// is not side-channel safe (and faster). The default behaviour2537// is side-channel safety.2538//2539// Remarks:2540// - Complete (i.e. works for all points)2541// - Writes intermediate results to poDst breaking the read-once/write-once rule2542//2543// Requirements:2544// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_ECURVE_OPERATIONS( pCurve ).2545//25462547VOID2548SYMCRYPT_CALL2549SymCryptEcpointAddDiffNonZero(2550_In_ PCSYMCRYPT_ECURVE pCurve,2551_In_ PCSYMCRYPT_ECPOINT poSrc1,2552_In_ PCSYMCRYPT_ECPOINT poSrc2,2553_Out_ PSYMCRYPT_ECPOINT poDst,2554_Out_writes_bytes_opt_( cbScratch )2555PBYTE pbScratch,2556SIZE_T cbScratch );2557//2558// Point addition when *peSrc1 != +- *peSrc22559// and none of them is equal to the zero point.2560//2561// Remarks:2562// - Side-channel safe2563// - Complete (i.e. works for all points)2564// - Writes intermediate results to poDst breaking the read-once/write-once rule2565//2566// Requirements:2567// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_ECURVE_OPERATIONS( pCurve ).2568//25692570VOID2571SYMCRYPT_CALL2572SymCryptEcpointDouble(2573_In_ PCSYMCRYPT_ECURVE pCurve,2574_In_ PCSYMCRYPT_ECPOINT poSrc,2575_Out_ PSYMCRYPT_ECPOINT poDst,2576UINT32 flags,2577_Out_writes_bytes_opt_( cbScratch )2578PBYTE pbScratch,2579SIZE_T cbScratch );2580//2581// Point doubling.2582//2583// Allowed flags:2584// SYMCRYPT_FLAG_DATA_PUBLIC: If set then the algorithm2585// is not side-channel safe (and faster). The default behaviour2586// is side-channel safety.2587//2588// Remarks:2589// - Side-channel safe2590// - Writes intermediate results to poDst breaking the read-once/write-once rule2591//2592// Requirements:2593// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_ECURVE_OPERATIONS( pCurve ).2594//25952596VOID2597SYMCRYPT_CALL2598SymCryptEcpointNegate(2599_In_ PCSYMCRYPT_ECURVE pCurve,2600_Inout_ PSYMCRYPT_ECPOINT poSrc,2601UINT32 mask,2602_Out_writes_bytes_opt_( cbScratch )2603PBYTE pbScratch,2604SIZE_T cbScratch );2605//2606// Negates (in place) the source point poSrc if mask == 0xffffffff.2607//2608// Requirements:2609// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_ECURVE_OPERATIONS( pCurve ).2610//26112612//=====================================================2613// SCALAR_ECURVE_OPERATIONS2614//26152616#define SYMCRYPT_SCRATCH_BYTES_FOR_SCALAR_ECURVE_OPERATIONS( _pCurve ) SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_SCALAR_ECURVE_OPERATIONS( (_pCurve), 1 )2617#define SYMCRYPT_SCRATCH_BYTES_FOR_MULTI_SCALAR_ECURVE_OPERATIONS( _pCurve, _nPoints ) SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_SCALAR_ECURVE_OPERATIONS( (_pCurve), (_nPoints) )26182619VOID2620SYMCRYPT_CALL2621SymCryptEcpointSetRandom(2622_In_ PCSYMCRYPT_ECURVE pCurve,2623_Out_ PSYMCRYPT_INT piScalar,2624_Out_ PSYMCRYPT_ECPOINT poDst,2625_Out_writes_bytes_opt_( cbScratch )2626PBYTE pbScratch,2627SIZE_T cbScratch );2628//2629// Set the destination point poDst to a random non-zero point2630// of the subgroup generated by the distinguished point.2631// The function outputs the integer k and the point kG2632// where k is picked uniformly at random from the set2633// [1, SubgroupOrder-1] ( 0 is excluded).2634//2635// Requirements:2636// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_SCALAR_ECURVE_OPERATIONS( pCurve ).2637//26382639SYMCRYPT_ERROR2640SYMCRYPT_CALL2641SymCryptEcpointScalarMul(2642_In_ PCSYMCRYPT_ECURVE pCurve,2643_In_ PCSYMCRYPT_INT piScalar,2644_In_opt_2645PCSYMCRYPT_ECPOINT poSrc,2646UINT32 flags,2647_Out_ PSYMCRYPT_ECPOINT poDst,2648_Out_writes_bytes_opt_( cbScratch )2649PBYTE pbScratch,2650SIZE_T cbScratch );2651//2652// Multiplication of point by scalar.2653// poDst = piScalar x poSrc2654//2655// If poSrc == NULL the algorithm uses the distinguished point of the curve as source2656// point and it might be faster (depending on the curve optimizations).2657//2658// Allowed flags:2659// SYMCRYPT_FLAG_ECC_LL_COFACTOR_MUL: If set then2660// the scalar is multiplied by the cofactor of2661// the curve. The default behaviour is to not multiply2662// by the cofactor.2663//2664// Remarks:2665// - Complete2666// - Side-channel safe2667//2668// Requirements:2669// - The piScalar must have SymCryptEcurveDigitsofScalarMultiplier( pCurve ) digits.2670// - For Non-Montgomery curves, the piScalar must be in the range [0, SubgroupOrder].2671// - This is the caller's responsibility, it is not checked.2672// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_SCALAR_ECURVE_OPERATIONS( pCurve ).2673//26742675// SYMCRYPT_ECURVE_MULTI_SCALAR_MUL_MAX_NPOINTS: The maximum number of points allowed for the2676// multi-scalar multiplication operation.2677#define SYMCRYPT_ECURVE_MULTI_SCALAR_MUL_MAX_NPOINTS (2)26782679SYMCRYPT_ERROR2680SYMCRYPT_CALL2681SymCryptEcpointMultiScalarMul(2682_In_ PCSYMCRYPT_ECURVE pCurve,2683_In_ PCSYMCRYPT_INT * piSrcScalarArray,2684_In_ PCSYMCRYPT_ECPOINT * poSrcEcpointArray,2685UINT32 nPoints,2686UINT32 flags,2687_Out_ PSYMCRYPT_ECPOINT poDst,2688_Out_writes_bytes_opt_( cbScratch )2689PBYTE pbScratch,2690SIZE_T cbScratch );2691//2692// It executes the multi scalar - add operation for nPoints2693// pairs of (exponents, points) in (piSrcScalarArray, poSrcEcpointArray).2694//2695// If poSrcEcpointArray[0] == NULL the algorithm uses the distinguished point of the curve as2696// the first source point and it might be faster (depending on the curve optimizations).2697// Only the first source point can be NULL.2698//2699// Allowed flags:2700// SYMCRYPT_FLAG_ECC_LL_COFACTOR_MUL: If set then2701// the scalar is multiplied by the cofactor of2702// the curve. The default behaviour is to not multiply2703// by the cofactor.2704// SYMCRYPT_FLAG_DATA_PUBLIC: If set then the algorithm2705// is not side-channel safe (For use in the ECDSA2706// verification with public information). The default behaviour2707// is side channel safe.2708//2709// Requirements:2710// - 1<= nPoints <= SYMCRYPT_ECURVE_MULTI_SCALAR_MUL_MAX_NPOINTS2711// - Each piScalar must have SymCryptEcurveDigitsofScalarMultiplier( pCurve ) digits.2712// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_MULTI_SCALAR_ECURVE_OPERATIONS( pCurve, nPoints ).2713//271427152716////////////////////////////////////////////////////////////////////////////2717// AES-CTR-DRBG2718//27192720#define SYMCRYPT_RNG_AES_INTERNAL_SEED_SIZE (32 + 16)27212722SYMCRYPT_ERROR2723SYMCRYPT_CALL2724SymCryptRngAesGenerateSmall(2725_Inout_ PSYMCRYPT_RNG_AES_STATE pRngState,2726_Out_writes_( cbRandom ) PBYTE pbRandom,2727SIZE_T cbRandom,2728_In_reads_opt_( cbAdditionalInput ) PCBYTE pbAdditionalInput,2729SIZE_T cbAdditionalInput );2730//2731// Generate random output from the state per SP 800-90.2732// Callers should almost always use SymCryptRngAesGenerate from symcrypt.h instead.2733//2734// This is the core generation function that produces up to 64 kB at a time2735// This function returns an error code so that we can test the2736// error handling of having done more than 2^48 requests between reseeds,2737// as required by SP 800-90.2738// This is also the Generate function of our SP800-90 compliant implementation.2739// If pRngState->fips140-2Check is true, this function runs the continuous self test2740// required by FIPS 140-2 (but not by FIPS 140-3 as far as we know).2741// pbAdditionalInput is optional.2742//27432744//=====================================================2745// ECDSA-EX2746//27472748SYMCRYPT_ERROR2749SYMCRYPT_CALL2750SymCryptEcDsaSignEx(2751_In_ PCSYMCRYPT_ECKEY pKey,2752_In_reads_bytes_( cbHashValue ) PCBYTE pbHashValue,2753SIZE_T cbHashValue,2754_In_opt_ PCSYMCRYPT_INT piK,2755SYMCRYPT_NUMBER_FORMAT format,2756UINT32 flags,2757_Out_writes_bytes_( cbSignature ) PBYTE pbSignature,2758SIZE_T cbSignature );2759//2760// This algorithm is the same as SymCryptEcDsaSign except that the caller can specify2761// a value of k in piK. It is used in verifying test vectors of ECDSA.2762//2763// Requirements:2764// - If piK is not NULL it must have SymCryptEcurveDigitsofScalarMultiplier( pCurve ) digits, and2765// must be in range [1, SubgroupOrder-1].2766// - If piK is not NULL and the generated signature would be 0, SYMCRYPT_INVALID_ARGUMENT is2767// returned.2768//2769// Allowed flags:2770// SYMCRYPT_FLAG_ECDSA_NO_TRUNCATION: If set then the hash value will2771// not be truncated.2772//2773// SYMCRYPT_FLAG_DATA_PUBLIC: If specified, all inputs, including the private key, are2774// considered as public information and are not protected against side channel attacks.2775// This should only be used when signing with a publicly known private key (i.e. in the ECDSA self-test)2776//27772778//=====================================================2779// ML-KEM-EX2780//27812782SYMCRYPT_ERROR2783SYMCRYPT_CALL2784SymCryptMlKemEncapsulateEx(2785_In_ PCSYMCRYPT_MLKEMKEY pkMlKemkey,2786_In_reads_bytes_( cbRandom ) PCBYTE pbRandom,2787SIZE_T cbRandom,2788_Out_writes_bytes_( cbAgreedSecret ) PBYTE pbAgreedSecret,2789SIZE_T cbAgreedSecret,2790_Out_writes_bytes_( cbCiphertext ) PBYTE pbCiphertext,2791SIZE_T cbCiphertext );2792//2793// Performs the Encapsulate operation of ML-KEM using caller-provided random input.2794// It is used in verifying test vectors of ML-KEM.2795//2796// This uses the public information of an ML-KEM keypair to generate an agreed secret2797// and a ciphertext. Only a peer with the private information of an ML-KEM keypair can2798// decapsulate the ciphertext to compute the agreed secret.2799//2800// The arguments are the following:2801// - pkMlKemkey: a key which contains public information required for encapsulation.2802// - (pbRandom, cbRandom): a buffer containing the input random.2803// Currently cbRandom must be 32 for all parameterizations of ML-KEM.2804// - (pbAgreedSecret, cbAgreedSecret): a buffer into which the generated secret is written.2805// Currently cbAgreedSecret must be 32 for all parameterizations of ML-KEM.2806// - (pbCiphertext, cbCiphertext): a buffer into which the encapsulated secret is written.2807// cbCiphertext must equal cbCiphertext given by SymCryptMlKemSizeofCiphertextFromParams,2808// though typically this value can be known statically (see definition of2809// SYMCRYPT_MLKEM_CIPHERTEXT_SIZE_*).2810//28112812SYMCRYPT_ERROR2813SYMCRYPT_CALL2814SymCryptCompositeMlKemEncapsulateEx(2815_In_ PCSYMCRYPT_COMPOSITE_MLKEMKEY pkCompositeMlKemkey,2816_In_reads_bytes_opt_( cbMlKemRandom ) PCBYTE pbMlKemRandom,2817SIZE_T cbMlKemRandom,2818_In_reads_bytes_opt_( cbTradRandom ) PCBYTE pbTradRandom,2819SIZE_T cbTradRandom,2820_Out_writes_bytes_( cbAgreedSecret ) PBYTE pbAgreedSecret,2821SIZE_T cbAgreedSecret,2822_Out_writes_bytes_( cbCiphertext ) PBYTE pbCiphertext,2823SIZE_T cbCiphertext );28242825//2826// Performs the Encapsulate operation of Composite ML-KEM using caller-provided random input.2827// It is used in verifying test vectors of Composite ML-KEM.2828//2829// This uses the public information of a Composite ML-KEM keypair to generate an agreed secret2830// and a ciphertext. Only a peer with the private information of a Composite ML-KEM keypair can2831// decapsulate the ciphertext to compute the agreed secret.2832//2833// The arguments are the following:2834// - pkCompositeMlKemkey: a key which contains public information required for encapsulation.2835// - (pbMlKemRandom, cbMlKemRandom): a buffer containing the input random for the ML-KEM component.2836// When pbMlKemRandom is NULL, cbMlKemRandom should be 0, and the function will generate the necessary random input internally.2837// Currently when pbMlKemRandom is not NULL, cbMlKemRandom must be 32 for all parameterizations of Composite ML-KEM.2838// - (pbTradRandom, cbTradRandom): a buffer containing the input random for the traditional component.2839// When the traditional portion is an EC key, cbTradRandom must be equal to the private key size of the EC key.2840// If pbTradRandom is NULL, cbTradRandom should be 0, and the function will generate the necessary random input internally.2841// Currently, only EC keys are supported for the traditional component.2842// - (pbAgreedSecret, cbAgreedSecret): a buffer into which the generated secret is written.2843// Currently cbAgreedSecret must be 32 for all parameterizations of Composite ML-KEM.2844// - (pbCiphertext, cbCiphertext): a buffer into which the encapsulated secret is written.2845// cbCiphertext must equal cbCiphertext given by SymCryptCompositeMlKemSizeofCiphertextFromParams,2846// though typically this value can be known statically (see definition of2847// SYMCRYPT_COMPOSITE_MLKEM_CIPHERTEXT_SIZE_*).2848//28492850//===================================================================2851// 802.11 SAE protocol2852//===================================================================2853//2854// WARNING: These functions are NOT part of the stable SymCrypt API. They are a private2855// interface for the Windows WiFi driver. These functions can change or disappear2856// at any time as we update our WiFi solutions.2857//2858// These functions implement the non-standard or 'custom' parts of the SAE protocol for2859// 802.11 SAE as specified in IEEE 801.11-2016 12.42860//2861// Parts of the protocol that are easy to implement with conventional crypto functions are2862// not included in this custom part.2863//2864// Limitation: The Hunting-and-Pecking method supports only NIST P256 curve. The Hash-to-Element2865// method supports curves NIST P256 and NIST P384.2866//28672868//2869// IANA Group numbers identify the elliptic curve and associated parameters to be used in the SAE method.2870//2871typedef enum _SYMCRYPT_802_11_SAE_GROUP {2872SYMCRYPT_SAE_GROUP_19 = 19, // NIST P2562873SYMCRYPT_SAE_GROUP_20, // NIST P3842874} SYMCRYPT_802_11_SAE_GROUP;28752876// The sizes of scalars, elliptic curve points, and HMAC outputs will vary depending on which group is selected.2877// The following macros define the largest possible sizes supported.2878#define SYMCRYPT_SAE_MAX_MOD_SIZE_BITS 3842879#define SYMCRYPT_SAE_MAX_MOD_SIZE_BYTES SYMCRYPT_BYTES_FROM_BITS( SYMCRYPT_SAE_MAX_MOD_SIZE_BITS )2880#define SYMCRYPT_SAE_MAX_EC_POINT_SIZE_BYTES ( 2 * SYMCRYPT_SAE_MAX_MOD_SIZE_BYTES )2881#define SYMCRYPT_SAE_MAX_HMAC_OUTPUT_SIZE_BYTES SYMCRYPT_BYTES_FROM_BITS( 384 )288228832884typedef struct _SYMCRYPT_802_11_SAE_CUSTOM_STATE SYMCRYPT_802_11_SAE_CUSTOM_STATE, *PSYMCRYPT_802_11_SAE_CUSTOM_STATE;2885typedef const SYMCRYPT_802_11_SAE_CUSTOM_STATE *PCSYMCRYPT_802_11_SAE_CUSTOM_STATE;2886//2887// The struct itself is opaque and is defined elsewhere.2888// Caller may not rely on the internal fields of the structure as they can2889// change at any time.2890//28912892VOID SymCrypt802_11SaeGetGroupSizes(2893SYMCRYPT_802_11_SAE_GROUP group,2894_Out_opt_ SIZE_T* pcbScalar,2895_Out_opt_ SIZE_T* pcbPoint );2896//2897// Helper function that returns the sizes of the field elements and elliptic curve points in bytes2898// for a given IANA group number. Both output parameters are optional.2899//29002901SYMCRYPT_ERROR2902SymCrypt802_11SaeCustomInit(2903_Out_ PSYMCRYPT_802_11_SAE_CUSTOM_STATE pState,2904_In_reads_( 6 ) PCBYTE pbMacA,2905_In_reads_( 6 ) PCBYTE pbMacB,2906_In_reads_( cbPassword ) PCBYTE pbPassword,2907SIZE_T cbPassword,2908_Out_opt_ PBYTE pbCounter,2909_Inout_updates_opt_( 32 ) PBYTE pbRand,2910_Inout_updates_opt_( 32 ) PBYTE pbMask );2911//2912// Initialize the state object with the MAC addresses and password.2913// All choices for the protocol (i.e. rand and mask) are made at this time.2914//2915// - State Protocol state to initialize2916// - pbMacA, pbMacB Two 6-byte MAC addresses with MacA >= MacB.2917// - pbPassword, cbPassword The password buffer2918// - pbCounter If not NULL, receives the counter value of the2919// successful PWE generation per section 12.4.4.2.22920// - pbRand Optional pointer to Rand buffer (see below)2921// - pbMask Optional pointer to Mask buffer (see below)2922//2923// The Rand and Mask buffers are optional. If a pointer is not provided then the caller2924// has no access to the corresponding value.2925// For either of these pointers there are three cases:2926// - If a NULL pointer is provided, the function generates an appropriate value internally,2927// but does not return it to the caller.2928// - If a buffer is provided and the buffer is all-zero, the function generates an appropriate2929// value internally and returns it in the buffer.2930// - If a buffer is provided and the buffer is nonzero, the value in the buffer is used for2931// the corresponding protocol parameter without further validation.2932// This last option is useful for testing as it lets the caller specify all the random choices.2933// Rand and Mask buffers are MSByte first.2934//2935// Note: currently this method only supports the NIST P256 curve. If we ever want to support other curves2936// we'll update this function to accept a curve parameter and update the SAL annotations2937// of the other functions.2938//29392940SYMCRYPT_ERROR2941SymCrypt802_11SaeCustomCreatePT(2942_In_reads_( cbSsid ) PCBYTE pbSsid,2943SIZE_T cbSsid,2944_In_reads_( cbPassword ) PCBYTE pbPassword,2945SIZE_T cbPassword,2946_In_reads_opt_( cbPasswordIdentifier ) PCBYTE pbPasswordIdentifier,2947SIZE_T cbPasswordIdentifier,2948_Out_writes_( 64 ) PBYTE pbPT );2949//2950// Generate the PT secret element for use with the SAE Hash-to-Element algorithm, as described in2951// section 12.4.4.2.3 of the 802.11 spec ("Hash-to-curve generation of the password element with2952// ECC groups"). The PT value can be "stored until needed to generate a session specific PWE."2953//2954// - pbSsid, cbSsid SSID for the connection as a string of bytes2955// - pbPassword, cbPassword Password buffer2956// - pbPasswordIdentifier, cbPasswordIdentifier Optional password identifier, as a string of bytes2957// - pbPT Out pointer to PT (as a byte buffer)2958//2959// This function uses the NIST P256 curve.2960//296129622963SYMCRYPT_ERROR2964SymCrypt802_11SaeCustomCreatePTGeneric(2965SYMCRYPT_802_11_SAE_GROUP group,2966_In_reads_( cbSsid ) PCBYTE pbSsid,2967SIZE_T cbSsid,2968_In_reads_( cbPassword ) PCBYTE pbPassword,2969SIZE_T cbPassword,2970_In_reads_opt_( cbPasswordIdentifier ) PCBYTE pbPasswordIdentifier,2971SIZE_T cbPasswordIdentifier,2972_Out_writes_( cbPT ) PBYTE pbPT,2973SIZE_T cbPT );2974//2975// Generic version of the SymCrypt802_11SaeCustomCreatePT() function that allows elliptic curve2976// group selection.2977// Generate the PT secret element for use with the SAE Hash-to-Element algorithm, as described in2978// section 12.4.4.2.3 of the 802.11 spec ("Hash-to-curve generation of the password element with2979// ECC groups"). The PT value can be "stored until needed to generate a session specific PWE."2980//2981// - group Group number for the elliptic curve selection2982// - pbSsid, cbSsid SSID for the connection as a string of bytes2983// - pbPassword, cbPassword Password buffer2984// - pbPasswordIdentifier, cbPasswordIdentifier Optional password identifier, as a string of bytes2985// - pbPT, cbPt PT (as a byte buffer)2986//298729882989SYMCRYPT_ERROR2990SymCrypt802_11SaeCustomInitH2E(2991_Out_ PSYMCRYPT_802_11_SAE_CUSTOM_STATE pState,2992_In_reads_( 64 ) PCBYTE pbPT,2993_In_reads_( 6 ) PCBYTE pbMacA,2994_In_reads_( 6 ) PCBYTE pbMacB,2995_Inout_updates_opt_( 32 ) PBYTE pbRand,2996_Inout_updates_opt_( 32 ) PBYTE pbMask );2997//2998// Initialize the state object using the Hash-to-Element algorithm, using the PT value calculated2999// by SymCrypt802_11SaeCustomCreatePT.3000//3001// - pState Protocol state3002// - pbPT PT value calculated using SymCrypt802_11SaeCustomCreatePT()3003// - pbMacA, pbMacB Two 6-byte MAC addresses3004// - pbRand Optional pointer to Rand buffer. See SymCrypt802_11SaeCustomInit() documentation for the use of this parameter.3005// - pbMask Optional pointer to Mask buffer. See SymCrypt802_11SaeCustomInit() documentation for the use of this parameter.3006//3007// See the comment on SymCrypt802_11SaeCustomInit() for more details about the pbRand and pbMask3008// parameters.3009//301030113012SYMCRYPT_ERROR3013SymCrypt802_11SaeCustomInitH2EGeneric(3014_Out_ PSYMCRYPT_802_11_SAE_CUSTOM_STATE pState,3015SYMCRYPT_802_11_SAE_GROUP group,3016_In_reads_( cbPT ) PCBYTE pbPT,3017SIZE_T cbPT,3018_In_reads_( 6 ) PCBYTE pbMacA,3019_In_reads_( 6 ) PCBYTE pbMacB,3020_Inout_updates_opt_( cbRand ) PBYTE pbRand,3021SIZE_T cbRand,3022_Inout_updates_opt_( cbMask ) PBYTE pbMask,3023SIZE_T cbMask );3024//3025// Generic version of the SymCrypt802_11SaeCustomInitH2E() function that allows elliptic curve3026// group selection.3027// Initialize the state object using the Hash-to-Element algorithm, using the PT value calculated3028// by SymCrypt802_11SaeCustomCreatePT.3029//3030// - pState Protocol state3031// - group Group number for the elliptic curve selection3032// - pbPT, cbPT PT value (as a byte array) calculated using SymCrypt802_11SaeCustomCreatePTGeneric().3033// PT must be generated on the same elliptic curve as the one supplied in the group parameter.3034// - pbMacA, pbMacB Two 6-byte MAC addresses3035// - pbRand, cbRand Optional Rand buffer. See SymCrypt802_11SaeCustomInit() documentation for the use of this parameter.3036// - pbMask, cbMask Optional Mask buffer. See SymCrypt802_11SaeCustomInit() documentation for the use of this parameter.3037//3038// See the comment on SymCrypt802_11SaeCustomInit() for more details about the pbRand and pbMask3039// parameters.3040//30413042SYMCRYPT_ERROR3043SymCrypt802_11SaeCustomCommitCreate(3044_In_ PCSYMCRYPT_802_11_SAE_CUSTOM_STATE pState,3045_Out_writes_( 32 ) PBYTE pbCommitScalar,3046_Out_writes_( 64 ) PBYTE pbCommitElement );3047//3048// Compute the commit-scalar and commit-element values for the Commit message.3049// This function does not update the pState and is multi-thread safe w.r.t. the pState object.3050//3051// - pState Protocol state that was initialized with SymCrypt802_11SaeCustomInit().3052// - pCommitScalar Buffer that receives the commit-scalar value, MSByte first.3053// - pCommitElement Buffer that receives the commit-element value encoded as two values3054// (x,y) in order, each value in MSByte first.3055//30563057SYMCRYPT_ERROR3058SymCrypt802_11SaeCustomCommitCreateGeneric(3059_In_ PCSYMCRYPT_802_11_SAE_CUSTOM_STATE pState,3060_Out_writes_( cbCommitScalar ) PBYTE pbCommitScalar,3061SIZE_T cbCommitScalar,3062_Out_writes_( cbCommitElement ) PBYTE pbCommitElement,3063SIZE_T cbCommitElement);3064//3065// Generic version of the SymCrypt802_11SaeCustomCommitCreate() function that uses the3066// state object to determine which elliptic curve group is selected.3067// Compute the commit-scalar and commit-element values for the Commit message.3068// This function does not update the pState and is multi-thread safe w.r.t. the pState object.3069//3070// - pState Protocol state that was initialized with SymCrypt802_11SaeCustomInit().3071// - pbCommitScalar, cbCommitScalar Buffer that receives the commit-scalar value, MSByte first.3072// - pbCommitElement, cbCommitElement Buffer that receives the commit-element value encoded as two values3073// (x,y) in order, each value in MSByte first.3074//30753076SYMCRYPT_ERROR3077SymCrypt802_11SaeCustomCommitProcess(3078_In_ PCSYMCRYPT_802_11_SAE_CUSTOM_STATE pState,3079_In_reads_( 32 ) PCBYTE pbPeerCommitScalar,3080_In_reads_( 64 ) PCBYTE pbPeerCommitElement,3081_Out_writes_( 32 ) PBYTE pbSharedSecret,3082_Out_writes_( 32 ) PBYTE pbScalarSum );3083//3084// Process the commit message received from the peer.3085// This function does not update pState and is multi-thread safe w.r.t. the pState object.3086//3087// - pState pointer to the protocol state.3088// - pbPeerCommitScalar pointer to the peer's commit scalar value, MSByte first.3089// - pbPeerCommitElement pointer to the peer's commit element, see CommitCreate for format.3090// - pbSharedSecret buffer that receives the 'k' value that is the shared secret, MSByte first3091// - pbScalarSum buffer that receives the sum of the two commit scalars, MSByte first3092//30933094SYMCRYPT_ERROR3095SymCrypt802_11SaeCustomCommitProcessGeneric(3096_In_ PCSYMCRYPT_802_11_SAE_CUSTOM_STATE pState,3097_In_reads_( cbPeerCommitScalar ) PCBYTE pbPeerCommitScalar,3098SIZE_T cbPeerCommitScalar,3099_In_reads_( cbPeerCommitElement ) PCBYTE pbPeerCommitElement,3100SIZE_T cbPeerCommitElement,3101_Out_writes_( cbSharedSecret ) PBYTE pbSharedSecret,3102SIZE_T cbSharedSecret,3103_Out_writes_( cbScalarSum ) PBYTE pbScalarSum,3104SIZE_T cbScalarSum );3105//3106// Generic version of the SymCrypt802_11SaeCustomCommitProcess() function that uses the3107// state object to determine which elliptic curve group is selected.3108// Process the commit message received from the peer.3109// This function does not update pState and is multi-thread safe w.r.t. the pState object.3110//3111// - pState pointer to the protocol state.3112// - pbPeerCommitScalar, cbPeerCommitScalar pointer to the peer's commit scalar value, MSByte first.3113// - pbPeerCommitElement, cbPeerCommitElement pointer to the peer's commit element, see CommitCreate for format.3114// - pbSharedSecret, cbSharedSecret buffer that receives the 'k' value that is the shared secret, MSByte first3115// - pbScalarSum, pbSharedSecret buffer that receives the sum of the two commit scalars, MSByte first3116//311731183119VOID3120SymCrypt802_11SaeCustomDestroy(3121_Inout_ PSYMCRYPT_802_11_SAE_CUSTOM_STATE pState );3122//3123// Wipe a state object.3124// After this call the memory used for pState is uninitialized and can be used for other purposes.3125// Note that it is not safe to just wipe the memory of the state object as the state3126// object contains pointers to other allocations, which can contain secret information.3127// The only way to safely destroy a state is to use this function.3128//31293130//===================================================================3131313231333134#ifdef __cplusplus3135}3136#endif313731383139