HSM using label of key object in PKCS11
<p>This block of code is loading a cryptoki.so library and retrieving slot info. This is getting a list of objects in slot num. 0. I don't need to access all the keys to perform a few functions, just a specific key pair. Is there a way to get a single desired token by using the label name, object ID, or handle?</p>

<pre><code>pkcs11 = PyKCS11.PyKCS11Lib()
pkcs11.load(lib)
pkcs11.initialize()
info = pkcs11.getInfo()
i = pkcs11.getSlotInfo(0)
pkcs11.openSession(0)

print "Library manufacturerID: " + info.manufacturerID

slots = pkcs11.getSlotList()
print "Available Slots:", len(slots)

for s in slots:
try:
    i = pkcs11.getSlotInfo(s)
    print "Slot no:", s
    print format_normal % ("slotDescription", i.slotDescription.strip())
    print format_normal % ("manufacturerID", i.manufacturerID.strip())

    t = pkcs11.getTokenInfo(s)
    print "TokenInfo"
    print format_normal % ("label", t.label.strip())
    print format_normal % ("manufacturerID", t.manufacturerID.strip())
    print format_normal % ("model", t.model.strip())


    session = pkcs11.openSession(s)
    print "Opened session 0x%08X" % session.session.value()
    if pin_available:
        try:
            session.login(pin=pin)
        except:
            print "login failed, exception:", str(sys.exc_info()[1])

    objects = session.findObjects()
    print
    print "Found %d objects: %s" % (len(objects), [x.value() for x in objects])
</code></pre>

<p>The specific script i'm running only has a few commands defined, such as <code>-pin --sign --decrypt --lib</code> do i need to define a common <code>pkcs11-tool</code> such as <code>--init-token or --token-label</code> to pass it as an argument when executing my script ? Or can i directly assign a variable to the desired LabelName within the python script?</p>

<p>So from command line i'm running </p>

<p><code>$./Test.py --pin=pass</code> and getting the following</p>

<pre><code>Library manufacturerID: Safenet, Inc.                   
Available Slots: 4
Slot no: 0
  slotDescription: ProtectServer K5E:00045
  manufacturerID: SafeNet Inc.
TokenInfo
  label: CKM
  manufacturerID: SafeNet Inc.
  model: K5E:PL25
Opened session 0x00000002

Found 52 objects: [5021, 5022, 5014, 5016, 4, 5, 6, 7, 8, 9, 16, 18, 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 5313, 5314, 4982, 5325, 5326, 5328, 5329, 5331, 5332, 5335, 5018, 4962, 5020, 4963, 5357, 5358, 5360, 5361, 5363, 5364, 5366, 5367, 5369, 5370, 5372, 5373, 5375, 5376]
</code></pre>

<p>I'm ultimately trying to get only one of these objects to run some tests.For instance <code>objectID = 201603040001</code> contains a private/cert file. I want to specify this particular handle. The actual label is something like <code>000103...3A0</code>. How can I define this so I don't get the rest of the objects inside the library.</p>

<p>Here's the a list of just a couple of the HSM objects </p>

<pre><code> HANDLE LABEL                  TYPE                       OBJECT-ID
  5314 00000103000003A1       X509PublicKeyCertificate   201603040001
  5313 00000103000003A1       RSAPrivateKey              201603040001
</code></pre>

<p>I'm trying to pull just one of the Labels.</p>

<p>Here's the defined usage </p>

<pre><code>def usage():
print "Usage:", sys.argv[0],
print "[-p pin][--pin=pin]",
print "[-s slot][--slot=slot]",
print "[-c lib][--lib=lib]",
print "[-h][--help]",
print "[-o][--opensession]"

try:
opts, args = getopt.getopt(sys.argv[1:], "p:c:Sd:h:s", ["pin=", "lib=", "sign", "decrypt", "help","slot="])
except getopt.GetoptError:
# print help information and exit:
usage()
sys.exit(2)
</code></pre>

<p>I'm not aware of how I can add an argument so I can use <code>--sign</code> with just a specific label. End game I want to use <code>$./Test.py --pin=pass --sign --label "00000103000003A4"</code> or by handle <code>$./Test.py --pin=pass --sign --handle=5313</code></p>

<p><strong>UPDATED</strong> <strong>from suggested comments below. still having trouble getting attributes for rsa private key and cert. Using the specific token has worked but those objects inside of it are returning bad attribute types</strong></p>

<pre><code>   t = pkcs11.getTokenInfo(s)
    print "TokenInfo"
    if 'CKM' == t.label.decode('ascii').strip():
            tokenInfo = pkcs11.getTokenInfo(slot)
    if '00000103000003A1' == tokenInfo.label.decode('ascii').strip():
            print format_normal % ("label", t.label.strip())
            print format_normal % ("manufacturerID", t.manufacturerID.strip())
            print format_normal % ("model", t.model.strip())


            session = pkcs11.openSession(s)
    print("Opened session 0x%08X" % session.session.value())
    if pin_available:
        try:
            if (pin is None) and \
                    (PyKCS11.CKF_PROTECTED_AUTHENTICATION_PATH &amp; t.flags):
                print("\nEnter your PIN for %s on the pinpad" % t.label.strip())
            session.login(pin=pin)
        except:
            print("login failed, exception:", str(sys.exc_info()[1]))
            break

    objects = session.findObjects([(CKA_LABEL, "00000103000003A4")])
    print()
    print("Found %d objects: %s" % (len(objects), [x.value() for x in objects]))

    all_attributes = list(PyKCS11.CKA.keys())
    # only use the integer values and not the strings like 'CKM_RSA_PKCS'
    all_attributes.remove(PyKCS11.CKA_PRIVATE_EXPONENT)
    all_attributes.remove(PyKCS11.CKA_PRIME_1)
    all_attributes.remove(PyKCS11.CKA_PRIME_2)
    all_attributes.remove(PyKCS11.CKA_EXPONENT_1)
    all_attributes.remove(PyKCS11.CKA_EXPONENT_2)
    all_attributes.remove(PyKCS11.CKA_COEFFICIENT)
    all_attributes = [e for e in all_attributes if isinstance(e, int)]

          n_obj = 1
    for o in objects:
        print()
        print((red + "==================== Object: %d ====================" + normal) % o.value())
        n_obj += 1
        try:
            attributes = session.getAttributeValue(o, all_attributes)
        except PyKCS11.PyKCS11Error as e:
            continue    
        attrDict = dict(zip(all_attributes, attributes))
        if attrDict[PyKCS11.CKA_CLASS] == PyKCS11.CKO_PRIVATE_KEY \
           and attrDict[PyKCS11.CKA_KEY_TYPE] == PyKCS11.CKK_RSA:
            m = attrDict[PyKCS11.CKA_MODULUS]
            e = attrDict[PyKCS11.CKA_PUBLIC_EXPONENT]
            if m and e:
                mx = eval(b'0x' + ''.join("%02X" %c for c in m))
                ex = eval(b'0x' + ''.join("%02X" %c for c in e))
            if sign:
                try:
                    toSign = "12345678901234567890123456789012"  # 32 bytes, SHA256 digest
                    print("* Signing with object 0x%08X following data: %s" % (o.value(), toSign))
                    signature = session.sign(o, toSign)
                    sx = eval(b'0x' + ''.join("%02X" % c for c in signature))
                    print("Signature:")
                    print(dump(''.join(map(chr, signature))))
                    if m and e:
                        print("Verifying using following public key:")
                        print("Modulus:")
                        print(dump(''.join(map(chr, m))))
                        print("Exponent:")
                        print(dump(''.join(map(chr, e))))
                        decrypted = pow(sx, ex, mx)  # RSA
                        print("Decrypted:")
                        d = binascii.unhexlify(hexx(decrypted))
                        print(dump(d))
                        if toSign == d[-20:]:
                            print("*** signature VERIFIED!\n")
</code></pre>

<p><strong>the following is what prints. nothing seems to be working using the specific objects, there are no error messages</strong> </p>

<pre><code>Slot no: 0
  slotDescription: ProtectServer K5E:00045
  manufacturerID: SafeNet Inc.
TokenInfo
Opened session 0x00000002

Found 2 objects: [5328, 5329]

==================== Object: 5328 ====================

==================== Object: 5329 ====================
</code></pre>

<p>You can work only with one token by checking its label before use, e.g.:</p>

<pre><code>tokenInfo = pkcs11.getTokenInfo(slot)
if 'DesiredTokenLabel' == tokenInfo.label.decode('ascii').strip():
    # Start working with this particular token
    session = pkcs11.openSession(s)
</code></pre>

<p>You can enumerate only specific object using a template argument for the <code>findObjects</code> call, e.g.:</p>

<pre><code># get objects labelled "PRIV"
objects = session.findObjects([(CKA_LABEL, "PRIV")])

# get all private key objects
objects = session.findObjects([(CKA_CLASS, CKO_PRIVATE_KEY)])

# get all private key objects labelled "PRIV"
objects = session.findObjects([(CKA_CLASS, CKO_PRIVATE_KEY),(CKA_LABEL, "PRIV")])

# get all RSA private key objects labelled "PRIV"
objects = session.findObjects([(CKA_CLASS, CKO_PRIVATE_KEY),(CKA_KEY_TYPE, CKK_RSA),(CKA_LABEL, "PRIV")])
</code></pre>

<p>Below is an example code with hard-coded parameters:</p>

<pre><code>from PyKCS11 import *

pkcs11 = PyKCS11.PyKCS11Lib()
pkcs11.load("your module path...")
slots = pkcs11.getSlotList()
for s in slots:
    t = pkcs11.getTokenInfo(s)
    if 'CKM' == t.label.decode('ascii').strip():
        session = pkcs11.openSession(s)
        objects = session.findObjects([(CKA_LABEL, "00000103000003A1")])
        print ("Found %d objects: %s" % (len(objects), [x.value() for x in objects]))
</code></pre>

<p>Please note that it is Python 3 as I can't use PyKCS11 in Python 2.x right now.</p>

<p>Soma additional (random) notes:</p>

<ul>
<li><p>do not rely on handles -- they may (and will) be different for different program runs</p></li>
<li><p>your program's command line arguments are up to you -- you must decide yourself if your program needs arguments like <code>--token-label</code></p></li>
</ul>

<p>Disclaimer: I am not that into python so please do validate my thoughts</p>

<p>Good luck!</p>

<p>EDIT(Regarding you recent edit)></p>

<p>No error is (most probably) shown because the exception is caught and ignored:</p>

<pre><code>try:
    attributes = session.getAttributeValue(o, all_attributes)
except PyKCS11.PyKCS11Error as e:
    continue
</code></pre>

python encryption cryptography pkcs#11 hsm