mirror of
https://github.com/luxfi/threshold.git
synced 2026-10-30 15:15:53 +00:00
Sibling of protocols/{slhdsa,mldsa}-tee for the corona Ring-LWE
primitive. Master trusted-dealer key (32 B, sign.KeySize) lives
sealed-at-rest in hsm.Provider; per-Sign the TEE attestation
authorizes release and then the dealer's GenerateKeys + the n-party
Round1 / Round2 / Finalize all run inside the attested process.
Composition (not inheritance):
Signer { gate kms.ReleaseGate; hsmP hsm.Provider;
appr approval.ApprovalProvider; cfg Config }
corona.threshold.GenerateKeys writes package-level globals
(sign.K, sign.Threshold) — coronaSerializer wraps every entry point
into corona so two concurrent Signers on the same process do not race
through that shared state. Workaround for an upstream constraint; not
a security boundary.
Permissionless path (corona.keyera.BootstrapPedersen — no party ever
holds the master) UNAFFECTED. This is the opt-in institutional-
custody extension. Use cases: foundation HSM ceremonies, single-
operator bridge custody.
11 tests + 9 Config sub-tests; t.Parallel; depends on luxfi/corona
v0.7.6 (canonical Signature/GroupKey/VerifyBytes wire codec).
83 lines
2.3 KiB
Go
83 lines
2.3 KiB
Go
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package rlwetee
|
|
|
|
import (
|
|
"context"
|
|
"crypto/sha256"
|
|
"crypto/subtle"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/luxfi/mpc/cc/attest"
|
|
"github.com/luxfi/mpc/pkg/kms"
|
|
)
|
|
|
|
// Envelope is the minimal kms.CompositeAttestation implementation
|
|
// consumed by this package. Mirrors slhdsa-tee.Envelope so embedders
|
|
// that compose multiple primitives share the same plumbing.
|
|
type Envelope struct {
|
|
Kind attest.Kind
|
|
EvidenceBytes []byte
|
|
ExpectedNonce [32]byte
|
|
RIM [32]byte
|
|
Hardware [32]byte
|
|
TEEPub [32]byte
|
|
VerifyOpts []attest.Option
|
|
}
|
|
|
|
var _ kms.CompositeAttestation = (*Envelope)(nil)
|
|
|
|
// Verify implements kms.CompositeAttestation.Verify.
|
|
func (e *Envelope) Verify(expectedNonce [32]byte) (bool, error) {
|
|
if subtle.ConstantTimeCompare(e.ExpectedNonce[:], expectedNonce[:]) != 1 {
|
|
return false, nil
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
// VerifyEvidence implements kms.CompositeAttestation.VerifyEvidence.
|
|
func (e *Envelope) VerifyEvidence(ctx context.Context, opts ...attest.Option) ([]*attest.VerifiedReport, error) {
|
|
if len(e.EvidenceBytes) == 0 {
|
|
return nil, fmt.Errorf("%w: empty evidence", attest.ErrInvalidEvidence)
|
|
}
|
|
allOpts := append([]attest.Option{}, e.VerifyOpts...)
|
|
allOpts = append(allOpts, opts...)
|
|
rep, err := attest.Dispatch(ctx, e.Kind, e.EvidenceBytes, allOpts...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := defaultRIMCheck(rep, e.RIM); err != nil {
|
|
return nil, err
|
|
}
|
|
return []*attest.VerifiedReport{rep}, nil
|
|
}
|
|
|
|
func (e *Envelope) RIMDigest() [32]byte { return e.RIM }
|
|
func (e *Envelope) HardwareFingerprint() [32]byte { return e.Hardware }
|
|
func (e *Envelope) TEEPublicKey() [32]byte { return e.TEEPub }
|
|
|
|
func (e *Envelope) EvidenceIssuers() []string {
|
|
switch e.Kind {
|
|
case attest.KindSEVSNP:
|
|
return []string{kms.IssuerSEVSNP}
|
|
case attest.KindTDX:
|
|
return []string{kms.IssuerTDX}
|
|
case attest.KindNRAS:
|
|
return []string{kms.IssuerNVNRAS}
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func defaultRIMCheck(rep *attest.VerifiedReport, expected [32]byte) error {
|
|
if rep == nil {
|
|
return errors.New("rlwe-tee: defaultRIMCheck: nil verified report")
|
|
}
|
|
got := sha256.Sum256(rep.Measurement)
|
|
if subtle.ConstantTimeCompare(got[:], expected[:]) != 1 {
|
|
return fmt.Errorf("%w: report measurement does not fold to operator-asserted RIM", attest.ErrPolicy)
|
|
}
|
|
return nil
|
|
}
|