Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve TPMUSensitiveComposite and crypto #372

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
117 changes: 117 additions & 0 deletions tpm2/crypto.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package tpm2

import (
"crypto"
"crypto/ecdh"
"crypto/ecdsa"
"crypto/elliptic"
Expand All @@ -9,6 +10,87 @@ import (
"math/big"
)

// Priv converts a TPM private key into one recognized by the crypto package.
func Priv(public TPMTPublic, sensitive TPMTSensitive) (crypto.PrivateKey, error) {

var privateKey crypto.PrivateKey

publicKey, err := Pub(public)
if err != nil {
return nil, err
}

switch public.Type {
case TPMAlgRSA:
publicKey := publicKey.(*rsa.PublicKey)

prime, err := sensitive.Sensitive.RSA()
if err != nil {
return nil, fmt.Errorf("failed to retrieve the RSA prime number")
}

P := new(big.Int).SetBytes(prime.Buffer)
Q := new(big.Int).Div(publicKey.N, P)
phiN := new(big.Int).Mul(new(big.Int).Sub(P, big.NewInt(1)), new(big.Int).Sub(Q, big.NewInt(1)))
D := new(big.Int).ModInverse(big.NewInt(int64(publicKey.E)), phiN)

privateKey = rsa.PrivateKey{
PublicKey: *publicKey,
D: D,
Primes: []*big.Int{P, Q},
}
privateKey := privateKey.(rsa.PrivateKey)

privateKey.Precompute()
default:
return nil, fmt.Errorf("unsupported public key type: %v", public.Type)
}

return privateKey, nil
}

// Pub converts a TPM public key into one recognized by the crypto package.
func Pub(public TPMTPublic) (crypto.PublicKey, error) {
var publicKey crypto.PublicKey

switch public.Type {
case TPMAlgRSA:
parameters, err := public.Parameters.RSADetail()
if err != nil {
return nil, fmt.Errorf("failed to retrieve the RSA parameters")
}

n, err := public.Unique.RSA()
if err != nil {
return nil, fmt.Errorf("failed to parse and retrieve the RSA modulus")
}

publicKey, err = RSAPub(parameters, n)
if err != nil {
return nil, fmt.Errorf("failed to retrieve the RSA public key")
}
case TPMAlgECC:
parameters, err := public.Parameters.ECCDetail()
if err != nil {
return nil, fmt.Errorf("failed to retrieve the ECC parameters")
}

pub, err := public.Unique.ECC()
if err != nil {
return nil, fmt.Errorf("failed to parse and retrieve the ECC point")
}

publicKey, err = ECDSAPub(parameters, pub)
if err != nil {
return nil, fmt.Errorf("failed to retrieve the ECC public key")
}
default:
return nil, fmt.Errorf("unsupported public key type: %v", public.Type)
}

return publicKey, nil
}

// RSAPub converts a TPM RSA public key into one recognized by the rsa package.
func RSAPub(parms *TPMSRSAParms, pub *TPM2BPublicKeyRSA) (*rsa.PublicKey, error) {
result := rsa.PublicKey{
Expand All @@ -24,6 +106,41 @@ func RSAPub(parms *TPMSRSAParms, pub *TPM2BPublicKeyRSA) (*rsa.PublicKey, error)
return &result, nil
}

// ECDSAPub converts a TPM ECC public key into one recognized by the ecdh package
func ECDSAPub(parms *TPMSECCParms, pub *TPMSECCPoint) (*ecdsa.PublicKey, error) {

var c elliptic.Curve
switch parms.CurveID {
case TPMECCNistP256:
c = elliptic.P256()
case TPMECCNistP384:
c = elliptic.P384()
case TPMECCNistP521:
c = elliptic.P521()
default:
return nil, fmt.Errorf("unknown curve: %v", parms.CurveID)
}

pubKey := ecdsa.PublicKey{
Curve: c,
X: big.NewInt(0).SetBytes(pub.X.Buffer),
Y: big.NewInt(0).SetBytes(pub.Y.Buffer),
}

return &pubKey, nil
}

// ECDHPub converts a TPM ECC public key into one recognized by the ecdh package
func ECDHPub(parms *TPMSECCParms, pub *TPMSECCPoint) (*ecdh.PublicKey, error) {

pubKey, err := ECDSAPub(parms, pub)
if err != nil {
return nil, err
}

return pubKey.ECDH()
}

// ECDHPubKey converts a TPM ECC public key into one recognized by the ecdh package
func ECDHPubKey(curve ecdh.Curve, pub *TPMSECCPoint) (*ecdh.PublicKey, error) {

Expand Down
32 changes: 32 additions & 0 deletions tpm2/structures.go
Original file line number Diff line number Diff line change
Expand Up @@ -2868,6 +2868,38 @@ func New2BTemplate[C TemplateContents](data C) TPM2BTemplate {
}
}

// Sym returns the 'sym' member of the union.
func (u *TPMUSensitiveComposite) Sym() (*TPM2BSymKey, error) {
if u.selector == TPMAlgSymCipher {
return u.contents.(*TPM2BSymKey), nil
}
return nil, fmt.Errorf("did not contain sym (selector value was %v)", u.selector)
}

// Bits returns the 'bits' member of the union.
func (u *TPMUSensitiveComposite) Bits() (*TPM2BSensitiveData, error) {
if u.selector == TPMAlgKeyedHash {
return u.contents.(*TPM2BSensitiveData), nil
}
return nil, fmt.Errorf("did not contain bits (selector value was %v)", u.selector)
}

// RSA returns the 'rsa' member of the union.
func (u *TPMUSensitiveComposite) RSA() (*TPM2BPrivateKeyRSA, error) {
if u.selector == TPMAlgRSA {
return u.contents.(*TPM2BPrivateKeyRSA), nil
}
return nil, fmt.Errorf("did not contain rsa (selector value was %v)", u.selector)
}

// ECC returns the 'ecc' member of the union.
func (u *TPMUSensitiveComposite) ECC() (*TPM2BECCParameter, error) {
if u.selector == TPMAlgECC {
return u.contents.(*TPM2BECCParameter), nil
}
return nil, fmt.Errorf("did not contain ecc (selector value was %v)", u.selector)
}

// TPMUSensitiveComposite represents a TPMU_SENSITIVE_COMPOSITE.
// See definition in Part 2: Structures, section 12.3.2.3.
type TPMUSensitiveComposite struct {
Expand Down