Skip to content

Python-pyhsm conversion to work with python3 #24

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyhsm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
See help(pyhsm.base) (L{pyhsm.base.YHSM}) for more information.
"""

__version__ = '1.2.2-dev0'
__version__ = '1.2.2'
__copyright__ = 'Yubico AB'
__organization__ = 'Yubico'
__license__ = 'BSD'
Expand Down
8 changes: 4 additions & 4 deletions pyhsm/aead_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def __repr__(self):
return '<%s instance at %s: nonce=%s, key_handle=0x%x, status=%s>' % (
self.__class__.__name__,
hex(id(self)),
self.nonce.encode('hex'),
self.nonce,
self.key_handle,
pyhsm.defines.status2str(self.status)
)
Expand Down Expand Up @@ -200,9 +200,9 @@ def __init__(self, nonce, key_handle, aead):
self.data = aead

def __repr__(self):
nonce_str = "None"
nonce_str = b"None"
if self.nonce is not None:
nonce_str = self.nonce.encode('hex')
nonce_str = self.nonce
return '<%s instance at %s: nonce=%s, key_handle=0x%x, data=%i bytes>' % (
self.__class__.__name__,
hex(id(self)),
Expand Down Expand Up @@ -262,4 +262,4 @@ def pack(self):
# uint8_t key[KEY_SIZE]; // AES key
# uint8_t uid[UID_SIZE]; // Unique (secret) ID
# } YUBIKEY_SECRETS;
return self.key + self.uid.ljust(pyhsm.defines.UID_SIZE, chr(0))
return self.key + self.uid.ljust(pyhsm.defines.UID_SIZE, b'\x00')
2 changes: 1 addition & 1 deletion pyhsm/aes_ecb_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def __init__(self, stick, key_handle, plaintext):
# uint8_t plaintext[YHSM_BLOCK_SIZE]; // Plaintext block
# } YHSM_ECB_BLOCK_ENCRYPT_REQ;
payload = struct.pack('<I', key_handle) + \
plaintext.ljust(pyhsm.defines.YSM_BLOCK_SIZE, chr(0x0))
plaintext.ljust(pyhsm.defines.YSM_BLOCK_SIZE, b'\x00')
YHSM_Cmd_AES_ECB.__init__(self, stick, pyhsm.defines.YSM_AES_ECB_BLOCK_ENCRYPT, payload)


Expand Down
20 changes: 10 additions & 10 deletions pyhsm/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def reset(self, test_sync = True):
pyhsm.cmd.reset(self.stick)
if test_sync:
# Now verify we are in sync
data = 'ekoeko'
data = b'ekoeko'
echo = self.echo(data)
# XXX analyze 'echo' to see if we are in config mode, and produce a
# nice exception if we are.
Expand Down Expand Up @@ -134,18 +134,18 @@ def test_comm(self):
In some scenarios, communications with the YubiHSM might be affected
by terminal line settings turning CR into LF for example.
"""
data = ''.join([chr(x) for x in range(256)])
data = data + '0d0a0d0a'.decode('hex')
data = bytes(range(256))
data+= bytes.fromhex('0d0a0d0a')
chunk_size = pyhsm.defines.YSM_MAX_PKT_SIZE - 10 # max size of echo
count = 0
while data:
this = data[:chunk_size]
data = data[chunk_size:]
res = self.echo(this)
for i in xrange(len(this)):
for i in range(len(this)):
if res[i] != this[i]:
msg = "Echo test failed at position %i (0x%x != 0x%x)" \
% (count + i, ord(res[i]), ord(this[i]))
% (count + i, res[i], this[i])
raise pyhsm.exception.YHSM_Error(msg)
count += len(this)

Expand Down Expand Up @@ -276,8 +276,8 @@ def unlock(self, password = None, otp = None):
res = True
if res and otp is not None:
(public_id, otp,) = pyhsm.yubikey.split_id_otp(otp)
public_id = pyhsm.yubikey.modhex_decode(public_id).decode('hex')
otp = pyhsm.yubikey.modhex_decode(otp).decode('hex')
public_id = pyhsm.yubikey.modhex_decode(public_id)
otp = pyhsm.yubikey.modhex_decode(otp)
return pyhsm.basic_cmd.YHSM_Cmd_HSM_Unlock(self.stick, public_id, otp).execute()
return res

Expand Down Expand Up @@ -452,13 +452,13 @@ def validate_aead_otp(self, public_id, otp, key_handle, aead):

@see: L{pyhsm.validate_cmd.YHSM_Cmd_AEAD_Validate_OTP}
"""
if type(public_id) is not str:
if type(public_id) is not bytes:
assert()
if type(otp) is not str:
if type(otp) is not bytes:
assert()
if type(key_handle) is not int:
assert()
if type(aead) is not str:
if type(aead) is not bytes:
assert()
return pyhsm.validate_cmd.YHSM_Cmd_AEAD_Validate_OTP( \
self.stick, public_id, otp, key_handle, aead).execute()
Expand Down
14 changes: 7 additions & 7 deletions pyhsm/basic_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ class YHSM_Cmd_Echo(YHSM_Cmd):
"""
Send something to the stick, and expect to get it echoed back.
"""
def __init__(self, stick, payload=''):
def __init__(self, stick, payload=b''):
payload = pyhsm.util.input_validate_str(payload, 'payload', max_len = pyhsm.defines.YSM_MAX_PKT_SIZE - 1)
# typedef struct {
# uint8_t numBytes; // Number of bytes in data field
# uint8_t data[YSM_MAX_PKT_SIZE - 1]; // Data
# } YSM_ECHO_REQ;
packed = chr(len(payload)) + payload
packed = bytes([len(payload)]) + payload
YHSM_Cmd.__init__(self, stick, pyhsm.defines.YSM_ECHO, packed)

def parse_result(self, data):
Expand Down Expand Up @@ -77,7 +77,7 @@ def __repr__(self):
hex(id(self)),
(self.version_major, self.version_minor, self.version_build),
self.protocol_ver,
self.system_uid.encode('hex')
self.system_uid
)
else:
return '<%s instance at %s (not executed)>' % (
Expand Down Expand Up @@ -119,7 +119,7 @@ def parse_result(self, data):
# uint8_t numBytes; // Number of bytes generated
# uint8_t rnd[YSM_MAX_PKT_SIZE - 1]; // Random data
# } YHSM_RANDOM_GENERATE_RESP;
num_bytes = pyhsm.util.validate_cmd_response_int('num_bytes', ord(data[0]), self.num_bytes)
num_bytes = pyhsm.util.validate_cmd_response_int('num_bytes', data[0], self.num_bytes)
return data[1:1 + num_bytes]


Expand Down Expand Up @@ -256,7 +256,7 @@ def __init__(self, stick, password=''):
# typedef struct {
# uint8_t password[YSM_BLOCK_SIZE]; // Unlock password
# } YSM_KEY_STORAGE_UNLOCK_REQ;
packed = payload.ljust(pyhsm.defines.YSM_BLOCK_SIZE, chr(0x0))
packed = payload.ljust(pyhsm.defines.YSM_BLOCK_SIZE, b'\x00')
YHSM_Cmd.__init__(self, stick, pyhsm.defines.YSM_KEY_STORAGE_UNLOCK, packed)

def parse_result(self, data):
Expand Down Expand Up @@ -297,7 +297,7 @@ def __init__(self, stick, key=''):
# typedef struct {
# uint8_t key[YSM_MAX_KEY_SIZE]; // Key store decryption key
# } YSM_KEY_STORE_DECRYPT_REQ;
packed = payload.ljust(pyhsm.defines.YSM_MAX_KEY_SIZE, chr(0x0))
packed = payload.ljust(pyhsm.defines.YSM_MAX_KEY_SIZE, b'\x00')
YHSM_Cmd.__init__(self, stick, pyhsm.defines.YSM_KEY_STORE_DECRYPT, packed)

def parse_result(self, data):
Expand Down Expand Up @@ -397,7 +397,7 @@ def __repr__(self):
return '<%s instance at %s: nonce=%s, pu_count=%i, volatile=%i>' % (
self.__class__.__name__,
hex(id(self)),
self.nonce.encode('hex'),
self.nonce,
self.pu_count,
self.volatile
)
4 changes: 2 additions & 2 deletions pyhsm/buffer_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def parse_result(self, data):
# typedef struct {
# uint8_t numBytes; // Number of bytes in buffer now
# } YSM_BUFFER_LOAD_RESP;
count = ord(data[0])
count = data[0]
if self.offset == 0:
# if offset was 0, the buffer was reset and
# we can verify the length returned
Expand Down Expand Up @@ -90,7 +90,7 @@ def parse_result(self, data):
# typedef struct {
# uint8_t numBytes; // Number of bytes in buffer now
# } YSM_BUFFER_LOAD_RESP;
count = ord(data[0])
count = data[0]
if self.offset == 0:
# if offset was 0, the buffer was reset and
# we can verify the length returned
Expand Down
12 changes: 7 additions & 5 deletions pyhsm/cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ def execute(self, read_response=True):
# YSM_NULL is the exception to the rule - it should NOT be prefixed with YSM_PKT.bcnt
cmd_buf = struct.pack('BB', len(self.payload) + 1, self.command)
else:
cmd_buf = chr(self.command)
cmd_buf = bytes([self.command])
if not isinstance(self.payload, (bytes, bytearray)):
self.payload = self.payload.encode()
cmd_buf += self.payload
debug_info = None
unlock = self.stick.acquire()
Expand Down Expand Up @@ -127,16 +129,16 @@ def _handle_invalid_read_response(self, res, expected_len):
if not res:
reset(self.stick)
raise pyhsm.exception.YHSM_Error('YubiHSM did not respond to command %s' \
% (pyhsm.defines.cmd2str(self.command)) )
% (pyhsm.defines.cmd2str(self.command)))
# try to check if it is a YubiHSM in configuration mode
self.stick.write('\r\r\r', '(mode test)')
res2 = self.stick.read(50) # expect a timeout
self.stick.write(b'\r\r\r', '(mode test)')
res2 = self.stick.read(50).decode() # expect a timeout
lines = res2.split('\n')
for this in lines:
if re.match('^(NO_CFG|WSAPI|HSM).*> .*', this):
raise pyhsm.exception.YHSM_Error('YubiHSM is in configuration mode')
raise pyhsm.exception.YHSM_Error('Unknown response from serial device %s : "%s"' \
% (self.stick.device, res.encode('hex')))
% (self.stick.device, res()))

def parse_result(self, data):
"""
Expand Down
2 changes: 1 addition & 1 deletion pyhsm/db_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def __repr__(self):
return '<%s instance at %s: public_id=%s, status=0x%x>' % (
self.__class__.__name__,
hex(id(self)),
self.public_id.encode('hex'),
bytes.fromhex(self.public_id),
self.status
)
else:
Expand Down
4 changes: 3 additions & 1 deletion pyhsm/hmac_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ def __repr__(self):
self.__class__.__name__,
hex(id(self)),
self.key_handle,
self.hash_result[:4].encode('hex'),
self.hash_result[:4],
self.final,
)


2 changes: 1 addition & 1 deletion pyhsm/ksm/db_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

def insert_slash(string, every=2):
"""insert_slash insert / every 2 char"""
return os.path.join(string[i:i+every] for i in xrange(0, len(string), every))
return os.path.join(string[i:i+every] for i in range(0, len(string), every))


def mkdir_p(path):
Expand Down
2 changes: 1 addition & 1 deletion pyhsm/ksm/db_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def main():
aead.key_handle = key_handle_to_int(keyhandle)

if not insert_query(connection, public_id, aead, keyhandle, aeadobj):
print("WARNING: could not insert %s" % public_id)
print(("WARNING: could not insert %s" % public_id))

#close sqlalchemy
connection.close()
Expand Down
52 changes: 26 additions & 26 deletions pyhsm/ksm/import_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def args_fixup(args):
sys.exit(1)

if args.aes_key:
args.aes_key = args.aes_key.decode('hex')
args.aes_key = bytes.fromhex(args.aes_key).decode()
keyhandles_fixup(args)


Expand Down Expand Up @@ -154,29 +154,29 @@ def import_keys(hsm, args):

l = line.split(',')
modhex_id = l[1]
uid = l[2].decode('hex')
key = l[3].decode('hex')
uid = l[2]
key = l[3]

if modhex_id and uid and key:
public_id = pyhsm.yubikey.modhex_decode(modhex_id)
padded_id = modhex_id.rjust(args.public_id_chars, 'c')

if int(public_id, 16) == 0:
print "WARNING: Skipping import of key with public ID: %s" % (padded_id)
print "This public ID is unsupported by the YubiHSM.\n"
print("WARNING: Skipping import of key with public ID: %s" % (padded_id))
print("This public ID is unsupported by the YubiHSM.\n")
continue

if args.verbose:
print " %s" % (padded_id)
print(" %s" % (padded_id))

secret = pyhsm.aead_cmd.YHSM_YubiKeySecret(key, uid)
hsm.load_secret(secret)

for kh in args.key_handles.keys():
for kh in list(args.key_handles.keys()):
if(args.random_nonce):
nonce = ""
nonce = b""
else:
nonce = public_id.decode('hex')
nonce = bytes.fromhex(public_id)
aead = hsm.generate_aead(nonce, kh)

if args.internal_db:
Expand All @@ -189,43 +189,43 @@ def import_keys(hsm, args):
args.output_dir, args.key_handles[kh], padded_id)

if args.verbose:
print " %4s, %i bytes (%s) -> %s" % \
(args.key_handles[kh], len(aead.data), shorten_aead(aead), filename)
print(" %4s, %i bytes (%s) -> %s" % \
(args.key_handles[kh], len(aead.data), shorten_aead(aead), filename))

aead.save(filename)

if args.verbose:
print ""
print("")

if res:
print "\nDone\n"
print("\nDone\n")
else:
print "\nDone (one or more entries rejected)"
print("\nDone (one or more entries rejected)")
return res


def store_in_internal_db(args, hsm, modhex_id, public_id, kh, aead):
""" Store record (AEAD) in YubiHSM internal DB """
if args.verbose:
print " %i bytes (%s) -> internal db..." % \
(len(aead.data), shorten_aead(aead)),
print(" %i bytes (%s) -> internal db..." % \
(len(aead.data), shorten_aead(aead)), end=' ')
try:
hsm.db_store_yubikey(public_id.decode('hex'), kh, aead)
hsm.db_store_yubikey(bytes.fromhex(public_id), kh, aead)
if args.verbose:
print "OK"
print("OK")
except pyhsm.exception.YHSM_CommandFailed as e:
if args.verbose:
print "%s" % (pyhsm.defines.status2str(e.status))
print("%s" % (pyhsm.defines.status2str(e.status)))
else:
print "Storing ID %s FAILED: %s" % (modhex_id, pyhsm.defines.status2str(e.status))
print("Storing ID %s FAILED: %s" % (modhex_id, pyhsm.defines.status2str(e.status)))
return False
return True


def shorten_aead(aead):
""" Produce pretty-printable version of long AEAD. """
head = aead.data[:4].encode('hex')
tail = aead.data[-4:].encode('hex')
head = aead.data[:4]
tail = aead.data[-4:]
return "%s...%s" % (head, tail)


Expand Down Expand Up @@ -253,10 +253,10 @@ def main():
"Did not get '# ykksm 1' header as first line of input.\n")
sys.exit(1)

print "output dir : %s" % (args.output_dir)
print "key handles : %s" % (args.key_handles)
print "YHSM device : %s" % (args.device)
print ""
print("output dir : %s" % (args.output_dir))
print("key handles : %s" % (args.key_handles))
print("YHSM device : %s" % (args.device))
print("")

if args.aes_key:
keys = {kh: args.aes_key for kh in args.key_handles}
Expand Down
Loading