mirror of
https://github.com/polhenarejos/pico-hsm.git
synced 2026-01-17 09:28:05 +00:00
Added support for kdf.
It supports HKDF, PBKDF2 and X963, with multiple MD (SHA family), salt/nonces and configurable output size. Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
parent
4113f6a65d
commit
63c85000d0
1 changed files with 99 additions and 18 deletions
|
|
@ -70,13 +70,16 @@ class APDUResponse(Exception):
|
|||
def hexy(a):
|
||||
return [hex(i) for i in a]
|
||||
|
||||
def send_apdu(card, command, p1, p2, data=None):
|
||||
def send_apdu(card, command, p1, p2, data=None, ne=None):
|
||||
lc = []
|
||||
dataf = []
|
||||
if (data):
|
||||
lc = [0x00] + list(len(data).to_bytes(2, 'big'))
|
||||
dataf = data
|
||||
le = [0x00, 0x00]
|
||||
if (ne is None):
|
||||
le = [0x00, 0x00]
|
||||
else:
|
||||
le = list(ne.to_bytes(2, 'big'))
|
||||
if (isinstance(command, list) and len(command) > 1):
|
||||
apdu = command
|
||||
else:
|
||||
|
|
@ -146,7 +149,17 @@ def parse_args():
|
|||
parser_cipher_decrypt = subparser_cipher.add_parser('decrypt', help='Performs decryption.')
|
||||
parser_cipher_keygen = subparser_cipher.add_parser('keygen', help='Generates new AES key.')
|
||||
parser_cipher_hmac = subparser_cipher.add_parser('hmac', help='Computes HMAC.')
|
||||
parser_cipher.add_argument('--alg', choices=['CHACHAPOLY','HMAC-SHA1','HMAC-SHA224','HMAC-SHA256','HMAC-SHA384','HMAC-SHA512'], help='Selects the algorithm.', required='keygen' not in sys.argv)
|
||||
parser_cipher_kdf = subparser_cipher.add_parser('kdf', help='Performs key derivation function on a secret key.')
|
||||
parser_cipher_encrypt.add_argument('--alg', choices=['CHACHAPOLY'], required=True)
|
||||
parser_cipher_encrypt.add_argument('--iteration', help='Iteration count.', required=any(['PBKDF2' in s for s in sys.argv]))
|
||||
parser_cipher_decrypt.add_argument('--alg', choices=['CHACHAPOLY'], required=True)
|
||||
parser_cipher_decrypt.add_argument('--iteration', help='Iteration count.', required=any(['PBKDF2' in s for s in sys.argv]))
|
||||
|
||||
parser_cipher_hmac.add_argument('--alg', choices=['HMAC-SHA1', 'HMAC-SHA224', 'HMAC-SHA256', 'HMAC-SHA384', 'HMAC-SHA512'], help='Selects the algorithm.', required=True)
|
||||
parser_cipher_kdf.add_argument('--alg', choices=['HKDF-SHA256', 'HKDF-SHA384', 'HKDF-SHA512', 'PBKDF2-SHA1', 'PBKDF2-SHA224', 'PBKDF2-SHA256', 'PBKDF2-SHA384', 'PBKDF2-SHA512', 'X963-SHA1', 'X963-SHA224', 'X963-SHA256', 'X963-SHA384', 'X963-SHA512'], help='Selects the algorithm.', required=True)
|
||||
parser_cipher_kdf.add_argument('--output-len', help='Specifies the output length of derived material.')
|
||||
parser_cipher_kdf.add_argument('--iteration', help='Iteration count.', required=any(['PBKDF2' in s for s in sys.argv]))
|
||||
|
||||
parser_cipher.add_argument('--iv', help='Sets the IV/nonce (hex string).')
|
||||
parser_cipher.add_argument('--file-in', help='File to encrypt or decrypt.')
|
||||
parser_cipher.add_argument('--file-out', help='File to write the result.')
|
||||
|
|
@ -429,6 +442,8 @@ def cipher(card, args):
|
|||
ret = send_apdu(card, 0x48, int(args.key), ksize)
|
||||
|
||||
else:
|
||||
enc = None
|
||||
aad = None
|
||||
if (args.alg == 'CHACHAPOLY'):
|
||||
oid = b'\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x03\x12'
|
||||
elif (args.alg == 'HMAC-SHA1'):
|
||||
|
|
@ -441,29 +456,95 @@ def cipher(card, args):
|
|||
oid = b'\x2A\x86\x48\x86\xF7\x0D\x02\x0A'
|
||||
elif (args.alg == 'HMAC-SHA512'):
|
||||
oid = b'\x2A\x86\x48\x86\xF7\x0D\x02\x0B'
|
||||
elif (args.alg == 'HKDF-SHA256'):
|
||||
oid = b'\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x03\x1D'
|
||||
elif (args.alg == 'HKDF-SHA384'):
|
||||
oid = b'\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x03\x1E'
|
||||
elif (args.alg == 'HKDF-SHA512'):
|
||||
oid = b'\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x03\x1F'
|
||||
elif (args.alg in ['PBKDF2-SHA1', 'PBKDF2-SHA224', 'PBKDF2-SHA256', 'PBKDF2-SHA384', 'PBKDF2-SHA512']):
|
||||
if ('PBKDF2' in args.alg):
|
||||
oid = b'\x2A\x86\x48\x86\xF7\x0D\x01\x05\x0C'
|
||||
salt = b'\x04' + bytes([len(args.iv)//2]) + unhexlify(args.iv)
|
||||
iteration = b'\x02' + bytes([len(int_to_bytes(int(args.iteration)))]) + int_to_bytes(int(args.iteration))
|
||||
prf = b'\x30\x0A\x06\x08\x2A\x86\x48\x86\xF7\x0D\x02'
|
||||
if (args.alg == 'PBKDF2-SHA1'):
|
||||
prf += b'\x07'
|
||||
elif (args.alg == 'PBKDF2-SHA224'):
|
||||
prf += b'\x08'
|
||||
elif (args.alg == 'PBKDF2-SHA256'):
|
||||
prf += b'\x09'
|
||||
elif (args.alg == 'PBKDF2-SHA384'):
|
||||
prf += b'\x0A'
|
||||
elif (args.alg == 'PBKDF2-SHA512'):
|
||||
prf += b'\x0B'
|
||||
enc = list(salt + iteration + prf)
|
||||
elif (args.alg in 'X963-SHA1', 'X963-SHA224', 'X963-SHA256', 'X963-SHA384', 'X963-SHA512'):
|
||||
oid = b'\x2B\x81\x05\x10\x86\x48\x3F'
|
||||
enc = b'\x2A\x86\x48\x86\xF7\x0D\x02'
|
||||
if (args.alg == 'X963-SHA1'):
|
||||
enc += b'\x07'
|
||||
elif (args.alg == 'X963-SHA224'):
|
||||
enc += b'\x08'
|
||||
elif (args.alg == 'X963-SHA256'):
|
||||
enc += b'\x09'
|
||||
elif (args.alg == 'X963-SHA384'):
|
||||
enc += b'\x0A'
|
||||
elif (args.alg == 'X963-SHA512'):
|
||||
enc += b'\x0B'
|
||||
'''
|
||||
# To be finished: it does not work with AES (only supported by HSM)
|
||||
elif (args.alg in ['PBES2-SHA1', 'PBES2-SHA224', 'PBES2-SHA256', 'PBES2-SHA384', 'PBES2-SHA512']):
|
||||
oid = b'\x2A\x86\x48\x86\xF7\x0D\x01\x05\x0D'
|
||||
if (not args.iv):
|
||||
sys.stderr.buffer.write(b'ERROR: --iv required')
|
||||
sys.exit(-1)
|
||||
salt = b'\x04' + bytes([len(args.iv)//2]) + unhexlify(args.iv)
|
||||
iteration = b'\x02' + bytes([len(int_to_bytes(int(args.iteration)))]) + int_to_bytes(int(args.iteration))
|
||||
prf = b'\x30\x0A\x06\x08\x2A\x86\x48\x86\xF7\x0D\x02'
|
||||
if (args.alg == 'PBES2-SHA1'):
|
||||
prf += b'\x07'
|
||||
elif (args.alg == 'PBES2-SHA224'):
|
||||
prf += b'\x08'
|
||||
elif (args.alg == 'PBES2-SHA256'):
|
||||
prf += b'\x09'
|
||||
elif (args.alg == 'PBES2-SHA384'):
|
||||
prf += b'\x0A'
|
||||
elif (args.alg == 'PBES2-SHA512'):
|
||||
prf += b'\x0B'
|
||||
oid_kdf = b'\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x05\x0C'
|
||||
aad = hexlify(oid_kdf + b'\x30' + bytes([len(salt)+len(iteration)+len(prf)]) + salt + iteration + prf)
|
||||
args.hex = True
|
||||
'''
|
||||
|
||||
if (args.subcommand[0] == 'e' or args.subcommand == 'hmac'):
|
||||
if (args.subcommand[0] == 'e' or args.subcommand == 'hmac' or args.subcommand == 'kdf'):
|
||||
alg = 0x51
|
||||
elif (args.subcommand[0] == 'd'):
|
||||
alg = 0x52
|
||||
|
||||
if (args.file_in):
|
||||
fin = open(args.file_in, 'rb')
|
||||
else:
|
||||
fin = sys.stdin.buffer
|
||||
enc = fin.read()
|
||||
fin.close()
|
||||
if (not enc):
|
||||
if (args.file_in):
|
||||
fin = open(args.file_in, 'rb')
|
||||
else:
|
||||
fin = sys.stdin.buffer
|
||||
enc = fin.read()
|
||||
fin.close()
|
||||
|
||||
data = [0x06, len(oid)] + list(oid) + [0x81, len(enc)] + list(enc)
|
||||
if (args.iv):
|
||||
data += [0x82, len(args.iv)/2] + list(unhexlify(args.iv))
|
||||
if (args.aad):
|
||||
if (args.hex):
|
||||
data += [0x83, len(args.aad)/2] + list(unhexlify(args.aad))
|
||||
else:
|
||||
data += [0x83, len(args.aad)] + list(args.aad)
|
||||
|
||||
ret = send_apdu(card, [0x80, 0x78], int(args.key), alg, data)
|
||||
if (args.iv and not 'PBKDF2' in args.alg and not 'PBES2' in args.alg):
|
||||
data += [0x82, len(args.iv)//2] + list(unhexlify(args.iv))
|
||||
if (not aad):
|
||||
aad = args.aad
|
||||
if (aad):
|
||||
if (args.hex):
|
||||
data += [0x83, len(aad)//2] + list(unhexlify(aad))
|
||||
else:
|
||||
data += [0x83, len(aad)] + list(aad)
|
||||
|
||||
ne = int(args.output_len) if 'output_len' in args and args.output_len else None
|
||||
|
||||
ret = send_apdu(card, [0x80, 0x78], int(args.key), alg, data=data, ne=ne)
|
||||
if (args.file_out):
|
||||
fout = open(args.file_out, 'wb')
|
||||
else:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue