• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (c) 2021, Google Inc.
2//
3// Permission to use, copy, modify, and/or distribute this software for any
4// purpose with or without fee is hereby granted, provided that the above
5// copyright notice and this permission notice appear in all copies.
6//
7// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15package subprocess
16
17import (
18	"encoding/binary"
19	"encoding/hex"
20	"encoding/json"
21	"fmt"
22)
23
24// The following structures reflect the JSON of ACVP hash tests. See
25// https://pages.nist.gov/ACVP/draft-celi-acvp-symmetric.html
26
27type xtsTestVectorSet struct {
28	Groups []xtsTestGroup `json:"testGroups"`
29}
30
31type xtsTestGroup struct {
32	ID         uint64 `json:"tgId"`
33	Type       string `json:"testType"`
34	Direction  string `json:"direction"`
35	KeyLen     int    `json:"keyLen"`
36	PayloadLen int    `json:"payloadLen"`
37	Tests      []struct {
38		ID            uint64  `json:"tcId"`
39		KeyHex        string  `json:"key"`
40		PlaintextHex  string  `json:"pt"`
41		CiphertextHex string  `json:"ct"`
42		SectorNum     *uint64 `json:"sequenceNumber"`
43		TweakHex      *string `json:"tweakValue"`
44	} `json:"tests"`
45}
46
47type xtsTestGroupResponse struct {
48	ID    uint64            `json:"tgId"`
49	Tests []xtsTestResponse `json:"tests"`
50}
51
52type xtsTestResponse struct {
53	ID            uint64 `json:"tcId"`
54	PlaintextHex  string `json:"pt,omitempty"`
55	CiphertextHex string `json:"ct,omitempty"`
56}
57
58// xts implements an ACVP algorithm by making requests to the subprocess to
59// encrypt/decrypt with AES-XTS.
60type xts struct{}
61
62func (h *xts) Process(vectorSet []byte, m Transactable) (interface{}, error) {
63	var parsed xtsTestVectorSet
64	if err := json.Unmarshal(vectorSet, &parsed); err != nil {
65		return nil, err
66	}
67
68	var ret []xtsTestGroupResponse
69	for _, group := range parsed.Groups {
70		response := xtsTestGroupResponse{
71			ID: group.ID,
72		}
73
74		if group.Type != "AFT" {
75			return nil, fmt.Errorf("unknown XTS test type %q", group.Type)
76		}
77
78		var decrypt bool
79		switch group.Direction {
80		case "encrypt":
81			decrypt = false
82		case "decrypt":
83			decrypt = true
84		default:
85			return nil, fmt.Errorf("unknown XTS direction %q", group.Direction)
86		}
87
88		funcName := "AES-XTS/" + group.Direction
89
90		for _, test := range group.Tests {
91			if group.KeyLen != len(test.KeyHex)*4/2 {
92				return nil, fmt.Errorf("test case %d/%d contains hex message of length %d but specifies a key length of %d (remember that XTS keys are twice the length of the underlying key size)", group.ID, test.ID, len(test.KeyHex), group.KeyLen)
93			}
94			key, err := hex.DecodeString(test.KeyHex)
95			if err != nil {
96				return nil, fmt.Errorf("failed to decode hex in test case %d/%d: %s", group.ID, test.ID, err)
97			}
98
99			var tweak [16]byte
100			if test.TweakHex != nil {
101				t, err := hex.DecodeString(*test.TweakHex)
102				if err != nil {
103					return nil, fmt.Errorf("failed to decode hex in test case %d/%d: %s", group.ID, test.ID, err)
104				}
105				if len(t) != len(tweak) {
106					return nil, fmt.Errorf("wrong tweak length (%d bytes) in test case %d/%d", len(t), group.ID, test.ID)
107				}
108				copy(tweak[:], t)
109			} else if test.SectorNum != nil {
110				// Sector numbers (or "sequence numbers", as NIST calls them) are turned
111				// into tweak values by encoding them in little-endian form. See IEEE
112				// 1619-2007, section 5.1.
113				binary.LittleEndian.PutUint64(tweak[:8], *test.SectorNum)
114			} else {
115				return nil, fmt.Errorf("neither sector number nor explicit tweak in test case %d/%d", group.ID, test.ID)
116			}
117
118			var msg []byte
119			if decrypt {
120				msg, err = hex.DecodeString(test.CiphertextHex)
121			} else {
122				msg, err = hex.DecodeString(test.PlaintextHex)
123			}
124
125			if err != nil {
126				return nil, fmt.Errorf("failed to decode hex in test case %d/%d: %s", group.ID, test.ID, err)
127			}
128
129			result, err := m.Transact(funcName, 1, key, msg, tweak[:])
130			if err != nil {
131				return nil, fmt.Errorf("submodule failed on test case %d/%d: %s", group.ID, test.ID, err)
132			}
133
134			testResponse := xtsTestResponse{ID: test.ID}
135			if decrypt {
136				testResponse.PlaintextHex = hex.EncodeToString(result[0])
137			} else {
138				testResponse.CiphertextHex = hex.EncodeToString(result[0])
139			}
140
141			response.Tests = append(response.Tests, testResponse)
142		}
143
144		ret = append(ret, response)
145	}
146
147	return ret, nil
148}
149