44
45
#include "app-common.h"
47
int (*status_cb)(void *opaque, const char *line);
51
assuan_error_t (*status_cb)(void *opaque, const char *line);
48
52
void *status_cb_arg;
62
struct writekey_parm_s
65
const unsigned char *keydata;
52
71
static char *default_reader_port;
53
static APP current_app;
72
static app_t current_app;
75
/* Local prototypes. */
76
static assuan_error_t learn_status_cb (void *opaque, const char *line);
79
/* To avoid cluttering the code with bunches of ifdefs we use a few
80
dummy functions instead and defines. */
81
#ifndef ENABLE_AGENT_SUPPORT
83
#define ASSUAN_LINELENGTH 100
85
static assuan_context_t
86
agent_open (int try, const char *orig_codeset)
92
agent_close (assuan_context_t ctx)
97
assuan_strerror (assuan_error_t err)
99
return "no Assuan support";
103
assuan_transact (assuan_context_t ctx,
105
assuan_error_t (*data_cb)(void *, const void *, size_t),
107
assuan_error_t (*inquire_cb)(void*, const char *),
108
void *inquire_cb_arg,
109
assuan_error_t (*status_cb)(void*, const char *),
112
return 100; /* ASSUAN_NOT_IMPLEMENTED */
115
assuan_send_data (assuan_context_t ctx, const void *buffer, size_t length)
117
return 100; /* ASSUAN_NOT_IMPLEMENTED */
119
#endif /*!ENABLE_AGENT_SUPPORT*/
57
122
/* Create a serialno/fpr string from the serial number and the secret
58
123
key. caller must free the returned string. There is no error
59
124
return. [Taken from 1.9's keyid.c]*/
125
ctrl->status_cb (ctrl->status_cb_arg, buf);
190
if (ctrl && ctrl->status_cb)
191
ctrl->status_cb (ctrl->status_cb_arg, buf);
127
193
va_end (arg_ptr);
131
void gcry_md_hash_buffer (int algo, void *digest,
132
const void *buffer, size_t length)
197
/* Replacement function of the Libgcrypt onewhich is used in gnupg
198
1.9. Thus function computes the digest of ALGO from the data in
199
BUFFER of LENGTH. ALGO must be supported. */
201
gcry_md_hash_buffer (int algo, void *digest,
202
const void *buffer, size_t length)
134
204
MD_HANDLE h = md_open (algo, 0);
317
/* Print an error message for a failed assuan_transact and return a
318
gpg error code. No error is printed if RC is 0. */
320
test_transact (int rc, const char *command)
324
log_error ("sending command `%s' to agent failed: %s\n",
325
command, assuan_strerror (rc));
326
return gpg_error (GPG_ERR_CARD);
330
/* Try to open a card using an already running agent. Prepare a
331
proper application context and return it. */
333
open_card_via_agent (int *scd_available)
335
assuan_context_t ctx;
337
struct agent_card_info_s info;
341
ctx = agent_open (1, NULL);
345
/* Request the serialbnumber of the card. If we get
346
NOT_SUPPORTED or NO_SCDAEMON back, the gpg-agent either has
347
disabled scdaemon or it can't be used. We close the connection
348
in this case and use our own code. This may happen if just the
349
gpg-agent has been installed for the sake of passphrase
351
memset (&info, 0, sizeof info);
352
rc = assuan_transact (ctx, "SCD SERIALNO openpgp",
353
NULL, NULL, NULL, NULL,
354
learn_status_cb, &info);
357
if ((rc & 0xffff) == 60 || (rc & 0xffff) == 119)
358
; /* No scdaemon available to gpg-agent. */
361
write_status_text (STATUS_CARDCTRL, "4");
362
log_info ("selecting openpgp failed: %s\n", assuan_strerror (rc));
365
agent_release_card_info (&info);
370
app = xcalloc (1, sizeof *app);
371
app->assuan_ctx = ctx;
250
378
/* Open the current card and select the openpgp application. Return
251
379
an APP context handle to be used for further procesing or NULL on
252
380
error or if no OpenPGP application exists.*/
259
387
int did_shutdown = 0;
390
/* First check whether we can contact a gpg-agent and divert all
391
operation to it. This is required because gpg as well as the
392
agent require exclusive access to the reader. */
397
app = open_card_via_agent (&scd_available);
399
goto ready; /* Yes, there is a agent with a usable card, go that way. */
401
return NULL; /* agent avilabale but card problem. */
405
/* No agent or usable agent, thus we do it on our own. */
265
409
if (did_shutdown)
324
474
card_close (void)
328
APP app = current_app;
478
app_t app = current_app;
329
479
current_app = NULL;
331
apdu_close_reader (app->slot);
482
agent_close (app->assuan_ctx);
484
apdu_close_reader (app->slot);
490
/* Format a cache ID from the serialnumber in SN and return it as an
491
allocated string. In case of an error NULL is returned. */
493
format_cacheid (const char *sn)
497
char *cacheid = NULL;
499
/* The serialnumber we use for a card is "CARDSN:serialno". Where
500
serialno is the BCD string (i.e. hex string) with the full
501
number. The serial number expect here constsis of hexdigits
502
followed by other characters, we cut off these other
506
for (s=sn,snlen=0; hexdigitp (s); s++, snlen++)
510
/* Yes, this looks indeed like an OpenPGP card S/N. */
511
cacheid = xtrymalloc (7+snlen+1);
514
memcpy (cacheid, "CARDSN:", 7);
515
memcpy (cacheid+7, sn, snlen);
516
cacheid[7+snlen] = 0;
337
523
/* Check that the serial number of the current card (as described by
338
524
APP) matches SERIALNO. If there is no match and we are not in
339
525
batch mode, present a prompt to insert the desired card. The
501
653
else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
503
655
xfree (parm->pubkey_url);
504
parm->pubkey_url = unescape_status_string (line);
656
parm->pubkey_url = unescape_percent_string (line);
506
658
else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
508
660
xfree (parm->login_data);
509
parm->login_data = unescape_status_string (line);
661
parm->login_data = unescape_percent_string (line);
511
663
else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
615
767
return gpg_error (GPG_ERR_CARD);
617
769
memset (info, 0, sizeof *info);
618
memset (&ctrl, 0, sizeof ctrl);
619
ctrl.status_cb = learn_status_cb;
620
ctrl.status_cb_arg = info;
622
rc = app_get_serial_and_stamp (app, &serial, &stamp);
625
send_status_info (&ctrl, "SERIALNO", serial, strlen(serial), NULL, 0);
627
rc = app->fnc.learn_status (app, &ctrl);
773
rc = assuan_transact (app->assuan_ctx, "SCD LEARN --force",
774
NULL, NULL, NULL, NULL,
775
learn_status_cb, info);
776
rc = test_transact (rc, "SCD LEARN");
780
memset (&ctrl, 0, sizeof ctrl);
781
ctrl.status_cb = learn_status_cb;
782
ctrl.status_cb_arg = info;
784
rc = app_get_serial_and_stamp (app, &serial, &stamp);
787
send_status_info (&ctrl, "SERIALNO",
788
serial, strlen(serial), NULL, 0);
790
rc = app->fnc.learn_status (app, &ctrl);
633
/* Get an attribite from the card. Make sure info is initialized. */
798
/* Get an attribute from the card. Make sure info is initialized. */
635
800
agent_scd_getattr (const char *name, struct agent_card_info_s *info)
638
804
struct ctrl_ctx_s ctrl;
640
806
app = current_app? current_app : open_card ();
642
808
return gpg_error (GPG_ERR_CARD);
644
ctrl.status_cb = learn_status_cb;
645
ctrl.status_cb_arg = info;
646
return app->fnc.getattr (app, &ctrl, name);
812
char line[ASSUAN_LINELENGTH];
814
/* We assume that NAME does not need escaping. */
815
if (12 + strlen (name) > DIM(line)-1)
816
return gpg_error (GPG_ERR_CARD);
817
stpcpy (stpcpy (line, "SCD GETATTR "), name);
819
rc = test_transact (assuan_transact (app->assuan_ctx, line,
820
NULL, NULL, NULL, NULL,
821
learn_status_cb, info),
826
ctrl.status_cb = learn_status_cb;
827
ctrl.status_cb_arg = info;
828
rc = app->fnc.getattr (app, &ctrl, name);
736
942
agent_scd_setattr (const char *name,
737
943
const unsigned char *value, size_t valuelen)
742
app = current_app? current_app : open_card ();
744
return gpg_error (GPG_ERR_CARD);
746
rc = app->fnc.setattr (app, name, pin_cb, NULL, value, valuelen);
749
write_status (STATUS_SC_OP_FAILURE);
948
app = current_app? current_app : open_card ();
950
return gpg_error (GPG_ERR_CARD);
954
char line[ASSUAN_LINELENGTH];
957
/* We assume that NAME does not need escaping. */
958
if (12 + strlen (name) > DIM(line)-1)
959
return gpg_error (GPG_ERR_CARD);
960
p = stpcpy (stpcpy (line, "SCD SETATTR "), name);
962
for (; valuelen; value++, valuelen--)
964
if (p >= line + DIM(line)-5 )
965
return gpg_error (GPG_ERR_CARD);
966
if (*value < ' ' || *value == '+' || *value == '%')
968
sprintf (p, "%%%02X", *value);
971
else if (*value == ' ')
978
rc = test_transact (assuan_transact (app->assuan_ctx, line,
979
NULL, NULL, NULL, NULL, NULL, NULL),
984
rc = app->fnc.setattr (app, name, pin_cb, NULL, value, valuelen);
988
write_status (STATUS_SC_OP_FAILURE);
993
/* Handle a KEYDATA inquiry. Note, we only send the data,
994
assuan_transact takes care of flushing and writing the end */
995
static assuan_error_t
996
inq_writekey_parms (void *opaque, const char *keyword)
998
struct writekey_parm_s *parm = opaque;
1000
return assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
1004
/* Send a WRITEKEY command to the SCdaemon. */
1006
agent_scd_writekey (int keyno, const unsigned char *keydata, size_t keydatalen)
1010
char line[ASSUAN_LINELENGTH];
1011
app = current_app? current_app : open_card ();
1013
return gpg_error (GPG_ERR_CARD);
1015
if (app->assuan_ctx)
1017
struct writekey_parm_s parms;
1019
snprintf (line, DIM(line)-1, "SCD WRITEKEY --force OPENPGP.%d", keyno);
1020
line[DIM(line)-1] = 0;
1021
parms.ctx = app->assuan_ctx;
1022
parms.keydata = keydata;
1023
parms.keydatalen = keydatalen;
1024
rc = test_transact (assuan_transact (app->assuan_ctx, line,
1026
inq_writekey_parms, &parms,
1032
snprintf (line, DIM(line)-1, "OPENPGP.%d", keyno);
1033
line[DIM(line)-1] = 0;
1034
rc = app->fnc.writekey (app, NULL, line, 0x0001,
1036
keydata, keydatalen);
1040
write_status (STATUS_SC_OP_FAILURE);
1046
static assuan_error_t
755
1047
genkey_status_cb (void *opaque, const char *line)
757
1049
struct agent_card_genkey_s *parm = opaque;
817
1109
return gpg_error (GPG_ERR_CARD);
819
1111
memset (info, 0, sizeof *info);
820
sprintf (keynostr, "%d", keyno);
821
ctrl.status_cb = genkey_status_cb;
822
ctrl.status_cb_arg = info;
824
rc = app->fnc.genkey (app, &ctrl, keynostr,
1113
if (app->assuan_ctx)
1115
snprintf (line, DIM(line)-1, "SCD GENKEY %s%d",
1116
force? "--force ":"", keyno);
1117
line[DIM(line)-1] = 0;
1118
rc = test_transact (assuan_transact (app->assuan_ctx, line,
1119
NULL, NULL, NULL, NULL,
1120
genkey_status_cb, info),
1125
snprintf (line, DIM(line)-1, "%d", keyno);
1126
ctrl.status_cb = genkey_status_cb;
1127
ctrl.status_cb_arg = info;
1128
rc = app->fnc.genkey (app, &ctrl, line,
828
1134
write_status (STATUS_SC_OP_FAILURE);
1139
static assuan_error_t
1140
membuf_data_cb (void *opaque, const void *buffer, size_t length)
1142
membuf_t *data = opaque;
1145
put_membuf (data, buffer, length);
832
1150
/* Send a PKSIGN command to the SCdaemon. */
834
1152
agent_scd_pksign (const char *serialno, int hashalgo,
835
1153
const unsigned char *indata, size_t indatalen,
836
1154
unsigned char **r_buf, size_t *r_buflen)
1156
struct pincb_parm_s parm;
1162
memset (&parm, 0, sizeof parm);
844
1165
app = current_app? current_app : open_card ();
846
1167
return gpg_error (GPG_ERR_CARD);
848
/* Check that the card's serialnumber is as required.*/
849
rc = check_card_serialno (app, serialno);
854
rc = app->fnc.sign (app, serialno, hashalgo,
1169
if (app->assuan_ctx)
1171
char *p, line[ASSUAN_LINELENGTH];
1176
if (indatalen*2 + 50 > DIM(line))
1177
return gpg_error (GPG_ERR_GENERAL);
1179
p = stpcpy (line, "SCD SETDATA ");
1180
for (i=0; i < indatalen ; i++, p += 2 )
1181
sprintf (p, "%02X", indata[i]);
1182
rc = test_transact (assuan_transact (app->assuan_ctx, line,
1183
NULL, NULL, NULL, NULL, NULL, NULL),
1187
init_membuf (&data, 1024);
1188
snprintf (line, DIM(line)-1, "SCD PKSIGN %s", serialno);
1189
line[DIM(line)-1] = 0;
1190
rc = test_transact (assuan_transact (app->assuan_ctx, line,
1191
membuf_data_cb, &data,
1192
NULL, NULL, NULL, NULL),
1195
xfree (get_membuf (&data, &len));
1197
*r_buf = get_membuf (&data, r_buflen);
1202
/* Check that the card's serialnumber is as required.*/
1203
rc = check_card_serialno (app, serialno);
1208
rc = app->fnc.sign (app, serialno, hashalgo,
859
write_status (STATUS_SC_OP_FAILURE);
1216
write_status (STATUS_SC_OP_FAILURE);
1217
if (!app->assuan_ctx)
1218
agent_clear_pin_cache (serialno);
867
1227
const unsigned char *indata, size_t indatalen,
868
1228
unsigned char **r_buf, size_t *r_buflen)
1230
struct pincb_parm_s parm;
1236
memset (&parm, 0, sizeof parm);
876
1239
app = current_app? current_app : open_card ();
878
1241
return gpg_error (GPG_ERR_CARD);
880
/* Check that the card's serialnumber is as required.*/
881
rc = check_card_serialno (app, serialno);
886
rc = app->fnc.decipher (app, serialno,
1243
if (app->assuan_ctx)
1245
char *p, line[ASSUAN_LINELENGTH];
1250
if (indatalen*2 + 50 > DIM(line))
1251
return gpg_error (GPG_ERR_GENERAL);
1253
p = stpcpy (line, "SCD SETDATA ");
1254
for (i=0; i < indatalen ; i++, p += 2 )
1255
sprintf (p, "%02X", indata[i]);
1256
rc = test_transact (assuan_transact (app->assuan_ctx, line,
1257
NULL, NULL, NULL, NULL, NULL, NULL),
1261
init_membuf (&data, 1024);
1262
snprintf (line, DIM(line)-1, "SCD PKDECRYPT %s", serialno);
1263
line[DIM(line)-1] = 0;
1264
rc = test_transact (assuan_transact (app->assuan_ctx, line,
1265
membuf_data_cb, &data,
1266
NULL, NULL, NULL, NULL),
1269
xfree (get_membuf (&data, &len));
1271
*r_buf = get_membuf (&data, r_buflen);
1276
/* Check that the card's serialnumber is as required.*/
1277
rc = check_card_serialno (app, serialno);
1282
rc = app->fnc.decipher (app, serialno,
891
write_status (STATUS_SC_OP_FAILURE);
1290
write_status (STATUS_SC_OP_FAILURE);
1291
if (!app->assuan_ctx)
1292
agent_clear_pin_cache (serialno);
909
1310
return gpg_error (GPG_ERR_CARD);
911
sprintf (chvnostr, "%d", chvno);
912
rc = app->fnc.change_pin (app, NULL, chvnostr, reset,
1312
if (app->assuan_ctx)
1314
char line[ASSUAN_LINELENGTH];
1316
snprintf (line, DIM(line)-1, "SCD PASSWD%s %d",
1317
reset? " --reset":"", chvno);
1318
line[DIM(line)-1] = 0;
1319
rc = test_transact (assuan_transact (app->assuan_ctx, line,
1320
NULL, NULL, NULL, NULL, NULL, NULL),
1327
sprintf (chvnostr, "%d", chvno);
1328
rc = app->fnc.change_pin (app, NULL, chvnostr, reset,
915
1333
write_status (STATUS_SC_OP_FAILURE);
923
1341
agent_scd_checkpin (const char *serialnobuf)
928
1346
app = current_app? current_app : open_card ();
930
1348
return gpg_error (GPG_ERR_CARD);
932
rc = app->fnc.check_pin (app, serialnobuf, pin_cb, NULL);
1350
if (app->assuan_ctx)
1352
char line[ASSUAN_LINELENGTH];
1354
if (15 + strlen (serialnobuf) > DIM(line)-1)
1355
return gpg_error (GPG_ERR_CARD);
1356
stpcpy (stpcpy (line, "SCD CHECKPIN "), serialnobuf);
1357
rc = test_transact (assuan_transact (app->assuan_ctx, line,
1358
NULL, NULL, NULL, NULL, NULL, NULL),
1363
rc = app->fnc.check_pin (app, serialnobuf, pin_cb, NULL);
934
1367
write_status (STATUS_SC_OP_FAILURE);
939
/* Wrapper to call the store key helper function of app-openpgp.c. */
941
agent_openpgp_storekey (int keyno,
942
unsigned char *template, size_t template_len,
944
const unsigned char *m, size_t mlen,
945
const unsigned char *e, size_t elen)
1374
agent_clear_pin_cache (const char *sn)
950
app = current_app? current_app : open_card ();
952
return gpg_error (GPG_ERR_CARD);
954
rc = app_openpgp_storekey (app, keyno, template, template_len,
955
created_at, m, mlen, e, elen,
958
write_status (STATUS_SC_OP_FAILURE);
1376
char *cacheid = format_cacheid (sn);
1379
passphrase_clear_cache (NULL, cacheid, 0);