mirror of
https://github.com/polhenarejos/pico-hsm.git
synced 2026-01-17 09:28:05 +00:00
Enhanced the procedure for burning the device certificate.
When initialized, the device generates a private key in place and stores it encrypted. The publick key is recovered and sent to our PKI, which generates a CV certificate. This CV certificate is stored inside the device, jointly with the DV CVC. Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
parent
cb492728ec
commit
36c8150f25
1 changed files with 51 additions and 104 deletions
155
burn-cvcerts.py
155
burn-cvcerts.py
|
|
@ -1,116 +1,63 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Wed Apr 13 20:15:01 2022
|
||||
|
||||
@author: Pol Henarejos
|
||||
"""
|
||||
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import ec
|
||||
import base64
|
||||
import urllib.request
|
||||
#! /usr/bin/env python3
|
||||
from smartcard.CardType import AnyCardType
|
||||
from smartcard.CardRequest import CardRequest
|
||||
from smartcard.Exceptions import CardRequestTimeoutException
|
||||
from cvc.certificates import CVC
|
||||
from cvc.asn1 import ASN1
|
||||
import json
|
||||
import sys
|
||||
import ssl
|
||||
import urllib.request
|
||||
import base64
|
||||
from getpass import getpass
|
||||
from binascii import hexlify
|
||||
|
||||
ssl._create_default_https_context = ssl._create_unverified_context
|
||||
class APDUResponse(Exception):
|
||||
def __init__(self, sw1, sw2):
|
||||
self.sw1 = sw1
|
||||
self.sw2 = sw2
|
||||
super().__init__(f'SW:{sw1:02X}{sw2:02X}')
|
||||
|
||||
def send_apdu(command, p1, p2, data):
|
||||
lc = [0x00] + list(len(data).to_bytes(2,'big'))
|
||||
le = [0x00, 0x00]
|
||||
apdu = [0x00] + [command, p1, p2] + lc + data + le
|
||||
response, sw1, sw2 = cardservice.connection.transmit(apdu)
|
||||
if (sw1 != 0x90):
|
||||
raise APDUResponse(sw1,sw2)
|
||||
return response
|
||||
|
||||
def print_var(v, name):
|
||||
s = '\n'
|
||||
s += "static const unsigned char "+name+"[] = {\n"
|
||||
s += "\t0x{:02x},0x{:02x},\n".format((len(v) & 0xff),((len(v)>> 8) & 0xff))
|
||||
for i in range(len(v)):
|
||||
if (i%16 == 0):
|
||||
s += '\t'
|
||||
s += "0x{:02x}".format((v[i]))
|
||||
if (i < len(v)-1):
|
||||
s += ','
|
||||
if (i%16 == 15):
|
||||
s += '\n'
|
||||
s += '\n'
|
||||
s += '};\n'
|
||||
return s
|
||||
cardtype = AnyCardType()
|
||||
|
||||
def main():
|
||||
args = sys.argv[1:]
|
||||
|
||||
private_key = ec.generate_private_key(ec.SECP192R1(), default_backend())
|
||||
public_key = private_key.public_key()
|
||||
pub_num = public_key.public_numbers()
|
||||
pbk = base64.urlsafe_b64encode(b'\x04'+pub_num.x.to_bytes(24,'big')+pub_num.y.to_bytes(24,'big'))
|
||||
try:
|
||||
# request card insertion
|
||||
cardrequest = CardRequest(timeout=10, cardType=cardtype)
|
||||
cardservice = cardrequest.waitforcard()
|
||||
|
||||
# connect to the card and perform a few transmits
|
||||
cardservice.connection.connect()
|
||||
|
||||
response = send_apdu(0xB1, 0xCE, 0x00, [0x54,0x02,0x00,0x00])
|
||||
|
||||
cert = bytearray(response)
|
||||
Y = CVC().decode(cert).pubkey().find(0x86).data()
|
||||
print(f'Public Point: {hexlify(Y).decode()}')
|
||||
|
||||
user_agent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.7) Gecko/2009021910 Firefox/3.0.7'
|
||||
|
||||
pbk = base64.urlsafe_b64encode(Y)
|
||||
data = urllib.parse.urlencode({'pubkey':pbk}).encode()
|
||||
req = urllib.request.Request("https://www.henarejos.me/pico-hsm.php", method='POST', data=data, headers={'User-Agent':user_agent,} ) #The assembled request
|
||||
req = urllib.request.Request("https://www.henarejos.me/pico-hsm/cvc/", method='POST', data=data, headers={'User-Agent':user_agent,} ) #The assembled request
|
||||
response = urllib.request.urlopen(req)
|
||||
resp = response.read().decode('utf-8')
|
||||
j = json.loads(resp)
|
||||
cvcert = base64.b64decode(j['cvcert'])
|
||||
dataef = base64.urlsafe_b64decode(j['cvcert']) + base64.urlsafe_b64decode(j['dvcert'])
|
||||
|
||||
dica = [
|
||||
0x7f,0x21,0x81,0xc5,0x7f,0x4e,0x81,0x8e,0x5f,0x29,0x01,0x00,0x42,0x0e,0x45,0x53,
|
||||
0x43,0x56,0x43,0x41,0x48,0x53,0x4d,0x30,0x30,0x30,0x30,0x31,0x7f,0x49,0x3f,0x06,
|
||||
0x0a,0x04,0x00,0x7f,0x00,0x07,0x02,0x02,0x02,0x02,0x03,0x86,0x31,0x04,0x93,0x7e,
|
||||
0xdf,0xf1,0xa6,0xd2,0x40,0x7e,0xb4,0x71,0xb2,0x97,0x50,0xdb,0x7e,0xe1,0x70,0xfb,
|
||||
0x6c,0xcd,0x06,0x47,0x2a,0x3e,0x9c,0x8d,0x59,0x56,0x57,0xbe,0x11,0x11,0x0a,0x08,
|
||||
0x81,0x54,0xed,0x22,0xc0,0x83,0xac,0xa1,0x2e,0x39,0x7b,0xd4,0x65,0x1f,0x5f,0x20,
|
||||
0x0e,0x45,0x53,0x44,0x56,0x43,0x41,0x48,0x53,0x4d,0x30,0x30,0x30,0x30,0x31,0x7f,
|
||||
0x4c,0x12,0x06,0x09,0x04,0x00,0x7f,0x00,0x07,0x03,0x01,0x02,0x02,0x53,0x05,0x80,
|
||||
0x00,0x00,0x00,0x04,0x5f,0x25,0x06,0x02,0x02,0x00,0x03,0x02,0x07,0x5f,0x24,0x06,
|
||||
0x02,0x05,0x01,0x02,0x03,0x01,0x5f,0x37,0x30,0x8b,0xb2,0x01,0xb6,0x24,0xfe,0xe5,
|
||||
0x4e,0x65,0x3a,0x02,0xa2,0xb2,0x27,0x2d,0x3d,0xb4,0xb0,0xc9,0xdd,0xbf,0x10,0x6d,
|
||||
0x99,0x49,0x46,0xd6,0xd0,0x72,0xc1,0xf3,0x4c,0xab,0x4f,0x32,0x14,0x7c,0xb0,0x99,
|
||||
0xb7,0x33,0x70,0xd6,0x00,0xff,0x73,0x0c,0x5d
|
||||
]
|
||||
response = send_apdu(0xa4, 0x00, 0x00, [0x2f,0x02])
|
||||
pin = getpass('PIN: ')
|
||||
response = send_apdu(0x20, 0x00, 0x81, list(pin.encode()))
|
||||
|
||||
apdu_data = [0x54, 0x02, 0x00, 0x00] + list(ASN1.make_tag(0x53, dataef))
|
||||
response = send_apdu(0xd7, 0x00, 0x00, apdu_data)
|
||||
|
||||
cvca = [
|
||||
0x7f, 0x21, 0x82, 0x01, 0x65, 0x7f, 0x4e, 0x82, 0x01, 0x2d, 0x5f, 0x29,
|
||||
0x01, 0x00, 0x42, 0x0e, 0x45, 0x53, 0x43, 0x56, 0x43, 0x41, 0x48, 0x53,
|
||||
0x4d, 0x30, 0x30, 0x30, 0x30, 0x31, 0x7f, 0x49, 0x81, 0xdd, 0x06, 0x0a,
|
||||
0x04, 0x00, 0x7f, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x03, 0x81, 0x18,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x82, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xfc, 0x83, 0x18, 0x64, 0x21, 0x05, 0x19, 0xe5, 0x9c, 0x80, 0xe7,
|
||||
0x0f, 0xa7, 0xe9, 0xab, 0x72, 0x24, 0x30, 0x49, 0xfe, 0xb8, 0xde, 0xec,
|
||||
0xc1, 0x46, 0xb9, 0xb1, 0x84, 0x31, 0x04, 0x18, 0x8d, 0xa8, 0x0e, 0xb0,
|
||||
0x30, 0x90, 0xf6, 0x7c, 0xbf, 0x20, 0xeb, 0x43, 0xa1, 0x88, 0x00, 0xf4,
|
||||
0xff, 0x0a, 0xfd, 0x82, 0xff, 0x10, 0x12, 0x07, 0x19, 0x2b, 0x95, 0xff,
|
||||
0xc8, 0xda, 0x78, 0x63, 0x10, 0x11, 0xed, 0x6b, 0x24, 0xcd, 0xd5, 0x73,
|
||||
0xf9, 0x77, 0xa1, 0x1e, 0x79, 0x48, 0x11, 0x85, 0x18, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x99, 0xde, 0xf8,
|
||||
0x36, 0x14, 0x6b, 0xc9, 0xb1, 0xb4, 0xd2, 0x28, 0x31, 0x86, 0x31, 0x04,
|
||||
0x08, 0x8f, 0xcd, 0xfc, 0xce, 0x87, 0xed, 0xd2, 0x85, 0x92, 0x06, 0x15,
|
||||
0xe6, 0x51, 0xd7, 0x64, 0x52, 0xd8, 0x57, 0xec, 0xbb, 0x40, 0x8c, 0x32,
|
||||
0x7a, 0xdb, 0x48, 0xa2, 0xa5, 0x14, 0xc1, 0xc9, 0xbd, 0x77, 0xcc, 0x97,
|
||||
0x83, 0x60, 0x7a, 0x74, 0x14, 0x93, 0xa7, 0x42, 0x74, 0x4a, 0xd1, 0x73,
|
||||
0x87, 0x01, 0x01, 0x5f, 0x20, 0x0e, 0x45, 0x53, 0x43, 0x56, 0x43, 0x41,
|
||||
0x48, 0x53, 0x4d, 0x30, 0x30, 0x30, 0x30, 0x31, 0x7f, 0x4c, 0x12, 0x06,
|
||||
0x09, 0x04, 0x00, 0x7f, 0x00, 0x07, 0x03, 0x01, 0x02, 0x02, 0x53, 0x05,
|
||||
0xc0, 0x00, 0x00, 0x00, 0x04, 0x5f, 0x25, 0x06, 0x02, 0x02, 0x00, 0x03,
|
||||
0x02, 0x06, 0x5f, 0x24, 0x06, 0x03, 0x00, 0x01, 0x02, 0x03, 0x01, 0x5f,
|
||||
0x37, 0x30, 0x72, 0x97, 0x77, 0x76, 0x64, 0xb6, 0x0c, 0x57, 0xa2, 0xc4,
|
||||
0x5e, 0x7b, 0xfd, 0x12, 0xe5, 0x20, 0x14, 0x3e, 0xde, 0x90, 0x38, 0xbf,
|
||||
0xb3, 0x02, 0x73, 0x91, 0x06, 0xf2, 0x73, 0x0d, 0x76, 0x06, 0x65, 0xd7,
|
||||
0x46, 0x49, 0x91, 0x0c, 0x51, 0x90, 0x89, 0x84, 0x8d, 0x4f, 0xb6, 0xe5,
|
||||
0x13, 0x40
|
||||
]
|
||||
|
||||
s = '#ifndef _CVCERTS_H_\n#define _CVCERTS_H_\n'
|
||||
s += print_var(cvca,'cvca')
|
||||
s += print_var(dica,'dica')
|
||||
s += print_var(cvcert,'termca')
|
||||
|
||||
pvk = private_key.private_numbers().private_value.to_bytes(24,'big')
|
||||
s += print_var(pvk,'termca_pk')
|
||||
s += '\n#endif\n'
|
||||
f = open(args[0] + '/src/hsm/cvcerts.h','w')
|
||||
f.write(s)
|
||||
f.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
print('Certificate uploaded successfully!')
|
||||
|
||||
except CardRequestTimeoutException:
|
||||
print('time-out: no card inserted during last 10s')
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue