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.

pull/232/head
David Garske 2022-07-21 15:55:08 -07:00
parent c32c111397
commit e9f35cc3ed
3 changed files with 227 additions and 34 deletions

View File

@ -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;

View File

@ -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);
}
}
}

View File

@ -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)