Skip to content

Commit c5d3578

Browse files
committed
Add test case for device attestation with step managed device ID
1 parent c2e04f4 commit c5d3578

File tree

1 file changed

+153
-40
lines changed

1 file changed

+153
-40
lines changed

acme/challenge_test.go

Lines changed: 153 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
203257
func 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) {
34993553
func 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

Comments
 (0)