Skip to content

Commit

Permalink
Merge pull request #10 from gemalto/update_mar_18
Browse files Browse the repository at this point in the history
Update mar 18
  • Loading branch information
astraw38 committed Mar 7, 2018
2 parents dd7ad99 + 38c1a96 commit 3d77fd6
Show file tree
Hide file tree
Showing 15 changed files with 256 additions and 138 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ coverage.xml

# Sphinx documentation
docs/_build/
_docbuild

# PyBuilder
target/
Expand Down
136 changes: 68 additions & 68 deletions README.MD
Original file line number Diff line number Diff line change
@@ -1,68 +1,68 @@
## Pycryptoki
[![Doc Status](https://readthedocs.org/projects/pycryptoki/badge/?version=latest)](http://pycryptoki.readthedocs.io/en/latest/)

Pycryptoki is a python wrapper around the PKCS11 library.

## Documentation

Latest API documentation can be found on [readthedocs](http://pycryptoki.readthedocs.io/en/latest/index.html).


## Installation

pip install git+https://github.com/gemalto/pycryptoki

## Key Generation Example

```py
from pycryptoki.default_templates import *
from pycryptoki.defines import *
from pycryptoki.key_generator import *
from pycryptoki.session_management import *
from pycryptoki.encryption import *


c_initialize_ex()
auth_session = c_open_session_ex(0) # HSM slot # in this example is 0
login_ex(auth_session, 0, 'userpin') # 0 is still the slot number, ‘userpin’ should be replaced by your password (None if PED or no challenge)

# Get some default templates
# They are simple python dictionaries, and can be modified to suit needs.
pub_template, priv_template = get_default_key_pair_template(CKM_RSA_PKCS_KEY_PAIR_GEN)

# Modifying template would look like:
pub_template[CKA_LABEL] = "RSA PKCS Pub Key"
pub_template[CKA_MODULUS_BITS] = 2048 # 2048 key size

pubkey, privkey = c_generate_key_pair_ex(auth_session, CKM_RSA_PKCS_KEY_PAIR_GEN, pub_template, priv_template)
print("Generated Private key at %s and Public key at %s" % (privkey, pubkey))

c_logout_ex(auth_session)
c_close_session_ex(auth_session)
c_finalize_ex()
```
## Verbose logging

If you want to see what calls to the C library are being performed, set pycryptoki logging to `DEBUG`:

```py
import logging
logging.basicConfig(level=logging.DEBUG)
```

## Tests

Test requirements can be installed via `pip install -r test_requirements.txt`.

Unittests can be run on any environment via:
```
py.test tests/unittests
```

Functional tests require an HSM to test against, and will actively test the integration
with the libCryptoki library. This *will* create and destroy objects on the HSM, so don't run
on a production HSM!

```
py.test tests/functional --slot=<slot_num> [--reset] [--password=<pwd>] [--copassword=<pwd>] [--user=<user>] [--loglevel=<level>]
```
## Pycryptoki
[![Doc Status](https://readthedocs.org/projects/pycryptoki/badge/?version=latest)](http://pycryptoki.readthedocs.io/en/latest/)

Pycryptoki is a python wrapper around the PKCS11 library.

## Documentation

Latest API documentation can be found on [readthedocs](http://pycryptoki.readthedocs.io/en/latest/index.html).


## Installation

pip install git+https://github.com/gemalto/pycryptoki

## Key Generation Example

```py
from pycryptoki.default_templates import *
from pycryptoki.defines import *
from pycryptoki.key_generator import *
from pycryptoki.session_management import *
from pycryptoki.encryption import *


c_initialize_ex()
auth_session = c_open_session_ex(0) # HSM slot # in this example is 0
login_ex(auth_session, 0, 'userpin') # 0 is still the slot number, ‘userpin’ should be replaced by your password (None if PED or no challenge)

# Get some default templates
# They are simple python dictionaries, and can be modified to suit needs.
pub_template, priv_template = get_default_key_pair_template(CKM_RSA_PKCS_KEY_PAIR_GEN)

# Modifying template would look like:
pub_template[CKA_LABEL] = "RSA PKCS Pub Key"
pub_template[CKA_MODULUS_BITS] = 2048 # 2048 key size

pubkey, privkey = c_generate_key_pair_ex(auth_session, CKM_RSA_PKCS_KEY_PAIR_GEN, pub_template, priv_template)
print("Generated Private key at %s and Public key at %s" % (privkey, pubkey))

c_logout_ex(auth_session)
c_close_session_ex(auth_session)
c_finalize_ex()
```
## Verbose logging

If you want to see what calls to the C library are being performed, set pycryptoki logging to `DEBUG`:

```py
import logging
logging.basicConfig(level=logging.DEBUG)
```

## Tests

Test requirements can be installed via `pip install -r test_requirements.txt`.

Unittests can be run on any environment via:
```
py.test tests/unittests
```

Functional tests require an HSM to test against, and will actively test the integration
with the libCryptoki library. This *will* create and destroy objects on the HSM, so don't run
on a production HSM!

```
py.test tests/functional --slot=<slot_num> [--reset] [--password=<pwd>] [--copassword=<pwd>] [--user=<user>] [--loglevel=<level>]
```
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@

# General information about the project.
project = u'Pycryptoki'
copyright = u'2016, Gemalto'
copyright = u'2018, Gemalto'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
Expand All @@ -61,7 +61,7 @@
# The short X.Y version.
version = '2.1'
# The full version, including alpha/beta/rc tags.
release = '2.1.0'
release = '2.1.1'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
4 changes: 4 additions & 0 deletions pycryptoki/common_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@
Utilities for pycryptoki
"""
from six import b, string_types
import logging
from _ctypes import pointer, POINTER
from ctypes import c_ulong, cast, create_string_buffer

from .cryptoki import CK_CHAR
from .defines import CKR_OK

LOG = logging.getLogger(__name__)


class CException(Exception):
"""
Expand Down Expand Up @@ -93,6 +96,7 @@ def array(self):
# If we get to this point, we have a specified size, a ctype,
# And our array is still none, but we're trying to access it.
# Therefore, we go ahead & allocate the memory
LOG.debug("Allocating %s buffer of size: %s", self.ctype, self._size.value)
self._array = (self.ctype * self._size.value)()
return cast(self._array, POINTER(self.ctype))

Expand Down
5 changes: 3 additions & 2 deletions pycryptoki/cryptoki_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,9 @@ def luna_function(*args):
return_value = late_binded_function(*args)
return return_value
except Exception as e:
raise CryptokiDLLException("Call to '%s(%s)' failed.".format(function_name,
", ".join(args)), e)
raise CryptokiDLLException("Call to '{}({})' "
"failed.".format(function_name,
", ".join([str(arg) for arg in args])), e)

luna_function.__name__ = function_name
return luna_function
16 changes: 14 additions & 2 deletions pycryptoki/daemon/rpyc_pycryptoki.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@
c_generate_key_pair, c_generate_key_pair_ex,
c_generate_key, c_generate_key_ex,
c_derive_key, c_derive_key_ex,
c_copy_object_ex, c_copy_object)
c_copy_object_ex, c_copy_object, ca_destroy_multiple_objects,
ca_destroy_multiple_objects_ex)
from pycryptoki.key_management import (ca_generatemofn, ca_generatemofn_ex,
ca_modifyusagecount, ca_modifyusagecount_ex)
from pycryptoki.key_usage import (ca_clonemofn, ca_clonemofn_ex,
Expand Down Expand Up @@ -124,7 +125,10 @@
ca_openapplicationID_ex, ca_openapplicationID,
ca_closeapplicationID, ca_closeapplicationID_ex,
ca_restart, ca_restart_ex,
ca_setapplicationID, ca_setapplicationID_ex)
ca_setapplicationID, ca_setapplicationID_ex,
c_get_slot_list, c_get_slot_list_ex,
c_get_slot_info, c_get_slot_info_ex,
c_get_info, c_get_info_ex)
from pycryptoki.sign_verify import (c_sign, c_sign_ex,
c_verify, c_verify_ex)
from pycryptoki.token_management import (c_init_token, c_init_token_ex,
Expand Down Expand Up @@ -237,6 +241,12 @@ def _rpyc_getattr(self, name):
exposed_ca_setapplicationID = staticmethod(ca_setapplicationID)
exposed_ca_restart_ex = staticmethod(ca_restart_ex)
exposed_ca_restart = staticmethod(ca_restart)
exposed_c_get_slot_list = staticmethod(c_get_slot_list)
exposed_c_get_slot_list_ex = staticmethod(c_get_slot_list_ex)
exposed_c_get_slot_info = staticmethod(c_get_slot_info)
exposed_c_get_slot_info_ex = staticmethod(c_get_slot_info_ex)
exposed_c_get_info = staticmethod(c_get_info)
exposed_c_get_info_ex = staticmethod(c_get_info_ex)

# object_attr_lookup.py
exposed_c_find_objects = staticmethod(c_find_objects)
Expand Down Expand Up @@ -362,6 +372,8 @@ def _rpyc_getattr(self, name):
exposed_ca_generatemofn_ex = staticmethod(ca_generatemofn_ex)
exposed_ca_modifyusagecount = staticmethod(ca_modifyusagecount)
exposed_ca_modifyusagecount_ex = staticmethod(ca_modifyusagecount_ex)
exposed_ca_destroy_multiple_objects = staticmethod(ca_destroy_multiple_objects)
exposed_ca_destroy_multiple_objects_ex = staticmethod(ca_destroy_multiple_objects_ex)

# key_usage.py
exposed_ca_clonemofn = staticmethod(ca_clonemofn)
Expand Down
2 changes: 2 additions & 0 deletions pycryptoki/defines.py
Original file line number Diff line number Diff line change
Expand Up @@ -994,6 +994,8 @@
CKK_CAMELLIA = 0x00000025
CKK_ARIA = 0x00000026
CKK_VENDOR_DEFINED = 0x80000000
CKK_EC_EDWARDS = (CKK_VENDOR_DEFINED + 0x12)
CKK_EC_MONTGOMERY = (CKK_VENDOR_DEFINED + 0x13)
CKC_X_509 = 0x00000000
CKC_X_509_ATTR_CERT = 0x00000001
CKC_WTLS = 0x00000002
Expand Down
40 changes: 26 additions & 14 deletions pycryptoki/encryption.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,8 @@ def do_multipart_operation(h_session,
if ret != CKR_OK:
LOG.debug("%s call on chunk %.20s (%s/%s) Failed w/ ret %s (%s)",
c_update_function.__name__,
chunk, index + 1, len(input_data_list), ret_vals_dictionary[ret], ret)
chunk, index + 1, len(input_data_list),
ret_vals_dictionary.get(ret, "Unknown retcode"), str(hex(ret)))
error = ret
break

Expand All @@ -279,7 +280,8 @@ def do_multipart_operation(h_session,
if ret != CKR_OK:
LOG.debug("%s call on chunk %.20s (%s/%s) Failed w/ ret %s (%s)",
c_update_function.__name__,
chunk, index + 1, len(input_data_list), ret_vals_dictionary[ret], ret)
chunk, index + 1, len(input_data_list),
ret_vals_dictionary.get(ret, "Unknown retcode"), str(hex(ret)))
error = ret
break

Expand All @@ -293,21 +295,31 @@ def do_multipart_operation(h_session,
CK_ULONG(MAX_BUFFER))
LOG.debug("%s call after a %s failure returned: %s (%s)",
c_finalize_function.__name__,
c_update_function.__name__, ret_vals_dictionary[ret], ret)
c_update_function.__name__,
ret_vals_dictionary.get(ret, "Unknown retcode"), str(hex(ret)))
return error, b"".join(python_data)

# Finalizing multipart decrypt operation
fin_out_data_len = CK_ULONG()
# Get buffer size for data
ret = c_finalize_function(h_session, None, byref(fin_out_data_len))
if ret != CKR_OK:
return ret, b"".join(python_data)
if output_buffer:
fin_out_data_len = CK_ULONG(max(output_buffer))
fin_out_data = create_string_buffer(b"", fin_out_data_len.value)

fin_out_data = create_string_buffer(b"", fin_out_data_len.value)
output = cast(fin_out_data, CK_BYTE_PTR)
ret = c_finalize_function(h_session, output, byref(fin_out_data_len))
if ret != CKR_OK:
return ret, b"".join(python_data)
ret = c_finalize_function(h_session, cast(fin_out_data, CK_BYTE_PTR),
byref(fin_out_data_len))
if ret != CKR_OK:
return ret, b"".join(python_data)
else:
# Finalizing multipart decrypt operation
fin_out_data_len = CK_ULONG()
# Get buffer size for data
ret = c_finalize_function(h_session, None, byref(fin_out_data_len))
if ret != CKR_OK:
return ret, b"".join(python_data)

fin_out_data = create_string_buffer(b"", fin_out_data_len.value)
output = cast(fin_out_data, CK_BYTE_PTR)
ret = c_finalize_function(h_session, output, byref(fin_out_data_len))
if ret != CKR_OK:
return ret, b"".join(python_data)

if fin_out_data_len.value > 0:
python_data.append(string_at(fin_out_data, fin_out_data_len.value))
Expand Down
2 changes: 1 addition & 1 deletion pycryptoki/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def check_luna_exception(ret, luna_function, args, kwargs):

arg_string = "({})".format("\n".join(log_list))
LOG.debug("Call to %s returned %s (%s)", luna_function,
ret_vals_dictionary.get(ret, "Unknown"), ret)
ret_vals_dictionary.get(ret, "Unknown retcode"), str(hex(ret)))
if ret != CKR_OK:
raise LunaCallException(ret, luna_function.__name__, arg_string)

Expand Down
19 changes: 17 additions & 2 deletions pycryptoki/key_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
from .attributes import Attributes
from .cryptoki import C_DeriveKey
from .cryptoki import C_DestroyObject, CK_OBJECT_HANDLE, CK_ULONG, C_GenerateKey, \
C_GenerateKeyPair, \
C_CopyObject
C_GenerateKeyPair, CA_DestroyMultipleObjects, C_CopyObject
from .default_templates import CKM_DES_KEY_GEN_TEMP, \
get_default_key_pair_template
from .defines import CKM_DES_KEY_GEN, CKM_RSA_PKCS_KEY_PAIR_GEN
from .mechanism import parse_mechanism
from .exceptions import make_error_handle_function
from .common_utils import AutoCArray


def c_destroy_object(h_session, h_object_value):
Expand All @@ -28,6 +28,21 @@ def c_destroy_object(h_session, h_object_value):

c_destroy_object_ex = make_error_handle_function(c_destroy_object)

def ca_destroy_multiple_objects(h_session, objects):
"""Delete multiple objects corresponding to given object handles
:param int h_session: Session handle
:param list objects: The handles of the objects to delete
:returns: Return code
"""
handles_count = len(objects)
handles = AutoCArray(data=objects, ctype=CK_ULONG)
ret = CA_DestroyMultipleObjects(h_session, handles_count, handles.array, byref(CK_ULONG()))
return ret


ca_destroy_multiple_objects_ex = make_error_handle_function(ca_destroy_multiple_objects)


def c_copy_object(h_session, h_object, template=None):
"""Method to call the C_CopyObject cryptoki command.
Expand Down
Loading

0 comments on commit 3d77fd6

Please sign in to comment.