Issues (20)

asyncua/crypto/security_policies.py (2 issues)

1
import logging
2
import struct
3
4
from abc import ABCMeta, abstractmethod
5
from ..ua import CryptographyNone, SecurityPolicy, MessageSecurityMode, UaError
6
7
try:
8
    from ..crypto import uacrypto
9
    CRYPTOGRAPHY_AVAILABLE = True
10
except ImportError:
11
    CRYPTOGRAPHY_AVAILABLE = False
12
13
14
POLICY_NONE_URI = 'http://opcfoundation.org/UA/SecurityPolicy#None'
15
16
17
def require_cryptography(obj):
18
    """
19
    Raise exception if cryptography module is not available.
20
    Call this function in constructors.
21
    """
22
    if not CRYPTOGRAPHY_AVAILABLE:
23
        raise UaError(f"Can't use {obj.__class__.__name__}, cryptography module is not installed")
24
25
26
class Signer(object):
27
    """
28
    Abstract base class for cryptographic signature algorithm
29
    """
30
31
    __metaclass__ = ABCMeta
32
33
    @abstractmethod
34
    def signature_size(self):
35
        pass
36
37
    @abstractmethod
38
    def signature(self, data):
39
        pass
40
41
42
class Verifier(object):
43
    """
44
    Abstract base class for cryptographic signature verification
45
    """
46
47
    __metaclass__ = ABCMeta
48
49
    @abstractmethod
50
    def signature_size(self):
51
        pass
52
53
    @abstractmethod
54
    def verify(self, data, signature):
55
        pass
56
57
58
class Encryptor(object):
59
    """
60
    Abstract base class for encryption algorithm
61
    """
62
63
    __metaclass__ = ABCMeta
64
65
    @abstractmethod
66
    def plain_block_size(self):
67
        pass
68
69
    @abstractmethod
70
    def encrypted_block_size(self):
71
        pass
72
73
    @abstractmethod
74
    def encrypt(self, data):
75
        pass
76
77
78
class Decryptor(object):
79
    """
80
    Abstract base class for decryption algorithm
81
    """
82
83
    __metaclass__ = ABCMeta
84
85
    @abstractmethod
86
    def plain_block_size(self):
87
        pass
88
89
    @abstractmethod
90
    def encrypted_block_size(self):
91
        pass
92
93
    @abstractmethod
94
    def decrypt(self, data):
95
        pass
96
97
98
class Cryptography(CryptographyNone):
99
    """
100
    Security policy: Sign or SignAndEncrypt
101
    """
102
103
    def __init__(self, mode=MessageSecurityMode.Sign):
104
        self.Signer = None
105
        self.Verifier = None
106
        self.Encryptor = None
107
        self.Decryptor = None
108
        if mode not in (MessageSecurityMode.Sign,
109
                        MessageSecurityMode.SignAndEncrypt):
110
            raise ValueError(f"unknown security mode {mode}")
111
        self.is_encrypted = (mode == MessageSecurityMode.SignAndEncrypt)
112
113
    def plain_block_size(self):
114
        """
115
        Size of plain text block for block cipher.
116
        """
117
        if self.is_encrypted:
118
            return self.Encryptor.plain_block_size()
119
        return 1
120
121
    def encrypted_block_size(self):
122
        """
123
        Size of encrypted text block for block cipher.
124
        """
125
        if self.is_encrypted:
126
            return self.Encryptor.encrypted_block_size()
127
        return 1
128
129
    def padding(self, size):
130
        """
131
        Create padding for a block of given size.
132
        plain_size = size + len(padding) + signature_size()
133
        plain_size = N * plain_block_size()
134
        """
135
        if not self.is_encrypted:
136
            return b''
137
        block_size = self.Encryptor.plain_block_size()
138
        extrapad_size = 2 if self.Encryptor.encrypted_block_size() > 256 else 1
139
        rem = (size + self.signature_size() + extrapad_size) % block_size
140
        if rem != 0:
141
            rem = block_size - rem
142
        data = bytes(bytearray([rem % 256])) * (rem + 1)
143
        if self.Encryptor.encrypted_block_size() > 256:
144
            data = data + bytes(bytearray([rem >> 8]))
145
        return data
146
147
    def min_padding_size(self):
148
        if self.is_encrypted:
149
            return 1
150
        return 0
151
152
    def signature_size(self):
153
        return self.Signer.signature_size()
154
155
    def signature(self, data):
156
        return self.Signer.signature(data)
157
158
    def vsignature_size(self):
159
        return self.Verifier.signature_size()
160
161
    def verify(self, data, sig):
162
        self.Verifier.verify(data, sig)
163
164
    def encrypt(self, data):
165
        if self.is_encrypted:
166
            if not len(data) % self.Encryptor.plain_block_size() == 0:
167
                raise ValueError
168
            return self.Encryptor.encrypt(data)
169
        return data
170
171
    def decrypt(self, data):
172
        if self.is_encrypted:
173
            return self.Decryptor.decrypt(data)
174
        return data
175
176
    def remove_padding(self, data):
177
        if self.is_encrypted:
178
            if self.Decryptor.encrypted_block_size() > 256:
179
                pad_size = struct.unpack('<h', data[-2:])[0] + 2
180
            else:
181
                pad_size = bytearray(data[-1:])[0] + 1
182
            return data[:-pad_size]
183
        return data
184
185
186
class SignerRsa(Signer):
187
188
    def __init__(self, client_pk):
189
        require_cryptography(self)
190
        self.client_pk = client_pk
191
        self.key_size = self.client_pk.key_size // 8
192
193
    def signature_size(self):
194
        return self.key_size
195
196
    def signature(self, data):
197
        return uacrypto.sign_sha1(self.client_pk, data)
198
199
200
class VerifierRsa(Verifier):
201
202
    def __init__(self, server_cert):
203
        require_cryptography(self)
204
        self.server_cert = server_cert
205
        self.key_size = self.server_cert.public_key().key_size // 8
206
207
    def signature_size(self):
208
        return self.key_size
209
210
    def verify(self, data, signature):
211
        uacrypto.verify_sha1(self.server_cert, data, signature)
212
213
214
class EncryptorRsa(Encryptor):
215
216
    def __init__(self, server_cert, enc_fn, padding_size):
217
        require_cryptography(self)
218
        self.server_cert = server_cert
219
        self.key_size = self.server_cert.public_key().key_size // 8
220
        self.encryptor = enc_fn
221
        self.padding_size = padding_size
222
223
    def plain_block_size(self):
224
        return self.key_size - self.padding_size
225
226
    def encrypted_block_size(self):
227
        return self.key_size
228
229
    def encrypt(self, data):
230
        encrypted = b''
231
        block_size = self.plain_block_size()
232
        for i in range(0, len(data), block_size):
233
            encrypted += self.encryptor(self.server_cert.public_key(),
234
                                        data[i: i + block_size])
235
        return encrypted
236
237
238
class DecryptorRsa(Decryptor):
239
240
    def __init__(self, client_pk, dec_fn, padding_size):
241
        require_cryptography(self)
242
        self.client_pk = client_pk
243
        self.key_size = self.client_pk.key_size // 8
244
        self.decryptor = dec_fn
245
        self.padding_size = padding_size
246
247
    def plain_block_size(self):
248
        return self.key_size - self.padding_size
249
250
    def encrypted_block_size(self):
251
        return self.key_size
252
253
    def decrypt(self, data):
254
        decrypted = b''
255
        block_size = self.encrypted_block_size()
256
        for i in range(0, len(data), block_size):
257
            decrypted += self.decryptor(self.client_pk,
258
                                        data[i: i + block_size])
259
        return decrypted
260
261
262
class SignerAesCbc(Signer):
263
264
    def __init__(self, key):
265
        require_cryptography(self)
266
        self.key = key
267
268
    def signature_size(self):
269
        return uacrypto.sha1_size()
270
271
    def signature(self, data):
272
        return uacrypto.hmac_sha1(self.key, data)
273
274
275
class VerifierAesCbc(Verifier):
276
277
    def __init__(self, key):
278
        require_cryptography(self)
279
        self.key = key
280
281
    def signature_size(self):
282
        return uacrypto.sha1_size()
283
284
    def verify(self, data, signature):
285
        expected = uacrypto.hmac_sha1(self.key, data)
286
        if signature != expected:
287
            raise uacrypto.InvalidSignature
288
289
290
class EncryptorAesCbc(Encryptor):
291
292
    def __init__(self, key, init_vec):
293
        require_cryptography(self)
294
        self.cipher = uacrypto.cipher_aes_cbc(key, init_vec)
295
296
    def plain_block_size(self):
297
        return self.cipher.algorithm.key_size // 8
298
299
    def encrypted_block_size(self):
300
        return self.cipher.algorithm.key_size // 8
301
302
    def encrypt(self, data):
303
        return uacrypto.cipher_encrypt(self.cipher, data)
304
305
306
class DecryptorAesCbc(Decryptor):
307
308
    def __init__(self, key, init_vec):
309
        require_cryptography(self)
310
        self.cipher = uacrypto.cipher_aes_cbc(key, init_vec)
311
312
    def plain_block_size(self):
313
        return self.cipher.algorithm.key_size // 8
314
315
    def encrypted_block_size(self):
316
        return self.cipher.algorithm.key_size // 8
317
318
    def decrypt(self, data):
319
        return uacrypto.cipher_decrypt(self.cipher, data)
320
321
322
class SignerSha256(Signer):
323
324
    def __init__(self, client_pk):
325
        require_cryptography(self)
326
        self.client_pk = client_pk
327
        self.key_size = self.client_pk.key_size // 8
328
329
    def signature_size(self):
330
        return self.key_size
331
332
    def signature(self, data):
333
        return uacrypto.sign_sha256(self.client_pk, data)
334
335
336
class VerifierSha256(Verifier):
337
338
    def __init__(self, server_cert):
339
        require_cryptography(self)
340
        self.server_cert = server_cert
341
        self.key_size = self.server_cert.public_key().key_size // 8
342
343
    def signature_size(self):
344
        return self.key_size
345
346
    def verify(self, data, signature):
347
        uacrypto.verify_sha256(self.server_cert, data, signature)
348
349
350
class SignerHMac256(Signer):
351
352
    def __init__(self, key):
353
        require_cryptography(self)
354
        self.key = key
355
356
    def signature_size(self):
357
        return uacrypto.sha256_size()
358
359
    def signature(self, data):
360
        return uacrypto.hmac_sha256(self.key, data)
361
362
363
class VerifierHMac256(Verifier):
364
365
    def __init__(self, key):
366
        require_cryptography(self)
367
        self.key = key
368
369
    def signature_size(self):
370
        return uacrypto.sha256_size()
371
372
    def verify(self, data, signature):
373
        expected = uacrypto.hmac_sha256(self.key, data)
374
        if signature != expected:
375
            raise uacrypto.InvalidSignature
376
377
378 View Code Duplication
class SecurityPolicyBasic128Rsa15(SecurityPolicy):
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
379
    """
380
    DEPRECATED, do not use anymore!
381
382
    Security Basic 128Rsa15
383
    A suite of algorithms that uses RSA15 as Key-Wrap-algorithm
384
    and 128-Bit (16 bytes) for encryption algorithms.
385
    - SymmetricSignatureAlgorithm - HmacSha1
386
      (http://www.w3.org/2000/09/xmldsig#hmac-sha1)
387
    - SymmetricEncryptionAlgorithm - Aes128
388
      (http://www.w3.org/2001/04/xmlenc#aes128-cbc)
389
    - AsymmetricSignatureAlgorithm - RsaSha1
390
      (http://www.w3.org/2000/09/xmldsig#rsa-sha1)
391
    - AsymmetricKeyWrapAlgorithm - KwRsa15
392
      (http://www.w3.org/2001/04/xmlenc#rsa-1_5)
393
    - AsymmetricEncryptionAlgorithm - Rsa15
394
      (http://www.w3.org/2001/04/xmlenc#rsa-1_5)
395
    - KeyDerivationAlgorithm - PSha1
396
      (http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512/dk/p_sha1)
397
    - DerivedSignatureKeyLength - 128 (16 bytes)
398
    - MinAsymmetricKeyLength - 1024 (128 bytes)
399
    - MaxAsymmetricKeyLength - 2048 (256 bytes)
400
    - CertificateSignatureAlgorithm - Sha1
401
402
    If a certificate or any certificate in the chain is not signed with
403
    a hash that is Sha1 or stronger then the certificate shall be rejected.
404
    """
405
406
    URI = "http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15"
407
    signature_key_size = 16
408
    symmetric_key_size = 16
409
    AsymmetricEncryptionURI = "http://www.w3.org/2001/04/xmlenc#rsa-1_5"
410
    AsymmetricSignatureURI = "http://www.w3.org/2000/09/xmldsig#rsa-sha1"
411
412
    @staticmethod
413
    def encrypt_asymmetric(pubkey, data):
414
        return uacrypto.encrypt_rsa15(pubkey, data)
415
416
    def __init__(self, server_cert, client_cert, client_pk, mode):
417
        logger = logging.getLogger(__name__)
418
        logger.warning("DEPRECATED! Do not use SecurityPolicyBasic128Rsa15 anymore!")
419
420
        require_cryptography(self)
421
        if isinstance(server_cert, bytes):
422
            server_cert = uacrypto.x509_from_der(server_cert)
423
        # even in Sign mode we need to asymmetrically encrypt secrets
424
        # transmitted in OpenSecureChannel. So SignAndEncrypt here
425
        self.asymmetric_cryptography = Cryptography(
426
            MessageSecurityMode.SignAndEncrypt)
427
        self.asymmetric_cryptography.Signer = SignerRsa(client_pk)
428
        self.asymmetric_cryptography.Verifier = VerifierRsa(server_cert)
429
        self.asymmetric_cryptography.Encryptor = EncryptorRsa(
430
            server_cert, uacrypto.encrypt_rsa15, 11)
431
        self.asymmetric_cryptography.Decryptor = DecryptorRsa(
432
            client_pk, uacrypto.decrypt_rsa15, 11)
433
        self.symmetric_cryptography = Cryptography(mode)
434
        self.Mode = mode
435
        self.server_certificate = uacrypto.der_from_x509(server_cert)
436
        self.client_certificate = uacrypto.der_from_x509(client_cert)
437
438
    def make_local_symmetric_key(self, secret, seed):
439
        key_sizes = (self.signature_key_size, self.symmetric_key_size, 16)
440
441
        (sigkey, key, init_vec) = uacrypto.p_sha1(secret, seed, key_sizes)
442
        self.symmetric_cryptography.Signer = SignerAesCbc(sigkey)
443
        self.symmetric_cryptography.Encryptor = EncryptorAesCbc(key, init_vec)
444
445
    def make_remote_symmetric_key(self, secret, seed):
446
        key_sizes = (self.signature_key_size, self.symmetric_key_size, 16)
447
448
        (sigkey, key, init_vec) = uacrypto.p_sha1(secret, seed, key_sizes)
449
        self.symmetric_cryptography.Verifier = VerifierAesCbc(sigkey)
450
        self.symmetric_cryptography.Decryptor = DecryptorAesCbc(key, init_vec)
451
452
453 View Code Duplication
class SecurityPolicyBasic256(SecurityPolicy):
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
454
    """
455
    DEPRECATED, do not use anymore!
456
457
    Security Basic 256
458
    A suite of algorithms that are for 256-Bit (32 bytes) encryption,
459
    algorithms include:
460
    - SymmetricSignatureAlgorithm - HmacSha1
461
      (http://www.w3.org/2000/09/xmldsig#hmac-sha1)
462
    - SymmetricEncryptionAlgorithm - Aes256
463
      (http://www.w3.org/2001/04/xmlenc#aes256-cbc)
464
    - AsymmetricSignatureAlgorithm - RsaSha1
465
      (http://www.w3.org/2000/09/xmldsig#rsa-sha1)
466
    - AsymmetricKeyWrapAlgorithm - KwRsaOaep
467
      (http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p)
468
    - AsymmetricEncryptionAlgorithm - RsaOaep
469
      (http://www.w3.org/2001/04/xmlenc#rsa-oaep)
470
    - KeyDerivationAlgorithm - PSha1
471
      (http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512/dk/p_sha1)
472
    - DerivedSignatureKeyLength - 192 (24 bytes)
473
    - MinAsymmetricKeyLength - 1024 (128 bytes)
474
    - MaxAsymmetricKeyLength - 2048 (256 bytes)
475
    - CertificateSignatureAlgorithm - Sha1
476
477
    If a certificate or any certificate in the chain is not signed with
478
    a hash that is Sha1 or stronger then the certificate shall be rejected.
479
    """
480
481
    URI = "http://opcfoundation.org/UA/SecurityPolicy#Basic256"
482
    signature_key_size = 24
483
    symmetric_key_size = 32
484
    AsymmetricEncryptionURI = "http://www.w3.org/2001/04/xmlenc#rsa-oaep"
485
    AsymmetricSignatureURI = "http://www.w3.org/2000/09/xmldsig#rsa-sha1"
486
487
    @staticmethod
488
    def encrypt_asymmetric(pubkey, data):
489
        return uacrypto.encrypt_rsa_oaep(pubkey, data)
490
491
    def __init__(self, server_cert, client_cert, client_pk, mode):
492
        logger = logging.getLogger(__name__)
493
        logger.warning("DEPRECATED! Do not use SecurityPolicyBasic256 anymore!")
494
495
        require_cryptography(self)
496
        if isinstance(server_cert, bytes):
497
            server_cert = uacrypto.x509_from_der(server_cert)
498
        # even in Sign mode we need to asymmetrically encrypt secrets
499
        # transmitted in OpenSecureChannel. So SignAndEncrypt here
500
        self.asymmetric_cryptography = Cryptography(
501
            MessageSecurityMode.SignAndEncrypt)
502
        self.asymmetric_cryptography.Signer = SignerRsa(client_pk)
503
        self.asymmetric_cryptography.Verifier = VerifierRsa(server_cert)
504
        self.asymmetric_cryptography.Encryptor = EncryptorRsa(
505
            server_cert, uacrypto.encrypt_rsa_oaep, 42)
506
        self.asymmetric_cryptography.Decryptor = DecryptorRsa(
507
            client_pk, uacrypto.decrypt_rsa_oaep, 42)
508
        self.symmetric_cryptography = Cryptography(mode)
509
        self.Mode = mode
510
        self.server_certificate = uacrypto.der_from_x509(server_cert)
511
        self.client_certificate = uacrypto.der_from_x509(client_cert)
512
513
    def make_local_symmetric_key(self, secret, seed):
514
        # specs part 6, 6.7.5
515
        key_sizes = (self.signature_key_size, self.symmetric_key_size, 16)
516
517
        (sigkey, key, init_vec) = uacrypto.p_sha1(secret, seed, key_sizes)
518
        self.symmetric_cryptography.Signer = SignerAesCbc(sigkey)
519
        self.symmetric_cryptography.Encryptor = EncryptorAesCbc(key, init_vec)
520
521
    def make_remote_symmetric_key(self, secret, seed):
522
523
        # specs part 6, 6.7.5
524
        key_sizes = (self.signature_key_size, self.symmetric_key_size, 16)
525
526
        (sigkey, key, init_vec) = uacrypto.p_sha1(secret, seed, key_sizes)
527
        self.symmetric_cryptography.Verifier = VerifierAesCbc(sigkey)
528
        self.symmetric_cryptography.Decryptor = DecryptorAesCbc(key, init_vec)
529
530
531
class SecurityPolicyBasic256Sha256(SecurityPolicy):
532
    """
533
    Security Basic 256Sha256
534
    A suite of algorithms that uses Sha256 as Key-Wrap-algorithm
535
    and 256-Bit (32 bytes) for encryption algorithms.
536
537
    - SymmetricSignatureAlgorithm_HMAC-SHA2-256
538
      https://tools.ietf.org/html/rfc4634
539
    - SymmetricEncryptionAlgorithm_AES256-CBC
540
      http://www.w3.org/2001/04/xmlenc#aes256-cbc
541
    - AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256
542
      http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
543
    - AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1
544
      http://www.w3.org/2001/04/xmlenc#rsa-oaep
545
    - KeyDerivationAlgorithm_P-SHA2-256
546
      http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512/dk/p_sha256
547
    - CertificateSignatureAlgorithm_RSA-PKCS15-SHA2-256
548
      http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
549
    - Basic256Sha256_Limits
550
        -> DerivedSignatureKeyLength: 256 bits
551
        -> MinAsymmetricKeyLength: 2048 bits
552
        -> MaxAsymmetricKeyLength: 4096 bits
553
        -> SecureChannelNonceLength: 32 bytes
554
    """
555
556
    URI = "http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256"
557
    signature_key_size = 32
558
    symmetric_key_size = 32
559
    AsymmetricEncryptionURI = "http://www.w3.org/2001/04/xmlenc#rsa-oaep"
560
    AsymmetricSignatureURI = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
561
562
    @staticmethod
563
    def encrypt_asymmetric(pubkey, data):
564
        return uacrypto.encrypt_rsa_oaep(pubkey, data)
565
566
    def __init__(self, peer_cert, host_cert, client_pk, mode,
567
                 permission_ruleset=None):
568
        require_cryptography(self)
569
        if isinstance(peer_cert, bytes):
570
            peer_cert = uacrypto.x509_from_der(peer_cert)
571
        # even in Sign mode we need to asymmetrically encrypt secrets
572
        # transmitted in OpenSecureChannel. So SignAndEncrypt here
573
        self.asymmetric_cryptography = Cryptography(
574
            MessageSecurityMode.SignAndEncrypt)
575
        self.asymmetric_cryptography.Signer = SignerSha256(client_pk)
576
        self.asymmetric_cryptography.Verifier = VerifierSha256(peer_cert)
577
        self.asymmetric_cryptography.Encryptor = EncryptorRsa(
578
            peer_cert, uacrypto.encrypt_rsa_oaep, 42)
579
        self.asymmetric_cryptography.Decryptor = DecryptorRsa(
580
            client_pk, uacrypto.decrypt_rsa_oaep, 42)
581
        self.symmetric_cryptography = Cryptography(mode)
582
        self.Mode = mode
583
        self.peer_certificate = uacrypto.der_from_x509(peer_cert)
584
        self.host_certificate = uacrypto.der_from_x509(host_cert)
585
        if permission_ruleset is None:
586
            from asyncua.crypto.permission_rules import SimpleRoleRuleset
587
            permission_ruleset = SimpleRoleRuleset()
588
        
589
        self.permissions = permission_ruleset
590
591
    def make_local_symmetric_key(self, secret, seed):
592
        # specs part 6, 6.7.5
593
        key_sizes = (self.signature_key_size, self.symmetric_key_size, 16)
594
595
        (sigkey, key, init_vec) = uacrypto.p_sha256(secret, seed, key_sizes)
596
        self.symmetric_cryptography.Signer = SignerHMac256(sigkey)
597
        self.symmetric_cryptography.Encryptor = EncryptorAesCbc(key, init_vec)
598
599
    def make_remote_symmetric_key(self, secret, seed):
600
601
        # specs part 6, 6.7.5
602
        key_sizes = (self.signature_key_size, self.symmetric_key_size, 16)
603
604
        (sigkey, key, init_vec) = uacrypto.p_sha256(secret, seed, key_sizes)
605
        self.symmetric_cryptography.Verifier = VerifierHMac256(sigkey)
606
        self.symmetric_cryptography.Decryptor = DecryptorAesCbc(key, init_vec)
607
608
609
def encrypt_asymmetric(pubkey, data, policy_uri):
610
    """
611
    Encrypt data with pubkey using an asymmetric algorithm.
612
    The algorithm is selected by policy_uri.
613
    Returns a tuple (encrypted_data, algorithm_uri)
614
    """
615
    for cls in [SecurityPolicyBasic256Sha256, SecurityPolicyBasic256, SecurityPolicyBasic128Rsa15]:
616
        if policy_uri == cls.URI:
617
            return (cls.encrypt_asymmetric(pubkey, data),
618
                    cls.AsymmetricEncryptionURI)
619
    if not policy_uri or policy_uri == POLICY_NONE_URI:
620
        return data, ''
621
    raise UaError(f"Unsupported security policy `{policy_uri}`")
622