1c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin/* Copyright (c) 2016, Google Inc. 2c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin * 3c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin * Permission to use, copy, modify, and/or distribute this software for any 4c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin * purpose with or without fee is hereby granted, provided that the above 5c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin * copyright notice and this permission notice appear in all copies. 6c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin * 7c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin 15c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjaminpackage main 16c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin 17c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjaminimport ( 18c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin "flag" 19c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin "fmt" 20c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin "os" 21c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin "os/exec" 22c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin "path/filepath" 23c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin "strings" 24c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin "syscall" 25c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin) 26c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin 27c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjaminvar ( 28c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin boringsslDir = flag.String("boringssl", ".", "The path to the BoringSSL checkout.") 29c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin opensslDir = flag.String("openssl", filepath.Join("..", "openssl"), "The path to the OpenSSL checkout.") 30c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin) 31c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin 32c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjaminfunc mapName(path string) string { 33572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan path = strings.Replace(path, filepath.FromSlash("/fipsmodule/"), string(filepath.Separator), 1) 34c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin switch filepath.ToSlash(path) { 358ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan case "crypto/cipher_extra/asm/aes128gcmsiv-x86_64.pl", "crypto/cipher_extra/asm/chacha20_poly1305_x86_64.pl", "crypto/rand/asm/rdrand-x86_64.pl": 36c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin return "" 37c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin case "crypto/ec/asm/p256-x86_64-asm.pl": 38c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin return filepath.FromSlash("crypto/ec/asm/ecp_nistz256-x86_64.pl") 39c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin } 40c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin return path 41c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin} 42c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin 43c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjaminfunc diff(from, to string) error { 44c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin cmd := exec.Command("diff", "-u", "--", from, to) 45c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin cmd.Stdout = os.Stdout 46c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin cmd.Stderr = os.Stderr 47c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin err := cmd.Run() 48c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin // diff returns exit code 1 if the files differ but it was otherwise 49c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin // successful. 50c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin if exitError, ok := err.(*exec.ExitError); ok && exitError.Sys().(syscall.WaitStatus).ExitStatus() == 1 { 51c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin return nil 52c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin } 53c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin return err 54c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin} 55c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin 56c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjaminfunc main() { 57c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin flag.Usage = func() { 58c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin fmt.Fprintf(os.Stderr, "Usage: diff_asm [flag...] [filter...]\n") 59c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin fmt.Fprintf(os.Stderr, "Filter arguments limit to assembly files which match arguments.\n") 60c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin fmt.Fprintf(os.Stderr, "If not using a filter, piping to `diffstat` may be useful.\n\n") 61c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin flag.PrintDefaults() 62c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin } 63c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin flag.Parse() 64c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin 65c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin // Find all the assembly files. 66c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin var files []string 67c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin err := filepath.Walk(*boringsslDir, func(path string, info os.FileInfo, err error) error { 68c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin if err != nil { 69c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin return nil 70c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin } 71c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin 72c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin path, err = filepath.Rel(*boringsslDir, path) 73c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin if err != nil { 74c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin return err 75c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin } 76c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin 77c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin dir := filepath.Base(filepath.Dir(path)) 78c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin if !info.IsDir() && (dir == "asm" || dir == "perlasm") && strings.HasSuffix(filepath.Base(path), ".pl") { 79c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin files = append(files, path) 80c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin } 81c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin 82c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin return nil 83c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin }) 84c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin if err != nil { 85c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin fmt.Fprintf(os.Stderr, "Error finding assembly: %s\n", err) 86c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin os.Exit(1) 87c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin } 88c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin 89c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin for _, file := range files { 90c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin opensslFile := mapName(file) 91c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin if len(opensslFile) == 0 { 92c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin continue 93c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin } 94c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin 95c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin if flag.NArg() > 0 { 96c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin var found bool 97c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin for _, arg := range flag.Args() { 98c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin if strings.Contains(file, arg) { 99c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin found = true 100c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin break 101c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin } 102c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin } 103c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin if !found { 104c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin continue 105c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin } 106c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin } 107c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin 108c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin if err := diff(filepath.Join(*opensslDir, opensslFile), filepath.Join(*boringsslDir, file)); err != nil { 109c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin fmt.Fprintf(os.Stderr, "Error comparing %s: %s\n", file, err) 110c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin os.Exit(1) 111c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin } 112c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin } 113c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin} 114