mirror of https://github.com/wolfSSL/wolfTPM.git
Added CSharp wrapper support for RSA encrypt/decrypt and Sign/Verify. Fixed issue with sign signature buffer size checking. Changed wrapper algorithm arguments to use enum TPM2_Alg.
parent
c32c111397
commit
e9f35cc3ed
|
|
@ -2496,6 +2496,7 @@ int wolfTPM2_SignHashScheme(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
|
|||
Sign_In signIn;
|
||||
Sign_Out signOut;
|
||||
int curveSize = 0;
|
||||
int sigOutSz = 0;
|
||||
|
||||
if (dev == NULL || key == NULL || digest == NULL || sig == NULL ||
|
||||
sigSz == NULL) {
|
||||
|
|
@ -2506,12 +2507,7 @@ int wolfTPM2_SignHashScheme(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
|
|||
/* get curve size */
|
||||
curveSize = wolfTPM2_GetCurveSize(
|
||||
key->pub.publicArea.parameters.eccDetail.curveID);
|
||||
if (curveSize <= 0 || *sigSz < (curveSize * 2)) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
}
|
||||
else if (key->pub.publicArea.type == TPM_ALG_RSA) {
|
||||
if (*sigSz < (int)sizeof(signOut.signature.signature.rsassa.sig.buffer)) {
|
||||
if (curveSize <= 0) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
}
|
||||
|
|
@ -2539,20 +2535,35 @@ int wolfTPM2_SignHashScheme(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
|
|||
|
||||
if (key->pub.publicArea.type == TPM_ALG_ECC) {
|
||||
/* Assemble R and S into signature (R then S) */
|
||||
*sigSz = signOut.signature.signature.ecdsa.signatureR.size +
|
||||
signOut.signature.signature.ecdsa.signatureS.size;
|
||||
XMEMCPY(sig, signOut.signature.signature.ecdsa.signatureR.buffer,
|
||||
signOut.signature.signature.ecdsa.signatureR.size);
|
||||
XMEMCPY(sig + signOut.signature.signature.ecdsa.signatureR.size,
|
||||
signOut.signature.signature.ecdsa.signatureS.buffer,
|
||||
signOut.signature.signature.ecdsa.signatureS.size);
|
||||
sigOutSz = signOut.signature.signature.ecdsa.signatureR.size +
|
||||
signOut.signature.signature.ecdsa.signatureS.size;
|
||||
if (sigOutSz > *sigSz) {
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
printf("TPM2_Sign: ECC result truncated %d -> %d\n",
|
||||
sigOutSz, *sigSz);
|
||||
#endif
|
||||
sigOutSz = *sigSz;
|
||||
}
|
||||
XMEMCPY(sig,
|
||||
signOut.signature.signature.ecdsa.signatureR.buffer,
|
||||
sigOutSz/2);
|
||||
XMEMCPY(sig + sigOutSz/2,
|
||||
signOut.signature.signature.ecdsa.signatureS.buffer,
|
||||
sigOutSz/2);
|
||||
}
|
||||
else if (key->pub.publicArea.type == TPM_ALG_RSA) {
|
||||
/* RSA signature size and buffer (with padding depending on scheme) */
|
||||
*sigSz = signOut.signature.signature.rsassa.sig.size;
|
||||
XMEMCPY(sig, signOut.signature.signature.rsassa.sig.buffer,
|
||||
signOut.signature.signature.rsassa.sig.size);
|
||||
sigOutSz = signOut.signature.signature.rsassa.sig.size;
|
||||
if (sigOutSz > *sigSz) {
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
printf("TPM2_Sign: RSA result truncated %d -> %d\n",
|
||||
sigOutSz, *sigSz);
|
||||
#endif
|
||||
sigOutSz = *sigSz;
|
||||
}
|
||||
XMEMCPY(sig, signOut.signature.signature.rsassa.sig.buffer, sigOutSz);
|
||||
}
|
||||
*sigSz = sigOutSz;
|
||||
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
printf("TPM2_Sign: %s %d\n",
|
||||
|
|
@ -2604,7 +2615,7 @@ int wolfTPM2_VerifyHashScheme(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
|
|||
if (curveSize <= 0 || sigSz < (curveSize * 2)) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
/* verify curvesize cannot exceed buffer */
|
||||
/* verify curve size cannot exceed buffer */
|
||||
if (curveSize > (int)sizeof(verifySigIn.signature.signature.ecdsa.signatureR.buffer))
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
|
|
|
|||
|
|
@ -108,8 +108,8 @@ namespace tpm_csharp_test
|
|||
private void GetSRK(Key srkKey, string auth)
|
||||
{
|
||||
int rc = device.CreateSRK(srkKey,
|
||||
(int)TPM2_Alg.RSA,
|
||||
auth);
|
||||
TPM2_Alg.RSA,
|
||||
auth);
|
||||
Assert.AreEqual((int)Status.TPM_RC_SUCCESS, rc);
|
||||
}
|
||||
|
||||
|
|
@ -142,7 +142,7 @@ namespace tpm_csharp_test
|
|||
}
|
||||
|
||||
rc = device.CreateKey(blob, parent_key, template,
|
||||
"ThisIsMyStorageKeyAuth");
|
||||
"ThisIsMyKeyAuth");
|
||||
Assert.AreEqual((int)Status.TPM_RC_SUCCESS, rc);
|
||||
|
||||
rc = device.LoadKey(blob, parent_key);
|
||||
|
|
@ -338,7 +338,8 @@ namespace tpm_csharp_test
|
|||
rc = device.ImportRsaPrivateKey(parent_key, blob,
|
||||
pub_buffer,
|
||||
exp, priv_buffer,
|
||||
(uint)TPM2_Alg.NULL, (uint)TPM2_Alg.NULL);
|
||||
TPM2_Alg.NULL,
|
||||
TPM2_Alg.NULL);
|
||||
Assert.AreEqual((int)Status.TPM_RC_SUCCESS, rc);
|
||||
|
||||
rc = device.UnloadHandle(blob);
|
||||
|
|
@ -425,7 +426,7 @@ namespace tpm_csharp_test
|
|||
Assert.AreEqual((int)Status.TPM_RC_SUCCESS, rc);
|
||||
|
||||
rc = device.CreateKey(keyBlob, parent_key, template,
|
||||
"ThisIsMyStorageKeyAuth");
|
||||
"ThisIsMyKeyAuth");
|
||||
Assert.AreEqual((int)Status.TPM_RC_SUCCESS, rc);
|
||||
|
||||
rc = device.LoadKey(keyBlob, parent_key);
|
||||
|
|
@ -466,7 +467,7 @@ namespace tpm_csharp_test
|
|||
Assert.AreEqual((int)Status.TPM_RC_SUCCESS, rc);
|
||||
|
||||
rc = device.CreateKey(keyBlob, parent_key, template,
|
||||
"ThisIsMyStorageKeyAuth");
|
||||
"ThisIsMyKeyAuth");
|
||||
Assert.AreEqual((int)Status.TPM_RC_SUCCESS, rc);
|
||||
|
||||
rc = device.LoadKey(keyBlob, parent_key);
|
||||
|
|
@ -511,7 +512,7 @@ namespace tpm_csharp_test
|
|||
Assert.AreEqual((int)Status.TPM_RC_SUCCESS, rc);
|
||||
|
||||
rc = device.CreateKey(keyBlob, parent_key, template,
|
||||
"ThisIsMyStorageKeyAuth");
|
||||
"ThisIsMyKeyAuth");
|
||||
Assert.AreEqual((int)Status.TPM_RC_SUCCESS, rc);
|
||||
|
||||
rc = device.LoadKey(keyBlob, parent_key);
|
||||
|
|
@ -561,7 +562,7 @@ namespace tpm_csharp_test
|
|||
|
||||
/* Generate new key */
|
||||
rc = device.CreateKey(keyBlob, parent_key, template,
|
||||
"ThisIsMyStorageKeyAuth");
|
||||
"ThisIsMyKeyAuth");
|
||||
Assert.AreEqual((int)Status.TPM_RC_SUCCESS, rc);
|
||||
|
||||
/* Load key */
|
||||
|
|
@ -596,5 +597,98 @@ namespace tpm_csharp_test
|
|||
Assert.AreEqual((int)Status.TPM_RC_SUCCESS, rc);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryRsaEncryptDecrypt()
|
||||
{
|
||||
int rc;
|
||||
KeyBlob keyBlob = new KeyBlob();
|
||||
Template template = new Template();
|
||||
const int RsaKeySz = 256;
|
||||
byte[] message = new byte[RsaKeySz];
|
||||
byte[] cipher = new byte[RsaKeySz];
|
||||
byte[] plain = new byte[RsaKeySz];
|
||||
|
||||
Console.WriteLine("Testing RSA Encrypt/Decrypt");
|
||||
|
||||
rc = template.GetKeyTemplate_RSA((ulong)(
|
||||
TPM2_Object.sensitiveDataOrigin |
|
||||
TPM2_Object.userWithAuth |
|
||||
TPM2_Object.decrypt |
|
||||
TPM2_Object.sign |
|
||||
TPM2_Object.noDA));
|
||||
Assert.AreEqual((int)Status.TPM_RC_SUCCESS, rc);
|
||||
|
||||
rc = device.CreateKey(keyBlob, parent_key, template,
|
||||
"ThisIsMyKeyAuth");
|
||||
Assert.AreEqual((int)Status.TPM_RC_SUCCESS, rc);
|
||||
|
||||
rc = device.LoadKey(keyBlob, parent_key);
|
||||
Assert.AreEqual((int)Status.TPM_RC_SUCCESS, rc);
|
||||
|
||||
/* Perform RSA encrypt / decrypt (no pad) */
|
||||
for (int i=0; i<message.Length; i++) {
|
||||
message[i] = 0x11;
|
||||
}
|
||||
rc = device.RsaEncrypt(keyBlob, message, cipher, TPM2_Alg.NULL);
|
||||
Assert.AreEqual(RsaKeySz, rc);
|
||||
|
||||
rc = device.RsaDecrypt(keyBlob, cipher, plain, TPM2_Alg.NULL);
|
||||
Assert.AreEqual(RsaKeySz, rc);
|
||||
|
||||
/* Validate encrypt / decrypt */
|
||||
for (int i=0; i<RsaKeySz; i++) {
|
||||
if (message[i] != plain[i]) {
|
||||
Assert.True(false);
|
||||
}
|
||||
}
|
||||
|
||||
rc = device.UnloadHandle(keyBlob);
|
||||
Assert.AreEqual((int)Status.TPM_RC_SUCCESS, rc);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TrySignVerify()
|
||||
{
|
||||
int rc;
|
||||
KeyBlob keyBlob = new KeyBlob();
|
||||
Template template = new Template();
|
||||
const int RsaKeySz = 256;
|
||||
const int HashDigestSz = 32;
|
||||
byte[] sig = new byte[RsaKeySz];
|
||||
byte[] digest = new byte[HashDigestSz];
|
||||
|
||||
Console.WriteLine("Testing RSA Sign/Verify");
|
||||
|
||||
rc = template.GetKeyTemplate_RSA((ulong)(
|
||||
TPM2_Object.sensitiveDataOrigin |
|
||||
TPM2_Object.userWithAuth |
|
||||
TPM2_Object.decrypt |
|
||||
TPM2_Object.sign |
|
||||
TPM2_Object.noDA));
|
||||
Assert.AreEqual((int)Status.TPM_RC_SUCCESS, rc);
|
||||
|
||||
rc = device.CreateKey(keyBlob, parent_key, template,
|
||||
"ThisIsMyKeyAuth");
|
||||
Assert.AreEqual((int)Status.TPM_RC_SUCCESS, rc);
|
||||
|
||||
rc = device.LoadKey(keyBlob, parent_key);
|
||||
Assert.AreEqual((int)Status.TPM_RC_SUCCESS, rc);
|
||||
|
||||
/* Perform RSA sign / verify - PKCSv1.5 (SSA) padding */
|
||||
for (int i=0; i<digest.Length; i++) {
|
||||
digest[i] = 0x11;
|
||||
}
|
||||
rc = device.SignHashScheme(keyBlob, digest, sig,
|
||||
TPM2_Alg.RSASSA, TPM2_Alg.SHA256);
|
||||
Assert.AreEqual(RsaKeySz, rc);
|
||||
|
||||
rc = device.VerifyHashScheme(keyBlob, sig, digest,
|
||||
TPM2_Alg.RSASSA, TPM2_Alg.SHA256);
|
||||
Assert.AreEqual((int)Status.TPM_RC_SUCCESS, rc);
|
||||
|
||||
rc = device.UnloadHandle(keyBlob);
|
||||
Assert.AreEqual((int)Status.TPM_RC_SUCCESS, rc);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,15 +62,18 @@ namespace wolfTPM
|
|||
}
|
||||
}
|
||||
|
||||
/* from TPM_RC_T and wolfCrypt error-crypt.h */
|
||||
public enum Status : int
|
||||
{
|
||||
TPM_RC_SUCCESS = 0,
|
||||
TPM_RC_HANDLE = 0x8B,
|
||||
TPM_RC_NV_UNAVAILABLE = 0x923,
|
||||
TPM_RC_SIGNATURE = 0x9B,
|
||||
BAD_FUNC_ARG = -173,
|
||||
NOT_COMPILED_IN = -174,
|
||||
}
|
||||
|
||||
/* from TPMA_OBJECT_mask */
|
||||
public enum TPM2_Object : ulong
|
||||
{
|
||||
fixedTPM = 0x00000002,
|
||||
|
|
@ -87,6 +90,7 @@ namespace wolfTPM
|
|||
sign = 0x00040000,
|
||||
}
|
||||
|
||||
/* from TPM_ALG_ID */
|
||||
public enum TPM2_Alg : uint
|
||||
{
|
||||
ERROR = 0x0000,
|
||||
|
|
@ -127,6 +131,7 @@ namespace wolfTPM
|
|||
ECB = 0x0044,
|
||||
}
|
||||
|
||||
/* from TPM_ECC_CURVE_T */
|
||||
public enum TPM2_ECC : uint
|
||||
{
|
||||
NONE = 0x0000,
|
||||
|
|
@ -140,6 +145,7 @@ namespace wolfTPM
|
|||
SM2_P256 = 0x0020,
|
||||
}
|
||||
|
||||
/* from TPM_SE_T */
|
||||
public enum SE : byte
|
||||
{
|
||||
HMAC = 0x00,
|
||||
|
|
@ -147,6 +153,7 @@ namespace wolfTPM
|
|||
TRIAL = 0x03,
|
||||
}
|
||||
|
||||
/* from TPMA_SESSION_mask */
|
||||
public enum SESSION_mask : byte
|
||||
{
|
||||
continueSession = 0x01,
|
||||
|
|
@ -157,6 +164,7 @@ namespace wolfTPM
|
|||
audit = 0x80,
|
||||
}
|
||||
|
||||
/* from TPM_RH_T */
|
||||
public enum TPM_RH : ulong
|
||||
{
|
||||
FIRST = 0x40000000,
|
||||
|
|
@ -179,6 +187,7 @@ namespace wolfTPM
|
|||
LAST = AUTH_FF,
|
||||
}
|
||||
|
||||
/* from wolfSSL WOLFSSL_FILETYPE_ASN1 and WOLFSSL_FILETYPE_PEM */
|
||||
public enum X509_Format : int
|
||||
{
|
||||
PEM = 1,
|
||||
|
|
@ -808,16 +817,16 @@ namespace wolfTPM
|
|||
[DllImport(DLLNAME, EntryPoint = "wolfTPM2_CreateSRK")]
|
||||
private static extern int wolfTPM2_CreateSRK(IntPtr dev,
|
||||
IntPtr srkKey,
|
||||
int alg,
|
||||
uint alg,
|
||||
string auth,
|
||||
int authSz);
|
||||
public int CreateSRK(Key srkKey,
|
||||
int alg,
|
||||
TPM2_Alg alg,
|
||||
string auth)
|
||||
{
|
||||
int rc = wolfTPM2_CreateSRK(device,
|
||||
srkKey.key,
|
||||
alg,
|
||||
(uint)alg,
|
||||
auth,
|
||||
auth.Length);
|
||||
if (rc != (int)Status.TPM_RC_SUCCESS) {
|
||||
|
|
@ -898,7 +907,7 @@ namespace wolfTPM
|
|||
public int ReadPublicKey(Key key, ulong handle)
|
||||
{
|
||||
int rc = wolfTPM2_ReadPublicKey(device, key.key, handle);
|
||||
if (rc != (int)Status.TPM_RC_SUCCESS &&
|
||||
if (rc != (int)Status.TPM_RC_SUCCESS &&
|
||||
rc != (int)Status.TPM_RC_HANDLE)
|
||||
{
|
||||
throw new WolfTpm2Exception(
|
||||
|
|
@ -909,7 +918,7 @@ namespace wolfTPM
|
|||
public int ReadPublicKey(KeyBlob keyBlob, ulong handle)
|
||||
{
|
||||
int rc = wolfTPM2_ReadPublicKey(device, keyBlob.keyblob, handle);
|
||||
if (rc != (int)Status.TPM_RC_SUCCESS &&
|
||||
if (rc != (int)Status.TPM_RC_SUCCESS &&
|
||||
rc != (int)Status.TPM_RC_HANDLE)
|
||||
{
|
||||
throw new WolfTpm2Exception(
|
||||
|
|
@ -1029,8 +1038,8 @@ namespace wolfTPM
|
|||
byte[] rsaPub,
|
||||
int exponent,
|
||||
byte[] rsaPriv,
|
||||
uint scheme,
|
||||
uint hashAlg)
|
||||
TPM2_Alg scheme,
|
||||
TPM2_Alg hashAlg)
|
||||
{
|
||||
int rc = wolfTPM2_ImportRsaPrivateKey(device,
|
||||
parentKey.key,
|
||||
|
|
@ -1040,8 +1049,8 @@ namespace wolfTPM
|
|||
exponent,
|
||||
rsaPriv,
|
||||
rsaPriv.Length,
|
||||
scheme,
|
||||
hashAlg);
|
||||
(uint)scheme,
|
||||
(uint)hashAlg);
|
||||
if (rc != (int)Status.TPM_RC_SUCCESS) {
|
||||
throw new WolfTpm2Exception(
|
||||
"wolfTPM2_ImportRsaPrivateKey", rc);
|
||||
|
|
@ -1203,6 +1212,85 @@ namespace wolfTPM
|
|||
return rc;
|
||||
}
|
||||
|
||||
[DllImport(DLLNAME, EntryPoint = "wolfTPM2_RsaEncrypt")]
|
||||
private static extern int wolfTPM2_RsaEncrypt(
|
||||
IntPtr dev, IntPtr key, uint padScheme, byte[] plain, int plainSz,
|
||||
byte[] enc, ref int encSz);
|
||||
public int RsaEncrypt(KeyBlob keyBlob, byte[] plain, byte[] enc,
|
||||
TPM2_Alg padScheme)
|
||||
{
|
||||
int encSz = enc.Length;
|
||||
int rc = wolfTPM2_RsaEncrypt(device, keyBlob.keyblob, (uint)padScheme,
|
||||
plain, plain.Length, enc, ref encSz);
|
||||
if (rc == 0) {
|
||||
rc = encSz;
|
||||
}
|
||||
else {
|
||||
throw new WolfTpm2Exception(
|
||||
"wolfTPM2_RsaEncrypt", rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
[DllImport(DLLNAME, EntryPoint = "wolfTPM2_RsaDecrypt")]
|
||||
private static extern int wolfTPM2_RsaDecrypt(
|
||||
IntPtr dev, IntPtr key, uint padScheme, byte[] enc, int encSz,
|
||||
byte[] plain, ref int plainSz);
|
||||
public int RsaDecrypt(KeyBlob keyBlob, byte[] enc, byte[] plain,
|
||||
TPM2_Alg padScheme)
|
||||
{
|
||||
int plainSz = enc.Length;
|
||||
int rc = wolfTPM2_RsaDecrypt(device, keyBlob.keyblob, (uint)padScheme,
|
||||
enc, enc.Length, plain, ref plainSz);
|
||||
if (rc == 0) {
|
||||
rc = plainSz;
|
||||
}
|
||||
else {
|
||||
throw new WolfTpm2Exception(
|
||||
"wolfTPM2_RsaDecrypt", rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
[DllImport(DLLNAME, EntryPoint = "wolfTPM2_SignHashScheme")]
|
||||
private static extern int wolfTPM2_SignHashScheme(
|
||||
IntPtr dev, IntPtr key, byte[] digest, int digestSz,
|
||||
byte[] sig, ref int sigSz, uint sigAlg, uint hashAlg);
|
||||
public int SignHashScheme(KeyBlob keyBlob, byte[] digest, byte[] sig,
|
||||
TPM2_Alg sigAlg, TPM2_Alg hashAlg)
|
||||
{
|
||||
int sigSz = sig.Length;
|
||||
int rc = wolfTPM2_SignHashScheme(device, keyBlob.keyblob,
|
||||
digest, digest.Length, sig, ref sigSz,
|
||||
(uint)sigAlg, (uint)hashAlg);
|
||||
if (rc == 0) {
|
||||
rc = sigSz;
|
||||
}
|
||||
else {
|
||||
throw new WolfTpm2Exception(
|
||||
"wolfTPM2_SignHashScheme", rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
[DllImport(DLLNAME, EntryPoint = "wolfTPM2_VerifyHashScheme")]
|
||||
private static extern int wolfTPM2_VerifyHashScheme(
|
||||
IntPtr dev, IntPtr key, byte[] sig, int sigSz,
|
||||
byte[] digest, int digestSz, uint sigAlg, uint hashAlg);
|
||||
public int VerifyHashScheme(KeyBlob keyBlob, byte[] sig, byte[] digest,
|
||||
TPM2_Alg sigAlg, TPM2_Alg hashAlg)
|
||||
{
|
||||
int rc = wolfTPM2_VerifyHashScheme(device, keyBlob.keyblob,
|
||||
sig, sig.Length, digest, digest.Length,
|
||||
(uint)sigAlg, (uint)hashAlg);
|
||||
if (rc != 0 && rc != (int)Status.TPM_RC_SIGNATURE) {
|
||||
throw new WolfTpm2Exception(
|
||||
"wolfTPM2_VerifyHashScheme", rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
[DllImport(DLLNAME, EntryPoint = "wolfTPM2_UnloadHandle")]
|
||||
private static extern int wolfTPM2_UnloadHandle(IntPtr dev, IntPtr handle);
|
||||
public int UnloadHandle(Key key)
|
||||
|
|
|
|||
Loading…
Reference in New Issue