OpenDNSSEC-libhsm 1.3.0
/build/buildd/opendnssec-1.3.0/libhsm/src/hsmspeed.c
Go to the documentation of this file.
00001 /*
00002  * $Id: hsmspeed.c 5320 2011-07-12 10:42:26Z jakob $
00003  *
00004  * Copyright (c) 2009 Nominet UK.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions
00009  * are met:
00010  * 1. Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  * 2. Redistributions in binary form must reproduce the above copyright
00013  *    notice, this list of conditions and the following disclaimer in the
00014  *    documentation and/or other materials provided with the distribution.
00015  *
00016  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00017  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00018  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00019  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00020  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00021  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00022  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00023  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00024  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00025  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00026  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00029 #include "config.h"
00030 
00031 #include <stdio.h>
00032 #include <string.h>
00033 #include <stdlib.h>
00034 #include <unistd.h>
00035 #include <pthread.h>
00036 
00037 #include <libhsm.h>
00038 #include <libhsmdns.h>
00039 
00040 #define PTHREAD_THREADS_MAX 2048
00041 
00042 /* Algorithm identifier and name */
00043 ldns_algorithm  algorithm = LDNS_RSASHA1;
00044 const char     *algoname  = "RSA/SHA1";
00045 
00046 extern char *optarg;
00047 char *progname = NULL;
00048 
00049 typedef struct {
00050     unsigned int id;
00051     hsm_ctx_t *ctx;
00052     hsm_key_t *key;
00053     unsigned int iterations;
00054 } sign_arg_t;
00055 
00056 void
00057 usage ()
00058 {
00059     fprintf(stderr,
00060         "usage: %s "
00061         "[-c config] -r repository [-i iterations] [-s keysize] [-t threads]\n",
00062         progname);
00063 }
00064 
00065 void *
00066 sign (void *arg)
00067 {
00068     hsm_ctx_t *ctx = NULL;
00069     hsm_key_t *key = NULL;
00070 
00071     size_t i;
00072     unsigned int iterations = 0;
00073 
00074     ldns_rr_list *rrset;
00075     ldns_rr *rr, *sig, *dnskey_rr;
00076     ldns_status status;
00077     hsm_sign_params_t *sign_params;
00078 
00079     sign_arg_t *sign_arg = arg;
00080 
00081     ctx = sign_arg->ctx;
00082     key = sign_arg->key;
00083     iterations = sign_arg->iterations;
00084 
00085     fprintf(stderr, "Signer thread #%d started...\n", sign_arg->id);
00086 
00087     /* Prepare dummy RRset for signing */
00088     rrset = ldns_rr_list_new();
00089     status = ldns_rr_new_frm_str(&rr, "regress.opendnssec.se. IN A 123.123.123.123", 0, NULL, NULL);
00090     if (status == LDNS_STATUS_OK) ldns_rr_list_push_rr(rrset, rr);
00091     status = ldns_rr_new_frm_str(&rr, "regress.opendnssec.se. IN A 124.124.124.124", 0, NULL, NULL);
00092     if (status == LDNS_STATUS_OK) ldns_rr_list_push_rr(rrset, rr);
00093     sign_params = hsm_sign_params_new();
00094     sign_params->algorithm = algorithm;
00095     sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "opendnssec.se.");
00096     dnskey_rr = hsm_get_dnskey(ctx, key, sign_params);
00097     sign_params->keytag = ldns_calc_keytag(dnskey_rr);
00098 
00099     /* Do some signing */
00100     for (i=0; i<iterations; i++) {
00101         sig = hsm_sign_rrset(ctx, rrset, key, sign_params);
00102         if (! sig) {
00103             fprintf(stderr,
00104                     "hsm_sign_rrset() returned error: %s in %s\n",
00105                     ctx->error_message,
00106                     ctx->error_action
00107             );
00108             break;
00109         }
00110         ldns_rr_free(sig);
00111     }
00112 
00113     /* Clean up */
00114     ldns_rr_list_deep_free(rrset);
00115     hsm_sign_params_free(sign_params);
00116     ldns_rr_free(dnskey_rr);
00117     hsm_destroy_context(ctx);
00118 
00119     fprintf(stderr, "Signer thread #%d done.\n", sign_arg->id);
00120 
00121     pthread_exit(NULL);
00122 }
00123 
00124 
00125 int
00126 main (int argc, char *argv[])
00127 {
00128     int result;
00129 
00130     hsm_ctx_t *ctx = NULL;
00131     hsm_key_t *key = NULL;
00132     unsigned int keysize = 1024;
00133     unsigned int iterations = 1;
00134     unsigned int threads = 1;
00135 
00136     static struct timeval start,end;
00137 
00138     char *config = NULL;
00139     const char *repository = NULL;
00140 
00141     sign_arg_t sign_arg_array[PTHREAD_THREADS_MAX];
00142 
00143     pthread_t      thread_array[PTHREAD_THREADS_MAX];
00144     pthread_attr_t thread_attr;
00145     void          *thread_status;
00146 
00147     int ch;
00148     unsigned int n;
00149     double elapsed, speed;
00150 
00151     progname = argv[0];
00152 
00153     while ((ch = getopt(argc, argv, "c:i:r:s:t:")) != -1) {
00154         switch (ch) {
00155         case 'c':
00156             config = strdup(optarg);
00157             break;
00158         case 'i':
00159             iterations = atoi(optarg);
00160             break;
00161         case 'r':
00162             repository = strdup(optarg);
00163             break;
00164         case 's':
00165             keysize = atoi(optarg);
00166             break;
00167         case 't':
00168             threads = atoi(optarg);
00169             break;
00170         default:
00171             usage();
00172             exit(1);
00173         }
00174     }
00175 
00176     if (!repository) {
00177         usage();
00178         exit(1);
00179     }
00180 
00181 #if 0
00182     if (!config) {
00183         usage();
00184         exit(1);
00185     }
00186 #endif
00187 
00188     /* Open HSM library */
00189     fprintf(stderr, "Opening HSM Library...\n");
00190     result = hsm_open(config, hsm_prompt_pin, NULL);
00191     if (result) {
00192         fprintf(stderr, "hsm_open() returned %d\n", result);
00193         exit(-1);
00194     }
00195 
00196     /* Create HSM context */
00197     ctx = hsm_create_context();
00198     if (! ctx) {
00199         fprintf(stderr, "hsm_create_context() returned error\n");
00200         exit(-1);
00201     }
00202 
00203     /* Generate a temporary key */
00204     fprintf(stderr, "Generating temporary key...\n");
00205     key = hsm_generate_rsa_key(ctx, repository, keysize);
00206     if (key) {
00207         char *id = hsm_get_key_id(ctx, key);
00208         fprintf(stderr, "Temporary key created: %s\n", id);
00209         free(id);
00210     } else {
00211         fprintf(stderr, "Could not generate a key pair in repository \"%s\"\n", repository);
00212         exit(-1);
00213     }
00214 
00215     /* Prepare threads */
00216     pthread_attr_init(&thread_attr);
00217     pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
00218 
00219     for (n=0; n<threads; n++) {
00220         sign_arg_array[n].id = n;
00221         sign_arg_array[n].ctx = hsm_create_context();
00222         if (! sign_arg_array[n].ctx) {
00223             fprintf(stderr, "hsm_create_context() returned error\n");
00224             exit(-1);
00225         }
00226         sign_arg_array[n].key = key;
00227         sign_arg_array[n].iterations = iterations;
00228     }
00229 
00230     fprintf(stderr, "Signing %d RRsets with %s using %d %s...\n",
00231         iterations, algoname, threads, (threads > 1 ? "threads" : "thread"));
00232     gettimeofday(&start, NULL);
00233 
00234     /* Create threads for signing */
00235     for (n=0; n<threads; n++) {
00236         result = pthread_create(&thread_array[n], &thread_attr,
00237             sign, (void *) &sign_arg_array[n]);
00238         if (result) {
00239             fprintf(stderr, "pthread_create() returned %d\n", result);
00240             exit(EXIT_FAILURE);
00241         }
00242     }
00243 
00244     /* Wait for threads to finish */
00245     for (n=0; n<threads; n++) {
00246         result = pthread_join(thread_array[n], &thread_status);
00247         if (result) {
00248             fprintf(stderr, "pthread_join() returned %d\n", result);
00249             exit(EXIT_FAILURE);
00250         }
00251     }
00252 
00253     gettimeofday(&end, NULL);
00254     fprintf(stderr, "Signing done.\n");
00255 
00256     /* Report results */
00257     end.tv_sec -= start.tv_sec;
00258     end.tv_usec-= start.tv_usec;
00259     elapsed =(double)(end.tv_sec)+(double)(end.tv_usec)*.000001;
00260     speed = iterations / elapsed * threads;
00261     printf("%d %s, %d signatures per thread, %.2f sig/s (RSA %d bits)\n",
00262         threads, (threads > 1 ? "threads" : "thread"), iterations,
00263         speed, keysize);
00264 
00265     /* Delete temporary key */
00266     fprintf(stderr, "Deleting temporary key...\n");
00267     result = hsm_remove_key(ctx, key);
00268     if (result) {
00269         fprintf(stderr, "hsm_remove_key() returned %d\n", result);
00270         exit(-1);
00271     }
00272 
00273     /* Clean up */
00274     hsm_destroy_context(ctx);
00275     (void) hsm_close();
00276     if (config) free(config);
00277 
00278     return 0;
00279 }