Back to index

lightning-sunbird  0.9+nobinonly
trivial.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is a trivial PKCS#11 test program.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #ifdef DEBUG
00038 static const char CVS_ID[] = "@(#) $RCSfile: trivial.c,v $ $Revision: 1.4 $ $Date: 2005/01/20 02:25:51 $";
00039 #endif /* DEBUG */
00040 
00041 /*
00042  * This is a very trivial program I wrote for testing out a 
00043  * couple data-only Cryptoki modules for NSS.  It's not a "real"
00044  * test program that prints out nice "PASS" or "FAIL" messages;
00045  * it just makes calls and dumps data.
00046  */
00047 
00048 #include "config.h"
00049 
00050 #ifdef HAVE_NSPR_H
00051 #include "nspr.h"
00052 #else
00053 #error "NSPR is required."
00054 #endif
00055 
00056 #ifdef WITH_NSS
00057 #define FGMR 1
00058 #include "ck.h"
00059 #else
00060 #include "pkcs11t.h"
00061 #include "pkcs11.h"
00062 #endif
00063 
00064 /* The RSA versions are sloppier with namespaces */
00065 #ifndef CK_TRUE
00066 #define CK_TRUE TRUE
00067 #endif
00068 
00069 #ifndef CK_FALSE
00070 #define CK_FALSE FALSE
00071 #endif
00072 
00073 int
00074 rmain
00075 (
00076   int argc,
00077   char *argv[]
00078 );
00079 
00080 int
00081 main
00082 (
00083   int argc,
00084   char *argv[]
00085 )
00086 {
00087   int rv = 0;
00088 
00089   PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 14);
00090   rv = rmain(argc, argv);
00091   PR_Cleanup();
00092 
00093   return rv;
00094 }
00095 
00096 static CK_ATTRIBUTE_TYPE all_known_attribute_types[] = {
00097   CKA_CLASS,
00098   CKA_TOKEN,
00099   CKA_PRIVATE,
00100   CKA_LABEL,
00101   CKA_APPLICATION,
00102   CKA_VALUE,
00103   CKA_CERTIFICATE_TYPE,
00104   CKA_ISSUER,
00105   CKA_SERIAL_NUMBER,
00106   CKA_KEY_TYPE,
00107   CKA_SUBJECT,
00108   CKA_ID,
00109   CKA_SENSITIVE,
00110   CKA_ENCRYPT,
00111   CKA_DECRYPT,
00112   CKA_WRAP,
00113   CKA_UNWRAP,
00114   CKA_SIGN,
00115   CKA_SIGN_RECOVER,
00116   CKA_VERIFY,
00117   CKA_VERIFY_RECOVER,
00118   CKA_DERIVE,
00119   CKA_START_DATE,
00120   CKA_END_DATE,
00121   CKA_MODULUS,
00122   CKA_MODULUS_BITS,
00123   CKA_PUBLIC_EXPONENT,
00124   CKA_PRIVATE_EXPONENT,
00125   CKA_PRIME_1,
00126   CKA_PRIME_2,
00127   CKA_EXPONENT_1,
00128   CKA_EXPONENT_2,
00129   CKA_COEFFICIENT,
00130   CKA_PRIME,
00131   CKA_SUBPRIME,
00132   CKA_BASE,
00133   CKA_VALUE_BITS,
00134   CKA_VALUE_LEN,
00135   CKA_EXTRACTABLE,
00136   CKA_LOCAL,
00137   CKA_NEVER_EXTRACTABLE,
00138   CKA_ALWAYS_SENSITIVE,
00139   CKA_MODIFIABLE,
00140 #ifdef CKA_NETSCAPE
00141   CKA_NETSCAPE_URL,
00142   CKA_NETSCAPE_EMAIL,
00143   CKA_NETSCAPE_SMIME_INFO,
00144   CKA_NETSCAPE_SMIME_TIMESTAMP,
00145   CKA_NETSCAPE_PKCS8_SALT,
00146   CKA_NETSCAPE_PASSWORD_CHECK,
00147   CKA_NETSCAPE_EXPIRES,
00148 #endif /* CKA_NETSCAPE */
00149 #ifdef CKA_TRUST
00150   CKA_TRUST_DIGITAL_SIGNATURE,
00151   CKA_TRUST_NON_REPUDIATION,
00152   CKA_TRUST_KEY_ENCIPHERMENT,
00153   CKA_TRUST_DATA_ENCIPHERMENT,
00154   CKA_TRUST_KEY_AGREEMENT,
00155   CKA_TRUST_KEY_CERT_SIGN,
00156   CKA_TRUST_CRL_SIGN,
00157   CKA_TRUST_SERVER_AUTH,
00158   CKA_TRUST_CLIENT_AUTH,
00159   CKA_TRUST_CODE_SIGNING,
00160   CKA_TRUST_EMAIL_PROTECTION,
00161   CKA_TRUST_IPSEC_END_SYSTEM,
00162   CKA_TRUST_IPSEC_TUNNEL,
00163   CKA_TRUST_IPSEC_USER,
00164   CKA_TRUST_TIME_STAMPING,
00165 #endif /* CKA_TRUST */
00166 };
00167 
00168 static number_of_all_known_attribute_types = 
00169   (sizeof(all_known_attribute_types)/sizeof(all_known_attribute_types[0]));
00170 
00171 int
00172 usage
00173 (
00174   char *argv0
00175 )
00176 {
00177   PR_fprintf(PR_STDERR, "Usage: %s [-i {string|--}] <library>.so\n", argv0);
00178   return 1;
00179 }
00180 
00181 int
00182 rmain
00183 (
00184   int argc,
00185   char *argv[]
00186 )
00187 {
00188   char *argv0 = argv[0];
00189   PRLibrary *lib;
00190   CK_C_GetFunctionList gfl;
00191   CK_FUNCTION_LIST_PTR epv = (CK_FUNCTION_LIST_PTR)NULL;
00192   CK_RV ck_rv;
00193   CK_INFO info;
00194   CK_ULONG nSlots;
00195   CK_SLOT_ID *pSlots;
00196   CK_ULONG i;
00197   CK_C_INITIALIZE_ARGS ia, *iap;
00198 
00199   (void)memset(&ia, 0, sizeof(CK_C_INITIALIZE_ARGS));
00200   iap = (CK_C_INITIALIZE_ARGS *)NULL;
00201   while( argv++, --argc ) {
00202     if( '-' == argv[0][0] ) {
00203       switch( argv[0][1] ) {
00204       case 'i':
00205         iap = &ia;
00206         if( ((char *)NULL != argv[1]) && ('-' != argv[1][0]) ) {
00207 #ifdef WITH_NSS
00208           ia.pConfig = argv[1];
00209           ia.ulConfigLen = strlen(argv[1]);
00210           argv++, --argc;
00211 #else
00212           return usage(argv0);
00213 #endif /* WITH_NSS */
00214         }
00215         break;
00216       case '-':
00217         argv++, --argc;
00218         goto endargs;
00219       default:
00220         return usage(argv0);
00221       }
00222     } else {
00223       break;
00224     }
00225   }
00226  endargs:;
00227 
00228   if( 1 != argc ) {
00229     return usage(argv0);
00230   }
00231 
00232   lib = PR_LoadLibrary(argv[0]);
00233   if( (PRLibrary *)NULL == lib ) {
00234     PR_fprintf(PR_STDERR, "Can't load %s: %ld, %ld\n", argv[1], PR_GetError(), PR_GetOSError());
00235     return 1;
00236   }
00237 
00238   gfl = (CK_C_GetFunctionList)PR_FindSymbol(lib, "C_GetFunctionList");
00239   if( (CK_C_GetFunctionList)NULL == gfl ) {
00240     PR_fprintf(PR_STDERR, "Can't find C_GetFunctionList in %s: %ld, %ld\n", argv[1], 
00241                PR_GetError(), PR_GetOSError());
00242     return 1;
00243   }
00244 
00245   ck_rv = (*gfl)(&epv);
00246   if( CKR_OK != ck_rv ) {
00247     PR_fprintf(PR_STDERR, "CK_GetFunctionList returned 0x%08x\n", ck_rv);
00248     return 1;
00249   }
00250 
00251   PR_fprintf(PR_STDOUT, "Module %s loaded, epv = 0x%08x.\n\n", argv[1], (CK_ULONG)epv);
00252 
00253   /* C_Initialize */
00254   ck_rv = epv->C_Initialize(iap);
00255   if( CKR_OK != ck_rv ) {
00256     PR_fprintf(PR_STDERR, "C_Initialize returned 0x%08x\n", ck_rv);
00257     return 1;
00258   }
00259 
00260   /* C_GetInfo */
00261   (void)memset(&info, 0, sizeof(CK_INFO));
00262   ck_rv = epv->C_GetInfo(&info);
00263   if( CKR_OK != ck_rv ) {
00264     PR_fprintf(PR_STDERR, "C_GetInfo returned 0x%08x\n", ck_rv);
00265     return 1;
00266   }
00267 
00268   PR_fprintf(PR_STDOUT, "Module Info:\n");
00269   PR_fprintf(PR_STDOUT, "    cryptokiVersion = %lu.%02lu\n", 
00270              (PRUint32)info.cryptokiVersion.major, (PRUint32)info.cryptokiVersion.minor);
00271   PR_fprintf(PR_STDOUT, "    manufacturerID = \"%.32s\"\n", info.manufacturerID);
00272   PR_fprintf(PR_STDOUT, "    flags = 0x%08lx\n", info.flags);
00273   PR_fprintf(PR_STDOUT, "    libraryDescription = \"%.32s\"\n", info.libraryDescription);
00274   PR_fprintf(PR_STDOUT, "    libraryVersion = %lu.%02lu\n", 
00275              (PRUint32)info.libraryVersion.major, (PRUint32)info.libraryVersion.minor);
00276   PR_fprintf(PR_STDOUT, "\n");
00277 
00278   /* C_GetSlotList */
00279   nSlots = 0;
00280   ck_rv = epv->C_GetSlotList(CK_FALSE, (CK_SLOT_ID_PTR)CK_NULL_PTR, &nSlots);
00281   switch( ck_rv ) {
00282   case CKR_BUFFER_TOO_SMALL:
00283   case CKR_OK:
00284     break;
00285   default:
00286     PR_fprintf(PR_STDERR, "C_GetSlotList(FALSE, NULL, ) returned 0x%08x\n", ck_rv);
00287     return 1;
00288   }
00289 
00290   PR_fprintf(PR_STDOUT, "There are %lu slots.\n", nSlots);
00291 
00292   pSlots = (CK_SLOT_ID_PTR)PR_Calloc(nSlots, sizeof(CK_SLOT_ID));
00293   if( (CK_SLOT_ID_PTR)NULL == pSlots ) {
00294     PR_fprintf(PR_STDERR, "[memory allocation of %lu bytes failed]\n", nSlots * sizeof(CK_SLOT_ID));
00295     return 1;
00296   }
00297 
00298   ck_rv = epv->C_GetSlotList(CK_FALSE, pSlots, &nSlots);
00299   if( CKR_OK != ck_rv ) {
00300     PR_fprintf(PR_STDERR, "C_GetSlotList(FALSE, , ) returned 0x%08x\n", ck_rv);
00301     return 1;
00302   }
00303 
00304   for( i = 0; i < nSlots; i++ ) {
00305     PR_fprintf(PR_STDOUT, "    [%lu]: CK_SLOT_ID = %lu\n", (i+1), pSlots[i]);
00306   }
00307 
00308   PR_fprintf(PR_STDOUT, "\n");
00309 
00310   /* C_GetSlotInfo */
00311   for( i = 0; i < nSlots; i++ ) {
00312     CK_SLOT_INFO sinfo;
00313 
00314     PR_fprintf(PR_STDOUT, "[%lu]: CK_SLOT_ID = %lu\n", (i+1), pSlots[i]);
00315 
00316     (void)memset(&sinfo, 0, sizeof(CK_SLOT_INFO));
00317     ck_rv = epv->C_GetSlotInfo(pSlots[i], &sinfo);
00318     if( CKR_OK != ck_rv ) {
00319       PR_fprintf(PR_STDERR, "C_GetSlotInfo(%lu, ) returned 0x%08x\n", pSlots[i], ck_rv);
00320       return 1;
00321     }
00322 
00323     PR_fprintf(PR_STDOUT, "    Slot Info:\n");
00324     PR_fprintf(PR_STDOUT, "        slotDescription = \"%.64s\"\n", sinfo.slotDescription);
00325     PR_fprintf(PR_STDOUT, "        manufacturerID = \"%.32s\"\n", sinfo.manufacturerID);
00326     PR_fprintf(PR_STDOUT, "        flags = 0x%08lx\n", sinfo.flags);
00327     PR_fprintf(PR_STDOUT, "            -> TOKEN PRESENT = %s\n", 
00328                sinfo.flags & CKF_TOKEN_PRESENT ? "TRUE" : "FALSE");
00329     PR_fprintf(PR_STDOUT, "            -> REMOVABLE DEVICE = %s\n",
00330                sinfo.flags & CKF_REMOVABLE_DEVICE ? "TRUE" : "FALSE");
00331     PR_fprintf(PR_STDOUT, "            -> HW SLOT = %s\n", 
00332                sinfo.flags & CKF_HW_SLOT ? "TRUE" : "FALSE");
00333     PR_fprintf(PR_STDOUT, "        hardwareVersion = %lu.%02lu\n", 
00334                (PRUint32)sinfo.hardwareVersion.major, (PRUint32)sinfo.hardwareVersion.minor);
00335     PR_fprintf(PR_STDOUT, "        firmwareVersion = %lu.%02lu\n",
00336                (PRUint32)sinfo.firmwareVersion.major, (PRUint32)sinfo.firmwareVersion.minor);
00337 
00338     if( sinfo.flags & CKF_TOKEN_PRESENT ) {
00339       CK_TOKEN_INFO tinfo;
00340       CK_MECHANISM_TYPE *pMechanismList;
00341       CK_ULONG nMechanisms = 0;
00342       CK_ULONG j;
00343 
00344       (void)memset(&tinfo, 0, sizeof(CK_TOKEN_INFO));
00345       ck_rv = epv->C_GetTokenInfo(pSlots[i], &tinfo);
00346       if( CKR_OK != ck_rv ) {
00347         PR_fprintf(PR_STDERR, "C_GetTokenInfo(%lu, ) returned 0x%08x\n", pSlots[i], ck_rv);
00348         return 1;
00349       }
00350 
00351       PR_fprintf(PR_STDOUT, "    Token Info:\n");
00352       PR_fprintf(PR_STDOUT, "        label = \"%.32s\"\n", tinfo.label);
00353       PR_fprintf(PR_STDOUT, "        manufacturerID = \"%.32s\"\n", tinfo.manufacturerID);
00354       PR_fprintf(PR_STDOUT, "        model = \"%.16s\"\n", tinfo.model);
00355       PR_fprintf(PR_STDOUT, "        serialNumber = \"%.16s\"\n", tinfo.serialNumber);
00356       PR_fprintf(PR_STDOUT, "        flags = 0x%08lx\n", tinfo.flags);
00357       PR_fprintf(PR_STDOUT, "            -> RNG = %s\n",
00358                  tinfo.flags & CKF_RNG ? "TRUE" : "FALSE");
00359       PR_fprintf(PR_STDOUT, "            -> WRITE PROTECTED = %s\n",
00360                  tinfo.flags & CKF_WRITE_PROTECTED ? "TRUE" : "FALSE");
00361       PR_fprintf(PR_STDOUT, "            -> LOGIN REQUIRED = %s\n",
00362                  tinfo.flags & CKF_LOGIN_REQUIRED ? "TRUE" : "FALSE");
00363       PR_fprintf(PR_STDOUT, "            -> USER PIN INITIALIZED = %s\n",
00364                  tinfo.flags & CKF_USER_PIN_INITIALIZED ? "TRUE" : "FALSE");
00365       PR_fprintf(PR_STDOUT, "            -> RESTORE KEY NOT NEEDED = %s\n",
00366                  tinfo.flags & CKF_RESTORE_KEY_NOT_NEEDED ? "TRUE" : "FALSE");
00367       PR_fprintf(PR_STDOUT, "            -> CLOCK ON TOKEN = %s\n",
00368                  tinfo.flags & CKF_CLOCK_ON_TOKEN ? "TRUE" : "FALSE");
00369 #ifdef CKF_SUPPORTS_PARALLEL
00370       PR_fprintf(PR_STDOUT, "            -> SUPPORTS PARALLEL = %s\n",
00371                  tinfo.flags & CKF_SUPPORTS_PARALLEL ? "TRUE" : "FALSE");
00372 #endif /* CKF_SUPPORTS_PARALLEL */
00373       PR_fprintf(PR_STDOUT, "            -> PROTECTED AUTHENTICATION PATH = %s\n",
00374                  tinfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH ? "TRUE" : "FALSE");
00375       PR_fprintf(PR_STDOUT, "            -> DUAL_CRYPTO_OPERATIONS = %s\n", 
00376                  tinfo.flags & CKF_DUAL_CRYPTO_OPERATIONS ? "TRUE" : "FALSE");
00377       PR_fprintf(PR_STDOUT, "        ulMaxSessionCount = %lu\n", tinfo.ulMaxSessionCount);
00378       PR_fprintf(PR_STDOUT, "        ulSessionCount = %lu\n", tinfo.ulSessionCount);
00379       PR_fprintf(PR_STDOUT, "        ulMaxRwSessionCount = %lu\n", tinfo.ulMaxRwSessionCount);
00380       PR_fprintf(PR_STDOUT, "        ulRwSessionCount = %lu\n", tinfo.ulRwSessionCount);
00381       PR_fprintf(PR_STDOUT, "        ulMaxPinLen = %lu\n", tinfo.ulMaxPinLen);
00382       PR_fprintf(PR_STDOUT, "        ulMinPinLen = %lu\n", tinfo.ulMinPinLen);
00383       PR_fprintf(PR_STDOUT, "        ulTotalPublicMemory = %lu\n", tinfo.ulTotalPublicMemory);
00384       PR_fprintf(PR_STDOUT, "        ulFreePublicMemory = %lu\n", tinfo.ulFreePublicMemory);
00385       PR_fprintf(PR_STDOUT, "        ulTotalPrivateMemory = %lu\n", tinfo.ulTotalPrivateMemory);
00386       PR_fprintf(PR_STDOUT, "        ulFreePrivateMemory = %lu\n", tinfo.ulFreePrivateMemory);
00387       PR_fprintf(PR_STDOUT, "        hardwareVersion = %lu.%02lu\n", 
00388                  (PRUint32)tinfo.hardwareVersion.major, (PRUint32)tinfo.hardwareVersion.minor);
00389       PR_fprintf(PR_STDOUT, "        firmwareVersion = %lu.%02lu\n",
00390                  (PRUint32)tinfo.firmwareVersion.major, (PRUint32)tinfo.firmwareVersion.minor);
00391       PR_fprintf(PR_STDOUT, "        utcTime = \"%.16s\"\n", tinfo.utcTime);
00392 
00393 
00394       ck_rv = epv->C_GetMechanismList(pSlots[i], (CK_MECHANISM_TYPE_PTR)CK_NULL_PTR, &nMechanisms);
00395       switch( ck_rv ) {
00396       case CKR_BUFFER_TOO_SMALL:
00397       case CKR_OK:
00398         break;
00399       default:
00400         PR_fprintf(PR_STDERR, "C_GetMechanismList(%lu, NULL, ) returned 0x%08x\n", pSlots[i], ck_rv);
00401         return 1;
00402       }
00403 
00404       PR_fprintf(PR_STDOUT, "    %lu mechanisms:\n", nMechanisms);
00405 
00406       pMechanismList = (CK_MECHANISM_TYPE_PTR)PR_Calloc(nMechanisms, sizeof(CK_MECHANISM_TYPE));
00407       if( (CK_MECHANISM_TYPE_PTR)NULL == pMechanismList ) {
00408         PR_fprintf(PR_STDERR, "[memory allocation of %lu bytes failed]\n", 
00409                    nMechanisms * sizeof(CK_MECHANISM_TYPE));
00410         return 1;
00411       }
00412 
00413       ck_rv = epv->C_GetMechanismList(pSlots[i], pMechanismList, &nMechanisms);
00414       if( CKR_OK != ck_rv ) {
00415         PR_fprintf(PR_STDERR, "C_GetMechanismList(%lu, , ) returned 0x%08x\n", pSlots[i], ck_rv);
00416         return 1;
00417       }
00418 
00419       for( j = 0; j < nMechanisms; j++ ) {
00420         PR_fprintf(PR_STDOUT, "        {%lu}: CK_MECHANISM_TYPE = %lu\n", (j+1), pMechanismList[j]);
00421       }
00422 
00423       PR_fprintf(PR_STDOUT, "\n");
00424 
00425       for( j = 0; j < nMechanisms; j++ ) {
00426         CK_MECHANISM_INFO minfo;
00427 
00428         (void)memset(&minfo, 0, sizeof(CK_MECHANISM_INFO));
00429         ck_rv = epv->C_GetMechanismInfo(pSlots[i], pMechanismList[j], &minfo);
00430         if( CKR_OK != ck_rv ) {
00431           PR_fprintf(PR_STDERR, "C_GetMechanismInfo(%lu, %lu, ) returned 0x%08x\n", pSlots[i], 
00432                      pMechanismList[j]);
00433           return 1;
00434         }
00435 
00436         PR_fprintf(PR_STDOUT, "    [%lu]: CK_MECHANISM_TYPE = %lu\n", (j+1), pMechanismList[j]);
00437         PR_fprintf(PR_STDOUT, "    ulMinKeySize = %lu\n", minfo.ulMinKeySize);
00438         PR_fprintf(PR_STDOUT, "    ulMaxKeySize = %lu\n", minfo.ulMaxKeySize);
00439         PR_fprintf(PR_STDOUT, "    flags = 0x%08x\n", minfo.flags);
00440         PR_fprintf(PR_STDOUT, "        -> HW = %s\n", minfo.flags & CKF_HW ? "TRUE" : "FALSE");
00441         PR_fprintf(PR_STDOUT, "        -> ENCRYPT = %s\n", minfo.flags & CKF_ENCRYPT ? "TRUE" : "FALSE");
00442         PR_fprintf(PR_STDOUT, "        -> DECRYPT = %s\n", minfo.flags & CKF_DECRYPT ? "TRUE" : "FALSE");
00443         PR_fprintf(PR_STDOUT, "        -> DIGEST = %s\n", minfo.flags & CKF_DIGEST ? "TRUE" : "FALSE");
00444         PR_fprintf(PR_STDOUT, "        -> SIGN = %s\n", minfo.flags & CKF_SIGN ? "TRUE" : "FALSE");
00445         PR_fprintf(PR_STDOUT, "        -> SIGN_RECOVER = %s\n", minfo.flags & CKF_SIGN_RECOVER ? "TRUE" : "FALSE");
00446         PR_fprintf(PR_STDOUT, "        -> VERIFY = %s\n", minfo.flags & CKF_VERIFY ? "TRUE" : "FALSE");
00447         PR_fprintf(PR_STDOUT, "        -> VERIFY_RECOVER = %s\n", minfo.flags & CKF_VERIFY_RECOVER ? "TRUE" : "FALSE");
00448         PR_fprintf(PR_STDOUT, "        -> GENERATE = %s\n", minfo.flags & CKF_GENERATE ? "TRUE" : "FALSE");
00449         PR_fprintf(PR_STDOUT, "        -> GENERATE_KEY_PAIR = %s\n", minfo.flags & CKF_GENERATE_KEY_PAIR ? "TRUE" : "FALSE");
00450         PR_fprintf(PR_STDOUT, "        -> WRAP = %s\n", minfo.flags & CKF_WRAP ? "TRUE" : "FALSE");
00451         PR_fprintf(PR_STDOUT, "        -> UNWRAP = %s\n", minfo.flags & CKF_UNWRAP ? "TRUE" : "FALSE");
00452         PR_fprintf(PR_STDOUT, "        -> DERIVE = %s\n", minfo.flags & CKF_DERIVE ? "TRUE" : "FALSE");
00453         PR_fprintf(PR_STDOUT, "        -> EXTENSION = %s\n", minfo.flags & CKF_EXTENSION ? "TRUE" : "FALSE");
00454 
00455         PR_fprintf(PR_STDOUT, "\n");
00456       }
00457 
00458       if( tinfo.flags & CKF_LOGIN_REQUIRED ) {
00459         PR_fprintf(PR_STDERR, "*** LOGIN REQUIRED but not yet implemented ***\n");
00460         /* all the stuff about logging in as SO and setting the user pin if needed, etc. */
00461         return 2;
00462       }
00463 
00464       /* session to find objects */
00465       {
00466         CK_SESSION_HANDLE h = (CK_SESSION_HANDLE)0;
00467         CK_SESSION_INFO sinfo;
00468         CK_ATTRIBUTE_PTR pTemplate;
00469         CK_ULONG tnObjects = 0;
00470 
00471         ck_rv = epv->C_OpenSession(pSlots[i], CKF_SERIAL_SESSION, (CK_VOID_PTR)CK_NULL_PTR, (CK_NOTIFY)CK_NULL_PTR, &h);
00472         if( CKR_OK != ck_rv ) {
00473           PR_fprintf(PR_STDERR, "C_OpenSession(%lu, CKF_SERIAL_SESSION, , ) returned 0x%08x\n", pSlots[i], ck_rv);
00474           return 1;
00475         }
00476 
00477         PR_fprintf(PR_STDOUT, "    Opened a session: handle = 0x%08x\n", h);
00478 
00479         (void)memset(&sinfo, 0, sizeof(CK_SESSION_INFO));
00480         ck_rv = epv->C_GetSessionInfo(h, &sinfo);
00481         if( CKR_OK != ck_rv ) {
00482           PR_fprintf(PR_STDOUT, "C_GetSessionInfo(%lu, ) returned 0x%08x\n", h, ck_rv);
00483           return 1;
00484         }
00485 
00486         PR_fprintf(PR_STDOUT, "    SESSION INFO:\n");
00487         PR_fprintf(PR_STDOUT, "        slotID = %lu\n", sinfo.slotID);
00488         PR_fprintf(PR_STDOUT, "        state = %lu\n", sinfo.state);
00489         PR_fprintf(PR_STDOUT, "        flags = 0x%08x\n", sinfo.flags);
00490 #ifdef CKF_EXCLUSIVE_SESSION
00491         PR_fprintf(PR_STDOUT, "            -> EXCLUSIVE SESSION = %s\n", sinfo.flags & CKF_EXCLUSIVE_SESSION ? "TRUE" : "FALSE");
00492 #endif /* CKF_EXCLUSIVE_SESSION */
00493         PR_fprintf(PR_STDOUT, "            -> RW SESSION = %s\n", sinfo.flags & CKF_RW_SESSION ? "TRUE" : "FALSE");
00494         PR_fprintf(PR_STDOUT, "            -> SERIAL SESSION = %s\n", sinfo.flags & CKF_SERIAL_SESSION ? "TRUE" : "FALSE");
00495 #ifdef CKF_INSERTION_CALLBACK
00496         PR_fprintf(PR_STDOUT, "            -> INSERTION CALLBACK = %s\n", sinfo.flags & CKF_INSERTION_CALLBACK ? "TRUE" : "FALSE");
00497 #endif /* CKF_INSERTION_CALLBACK */
00498         PR_fprintf(PR_STDOUT, "        ulDeviceError = %lu\n", sinfo.ulDeviceError);
00499         PR_fprintf(PR_STDOUT, "\n");
00500 
00501         ck_rv = epv->C_FindObjectsInit(h, (CK_ATTRIBUTE_PTR)CK_NULL_PTR, 0);
00502         if( CKR_OK != ck_rv ) {
00503           PR_fprintf(PR_STDOUT, "C_FindObjectsInit(%lu, NULL_PTR, 0) returned 0x%08x\n", h, ck_rv);
00504           return 1;
00505         }
00506 
00507         pTemplate = (CK_ATTRIBUTE_PTR)PR_Calloc(number_of_all_known_attribute_types, sizeof(CK_ATTRIBUTE));
00508         if( (CK_ATTRIBUTE_PTR)NULL == pTemplate ) {
00509           PR_fprintf(PR_STDERR, "[memory allocation of %lu bytes failed]\n", 
00510                      number_of_all_known_attribute_types * sizeof(CK_ATTRIBUTE));
00511           return 1;
00512         }
00513 
00514         PR_fprintf(PR_STDOUT, "    All objects:\n");
00515 
00516         while(1) {
00517           CK_OBJECT_HANDLE o = (CK_OBJECT_HANDLE)0;
00518           CK_ULONG nObjects = 0;
00519           CK_ULONG k;
00520           CK_ULONG nAttributes = 0;
00521           CK_ATTRIBUTE_PTR pT2;
00522           CK_ULONG l;
00523 
00524           ck_rv = epv->C_FindObjects(h, &o, 1, &nObjects);
00525           if( CKR_OK != ck_rv ) {
00526             PR_fprintf(PR_STDERR, "C_FindObjects(%lu, , 1, ) returned 0x%08x\n", h, ck_rv);
00527             return 1;
00528           }
00529 
00530           if( 0 == nObjects ) {
00531             PR_fprintf(PR_STDOUT, "\n");
00532             break;
00533           }
00534 
00535           tnObjects++;
00536 
00537           PR_fprintf(PR_STDOUT, "        OBJECT HANDLE %lu:\n", o);
00538 
00539           for( k = 0; k < number_of_all_known_attribute_types; k++ ) {
00540             pTemplate[k].type = all_known_attribute_types[k];
00541             pTemplate[k].pValue = (CK_VOID_PTR)CK_NULL_PTR;
00542             pTemplate[k].ulValueLen = 0;
00543           }
00544 
00545           ck_rv = epv->C_GetAttributeValue(h, o, pTemplate, number_of_all_known_attribute_types);
00546           switch( ck_rv ) {
00547           case CKR_OK:
00548           case CKR_ATTRIBUTE_SENSITIVE:
00549           case CKR_ATTRIBUTE_TYPE_INVALID:
00550           case CKR_BUFFER_TOO_SMALL:
00551             break;
00552           default:
00553             PR_fprintf(PR_STDERR, "C_GetAtributeValue(%lu, %lu, {all attribute types}, %lu) returned 0x%08x\n",
00554                        h, o, number_of_all_known_attribute_types, ck_rv);
00555             return 1;
00556           }
00557 
00558           for( k = 0; k < number_of_all_known_attribute_types; k++ ) {
00559             if( -1 != (CK_LONG)pTemplate[k].ulValueLen ) {
00560               nAttributes++;
00561             }
00562           }
00563 
00564           if( 1 ) {
00565             PR_fprintf(PR_STDOUT, "            %lu attributes:\n", nAttributes);
00566             for( k = 0; k < number_of_all_known_attribute_types; k++ ) {
00567               if( -1 != (CK_LONG)pTemplate[k].ulValueLen ) {
00568                 PR_fprintf(PR_STDOUT, "                0x%08x (len = %lu)\n", pTemplate[k].type, 
00569                            pTemplate[k].ulValueLen);
00570               }
00571             }
00572             PR_fprintf(PR_STDOUT, "\n");
00573           }
00574 
00575           pT2 = (CK_ATTRIBUTE_PTR)PR_Calloc(nAttributes, sizeof(CK_ATTRIBUTE));
00576           if( (CK_ATTRIBUTE_PTR)NULL == pT2 ) {
00577             PR_fprintf(PR_STDERR, "[memory allocation of %lu bytes failed]\n", 
00578                        nAttributes * sizeof(CK_ATTRIBUTE));
00579             return 1;
00580           }
00581 
00582           for( l = 0, k = 0; k < number_of_all_known_attribute_types; k++ ) {
00583             if( -1 != (CK_LONG)pTemplate[k].ulValueLen ) {
00584               pT2[l].type = pTemplate[k].type;
00585               pT2[l].ulValueLen = pTemplate[k].ulValueLen;
00586               pT2[l].pValue = (CK_VOID_PTR)PR_Malloc(pT2[l].ulValueLen);
00587               if( (CK_VOID_PTR)NULL == pT2[l].pValue ) {
00588                 PR_fprintf(PR_STDERR, "[memory allocation of %lu bytes failed]\n", pT2[l].ulValueLen);
00589                 return 1;
00590               }
00591               l++;
00592             }
00593           }
00594 
00595           PR_ASSERT( l == nAttributes );
00596 
00597           ck_rv = epv->C_GetAttributeValue(h, o, pT2, nAttributes);
00598           switch( ck_rv ) {
00599           case CKR_OK:
00600           case CKR_ATTRIBUTE_SENSITIVE:
00601           case CKR_ATTRIBUTE_TYPE_INVALID:
00602           case CKR_BUFFER_TOO_SMALL:
00603             break;
00604           default:
00605             PR_fprintf(PR_STDERR, "C_GetAtributeValue(%lu, %lu, {existant attribute types}, %lu) returned 0x%08x\n",
00606                        h, o, nAttributes, ck_rv);
00607             return 1;
00608           }
00609 
00610           for( l = 0; l < nAttributes; l++ ) {
00611             PR_fprintf(PR_STDOUT, "            type = 0x%08x, len = %ld", pT2[l].type, (CK_LONG)pT2[l].ulValueLen);
00612             if( -1 == (CK_LONG)pT2[l].ulValueLen ) {
00613               ;
00614             } else {
00615               CK_ULONG m;
00616 
00617               if( pT2[l].ulValueLen <= 8 ) {
00618                 PR_fprintf(PR_STDOUT, ", value = ");
00619               } else {
00620                 PR_fprintf(PR_STDOUT, ", value = \n                ");
00621               }
00622 
00623               for( m = 0; (m < pT2[l].ulValueLen) && (m < 20); m++ ) {
00624                 PR_fprintf(PR_STDOUT, "%02x", (CK_ULONG)(0xff & ((CK_CHAR_PTR)pT2[l].pValue)[m]));
00625               }
00626 
00627               PR_fprintf(PR_STDOUT, " ");
00628 
00629               for( m = 0; (m < pT2[l].ulValueLen) && (m < 20); m++ ) {
00630                 CK_CHAR c = ((CK_CHAR_PTR)pT2[l].pValue)[m];
00631                 if( (c < 0x20) || (c >= 0x7f) ) {
00632                   c = '.';
00633                 }
00634                 PR_fprintf(PR_STDOUT, "%c", c);
00635               }
00636             }
00637 
00638             PR_fprintf(PR_STDOUT, "\n");
00639           }
00640           
00641           PR_fprintf(PR_STDOUT, "\n");
00642 
00643           for( l = 0; l < nAttributes; l++ ) {
00644             PR_Free(pT2[l].pValue);
00645           }
00646           PR_Free(pT2);
00647         } /* while(1) */
00648 
00649         ck_rv = epv->C_FindObjectsFinal(h);
00650         if( CKR_OK != ck_rv ) {
00651           PR_fprintf(PR_STDERR, "C_FindObjectsFinal(%lu) returned 0x%08x\n", h, ck_rv);
00652           return 1;
00653         }
00654 
00655         PR_fprintf(PR_STDOUT, "    (%lu objects total)\n", tnObjects);
00656 
00657         ck_rv = epv->C_CloseSession(h);
00658         if( CKR_OK != ck_rv ) {
00659           PR_fprintf(PR_STDERR, "C_CloseSession(%lu) returned 0x%08x\n", h, ck_rv);
00660           return 1;
00661         }
00662       } /* session to find objects */
00663 
00664       /* session to create, find, and delete a couple session objects */
00665       {
00666         CK_SESSION_HANDLE h = (CK_SESSION_HANDLE)0;
00667         CK_ATTRIBUTE one[7], two[7], three[7], delta[1], mask[1];
00668         CK_OBJECT_CLASS cko_data = CKO_DATA;
00669         CK_BBOOL false = CK_FALSE, true = CK_TRUE;
00670         char *key = "TEST PROGRAM";
00671         CK_ULONG key_len = strlen(key);
00672         CK_OBJECT_HANDLE hOneIn = (CK_OBJECT_HANDLE)0, hTwoIn = (CK_OBJECT_HANDLE)0, 
00673           hThreeIn = (CK_OBJECT_HANDLE)0, hDeltaIn = (CK_OBJECT_HANDLE)0;
00674         CK_OBJECT_HANDLE found[10];
00675         CK_ULONG nFound;
00676 
00677         ck_rv = epv->C_OpenSession(pSlots[i], CKF_SERIAL_SESSION, (CK_VOID_PTR)CK_NULL_PTR, (CK_NOTIFY)CK_NULL_PTR, &h);
00678         if( CKR_OK != ck_rv ) {
00679           PR_fprintf(PR_STDERR, "C_OpenSession(%lu, CKF_SERIAL_SESSION, , ) returned 0x%08x\n", pSlots[i], ck_rv);
00680           return 1;
00681         }
00682 
00683         PR_fprintf(PR_STDOUT, "    Opened a session: handle = 0x%08x\n", h);
00684 
00685         one[0].type = CKA_CLASS;
00686         one[0].pValue = &cko_data;
00687         one[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
00688         one[1].type = CKA_TOKEN;
00689         one[1].pValue = &false;
00690         one[1].ulValueLen = sizeof(CK_BBOOL);
00691         one[2].type = CKA_PRIVATE;
00692         one[2].pValue = &false;
00693         one[2].ulValueLen = sizeof(CK_BBOOL);
00694         one[3].type = CKA_MODIFIABLE;
00695         one[3].pValue = &true;
00696         one[3].ulValueLen = sizeof(CK_BBOOL);
00697         one[4].type = CKA_LABEL;
00698         one[4].pValue = "Test data object one";
00699         one[4].ulValueLen = strlen(one[4].pValue);
00700         one[5].type = CKA_APPLICATION;
00701         one[5].pValue = key;
00702         one[5].ulValueLen = key_len;
00703         one[6].type = CKA_VALUE;
00704         one[6].pValue = "Object one";
00705         one[6].ulValueLen = strlen(one[6].pValue);
00706 
00707         two[0].type = CKA_CLASS;
00708         two[0].pValue = &cko_data;
00709         two[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
00710         two[1].type = CKA_TOKEN;
00711         two[1].pValue = &false;
00712         two[1].ulValueLen = sizeof(CK_BBOOL);
00713         two[2].type = CKA_PRIVATE;
00714         two[2].pValue = &false;
00715         two[2].ulValueLen = sizeof(CK_BBOOL);
00716         two[3].type = CKA_MODIFIABLE;
00717         two[3].pValue = &true;
00718         two[3].ulValueLen = sizeof(CK_BBOOL);
00719         two[4].type = CKA_LABEL;
00720         two[4].pValue = "Test data object two";
00721         two[4].ulValueLen = strlen(two[4].pValue);
00722         two[5].type = CKA_APPLICATION;
00723         two[5].pValue = key;
00724         two[5].ulValueLen = key_len;
00725         two[6].type = CKA_VALUE;
00726         two[6].pValue = "Object two";
00727         two[6].ulValueLen = strlen(two[6].pValue);
00728 
00729         three[0].type = CKA_CLASS;
00730         three[0].pValue = &cko_data;
00731         three[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
00732         three[1].type = CKA_TOKEN;
00733         three[1].pValue = &false;
00734         three[1].ulValueLen = sizeof(CK_BBOOL);
00735         three[2].type = CKA_PRIVATE;
00736         three[2].pValue = &false;
00737         three[2].ulValueLen = sizeof(CK_BBOOL);
00738         three[3].type = CKA_MODIFIABLE;
00739         three[3].pValue = &true;
00740         three[3].ulValueLen = sizeof(CK_BBOOL);
00741         three[4].type = CKA_LABEL;
00742         three[4].pValue = "Test data object three";
00743         three[4].ulValueLen = strlen(three[4].pValue);
00744         three[5].type = CKA_APPLICATION;
00745         three[5].pValue = key;
00746         three[5].ulValueLen = key_len;
00747         three[6].type = CKA_VALUE;
00748         three[6].pValue = "Object three";
00749         three[6].ulValueLen = strlen(three[6].pValue);
00750 
00751         ck_rv = epv->C_CreateObject(h, one, 7, &hOneIn);
00752         if( CKR_OK != ck_rv ) {
00753           PR_fprintf(PR_STDERR, "C_CreateObject(%lu, one, 7, ) returned 0x%08x\n", h, ck_rv);
00754           return 1;
00755         }
00756 
00757         PR_fprintf(PR_STDOUT, "    Created object one: handle = %lu\n", hOneIn);
00758 
00759         ck_rv = epv->C_CreateObject(h, two, 7, &hTwoIn);
00760         if( CKR_OK != ck_rv ) {
00761           PR_fprintf(PR_STDERR, "C_CreateObject(%lu, two, 7, ) returned 0x%08x\n", h, ck_rv);
00762           return 1;
00763         }
00764 
00765         PR_fprintf(PR_STDOUT, "    Created object two: handle = %lu\n", hTwoIn);
00766 
00767         ck_rv = epv->C_CreateObject(h, three, 7, &hThreeIn);
00768         if( CKR_OK != ck_rv ) {
00769           PR_fprintf(PR_STDERR, "C_CreateObject(%lu, three, 7, ) returned 0x%08x\n", h, ck_rv);
00770           return 1;
00771         }
00772 
00773         PR_fprintf(PR_STDOUT, "    Created object three: handle = %lu\n", hThreeIn);
00774 
00775         delta[0].type = CKA_VALUE;
00776         delta[0].pValue = "Copied object";
00777         delta[0].ulValueLen = strlen(delta[0].pValue);
00778 
00779         ck_rv = epv->C_CopyObject(h, hThreeIn, delta, 1, &hDeltaIn);
00780         if( CKR_OK != ck_rv ) {
00781           PR_fprintf(PR_STDERR, "C_CopyObject(%lu, %lu, delta, 1, ) returned 0x%08x\n", 
00782                      h, hThreeIn, ck_rv);
00783           return 1;
00784         }
00785 
00786         PR_fprintf(PR_STDOUT, "    Copied object three: new handle = %lu\n", hDeltaIn);
00787 
00788         mask[0].type = CKA_APPLICATION;
00789         mask[0].pValue = key;
00790         mask[0].ulValueLen = key_len;
00791 
00792         ck_rv = epv->C_FindObjectsInit(h, mask, 1);
00793         if( CKR_OK != ck_rv ) {
00794           PR_fprintf(PR_STDERR, "C_FindObjectsInit(%lu, mask, 1) returned 0x%08x\n", 
00795                      h, ck_rv);
00796           return 1;
00797         }
00798 
00799         (void)memset(&found, 0, sizeof(found));
00800         nFound = 0;
00801         ck_rv = epv->C_FindObjects(h, found, 10, &nFound);
00802         if( CKR_OK != ck_rv ) {
00803           PR_fprintf(PR_STDERR, "C_FindObjects(%lu,, 10, ) returned 0x%08x\n", 
00804                      h, ck_rv);
00805           return 1;
00806         }
00807 
00808         if( 4 != nFound ) {
00809           PR_fprintf(PR_STDERR, "Found %lu objects, not 4.\n", nFound);
00810           return 1;
00811         }
00812 
00813         PR_fprintf(PR_STDOUT, "    Found 4 objects: %lu, %lu, %lu, %lu\n", 
00814                    found[0], found[1], found[2], found[3]);
00815 
00816         ck_rv = epv->C_FindObjectsFinal(h);
00817         if( CKR_OK != ck_rv ) {
00818           PR_fprintf(PR_STDERR, "C_FindObjectsFinal(%lu) returned 0x%08x\n", h, ck_rv);
00819           return 1;
00820         }
00821 
00822         ck_rv = epv->C_DestroyObject(h, hThreeIn);
00823         if( CKR_OK != ck_rv ) {
00824           PR_fprintf(PR_STDERR, "C_DestroyObject(%lu, %lu) returned 0x%08x\n", h, hThreeIn, ck_rv);
00825           return 1;
00826         }
00827 
00828         PR_fprintf(PR_STDOUT, "    Destroyed object three (handle = %lu)\n", hThreeIn);
00829 
00830         delta[0].type = CKA_APPLICATION;
00831         delta[0].pValue = "Changed application";
00832         delta[0].ulValueLen = strlen(delta[0].pValue);
00833 
00834         ck_rv = epv->C_SetAttributeValue(h, hTwoIn, delta, 1);
00835         if( CKR_OK != ck_rv ) {
00836           PR_fprintf(PR_STDERR, "C_SetAttributeValue(%lu, %lu, delta, 1) returned 0x%08x\n", 
00837                      h, hTwoIn, ck_rv);
00838           return 1;
00839         }
00840 
00841         PR_fprintf(PR_STDOUT, "    Changed object two (handle = %lu).\n", hTwoIn);
00842 
00843         /* Can another session find these session objects? */
00844         {
00845           CK_SESSION_HANDLE h2 = (CK_SESSION_HANDLE)0;
00846 
00847           ck_rv = epv->C_OpenSession(pSlots[i], CKF_SERIAL_SESSION, (CK_VOID_PTR)CK_NULL_PTR, (CK_NOTIFY)CK_NULL_PTR, &h2);
00848           if( CKR_OK != ck_rv ) {
00849             PR_fprintf(PR_STDERR, "C_OpenSession(%lu, CKF_SERIAL_SESSION, , ) returned 0x%08x\n", pSlots[i], ck_rv);
00850             return 1;
00851           }
00852 
00853           PR_fprintf(PR_STDOUT, "    Opened a second session: handle = 0x%08x\n", h2);
00854 
00855           /* mask is still the same */
00856 
00857           ck_rv = epv->C_FindObjectsInit(h2, mask, 1);
00858           if( CKR_OK != ck_rv ) {
00859             PR_fprintf(PR_STDERR, "C_FindObjectsInit(%lu, mask, 1) returned 0x%08x\n", 
00860                        h2, ck_rv);
00861             return 1;
00862           }
00863 
00864           (void)memset(&found, 0, sizeof(found));
00865           nFound = 0;
00866           ck_rv = epv->C_FindObjects(h2, found, 10, &nFound);
00867           if( CKR_OK != ck_rv ) {
00868             PR_fprintf(PR_STDERR, "C_FindObjects(%lu,, 10, ) returned 0x%08x\n", 
00869                        h2, ck_rv);
00870             return 1;
00871           }
00872 
00873           if( 2 != nFound ) {
00874             PR_fprintf(PR_STDERR, "Found %lu objects, not 2.\n", nFound);
00875             return 1;
00876           }
00877 
00878           PR_fprintf(PR_STDOUT, "    Found 2 objects: %lu, %lu\n", 
00879                      found[0], found[1]);
00880 
00881           ck_rv = epv->C_FindObjectsFinal(h2);
00882           if( CKR_OK != ck_rv ) {
00883             PR_fprintf(PR_STDERR, "C_FindObjectsFinal(%lu) returned 0x%08x\n", h2, ck_rv);
00884             return 1;
00885           }
00886 
00887           /* Leave the session hanging open, we'll CloseAllSessions later */
00888         } /* Can another session find these session objects? */
00889 
00890         ck_rv = epv->C_CloseAllSessions(pSlots[i]);
00891         if( CKR_OK != ck_rv ) {
00892           PR_fprintf(PR_STDERR, "C_CloseAllSessions(%lu) returned 0x%08x\n", pSlots[i], ck_rv);
00893           return 1;
00894         }
00895       } /* session to create, find, and delete a couple session objects */
00896 
00897       /* Might be interesting to do a find here to verify that all session objects are gone. */
00898 
00899       if( tinfo.flags & CKF_WRITE_PROTECTED ) {
00900         PR_fprintf(PR_STDOUT, "Token is write protected, skipping token-object tests.\n");
00901       } else {
00902         CK_SESSION_HANDLE h = (CK_SESSION_HANDLE)0;
00903         CK_ATTRIBUTE tobj[7], tsobj[7], stobj[7], delta[1], mask[2];
00904         CK_OBJECT_CLASS cko_data = CKO_DATA;
00905         CK_BBOOL false = CK_FALSE, true = CK_TRUE;
00906         char *key = "TEST PROGRAM";
00907         CK_ULONG key_len = strlen(key);
00908         CK_OBJECT_HANDLE hTIn = (CK_OBJECT_HANDLE)0, hTSIn = (CK_OBJECT_HANDLE)0, 
00909           hSTIn = (CK_OBJECT_HANDLE)0, hDeltaIn = (CK_OBJECT_HANDLE)0;
00910         CK_OBJECT_HANDLE found[10];
00911         CK_ULONG nFound;
00912 
00913         ck_rv = epv->C_OpenSession(pSlots[i], CKF_SERIAL_SESSION, (CK_VOID_PTR)CK_NULL_PTR, (CK_NOTIFY)CK_NULL_PTR, &h);
00914         if( CKR_OK != ck_rv ) {
00915           PR_fprintf(PR_STDERR, "C_OpenSession(%lu, CKF_SERIAL_SESSION, , ) returned 0x%08x\n", pSlots[i], ck_rv);
00916           return 1;
00917         }
00918 
00919         PR_fprintf(PR_STDOUT, "    Opened a session: handle = 0x%08x\n", h);
00920 
00921         tobj[0].type = CKA_CLASS;
00922         tobj[0].pValue = &cko_data;
00923         tobj[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
00924         tobj[1].type = CKA_TOKEN;
00925         tobj[1].pValue = &true;
00926         tobj[1].ulValueLen = sizeof(CK_BBOOL);
00927         tobj[2].type = CKA_PRIVATE;
00928         tobj[2].pValue = &false;
00929         tobj[2].ulValueLen = sizeof(CK_BBOOL);
00930         tobj[3].type = CKA_MODIFIABLE;
00931         tobj[3].pValue = &true;
00932         tobj[3].ulValueLen = sizeof(CK_BBOOL);
00933         tobj[4].type = CKA_LABEL;
00934         tobj[4].pValue = "Test data object token";
00935         tobj[4].ulValueLen = strlen(tobj[4].pValue);
00936         tobj[5].type = CKA_APPLICATION;
00937         tobj[5].pValue = key;
00938         tobj[5].ulValueLen = key_len;
00939         tobj[6].type = CKA_VALUE;
00940         tobj[6].pValue = "Object token";
00941         tobj[6].ulValueLen = strlen(tobj[6].pValue);
00942 
00943         tsobj[0].type = CKA_CLASS;
00944         tsobj[0].pValue = &cko_data;
00945         tsobj[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
00946         tsobj[1].type = CKA_TOKEN;
00947         tsobj[1].pValue = &true;
00948         tsobj[1].ulValueLen = sizeof(CK_BBOOL);
00949         tsobj[2].type = CKA_PRIVATE;
00950         tsobj[2].pValue = &false;
00951         tsobj[2].ulValueLen = sizeof(CK_BBOOL);
00952         tsobj[3].type = CKA_MODIFIABLE;
00953         tsobj[3].pValue = &true;
00954         tsobj[3].ulValueLen = sizeof(CK_BBOOL);
00955         tsobj[4].type = CKA_LABEL;
00956         tsobj[4].pValue = "Test data object token->session";
00957         tsobj[4].ulValueLen = strlen(tsobj[4].pValue);
00958         tsobj[5].type = CKA_APPLICATION;
00959         tsobj[5].pValue = key;
00960         tsobj[5].ulValueLen = key_len;
00961         tsobj[6].type = CKA_VALUE;
00962         tsobj[6].pValue = "Object token->session";
00963         tsobj[6].ulValueLen = strlen(tsobj[6].pValue);
00964 
00965         stobj[0].type = CKA_CLASS;
00966         stobj[0].pValue = &cko_data;
00967         stobj[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
00968         stobj[1].type = CKA_TOKEN;
00969         stobj[1].pValue = &false;
00970         stobj[1].ulValueLen = sizeof(CK_BBOOL);
00971         stobj[2].type = CKA_PRIVATE;
00972         stobj[2].pValue = &false;
00973         stobj[2].ulValueLen = sizeof(CK_BBOOL);
00974         stobj[3].type = CKA_MODIFIABLE;
00975         stobj[3].pValue = &true;
00976         stobj[3].ulValueLen = sizeof(CK_BBOOL);
00977         stobj[4].type = CKA_LABEL;
00978         stobj[4].pValue = "Test data object session->token";
00979         stobj[4].ulValueLen = strlen(stobj[4].pValue);
00980         stobj[5].type = CKA_APPLICATION;
00981         stobj[5].pValue = key;
00982         stobj[5].ulValueLen = key_len;
00983         stobj[6].type = CKA_VALUE;
00984         stobj[6].pValue = "Object session->token";
00985         stobj[6].ulValueLen = strlen(stobj[6].pValue);
00986 
00987         ck_rv = epv->C_CreateObject(h, tobj, 7, &hTIn);
00988         if( CKR_OK != ck_rv ) {
00989           PR_fprintf(PR_STDERR, "C_CreateObject(%lu, tobj, 7, ) returned 0x%08x\n", h, ck_rv);
00990           return 1;
00991         }
00992 
00993         PR_fprintf(PR_STDOUT, "    Created object token: handle = %lu\n", hTIn);
00994 
00995         ck_rv = epv->C_CreateObject(h, tsobj, 7, &hTSIn);
00996         if( CKR_OK != ck_rv ) {
00997           PR_fprintf(PR_STDERR, "C_CreateObject(%lu, tobj, 7, ) returned 0x%08x\n", h, ck_rv);
00998           return 1;
00999         }
01000 
01001         PR_fprintf(PR_STDOUT, "    Created object token->session: handle = %lu\n", hTSIn);
01002         ck_rv = epv->C_CreateObject(h, stobj, 7, &hSTIn);
01003         if( CKR_OK != ck_rv ) {
01004           PR_fprintf(PR_STDERR, "C_CreateObject(%lu, tobj, 7, ) returned 0x%08x\n", h, ck_rv);
01005           return 1;
01006         }
01007 
01008         PR_fprintf(PR_STDOUT, "    Created object session->token: handle = %lu\n", hSTIn);
01009 
01010         /* I've created two token objects and one session object; find the two */
01011 
01012         mask[0].type = CKA_APPLICATION;
01013         mask[0].pValue = key;
01014         mask[0].ulValueLen = key_len;
01015         mask[1].type = CKA_TOKEN;
01016         mask[1].pValue = &true;
01017         mask[1].ulValueLen = sizeof(CK_BBOOL);
01018 
01019         ck_rv = epv->C_FindObjectsInit(h, mask, 2);
01020         if( CKR_OK != ck_rv ) {
01021           PR_fprintf(PR_STDERR, "C_FindObjectsInit(%lu, mask, 2) returned 0x%08x\n", 
01022                      h, ck_rv);
01023           return 1;
01024         }
01025 
01026         (void)memset(&found, 0, sizeof(found));
01027         nFound = 0;
01028         ck_rv = epv->C_FindObjects(h, found, 10, &nFound);
01029         if( CKR_OK != ck_rv ) {
01030           PR_fprintf(PR_STDERR, "C_FindObjects(%lu,, 10, ) returned 0x%08x\n", 
01031                      h, ck_rv);
01032           return 1;
01033         }
01034 
01035         if( 2 != nFound ) {
01036           PR_fprintf(PR_STDERR, "Found %lu objects, not 2.\n", nFound);
01037           return 1;
01038         }
01039 
01040         PR_fprintf(PR_STDOUT, "    Found 2 objects: %lu, %lu\n", 
01041                    found[0], found[1]);
01042 
01043         ck_rv = epv->C_FindObjectsFinal(h);
01044         if( CKR_OK != ck_rv ) {
01045           PR_fprintf(PR_STDERR, "C_FindObjectsFinal(%lu) returned 0x%08x\n", h, ck_rv);
01046           return 1;
01047         }
01048 
01049         /* Convert a token to session object */
01050 
01051         delta[0].type = CKA_TOKEN;
01052         delta[0].pValue = &false;
01053         delta[0].ulValueLen = sizeof(CK_BBOOL);
01054 
01055         ck_rv = epv->C_SetAttributeValue(h, hTSIn, delta, 1);
01056         if( CKR_OK != ck_rv ) {
01057           PR_fprintf(PR_STDERR, "C_SetAttributeValue(%lu, %lu, delta, 1) returned 0x%08x\n", 
01058                      h, hTSIn, ck_rv);
01059           return 1;
01060         }
01061 
01062         PR_fprintf(PR_STDOUT, "    Changed object from token to session (handle = %lu).\n", hTSIn);
01063 
01064         /* Now find again; there should be one */
01065 
01066         mask[0].type = CKA_APPLICATION;
01067         mask[0].pValue = key;
01068         mask[0].ulValueLen = key_len;
01069         mask[1].type = CKA_TOKEN;
01070         mask[1].pValue = &true;
01071         mask[1].ulValueLen = sizeof(CK_BBOOL);
01072 
01073         ck_rv = epv->C_FindObjectsInit(h, mask, 2);
01074         if( CKR_OK != ck_rv ) {
01075           PR_fprintf(PR_STDERR, "C_FindObjectsInit(%lu, mask, 2) returned 0x%08x\n", 
01076                      h, ck_rv);
01077           return 1;
01078         }
01079 
01080         (void)memset(&found, 0, sizeof(found));
01081         nFound = 0;
01082         ck_rv = epv->C_FindObjects(h, found, 10, &nFound);
01083         if( CKR_OK != ck_rv ) {
01084           PR_fprintf(PR_STDERR, "C_FindObjects(%lu,, 10, ) returned 0x%08x\n", 
01085                      h, ck_rv);
01086           return 1;
01087         }
01088 
01089         if( 1 != nFound ) {
01090           PR_fprintf(PR_STDERR, "Found %lu objects, not 1.\n", nFound);
01091           return 1;
01092         }
01093 
01094         PR_fprintf(PR_STDOUT, "    Found 1 objects: %lu\n", 
01095                    found[0]);
01096 
01097         ck_rv = epv->C_FindObjectsFinal(h);
01098         if( CKR_OK != ck_rv ) {
01099           PR_fprintf(PR_STDERR, "C_FindObjectsFinal(%lu) returned 0x%08x\n", h, ck_rv);
01100           return 1;
01101         }
01102 
01103         /* Convert a session to a token object */
01104 
01105         delta[0].type = CKA_TOKEN;
01106         delta[0].pValue = &true;
01107         delta[0].ulValueLen = sizeof(CK_BBOOL);
01108 
01109         ck_rv = epv->C_SetAttributeValue(h, hSTIn, delta, 1);
01110         if( CKR_OK != ck_rv ) {
01111           PR_fprintf(PR_STDERR, "C_SetAttributeValue(%lu, %lu, delta, 1) returned 0x%08x\n", 
01112                      h, hSTIn, ck_rv);
01113           return 1;
01114         }
01115 
01116         PR_fprintf(PR_STDOUT, "    Changed object from session to token (handle = %lu).\n", hSTIn);
01117 
01118         /* Now find again; there should be two again */
01119 
01120         mask[0].type = CKA_APPLICATION;
01121         mask[0].pValue = key;
01122         mask[0].ulValueLen = key_len;
01123         mask[1].type = CKA_TOKEN;
01124         mask[1].pValue = &true;
01125         mask[1].ulValueLen = sizeof(CK_BBOOL);
01126 
01127         ck_rv = epv->C_FindObjectsInit(h, mask, 2);
01128         if( CKR_OK != ck_rv ) {
01129           PR_fprintf(PR_STDERR, "C_FindObjectsInit(%lu, mask, 2) returned 0x%08x\n", 
01130                      h, ck_rv);
01131           return 1;
01132         }
01133 
01134         (void)memset(&found, 0, sizeof(found));
01135         nFound = 0;
01136         ck_rv = epv->C_FindObjects(h, found, 10, &nFound);
01137         if( CKR_OK != ck_rv ) {
01138           PR_fprintf(PR_STDERR, "C_FindObjects(%lu,, 10, ) returned 0x%08x\n", 
01139                      h, ck_rv);
01140           return 1;
01141         }
01142 
01143         if( 2 != nFound ) {
01144           PR_fprintf(PR_STDERR, "Found %lu objects, not 2.\n", nFound);
01145           return 1;
01146         }
01147 
01148         PR_fprintf(PR_STDOUT, "    Found 2 objects: %lu, %lu\n", 
01149                    found[0], found[1]);
01150 
01151         ck_rv = epv->C_FindObjectsFinal(h);
01152         if( CKR_OK != ck_rv ) {
01153           PR_fprintf(PR_STDERR, "C_FindObjectsFinal(%lu) returned 0x%08x\n", h, ck_rv);
01154           return 1;
01155         }
01156 
01157         /* Delete the two (found) token objects to clean up */
01158 
01159         ck_rv = epv->C_DestroyObject(h, found[0]);
01160         if( CKR_OK != ck_rv ) {
01161           PR_fprintf(PR_STDERR, "C_DestroyObject(%lu, %lu) returned 0x%08x\n", h, found[0], ck_rv);
01162           return 1;
01163         }
01164 
01165         PR_fprintf(PR_STDOUT, "    Destroyed token object (handle = %lu)\n", found[0]);
01166 
01167         ck_rv = epv->C_DestroyObject(h, found[1]);
01168         if( CKR_OK != ck_rv ) {
01169           PR_fprintf(PR_STDERR, "C_DestroyObject(%lu, %lu) returned 0x%08x\n", h, found[1], ck_rv);
01170           return 1;
01171         }
01172 
01173         PR_fprintf(PR_STDOUT, "    Destroyed token object (handle = %lu)\n", found[1]);
01174         
01175         /* Close the session and all objects should be gone */
01176 
01177         ck_rv = epv->C_CloseSession(h);
01178         if( CKR_OK != ck_rv ) {
01179           PR_fprintf(PR_STDERR, "C_CloseSession(%lu) returned 0x%08x\n", h, ck_rv);
01180           return 1;
01181         }
01182       } /* if( tinfo.flags & CKF_WRITE_PROTECTED ) */
01183 
01184       if( tinfo.flags & CKF_WRITE_PROTECTED ) {
01185         PR_fprintf(PR_STDOUT, "Token is write protected, skipping leaving a record.\n");
01186       } else {
01187         CK_SESSION_HANDLE h = (CK_SESSION_HANDLE)0;
01188         CK_ATTRIBUTE record[7], mask[2];
01189         CK_OBJECT_CLASS cko_data = CKO_DATA;
01190         CK_BBOOL false = CK_FALSE, true = CK_TRUE;
01191         char *key = "TEST RECORD";
01192         CK_ULONG key_len = strlen(key);
01193         CK_OBJECT_HANDLE hin = (CK_OBJECT_HANDLE)0;
01194         char timebuffer[256];
01195 
01196         ck_rv = epv->C_OpenSession(pSlots[i], CKF_SERIAL_SESSION, (CK_VOID_PTR)CK_NULL_PTR, (CK_NOTIFY)CK_NULL_PTR, &h);
01197         if( CKR_OK != ck_rv ) {
01198           PR_fprintf(PR_STDERR, "C_OpenSession(%lu, CKF_SERIAL_SESSION, , ) returned 0x%08x\n", pSlots[i], ck_rv);
01199           return 1;
01200         }
01201 
01202         PR_fprintf(PR_STDOUT, "    Opened a session: handle = 0x%08x\n", h);
01203 
01204         /* I can't believe how hard NSPR makes this operation */
01205         {
01206           time_t now = 0;
01207           struct tm *tm;
01208           time(&now);
01209           tm = localtime(&now);
01210           strftime(timebuffer, sizeof(timebuffer), "%Y-%m-%d %T %Z", tm);
01211         }
01212 
01213         record[0].type = CKA_CLASS;
01214         record[0].pValue = &cko_data;
01215         record[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
01216         record[1].type = CKA_TOKEN;
01217         record[1].pValue = &true;
01218         record[1].ulValueLen = sizeof(CK_BBOOL);
01219         record[2].type = CKA_PRIVATE;
01220         record[2].pValue = &false;
01221         record[2].ulValueLen = sizeof(CK_BBOOL);
01222         record[3].type = CKA_MODIFIABLE;
01223         record[3].pValue = &true;
01224         record[3].ulValueLen = sizeof(CK_BBOOL);
01225         record[4].type = CKA_LABEL;
01226         record[4].pValue = "Test record";
01227         record[4].ulValueLen = strlen(record[4].pValue);
01228         record[5].type = CKA_APPLICATION;
01229         record[5].pValue = key;
01230         record[5].ulValueLen = key_len;
01231         record[6].type = CKA_VALUE;
01232         record[6].pValue = timebuffer;
01233         record[6].ulValueLen = strlen(timebuffer)+1;
01234 
01235         PR_fprintf(PR_STDOUT, "    Timestamping with \"%s\"\n", timebuffer);
01236 
01237         ck_rv = epv->C_CreateObject(h, record, 7, &hin);
01238         if( CKR_OK != ck_rv ) {
01239           PR_fprintf(PR_STDERR, "C_CreateObject(%lu, tobj, 7, ) returned 0x%08x\n", h, ck_rv);
01240           return 1;
01241         }
01242 
01243         PR_fprintf(PR_STDOUT, "    Created record object: handle = %lu\n", hin);
01244         
01245         PR_fprintf(PR_STDOUT, "   == All test timestamps ==\n");
01246 
01247         mask[0].type = CKA_CLASS;
01248         mask[0].pValue = &cko_data;
01249         mask[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
01250         mask[1].type = CKA_APPLICATION;
01251         mask[1].pValue = key;
01252         mask[1].ulValueLen = key_len;
01253 
01254         ck_rv = epv->C_FindObjectsInit(h, mask, 2);
01255         if( CKR_OK != ck_rv ) {
01256           PR_fprintf(PR_STDERR, "C_FindObjectsInit(%lu, mask, 1) returned 0x%08x\n", 
01257                      h, ck_rv);
01258           return 1;
01259         }
01260 
01261         while( 1 ) {
01262           CK_OBJECT_HANDLE o = (CK_OBJECT_HANDLE)0;
01263           CK_ULONG nObjects = 0;
01264           CK_ATTRIBUTE value[1];
01265           char buffer[1024];
01266 
01267           ck_rv = epv->C_FindObjects(h, &o, 1, &nObjects);
01268           if( CKR_OK != ck_rv ) {
01269             PR_fprintf(PR_STDERR, "C_FindObjects(%lu, , 1, ) returned 0x%08x\n", h, ck_rv);
01270             return 1;
01271           }
01272 
01273           if( 0 == nObjects ) {
01274             PR_fprintf(PR_STDOUT, "\n");
01275             break;
01276           }
01277 
01278           value[0].type = CKA_VALUE;
01279           value[0].pValue = buffer;
01280           value[0].ulValueLen = sizeof(buffer);
01281 
01282           ck_rv = epv->C_GetAttributeValue(h, o, value, 1);
01283           switch( ck_rv ) {
01284           case CKR_OK:
01285             PR_fprintf(PR_STDOUT, "    %s\n", value[0].pValue);
01286             break;
01287           case CKR_ATTRIBUTE_SENSITIVE:
01288             PR_fprintf(PR_STDOUT, "    [Sensitive???]\n");
01289             break;
01290           case CKR_ATTRIBUTE_TYPE_INVALID:
01291             PR_fprintf(PR_STDOUT, "    [Invalid attribute???]\n");
01292             break;
01293           case CKR_BUFFER_TOO_SMALL:
01294             PR_fprintf(PR_STDOUT, "    (result > 1k (%lu))\n", value[0].ulValueLen);
01295             break;
01296           default:
01297             PR_fprintf(PR_STDERR, "C_GetAtributeValue(%lu, %lu, CKA_VALUE, 1) returned 0x%08x\n",
01298                        h, o);
01299             return 1;
01300           }
01301         } /* while */
01302 
01303         ck_rv = epv->C_FindObjectsFinal(h);
01304         if( CKR_OK != ck_rv ) {
01305           PR_fprintf(PR_STDERR, "C_FindObjectsFinal(%lu) returned 0x%08x\n", h, ck_rv);
01306           return 1;
01307         }
01308       } /* "leaving a record" else clause */
01309 
01310     }
01311 
01312     PR_fprintf(PR_STDOUT, "\n");
01313   }
01314 
01315   return 0;
01316 }