linotp.lib.security.pkcs11 module

This Security module (hsm) is used to access hardware security modules via PKCS11 for encrypting and decrypting the data

linotp.ini: linotpActiveSecurityModule = lunasa linotpSecurity.lunasa.module = linotp.lib.security.pkcs11.Pkcs11SecurityModule linotpSecurity.lunasa.library = libCryptoki2_64.so linotpSecurity.lunasa.tokenHandle =21 linotpSecurity.lunasa.valueHandle =22 linotpSecurity.lunasa.configHandle =23 linotpSecurity.lunasa.defaultHandle =22 linotpSecurity.lunasa.configLabel = config linotpSecurity.lunasa.tokenLabel = token linotpSecurity.lunasa.valueLabel = value linotpSecurity.lunasa.password = 6SNq-L9WL-SSW4-NGNL linotpSecurity.lunasa.slotid = 1 linotpActiveSecurityModule = lunasa

class linotp.lib.security.pkcs11.CK_ATTRIBUTE

Bases: Structure

pValue

Structure/Union member

type

Structure/Union member

ulValueLen

Structure/Union member

class linotp.lib.security.pkcs11.CK_MECHANISM

Bases: Structure

mechanism

Structure/Union member

pParameter

Structure/Union member

usParameterLen

Structure/Union member

class linotp.lib.security.pkcs11.CK_TOKEN_INFO

Bases: Structure

firmwareVersion

Structure/Union member

flags

Structure/Union member

hardwareVersion

Structure/Union member

label

Structure/Union member

manufacturerID

Structure/Union member

model

Structure/Union member

serialNumber

Structure/Union member

ulFreePrivateMemory

Structure/Union member

ulFreePublicMemory

Structure/Union member

ulMaxPinLen

Structure/Union member

ulMaxRwSessionCount

Structure/Union member

ulMaxSessionCount

Structure/Union member

ulMinPinLen

Structure/Union member

ulRwSessionCount

Structure/Union member

ulSessionCount

Structure/Union member

ulTotalPrivateMemory

Structure/Union member

ulTotalPublicMemory

Structure/Union member

utcTime

Structure/Union member

class linotp.lib.security.pkcs11.CK_VERSION

Bases: Structure

major

Structure/Union member

minor

Structure/Union member

class linotp.lib.security.pkcs11.Pkcs11SecurityModule(config=None, add_conf=None)

Bases: DefaultSecurityModule

Class that handles all AES stuff

createAES(label: bytes, ks: int = 32) c_ulong

Creates a new AES key with the given label and the given length

returns the handle

decrypt(value: bytes, iv: bytes, id: int = 0) bytes

decrypts the given data, using the IV and the key specified by the handle lookup id

Parameters
  • data – the encrypted input data

  • iv – the initialisation vector

  • id – id in handle dict - possible id’s are: 0,1,2

Returns

the decrypted (unpadded) data

decryptPassword(cryptPass: str) bytes

dedicated security module methods: decryptPassword which used one slot id to decryt a string

Parameters

cryptPassword (byte string) – the crypted password - leading iv, seperated by the ‘:’

Returns

decrypted data

Return type

byte string

decryptPin(cryptPin: str) bytes

dedicated security module methods: decryptPin which used one slot id to decryt a string

Parameters

cryptPin (byte string) – the crypted pin - - leading iv, seperated by the ‘:’

Returns

decrypted data

Return type

byte string

encrypt(data: bytes, iv: bytes, id: int = 0) bytes

encrypts the given input data

AES CBC works with a blocksize of 16 byte. Thus data must be a multiple of 16 bytes. This is as well required for the IV.

Note: AES_ECB does not require an IV

Parameters
  • data – the to-be-encrypted data

  • iv – the initialisation vector

  • id – id in handle dict - possible id’s are: 0,1,2

Returns

the encrypted byte string

encryptPassword(password: bytes) str

dedicated security module methods: encryptPassword which used one slot id to encrypt a string

Parameters

password (byte string) – the to be encrypted password

Returns

encrypted data - leading iv, seperated by the ‘:’

Return type

byte string

encryptPin(pin: bytes, iv: Optional[bytes] = None) str

dedicated security module methods: encryptPin which used one slot id to encrypt a string

Parameters
  • pin (byte string) – the to be encrypted pin

  • iv (buffer (20 bytes random)) – initialisation vector (optional)

Returns

encrypted data - leading iv, seperated by the ‘:’

Return type

byte string

find_aes_keys(label='testAES', wanted=1)

Find and AES key with the given label

The number of keys to be found is restricted by “wanted” finding aes keys is done by setting some search attributes when searching for objects. the search attributes which describe an aes key are:

type, class, public accessible, belonging to the current token, usable for encryption / decryption

Parameters
  • label – the label of the aes key

  • wanted – number of maximum returned key

Returns

if wanted == 1 return 0 or the last in list else return list of aes keys

gettokeninfo(slotid=0)

This returns a dictionary with the token info

initpkcs11()

Initialize the PKCS11 library

isReady()

provides the status, if the security module is fully initializes this is required especially for the runtime confi like set password ++

Returns

status, if the module is fully operational

Return type

boolean

login(password=None, slotid=0)

Open a session on the first token

After this, we got a self.hSession

logout()

closes the existing session

number_or_null = {'anyOf': [{'type': 'number'}, {'type': 'null'}]}
pad(unpadded_str, block=16)

PKCS7 padding pads the missing bytes with the value of the number of the bytes. If 4 bytes are missing, this missing bytes are filled with 

Parameters
  • unpadded_str (bytes) – The byte string to pad

  • block (int) – Block size

Returns

padded byte string

Return type

bytes

populate_handles()

In a HA Group of LunaSAs the handle do not exist. They first need to be populated

The Label overwrites the handles!

random(l: int = 32) bytes

create a random value and return it l specifies the length of the random data to be created.

schema = {'properties': {'configHandle': {'anyOf': [{'type': 'number'}, {'type': 'null'}]}, 'configLabel': {'type': 'string'}, 'defaultHandle': {'anyOf': [{'type': 'number'}, {'type': 'null'}]}, 'defaultLabel': {'type': 'string'}, 'library': {'type': 'string'}, 'module': {'type': 'string'}, 'password': {'type': 'string'}, 'poolsize': {'type': 'number'}, 'slotid': {'type': 'number'}, 'tokenHandle': {'anyOf': [{'type': 'number'}, {'type': 'null'}]}, 'tokenLabel': {'type': 'string'}, 'valueHandle': {'anyOf': [{'type': 'number'}, {'type': 'null'}]}, 'valueLabel': {'type': 'string'}}, 'required': ['module', 'library', 'password', 'slotid', 'defaultLabel'], 'type': 'object'}
setup_module(params)

used to set the password, if the password is not contained in the config file

unpad(padded_byte_str: bytes, block_size: int = 16) bytes

PKCS7 padding pads the missing bytes with the value of the number of the bytes. If 4 bytes are missing, this missing bytes are filled with 

unpad removes and checks the PKCS #7 padding by verifying that the padding byte string only contains the pad chars

Parameters
  • padded_byte_str – The binary string to unpad

  • block_size – Block size

Raises

ValueError – If padded_byte_str is not correctly padded a ValueError can be raised. This depends on the ‘pkcs11.accept_invalid_padding’ LinOTP config option. If set to False (default) ValueError is raised. The reason why the data is sometimes incorrectly padded is because the pad() method delivered with LinOTP version < 2.7.1 didn’t pad correctly when the data-length was a multiple of the block-length. Beware that in some cases (statistically about 0.4% of data-chunks whose length is a multiple of the block length) the incorrect padding can not be detected and incomplete data is returned. One example for this last case is when the data ends with the byte 0x01. This is recognized as legitimate padding and is removed before returning the data, thus removing a legitimate byte from the data and making it unusable. If you didn’t upgrade from a LinOTP version before 2.7.1 (or don’t use a PKCS#11 HSM) you will not be affected by this in any way. ValueError will of course also be raised if you data became corrupt for some other reason (e.g. disk failure) and can not be unpadded. In this case you should NOT set ‘pkcs11.accept_invalid_padding’ to True because your data will be unusable anyway.

Returns

unpadded string or sometimes padded string when ‘pkcs11.accept_invalid_padding’ is set to True. See above.

Return type

str

linotp.lib.security.pkcs11.main()

This module can be called to create an AES key.

Parameters are:

-p / –password= The Passwort of the partition. Can be ommitted.

Then you are asked

-s / –slot= The Slot number (default 0) -n / –name= The name of the AES key. -f / –find= Find the AES key -h / –help -e / –encrypt= Encrypt this data (also need slot and handle) -l / –label= Specify the label of the object for encryption

example:
create a key:

pkcs11 -s 1335299873-p 1234-n dummy

find aes key:

pkcs11 -s 1335299873-p 1234-f dummy

encryption:

pkcs11 -s 1335299873-p 1234-l dummy -e ‘this is a test’

linotp.lib.security.pkcs11.output(loglevel, text)
linotp.lib.security.pkcs11.pkcs11error(rv)