Skip to content

Commit 1c7bced

Browse files
committed
Merge remote-tracking branch 'origin/pull/37'
* origin/pull/37: add support for owner password
2 parents f1be81b + e3226d3 commit 1c7bced

File tree

15 files changed

+317
-65
lines changed

15 files changed

+317
-65
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ $ export SSH_AUTH_SOCK="$(ssh-tpm-agent --print-socket)"
6363
6464
```
6565
66+
**Note:** For `ssh-tpm-agent` you can specify the TPM owner password using the command line flags `-o` or `--owner-password`, which are preferred. Alternatively, you can use the environment variable `SSH_TPM_AGENT_OWNER_PASSWORD`.
67+
6668
### Import existing key
6769
6870
Useful if you want to back up the key to a remote secure storage while using the key day-to-day from the TPM.

agent/agent.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ var SSH_TPM_AGENT_ADD = "tpm-add-key"
2929
type Agent struct {
3030
mu sync.Mutex
3131
tpm func() transport.TPMCloser
32+
op func() ([]byte, error)
3233
pin func(*key.Key) ([]byte, error)
3334
listener *net.UnixListener
3435
quit chan interface{}
@@ -83,7 +84,7 @@ func (a *Agent) signers() ([]ssh.Signer, error) {
8384
}
8485

8586
for _, k := range a.keys {
86-
s, err := ssh.NewSignerFromSigner(signer.NewTPMSigner(k, a.tpm, a.pin))
87+
s, err := ssh.NewSignerFromSigner(signer.NewTPMSigner(k, a.op, a.tpm, a.pin))
8788
if err != nil {
8889
return nil, fmt.Errorf("failed to prepare signer: %w", err)
8990
}
@@ -343,10 +344,11 @@ func LoadKeys(keyDir string) (map[string]*key.Key, error) {
343344
return keys, err
344345
}
345346

346-
func NewAgent(listener *net.UnixListener, agents []agent.ExtendedAgent, tpmFetch func() transport.TPMCloser, pin func(*key.Key) ([]byte, error)) *Agent {
347+
func NewAgent(listener *net.UnixListener, agents []agent.ExtendedAgent, tpmFetch func() transport.TPMCloser, ownerPassword func() ([]byte, error), pin func(*key.Key) ([]byte, error)) *Agent {
347348
a := &Agent{
348349
agents: agents,
349350
tpm: tpmFetch,
351+
op: ownerPassword,
350352
listener: listener,
351353
pin: pin,
352354
quit: make(chan interface{}),

agent/agent_test.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,11 @@ func TestAddKey(t *testing.T) {
3131
ag := NewAgent(unixList,
3232
[]agent.ExtendedAgent{},
3333
// TPM Callback
34-
func() transport.TPMCloser {
35-
return tpm
36-
},
34+
func() transport.TPMCloser { return tpm },
35+
// Owner password
36+
func() ([]byte, error) { return []byte(""), nil },
3737
// PIN Callback
38-
func(_ *key.Key) ([]byte, error) {
39-
return []byte(""), nil
40-
},
38+
func(_ *key.Key) ([]byte, error) { return []byte(""), nil },
4139
)
4240
defer ag.Stop()
4341

@@ -49,7 +47,7 @@ func TestAddKey(t *testing.T) {
4947

5048
client := agent.NewClient(conn)
5149

52-
k, err := key.CreateKey(tpm, tpm2.TPMAlgECC, 256, []byte(""), "")
50+
k, err := key.CreateKey(tpm, tpm2.TPMAlgECC, 256, []byte(""), []byte(""), "")
5351
if err != nil {
5452
t.Fatal(err)
5553
}

cmd/ssh-tpm-agent/main.go

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ Options:
4444
4545
--no-load Do not load TPM sealed keys by default.
4646
47+
-o, --owner-password Ask for the owner password.
48+
4749
-d Enable debug logging.
4850
4951
--install-user-units Installs systemd system units and sshd configs for using
@@ -98,10 +100,10 @@ func main() {
98100
}
99101

100102
var (
101-
socketPath, keyDir string
102-
swtpmFlag, printSocketFlag bool
103-
installUserUnits bool
104-
system, noLoad, debugMode bool
103+
socketPath, keyDir string
104+
swtpmFlag, printSocketFlag bool
105+
installUserUnits, system, noLoad bool
106+
askOwnerPassword, debugMode bool
105107
)
106108

107109
envSocketPath := func() string {
@@ -126,6 +128,8 @@ func main() {
126128
flag.BoolVar(&installUserUnits, "install-user-units", false, "install systemd user units")
127129
flag.BoolVar(&system, "install-system", false, "install systemd user units")
128130
flag.BoolVar(&noLoad, "no-load", false, "don't load TPM sealed keys")
131+
flag.BoolVar(&askOwnerPassword, "o", false, "ask for the owner password")
132+
flag.BoolVar(&askOwnerPassword, "owner-password", false, "ask for the owner password")
129133
flag.BoolVar(&debugMode, "d", false, "debug mode")
130134
flag.Parse()
131135

@@ -201,12 +205,23 @@ func main() {
201205
return tpm
202206
},
203207

208+
// Owner password
209+
func() ([]byte, error) {
210+
if askOwnerPassword {
211+
return pinentry.GetOwnerPassword()
212+
} else {
213+
ownerPassword := os.Getenv("SSH_TPM_AGENT_OWNER_PASSWORD")
214+
215+
return []byte(ownerPassword), nil
216+
}
217+
},
218+
204219
// PIN Callback
205220
func(key *key.Key) ([]byte, error) {
206221
pbytes := tpm2.New2B(key.Pubkey)
207222
keyHash := sha256.Sum256(pbytes.Bytes())
208223
keyInfo := fmt.Sprintf("ssh-tpm-agent/%x", keyHash)
209-
return pinentry.GetPinentry(keyInfo)
224+
return pinentry.GetPin(keyInfo)
210225
},
211226
)
212227

cmd/ssh-tpm-agent/main_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,9 @@ func runSSHAuth(t *testing.T, keytype tpm2.TPMAlgID, bits int, pin []byte, keyfn
140140
ag := agent.NewAgent(unixList,
141141
[]sshagent.ExtendedAgent{},
142142
// TPM Callback
143-
func() transport.TPMCloser {
144-
return tpm
145-
},
143+
func() transport.TPMCloser { return tpm },
144+
// Owner password
145+
func() ([]byte, error) { return []byte(""), nil },
146146
// PIN Callback
147147
func(_ *key.Key) ([]byte, error) {
148148
return pin, nil

cmd/ssh-tpm-keygen/main.go

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const usage = `Usage:
3131
ssh-tpm-keygen
3232
3333
Options:
34+
-o, --owner-password Ask for the owner password.
3435
-C Provide a comment with the key.
3536
-f Output keyfile.
3637
-N PIN for the key.
@@ -94,12 +95,24 @@ func getPin() []byte {
9495
}
9596
}
9697

98+
func getOwnerPassword() []byte {
99+
fmt.Printf("Enter owner password: ")
100+
password, err := term.ReadPassword(int(syscall.Stdin))
101+
fmt.Println("")
102+
if err != nil {
103+
log.Fatal(err)
104+
}
105+
106+
return password
107+
}
108+
97109
func main() {
98110
flag.Usage = func() {
99111
fmt.Println(usage)
100112
}
101113

102114
var (
115+
askOwnerPassword bool
103116
comment, outputFile, keyPin string
104117
keyType, importKey string
105118
bits int
@@ -123,6 +136,8 @@ func main() {
123136
return user.Username + "@" + host
124137
}()
125138

139+
flag.BoolVar(&askOwnerPassword, "o", false, "ask for the owner password")
140+
flag.BoolVar(&askOwnerPassword, "owner-password", false, "ask for the owner password")
126141
flag.StringVar(&comment, "C", defaultComment, "provide a comment, default to user@host")
127142
flag.StringVar(&outputFile, "f", "", "output keyfile")
128143
flag.StringVar(&keyPin, "N", "", "new pin for the key")
@@ -164,6 +179,14 @@ func main() {
164179
os.Exit(0)
165180
}
166181

182+
// Ask for owner password
183+
var ownerPassword []byte
184+
if askOwnerPassword {
185+
ownerPassword = getOwnerPassword()
186+
} else {
187+
ownerPassword = []byte("")
188+
}
189+
167190
// Generate host keys
168191
if hostKeys {
169192
// Mimics the `ssh-keygen -A -f ./something` behaviour
@@ -190,7 +213,7 @@ func main() {
190213

191214
slog.Info("Generating new host key", slog.String("algorithm", strings.ToUpper(n)))
192215

193-
k, err := key.CreateKey(tpm, t.alg, t.bits, []byte(""), defaultComment)
216+
k, err := key.CreateKey(tpm, t.alg, t.bits, ownerPassword, []byte(""), defaultComment)
194217
if err != nil {
195218
log.Fatal(err)
196219
}
@@ -275,7 +298,7 @@ func main() {
275298
}
276299
fmt.Println()
277300

278-
newkey, err := key.ChangeAuth(tpm, k, oldPin, newPin)
301+
newkey, err := key.ChangeAuth(tpm, ownerPassword, k, oldPin, newPin)
279302
if err != nil {
280303
log.Fatal("Failed changing pin on the key.")
281304
}
@@ -409,12 +432,12 @@ func main() {
409432

410433
if importKey != "" {
411434
// TODO: Read public key for comment
412-
k, err = key.ImportKey(tpm, toImportKey, pin, comment)
435+
k, err = key.ImportKey(tpm, ownerPassword, toImportKey, pin, comment)
413436
if err != nil {
414437
log.Fatal(err)
415438
}
416439
} else {
417-
k, err = key.CreateKey(tpm, tpmkeyType, bits, pin, comment)
440+
k, err = key.CreateKey(tpm, tpmkeyType, bits, ownerPassword, pin, comment)
418441
if err != nil {
419442
log.Fatal(err)
420443
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ go 1.22.0
55
require (
66
github.com/foxboron/go-tpm-keyfiles v0.0.0-20240225134915-950e719db3d9
77
github.com/foxboron/swtpm_test v0.0.0-20230726224112-46aaafdf7006
8-
github.com/google/go-tpm v0.9.1-0.20240411180339-1fb84445f623
8+
github.com/google/go-tpm v0.9.1-0.20240514145214-58e3e47cd434
99
github.com/twpayne/go-pinentry v0.3.0
1010
golang.org/x/crypto v0.21.0
1111
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ github.com/google/go-sev-guest v0.6.1 h1:NajHkAaLqN9/aW7bCFSUplUMtDgk2+HcN7jC2bt
1414
github.com/google/go-sev-guest v0.6.1/go.mod h1:UEi9uwoPbLdKGl1QHaq1G8pfCbQ4QP0swWX4J0k6r+Q=
1515
github.com/google/go-tpm v0.9.1-0.20240411180339-1fb84445f623 h1:LGYp08nFCGgxM/pRoE4etWElLB2WsrhJiBG4jK04MPE=
1616
github.com/google/go-tpm v0.9.1-0.20240411180339-1fb84445f623/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
17+
github.com/google/go-tpm v0.9.1-0.20240514145214-58e3e47cd434 h1:uPadaCeI0VnloLvthGLalr0Io0IDoI1VEQ95APzVAiw=
18+
github.com/google/go-tpm v0.9.1-0.20240514145214-58e3e47cd434/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
1719
github.com/google/go-tpm-tools v0.3.13-0.20230620182252-4639ecce2aba h1:qJEJcuLzH5KDR0gKc0zcktin6KSAwL7+jWKBYceddTc=
1820
github.com/google/go-tpm-tools v0.3.13-0.20230620182252-4639ecce2aba/go.mod h1:EFYHy8/1y2KfgTAsx7Luu7NGhoxtuVHnNo8jE7FikKc=
1921
github.com/google/logger v1.1.1 h1:+6Z2geNxc9G+4D4oDO9njjjn2d0wN5d7uOo0vOIW1NQ=

internal/keytest/keytest.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func MkECDSA(t *testing.T, a elliptic.Curve) ecdsa.PrivateKey {
3636
// Test helper for CreateKey
3737
func MkKey(t *testing.T, tpm transport.TPMCloser, keytype tpm2.TPMAlgID, bits int, pin []byte, comment string) (*key.Key, error) {
3838
t.Helper()
39-
return key.CreateKey(tpm, keytype, bits, pin, comment)
39+
return key.CreateKey(tpm, keytype, bits, []byte(""), pin, comment)
4040
}
4141

4242
// Helper to make an importable key
@@ -56,7 +56,7 @@ func MkImportableKey(t *testing.T, tpm transport.TPMCloser, keytype tpm2.TPMAlgI
5656
case tpm2.TPMAlgRSA:
5757
pk = MkRSA(t, bits)
5858
}
59-
return key.ImportKey(tpm, pk, pin, comment)
59+
return key.ImportKey(tpm, []byte(""), pk, pin, comment)
6060
}
6161

6262
// Give us some random bytes

key/key.go

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -153,13 +153,16 @@ func DecodeKey(pemBytes []byte) (*Key, error) {
153153
}
154154

155155
// Creates a Storage Key, or return the loaded storage key
156-
func CreateSRK(tpm transport.TPMCloser) (*tpm2.AuthHandle, *tpm2.TPMTPublic, error) {
156+
func CreateSRK(tpm transport.TPMCloser, ownerPassword []byte) (*tpm2.AuthHandle, *tpm2.TPMTPublic, error) {
157157
srk := tpm2.CreatePrimary{
158-
PrimaryHandle: tpm2.TPMRHOwner,
158+
PrimaryHandle: tpm2.AuthHandle{
159+
Handle: tpm2.TPMRHOwner,
160+
Auth: tpm2.PasswordAuth(ownerPassword),
161+
},
159162
InSensitive: tpm2.TPM2BSensitiveCreate{
160163
Sensitive: &tpm2.TPMSSensitiveCreate{
161164
UserAuth: tpm2.TPM2BAuth{
162-
Buffer: []byte(nil),
165+
Buffer: []byte(""),
163166
},
164167
},
165168
},
@@ -230,7 +233,7 @@ func createRSAKey(bits tpm2.TPMKeyBits, sha tpm2.TPMAlgID) tpm2.TPM2B[tpm2.TPMTP
230233
})
231234
}
232235

233-
func CreateKey(tpm transport.TPMCloser, keytype tpm2.TPMAlgID, bits int, pin []byte, comment string) (*Key, error) {
236+
func CreateKey(tpm transport.TPMCloser, keytype tpm2.TPMAlgID, bits int, ownerPassword []byte, pin []byte, comment string) (*Key, error) {
234237
rsaBits := []int{2048}
235238
ecdsaBits := []int{256, 384, 521}
236239

@@ -258,7 +261,7 @@ func CreateKey(tpm transport.TPMCloser, keytype tpm2.TPMAlgID, bits int, pin []b
258261
return nil, fmt.Errorf("unsupported key type")
259262
}
260263

261-
srkHandle, srkPublic, err := CreateSRK(tpm)
264+
srkHandle, srkPublic, err := CreateSRK(tpm, ownerPassword)
262265
if err != nil {
263266
return nil, fmt.Errorf("failed creating SRK: %v", err)
264267
}
@@ -296,8 +299,7 @@ func CreateKey(tpm transport.TPMCloser, keytype tpm2.TPMAlgID, bits int, pin []b
296299
emptyAuth = false
297300
}
298301

299-
var createRsp *tpm2.CreateResponse
300-
createRsp, err = createKey.Execute(tpm,
302+
createRsp, err := createKey.Execute(tpm,
301303
tpm2.HMAC(tpm2.TPMAlgSHA256, 16,
302304
tpm2.AESEncryption(128, tpm2.EncryptIn),
303305
tpm2.Salted(srkHandle.Handle, *srkPublic)))
@@ -315,7 +317,7 @@ func CreateKey(tpm transport.TPMCloser, keytype tpm2.TPMAlgID, bits int, pin []b
315317
return &Key{tpmkey}, nil
316318
}
317319

318-
func ImportKey(tpm transport.TPMCloser, pk any, pin []byte, comment string) (*Key, error) {
320+
func ImportKey(tpm transport.TPMCloser, ownerPassword []byte, pk any, pin []byte, comment string) (*Key, error) {
319321
var public tpm2.TPMTPublic
320322
var sensitive tpm2.TPMTSensitive
321323
var unique tpm2.TPMUPublicID
@@ -419,7 +421,7 @@ func ImportKey(tpm transport.TPMCloser, pk any, pin []byte, comment string) (*Ke
419421
return nil, fmt.Errorf("unsupported key type")
420422
}
421423

422-
srkHandle, srkPublic, err := CreateSRK(tpm)
424+
srkHandle, srkPublic, err := CreateSRK(tpm, ownerPassword)
423425
if err != nil {
424426
return nil, fmt.Errorf("failed creating SRK: %v", err)
425427
}
@@ -434,7 +436,7 @@ func ImportKey(tpm transport.TPMCloser, pk any, pin []byte, comment string) (*Ke
434436
emptyAuth = false
435437
}
436438

437-
// We need the size calcualted in the buffer, so we do this serialization dance
439+
// We need the size calculated in the buffer, so we do this serialization dance
438440
l := tpm2.Marshal(tpm2.TPM2BPrivate{Buffer: tpm2.Marshal(sensitive)})
439441

440442
pubbytes := tpm2.New2B(public)
@@ -483,8 +485,8 @@ func LoadKeyWithParent(tpm transport.TPMCloser, parent tpm2.AuthHandle, key *Key
483485
}, nil
484486
}
485487

486-
func LoadKey(tpm transport.TPMCloser, key *Key) (*tpm2.AuthHandle, error) {
487-
srkHandle, _, err := CreateSRK(tpm)
488+
func LoadKey(tpm transport.TPMCloser, ownerPassword []byte, key *Key) (*tpm2.AuthHandle, error) {
489+
srkHandle, _, err := CreateSRK(tpm, ownerPassword)
488490
if err != nil {
489491
return nil, err
490492
}
@@ -571,7 +573,7 @@ func newRSASigScheme(digest tpm2.TPMAlgID) tpm2.TPMTSigScheme {
571573
}
572574
}
573575

574-
func Sign(tpm transport.TPMCloser, key *Key, digest []byte, auth []byte, digestalg tpm2.TPMAlgID) ([]byte, error) {
576+
func Sign(tpm transport.TPMCloser, ownerPassword []byte, key *Key, digest []byte, auth []byte, digestalg tpm2.TPMAlgID) ([]byte, error) {
575577
var digestlength int
576578

577579
switch digestalg {
@@ -587,7 +589,7 @@ func Sign(tpm transport.TPMCloser, key *Key, digest []byte, auth []byte, digesta
587589
return nil, fmt.Errorf("incorrect checksum length. expected %v got %v", digestlength, len(digest))
588590
}
589591

590-
srkHandle, srkPublic, err := CreateSRK(tpm)
592+
srkHandle, srkPublic, err := CreateSRK(tpm, ownerPassword)
591593
if err != nil {
592594
return nil, fmt.Errorf("failed creating SRK: %v", err)
593595
}
@@ -649,10 +651,10 @@ func Sign(tpm transport.TPMCloser, key *Key, digest []byte, auth []byte, digesta
649651

650652
// ChangeAuth changes the object authn header to something else
651653
// notice this changes the private blob inside the key in-place.
652-
func ChangeAuth(tpm transport.TPMCloser, key *Key, oldpin, newpin []byte) (*Key, error) {
654+
func ChangeAuth(tpm transport.TPMCloser, ownerPassword []byte, key *Key, oldpin, newpin []byte) (*Key, error) {
653655
var err error
654656

655-
srkHandle, _, err := CreateSRK(tpm)
657+
srkHandle, _, err := CreateSRK(tpm, ownerPassword)
656658
if err != nil {
657659
return nil, fmt.Errorf("failed creating SRK: %v", err)
658660
}

0 commit comments

Comments
 (0)