• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (c) 2020, 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	"bytes"
19	"encoding/hex"
20	"encoding/json"
21	"fmt"
22)
23
24type kasDHVectorSet struct {
25	Groups []kasDHTestGroup `json:"testGroups"`
26}
27
28type kasDHTestGroup struct {
29	ID     uint64      `json:"tgId"`
30	Type   string      `json:"testType"`
31	Role   string      `json:"kasRole"`
32	Mode   string      `json:"kasMode"`
33	Scheme string      `json:"scheme"`
34	PHex   string      `json:"p"`
35	QHex   string      `json:"q"`
36	GHex   string      `json:"g"`
37	Tests  []kasDHTest `json:"tests"`
38}
39
40type kasDHTest struct {
41	ID            uint64 `json:"tcId"`
42	PeerPublicHex string `json:"ephemeralPublicServer"`
43	PrivateKeyHex string `json:"ephemeralPrivateIut"`
44	PublicKeyHex  string `json:"ephemeralPublicIut"`
45	ResultHex     string `json:"z"`
46}
47
48type kasDHTestGroupResponse struct {
49	ID    uint64              `json:"tgId"`
50	Tests []kasDHTestResponse `json:"tests"`
51}
52
53type kasDHTestResponse struct {
54	ID             uint64 `json:"tcId"`
55	LocalPublicHex string `json:"ephemeralPublicIut,omitempty"`
56	ResultHex      string `json:"z,omitempty"`
57	Passed         *bool  `json:"testPassed,omitempty"`
58}
59
60type kasDH struct{}
61
62func (k *kasDH) Process(vectorSet []byte, m Transactable) (interface{}, error) {
63	var parsed kasDHVectorSet
64	if err := json.Unmarshal(vectorSet, &parsed); err != nil {
65		return nil, err
66	}
67
68	// See https://pages.nist.gov/ACVP/draft-hammett-acvp-kas-ffc-sp800-56ar3.html
69	var ret []kasDHTestGroupResponse
70	for _, group := range parsed.Groups {
71		response := kasDHTestGroupResponse{
72			ID: group.ID,
73		}
74
75		var privateKeyGiven bool
76		switch group.Type {
77		case "AFT":
78			privateKeyGiven = false
79		case "VAL":
80			privateKeyGiven = true
81		default:
82			return nil, fmt.Errorf("unknown test type %q", group.Type)
83		}
84
85		switch group.Role {
86		case "initiator", "responder":
87			break
88		default:
89			return nil, fmt.Errorf("unknown role %q", group.Role)
90		}
91
92		if group.Scheme != "dhEphem" {
93			return nil, fmt.Errorf("unknown scheme %q", group.Scheme)
94		}
95
96		p, err := hex.DecodeString(group.PHex)
97		if err != nil {
98			return nil, err
99		}
100
101		q, err := hex.DecodeString(group.QHex)
102		if err != nil {
103			return nil, err
104		}
105
106		g, err := hex.DecodeString(group.GHex)
107		if err != nil {
108			return nil, err
109		}
110
111		const method = "FFDH"
112		for _, test := range group.Tests {
113			if len(test.PeerPublicHex) == 0 {
114				return nil, fmt.Errorf("%d/%d is missing peer's key", group.ID, test.ID)
115			}
116
117			peerPublic, err := hex.DecodeString(test.PeerPublicHex)
118			if err != nil {
119				return nil, err
120			}
121
122			if (len(test.PrivateKeyHex) != 0) != privateKeyGiven {
123				return nil, fmt.Errorf("%d/%d incorrect private key presence", group.ID, test.ID)
124			}
125
126			if privateKeyGiven {
127				privateKey, err := hex.DecodeString(test.PrivateKeyHex)
128				if err != nil {
129					return nil, err
130				}
131
132				publicKey, err := hex.DecodeString(test.PublicKeyHex)
133				if err != nil {
134					return nil, err
135				}
136
137				expectedOutput, err := hex.DecodeString(test.ResultHex)
138				if err != nil {
139					return nil, err
140				}
141
142				result, err := m.Transact(method, 2, p, q, g, peerPublic, privateKey, publicKey)
143				if err != nil {
144					return nil, err
145				}
146
147				ok := bytes.Equal(result[1], expectedOutput)
148				response.Tests = append(response.Tests, kasDHTestResponse{
149					ID:     test.ID,
150					Passed: &ok,
151				})
152			} else {
153				result, err := m.Transact(method, 2, p, q, g, peerPublic, nil, nil)
154				if err != nil {
155					return nil, err
156				}
157
158				response.Tests = append(response.Tests, kasDHTestResponse{
159					ID:             test.ID,
160					LocalPublicHex: hex.EncodeToString(result[0]),
161					ResultHex:      hex.EncodeToString(result[1]),
162				})
163			}
164		}
165
166		ret = append(ret, response)
167	}
168
169	return ret, nil
170}
171