当C#中的GlobalPlatform接口函数接口函数时,类型无法被误误。
我一直在努力创建C#中GlobalPlatform库的接口,目前遇到此错误:
System.ArgumentException: Type could not be marshaled because the length of an embedded array instance does not match the declared length in the layout.
at System.StubHelpers.StubHelpers.FmtClassUpdateNativeInternal(Object obj, Byte* pNative, CleanupWorkList& pCleanupWorkList)
at LibGlobalPlatform.GlobalPlatform.GP211_mutual_authentication_wrapper(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, Byte[] baseKey, Byte[] S_ENC, Byte[] S_MAC, Byte[] DEK, Int32 keyLength, Byte keySetVersion, Byte keyIndex, Byte secureChannelProcotol, Byte secureChannelProtocolImpl, Byte securityLevel, Byte derivationMethod, GP211_SECURITY_INFO& secInfo, OPGP_ERROR_STATUS& cardStatus)
调用以下(C)函数时:
void GP211_mutual_authentication_wrapper(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo,
BYTE baseKey[32], BYTE S_ENC[32], BYTE S_MAC[32],
BYTE DEK[32], DWORD keyLength, BYTE keySetVersion,
BYTE keyIndex, BYTE secureChannelProtocol,
BYTE secureChannelProtocolImpl,
BYTE securityLevel, BYTE derivationMethod, GP211_SECURITY_INFO *secInfo,
OPGP_ERROR_STATUS *cardErrorStatus);
其函数签名如下:
[DllImport("globalPlatform.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void GP211_mutual_authentication_wrapper(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, byte[] baseKey, byte[] S_ENC,
byte[] S_MAC, byte[] DEK, int keyLength, byte keySetVersion, byte keyIndex, byte secureChannelProcotol,
byte secureChannelProtocolImpl, byte securityLevel, byte derivationMethod, ref GP211_SECURITY_INFO secInfo,
ref OPGP_ERROR_STATUS cardStatus);
我将其称为函数:
GlobalPlatform.OPGP_ERROR_STATUS cardStatus = new GlobalPlatform.OPGP_ERROR_STATUS();
GlobalPlatform.OPGP_CARD_CONTEXT cardContext = new GlobalPlatform.OPGP_CARD_CONTEXT();
GlobalPlatform.OPGP_CARD_INFO cardInfo = new GlobalPlatform.OPGP_CARD_INFO();
GlobalPlatform.GP211_SECURITY_INFO secInfo = new GlobalPlatform.GP211_SECURITY_INFO();
byte[] baseKey = new byte[32];
byte[] S_ENC = new byte[32];
byte[] S_MAC = new byte[32];
byte[] DEK = new byte[32];
GlobalPlatform.GP211_mutual_authentication_wrapper(cardContext, cardInfo, baseKey, S_ENC, S_MAC, DEK, keyLength, keySetVersion, keyIndex, scp, scpImpl, securityLevel, derivationMethod, ref secInfo, ref cardStatus);
所测试的结构参数为除gp211_security_info
struct未经测试外,在其他功能中工作。结构的源代码定义如下:
typedef struct {
BYTE securityLevel; //!< The security level.
BYTE secureChannelProtocol; //!< The Secure Channel Protocol.
BYTE secureChannelProtocolImpl; //!< The Secure Channel Protocol implementation.
BYTE C_MACSessionKey[32]; //!< The Secure Channel C-MAC session key.
BYTE R_MACSessionKey[32]; //!< The Secure Channel R-MAC session key.
BYTE encryptionSessionKey[32]; //!< The Secure Channel encryption session key.
BYTE dataEncryptionSessionKey[32]; //!< Secure Channel data encryption key.
/*
* Philip Wendland: lastC_MAC must be 16 Bytes for SCP03 because the MAC chaining value
* for MAC code generation is 16 Bytes (according to GP 2.2 Amendment D), not 8.
*/
BYTE lastC_MAC[16]; //!< The last computed C-MAC. Only 8 byte used for SCP01 and SCP02. Used as MAC Chaining Value for SCP03.
BYTE lastR_MAC[8]; //!< The last computed R-MAC.
/* Augusto: added two more attributes for key information */
BYTE keySetVersion; //!< The keyset version used in secure channel
BYTE keyIndex; //!< The key index used in secured channel
BYTE invokingAid[16]; //!< The invoking AID used for the mutual authentication.
DWORD invokingAidLength; //!< The length of the invoking AID buffer.
LONG sessionEncryptionCounter; //!< Session counter for SCP03 ICV encryption.
DWORD keyLength; //!< The key length. 16,24 or 32 bytes.
} GP211_SECURITY_INFO;
在C#I中,将结构编写为这样:
[StructLayout(LayoutKind.Sequential)]
public class GP211_SECURITY_INFO
{
public byte securityLevel;
public byte secureChannelProtocol;
public byte secureChanngelProtocolImpl;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public byte[] C_MACSessionKey;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public byte[] R_MACSessionKey;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public byte[] encryptionSessionKey;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public byte[] dataEncryptionSessionKey;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] lastC_MAC;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] lastR_MAC;
public byte keySetVersion;
public byte keyIndex;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] invokingAid;
public int invokingAidLength;
public long sessionEncryptionCounter; // long
public int keyLength;
}
解决错误的任何建议?还是我缺少任何东西?
更新: 我以下结构中的数组初始化了数组,并设法通过上述错误来传递:
GlobalPlatform.GP211_SECURITY_INFO secInfo = new GlobalPlatform.GP211_SECURITY_INFO();
secInfo.C_MACSessionKey = new byte[32];
secInfo.R_MACSessionKey = new byte[32];
secInfo.dataEncryptionSessionKey = new byte[32];
secInfo.lastC_MAC = new byte[16];
secInfo.lastR_MAC = new byte[8];
secInfo.invokingAid = new byte[16];
但是出现了其他问题:
- 当在C中打印结构的数组时,该值与已初始化的值不同。例如,当用零初始化时,它打印了一些随机值。
- 该函数
gp211_mutual_authentication_wrapper
似乎运行并在dll侧恢复正常,但是在c#side中,它引起了异常在consolegp.exe in Consolegp.exe上抛出0x76b1c3a2:microsoft c ++异常:未签名:位置0x010fdf70。
函数完成后错误。
I have been working to create an interface of globalplatform library in C#, and currently stuck with this error:
System.ArgumentException: Type could not be marshaled because the length of an embedded array instance does not match the declared length in the layout.
at System.StubHelpers.StubHelpers.FmtClassUpdateNativeInternal(Object obj, Byte* pNative, CleanupWorkList& pCleanupWorkList)
at LibGlobalPlatform.GlobalPlatform.GP211_mutual_authentication_wrapper(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, Byte[] baseKey, Byte[] S_ENC, Byte[] S_MAC, Byte[] DEK, Int32 keyLength, Byte keySetVersion, Byte keyIndex, Byte secureChannelProcotol, Byte secureChannelProtocolImpl, Byte securityLevel, Byte derivationMethod, GP211_SECURITY_INFO& secInfo, OPGP_ERROR_STATUS& cardStatus)
When calling the following (C) function:
void GP211_mutual_authentication_wrapper(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo,
BYTE baseKey[32], BYTE S_ENC[32], BYTE S_MAC[32],
BYTE DEK[32], DWORD keyLength, BYTE keySetVersion,
BYTE keyIndex, BYTE secureChannelProtocol,
BYTE secureChannelProtocolImpl,
BYTE securityLevel, BYTE derivationMethod, GP211_SECURITY_INFO *secInfo,
OPGP_ERROR_STATUS *cardErrorStatus);
Its function signature is the following:
[DllImport("globalPlatform.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void GP211_mutual_authentication_wrapper(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, byte[] baseKey, byte[] S_ENC,
byte[] S_MAC, byte[] DEK, int keyLength, byte keySetVersion, byte keyIndex, byte secureChannelProcotol,
byte secureChannelProtocolImpl, byte securityLevel, byte derivationMethod, ref GP211_SECURITY_INFO secInfo,
ref OPGP_ERROR_STATUS cardStatus);
I call the function like this:
GlobalPlatform.OPGP_ERROR_STATUS cardStatus = new GlobalPlatform.OPGP_ERROR_STATUS();
GlobalPlatform.OPGP_CARD_CONTEXT cardContext = new GlobalPlatform.OPGP_CARD_CONTEXT();
GlobalPlatform.OPGP_CARD_INFO cardInfo = new GlobalPlatform.OPGP_CARD_INFO();
GlobalPlatform.GP211_SECURITY_INFO secInfo = new GlobalPlatform.GP211_SECURITY_INFO();
byte[] baseKey = new byte[32];
byte[] S_ENC = new byte[32];
byte[] S_MAC = new byte[32];
byte[] DEK = new byte[32];
GlobalPlatform.GP211_mutual_authentication_wrapper(cardContext, cardInfo, baseKey, S_ENC, S_MAC, DEK, keyLength, keySetVersion, keyIndex, scp, scpImpl, securityLevel, derivationMethod, ref secInfo, ref cardStatus);
The struct paramaters tested to be working in other functions, except the GP211_SECURITY_INFO
struct is untested. The source code of the struct is defined as follow:
typedef struct {
BYTE securityLevel; //!< The security level.
BYTE secureChannelProtocol; //!< The Secure Channel Protocol.
BYTE secureChannelProtocolImpl; //!< The Secure Channel Protocol implementation.
BYTE C_MACSessionKey[32]; //!< The Secure Channel C-MAC session key.
BYTE R_MACSessionKey[32]; //!< The Secure Channel R-MAC session key.
BYTE encryptionSessionKey[32]; //!< The Secure Channel encryption session key.
BYTE dataEncryptionSessionKey[32]; //!< Secure Channel data encryption key.
/*
* Philip Wendland: lastC_MAC must be 16 Bytes for SCP03 because the MAC chaining value
* for MAC code generation is 16 Bytes (according to GP 2.2 Amendment D), not 8.
*/
BYTE lastC_MAC[16]; //!< The last computed C-MAC. Only 8 byte used for SCP01 and SCP02. Used as MAC Chaining Value for SCP03.
BYTE lastR_MAC[8]; //!< The last computed R-MAC.
/* Augusto: added two more attributes for key information */
BYTE keySetVersion; //!< The keyset version used in secure channel
BYTE keyIndex; //!< The key index used in secured channel
BYTE invokingAid[16]; //!< The invoking AID used for the mutual authentication.
DWORD invokingAidLength; //!< The length of the invoking AID buffer.
LONG sessionEncryptionCounter; //!< Session counter for SCP03 ICV encryption.
DWORD keyLength; //!< The key length. 16,24 or 32 bytes.
} GP211_SECURITY_INFO;
And in C# I marshalled the struct like this:
[StructLayout(LayoutKind.Sequential)]
public class GP211_SECURITY_INFO
{
public byte securityLevel;
public byte secureChannelProtocol;
public byte secureChanngelProtocolImpl;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public byte[] C_MACSessionKey;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public byte[] R_MACSessionKey;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public byte[] encryptionSessionKey;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public byte[] dataEncryptionSessionKey;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] lastC_MAC;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] lastR_MAC;
public byte keySetVersion;
public byte keyIndex;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] invokingAid;
public int invokingAidLength;
public long sessionEncryptionCounter; // long
public int keyLength;
}
Any suggestion to fix the error? Or is there any things that I missing on?
Update:
I initialized the array in the struct as follow and managed to get pass the error above:
GlobalPlatform.GP211_SECURITY_INFO secInfo = new GlobalPlatform.GP211_SECURITY_INFO();
secInfo.C_MACSessionKey = new byte[32];
secInfo.R_MACSessionKey = new byte[32];
secInfo.dataEncryptionSessionKey = new byte[32];
secInfo.lastC_MAC = new byte[16];
secInfo.lastR_MAC = new byte[8];
secInfo.invokingAid = new byte[16];
But other problems appeared:
- When printing the array of the struct in the C, the value is different with the value it has been initialized with. For example when initialized with zeros, it printed some random value.
- The function
GP211_mutual_authentication_wrapper
seems to be ran and exited just fine in the dll side, but in the C# side it causedException thrown at 0x76B1C3A2 in ConsoleGP.exe: Microsoft C++ exception: unsigned long at memory location 0x010FDF70.
error when the function finished.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论