/usr/share/pyshared/yubico/yubikey_frame.py is in python-yubico 1.1.0-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | """
module for creating frames of data that can be sent to a YubiKey
"""
# Copyright (c) 2010, Yubico AB
# See the file COPYING for licence statement.
__all__ = [
# constants
# functions
# classes
'YubiKeyFrame',
]
import struct
import yubico_util
import yubikey_defs
import yubico_exception
import yubikey_config
from yubico import __version__
class YubiKeyFrame:
"""
Class containing an YKFRAME (as defined in ykdef.h).
A frame is basically 64 bytes of data. When this is to be sent
to a YubiKey, it is put inside 10 USB HID feature reports. Each
feature report is 7 bytes of data plus 1 byte of sequencing and
flags.
"""
def __init__(self, command, payload=''):
if payload is '':
payload = '\x00' * 64
if len(payload) != 64:
raise yubico_exception.InputError('payload must be empty or 64 bytes')
self.payload = payload
self.command = command
self.crc = yubico_util.crc16(payload)
def __repr__(self):
return '<%s.%s instance at %s: %s>' % (
self.__class__.__module__,
self.__class__.__name__,
hex(id(self)),
self.command
)
def to_string(self):
"""
Return the frame as a 70 byte string.
"""
# From ykdef.h :
#
# // Frame structure
# #define SLOT_DATA_SIZE 64
# typedef struct {
# unsigned char payload[SLOT_DATA_SIZE];
# unsigned char slot;
# unsigned short crc;
# unsigned char filler[3];
# } YKFRAME;
filler = ''
return struct.pack('<64sBH3s',
self.payload, self.command, self.crc, filler)
def to_feature_reports(self, debug=False):
"""
Return the frame as an array of 8-byte parts, ready to be sent to a YubiKey.
"""
rest = self.to_string()
seq = 0
out = []
# When sending a frame to the YubiKey, we can (should) remove any
# 7-byte serie that only consists of '\x00', besides the first
# and last serie.
while rest:
this, rest = rest[:7], rest[7:]
if seq > 0 and rest:
# never skip first or last serie
if this != '\x00\x00\x00\x00\x00\x00\x00':
this += chr(yubikey_defs.SLOT_WRITE_FLAG + seq)
out.append(self._debug_string(debug, this))
else:
this += chr(yubikey_defs.SLOT_WRITE_FLAG + seq)
out.append(self._debug_string(debug, this))
seq += 1
return out
def _debug_string(self, debug, data):
"""
Annotate a frames data, if debug is True.
"""
if not debug:
return data
if self.command in [yubikey_config.SLOT_CONFIG,
yubikey_config.SLOT_CONFIG2,
yubikey_config.SLOT_UPDATE1,
yubikey_config.SLOT_UPDATE2,
yubikey_config.SLOT_SWAP,
]:
# annotate according to config_st (see yubikey_config.to_string())
if ord(data[-1]) == 0x80:
return (data, "FFFFFFF")
if ord(data[-1]) == 0x81:
return (data, "FFFFFFF")
if ord(data[-1]) == 0x82:
return (data, "FFUUUUU")
if ord(data[-1]) == 0x83:
return (data, "UKKKKKK")
if ord(data[-1]) == 0x84:
return (data, "KKKKKKK")
if ord(data[-1]) == 0x85:
return (data, "KKKAAAA")
if ord(data[-1]) == 0x86:
return (data, "AAlETCr")
if ord(data[-1]) == 0x87:
return (data, "rCR")
# after payload
if ord(data[-1]) == 0x89:
return (data, " Scr")
else:
return (data, '')
|