Repository: gopcua/opcua
Pull request #363 (2020-08-15 20:27:18)

ua: ensure variant array dimensions are greater than zero
According to the [reference](https://reference.opcfoundation.org/v104/Core/docs/Part6/5.2.2/#5.2.2.16), all dimensions shall be specified and shall be greater than zero. So if any dimension is less than 1, return an error.

Fixes https://github.com/gopcua/opcua/issues/362, because it will ensure that the code bails before trying to split a multi-dimensional array.

What do you think @magiconair?


Patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index a542ce4..e140154 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -4,15 +4,15 @@ workflows:
   version: 2
   test:
     jobs:
+      - test-1.13
+      - test-1.13-32bit
       - test-1.14
       - test-1.14-32bit
-      - test-1.15
-      - test-1.15-32bit
 
 jobs:
-  test-1.14:
+  test-1.13:
     docker:
-      - image: 'circleci/golang:1.14'
+      - image: 'circleci/golang:1.13'
     environment:
       - GO_TEST_FLAGS: -race
     steps: &ref_0
@@ -29,21 +29,21 @@ jobs:
           key: go-mod-{{ checksum "go.sum" }}
           paths:
             - "/go/pkg/mod"
-  test-1.15:
+  test-1.14:
     docker:
-      - image: 'circleci/golang:1.15'
+      - image: 'circleci/golang:1.14'
     environment:
       - GO_TEST_FLAGS: -race
     steps: *ref_0
-  test-1.14-32bit:
+  test-1.13-32bit:
     docker:
-      - image: 'circleci/golang:1.14'
+      - image: 'circleci/golang:1.13'
     environment:
       - GOARCH: 386
     steps: *ref_0
-  test-1.15-32bit:
+  test-1.14-32bit:
     docker:
-      - image: 'circleci/golang:1.15'
+      - image: 'circleci/golang:1.14'
     environment:
       - GOARCH: 386
     steps: *ref_0
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index 81944ff..d71e93f 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -7,7 +7,7 @@ jobs:
     strategy:
       matrix:
         os: [ubuntu-latest, windows-latest]
-        go: ["1.14.x", "1.15.x"]
+        go: ["1.13.x", "1.14.x"]
 
     steps:
       - name: Setup Go ${{ matrix.go }}
diff --git a/ua/variant.go b/ua/variant.go
index 7fba8f1..72d37f1 100644
--- a/ua/variant.go
+++ b/ua/variant.go
@@ -44,7 +44,7 @@ type Variant struct {
 	// field.
 	arrayLength int32
 
-	// arrayDimensionsLength is the numer of dimensions.
+	// arrayDimensionsLength is the number of dimensions.
 	// This field is only present if the 'array dimensions' flag
 	// is set.
 	arrayDimensionsLength int32
@@ -147,7 +147,7 @@ func (m *Variant) Decode(b []byte) (int, error) {
 		m.arrayDimensions = make([]int32, m.arrayDimensionsLength)
 		for i := 0; i < int(m.arrayDimensionsLength); i++ {
 			m.arrayDimensions[i] = buf.ReadInt32()
-			if m.arrayDimensions[i] < 0 {
+			if m.arrayDimensions[i] < 1 {
 				return buf.Pos(), StatusBadEncodingLimitsExceeded
 			}
 		}
diff --git a/uapolicy/policyAes128Sha256RsaOaep.go b/uapolicy/policyAes128Sha256RsaOaep.go
index 156f4e3..26935a8 100644
--- a/uapolicy/policyAes128Sha256RsaOaep.go
+++ b/uapolicy/policyAes128Sha256RsaOaep.go
@@ -66,16 +66,15 @@ func newAes128Sha256RsaOaepSymmetric(localNonce []byte, remoteNonce []byte) (*En
 	remoteKeys := generateKeys(remoteHmac, localNonce, signatureKeyLength, encryptionKeyLength, encryptionBlockSize)
 
 	return &EncryptionAlgorithm{
-		blockSize:             AESBlockSize,
-		plainttextBlockSize:   AESBlockSize - AESMinPadding,
-		encrypt:               &AES{KeyLength: 128, IV: remoteKeys.iv, Secret: remoteKeys.encryption}, // AES128-CBC
-		decrypt:               &AES{KeyLength: 128, IV: localKeys.iv, Secret: localKeys.encryption},   // AES128-CBC
-		signature:             &HMAC{Hash: crypto.SHA256, Secret: remoteKeys.signing},                 // HMAC-SHA2-256
-		verifySignature:       &HMAC{Hash: crypto.SHA256, Secret: localKeys.signing},                  // HMAC-SHA2-256
-		signatureLength:       256 / 8,
-		remoteSignatureLength: 256 / 8,
-		encryptionURI:         "http://www.w3.org/2001/04/xmlenc#aes128-cbc",
-		signatureURI:          "http://www.w3.org/2000/09/xmldsig#hmac-sha256",
+		blockSize:           AESBlockSize,
+		plainttextBlockSize: AESBlockSize - AESMinPadding,
+		encrypt:             &AES{KeyLength: 128, IV: remoteKeys.iv, Secret: remoteKeys.encryption}, // AES128-CBC
+		decrypt:             &AES{KeyLength: 128, IV: localKeys.iv, Secret: localKeys.encryption},   // AES128-CBC
+		signature:           &HMAC{Hash: crypto.SHA256, Secret: remoteKeys.signing},                 // HMAC-SHA2-256
+		verifySignature:     &HMAC{Hash: crypto.SHA256, Secret: localKeys.signing},                  // HMAC-SHA2-256
+		signatureLength:     256 / 8,
+		encryptionURI:       "http://www.w3.org/2001/04/xmlenc#aes128-cbc",
+		signatureURI:        "http://www.w3.org/2000/09/xmldsig#hmac-sha256",
 	}, nil
 }
 
@@ -106,16 +105,15 @@ func newAes128Sha256RsaOaepAsymmetric(localKey *rsa.PrivateKey, remoteKey *rsa.P
 	}
 
 	return &EncryptionAlgorithm{
-		blockSize:             remoteKeySize,
-		plainttextBlockSize:   remoteKeySize - RSAOAEPMinPaddingSHA1,
-		encrypt:               &RSAOAEP{Hash: crypto.SHA1, PublicKey: remoteKey},    // RSA-OAEP-SHA1
-		decrypt:               &RSAOAEP{Hash: crypto.SHA1, PrivateKey: localKey},    // RSA-OAEP-SHA1
-		signature:             &PKCS1v15{Hash: crypto.SHA256, PrivateKey: localKey}, // RSA-PKCS15-SHA2-256
-		verifySignature:       &PKCS1v15{Hash: crypto.SHA256, PublicKey: remoteKey}, // RSA-PKCS15-SHA2-256
-		nonceLength:           nonceLength,
-		signatureLength:       localKeySize,
-		remoteSignatureLength: remoteKeySize,
-		encryptionURI:         "http://opcfoundation.org/ua/security/rsa-oaep-sha1",
-		signatureURI:          "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
+		blockSize:           remoteKeySize,
+		plainttextBlockSize: remoteKeySize - RSAOAEPMinPaddingSHA1,
+		encrypt:             &RSAOAEP{Hash: crypto.SHA1, PublicKey: remoteKey},    // RSA-OAEP-SHA1
+		decrypt:             &RSAOAEP{Hash: crypto.SHA1, PrivateKey: localKey},    // RSA-OAEP-SHA1
+		signature:           &PKCS1v15{Hash: crypto.SHA256, PrivateKey: localKey}, // RSA-PKCS15-SHA2-256
+		verifySignature:     &PKCS1v15{Hash: crypto.SHA256, PublicKey: remoteKey}, // RSA-PKCS15-SHA2-256
+		nonceLength:         nonceLength,
+		signatureLength:     localKeySize,
+		encryptionURI:       "http://opcfoundation.org/ua/security/rsa-oaep-sha1",
+		signatureURI:        "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
 	}, nil
 }
diff --git a/uapolicy/policyAes256Sha256RsaPss.go b/uapolicy/policyAes256Sha256RsaPss.go
index d6aec7a..d303f43 100644
--- a/uapolicy/policyAes256Sha256RsaPss.go
+++ b/uapolicy/policyAes256Sha256RsaPss.go
@@ -70,16 +70,15 @@ func newAes256Sha256RsaPssSymmetric(localNonce []byte, remoteNonce []byte) (*Enc
 	remoteKeys := generateKeys(remoteHmac, localNonce, signatureKeyLength, encryptionKeyLength, encryptionBlockSize)
 
 	return &EncryptionAlgorithm{
-		blockSize:             AESBlockSize,
-		plainttextBlockSize:   AESBlockSize - AESMinPadding,
-		encrypt:               &AES{KeyLength: 256, IV: remoteKeys.iv, Secret: remoteKeys.encryption}, // AES256-CBC
-		decrypt:               &AES{KeyLength: 256, IV: localKeys.iv, Secret: localKeys.encryption},   // AES256-CBC
-		signature:             &HMAC{Hash: crypto.SHA256, Secret: remoteKeys.signing},                 // HMAC-SHA2-256
-		verifySignature:       &HMAC{Hash: crypto.SHA256, Secret: localKeys.signing},                  // HMAC-SHA2-256
-		signatureLength:       256 / 8,
-		remoteSignatureLength: 256 / 8,
-		encryptionURI:         "http://opcfoundation.org/UA/security/rsa-oaep-sha2-256",
-		signatureURI:          "http://www.w3.org/2000/09/xmldsig#hmac-sha256",
+		blockSize:           AESBlockSize,
+		plainttextBlockSize: AESBlockSize - AESMinPadding,
+		encrypt:             &AES{KeyLength: 256, IV: remoteKeys.iv, Secret: remoteKeys.encryption}, // AES256-CBC
+		decrypt:             &AES{KeyLength: 256, IV: localKeys.iv, Secret: localKeys.encryption},   // AES256-CBC
+		signature:           &HMAC{Hash: crypto.SHA256, Secret: remoteKeys.signing},                 // HMAC-SHA2-256
+		verifySignature:     &HMAC{Hash: crypto.SHA256, Secret: localKeys.signing},                  // HMAC-SHA2-256
+		signatureLength:     256 / 8,
+		encryptionURI:       "http://opcfoundation.org/UA/security/rsa-oaep-sha2-256",
+		signatureURI:        "http://www.w3.org/2000/09/xmldsig#hmac-sha256",
 	}, nil
 }
 
@@ -110,16 +109,15 @@ func newAes256Sha256RsaPssAsymmetric(localKey *rsa.PrivateKey, remoteKey *rsa.Pu
 	}
 
 	return &EncryptionAlgorithm{
-		blockSize:             remoteKeySize,
-		plainttextBlockSize:   remoteKeySize - RSAOAEPMinPaddingSHA256,
-		encrypt:               &RSAOAEP{Hash: crypto.SHA256, PublicKey: remoteKey}, // RSA-OAEP-SHA256
-		decrypt:               &RSAOAEP{Hash: crypto.SHA256, PrivateKey: localKey}, // RSA-OAEP-SHA256
-		signature:             &RSAPSS{Hash: crypto.SHA256, PrivateKey: localKey},  // RSA-PSS-SHA2-256
-		verifySignature:       &RSAPSS{Hash: crypto.SHA256, PublicKey: remoteKey},  // RSA-PSS-SHA2-256
-		nonceLength:           nonceLength,
-		signatureLength:       localKeySize,
-		remoteSignatureLength: remoteKeySize,
-		encryptionURI:         "http://opcfoundation.org/UA/security/rsa-oaep-sha2-256",
-		signatureURI:          "http://opcfoundation.org/UA/security/rsa-pss-sha2-256",
+		blockSize:           remoteKeySize,
+		plainttextBlockSize: remoteKeySize - RSAOAEPMinPaddingSHA256,
+		encrypt:             &RSAOAEP{Hash: crypto.SHA256, PublicKey: remoteKey}, // RSA-OAEP-SHA256
+		decrypt:             &RSAOAEP{Hash: crypto.SHA256, PrivateKey: localKey}, // RSA-OAEP-SHA256
+		signature:           &RSAPSS{Hash: crypto.SHA256, PrivateKey: localKey},  // RSA-PSS-SHA2-256
+		verifySignature:     &RSAPSS{Hash: crypto.SHA256, PublicKey: remoteKey},  // RSA-PSS-SHA2-256
+		nonceLength:         nonceLength,
+		signatureLength:     localKeySize,
+		encryptionURI:       "http://opcfoundation.org/UA/security/rsa-oaep-sha2-256",
+		signatureURI:        "http://opcfoundation.org/UA/security/rsa-pss-sha2-256",
 	}, nil
 }
diff --git a/uapolicy/policyBasic128Rsa15.go b/uapolicy/policyBasic128Rsa15.go
index 05719a2..eb8bfa2 100644
--- a/uapolicy/policyBasic128Rsa15.go
+++ b/uapolicy/policyBasic128Rsa15.go
@@ -55,16 +55,15 @@ func newBasic128Rsa15Symmetric(localNonce []byte, remoteNonce []byte) (*Encrypti
 	remoteKeys := generateKeys(remoteHmac, localNonce, signatureKeyLength, encryptionKeyLength, encryptionBlockSize)
 
 	return &EncryptionAlgorithm{
-		blockSize:             AESBlockSize,
-		plainttextBlockSize:   AESBlockSize - AESMinPadding,
-		encrypt:               &AES{KeyLength: 128, IV: remoteKeys.iv, Secret: remoteKeys.encryption}, // AES128-CBC
-		decrypt:               &AES{KeyLength: 128, IV: localKeys.iv, Secret: localKeys.encryption},   // AES128-CBC
-		signature:             &HMAC{Hash: crypto.SHA1, Secret: remoteKeys.signing},                   // HMAC-SHA1
-		verifySignature:       &HMAC{Hash: crypto.SHA1, Secret: localKeys.signing},                    // HMAC-SHA1
-		signatureLength:       160 / 8,
-		remoteSignatureLength: 160 / 8,
-		encryptionURI:         "http://www.w3.org/2001/04/xmlenc#aes128-cbc",
-		signatureURI:          "http://www.w3.org/2000/09/xmldsig#hmac-sha1",
+		blockSize:           AESBlockSize,
+		plainttextBlockSize: AESBlockSize - AESMinPadding,
+		encrypt:             &AES{KeyLength: 128, IV: remoteKeys.iv, Secret: remoteKeys.encryption}, // AES128-CBC
+		decrypt:             &AES{KeyLength: 128, IV: localKeys.iv, Secret: localKeys.encryption},   // AES128-CBC
+		signature:           &HMAC{Hash: crypto.SHA1, Secret: remoteKeys.signing},                   // HMAC-SHA1
+		verifySignature:     &HMAC{Hash: crypto.SHA1, Secret: localKeys.signing},                    // HMAC-SHA1
+		signatureLength:     160 / 8,
+		encryptionURI:       "http://www.w3.org/2001/04/xmlenc#aes128-cbc",
+		signatureURI:        "http://www.w3.org/2000/09/xmldsig#hmac-sha1",
 	}, nil
 }
 
@@ -95,16 +94,15 @@ func newBasic128Rsa15Asymmetric(localKey *rsa.PrivateKey, remoteKey *rsa.PublicK
 	}
 
 	return &EncryptionAlgorithm{
-		blockSize:             remoteKeySize,
-		plainttextBlockSize:   remoteKeySize - PKCS1v15MinPadding,
-		encrypt:               &PKCS1v15{PublicKey: remoteKey},                    // RSA-SHA15+KWRSA15
-		decrypt:               &PKCS1v15{PrivateKey: localKey},                    // RSA-SHA15+KWRSA15
-		signature:             &PKCS1v15{Hash: crypto.SHA1, PrivateKey: localKey}, // RSA-SHA1
-		verifySignature:       &PKCS1v15{Hash: crypto.SHA1, PublicKey: remoteKey}, // RSA-SHA1
-		nonceLength:           nonceLength,
-		signatureLength:       localKeySize,
-		remoteSignatureLength: remoteKeySize,
-		encryptionURI:         "http://www.w3.org/2001/04/xmlenc#rsa-1_5",
-		signatureURI:          "http://www.w3.org/2000/09/xmldsig#rsa-sha1",
+		blockSize:           remoteKeySize,
+		plainttextBlockSize: remoteKeySize - PKCS1v15MinPadding,
+		encrypt:             &PKCS1v15{PublicKey: remoteKey},                    // RSA-SHA15+KWRSA15
+		decrypt:             &PKCS1v15{PrivateKey: localKey},                    // RSA-SHA15+KWRSA15
+		signature:           &PKCS1v15{Hash: crypto.SHA1, PrivateKey: localKey}, // RSA-SHA1
+		verifySignature:     &PKCS1v15{Hash: crypto.SHA1, PublicKey: remoteKey}, // RSA-SHA1
+		nonceLength:         nonceLength,
+		signatureLength:     localKeySize,
+		encryptionURI:       "http://www.w3.org/2001/04/xmlenc#rsa-1_5",
+		signatureURI:        "http://www.w3.org/2000/09/xmldsig#rsa-sha1",
 	}, nil
 }
diff --git a/uapolicy/policyBasic256.go b/uapolicy/policyBasic256.go
index a1b69ec..ac40bc1 100644
--- a/uapolicy/policyBasic256.go
+++ b/uapolicy/policyBasic256.go
@@ -54,16 +54,15 @@ func newBasic256Symmetric(localNonce []byte, remoteNonce []byte) (*EncryptionAlg
 	remoteKeys := generateKeys(remoteHmac, localNonce, signatureKeyLength, encryptionKeyLength, encryptionBlockSize)
 
 	return &EncryptionAlgorithm{
-		blockSize:             AESBlockSize,
-		plainttextBlockSize:   AESBlockSize - AESMinPadding,
-		encrypt:               &AES{KeyLength: 256, IV: remoteKeys.iv, Secret: remoteKeys.encryption}, // AES256-CBC
-		decrypt:               &AES{KeyLength: 256, IV: localKeys.iv, Secret: localKeys.encryption},   // AES256-CBC
-		signature:             &HMAC{Hash: crypto.SHA1, Secret: remoteKeys.signing},                   // HMAC-SHA1
-		verifySignature:       &HMAC{Hash: crypto.SHA1, Secret: localKeys.signing},                    // HMAC-SHA1
-		signatureLength:       160 / 8,
-		remoteSignatureLength: 160 / 8,
-		encryptionURI:         "http://www.w3.org/2001/04/xmlenc#aes256-cbc",
-		signatureURI:          "http://www.w3.org/2000/09/xmldsig#hmac-sha1",
+		blockSize:           AESBlockSize,
+		plainttextBlockSize: AESBlockSize - AESMinPadding,
+		encrypt:             &AES{KeyLength: 256, IV: remoteKeys.iv, Secret: remoteKeys.encryption}, // AES256-CBC
+		decrypt:             &AES{KeyLength: 256, IV: localKeys.iv, Secret: localKeys.encryption},   // AES256-CBC
+		signature:           &HMAC{Hash: crypto.SHA1, Secret: remoteKeys.signing},                   // HMAC-SHA1
+		verifySignature:     &HMAC{Hash: crypto.SHA1, Secret: localKeys.signing},                    // HMAC-SHA1
+		signatureLength:     160 / 8,
+		encryptionURI:       "http://www.w3.org/2001/04/xmlenc#aes256-cbc",
+		signatureURI:        "http://www.w3.org/2000/09/xmldsig#hmac-sha1",
 	}, nil
 }
 
@@ -94,16 +93,15 @@ func newBasic256Asymmetric(localKey *rsa.PrivateKey, remoteKey *rsa.PublicKey) (
 	}
 
 	return &EncryptionAlgorithm{
-		blockSize:             remoteKeySize,
-		plainttextBlockSize:   remoteKeySize - RSAOAEPMinPaddingSHA1,
-		encrypt:               &RSAOAEP{Hash: crypto.SHA1, PublicKey: remoteKey},  // RSA-OAEP
-		decrypt:               &RSAOAEP{Hash: crypto.SHA1, PrivateKey: localKey},  // RSA-OAEP
-		signature:             &PKCS1v15{Hash: crypto.SHA1, PrivateKey: localKey}, // RSA-SHA1
-		verifySignature:       &PKCS1v15{Hash: crypto.SHA1, PublicKey: remoteKey}, // RSA-SHA1
-		nonceLength:           nonceLength,
-		signatureLength:       localKeySize,
-		remoteSignatureLength: remoteKeySize,
-		encryptionURI:         "http://www.w3.org/2001/04/xmlenc#rsa-oaep",
-		signatureURI:          "http://www.w3.org/2000/09/xmldsig#rsa-sha1",
+		blockSize:           remoteKeySize,
+		plainttextBlockSize: remoteKeySize - RSAOAEPMinPaddingSHA1,
+		encrypt:             &RSAOAEP{Hash: crypto.SHA1, PublicKey: remoteKey},  // RSA-OAEP
+		decrypt:             &RSAOAEP{Hash: crypto.SHA1, PrivateKey: localKey},  // RSA-OAEP
+		signature:           &PKCS1v15{Hash: crypto.SHA1, PrivateKey: localKey}, // RSA-SHA1
+		verifySignature:     &PKCS1v15{Hash: crypto.SHA1, PublicKey: remoteKey}, // RSA-SHA1
+		nonceLength:         nonceLength,
+		signatureLength:     localKeySize,
+		encryptionURI:       "http://www.w3.org/2001/04/xmlenc#rsa-oaep",
+		signatureURI:        "http://www.w3.org/2000/09/xmldsig#rsa-sha1",
 	}, nil
 }
diff --git a/uapolicy/policyBasic256Sha256.go b/uapolicy/policyBasic256Sha256.go
index 44f77ba..297df43 100644
--- a/uapolicy/policyBasic256Sha256.go
+++ b/uapolicy/policyBasic256Sha256.go
@@ -68,16 +68,15 @@ func newBasic256Rsa256Symmetric(localNonce []byte, remoteNonce []byte) (*Encrypt
 	remoteKeys := generateKeys(remoteHmac, localNonce, signatureKeyLength, encryptionKeyLength, encryptionBlockSize)
 
 	return &EncryptionAlgorithm{
-		blockSize:             AESBlockSize,
-		plainttextBlockSize:   AESBlockSize - AESMinPadding,
-		encrypt:               &AES{KeyLength: 256, IV: remoteKeys.iv, Secret: remoteKeys.encryption}, // AES256-CBC
-		decrypt:               &AES{KeyLength: 256, IV: localKeys.iv, Secret: localKeys.encryption},   // AES256-CBC
-		signature:             &HMAC{Hash: crypto.SHA256, Secret: remoteKeys.signing},                 // HMAC-SHA2-256
-		verifySignature:       &HMAC{Hash: crypto.SHA256, Secret: localKeys.signing},                  // HMAC-SHA2-256
-		signatureLength:       256 / 8,
-		remoteSignatureLength: 256 / 8,
-		encryptionURI:         "http://www.w3.org/2001/04/xmlenc#aes256-cbc",
-		signatureURI:          "http://www.w3.org/2000/09/xmldsig#hmac-sha256",
+		blockSize:           AESBlockSize,
+		plainttextBlockSize: AESBlockSize - AESMinPadding,
+		encrypt:             &AES{KeyLength: 256, IV: remoteKeys.iv, Secret: remoteKeys.encryption}, // AES256-CBC
+		decrypt:             &AES{KeyLength: 256, IV: localKeys.iv, Secret: localKeys.encryption},   // AES256-CBC
+		signature:           &HMAC{Hash: crypto.SHA256, Secret: remoteKeys.signing},                 // HMAC-SHA2-256
+		verifySignature:     &HMAC{Hash: crypto.SHA256, Secret: localKeys.signing},                  // HMAC-SHA2-256
+		signatureLength:     256 / 8,
+		encryptionURI:       "http://www.w3.org/2001/04/xmlenc#aes256-cbc",
+		signatureURI:        "http://www.w3.org/2000/09/xmldsig#hmac-sha256",
 	}, nil
 }
 
@@ -107,16 +106,15 @@ func newBasic256Rsa256Asymmetric(localKey *rsa.PrivateKey, remoteKey *rsa.Public
 	}
 
 	return &EncryptionAlgorithm{
-		blockSize:             remoteKeySize,
-		plainttextBlockSize:   remoteKeySize - RSAOAEPMinPaddingSHA1,
-		encrypt:               &RSAOAEP{Hash: crypto.SHA1, PublicKey: remoteKey},    // RSA-OAEP
-		decrypt:               &RSAOAEP{Hash: crypto.SHA1, PrivateKey: localKey},    // RSA-OAEP
-		signature:             &PKCS1v15{Hash: crypto.SHA256, PrivateKey: localKey}, // RSA-PKCS15-SHA2-256
-		verifySignature:       &PKCS1v15{Hash: crypto.SHA256, PublicKey: remoteKey}, // RSA-PKCS15-SHA2-256
-		nonceLength:           nonceLength,
-		signatureLength:       localKeySize,
-		remoteSignatureLength: remoteKeySize,
-		encryptionURI:         "http://www.w3.org/2001/04/xmlenc#rsa-oaep",
-		signatureURI:          "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
+		blockSize:           remoteKeySize,
+		plainttextBlockSize: remoteKeySize - RSAOAEPMinPaddingSHA1,
+		encrypt:             &RSAOAEP{Hash: crypto.SHA1, PublicKey: remoteKey},    // RSA-OAEP
+		decrypt:             &RSAOAEP{Hash: crypto.SHA1, PrivateKey: localKey},    // RSA-OAEP
+		signature:           &PKCS1v15{Hash: crypto.SHA256, PrivateKey: localKey}, // RSA-PKCS15-SHA2-256
+		verifySignature:     &PKCS1v15{Hash: crypto.SHA256, PublicKey: remoteKey}, // RSA-PKCS15-SHA2-256
+		nonceLength:         nonceLength,
+		signatureLength:     localKeySize,
+		encryptionURI:       "http://www.w3.org/2001/04/xmlenc#rsa-oaep",
+		signatureURI:        "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
 	}, nil
 }
diff --git a/uapolicy/policyNone.go b/uapolicy/policyNone.go
index 13f6f6c..818f704 100644
--- a/uapolicy/policyNone.go
+++ b/uapolicy/policyNone.go
@@ -27,26 +27,24 @@ SecurityPolicy_None_Limits 		DerivedSignatureKeyLength: 0
 */
 func newNoneAsymmetric(*rsa.PrivateKey, *rsa.PublicKey) (*EncryptionAlgorithm, error) {
 	return &EncryptionAlgorithm{
-		blockSize:             NoneBlockSize,
-		plainttextBlockSize:   NoneBlockSize - NoneMinPadding,
-		encrypt:               &None{},
-		decrypt:               &None{},
-		signature:             &None{},
-		verifySignature:       &None{},
-		signatureLength:       0,
-		remoteSignatureLength: 0,
+		blockSize:           NoneBlockSize,
+		plainttextBlockSize: NoneBlockSize - NoneMinPadding,
+		encrypt:             &None{},
+		decrypt:             &None{},
+		signature:           &None{},
+		verifySignature:     &None{},
+		signatureLength:     0,
 	}, nil
 }
 
 func newNoneSymmetric([]byte, []byte) (*EncryptionAlgorithm, error) {
 	return &EncryptionAlgorithm{
-		blockSize:             NoneBlockSize,
-		plainttextBlockSize:   NoneBlockSize - NoneMinPadding,
-		encrypt:               &None{},
-		decrypt:               &None{},
-		signature:             &None{},
-		verifySignature:       &None{},
-		signatureLength:       0,
-		remoteSignatureLength: 0,
+		blockSize:           NoneBlockSize,
+		plainttextBlockSize: NoneBlockSize - NoneMinPadding,
+		encrypt:             &None{},
+		decrypt:             &None{},
+		signature:           &None{},
+		verifySignature:     &None{},
+		signatureLength:     0,
 	}, nil
 }
diff --git a/uapolicy/securitypolicy.go b/uapolicy/securitypolicy.go
index d2410e4..cb88c9c 100644
--- a/uapolicy/securitypolicy.go
+++ b/uapolicy/securitypolicy.go
@@ -62,17 +62,16 @@ func Symmetric(uri string, localNonce, remoteNonce []byte) (*EncryptionAlgorithm
 // The zero value of this struct will use SecurityPolicy#None although
 // using in this manner is discouraged for readability
 type EncryptionAlgorithm struct {
-	blockSize             int
-	plainttextBlockSize   int
-	decrypt               interface{ Decrypt([]byte) ([]byte, error) }
-	encrypt               interface{ Encrypt([]byte) ([]byte, error) }
-	signature             interface{ Signature([]byte) ([]byte, error) }
-	verifySignature       interface{ Verify([]byte, []byte) error }
-	nonceLength           int
-	signatureLength       int
-	remoteSignatureLength int
-	encryptionURI         string
-	signatureURI          string
+	blockSize           int
+	plainttextBlockSize int
+	decrypt             interface{ Decrypt([]byte) ([]byte, error) }
+	encrypt             interface{ Encrypt([]byte) ([]byte, error) }
+	signature           interface{ Signature([]byte) ([]byte, error) }
+	verifySignature     interface{ Verify([]byte, []byte) error }
+	nonceLength         int
+	signatureLength     int
+	encryptionURI       string
+	signatureURI        string
 }
 
 // BlockSize returns the underlying encryption algorithm's blocksize.
@@ -128,16 +127,11 @@ func (e *EncryptionAlgorithm) VerifySignature(message, signature []byte) error {
 	return e.verifySignature.Verify(message, signature)
 }
 
-// SignatureLength returns the length in bytes for outgoing signatures.
+// SignatureLength returns the length in bytes for the signature algorithm
 func (e *EncryptionAlgorithm) SignatureLength() int {
 	return e.signatureLength
 }
 
-// RemoteSignatureLength returns the length in bytes for incoming signatures.
-func (e *EncryptionAlgorithm) RemoteSignatureLength() int {
-	return e.remoteSignatureLength
-}
-
 // NonceLength returns the recommended nonce length in bytes for the security policy
 // Only applicable for the Asymmetric security algorithm.  Symmetric algorithms should
 // report NonceLength as zero
diff --git a/uasc/secure_channel_crypto.go b/uasc/secure_channel_crypto.go
index ebd59ba..d97654c 100644
--- a/uasc/secure_channel_crypto.go
+++ b/uasc/secure_channel_crypto.go
@@ -95,8 +95,8 @@ func (s *SecureChannel) verifyAndDecrypt(m *MessageChunk, b []byte) ([]byte, err
 		b = append(b[:headerLength], p...)
 	}
 
-	signature := b[len(b)-s.enc.RemoteSignatureLength():]
-	messageToVerify := b[:len(b)-s.enc.RemoteSignatureLength()]
+	signature := b[len(b)-s.enc.SignatureLength():]
+	messageToVerify := b[:len(b)-s.enc.SignatureLength()]
 
 	if err = s.enc.VerifySignature(messageToVerify, signature); err != nil {
 		return nil, ua.StatusBadSecurityChecksFailed


Test patch:
diff --git a/ua/variant_test.go b/ua/variant_test.go
index 422f974..0611dc1 100644
--- a/ua/variant_test.go
+++ b/ua/variant_test.go
@@ -259,7 +259,7 @@ func TestVariant(t *testing.T) {
 			},
 		},
 		{
-			Name: "ExtensionObjeject",
+			Name: "ExtensionObject",
 			Struct: MustVariant(NewExtensionObject(
 				&AnonymousIdentityToken{PolicyID: "anonymous"},
 			)),
@@ -277,7 +277,7 @@ func TestVariant(t *testing.T) {
 			},
 		},
 		{
-			Name: "ExtensionObjeject - ServerStatusDataType",
+			Name: "ExtensionObject - ServerStatusDataType",
 			Struct: MustVariant(NewExtensionObject(
 				&ServerStatusDataType{
 					StartTime:   time.Date(2019, 3, 29, 19, 45, 3, 816525000, time.UTC), // Mar 29, 2019 20:45:03.816525000 CET
@@ -450,27 +450,6 @@ func TestVariant(t *testing.T) {
 				0x01, 0x00, 0x00, 0x00,
 			},
 		},
-		{
-			Name: "[0][0][0]uint32",
-			Struct: MustVariant([][][]uint32{
-				{{}, {}},
-				{{}, {}},
-				{{}, {}},
-			}),
-			Bytes: []byte{
-				// variant encoding mask
-				0xc7,
-				// array length
-				0x00, 0x00, 0x00, 0x00,
-				// array values
-				// array dimensions length
-				0x03, 0x00, 0x00, 0x00,
-				// array dimensions
-				0x03, 0x00, 0x00, 0x00,
-				0x02, 0x00, 0x00, 0x00,
-				0x00, 0x00, 0x00, 0x00,
-			},
-		},
 	}
 	RunCodecTest(t, cases)
 }
@@ -574,9 +553,9 @@ func TestArray(t *testing.T) {
 			// array values
 			0x01, 0x00, 0x00, 0x00,
 			0x01, 0x00, 0x00, 0x00,
-			// array dimesions length
+			// array dimensions length
 			0xff, 0xff, 0xff, 0xff, // -1
-			// array dimesions
+			// array dimensions
 			0x01, 0x00, 0x00, 0x00,
 			0x01, 0x00, 0x00, 0x00,
 		}
@@ -595,9 +574,9 @@ func TestArray(t *testing.T) {
 			// array values
 			0x01, 0x00, 0x00, 0x00,
 			0x01, 0x00, 0x00, 0x00,
-			// array dimesions length
+			// array dimensions length
 			0x02, 0x00, 0x00, 0x00,
-			// array dimesions
+			// array dimensions
 			0x01, 0x00, 0x00, 0x00,
 			0xff, 0xff, 0xff, 0xff, // -1
 		}
@@ -607,6 +586,25 @@ func TestArray(t *testing.T) {
 			t.Fatalf("got error %#v want %#v", got, want)
 		}
 	})
+	t.Run("dimensions zero", func(t *testing.T) {
+		b := []byte{
+			// variant encoding mask
+			0xc7,
+			// array length
+			0x00, 0x00, 0x00, 0x00,
+			// array values
+			// array dimensions length
+			0x02, 0x00, 0x00, 0x00,
+			// array dimensions
+			0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00,
+		}
+
+		_, err := Decode(b, MustVariant([][]uint32{{}, {}}))
+		if got, want := err, StatusBadEncodingLimitsExceeded; !errors.Equal(got, want) {
+			t.Fatalf("got error %#v want %#v", got, want)
+		}
+	})
 }
 
 func TestSet(t *testing.T) {