// Copyright (c) 2017, Google Inc. // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // The make_nist_aesvs_kat_tests utility converts a Known Answer Test // (KAT) files from the NIST CAVP AES Validation Suite (AESVS) into a // format that can be consumed by cipher_test. // // The AESVS specification can be found at // http://csrc.nist.gov/groups/STM/cavp/documents/aes/AESAVS.pdf. // // The KAT vectors are located at // http://csrc.nist.gov/groups/STM/cavp/documents/aes/KAT_AES.zip // (linked from // http://csrc.nist.gov/groups/STM/cavp/block-ciphers.html). package main import ( "bufio" "flag" "fmt" "io" "log" "os" "strings" ) var ( inFile = flag.String("in", "", "The input file name.") cmdLineLabelStr = flag.String("extra-labels", "", "Comma-separated list of additional label pairs to add (e.g. 'Cipher=AES-128-CBC,Operation=ENCRYPT')") swapIVAndPlaintext = flag.Bool("swap-iv-plaintext", false, "When processing CBC vector files for CTR mode, swap IV and plaintext.") ) // The character to delimit key-value pairs throughout the file ('=' or ':'). var kvDelim rune func parseKeyValue(s string) (key, value string) { if kvDelim == 0 { i := strings.IndexAny(s, "=:") if i != -1 { kvDelim = rune(s[i]) } } if i := strings.IndexRune(s, kvDelim); kvDelim != 0 && i != -1 { key, value = s[:i], s[i+1:] } else { key = s } return strings.TrimSpace(key), strings.TrimSpace(value) } type kvPair struct { key, value string } var kvTranslations = map[kvPair]kvPair{ {"ENCRYPT", ""}: {"Operation", "ENCRYPT"}, {"DECRYPT", ""}: {"Operation", "DECRYPT"}, {"COUNT", ""}: {"Count", ""}, {"KEY", ""}: {"Key", ""}, {"PLAINTEXT", ""}: {"Plaintext", ""}, {"CIPHERTEXT", ""}: {"Ciphertext", ""}, {"COUNT", ""}: {"", ""}, // delete } func translateKeyValue(key, value string) (string, string) { if t, ok := kvTranslations[kvPair{key, ""}]; ok { if len(t.value) == 0 && len(value) != 0 { return t.key, value } return t.key, t.value } if t, ok := kvTranslations[kvPair{key, value}]; ok { return t.key, t.value } return key, value } func printKeyValue(key, value string) { if len(value) == 0 { fmt.Println(key) } else { fmt.Printf("%s: %s\n", key, value) } } func generateTest(r io.Reader) { s := bufio.NewScanner(r) // Label blocks consist of lines of the form "[key]" or "[key = // value]". |labels| holds keys and values of the most recent block // of labels. var labels map[string]string // Auxiliary labels passed as a flag. cmdLineLabels := make(map[string]string) if len(*cmdLineLabelStr) != 0 { pairs := strings.Split(*cmdLineLabelStr, ",") for _, p := range pairs { key, value := parseKeyValue(p) cmdLineLabels[key] = value } } kvDelim = 0 // Whether we are in a test or a label section. inLabels := false inTest := false n := 0 for s.Scan() { n++ line := s.Text() l := strings.TrimSpace(line) l = strings.SplitN(l, "#", 2)[0] // Trim trailing comments. // Blank line. if len(l) == 0 { if inTest { fmt.Println() } inTest = false inLabels = false continue } // Label section. if l[0] == '[' { if l[len(l)-1] != ']' { log.Fatalf("line #%d invalid: %q", n, line) } if !inLabels { labels = make(map[string]string) inLabels = true } k, v := parseKeyValue(l[1 : len(l)-1]) k, v = translateKeyValue(k, v) if len(k) != 0 { labels[k] = v } continue } // Repeat the label map at the beginning of each test section. if !inTest { inTest = true for k, v := range cmdLineLabels { printKeyValue(k, v) } for k, v := range labels { printKeyValue(k, v) } } k, v := parseKeyValue(l) k, v = translateKeyValue(k, v) if len(k) != 0 { printKeyValue(k, v) } } } func main() { flag.Parse() if *swapIVAndPlaintext { kvTranslations[kvPair{"PLAINTEXT", ""}] = kvPair{"IV", ""} kvTranslations[kvPair{"IV", ""}] = kvPair{"Plaintext", ""} } if len(*inFile) == 0 { fmt.Fprintln(os.Stderr, "-in required") flag.Usage() os.Exit(1) } f, err := os.Open(*inFile) if err != nil { log.Fatal(err) } defer f.Close() args := append([]string{"make_nist_aesvs_kat_tests"}, os.Args[1:]...) fmt.Printf("# Generated by %q\n\n", strings.Join(args, " ")) generateTest(f) }