X.509 Structure


OpenSSL 라이브러리를 이용하여 X.509 포맷의 인증서를 만들고 검사하는 방법에 대해 간략한 샘플 코드를 공개한다.

OpenSSL은 컴파일을 해야 하는데, 이게 좀 귀찮다. 그러니 이미 컴파일된 바이너리를 배포하는 웹사이트를 통해 받아두면 편하다.

컴파일된 바이너리: https://wiki.openssl.org/index.php/Binaries


소스

아래는 OpenSSL을 이용한 X.509 인증서를 만들고 PKCS#12 형태의 전달 가능한 파일로도 변환할 수 있다.

X509.cpp

// X509.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <cstdio>
#include <iostream>

#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/pkcs12.h>
#include <openssl/err.h>

/* Generates a 2048-bit RSA key. */
EVP_PKEY * generate_key()
{
/* Allocate memory for the EVP_PKEY structure. */
EVP_PKEY * pkey = EVP_PKEY_new();
if (!pkey)
{
std::cerr << "Unable to create EVP_PKEY structure." << std::endl;
return NULL;
}
/* Generate the RSA key and assign it to pkey. */
RSA * rsa = RSA_generate_key(2048, RSA_F4, NULL, NULL);
if (!EVP_PKEY_assign_RSA(pkey, rsa))
{
std::cerr << "Unable to generate 2048-bit RSA key." << std::endl;
EVP_PKEY_free(pkey);
return NULL;
}
/* The key has been generated, return it. */
return pkey;
}

/* Generates a self-signed x509 certificate. */
X509 * generate_x509(EVP_PKEY * pkey)
{
/* Allocate memory for the X509 structure. */
X509 * x509 = X509_new();
if (!x509)
{
std::cerr << "Unable to create X509 structure." << std::endl;
return NULL;
}
/* Set the serial number. */
ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
/* This certificate is valid from now until exactly one year from now. */
X509_gmtime_adj(X509_get_notBefore(x509), 0);
X509_gmtime_adj(X509_get_notAfter(x509), 31536000L);
/* Set the public key for our certificate. */
X509_set_pubkey(x509, pkey);
/* We want to copy the subject name to the issuer name. */
X509_NAME * name = X509_get_subject_name(x509);
/* Set the country code and common name. */
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char *)"CA", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char *)"MyCompany", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)"localhost", -1, -1, 0);
/* Now set the issuer name. */
X509_set_issuer_name(x509, name);
/* Actually sign the certificate with our key. */
if (!X509_sign(x509, pkey, EVP_sha1()))
{
std::cerr << "Error signing certificate." << std::endl;
X509_free(x509);
return NULL;
}
return x509;
}

bool write_to_disk(EVP_PKEY * pkey, X509 * x509)
{
/* Open the PEM file for writing the key to disk. */
FILE * pkey_file = fopen("key.pem", "wb");
if (!pkey_file)
{
std::cerr << "Unable to open \"key.pem\" for writing." << std::endl;
return false;
}
/* Write the key to disk. */
bool ret = PEM_write_PrivateKey(pkey_file, pkey, NULL, NULL, 0, NULL, NULL);
fclose(pkey_file);
if (!ret)
{
std::cerr << "Unable to write private key to disk." << std::endl;
return false;
}
/* Open the PEM file for writing the certificate to disk. */
FILE * x509_file = fopen("cert.pem", "wb");
if (!x509_file)
{
std::cerr << "Unable to open \"cert.pem\" for writing." << std::endl;
return false;
}
/* Write the certificate to disk. */
ret = PEM_write_X509(x509_file, x509);
fclose(x509_file);
if (!ret)
{
std::cerr << "Unable to write certificate to disk." << std::endl;
return false;
}
return true;
}

/* Check the X509 certificate. */
void check_certificate_validaty(X509* certificate)
{
/* a newly initialised X509_STORE_CTX structure */
X509_STORE_CTX *ctx = X509_STORE_CTX_new();

/* a newly initialised X509_STORE structure */
X509_STORE *store = X509_STORE_new();

/* Copy a certificate to X509_STORE structure */
X509_STORE_add_cert(store, certificate);

/* Set up a X509_STORE_CTX for verification. */
X509_STORE_CTX_init(ctx, store, certificate, NULL);

/* Verify a X.509 certification. */
if (X509_verify_cert(ctx) == 1)
{
printf("Certificate verified ok\n");
}
else
{
printf("Certificate verified fail\n");
}
}

bool write_pkcs12()
{
X509 *cert;
PKCS12 *p12;

OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();

/* Allocate memory for the EVP_PKEY structure. */
EVP_PKEY *pkey = EVP_PKEY_new();
if(!pkey)
{
std::cerr << "Unable to create EVP_PKEY structure." << std::endl;
return false;
}

/* Open the PEM file for reading the key on disk. */
FILE *fp = fopen("key.pem", "r");
if (!fp)
{
std::cerr << "Unable to open \"key.pem\" for reading." << std::endl;
return false;
}

/* Read a private key from the PEM file. */
pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
if (!pkey)
{
std::cerr << "Error loading certificate private key content." << std::endl;
return false;
}
fclose(fp);

/* Open the PEM file for reading the certificate on disk. */
fp = fopen("cert.pem", "r");
if (!fp)
{
std::cerr << "Unable to open \"cert.pem\" for reading." << std::endl;
return false;
}

/* Read the X.509 certification from the PEM file. */
cert = PEM_read_X509(fp, NULL, NULL, NULL);
rewind(fp);
fclose(fp);

/* Allocate memory for the PKCS#12 structure. */
p12 = PKCS12_create("PASSWORD", "NAME", pkey, cert, NULL, 0, 0, 0, 0, 0);
if (!p12) {
std::cerr << "Error creating PKCS#12 structure." << std::endl;
return false;
}

/* Open the PEM file for reading the certificate on disk. */
fp = fopen("cert.p12", "wb");
if (!fp)
{
std::cerr << "Unable to open \"cert.p12\" for reading." << std::endl;
return false;
}

/* Write the PKCS#12 certification to disk */
i2d_PKCS12_fp(fp, p12);
PKCS12_free(p12);
fclose(fp);

return true;
}

int main(int argc, char ** argv)
{
/* Generate the key. */
std::cout << "Generating RSA key..." << std::endl;
EVP_PKEY * pkey = generate_key();
if(!pkey)
return 1;
/* Generate the certificate. */
std::cout << "Generating x509 certificate..." << std::endl;
X509 * x509 = generate_x509(pkey);
if(!x509)
{
EVP_PKEY_free(pkey);
return 1;
}

check_certificate_validaty(x509);

/* Write the private key and certificate out to disk. */
std::cout << "Writing key and certificate to disk..." << std::endl;
bool ret = write_to_disk(pkey, x509);
EVP_PKEY_free(pkey);
X509_free(x509);
if (ret)
{
std::cout << "Success a writing key and certificate!" << std::endl;
}
else
return 1;

std::cout << "Writing the pkcs#12 certificate to disk..." << std::endl;
ret = write_pkcs12();

if (ret)
{
std::cout << "Success the pkcs#12 certificate!" << std::endl;
return 0;
}
else
return 1;
}


저작자 표시 비영리 변경 금지
신고

WEMOwemo logo


WeMo Light Switches:

  1. Hold down reset until it blinks amber and green
  2. Roughly 30 to 60 seconds in total

WeMo Motion Senors, Switches and Links:

  1. Unplug the WeMo
  2. Hold down the reset button
  3. Plug the WeMo in
  4. Release the reset button a few seconds after it starts flashing amber
  5. Once the WeMo is flashing amber and green the reset is complete

WeMo Bulbs:

  1. Start with bulb on for 5 seconds
  2. Switch bulb off for 5 seconds
  3. Switch bulb on for 5 seconds
  4. Switch bulb off for 5 seconds
  5. Switch bulb on for 5 seconds
  6. Switch bulb off for 5 seconds
  7. Switch bulb on
  8. After 5 seconds the WeMo bulb should blink 3 times and the reset is complete


저작자 표시 비영리 변경 금지
신고

이전글: Tkinter로 만드는 스마트카드 통신 프로그램 - 4


Smartcard ManagerSCM


목표

1. 상호인증(mutual authentication) 기능 추가

2. 상호인증 후 GET STATUS command를 이용하여 card content들을 treeview에 표시



특이사항

1. GlobalPlatform 관련 소스는 공개하지 않음. 

2. Treeview에 item 관리하는 부분이 효과적인지 모르겠음.



소스코드

main.py

# imports
# Use Tkinter for python 2, tkinter for python 3
import tkinter as tk
import scm

if __name__ == '__main__':
root = tk.Tk()
scm.MainPage(root)
root.mainloop() # Start GUI


scm/__init__.py

"""Smartcard manager
"""

# Use Tkinter for python 2, tkinter for python 3
import tkinter as tk
import tkinter.scrolledtext as tkst
import tkinter.messagebox as tkmb
from tkinter import ttk
from tkinter import Menu

from smartcard.System import readers
from smartcard.util import toHexString, toBytes

from scm.gp import GP
from scm.apdu import *


class Page(object):
"""Page class
This class is a basic class of the smartcard manager's UI
"""

def __init__(self, root, debugger=None, connector=None):
"""Construct new Page.

Args:
root -- the tkinter
debugger -- the DebuggerWidget instance
connector -- the Connector instance
"""
self.root = root
self.debugger = debugger
self.connector = connector


class MainPage(Page):
"""MainPage class
The smartcard manager's Main UI
"""

def __init__(self, root):
"""Construct new Page.
"""
super().__init__(root) #Call a super class's constructor
self.debugger = DebuggerWidget()
self.connector = Connector(self.debugger)
self.root.title('Main')
self._create_widgets()
self.debugger.set_debug_widget(self.st_log)

def _create_widgets(self):
"""Creates widgets
"""
self._create_apdu_frame()
self._create_app_frame()
self._create_menu()

def _create_menu(self):
"""Creates menus
"""
self.menu_bar = Menu(self.root) # Create a menu
self.root.config(menu=self.menu_bar)
self.menu_file = Menu(self.menu_bar, tearoff=0) # Create the File Menu
self.menu_file.add_command(label="Exit", command=self.click_exit) # Add the "Exit" menu and bind a function
self.menu_bar.add_cascade(label="File", menu=self.menu_file)
self.menu_help = Menu(self.menu_bar, tearoff=0)
self.menu_help.add_command(label="About", command=self.click_about) # Add the "About" menu and bind a function
self.menu_bar.add_cascade(label="Help", menu=self.menu_help)

def _create_apdu_frame(self):
"""Creates an apdu frame
"""
self.frame_apdu = tk.Frame(self.root)
self.frame_apdu.grid(column=0, row=0)
self.label_reader = ttk.Label(self.frame_apdu, text='Reader')
self.label_reader.grid(column=0, row=0)
self.str_reader_name = tk.StringVar() # String variable
self.combo_reader = ttk.Combobox(self.frame_apdu, width=30, state='readonly'
, textvariable=self.str_reader_name) # Create a combobox
self.combo_reader.grid(column=1, row=0)
self.combo_reader['values'] = self.connector.get_all_connectors()
try:
self.combo_reader.current(0)
except Exception:
pass
self.button_reset = ttk.Button(self.frame_apdu, text='Reset...', command=self.click_reset) # Create a button
self.button_reset.grid(column=2, row=0)
self.st_log = tkst.ScrolledText(self.frame_apdu, width=50, height=20, wrap=tk.WORD) # Create a scrolledtext5
self.st_log.grid(column=0, row=1, columnspan=3)
self.entry_cmd = tk.Entry(self.frame_apdu, width=40) # Create a entry
self.entry_cmd.grid(column=0, row=2, columnspan=2)
self.entry_cmd.focus_set()
self.button_cmd = ttk.Button(self.frame_apdu, text='Send...', command=self.click_send) # Create a button
self.button_cmd.grid(column=2, row=2)

def _create_app_frame(self):
"""Creates applications frame
"""
self.frame_app = tk.Frame(self.root)
self.frame_app.grid(column=1, row=0)
self.lable_enc = ttk.Label(self.frame_app, text='ENC')
self.lable_enc.grid(column=0, row=0)
self.entry_enc = tk.Entry(self.frame_app)
self.entry_enc.config(width='33')
self.entry_enc.grid(column=1, row=0, columnspan=2)
self.entry_enc.insert(tk.INSERT, '404142434445464748494A4B4C4D4E4F')
self.label_mac = ttk.Label(self.frame_app, text='MAC')
self.label_mac.grid(column=0, row=1)
self.entry_mac = tk.Entry(self.frame_app)
self.entry_mac.config(width='33')
self.entry_mac.grid(column=1, row=1, columnspan=2)
self.entry_mac.insert(tk.INSERT, '404142434445464748494A4B4C4D4E4F')
self.label_dek = ttk.Label(self.frame_app, text='DEK')
self.label_dek.grid(column=0, row=2)
self.entry_dek = tk.Entry(self.frame_app)
self.entry_dek.config(width='33')
self.entry_dek.grid(column=1, row=2, columnspan=2)
self.entry_dek.insert(tk.INSERT, '404142434445464748494A4B4C4D4E4F')
self.sv_rule = tk.StringVar()
self.radio_none = tk.Radiobutton(self.frame_app, text=gp.NO_DERIVATION
, variable=self.sv_rule, value=gp.NO_DERIVATION)
self.radio_none.grid(column=0, row=3)
self.radio_cpg201 = tk.Radiobutton(self.frame_app, text=gp.CPG201
, variable=self.sv_rule, value=gp.CPG201)
self.radio_cpg201.config(state='disabled')
self.radio_cpg201.grid(column=1, row=3)
self.radio_cpg211 = tk.Radiobutton(self.frame_app, text=gp.CPG211
, variable=self.sv_rule, value=gp.CPG211)
self.radio_cpg211.config(state='disabled')
self.radio_cpg211.grid(column=2, row=3)
self.radio_none.select()
self.treeveiw_apps = ttk.Treeview(self.frame_app, height=9)
self.treeveiw_apps['columns'] = ('Life Cycle State', 'Privilieges')
self.treeveiw_apps.heading('#0', text='AID')
self.treeveiw_apps.heading('#1', text='Life Cycle State')
self.treeveiw_apps.heading('#2', text='Privilieges')
self.treeveiw_apps.column('#0', width=200)
self.treeveiw_apps.column('#1', width=50)
self.treeveiw_apps.column('#2', width=50)
self.tvi_isd = self.treeveiw_apps.insert('', 0, text='Issuer Security Domain')
self.tvi_elf = self.treeveiw_apps.insert('', 1, text='Excutable Load Files')
self.tvi_app = self.treeveiw_apps.insert('', 2, text='Applications')
self.treeveiw_apps.grid(column=0, row=4, columnspan=3)
self.button_auth = ttk.Button(self.frame_app, text='Get Status...'
, command=self.click_getstatus)
self.button_auth.grid(column=0, row=5, columnspan=3)

def click_reset(self):
"""Click a reset button
"""
try:
self.connector.select_reader(self.str_reader_name.get())
self.connector.reset()
self.gp = GP(self.connector)
except Exception:
tkmb.showinfo('Error', 'Please check a card or readers...')

def click_send(self):
"""Click a send button
"""
self.connector.send_command(self.entry_cmd.get())

def click_exit(self):
"""Click a exit menu
"""
self.root.quit()
self.root.destroy()
exit()

def click_auth(self):
"""Click a exit menu
"""
try:
result, sw1, sw2 = self.gp.mutual_auth(enc=toBytes(self.entry_enc.get())
, mac=toBytes(self.entry_mac.get())
, dek=toBytes(self.entry_dek.get())
, rule=self.sv_rule.get())
if not result:
tkmb.showinfo('Error', 'mutual auth error...')
except NotImplementedError:
tkmb.showinfo('Error', 'mutual auth error...')
except RuntimeError:
tkmb.showinfo('Error', 'mutual auth error...')
except Exception:
tkmb.showinfo('Error', 'Please check a card or readers...')
return

def click_about(self):
"""Click a abount menu
"""
tkmb.showinfo('About', 'About...')

def click_getstatus(self):
"""Click a reset button
"""
for i in self.treeveiw_apps.get_children():
self.treeveiw_apps.delete(i)
self.tvi_isd = self.treeveiw_apps.insert('', 0, text='Issuer Security Domain')
self.tvi_elf = self.treeveiw_apps.insert('', 1, text='Excutable Load Files')
self.tvi_app = self.treeveiw_apps.insert('', 2, text='Applications')
try:
result, sw1, sw2 = self.gp.mutual_auth(enc=toBytes(self.entry_enc.get())
, mac=toBytes(self.entry_mac.get())
, dek=toBytes(self.entry_dek.get())
, rule=self.sv_rule.get())
if not result:
tkmb.showinfo('Error', 'mutual auth error...')
return
#GET STATUS Command
gs_apdu = GetStatus([0x80, 0xF2, 0x80, 0x00, 0x02, 0x4F, 0x00])
response, sw1, sw2 = self.connector.send_apdu(gs_apdu)
if sw1 == 0x90 and sw2 == 0x00:
data = gs_apdu.parse_response()
self.treeveiw_apps.insert(self.tvi_isd, 0, text=toHexString(data[0][0])
, values=('{:02X}'.format(data[0][1])
, '{:02X}'.format(data[0][2])))
gs_apdu = GetStatus([0x80, 0xF2, 0x20, 0x00, 0x02, 0x4F, 0x00])
response, sw1, sw2 = self.connector.send_apdu(gs_apdu)
if sw1 == 0x90 and sw2 == 0x00:
data = gs_apdu.parse_response()
for x in range(len(data)):
self.treeveiw_apps.insert(self.tvi_elf, 0, text=toHexString(data[x][0])
, values=('{:02X}'.format(data[x][1])
, '{:02X}'.format(data[x][2])))
gs_apdu = GetStatus([0x80, 0xF2, 0x24, 0x00, 0x02, 0x4F, 0x00])
response, sw1, sw2 = self.connector.send_apdu(gs_apdu)
if sw1 == 0x90 and sw2 == 0x00:
data = gs_apdu.parse_response()
for x in range(len(data)):
self.treeveiw_apps.insert(self.tvi_app, 0, text=toHexString(data[x][0])
, values=('{:02X}'.format(data[x][1])
, '{:02X}'.format(data[x][2])))
except NotImplementedError:
tkmb.showinfo('Error', 'mutual auth error...')
return
except RuntimeError:
tkmb.showinfo('Error', 'mutual auth error...')
return
except Exception:
tkmb.showinfo('Error', 'Please check a card or readers...')
return


class DebuggerWidget(object):
"""Debugger class
"""

def __init__(self):
"""Construct a new Debugger.
"""
self.__printer = None

def set_debug_widget(self, widget):
"""Sets a tkinter widget for printing a log.
It recommends that the widget is an instance of the Entry widget.
"""
self.__printer = widget

def print_log(self, str_log_message):
"""Prints a log message
"""
if self.__printer is not None:
self.__printer.insert(tk.END, str_log_message)
self.__printer.see(tk.END)
print(str_log_message)


class SCComponent(object):
"""SCComponent class
It is a base class of the ''scm'' module.
"""

def __init__(self, debugger):
"""Construct a new SCComponent.
"""
self.debugger = debugger

def print_log(self, str_log_message):
"""Prints a log message
"""
self.debugger.print_log(str_log_message)


class Connector(SCComponent):
"""Connector class
"""

def __init__(self, debugger):
"""Construct a new Connector.
"""
super().__init__(debugger)
self.refresh()
self._selected_reader = None
self._connection = None

def get_all_connectors(self):
"""Returns the list of all smartcard connectors'' names.

Returns:
The name list of all smaartcard connectors.
"""
n = len(self._readers)
names = []
for i in range(n):
names.append(self._readers[i].name)
return names

def get_selected_connector_name(self):
"""Returns the name of a selected connector.

Returns:
the name of a selected connector.
"""
return self._selected_reader.name

def refresh(self):
"""Refresh the list of smartcard connectors.
"""
self._readers = readers()

def select_reader(self, str_connector_name):
"""Sets a selected connector

Args:
str_connector_name (str) -- the name of a selected connector.

Raises:
ValueError -- The ''str_connector_name'' value is invalid.
"""
b_found = False
for r in self._readers:
if r.name == str_connector_name:
self._selected_reader = r
b_found = True
break
if not b_found:
raise ValueError

def reset(self):
"""Reset a card in a selected connector

Returns:
The ATR(Answer to Reset) of a card.

Raises:
IOError -- the card does not connected to a selected connector.
"""
if self._selected_reader is None:
raise IOError
if self._connection is not None:
self._connection.disconnect()
self._connection = None
self._connection = self._selected_reader.createConnection()
self._connection.connect()
self.print_log('ATR: ' + self.get_atr() + '\n')
return self.get_atr()

def get_atr(self):
"""Returns a ATR(Answer to Reset) of a card.

Returns:
The ATR(Answer to Reset) of a card.
"""
return toHexString(self._connection.getATR())

def send_command(self, apdu):
"""Sends a apdu command to a smartcard.
"""
if type(apdu) == str:
#buf_apdu = CommandAPDU(apdu).toBytes()
buf_apdu = toBytes(apdu)
elif type(apdu) == list:
buf_apdu = apdu
response, sw1, sw2 = self._connection.transmit(buf_apdu)
capdu = '< ' + toHexString(buf_apdu) + '\n'
rapdu = ('> ' + toHexString(response) + '\n> {:02X}'.format(sw1)
+ ' {:02X}'.format(sw2) +'\n')
self.print_log(capdu)
self.print_log(rapdu)
if sw1 == 0x61: # Get Response
get_response = '00C00000' + '{:02X}'.format(sw2)
buf_apdu = toBytes(get_response)
response, sw1, sw2 = self._connection.transmit(buf_apdu)
capdu = '< ' + toHexString(buf_apdu) + '\n'
rapdu = ('> ' + toHexString(response) + '\n> {:02X}'.format(sw1)
+ ' {:02X}'.format(sw2) +'\n')
self.print_log(capdu)
self.print_log(rapdu)
return response, sw1, sw2

def send_apdu(self, apdu):
"""Sends a apdu command to a smartcard.

Args:
apdu -- APDU instance
"""
response, sw1, sw2 = self.send_command(apdu.get_apdu())
apdu.response(response, sw1, sw2)
return response, sw1, sw2


scm/gp.py

"""Globalplatform module
"""

NO_DERIVATION = "none"
CPG201 = 'cpg201'
CPG211 = 'cpg211'


class GP(object):
"""GlobalPlatform class
"""

def __init__(self, cnt):
"""Construct a new GlobalPlatform.

Args:
cnt -- the scm.system.Connector instance
"""
pass

def mutual_auth(self, **kwlist):
"""Perform mutual auth between a card and a terminal.

Keyword arguments:
enc -- the encryption key
mac -- the message authentication code key
dek -- the data encryption key
rule -- the derivation rule (default NO_DERIVATION)

Returns:
True/ False -- If mutual auth is success, it will return True.
sw1 -- Status word1
sw2 -- Status word2

Raise:
RuntimeError -- runtime error
NotImplementedError -- supports only SCP02
"""
pass


scm/apdu.py

"""APDU module
"""


class APDU(object):
"""APDU class
"""

#define static variables
OFFSET_CLA = 0
OFFSET_INS = 1
OFFSET_P1 = 2
OFFSET_P2 = 3
OFFSET_LC = 4
OFFSET_DATA = 5

def __init__(self, apdu):
"""Constructor

Args:
apdu -- full command apdu(str or list).

Raise:
The apdu argument must be str or list.
If it is not str or list, raise the TypeError.
"""
self._apdu_buffer = []
if type(apdu) is str:
for i in range(0, len(apdu), 2):
self._apdu_buffer.append(int(apdu[i:i+2], base=16))
elif type(apdu) is list:
self._apdu_buffer = apdu
else:
raise TypeError
print(self._apdu_buffer)

def get_apdu(self):
"""Returns the apdu buffer
"""
return self._apdu_buffer

def cla(self):
"""Gets the Class byte

Returns:
The Class byte
"""
return self._apdu_buffer[APDU.OFFSET_CLA]

def ins(self):
"""Gets the Instruction

Returns:
The Instruction
"""
return self._apdu_buffer[APDU.OFFSET_INS]

def p1(self):
"""Gets the P1

Returns:
The P1
"""
return self._apdu_buffer[APDU.OFFSET_P1]

def p2(self):
"""Gets the P2

Returns:
The P2
"""
return self._apdu_buffer[APDU.OFFSET_P2]

def response(self, resp, sw1, sw2):
"""Sets a response message

Argss:
response -- data of the resposne message
sw1 -- status word1
sw2 -- status word2
"""
self.resp = resp
self.sw1 = sw1
self.sw2 = sw2

def parse_response(self):
"""Parses data of the response message in the Command

Returns:
Parsed resposne data
"""
raise NotImplementedError


class GetStatus(APDU):
"""GET STATUS Command class
"""

def __init__(self, apdu):
"""Constructor

Args:
apdu -- full command apdu(str or list).

Raise:
The apdu argument must be str or list.
If it is not str or list, raise the TypeError.
"""
super().__init__(apdu)

def parse_response(self):
"""Parses data of the response message in the Command

Returns:
Parsed resposne data(list)
"""
rets = []
if self.resp[0] == 0xE3:
#GlobalPlatform Registry Data(TLV)
raise NotImplementedError
elif self.resp[0] >= 5 and self.resp[0] <= 10:
try:
if self.p1() != 0x80 and self.p1() != 0x40 \
and self.p1() != 0x20 and self.p1() != 0x10:
raise ValueError
i = 0
while True:
data = []
len_aid = self.resp[i]
i = i + 1
data.append(self.resp[i:i+len_aid])
i = i + len_aid
data.append(self.resp[i])
i = i + 1
data.append(self.resp[i])
i = i + 1
if self.p1() == 0x10:
ems = []
em_num = self.resp[i]
i = i + 1
for l in range(em_num):
len_aid = self.resp[i]
i = i + 1
ems.append(self.resp[i:i+len_aid])
i = i + len_aid
data.append(ems)
rets.append(data)
if i >= len(self.resp):
break
except IndexError:
raise ValueError
else:
raise ValueError
return rets


이 시리즈는 이제 끝!

저작자 표시 비영리 변경 금지
신고

+ Recent posts

티스토리 툴바