@@ -20,7 +20,9 @@ import (
2020 "crypto/ecdsa"
2121 "crypto/elliptic"
2222 "crypto/rsa"
23+ "crypto/x509"
2324 "encoding/asn1"
25+ "encoding/base64"
2426 "errors"
2527 "fmt"
2628 "io"
@@ -106,6 +108,21 @@ func (t *wrappedTPM20) info() (*TPMInfo, error) {
106108 return & tInfo , nil
107109}
108110
111+ // createEK creates a persistent EK given an ek template and a handle location
112+ func (t * wrappedTPM20 ) createEK (ekTemplate tpm2.Public , targetEKHandle tpmutil.Handle , rerr error ) error {
113+ keyHnd , _ , err := tpm2 .CreatePrimary (t .rwc , tpm2 .HandleEndorsement , tpm2.PCRSelection {}, "" , "" , ekTemplate )
114+ if err != nil {
115+ return fmt .Errorf ("ReadPublic failed (%v), and then CreatePrimary failed: %v" , rerr , err )
116+ }
117+ defer tpm2 .FlushContext (t .rwc , keyHnd )
118+
119+ err = tpm2 .EvictControl (t .rwc , "" , tpm2 .HandleOwner , keyHnd , targetEKHandle )
120+ if err != nil {
121+ return fmt .Errorf ("EvictControl failed: %v" , err )
122+ }
123+ return nil
124+ }
125+
109126// Return value: handle, whether we generated a new one, error.
110127func (t * wrappedTPM20 ) getEndorsementKeyHandle (ek * EK ) (tpmutil.Handle , bool , error ) {
111128 var ekHandle tpmutil.Handle
@@ -138,15 +155,9 @@ func (t *wrappedTPM20) getEndorsementKeyHandle(ek *EK) (tpmutil.Handle, bool, er
138155 }
139156 rerr := err // Preserve this failure for later logging, if needed
140157
141- keyHnd , _ , err := tpm2 .CreatePrimary (t .rwc , tpm2 .HandleEndorsement , tpm2.PCRSelection {}, "" , "" , ekTemplate )
142- if err != nil {
143- return 0 , false , fmt .Errorf ("ReadPublic failed (%v), and then CreatePrimary failed: %v" , rerr , err )
144- }
145- defer tpm2 .FlushContext (t .rwc , keyHnd )
146-
147- err = tpm2 .EvictControl (t .rwc , "" , tpm2 .HandleOwner , keyHnd , ekHandle )
158+ err = t .createEK (ekTemplate , ekHandle , rerr )
148159 if err != nil {
149- return 0 , false , fmt . Errorf ( "EvictControl failed: %v" , err )
160+ return 0 , false , err
150161 }
151162
152163 return ekHandle , true , nil
@@ -171,27 +182,112 @@ func (t *wrappedTPM20) getStorageRootKeyHandle(parent ParentKeyConfig) (tpmutil.
171182 default :
172183 return 0 , false , fmt .Errorf ("unsupported SRK algorithm: %v" , parent .Algorithm )
173184 }
174- keyHnd , _ , err := tpm2 . CreatePrimary ( t . rwc , tpm2 . HandleOwner , tpm2. PCRSelection {}, "" , "" , srkTemplate )
185+ err = t . createEK ( srkTemplate , srkHandle , rerr )
175186 if err != nil {
176- return 0 , false , fmt . Errorf ( "ReadPublic failed (%v), and then CreatePrimary failed: %v" , rerr , err )
187+ return 0 , false , err
177188 }
178- defer tpm2 .FlushContext (t .rwc , keyHnd )
189+ return srkHandle , true , nil
190+ }
179191
180- err = tpm2 .EvictControl (t .rwc , "" , tpm2 .HandleOwner , keyHnd , srkHandle )
192+ // returns the base64 encoding of the der encoding of a public key
193+ func serializePublicKey (pub crypto.PublicKey ) (string , error ) {
194+ derKey , err := x509 .MarshalPKIXPublicKey (pub )
181195 if err != nil {
182- return 0 , false , fmt . Errorf ( "EvictControl failed: %v " , err )
196+ return " " , err
183197 }
198+ return base64 .StdEncoding .EncodeToString (derKey ), nil
199+ }
184200
185- return srkHandle , true , nil
201+ // Unfortunatelly some TPMs have a non rsa2048 key in the commonRSAEkEquivalentHandle
202+ // handle location. Thus we need an alternative handle to use for both creating
203+ // and searching for the rsa2048 ek.
204+ // The "Registry-of-Reserved-TPM-2.0-Handles-and-Localities-Version 1.2" section 2.3.1
205+ // asserts that persistent EK handles should be in the range 0x8101000-0x810100FF
206+ // Thus any value in this range is acceptable, so we arbitrarily chose
207+ // a value inmediatelly after the ECC (p256) handle.
208+ const altRSAEkEquivalentHandle = commonECCEkEquivalentHandle + 1
209+
210+ // creates a map of a base64 pkcs8 encoding of public keys to handles
211+ func (t * wrappedTPM20 ) getKeyHandleKeyMap () (map [string ]tpmutil.Handle , map [tpmutil.Handle ]struct {}, error ) {
212+ key2Handle := make (map [string ]tpmutil.Handle )
213+ handleFound := make (map [tpmutil.Handle ]struct {})
214+ // The handles to searh today are the nvram locations where we expect to find keys
215+ // we could augment this list int the future, by including the equivalent of
216+ // "tpm2_getcap handles-persistent". However we want to limit the number of locations
217+ // to probe as accessing the tpm is a relatively slow path.
218+ knownHandlesToSearch := []tpmutil.Handle {
219+ commonRSAEkEquivalentHandle ,
220+ commonECCEkEquivalentHandle ,
221+ altRSAEkEquivalentHandle ,
222+ }
223+ for _ , keyHandle := range knownHandlesToSearch {
224+ pub , _ , _ , err := tpm2 .ReadPublic (t .rwc , keyHandle )
225+ if err != nil {
226+ continue
227+ }
228+ if pub .RSAParameters != nil || pub .ECCParameters != nil {
229+ key , err := pub .Key ()
230+ if err != nil {
231+ return nil , nil , fmt .Errorf ("failed to obtain public key for handle %x: %w" , keyHandle , err )
232+ }
233+ serializedKey , err := serializePublicKey (key )
234+ if err != nil {
235+ return nil , nil , fmt .Errorf ("failed to serialize public key for handle %x: %w" , keyHandle , err )
236+ }
237+ key2Handle [serializedKey ] = keyHandle
238+ handleFound [keyHandle ] = struct {}{}
239+ }
240+ }
241+ return key2Handle , handleFound , nil
242+ }
243+
244+ func (t * wrappedTPM20 ) create2048RSAEKInAvailableSlot (handleFoundMap map [tpmutil.Handle ]struct {}) (tpmutil.Handle , error ) {
245+ rsakeyHandles := []tpmutil.Handle {
246+ commonRSAEkEquivalentHandle ,
247+ altRSAEkEquivalentHandle ,
248+ }
249+ for _ , targetHandle := range rsakeyHandles {
250+ _ , handleInUse := handleFoundMap [targetHandle ]
251+ if handleInUse {
252+ continue
253+ }
254+ ekTemplate := t .rsaEkTemplate ()
255+ err := t .createEK (ekTemplate , targetHandle , fmt .Errorf ("" ))
256+ if err != nil {
257+ return tpmutil .Handle (0 ), err
258+ }
259+ return targetHandle , nil
260+ }
261+ return tpmutil .Handle (0 ), fmt .Errorf ("no available handles to create RSA 2048 key in persistent handle" )
186262}
187263
188264func (t * wrappedTPM20 ) ekCertificates () ([]EK , error ) {
189265 var res []EK
190- if rsaCert , err := readEKCertFromNVRAM20 (t .rwc , nvramRSACertIndex ); err == nil {
191- res = append (res , EK {Public : crypto .PublicKey (rsaCert .PublicKey ), Certificate : rsaCert , handle : commonRSAEkEquivalentHandle })
266+ certIndexes := []int {nvramRSACertIndex , nvramECCCertIndex }
267+ keyHandleMap , handleFoundMap , err := t .getKeyHandleKeyMap ()
268+ if err != nil {
269+ return nil , err
192270 }
193- if eccCert , err := readEKCertFromNVRAM20 (t .rwc , nvramECCCertIndex ); err == nil {
194- res = append (res , EK {Public : crypto .PublicKey (eccCert .PublicKey ), Certificate : eccCert , handle : commonECCEkEquivalentHandle })
271+ for _ , certIndex := range certIndexes {
272+ if cert , err := readEKCertFromNVRAM20 (t .rwc , tpmutil .Handle (certIndex )); err == nil {
273+ serializedKey , err := serializePublicKey (cert .PublicKey )
274+ if err != nil {
275+ return nil , err
276+ }
277+
278+ handleToUse , keyfound := keyHandleMap [serializedKey ]
279+ if ! keyfound && certIndex == nvramRSACertIndex {
280+ handleToUse , err = t .create2048RSAEKInAvailableSlot (handleFoundMap )
281+ if err != nil {
282+ return nil , err
283+ }
284+ keyfound = true
285+ }
286+ if ! keyfound {
287+ continue
288+ }
289+ res = append (res , EK {Public : crypto .PublicKey (cert .PublicKey ), Certificate : cert , handle : handleToUse })
290+ }
195291 }
196292 return res , nil
197293}
0 commit comments