package notify import "errors" var ( errClientSessionQueueUnavailable = errors.New("client session queue is unavailable") errServerSessionQueueUnavailable = errors.New("server session queue is unavailable") errTransportPayloadEncryptFailed = errors.New("transport payload encrypt failed") errTransportPayloadDecryptFailed = errors.New("transport payload decrypt failed") ) func encryptTransportPayloadCodec(mode ProtectionMode, runtime *modernPSKCodecRuntime, msgEn func([]byte, []byte) []byte, secretKey []byte, data []byte) ([]byte, error) { if mode == ProtectionExternal { return data, nil } if runtime != nil { encoded, err := runtime.sealPlainPayload(data) if err != nil { return nil, errTransportPayloadEncryptFailed } return encoded, nil } if msgEn == nil { return nil, errTransportPayloadEncryptFailed } encoded := msgEn(secretKey, data) if encoded == nil && len(data) != 0 { return nil, errTransportPayloadEncryptFailed } return encoded, nil } func decryptTransportPayloadCodec(mode ProtectionMode, runtime *modernPSKCodecRuntime, msgDe func([]byte, []byte) []byte, secretKey []byte, data []byte) ([]byte, error) { if mode == ProtectionExternal { return data, nil } if runtime != nil { plain, err := runtime.openPayload(data) if err != nil { return nil, errTransportPayloadDecryptFailed } return plain, nil } if msgDe == nil { return nil, errTransportPayloadDecryptFailed } plain := msgDe(secretKey, data) if plain == nil && len(data) != 0 { return nil, errTransportPayloadDecryptFailed } return plain, nil } func decryptTransportPayloadCodecPooled(mode ProtectionMode, runtime *modernPSKCodecRuntime, msgDe func([]byte, []byte) []byte, secretKey []byte, data []byte, release func()) ([]byte, func(), error) { if mode == ProtectionExternal { return data, release, nil } if runtime != nil { plain, plainRelease, err := runtime.openPayloadPooled(data, release) if err != nil { return nil, nil, errTransportPayloadDecryptFailed } return plain, plainRelease, nil } if msgDe == nil { if release != nil { release() } return nil, nil, errTransportPayloadDecryptFailed } plain := msgDe(secretKey, data) if release != nil { release() } if plain == nil && len(data) != 0 { return nil, nil, errTransportPayloadDecryptFailed } return plain, nil, nil } func decryptTransportPayloadCodecOwnedPooled(mode ProtectionMode, runtime *modernPSKCodecRuntime, msgDe func([]byte, []byte) []byte, secretKey []byte, data []byte) ([]byte, func(), error) { if mode == ProtectionExternal { return data, nil, nil } if runtime != nil { plain, plainRelease, err := runtime.openPayloadOwnedPooled(data) if err != nil { return nil, nil, errTransportPayloadDecryptFailed } return plain, plainRelease, nil } if msgDe == nil { return nil, nil, errTransportPayloadDecryptFailed } plain := msgDe(secretKey, data) if plain == nil && len(data) != 0 { return nil, nil, errTransportPayloadDecryptFailed } return plain, nil, nil } func (c *ClientCommon) encodeTransferMsg(msg TransferMsg) ([]byte, error) { data, err := c.sequenceEn(msg) if err != nil { return nil, err } data, err = c.encryptTransportPayload(data) if err != nil { return nil, err } queue := c.clientQueueSnapshot() if queue == nil { return nil, errClientSessionQueueUnavailable } return queue.BuildMessage(data), nil } func (c *ClientCommon) decodeTransferMsg(data []byte) (TransferMsg, error) { plain, err := c.decryptTransportPayload(data) if err != nil { return TransferMsg{}, err } msg, err := c.sequenceDe(plain) if err != nil { return TransferMsg{}, err } transfer, ok := msg.(TransferMsg) if !ok { return TransferMsg{}, errors.New("invalid transfer message") } return transfer, nil } func (s *ServerCommon) encodeTransferMsg(c *ClientConn, msg TransferMsg) ([]byte, error) { data, err := s.sequenceEn(msg) if err != nil { return nil, err } logical := logicalConnFromClient(c) msgEn := c.clientConnMsgEnSnapshot() secretKey := c.clientConnSecretKeySnapshot() mode := ProtectionManaged if logical != nil { mode = logical.protectionModeSnapshot() } data, err = encryptTransportPayloadCodec(mode, c.clientConnModernPSKRuntimeSnapshot(), msgEn, secretKey, data) if err != nil { return nil, err } queue := s.serverQueueSnapshot() if queue == nil { return nil, errServerSessionQueueUnavailable } return queue.BuildMessage(data), nil } func (s *ServerCommon) decodeTransferMsg(c *ClientConn, data []byte) (TransferMsg, error) { msgDe := c.clientConnMsgDeSnapshot() secretKey := c.clientConnSecretKeySnapshot() mode := ProtectionManaged if logical := logicalConnFromClient(c); logical != nil { mode = logical.protectionModeSnapshot() } plain, err := decryptTransportPayloadCodec(mode, c.clientConnModernPSKRuntimeSnapshot(), msgDe, secretKey, data) if err != nil { return TransferMsg{}, err } msg, err := s.sequenceDe(plain) if err != nil { return TransferMsg{}, err } transfer, ok := msg.(TransferMsg) if !ok { return TransferMsg{}, errors.New("invalid transfer message") } return transfer, nil } func (c *ClientCommon) encodeEnvelopePayload(env Envelope) ([]byte, error) { data, err := c.encodeEnvelopePlain(env) if err != nil { return nil, err } return c.encryptTransportPayload(data) } func (c *ClientCommon) encodeEnvelopePlain(env Envelope) ([]byte, error) { data, err := c.sequenceEn(env) if err != nil { return nil, err } return data, nil } func (c *ClientCommon) encryptTransportPayload(data []byte) ([]byte, error) { profile := c.clientTransportProtectionSnapshot() return encryptTransportPayloadCodec(profile.mode, profile.runtime, profile.msgEn, profile.secretKey, data) } func (c *ClientCommon) encodeEnvelope(env Envelope) ([]byte, error) { data, err := c.encodeEnvelopePayload(env) if err != nil { return nil, err } queue := c.clientQueueSnapshot() if queue == nil { return nil, errClientSessionQueueUnavailable } return queue.BuildMessage(data), nil } func (c *ClientCommon) decodeEnvelope(data []byte) (Envelope, error) { plain, err := c.decryptTransportPayload(data) if err != nil { return Envelope{}, err } return c.decodeEnvelopePlain(plain) } func (c *ClientCommon) decryptTransportPayload(data []byte) ([]byte, error) { profile := c.clientTransportProtectionSnapshot() return decryptTransportPayloadCodec(profile.mode, profile.runtime, profile.msgDe, profile.secretKey, data) } func (c *ClientCommon) decodeEnvelopePlain(data []byte) (Envelope, error) { msg, err := c.sequenceDe(data) if err != nil { return Envelope{}, err } env, ok := msg.(Envelope) if ok { return env, nil } transfer, ok := msg.(TransferMsg) if !ok { return Envelope{}, errors.New("invalid envelope") } wrapped, err := wrapTransferMsgEnvelope(transfer, c.sequenceEn) if err != nil { return Envelope{}, err } return wrapped, nil } func (s *ServerCommon) encodeEnvelope(c *ClientConn, env Envelope) ([]byte, error) { return s.encodeEnvelopeLogical(logicalConnFromClient(c), env) } func (s *ServerCommon) encodeEnvelopePayloadLogical(logical *LogicalConn, env Envelope) ([]byte, error) { if logical == nil { return nil, errTransportDetached } data, err := s.encodeEnvelopePlain(env) if err != nil { return nil, err } return s.encryptTransportPayloadLogical(logical, data) } func (s *ServerCommon) encodeEnvelopePlain(env Envelope) ([]byte, error) { data, err := s.sequenceEn(env) if err != nil { return nil, err } return data, nil } func (s *ServerCommon) encryptTransportPayloadLogical(logical *LogicalConn, data []byte) ([]byte, error) { if logical == nil { return nil, errTransportDetached } msgEn := logical.msgEnSnapshot() secretKey := logical.secretKeySnapshot() if msgEn == nil { return nil, errTransportDetached } return encryptTransportPayloadCodec(logical.protectionModeSnapshot(), logical.modernPSKRuntimeSnapshot(), msgEn, secretKey, data) } func (s *ServerCommon) encodeEnvelopeLogical(logical *LogicalConn, env Envelope) ([]byte, error) { data, err := s.encodeEnvelopePayloadLogical(logical, env) if err != nil { return nil, err } queue := s.serverQueueSnapshot() if queue == nil { return nil, errServerSessionQueueUnavailable } return queue.BuildMessage(data), nil } func (s *ServerCommon) decodeEnvelope(c *ClientConn, data []byte) (Envelope, error) { return s.decodeEnvelopeLogical(logicalConnFromClient(c), data) } func (s *ServerCommon) decodeEnvelopeLogical(logical *LogicalConn, data []byte) (Envelope, error) { if logical == nil { return Envelope{}, errTransportDetached } plain, err := s.decryptTransportPayloadLogical(logical, data) if err != nil { return Envelope{}, err } return s.decodeEnvelopePlain(plain) } func (s *ServerCommon) decryptTransportPayloadLogical(logical *LogicalConn, data []byte) ([]byte, error) { if logical == nil { return nil, errTransportDetached } msgDe := logical.msgDeSnapshot() secretKey := logical.secretKeySnapshot() if msgDe == nil { return nil, errTransportDetached } return decryptTransportPayloadCodec(logical.protectionModeSnapshot(), logical.modernPSKRuntimeSnapshot(), msgDe, secretKey, data) } func (s *ServerCommon) decodeEnvelopePlain(data []byte) (Envelope, error) { msg, err := s.sequenceDe(data) if err != nil { return Envelope{}, err } env, ok := msg.(Envelope) if ok { return env, nil } transfer, ok := msg.(TransferMsg) if !ok { return Envelope{}, errors.New("invalid envelope") } wrapped, err := wrapTransferMsgEnvelope(transfer, s.sequenceEn) if err != nil { return Envelope{}, err } return wrapped, nil }