package mls // MLS cryptographic types (RFC 9420 §5.3, §6). // Key type aliases, credentials, and HPKE ciphertext. import "errors" var ( errInvalidCredentialType = errors.New("mls: invalid credential type") ) // Key type aliases — all are raw byte slices. type ( hpkePublicKey []byte hpkePrivateKey []byte signaturePublicKey []byte signaturePrivateKey []byte ) // --- Credential --- type credentialType uint16 const ( credentialTypeBasic credentialType = 0x0001 credentialTypeX509 credentialType = 0x0002 ) // Credential holds information about a group member's identity. type Credential struct { credentialType credentialType identity []byte // for credentialTypeBasic certificates [][]byte // for credentialTypeX509 } // NewBasicCredential creates a basic credential with an application-specific identity. func NewBasicCredential(identity []byte) *Credential { return &Credential{ credentialType: credentialTypeBasic, identity: identity, } } func (cred *Credential) unmarshal(r *Reader) error { *cred = Credential{} v, ok := r.readUint16() if !ok { return errUnexpectedEOF } cred.credentialType = credentialType(v) switch cred.credentialType { case credentialTypeBasic: cred.identity, ok = r.readOpaqueVec() if !ok { return errUnexpectedEOF } return nil case credentialTypeX509: return r.readVector(func(r *Reader) error { cert, ok := r.readOpaqueVec() if !ok { return errUnexpectedEOF } cred.certificates = append(cred.certificates, cert) return nil }) default: return errInvalidCredentialType } } func (cred *Credential) marshal(w *Writer) { w.addUint16(uint16(cred.credentialType)) switch cred.credentialType { case credentialTypeBasic: w.writeOpaqueVec(cred.identity) case credentialTypeX509: w.writeVector(len(cred.certificates), func(w *Writer, i int) { w.writeOpaqueVec(cred.certificates[i]) }) default: panic("unreachable") } } // --- HPKE Ciphertext --- type hpkeCiphertext struct { kemOutput []byte ciphertext []byte } func (hc *hpkeCiphertext) unmarshal(r *Reader) error { *hc = hpkeCiphertext{} var ok bool hc.kemOutput, ok = r.readOpaqueVec() if !ok { return errUnexpectedEOF } hc.ciphertext, ok = r.readOpaqueVec() if !ok { return errUnexpectedEOF } return nil } func (hc *hpkeCiphertext) marshal(w *Writer) { w.writeOpaqueVec(hc.kemOutput) w.writeOpaqueVec(hc.ciphertext) }