G'day,

I'm using libmusclepkcs11.so to create data objects on a Cyberflex e-gate 32K card. I can create and lookup multiple data objects in a session, but once the session is closed, I can only lookup one of the data objects created. Each data object is created as a token object, and I'm searching for data objects by looking for all objects where CKA_CLASS has the value CKO_DATA.

Is this a PKCS#11 issue, a card issue, a libmusclepkcs11 issue, a Muscle applet issue, or a programming issue? I'd like to store and view mutliple data objects on a card, but it seems that I can only view one data object afterwards.

Attached is the application I use to create and view data objects on the card. Also attached is some sample output, where I create three data objects in one session (and a lookup returns three data object handles). When I next run the application, only one data object is returned via the same lookup.

Any tips on how to view multiple data objects appreciated.

I'm using libmusclecard-1.2.9-beta7, and the Muscle applet as loaded using CardManagerClient 1.0.1

-- Geoff



/*
 * Program to add, delete, and view a data object via PKCS#11
 */
#include <stdio.h>
#include <assert.h>
#include <dlfcn.h>
#include <string.h>
#include <stdlib.h>

/* unix defns for pkcs11.h */
#define CK_PTR *

#define CK_DEFINE_FUNCTION(returnType, name) \
   returnType name

#define CK_DECLARE_FUNCTION(returnType, name) \
   returnType name

#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
   returnType (* name)

#define CK_CALLBACK_FUNCTION(returnType, name) \
   returnType (* name)

#ifndef NULL_PTR
#define NULL_PTR 0
#endif

#include <pkcs11.h>

typedef struct Session {
  CK_FUNCTION_LIST_PTR functions;
  CK_SESSION_HANDLE handle;
} Session;

static Session *open_session (const char *module, int slot, char *pin);
static void close_session (const Session *session);

static void create_data_objects (const Session *session, int objects);

static void delete_data_objects (const Session *session);

static void view_data_objects (const Session *session);

static const char * get_attr_type_str (const CK_ATTRIBUTE_TYPE type);
static const char * get_attr_value_str (const CK_ATTRIBUTE *attr);
static const char *get_rv_string(const CK_RV rv);
static void dump_attributes (const Session *session, CK_OBJECT_HANDLE hObject);


static void printUsage (const char *progname) {
  printf ("Usage: %s {option}\n", progname);
  printf ("Options:\n");
  printf ("  --module <path>       Path to PKCS#11 module\n");
  printf ("  --slot <num>          Slot number to use [DEFAULT=0]\n");
  printf ("  --pin <pin>           PIN for user login\n");
  printf ("  --create {x|y|z}      Create data object x, y, or z\n");
  printf ("  --delete              Delete data object(s)\n");
  printf ("  --view                View data objects\n");
  printf ("  --help                Show this help\n");
}

/* Actions that may be performed */
typedef enum {
  ACTION_NONE,       /* No action defined */
  ACTION_CREATE,     /* Create data objects */
  ACTION_DELETE,     /* Delete all data objects */
  ACTION_VIEW,       /* View all data objects */
} Action;
  

#define OBJECT_X 0x0001
#define OBJECT_Y 0x0002
#define OBJECT_Z 0x0004

int main (int argc, char **argv) {
  const char *module = NULL;
  int slot = 0;
  char *pin = NULL;
  int i;
  Action action = ACTION_NONE;
  int objects = 0;
  Session *session;

  /* Process args. */
  for (i = 1; i < argc; i++) {
    const char *arg = argv[i];
    if (strcmp (arg, "--module") == 0) {
      module = argv[++i];
    }
    else if (strcmp (arg, "--slot") == 0) {
      slot = atoi (argv[++i]);
    }
    else if (strcmp (arg, "--pin") == 0) {
      pin = argv[++i];
    }
    else if (strcmp (arg, "--create") == 0) {
      action = ACTION_CREATE;
      while (i < (argc-1) && strcmp (argv[i+1], "--") != 0) {
        const char *s = argv[++i];
        if (strcmp (s, "x") == 0) {
          objects |= OBJECT_X;
        }
        else if (strcmp (s, "y") == 0) {
          objects |= OBJECT_Y;
        }
        else if (strcmp (s, "z") == 0) {
          objects |= OBJECT_Z;
        }
        else {
          printf ("*** Unknown object: %s ***\n", s);
          printUsage (argv[0]);
          exit (1);
        }
      }  
    }  
    else if (strcmp (arg, "--delete") == 0) {
      action = ACTION_DELETE;
    }  
    else if (strcmp (arg, "--view") == 0) {
      action = ACTION_VIEW;
    }  
    else if (strcmp (arg, "--help") == 0) {
      printUsage (argv[0]);
      exit (0);
    }
    else {
      printf ("*** Unknown option: '%s' ***\n", arg);
      printUsage (argv[0]);
      exit (-1);
    }
  }

  /* Make sure a module was specified. */
  if (module == NULL) {
    printf ("*** Must specify a module ***\n");
    printUsage (argv[0]);
    exit (-1);
  }

  /* Make sure an action was specified */
  if (action == ACTION_NONE) {
    printf ("*** Must specify an action (--create, --delete, or --view) ***\n");
    printUsage (argv[0]);
    exit (-1);
  }
      
  session = open_session (module, slot, pin);
  if (session == NULL) {
    exit (-1);
  }

  /* Perform the appropriate action */
  switch (action) {
  case ACTION_CREATE:
    create_data_objects (session, objects);
    break;
  case ACTION_DELETE:
    delete_data_objects (session);
    break;       
  case ACTION_VIEW:
    view_data_objects (session);
    break; 
  default:
    assert (0); /* should not get here */
  }
      
  close_session (session);

  return 0;
}

/** 
 * Create data object with given attributes 
 */
static CK_OBJECT_HANDLE create_data_object (const Session *session,
                                            CK_BBOOL attr_private,
                                            CK_CHAR *attr_application,
                                            CK_CHAR *attr_label,
                                            CK_CHAR *attr_value)
{
  CK_RV rv;
  CK_BBOOL true = TRUE;
  CK_OBJECT_HANDLE hObject;
  CK_OBJECT_CLASS objectClass = CKO_DATA;
  CK_ATTRIBUTE template[] = {
    { CKA_CLASS, &objectClass, sizeof (CK_OBJECT_CLASS) },
    { CKA_TOKEN, &true, sizeof (CK_BBOOL) },
    { CKA_PRIVATE, &attr_private, sizeof (CK_BBOOL) }, 
    { CKA_MODIFIABLE, &true, sizeof (CK_BBOOL) },
    { CKA_APPLICATION, attr_application, strlen (attr_application) },
    { CKA_LABEL, attr_label, strlen (attr_label) },
    { CKA_VALUE, attr_value, strlen (attr_value) },
    { CKA_OBJECT_ID, NULL, 0 },
  };
  CK_ULONG templateSize = sizeof (template) / sizeof (template[0]);
  CK_ULONG i;

  /* Pre-condition checks. */
  assert (session != NULL);
  
  printf ("## Creating object with template:\n");
  for (i = 0; i < templateSize; i++) {
    CK_ATTRIBUTE *attr = &template[i];
    printf ("%s: length = %u, value = %s\n", 
            get_attr_type_str (attr->type), 
            (unsigned int) attr->ulValueLen,
	    get_attr_value_str (attr));
  }

  printf ("## Creating object ... ");
  rv = (*session->functions->C_CreateObject) (session->handle, template, 
                                              templateSize, &hObject); 
  if (rv != CKR_OK) {
    printf ("failed: %s\n", get_rv_string (rv));
    return CK_INVALID_HANDLE;
  }
  printf ("ok: handle = %04lX\n", hObject);
  
  return hObject;
}


/**
 * Create data objects 
 */
static void create_data_objects (const Session *session, int objects)
{
  printf ("========== Creating data objects ==========\n");

  /* private="TRUE", application="test", label="x", value="foo" */
  if (objects & OBJECT_X) {
    printf ("=== Creating object X ===\n");
    create_data_object (session, TRUE, "test", "x", "foo");
  }
 
  /* private="FALSE", application="test", label="y", value="bar" */
  if (objects & OBJECT_Y) {
    printf ("=== Creating object Y ===\n");
    create_data_object (session, FALSE, "test", "y", "bar");
  }

  /* private="false", application="test", label="z", value="baz" */
  if (objects & OBJECT_Z) {
    printf ("=== Creating object Z ===\n");
    create_data_object (session, FALSE, "test", "z", "baz");
  }
  printf ("===========================================\n");

  /* Now view all data objects */
  view_data_objects (session);
}

typedef struct { 
  CK_OBJECT_HANDLE *hObjects;
  CK_ULONG ulCount;
} ObjectHandles;
  
#define MAX_OBJECTS 128

/**
 * Get handles of all data objects. 
 */
static ObjectHandles *get_data_object_handles (const Session *session)
{
  CK_RV rv;
  ObjectHandles *handles;
  CK_OBJECT_CLASS objClass = CKO_DATA;

  /* Template matches all objects with CKA_CLASS == CKO_DATA */
  CK_ATTRIBUTE template[] = {
    { CKA_CLASS, &objClass, sizeof (objClass) },
  };
  CK_ULONG ulTemplateCount = sizeof (template) / sizeof (template[0]);
  
  /* Pre-condition checks. */
  assert (session != NULL);

  /* Allocate object handles structure */
  handles = (ObjectHandles *) malloc (sizeof (ObjectHandles));
  assert (handles != NULL);
  
  /* Allocate array of object handles */
  handles->ulCount = MAX_OBJECTS;
  handles->hObjects = (CK_OBJECT_HANDLE *) 
                        malloc (sizeof (CK_OBJECT_HANDLE) * MAX_OBJECTS);
  assert (handles->hObjects != NULL);
  
  /* Initiate the object search */
  printf ("## Searching for data objects ... ");
  rv = (*session->functions->C_FindObjectsInit)(session->handle, template, 
                                                ulTemplateCount);
  if (rv != CKR_OK && rv != CKR_ATTRIBUTE_TYPE_INVALID) {
    printf ("failed: %s\n", get_rv_string (rv));
    return NULL;
  }
  
  /* Perform the search */
  rv = (*session->functions->C_FindObjects) (session->handle, 
                                             handles->hObjects, 
                                             handles->ulCount,
                                             &handles->ulCount);
  if (rv != CKR_OK) {
    printf ("failed: %s\n", get_rv_string (rv));
    return NULL;
  }
  printf ("ok\n");

  printf ("## Found %lu data object(s)\n", handles->ulCount);
  
  /* Remember to call C_FindObjectsFinal to terminate the search */
  printf ("## Finalizing search ... ");
  rv = (*session->functions->C_FindObjectsFinal)(session->handle);
  if (rv != CKR_OK) {
    printf ("failed: %s\n", get_rv_string (rv));
    return NULL;
  }
  printf ("ok\n");

  return handles;
}

/**
 * Delete all data objects
 */
static void delete_data_objects (const Session *session)
{
  ObjectHandles *handles;
  CK_ULONG i;
  
  /* Pre-condition checks. */
  assert (session != NULL);

  printf ("========== Deleting data objects ==========\n");
  
  /* Get handles to all data objects */
  handles = get_data_object_handles (session);
  assert (handles != NULL);
  
  /* For each handle, delete the corresponding object */
  for (i = 0; i < handles->ulCount; i++) {
    CK_OBJECT_HANDLE hObject = handles->hObjects[i];
    assert (hObject != CK_INVALID_HANDLE);
    printf ("## Object %04lX shall be deleted, attributes are:\n", hObject);
    dump_attributes (session, hObject);
    printf ("## Deleting object %04lX\n", hObject);
    (*session->functions->C_DestroyObject) (session->handle, hObject);
  }

  handles = get_data_object_handles (session);
  assert (handles != NULL);

  /* Emit a warning if data objects can still be found */
  if (handles->ulCount > 0) {
    printf ("WARNING: there are still %lu data object(s) present\n",
            handles->ulCount);
  }

  printf ("==========================================\n");
}

/**
 * View all data objects.
 */
static void view_data_objects (const Session *session)
{
  ObjectHandles *handles;
  CK_ULONG i;
  
  /* Pre-condition checks. */
  assert (session != NULL);

  printf ("========== Viewing data objects ==========\n");

  /* Get handles to all data objects */
  handles = get_data_object_handles (session);
  assert (handles != NULL);
  
  /* View attributes of corresponding object */
  for (i = 0; i < handles->ulCount; i++) {
    CK_OBJECT_HANDLE hObject = handles->hObjects[i];
    assert (hObject != CK_INVALID_HANDLE);
    printf ("## Viewing attributes of object %04lX\n", hObject);
    dump_attributes (session, hObject);
  }

  printf ("==========================================\n");
}

/* =================== Attribute display functions ====================== */

typedef const char * (*AttributeToStringFn) (const CK_ATTRIBUTE *attr);

/* Information about an attribute */
typedef struct {
  CK_ATTRIBUTE_TYPE type;
  const char *name;
  const AttributeToStringFn converter;
} AttributeInfo;

/**
 * Get string representation of an attribute containing a CK_OBJECT_CLASS
 * value.
 */
static const char * ObjectClassToString (const CK_ATTRIBUTE *attr) {
  CK_OBJECT_CLASS *value;
  char buf[128];
    
  /* Pre-condition checks */
  assert (attr != NULL);
  assert (attr->ulValueLen == sizeof (CK_OBJECT_CLASS));
  assert (attr->pValue != NULL);
  
  value = (CK_OBJECT_CLASS *) attr->pValue;
 
  switch (*value) {
  case CKO_DATA: return "CKO_DATA";
  case CKO_CERTIFICATE: return "CKO_CERTIFICATE";
  case CKO_PUBLIC_KEY: return "CKO_PUBLIC_KEY";
  case CKO_PRIVATE_KEY: return "CKO_PRIVATE_KEY";
  case CKO_SECRET_KEY: return "CKO_SECRET_KEY";
  case CKO_HW_FEATURE: return "CKO_HW_FEATURE";
  case CKO_DOMAIN_PARAMETERS: return "CKO_DOMAIN_PARAMETERS";
  /* Undefined: case CKO_MECHANISM: return "CKO_MECHANISM"; */
  }
  
  /* Check for vendor-defined value */
  if (*value >= CKO_VENDOR_DEFINED) {
    return "CKO_VENDOR_DEFINED";
  }
  
  /* Unknown object class */
  sprintf (buf, "<Unknown:%04lX>", *value);
  return strdup (buf);  
}
  
/**
 * Get a string representation of an attribute containing a CK_BBOOL 
 * value.
 */
static const char * BBoolToString (const CK_ATTRIBUTE *attr) {
  const CK_BBOOL *value;
  
  /* Pre-condition checks */
  assert (attr != NULL);
  assert (attr->ulValueLen == sizeof (CK_BBOOL));
  assert (attr->pValue != NULL);
  
  value = (CK_BBOOL *) attr->pValue;
  
  return (*value) ? "TRUE" : "FALSE";
}

/**
 * Get the string representation of an attribute containing an RFC2279 
 * string value.
 */
static const char * RFC2279StringToString (const CK_ATTRIBUTE *attr) {  
  char *buf;
  
  /* Pre-condition checks */
  assert (attr != NULL);
  assert (attr->pValue != NULL);
  assert (attr->ulValueLen != -1);

  /* Allocate buffer to hold string, and terminating zero */
  buf = (char *) malloc (attr->ulValueLen + 1);
  assert (buf != NULL);

  /* Copy rfc2279 string, and add terminating zero */
  strncpy (buf, attr->pValue, attr->ulValueLen);
  buf[attr->ulValueLen] = (char) 0;

  return buf;
}  

/** 
 * Get the string representation of an attribute containing a 
 * byte array.
 */
static const char * ByteArrayToString  (const CK_ATTRIBUTE *attr) {  
  CK_BYTE *value;
  char *buf;
  CK_ULONG i;
  
  /* Pre-condition checks */
  assert (attr != NULL);
  assert (attr->pValue != NULL);
  assert (attr->ulValueLen != -1);

  value = (CK_BYTE *) attr->pValue;
  
  /* Allocate buffer to hold hex representation */
  buf = (char *) malloc (attr->ulValueLen * 3);
  assert (buf != NULL);
  
  /* Copy byte array to hex buffer */
  for (i = 0; i < attr->ulValueLen; i++) {
    char t[3];

    if (i > 0) {
      buf[(i*3)-1] = ':';
    }

    sprintf (t, "%02X", value[i]);
    buf[(i*3)] = t[0];
    buf[(i*3)+1] = t[1];
  }
  buf[attr->ulValueLen*3] = 0;
  
  return buf;
}
  
/** Attribute information table */  
static const AttributeInfo ATTRIBUTE_INFOS[] = {
  { CKA_CLASS, "CKA_CLASS", ObjectClassToString },
  { CKA_TOKEN, "CKA_TOKEN", BBoolToString },
  { CKA_PRIVATE, "CKA_PRIVATE", BBoolToString },
  { CKA_MODIFIABLE, "CKA_MODIFIABLE", BBoolToString },
  { CKA_LABEL, "CKA_LABEL", RFC2279StringToString },
  { CKA_APPLICATION, "CKA_APPLICATION", RFC2279StringToString },
  { CKA_OBJECT_ID, "CKA_OBJECT_ID", ByteArrayToString },
  { CKA_VALUE, "CKA_VALUE", ByteArrayToString },
};
#define NUM_ATTRIBUTE_INFOS \
  (sizeof (ATTRIBUTE_INFOS) / sizeof (ATTRIBUTE_INFOS[0]))
  
/** 
 * Get a string representing the attribute type.
 */
static const char * get_attr_type_str (const CK_ATTRIBUTE_TYPE type) {
  char buf[128];
  size_t i;
    
  for (i = 0; i < NUM_ATTRIBUTE_INFOS; i++) {
    if (ATTRIBUTE_INFOS[i].type == type) {
      return ATTRIBUTE_INFOS[i].name;
    }
  }    
  
  sprintf (buf, "Unknown: %lu", type);
  return strdup (buf);
}

/**
 * Get a string representing the attribute value.
 */
static const char * get_attr_value_str (const CK_ATTRIBUTE *attr) {
  char buf[128];
  size_t i;
    
  /* Check for empty value */
  if (attr->pValue == NULL || attr->ulValueLen == -1) {
    return "<empty>";
  }

  /* Check for known attribute type, and call converter fn */
  for (i = 0; i < NUM_ATTRIBUTE_INFOS; i++) {
    if (ATTRIBUTE_INFOS[i].type == attr->type) {
      return ATTRIBUTE_INFOS[i].converter (attr);
    }
  }

  /* Unknown attribute type */
  sprintf (buf, "<Unknown: %lu>", attr->type);
  return strdup (buf);
}
  
/**
 * Dump all data attributes for the object with the given handle.
 */
static void dump_attributes (const Session *session, CK_OBJECT_HANDLE hObject)
{
  CK_RV rv;
  CK_ATTRIBUTE template[] = {
    { CKA_CLASS, NULL_PTR, 0 },
    { CKA_TOKEN, NULL_PTR, 0 },
    { CKA_PRIVATE, NULL_PTR, 0 },
    { CKA_MODIFIABLE, NULL_PTR, 0 },
    { CKA_LABEL, NULL_PTR, 0 },
    { CKA_APPLICATION, NULL_PTR, 0 },
    { CKA_OBJECT_ID, NULL_PTR, 0 },
    { CKA_VALUE, NULL_PTR, 0 }
  };
  CK_ULONG templateSize = sizeof (template) / sizeof (template[0]);
  CK_ULONG i;
  
  /* Pre-condition checks. */
  assert (session != NULL);
  assert (hObject != CK_INVALID_HANDLE);

    /* Get the length of the attributes */
  printf ("## Getting attribute values ... ");
  rv = (*session->functions->C_GetAttributeValue) (session->handle, hObject, 
                                                   template, templateSize);
  if (rv != CKR_OK && rv != CKR_ATTRIBUTE_TYPE_INVALID) {
    printf ("failed: %s\n", get_rv_string (rv));
    return;
  }
  
  /* Allocate memory for the attribute values. */
  for (i = 0; i < templateSize; i++) {
    CK_ATTRIBUTE *attr = &template[i];

    /* Check that the attribute's length can be determined. */
    if (attr->ulValueLen != -1) {
      /* Allocate space for the attribute value. */
      attr->pValue = (CK_BYTE_PTR) malloc (attr->ulValueLen);
      assert (attr->pValue != NULL);
    }  
  }

  /* Get the value of the attributes */
  rv = (*session->functions->C_GetAttributeValue) (session->handle, hObject, 
                                                   template, templateSize);
  if (rv != CKR_OK && rv != CKR_ATTRIBUTE_TYPE_INVALID) {
    printf ("failed: %s\n", get_rv_string (rv));
    return;
  }
  printf ("ok\n");

  for (i = 0; i < templateSize; i++) {
    CK_ATTRIBUTE *attr = &template[i];
    printf ("%s: length = %lu, value = %s\n", 
            get_attr_type_str (attr->type), 
            attr->ulValueLen,
	    get_attr_value_str (attr));
  }
}

/* ===================== Session management ============================= */

/**
 * Open a new session.
 */
static Session *open_session (const char *module, int slot, char *pin) {
  Session *session;
  void *hModule;
  CK_C_GetFunctionList pC_GetFunctionList;
  CK_RV rv;
  
  /* Pre-condition checks */
  assert (module != NULL);
  
  session = (Session *) calloc (1, sizeof (Session));
  assert (session != NULL); 

  /* Load the PKCS #11 module. */
  printf ("## Loading module: %s ...", module);
  fflush (stdout);
  hModule = dlopen (module, RTLD_LAZY);
  printf ((hModule == NULL) ? "failed\n" : "ok\n");
  assert (hModule!=NULL);

  /* Get function pointer to C_GetFunctionList. */
  pC_GetFunctionList = 
    (CK_C_GetFunctionList) dlsym (hModule, "C_GetFunctionList");
  assert (pC_GetFunctionList!=NULL);

  /* Get function pointers to all PKCS #11 functions. */
  rv = (*pC_GetFunctionList) (&session->functions);
  assert (rv == CKR_OK);

  /* Initalize Cryptoki. */
  rv = (*session->functions->C_Initialize) (NULL);
  assert (rv==CKR_OK);
  
  /* Open a read/write session on the given slot */
  printf ("## Opening session for slot = %02d ... ", slot);
  rv = (*session->functions->C_OpenSession)(slot, 
                                            CKF_SERIAL_SESSION|CKF_RW_SESSION,
                                            0, 0, &session->handle);
  if (rv != CKR_OK) {
    printf ("failed: %s\n", get_rv_string (rv));
    return NULL;
  }
  printf ("ok\n");  

  if (pin != NULL) {
    printf ("## Performing login with PIN '%s' .... ", pin);
    rv = (*session->functions->C_Login)(session->handle, CKU_USER, 
                                        pin, strlen(pin));
    if (rv != CKR_OK) {
      printf ("failed: %s\n", get_rv_string (rv));
      return NULL;
    }
    printf ("ok\n");  
  }

  return session;
} 

/**
 * Close the session.
 */
static void close_session (const Session *session) {
  CK_RV rv;

  /* Pre-condition checks */
  assert (session != NULL); 
    
  printf ("## Finalizing ... ");
  rv = (*session->functions->C_Finalize)(0);
  if (rv != CKR_OK) {
    printf ("failed: %s\n", get_rv_string (rv));
  }
  else {
    printf ("ok\n");
  }
}   

static const char *get_rv_string(const CK_RV rv) {
  static char buf[128];

  switch (rv) {
  case CKR_ARGUMENTS_BAD: return "bad arguments";
  case CKR_CANCEL: return "cancel";
  case CKR_CRYPTOKI_NOT_INITIALIZED: return "cryptoki not initialized";
  case CKR_DATA_LEN_RANGE: return "data len range";
  case CKR_DEVICE_ERROR: return "device error";
  case CKR_DEVICE_MEMORY: return "device memory";
  case CKR_DEVICE_REMOVED: return "device removed";
  case CKR_FUNCTION_CANCELED: return "function canceled";
  case CKR_FUNCTION_FAILED: return "function failed";
  case CKR_FUNCTION_NOT_SUPPORTED: return "function not supported";
  case CKR_GENERAL_ERROR: return "general error";
  case CKR_HOST_MEMORY: return "host memory";
  case CKR_OK: return "ok";
  case CKR_OPERATION_ACTIVE: return "operation active";
  case CKR_OPERATION_NOT_INITIALIZED: return "operation not initialized";
  case CKR_PIN_INCORRECT: return "pin incorrect";
  case CKR_PIN_LOCKED: return "pin locked";
  case CKR_RANDOM_SEED_NOT_SUPPORTED: return "random seed not supported";
  case CKR_RANDOM_NO_RNG: return "no rng";
  case CKR_SESSION_CLOSED: return "session closed";
  case CKR_SESSION_COUNT: return "session count";
  case CKR_SESSION_HANDLE_INVALID: return "session handle invalid";
  case CKR_SESSION_PARALLEL_NOT_SUPPORTED: return "session parallel not supported";
  case CKR_SESSION_READ_ONLY: return "session read only";
  case CKR_SESSION_EXISTS: return "session exists";
  case CKR_SESSION_READ_ONLY_EXISTS: return "session read-only exists";
  case CKR_SESSION_READ_WRITE_SO_EXISTS: return "session read write SO exists";
  case CKR_SIGNATURE_INVALID: return "signature invalid";
  case CKR_SIGNATURE_LEN_RANGE: return "signature len range";
  case CKR_SLOT_ID_INVALID: return "slot id invalid";
  case CKR_TEMPLATE_INCOMPLETE: return "template incomplete";
  case CKR_TEMPLATE_INCONSISTENT: return "template inconsistent";
  case CKR_TOKEN_NOT_PRESENT: return "token not present";
  case CKR_TOKEN_NOT_RECOGNIZED: return "token not recognized";
  case CKR_USER_ALREADY_LOGGED_IN: return "user already logged in";
  case CKR_USER_NOT_LOGGED_IN: return "user not logged in";
  case CKR_USER_PIN_NOT_INITIALIZED: return "user pin not initialized";
  case CKR_USER_TOO_MANY_TYPES: return "user too many types";
  case CKR_USER_TYPE_INVALID: return "user type invalid";
  }

  sprintf (buf, "Unknown error: %lu", rv);
  return strdup (buf);
}
-- Create three data objects on the card --

$ ./p11-add-data-object --module /usr/local/lib/libmusclepkcs11.so --slot 1 
--pin 00000000 --create x y z
## Loading module: /usr/local/lib/libmusclepkcs11.so ...ok
## Opening session for slot = 01 ... ok
## Performing login with PIN '00000000' .... ok
========== Creating data objects ==========
=== Creating object X ===
## Creating object with template:
CKA_CLASS: length = 4, value = CKO_DATA
CKA_TOKEN: length = 1, value = TRUE
CKA_PRIVATE: length = 1, value = TRUE
CKA_MODIFIABLE: length = 1, value = TRUE
CKA_APPLICATION: length = 4, value = test
CKA_LABEL: length = 1, value = x
CKA_VALUE: length = 3, value = 66:6F:6F
CKA_OBJECT_ID: length = 0, value = <empty>
## Creating object ... ok: handle = 804E508
=== Creating object Y ===
## Creating object with template:
CKA_CLASS: length = 4, value = CKO_DATA
CKA_TOKEN: length = 1, value = TRUE
CKA_PRIVATE: length = 1, value = FALSE
CKA_MODIFIABLE: length = 1, value = TRUE
CKA_APPLICATION: length = 4, value = test
CKA_LABEL: length = 1, value = y
CKA_VALUE: length = 3, value = 62:61:72
CKA_OBJECT_ID: length = 0, value = <empty>
## Creating object ... ok: handle = 804F020
=== Creating object Z ===
## Creating object with template:
CKA_CLASS: length = 4, value = CKO_DATA
CKA_TOKEN: length = 1, value = TRUE
CKA_PRIVATE: length = 1, value = FALSE
CKA_MODIFIABLE: length = 1, value = TRUE
CKA_APPLICATION: length = 4, value = test
CKA_LABEL: length = 1, value = z
CKA_VALUE: length = 3, value = 62:61:7A
CKA_OBJECT_ID: length = 0, value = <empty>
## Creating object ... ok: handle = 804F208
===========================================
========== Viewing data objects ==========
## Searching for data objects ... ok
## Found 3 data object(s)
## Finalizing search ... ok
## Viewing attributes of object 804F208
## Getting attribute values ... ok
CKA_CLASS: length = 4, value = CKO_DATA
CKA_TOKEN: length = 1, value = TRUE
CKA_PRIVATE: length = 1, value = FALSE
CKA_MODIFIABLE: length = 1, value = TRUE
CKA_LABEL: length = 1, value = z
CKA_APPLICATION: length = 4, value = test
CKA_OBJECT_ID: length = 0, value =
CKA_VALUE: length = 3, value = 62:61:7Ah
## Viewing attributes of object 804F020
## Getting attribute values ... ok
CKA_CLASS: length = 4, value = CKO_DATA
CKA_TOKEN: length = 1, value = TRUE
CKA_PRIVATE: length = 1, value = FALSE
CKA_MODIFIABLE: length = 1, value = TRUE
CKA_LABEL: length = 1, value = y
CKA_APPLICATION: length = 4, value = test
CKA_OBJECT_ID: length = 0, value =
CKA_VALUE: length = 3, value = 62:61:72
## Viewing attributes of object 804E508
## Getting attribute values ... ok
CKA_CLASS: length = 4, value = CKO_DATA
CKA_TOKEN: length = 1, value = TRUE
CKA_PRIVATE: length = 1, value = TRUE
CKA_MODIFIABLE: length = 1, value = TRUE
CKA_LABEL: length = 1, value = x
CKA_APPLICATION: length = 4, value = test
CKA_OBJECT_ID: length = 0, value =
CKA_VALUE: length = 3, value = 66:6F:6F
==========================================
## Finalizing ... ok



-- View all data objects on the card ---

$ ./p11-add-data-object --module /usr/local/lib/libmusclepkcs11.so --slot 1 
--pin 00000000 --view
## Loading module: /usr/local/lib/libmusclepkcs11.so ...ok
## Opening session for slot = 01 ... ok
## Performing login with PIN '00000000' .... ok
========== Viewing data objects ==========
## Searching for data objects ... ok
## Found 1 data object(s)
## Finalizing search ... ok
## Viewing attributes of object 804E508
## Getting attribute values ... ok
CKA_CLASS: length = 4, value = CKO_DATA
CKA_TOKEN: length = 1, value = TRUE
CKA_PRIVATE: length = 1, value = FALSE
CKA_MODIFIABLE: length = 1, value = TRUE
CKA_LABEL: length = 1, value = z
CKA_APPLICATION: length = 4, value = test
CKA_OBJECT_ID: length = 0, value =
CKA_VALUE: length = 3, value = 62:61:7A
==========================================
## Finalizing ... ok
_______________________________________________
Muscle mailing list
[email protected]
http://lists.drizzle.com/mailman/listinfo/muscle

Reply via email to