85 lines
1.6 KiB
Go
85 lines
1.6 KiB
Go
package crypto
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"sync"
|
|
)
|
|
|
|
// Sentinel errors for registry operations.
|
|
var (
|
|
ErrUnknownScheme = errors.New("unknown KEM scheme")
|
|
ErrDuplicateScheme = errors.New("duplicate KEM scheme registration")
|
|
)
|
|
|
|
// KEMFactory is a constructor function that returns a fresh KEM instance.
|
|
type KEMFactory func() KEM
|
|
|
|
// Registry is a concurrent-safe map of KEM scheme IDs to their factories.
|
|
type Registry interface {
|
|
Register(
|
|
schemeID uint16,
|
|
factory KEMFactory,
|
|
) error
|
|
Lookup(
|
|
schemeID uint16,
|
|
) (
|
|
KEMFactory,
|
|
error,
|
|
)
|
|
}
|
|
|
|
// registry is the private implementation of Registry.
|
|
type registry struct {
|
|
mutex sync.RWMutex
|
|
factories map[uint16]KEMFactory
|
|
}
|
|
|
|
// NewRegistry creates a new empty Registry.
|
|
func NewRegistry() Registry {
|
|
return ®istry{
|
|
factories: make(map[uint16]KEMFactory),
|
|
}
|
|
}
|
|
|
|
// Register adds a KEMFactory for the given schemeID.
|
|
// Returns ErrDuplicateScheme if the schemeID is already registered.
|
|
func (r *registry) Register(schemeID uint16, factory KEMFactory) error {
|
|
r.mutex.Lock()
|
|
defer r.mutex.Unlock()
|
|
|
|
if _, exists := r.factories[schemeID]; exists {
|
|
return fmt.Errorf(
|
|
"scheme 0x%04x: %w",
|
|
schemeID,
|
|
ErrDuplicateScheme,
|
|
)
|
|
}
|
|
|
|
r.factories[schemeID] = factory
|
|
return nil
|
|
}
|
|
|
|
// Lookup retrieves the KEMFactory for the given schemeID.
|
|
// Returns ErrUnknownScheme if the schemeID is not registered.
|
|
func (r *registry) Lookup(
|
|
schemeID uint16,
|
|
) (
|
|
KEMFactory,
|
|
error,
|
|
) {
|
|
r.mutex.RLock()
|
|
defer r.mutex.RUnlock()
|
|
|
|
factory, exists := r.factories[schemeID]
|
|
if !exists {
|
|
return nil, fmt.Errorf(
|
|
"scheme 0x%04x: %w",
|
|
schemeID,
|
|
ErrUnknownScheme,
|
|
)
|
|
}
|
|
|
|
return factory, nil
|
|
}
|