Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 
 
 
 

470 rindas
12 KiB

  1. // run_cavp.go processes CAVP input files and generates suitable response
  2. // files, optionally comparing the results against the provided FAX files.
  3. package main
  4. import (
  5. "bufio"
  6. "flag"
  7. "fmt"
  8. "os"
  9. "os/exec"
  10. "path/filepath"
  11. "runtime"
  12. "strings"
  13. "sync"
  14. "time"
  15. )
  16. var (
  17. oraclePath = flag.String("oracle-bin", "", "Path to the oracle binary")
  18. suiteDir = flag.String("suite-dir", "", "Base directory containing the CAVP test suite")
  19. noFAX = flag.Bool("no-fax", false, "Skip comparing against FAX files")
  20. )
  21. // test describes a single request file.
  22. type test struct {
  23. // inFile is the base of the filename without an extension, i.e.
  24. // “ECBMCT128”.
  25. inFile string
  26. // args are the arguments (not including the input filename) to the
  27. // oracle binary.
  28. args []string
  29. // noFAX, if true, indicates that the output cannot be compared against
  30. // the FAX file. (E.g. because the primitive is non-deterministic.)
  31. noFAX bool
  32. }
  33. // testSuite describes a series of tests that are handled by a single oracle
  34. // binary.
  35. type testSuite struct {
  36. // directory is the name of the directory in the CAVP input, i.e. “AES”.
  37. directory string
  38. // suite names the test suite to pass as the first command-line argument.
  39. suite string
  40. // faxScanFunc, if not nil, is the function to use instead of
  41. // (*bufio.Scanner).Scan. This can be used to skip lines.
  42. faxScanFunc func(*bufio.Scanner) bool
  43. tests []test
  44. }
  45. func (t *testSuite) getDirectory() string {
  46. return filepath.Join(*suiteDir, t.directory)
  47. }
  48. var aesGCMTests = testSuite{
  49. "AES_GCM",
  50. "aes_gcm",
  51. nil,
  52. []test{
  53. {"gcmDecrypt128", []string{"dec", "aes-128-gcm"}, false},
  54. {"gcmDecrypt256", []string{"dec", "aes-256-gcm"}, false},
  55. {"gcmEncryptExtIV128", []string{"enc", "aes-128-gcm"}, false},
  56. {"gcmEncryptExtIV256", []string{"enc", "aes-256-gcm"}, false},
  57. },
  58. }
  59. var aesTests = testSuite{
  60. "AES",
  61. "aes",
  62. nil,
  63. []test{
  64. {"CBCGFSbox128", []string{"kat", "aes-128-cbc"}, false},
  65. {"CBCGFSbox192", []string{"kat", "aes-192-cbc"}, false},
  66. {"CBCGFSbox256", []string{"kat", "aes-256-cbc"}, false},
  67. {"CBCKeySbox128", []string{"kat", "aes-128-cbc"}, false},
  68. {"CBCKeySbox192", []string{"kat", "aes-192-cbc"}, false},
  69. {"CBCKeySbox256", []string{"kat", "aes-256-cbc"}, false},
  70. {"CBCMMT128", []string{"kat", "aes-128-cbc"}, false},
  71. {"CBCMMT192", []string{"kat", "aes-192-cbc"}, false},
  72. {"CBCMMT256", []string{"kat", "aes-256-cbc"}, false},
  73. {"CBCVarKey128", []string{"kat", "aes-128-cbc"}, false},
  74. {"CBCVarKey192", []string{"kat", "aes-192-cbc"}, false},
  75. {"CBCVarKey256", []string{"kat", "aes-256-cbc"}, false},
  76. {"CBCVarTxt128", []string{"kat", "aes-128-cbc"}, false},
  77. {"CBCVarTxt192", []string{"kat", "aes-192-cbc"}, false},
  78. {"CBCVarTxt256", []string{"kat", "aes-256-cbc"}, false},
  79. {"ECBGFSbox128", []string{"kat", "aes-128-ecb"}, false},
  80. {"ECBGFSbox192", []string{"kat", "aes-192-ecb"}, false},
  81. {"ECBGFSbox256", []string{"kat", "aes-256-ecb"}, false},
  82. {"ECBKeySbox128", []string{"kat", "aes-128-ecb"}, false},
  83. {"ECBKeySbox192", []string{"kat", "aes-192-ecb"}, false},
  84. {"ECBKeySbox256", []string{"kat", "aes-256-ecb"}, false},
  85. {"ECBMMT128", []string{"kat", "aes-128-ecb"}, false},
  86. {"ECBMMT192", []string{"kat", "aes-192-ecb"}, false},
  87. {"ECBMMT256", []string{"kat", "aes-256-ecb"}, false},
  88. {"ECBVarKey128", []string{"kat", "aes-128-ecb"}, false},
  89. {"ECBVarKey192", []string{"kat", "aes-192-ecb"}, false},
  90. {"ECBVarKey256", []string{"kat", "aes-256-ecb"}, false},
  91. {"ECBVarTxt128", []string{"kat", "aes-128-ecb"}, false},
  92. {"ECBVarTxt192", []string{"kat", "aes-192-ecb"}, false},
  93. {"ECBVarTxt256", []string{"kat", "aes-256-ecb"}, false},
  94. // AES Monte-Carlo tests
  95. {"ECBMCT128", []string{"mct", "aes-128-ecb"}, false},
  96. {"ECBMCT192", []string{"mct", "aes-192-ecb"}, false},
  97. {"ECBMCT256", []string{"mct", "aes-256-ecb"}, false},
  98. {"CBCMCT128", []string{"mct", "aes-128-cbc"}, false},
  99. {"CBCMCT192", []string{"mct", "aes-192-cbc"}, false},
  100. {"CBCMCT256", []string{"mct", "aes-256-cbc"}, false},
  101. },
  102. }
  103. var ecdsa2KeyPairTests = testSuite{
  104. "ECDSA2",
  105. "ecdsa2_keypair",
  106. nil,
  107. []test{{"KeyPair", nil, true}},
  108. }
  109. var ecdsa2PKVTests = testSuite{
  110. "ECDSA2",
  111. "ecdsa2_pkv",
  112. nil,
  113. []test{{"PKV", nil, false}},
  114. }
  115. var ecdsa2SigGenTests = testSuite{
  116. "ECDSA2",
  117. "ecdsa2_siggen",
  118. nil,
  119. []test{
  120. {"SigGen", []string{"SigGen"}, true},
  121. {"SigGenComponent", []string{"SigGenComponent"}, true},
  122. },
  123. }
  124. var ecdsa2SigVerTests = testSuite{
  125. "ECDSA2",
  126. "ecdsa2_sigver",
  127. nil,
  128. []test{{"SigVer", nil, false}},
  129. }
  130. var rsa2KeyGenTests = testSuite{
  131. "RSA2",
  132. "rsa2_keygen",
  133. nil,
  134. []test{
  135. {"KeyGen_RandomProbablyPrime3_3", nil, true},
  136. },
  137. }
  138. var rsa2SigGenTests = testSuite{
  139. "RSA2",
  140. "rsa2_siggen",
  141. nil,
  142. []test{
  143. {"SigGen15_186-3", []string{"pkcs15"}, true},
  144. {"SigGenPSS_186-3", []string{"pss"}, true},
  145. },
  146. }
  147. var rsa2SigVerTests = testSuite{
  148. "RSA2",
  149. "rsa2_sigver",
  150. func(s *bufio.Scanner) bool {
  151. for {
  152. if !s.Scan() {
  153. return false
  154. }
  155. line := s.Text()
  156. if strings.HasPrefix(line, "p = ") || strings.HasPrefix(line, "d = ") || strings.HasPrefix(line, "SaltVal = ") || strings.HasPrefix(line, "EM with ") {
  157. continue
  158. }
  159. if strings.HasPrefix(line, "q = ") {
  160. // Skip the "q = " line and an additional blank line.
  161. if !s.Scan() {
  162. return false
  163. }
  164. if len(strings.TrimSpace(s.Text())) > 0 {
  165. return false
  166. }
  167. continue
  168. }
  169. return true
  170. }
  171. },
  172. []test{
  173. {"SigVer15_186-3", []string{"pkcs15"}, false},
  174. {"SigVerPSS_186-3", []string{"pss"}, false},
  175. },
  176. }
  177. var hmacTests = testSuite{
  178. "HMAC",
  179. "hmac",
  180. nil,
  181. []test{{"HMAC", nil, false}},
  182. }
  183. var shaTests = testSuite{
  184. "SHA",
  185. "sha",
  186. nil,
  187. []test{
  188. {"SHA1LongMsg", []string{"SHA1"}, false},
  189. {"SHA1ShortMsg", []string{"SHA1"}, false},
  190. {"SHA224LongMsg", []string{"SHA224"}, false},
  191. {"SHA224ShortMsg", []string{"SHA224"}, false},
  192. {"SHA256LongMsg", []string{"SHA256"}, false},
  193. {"SHA256ShortMsg", []string{"SHA256"}, false},
  194. {"SHA384LongMsg", []string{"SHA384"}, false},
  195. {"SHA384ShortMsg", []string{"SHA384"}, false},
  196. {"SHA512LongMsg", []string{"SHA512"}, false},
  197. {"SHA512ShortMsg", []string{"SHA512"}, false},
  198. },
  199. }
  200. var shaMonteTests = testSuite{
  201. "SHA",
  202. "sha_monte",
  203. nil,
  204. []test{
  205. {"SHA1Monte", []string{"SHA1"}, false},
  206. {"SHA224Monte", []string{"SHA224"}, false},
  207. {"SHA256Monte", []string{"SHA256"}, false},
  208. {"SHA384Monte", []string{"SHA384"}, false},
  209. {"SHA512Monte", []string{"SHA512"}, false},
  210. },
  211. }
  212. var ctrDRBGTests = testSuite{
  213. "DRBG800-90A",
  214. "ctr_drbg",
  215. nil,
  216. []test{{"CTR_DRBG", nil, false}},
  217. }
  218. var tdesTests = testSuite{
  219. "TDES",
  220. "tdes",
  221. nil,
  222. []test{
  223. {"TCBCMMT2", []string{"kat", "des-ede-cbc"}, false},
  224. {"TCBCMMT3", []string{"kat", "des-ede3-cbc"}, false},
  225. {"TCBCMonte2", []string{"mct", "des-ede3-cbc"}, false},
  226. {"TCBCMonte3", []string{"mct", "des-ede3-cbc"}, false},
  227. {"TCBCinvperm", []string{"kat", "des-ede3-cbc"}, false},
  228. {"TCBCpermop", []string{"kat", "des-ede3-cbc"}, false},
  229. {"TCBCsubtab", []string{"kat", "des-ede3-cbc"}, false},
  230. {"TCBCvarkey", []string{"kat", "des-ede3-cbc"}, false},
  231. {"TCBCvartext", []string{"kat", "des-ede3-cbc"}, false},
  232. {"TECBMMT2", []string{"kat", "des-ede"}, false},
  233. {"TECBMMT3", []string{"kat", "des-ede3"}, false},
  234. {"TECBMonte2", []string{"mct", "des-ede3"}, false},
  235. {"TECBMonte3", []string{"mct", "des-ede3"}, false},
  236. {"TECBinvperm", []string{"kat", "des-ede3"}, false},
  237. {"TECBpermop", []string{"kat", "des-ede3"}, false},
  238. {"TECBsubtab", []string{"kat", "des-ede3"}, false},
  239. {"TECBvarkey", []string{"kat", "des-ede3"}, false},
  240. {"TECBvartext", []string{"kat", "des-ede3"}, false},
  241. },
  242. }
  243. var keyWrapTests = testSuite{
  244. "KeyWrap38F",
  245. "keywrap",
  246. nil,
  247. []test{
  248. {"KW_AD_128", []string{"dec", "128"}, false},
  249. {"KW_AD_256", []string{"dec", "256"}, false},
  250. {"KW_AE_128", []string{"enc", "128"}, false},
  251. {"KW_AE_256", []string{"enc", "256"}, false},
  252. },
  253. }
  254. var allTestSuites = []*testSuite{
  255. &aesGCMTests,
  256. &aesTests,
  257. &ctrDRBGTests,
  258. &ecdsa2KeyPairTests,
  259. &ecdsa2PKVTests,
  260. &ecdsa2SigGenTests,
  261. &ecdsa2SigVerTests,
  262. &hmacTests,
  263. &keyWrapTests,
  264. &rsa2KeyGenTests,
  265. &rsa2SigGenTests,
  266. &rsa2SigVerTests,
  267. &shaTests,
  268. &shaMonteTests,
  269. &tdesTests,
  270. }
  271. // testInstance represents a specific test in a testSuite.
  272. type testInstance struct {
  273. suite *testSuite
  274. testIndex int
  275. }
  276. func worker(wg *sync.WaitGroup, work <-chan testInstance) {
  277. defer wg.Done()
  278. for ti := range work {
  279. test := ti.suite.tests[ti.testIndex]
  280. if err := doTest(ti.suite, test); err != nil {
  281. fmt.Fprintf(os.Stderr, "%s\n", err)
  282. os.Exit(2)
  283. }
  284. if !*noFAX && !test.noFAX {
  285. if err := compareFAX(ti.suite, test); err != nil {
  286. fmt.Fprintf(os.Stderr, "%s\n", err)
  287. os.Exit(3)
  288. }
  289. }
  290. }
  291. }
  292. func main() {
  293. flag.Parse()
  294. if len(*oraclePath) == 0 {
  295. fmt.Fprintf(os.Stderr, "Must give -oracle-bin\n")
  296. os.Exit(1)
  297. }
  298. work := make(chan testInstance)
  299. var wg sync.WaitGroup
  300. for i := 0; i < runtime.NumCPU(); i++ {
  301. wg.Add(1)
  302. go worker(&wg, work)
  303. }
  304. for _, suite := range allTestSuites {
  305. for i := range suite.tests {
  306. work <- testInstance{suite, i}
  307. }
  308. }
  309. close(work)
  310. wg.Wait()
  311. }
  312. func doTest(suite *testSuite, test test) error {
  313. args := []string{suite.suite}
  314. args = append(args, test.args...)
  315. args = append(args, filepath.Join(suite.getDirectory(), "req", test.inFile+".req"))
  316. respDir := filepath.Join(suite.getDirectory(), "resp")
  317. if err := os.Mkdir(respDir, 0755); err != nil && !os.IsExist(err) {
  318. return fmt.Errorf("cannot create resp directory: %s", err)
  319. }
  320. outPath := filepath.Join(respDir, test.inFile+".rsp")
  321. outFile, err := os.OpenFile(outPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
  322. if err != nil {
  323. return fmt.Errorf("cannot open output file for %q %q: %s", suite.getDirectory(), test.inFile, err)
  324. }
  325. defer outFile.Close()
  326. cmd := exec.Command(*oraclePath, args...)
  327. cmd.Stdout = outFile
  328. cmd.Stderr = os.Stderr
  329. cmdLine := strings.Join(append([]string{*oraclePath}, args...), " ")
  330. startTime := time.Now()
  331. if err := cmd.Run(); err != nil {
  332. return fmt.Errorf("cannot run command for %q %q (%s): %s", suite.getDirectory(), test.inFile, cmdLine, err)
  333. }
  334. fmt.Printf("%s (%ds)\n", cmdLine, int(time.Since(startTime).Seconds()))
  335. return nil
  336. }
  337. func canonicalizeLine(in string) string {
  338. if strings.HasPrefix(in, "Result = P (") {
  339. return "Result = P"
  340. }
  341. if strings.HasPrefix(in, "Result = F (") {
  342. return "Result = F"
  343. }
  344. return in
  345. }
  346. func compareFAX(suite *testSuite, test test) error {
  347. faxScanFunc := suite.faxScanFunc
  348. if faxScanFunc == nil {
  349. faxScanFunc = (*bufio.Scanner).Scan
  350. }
  351. respPath := filepath.Join(suite.getDirectory(), "resp", test.inFile+".rsp")
  352. respFile, err := os.Open(respPath)
  353. if err != nil {
  354. return fmt.Errorf("cannot read output of %q %q: %s", suite.getDirectory(), test.inFile, err)
  355. }
  356. defer respFile.Close()
  357. faxPath := filepath.Join(suite.getDirectory(), "fax", test.inFile+".fax")
  358. faxFile, err := os.Open(faxPath)
  359. if err != nil {
  360. return fmt.Errorf("cannot open fax file for %q %q: %s", suite.getDirectory(), test.inFile, err)
  361. }
  362. defer faxFile.Close()
  363. respScanner := bufio.NewScanner(respFile)
  364. faxScanner := bufio.NewScanner(faxFile)
  365. lineNo := 0
  366. inHeader := true
  367. for respScanner.Scan() {
  368. lineNo++
  369. respLine := respScanner.Text()
  370. var faxLine string
  371. if inHeader && (len(respLine) == 0 || respLine[0] == '#') {
  372. continue
  373. }
  374. for {
  375. haveFaxLine := false
  376. if inHeader {
  377. for faxScanFunc(faxScanner) {
  378. faxLine = faxScanner.Text()
  379. if len(faxLine) != 0 && faxLine[0] != '#' {
  380. haveFaxLine = true
  381. break
  382. }
  383. }
  384. inHeader = false
  385. } else {
  386. if faxScanFunc(faxScanner) {
  387. faxLine = faxScanner.Text()
  388. haveFaxLine = true
  389. }
  390. }
  391. if !haveFaxLine {
  392. // Ignore blank lines at the end of the generated file.
  393. if len(respLine) == 0 {
  394. break
  395. }
  396. return fmt.Errorf("resp file is longer than fax for %q %q", suite.getDirectory(), test.inFile)
  397. }
  398. if strings.HasPrefix(faxLine, " (Reason: ") {
  399. continue
  400. }
  401. break
  402. }
  403. if canonicalizeLine(faxLine) == canonicalizeLine(respLine) {
  404. continue
  405. }
  406. return fmt.Errorf("resp and fax differ at line %d for %q %q: %q vs %q", lineNo, suite.getDirectory(), test.inFile, respLine, faxLine)
  407. }
  408. if faxScanFunc(faxScanner) {
  409. return fmt.Errorf("fax file is longer than resp for %q %q", suite.getDirectory(), test.inFile)
  410. }
  411. return nil
  412. }