📄 iso7816-2.c
字号:
} return 0;}/* Perform a PUT DATA command on card in SLOT. Write DATA of length DATALEN to TAG. */gpg_error_tiso7816_put_data (int slot, int tag, const unsigned char *data, size_t datalen){ int sw; sw = apdu_send_simple (slot, 0x00, CMD_PUT_DATA, ((tag >> 8) & 0xff), (tag & 0xff), datalen, (const char*)data); return map_sw (sw);}/* Manage Security Environment. This is a weird operation and there is no easy abstraction for it. Furthermore, some card seem to have a different interpreation of 7816-8 and thus we resort to let the caller decide what to do. */gpg_error_tiso7816_manage_security_env (int slot, int p1, int p2, const unsigned char *data, size_t datalen){ int sw; if (p1 < 0 || p1 > 255 || p2 < 0 || p2 > 255 ) return gpg_error (GPG_ERR_INV_VALUE); sw = apdu_send_simple (slot, 0x00, CMD_MSE, p1, p2, data? datalen : -1, (const char*)data); return map_sw (sw);}/* Perform the security operation COMPUTE DIGITAL SIGANTURE. On success 0 is returned and the data is availavle in a newly allocated buffer stored at RESULT with its length stored at RESULTLEN. */gpg_error_tiso7816_compute_ds (int slot, const unsigned char *data, size_t datalen, unsigned char **result, size_t *resultlen){ int sw; if (!data || !datalen || !result || !resultlen) return gpg_error (GPG_ERR_INV_VALUE); *result = NULL; *resultlen = 0; sw = apdu_send (slot, 0x00, CMD_PSO, 0x9E, 0x9A, datalen, (const char*)data, result, resultlen); if (sw != SW_SUCCESS) { /* Make sure that pending buffers are released. */ xfree (*result); *result = NULL; *resultlen = 0; return map_sw (sw); } return 0;}/* Perform the security operation DECIPHER. PADIND is the padding indicator to be used. It should be 0 if no padding is required, a value of -1 suppresses the padding byte. On success 0 is returned and the plaintext is available in a newly allocated buffer stored at RESULT with its length stored at RESULTLEN. */gpg_error_tiso7816_decipher (int slot, const unsigned char *data, size_t datalen, int padind, unsigned char **result, size_t *resultlen){ int sw; unsigned char *buf; if (!data || !datalen || !result || !resultlen) return gpg_error (GPG_ERR_INV_VALUE); *result = NULL; *resultlen = 0; if (padind >= 0) { /* We need to prepend the padding indicator. */ buf = xtrymalloc (datalen + 1); if (!buf) return gpg_error (gpg_err_code_from_errno (errno)); *buf = padind; /* Padding indicator. */ memcpy (buf+1, data, datalen); sw = apdu_send (slot, 0x00, CMD_PSO, 0x80, 0x86, datalen+1, (char*)buf, result, resultlen); xfree (buf); } else { sw = apdu_send (slot, 0x00, CMD_PSO, 0x80, 0x86, datalen, (const char *)data, result, resultlen); } if (sw != SW_SUCCESS) { /* Make sure that pending buffers are released. */ xfree (*result); *result = NULL; *resultlen = 0; return map_sw (sw); } return 0;}gpg_error_tiso7816_internal_authenticate (int slot, const unsigned char *data, size_t datalen, unsigned char **result, size_t *resultlen){ int sw; if (!data || !datalen || !result || !resultlen) return gpg_error (GPG_ERR_INV_VALUE); *result = NULL; *resultlen = 0; sw = apdu_send (slot, 0x00, CMD_INTERNAL_AUTHENTICATE, 0, 0, datalen, (const char*)data, result, resultlen); if (sw != SW_SUCCESS) { /* Make sure that pending buffers are released. */ xfree (*result); *result = NULL; *resultlen = 0; return map_sw (sw); } return 0;}static gpg_error_tdo_generate_keypair (int slot, int readonly, const unsigned char *data, size_t datalen, unsigned char **result, size_t *resultlen){ int sw; if (!data || !datalen || !result || !resultlen) return gpg_error (GPG_ERR_INV_VALUE); *result = NULL; *resultlen = 0; sw = apdu_send (slot, 0x00, CMD_GENERATE_KEYPAIR, readonly? 0x81:0x80, 0, datalen, (const char*)data, result, resultlen); if (sw != SW_SUCCESS) { /* Make sure that pending buffers are released. */ xfree (*result); *result = NULL; *resultlen = 0; return map_sw (sw); } return 0;}gpg_error_tiso7816_generate_keypair (int slot, const unsigned char *data, size_t datalen, unsigned char **result, size_t *resultlen){ return do_generate_keypair (slot, 0, data, datalen, result, resultlen);}gpg_error_tiso7816_read_public_key (int slot, const unsigned char *data, size_t datalen, unsigned char **result, size_t *resultlen){ return do_generate_keypair (slot, 1, data, datalen, result, resultlen);}gpg_error_tiso7816_get_challenge (int slot, int length, unsigned char *buffer){ int sw; unsigned char *result; size_t resultlen, n; if (!buffer || length < 1) return gpg_error (GPG_ERR_INV_VALUE); do { result = NULL; n = length > 254? 254 : length; sw = apdu_send_le (slot, 0x00, CMD_GET_CHALLENGE, 0, 0, -1, NULL, n, &result, &resultlen); if (sw != SW_SUCCESS) { /* Make sure that pending buffers are released. */ xfree (result); return map_sw (sw); } if (resultlen > n) resultlen = n; memcpy (buffer, result, resultlen); buffer += resultlen; length -= resultlen; xfree (result); } while (length > 0); return 0;}/* Perform a READ BINARY command requesting a maximum of NMAX bytes from OFFSET. With NMAX = 0 the entire file is read. The result is stored in a newly allocated buffer at the address passed by RESULT. Returns the length of this data at the address of RESULTLEN. */gpg_error_tiso7816_read_binary (int slot, size_t offset, size_t nmax, unsigned char **result, size_t *resultlen){ int sw; unsigned char *buffer; size_t bufferlen; int read_all = !nmax; size_t n; if (!result || !resultlen) return gpg_error (GPG_ERR_INV_VALUE); *result = NULL; *resultlen = 0; /* We can only encode 15 bits in p0,p1 to indicate an offset. Thus we check for this limit. */ if (offset > 32767) return gpg_error (GPG_ERR_INV_VALUE); do { buffer = NULL; bufferlen = 0; /* Note, that we to set N to 254 due to problems either with the ccid driver or some TCOS cards. It actually should be 0 which is the official ISO value to read a variable length object. */ if (read_all || nmax > 254) n = 254; else n = nmax; sw = apdu_send_le (slot, 0x00, CMD_READ_BINARY, ((offset>>8) & 0xff), (offset & 0xff) , -1, NULL, n, &buffer, &bufferlen); if ( SW_EXACT_LENGTH_P(sw) ) { n = (sw & 0x00ff); sw = apdu_send_le (slot, 0x00, CMD_READ_BINARY, ((offset>>8) & 0xff), (offset & 0xff) , -1, NULL, n, &buffer, &bufferlen); } if (*result && sw == SW_BAD_P0_P1) { /* Bad Parameter means that the offset is outside of the EF. When reading all data we take this as an indication for EOF. */ break; } if (sw != SW_SUCCESS && sw != SW_EOF_REACHED) { /* Make sure that pending buffers are released. */ xfree (buffer); xfree (*result); *result = NULL; *resultlen = 0; return map_sw (sw); } if (*result) /* Need to extend the buffer. */ { unsigned char *p = xtryrealloc (*result, *resultlen + bufferlen); if (!p) { gpg_error_t err = gpg_error_from_syserror (); xfree (buffer); xfree (*result); *result = NULL; *resultlen = 0; return err; } *result = p; memcpy (*result + *resultlen, buffer, bufferlen); *resultlen += bufferlen; xfree (buffer); buffer = NULL; } else /* Transfer the buffer into our result. */ { *result = buffer; *resultlen = bufferlen; } offset += bufferlen; if (offset > 32767) break; /* We simply truncate the result for too large files. */ if (nmax > bufferlen) nmax -= bufferlen; else nmax = 0; } while ((read_all && sw != SW_EOF_REACHED) || (!read_all && nmax)); return 0;}/* Perform a READ RECORD command. RECNO gives the record number to read with 0 indicating the current record. RECCOUNT must be 1 (not all cards support reading of more than one record). SHORT_EF should be 0 to read the current EF or contain a short EF. The result is stored in a newly allocated buffer at the address passed by RESULT. Returns the length of this data at the address of RESULTLEN. */gpg_error_tiso7816_read_record (int slot, int recno, int reccount, int short_ef, unsigned char **result, size_t *resultlen){ int sw; unsigned char *buffer; size_t bufferlen; if (!result || !resultlen) return gpg_error (GPG_ERR_INV_VALUE); *result = NULL; *resultlen = 0; /* We can only encode 15 bits in p0,p1 to indicate an offset. Thus we check for this limit. */ if (recno < 0 || recno > 255 || reccount != 1 || short_ef < 0 || short_ef > 254 ) return gpg_error (GPG_ERR_INV_VALUE); buffer = NULL; bufferlen = 0; /* Fixme: Either the ccid driver or the TCOS cards have problems with an Le of 0. */ sw = apdu_send_le (slot, 0x00, CMD_READ_RECORD, recno, short_ef? short_ef : 0x04, -1, NULL, 254, &buffer, &bufferlen); if (sw != SW_SUCCESS && sw != SW_EOF_REACHED) { /* Make sure that pending buffers are released. */ xfree (buffer); xfree (*result); *result = NULL; *resultlen = 0; return map_sw (sw); } *result = buffer; *resultlen = bufferlen; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -