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