Skip to content

Commit f5d5ec4

Browse files
committed
add direct x509 support
Signed-off-by: sal rashid <[email protected]>
1 parent 89bbd6f commit f5d5ec4

File tree

8 files changed

+388
-46
lines changed

8 files changed

+388
-46
lines changed

.goreleaser.yml

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
project_name: github.com/salrashid123/signer
2+
version: 2
3+
release:
4+
draft: true
5+
github:
6+
owner: salrashid123
7+
name: github.com/salrashid123
8+
name_template: '{{.Tag}}'
9+
extra_files:
10+
gomod:
11+
dir: ./tpm/
12+
gobinary: go
13+
builds:
14+
- skip: true
15+
archives:
16+
- id: archive
17+
name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
18+
formats: ['tar.gz']
19+
files:
20+
- LICENSE*
21+
- README*
22+
- dist/*.sig
23+
snapshot:
24+
version_template: '{{ .Version }}'
25+
checksum:
26+
name_template: '{{ .ProjectName }}_checksums.txt'
27+
algorithm: sha256
28+
dist: dist
29+
signs:
30+
- cmd: gpg
31+
id: gpg
32+
artifacts: all
33+
output: true
34+
args:
35+
- "--batch"
36+
- "--local-user"
37+
- "{{ .Env.GPG_FINGERPRINT }}" # "5D8EA7261718FE5728BA937C97341836616BF511" [email protected] https://keyserver.ubuntu.com/pks/lookup?search=5D8EA7261718FE5728BA937C97341836616BF511&fingerprint=on&op=index
38+
- "--output"
39+
- "${signature}"
40+
- "--detach-sign"
41+
- "${artifact}"
42+
env_files:
43+
github_token: ~/.config/goreleaser/github_token
44+
source:
45+
name_template: '{{ .ProjectName }}-{{ .Version }}'
46+
format: tar.gz
47+
github_urls:
48+
download: https://github.com

example/README.md

+10-13
Original file line numberDiff line numberDiff line change
@@ -56,55 +56,52 @@ cd example/
5656
## RSA - no password
5757
tpm2_createprimary -C o -G rsa2048:aes128cfb -g sha256 -c primary.ctx -a 'restricted|decrypt|fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda'
5858
tpm2_create -G rsa2048:rsassa:null -g sha256 -u key.pub -r key.priv -C primary.ctx
59-
tpm2_flushcontext -t
6059
tpm2_getcap handles-transient
6160
tpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx
6261
tpm2_evictcontrol -C o -c key.ctx 0x81008001
63-
tpm2_flushcontext -t
62+
63+
### RSA - no password with PEM key file
64+
65+
printf '\x00\x00' > unique.dat
66+
tpm2_createprimary -C o -G ecc -g sha256 -c primary.ctx -a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt" -u unique.dat
67+
68+
tpm2_create -G rsa2048:rsapss:null -g sha256 -u key.pub -r key.priv -C primary.ctx --format=pem --output=rsapss_public.pem
69+
tpm2_getcap handles-transient
70+
tpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx
71+
tpm2_encodeobject -C primary.ctx -u key.pub -r key.priv -o key.pem
6472

6573
## rsa-pss
6674
tpm2_createprimary -C o -G rsa2048:aes128cfb -g sha256 -c primary.ctx -a 'restricted|decrypt|fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda'
67-
tpm2_create -G rsa2048:rsapss:null -g sha256 -u key.pub -r key.priv -C primary.ctx --format=pem --output=rsapss_public.pem
68-
tpm2_flushcontext -t
6975
tpm2_getcap handles-transient
7076
tpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx
7177
tpm2_evictcontrol -C o -c key.ctx 0x81008004
72-
tpm2_flushcontext -t
7378

7479
## ecc
7580
tpm2_createprimary -C o -G rsa2048:aes128cfb -g sha256 -c primary.ctx -a 'restricted|decrypt|fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda'
7681
tpm2_create -G ecc:ecdsa -g sha256 -u key.pub -r key.priv -C primary.ctx --format=pem --output=ecc_public.pem
77-
tpm2_flushcontext -t
7882
tpm2_getcap handles-transient
7983
tpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx
8084
tpm2_evictcontrol -C o -c key.ctx 0x81008005
81-
tpm2_flushcontext -t
82-
8385

8486
## for policyPCR
8587

8688
tpm2_pcrread sha256:23
8789
tpm2_startauthsession -S session.dat
8890
tpm2_policypcr -S session.dat -l sha256:23 -L policy.dat
8991
tpm2_flushcontext session.dat
90-
tpm2_flushcontext -t
9192
tpm2_createprimary -C o -G rsa2048:aes128cfb -g sha256 -c primary.ctx -a 'restricted|decrypt|fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda'
9293
tpm2_create -G rsa2048:rsassa:null -g sha256 -u key.pub -r key.priv -C primary.ctx -L policy.dat
93-
tpm2_flushcontext -t
9494
tpm2_getcap handles-transient
9595
tpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx
9696
tpm2_evictcontrol -C o -c key.ctx 0x81008006
97-
tpm2_flushcontext -t
9897

9998
## for policyPassword
10099

101100
tpm2_createprimary -C o -G rsa2048:aes128cfb -g sha256 -c primary.ctx -a 'restricted|decrypt|fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda'
102101
tpm2_create -G rsa2048:rsassa:null -p testpwd -g sha256 -u key.pub -r key.priv -C primary.ctx
103-
tpm2_flushcontext -t
104102
tpm2_getcap handles-transient
105103
tpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx
106104
tpm2_evictcontrol -C o -c key.ctx 0x81008007
107-
tpm2_flushcontext -t
108105

109106
## =====
110107

example/go.mod

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
module main
22

3-
go 1.22
3+
go 1.22.0
44

5-
toolchain go1.22.2
5+
toolchain go1.24.0
66

77
require (
88
github.com/google/go-tpm v0.9.1
@@ -20,6 +20,7 @@ require (
2020
cloud.google.com/go/kms v1.17.1 // indirect
2121
cloud.google.com/go/longrunning v0.5.7 // indirect
2222
github.com/felixge/httpsnoop v1.0.4 // indirect
23+
github.com/foxboron/go-tpm-keyfiles v0.0.0-20241207144721-04534a2f2feb // indirect
2324
github.com/go-logr/logr v1.4.2 // indirect
2425
github.com/go-logr/stdr v1.2.2 // indirect
2526
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect

example/go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
2626
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
2727
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
2828
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
29+
github.com/foxboron/go-tpm-keyfiles v0.0.0-20241207144721-04534a2f2feb h1:kwNzot0LHHST1wdN8zP5hSWITzPubfEZlwyRspMAzFg=
30+
github.com/foxboron/go-tpm-keyfiles v0.0.0-20241207144721-04534a2f2feb/go.mod h1:uAyTlAUxchYuiFjTHmuIEJ4nGSm7iOPaGcAyA81fJ80=
2931
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
3032
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
3133
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+165
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
package main
2+
3+
import (
4+
"crypto"
5+
"crypto/rand"
6+
"crypto/rsa"
7+
"crypto/sha256"
8+
"encoding/base64"
9+
"flag"
10+
"fmt"
11+
"io"
12+
"log"
13+
"net"
14+
"os"
15+
"slices"
16+
17+
keyfile "github.com/foxboron/go-tpm-keyfiles"
18+
"github.com/google/go-tpm-tools/simulator"
19+
"github.com/google/go-tpm/tpm2"
20+
"github.com/google/go-tpm/tpm2/transport"
21+
"github.com/google/go-tpm/tpmutil"
22+
saltpm "github.com/salrashid123/signer/tpm"
23+
)
24+
25+
const ()
26+
27+
/*
28+
29+
30+
## keyfile with H2 template
31+
printf '\x00\x00' > unique.dat
32+
tpm2_createprimary -C o -G ecc -g sha256 -c primary.ctx -a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt" -u unique.dat
33+
34+
tpm2_create -G rsa2048:rsapss:null -g sha256 -u key.pub -r key.priv -C primary.ctx --format=pem --output=rsapss_public.pem
35+
tpm2_getcap handles-transient
36+
tpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx
37+
tpm2_encodeobject -C primary.ctx -u key.pub -r key.priv -o key.pem
38+
*/
39+
40+
var (
41+
tpmPath = flag.String("tpm-path", "/dev/tpmrm0", "Path to the TPM device (character device or a Unix socket).")
42+
pemFile = flag.String("pemFile", "key.pem", "KeyFile in PEM format")
43+
)
44+
45+
var TPMDEVICES = []string{"/dev/tpm0", "/dev/tpmrm0"}
46+
47+
func OpenTPM(path string) (io.ReadWriteCloser, error) {
48+
if slices.Contains(TPMDEVICES, path) {
49+
return tpmutil.OpenTPM(path)
50+
} else if path == "simulator" {
51+
return simulator.Get()
52+
} else {
53+
return net.Dial("tcp", path)
54+
}
55+
}
56+
57+
func main() {
58+
59+
flag.Parse()
60+
61+
rwc, err := OpenTPM(*tpmPath)
62+
if err != nil {
63+
log.Fatalf("can't open TPM %q: %v", *tpmPath, err)
64+
}
65+
defer func() {
66+
if err := rwc.Close(); err != nil {
67+
log.Fatalf("can't close TPM %q: %v", *tpmPath, err)
68+
}
69+
}()
70+
71+
rwr := transport.FromReadWriter(rwc)
72+
73+
c, err := os.ReadFile(*pemFile)
74+
if err != nil {
75+
log.Fatalf("can't load keys %q: %v", *tpmPath, err)
76+
}
77+
key, err := keyfile.Decode(c)
78+
if err != nil {
79+
log.Fatalf("can't decode keys %q: %v", *tpmPath, err)
80+
}
81+
82+
primaryKey, err := tpm2.CreatePrimary{
83+
PrimaryHandle: key.Parent,
84+
InPublic: tpm2.New2B(keyfile.ECCSRK_H2_Template),
85+
}.Execute(rwr)
86+
if err != nil {
87+
log.Fatalf("can't create primary %q: %v", *tpmPath, err)
88+
}
89+
90+
defer func() {
91+
flushContextCmd := tpm2.FlushContext{
92+
FlushHandle: primaryKey.ObjectHandle,
93+
}
94+
_, _ = flushContextCmd.Execute(rwr)
95+
}()
96+
97+
rsaKey, err := tpm2.Load{
98+
ParentHandle: tpm2.AuthHandle{
99+
Handle: primaryKey.ObjectHandle,
100+
Name: tpm2.TPM2BName(primaryKey.Name),
101+
Auth: tpm2.PasswordAuth([]byte("")),
102+
},
103+
InPublic: key.Pubkey,
104+
InPrivate: key.Privkey,
105+
}.Execute(rwr)
106+
107+
if err != nil {
108+
log.Fatalf("can't load hmacKey : %v", err)
109+
}
110+
111+
pub, err := tpm2.ReadPublic{
112+
ObjectHandle: rsaKey.ObjectHandle,
113+
}.Execute(rwr)
114+
if err != nil {
115+
log.Fatalf("error executing tpm2.ReadPublic %v", err)
116+
}
117+
118+
stringToSign := "foo"
119+
fmt.Printf("Data to sign %s\n", stringToSign)
120+
121+
b := []byte(stringToSign)
122+
123+
h := sha256.New()
124+
h.Write(b)
125+
digest := h.Sum(nil)
126+
127+
r, err := saltpm.NewTPMCrypto(&saltpm.TPM{
128+
TpmDevice: rwc,
129+
NamedHandle: &tpm2.NamedHandle{
130+
Handle: rsaKey.ObjectHandle,
131+
Name: pub.Name,
132+
},
133+
})
134+
135+
if err != nil {
136+
fmt.Println(err)
137+
os.Exit(1)
138+
}
139+
140+
s, err := r.Sign(rand.Reader, digest, crypto.SHA256)
141+
if err != nil {
142+
log.Println(err)
143+
os.Exit(1)
144+
}
145+
fmt.Printf("RSA Signed String: %s\n", base64.StdEncoding.EncodeToString(s))
146+
147+
rsaPubKey, ok := r.Public().(*rsa.PublicKey)
148+
if !ok {
149+
fmt.Println(err)
150+
os.Exit(1)
151+
}
152+
153+
opts := &rsa.PSSOptions{
154+
Hash: crypto.SHA256,
155+
SaltLength: rsa.PSSSaltLengthAuto,
156+
}
157+
err = rsa.VerifyPSS(rsaPubKey, crypto.SHA256, digest, s, opts)
158+
if err != nil {
159+
fmt.Println(err)
160+
return
161+
}
162+
163+
fmt.Printf("RSA Signed String verified\n")
164+
165+
}

kms/kms.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,17 @@ type KMS struct {
4040
KeyRing string
4141
Key string
4242
KeyVersion string
43-
x509Certificate *x509.Certificate
43+
X509Certificate *x509.Certificate
4444
ECCRawOutput bool // for ECC keys, output raw signatures. If false, signature is ans1 formatted
4545
SignatureAlgorithm x509.SignatureAlgorithm
4646
}
4747

4848
func NewKMSCrypto(conf *KMS) (KMS, error) {
4949

50+
if conf.X509Certificate != nil && conf.PublicKeyFile != "" {
51+
return KMS{}, fmt.Errorf("salrashid123/signer: Either X509Certificate or a the path to the certificate must be specified; not both")
52+
}
53+
5054
if conf.SignatureAlgorithm == x509.UnknownSignatureAlgorithm {
5155
conf.SignatureAlgorithm = x509.SHA256WithRSA
5256
}
@@ -87,11 +91,7 @@ func (t KMS) Public() crypto.PublicKey {
8791

8892
func (t KMS) TLSCertificate() (tls.Certificate, error) {
8993

90-
if t.PublicKeyFile == "" {
91-
return tls.Certificate{}, fmt.Errorf("public X509 certificate not specified")
92-
}
93-
94-
if t.x509Certificate == nil {
94+
if t.X509Certificate == nil {
9595
pubPEM, err := os.ReadFile(t.PublicKeyFile)
9696
if err != nil {
9797
return tls.Certificate{}, fmt.Errorf("unable to read keys %v", err)
@@ -104,14 +104,14 @@ func (t KMS) TLSCertificate() (tls.Certificate, error) {
104104
if err != nil {
105105
return tls.Certificate{}, fmt.Errorf("failed to parse public key: %v ", err)
106106
}
107-
t.x509Certificate = pub
107+
t.X509Certificate = pub
108108
}
109109

110110
var privKey crypto.PrivateKey = t
111111
return tls.Certificate{
112112
PrivateKey: privKey,
113-
Leaf: t.x509Certificate,
114-
Certificate: [][]byte{t.x509Certificate.Raw},
113+
Leaf: t.X509Certificate,
114+
Certificate: [][]byte{t.X509Certificate.Raw},
115115
}, nil
116116
}
117117

0 commit comments

Comments
 (0)