@@ -2,16 +2,23 @@ package token
22
33import (
44 "bytes"
5+ "crypto/ecdsa"
6+ "crypto/rsa"
57 "crypto/tls"
68 "encoding/json"
9+ "encoding/pem"
710 "errors"
811 "fmt"
912 "net/http"
1013 "net/url"
14+ "os"
1115 "path"
1216
17+ "github.com/google/go-tpm/legacy/tpm2"
1318 "github.com/google/uuid"
1419 "github.com/urfave/cli"
20+ "go.step.sm/crypto/pemutil"
21+ "go.step.sm/crypto/tpm/tss2"
1522
1623 "github.com/smallstep/cli-utils/errs"
1724 "github.com/smallstep/cli-utils/ui"
@@ -40,7 +47,7 @@ func createCommand() cli.Command {
4047: File to read the certificate (PEM format). This certificate must be signed by a trusted root configured in the Smallstep dashboard.
4148
4249<key-file>
43- : File to read the private key (PEM format).
50+ : File to read the private key (PEM format, TSS2-wrapped keys are supported ).
4451
4552## EXAMPLES
4653Use a certificate to get a new API token:
@@ -86,10 +93,57 @@ func createAction(ctx *cli.Context) (err error) {
8693 parsedURL .Path = path .Join (parsedURL .Path , "api/auth" )
8794 apiURL := parsedURL .String ()
8895
89- clientCert , err := tls . LoadX509KeyPair ( crtFile , keyFile )
96+ buf , err := os . ReadFile ( keyFile )
9097 if err != nil {
9198 return err
9299 }
100+ pem , _ := pem .Decode (buf )
101+
102+ var (
103+ clientCert tls.Certificate
104+ )
105+
106+ switch pem .Type {
107+ case "TSS2 PRIVATE KEY" :
108+ chain , err := pemutil .ReadCertificateBundle (crtFile )
109+ if err != nil {
110+ return err
111+ }
112+
113+ key , err := tss2 .ParsePrivateKey (pem .Bytes )
114+ if err != nil {
115+ return err
116+ }
117+
118+ raw := make ([][]byte , len (chain ))
119+ for _ , crt := range chain {
120+ raw = append (raw , crt .Raw )
121+ }
122+
123+ rw , err := tpm2 .OpenTPM ()
124+ if err != nil {
125+ return err
126+ }
127+
128+ defer rw .Close ()
129+
130+ signer , err := tss2 .CreateSigner (rw , key )
131+ if err != nil {
132+ return err
133+ }
134+
135+ clientCert = tls.Certificate {
136+ PrivateKey : signer ,
137+ Leaf : chain [0 ],
138+ Certificate : raw ,
139+ }
140+ default :
141+ clientCert , err = tls .LoadX509KeyPair (crtFile , keyFile )
142+ if err != nil {
143+ return err
144+ }
145+ }
146+
93147 b := & bytes.Buffer {}
94148 r := & createTokenReq {
95149 Bundle : clientCert .Certificate ,
@@ -115,6 +169,9 @@ func createAction(ctx *cli.Context) (err error) {
115169 GetClientCertificate : func (* tls.CertificateRequestInfo ) (* tls.Certificate , error ) {
116170 return & clientCert , nil
117171 },
172+ CipherSuites : []uint16 {
173+ tls .TLS_RSA_WITH_AES_256_GCM_SHA384 ,
174+ },
118175 MinVersion : tls .VersionTLS12 ,
119176 }
120177 client := http.Client {
0 commit comments