package accesskey_test import ( "bytes" "errors" "testing" datekeys "g.activething.com/go/DateKeys" "g.activething.com/go/DateKeys/accesskey" "g.activething.com/go/DateKeys/internal/cbortest" ) // Spec §40, §57, §69.1: a .dkk reports the code of its first failing layer: // the frame (magic, framing version, FLAGS and RESERVED, BODY_LEN in 1 to // 16 MiB, the body present and nothing after it), then the type tag and the // schema version, then the CDDL, and last access_type and access_material // (keys 4 and 5), whose own code is ERR_ACCESS_INVALID. A field of the wrong // CBOR type breaks the CDDL (layer 3), not its own rule. func TestDecodePrecedence(t *testing.T) { good, _ := loadDKK(t, "time_and_key_portable") w, err := cbortest.UnmarshalMap(good[accesskey.PreludeSize:]) if err != nil { t.Fatal(err) } with := func(edit func(m map[uint64]any)) []byte { m := map[uint64]any{} for k, v := range w { m[k] = v } edit(m) b, err := cbortest.Marshal(m) if err != nil { t.Fatal(err) } return frame(b) } set := func(b []byte, i int, v byte) []byte { c := bytes.Clone(b); c[i] = v; return c } malformed := frame([]byte{0xff}) a := map[uint64]any{0: "org.example.a", 1: uint64(1)} for _, tc := range []struct { name string in []byte want error }{ {"BODY_LEN 0", frame(nil), datekeys.ErrIntegrity}, {"BODY_LEN 0 and FLAGS 1", set(frame(nil), 5, 1), datekeys.ErrInvalidFlags}, {"FLAGS 1 and a malformed body", set(malformed, 5, 1), datekeys.ErrInvalidFlags}, {"data after a malformed body", append(bytes.Clone(malformed), 0), datekeys.ErrIntegrity}, {"type tag of another schema and version 2", with(func(m map[uint64]any) { m[0], m[1] = "datekeycap", uint64(2) }), datekeys.ErrNonCanonicalCBOR}, {"version 2, unknown key and unknown access_type", with(func(m map[uint64]any) { m[1], m[9], m[4] = uint64(2), "x", "mlkem768" }), datekeys.ErrUnsupportedVersion}, {"unknown key and unknown access_type", with(func(m map[uint64]any) { m[9], m[4] = "x", "mlkem768" }), datekeys.ErrNonCanonicalCBOR}, {"extension_id in both arrays and short material", with(func(m map[uint64]any) { m[7], m[8], m[5] = []any{a}, []any{a}, make([]byte, 31) }), datekeys.ErrNonCanonicalCBOR}, {"access_type of another CBOR type", with(func(m map[uint64]any) { m[4] = uint64(1) }), datekeys.ErrNonCanonicalCBOR}, {"access_material of another CBOR type", with(func(m map[uint64]any) { m[5] = "material" }), datekeys.ErrNonCanonicalCBOR}, {"unknown access_type and short material", with(func(m map[uint64]any) { m[4], m[5] = "mlkem768", make([]byte, 31) }), datekeys.ErrAccessInvalid}, } { if _, err := accesskey.Decode(bytes.NewReader(tc.in)); !errors.Is(err, tc.want) { t.Errorf("%s: got %v, want %v", tc.name, err, tc.want) } } }