Skip to content

Commit

Permalink
feat: TPM2_RSA_Encrypt and TPM2_RSA_Decrypt (#356)
Browse files Browse the repository at this point in the history
  • Loading branch information
dflamand committed Apr 11, 2024
1 parent 48897af commit cfdeb6e
Show file tree
Hide file tree
Showing 3 changed files with 213 additions and 0 deletions.
14 changes: 14 additions & 0 deletions tpm2/structures.go
Original file line number Diff line number Diff line change
Expand Up @@ -2299,6 +2299,20 @@ type TPMTRSAScheme struct {
Details TPMUAsymScheme `gotpm:"tag=Scheme"`
}

// TPMIAlgRSADecrypt represents a TPMI_ALG_RSA_DECRYPT.
// See definition in Part 2: Structures, section 11.2.4.3.
type TPMIAlgRSADecrypt = TPMAlgID

// TPMTRSADecrypt represents a TPMT_RSA_DECRYPT.
// See definition in Part 2: Structures, section 11.2.4.4.
type TPMTRSADecrypt struct {
marshalByReflection
// scheme selector
Scheme TPMIAlgRSADecrypt `gotpm:"nullable"`
// scheme parameters
Details TPMUAsymScheme `gotpm:"tag=Scheme"`
}

// TPM2BPublicKeyRSA represents a TPM2B_PUBLIC_KEY_RSA.
// See definition in Part 2: Structures, section 11.2.4.5.
type TPM2BPublicKeyRSA TPM2BData
Expand Down
137 changes: 137 additions & 0 deletions tpm2/test/rsa_encryption_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package tpm2test

import (
"bytes"
"testing"

. "github.com/google/go-tpm/tpm2"
"github.com/google/go-tpm/tpm2/transport/simulator"
)

func TestRSAEncryption(t *testing.T) {
theTpm, err := simulator.OpenSimulator()
if err != nil {
t.Fatalf("could not connect to TPM simulator: %v", err)
}
t.Cleanup(func() {
if err := theTpm.Close(); err != nil {
t.Errorf("%v", err)
}
})

createPrimaryCmd := CreatePrimary{
PrimaryHandle: TPMRHOwner,
InPublic: New2B(RSASRKTemplate),
}
createPrimaryRsp, err := createPrimaryCmd.Execute(theTpm)
if err != nil {
t.Fatalf("%v", err)
}
t.Cleanup(func() {
flushContextCmd := FlushContext{FlushHandle: createPrimaryRsp.ObjectHandle}
if _, err := flushContextCmd.Execute(theTpm); err != nil {
t.Errorf("%v", err)
}
})

createCmd := Create{
ParentHandle: NamedHandle{
Handle: createPrimaryRsp.ObjectHandle,
Name: createPrimaryRsp.Name,
},
InPublic: New2B(TPMTPublic{
Type: TPMAlgRSA,
NameAlg: TPMAlgSHA256,
ObjectAttributes: TPMAObject{
FixedTPM: true,
STClear: false,
FixedParent: true,
SensitiveDataOrigin: true,
UserWithAuth: true,
AdminWithPolicy: false,
NoDA: true,
EncryptedDuplication: false,
Restricted: false,
Decrypt: true,
SignEncrypt: true,
},
Parameters: NewTPMUPublicParms(
TPMAlgRSA,
&TPMSRSAParms{
KeyBits: 2048,
},
),
Unique: NewTPMUPublicID(
TPMAlgRSA,
&TPM2BPublicKeyRSA{
Buffer: make([]byte, 256),
},
),
}),
}
createRsp, err := createCmd.Execute(theTpm)
if err != nil {
t.Fatalf("%v", err)
}

loadCmd := Load{
ParentHandle: NamedHandle{
Handle: createPrimaryRsp.ObjectHandle,
Name: createPrimaryRsp.Name,
},
InPrivate: createRsp.OutPrivate,
InPublic: createRsp.OutPublic,
}
loadRsp, err := loadCmd.Execute(theTpm)
if err != nil {
t.Fatalf("%v", err)
}
t.Cleanup(func() {
flushContextCmd := FlushContext{FlushHandle: loadRsp.ObjectHandle}
if _, err := flushContextCmd.Execute(theTpm); err != nil {
t.Errorf("%v", err)
}
})

message := []byte("secret")

encryptCmd := RSAEncrypt{
KeyHandle: loadRsp.ObjectHandle,
Message: TPM2BPublicKeyRSA{Buffer: message},
InScheme: TPMTRSADecrypt{
Scheme: TPMAlgOAEP,
Details: NewTPMUAsymScheme(
TPMAlgOAEP,
&TPMSEncSchemeOAEP{
HashAlg: TPMAlgSHA256,
},
),
},
}
encryptRsp, err := encryptCmd.Execute(theTpm)
if err != nil {
t.Fatalf("%v", err)
}

decryptCmd := RSADecrypt{
KeyHandle: loadRsp.ObjectHandle,
CipherText: TPM2BPublicKeyRSA{Buffer: encryptRsp.OutData.Buffer},
InScheme: TPMTRSADecrypt{
Scheme: TPMAlgOAEP,
Details: NewTPMUAsymScheme(
TPMAlgOAEP,
&TPMSEncSchemeOAEP{
HashAlg: TPMAlgSHA256,
},
),
},
}
decryptRsp, err := decryptCmd.Execute(theTpm)
if err != nil {
t.Fatalf("%v", err)
}

if !bytes.Equal(message, decryptRsp.Message.Buffer) {
t.Errorf("want %x got %x", message, decryptRsp.Message.Buffer)
}
}
62 changes: 62 additions & 0 deletions tpm2/tpm2.go
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,68 @@ type CreateLoadedResponse struct {
Name TPM2BName
}

// RSAEncrypt is the input to TPM2_RSA_Encrypt
// See definition in Part 3, Commands, section 14.2.
type RSAEncrypt struct {
// reference to public portion of RSA key to use for encryption
KeyHandle handle `gotpm:"handle"`
// message to be encrypted
Message TPM2BPublicKeyRSA
// the padding scheme to use if scheme associated with keyHandle is TPM_ALG_NULL
InScheme TPMTRSADecrypt `gotpm:"nullable"`
// optional label L to be associated with the message
Label TPM2BData `gotpm:"optional"`
}

// Command implements the Command interface.
func (RSAEncrypt) Command() TPMCC { return TPMCCRSAEncrypt }

// Execute executes the command and returns the response.
func (cmd RSAEncrypt) Execute(t transport.TPM, s ...Session) (*RSAEncryptResponse, error) {
var rsp RSAEncryptResponse
if err := execute[RSAEncryptResponse](t, cmd, &rsp, s...); err != nil {
return nil, err
}
return &rsp, nil
}

// RSAEncryptResponse is the response from TPM2_RSA_Encrypt
type RSAEncryptResponse struct {
// encrypted output
OutData TPM2BPublicKeyRSA
}

// RSADecrypt is the input to TPM2_RSA_Decrypt
// See definition in Part 3, Commands, section 14.3.
type RSADecrypt struct {
// RSA key to use for decryption
KeyHandle handle `gotpm:"handle,auth"`
// cipher text to be decrypted
CipherText TPM2BPublicKeyRSA
// the padding scheme to use if scheme associated with keyHandle is TPM_ALG_NULL
InScheme TPMTRSADecrypt `gotpm:"nullable"`
// label whose association with the message is to be verified
Label TPM2BData `gotpm:"optional"`
}

// Command implements the Command interface.
func (RSADecrypt) Command() TPMCC { return TPMCCRSADecrypt }

// Execute executes the command and returns the response.
func (cmd RSADecrypt) Execute(t transport.TPM, s ...Session) (*RSADecryptResponse, error) {
var rsp RSADecryptResponse
if err := execute[RSADecryptResponse](t, cmd, &rsp, s...); err != nil {
return nil, err
}
return &rsp, nil
}

// RSADecryptResponse is the response from TPM2_RSA_Decrypt
type RSADecryptResponse struct {
// decrypted output
Message TPM2BPublicKeyRSA
}

// ECDHZGen is the input to TPM2_ECDHZGen.
// See definition in Part 3, Commands, section 14.5
type ECDHZGen struct {
Expand Down

0 comments on commit cfdeb6e

Please sign in to comment.