opensc/src/libopensc/sc.c

831 lines
19 KiB
C
Raw Normal View History

/*
* sc.c: General functions
*
* Copyright (C) 2001, 2002 Juha Yrjölä <juha.yrjola@iki.fi>
*
* 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
*/
#include "config.h"
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#ifdef ENABLE_OPENSSL
#include <openssl/crypto.h> /* for OPENSSL_cleanse */
#endif
#include "internal.h"
#ifdef PACKAGE_VERSION
static const char *sc_version = PACKAGE_VERSION;
#else
static const char *sc_version = "(undef)";
#endif
const char *sc_get_version(void)
{
return sc_version;
}
int sc_hex_to_bin(const char *in, u8 *out, size_t *outlen)
{
int err = 0;
size_t left, count = 0;
assert(in != NULL && out != NULL && outlen != NULL);
left = *outlen;
while (*in != '\0') {
int byte = 0, nybbles = 2;
while (nybbles-- && *in && *in != ':' && *in != ' ') {
char c;
byte <<= 4;
c = *in++;
if ('0' <= c && c <= '9')
c -= '0';
else
if ('a' <= c && c <= 'f')
c = c - 'a' + 10;
else
if ('A' <= c && c <= 'F')
c = c - 'A' + 10;
else {
err = SC_ERROR_INVALID_ARGUMENTS;
goto out;
}
byte |= c;
}
if (*in == ':' || *in == ' ')
in++;
if (left <= 0) {
err = SC_ERROR_BUFFER_TOO_SMALL;
break;
}
out[count++] = (u8) byte;
left--;
}
out:
*outlen = count;
return err;
}
int sc_bin_to_hex(const u8 *in, size_t in_len, char *out, size_t out_len,
int in_sep)
{
unsigned int n, sep_len;
char *pos, *end, sep;
sep = (char)in_sep;
sep_len = sep > 0 ? 1 : 0;
pos = out;
end = out + out_len;
for (n = 0; n < in_len; n++) {
if (pos + 3 + sep_len >= end)
return SC_ERROR_BUFFER_TOO_SMALL;
if (n && sep_len)
*pos++ = sep;
sprintf(pos, "%02x", in[n]);
pos += 2;
}
*pos = '\0';
return 0;
}
void ulong2bebytes(u8 *buf, unsigned long x)
{
buf[3] = (u8) (x & 0xff);
buf[2] = (u8) ((x >> 8) & 0xff);
buf[1] = (u8) ((x >> 16) & 0xff);
buf[0] = (u8) ((x >> 24) & 0xff);
}
void ushort2bebytes(u8 *buf, unsigned short x)
{
buf[1] = (u8) (x & 0xff);
buf[0] = (u8) ((x >> 8) & 0xff);
}
unsigned long bebytes2ulong(const u8 *buf)
{
return (unsigned long) (buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]);
}
unsigned short bebytes2ushort(const u8 *buf)
{
return (unsigned short) (buf[0] << 8 | buf[1]);
}
int sc_format_oid(struct sc_object_id *oid, const char *in)
{
int ii;
const char *p;
char *q;
if (oid == NULL || in == NULL)
return SC_ERROR_INVALID_ARGUMENTS;
/* init oid */
for (ii=0; ii<SC_MAX_OBJECT_ID_OCTETS; ii++)
oid->value[ii] = -1;
p = in;
for (ii=0; ii < SC_MAX_OBJECT_ID_OCTETS; ii++) {
oid->value[ii] = strtol(p, &q, 10);
if (!*q)
break;
if (!(q[0] == '.' && isdigit(q[1]))) {
return SC_ERROR_INVALID_ARGUMENTS;
}
p = q + 1;
}
if (ii == 1)
/* reject too short OIDs */
return SC_ERROR_INVALID_ARGUMENTS;
return SC_SUCCESS;
}
int sc_compare_oid(const struct sc_object_id *oid1, const struct sc_object_id *oid2)
{
int i;
assert(oid1 != NULL && oid2 != NULL);
for (i = 0; i < SC_MAX_OBJECT_ID_OCTETS; i++) {
if (oid1->value[i] != oid2->value[i])
return 0;
if (oid1->value[i] < 0)
return 1;
}
return 1;
}
int sc_detect_card_presence(sc_reader_t *reader)
{
int r;
SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_VERBOSE);
if (reader->ops->detect_card_presence == NULL)
SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NOT_SUPPORTED);
r = reader->ops->detect_card_presence(reader);
SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_NORMAL, r);
}
int sc_path_set(sc_path_t *path, int type, const u8 *id, size_t id_len,
int idx, int count)
{
if (path == NULL || id == NULL || id_len == 0 || id_len > SC_MAX_PATH_SIZE)
return SC_ERROR_INVALID_ARGUMENTS;
memset(path, 0, sizeof(*path));
memcpy(path->value, id, id_len);
path->len = id_len;
path->type = type;
path->index = idx;
path->count = count;
return SC_SUCCESS;
}
void sc_format_path(const char *str, sc_path_t *path)
{
int type = SC_PATH_TYPE_PATH;
memset(path, 0, sizeof(*path));
if (*str == 'i' || *str == 'I') {
type = SC_PATH_TYPE_FILE_ID;
str++;
}
path->len = sizeof(path->value);
if (sc_hex_to_bin(str, path->value, &path->len) >= 0) {
path->type = type;
}
path->count = -1;
return;
}
int sc_append_path(sc_path_t *dest, const sc_path_t *src)
{
return sc_concatenate_path(dest, dest, src);
}
int sc_append_path_id(sc_path_t *dest, const u8 *id, size_t idlen)
{
if (dest->len + idlen > SC_MAX_PATH_SIZE)
return SC_ERROR_INVALID_ARGUMENTS;
memcpy(dest->value + dest->len, id, idlen);
dest->len += idlen;
return 0;
}
int sc_append_file_id(sc_path_t *dest, unsigned int fid)
{
u8 id[2] = { fid >> 8, fid & 0xff };
return sc_append_path_id(dest, id, 2);
}
int sc_concatenate_path(sc_path_t *d, const sc_path_t *p1, const sc_path_t *p2)
{
sc_path_t tpath;
if (d == NULL || p1 == NULL || p2 == NULL)
return SC_ERROR_INVALID_ARGUMENTS;
if (p1->type == SC_PATH_TYPE_DF_NAME || p2->type == SC_PATH_TYPE_DF_NAME)
/* we do not support concatenation of AIDs at the moment */
return SC_ERROR_NOT_SUPPORTED;
if (p1->len + p2->len > SC_MAX_PATH_SIZE)
return SC_ERROR_INVALID_ARGUMENTS;
memset(&tpath, 0, sizeof(sc_path_t));
memcpy(tpath.value, p1->value, p1->len);
memcpy(tpath.value + p1->len, p2->value, p2->len);
tpath.len = p1->len + p2->len;
tpath.type = SC_PATH_TYPE_PATH;
/* use 'index' and 'count' entry of the second path object */
tpath.index = p2->index;
tpath.count = p2->count;
/* the result is currently always as path */
tpath.type = SC_PATH_TYPE_PATH;
*d = tpath;
return SC_SUCCESS;
}
const char *sc_print_path(const sc_path_t *path)
{
static char buffer[SC_MAX_PATH_STRING_SIZE + SC_MAX_AID_STRING_SIZE];
if (sc_path_print(buffer, sizeof(buffer), path) != SC_SUCCESS)
buffer[0] = '\0';
return buffer;
}
int sc_path_print(char *buf, size_t buflen, const sc_path_t *path)
{
size_t i;
if (buf == NULL || path == NULL)
return SC_ERROR_INVALID_ARGUMENTS;
if (buflen < path->len * 2 + path->aid.len * 2 + 1)
return SC_ERROR_BUFFER_TOO_SMALL;
buf[0] = '\0';
if (path->aid.len) {
for (i = 0; i < path->aid.len; i++)
snprintf(buf + strlen(buf), buflen - strlen(buf), "%02x", path->aid.value[i]);
snprintf(buf + strlen(buf), buflen - strlen(buf), "::");
}
for (i = 0; i < path->len; i++)
snprintf(buf + strlen(buf), buflen - strlen(buf), "%02x", path->value[i]);
if (!path->aid.len && path->type == SC_PATH_TYPE_DF_NAME)
snprintf(buf + strlen(buf), buflen - strlen(buf), "::");
return SC_SUCCESS;
}
int sc_compare_path(const sc_path_t *path1, const sc_path_t *path2)
{
return path1->len == path2->len
&& !memcmp(path1->value, path2->value, path1->len);
}
int sc_compare_path_prefix(const sc_path_t *prefix, const sc_path_t *path)
{
sc_path_t tpath;
if (prefix->len > path->len)
return 0;
tpath = *path;
tpath.len = prefix->len;
return sc_compare_path(&tpath, prefix);
}
const sc_path_t *sc_get_mf_path(void)
{
static const sc_path_t mf_path = {
{0x3f, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2,
0,
0,
SC_PATH_TYPE_PATH,
{{0},0}
};
return &mf_path;
}
int sc_file_add_acl_entry(sc_file_t *file, unsigned int operation,
unsigned int method, unsigned long key_ref)
{
sc_acl_entry_t *p, *_new;
assert(file != NULL);
assert(operation < SC_MAX_AC_OPS);
switch (method) {
case SC_AC_NEVER:
sc_file_clear_acl_entries(file, operation);
file->acl[operation] = (sc_acl_entry_t *) 1;
return 0;
case SC_AC_NONE:
sc_file_clear_acl_entries(file, operation);
file->acl[operation] = (sc_acl_entry_t *) 2;
return 0;
case SC_AC_UNKNOWN:
sc_file_clear_acl_entries(file, operation);
file->acl[operation] = (sc_acl_entry_t *) 3;
return 0;
default:
/* NONE and UNKNOWN get zapped when a new AC is added.
* If the ACL is NEVER, additional entries will be
* dropped silently. */
if (file->acl[operation] == (sc_acl_entry_t *) 1)
return 0;
if (file->acl[operation] == (sc_acl_entry_t *) 2
|| file->acl[operation] == (sc_acl_entry_t *) 3)
file->acl[operation] = NULL;
}
/* If the entry is already present (e.g. due to the mapping)
* of the card's AC with OpenSC's), don't add it again. */
for (p = file->acl[operation]; p != NULL; p = p->next) {
if ((p->method == method) && (p->key_ref == key_ref))
return 0;
}
Do not cast the return value of malloc(3) and calloc(3) From http://en.wikipedia.org/wiki/Malloc#Casting_and_type_safety " Casting and type safety malloc returns a void pointer (void *), which indicates that it is a pointer to a region of unknown data type. One may "cast" (see type conversion) this pointer to a specific type, as in int *ptr = (int*)malloc(10 * sizeof (int)); When using C, this is considered bad practice; it is redundant under the C standard. Moreover, putting in a cast may mask failure to include the header stdlib.h, in which the prototype for malloc is found. In the absence of a prototype for malloc, the C compiler will assume that malloc returns an int, and will issue a warning in a context such as the above, provided the error is not masked by a cast. On certain architectures and data models (such as LP64 on 64 bit systems, where long and pointers are 64 bit and int is 32 bit), this error can actually result in undefined behavior, as the implicitly declared malloc returns a 32 bit value whereas the actually defined function returns a 64 bit value. Depending on calling conventions and memory layout, this may result in stack smashing. The returned pointer need not be explicitly cast to a more specific pointer type, since ANSI C defines an implicit conversion between the void pointer type and other pointers to objects. An explicit cast of malloc's return value is sometimes performed because malloc originally returned a char *, but this cast is unnecessary in standard C code.[4][5] Omitting the cast, however, creates an incompatibility with C++, which does require it. The lack of a specific pointer type returned from malloc is type-unsafe behaviour: malloc allocates based on byte count but not on type. This distinguishes it from the C++ new operator that returns a pointer whose type relies on the operand. (see C Type Safety). " See also http://www.opensc-project.org/pipermail/opensc-devel/2010-August/014586.html git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@4636 c6295689-39f2-0310-b995-f0e70906c6a9
2010-08-18 15:08:51 +00:00
_new = malloc(sizeof(sc_acl_entry_t));
if (_new == NULL)
return SC_ERROR_OUT_OF_MEMORY;
_new->method = method;
_new->key_ref = key_ref;
_new->next = NULL;
p = file->acl[operation];
if (p == NULL) {
file->acl[operation] = _new;
return 0;
}
while (p->next != NULL)
p = p->next;
p->next = _new;
return 0;
}
const sc_acl_entry_t * sc_file_get_acl_entry(const sc_file_t *file,
unsigned int operation)
{
sc_acl_entry_t *p;
static const sc_acl_entry_t e_never = {
SC_AC_NEVER, SC_AC_KEY_REF_NONE, {{0, 0, 0, {0}}}, NULL
};
static const sc_acl_entry_t e_none = {
SC_AC_NONE, SC_AC_KEY_REF_NONE, {{0, 0, 0, {0}}}, NULL
};
static const sc_acl_entry_t e_unknown = {
SC_AC_UNKNOWN, SC_AC_KEY_REF_NONE, {{0, 0, 0, {0}}}, NULL
};
assert(file != NULL);
assert(operation < SC_MAX_AC_OPS);
p = file->acl[operation];
if (p == (sc_acl_entry_t *) 1)
return &e_never;
if (p == (sc_acl_entry_t *) 2)
return &e_none;
if (p == (sc_acl_entry_t *) 3)
return &e_unknown;
return file->acl[operation];
}
void sc_file_clear_acl_entries(sc_file_t *file, unsigned int operation)
{
sc_acl_entry_t *e;
assert(file != NULL);
assert(operation < SC_MAX_AC_OPS);
e = file->acl[operation];
if (e == (sc_acl_entry_t *) 1 ||
e == (sc_acl_entry_t *) 2 ||
e == (sc_acl_entry_t *) 3) {
file->acl[operation] = NULL;
return;
}
while (e != NULL) {
sc_acl_entry_t *tmp = e->next;
free(e);
e = tmp;
}
file->acl[operation] = NULL;
}
sc_file_t * sc_file_new(void)
{
sc_file_t *file = (sc_file_t *)calloc(1, sizeof(sc_file_t));
if (file == NULL)
return NULL;
file->magic = SC_FILE_MAGIC;
return file;
}
void sc_file_free(sc_file_t *file)
{
unsigned int i;
assert(sc_file_valid(file));
file->magic = 0;
for (i = 0; i < SC_MAX_AC_OPS; i++)
sc_file_clear_acl_entries(file, i);
if (file->sec_attr)
free(file->sec_attr);
if (file->prop_attr)
free(file->prop_attr);
if (file->type_attr)
free(file->type_attr);
free(file);
}
void sc_file_dup(sc_file_t **dest, const sc_file_t *src)
{
sc_file_t *newf;
const sc_acl_entry_t *e;
unsigned int op;
assert(sc_file_valid(src));
*dest = NULL;
newf = sc_file_new();
if (newf == NULL)
return;
*dest = newf;
memcpy(&newf->path, &src->path, sizeof(struct sc_path));
memcpy(&newf->name, &src->name, sizeof(src->name));
newf->namelen = src->namelen;
newf->type = src->type;
newf->shareable = src->shareable;
newf->ef_structure = src->ef_structure;
newf->size = src->size;
newf->id = src->id;
newf->status = src->status;
for (op = 0; op < SC_MAX_AC_OPS; op++) {
newf->acl[op] = NULL;
e = sc_file_get_acl_entry(src, op);
if (e != NULL) {
if (sc_file_add_acl_entry(newf, op, e->method, e->key_ref) < 0)
goto err;
}
}
newf->record_length = src->record_length;
newf->record_count = src->record_count;
if (sc_file_set_sec_attr(newf, src->sec_attr, src->sec_attr_len) < 0)
goto err;
if (sc_file_set_prop_attr(newf, src->prop_attr, src->prop_attr_len) < 0)
goto err;
if (sc_file_set_type_attr(newf, src->type_attr, src->type_attr_len) < 0)
goto err;
return;
err:
if (newf != NULL)
sc_file_free(newf);
*dest = NULL;
}
int sc_file_set_sec_attr(sc_file_t *file, const u8 *sec_attr,
size_t sec_attr_len)
{
u8 *tmp;
assert(sc_file_valid(file));
if (sec_attr == NULL) {
if (file->sec_attr != NULL)
free(file->sec_attr);
file->sec_attr = NULL;
file->sec_attr_len = 0;
return 0;
}
tmp = (u8 *) realloc(file->sec_attr, sec_attr_len);
if (!tmp) {
if (file->sec_attr)
free(file->sec_attr);
file->sec_attr = NULL;
file->sec_attr_len = 0;
return SC_ERROR_OUT_OF_MEMORY;
}
file->sec_attr = tmp;
memcpy(file->sec_attr, sec_attr, sec_attr_len);
file->sec_attr_len = sec_attr_len;
return 0;
}
int sc_file_set_prop_attr(sc_file_t *file, const u8 *prop_attr,
size_t prop_attr_len)
{
u8 *tmp;
assert(sc_file_valid(file));
if (prop_attr == NULL) {
if (file->prop_attr != NULL)
free(file->prop_attr);
file->prop_attr = NULL;
file->prop_attr_len = 0;
return 0;
}
tmp = (u8 *) realloc(file->prop_attr, prop_attr_len);
if (!tmp) {
if (file->prop_attr)
free(file->prop_attr);
file->prop_attr = NULL;
file->prop_attr_len = 0;
return SC_ERROR_OUT_OF_MEMORY;
}
file->prop_attr = tmp;
memcpy(file->prop_attr, prop_attr, prop_attr_len);
file->prop_attr_len = prop_attr_len;
return 0;
}
int sc_file_set_type_attr(sc_file_t *file, const u8 *type_attr,
size_t type_attr_len)
{
u8 *tmp;
assert(sc_file_valid(file));
if (type_attr == NULL) {
if (file->type_attr != NULL)
free(file->type_attr);
file->type_attr = NULL;
file->type_attr_len = 0;
return 0;
}
tmp = (u8 *) realloc(file->type_attr, type_attr_len);
if (!tmp) {
if (file->type_attr)
free(file->type_attr);
file->type_attr = NULL;
file->type_attr_len = 0;
return SC_ERROR_OUT_OF_MEMORY;
}
file->type_attr = tmp;
memcpy(file->type_attr, type_attr, type_attr_len);
file->type_attr_len = type_attr_len;
return 0;
}
int sc_file_valid(const sc_file_t *file) {
#ifndef NDEBUG
assert(file != NULL);
#endif
return file->magic == SC_FILE_MAGIC;
}
int _sc_parse_atr(sc_reader_t *reader)
{
u8 *p = reader->atr.value;
int atr_len = (int) reader->atr.len;
int n_hist, x;
int tx[4] = {-1, -1, -1, -1};
int i, FI, DI;
const int Fi_table[] = {
372, 372, 558, 744, 1116, 1488, 1860, -1,
-1, 512, 768, 1024, 1536, 2048, -1, -1 };
const int f_table[] = {
40, 50, 60, 80, 120, 160, 200, -1,
-1, 50, 75, 100, 150, 200, -1, -1 };
const int Di_table[] = {
-1, 1, 2, 4, 8, 16, 32, -1,
12, 20, -1, -1, -1, -1, -1, -1 };
reader->atr_info.hist_bytes_len = 0;
reader->atr_info.hist_bytes = NULL;
if (atr_len == 0) {
sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "empty ATR - card not present?\n");
return SC_ERROR_INTERNAL;
}
if (p[0] != 0x3B && p[0] != 0x3F) {
sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "invalid sync byte in ATR: 0x%02X\n", p[0]);
return SC_ERROR_INTERNAL;
}
n_hist = p[1] & 0x0F;
x = p[1] >> 4;
p += 2;
atr_len -= 2;
for (i = 0; i < 4 && atr_len > 0; i++) {
if (x & (1 << i)) {
tx[i] = *p;
p++;
atr_len--;
} else
tx[i] = -1;
}
if (tx[0] >= 0) {
reader->atr_info.FI = FI = tx[0] >> 4;
reader->atr_info.DI = DI = tx[0] & 0x0F;
reader->atr_info.Fi = Fi_table[FI];
reader->atr_info.f = f_table[FI];
reader->atr_info.Di = Di_table[DI];
} else {
reader->atr_info.Fi = -1;
reader->atr_info.f = -1;
reader->atr_info.Di = -1;
}
if (tx[2] >= 0)
reader->atr_info.N = tx[3];
else
reader->atr_info.N = -1;
while (tx[3] > 0 && tx[3] & 0xF0 && atr_len > 0) {
x = tx[3] >> 4;
for (i = 0; i < 4 && atr_len > 0; i++) {
if (x & (1 << i)) {
tx[i] = *p;
p++;
atr_len--;
} else
tx[i] = -1;
}
}
if (atr_len <= 0)
return 0;
if (n_hist > atr_len)
n_hist = atr_len;
reader->atr_info.hist_bytes_len = n_hist;
reader->atr_info.hist_bytes = p;
return 0;
}
void *sc_mem_alloc_secure(size_t len)
{
void *pointer;
pointer = calloc(len, sizeof(unsigned char));
if (!pointer)
return NULL;
#ifdef HAVE_SYS_MMAN_H
/* TODO Windows support and mprotect too */
/* Do not swap the memory */
if (mlock(pointer, len) == -1) {
free(pointer);
return NULL;
}
#endif
return pointer;
}
void sc_mem_clear(void *ptr, size_t len)
{
Complete rewrite of OpenSC build system. 1. Build system now supports MinGW (Windows) compilation using msys and cross compilation. 2. Ability to explicitly disable and enable dependencies of the package. 3. openct, pcsc and nsplugins features are disabled by default. 4. Modified pcsc driver to use pcsc dynamically, no compile time dependency is required. 5. --enable-pcsc-lite configuration option renamed to --enable-pcsc. 6. Install opensc.conf file (as opensc.conf.new if opensc.conf exists). 7. Add--enable-doc configuration option, allow installing documentation into target. 8. Add --disable-man configuration option, allow msys mingw32 users to build from svn without extra dependencies. 9. Add export files to each library in order to export only required symbols. Windows native build may use these files instead of scanning objects' symbols. 10. Add opensc-tool --info to display some general information about the build. 11. Create compatibility library to be linked against library instread of recompiling the same source files in different places. 12. Add different win32 version resource to each class of outputs. 13. Make xsl-stylesheets location selectable. 14. Some win32 fixups. 15. Some warning fixups. 16. Many other autoconf/automake cleanups. Alon Bar-Lev svn diff -r 3315:3399 https://www.opensc-project.org/svn/opensc/branches/alonbl/mingw _M . D configure.in _M src _M src/openssh M src/openssh/Makefile.am _M src/tools M src/tools/rutoken-tool.c M src/tools/opensc-tool.c M src/tools/cardos-info.c M src/tools/pkcs15-crypt.c M src/tools/pkcs15-init.c M src/tools/piv-tool.c M src/tools/netkey-tool.c M src/tools/eidenv.c M src/tools/cryptoflex-tool.c M src/tools/util.c M src/tools/pkcs11-tool.c M src/tools/pkcs15-tool.c M src/tools/util.h M src/tools/opensc-explorer.c M src/tools/Makefile.am _M src/pkcs11 M src/pkcs11/pkcs11-global.c M src/pkcs11/framework-pkcs15.c M src/pkcs11/mechanism.c M src/pkcs11/pkcs11-display.c M src/pkcs11/pkcs11-object.c A src/pkcs11/opensc-pkcs11.exports M src/pkcs11/sc-pkcs11.h M src/pkcs11/pkcs11-spy.c M src/pkcs11/openssl.c M src/pkcs11/Makefile.am A src/pkcs11/pkcs11-spy.exports _M src/tests _M src/tests/regression M src/tests/regression/Makefile.am M src/tests/sc-test.c M src/tests/pintest.c M src/tests/Makefile.am _M src/include _M src/include/opensc M src/include/opensc/Makefile.am A src/include/opensc/svnignore M src/include/Makefile.am _M src/signer _M src/signer/npinclude M src/signer/npinclude/Makefile.am M src/signer/Makefile.am A src/signer/signer.exports _M src/common A src/common/compat_dummy.c D src/common/getopt.txt D src/common/strlcpy.c D src/common/LICENSE A src/common/compat_getopt.txt A src/common/compat_strlcpy.c A src/common/LICENSE.compat_getopt A src/common/compat_getopt.c D src/common/strlcpy.h D src/common/ChangeLog D src/common/getpass.c D src/common/my_getopt.c A src/common/compat_strlcpy.h A src/common/compat_getpass.c A src/common/compat_getopt.h A src/common/ChangeLog.compat_getopt D src/common/README.strlcpy D src/common/my_getopt.h A src/common/compat_getpass.h A src/common/README.compat_strlcpy D src/common/strlcpy.3 A src/common/README.compat_getopt D src/common/getopt.3 D src/common/README.my_getopt A src/common/compat_strlcpy.3 A src/common/compat_getopt.3 M src/common/Makefile.am M src/Makefile.am _M src/pkcs15init M src/pkcs15init/pkcs15-oberthur.c M src/pkcs15init/profile.c M src/pkcs15init/pkcs15-lib.c M src/pkcs15init/pkcs15-rutoken.c A src/pkcs15init/pkcs15init.exports M src/pkcs15init/pkcs15-gpk.c M src/pkcs15init/Makefile.am _M src/scconf M src/scconf/Makefile.am M src/scconf/parse.c A src/scconf/scconf.exports _M src/libopensc M src/libopensc/card-rutoken.c M src/libopensc/compression.c M src/libopensc/sc.c M src/libopensc/card-piv.c M src/libopensc/pkcs15-openpgp.c M src/libopensc/pkcs15-postecert.c M src/libopensc/pkcs15-tcos.c M src/libopensc/opensc-config.in M src/libopensc/reader-pcsc.c A src/libopensc/internal-winscard.h M src/libopensc/ctx.c A src/libopensc/libopensc.exports M src/libopensc/pkcs15-piv.c M src/libopensc/pkcs15-infocamere.c M src/libopensc/internal.h M src/libopensc/pkcs15-actalis.c M src/libopensc/pkcs15-starcert.c M src/libopensc/card-oberthur.c M src/libopensc/pkcs15-atrust-acos.c M src/libopensc/p15card-helper.c D src/libopensc/part10.h M src/libopensc/ui.c M src/libopensc/card-gpk.c M src/libopensc/pkcs15-wrap.c M src/libopensc/pkcs15-gemsafeGPK.c M src/libopensc/log.c M src/libopensc/pkcs15-esteid.c M src/libopensc/pkcs15-prkey-rutoken.c M src/libopensc/log.h M src/libopensc/Makefile.am M src/libopensc/reader-openct.c _M aclocal M aclocal/Makefile.am _M win32 M win32/Makefile.am A win32/versioninfo.rc.in A win32/ltrc.inc A configure.ac _M doc _M doc/tools M doc/tools/pkcs15-profile.xml D doc/changelog.sh D doc/export-wiki.xsl _M doc/api _M doc/api/file M doc/api/man.xsl _M doc/api/asn1 _M doc/api/apps _M doc/api/init _M doc/api/types _M doc/api/card M doc/api/html.xsl _M doc/api/misc _M doc/api/util M doc/Makefile.am D doc/export-wiki.sh AM doc/nonpersistent A doc/nonpersistent/export-wiki.xsl A doc/nonpersistent/Makefile.am A doc/nonpersistent/export-wiki.sh A doc/nonpersistent/svn2cl.xsl D doc/generate-man.sh D doc/svn2cl.xsl M Makefile.am A svnignore _M etc M etc/opensc.conf.in M etc/Makefile.am D man _M solaris M solaris/Makefile git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3405 c6295689-39f2-0310-b995-f0e70906c6a9
2008-03-06 16:06:59 +00:00
#ifdef ENABLE_OPENSSL
/* FIXME: Bug in 1.0.0-beta series crashes with 0 length */
if (len > 0)
OPENSSL_cleanse(ptr, len);
#else
memset(ptr, 0, len);
#endif
}
static int
sc_remote_apdu_allocate(struct sc_remote_data *rdata,
struct sc_remote_apdu **new_rapdu)
{
struct sc_remote_apdu *rapdu = NULL, *rr;
if (!rdata)
return SC_ERROR_INVALID_ARGUMENTS;
rapdu = calloc(1, sizeof(struct sc_remote_apdu));
if (rapdu == NULL)
return SC_ERROR_OUT_OF_MEMORY;
rapdu->apdu.data = &rapdu->sbuf[0];
rapdu->apdu.resp = &rapdu->rbuf[0];
rapdu->apdu.resplen = sizeof(rapdu->rbuf);
if (new_rapdu)
*new_rapdu = rapdu;
if (rdata->data == NULL) {
rdata->data = rapdu;
rdata->length = 1;
return SC_SUCCESS;
}
for (rr = rdata->data; rr->next; rr = rr->next)
;
rr->next = rapdu;
rdata->length++;
return SC_SUCCESS;
}
static void
sc_remote_apdu_free (struct sc_remote_data *rdata)
{
struct sc_remote_apdu *rapdu = NULL;
if (!rdata)
return;
rapdu = rdata->data;
while(rapdu) {
struct sc_remote_apdu *rr = rapdu->next;
free(rapdu);
rapdu = rr;
}
}
void sc_remote_data_init(struct sc_remote_data *rdata)
{
if (!rdata)
return;
memset(rdata, 0, sizeof(struct sc_remote_data));
rdata->alloc = sc_remote_apdu_allocate;
rdata->free = sc_remote_apdu_free;
}
/**************************** mutex functions ************************/
int sc_mutex_create(const sc_context_t *ctx, void **mutex)
{
if (ctx == NULL)
return SC_ERROR_INVALID_ARGUMENTS;
if (ctx->thread_ctx != NULL && ctx->thread_ctx->create_mutex != NULL)
return ctx->thread_ctx->create_mutex(mutex);
else
return SC_SUCCESS;
}
int sc_mutex_lock(const sc_context_t *ctx, void *mutex)
{
if (ctx == NULL)
return SC_ERROR_INVALID_ARGUMENTS;
if (ctx->thread_ctx != NULL && ctx->thread_ctx->lock_mutex != NULL)
return ctx->thread_ctx->lock_mutex(mutex);
else
return SC_SUCCESS;
}
int sc_mutex_unlock(const sc_context_t *ctx, void *mutex)
{
if (ctx == NULL)
return SC_ERROR_INVALID_ARGUMENTS;
if (ctx->thread_ctx != NULL && ctx->thread_ctx->unlock_mutex != NULL)
return ctx->thread_ctx->unlock_mutex(mutex);
else
return SC_SUCCESS;
}
int sc_mutex_destroy(const sc_context_t *ctx, void *mutex)
{
if (ctx == NULL)
return SC_ERROR_INVALID_ARGUMENTS;
if (ctx->thread_ctx != NULL && ctx->thread_ctx->destroy_mutex != NULL)
return ctx->thread_ctx->destroy_mutex(mutex);
else
return SC_SUCCESS;
}
unsigned long sc_thread_id(const sc_context_t *ctx)
{
if (ctx == NULL || ctx->thread_ctx == NULL ||
ctx->thread_ctx->thread_id == NULL)
return 0UL;
else
return ctx->thread_ctx->thread_id();
}