-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add signer implementation to tss2.TPPKey
This PR adds a signer implementation for TSS2 keys, it also adds new methods to marshal those keys to PEM.
- Loading branch information
Showing
7 changed files
with
665 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package tss2 | ||
|
||
import ( | ||
"encoding/pem" | ||
|
||
"github.com/google/go-tpm/legacy/tpm2" | ||
) | ||
|
||
// TPMOption is the type used to modify a [TPMKey]. | ||
type TPMOption func(*TPMKey) | ||
|
||
// New creates a new [TPMKey] with the given public and private keys. | ||
func New(pub, priv []byte, opts ...TPMOption) *TPMKey { | ||
key := &TPMKey{ | ||
Type: oidLoadableKey, | ||
EmptyAuth: true, | ||
Parent: int(tpm2.HandleOwner), | ||
PublicKey: integrityPrefix(pub), | ||
PrivateKey: integrityPrefix(priv), | ||
} | ||
for _, fn := range opts { | ||
fn(key) | ||
} | ||
return key | ||
} | ||
|
||
// Encode encodes the [TPMKey] returns a [*pem.Block]. | ||
func (k *TPMKey) Encode() (*pem.Block, error) { | ||
b, err := MarshalPrivateKey(k) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &pem.Block{ | ||
Type: "TSS2 PRIVATE KEY", | ||
Bytes: b, | ||
}, nil | ||
} | ||
|
||
// EncodeToMemory encodes the [TPMKey] and returns an encoded PEM block. | ||
func (k *TPMKey) EncodeToMemory() ([]byte, error) { | ||
block, err := k.Encode() | ||
if err != nil { | ||
return nil, err | ||
} | ||
return pem.EncodeToMemory(block), nil | ||
} | ||
|
||
// Encode encodes the given public and private key and returns a [*pem.Block]. | ||
func Encode(pub, priv []byte, opts ...TPMOption) (*pem.Block, error) { | ||
return New(pub, priv, opts...).Encode() | ||
} | ||
|
||
// EncodeToMemory encodes the given public and private key and returns an | ||
// encoded PEM block. | ||
func EncodeToMemory(pub, priv []byte, opts ...TPMOption) ([]byte, error) { | ||
return New(pub, priv, opts...).EncodeToMemory() | ||
} | ||
|
||
func integrityPrefix(b []byte) []byte { | ||
s := len(b) | ||
return append([]byte{byte(s >> 8 & 0xFF), byte(s & 0xFF)}, b...) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
package tss2 | ||
|
||
import ( | ||
"encoding/pem" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestNew(t *testing.T) { | ||
type args struct { | ||
pub []byte | ||
priv []byte | ||
opts []TPMOption | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
want *TPMKey | ||
}{ | ||
{"ok", args{[]byte("public"), []byte("private"), nil}, &TPMKey{ | ||
Type: oidLoadableKey, | ||
EmptyAuth: true, | ||
Parent: 0x40000001, | ||
PublicKey: append([]byte{0, 6}, []byte("public")...), | ||
PrivateKey: append([]byte{0, 7}, []byte("private")...), | ||
}}, | ||
{"ok with options", args{[]byte("public"), []byte("private"), []TPMOption{ | ||
func(k *TPMKey) { | ||
k.EmptyAuth = false | ||
}, | ||
func(k *TPMKey) { | ||
k.Policy = append(k.Policy, TPMPolicy{CommandCode: 1, CommandPolicy: []byte("command-policy")}) | ||
}, | ||
}}, &TPMKey{ | ||
Type: oidLoadableKey, | ||
EmptyAuth: false, | ||
Policy: []TPMPolicy{{CommandCode: 1, CommandPolicy: []byte("command-policy")}}, | ||
Parent: 0x40000001, | ||
PublicKey: append([]byte{0, 6}, []byte("public")...), | ||
PrivateKey: append([]byte{0, 7}, []byte("private")...), | ||
}}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
assert.Equal(t, tt.want, New(tt.args.pub, tt.args.priv, tt.args.opts...)) | ||
}) | ||
} | ||
} | ||
|
||
func TestTPMKey_Encode(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
tpmKey *TPMKey | ||
want *pem.Block | ||
assertion assert.ErrorAssertionFunc | ||
}{ | ||
{"ok", New([]byte("public"), []byte("private")), &pem.Block{ | ||
Type: "TSS2 PRIVATE KEY", | ||
Bytes: []byte{ | ||
0x30, 0x28, | ||
0x6, 0x6, 0x67, 0x81, 0x5, 0xa, 0x1, 0x3, | ||
0xa0, 0x3, 0x1, 0x1, 0xff, | ||
0x2, 0x4, 0x40, 0x0, 0x0, 0x1, | ||
0x4, 0x8, 0x0, 0x6, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, | ||
0x4, 0x9, 0x0, 0x7, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, | ||
}, | ||
}, assert.NoError}, | ||
{"fail", nil, nil, assert.Error}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
got, err := tt.tpmKey.Encode() | ||
tt.assertion(t, err) | ||
assert.Equal(t, tt.want, got) | ||
}) | ||
} | ||
} | ||
|
||
func TestTPMKey_EncodeToMemory(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
tpmKey *TPMKey | ||
want []byte | ||
assertion assert.ErrorAssertionFunc | ||
}{ | ||
{"ok", New([]byte("public"), []byte("private")), []byte(`-----BEGIN TSS2 PRIVATE KEY----- | ||
MCgGBmeBBQoBA6ADAQH/AgRAAAABBAgABnB1YmxpYwQJAAdwcml2YXRl | ||
-----END TSS2 PRIVATE KEY----- | ||
`), assert.NoError}, | ||
{"fail", nil, nil, assert.Error}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
got, err := tt.tpmKey.EncodeToMemory() | ||
tt.assertion(t, err) | ||
assert.Equal(t, tt.want, got) | ||
t.Log(string(got)) | ||
}) | ||
} | ||
} | ||
|
||
func TestEncode(t *testing.T) { | ||
type args struct { | ||
pub []byte | ||
priv []byte | ||
opts []TPMOption | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
want *pem.Block | ||
assertion assert.ErrorAssertionFunc | ||
}{ | ||
{"ok", args{[]byte("public"), []byte("private"), nil}, &pem.Block{ | ||
Type: "TSS2 PRIVATE KEY", | ||
Bytes: []byte{ | ||
0x30, 0x28, | ||
0x6, 0x6, 0x67, 0x81, 0x5, 0xa, 0x1, 0x3, | ||
0xa0, 0x3, 0x1, 0x1, 0xff, | ||
0x2, 0x4, 0x40, 0x0, 0x0, 0x1, | ||
0x4, 0x8, 0x0, 0x6, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, | ||
0x4, 0x9, 0x0, 0x7, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, | ||
}, | ||
}, assert.NoError}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
got, err := Encode(tt.args.pub, tt.args.priv, tt.args.opts...) | ||
tt.assertion(t, err) | ||
assert.Equal(t, tt.want, got) | ||
}) | ||
} | ||
} | ||
|
||
func TestEncodeToMemory(t *testing.T) { | ||
type args struct { | ||
pub []byte | ||
priv []byte | ||
opts []TPMOption | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
want []byte | ||
assertion assert.ErrorAssertionFunc | ||
}{ | ||
{"ok", args{[]byte("public"), []byte("private"), nil}, []byte(`-----BEGIN TSS2 PRIVATE KEY----- | ||
MCgGBmeBBQoBA6ADAQH/AgRAAAABBAgABnB1YmxpYwQJAAdwcml2YXRl | ||
-----END TSS2 PRIVATE KEY----- | ||
`), assert.NoError}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
got, err := EncodeToMemory(tt.args.pub, tt.args.priv, tt.args.opts...) | ||
tt.assertion(t, err) | ||
assert.Equal(t, tt.want, got) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
//go:build !tpm && !tpmsimulator | ||
|
||
package tss2 | ||
|
||
import ( | ||
"io" | ||
"testing" | ||
) | ||
|
||
func openTPM(t *testing.T) io.ReadWriteCloser { | ||
t.Helper() | ||
t.Skip("Use tags tpm or tpmsimulator") | ||
return nil | ||
} |
Oops, something went wrong.