acvp: handle more private key formats.

This change adds a config parameter PrivateKeyFile (to replace
PrivateKeyDERFile, although that still exists) because taking PKCS#1 DER
is a little odd for people. Also probe for PEM/DER and PKCS#1/8
automatically to try and work with whatever private key the user has.

Change-Id: I0f4efcd79528cfb26f791e9ee8c5141fc6a93723
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/43344
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/util/fipstools/acvp/ACVP.md b/util/fipstools/acvp/ACVP.md
index ddae4ed..71501de 100644
--- a/util/fipstools/acvp/ACVP.md
+++ b/util/fipstools/acvp/ACVP.md
@@ -13,14 +13,14 @@
 {
         "ACVPServer": "https://demo.acvts.nist.gov/",
         "CertPEMFile": "certificate_from_nist.pem",
-        "PrivateKeyDERFile": "your_private_key.key",
+        "PrivateKeyFile": "your_private_key.key",
         "TOTPSecret": "<base64 from NIST goes here>",
         "SessionTokensCache": "~/.cache/acvp-session-tokens",
         "LogFile": "log"
 }
 ```
 
-NIST's ACVP servers use both TLS client certificates and TOTP for authentication. When registering with NIST, they'll sign a CSR and return a certificate in PEM format, which is pointed to be `CertPEMFile`. The corresponding PKCS#1, DER-encoded private key is expected in `PrivateKeyDERFile`. Lastly, NIST will provide a file that contains the base64-encoded TOTP seed, which must be pasted in as the value of `TOTPSecret`.
+NIST's ACVP servers use both TLS client certificates and TOTP for authentication. When registering with NIST, they'll sign a CSR and return a certificate in PEM format, which is pointed to be `CertPEMFile`. The corresponding private key is expected in `PrivateKeyFile`. Lastly, NIST will provide a file that contains the base64-encoded TOTP seed, which must be pasted in as the value of `TOTPSecret`.
 
 NIST's ACVP server provides special access tokens for each test session and test sessions can _only_ be accessed via those tokens. The reasoning behind this is unclear but this client can, optionally, keep records of these access tokens in the directory named by `SessionTokensCache`. If that directory name begins with `~/` then that prefix will be replaced with the value of `$HOME`.
 
diff --git a/util/fipstools/acvp/acvptool/acvp.go b/util/fipstools/acvp/acvptool/acvp.go
index feebed5..bc8b0d8 100644
--- a/util/fipstools/acvp/acvptool/acvp.go
+++ b/util/fipstools/acvp/acvptool/acvp.go
@@ -17,6 +17,7 @@
 import (
 	"bufio"
 	"bytes"
+	"crypto"
 	"crypto/hmac"
 	"crypto/sha256"
 	"crypto/x509"
@@ -51,6 +52,7 @@
 
 type Config struct {
 	CertPEMFile        string
+	PrivateKeyFile     string
 	PrivateKeyDERFile  string
 	TOTPSecret         string
 	ACVPServer         string
@@ -281,17 +283,35 @@
 	block, _ := pem.Decode(certPEM)
 	certDER := block.Bytes
 
-	if len(config.PrivateKeyDERFile) == 0 {
-		log.Fatal("Config file missing PrivateKeyDERFile")
+	if len(config.PrivateKeyDERFile) == 0 && len(config.PrivateKeyFile) == 0 {
+		log.Fatal("Config file missing PrivateKeyDERFile and PrivateKeyFile")
 	}
-	keyDER, err := ioutil.ReadFile(config.PrivateKeyDERFile)
-	if err != nil {
-		log.Fatalf("failed to read private key from %q: %s", config.PrivateKeyDERFile, err)
+	if len(config.PrivateKeyDERFile) != 0 && len(config.PrivateKeyFile) != 0 {
+		log.Fatal("Config file has both PrivateKeyDERFile and PrivateKeyFile. Can only have one.")
+	}
+	privateKeyFile := config.PrivateKeyDERFile
+	if len(config.PrivateKeyFile) > 0 {
+		privateKeyFile = config.PrivateKeyFile
 	}
 
-	certKey, err := x509.ParsePKCS1PrivateKey(keyDER)
+	keyBytes, err := ioutil.ReadFile(privateKeyFile)
 	if err != nil {
-		log.Fatalf("failed to parse private key from %q: %s", config.PrivateKeyDERFile, err)
+		log.Fatalf("failed to read private key from %q: %s", privateKeyFile, err)
+	}
+
+	var keyDER []byte
+	pemBlock, _ := pem.Decode(keyBytes)
+	if pemBlock != nil {
+		keyDER = pemBlock.Bytes
+	} else {
+		keyDER = keyBytes
+	}
+
+	var certKey crypto.PrivateKey
+	if certKey, err = x509.ParsePKCS1PrivateKey(keyDER); err != nil {
+		if certKey, err = x509.ParsePKCS8PrivateKey(keyDER); err != nil {
+			log.Fatalf("failed to parse private key from %q: %s", privateKeyFile, err)
+		}
 	}
 
 	var middle Middle