diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644
index 0000000..90c2903
--- /dev/null
+++ b/tests/conftest.py
@@ -0,0 +1,246 @@
+
+import sys
+import pytest
+from binascii import hexlify
+from utils import APDUResponse, DOPrefixes, KeyType, Algorithm
+import hashlib
+
+try:
+ from cvc.asn1 import ASN1
+ from cvc import oid
+ from cvc.certificates import CVC
+ from cvc.ec_curves import ec_domain, find_curve
+except ModuleNotFoundError:
+ print('ERROR: cvc module not found! Install pycvc package.\nTry with `pip install pycvc`')
+ sys.exit(-1)
+
+try:
+ from smartcard.CardType import AnyCardType
+ from smartcard.CardRequest import CardRequest
+ from smartcard.Exceptions import CardRequestTimeoutException, CardConnectionException
+except ModuleNotFoundError:
+ print('ERROR: smarctard module not found! Install pyscard package.\nTry with `pip install pyscard`')
+ sys.exit(-1)
+
+try:
+ from cryptography.hazmat.primitives.asymmetric import ec, rsa, utils, padding
+ from cryptography.hazmat.primitives.kdf.hkdf import HKDF
+ from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
+ from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305
+ from cryptography.hazmat.primitives import hashes, serialization
+except ModuleNotFoundError:
+ print('ERROR: cryptography module not found! Install cryptography package.\nTry with `pip install cryptography`')
+ sys.exit(-1)
+
+class Device:
+ class EcDummy:
+ def __init__(self, name):
+ self.name = name
+
+ def __init__(self,pin='648219'):
+ self.__pin = pin
+ cardtype = AnyCardType()
+ try:
+ # request card insertion
+ cardrequest = CardRequest(timeout=10, cardType=cardtype)
+ self.__card = cardrequest.waitforcard()
+
+ # connect to the card and perform a few transmits
+ self.__card.connection.connect()
+
+ except CardRequestTimeoutException:
+ raise Exception('time-out: no card inserted during last 10s')
+ self.select_applet()
+
+ def select_applet(self):
+ self.__card.connection.transmit([0x00, 0xA4, 0x04, 0x00, 0xB, 0xE8, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x81, 0xC3, 0x1F, 0x02, 0x01, 0x0])
+
+ def send(self, command, cla=0x00, p1=0x00, p2=0x00, ne=None, data=None):
+ lc = []
+ dataf = []
+ if (data):
+ lc = [0x00] + list(len(data).to_bytes(2, 'big'))
+ dataf = list(data)
+ if (ne is None):
+ le = [0x00, 0x00]
+ else:
+ le = list(ne.to_bytes(2, 'big'))
+ if (isinstance(command, list) and len(command) > 1):
+ apdu = command
+ else:
+ apdu = [cla, command]
+
+ apdu = apdu + [p1, p2] + lc + dataf + le
+ try:
+ response, sw1, sw2 = self.__card.connection.transmit(apdu)
+ except CardConnectionException:
+ self.__card.connection.reconnect()
+ response, sw1, sw2 = self.__card.connection.transmit(apdu)
+
+ if (sw1 != 0x90):
+ if (sw1 == 0x63 and sw2 & 0xF0 == 0xC0):
+ pass
+ elif (sw1 == 0x6A and sw2 == 0x82):
+ self.select_applet()
+ if (sw1 == 0x90):
+ response, sw1, sw2 = self.__card.connection.transmit(apdu)
+ if (sw1 == 0x90):
+ return response
+ elif (sw1 == 0x69 and sw2 == 0x82):
+ response, sw1, sw2 = self.__card.connection.transmit([0x00, 0x20, 0x00, 0x81, len(self.__pin)] + list(self.__pin.encode()) + [0x0])
+ if (sw1 == 0x90):
+ response, sw1, sw2 = self.__card.connection.transmit(apdu)
+ if (sw1 == 0x90):
+ return response
+ raise APDUResponse(sw1, sw2)
+ return response
+
+ def get_login_retries(self):
+ self.select_applet()
+ try:
+ self.send(command=0x20, p2=0x81)
+ except APDUResponse as e:
+ if (e.sw1 == 0x63 and e.sw2 & 0xF0 == 0xC0):
+ return e.sw2 & 0x0F
+ raise e
+
+ def initialize(self, pin='648219', sopin='57621880', options=None, retries=3, dkek_shares=None, puk_auts=None, puk_min_auts=None, key_domains=None):
+ if (retries is not None and not 0 < retries <= 10):
+ raise ValueError('Retries must be in the range (0,10]')
+ if (dkek_shares is not None and not 0 <= dkek_shares <= 10):
+ raise ValueError('DKEK shares must be in the range [0,10]')
+ if ((puk_auts is not None and puk_min_auts is None) or (puk_auts is None and puk_min_auts is not None)):
+ raise ValueError('PUK Auts and PUK Min Auts must be specified both')
+ if (puk_auts is not None and not 0 < puk_auts <= 8):
+ raise ValueError('PUK Auts must be in the range (0,8]')
+ if (puk_min_auts is not None and not 0 < puk_min_auts <= 8):
+ raise ValueError('PUK Min Auts must be in the range (0,8]')
+ if (puk_auts is not None and puk_min_auts is not None and puk_min_auts > puk_auts):
+ raise ValueError('PUK Min Auts must be less or equal to PUK Auts')
+ if (key_domains is not None and not 0 < key_domains <= 8):
+ raise ValueError('Key Domains must be in the range (0,8]')
+
+ a = ASN1()
+ if (pin is not None):
+ a = a.add_tag(0x81, pin.encode())
+ if (sopin is not None):
+ a = a.add_tag(0x82, sopin.encode())
+ if (retries is not None):
+ a = a.add_tag(0x91, bytes([retries]))
+ if (dkek_shares is not None):
+ a = a.add_tag(0x92, bytes([dkek_shares]))
+ if (puk_auts is not None and puk_min_auts is not None):
+ a = a.add_tag(0x93, bytes([puk_auts, puk_min_auts]))
+ if (key_domains is not None):
+ a = a.add_tag(0x97, bytes([key_domains]))
+
+ data = a.encode()
+
+ self.send(cla=0x80, command=0x50, data=data)
+
+ def login(self, pin=None):
+ if (pin is None):
+ pin = self.__pin
+ self.send(command=0x20, p2=0x81, data=pin.encode())
+
+ def get_first_free_id(self):
+ kids = self.list_keys(prefix=DOPrefixes.KEY_PREFIX)
+ mset = set(range(max(kids)))-set(kids)
+ if (len(mset) > 0):
+ return min(mset)
+ if (max(kids) == 255):
+ raise ValueError('Max number of key id reached')
+ return max(kids)+1
+
+ def list_keys(self, prefix=None):
+ resp = self.send(command=0x58)
+ if (prefix is not None):
+ grouped = [(resp[i],resp[i+1]) for i in range(0, len(resp), 2) if resp[i] == prefix.value]
+ _, kids = zip(*grouped)
+ return kids
+ return [(resp[i],resp[i+1]) for i in range(0, len(resp), 2)]
+
+ def keypair_generation(self, type, param):
+ a = ASN1().add_tag(0x5f29, bytes([0])).add_tag(0x42, 'UTCA00001'.encode())
+ if (type == KeyType.RSA):
+ if (not 1024 <= param <= 4096):
+ raise ValueError('RSA bits must be in the range [1024,4096]')
+ a.add_tag(0x7f49, ASN1().add_oid(oid.ID_TA_RSA_V1_5_SHA_256).add_tag(0x2, param.to_bytes(2, 'big')).encode())
+ elif (type == KeyType.ECC):
+ if (param not in ('secp192r1', 'secp256r1', 'secp384r1', 'secp521r1', 'brainpoolP256r1', 'brainpoolP384r1', 'brainpoolP512r1', 'secp192k1', 'secp256k1')):
+ raise ValueError('Wrong elliptic curve name')
+
+ dom = ec_domain(Device.EcDummy(param))
+ pubctx = [dom.P, dom.A, dom.B, dom.G, dom.O, None, dom.F]
+ a.add_object(0x7f49, oid.ID_TA_ECDSA_SHA_256, pubctx)
+ a.add_tag(0x5f20, 'UTCDUMMY00001'.encode())
+ data = a.encode()
+
+ keyid = self.get_first_free_id()
+ self.send(command=0x46, p1=keyid, data=list(data))
+ return keyid
+
+ def delete_file(self, fid):
+ self.send(command=0xE4, data=[fid >> 8, fid & 0xff])
+
+ def public_key(self, type, keyid, param=None):
+ response = self.send(command=0xB1, p1=0xCE, p2=keyid, data=[0x54, 0x02, 0x00, 0x00])
+
+ cert = bytearray(response)
+ roid = CVC().decode(cert).pubkey().oid()
+ if (roid == oid.ID_TA_ECDSA_SHA_256):
+ curve = find_curve(ec_domain(Device.EcDummy(param)).P)
+ Y = bytes(CVC().decode(cert).pubkey().find(0x86).data())
+ return ec.EllipticCurvePublicKey.from_encoded_point(
+ curve,
+ Y,
+ )
+ elif (roid == oid.ID_TA_RSA_V1_5_SHA_256):
+ n = int.from_bytes(bytes(CVC().decode(cert).pubkey().find(0x81).data()), 'big')
+ e = int.from_bytes(bytes(CVC().decode(cert).pubkey().find(0x82).data()), 'big')
+ return rsa.RSAPublicNumbers(e, n).public_key()
+ return None
+
+ def sign(self, keyid, scheme, data):
+ resp = self.send(cla=0x80, command=0x68, p1=keyid, p2=scheme.value, data=data)
+ return resp
+
+ def verify(self, pubkey, data, signature, scheme):
+ if (Algorithm.ALGO_EC_RAW.value <= scheme.value <= Algorithm.ALGO_EC_SHA512.value):
+ if (scheme == Algorithm.ALGO_EC_SHA1):
+ hsh = hashes.SHA1()
+ elif (scheme == Algorithm.ALGO_EC_SHA224):
+ hsh = hashes.SHA224()
+ elif (scheme == Algorithm.ALGO_EC_SHA256):
+ hsh = hashes.SHA256()
+ elif (scheme == Algorithm.ALGO_EC_RAW):
+ hsh = utils.Prehashed(hashes.SHA512())
+ elif (scheme == Algorithm.ALGO_EC_SHA384):
+ hsh = hashes.SHA384()
+ elif (scheme == Algorithm.ALGO_EC_SHA512):
+ hsh = hashes.SHA512()
+ return pubkey.verify(signature, data, ec.ECDSA(hsh))
+ elif (Algorithm.ALGO_RSA_PKCS1_SHA1.value <= scheme.value <= Algorithm.ALGO_RSA_PSS_SHA512.value):
+ if (scheme == Algorithm.ALGO_RSA_PKCS1_SHA1 or scheme == Algorithm.ALGO_RSA_PSS_SHA1):
+ hsh = hashes.SHA1()
+ elif (scheme == Algorithm.ALGO_RSA_PKCS1_SHA224 or scheme == Algorithm.ALGO_RSA_PSS_SHA224):
+ hsh = hashes.SHA224()
+ elif (scheme == Algorithm.ALGO_RSA_PKCS1_SHA256 or scheme == Algorithm.ALGO_RSA_PSS_SHA256):
+ hsh = hashes.SHA256()
+ elif (scheme == Algorithm.ALGO_RSA_PKCS1_SHA384 or scheme == Algorithm.ALGO_RSA_PSS_SHA384):
+ hsh = hashes.SHA384()
+ elif (scheme == Algorithm.ALGO_RSA_PKCS1_SHA512 or scheme == Algorithm.ALGO_RSA_PSS_SHA512):
+ hsh = hashes.SHA512()
+ if (Algorithm.ALGO_RSA_PKCS1_SHA1.value <= scheme.value <= Algorithm.ALGO_RSA_PKCS1_SHA512.value):
+ padd = padding.PKCS1v15()
+ elif (Algorithm.ALGO_RSA_PSS_SHA1.value <= scheme.value <= Algorithm.ALGO_RSA_PSS_SHA512.value):
+ padd = padding.PSS(
+ mgf=padding.MGF1(hsh),
+ salt_length=padding.PSS.AUTO
+ )
+ return pubkey.verify(signature, data, padd, hsh)
+
+@pytest.fixture(scope="session")
+def device():
+ dev = Device()
+ return dev
diff --git a/tests/pico-hsm/test_keypair_gen.py b/tests/pico-hsm/test_keypair_gen.py
new file mode 100644
index 0000000..ff8f120
--- /dev/null
+++ b/tests/pico-hsm/test_keypair_gen.py
@@ -0,0 +1,40 @@
+"""
+/*
+ * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
+ * Copyright (c) 2022 Pol Henarejos.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+"""
+
+import pytest
+from utils import KeyType, DOPrefixes
+
+@pytest.mark.parametrize(
+ "curve", ['secp192r1', 'secp256r1', 'secp384r1', 'secp521r1', 'brainpoolP256r1', 'brainpoolP384r1', 'brainpoolP512r1', 'secp192k1', 'secp256k1']
+)
+def test_gen_ecc(device, curve):
+ keyid = device.keypair_generation(KeyType.ECC, curve)
+ resp = device.list_keys()
+ assert((DOPrefixes.KEY_PREFIX.value, keyid) in resp)
+ device.delete_file(DOPrefixes.KEY_PREFIX.value << 8 | keyid)
+
+@pytest.mark.parametrize(
+ "modulus", [1024, 2048, 4096]
+)
+def test_gen_rsa(device, modulus):
+ keyid = device.keypair_generation(KeyType.RSA, modulus)
+ resp = device.list_keys()
+ assert((DOPrefixes.KEY_PREFIX.value, keyid) in resp)
+ device.delete_file(DOPrefixes.KEY_PREFIX.value << 8 | keyid)
+
diff --git a/tests/pico-hsm/test_pin.py b/tests/pico-hsm/test_pin.py
new file mode 100644
index 0000000..2e96a0e
--- /dev/null
+++ b/tests/pico-hsm/test_pin.py
@@ -0,0 +1,48 @@
+"""
+/*
+ * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
+ * Copyright (c) 2022 Pol Henarejos.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+"""
+
+import pytest
+from utils import APDUResponse, SWCodes
+
+PIN = '648219'
+
+def test_pin(device):
+ device.initialize(retries=3)
+ retries = device.get_login_retries()
+ assert(retries == 3)
+
+ device.login(PIN)
+
+ with pytest.raises(APDUResponse) as e:
+ device.login('112233')
+ assert(e.value.sw1 == 0x63 and e.value.sw2 == 0xC2)
+
+ with pytest.raises(APDUResponse) as e:
+ device.login('112233')
+ assert(e.value.sw1 == 0x63 and e.value.sw2 == 0xC1)
+
+ with pytest.raises(APDUResponse) as e:
+ device.login('112233')
+ assert(e.value.sw == SWCodes.SW_PIN_BLOCKED.value)
+
+ device.initialize(retries=3)
+ retries = device.get_login_retries()
+ assert(retries == 3)
+
+
diff --git a/tests/pico-hsm/test_signature.py b/tests/pico-hsm/test_signature.py
new file mode 100644
index 0000000..4c88742
--- /dev/null
+++ b/tests/pico-hsm/test_signature.py
@@ -0,0 +1,57 @@
+"""
+/*
+ * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
+ * Copyright (c) 2022 Pol Henarejos.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+"""
+
+import pytest
+from utils import KeyType, DOPrefixes, Algorithm
+from binascii import hexlify
+import hashlib
+
+data = b'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam neque urna, iaculis quis auctor scelerisque, auctor ut risus. In rhoncus, odio consequat consequat ultrices, ex libero dictum risus, accumsan interdum nisi orci ac neque. Ut vitae sem in metus hendrerit facilisis. Mauris maximus tristique mi, quis blandit lectus convallis eget.'
+
+
+@pytest.mark.parametrize(
+ "curve", ['secp192r1', 'secp256r1', 'secp384r1', 'secp521r1',]
+)
+@pytest.mark.parametrize(
+ "scheme", [Algorithm.ALGO_EC_RAW, Algorithm.ALGO_EC_SHA1, Algorithm.ALGO_EC_SHA224, Algorithm.ALGO_EC_SHA256, Algorithm.ALGO_EC_SHA384, Algorithm.ALGO_EC_SHA512]
+)
+def test_signature_ecc(device, curve, scheme):
+ keyid = device.keypair_generation(KeyType.ECC, curve)
+ pubkey = device.public_key(type=KeyType.ECC, keyid=keyid, param=curve)
+ if (scheme == Algorithm.ALGO_EC_RAW):
+ datab = hashlib.sha512(data).digest()
+ else:
+ datab = data
+ signature = device.sign(keyid=keyid, scheme=scheme, data=datab)
+ device.delete_file(DOPrefixes.KEY_PREFIX.value << 8 | keyid)
+ device.verify(pubkey, datab, signature, scheme)
+
+@pytest.mark.parametrize(
+ "modulus", [1024,2048]
+)
+@pytest.mark.parametrize(
+ "scheme", [Algorithm.ALGO_RSA_PKCS1_SHA1, Algorithm.ALGO_RSA_PKCS1_SHA224, Algorithm.ALGO_RSA_PKCS1_SHA256, Algorithm.ALGO_RSA_PKCS1_SHA384, Algorithm.ALGO_RSA_PKCS1_SHA512, Algorithm.ALGO_RSA_PSS_SHA1, Algorithm.ALGO_RSA_PSS_SHA224, Algorithm.ALGO_RSA_PSS_SHA256, Algorithm.ALGO_RSA_PSS_SHA384, Algorithm.ALGO_RSA_PSS_SHA512]
+)
+def test_signature_rsa(device, modulus, scheme):
+ keyid = device.keypair_generation(KeyType.RSA, modulus)
+ pubkey = device.public_key(type=KeyType.RSA, keyid=keyid)
+ signature = device.sign(keyid=keyid, scheme=scheme, data=data)
+ device.delete_file(DOPrefixes.KEY_PREFIX.value << 8 | keyid)
+ device.verify(pubkey, data, signature, scheme)
+
diff --git a/tests/utils.py b/tests/utils.py
new file mode 100644
index 0000000..4923507
--- /dev/null
+++ b/tests/utils.py
@@ -0,0 +1,120 @@
+"""
+/*
+ * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
+ * Copyright (c) 2022 Pol Henarejos.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+"""
+
+from enum import Enum
+
+class SWCodes(Enum):
+ SW_BYTES_REMAINING_00 = 0x6100
+ SW_WARNING_STATE_UNCHANGED = 0x6200
+ SW_WARNING_CORRUPTED = 0x6281
+ SW_WARNING_EOF = 0x6282
+ SW_WARNING_EF_DEACTIVATED = 0x6283
+ SW_WARNING_WRONG_FCI = 0x6284
+ SW_WARNING_EF_TERMINATED = 0x6285
+
+ SW_WARNING_NOINFO = 0x6300
+ SW_WARNING_FILLUP = 0x6381
+
+ SW_EXEC_ERROR = 0x6400
+
+ SW_SECURE_MESSAGE_EXEC_ERROR = 0x6600
+
+ SW_WRONG_LENGTH = 0x6700
+
+ SW_LOGICAL_CHANNEL_NOT_SUPPORTED = 0x6881
+ SW_SECURE_MESSAGING_NOT_SUPPORTED = 0x6882
+
+ SW_COMMAND_INCOMPATIBLE = 0x6981
+ SW_SECURITY_STATUS_NOT_SATISFIED = 0x6982
+ SW_PIN_BLOCKED = 0x6983
+ SW_DATA_INVALID = 0x6984
+ SW_CONDITIONS_NOT_SATISFIED = 0x6985
+ SW_COMMAND_NOT_ALLOWED = 0x6986
+ SW_SECURE_MESSAGING_MISSING_DO = 0x6987
+ SW_SECURE_MESSAGING_INCORRECT_DO = 0x6988
+ SW_APPLET_SELECT_FAILED = 0x6999
+
+ SW_INCORRECT_PARAMS = 0x6A80
+ SW_FUNC_NOT_SUPPORTED = 0x6A81
+ SW_FILE_NOT_FOUND = 0x6A82
+ SW_RECORD_NOT_FOUND = 0x6A83
+ SW_FILE_FULL = 0x6A84
+ SW_WRONG_NE = 0x6A85
+ SW_INCORRECT_P1P2 = 0x6A86
+ SW_WRONG_NC = 0x6A87
+ SW_REFERENCE_NOT_FOUND = 0x6A88
+ SW_FILE_EXISTS = 0x6A89
+
+ SW_WRONG_P1P2 = 0x6B00
+
+ SW_CORRECT_LENGTH_00 = 0x6C00
+
+ SW_INS_NOT_SUPPORTED = 0x6D00
+
+ SW_CLA_NOT_SUPPORTED = 0x6E00
+
+ SW_UNKNOWN = 0x6F00
+
+ SW_OK = 0x900
+
+class APDUResponse(Exception):
+ def __init__(self, sw1, sw2):
+ self.sw1 = sw1
+ self.sw2 = sw2
+ self.sw = sw1 << 8 | sw2
+ super().__init__(f'SW:{sw1:02X}{sw2:02X}')
+
+class DOPrefixes(Enum):
+ PRKD_PREFIX = 0xC4
+ CD_PREFIX = 0xC8
+ DCOD_PREFIX = 0xC9
+ CA_CERTIFICATE_PREFIX = 0xCA
+ KEY_PREFIX = 0xCC
+ PROT_DATA_PREFIX = 0xCD
+ EE_CERTIFICATE_PREFIX = 0xCE
+ DATA_PREFIX = 0xCF
+
+class KeyType(Enum):
+ RSA = 1
+ ECC = 2
+
+class Algorithm(Enum):
+ ALGO_EC_RAW = 0x70
+ ALGO_EC_SHA1 = 0x71
+ ALGO_EC_SHA224 = 0x72
+ ALGO_EC_SHA256 = 0x73
+ ALGO_EC_SHA384 = 0x74
+ ALGO_EC_SHA512 = 0x75
+
+ ALGO_RSA_RAW = 0x20
+ ALGO_RSA_DECRYPT = 0x21
+ ALGO_RSA_DECRYPT_PKCS1 = 0x22
+ ALGO_RSA_DECRYPT_OEP = 0x23
+ ALGO_RSA_PKCS1 = 0x30
+ ALGO_RSA_PKCS1_SHA1 = 0x31
+ ALGO_RSA_PKCS1_SHA224 = 0x32
+ ALGO_RSA_PKCS1_SHA256 = 0x33
+ ALGO_RSA_PKCS1_SHA384 = 0x34
+ ALGO_RSA_PKCS1_SHA512 = 0x35
+ ALGO_RSA_PSS = 0x40
+ ALGO_RSA_PSS_SHA1 = 0x41
+ ALGO_RSA_PSS_SHA224 = 0x42
+ ALGO_RSA_PSS_SHA256 = 0x43
+ ALGO_RSA_PSS_SHA384 = 0x44
+ ALGO_RSA_PSS_SHA512 = 0x45