ReactOS 0.4.17-dev-1005-g171e1de
mlkem.c File Reference
#include "precomp.h"
Include dependency graph for mlkem.c:

Go to the source code of this file.

Macros

#define NROWS_MLKEM512   (2)
 
#define NROWS_MLKEM768   (3)
 
#define NROWS_MLKEM1024   (4)
 
#define SYMCRYPT_MLKEM_SIZEOF_ENCODED_UNCOMPRESSED_VECTOR(_nRows)   (384UL * _nRows)
 
#define SYMCRYPT_MLKEM_SIZEOF_FORMAT_DECAPSULATION_KEY(_nRows)   ((2*SYMCRYPT_MLKEM_SIZEOF_ENCODED_UNCOMPRESSED_VECTOR(_nRows)) + (3*32))
 
#define SYMCRYPT_MLKEM_SIZEOF_FORMAT_ENCAPSULATION_KEY(_nRows)   (SYMCRYPT_MLKEM_SIZEOF_ENCODED_UNCOMPRESSED_VECTOR(_nRows) + 32)
 

Functions

static SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemkeyGetInternalParamsFromParams (SYMCRYPT_MLKEM_PARAMS params, _Out_ PSYMCRYPT_MLKEM_INTERNAL_PARAMS pInternalParams)
 
static PSYMCRYPT_MLKEMKEY SYMCRYPT_CALL SymCryptMlKemkeyInitialize (_In_ PCSYMCRYPT_MLKEM_INTERNAL_PARAMS pInternalParams, _Out_writes_bytes_(cbKey) PBYTE pbKey, UINT32 cbKey)
 
PSYMCRYPT_MLKEMKEY SYMCRYPT_CALL SymCryptMlKemkeyAllocate (SYMCRYPT_MLKEM_PARAMS params)
 
VOID SYMCRYPT_CALL SymCryptMlKemkeyFree (_Inout_ PSYMCRYPT_MLKEMKEY pkMlKemkey)
 
 C_ASSERT (SYMCRYPT_MLKEM_SIZEOF_FORMAT_DECAPSULATION_KEY(NROWS_MLKEM512)==SYMCRYPT_MLKEM_DECAPSULATION_KEY_SIZE_MLKEM512)
 
 C_ASSERT (SYMCRYPT_MLKEM_SIZEOF_FORMAT_DECAPSULATION_KEY(NROWS_MLKEM768)==SYMCRYPT_MLKEM_DECAPSULATION_KEY_SIZE_MLKEM768)
 
 C_ASSERT (SYMCRYPT_MLKEM_SIZEOF_FORMAT_DECAPSULATION_KEY(NROWS_MLKEM1024)==SYMCRYPT_MLKEM_DECAPSULATION_KEY_SIZE_MLKEM1024)
 
 C_ASSERT (SYMCRYPT_MLKEM_SIZEOF_FORMAT_ENCAPSULATION_KEY(NROWS_MLKEM512)==SYMCRYPT_MLKEM_ENCAPSULATION_KEY_SIZE_MLKEM512)
 
 C_ASSERT (SYMCRYPT_MLKEM_SIZEOF_FORMAT_ENCAPSULATION_KEY(NROWS_MLKEM768)==SYMCRYPT_MLKEM_ENCAPSULATION_KEY_SIZE_MLKEM768)
 
 C_ASSERT (SYMCRYPT_MLKEM_SIZEOF_FORMAT_ENCAPSULATION_KEY(NROWS_MLKEM1024)==SYMCRYPT_MLKEM_ENCAPSULATION_KEY_SIZE_MLKEM1024)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemSizeofKeyFormatFromParams (SYMCRYPT_MLKEM_PARAMS params, SYMCRYPT_MLKEMKEY_FORMAT mlKemkeyFormat, _Out_ SIZE_T *pcbKeyFormat)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemSizeofCiphertextFromParams (SYMCRYPT_MLKEM_PARAMS params, _Out_ SIZE_T *pcbCiphertext)
 
static VOID SYMCRYPT_CALL SymCryptMlKemkeyExpandPublicMatrixFromPublicSeed (_Inout_ PSYMCRYPT_MLKEMKEY pkMlKemkey, _Inout_ PSYMCRYPT_MLKEM_INTERNAL_COMPUTATION_TEMPORARIES pCompTemps)
 
static VOID SYMCRYPT_CALL SymCryptMlKemkeyComputeEncapsulationKeyHash (_Inout_ PSYMCRYPT_MLKEMKEY pkMlKemkey, _Inout_ PSYMCRYPT_MLKEM_INTERNAL_COMPUTATION_TEMPORARIES pCompTemps, SIZE_T cbEncodedVector)
 
static VOID SYMCRYPT_CALL SymCryptMlKemkeyExpandFromPrivateSeed (_Inout_ PSYMCRYPT_MLKEMKEY pkMlKemkey, _Inout_ PSYMCRYPT_MLKEM_INTERNAL_COMPUTATION_TEMPORARIES pCompTemps)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemkeySetValue (_In_reads_bytes_(cbSrc) PCBYTE pbSrc, SIZE_T cbSrc, SYMCRYPT_MLKEMKEY_FORMAT mlKemkeyFormat, UINT32 flags, _Inout_ PSYMCRYPT_MLKEMKEY pkMlKemkey)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemkeyGetValue (_In_ PCSYMCRYPT_MLKEMKEY pkMlKemkey, _Out_writes_bytes_(cbDst) PBYTE pbDst, SIZE_T cbDst, SYMCRYPT_MLKEMKEY_FORMAT mlKemkeyFormat, UINT32 flags)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemkeyGenerate (_Inout_ PSYMCRYPT_MLKEMKEY pkMlKemkey, UINT32 flags)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemEncapsulateInternal (_In_ PCSYMCRYPT_MLKEMKEY pkMlKemkey, _Out_writes_bytes_(cbAgreedSecret) PBYTE pbAgreedSecret, SIZE_T cbAgreedSecret, _Out_writes_bytes_(cbCiphertext) PBYTE pbCiphertext, SIZE_T cbCiphertext, _In_reads_bytes_(SYMCRYPT_MLKEM_SIZEOF_ENCAPS_RANDOM) PCBYTE pbRandom, _Inout_ PSYMCRYPT_MLKEM_INTERNAL_COMPUTATION_TEMPORARIES pCompTemps)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemEncapsulateEx (_In_ PCSYMCRYPT_MLKEMKEY pkMlKemkey, _In_reads_bytes_(cbRandom) PCBYTE pbRandom, SIZE_T cbRandom, _Out_writes_bytes_(cbAgreedSecret) PBYTE pbAgreedSecret, SIZE_T cbAgreedSecret, _Out_writes_bytes_(cbCiphertext) PBYTE pbCiphertext, SIZE_T cbCiphertext)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemEncapsulate (_In_ PCSYMCRYPT_MLKEMKEY pkMlKemkey, _Out_writes_bytes_(cbAgreedSecret) PBYTE pbAgreedSecret, SIZE_T cbAgreedSecret, _Out_writes_bytes_(cbCiphertext) PBYTE pbCiphertext, SIZE_T cbCiphertext)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemDecapsulate (_In_ PCSYMCRYPT_MLKEMKEY pkMlKemkey, _In_reads_bytes_(cbCiphertext) PCBYTE pbCiphertext, SIZE_T cbCiphertext, _Out_writes_bytes_(cbAgreedSecret) PBYTE pbAgreedSecret, SIZE_T cbAgreedSecret)
 

Variables

const SYMCRYPT_MLKEM_INTERNAL_PARAMS SymCryptMlKemInternalParamsMlKem512
 
const SYMCRYPT_MLKEM_INTERNAL_PARAMS SymCryptMlKemInternalParamsMlKem768
 
const SYMCRYPT_MLKEM_INTERNAL_PARAMS SymCryptMlKemInternalParamsMlKem1024
 

Macro Definition Documentation

◆ NROWS_MLKEM1024

#define NROWS_MLKEM1024   (4)

Definition at line 11 of file mlkem.c.

◆ NROWS_MLKEM512

#define NROWS_MLKEM512   (2)

Definition at line 9 of file mlkem.c.

◆ NROWS_MLKEM768

#define NROWS_MLKEM768   (3)

Definition at line 10 of file mlkem.c.

◆ SYMCRYPT_MLKEM_SIZEOF_ENCODED_UNCOMPRESSED_VECTOR

#define SYMCRYPT_MLKEM_SIZEOF_ENCODED_UNCOMPRESSED_VECTOR (   _nRows)    (384UL * _nRows)

Definition at line 193 of file mlkem.c.

◆ SYMCRYPT_MLKEM_SIZEOF_FORMAT_DECAPSULATION_KEY

#define SYMCRYPT_MLKEM_SIZEOF_FORMAT_DECAPSULATION_KEY (   _nRows)    ((2*SYMCRYPT_MLKEM_SIZEOF_ENCODED_UNCOMPRESSED_VECTOR(_nRows)) + (3*32))

Definition at line 197 of file mlkem.c.

◆ SYMCRYPT_MLKEM_SIZEOF_FORMAT_ENCAPSULATION_KEY

#define SYMCRYPT_MLKEM_SIZEOF_FORMAT_ENCAPSULATION_KEY (   _nRows)    (SYMCRYPT_MLKEM_SIZEOF_ENCODED_UNCOMPRESSED_VECTOR(_nRows) + 32)

Definition at line 200 of file mlkem.c.

Function Documentation

◆ C_ASSERT() [1/6]

◆ C_ASSERT() [2/6]

◆ C_ASSERT() [3/6]

◆ C_ASSERT() [4/6]

◆ C_ASSERT() [5/6]

◆ C_ASSERT() [6/6]

◆ SymCryptMlKemDecapsulate()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemDecapsulate ( _In_ PCSYMCRYPT_MLKEMKEY  pkMlKemkey,
_In_reads_bytes_(cbCiphertext) PCBYTE  pbCiphertext,
SIZE_T  cbCiphertext,
_Out_writes_bytes_(cbAgreedSecret) PBYTE  pbAgreedSecret,
SIZE_T  cbAgreedSecret 
)

Definition at line 1026 of file mlkem.c.

1032{
1034 BYTE pbDecryptedRandom[SYMCRYPT_MLKEM_SIZEOF_ENCAPS_RANDOM];
1035 BYTE pbDecapsulatedSecret[SYMCRYPT_MLKEM_SIZEOF_AGREED_SECRET];
1036 BYTE pbImplicitRejectionSecret[SYMCRYPT_MLKEM_SIZEOF_AGREED_SECRET];
1037 PBYTE pbReadCiphertext, pbReencapsulatedCiphertext;
1038 BOOLEAN successfulReencrypt;
1039
1040 PBYTE pbCurr;
1041 PBYTE pbAlloc = NULL;
1042 const SIZE_T cbAlloc = sizeof(SYMCRYPT_MLKEM_INTERNAL_COMPUTATION_TEMPORARIES) + (2*cbCiphertext);
1043
1044 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
1045 SIZE_T cbU, cbV, cbCopy;
1047 PSYMCRYPT_MLKEM_POLYELEMENT peTmp0, peTmp1;
1049 PSYMCRYPT_SHAKE256_STATE pShakeState;
1050 const UINT32 nRows = pkMlKemkey->params.nRows;
1051 const UINT32 nBitsOfU = pkMlKemkey->params.nBitsOfU;
1052 const UINT32 nBitsOfV = pkMlKemkey->params.nBitsOfV;
1053 const UINT32 cbPolyElement = pkMlKemkey->params.cbPolyElement;
1054 const UINT32 cbVector = pkMlKemkey->params.cbVector;
1055
1056 // u vector encoded with nBitsOfU * SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS bits per polynomial
1058 // v polynomial encoded with nBitsOfV * SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS bits
1060
1061 if( (cbAgreedSecret != SYMCRYPT_MLKEM_SIZEOF_AGREED_SECRET) ||
1062 (cbCiphertext != cbU + cbV) ||
1063 !pkMlKemkey->hasPrivateKey )
1064 {
1065 scError = SYMCRYPT_INVALID_ARGUMENT;
1066 goto cleanup;
1067 }
1068
1069 pbAlloc = SymCryptCallbackAlloc( cbAlloc );
1070 if( pbAlloc == NULL )
1071 {
1072 scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
1073 goto cleanup;
1074 }
1075 pbCurr = pbAlloc;
1076
1079
1080 pbReadCiphertext = pbCurr;
1081 pbCurr += cbCiphertext;
1082
1083 pbReencapsulatedCiphertext = pbCurr;
1084 pbCurr += cbCiphertext;
1085
1086 SYMCRYPT_ASSERT( pbCurr == (pbAlloc + cbAlloc) );
1087
1088 // Read the input ciphertext once to local pbReadCiphertext to ensure our view of ciphertext consistent
1089 memcpy( pbReadCiphertext, pbCiphertext, cbCiphertext );
1090
1091 pvu = SymCryptMlKemVectorCreate( pCompTemps->abVectorBuffer0, cbVector, nRows );
1092 SYMCRYPT_ASSERT( pvu != NULL );
1093 peTmp0 = SymCryptMlKemPolyElementCreate( pCompTemps->abPolyElementBuffer0, cbPolyElement );
1094 SYMCRYPT_ASSERT( peTmp0 != NULL );
1095 peTmp1 = SymCryptMlKemPolyElementCreate( pCompTemps->abPolyElementBuffer1, cbPolyElement );
1096 SYMCRYPT_ASSERT( peTmp1 != NULL );
1097 paTmp = SymCryptMlKemPolyElementAccumulatorCreate( pCompTemps->abPolyElementAccumulatorBuffer, 2*cbPolyElement );
1098 SYMCRYPT_ASSERT( paTmp != NULL );
1099
1100 // Decode and decompress u
1101 scError = SymCryptMlKemVectorDecodeAndDecompress( pbReadCiphertext, cbU, nBitsOfU, pvu );
1102 SYMCRYPT_ASSERT( scError == SYMCRYPT_NO_ERROR );
1103
1104 // Perform NTT on u
1106
1107 // peTmp0 = (s o NTT(u)) ./ R
1108 SymCryptMlKemVectorMontDotProduct( pkMlKemkey->pvs, pvu, peTmp0, paTmp );
1109
1110 // peTmp0 = INTT(s o NTT(u))
1112
1113 // Decode and decompress v
1114 scError = SymCryptMlKemPolyElementDecodeAndDecompress( pbReadCiphertext+cbU, nBitsOfV, peTmp1 );
1115 SYMCRYPT_ASSERT( scError == SYMCRYPT_NO_ERROR );
1116
1117 // peTmp0 = w = v - INTT(s o NTT(u))
1118 SymCryptMlKemPolyElementSub( peTmp1, peTmp0, peTmp0 );
1119
1120 // pbDecryptedRandom = m' = Encoding of w
1121 SymCryptMlKemPolyElementCompressAndEncode( peTmp0, 1, pbDecryptedRandom );
1122
1123 // Compute:
1124 // pbDecapsulatedSecret = K' = Decapsulated secret (without implicit rejection)
1125 // pbReencapsulatedCiphertext = c' = Ciphertext from re-encapsulating decrypted random value
1127 pkMlKemkey,
1128 pbDecapsulatedSecret, sizeof(pbDecapsulatedSecret),
1129 pbReencapsulatedCiphertext, cbCiphertext,
1130 pbDecryptedRandom,
1131 pCompTemps );
1132 SYMCRYPT_ASSERT( scError == SYMCRYPT_NO_ERROR );
1133
1134 // Compute the secret we will return if using implicit rejection
1135 // pbImplicitRejectionSecret = K_bar = SHAKE256( z || c )
1136 pShakeState = &pCompTemps->hashState0.shake256State;
1137 SymCryptShake256Init( pShakeState );
1138 SymCryptShake256Append( pShakeState, pkMlKemkey->privateRandom, sizeof(pkMlKemkey->privateRandom) );
1139 SymCryptShake256Append( pShakeState, pbReadCiphertext, cbCiphertext );
1140 SymCryptShake256Extract( pShakeState, pbImplicitRejectionSecret, sizeof(pbImplicitRejectionSecret), FALSE );
1141
1142 // Constant time test if re-encryption successful
1143 successfulReencrypt = SymCryptEqual( pbReencapsulatedCiphertext, pbReadCiphertext, cbCiphertext );
1144
1145 // If not successful, perform side-channel-safe copy of Implicit Rejection secret over Decapsulated secret
1146 cbCopy = (((SIZE_T)successfulReencrypt)-1) & SYMCRYPT_MLKEM_SIZEOF_AGREED_SECRET;
1147 SymCryptScsCopy( pbImplicitRejectionSecret, cbCopy, pbDecapsulatedSecret, SYMCRYPT_MLKEM_SIZEOF_AGREED_SECRET );
1148
1149 // Write agreed secret (with implicit rejection) to pbAgreedSecret
1150 memcpy( pbAgreedSecret, pbDecapsulatedSecret, SYMCRYPT_MLKEM_SIZEOF_AGREED_SECRET );
1151
1152cleanup:
1153 if( pbAlloc != NULL )
1154 {
1155 SymCryptWipe( pbAlloc, cbAlloc );
1156 SymCryptCallbackFree( pbAlloc );
1157 }
1158
1159 SymCryptWipeKnownSize( pbDecryptedRandom, sizeof(pbDecryptedRandom) );
1160 SymCryptWipeKnownSize( pbDecapsulatedSecret, sizeof(pbDecapsulatedSecret) );
1161 SymCryptWipeKnownSize( pbImplicitRejectionSecret, sizeof(pbImplicitRejectionSecret) );
1162
1163 return scError;
1164}
unsigned char BOOLEAN
Definition: actypes.h:127
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
static void cleanup(void)
Definition: main.c:1335
void SYMCRYPT_CALL SymCryptCallbackFree(void *ptr)
Definition: implglue.c:42
void *SYMCRYPT_CALL SymCryptCallbackAlloc(SIZE_T size)
Definition: implglue.c:37
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemEncapsulateInternal(_In_ PCSYMCRYPT_MLKEMKEY pkMlKemkey, _Out_writes_bytes_(cbAgreedSecret) PBYTE pbAgreedSecret, SIZE_T cbAgreedSecret, _Out_writes_bytes_(cbCiphertext) PBYTE pbCiphertext, SIZE_T cbCiphertext, _In_reads_bytes_(SYMCRYPT_MLKEM_SIZEOF_ENCAPS_RANDOM) PCBYTE pbRandom, _Inout_ PSYMCRYPT_MLKEM_INTERNAL_COMPUTATION_TEMPORARIES pCompTemps)
Definition: mlkem.c:807
VOID SYMCRYPT_CALL SymCryptMlKemPolyElementSub(_In_ PCSYMCRYPT_MLKEM_POLYELEMENT peSrc1, _In_ PCSYMCRYPT_MLKEM_POLYELEMENT peSrc2, _Out_ PSYMCRYPT_MLKEM_POLYELEMENT peDst)
PSYMCRYPT_MLKEM_VECTOR SYMCRYPT_CALL SymCryptMlKemVectorCreate(_Out_writes_bytes_(cbBuffer) PBYTE pbBuffer, UINT32 cbBuffer, UINT32 nRows)
PSYMCRYPT_MLKEM_POLYELEMENT SYMCRYPT_CALL SymCryptMlKemPolyElementCreate(_Out_writes_bytes_(cbBuffer) PBYTE pbBuffer, UINT32 cbBuffer)
VOID SYMCRYPT_CALL SymCryptMlKemPolyElementINTTAndMulR(_Inout_ PSYMCRYPT_MLKEM_POLYELEMENT peSrc)
VOID SYMCRYPT_CALL SymCryptMlKemVectorNTT(_Inout_ PSYMCRYPT_MLKEM_VECTOR pvSrc)
PSYMCRYPT_MLKEM_POLYELEMENT_ACCUMULATOR SYMCRYPT_CALL SymCryptMlKemPolyElementAccumulatorCreate(_Out_writes_bytes_(cbBuffer) PBYTE pbBuffer, UINT32 cbBuffer)
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemPolyElementDecodeAndDecompress(_In_reads_bytes_(nBitsPerCoefficient *(SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS/8)) PCBYTE pbSrc, UINT32 nBitsPerCoefficient, _Out_ PSYMCRYPT_MLKEM_POLYELEMENT peDst)
VOID SYMCRYPT_CALL SymCryptMlKemVectorMontDotProduct(_In_ PCSYMCRYPT_MLKEM_VECTOR pvSrc1, _In_ PCSYMCRYPT_MLKEM_VECTOR pvSrc2, _Inout_ PSYMCRYPT_MLKEM_POLYELEMENT peDst, _Inout_ PSYMCRYPT_MLKEM_POLYELEMENT_ACCUMULATOR paTmp)
VOID SYMCRYPT_CALL SymCryptMlKemPolyElementCompressAndEncode(_In_ PCSYMCRYPT_MLKEM_POLYELEMENT peSrc, UINT32 nBitsPerCoefficient, _Out_writes_bytes_(nBitsPerCoefficient *(SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS/8)) PBYTE pbDst)
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemVectorDecodeAndDecompress(_In_reads_bytes_(cbSrc) PCBYTE pbSrc, SIZE_T cbSrc, UINT32 nBitsPerCoefficient, _Out_ PSYMCRYPT_MLKEM_VECTOR pvDst)
BYTE * PBYTE
Definition: pedump.c:66
#define SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS
Definition: sc_lib.h:4347
PSYMCRYPT_MLKEMKEY pkMlKemkey
Definition: sc_lib.h:4444
SYMCRYPT_MLKEM_POLYELEMENT * PSYMCRYPT_MLKEM_POLYELEMENT
Definition: sc_lib_mlkem.h:18
UINT32 cbPolyElement
Definition: sc_lib_mlkem.h:65
SYMCRYPT_MLKEM_POLYELEMENT_ACCUMULATOR * PSYMCRYPT_MLKEM_POLYELEMENT_ACCUMULATOR
Definition: sc_lib_mlkem.h:25
UINT8 nBitsOfU
Definition: sc_lib_mlkem.h:75
#define SYMCRYPT_MLKEM_SIZEOF_ENCAPS_RANDOM
Definition: sc_lib_mlkem.h:133
UINT8 nRows
Definition: sc_lib_mlkem.h:69
#define SYMCRYPT_MLKEM_SIZEOF_AGREED_SECRET
Definition: sc_lib_mlkem.h:132
SYMCRYPT_MLKEM_INTERNAL_COMPUTATION_TEMPORARIES
Definition: sc_lib_mlkem.h:153
UINT32 cbVector
Definition: sc_lib_mlkem.h:66
* PSYMCRYPT_MLKEM_VECTOR
Definition: sc_lib_mlkem.h:37
UINT8 nBitsOfV
Definition: sc_lib_mlkem.h:77
SYMCRYPT_MLKEM_INTERNAL_COMPUTATION_TEMPORARIES * PSYMCRYPT_MLKEM_INTERNAL_COMPUTATION_TEMPORARIES
Definition: sc_lib_mlkem.h:154
#define SYMCRYPT_ASSERT(_x)
Definition: symcrypt.h:10807
FORCEINLINE VOID SYMCRYPT_CALL SymCryptWipeKnownSize(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
VOID SYMCRYPT_CALL SymCryptWipe(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
Definition: libmain.c:137
VOID SYMCRYPT_CALL SymCryptShake256Append(_Inout_ PSYMCRYPT_SHAKE256_STATE pState, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData)
VOID SYMCRYPT_CALL SymCryptShake256Extract(_Inout_ PSYMCRYPT_SHAKE256_STATE pState, _Out_writes_(cbResult) PBYTE pbResult, SIZE_T cbResult, BOOLEAN bWipe)
VOID SYMCRYPT_CALL SymCryptShake256Init(_Out_ PSYMCRYPT_SHAKE256_STATE pState)
BOOLEAN SYMCRYPT_CALL SymCryptEqual(_In_reads_(cbBytes) PCBYTE pbSrc1, _In_reads_(cbBytes) PCBYTE pbSrc2, SIZE_T cbBytes)
Definition: equal.c:11
SYMCRYPT_ERROR
Definition: symcrypt.h:227
UINT32 cbAlloc
SYMCRYPT_MAGIC_FIELD * PSYMCRYPT_SHAKE256_STATE
VOID SYMCRYPT_CALL SymCryptScsCopy(_In_reads_(cbDst) PCBYTE pbSrc, SIZE_T cbSrc, _Out_writes_(cbDst) PBYTE pbDst, SIZE_T cbDst)
Definition: scsTools.c:108
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t UINT32
Definition: typedefs.h:59
unsigned char BYTE
Definition: xxhash.c:193

Referenced by SymCryptMlKemkeyGenerate().

◆ SymCryptMlKemEncapsulate()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemEncapsulate ( _In_ PCSYMCRYPT_MLKEMKEY  pkMlKemkey,
_Out_writes_bytes_(cbAgreedSecret) PBYTE  pbAgreedSecret,
SIZE_T  cbAgreedSecret,
_Out_writes_bytes_(cbCiphertext) PBYTE  pbCiphertext,
SIZE_T  cbCiphertext 
)

Definition at line 996 of file mlkem.c.

1002{
1003 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
1005
1006 scError = SymCryptCallbackRandom( pbm, sizeof(pbm) );
1007 if( scError != SYMCRYPT_NO_ERROR )
1008 {
1009 goto cleanup;
1010 }
1011
1013 pkMlKemkey,
1014 pbm, sizeof(pbm),
1015 pbAgreedSecret, cbAgreedSecret,
1016 pbCiphertext, cbCiphertext );
1017
1018cleanup:
1019 SymCryptWipeKnownSize( pbm, sizeof(pbm) );
1020
1021 return scError;
1022}
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptCallbackRandom(BYTE *buf, SIZE_T size)
Definition: implglue.c:56
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemEncapsulateEx(_In_ PCSYMCRYPT_MLKEMKEY pkMlKemkey, _In_reads_bytes_(cbRandom) PCBYTE pbRandom, SIZE_T cbRandom, _Out_writes_bytes_(cbAgreedSecret) PBYTE pbAgreedSecret, SIZE_T cbAgreedSecret, _Out_writes_bytes_(cbCiphertext) PBYTE pbCiphertext, SIZE_T cbCiphertext)
Definition: mlkem.c:952

Referenced by SymCryptMlKemkeyGenerate().

◆ SymCryptMlKemEncapsulateEx()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemEncapsulateEx ( _In_ PCSYMCRYPT_MLKEMKEY  pkMlKemkey,
_In_reads_bytes_(cbRandom) PCBYTE  pbRandom,
SIZE_T  cbRandom,
_Out_writes_bytes_(cbAgreedSecret) PBYTE  pbAgreedSecret,
SIZE_T  cbAgreedSecret,
_Out_writes_bytes_(cbCiphertext) PBYTE  pbCiphertext,
SIZE_T  cbCiphertext 
)

Definition at line 952 of file mlkem.c.

960{
961 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
963
965 {
966 scError = SYMCRYPT_INVALID_ARGUMENT;
967 goto cleanup;
968 }
969
971 if( pCompTemps == NULL )
972 {
973 scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
974 goto cleanup;
975 }
976
979 pbAgreedSecret, cbAgreedSecret,
980 pbCiphertext, cbCiphertext,
981 pbRandom,
982 pCompTemps );
983
984cleanup:
985 if( pCompTemps != NULL )
986 {
987 SymCryptWipe( pCompTemps, sizeof(*pCompTemps) );
988 SymCryptCallbackFree( pCompTemps );
989 }
990
991 return scError;
992}

Referenced by SymCryptMlKemEncapsulate().

◆ SymCryptMlKemEncapsulateInternal()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemEncapsulateInternal ( _In_ PCSYMCRYPT_MLKEMKEY  pkMlKemkey,
_Out_writes_bytes_(cbAgreedSecret) PBYTE  pbAgreedSecret,
SIZE_T  cbAgreedSecret,
_Out_writes_bytes_(cbCiphertext) PBYTE  pbCiphertext,
SIZE_T  cbCiphertext,
_In_reads_bytes_(SYMCRYPT_MLKEM_SIZEOF_ENCAPS_RANDOM) PCBYTE  pbRandom,
_Inout_ PSYMCRYPT_MLKEM_INTERNAL_COMPUTATION_TEMPORARIES  pCompTemps 
)

Definition at line 807 of file mlkem.c.

818{
819 BYTE CBDSampleBuffer[3*64 + 1];
820 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
821 PSYMCRYPT_MLKEM_VECTOR pvrInner;
823 PSYMCRYPT_MLKEM_POLYELEMENT peTmp0, peTmp1;
825 PSYMCRYPT_SHA3_512_STATE pHashState = &pCompTemps->hashState0.sha3_512State;
826 PSYMCRYPT_SHAKE256_STATE pShakeBaseState = &pCompTemps->hashState0.shake256State;
827 PSYMCRYPT_SHAKE256_STATE pShakeWorkState = &pCompTemps->hashState1.shake256State;
828 SIZE_T cbU, cbV;
829 UINT32 i;
830 const UINT32 nRows = pkMlKemkey->params.nRows;
831 const UINT32 nBitsOfU = pkMlKemkey->params.nBitsOfU;
832 const UINT32 nBitsOfV = pkMlKemkey->params.nBitsOfV;
833 const UINT32 nEta1 = pkMlKemkey->params.nEta1;
834 const UINT32 nEta2 = pkMlKemkey->params.nEta2;
835 const UINT32 cbPolyElement = pkMlKemkey->params.cbPolyElement;
836 const UINT32 cbVector = pkMlKemkey->params.cbVector;
837
838 // u vector encoded with nBitsOfU * SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS bits per polynomial
840 // v polynomial encoded with nBitsOfV * SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS bits
842
843 if( (cbAgreedSecret != SYMCRYPT_MLKEM_SIZEOF_AGREED_SECRET) ||
844 (cbCiphertext != cbU + cbV) )
845 {
846 scError = SYMCRYPT_INVALID_ARGUMENT;
847 goto cleanup;
848 }
849
850 pvrInner = SymCryptMlKemVectorCreate( pCompTemps->abVectorBuffer0, cbVector, nRows );
851 SYMCRYPT_ASSERT( pvrInner != NULL );
852 pvTmp = SymCryptMlKemVectorCreate( pCompTemps->abVectorBuffer1, cbVector, nRows );
853 SYMCRYPT_ASSERT( pvTmp != NULL );
854 peTmp0 = SymCryptMlKemPolyElementCreate( pCompTemps->abPolyElementBuffer0, cbPolyElement );
855 SYMCRYPT_ASSERT( peTmp0 != NULL );
856 peTmp1 = SymCryptMlKemPolyElementCreate( pCompTemps->abPolyElementBuffer1, cbPolyElement );
857 SYMCRYPT_ASSERT( peTmp1 != NULL );
858 paTmp = SymCryptMlKemPolyElementAccumulatorCreate( pCompTemps->abPolyElementAccumulatorBuffer, 2*cbPolyElement );
859 SYMCRYPT_ASSERT( paTmp != NULL );
860
861 // CBDSampleBuffer = (K || rOuter) = SHA3-512(pbRandom || encapsKeyHash)
862 SymCryptSha3_512Init( pHashState );
864 SymCryptSha3_512Append( pHashState, pkMlKemkey->encapsKeyHash, sizeof(pkMlKemkey->encapsKeyHash) );
865 SymCryptSha3_512Result( pHashState, CBDSampleBuffer );
866
867 // Write K to pbAgreedSecret
868 memcpy( pbAgreedSecret, CBDSampleBuffer, SYMCRYPT_MLKEM_SIZEOF_AGREED_SECRET );
869
870 // Initialize pShakeStateBase with rOuter
871 SymCryptShake256Init( pShakeBaseState );
872 SymCryptShake256Append( pShakeBaseState, CBDSampleBuffer+cbAgreedSecret, 32 );
873
874 // Expand rInner vector
875 for( i=0; i<nRows; i++ )
876 {
877 CBDSampleBuffer[0] = (BYTE) i;
878 SymCryptShake256StateCopy( pShakeBaseState, pShakeWorkState );
879 SymCryptShake256Append( pShakeWorkState, CBDSampleBuffer, 1 );
880
881 SymCryptShake256Extract( pShakeWorkState, CBDSampleBuffer, 64ul*nEta1, FALSE );
882
884 }
885
886 // Perform NTT on rInner
887 SymCryptMlKemVectorNTT( pvrInner );
888
889 // Set pvTmp to 0
891
892 // pvTmp = (Atranspose o rInner) ./ R
893 SymCryptMlKemMatrixVectorMontMulAndAdd( pkMlKemkey->pmAtranspose, pvrInner, pvTmp, paTmp );
894
895 // pvTmp = INTT(Atranspose o rInner)
897
898 // Expand e1 and add it to pvTmp - do addition PolyElement-wise to reduce memory usage
899 for( i=0; i<nRows; i++ )
900 {
901 CBDSampleBuffer[0] = (BYTE) (nRows+i);
902 SymCryptShake256StateCopy( pShakeBaseState, pShakeWorkState );
903 SymCryptShake256Append( pShakeWorkState, CBDSampleBuffer, 1 );
904
905 SymCryptShake256Extract( pShakeWorkState, CBDSampleBuffer, 64ul*nEta2, FALSE );
906
907 SymCryptMlKemPolyElementSampleCBDFromBytes( CBDSampleBuffer, nEta2, peTmp0 );
908
910 }
911
912 // pvTmp = u = INTT(Atranspose o rInner) + e1
913 // Compress and encode u into prefix of ciphertext
914 SymCryptMlKemVectorCompressAndEncode( pvTmp, nBitsOfU, pbCiphertext, cbU );
915
916 // peTmp0 = (t o r) ./ R
917 SymCryptMlKemVectorMontDotProduct( pkMlKemkey->pvt, pvrInner, peTmp0, paTmp );
918
919 // peTmp0 = INTT(t o r)
921
922 // Expand e2 polynomial in peTmp1
923 CBDSampleBuffer[0] = (BYTE) (2*nRows);
924 SymCryptShake256StateCopy( pShakeBaseState, pShakeWorkState );
925 SymCryptShake256Append( pShakeWorkState, CBDSampleBuffer, 1 );
926
927 SymCryptShake256Extract( pShakeWorkState, CBDSampleBuffer, 64ul*nEta2, FALSE );
928
929 SymCryptMlKemPolyElementSampleCBDFromBytes( CBDSampleBuffer, nEta2, peTmp1 );
930
931 // peTmp = INTT(t o r) + e2
932 SymCryptMlKemPolyElementAdd( peTmp0, peTmp1, peTmp0 );
933
934 // peTmp1 = mu
935 SymCryptMlKemPolyElementDecodeAndDecompress( pbRandom, 1, peTmp1 );
936
937 // peTmp0 = v = INTT(t o r) + e2 + mu
938 SymCryptMlKemPolyElementAdd( peTmp0, peTmp1, peTmp0 );
939
940 // Compress and encode v into remainder of ciphertext
941 SymCryptMlKemPolyElementCompressAndEncode( peTmp0, nBitsOfV, pbCiphertext+cbU );
942
943cleanup:
944 SymCryptWipeKnownSize( CBDSampleBuffer, sizeof(CBDSampleBuffer) );
945
946 return scError;
947}
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
VOID SYMCRYPT_CALL SymCryptMlKemVectorCompressAndEncode(_In_ PCSYMCRYPT_MLKEM_VECTOR pvSrc, UINT32 nBitsPerCoefficient, _Out_writes_bytes_(cbDst) PBYTE pbDst, SIZE_T cbDst)
VOID SYMCRYPT_CALL SymCryptMlKemMatrixVectorMontMulAndAdd(_In_ PCSYMCRYPT_MLKEM_MATRIX pmSrc1, _In_ PCSYMCRYPT_MLKEM_VECTOR pvSrc2, _Inout_ PSYMCRYPT_MLKEM_VECTOR pvDst, _Inout_ PSYMCRYPT_MLKEM_POLYELEMENT_ACCUMULATOR paTmp)
VOID SYMCRYPT_CALL SymCryptMlKemVectorSetZero(_Inout_ PSYMCRYPT_MLKEM_VECTOR pvSrc)
VOID SYMCRYPT_CALL SymCryptMlKemPolyElementAdd(_In_ PCSYMCRYPT_MLKEM_POLYELEMENT peSrc1, _In_ PCSYMCRYPT_MLKEM_POLYELEMENT peSrc2, _Out_ PSYMCRYPT_MLKEM_POLYELEMENT peDst)
VOID SYMCRYPT_CALL SymCryptMlKemPolyElementSampleCBDFromBytes(_In_reads_bytes_(eta *2 *(SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS/8)+1) PCBYTE pbSrc, _In_range_(2, 3) UINT32 eta, _Out_ PSYMCRYPT_MLKEM_POLYELEMENT peDst)
VOID SYMCRYPT_CALL SymCryptMlKemVectorINTTAndMulR(_Inout_ PSYMCRYPT_MLKEM_VECTOR pvSrc)
#define SYMCRYPT_INTERNAL_MLKEM_VECTOR_ELEMENT(_row, _pVector)
Definition: sc_lib_mlkem.h:129
UINT8 nEta2
Definition: sc_lib_mlkem.h:73
UINT8 nEta1
Definition: sc_lib_mlkem.h:71
VOID SYMCRYPT_CALL SymCryptSha3_512Init(_Out_ PSYMCRYPT_SHA3_512_STATE pState)
Definition: sha3_512.c:45
VOID SYMCRYPT_CALL SymCryptShake256StateCopy(_In_ PCSYMCRYPT_SHAKE256_STATE pSrc, _Out_ PSYMCRYPT_SHAKE256_STATE pDst)
VOID SYMCRYPT_CALL SymCryptSha3_512Append(_Inout_ PSYMCRYPT_SHA3_512_STATE pState, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData)
Definition: sha3_512.c:60
VOID SYMCRYPT_CALL SymCryptSha3_512Result(_Inout_ PSYMCRYPT_SHA3_512_STATE pState, _Out_writes_(SYMCRYPT_SHA3_512_RESULT_SIZE) PBYTE pbResult)
Definition: sha3_512.c:74
SYMCRYPT_MAGIC_FIELD * PSYMCRYPT_SHA3_512_STATE

Referenced by SymCryptMlKemDecapsulate(), and SymCryptMlKemEncapsulateEx().

◆ SymCryptMlKemkeyAllocate()

PSYMCRYPT_MLKEMKEY SYMCRYPT_CALL SymCryptMlKemkeyAllocate ( SYMCRYPT_MLKEM_PARAMS  params)

Definition at line 140 of file mlkem.c.

142{
143 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
144 PBYTE pbKey = NULL;
146 SYMCRYPT_MLKEM_INTERNAL_PARAMS internalParams;
147
149
150 scError = SymCryptMlKemkeyGetInternalParamsFromParams(params, &internalParams);
151 if( scError != SYMCRYPT_NO_ERROR )
152 {
153 goto cleanup;
154 }
155
156 cbKey = sizeof(SYMCRYPT_MLKEMKEY) + internalParams.cbMatrix + (2*internalParams.cbVector);
157
159 if ( pbKey == NULL )
160 {
161 goto cleanup;
162 }
163
164 pKey = SymCryptMlKemkeyInitialize( &internalParams, pbKey, cbKey );
165 if ( pKey == NULL )
166 {
167 goto cleanup;
168 }
169
170 pbKey = NULL;
171
172cleanup:
173 if ( pbKey != NULL )
174 {
176 }
177
178 return pKey;
179}
GLenum const GLfloat * params
Definition: glext.h:5645
static PSYMCRYPT_MLKEMKEY SYMCRYPT_CALL SymCryptMlKemkeyInitialize(_In_ PCSYMCRYPT_MLKEM_INTERNAL_PARAMS pInternalParams, _Out_writes_bytes_(cbKey) PBYTE pbKey, UINT32 cbKey)
Definition: mlkem.c:90
static SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemkeyGetInternalParamsFromParams(SYMCRYPT_MLKEM_PARAMS params, _Out_ PSYMCRYPT_MLKEM_INTERNAL_PARAMS pInternalParams)
Definition: mlkem.c:61
SYMCRYPT_MLKEM_INTERNAL_PARAMS
Definition: sc_lib_mlkem.h:79
struct _SYMCRYPT_MLKEMKEY SYMCRYPT_MLKEMKEY
PCBYTE pbKey
SYMCRYPT_MLKEMKEY * PSYMCRYPT_MLKEMKEY
PCBYTE SIZE_T cbKey
PCSYMCRYPT_HMAC_MD5_EXPANDED_KEY pKey

◆ SymCryptMlKemkeyComputeEncapsulationKeyHash()

static VOID SYMCRYPT_CALL SymCryptMlKemkeyComputeEncapsulationKeyHash ( _Inout_ PSYMCRYPT_MLKEMKEY  pkMlKemkey,
_Inout_ PSYMCRYPT_MLKEM_INTERNAL_COMPUTATION_TEMPORARIES  pCompTemps,
SIZE_T  cbEncodedVector 
)
static

Definition at line 321 of file mlkem.c.

325{
326 PSYMCRYPT_SHA3_256_STATE pState = &pCompTemps->hashState0.sha3_256State;
327
329 SymCryptSha3_256Append( pState, pkMlKemkey->encodedT, cbEncodedVector );
330 SymCryptSha3_256Append( pState, pkMlKemkey->publicSeed, sizeof(pkMlKemkey->publicSeed) );
331 SymCryptSha3_256Result( pState, pkMlKemkey->encapsKeyHash );
332}
VOID SYMCRYPT_CALL SymCryptSha3_256Init(_Out_ PSYMCRYPT_SHA3_256_STATE pState)
Definition: sha3_256.c:45
VOID SYMCRYPT_CALL SymCryptSha3_256Result(_Inout_ PSYMCRYPT_SHA3_256_STATE pState, _Out_writes_(SYMCRYPT_SHA3_256_RESULT_SIZE) PBYTE pbResult)
Definition: sha3_256.c:74
VOID SYMCRYPT_CALL SymCryptSha3_256Append(_Inout_ PSYMCRYPT_SHA3_256_STATE pState, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData)
Definition: sha3_256.c:60
SYMCRYPT_MAGIC_FIELD * PSYMCRYPT_SHA3_256_STATE
PSYMCRYPT_COMMON_HASH_STATE pState

Referenced by SymCryptMlKemkeyExpandFromPrivateSeed(), and SymCryptMlKemkeySetValue().

◆ SymCryptMlKemkeyExpandFromPrivateSeed()

static VOID SYMCRYPT_CALL SymCryptMlKemkeyExpandFromPrivateSeed ( _Inout_ PSYMCRYPT_MLKEMKEY  pkMlKemkey,
_Inout_ PSYMCRYPT_MLKEM_INTERNAL_COMPUTATION_TEMPORARIES  pCompTemps 
)
static

Definition at line 337 of file mlkem.c.

340{
341 BYTE privateSeedHash[SYMCRYPT_SHA3_512_RESULT_SIZE];
342 BYTE CBDSampleBuffer[3*64 + 1];
345 PSYMCRYPT_SHAKE256_STATE pShakeStateBase = &pCompTemps->hashState0.shake256State;
346 PSYMCRYPT_SHAKE256_STATE pShakeStateWork = &pCompTemps->hashState1.shake256State;
347 UINT32 i;
348 const UINT32 nRows = pkMlKemkey->params.nRows;
349 const UINT32 nEta1 = pkMlKemkey->params.nEta1;
351 const UINT32 cbPolyElement = pkMlKemkey->params.cbPolyElement;
352 const UINT32 cbVector = pkMlKemkey->params.cbVector;
353
354 SYMCRYPT_ASSERT( pkMlKemkey->hasPrivateSeed );
355 SYMCRYPT_ASSERT( (nEta1 == 2) || (nEta1 == 3) );
356 SYMCRYPT_ASSERT( cbEncodedVector <= sizeof(pkMlKemkey->encodedT) );
357
358 pvTmp = SymCryptMlKemVectorCreate( pCompTemps->abVectorBuffer0, cbVector, nRows );
359 SYMCRYPT_ASSERT( pvTmp != NULL );
360 paTmp = SymCryptMlKemPolyElementAccumulatorCreate( pCompTemps->abPolyElementAccumulatorBuffer, 2*cbPolyElement );
361 SYMCRYPT_ASSERT( paTmp != NULL );
362
363 // (rho || sigma) = G(d || k)
364 // use CBDSampleBuffer to concatenate the private seed and encoding of nRows
365 memcpy( CBDSampleBuffer, pkMlKemkey->privateSeed, sizeof(pkMlKemkey->privateSeed) );
366 CBDSampleBuffer[sizeof(pkMlKemkey->privateSeed)] = (BYTE) nRows;
367 SymCryptSha3_512( CBDSampleBuffer, sizeof(pkMlKemkey->privateSeed)+1, privateSeedHash );
368
369 // copy public seed
370 memcpy( pkMlKemkey->publicSeed, privateSeedHash, sizeof(pkMlKemkey->publicSeed) );
371
372 // generate A from public seed
374
375 // Initialize pShakeStateBase with sigma
376 SymCryptShake256Init( pShakeStateBase );
377 SymCryptShake256Append( pShakeStateBase, privateSeedHash+sizeof(pkMlKemkey->publicSeed), 32 );
378
379 // Expand s in place
380 for( i=0; i<nRows; i++ )
381 {
382 CBDSampleBuffer[0] = (BYTE) i;
383 SymCryptShake256StateCopy( pShakeStateBase, pShakeStateWork );
384 SymCryptShake256Append( pShakeStateWork, CBDSampleBuffer, 1 );
385
386 SymCryptShake256Extract( pShakeStateWork, CBDSampleBuffer, 64ul*nEta1, FALSE );
387
389 }
390 // Expand e in t, ready for multiply-add
391 for( i=0; i<nRows; i++ )
392 {
393 CBDSampleBuffer[0] = (BYTE) (nRows+i);
394 SymCryptShake256StateCopy( pShakeStateBase, pShakeStateWork );
395 SymCryptShake256Append( pShakeStateWork, CBDSampleBuffer, 1 );
396
397 SymCryptShake256Extract( pShakeStateWork, CBDSampleBuffer, 64ul*nEta1, FALSE );
398
400 }
401
402 // Perform NTT on s and e
405
406 // pvTmp = s .* R
407 SymCryptMlKemVectorMulR( pkMlKemkey->pvs, pvTmp );
408
409 // t = ((A o (s .* R)) ./ R) + e = A o s + e
410 SymCryptMlKemMatrixVectorMontMulAndAdd( pkMlKemkey->pmAtranspose, pvTmp, pkMlKemkey->pvt, paTmp );
411
412 // transpose A
414
415 // precompute byte-encoding of public vector t
416 SymCryptMlKemVectorCompressAndEncode( pkMlKemkey->pvt, 12, pkMlKemkey->encodedT, cbEncodedVector );
417
418 // precompute hash of encapsulation key blob
419 SymCryptMlKemkeyComputeEncapsulationKeyHash( pkMlKemkey, pCompTemps, cbEncodedVector );
420
421 // Cleanup!
422 SymCryptWipeKnownSize( privateSeedHash, sizeof(privateSeedHash) );
423 SymCryptWipeKnownSize( CBDSampleBuffer, sizeof(CBDSampleBuffer) );
424}
static VOID SYMCRYPT_CALL SymCryptMlKemkeyExpandPublicMatrixFromPublicSeed(_Inout_ PSYMCRYPT_MLKEMKEY pkMlKemkey, _Inout_ PSYMCRYPT_MLKEM_INTERNAL_COMPUTATION_TEMPORARIES pCompTemps)
Definition: mlkem.c:288
static VOID SYMCRYPT_CALL SymCryptMlKemkeyComputeEncapsulationKeyHash(_Inout_ PSYMCRYPT_MLKEMKEY pkMlKemkey, _Inout_ PSYMCRYPT_MLKEM_INTERNAL_COMPUTATION_TEMPORARIES pCompTemps, SIZE_T cbEncodedVector)
Definition: mlkem.c:321
#define SYMCRYPT_MLKEM_SIZEOF_ENCODED_UNCOMPRESSED_VECTOR(_nRows)
Definition: mlkem.c:193
VOID SYMCRYPT_CALL SymCryptMlKemVectorMulR(_In_ PCSYMCRYPT_MLKEM_VECTOR pvSrc, _Out_ PSYMCRYPT_MLKEM_VECTOR pvDst)
VOID SYMCRYPT_CALL SymCryptMlKemMatrixTranspose(_Inout_ PSYMCRYPT_MLKEM_MATRIX pmSrc)
#define SYMCRYPT_SHA3_512_RESULT_SIZE
Definition: symcrypt.h:1722
VOID SYMCRYPT_CALL SymCryptSha3_512(_In_reads_(cbData) PCBYTE pbData, SIZE_T cbData, _Out_writes_(SYMCRYPT_SHA3_512_RESULT_SIZE) PBYTE pbResult)

Referenced by SymCryptMlKemkeySetValue().

◆ SymCryptMlKemkeyExpandPublicMatrixFromPublicSeed()

static VOID SYMCRYPT_CALL SymCryptMlKemkeyExpandPublicMatrixFromPublicSeed ( _Inout_ PSYMCRYPT_MLKEMKEY  pkMlKemkey,
_Inout_ PSYMCRYPT_MLKEM_INTERNAL_COMPUTATION_TEMPORARIES  pCompTemps 
)
static

Definition at line 288 of file mlkem.c.

291{
292 UINT32 i, j;
293 BYTE coordinates[2];
294
295 PSYMCRYPT_SHAKE128_STATE pShakeStateBase = &pCompTemps->hashState0.shake128State;
296 PSYMCRYPT_SHAKE128_STATE pShakeStateWork = &pCompTemps->hashState1.shake128State;
297 const UINT32 nRows = pkMlKemkey->params.nRows;
298
299 SymCryptShake128Init( pShakeStateBase );
300 SymCryptShake128Append( pShakeStateBase, pkMlKemkey->publicSeed, sizeof(pkMlKemkey->publicSeed) );
301
302 for( i=0; i<nRows; i++ )
303 {
304 coordinates[1] = (BYTE)i;
305 for( j=0; j<nRows; j++ )
306 {
307 coordinates[0] = (BYTE)j;
308 SymCryptShake128StateCopy( pShakeStateBase, pShakeStateWork );
309 SymCryptShake128Append( pShakeStateWork, coordinates, sizeof(coordinates) );
310
311 SymCryptMlKemPolyElementSampleNTTFromShake128( pShakeStateWork, pkMlKemkey->pmAtranspose->apPolyElements[(i*nRows)+j] );
312 }
313 }
314
315 // no need to wipe; everything computed here is always public
316}
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
VOID SYMCRYPT_CALL SymCryptMlKemPolyElementSampleNTTFromShake128(_Inout_ PSYMCRYPT_SHAKE128_STATE pState, _Out_ PSYMCRYPT_MLKEM_POLYELEMENT peDst)
VOID SYMCRYPT_CALL SymCryptShake128Append(_Inout_ PSYMCRYPT_SHAKE128_STATE pState, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData)
VOID SYMCRYPT_CALL SymCryptShake128Init(_Out_ PSYMCRYPT_SHAKE128_STATE pState)
VOID SYMCRYPT_CALL SymCryptShake128StateCopy(_In_ PCSYMCRYPT_SHAKE128_STATE pSrc, _Out_ PSYMCRYPT_SHAKE128_STATE pDst)
SYMCRYPT_MAGIC_FIELD * PSYMCRYPT_SHAKE128_STATE

Referenced by SymCryptMlKemkeyExpandFromPrivateSeed(), and SymCryptMlKemkeySetValue().

◆ SymCryptMlKemkeyFree()

VOID SYMCRYPT_CALL SymCryptMlKemkeyFree ( _Inout_ PSYMCRYPT_MLKEMKEY  pkMlKemkey)

Definition at line 183 of file mlkem.c.

185{
187
188 SymCryptWipe( (PBYTE) pkMlKemkey, pkMlKemkey->cbTotalSize );
189
191}
#define SYMCRYPT_CHECK_MAGIC(p)

◆ SymCryptMlKemkeyGenerate()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemkeyGenerate ( _Inout_ PSYMCRYPT_MLKEMKEY  pkMlKemkey,
UINT32  flags 
)

Definition at line 701 of file mlkem.c.

704{
705 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
707 PBYTE pbPctCipherText = NULL;
708 SIZE_T cbPctCipherText = 0;
709
710 // Ensure only allowed flags are specified
711 UINT32 allowedFlags = SYMCRYPT_FLAG_KEY_NO_FIPS;
712
713 if ( ( flags & ~allowedFlags ) != 0 )
714 {
715 scError = SYMCRYPT_INVALID_ARGUMENT;
716 goto cleanup;
717 }
718
719 scError = SymCryptCallbackRandom( privateSeed, sizeof(privateSeed) );
720 if( scError != SYMCRYPT_NO_ERROR )
721 {
722 goto cleanup;
723 }
724
726 if( scError != SYMCRYPT_NO_ERROR )
727 {
728 goto cleanup;
729 }
730
731 // SymCryptMlKemkeySetValue ensures the self-test is run before
732 // first operational use of MlKem
733
734 if( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 )
735 {
736 // PCT on key generation, encaps/decaps and check that both parties get the same shared secret with the generated key
737 SIZE_T cbU, cbV;
738 const UINT32 nRows = pkMlKemkey->params.nRows;
739 const UINT32 nBitsOfU = pkMlKemkey->params.nBitsOfU;
740 const UINT32 nBitsOfV = pkMlKemkey->params.nBitsOfV;
741
742 // u vector encoded with nBitsOfU * SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS bits per polynomial
744 // v polynomial encoded with nBitsOfV * SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS bits
746 cbPctCipherText = cbU + cbV;
747
748 pbPctCipherText = SymCryptCallbackAlloc( cbPctCipherText );
749 if( pbPctCipherText == NULL )
750 {
751 scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
752 goto cleanup;
753 }
754
756
757 // reuse bytes 0..31 of privateSeed buffer for encapsulation shared secret
758 scError = SymCryptMlKemEncapsulate(
761 pbPctCipherText, cbPctCipherText );
762 if( scError != SYMCRYPT_NO_ERROR )
763 {
764 scError = SYMCRYPT_FIPS_FAILURE;
765 goto cleanup;
766 }
767
768 // reuse second 32..63 bytes of privateSeed buffer for encapsulation shared secret
769 scError = SymCryptMlKemDecapsulate(
771 pbPctCipherText, cbPctCipherText,
773 if( scError != SYMCRYPT_NO_ERROR )
774 {
775 scError = SYMCRYPT_FIPS_FAILURE;
776 goto cleanup;
777 }
778
780 {
781 // Do not fatal on PCT failure here, as it is expected with very low probability that
782 // with correct keygen and encaps/decaps, the agreed secrets do not match
783 scError = SYMCRYPT_FIPS_FAILURE;
784 goto cleanup;
785 }
786
787 // could track having run the PCT with a flag in pkMlKemkey->fAlgorithmInfo,
788 // but currently no need to do that given we don't ever defer the PCT
789 }
790
791cleanup:
792 if( pbPctCipherText != NULL )
793 {
794 // Wiping is not required for security, but has low relative cost
795 // and better to be on the safe side for FIPS
796 SymCryptWipe( pbPctCipherText, cbPctCipherText );
797 SymCryptCallbackFree( pbPctCipherText );
798 }
799
801
802 return scError;
803}
GLbitfield flags
Definition: glext.h:7161
#define C_ASSERT(e)
Definition: intsafe.h:73
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemEncapsulate(_In_ PCSYMCRYPT_MLKEMKEY pkMlKemkey, _Out_writes_bytes_(cbAgreedSecret) PBYTE pbAgreedSecret, SIZE_T cbAgreedSecret, _Out_writes_bytes_(cbCiphertext) PBYTE pbCiphertext, SIZE_T cbCiphertext)
Definition: mlkem.c:996
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemkeySetValue(_In_reads_bytes_(cbSrc) PCBYTE pbSrc, SIZE_T cbSrc, SYMCRYPT_MLKEMKEY_FORMAT mlKemkeyFormat, UINT32 flags, _Inout_ PSYMCRYPT_MLKEMKEY pkMlKemkey)
Definition: mlkem.c:428
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemDecapsulate(_In_ PCSYMCRYPT_MLKEMKEY pkMlKemkey, _In_reads_bytes_(cbCiphertext) PCBYTE pbCiphertext, SIZE_T cbCiphertext, _Out_writes_bytes_(cbAgreedSecret) PBYTE pbAgreedSecret, SIZE_T cbAgreedSecret)
Definition: mlkem.c:1026
BYTE privateSeed[SYMCRYPT_COMPOSITE_MLKEM_IRTF_PRIVATE_SEED_SIZE]
Definition: sc_lib.h:4450
#define SYMCRYPT_MLKEM_PRIVATE_SEED_SIZE
Definition: symcrypt.h:10007
@ SYMCRYPT_MLKEMKEY_FORMAT_PRIVATE_SEED
Definition: symcrypt.h:9964
#define SYMCRYPT_FLAG_KEY_NO_FIPS
Definition: symcrypt.h:7579

◆ SymCryptMlKemkeyGetInternalParamsFromParams()

static SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemkeyGetInternalParamsFromParams ( SYMCRYPT_MLKEM_PARAMS  params,
_Out_ PSYMCRYPT_MLKEM_INTERNAL_PARAMS  pInternalParams 
)
static

Definition at line 61 of file mlkem.c.

64{
65 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
66
67 switch( params )
68 {
70 *pInternalParams = SymCryptMlKemInternalParamsMlKem512;
71 break;
73 *pInternalParams = SymCryptMlKemInternalParamsMlKem768;
74 break;
76 *pInternalParams = SymCryptMlKemInternalParamsMlKem1024;
77 break;
78 default:
79 scError = SYMCRYPT_INVALID_ARGUMENT;
80 goto cleanup;
81 }
82
84 return scError;
85}
const SYMCRYPT_MLKEM_INTERNAL_PARAMS SymCryptMlKemInternalParamsMlKem1024
Definition: mlkem.c:43
const SYMCRYPT_MLKEM_INTERNAL_PARAMS SymCryptMlKemInternalParamsMlKem512
Definition: mlkem.c:13
const SYMCRYPT_MLKEM_INTERNAL_PARAMS SymCryptMlKemInternalParamsMlKem768
Definition: mlkem.c:28
@ SYMCRYPT_MLKEM_PARAMS_MLKEM768
Definition: symcrypt.h:9981
@ SYMCRYPT_MLKEM_PARAMS_MLKEM512
Definition: symcrypt.h:9980
@ SYMCRYPT_MLKEM_PARAMS_MLKEM1024
Definition: symcrypt.h:9982

Referenced by SymCryptMlKemkeyAllocate(), SymCryptMlKemSizeofCiphertextFromParams(), and SymCryptMlKemSizeofKeyFormatFromParams().

◆ SymCryptMlKemkeyGetValue()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemkeyGetValue ( _In_ PCSYMCRYPT_MLKEMKEY  pkMlKemkey,
_Out_writes_bytes_(cbDst) PBYTE  pbDst,
SIZE_T  cbDst,
SYMCRYPT_MLKEMKEY_FORMAT  mlKemkeyFormat,
UINT32  flags 
)

Definition at line 601 of file mlkem.c.

607{
608 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
609 PBYTE pbCurr = pbDst;
610 const UINT32 nRows = pkMlKemkey->params.nRows;
612
614
615 if( mlKemkeyFormat == SYMCRYPT_MLKEMKEY_FORMAT_NULL )
616 {
617 scError = SYMCRYPT_INVALID_ARGUMENT;
618 goto cleanup;
619 }
620
621 if( mlKemkeyFormat == SYMCRYPT_MLKEMKEY_FORMAT_PRIVATE_SEED )
622 {
624 {
625 scError = SYMCRYPT_WRONG_KEY_SIZE;
626 goto cleanup;
627 }
628
629 if( !pkMlKemkey->hasPrivateSeed )
630 {
631 scError = SYMCRYPT_INCOMPATIBLE_FORMAT;
632 goto cleanup;
633 }
634
635 memcpy( pbCurr, pkMlKemkey->privateSeed, sizeof(pkMlKemkey->privateSeed) );
636 pbCurr += sizeof(pkMlKemkey->privateSeed);
637
638 memcpy( pbCurr, pkMlKemkey->privateRandom, sizeof(pkMlKemkey->privateRandom) );
639 pbCurr += sizeof(pkMlKemkey->privateRandom);
640 }
641 else if( mlKemkeyFormat == SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY )
642 {
644 {
645 scError = SYMCRYPT_INVALID_ARGUMENT;
646 goto cleanup;
647 }
648
649 if( !pkMlKemkey->hasPrivateKey )
650 {
651 scError = SYMCRYPT_INCOMPATIBLE_FORMAT;
652 goto cleanup;
653 }
654
655 // We don't precompute byte-encoding of private key as exporting decapsulation key is not a critical path operation
656 // All other fields are kept in memory
657 SymCryptMlKemVectorCompressAndEncode( pkMlKemkey->pvs, 12, pbCurr, cbEncodedVector );
658 pbCurr += cbEncodedVector;
659
660 memcpy( pbCurr, pkMlKemkey->encodedT, cbEncodedVector );
661 pbCurr += cbEncodedVector;
662
663 memcpy( pbCurr, pkMlKemkey->publicSeed, sizeof(pkMlKemkey->publicSeed) );
664 pbCurr += sizeof(pkMlKemkey->publicSeed);
665
666 memcpy( pbCurr, pkMlKemkey->encapsKeyHash, sizeof(pkMlKemkey->encapsKeyHash) );
667 pbCurr += sizeof(pkMlKemkey->encapsKeyHash);
668
669 memcpy( pbCurr, pkMlKemkey->privateRandom, sizeof(pkMlKemkey->privateRandom) );
670 pbCurr += sizeof(pkMlKemkey->privateRandom);
671 }
672 else if( mlKemkeyFormat == SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY )
673 {
675 {
676 scError = SYMCRYPT_INVALID_ARGUMENT;
677 goto cleanup;
678 }
679
680 memcpy( pbCurr, pkMlKemkey->encodedT, cbEncodedVector );
681 pbCurr += cbEncodedVector;
682
683 memcpy( pbCurr, pkMlKemkey->publicSeed, sizeof(pkMlKemkey->publicSeed) );
684 pbCurr += sizeof(pkMlKemkey->publicSeed);
685 }
686 else
687 {
688 scError = SYMCRYPT_NOT_IMPLEMENTED;
689 goto cleanup;
690 }
691
692 SYMCRYPT_ASSERT( pbCurr == pbDst + cbDst );
693
694cleanup:
695 return scError;
696}
#define SYMCRYPT_MLKEM_SIZEOF_FORMAT_ENCAPSULATION_KEY(_nRows)
Definition: mlkem.c:200
#define SYMCRYPT_MLKEM_SIZEOF_FORMAT_DECAPSULATION_KEY(_nRows)
Definition: mlkem.c:197
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
@ SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY
Definition: symcrypt.h:9972
@ SYMCRYPT_MLKEMKEY_FORMAT_NULL
Definition: symcrypt.h:9963
@ SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY
Definition: symcrypt.h:9969
PCBYTE PBYTE pbDst

◆ SymCryptMlKemkeyInitialize()

static PSYMCRYPT_MLKEMKEY SYMCRYPT_CALL SymCryptMlKemkeyInitialize ( _In_ PCSYMCRYPT_MLKEM_INTERNAL_PARAMS  pInternalParams,
_Out_writes_bytes_(cbKey) PBYTE  pbKey,
UINT32  cbKey 
)
static

Definition at line 90 of file mlkem.c.

94{
97 PBYTE pbCurr = pbKey + sizeof(SYMCRYPT_MLKEMKEY);
98
100
101 pKey->fAlgorithmInfo = 0;
102 pKey->params = *pInternalParams;
103 pKey->cbTotalSize = cbKey;
104 pKey->hasPrivateSeed = FALSE;
105 pKey->hasPrivateKey = FALSE;
106
107 pKey->pmAtranspose = SymCryptMlKemMatrixCreate( pbCurr, pInternalParams->cbMatrix, pInternalParams->nRows );
108 if( pKey->pmAtranspose == NULL )
109 {
110 goto cleanup;
111 }
112 pbCurr += pInternalParams->cbMatrix;
113
114 pKey->pvt = SymCryptMlKemVectorCreate( pbCurr, pInternalParams->cbVector, pInternalParams->nRows );
115 if( pKey->pvt == NULL )
116 {
117 goto cleanup;
118 }
119 pbCurr += pInternalParams->cbVector;
120
121 pKey->pvs = SymCryptMlKemVectorCreate( pbCurr, pInternalParams->cbVector, pInternalParams->nRows );
122 if( pKey->pvs == NULL )
123 {
124 goto cleanup;
125 }
126 pbCurr += pInternalParams->cbVector;
127
128 SYMCRYPT_ASSERT( pbCurr == (pbKey + cbKey) );
129
131
132 pRes = pKey;
133
134cleanup:
135 return pRes;
136}
PSYMCRYPT_MLKEM_MATRIX SYMCRYPT_CALL SymCryptMlKemMatrixCreate(_Out_writes_bytes_(cbBuffer) PBYTE pbBuffer, UINT32 cbBuffer, UINT32 nRows)
#define SYMCRYPT_SET_MAGIC(p)

Referenced by SymCryptMlKemkeyAllocate().

◆ SymCryptMlKemkeySetValue()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemkeySetValue ( _In_reads_bytes_(cbSrc) PCBYTE  pbSrc,
SIZE_T  cbSrc,
SYMCRYPT_MLKEMKEY_FORMAT  mlKemkeyFormat,
UINT32  flags,
_Inout_ PSYMCRYPT_MLKEMKEY  pkMlKemkey 
)

Definition at line 428 of file mlkem.c.

434{
435 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
436 PCBYTE pbCurr = pbSrc;
438 const UINT32 nRows = pkMlKemkey->params.nRows;
440
441 // Ensure only allowed flags are specified
443
444 if ( ( flags & ~allowedFlags ) != 0 )
445 {
446 scError = SYMCRYPT_INVALID_ARGUMENT;
447 goto cleanup;
448 }
449
450 // Check that minimal validation flag only specified with no fips
451 if ( ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 ) &&
453 {
454 scError = SYMCRYPT_INVALID_ARGUMENT;
455 goto cleanup;
456 }
457
458 if( mlKemkeyFormat == SYMCRYPT_MLKEMKEY_FORMAT_NULL )
459 {
460 scError = SYMCRYPT_INVALID_ARGUMENT;
461 goto cleanup;
462 }
463
464 if( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 )
465 {
466 // Ensure ML-KEM algorithm selftest is run before first use of ML-KEM algorithms;
467 // notably _before_ first full KeyGen
471 }
472
474 if( pCompTemps == NULL )
475 {
476 scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
477 goto cleanup;
478 }
479
480 if( mlKemkeyFormat == SYMCRYPT_MLKEMKEY_FORMAT_PRIVATE_SEED )
481 {
483 {
484 scError = SYMCRYPT_WRONG_KEY_SIZE;
485 goto cleanup;
486 }
487
488 pkMlKemkey->hasPrivateSeed = TRUE;
489 memcpy( pkMlKemkey->privateSeed, pbCurr, sizeof(pkMlKemkey->privateSeed) );
490 pbCurr += sizeof(pkMlKemkey->privateSeed);
491
492 pkMlKemkey->hasPrivateKey = TRUE;
493 memcpy( pkMlKemkey->privateRandom, pbCurr, sizeof(pkMlKemkey->privateRandom) );
494 pbCurr += sizeof(pkMlKemkey->privateRandom);
495
497 }
498 else if( mlKemkeyFormat == SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY )
499 {
501 {
502 scError = SYMCRYPT_WRONG_KEY_SIZE;
503 goto cleanup;
504 }
505
506 // decode s
507 scError = SymCryptMlKemVectorDecodeAndDecompress( pbCurr, cbEncodedVector, 12, pkMlKemkey->pvs );
508 if( scError != SYMCRYPT_NO_ERROR )
509 {
510 goto cleanup;
511 }
512 pbCurr += cbEncodedVector;
513
514 // copy t and decode t
515 memcpy( pkMlKemkey->encodedT, pbCurr, cbEncodedVector );
516 pbCurr += cbEncodedVector;
517 scError = SymCryptMlKemVectorDecodeAndDecompress( pkMlKemkey->encodedT, cbEncodedVector, 12, pkMlKemkey->pvt );
518 if( scError != SYMCRYPT_NO_ERROR )
519 {
520 goto cleanup;
521 }
522
523 // copy public seed and expand public matrix
524 memcpy( pkMlKemkey->publicSeed, pbCurr, sizeof(pkMlKemkey->publicSeed) );
525 pbCurr += sizeof(pkMlKemkey->publicSeed);
527
528 // transpose A
530
531 // compute hash of encapsulation key blob
532 SymCryptMlKemkeyComputeEncapsulationKeyHash( pkMlKemkey, pCompTemps, cbEncodedVector );
533
534 // check hash of encapsulation key matches hash in the provided blob
535 if( !SymCryptEqual( pbCurr, pkMlKemkey->encapsKeyHash, sizeof(pkMlKemkey->encapsKeyHash) ) )
536 {
537 scError = SYMCRYPT_INVALID_BLOB;
538 goto cleanup;
539 }
540 pbCurr += sizeof(pkMlKemkey->encapsKeyHash);
541
542 // copy private random
543 memcpy( pkMlKemkey->privateRandom, pbCurr, sizeof(pkMlKemkey->privateRandom) );
544 pbCurr += sizeof(pkMlKemkey->privateRandom);
545
546 pkMlKemkey->hasPrivateSeed = FALSE;
547 pkMlKemkey->hasPrivateKey = TRUE;
548 }
549 else if( mlKemkeyFormat == SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY )
550 {
552 {
553 scError = SYMCRYPT_WRONG_KEY_SIZE;
554 goto cleanup;
555 }
556
557 // copy t and decode t
558 memcpy( pkMlKemkey->encodedT, pbCurr, cbEncodedVector );
559 pbCurr += cbEncodedVector;
560 scError = SymCryptMlKemVectorDecodeAndDecompress( pkMlKemkey->encodedT, cbEncodedVector, 12, pkMlKemkey->pvt );
561 if( scError != SYMCRYPT_NO_ERROR )
562 {
563 goto cleanup;
564 }
565
566 // copy public seed and expand public matrix
567 memcpy( pkMlKemkey->publicSeed, pbCurr, sizeof(pkMlKemkey->publicSeed) );
568 pbCurr += sizeof(pkMlKemkey->publicSeed);
570
571 // transpose A
573
574 // precompute hash of encapsulation key blob
575 SymCryptMlKemkeyComputeEncapsulationKeyHash( pkMlKemkey, pCompTemps, cbEncodedVector );
576
577 pkMlKemkey->hasPrivateSeed = FALSE;
578 pkMlKemkey->hasPrivateKey = FALSE;
579 }
580 else
581 {
582 scError = SYMCRYPT_NOT_IMPLEMENTED;
583 goto cleanup;
584 }
585
586 SYMCRYPT_ASSERT( pbCurr == pbSrc + cbSrc );
587
588cleanup:
589 if( pCompTemps != NULL )
590 {
591 SymCryptWipe( pCompTemps, sizeof(*pCompTemps) );
592 SymCryptCallbackFree( pCompTemps );
593 }
594
595 return scError;
596}
#define TRUE
Definition: types.h:120
static VOID SYMCRYPT_CALL SymCryptMlKemkeyExpandFromPrivateSeed(_Inout_ PSYMCRYPT_MLKEMKEY pkMlKemkey, _Inout_ PSYMCRYPT_MLKEM_INTERNAL_COMPUTATION_TEMPORARIES pCompTemps)
Definition: mlkem.c:337
#define SYMCRYPT_RUN_SELFTEST_ONCE(AlgorithmSelftestFunction, AlgorithmSelftestFlag)
Definition: sc_lib.h:3686
#define SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION
Definition: symcrypt.h:7586
VOID SYMCRYPT_CALL SymCryptMlKemSelftest(void)
PCBYTE pbSrc
@ SYMCRYPT_SELFTEST_ALGORITHM_MLKEM
const BYTE * PCBYTE

Referenced by SymCryptMlKemkeyGenerate().

◆ SymCryptMlKemSizeofCiphertextFromParams()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemSizeofCiphertextFromParams ( SYMCRYPT_MLKEM_PARAMS  params,
_Out_ SIZE_T *  pcbCiphertext 
)

Definition at line 257 of file mlkem.c.

260{
261 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
262 SYMCRYPT_MLKEM_INTERNAL_PARAMS internalParams;
263 SIZE_T cbU, cbV;
264
265 scError = SymCryptMlKemkeyGetInternalParamsFromParams(params, &internalParams);
266 if( scError != SYMCRYPT_NO_ERROR )
267 {
268 goto cleanup;
269 }
270
271 // u vector encoded with nBitsOfU * SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS bits per polynomial
272 cbU = ((SIZE_T)internalParams.nRows) * internalParams.nBitsOfU * (SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS / 8);
273 // v polynomial encoded with nBitsOfV * SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS bits
274 cbV = ((SIZE_T)internalParams.nBitsOfV) * (SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS / 8);
275 *pcbCiphertext = cbU + cbV;
276
277 SYMCRYPT_ASSERT( (internalParams.params != SYMCRYPT_MLKEM_PARAMS_MLKEM512) || ((cbU + cbV) == SYMCRYPT_MLKEM_CIPHERTEXT_SIZE_MLKEM512) );
278 SYMCRYPT_ASSERT( (internalParams.params != SYMCRYPT_MLKEM_PARAMS_MLKEM768) || ((cbU + cbV) == SYMCRYPT_MLKEM_CIPHERTEXT_SIZE_MLKEM768) );
279 SYMCRYPT_ASSERT( (internalParams.params != SYMCRYPT_MLKEM_PARAMS_MLKEM1024) || ((cbU + cbV) == SYMCRYPT_MLKEM_CIPHERTEXT_SIZE_MLKEM1024) );
280
281cleanup:
282 return scError;
283}
#define SYMCRYPT_MLKEM_CIPHERTEXT_SIZE_MLKEM768
Definition: symcrypt.h:10031
#define SYMCRYPT_MLKEM_CIPHERTEXT_SIZE_MLKEM512
Definition: symcrypt.h:10030
#define SYMCRYPT_MLKEM_CIPHERTEXT_SIZE_MLKEM1024
Definition: symcrypt.h:10032

◆ SymCryptMlKemSizeofKeyFormatFromParams()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemSizeofKeyFormatFromParams ( SYMCRYPT_MLKEM_PARAMS  params,
SYMCRYPT_MLKEMKEY_FORMAT  mlKemkeyFormat,
_Out_ SIZE_T *  pcbKeyFormat 
)

Definition at line 212 of file mlkem.c.

216{
217 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
218 SYMCRYPT_MLKEM_INTERNAL_PARAMS internalParams;
219
220 if( mlKemkeyFormat == SYMCRYPT_MLKEMKEY_FORMAT_NULL )
221 {
222 scError = SYMCRYPT_INCOMPATIBLE_FORMAT;
223 goto cleanup;
224 }
225
226 scError = SymCryptMlKemkeyGetInternalParamsFromParams(params, &internalParams);
227 if( scError != SYMCRYPT_NO_ERROR )
228 {
229 goto cleanup;
230 }
231
232 switch( mlKemkeyFormat )
233 {
235 *pcbKeyFormat = SYMCRYPT_MLKEM_PRIVATE_SEED_SIZE;
236 break;
237
239 *pcbKeyFormat = SYMCRYPT_MLKEM_SIZEOF_FORMAT_DECAPSULATION_KEY(internalParams.nRows);
240 break;
241
243 *pcbKeyFormat = SYMCRYPT_MLKEM_SIZEOF_FORMAT_ENCAPSULATION_KEY(internalParams.nRows);
244 break;
245
246 default:
247 scError = SYMCRYPT_INVALID_ARGUMENT;
248 goto cleanup;
249 }
250
251cleanup:
252 return scError;
253}

Variable Documentation

◆ SymCryptMlKemInternalParamsMlKem1024

const SYMCRYPT_MLKEM_INTERNAL_PARAMS SymCryptMlKemInternalParamsMlKem1024
Initial value:
=
{
.nRows = NROWS_MLKEM1024,
.cbMatrix = sizeof(SYMCRYPT_MLKEM_MATRIX) + (NROWS_MLKEM1024 *
.nEta1 = 2,
.nEta2 = 2,
.nBitsOfU = 11,
.nBitsOfV = 5,
}
#define NROWS_MLKEM1024
Definition: mlkem.c:11
SYMCRYPT_MLKEM_MATRIX
Definition: sc_lib_mlkem.h:53
#define SYMCRYPT_INTERNAL_MLKEM_SIZEOF_POLYRINGELEMENT
Definition: sc_lib_mlkem.h:125
SYMCRYPT_MLKEM_VECTOR
Definition: sc_lib_mlkem.h:37

Definition at line 43 of file mlkem.c.

Referenced by SymCryptMlKemkeyGetInternalParamsFromParams().

◆ SymCryptMlKemInternalParamsMlKem512

const SYMCRYPT_MLKEM_INTERNAL_PARAMS SymCryptMlKemInternalParamsMlKem512
Initial value:
=
{
.nRows = NROWS_MLKEM512,
.cbMatrix = sizeof(SYMCRYPT_MLKEM_MATRIX) + (NROWS_MLKEM512 *
.nEta1 = 3,
.nEta2 = 2,
.nBitsOfU = 10,
.nBitsOfV = 4,
}
#define NROWS_MLKEM512
Definition: mlkem.c:9

Definition at line 13 of file mlkem.c.

Referenced by SymCryptMlKemkeyGetInternalParamsFromParams().

◆ SymCryptMlKemInternalParamsMlKem768

const SYMCRYPT_MLKEM_INTERNAL_PARAMS SymCryptMlKemInternalParamsMlKem768
Initial value:
=
{
.nRows = NROWS_MLKEM768,
.cbMatrix = sizeof(SYMCRYPT_MLKEM_MATRIX) + (NROWS_MLKEM768 *
.nEta1 = 2,
.nEta2 = 2,
.nBitsOfU = 10,
.nBitsOfV = 4,
}
#define NROWS_MLKEM768
Definition: mlkem.c:10

Definition at line 28 of file mlkem.c.

Referenced by SymCryptMlKemkeyGetInternalParamsFromParams().