OpenNHP/opennhp · error
unsupported GCM type
Error message
unsupported GCM type: %d
What it means
AeadFromKey returns this error when the GcmTypeEnum argument is not GCM_AES256 (0), GCM_SM4 (1), or GCM_CHACHA20POLY1305 (2). Because GcmTypeEnum is an int enum, any out-of-range integer — from bad config, wire data, or an uninitialized variable — lands in the default branch. It means an unrecognized AEAD algorithm selector reached the crypto layer.
Solutions
- Obtain GCM types via NewCipherSuite(scheme) instead of constructing them manually
- Validate externally-sourced integers against the GCM_AES256/GCM_SM4/GCM_CHACHA20POLY1305 constants before casting
- Log the numeric value and compare with the enum constants 0/1/2
- If a new constant was added, add its case to AeadFromKey (and CBC paths) and rebuild
- Note CBCEncryption has its own unsupported-value message — check which function actually returned the error
Example fix
// before
aead, err := core.AeadFromKey(core.GcmTypeEnum(cfg.AeadCode), &key)
// after
if cfg.AeadCode < int(core.GCM_AES256) || cfg.AeadCode > int(core.GCM_CHACHA20POLY1305) {
return fmt.Errorf("invalid aead code %d", cfg.AeadCode)
}
aead, err := core.AeadFromKey(core.GcmTypeEnum(cfg.AeadCode), &key)
if err != nil {
return err
} Defensive patterns
Strategy: validation
Validate before calling
func isValidGcmType(t core.GcmTypeEnum) bool {
return t >= core.GCM_AES256 && t <= core.GCM_CHACHA20POLY1305
}
if !isValidGcmType(t) {
return fmt.Errorf("gcm type %d out of range", int(t))
} Type guard
func asGcmType(v int) (core.GcmTypeEnum, bool) {
if v < int(core.GCM_AES256) || v > int(core.GCM_CHACHA20POLY1305) {
return 0, false
}
return core.GcmTypeEnum(v), true
} Try / catch
aead, err := core.AeadFromKey(t, &key)
if err != nil {
if strings.Contains(err.Error(), "unsupported GCM type") {
return fmt.Errorf("bad AEAD selector %d: %w", int(t), err)
}
return err
} Prevention
- Get GCM types only from NewCipherSuite(scheme)
- Range-check any integer from config or wire data before casting to GcmTypeEnum
- Add a switch case in AeadFromKey whenever GcmTypeEnum is extended
When it happens
Trigger: Passing a GcmTypeEnum cast from an unvalidated integer (e.g. -1 sentinel, value from config.toml or a protocol field), or adding a new GcmTypeEnum constant without a corresponding case in AeadFromKey.
Common situations: Mapping a cipher-scheme number to GCM type with an off-by-one or wrong table; deserializing a peer's algorithm identifier that doesn't match the local enum; extending the enum in a fork without updating the switch.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- unsupported hash type
- Failed to decrypt ztdo file
- failed to create ChaCha20-Poly1305
- unsupported cipher type for CBC decryption
- unknown symmetric mode name
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/7714a1fd569195c7.
Report an issue: GitHub.
Appendix: source
Thrown at nhp/core/crypto.go:183
sm4Block, err := sm4.NewCipher(key[:16])
if err != nil {
return nil, fmt.Errorf("failed to create SM4 cipher: %w", err)
}
aead, err := cipher.NewGCM(sm4Block)
if err != nil {
return nil, fmt.Errorf("failed to create SM4-GCM: %w", err)
}
return aead, nil
case GCM_CHACHA20POLY1305:
aead, err := chacha20poly1305.New(key[:])
if err != nil {
return nil, fmt.Errorf("failed to create ChaCha20-Poly1305: %w", err)
}
return aead, nil
default:
return nil, fmt.Errorf("unsupported GCM type: %d", t)
}
}
func CBCEncryption(t GcmTypeEnum, key *[SymmetricKeySize]byte, plaintext []byte, inPlace bool) ([]byte, error) {
var block cipher.Block
var iv []byte
var err error
switch t {
case GCM_AES256:
block, err = aes.NewCipher(key[:])
if err != nil {
return nil, fmt.Errorf("failed to create AES cipher for CBC: %w", err)
}
iv = key[8:24]
case GCM_SM4:
block, err = sm4.NewCipher(key[:16])
if err != nil {View on GitHub (pinned to 6e04ca5ff0)