/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is the PKIX-C library. * * The Initial Developer of the Original Code is * Sun Microsystems, Inc. * Portions created by the Initial Developer are * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved. * * Contributor(s): * Sun Microsystems, Inc. * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ /* * libpkixBuildThreads.c * * libpkix Builder Performance Evaluation application (multi-threaded) * */ #include #include #include "secutil.h" #include "nspr.h" #include "prtypes.h" #include "prtime.h" #include "prlong.h" #include "pk11func.h" #include "secasn1.h" #include "cert.h" #include "cryptohi.h" #include "secoid.h" #include "certdb.h" #include "nss.h" #include "pkix.h" #include "pkix_tools.h" #include "pkix_pl_cert.h" #include "testutil.h" #include "testutil_nss.h" static void *plContext = NULL; #undef pkixTempResult #define PERF_DECREF(obj) \ { \ PKIX_Error *pkixTempResult = NULL; \ if (obj){ \ pkixTempResult = PKIX_PL_Object_DecRef \ ((PKIX_PL_Object *)(obj), plContext); \ obj = NULL; \ } \ } static void finish(char* message, int code); typedef struct ThreadDataStr tData; struct ThreadDataStr { CERTCertificate* anchor; char* eecertName; PRIntervalTime duration; CERTCertDBHandle *handle; PRUint32 iterations; }; #define PKIX_LOGGER_ON 1 #ifdef PKIX_LOGGER_ON char *logLevels[] = { "None", "Fatal Error", "Error", "Warning", "Debug", "Trace" }; static PKIX_Error *loggerCallback( PKIX_Logger *logger, PKIX_PL_String *message, PKIX_UInt32 logLevel, PKIX_ERRORCLASS logComponent, void *plContext) { char *msg = NULL; static int callCount = 0; msg = PKIX_String2ASCII(message, plContext); printf("Logging %s (%s): %s\n", logLevels[logLevel], PKIX_ERRORCLASSNAMES[logComponent], msg); PR_Free((void *)msg); return(NULL); } #endif /* PKIX_LOGGER_ON */ static void ThreadEntry(void* data) { tData* tdata = (tData*) data; PRIntervalTime duration = tdata->duration; PRIntervalTime start = PR_IntervalNow(); PKIX_List *anchors = NULL; PKIX_ProcessingParams *procParams = NULL; PKIX_BuildResult *buildResult = NULL; CERTCertificate* nsseecert; PKIX_PL_Cert *eeCert = NULL; PKIX_CertStore *certStore = NULL; PKIX_List *certStores = NULL; PKIX_ComCertSelParams *certSelParams = NULL; PKIX_CertSelector *certSelector = NULL; PKIX_PL_Date *nowDate = NULL; void *state = NULL; /* only relevant with non-blocking I/O */ void *nbioContext = NULL; /* only relevant with non-blocking I/O */ PR_ASSERT(duration); if (!duration){ return; } do { /* libpkix code */ /* keep more update time, testing cache */ PKIX_PL_Date_Create_UTCTime(NULL, &nowDate, plContext); /* CertUsage is 0x10 and no NSS arena */ /* We haven't determined how we obtain the value of wincx */ nsseecert = CERT_FindCertByNicknameOrEmailAddr(tdata->handle, tdata->eecertName); if (!nsseecert) finish("Unable to find eecert.\n", 1); pkix_pl_Cert_CreateWithNSSCert (nsseecert, &eeCert, plContext); PKIX_List_Create(&anchors, plContext); /* * This code is retired. * pkix_pl_Cert_CreateWithNSSCert * (tdata->anchor, &anchorCert, NULL); * PKIX_TrustAnchor_CreateWithCert(anchorCert, &anchor, NULL); * PKIX_List_AppendItem(anchors, (PKIX_PL_Object *)anchor, NULL); */ PKIX_ProcessingParams_Create(anchors, &procParams, plContext); PKIX_ProcessingParams_SetRevocationEnabled (procParams, PKIX_TRUE, plContext); PKIX_ProcessingParams_SetDate (procParams, nowDate, plContext); /* create CertSelector with target certificate in params */ PKIX_ComCertSelParams_Create(&certSelParams, plContext); PKIX_ComCertSelParams_SetCertificate (certSelParams, eeCert, plContext); PKIX_CertSelector_Create (NULL, NULL, &certSelector, plContext); PKIX_CertSelector_SetCommonCertSelectorParams (certSelector, certSelParams, plContext); PKIX_ProcessingParams_SetTargetCertConstraints (procParams, certSelector, plContext); PKIX_PL_Pk11CertStore_Create(&certStore, plContext); PKIX_List_Create(&certStores, plContext); PKIX_List_AppendItem (certStores, (PKIX_PL_Object *)certStore, plContext); PKIX_ProcessingParams_SetCertStores (procParams, certStores, plContext); PKIX_BuildChain (procParams, &nbioContext, &state, &buildResult, NULL, plContext); /* * As long as we use only CertStores with blocking I/O, we * know we must be done at this point. */ if (!buildResult){ (void) fprintf(stderr, "libpkix BuildChain failed.\n"); PORT_Assert(0); return; } tdata->iterations ++; PERF_DECREF(nowDate); PERF_DECREF(anchors); PERF_DECREF(procParams); PERF_DECREF(buildResult); PERF_DECREF(certStore); PERF_DECREF(certStores); PERF_DECREF(certSelParams); PERF_DECREF(certSelector); PERF_DECREF(eeCert); } while ((PR_IntervalNow() - start) < duration); } static void Test( CERTCertificate* anchor, char* eecertName, PRIntervalTime duration, CERTCertDBHandle *handle, PRUint32 threads) { tData data; tData** alldata; PRIntervalTime starttime, endtime, elapsed; PRUint32 msecs; float total = 0; PRThread** pthreads = NULL; PRUint32 i = 0; data.duration = duration; data.anchor = anchor; data.eecertName = eecertName; data.handle = handle; data.iterations = 0; starttime = PR_IntervalNow(); pthreads = (PRThread**)PR_Malloc(threads*sizeof (PRThread*)); alldata = (tData**)PR_Malloc(threads*sizeof (tData*)); for (i = 0; i < threads; i++){ alldata[i] = (tData*)PR_Malloc(sizeof (tData)); *alldata[i] = data; pthreads[i] = PR_CreateThread(PR_USER_THREAD, ThreadEntry, (void*) alldata[i], PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); } for (i = 0; i < threads; i++) { tData* args = alldata[i]; PR_JoinThread(pthreads[i]); total += args->iterations; PR_Free((void*)args); } PR_Free((void*) pthreads); PR_Free((void*) alldata); endtime = PR_IntervalNow(); endtime = PR_IntervalNow(); elapsed = endtime - starttime; msecs = PR_IntervalToMilliseconds(elapsed); total /= msecs; total *= 1000; (void) fprintf(stdout, "%f operations per second.\n", total); } static void finish(char* message, int code) { (void) printf(message); exit(code); } static void usage(char* progname) { (void) printf("Usage : %s <-d certStoreDirectory> " " \n\n", progname); finish("", 0); } int libpkix_buildthreads(int argc, char** argv) { CERTCertDBHandle *handle = NULL; CERTCertificate* eecert = NULL; PRIntervalTime duration = PR_SecondsToInterval(1); PRUint32 threads = 1; PKIX_UInt32 actualMinorVersion; PKIX_UInt32 j = 0; PKIX_Logger *logger = NULL; void *wincx = NULL; /* if (argc != 5) -- when TrustAnchor used to be on command line */ if (argc != 4) { usage(argv[0]); } if (atoi(argv[1]) > 0) { duration = PR_SecondsToInterval(atoi(argv[1])); } if (atoi(argv[2]) > 0) { threads = atoi(argv[2]); } PKIX_PL_NssContext_Create(certificateUsageEmailSigner, PKIX_FALSE, NULL, &plContext); handle = CERT_GetDefaultCertDB(); PR_ASSERT(handle); #ifdef PKIX_LOGGER_ON /* set logger to log trace and up */ PKIX_SetLoggers(NULL, plContext); PKIX_Logger_Create(loggerCallback, NULL, &logger, plContext); PKIX_Logger_SetMaxLoggingLevel (logger, PKIX_LOGGER_LEVEL_WARNING, plContext); PKIX_AddLogger(logger, plContext); #endif /* PKIX_LOGGER_ON */ /* * This code is retired * anchor = CERT_FindCertByNicknameOrEmailAddr(handle, argv[3]); * if (!anchor) finish("Unable to find anchor.\n", 1); * * eecert = CERT_FindCertByNicknameOrEmailAddr(handle, argv[4]); * if (!eecert) finish("Unable to find eecert.\n", 1); * * Test(anchor, eecert, duration, threads); */ Test(NULL, argv[3], duration, handle, threads); PERF_DECREF(logger); PKIX_Shutdown(plContext); return (0); }