-
-
Notifications
You must be signed in to change notification settings - Fork 225
Add BCrypt types and test for CCM block chaining mode #74
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// Copyright (c) to owners found in https://github.com/AArnott/pinvoke/blob/master/COPYRIGHT.md. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. | ||
|
||
namespace PInvoke | ||
{ | ||
using System; | ||
|
||
/// <content> | ||
/// Contains the <see cref="AuthModeFlags"/> nested type. | ||
/// </content> | ||
public partial class BCrypt | ||
{ | ||
/// <summary> | ||
/// Flags for the <see cref="BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO.dwFlags"/> field. | ||
/// </summary> | ||
[Flags] | ||
public enum AuthModeFlags | ||
{ | ||
/// <summary> | ||
/// No flags. | ||
/// </summary> | ||
None = 0x0, | ||
|
||
/// <summary> | ||
/// Indicates that <see cref="BCryptEncrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> and <see cref="BCryptDecrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> function calls are being chained and that the MAC value will not be computed. On the last call in the chain, clear this value to compute the MAC value for the entire chain. | ||
/// </summary> | ||
BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG = 0x1, | ||
|
||
/// <summary> | ||
/// Indicates that this <see cref="BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO"/> structure is being used in a sequence of chained <see cref="BCryptEncrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> or <see cref="BCryptDecrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> function calls. This flag is set and maintained internally. | ||
/// Note: During the chaining sequence, this flag value is maintained internally and must not be changed or the value of the computed MAC will be corrupted. | ||
/// </summary> | ||
BCRYPT_AUTH_MODE_IN_PROGRESS_FLAG = 0x2, | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
// Copyright (c) to owners found in https://github.com/AArnott/pinvoke/blob/master/COPYRIGHT.md. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. | ||
|
||
namespace PInvoke | ||
{ | ||
using System; | ||
using System.Runtime.InteropServices; | ||
|
||
/// <content> | ||
/// Contains the <see cref="BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO"/> nested type. | ||
/// </content> | ||
public partial class BCrypt | ||
{ | ||
/// <summary> | ||
/// Used with the <see cref="BCryptEncrypt(SafeKeyHandle, byte[], IntPtr, byte[], BCryptEncryptFlags)"/> and <see cref="BCryptDecrypt(SafeKeyHandle, byte[], IntPtr, byte[], BCryptEncryptFlags)"/> functions | ||
/// to contain additional information related to authenticated cipher modes. | ||
/// </summary> | ||
[StructLayout(LayoutKind.Sequential)] | ||
public struct BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO | ||
{ | ||
/// <summary> | ||
/// The version of the <see cref="BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO"/> struct. | ||
/// </summary> | ||
public const uint BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO_VERSION = 1; | ||
|
||
/// <summary> | ||
/// The size, in bytes, of this structure. | ||
/// Do not set this field directly. Use the <see cref="Create"/> method instead. | ||
/// </summary> | ||
public uint cbSize; | ||
|
||
/// <summary> | ||
/// The version number of the structure. | ||
/// The only supported value is <see cref="BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO_VERSION"/>. | ||
/// Do not set this field directly. Use the <see cref="Create"/> method instead. | ||
/// </summary> | ||
public uint dwInfoVersion; | ||
|
||
/// <summary> | ||
/// A pointer to a buffer that contains a nonce. | ||
/// The Microsoft algorithm providers for Advanced Encryption Standard (AES) | ||
/// require a nonce for the Counter with CBC-MAC (CCM) and Galois/Counter Mode (GCM) | ||
/// chaining modes, and will return an error if none is present. | ||
/// If a nonce is not used, this member must be set to NULL. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know what we should do about documentation in cases like that, I replaced That's just a detail but might be interesting to unify on it at some point (Maybe a big XML doc cleanup before we reach 1.0). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ya, in all my xml doc comment fixups (adding see cref's etc.) I haven't bothered fixing references to NULL. Sometimes it will be IntPtr.Zero. Other times it will be null. While the doc would be cleaner, I figure unless there's an automated way to fix it up, it's probably not worth our time since readers should be able to figure out what it means. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think there is a good way to make it automated but it could be made assisted, also the point is moot if we decide to do pointer only or to codegen the IntPtr variants. |
||
/// </summary> | ||
public IntPtr pbNonce; | ||
|
||
/// <summary> | ||
/// The size, in bytes, of the buffer pointed to by the <see cref="pbNonce"/> member. | ||
/// If a nonce is not used, this member must be set to zero. | ||
/// </summary> | ||
public int cbNonce; | ||
|
||
/// <summary> | ||
/// A pointer to a buffer that contains the authenticated data. | ||
/// This is data that will be included in the Message Authentication Code (MAC) but not encrypted. | ||
/// If there is no authenticated data, this member must be set to NULL. | ||
/// </summary> | ||
public IntPtr pbAuthData; | ||
|
||
/// <summary> | ||
/// The size, in bytes, of the buffer pointed to by the <see cref="pbAuthData"/> member. | ||
/// If there is no authenticated data, this member must be set to zero. | ||
/// </summary> | ||
public int cbAuthData; | ||
|
||
/// <summary> | ||
/// A pointer to a buffer. | ||
/// The use of this member depends on the function to which the structure is passed. | ||
/// For <see cref="BCryptEncrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> | ||
/// the buffer will receive the authentication tag. | ||
/// For <see cref="BCryptDecrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> | ||
/// the buffer contains the authentication tag to be checked against. | ||
/// If there is no tag, this member must be set to NULL. | ||
/// </summary> | ||
public IntPtr pbTag; | ||
|
||
/// <summary> | ||
/// The size, in bytes, of the <see cref="pbTag"/> buffer. | ||
/// The buffer must be long enough to include the whole authentication tag. | ||
/// Some authentication modes, such as CCM and GCM, support checking against a tag | ||
/// with multiple lengths. To obtain the valid authentication tag lengths use | ||
/// <see cref="BCryptGetProperty{T}(SafeHandle, string, BCryptGetPropertyFlags)"/> to query the <see cref="PropertyNames.AuthTagLength"/> property. | ||
/// If there is no tag, this member must be set to zero. | ||
/// </summary> | ||
public int cbTag; | ||
|
||
/// <summary> | ||
/// A pointer to a buffer that stores the partially computed MAC between calls to <see cref="BCryptEncrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> and <see cref="BCryptDecrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> when chaining encryption or decryption. | ||
/// If the input to encryption or decryption is scattered across multiple buffers, then you must chain calls to the <see cref="BCryptEncrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> and <see cref="BCryptDecrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> functions. Chaining is indicated by setting the <see cref="AuthModeFlags.BCRYPT_AUTH_MODE_IN_PROGRESS_FLAG"/> flag in the <see cref="dwFlags"/> member. | ||
/// This buffer must be supplied by the caller and must be at least as large as the maximum length of an authentication tag for the cipher you are using. To get the valid authentication tag lengths, use <see cref="BCryptGetProperty{T}(SafeHandle, string, BCryptGetPropertyFlags)"/> to query the <see cref="PropertyNames.AuthTagLength"/> property. | ||
/// If <see cref="BCryptEncrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> and <see cref="BCryptDecrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> calls are not being chained, this member must be set to NULL. | ||
/// </summary> | ||
public IntPtr pbMacContext; | ||
|
||
/// <summary> | ||
/// The size, in bytes, of the buffer pointed to by the <see cref="pbMacContext"/> member. | ||
/// If <see cref="BCryptEncrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> and <see cref="BCryptDecrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> calls are not being chained, this member must be set to zero. | ||
/// </summary> | ||
public int cbMacContext; | ||
|
||
/// <summary> | ||
/// The length, in bytes, of additional authenticated data (AAD) to be used by the <see cref="BCryptEncrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> and <see cref="BCryptDecrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> functions. This member is used only when chaining calls. | ||
/// This member is used only when the <see cref="AuthModeFlags.BCRYPT_AUTH_MODE_IN_PROGRESS_FLAG"/> flag in the <see cref="dwFlags"/> member is set. | ||
/// On the first call to <see cref="BCryptEncrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> or <see cref="BCryptDecrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> you must set this field to zero. | ||
/// Note: During the chaining sequence, this member is maintained internally and must not be changed or the value of the computed MAC will be corrupted. | ||
/// </summary> | ||
public int cbAAD; | ||
|
||
/// <summary> | ||
/// The length, in bytes, of the payload data that was encrypted or decrypted. This member is used only when chaining calls. | ||
/// This member is used only when the <see cref="AuthModeFlags.BCRYPT_AUTH_MODE_IN_PROGRESS_FLAG"/> flag in the <see cref="dwFlags"/> member is set. | ||
/// On the first call to <see cref="BCryptEncrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> or <see cref="BCryptDecrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> you must set this field to zero. | ||
/// Note: During the chaining sequence, this member is maintained internally and must not be changed or the value of the computed MAC will be corrupted. | ||
/// </summary> | ||
public long cbData; | ||
|
||
/// <summary> | ||
/// This flag is used when chaining <see cref="BCryptEncrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> or <see cref="BCryptDecrypt(SafeKeyHandle, byte[], int, IntPtr, byte[], int, byte[], int, out int, BCryptEncryptFlags)"/> function calls. | ||
/// If calls are not being chained, this member must be set to zero. | ||
/// </summary> | ||
public AuthModeFlags dwFlags; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO"/> struct. | ||
/// </summary> | ||
/// <returns>An initialized instance.</returns> | ||
public static BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO Create() | ||
{ | ||
return new BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO | ||
{ | ||
cbSize = (uint)Marshal.SizeOf(typeof(BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO)), | ||
dwInfoVersion = BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO_VERSION, | ||
}; | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// Copyright (c) to owners found in https://github.com/AArnott/pinvoke/blob/master/COPYRIGHT.md. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. | ||
|
||
namespace PInvoke | ||
{ | ||
using System.Collections.Generic; | ||
using System.Runtime.InteropServices; | ||
|
||
/// <content> | ||
/// Contains the <see cref="BCRYPT_AUTH_TAG_LENGTHS_STRUCT"/> nested type. | ||
/// </content> | ||
public partial class BCrypt | ||
{ | ||
/// <summary> | ||
/// defines the range of tag sizes that are supported by the provider. This structure is used with the <see cref="PropertyNames.AuthTagLength"/> property. | ||
/// </summary> | ||
[StructLayout(LayoutKind.Sequential)] | ||
public struct BCRYPT_AUTH_TAG_LENGTHS_STRUCT | ||
{ | ||
/// <summary> | ||
/// The minimum length, in bytes, of a tag. | ||
/// </summary> | ||
public int MinLength; | ||
|
||
/// <summary> | ||
/// The maximum length, in bytes, of a tag. | ||
/// </summary> | ||
public int MaxLength; | ||
|
||
/// <summary> | ||
/// The number of bytes that the tag size can be incremented between dwMinLength and dwMaxLength. | ||
/// </summary> | ||
public int Increment; | ||
|
||
/// <summary> | ||
/// Gets a sequence of allowed tag sizes, from smallest to largest. | ||
/// </summary> | ||
public IEnumerable<int> TagSizes | ||
{ | ||
get | ||
{ | ||
for (int tagLength = this.MinLength; tagLength <= this.MaxLength; tagLength += this.Increment) | ||
{ | ||
yield return tagLength; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still feel bad to have
IntPtr
instead of pointers here, i'm still conflicted on the subject. Using pointers would block a few esoteric languages (PowerShell is the one with the biggest user base I can think of) but not using it is forcing all callers to copy paste the same conversion.On that subject I remarket that the current design for
System.Span
only exposes the pointer (UnsafePointer
) but not anIntPtr
version, maybe there's a trend starting (Or it's just because the lib development is still in flux and it will change).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. I'm really not liking the IntPtr either. I wonder if we had two P/Invoke overloads (one with IntPtr the other with T*) if Powershell would be able to pick the right overload with its limited typing system.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll open an issue to revisit changing IntPtr's to pointers in general, since for this PR I'm just conforming to what BCrypt and other libs AFAIK already have.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes let's discuss on the issue #76, we'll need to list the full pro/cons of each solution before starting moving code in any direction.