From 7a75c624c6b592b5116458b6a721e1affaab3a48 Mon Sep 17 00:00:00 2001 From: Tim Trippel Date: Sat, 28 Sep 2024 18:14:55 -0700 Subject: [PATCH] [spmutil] add KDF seed loading subcommands This adds KDF seed loading subcommands to support the KDF operations that will be used to generate OpenTitan Earlgrey LC tokens and Wafer Auth Secrets during provisioning. This partially addresses #4. Signed-off-by: Tim Trippel --- docs/spm.md | 16 ++++++++-- run_integration_tests.sh | 8 ++++- src/pk11/kdf.go | 1 + src/spm/spmutil.go | 69 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 90 insertions(+), 4 deletions(-) diff --git a/docs/spm.md b/docs/spm.md index 1c00288..014ad9f 100644 --- a/docs/spm.md +++ b/docs/spm.md @@ -101,7 +101,13 @@ $ bazelisk run //src/spm:spmutil -- \ --hsm_so=${OPENTITAN_VAR_DIR}/softhsm2/libsofthsm2.so \ --hsm_type=0 \ --hsm_slot=0 \ - --force_keygen --gen_kg --gen_kca \ + --force_keygen \ + --gen_kg \ + --gen_kca \ + --load_low_sec_ks \ + --low_sec_ks="0x23df79a8052010ef6e3d49255b606f871cff06170247c1145ebb71ad23834061" \ + --load_high_sec_ks \ + --high_sec_ks="0xaba9d5616e5a7c18b9a41d8a22f42d4dc3bafa9ca1fad01e404e708b1eab21fd" \ --ca_outfile=${OPENTITAN_VAR_DIR}/spm/config/certs/NuvotonTPMRootCA0200.cer ``` @@ -114,7 +120,13 @@ $ bazelisk run //src/spm:spmutil -- \ --hsm_so=/usr/safenet/lunaclient/lib/libCryptoki2_64.so \ --hsm_type=1 \ --hsm_slot=0 \ - --force_keygen --gen_kg --gen_kca \ + --force_keygen \ + --gen_kg \ + --gen_kca \ + --load_low_sec_ks \ + --low_sec_ks="0x23df79a8052010ef6e3d49255b606f871cff06170247c1145ebb71ad23834061" \ + --load_high_sec_ks \ + --high_sec_ks="0xaba9d5616e5a7c18b9a41d8a22f42d4dc3bafa9ca1fad01e404e708b1eab21fd" \ --ca_outfile=${OPENTITAN_VAR_DIR}/spm/config/certs/NuvotonTPMRootCA0200.cer ``` diff --git a/run_integration_tests.sh b/run_integration_tests.sh index 47ada68..19b448c 100755 --- a/run_integration_tests.sh +++ b/run_integration_tests.sh @@ -32,7 +32,13 @@ bazelisk run //src/spm:spmutil -- \ --hsm_so=${OPENTITAN_VAR_DIR}/softhsm2/libsofthsm2.so \ --hsm_type=0 \ --hsm_slot=0 \ - --force_keygen --gen_kg --gen_kca \ + --force_keygen \ + --gen_kg \ + --gen_kca \ + --load_low_sec_ks \ + --low_sec_ks="0x23df79a8052010ef6e3d49255b606f871cff06170247c1145ebb71ad23834061" \ + --load_high_sec_ks \ + --high_sec_ks="0xaba9d5616e5a7c18b9a41d8a22f42d4dc3bafa9ca1fad01e404e708b1eab21fd" \ --ca_outfile=${OPENTITAN_VAR_DIR}/spm/config/certs/NuvotonTPMRootCA0200.cer bazelisk run //src/pa:loadtest -- \ diff --git a/src/pk11/kdf.go b/src/pk11/kdf.go index 75ca3b1..066e5d8 100644 --- a/src/pk11/kdf.go +++ b/src/pk11/kdf.go @@ -222,6 +222,7 @@ func (s *Session) ImportKeyMaterial(key []byte, opts *KeyOptions) (SecretKey, er pkcs11.NewAttribute(pkcs11.CKA_DERIVE, true), pkcs11.NewAttribute(pkcs11.CKA_SENSITIVE, !opts.Extractable), pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, opts.Extractable), + pkcs11.NewAttribute(pkcs11.CKA_TOKEN, opts.Token), } s.tok.m.appendAttrKeyID(&tpl) diff --git a/src/spm/spmutil.go b/src/spm/spmutil.go index edf1b53..3013e4a 100644 --- a/src/spm/spmutil.go +++ b/src/spm/spmutil.go @@ -10,6 +10,7 @@ import ( "crypto/elliptic" "crypto/x509" "crypto/x509/pkix" + "encoding/hex" "errors" "flag" "fmt" @@ -31,13 +32,19 @@ var ( hsmSlot = flag.Int("hsm_slot", 0, "The HSM slot number; required") genKG = flag.Bool("gen_kg", false, "Generate KG; optional") genKCA = flag.Bool("gen_kca", false, "Generate KCA; optional") - forceKeygen = flag.Bool("force_keygen", false, "Destroy existing keys before keygen; optional") + loadHighSecKS = flag.Bool("load_high_sec_ks", false, "Load high security KDF seed; optional") + loadLowSecKS = flag.Bool("load_low_sec_ks", false, "Load low security KDF seed; optional") + forceKeygen = flag.Bool("force_keygen", false, "Destroy existing keys and seeds before keygen; optional") caCertOutputPath = flag.String("ca_outfile", "", "CA output path; required when --gen_kca is set to true") + highSecKS = flag.String("high_sec_ks", "", "High security key seed; required when --load_high_sec_ks is set to true") + lowSecKS = flag.String("low_sec_ks", "", "Low security key seed; required when --load_low_sec_ks is set to true") version = flag.Bool("version", false, "Print version information and exit") ) const ( kgName = "KG" + hsksName = "HighSecKdfSeed" + lsksName = "LowSecKdfSeed" kcaPrivName = "KCAPriv" kcaPubName = "KCAPub" ) @@ -60,6 +67,8 @@ func DestroyKeys(session *pk11.Session) error { label string }{ {pk11.ClassSecretKey, kgName}, + {pk11.ClassSecretKey, hsksName}, + {pk11.ClassSecretKey, lsksName}, {pk11.ClassPrivateKey, kcaPrivName}, {pk11.ClassPublicKey, kcaPubName}, } @@ -101,6 +110,62 @@ func GenerateKG(session *pk11.Session) error { return nil } +// loadKdfSeed loads a secret seed that may be used to derive symmetric keys +// from during the provisioning flow. +func loadKdfSeed(session *pk11.Session, seedName string, seed []byte) error { + // Skip seed load if there is a seed with the same name already available. + if _, err := session.FindKeyByLabel(pk11.ClassSecretKey, seedName); err == nil { + log.Printf("KDF seed with label %q already exists.", seedName) + return nil + } + + // Load the seed into the HSM. + kdfSeed, err := session.ImportKeyMaterial(seed, &pk11.KeyOptions{ + Extractable: true, + Token: true, + }) + if err != nil { + return fmt.Errorf("failed to load KDF seed, error: %v", err) + } + + // Set a label name on the seed. + if err := kdfSeed.SetLabel(seedName); err != nil { + return fmt.Errorf("failed to set KDF seed label %q, error: %v", seedName, err) + } + + return nil +} + +// LoadHighSecKdfSeed loads a high security secret seed that may be used to +// derive symmetric keys from during the provisioning flow. This seed is +// expected to be rotated frequently. +func LoadHighSecKdfSeed(session *pk11.Session) error { + if *highSecKS == "" { + return errors.New("--high_sec_ks flag not set") + } + seed, _ := hex.DecodeString(*highSecKS) + err := loadKdfSeed(session, hsksName, seed) + if err != nil { + return fmt.Errorf("failed to load high security KDF seed: %q", seed) + } + return nil +} + +// LoadLowSecKdfSeed loads a low security secret seed that may be used to derive +// symmetric keys from during the provisioning flow. This seed is NOT expected +// to be rotated frequently. +func LoadLowSecKdfSeed(session *pk11.Session) error { + if *lowSecKS == "" { + return errors.New("--low_sec_ks flag not set") + } + seed, _ := hex.DecodeString(*lowSecKS) + err := loadKdfSeed(session, lsksName, seed) + if err != nil { + return fmt.Errorf("failed to load low security KDF seed: %q", seed) + } + return nil +} + // buildCACert returns a root CA certificate template. func buildCACert(session *pk11.Session) (*x509.Certificate, error) { serialNumber, err := session.GenerateRandom(10) @@ -221,6 +286,8 @@ func main() { {"Removing previous keys", *forceKeygen, DestroyKeys}, {"Generating KG", *genKG, GenerateKG}, {"Generating KCA", *genKCA, GenerateKCA}, + {"Loading high security KDF seed", *loadHighSecKS, LoadHighSecKdfSeed}, + {"Loading low security KDF seed", *loadLowSecKS, LoadLowSecKdfSeed}, } { if !task.run { continue