@@ -200,6 +200,60 @@ func mustAttestYubikey(t *testing.T, _, keyAuthorization string, serial int) ([]
200200 return payload , leaf , ca .Root
201201}
202202
203+ type stepManagedDevice struct {
204+ DeviceID string
205+ }
206+
207+ func mustAttestStepManagedDeviceID (t * testing.T , _ , keyAuthorization , serialNumber string ) ([]byte , * x509.Certificate , * x509.Certificate ) {
208+ t .Helper ()
209+
210+ ca , err := minica .New ()
211+ require .NoError (t , err )
212+
213+ keyAuthSum := sha256 .Sum256 ([]byte (keyAuthorization ))
214+
215+ signer , err := ecdsa .GenerateKey (elliptic .P256 (), rand .Reader )
216+ require .NoError (t , err )
217+ sig , err := signer .Sign (rand .Reader , keyAuthSum [:], crypto .SHA256 )
218+ require .NoError (t , err )
219+ cborSig , err := cbor .Marshal (sig )
220+ require .NoError (t , err )
221+
222+ v , err := asn1 .Marshal (stepManagedDevice {DeviceID : serialNumber })
223+ require .NoError (t , err )
224+
225+ leaf , err := ca .Sign (& x509.Certificate {
226+ Subject : pkix.Name {CommonName : "attestation cert" },
227+ PublicKey : signer .Public (),
228+ ExtraExtensions : []pkix.Extension {
229+ {Id : oidStepManagedDevice , Value : v },
230+ },
231+ })
232+ require .NoError (t , err )
233+
234+ attObj , err := cbor .Marshal (struct {
235+ Format string `json:"fmt"`
236+ AttStatement map [string ]interface {} `json:"attStmt,omitempty"`
237+ }{
238+ Format : "step" ,
239+ AttStatement : map [string ]interface {}{
240+ "x5c" : []interface {}{leaf .Raw , ca .Intermediate .Raw },
241+ "alg" : - 7 ,
242+ "sig" : cborSig ,
243+ },
244+ })
245+ require .NoError (t , err )
246+
247+ payload , err := json .Marshal (struct {
248+ AttObj string `json:"attObj"`
249+ }{
250+ AttObj : base64 .RawURLEncoding .EncodeToString (attObj ),
251+ })
252+ require .NoError (t , err )
253+
254+ return payload , leaf , ca .Root
255+ }
256+
203257func newWireProvisionerWithOptions (t * testing.T , options * provisioner.Options ) * provisioner.ACME {
204258 t .Helper ()
205259 prov := & provisioner.ACME {
@@ -3499,9 +3553,8 @@ func Test_doAppleAttestationFormat(t *testing.T) {
34993553func Test_doStepAttestationFormat (t * testing.T ) {
35003554 ctx := context .Background ()
35013555 ca , err := minica .New ()
3502- if err != nil {
3503- t .Fatal (err )
3504- }
3556+ require .NoError (t , err )
3557+
35053558 caRoot := pem .EncodeToMemory (& pem.Block {Type : "CERTIFICATE" , Bytes : ca .Root .Raw })
35063559
35073560 makeLeaf := func (signer crypto.Signer , serialNumber []byte ) * x509.Certificate {
@@ -3512,63 +3565,63 @@ func Test_doStepAttestationFormat(t *testing.T) {
35123565 {Id : oidYubicoSerialNumber , Value : serialNumber },
35133566 },
35143567 })
3515- if err != nil {
3516- t .Fatal (err )
3517- }
3568+ require .NoError (t , err )
3569+ return leaf
3570+ }
3571+
3572+ makeLeafWithStepManagedDeviceID := func (signer crypto.Signer , serialNumber string ) * x509.Certificate {
3573+ v , err := asn1 .Marshal (stepManagedDevice {DeviceID : serialNumber })
3574+ require .NoError (t , err )
3575+ leaf , err := ca .Sign (& x509.Certificate {
3576+ Subject : pkix.Name {CommonName : "attestation cert" },
3577+ PublicKey : signer .Public (),
3578+ ExtraExtensions : []pkix.Extension {
3579+ {Id : oidStepManagedDevice , Value : v },
3580+ },
3581+ })
3582+ require .NoError (t , err )
35183583 return leaf
35193584 }
3585+
35203586 mustSigner := func (kty , crv string , size int ) crypto.Signer {
35213587 s , err := keyutil .GenerateSigner (kty , crv , size )
3522- if err != nil {
3523- t .Fatal (err )
3524- }
3588+ require .NoError (t , err )
35253589 return s
35263590 }
35273591
35283592 signer , err := ecdsa .GenerateKey (elliptic .P256 (), rand .Reader )
3529- if err != nil {
3530- t .Fatal (err )
3531- }
3593+ require .NoError (t , err )
3594+
3595+ fingerprint , err := keyutil .Fingerprint (signer .Public ())
3596+ require .NoError (t , err )
3597+
35323598 serialNumber , err := asn1 .Marshal (1234 )
3533- if err != nil {
3534- t .Fatal (err )
3535- }
3599+ require .NoError (t , err )
3600+
35363601 leaf := makeLeaf (signer , serialNumber )
3537- fingerprint , err := keyutil .Fingerprint (signer .Public ())
3538- if err != nil {
3539- t .Fatal (err )
3540- }
3602+ leafWithStepManagedDeviceID := makeLeafWithStepManagedDeviceID (signer , "1234" )
35413603
35423604 jwk , err := jose .GenerateJWK ("EC" , "P-256" , "ES256" , "sig" , "" , 0 )
3543- if err != nil {
3544- t .Fatal (err )
3545- }
3605+ require .NoError (t , err )
3606+
35463607 keyAuth , err := KeyAuthorization ("token" , jwk )
3547- if err != nil {
3548- t .Fatal (err )
3549- }
3608+ require .NoError (t , err )
3609+
35503610 keyAuthSum := sha256 .Sum256 ([]byte (keyAuth ))
35513611 sig , err := signer .Sign (rand .Reader , keyAuthSum [:], crypto .SHA256 )
3552- if err != nil {
3553- t .Fatal (err )
3554- }
3612+ require .NoError (t , err )
3613+
35553614 cborSig , err := cbor .Marshal (sig )
3556- if err != nil {
3557- t .Fatal (err )
3558- }
3615+ require .NoError (t , err )
35593616
35603617 otherSigner , err := ecdsa .GenerateKey (elliptic .P256 (), rand .Reader )
3561- if err != nil {
3562- t .Fatal (err )
3563- }
3618+ require .NoError (t , err )
3619+
35643620 otherSig , err := otherSigner .Sign (rand .Reader , keyAuthSum [:], crypto .SHA256 )
3565- if err != nil {
3566- t .Fatal (err )
3567- }
3621+ require .NoError (t , err )
3622+
35683623 otherCBORSig , err := cbor .Marshal (otherSig )
3569- if err != nil {
3570- t .Fatal (err )
3571- }
3624+ require .NoError (t , err )
35723625
35733626 type args struct {
35743627 ctx context.Context
@@ -3595,6 +3648,18 @@ func Test_doStepAttestationFormat(t *testing.T) {
35953648 Certificate : leaf ,
35963649 Fingerprint : fingerprint ,
35973650 }, false },
3651+ {"ok/step-managed-device-id" , args {ctx , mustAttestationProvisioner (t , caRoot ), & Challenge {Token : "token" }, jwk , & attestationObject {
3652+ Format : "step" ,
3653+ AttStatement : map [string ]interface {}{
3654+ "x5c" : []interface {}{leafWithStepManagedDeviceID .Raw , ca .Intermediate .Raw },
3655+ "alg" : - 7 ,
3656+ "sig" : cborSig ,
3657+ },
3658+ }}, & stepAttestationData {
3659+ SerialNumber : "1234" ,
3660+ Certificate : leafWithStepManagedDeviceID ,
3661+ Fingerprint : fingerprint ,
3662+ }, false },
35983663 {"fail yubico issuer" , args {ctx , mustAttestationProvisioner (t , nil ), & Challenge {Token : "token" }, jwk , & attestationObject {
35993664 Format : "step" ,
36003665 AttStatement : map [string ]interface {}{
@@ -4757,6 +4822,54 @@ func Test_deviceAttest01Validate(t *testing.T) {
47574822 caRoot := pem .EncodeToMemory (& pem.Block {Type : "CERTIFICATE" , Bytes : root .Raw })
47584823 ctx := NewProvisionerContext (context .Background (), mustAttestationProvisioner (t , caRoot ))
47594824
4825+ return test {
4826+ args : args {
4827+ ctx : ctx ,
4828+ jwk : jwk ,
4829+ ch : & Challenge {
4830+ ID : "chID" ,
4831+ AuthorizationID : "azID" ,
4832+ Token : "token" ,
4833+ Type : "device-attest-01" ,
4834+ Status : StatusPending ,
4835+ Value : "12345678" ,
4836+ },
4837+ payload : payload ,
4838+ db : & MockDB {
4839+ MockGetAuthorization : func (ctx context.Context , id string ) (* Authorization , error ) {
4840+ assert .Equal (t , "azID" , id )
4841+ return & Authorization {ID : "azID" }, nil
4842+ },
4843+ MockUpdateAuthorization : func (ctx context.Context , az * Authorization ) error {
4844+ fingerprint , err := keyutil .Fingerprint (leaf .PublicKey )
4845+ assert .NoError (t , err )
4846+ assert .Equal (t , "azID" , az .ID )
4847+ assert .Equal (t , fingerprint , az .Fingerprint )
4848+ return nil
4849+ },
4850+ MockUpdateChallenge : func (ctx context.Context , updch * Challenge ) error {
4851+ assert .Equal (t , "chID" , updch .ID )
4852+ assert .Equal (t , "token" , updch .Token )
4853+ assert .Equal (t , StatusValid , updch .Status )
4854+ assert .Equal (t , ChallengeType ("device-attest-01" ), updch .Type )
4855+ assert .Equal (t , "12345678" , updch .Value )
4856+ assert .Equal (t , payload , updch .Payload )
4857+ assert .Equal (t , "step" , updch .PayloadFormat )
4858+
4859+ return nil
4860+ },
4861+ },
4862+ },
4863+ wantErr : nil ,
4864+ }
4865+ },
4866+ "ok/step-managed-device-id" : func (t * testing.T ) test {
4867+ jwk , keyAuth := mustAccountAndKeyAuthorization (t , "token" )
4868+ payload , leaf , root := mustAttestStepManagedDeviceID (t , "nonce" , keyAuth , "12345678" )
4869+
4870+ caRoot := pem .EncodeToMemory (& pem.Block {Type : "CERTIFICATE" , Bytes : root .Raw })
4871+ ctx := NewProvisionerContext (context .Background (), mustAttestationProvisioner (t , caRoot ))
4872+
47604873 return test {
47614874 args : args {
47624875 ctx : ctx ,
0 commit comments