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

Introduce Direct TPM2 API #266

Merged
merged 9 commits into from
Feb 19, 2022
Binary file added .tempnotes.txt.swp
Binary file not shown.
46 changes: 46 additions & 0 deletions direct/helpers/crypto.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package helpers

import (
"crypto/elliptic"
"crypto/rsa"
"math/big"

"github.com/google/go-tpm/direct/structures/tpm2b"
"github.com/google/go-tpm/direct/structures/tpms"
)

// RSAPub converts a TPM RSA public key into one recognized by the rsa package.
func RSAPub(parms *tpms.RSAParms, pub *tpm2b.PublicKeyRSA) (*rsa.PublicKey, error) {
result := rsa.PublicKey{
N: big.NewInt(0).SetBytes(pub.Buffer),
E: int(parms.Exponent),
}
// TPM considers 65537 to be the default RSA public exponent, and 0 in
// the parms
// indicates so.
if result.E == 0 {
result.E = 65537
}
return &result, nil
}

// ECDHPub is a convenience wrapper around the necessary info to perform point
// multiplication with the elliptic package.
type ECDHPub struct {
Curve elliptic.Curve
X, Y *big.Int
}

// ECCPub converts a TPM ECC public key into one recognized by the elliptic
// package's point-multiplication functions, for use in ECDH.
func ECCPub(parms *tpms.ECCParms, pub *tpms.ECCPoint) (*ECDHPub, error) {
curve, err := parms.CurveID.Curve()
if err != nil {
return nil, err
}
return &ECDHPub{
Curve: curve,
X: big.NewInt(0).SetBytes(pub.X.Buffer),
Y: big.NewInt(0).SetBytes(pub.Y.Buffer),
}, nil
}
14 changes: 14 additions & 0 deletions direct/helpers/names.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package helpers

import (
"encoding/binary"

"github.com/google/go-tpm/direct/structures/tpm"
)

// PrimaryHandleName returns the TPM Name of a primary handle.
func PrimaryHandleName(h tpm.Handle) []byte {
result := make([]byte, 4)
binary.BigEndian.PutUint32(result, uint32(h))
return result
}
12 changes: 12 additions & 0 deletions direct/helpers/wrappers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package helpers

import "github.com/google/go-tpm/direct/structures/tpm"

// This file provides wrapper functions for concrete types used by tpm2, for
// setting union member pointers.

// NewKeyBits allocates and returns the address of a new tpm.KeyBits.
func NewKeyBits(v tpm.KeyBits) *tpm.KeyBits { return &v }

// NewAlgID allocates and returns the address of a new tpm.AlgID.
func NewAlgID(v tpm.AlgID) *tpm.AlgID { return &v }
83 changes: 83 additions & 0 deletions direct/structures/internal/bitfield.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package internal

import (
"fmt"
)

// Bitfield represents a TPM bitfield (i.e., TPMA_*) type.
type Bitfield interface {
// Length returns the length of the bitfield.
Length() int
}

// BitGetter represents a TPM bitfield (i.e., TPMA_*) type that can be read.
type BitGetter interface {
Bitfield
// GetReservedBit returns the value of the given reserved bit.
// If the bit is not reserved, returns false.
GetReservedBit(pos int) bool
}

// BitSetter represents a TPM bitfield (i.e., TPMA_*) type that can be written.
type BitSetter interface {
Bitfield
// GetReservedBit sets the value of the given reserved bit.
SetReservedBit(pos int, val bool)
}

func checkPos(pos int, len int) {
if pos >= len || pos < 0 {
panic(fmt.Errorf("bit %d out of range for %d-bit field", pos, len))
}
}

// bitfield8 represents an 8-bit bitfield which may have reserved bits.
// 8-bit TPMA_* types embed this one, and the reserved bits are stored in it.
type bitfield8 uint8

// Length implements the Bitfield interface.
func (bitfield8) Length() int {
return 8
}

// GetReservedBit implements the BitGetter interface.
func (r bitfield8) GetReservedBit(pos int) bool {
checkPos(pos, 8)
return r&(1<<pos) != 0
}

// SetReservedBit implements the BitSetter interface.
func (r *bitfield8) SetReservedBit(pos int, val bool) {
checkPos(pos, 8)
if val {
*r |= 1 << pos
} else {
*r &= ^(1 << pos)
}
}

// bitfield32 represents a 32-bit bitfield which may have reserved bits.
// 32-bit TPMA_* types embed this one, and the reserved bits are stored in it.
type bitfield32 uint32

// Length implements the Bitfield interface.
func (bitfield32) Length() int {
return 32
}

// GetReservedBit implements the BitGetter interface.
func (r bitfield32) GetReservedBit(pos int) bool {
checkPos(pos, 32)
return r&(1<<pos) != 0
}

// SetReservedBit implements the BitSetter interface.
func (r *bitfield32) SetReservedBit(pos int, val bool) {
checkPos(pos, 32)
if val {
*r |= 1 << pos
} else {
*r &= ^(1 << pos)
}
}

Loading