@@ -56,89 +56,19 @@ public CbcAuthenticatedEncryptor(Secret keyDerivationKey, BCryptAlgorithmHandle
5656 _contextHeader = CreateContextHeader ( ) ;
5757 }
5858
59- private byte [ ] CreateContextHeader ( )
59+ public int GetDecryptedSize ( int cipherTextLength )
6060 {
61- var retVal = new byte [ checked (
62- 1 /* KDF alg */
63- + 1 /* chaining mode */
64- + sizeof ( uint ) /* sym alg key size */
65- + sizeof ( uint ) /* sym alg block size */
66- + sizeof ( uint ) /* hmac alg key size */
67- + sizeof ( uint ) /* hmac alg digest size */
68- + _symmetricAlgorithmBlockSizeInBytes /* ciphertext of encrypted empty string */
69- + _hmacAlgorithmDigestLengthInBytes /* digest of HMACed empty string */ ) ] ;
70-
71- fixed ( byte * pbRetVal = retVal )
72- {
73- byte * ptr = pbRetVal ;
74-
75- // First is the two-byte header
76- * ( ptr ++ ) = 0 ; // 0x00 = SP800-108 CTR KDF w/ HMACSHA512 PRF
77- * ( ptr ++ ) = 0 ; // 0x00 = CBC encryption + HMAC authentication
78-
79- // Next is information about the symmetric algorithm (key size followed by block size)
80- BitHelpers . WriteTo ( ref ptr , _symmetricAlgorithmSubkeyLengthInBytes ) ;
81- BitHelpers. WriteTo ( ref ptr , _symmetricAlgorithmBlockSizeInBytes ) ;
82-
83- // Next is information about the HMAC algorithm (key size followed by digest size)
84- BitHelpers . WriteTo ( ref ptr , _hmacAlgorithmSubkeyLengthInBytes ) ;
85- BitHelpers. WriteTo ( ref ptr , _hmacAlgorithmDigestLengthInBytes ) ;
86-
87- // See the design document for an explanation of the following code.
88- var tempKeys = new byte [ _symmetricAlgorithmSubkeyLengthInBytes + _hmacAlgorithmSubkeyLengthInBytes ] ;
89- fixed ( byte * pbTempKeys = tempKeys)
90- {
91- byte dummy ;
92-
93- // Derive temporary keys for encryption + HMAC.
94- using ( var provider = SP800_108_CTR_HMACSHA512Util . CreateEmptyProvider ( ) )
95- {
96- provider . DeriveKey (
97- pbLabel : & dummy ,
98- cbLabel : 0 ,
99- pbContext : & dummy ,
100- cbContext : 0 ,
101- pbDerivedKey : pbTempKeys ,
102- cbDerivedKey : ( uint ) tempKeys . Length ) ;
103- }
104-
105- // At this point, tempKeys := { K_E || K_H }.
106- byte* pbSymmetricEncryptionSubkey = pbTempKeys ;
107- byte * pbHmacSubkey = & pbTempKeys [ _symmetricAlgorithmSubkeyLengthInBytes ] ;
108-
109- // Encrypt a zero-length input string with an all-zero IV and copy the ciphertext to the return buffer.
110- using ( var symmetricKeyHandle = _symmetricAlgorithmHandle. GenerateSymmetricKey ( pbSymmetricEncryptionSubkey , _symmetricAlgorithmSubkeyLengthInBytes ) )
111- {
112- fixed ( byte * pbIV = new byte [ _symmetricAlgorithmBlockSizeInBytes ] /* will be zero-initialized */ )
113- {
114- DoCbcEncrypt(
115- symmetricKeyHandle : symmetricKeyHandle ,
116- pbIV : pbIV ,
117- pbInput : & dummy ,
118- cbInput : 0 ,
119- pbOutput : ptr ,
120- cbOutput : _symmetricAlgorithmBlockSizeInBytes ) ;
121- }
122- }
123- ptr += _symmetricAlgorithmBlockSizeInBytes;
124-
125- // MAC a zero-length input string and copy the digest to the return buffer.
126- using ( var hashHandle = _hmacAlgorithmHandle. CreateHmac ( pbHmacSubkey , _hmacAlgorithmSubkeyLengthInBytes ) )
127- {
128- hashHandle. HashData (
129- pbInput : & dummy ,
130- cbInput : 0 ,
131- pbHashDigest : ptr ,
132- cbHashDigest : _hmacAlgorithmDigestLengthInBytes ) ;
133- }
61+ throw new NotImplementedException ( ) ;
62+ }
13463
135- ptr += _hmacAlgorithmDigestLengthInBytes ;
136- CryptoUtil . Assert ( ptr - pbRetVal == retVal . Length , "ptr - pbRetVal == retVal.Length" ) ;
137- }
138- }
64+ public bool TryDecrypt ( ReadOnlySpan < byte > cipherText , ReadOnlySpan < byte > additionalAuthenticatedData , Span < byte > destination , out int bytesWritten )
65+ {
66+ throw new NotImplementedException ( ) ;
67+ }
13968
140- // retVal := { version || chainingMode || symAlgKeySize || symAlgBlockSize || hmacAlgKeySize || hmacAlgDigestSize || E("") || MAC("") }.
141- return retVal;
69+ public byte [ ] Decrypt ( ArraySegment < byte > ciphertext , ArraySegment < byte > additionalAuthenticatedData )
70+ {
71+ throw new NotImplementedException ( ) ;
14272 }
14373
14474 protected override byte [ ] DecryptImpl ( byte * pbCiphertext , uint cbCiphertext , byte * pbAdditionalAuthenticatedData , uint cbAdditionalAuthenticatedData )
@@ -202,14 +132,6 @@ protected override byte[] DecryptImpl(byte* pbCiphertext, uint cbCiphertext, byt
202132 }
203133 }
204134
205- public override void Dispose( )
206- {
207- _sp800_108_ctr_hmac_provider. Dispose( ) ;
208-
209- // We don't want to dispose of the underlying algorithm instances because they
210- // might be reused.
211- }
212-
213135 // 'pbIV' must be a pointer to a buffer equal in length to the symmetric algorithm block size.
214136 private byte [ ] DoCbcDecrypt ( BCryptKeyHandle symmetricKeyHandle , byte * pbIV , byte * pbInput , uint cbInput )
215137 {
@@ -299,13 +221,13 @@ private void DoCbcEncrypt(BCryptKeyHandle symmetricKeyHandle, byte* pbIV, byte*
299221 CryptoUtil . Assert ( dwEncryptedBytes == cbOutput , "dwEncryptedBytes == cbOutput" ) ;
300222 }
301223
302- public override int GetEncryptedSize( int plainTextLength)
224+ public int GetEncryptedSize ( int plainTextLength )
303225 {
304226 uint paddedCiphertextLength = GetCbcEncryptedOutputSizeWithPadding ( ( uint ) plainTextLength ) ;
305227 return checked ( ( int ) ( KEY_MODIFIER_SIZE_IN_BYTES + _symmetricAlgorithmBlockSizeInBytes + paddedCiphertextLength + _hmacAlgorithmDigestLengthInBytes ) ) ;
306228 }
307229
308- public override bool TryEncrypt( ReadOnlySpan < byte > plaintext , ReadOnlySpan < byte > additionalAuthenticatedData , Span < byte > destination , out int bytesWritten )
230+ public bool TryEncrypt ( ReadOnlySpan < byte > plaintext , ReadOnlySpan < byte > additionalAuthenticatedData , Span < byte > destination , out int bytesWritten )
309231 {
310232 bytesWritten = 0 ;
311233
@@ -404,7 +326,10 @@ public override bool TryEncrypt(ReadOnlySpan<byte> plaintext, ReadOnlySpan<byte>
404326 }
405327 }
406328
407- public override byte [ ] Encrypt( ArraySegment< byte > plaintext, ArraySegment < byte > additionalAuthenticatedData , uint preBufferSize , uint postBufferSize )
329+ public byte [ ] Encrypt ( ArraySegment < byte > plaintext , ArraySegment < byte > additionalAuthenticatedData )
330+ => Encrypt ( plaintext , additionalAuthenticatedData , 0 , 0 ) ;
331+
332+ public byte [ ] Encrypt ( ArraySegment < byte > plaintext , ArraySegment < byte > additionalAuthenticatedData , uint preBufferSize , uint postBufferSize )
408333 {
409334 plaintext . Validate ( ) ;
410335 additionalAuthenticatedData . Validate ( ) ;
@@ -490,4 +415,97 @@ private bool ValidateHash(BCryptHashHandle hashHandle, byte* pbInput, uint cbInp
490415 hashHandle . HashData ( pbInput , cbInput , pbActualDigest , _hmacAlgorithmDigestLengthInBytes ) ;
491416 return CryptoUtil . TimeConstantBuffersAreEqual ( pbExpectedDigest , pbActualDigest , _hmacAlgorithmDigestLengthInBytes ) ;
492417 }
418+
419+ private byte [ ] CreateContextHeader ( )
420+ {
421+ var retVal = new byte [ checked (
422+ 1 /* KDF alg */
423+ + 1 /* chaining mode */
424+ + sizeof ( uint ) /* sym alg key size */
425+ + sizeof ( uint ) /* sym alg block size */
426+ + sizeof ( uint ) /* hmac alg key size */
427+ + sizeof ( uint ) /* hmac alg digest size */
428+ + _symmetricAlgorithmBlockSizeInBytes /* ciphertext of encrypted empty string */
429+ + _hmacAlgorithmDigestLengthInBytes /* digest of HMACed empty string */ ) ] ;
430+
431+ fixed ( byte * pbRetVal = retVal )
432+ {
433+ byte * ptr = pbRetVal ;
434+
435+ // First is the two-byte header
436+ * ( ptr ++ ) = 0 ; // 0x00 = SP800-108 CTR KDF w/ HMACSHA512 PRF
437+ * ( ptr ++ ) = 0 ; // 0x00 = CBC encryption + HMAC authentication
438+
439+ // Next is information about the symmetric algorithm (key size followed by block size)
440+ BitHelpers . WriteTo ( ref ptr , _symmetricAlgorithmSubkeyLengthInBytes ) ;
441+ BitHelpers. WriteTo ( ref ptr , _symmetricAlgorithmBlockSizeInBytes ) ;
442+
443+ // Next is information about the HMAC algorithm (key size followed by digest size)
444+ BitHelpers . WriteTo ( ref ptr , _hmacAlgorithmSubkeyLengthInBytes ) ;
445+ BitHelpers. WriteTo ( ref ptr , _hmacAlgorithmDigestLengthInBytes ) ;
446+
447+ // See the design document for an explanation of the following code.
448+ var tempKeys = new byte [ _symmetricAlgorithmSubkeyLengthInBytes + _hmacAlgorithmSubkeyLengthInBytes ] ;
449+ fixed ( byte * pbTempKeys = tempKeys)
450+ {
451+ byte dummy ;
452+
453+ // Derive temporary keys for encryption + HMAC.
454+ using ( var provider = SP800_108_CTR_HMACSHA512Util . CreateEmptyProvider ( ) )
455+ {
456+ provider . DeriveKey (
457+ pbLabel : & dummy ,
458+ cbLabel : 0 ,
459+ pbContext : & dummy ,
460+ cbContext : 0 ,
461+ pbDerivedKey : pbTempKeys ,
462+ cbDerivedKey : ( uint ) tempKeys . Length ) ;
463+ }
464+
465+ // At this point, tempKeys := { K_E || K_H }.
466+ byte* pbSymmetricEncryptionSubkey = pbTempKeys ;
467+ byte * pbHmacSubkey = & pbTempKeys [ _symmetricAlgorithmSubkeyLengthInBytes ] ;
468+
469+ // Encrypt a zero-length input string with an all-zero IV and copy the ciphertext to the return buffer.
470+ using ( var symmetricKeyHandle = _symmetricAlgorithmHandle. GenerateSymmetricKey ( pbSymmetricEncryptionSubkey , _symmetricAlgorithmSubkeyLengthInBytes ) )
471+ {
472+ fixed ( byte * pbIV = new byte [ _symmetricAlgorithmBlockSizeInBytes ] /* will be zero-initialized */ )
473+ {
474+ DoCbcEncrypt(
475+ symmetricKeyHandle : symmetricKeyHandle ,
476+ pbIV : pbIV ,
477+ pbInput : & dummy ,
478+ cbInput : 0 ,
479+ pbOutput : ptr ,
480+ cbOutput : _symmetricAlgorithmBlockSizeInBytes ) ;
481+ }
482+ }
483+ ptr += _symmetricAlgorithmBlockSizeInBytes;
484+
485+ // MAC a zero-length input string and copy the digest to the return buffer.
486+ using ( var hashHandle = _hmacAlgorithmHandle. CreateHmac ( pbHmacSubkey , _hmacAlgorithmSubkeyLengthInBytes ) )
487+ {
488+ hashHandle. HashData (
489+ pbInput : & dummy ,
490+ cbInput : 0 ,
491+ pbHashDigest : ptr ,
492+ cbHashDigest : _hmacAlgorithmDigestLengthInBytes ) ;
493+ }
494+
495+ ptr += _hmacAlgorithmDigestLengthInBytes;
496+ CryptoUtil. Assert ( ptr - pbRetVal == retVal . Length , "ptr - pbRetVal == retVal.Length" ) ;
497+ }
498+ }
499+
500+ // retVal := { version || chainingMode || symAlgKeySize || symAlgBlockSize || hmacAlgKeySize || hmacAlgDigestSize || E("") || MAC("") }.
501+ return retVal;
502+ }
503+
504+ public void Dispose( )
505+ {
506+ _sp800_108_ctr_hmac_provider. Dispose ( ) ;
507+
508+ // We don't want to dispose of the underlying algorithm instances because they
509+ // might be reused.
510+ }
493511}
0 commit comments