aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--scd/iso7816.c61
-rw-r--r--scd/iso7816.h3
2 files changed, 64 insertions, 0 deletions
diff --git a/scd/iso7816.c b/scd/iso7816.c
index dcb2845c7..1d654eb71 100644
--- a/scd/iso7816.c
+++ b/scd/iso7816.c
@@ -628,6 +628,67 @@ iso7816_decipher (int slot, int extended_mode,
}
+/* Perform the security operation COMPUTE SHARED SECRET. On success 0
+ is returned and the shared secret is available in a newly allocated
+ buffer stored at RESULT with its length stored at RESULTLEN. For
+ LE see do_generate_keypair. */
+gpg_error_t
+iso7816_pso_csv (int slot, int extended_mode,
+ const unsigned char *data, size_t datalen, int le,
+ unsigned char **result, size_t *resultlen)
+{
+ int sw;
+ unsigned char *buf;
+ unsigned int nbuf;
+
+ if (!data || !datalen || !result || !resultlen)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ *result = NULL;
+ *resultlen = 0;
+
+ if (!extended_mode)
+ le = 256; /* Ignore provided Le and use what apdu_send uses. */
+ else if (le >= 0 && le < 256)
+ le = 256;
+
+ /* Data needs to be in BER-TLV format. */
+ buf = xtrymalloc (datalen + 4);
+ if (!buf)
+ return gpg_error_from_syserror ();
+ nbuf = 0;
+ buf[nbuf++] = 0x9c;
+ if (datalen < 128)
+ buf[nbuf++] = datalen;
+ else if (datalen < 256)
+ {
+ buf[nbuf++] = 0x81;
+ buf[nbuf++] = datalen;
+ }
+ else
+ {
+ buf[nbuf++] = 0x82;
+ buf[nbuf++] = datalen << 8;
+ buf[nbuf++] = datalen;
+ }
+ memcpy (buf+nbuf, data, datalen);
+ sw = apdu_send_le (slot, extended_mode,
+ 0x00, CMD_PSO, 0x80, 0xa6,
+ datalen+nbuf, (const char *)buf, le,
+ result, resultlen);
+ xfree (buf);
+ if (sw != SW_SUCCESS)
+ {
+ /* Make sure that pending buffers are released. */
+ xfree (*result);
+ *result = NULL;
+ *resultlen = 0;
+ return map_sw (sw);
+ }
+
+ return 0;
+}
+
+
/* For LE see do_generate_keypair. */
gpg_error_t
iso7816_internal_authenticate (int slot, int extended_mode,
diff --git a/scd/iso7816.h b/scd/iso7816.h
index f7934bb5b..d22f0bec5 100644
--- a/scd/iso7816.h
+++ b/scd/iso7816.h
@@ -110,6 +110,9 @@ gpg_error_t iso7816_decipher (int slot, int extended_mode,
const unsigned char *data, size_t datalen,
int le, int padind,
unsigned char **result, size_t *resultlen);
+gpg_error_t iso7816_pso_csv (int slot, int extended_mode,
+ const unsigned char *data, size_t datalen, int le,
+ unsigned char **result, size_t *resultlen);
gpg_error_t iso7816_internal_authenticate (int slot, int extended_mode,
const unsigned char *data, size_t datalen,
int le,