add netkey-tool from Peter Koch

git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@2349 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
nils 2005-06-14 21:37:19 +00:00
parent 030d58d7ca
commit a6db0256c9
4 changed files with 743 additions and 1 deletions

View File

@ -16,6 +16,7 @@ MANSRC = \
pkcs15-tool.1 \
pkcs11-tool.1 \
cardos-info.1 \
netkey-tool.1 \
opensc.7 \
pkcs15.7 \
sc_connect_card.3 \

102
docs/netkey-tool.1 Normal file
View File

@ -0,0 +1,102 @@
.PU
.ds nm \fBnetkey-tool\fR
.TH netkey-tool 1 "May 16, 2005" "" OpenSC
.SH NAME
netkey-tool \- utility for NetKey E4 smartcards
.SH SYNOPSIS
\*(nm
.RI [OPTIONS]
[command]
.SH DESCRIPTION
The \*(nm utility can be used from the command line to perform
some smart card operations with NetKey E4 cards that cannot
be done easily with other OpenSC-tools, such as changing local
PINs, storing certificates into empty NetKey E4 cert-files or
displaying the initial PUK-value.
.SH OPTIONS
.TP
.BR \-\-help ", " \-h
Displays a short help message.
format
.TP
.BR \-v
Causes \*(nm to be more verbose. Specify this flag several times
to enable debug output in the opensc library.
.TP
.BR "\-\-pin " \fIpin-value\fP ", \-p " \fIpin-value\fP
Specifies the current value of the global PIN.
.TP
.BR "\-\-puk " \fIpin-value\fP ", \-u " \fIpin-value\fP
Specifies the current value of the global PUK.
.TP
.BR "\-\-pin0 " \fIpin-value\fP ", \-0 " \fIpin-value\fP
Specifies the current value of the local PIN0 (aka local PIN).
.TP
.BR "\-\-pin1 " \fIpin-value\fP ", \-1 " \fIpin-value\fP
Specifies the current value of the local PIN1 (aka local PUK).
.SH PIN FORMAT
With \fIpin-value\fP you can specify one of the cards pins.
You may use plain ascii-strings (i.e. 123456) or a hex-string
(i.e. 31:32:33:34:35:36). A hex-string consists
of exacly n 2-digit hexnumbers separated by n-1 colons.
Don't use leading or trailing colons or 1-digit hex-numbers. :12:34:
and 1:2:3:4 are both pins of length 7 and you most likely
intedend to use 12:34 or 01:02:03:04 wich are pins of length
2 and 4.
.SH COMMANDS
When used without any options or commands, \*(nm will
display information about the smartcards pins and
certificates. This will not change your card in
any aspect (assumed there are no bugs in \*(nm).
In particular the tries-left counters of the pins
are investigated without doing actual pin-verifications.
If you specify the global PIN via the \fB\-\-pin\fP option,
\*(nm will also display the initial value of the cards
global PUK. If your global PUK was changed \*(nm will
still diplay its initial value. There's no way to recover
a lost global PUK once it was changed and got lost. There's
also no way to display the initial value of your global
PUK without knowing the current value of your global PIN.
For most of the commands that \*(nm can execute, you have
to specify one pin. One notable exeption is the
\fBnullpin\fP command, but this command can only be executed
once in the lifetime of a NetKey E4 card.
.IP "\fBunblock pin | pin0 | pin1\fP" 4
This unblocks the specified pin. This needs the value
of another pin and if you don't specify a correct one,
\*(nm will tell you which one is needed.
.IP "\fBchange pin | puk | pin0 | pin1 \fIpin-value\fP" 4
This changes the value of the specified pin to the given
new value. This needs the value of either the same
pin or another pin and if you don't specify a correct one,
\*(nm will tell you which one is needed.
.IP "\fBnullpin \fIpin-value\fP" 4
This command can be executed only if the global PIN
of your card is in nullpin-state. There's no way to
return back to nullpin-state once you have changed
your global PIN. You don't need a pin to execute
the nullpin-command. After a succesfull nullpin-command
\*(nm will display your cards initial PUK-value.
.IP "\fBcert \fIno\fP \fIfilename\fP" 4
This command will read one of your cards certificates
(as specified by number \fIno\fP) and save this
certificate into file \fIfilename\fP in PEM-format.
Certificates on a NetKey E4 card are readable without
a pin, so you don't have to specify one.
.IP "\fBcert \fIfilename\fP \fIno\fP" 4
This command will read the first PEM-encoded certificate from
file \fIfilename\fP and store this into your smartcards
certificate file number \fIno\fP. Some of your
smartcards certificate files might be readonly, so
this will not work with all values of \fIno\fP. If
a certificate file is writable you must specify a
pin in order to change it. If you try to use this
command without specifying a pin, \*(nm will tell
you which one is needed.
.SH SEE ALSO
.BR opensc (7),
.BR opensc-explorer (1)
.SH AUTHORS
\*(nm was written by Peter Koch <pk_opensc@web.de>.

View File

@ -7,7 +7,7 @@ EXTRA_DIST = Makefile.mak
AM_LDFLAGS = @LIBOPENSC@
if HAVE_SSL
PROGRAMS_SSL = cryptoflex-tool pkcs15-init
PROGRAMS_SSL = cryptoflex-tool pkcs15-init netkey-tool
endif
bin_PROGRAMS = opensc-tool opensc-explorer pkcs15-tool pkcs15-crypt \
@ -32,5 +32,7 @@ cardos_info_SOURCES = cardos-info.c util.c
cardos_info_LDADD = @GETOPTSRC@
eidenv_SOURCES = eidenv.c
eidenv_LDADD = @GETOPTSRC@
netkey_tool_SOURCES = netkey-tool.c
netkey_tool_LDADD = @GETOPTSRC@ @LIBCRYPTO@
noinst_HEADERS = util.h

637
src/tools/netkey-tool.c Normal file
View File

@ -0,0 +1,637 @@
/*
* Netkey-Tool for Telesec Netkey E4 cards.
*
* compile with:
* gcc -I<opensc-path>/include -I<openssl-path>/include \
* -L<opensc-path>/lib -L<openssl-path>/lib \
* -o netkey-tool netkey-tool.c -lopensc -lcrypto
*
* Copyright (C) 2005, Peter Koch <pk_opensc@web.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#else
# ifdef linux
# define HAVE_GETOPT_H
# endif
#endif
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_GETOPT_H
# include <getopt.h>
#endif
#include <string.h>
#include <errno.h>
#include <opensc/opensc.h>
#include <openssl/x509v3.h>
#include <openssl/pem.h>
static struct {
char *path;
int readonly;
char *label;
} certlist[]={
{"DF01C000", 1, "Telesec Signatur Zertifikat"},
{"DF014331", 0, "User Signatur Zertifikat1"},
{"DF014332", 0, "User Signatur Zertifikat2"},
{"DF01C100", 1, "Telesec Authentifizierungs Zertifikat"},
{"DF014371", 0, "User Authentifizierungs Zertifikat1"},
{"DF014372", 0, "User Authentifizierungs Zertifikat2"},
{"DF01C200", 1, "Telesec Verschlüsselungs Zertifikat"},
{"DF0143B1", 0, "User Verschlüsselungs Zertifikat1"},
{"DF0143B2", 0, "User Verschlüsselungs Zertifikat2"},
};
static struct {
char *path;
char *name;
char *label;
int p1, p2;
int tries;
int len;
u8 value[32];
} pinlist[]={
{"3F005000", "pin", "global PIN", 1,-1, 0, 0},
{"3F005001", "puk", "global PUK", -1,-1, 0, 0},
{"3F00DF015080", "pin0", "local PIN0", 3, 0, 0, 0},
{"3F00DF015081", "pin1", "local PIN1", 0,-1, 0, 0},
};
void show_pin(
sc_card_t *card,
int pin
){
sc_path_t p;
sc_file_t *f;
struct sc_apdu a;
int i, max;
sc_format_path(pinlist[pin].path,&p);
if((i=sc_select_file(card,&p,&f))<0){
printf("\nCannot select PIN-file %s, is this a NetKey-Card ??\n", pinlist[pin].path);
return;
}
if(f->type!=SC_FILE_TYPE_WORKING_EF || f->ef_structure!=SC_FILE_EF_LINEAR_VARIABLE_TLV ||
f->prop_attr_len!=5 || f->prop_attr[0]!=0x01 || f->prop_attr[1]!=0x80
){
printf("\nInvald PIN-file: Type=%d, EF-Structure=%d, Prop-Len=%d %02X:%02X:%02X\n",
f->type, f->ef_structure, f->prop_attr_len,
f->prop_attr[0], f->prop_attr[1], f->prop_attr[2]
);
return;
}
pinlist[pin].tries=f->prop_attr[3], max=f->prop_attr[4];
if(pinlist[pin].len){
sc_format_apdu(card, &a, SC_APDU_CASE_3_SHORT, 0x20, 0x00, f->prop_attr[2] | (pin>1 ? 0x80 : 0x00) );
a.data=pinlist[pin].value, a.lc=a.datalen=pinlist[pin].len;
} else {
sc_format_apdu(card, &a, SC_APDU_CASE_1, 0x20, 0x00, f->prop_attr[2] | (pin>1 ? 0x80 : 0x00) );
}
if((i=sc_transmit_apdu(card, &a))<0){
printf("\nsc_transmit_apdu() failed, %s\n", sc_strerror(i));
return;
}
printf("%s: %d tries left, %d tries max, ", pinlist[pin].label, pinlist[pin].tries, max);
if(a.sw1==0x63 && (a.sw2&0xF0)==0xC0) printf("not verified\n");
else if(a.sw1==0x90 && a.sw2==0x00) printf("verified\n");
else if(a.sw1==0x69 && a.sw2==0x83) printf("blocked\n");
else if(a.sw1==0x69 && a.sw2==0x85) printf("NullPin\n");
else printf("Error %02X%02X\n", a.sw1, a.sw2);
}
void show_certs(
sc_card_t *card
){
sc_path_t p;
sc_file_t *f;
X509 *c;
u8 buf[2000], *q;
int i, j;
printf("\n");
for(i=0;i<sizeof(certlist)/sizeof(certlist[0]);++i){
printf("Certificate %d: %s", i, certlist[i].label); fflush(stdout);
sc_format_path(certlist[i].path,&p);
if((j=sc_select_file(card,&p,&f))<0){
printf(", Cannot select Cert-file %s, is this a NetKey-Card ??\n",
certlist[i].path
);
continue;
}
if(f->type!=SC_FILE_TYPE_WORKING_EF || f->ef_structure!=SC_FILE_EF_TRANSPARENT){
printf(", Invald Cert-file: Type=%d, EF-Structure=%d\n", f->type, f->ef_structure);
continue;
}
if((j=sc_read_binary(card,0,buf,f->size,0))<0){
printf(", Cannot read Cert-file, %s\n", sc_strerror(j));
continue;
}
printf(", Maxlen=%u", f->size);
q=buf;
if(q[0]==0x30 && q[1]==0x82){
if(q[4]==6 && q[5]<10 && q[q[5]+6]==0x30 && q[q[5]+7]==0x82) q+=q[5]+6;
printf(", Len=%u\n", (q[2]<<8)|q[3]);
if((c=d2i_X509(NULL,&q,f->size))){
X509_NAME_get_text_by_NID(c->cert_info->subject, NID_commonName, buf,sizeof(buf));
printf(" Subject-CN: %s\n", buf);
X509_NAME_get_text_by_NID(c->cert_info->issuer, NID_commonName, buf,sizeof(buf));
printf(" Issuer-CN: %s\n", buf);
X509_free(c);
} else printf(" Invalid Certificate-Data\n");
} else printf(", empty\n");
}
}
void show_initial_puk(
sc_card_t *card
){
sc_path_t p;
sc_file_t *f;
struct sc_apdu a;
u8 buf1[128], buf2[128];
int i;
printf("\nReading crypted Initial-PUK-file: ");
sc_format_path("3F004350",&p);
if((i=sc_select_file(card,&p,&f))<0){
printf("Cannot select crypted Initial-PUK-file, %s\n", sc_strerror(i));
return;
}
if((i=sc_read_binary(card,0,buf1,128,0))!=128){
printf("Cannot read crypted Initial-PUK-file, %s\n", sc_strerror(i));
return;
}
printf("OK\nDecrypting crypted Initial-PUK-file: ");
sc_format_path("3F00DF01",&p);
if((i=sc_select_file(card,&p,&f))<0){
printf("Cannot select DF01, %s\n", sc_strerror(i));
return;
}
sc_format_apdu(card, &a, SC_APDU_CASE_3_SHORT, 0x22, 0xC1, 0xB8);
buf2[0]=0x80, buf2[1]=0x01, buf2[2]=0x10, buf2[3]=0x84, buf2[4]=0x01, buf2[5]=0x81;
a.data=buf2, a.lc=a.datalen=6;
if((i=sc_transmit_apdu(card, &a))<0){
printf("sc_transmit_apdu(MSE) failed, %s\n", sc_strerror(i));
return;
}
if(a.sw1!=0x90 && a.sw2!=0x00){
printf("MSE=%02X%02X\n", a.sw1, a.sw2);
return;
}
sc_format_apdu(card, &a, SC_APDU_CASE_4_SHORT, 0x2A, 0x84, 0x80);
a.data=buf1, a.lc=a.datalen=128;
a.resp=buf2, a.le=a.resplen=128;
if((i=sc_transmit_apdu(card, &a))<0){
printf("sc_transmit_apdu(PSO) failed, %s\n", sc_strerror(i));
return;
}
if(a.sw1!=0x90 && a.sw2!=0x00){
printf("PSO=%02X%02X\n", a.sw1, a.sw2);
return;
}
printf("OK ==> Initial-PUK:"); for(i=120;i<128;++i) printf("%c",buf2[i]); printf("\n");
}
void show_card(
sc_card_t *card
){
sc_path_t path;
sc_file_t *file;
u8 buf[100];
int i, len;
sc_format_path("3F002F02",&path);
if((i=sc_select_file(card,&path,&file))<0){
printf("\nCannot select Serial-Number 2F02, is this a NetKey-Card ??\n");
return;
}
if(file->type!=SC_FILE_TYPE_WORKING_EF || file->ef_structure!=SC_FILE_EF_TRANSPARENT ||
file->size!=12 || (len=sc_read_binary(card,0,buf,12,0))!=12 || buf[0]!=0x5A || buf[1]!=0x0A
){
printf("\nInvald Serial-Number: Type=%d, EF-Structure=%d, Size=%d\n",
file->type, file->ef_structure, file->size
);
return;
}
printf("\nSerial-Number: ");
for(i=2;i<11;++i) printf("%02X", buf[i]);
printf("%X\n\n", buf[11]>>4);
for(i=0;i<4;++i) show_pin(card, i);
// printf("%s: %u tries left, %u tries max, %s\n", pinlist[i].label, pinlist[i].tries, max, status);
if(pinlist[0].len) show_initial_puk(card);
}
void handle_change(
sc_card_t *card,
int pin1,
int pin2,
int do_change,
u8 *newpin,
int newlen
){
sc_path_t p;
sc_file_t *f;
struct sc_apdu a;
u8 ref;
int i;
printf("\n%s %s with %s: ", do_change ? "Changing" : "Unblocking", pinlist[pin1].label, pinlist[pin2].label);
sc_format_path(pinlist[pin1].path,&p);
if((i=sc_select_file(card,&p,&f))<0){
printf("\nCannot select %s, %s\n", pinlist[pin1].label, sc_strerror(i));
return;
}
ref=f->prop_attr[2] | (strlen(pinlist[pin1].path)>8 ? 0x80 : 0x00);
if(do_change){
sc_format_apdu(card, &a, SC_APDU_CASE_3_SHORT, 0x24, 0x01, ref);
a.data=newpin, a.lc=a.datalen=newlen;
} else {
sc_format_apdu(card, &a, SC_APDU_CASE_1, 0x2C, 0x03, ref);
}
if((i=sc_transmit_apdu(card, &a))<0){
printf("\nsc_transmit_apdu() failed, %s\n", sc_strerror(i));
return;
}
if(a.sw1!=0x90 && a.sw2!=0x00){
printf("%02X%02X\n", a.sw1, a.sw2);
return;
}
printf("OK\n");
}
void handle_nullpin(
sc_card_t *card,
u8 *newpin,
int newlen
){
sc_path_t p;
sc_file_t *f;
struct sc_apdu a;
u8 ref, buf[40];
int i;
printf("\nSetting initial PIN-value: ");
sc_format_path(pinlist[0].path,&p);
if((i=sc_select_file(card,&p,&f))<0){
printf("\nCannot select %s, %s\n", pinlist[0].label, sc_strerror(i));
return;
}
ref=f->prop_attr[2];
sc_format_apdu(card, &a, SC_APDU_CASE_1, 0x20, 0x00, f->prop_attr[2]);
if((i=sc_transmit_apdu(card, &a))<0){
printf("sc_transmit_apdu() failed, %s\n", sc_strerror(i));
return;
}
if(a.sw1!=0x69 && a.sw2!=0x85){
printf("global PIN is not in NullPin-state (%02X%02X)\n", a.sw1, a.sw2);
return;
}
sc_format_apdu(card, &a, SC_APDU_CASE_3_SHORT, 0x24, 0x00, ref);
for(i=0;i<6;++i) buf[i]=0;
for(i=0;i<newlen;++i) buf[6+i]=newpin[i];
a.data=buf, a.lc=a.datalen=6+newlen;
if((i=sc_transmit_apdu(card, &a))<0){
printf("sc_transmit_apdu() failed, %s\n", sc_strerror(i));
return;
}
if(a.sw1!=0x90 && a.sw2!=0x00){
printf("Error %02X%02X\n", a.sw1, a.sw2);
return;
}
printf("OK\n");
}
void handle_readcert(
sc_card_t *card,
int cert,
char *file
){
sc_path_t p;
sc_file_t *f;
FILE *fp;
X509 *c;
u8 buf[1536], *q;
int i, len;
printf("\nReading Card-Certificate %d: ", cert); fflush(stdout);
sc_format_path(certlist[cert].path,&p);
if((i=sc_select_file(card,&p,&f))<0){
printf("cannot select certfile, %s\n", sc_strerror(i));
return;
}
if((len=sc_read_binary(card,0,buf,f->size,0))<0){
printf("Cannot read Cert, %s\n", sc_strerror(len));
return;
}
q=buf;
if(q[0]==0x30 && q[1]==0x82 && q[4]==6 && q[5]<10 && q[q[5]+6]==0x30 && q[q[5]+7]==0x82) q+=q[5]+6;
if((c=d2i_X509(NULL,&q,len))==NULL){
printf("cardfile contains %d bytes which are not a certificate\n", len);
return;
}
printf("Writing Cert to %s: ", file); fflush(stdout);
if((fp=fopen(file,"w"))==NULL) printf("Cannot open file, %s\n", strerror(errno));
else {
fprintf(fp,"Certificate %d from Netkey E4 card\n\n", cert);
PEM_write_X509(fp,c);
printf("OK\n");
}
X509_free(c);
}
void handle_writecert(
sc_card_t *card,
int cert,
char *file
){
sc_path_t p;
sc_file_t *f;
FILE *fp;
X509 *c;
u8 buf[1536], *q;
int i, len;
printf("\nReading Cert from %s: ", file); fflush(stdout);
if((fp=fopen(file,"r"))==NULL){
printf("Cannot open file, %s\n", strerror(errno));
return;
}
c=PEM_read_X509(fp,NULL,NULL,NULL);
fclose(fp);
if(c==NULL){
printf("file does not conatin PEM-encoded certificate\n");
return;
}
printf("OK\nStoring Cert into Card-Certificate %d: ", cert); fflush(stdout);
q=buf; len=i2d_X509(c,NULL); if(len>0 && len<=sizeof(buf)) i2d_X509(c,&q);
X509_free(c);
if(len<=0 || len>sizeof(buf)){
printf("certificate too long or invalid (Len=%d)\n", len);
return;
}
sc_format_path(certlist[cert].path,&p);
if((i=sc_select_file(card,&p,&f))<0){
printf("cannot select certfile, %s\n", sc_strerror(i));
return;
}
if((i=sc_update_binary(card,0,buf,len,0))<0){
printf("cannot store cert, %s\n", sc_strerror(i));
return;
}
printf("OK\n");
}
int pin_string2int(
char *s
){
int i;
for(i=0;i<sizeof(pinlist)/sizeof(pinlist[0]);++i) if(!strcasecmp(pinlist[i].name,s)) return i;
return -1;
}
void set_pin(
u8 *data,
int *pinlen,
char *pin
){
int hex, i, j=0, len;
char *p;
len=strlen(pin);
hex=(len>=5 && len%3==2);
if(hex){
len=(len+1)/3;
hex=(len<=32);
}
for(i=0;hex && i<len;++i){
if(i>0 && pin[3*i-1]!=':') hex=0;
else j=strtol(pin+3*i,&p,16);
if(hex && (j<0 || j>255 || (p-pin)!=3*i+2)) hex=0;
}
if(hex){
for(i=0;hex && i<len;++i) data[i]=strtol(pin+3*i,&p,16);
*pinlen=len;
} else {
len=strlen(pin); if(len>32) len=32;
for(i=0;i<len;++i) data[i]=((u8*)pin)[i];
*pinlen=len;
}
}
int main(
int argc,
char *argv[]
){
static struct option options[]={
{ "help", 0, 0, 'h' },
{ "verbose", 0, 0, 'v' },
{ "reader", 1, 0, 'r' },
{ "pin", 1, 0, 'p' },
{ "puk", 1, 0, 'u' },
{ "pin0", 1, 0, '0' },
{ "pin1", 1, 0, 'r' },
{ 0, 0, 0, 0 }
};
sc_context_t *ctx;
sc_card_t *card;
int do_help=0, do_unblock=0, do_change=0, do_nullpin=0, do_readcert=0, do_writecert=0;
u8 newpin[32];
char *certfile=NULL, *p;
int i, oerr=0, reader=0, debug=0, newlen=0, pin_nr=-1, cert_nr=-1;
while((i=getopt_long(argc,argv,"hvr:p:u:0:1:",options,NULL))!=EOF) switch(i){
case 'h': ++do_help; break;
case 'v': ++debug; break;
case 'r': reader=atoi(optarg); break;
case 'p': set_pin(pinlist[0].value, &pinlist[0].len, optarg); break;
case 'u': set_pin(pinlist[1].value, &pinlist[1].len, optarg); break;
case '0': set_pin(pinlist[2].value, &pinlist[2].len, optarg); break;
case '1': set_pin(pinlist[3].value, &pinlist[3].len, optarg); break;
default: ++oerr;
}
if(do_help){
fprintf(stderr,"This is netkey-tool V1.0, May 15 2005, Copyright Peter Koch <pk_opensc@web.de>\n");
fprintf(stderr,"usage: %s <options> command\n", argv[0]);
fprintf(stderr,"\nOptions:\n");
fprintf(stderr," -v : verbose, may be specified several times\n");
fprintf(stderr," --reader <num>, -r <num> : use reader num (default 0)\n");
fprintf(stderr," --pin <ppp>, -p <ppp> : global PIN\n");
fprintf(stderr," --puk <ppp>, -u <ppp> : global PUK\n");
fprintf(stderr," --pin0 <ppp>, -0 <ppp> : local PIN0\n");
fprintf(stderr," --pin1 <ppp>, -1 <ppp> : local PIN1\n");
fprintf(stderr,"\nCommands:\n");
fprintf(stderr," unblock {pin | pin0 | pin1}\n");
fprintf(stderr," change {pin | puk | pin0 | pin1} <new pin>\n");
fprintf(stderr," nullpin <new pin>\n");
fprintf(stderr," cert <num> <certfile>\n");
fprintf(stderr," cert <certfile> <num>\n");
fprintf(stderr,"\nExamples:\n");
fprintf(stderr,"list PINs and Certs without changing anything. Try this first!!\n");
fprintf(stderr," %s\n", argv[0]);
fprintf(stderr,"\nlist PINs and Certs and initial PUK-value (after verification of global PIN)\n");
fprintf(stderr," %s --pin 123456\n", argv[0]);
fprintf(stderr,"\nchange local PIN0 to 654321 after verification of global PIN\n");
fprintf(stderr," %s --pin 123456 change pin0 654321\n", argv[0]);
fprintf(stderr,"\nchange global PIN from hex 01:02:03:04:05:06 to ascii 123456\n");
fprintf(stderr," %s --pin 01:02:03:04:05:06 change pin 123456\n", argv[0]);
fprintf(stderr,"\nunblock global PIN with global PUK\n");
fprintf(stderr," %s --puk 12345678 unblock pin\n", argv[0]);
fprintf(stderr,"\nset global PIN to initial value when in NullPin-state\n");
fprintf(stderr," %s nullpin 123456\n", argv[0]);
fprintf(stderr,"\nstore Certificate into card at position 2 and read it back into file\n");
fprintf(stderr," %s --pin1 123456 cert /tmp/cert1 2\n", argv[0]);
fprintf(stderr," %s cert 2 /tmp/cert2\n", argv[0]);
fprintf(stderr,"\nBe carful - this tool may destroy your card\n");
fprintf(stderr,"\nQuestions? Comments? ==> opensc-user@opensc.org\n");
exit(1);
}
if(optind==argc-2 && !strcmp(argv[optind],"unblock")){
++optind, do_unblock=1;
pin_nr=pin_string2int(argv[optind++]);
if(pin_nr<0 || pin_nr==1) ++oerr;
}
if(optind==argc-3 && !strcmp(argv[optind],"change")){
++optind, do_change=1;
pin_nr=pin_string2int(argv[optind++]);
if(pin_nr<0 || pin_nr>3) ++oerr;
set_pin(newpin,&newlen,argv[optind++]);
}
if(optind==argc-2 && !strcmp(argv[optind],"nullpin")){
++optind, do_nullpin=1;
set_pin(newpin,&newlen,argv[optind++]);
}
if(optind==argc-3 && !strcmp(argv[optind],"cert")){
++optind;
cert_nr=strtol(argv[optind],&p,10);
if(argv[optind][0] && !*p && cert_nr>=0 && cert_nr<sizeof(certlist)/sizeof(certlist[0])){
do_readcert=1, certfile=argv[optind+1];
} else {
do_writecert=1, certfile=argv[optind];
cert_nr=strtol(argv[optind+1],&p,10);
if(!argv[optind][0] || *p || cert_nr<0 || cert_nr>=sizeof(certlist)/sizeof(certlist[0])) ++oerr;
}
optind+=2;
}
if(oerr || optind!=argc){
fprintf(stderr,"%s: invalid usage, try --help\n", argv[0]);
exit(1);
}
if((i=sc_establish_context(&ctx, argv[0]))<0){
fprintf(stderr,"Establish-Context failed: %s\n", sc_strerror(i));
exit(1);
}
ctx->debug=debug;
if(ctx->debug>0) printf("Context for application \"%s\" created, Debug=%d\n", ctx->app_name, ctx->debug);
for(i=0;ctx->card_drivers[i];++i) if(!strcmp("tcos", ctx->card_drivers[i]->short_name)) break;
if(!ctx->card_drivers[i]){
fprintf(stderr,"Context does not support TCOS-cards\n");
exit(1);
}
printf("%d Reader detected\n", ctx->reader_count);
for(i=0;i<ctx->reader_count;++i){
printf("%d: %s, Driver: %s, %d Slot(s)\n",
i, ctx->reader[i]->name, ctx->reader[i]->driver->name,
ctx->reader[i]->slot_count
);
}
if(reader<0 || reader>=ctx->reader_count){
fprintf(stderr,"Cannot open reader %d\n", reader);
exit(1);
}
if((i=sc_connect_card(ctx->reader[0], 0, &card))<0){
fprintf(stderr,"Connect-Card failed: %s\n", sc_strerror(i));
exit(1);
}
printf("\nCard detected (driver: %s)\nATR:", card->driver->name);
for(i=0;i<card->atr_len;++i) printf("%c%02X", i?':':' ', card->atr[i]); printf("\n");
if((i=sc_lock(card))<0){
fprintf(stderr,"Lock failed: %s\n", sc_strerror(i));
exit(1);
}
show_card(card);
if(do_unblock || do_change){
int i1=pinlist[pin_nr].p1, i2=pinlist[pin_nr].p2;
if((do_unblock || !pinlist[pin_nr].len) &&
(i1<0 || !pinlist[i1].len) && (i2<0 || !pinlist[i2].len)
){
fprintf(stderr, "\nNeed %s", do_change ? pinlist[pin_nr].label : pinlist[i1].label);
if(do_change && i1>=0) fprintf(stderr, " or %s", pinlist[i1].label);
if(i2>=0) fprintf(stderr, " or %s", pinlist[i2].label);
fprintf(stderr, " to %s %s\n", do_change ? "change" : "unblock", pinlist[pin_nr].label);
} else {
if(do_change && pinlist[pin_nr].len) i1=pin_nr;
if(i1<0 || !pinlist[i1].len) i1=i2;
handle_change(card, pin_nr, i1, do_change, newpin, newlen);
}
}
if(do_nullpin){
handle_nullpin(card, newpin, newlen);
show_initial_puk(card);
}
if(do_readcert) handle_readcert(card, cert_nr, certfile);
if(do_writecert){
if(certlist[cert_nr].readonly){
fprintf(stderr, "\nReadonly-Certificate %d cannot be changed\n", cert_nr);
} else if(!pinlist[0].len && !pinlist[3].len){
fprintf(stderr, "\nNeed %s or %s to change Card-Certificate %d\n",
pinlist[0].label, pinlist[3].label, cert_nr
);
} else handle_writecert(card, cert_nr, certfile);
}
if(do_unblock+do_change+do_nullpin+do_readcert==0) show_certs(card);
sc_unlock(card);
sc_disconnect_card(card,0);
sc_release_context(ctx);
exit(0);
}