@@ -308,7 +308,99 @@ public override int GetEncryptedSize(int plainTextLength, uint preBufferSize, ui
308308
309309 public override bool TryEncrypt( ReadOnlySpan < byte > plainText , ReadOnlySpan < byte > additionalAuthenticatedData , Span < byte > destination , out int bytesWritten)
310310 {
311- throw new NotImplementedException ( ) ;
311+ bytesWritten = 0 ;
312+
313+ try
314+ {
315+ // This buffer will be used to hold the symmetric encryption and HMAC subkeys
316+ // used in the generation of this payload.
317+ var cbTempSubkeys = checked ( _symmetricAlgorithmSubkeyLengthInBytes + _hmacAlgorithmSubkeyLengthInBytes) ;
318+ byte * pbTempSubkeys = stackalloc byte [ checked ( ( int ) cbTempSubkeys ) ] ;
319+
320+ try
321+ {
322+ // Randomly generate the key modifier and IV.
323+ var cbKeyModifierAndIV = checked ( KEY_MODIFIER_SIZE_IN_BYTES + _symmetricAlgorithmBlockSizeInBytes ) ;
324+ byte * pbKeyModifierAndIV = stackalloc byte [ checked ( ( int ) cbKeyModifierAndIV ) ] ;
325+ _genRandom . GenRandom ( pbKeyModifierAndIV , cbKeyModifierAndIV ) ;
326+
327+ // Calculate offsets
328+ byte * pbKeyModifier = pbKeyModifierAndIV;
329+ byte * pbIV = & pbKeyModifierAndIV[ KEY_MODIFIER_SIZE_IN_BYTES] ;
330+
331+ // Use the KDF to generate a new symmetric encryption and HMAC subkey
332+ fixed ( byte * pbAdditionalAuthenticatedData = additionalAuthenticatedData)
333+ {
334+ _sp800_108_ctr_hmac_provider. DeriveKeyWithContextHeader(
335+ pbLabel : pbAdditionalAuthenticatedData ,
336+ cbLabel : ( uint ) additionalAuthenticatedData . Length,
337+ contextHeader : _contextHeader ,
338+ pbContext : pbKeyModifier ,
339+ cbContext : KEY_MODIFIER_SIZE_IN_BYTES ,
340+ pbDerivedKey : pbTempSubkeys ,
341+ cbDerivedKey : cbTempSubkeys ) ;
342+ }
343+
344+ // Calculate offsets
345+ byte * pbSymmetricEncryptionSubkey = pbTempSubkeys;
346+ byte * pbHmacSubkey = & pbTempSubkeys[ _symmetricAlgorithmSubkeyLengthInBytes] ;
347+
348+ using ( var symmetricKeyHandle = _symmetricAlgorithmHandle. GenerateSymmetricKey( pbSymmetricEncryptionSubkey , _symmetricAlgorithmSubkeyLengthInBytes ) )
349+ {
350+ // Get the padded output size
351+ fixed ( byte * pbPlainText = plainText)
352+ {
353+ var cbOutputCiphertext = GetCbcEncryptedOutputSizeWithPadding ( symmetricKeyHandle , pbPlainText , ( uint ) plainText . Length ) ;
354+
355+ fixed ( byte * pbDestination = destination)
356+ {
357+ // Calculate offsets in destination
358+ byte * pbOutputKeyModifier = pbDestination;
359+ byte * pbOutputIV = & pbOutputKeyModifier[ KEY_MODIFIER_SIZE_IN_BYTES] ;
360+ byte * pbOutputCiphertext = & pbOutputIV[ _symmetricAlgorithmBlockSizeInBytes] ;
361+ byte * pbOutputHmac = & pbOutputCiphertext[ cbOutputCiphertext] ;
362+
363+ // Copy key modifier and IV to destination
364+ UnsafeBufferUtil . BlockCopy( from : pbKeyModifierAndIV , to : pbOutputKeyModifier , byteCount : cbKeyModifierAndIV ) ;
365+ bytesWritten += checked ( ( int ) cbKeyModifierAndIV) ;
366+
367+ // Perform CBC encryption directly into destination
368+ DoCbcEncrypt (
369+ symmetricKeyHandle : symmetricKeyHandle ,
370+ pbIV : pbIV ,
371+ pbInput : pbPlainText ,
372+ cbInput : ( uint ) plainText . Length,
373+ pbOutput : pbOutputCiphertext ,
374+ cbOutput : cbOutputCiphertext ) ;
375+ bytesWritten += checked ( ( int ) cbOutputCiphertext ) ;
376+
377+ // Compute the HMAC over the IV and the ciphertext
378+ using ( var hashHandle = _hmacAlgorithmHandle. CreateHmac( pbHmacSubkey, _hmacAlgorithmSubkeyLengthInBytes ) )
379+ {
380+ hashHandle. HashData(
381+ pbInput: pbOutputIV,
382+ cbInput : checked ( _symmetricAlgorithmBlockSizeInBytes + cbOutputCiphertext ) ,
383+ pbHashDigest : pbOutputHmac ,
384+ cbHashDigest : _hmacAlgorithmDigestLengthInBytes ) ;
385+ }
386+ bytesWritten += checked ( ( int ) _hmacAlgorithmDigestLengthInBytes ) ;
387+
388+ return true;
389+ }
390+ }
391+ }
392+ }
393+ finally
394+ {
395+ // Buffer contains sensitive material; delete it.
396+ UnsafeBufferUtil. SecureZeroMemory( pbTempSubkeys, cbTempSubkeys ) ;
397+ }
398+ }
399+ catch ( Exception ex) when ( ex . RequiresHomogenization ( ) )
400+ {
401+ // Homogenize all exceptions to CryptographicException.
402+ throw Error . CryptCommon_GenericError ( ex ) ;
403+ }
312404 }
313405#endif
314406
0 commit comments