This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 7c21ea88ce2db4e36b4f9100c08d9eee521ed51e
Author: Sebastian Rühl <sru...@apache.org>
AuthorDate: Fri Jul 28 11:35:59 2023 +0200

    feat(plc4go/opcua): work on encryption part
---
 plc4go/internal/opcua/CertificateGenerator.go | 150 +++++++++++++++++++++
 plc4go/internal/opcua/CertificateKeyPair.go   |  11 +-
 plc4go/internal/opcua/Configuration.go        |  44 +++++-
 plc4go/internal/opcua/Driver.go               |   4 +-
 plc4go/internal/opcua/EncryptionHandler.go    | 184 ++++++++++++++++++++++++--
 plc4go/internal/opcua/SecureChannel.go        |  48 +++++--
 6 files changed, 406 insertions(+), 35 deletions(-)

diff --git a/plc4go/internal/opcua/CertificateGenerator.go 
b/plc4go/internal/opcua/CertificateGenerator.go
new file mode 100644
index 0000000000..63e7e534dd
--- /dev/null
+++ b/plc4go/internal/opcua/CertificateGenerator.go
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package opcua
+
+import (
+       "bytes"
+       "crypto/rand"
+       "crypto/rsa"
+       "crypto/tls"
+       "crypto/x509"
+       "crypto/x509/pkix"
+       "encoding/pem"
+       "math/big"
+       "net"
+       "time"
+
+       "github.com/pkg/errors"
+)
+
+func generateCertificate() (*CertificateKeyPair, error) {
+       // From: 
https://gist.github.com/shaneutt/5e1995295cff6721c89a71d13a71c251
+       // set up our CA certificate
+       ca := &x509.Certificate{
+               SerialNumber: big.NewInt(40),
+               Subject: pkix.Name{
+                       CommonName:         "Apache PLC4X Driver Client",
+                       Organization:       []string{"Apache Software 
Foundation"},
+                       OrganizationalUnit: []string{"dev"},
+                       Locality:           []string{""},
+                       Country:            []string{"US"},
+                       Province:           []string{""},
+               },
+               NotBefore:             time.Now().Add(-24 * time.Hour),
+               NotAfter:              time.Now().AddDate(25, 0, 0),
+               IsCA:                  true,
+               ExtKeyUsage:           
[]x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
+               KeyUsage:              x509.KeyUsageDigitalSignature | 
x509.KeyUsageCertSign,
+               BasicConstraintsValid: true,
+       }
+
+       // create our private and public key
+       caPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+       if err != nil {
+               return nil, errors.Wrap(err, "error generating key")
+       }
+
+       // create the CA
+       caBytes, err := x509.CreateCertificate(rand.Reader, ca, ca, 
&caPrivateKey.PublicKey, caPrivateKey)
+       if err != nil {
+               return nil, errors.Wrap(err, "error creating certificate")
+       }
+
+       // pem encode
+       caPEM := new(bytes.Buffer)
+       if err := pem.Encode(caPEM, &pem.Block{
+               Type:  "CERTIFICATE",
+               Bytes: caBytes,
+       }); err != nil {
+               return nil, errors.Wrap(err, "error pem encode")
+       }
+
+       caPrivateKeyPEM := new(bytes.Buffer)
+       if err := pem.Encode(caPrivateKeyPEM, &pem.Block{
+               Type:  "RSA PRIVATE KEY",
+               Bytes: x509.MarshalPKCS1PrivateKey(caPrivateKey),
+       }); err != nil {
+               return nil, errors.Wrap(err, "error pem encode")
+       }
+
+       // set up our server certificate
+       cert := &x509.Certificate{
+               SerialNumber: big.NewInt(2019),
+               Subject: pkix.Name{
+                       Organization:  []string{"Company, INC."},
+                       Country:       []string{"US"},
+                       Province:      []string{""},
+                       Locality:      []string{"San Francisco"},
+                       StreetAddress: []string{"Golden Gate Bridge"},
+                       PostalCode:    []string{"94016"},
+               },
+               IPAddresses:  []net.IP{net.IPv4(127, 0, 0, 1), 
net.IPv6loopback},
+               NotBefore:    time.Now(),
+               NotAfter:     time.Now().AddDate(10, 0, 0),
+               SubjectKeyId: []byte{1, 2, 3, 4, 6},
+               ExtKeyUsage:  []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, 
x509.ExtKeyUsageServerAuth},
+               KeyUsage:     x509.KeyUsageDigitalSignature,
+       }
+
+       certPrivateKey, err := rsa.GenerateKey(rand.Reader, 4096)
+       if err != nil {
+               return nil, errors.Wrap(err, "error generating key")
+       }
+
+       certBytes, err := x509.CreateCertificate(rand.Reader, cert, ca, 
&certPrivateKey.PublicKey, caPrivateKeyPEM)
+       if err != nil {
+               return nil, errors.Wrap(err, "error creating certificate")
+       }
+
+       certPEM := new(bytes.Buffer)
+       if err := pem.Encode(certPEM, &pem.Block{
+               Type:  "CERTIFICATE",
+               Bytes: certBytes,
+       }); err != nil {
+               return nil, errors.Wrap(err, "error pem encode")
+       }
+
+       certPrivKeyPEM := new(bytes.Buffer)
+       if err := pem.Encode(certPrivKeyPEM, &pem.Block{
+               Type:  "RSA PRIVATE KEY",
+               Bytes: x509.MarshalPKCS1PrivateKey(certPrivateKey),
+       }); err != nil {
+               return nil, errors.Wrap(err, "error pem encode")
+       }
+
+       serverCert, err := tls.X509KeyPair(certPEM.Bytes(), 
certPrivKeyPEM.Bytes())
+       if err != nil {
+               return nil, errors.Wrap(err, "error building keypair")
+       }
+
+       serverTLSConf := &tls.Config{
+               Certificates: []tls.Certificate{serverCert},
+       }
+       _ = serverTLSConf
+
+       certpool := x509.NewCertPool()
+       certpool.AppendCertsFromPEM(caPEM.Bytes())
+       clientTLSConf := &tls.Config{
+               RootCAs: certpool,
+       }
+       _ = clientTLSConf
+
+       return NewCertificateKeyPair(caPrivateKey, cert), nil
+}
diff --git a/plc4go/internal/opcua/CertificateKeyPair.go 
b/plc4go/internal/opcua/CertificateKeyPair.go
index c4bba2453d..68a7671052 100644
--- a/plc4go/internal/opcua/CertificateKeyPair.go
+++ b/plc4go/internal/opcua/CertificateKeyPair.go
@@ -20,17 +20,18 @@
 package opcua
 
 import (
+       "crypto/rsa"
        "crypto/sha1"
        "crypto/x509"
 )
 
 type CertificateKeyPair struct {
-       keyPair     x509.KeyUsage
-       certificate x509.Certificate
+       keyPair     *rsa.PrivateKey
+       certificate *x509.Certificate
        thumbprint  []byte
 }
 
-func NewCertificateKeyPair(keyPair x509.KeyUsage, certificate 
x509.Certificate) *CertificateKeyPair {
+func NewCertificateKeyPair(keyPair *rsa.PrivateKey, certificate 
*x509.Certificate) *CertificateKeyPair {
        thumbprint := sha1.Sum(certificate.Raw)
        return &CertificateKeyPair{
                keyPair:     keyPair,
@@ -39,11 +40,11 @@ func NewCertificateKeyPair(keyPair x509.KeyUsage, 
certificate x509.Certificate)
        }
 }
 
-func (p *CertificateKeyPair) getKeyPair() x509.KeyUsage {
+func (p *CertificateKeyPair) getKeyPair() *rsa.PrivateKey {
        return p.keyPair
 }
 
-func (p *CertificateKeyPair) getCertificate() x509.Certificate {
+func (p *CertificateKeyPair) getCertificate() *x509.Certificate {
        return p.certificate
 }
 
diff --git a/plc4go/internal/opcua/Configuration.go 
b/plc4go/internal/opcua/Configuration.go
index 98d995fa38..850251ae50 100644
--- a/plc4go/internal/opcua/Configuration.go
+++ b/plc4go/internal/opcua/Configuration.go
@@ -20,11 +20,14 @@
 package opcua
 
 import (
-       readWriteModel 
"github.com/apache/plc4x/plc4go/protocols/opcua/readwrite/model"
-       "github.com/pkg/errors"
+       "os"
+       "path"
        "reflect"
        "strconv"
 
+       readWriteModel 
"github.com/apache/plc4x/plc4go/protocols/opcua/readwrite/model"
+
+       "github.com/pkg/errors"
        "github.com/rs/zerolog"
 )
 
@@ -46,7 +49,9 @@ type Configuration struct {
        keyStoreFile      string
        certDirectory     string
        keyStorePassword  string
-       ckp               CertificateKeyPair
+       ckp               *CertificateKeyPair
+
+       log zerolog.Logger `ignore:"true"`
 }
 
 func ParseFromOptions(log zerolog.Logger, options map[string][]string) 
(Configuration, error) {
@@ -74,13 +79,40 @@ func ParseFromOptions(log zerolog.Logger, options 
map[string][]string) (Configur
                        }
                }
        }
+       configuration.log = log
        return configuration, nil
 }
 
-func (c *Configuration) openKeyStore() {
+func (c *Configuration) openKeyStore() error {
        c.isEncrypted = true
-       // TODO: load keystore yada yada
-       // TODO: NewCertificateKeyPair()
+       securityTempDir := path.Join(c.certDirectory, "security")
+       if _, err := os.Stat(securityTempDir); errors.Is(err, os.ErrNotExist) {
+               if err := os.Mkdir(securityTempDir, 700); err != nil {
+                       return errors.New("Unable to create directory please 
confirm folder permissions on " + securityTempDir)
+               }
+       }
+
+       serverKeyStore := path.Join(securityTempDir, c.keyStoreFile)
+       if _, err := os.Stat(securityTempDir); errors.Is(err, os.ErrNotExist) {
+               var err error
+               c.ckp, err = generateCertificate()
+               if err != nil {
+                       return errors.Wrap(err, "error generating certificate")
+               }
+               c.log.Info().Str("serverKeyStore", 
serverKeyStore).Msg("Creating keystore")
+               // TODO: not sure how to do that in golang. Seems pkc12 can 
only decode for now
+               _ = os.WriteFile(serverKeyStore, []byte{0xA}, 0700)
+       } else {
+               c.log.Info().Str("serverKeyStore", serverKeyStore).Msg("Loading 
keystore")
+               serverKeyStoreContent, err := os.ReadFile(serverKeyStore)
+               if err != nil {
+                       return errors.Wrap(err, "error reading "+serverKeyStore)
+               }
+               // TODO: here we can parse with "golang.org/x/crypto/pkcs12" 
Decode
+               _ = serverKeyStoreContent
+       }
+
+       return nil
 }
 
 func createDefaultConfiguration() Configuration {
diff --git a/plc4go/internal/opcua/Driver.go b/plc4go/internal/opcua/Driver.go
index b29a73fe70..66e1d96513 100644
--- a/plc4go/internal/opcua/Driver.go
+++ b/plc4go/internal/opcua/Driver.go
@@ -123,7 +123,9 @@ func (m *Driver) GetConnectionWithContext(ctx 
context.Context, transportUrl url.
        configuration.endpoint = "opc." + transportCode + "://" + transportHost 
+ ":" + transportPort + "" + transportEndpoint
 
        if configuration.securityPolicy != "" && configuration.securityPolicy 
!= "None" {
-               configuration.openKeyStore()
+               if err := configuration.openKeyStore(); err != nil {
+                       return m.reportError(errors.Wrap(err, "error opening 
key store"))
+               }
        }
 
        driverContext := NewDriverContext(configuration)
diff --git a/plc4go/internal/opcua/EncryptionHandler.go 
b/plc4go/internal/opcua/EncryptionHandler.go
index 4cb43c3de0..bdad7b63d1 100644
--- a/plc4go/internal/opcua/EncryptionHandler.go
+++ b/plc4go/internal/opcua/EncryptionHandler.go
@@ -20,34 +20,192 @@
 package opcua
 
 import (
+       "context"
+       "crypto"
+       "crypto/rand"
+       "crypto/rsa"
+       "crypto/sha256"
        "crypto/x509"
+       "encoding/binary"
+
        readWriteModel 
"github.com/apache/plc4x/plc4go/protocols/opcua/readwrite/model"
+       "github.com/apache/plc4x/plc4go/spi/utils"
+
+       "github.com/pkg/errors"
+       "github.com/rs/zerolog"
 )
 
 type EncryptionHandler struct {
-       // TODO: implement me
+       serverCertificate *x509.Certificate
+       clientCertificate *x509.Certificate
+       clientPrivateKey  *rsa.PrivateKey
+       clientPublicKey   crypto.PublicKey
+       securityPolicy    string
+
+       log zerolog.Logger
+}
+
+func NewEncryptionHandler(log zerolog.Logger, ckp *CertificateKeyPair, 
senderCertificate []byte, securityPolicy string) *EncryptionHandler {
+       e := &EncryptionHandler{
+               securityPolicy: securityPolicy,
+               log:            log,
+       }
+       if ckp != nil {
+               e.clientPrivateKey = ckp.getKeyPair()
+               e.clientPublicKey = ckp.getKeyPair().Public()
+               e.clientCertificate = ckp.getCertificate()
+       }
+       if senderCertificate != nil {
+               var err error
+               e.serverCertificate, err = 
e.getCertificateX509(senderCertificate)
+               if err != nil {
+                       e.log.Error().Err(err).Msg("error getting sender 
certificate")
+               }
+       }
+       return e
+}
+
+func (h *EncryptionHandler) encodeMessage(ctx context.Context, pdu 
readWriteModel.MessagePDU, message []byte) ([]byte, error) {
+       const PREENCRYPTED_BLOCK_LENGTH = 190
+       unencryptedLength := int(pdu.GetLengthInBytes(ctx))
+       openRequestLength := len(message)
+       positionFirstBlock := unencryptedLength - openRequestLength - 8
+       paddingSize := PREENCRYPTED_BLOCK_LENGTH - ((openRequestLength + 256 + 
1 + 8) % PREENCRYPTED_BLOCK_LENGTH)
+       preEncryptedLength := openRequestLength + 256 + 1 + 8 + paddingSize
+       if preEncryptedLength%PREENCRYPTED_BLOCK_LENGTH != 0 {
+               return nil, errors.Errorf("Pre encrypted block length %d isn't 
a multiple of the block size", preEncryptedLength)
+       }
+       numberOfBlocks := preEncryptedLength / PREENCRYPTED_BLOCK_LENGTH
+       encryptedLength := numberOfBlocks*256 + positionFirstBlock
+       buf := 
utils.NewWriteBufferByteBased(utils.WithByteOrderForByteBasedBuffer(binary.LittleEndian))
+       if err := readWriteModel.NewOpcuaAPU(pdu, 
false).SerializeWithWriteBuffer(ctx, buf); err != nil {
+               return nil, errors.Wrap(err, "error serializing")
+       }
+       paddingByte := byte(paddingSize)
+       if err := buf.WriteByte("", paddingByte); err != nil {
+               return nil, errors.Wrap(err, "error writing byte")
+       }
+       for i := 0; i < paddingSize; i++ {
+               if err := buf.WriteByte("", paddingByte); err != nil {
+                       return nil, errors.Wrap(err, "error writing byte")
+               }
+       }
+       //Writing Message Length
+       {
+               if err := buf.WriteInt32("", 32, int32(encryptedLength)); err 
!= nil {
+                       return nil, errors.Wrap(err, "error writing int32")
+               }
+               allBytes := buf.GetBytes()
+               encryptedLengthBytes := allBytes[len(allBytes)-4:]
+               allBytes = allBytes[:len(allBytes)-4]
+               allBytes = append(allBytes[:4], append(encryptedLengthBytes, 
allBytes[8:]...)...)
+               buf = 
utils.NewWriteBufferByteBased(utils.WithByteOrderForByteBasedBuffer(binary.LittleEndian))
+               if err := buf.WriteByteArray("", allBytes); err != nil {
+                       return nil, errors.Wrap(err, "error writing back bytes")
+               }
+       }
+
+       signature, err := 
h.sign(buf.GetBytes()[:unencryptedLength+paddingSize+1])
+       if err != nil {
+               return nil, errors.Wrap(err, "error signing")
+       }
+       //Write the signature to the end of the buffer
+       for _, b := range signature {
+               if err := buf.WriteByte("", b); err != nil {
+                       return nil, errors.Wrap(err, "error writing byte")
+               }
+       }
+       //buf.SetPos(uint16(positionFirstBlock))// TODO: check if we need to 
move the position at all
+       if err := h.encryptBlock(buf, 
buf.GetBytes()[positionFirstBlock:positionFirstBlock+preEncryptedLength]); err 
!= nil {
+               return nil, errors.Wrap(err, "error encrypting block")
+       }
+       return buf.GetBytes(), nil
+}
+
+func (h *EncryptionHandler) decodeMessage(ctx context.Context, pdu 
readWriteModel.OpcuaAPU) (readWriteModel.OpcuaAPU, error) {
+       h.log.Info().Msgf("Decoding Message with Security policy %s", 
h.securityPolicy)
+       switch h.securityPolicy {
+       case "None":
+               return pdu, nil
+       case "Basic256Sha256":
+               var message []byte
+               switch pduMessage := pdu.GetMessage().(type) {
+               case readWriteModel.OpcuaOpenResponseExactly:
+                       message = pduMessage.GetMessage()
+               case readWriteModel.OpcuaMessageResponseExactly:
+                       message = pduMessage.GetMessage()
+               default:
+                       return pdu, nil
+               }
+               encryptedLength := int(pdu.GetLengthInBytes(ctx))
+               encryptedMessageLength := len(message) + 8
+               headerLength := encryptedLength - encryptedMessageLength
+               buf := 
utils.NewWriteBufferByteBased(utils.WithByteOrderForByteBasedBuffer(binary.LittleEndian))
+               if err := pdu.SerializeWithWriteBuffer(ctx, buf); err != nil {
+                       return nil, errors.Wrap(err, "error serializing")
+               }
+               allBytes := buf.GetBytes()
+               data := allBytes[headerLength:encryptedLength]
+               buf = 
utils.NewWriteBufferByteBased(utils.WithByteOrderForByteBasedBuffer(binary.LittleEndian))
+               if err := buf.WriteByteArray("", allBytes[:headerLength-1]); 
err != nil {
+                       return nil, errors.Wrap(err, "error serializing")
+               }
+               if err := h.decryptBlock(buf, data); err != nil {
+                       return nil, errors.Wrap(err, "error decrypting")
+               }
+               {
+                       if err := buf.WriteInt32("", 32, 
int32(encryptedLength)); err != nil {
+                               return nil, errors.Wrap(err, "error writing 
int32")
+                       }
+                       encryptedLengthBytes := allBytes[len(allBytes)-4:]
+                       allBytes = allBytes[:len(allBytes)-4]
+                       allBytes = append(allBytes[:4], 
append(encryptedLengthBytes, allBytes[8:]...)...)
+                       buf = 
utils.NewWriteBufferByteBased(utils.WithByteOrderForByteBasedBuffer(binary.LittleEndian))
+                       if err := buf.WriteByteArray("", allBytes); err != nil {
+                               return nil, errors.Wrap(err, "error writing 
back bytes")
+                       }
+               }
+
+               readBuffer := utils.NewReadBufferByteBased(buf.GetBytes(), 
utils.WithByteOrderForReadBufferByteBased(binary.LittleEndian))
+               return readWriteModel.OpcuaAPUParseWithBuffer(ctx, readBuffer, 
true)
+       }
+       return pdu, nil
 }
 
-func NewEncryptionHandler(any, []byte, string) *EncryptionHandler {
-       return &EncryptionHandler{}
+func (h *EncryptionHandler) decryptBlock(buf utils.WriteBufferByteBased, data 
[]byte) error {
+       oaep, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, 
h.clientPrivateKey, data, nil)
+       if err != nil {
+               return errors.Wrap(err, "error DecryptOAEP")
+       }
+       return buf.WriteByteArray("", oaep)
 }
 
-func (h *EncryptionHandler) encodeMessage(messageRequest 
readWriteModel.MessagePDU, bytes []byte) []byte {
-       return nil
+func (h *EncryptionHandler) getCertificateX509(senderCertificate []byte) 
(*x509.Certificate, error) {
+       return x509.ParseCertificate(senderCertificate)
 }
 
-func (h *EncryptionHandler) decodeMessage(apu readWriteModel.OpcuaAPU) 
readWriteModel.OpcuaAPUExactly {
-       return nil
+func (h *EncryptionHandler) setServerCertificate(serverCertificate 
*x509.Certificate) {
+       h.serverCertificate = serverCertificate
 }
 
-func (h *EncryptionHandler) getCertificateX509(senderCertificate []byte) 
x509.Certificate {
-       return x509.Certificate{}
+func (h *EncryptionHandler) encryptPassword(password []byte) ([]byte, error) {
+       publicKey := h.serverCertificate.PublicKey.(rsa.PublicKey)
+       encryptOAEP, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, 
&publicKey, password, nil)
+       if err != nil {
+               return nil, errors.Wrap(err, "error EncryptOAEP")
+       }
+       return encryptOAEP, nil
 }
 
-func (h *EncryptionHandler) setServerCertificate(certificateX509 
x509.Certificate) {
-       return
+func (h *EncryptionHandler) encryptBlock(buf utils.WriteBufferByteBased, data 
[]byte) error {
+       publicKey := h.serverCertificate.PublicKey.(rsa.PublicKey)
+       encryptOAEP, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, 
&publicKey, data, nil)
+       if err != nil {
+               return errors.Wrap(err, "error EncryptOAEP")
+       }
+       return buf.WriteByteArray("", encryptOAEP)
 }
 
-func (h *EncryptionHandler) encryptPassword(password []byte) []byte {
-       return nil
+func (h *EncryptionHandler) sign(data []byte) ([]byte, error) {
+       return h.clientPrivateKey.Sign(rand.Reader, data, crypto.SHA256)
 }
diff --git a/plc4go/internal/opcua/SecureChannel.go 
b/plc4go/internal/opcua/SecureChannel.go
index cda111c59b..b17a476790 100644
--- a/plc4go/internal/opcua/SecureChannel.go
+++ b/plc4go/internal/opcua/SecureChannel.go
@@ -146,14 +146,14 @@ func NewSecureChannel(log zerolog.Logger, ctx 
DriverContext, configuration Confi
        if configuration.securityPolicy == "Basic256Sha256" {
                //Sender Certificate gets populated during the 'discover' phase 
when encryption is enabled.
                s.senderCertificate = configuration.senderCertificate
-               s.encryptionHandler = NewEncryptionHandler(ckp, 
s.senderCertificate, configuration.securityPolicy)
+               s.encryptionHandler = NewEncryptionHandler(s.log, ckp, 
s.senderCertificate, configuration.securityPolicy)
                certificate := ckp.getCertificate()
                s.publicCertificate = 
readWriteModel.NewPascalByteString(int32(len(certificate.Raw)), certificate.Raw)
                s.isEncrypted = true
 
                s.thumbprint = configuration.thumbprint
        } else {
-               s.encryptionHandler = NewEncryptionHandler(ckp, 
s.senderCertificate, configuration.securityPolicy)
+               s.encryptionHandler = NewEncryptionHandler(s.log, ckp, 
s.senderCertificate, configuration.securityPolicy)
                s.publicCertificate = NULL_BYTE_STRING
                s.thumbprint = NULL_BYTE_STRING
                s.isEncrypted = false
@@ -190,8 +190,12 @@ func (s *SecureChannel) submit(ctx context.Context, codec 
*MessageCodec, errorDi
 
        var apu readWriteModel.OpcuaAPU
        if s.isEncrypted {
-               var err error
-               apu, err = readWriteModel.OpcuaAPUParse(ctx, 
s.encryptionHandler.encodeMessage(messageRequest, buffer.GetBytes()), false)
+               message, err := s.encryptionHandler.encodeMessage(ctx, 
messageRequest, buffer.GetBytes())
+               if err != nil {
+                       errorDispatcher(err)
+                       return
+               }
+               apu, err = readWriteModel.OpcuaAPUParse(ctx, message, false)
                if err != nil {
                        errorDispatcher(err)
                        return
@@ -209,7 +213,12 @@ func (s *SecureChannel) submit(ctx context.Context, codec 
*MessageCodec, errorDi
                                        s.log.Debug().Type("type", 
message).Msg("Not relevant")
                                        return false
                                }
-                               opcuaAPU = 
s.encryptionHandler.decodeMessage(opcuaAPU)
+                               if decodedOpcuaAPU, err := 
s.encryptionHandler.decodeMessage(ctx, opcuaAPU); err != nil {
+                                       s.log.Debug().Err(err).Msg("error 
decoding")
+                                       return false
+                               } else {
+                                       opcuaAPU = 
decodedOpcuaAPU.(readWriteModel.OpcuaAPUExactly)
+                               }
                                messagePDU := opcuaAPU.GetMessage()
                                opcuaResponse, ok := 
messagePDU.(readWriteModel.OpcuaMessageResponseExactly)
                                if !ok {
@@ -230,7 +239,7 @@ func (s *SecureChannel) submit(ctx context.Context, codec 
*MessageCodec, errorDi
                        },
                        func(message spi.Message) error {
                                opcuaAPU := message.(readWriteModel.OpcuaAPU)
-                               opcuaAPU = 
s.encryptionHandler.decodeMessage(opcuaAPU)
+                               opcuaAPU, _ = 
s.encryptionHandler.decodeMessage(ctx, opcuaAPU)
                                messagePDU := opcuaAPU.GetMessage()
                                opcuaResponse := 
messagePDU.(readWriteModel.OpcuaMessageResponse)
                                if opcuaResponse.GetChunk() == (FINAL_CHUNK) {
@@ -377,7 +386,12 @@ func (s *SecureChannel) onConnectOpenSecureChannel(ctx 
context.Context, codec *M
        var apu readWriteModel.OpcuaAPU
 
        if s.isEncrypted {
-               apu, err = readWriteModel.OpcuaAPUParse(ctx, 
s.encryptionHandler.encodeMessage(openRequest, buffer.GetBytes()), false)
+               message, err := s.encryptionHandler.encodeMessage(ctx, 
openRequest, buffer.GetBytes())
+               if err != nil {
+                       s.log.Debug().Err(err).Msg("error encoding")
+                       return
+               }
+               apu, err = readWriteModel.OpcuaAPUParse(ctx, message, false)
                if err != nil {
                        s.log.Debug().Err(err).Msg("error parsing")
                        return
@@ -554,7 +568,12 @@ func (s *SecureChannel) onConnectCreateSessionRequest(ctx 
context.Context, codec
 
 func (s *SecureChannel) onConnectActivateSessionRequest(ctx context.Context, 
codec *MessageCodec, opcuaMessageResponse readWriteModel.CreateSessionResponse, 
sessionResponse readWriteModel.CreateSessionResponse) {
        s.senderCertificate = 
sessionResponse.GetServerCertificate().GetStringValue()
-       
s.encryptionHandler.setServerCertificate(s.encryptionHandler.getCertificateX509(s.senderCertificate))
+       certificate, err := 
s.encryptionHandler.getCertificateX509(s.senderCertificate)
+       if err != nil {
+               s.log.Error().Err(err).Msg("error getting certificate")
+               return
+       }
+       s.encryptionHandler.setServerCertificate(certificate)
        s.senderNonce = sessionResponse.GetServerNonce().GetStringValue()
        endpoints := make([]string, 3)
        if address, err := url.Parse(s.configuration.host); err != nil {
@@ -1297,7 +1316,12 @@ func (s *SecureChannel) keepAlive() {
                        var apu readWriteModel.OpcuaAPU
 
                        if s.isEncrypted {
-                               apu, err = readWriteModel.OpcuaAPUParse(ctx, 
s.encryptionHandler.encodeMessage(openRequest, buffer.GetBytes()), false)
+                               message, err := 
s.encryptionHandler.encodeMessage(ctx, openRequest, buffer.GetBytes())
+                               if err != nil {
+                                       s.log.Error().Err(err).Msg("error 
encoding")
+                                       return
+                               }
+                               apu, err = readWriteModel.OpcuaAPUParse(ctx, 
message, false)
                                if err != nil {
                                        s.log.Error().Err(err).Msg("error 
parsing")
                                        return
@@ -1507,7 +1531,11 @@ func (s *SecureChannel) getIdentityToken(tokenType 
readWriteModel.UserTokenType,
                encodeablePassword := make([]byte, 
4+len(passwordBytes)+len(s.senderNonce))
                n, err := encodeableBuffer.Read(encodeablePassword)
                s.log.Debug().Err(err).Int("n", n).Msg("read")
-               encryptedPassword := 
s.encryptionHandler.encryptPassword(encodeablePassword)
+               encryptedPassword, err := 
s.encryptionHandler.encryptPassword(encodeablePassword)
+               if err != nil {
+                       s.log.Error().Err(err).Msg("error encrypting password")
+                       return nil
+               }
                userNameIdentityToken := 
readWriteModel.NewUserNameIdentityToken(
                        readWriteModel.NewPascalString(s.username),
                        
readWriteModel.NewPascalByteString(int32(len(encryptedPassword)), 
encryptedPassword),

Reply via email to