Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions coordinator/clientapi/clientapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ type core interface {
}) error
GetState(context.Context) (state.State, string, error)
GenerateSecrets(
map[string]manifest.Secret, uuid.UUID, *x509.Certificate, *ecdsa.PrivateKey, *ecdsa.PrivateKey,
map[string]manifest.Secret, uuid.UUID, string, *x509.Certificate, *ecdsa.PrivateKey, *ecdsa.PrivateKey,
) (map[string]manifest.Secret, error)
GetQuote(reportData []byte) ([]byte, error)
GenerateQuote([]byte) error
Expand Down Expand Up @@ -387,13 +387,13 @@ func (a *ClientAPI) SetManifest(ctx context.Context, rawManifest []byte) (recove
}

// Generate shared secrets specified in manifest
secrets, err := a.core.GenerateSecrets(mnf.Secrets, uuid.Nil, marbleRootCert, intermediatePrivK, rootPrivK)
secrets, err := a.core.GenerateSecrets(mnf.Secrets, uuid.Nil, "", marbleRootCert, intermediatePrivK, rootPrivK)
if err != nil {
a.log.Error("Could not generate specified secrets for the given manifest.", zap.Error(err))
return nil, fmt.Errorf("generating secrets from manifest: %w", err)
}
// generate placeholders for private secrets specified in manifest
privSecrets, err := a.core.GenerateSecrets(mnf.Secrets, uuid.New(), marbleRootCert, intermediatePrivK, rootPrivK)
privSecrets, err := a.core.GenerateSecrets(mnf.Secrets, uuid.New(), "", marbleRootCert, intermediatePrivK, rootPrivK)
if err != nil {
a.log.Error("Could not generate specified secrets for the given manifest.", zap.Error(err))
return nil, fmt.Errorf("generating placeholder secrets from manifest: %w", err)
Expand Down Expand Up @@ -604,7 +604,7 @@ func (a *ClientAPI) UpdateManifest(ctx context.Context, rawUpdateManifest []byte
}

// Regenerate shared secrets specified in manifest
regeneratedSecrets, err := a.core.GenerateSecrets(secretsToRegenerate, uuid.Nil, marbleRootCert, intermediatePrivK, rootPrivK)
regeneratedSecrets, err := a.core.GenerateSecrets(secretsToRegenerate, uuid.Nil, "", marbleRootCert, intermediatePrivK, rootPrivK)
if err != nil {
a.log.Error("Could not generate specified secrets for the given manifest.", zap.Error(err))
return fmt.Errorf("regenerating shared secrets for updated manifest: %w", err)
Expand Down
2 changes: 1 addition & 1 deletion coordinator/clientapi/clientapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -924,7 +924,7 @@ func (c *fakeCore) GetState(_ context.Context) (state.State, string, error) {
}

func (c *fakeCore) GenerateSecrets(
newSecrets map[string]manifest.Secret, _ uuid.UUID, rootCert *x509.Certificate, privK *ecdsa.PrivateKey, _ *ecdsa.PrivateKey,
newSecrets map[string]manifest.Secret, _ uuid.UUID, _ string, rootCert *x509.Certificate, privK *ecdsa.PrivateKey, _ *ecdsa.PrivateKey,
) (map[string]manifest.Secret, error) {
if c.generateSecretsErr != nil || c.generatedSecrets != nil {
return c.generatedSecrets, c.generateSecretsErr
Expand Down
6 changes: 4 additions & 2 deletions coordinator/core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ func (c *Core) GetState(ctx context.Context) (state.State, string, error) {

// GenerateSecrets generates secrets for the given manifest and parent certificate.
func (c *Core) GenerateSecrets(
secrets map[string]manifest.Secret, id uuid.UUID,
secrets map[string]manifest.Secret, id uuid.UUID, marbleName string,
parentCertificate *x509.Certificate, parentPrivKey *ecdsa.PrivateKey, rootPrivK *ecdsa.PrivateKey,
) (map[string]manifest.Secret, error) {
// Create a new map so we do not overwrite the entries in the manifest
Expand Down Expand Up @@ -395,7 +395,9 @@ func (c *Core) GenerateSecrets(
salt := id.String() + name
secretKeyDerive := rootPrivK.D.Bytes()
var err error
generatedValue, err = util.DeriveKey(secretKeyDerive, []byte(salt), secret.Size/8)

// Derive key using the uuid and secret name as salt, and the marble's name as info
generatedValue, err = util.DeriveKey(secretKeyDerive, []byte(salt), []byte(marbleName), secret.Size/8)
if err != nil {
return nil, err
}
Expand Down
16 changes: 8 additions & 8 deletions coordinator/core/core_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ func TestGenerateSecrets(t *testing.T) {
rootPrivK := testutil.GetPrivateKey(t, c.txHandle, constants.SKCoordinatorRootKey)

// This should return valid secrets
generatedSecrets, err := c.GenerateSecrets(secretsToGenerate, uuid.Nil, rootCert, rootPrivK, rootPrivK)
generatedSecrets, err := c.GenerateSecrets(secretsToGenerate, uuid.Nil, "", rootCert, rootPrivK, rootPrivK)
require.NoError(err)
// Check if rawTest1 has 128 Bits/16 Bytes and rawTest2 256 Bits/8 Bytes
assert.Len(generatedSecrets["rawTest1"].Public, 16)
Expand All @@ -222,7 +222,7 @@ func TestGenerateSecrets(t *testing.T) {

// Make sure a certificate gets a new serial number if its regenerated
firstSerial := generatedSecrets["cert-rsa-test"].Cert.SerialNumber
secondGeneration, err := c.GenerateSecrets(generatedSecrets, uuid.Nil, rootCert, rootPrivK, rootPrivK)
secondGeneration, err := c.GenerateSecrets(generatedSecrets, uuid.Nil, "", rootCert, rootPrivK, rootPrivK)
assert.NoError(err)
assert.NotEqualValues(*firstSerial, *secondGeneration["cert-rsa-test"].Cert.SerialNumber)

Expand Down Expand Up @@ -264,31 +264,31 @@ func TestGenerateSecrets(t *testing.T) {
assert.NoError(err)

// Check if we get an empty secret map as output for an empty map as input
generatedSecrets, err = c.GenerateSecrets(secretsEmptyMap, uuid.Nil, rootCert, rootPrivK, rootPrivK)
generatedSecrets, err = c.GenerateSecrets(secretsEmptyMap, uuid.Nil, "", rootCert, rootPrivK, rootPrivK)
require.NoError(err)
assert.IsType(map[string]manifest.Secret{}, generatedSecrets)
assert.Len(generatedSecrets, 0)

// Check if we get an empty secret map as output for nil
generatedSecrets, err = c.GenerateSecrets(nil, uuid.Nil, rootCert, rootPrivK, rootPrivK)
generatedSecrets, err = c.GenerateSecrets(nil, uuid.Nil, "", rootCert, rootPrivK, rootPrivK)
require.NoError(err)
assert.IsType(map[string]manifest.Secret{}, generatedSecrets)
assert.Len(generatedSecrets, 0)

// If no size is specified, the function should fail
_, err = c.GenerateSecrets(secretsNoSize, uuid.Nil, rootCert, rootPrivK, rootPrivK)
_, err = c.GenerateSecrets(secretsNoSize, uuid.Nil, "", rootCert, rootPrivK, rootPrivK)
assert.Error(err)

// Also, it should fail if we try to generate a secret with an unknown type
_, err = c.GenerateSecrets(secretsInvalidType, uuid.Nil, rootCert, rootPrivK, rootPrivK)
_, err = c.GenerateSecrets(secretsInvalidType, uuid.Nil, "", rootCert, rootPrivK, rootPrivK)
assert.Error(err)

// If Ed25519 key size is specified, we should fail
_, err = c.GenerateSecrets(secretsEd25519WrongKeySize, uuid.Nil, rootCert, rootPrivK, rootPrivK)
_, err = c.GenerateSecrets(secretsEd25519WrongKeySize, uuid.Nil, "", rootCert, rootPrivK, rootPrivK)
assert.Error(err)

// However, for ECDSA we fail as we can have multiple curves
_, err = c.GenerateSecrets(secretsECDSAWrongKeySize, uuid.Nil, rootCert, rootPrivK, rootPrivK)
_, err = c.GenerateSecrets(secretsECDSAWrongKeySize, uuid.Nil, "", rootCert, rootPrivK, rootPrivK)
assert.Error(err)
}

Expand Down
36 changes: 21 additions & 15 deletions coordinator/core/marbleapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ func (c *Core) Activate(ctx context.Context, req *rpc.ActivationReq) (res *rpc.A
}
defer rollback()

if err := c.verifyManifestRequirement(txdata, tlsCert, req.GetQuote(), req.GetMarbleType()); err != nil {
marbleName, err := c.verifyManifestRequirement(txdata, tlsCert, req.GetQuote(), req.GetMarbleType())
if err != nil {
c.log.Error("Marble verification failed", zap.Error(err))
return nil, status.Errorf(codes.PermissionDenied, "marble verification failed: %s", err)
}
Expand Down Expand Up @@ -127,7 +128,7 @@ func (c *Core) Activate(ctx context.Context, req *rpc.ActivationReq) (res *rpc.A
}

// Generate unique (= per marble) secrets
privateSecrets, err := c.GenerateSecrets(secrets, marbleUUID, marbleRootCert, intermediatePrivK, rootPrivK)
privateSecrets, err := c.GenerateSecrets(secrets, marbleUUID, marbleName, marbleRootCert, intermediatePrivK, rootPrivK)
if err != nil {
c.log.Error("Couldn't generate specified secrets for the given manifest", zap.Error(err))
return nil, status.Errorf(codes.Internal, "generating secrets for marble: %s", err)
Expand Down Expand Up @@ -184,64 +185,69 @@ func (c *Core) Activate(ctx context.Context, req *rpc.ActivationReq) (res *rpc.A
}

// verifyManifestRequirement verifies marble attempting to register with respect to manifest.
func (c *Core) verifyManifestRequirement(txdata storeGetter, tlsCert *x509.Certificate, certQuote []byte, marbleType string) error {
func (c *Core) verifyManifestRequirement(txdata storeGetter, tlsCert *x509.Certificate, certQuote []byte, marbleType string) (string, error) {
marble, err := txdata.GetMarble(marbleType)
if err != nil {
if errors.Is(err, store.ErrValueUnset) {
return fmt.Errorf("unknown marble type requested")
return "", fmt.Errorf("unknown marble type requested")
}
return fmt.Errorf("loading marble data: %w", err)
return "", fmt.Errorf("loading marble data: %w", err)
}

pkg, err := txdata.GetPackage(marble.Package)
if err != nil {
if errors.Is(err, store.ErrValueUnset) {
return fmt.Errorf("undefined package %q", marble.Package)
return "", fmt.Errorf("undefined package %q", marble.Package)
}
return fmt.Errorf("loading package data: %w", err)
return "", fmt.Errorf("loading package data: %w", err)
}

infraIter, err := txdata.GetIterator(request.Infrastructure)
if err != nil {
return fmt.Errorf("getting infrastructure iterator: %w", err)
return "", fmt.Errorf("getting infrastructure iterator: %w", err)
}

if !c.inSimulationMode() {
if !infraIter.HasNext() {
if err := c.qv.Validate(certQuote, tlsCert.Raw, pkg, quote.InfrastructureProperties{}); err != nil {
return fmt.Errorf("invalid quote: %w", err)
return "", fmt.Errorf("invalid quote: %w", err)
}
} else {
infraMatch := false
for infraIter.HasNext() {
infraName, err := infraIter.GetNext()
if err != nil {
return err
return "", err
}
infra, err := txdata.GetInfrastructure(infraName)
if err != nil {
return fmt.Errorf("loading infrastructure: %w", err)
return "", fmt.Errorf("loading infrastructure: %w", err)
}
if c.qv.Validate(certQuote, tlsCert.Raw, pkg, infra) == nil {
infraMatch = true
break
}
}
if !infraMatch {
return fmt.Errorf("invalid infrastructure")
return "", fmt.Errorf("invalid infrastructure")
}
}
}

// check activation budget (MaxActivations == 0 means infinite budget)
activations, err := txdata.GetActivations(marbleType)
if err != nil {
return fmt.Errorf("could not retrieve activations for marble type %q: %w", marbleType, err)
return "", fmt.Errorf("could not retrieve activations for marble type %q: %w", marbleType, err)
}
if marble.MaxActivations > 0 && activations >= marble.MaxActivations {
return fmt.Errorf("reached max activations count (%d) for marble type %q", marble.MaxActivations, marbleType)
return "", fmt.Errorf("reached max activations count (%d) for marble type %q", marble.MaxActivations, marbleType)
}
return nil

marbleName := marbleType
if marble.DisableSecretBinding {
marbleName = ""
}
return marbleName, nil
}

// generateCertFromCSR signs the CSR from marble attempting to register.
Expand Down
Loading