diff --git a/util/fipstools/acvp/acvptool/acvp.go b/util/fipstools/acvp/acvptool/acvp.go index 87c2f8741..f4975327b 100644 --- a/util/fipstools/acvp/acvptool/acvp.go +++ b/util/fipstools/acvp/acvptool/acvp.go @@ -178,6 +178,20 @@ func trimLeadingSlash(s string) string { return s } +// looksLikeHeaderElement returns true iff element looks like it's a header, +// not a test. Some ACVP files contain a header as the first element that +// should be duplicated into the response, and some don't. If the element +// contains a "url" field then we guess that it's a header. +func looksLikeHeaderElement(element json.RawMessage) bool { + var headerFields struct { + URL string `json:"url"` + } + if err := json.Unmarshal(element, &headerFields); err != nil { + return false + } + return len(headerFields.URL) > 0 +} + // processFile reads a file containing vector sets, at least in the format // preferred by our lab, and writes the results to stdout. func processFile(filename string, supportedAlgos []map[string]interface{}, middle Middle) error { @@ -191,11 +205,18 @@ func processFile(filename string, supportedAlgos []map[string]interface{}, middl return err } - // There must be at least a header and one vector set in the file. - if len(elements) < 2 { - return fmt.Errorf("only %d elements in JSON array", len(elements)) + // There must be at least one element in the file. + if len(elements) < 1 { + return errors.New("JSON input is empty") + } + + var header json.RawMessage + if looksLikeHeaderElement(elements[0]) { + header, elements = elements[0], elements[1:] + if len(elements) == 0 { + return errors.New("JSON input is empty") + } } - header := elements[0] // Build a map of which algorithms our Middle supports. algos := make(map[string]struct{}) @@ -213,13 +234,17 @@ func processFile(filename string, supportedAlgos []map[string]interface{}, middl var result bytes.Buffer result.WriteString("[") - headerBytes, err := json.MarshalIndent(header, "", " ") - if err != nil { - return err + + if header != nil { + headerBytes, err := json.MarshalIndent(header, "", " ") + if err != nil { + return err + } + result.Write(headerBytes) + result.WriteString(",") } - result.Write(headerBytes) - for i, element := range elements[1:] { + for i, element := range elements { var commonFields struct { Algo string `json:"algorithm"` ID uint64 `json:"vsId"` @@ -247,7 +272,9 @@ func processFile(filename string, supportedAlgos []map[string]interface{}, middl return err } - result.WriteString(",") + if i != 0 { + result.WriteString(",") + } result.Write(replyBytes) }