Skip to content

Commit

Permalink
[spm] Make HSM assets configurable at the SKU level.
Browse files Browse the repository at this point in the history
Refactor the key loading mechanism so that the spm
only loads assets specific to the SKU configuration provided
at service instantiation.

The following SKU configuration settings are introduced in this change:

* `SymmetricKeys`: List of keys of `pk11.ClassSecretKey` type.
* `PrivateKeys`: List of keys of  `pk11.ClassPrivateKey` type.
* `Certs`: List of certificates, including root and intermediate CA
  certificates.

Signed-off-by: Miguel Osorio <[email protected]>
  • Loading branch information
moidx committed Feb 4, 2025
1 parent c613e37 commit 3e8351b
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 97 deletions.
7 changes: 3 additions & 4 deletions config/dev/spm/sku_sival.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
sku: "prod_a"
slotId: 0
numSessions: 3
highSecSeedKeyName: "HighSecKdfSeed"
lowSecSeedKeyName: "LowSecKdfSeed"
caKeyName: "KCAPriv"
rootCAPath: certs/NuvotonTPMRootCA0200.cer
symmetricKeys:
- name: "HighSecKdfSeed"
- name: "LowSecKdfSeed"
18 changes: 12 additions & 6 deletions config/dev/spm/sku_tpm_1.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
sku: "tpm_1"
slotId: 0
numSessions: 3
wrapKeyName: "KG"
caKeyName: "KCAPriv"
certTemplate:
- certPath: certs/TPMEkRsaCertTemplate.cer
- certPath: certs/TPMEkEccCertTemplate.cer
symmetricKeys:
- name: "KG"
privateKeys:
- name: "KCAPriv"
certTemplates:
- name: "TPMEkRsaCertTemplate"
path: certs/TPMEkRsaCertTemplate.cer
- name: "TPMEkEccCertTemplate"
path: certs/TPMEkEccCertTemplate.cer
certTemplateSAN:
tpmManufacturer: "id:4E544300"
tpmModel: "NPCT75x"
Expand All @@ -27,4 +31,6 @@ keyWrapConfig:
size: 384
name: 1
hash: 2
rootCAPath: certs/NuvotonTPMRootCA0200.cer
certs:
- name: "RootCA"
path: certs/NuvotonTPMRootCA0200.cer
2 changes: 1 addition & 1 deletion docs/spm.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ to run outside of a container. For example:
$ config/dev/softhsm/init.sh \
config/dev \
bazel-bin/external/softhsm2/softhsm2 \
"$(pwd)/.opentitan
"$(pwd)/.opentitan"
Execute the following command before launching the spm service:
export SOFTHSM2_CONF=/home/user/ot-provisioning/.opentitan/spm/softhsm2/softhsm2.conf
SoftHSM configuration result: PASS!
Expand Down
10 changes: 5 additions & 5 deletions src/pa/loadtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ func (c *clientTask) setup(ctx context.Context) error {
// Send request to PA and wait for response that contains auth_token.
request := &pbp.InitSessionRequest{Sku: *testSKUName, SkuAuth: *testSKUAuth}
response, err := c.client.InitSession(client_ctx, request)
c.auth_token = response.SkuSessionToken
if err != nil {
return err
}
c.auth_token = response.SkuSessionToken
return nil
}

Expand Down Expand Up @@ -127,25 +127,25 @@ func (c *clientTask) ot_run(ctx context.Context, numCalls int) {
request := &pbp.DeriveSymmetricKeysRequest{
Sku: *testSKUName,
Params: []*pbp.SymmetricKeygenParams{
&pbp.SymmetricKeygenParams{
{
Seed: pbp.SymmetricKeySeed_SYMMETRIC_KEY_SEED_LOW_SECURITY,
Type: pbp.SymmetricKeyType_SYMMETRIC_KEY_TYPE_RAW,
Size: pbp.SymmetricKeySize_SYMMETRIC_KEY_SIZE_128_BITS,
Diversifier: "test_unlock",
},
&pbp.SymmetricKeygenParams{
{
Seed: pbp.SymmetricKeySeed_SYMMETRIC_KEY_SEED_LOW_SECURITY,
Type: pbp.SymmetricKeyType_SYMMETRIC_KEY_TYPE_RAW,
Size: pbp.SymmetricKeySize_SYMMETRIC_KEY_SIZE_128_BITS,
Diversifier: "test_exit",
},
&pbp.SymmetricKeygenParams{
{
Seed: pbp.SymmetricKeySeed_SYMMETRIC_KEY_SEED_HIGH_SECURITY,
Type: pbp.SymmetricKeyType_SYMMETRIC_KEY_TYPE_HASHED_OT_LC_TOKEN,
Size: pbp.SymmetricKeySize_SYMMETRIC_KEY_SIZE_128_BITS,
Diversifier: "rma,device_id",
},
&pbp.SymmetricKeygenParams{
{
Seed: pbp.SymmetricKeySeed_SYMMETRIC_KEY_SEED_HIGH_SECURITY,
Type: pbp.SymmetricKeyType_SYMMETRIC_KEY_TYPE_RAW,
Size: pbp.SymmetricKeySize_SYMMETRIC_KEY_SIZE_256_BITS,
Expand Down
11 changes: 10 additions & 1 deletion src/spm/services/certloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ type Key struct {
Exp []byte `yaml:"exp"`
}

type SymmetricKey struct {
Name string `yaml:"name"`
}

type PrivateKey struct {
Name string `yaml:"name"`
}

// A SKUKey tracks information necessary to identify a specific signer
// template.
type SKUKey struct {
Expand All @@ -71,7 +79,8 @@ type CertificateSubjectAltName struct {
}

type CertificateConfig struct {
CertPath string `yaml:"certPath"`
Name string `yaml:"name"`
Path string `yaml:"path"`
}

// New creates a new instance of the tpm certificate template builder.
Expand Down
108 changes: 64 additions & 44 deletions src/spm/services/se_pk11.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,33 +85,27 @@ type HSMConfig struct {
// NumSessions configures the number of sessions to open in `SlotID`.
NumSessions int

// KGName is the KG key label used to find the key in the HSM.
KGName string
// SymmetricKeys contains the list of symmetric key labels to use for
// retrieving long-lived symmetric keys on the HSM.
SymmetricKeys []string

// KcaName is the KCA key label used to find the key in the HSM.
KcaName string

// KHsksName is the HighSecKdfSeed key label used to find the key in the HSM.
KHsksName string

// KLsksName is the LowSecKdfSeed key label used to find the key in the HSM.
KLsksName string
// PrivateKeys contains the list of private key labels to use for
// retrieving long-lived private keys on the HSM.
PrivateKeys []string

// hsmType contains the type of the HSM (SoftHSM or NetworkHSM)
HSMType pk11.HSMType
}

// HSM is a wrapper over a pk11 session that conforms to the SPM interface.
type HSM struct {
// UIDs of key objects to use for retrieving long-lived keys on the HSM.
//
// KG and KT are their names in the flows specification: they correspond to the
// product revision-wide global secret (KG) and the static transport key used
// to derive per-device transport keys (KT).
//
// May be nil if those keys are not present and not used by any of the called
// methods.
KG, KT, Kca, KHsks, KLsks []byte
// UIDs of key objects to use for retrieving long-lived symmetric keys on
// the HSM.
SymmetricKeys map[string][]byte

// UIDs of key objects to use for retrieving long-lived private keys on
// the HSM.
PrivateKeys map[string][]byte

// The PKCS#11 session we're working with.
sessions *sessionQueue
Expand Down Expand Up @@ -184,29 +178,22 @@ func NewHSM(cfg HSMConfig) (*HSM, error) {
session, release := hsm.sessions.getHandle()
defer release()

if cfg.KcaName != "" {
hsm.Kca, err = getKeyIDByLabel(session, pk11.ClassPrivateKey, cfg.KcaName)
if err != nil {
return nil, status.Errorf(codes.Internal, "fail to find Kca key ID: %q, error: %v", cfg.KcaName, err)
}
}
if cfg.KGName != "" {
hsm.KG, err = getKeyIDByLabel(session, pk11.ClassSecretKey, cfg.KGName)
hsm.SymmetricKeys = make(map[string][]byte)
for _, key := range cfg.SymmetricKeys {
id, err := getKeyIDByLabel(session, pk11.ClassSecretKey, key)
if err != nil {
return nil, status.Errorf(codes.Internal, "fail to find KG key ID: %q, error: %v", cfg.KGName, err)
return nil, status.Errorf(codes.Internal, "fail to find symmetric key ID: %q, error: %v", key, err)
}
hsm.SymmetricKeys[key] = id
}
if cfg.KHsksName != "" {
hsm.KHsks, err = getKeyIDByLabel(session, pk11.ClassSecretKey, cfg.KHsksName)
if err != nil {
return nil, status.Errorf(codes.Internal, "fail to find KHsks key ID: %q, error: %v", cfg.KHsksName, err)
}
}
if cfg.KLsksName != "" {
hsm.KLsks, err = getKeyIDByLabel(session, pk11.ClassSecretKey, cfg.KLsksName)

hsm.PrivateKeys = make(map[string][]byte)
for _, key := range cfg.PrivateKeys {
id, err := getKeyIDByLabel(session, pk11.ClassPrivateKey, key)
if err != nil {
return nil, status.Errorf(codes.Internal, "fail to find KLsks key ID: %q, error: %v", cfg.KLsksName, err)
return nil, status.Errorf(codes.Internal, "fail to find private key ID: %q, error: %v", key, err)
}
hsm.PrivateKeys[key] = id
}

return hsm, nil
Expand All @@ -227,7 +214,11 @@ var transportKeyLabel = []byte("transport key")
// deriveTransportSecret derives the transport secret for the device with the
// given ID, and returns a handle to it.
func (h *HSM) deriveTransportSecret(session *pk11.Session, deviceId []byte) (pk11.SecretKey, error) {
transportStatic, err := session.FindSecretKey(h.KT)
kt, ok := h.SymmetricKeys["KT"]
if !ok {
return pk11.SecretKey{}, status.Errorf(codes.Internal, "failed to find KT key UID")
}
transportStatic, err := session.FindSecretKey(kt)
if err != nil {
return pk11.SecretKey{}, err
}
Expand All @@ -242,7 +233,12 @@ func (h *HSM) DeriveAndWrapTransportSecret(deviceId []byte) ([]byte, error) {
session, release := h.sessions.getHandle()
defer release()

global, err := session.FindSecretKey(h.KG)
kg, ok := h.SymmetricKeys["KG"]
if !ok {
return nil, status.Errorf(codes.Internal, "failed to find KG key UID")
}

global, err := session.FindSecretKey(kg)
if err != nil {
return nil, err
}
Expand All @@ -260,7 +256,13 @@ func (h *HSM) DeriveAndWrapTransportSecret(deviceId []byte) ([]byte, error) {
func (h *HSM) VerifySession() error {
session, release := h.sessions.getHandle()
defer release()
_, err := session.FindPrivateKey(h.Kca)

kca, ok := h.PrivateKeys["KCAPriv"]
if !ok {
return status.Errorf(codes.Internal, "failed to find KCAPriv key UID")
}

_, err := session.FindPrivateKey(kca)
if err != nil {
return status.Errorf(codes.Internal, "failed to verify session: %v", err)
}
Expand All @@ -280,7 +282,12 @@ func (h *HSM) GenerateKeyPairAndCert(caCert *x509.Certificate, params []SigningP
session, release := h.sessions.getHandle()
defer release()

caObj, err := session.FindPrivateKey(h.Kca)
kca, ok := h.PrivateKeys["KCAPriv"]
if !ok {
return nil, status.Errorf(codes.Internal, "failed to find KCAPriv key UID")
}

caObj, err := session.FindPrivateKey(kca)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to find Kca key object: %v", err)
}
Expand All @@ -290,7 +297,12 @@ func (h *HSM) GenerateKeyPairAndCert(caCert *x509.Certificate, params []SigningP
return nil, status.Errorf(codes.Internal, "failed to get Kca signer: %v", err)
}

wi, err := session.FindSecretKey(h.KG)
kg, ok := h.SymmetricKeys["KG"]
if !ok {
return nil, status.Errorf(codes.Internal, "failed to find KG key UID")
}

wi, err := session.FindSecretKey(kg)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get KG key object: %v", err)
}
Expand Down Expand Up @@ -348,12 +360,20 @@ func (h *HSM) GenerateSymmetricKeys(params []*SymmetricKeygenParams) ([][]byte,
var seed pk11.SecretKey
var err error
if p.UseHighSecuritySeed {
seed, err = session.FindSecretKey(h.KHsks)
khs, ok := h.SymmetricKeys["HighSecKdfSeed"]
if !ok {
return nil, status.Errorf(codes.Internal, "failed to find HighSecKdfSeed key UID")
}
seed, err = session.FindSecretKey(khs)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get KHsks key object: %v", err)
}
} else {
seed, err = session.FindSecretKey(h.KLsks)
kls, ok := h.SymmetricKeys["LowSecKdfSeed"]
if !ok {
return nil, status.Errorf(codes.Internal, "failed to find LowSecKdfSeed key UID")
}
seed, err = session.FindSecretKey(kls)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get KLsks key object: %v", err)
}
Expand Down
13 changes: 11 additions & 2 deletions src/spm/services/se_pk11_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,16 @@ func MakeHSM(t *testing.T) (*HSM, []byte, []byte, []byte, []byte) {
err = sessions.insert(s)
ts.Check(t, err)

return &HSM{KG: gUID, KT: tUID, KHsks: hsksUID, KLsks: lsksUID, sessions: sessions},
return &HSM{
SymmetricKeys: map[string][]byte{
"KG": gUID,
"KT": tUID,
"HighSecKdfSeed": hsksUID,
"LowSecKdfSeed": lsksUID,
},
PrivateKeys: map[string][]byte{},
sessions: sessions,
},
[]byte(globalKeyBytes.(pk11.AESKey)),
transportKeySeed,
hsKeySeed,
Expand Down Expand Up @@ -290,7 +299,7 @@ func TestGenerateCert(t *testing.T) {
})
ts.Check(t, err)

hsm.Kca = caKeyHandle
hsm.PrivateKeys["KCAPriv"] = caKeyHandle
certs, err := hsm.GenerateKeyPairAndCert(caCert, []SigningParams{{template, elliptic.P256()}})
ts.Check(t, err)

Expand Down
Loading

0 comments on commit 3e8351b

Please sign in to comment.