/[smeserver]/rpms/openssl/sme8/openssl-thread-test.c
ViewVC logotype

Annotation of /rpms/openssl/sme8/openssl-thread-test.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1 - (hide annotations) (download)
Tue Feb 18 03:03:10 2014 UTC (10 years, 8 months ago) by wellsi
Branch: MAIN
CVS Tags: openssl-0_9_8e-28_el5_sme, openssl-0_9_8e-33_1_el5_sme, openssl-0_9_8e-32_1_el5_sme, openssl-0_9_8e-27_1_el5_sme, openssl-0_9_8e-27_el5_10_1, openssl-0_9_8e-31_1_el5_sme, HEAD
Branch point for: upstream
Content type: text/plain
Initial import

1 wellsi 1.1 /* Test program to verify that RSA signing is thread-safe in OpenSSL. */
2    
3     #include <assert.h>
4     #include <errno.h>
5     #include <fcntl.h>
6     #include <limits.h>
7     #include <pthread.h>
8     #include <stdio.h>
9     #include <string.h>
10     #include <unistd.h>
11    
12     #include <openssl/crypto.h>
13     #include <openssl/err.h>
14     #include <openssl/objects.h>
15     #include <openssl/rand.h>
16     #include <openssl/rsa.h>
17     #include <openssl/md5.h>
18     #include <openssl/ssl.h>
19    
20     /* Just assume we want to do engine stuff if we're using 0.9.6b or
21     * higher. This assumption is only valid for versions bundled with RHL. */
22     #if OPENSSL_VERSION_NUMBER >= 0x0090602fL
23     #include <openssl/engine.h>
24     #define USE_ENGINE
25     #endif
26    
27     #define MAX_THREAD_COUNT 10000
28     #define ITERATION_COUNT 10
29     #define MAIN_COUNT 100
30    
31     /* OpenSSL requires us to provide thread ID and locking primitives. */
32     pthread_mutex_t *mutex_locks = NULL;
33     static unsigned long
34     thread_id_cb(void)
35     {
36     return (unsigned long) pthread_self();
37     }
38     static void
39     lock_cb(int mode, int n, const char *file, int line)
40     {
41     if (mode & CRYPTO_LOCK) {
42     pthread_mutex_lock(&mutex_locks[n]);
43     } else {
44     pthread_mutex_unlock(&mutex_locks[n]);
45     }
46     }
47    
48     struct thread_args {
49     RSA *rsa;
50     int digest_type;
51     unsigned char *digest;
52     unsigned int digest_len;
53     unsigned char *signature;
54     unsigned int signature_len;
55     pthread_t main_thread;
56     };
57    
58     static int print = 0;
59    
60     pthread_mutex_t sign_lock = PTHREAD_MUTEX_INITIALIZER;
61     static int locked_sign = 0;
62     static void SIGN_LOCK() {if (locked_sign) pthread_mutex_lock(&sign_lock);}
63     static void SIGN_UNLOCK() {if (locked_sign) pthread_mutex_unlock(&sign_lock);}
64    
65     pthread_mutex_t verify_lock = PTHREAD_MUTEX_INITIALIZER;
66     static int locked_verify = 0;
67     static void VERIFY_LOCK() {if (locked_verify) pthread_mutex_lock(&verify_lock);}
68     static void VERIFY_UNLOCK() {if (locked_verify) pthread_mutex_unlock(&verify_lock);}
69    
70     pthread_mutex_t failure_count_lock = PTHREAD_MUTEX_INITIALIZER;
71     long failure_count = 0;
72     static void
73     failure()
74     {
75     pthread_mutex_lock(&failure_count_lock);
76     failure_count++;
77     pthread_mutex_unlock(&failure_count_lock);
78     }
79    
80     static void *
81     thread_main(void *argp)
82     {
83     struct thread_args *args = argp;
84     unsigned char *signature;
85     unsigned int signature_len, signature_alloc_len;
86     int ret, i;
87    
88     signature_alloc_len = args->signature_len;
89     if (RSA_size(args->rsa) > signature_alloc_len) {
90     signature_alloc_len = RSA_size(args->rsa);
91     }
92     signature = malloc(signature_alloc_len);
93     if (signature == NULL) {
94     fprintf(stderr, "Skipping checks in thread %lu -- %s.\n",
95     (unsigned long) pthread_self(), strerror(errno));
96     pthread_exit(0);
97     return NULL;
98     }
99     for (i = 0; i < ITERATION_COUNT; i++) {
100     signature_len = signature_alloc_len;
101     SIGN_LOCK();
102     ret = RSA_check_key(args->rsa);
103     ERR_print_errors_fp(stdout);
104     if (ret != 1) {
105     failure();
106     break;
107     }
108     ret = RSA_sign(args->digest_type,
109     args->digest,
110     args->digest_len,
111     signature, &signature_len,
112     args->rsa);
113     SIGN_UNLOCK();
114     ERR_print_errors_fp(stdout);
115     if (ret != 1) {
116     failure();
117     break;
118     }
119    
120     VERIFY_LOCK();
121     ret = RSA_verify(args->digest_type,
122     args->digest,
123     args->digest_len,
124     signature, signature_len,
125     args->rsa);
126     VERIFY_UNLOCK();
127     if (ret != 1) {
128     fprintf(stderr,
129     "Signature from thread %lu(%d) fails "
130     "verification (passed in thread #%lu)!\n",
131     (long) pthread_self(), i,
132     (long) args->main_thread);
133     ERR_print_errors_fp(stdout);
134     failure();
135     continue;
136     }
137     if (print) {
138     fprintf(stderr, ">%d\n", i);
139     }
140     }
141     free(signature);
142    
143     pthread_exit(0);
144    
145     return NULL;
146     }
147    
148     unsigned char *
149     xmemdup(unsigned char *s, size_t len)
150     {
151     unsigned char *r;
152     r = malloc(len);
153     if (r == NULL) {
154     fprintf(stderr, "Out of memory.\n");
155     ERR_print_errors_fp(stdout);
156     assert(r != NULL);
157     }
158     memcpy(r, s, len);
159     return r;
160     }
161    
162     int
163     main(int argc, char **argv)
164     {
165     RSA *rsa;
166     MD5_CTX md5;
167     int fd, i;
168     pthread_t threads[MAX_THREAD_COUNT];
169     int thread_count = 1000;
170     unsigned char *message, *digest;
171     unsigned int message_len, digest_len;
172     unsigned char *correct_signature;
173     unsigned int correct_siglen, ret;
174     struct thread_args master_args, *args;
175     int sync = 0, seed = 0;
176     int again = 1;
177     #ifdef USE_ENGINE
178     char *engine = NULL;
179     ENGINE *e = NULL;
180     #endif
181    
182     pthread_mutex_init(&failure_count_lock, NULL);
183    
184     for (i = 1; i < argc; i++) {
185     if (strcmp(argv[i], "--seed") == 0) {
186     printf("Seeding PRNG.\n");
187     seed++;
188     } else
189     if (strcmp(argv[i], "--sync") == 0) {
190     printf("Running synchronized.\n");
191     sync++;
192     } else
193     if ((strcmp(argv[i], "--threads") == 0) && (i < argc - 1)) {
194     i++;
195     thread_count = atol(argv[i]);
196     if (thread_count > MAX_THREAD_COUNT) {
197     thread_count = MAX_THREAD_COUNT;
198     }
199     printf("Starting %d threads.\n", thread_count);
200     sync++;
201     } else
202     if (strcmp(argv[i], "--sign") == 0) {
203     printf("Locking signing.\n");
204     locked_sign++;
205     } else
206     if (strcmp(argv[i], "--verify") == 0) {
207     printf("Locking verifies.\n");
208     locked_verify++;
209     } else
210     if (strcmp(argv[i], "--print") == 0) {
211     printf("Tracing.\n");
212     print++;
213     #ifdef USE_ENGINE
214     } else
215     if ((strcmp(argv[i], "--engine") == 0) && (i < argc - 1)) {
216     printf("Using engine \"%s\".\n", argv[i + 1]);
217     engine = argv[i + 1];
218     i++;
219     #endif
220     } else {
221     printf("Bad argument: %s\n", argv[i]);
222     return 1;
223     }
224     }
225    
226     /* Get some random data to sign. */
227     fd = open("/dev/urandom", O_RDONLY);
228     if (fd == -1) {
229     fprintf(stderr, "Error opening /dev/urandom: %s\n",
230     strerror(errno));
231     }
232    
233     if (print) {
234     fprintf(stderr, "Reading random data.\n");
235     }
236     message = malloc(message_len = 9371);
237     read(fd, message, message_len);
238     close(fd);
239    
240     /* Initialize the SSL library and set up thread-safe locking. */
241     ERR_load_crypto_strings();
242     SSL_library_init();
243     mutex_locks = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
244     for (i = 0; i < CRYPTO_num_locks(); i++) {
245     pthread_mutex_init(&mutex_locks[i], NULL);
246     }
247     CRYPTO_set_id_callback(thread_id_cb);
248     CRYPTO_set_locking_callback(lock_cb);
249     ERR_print_errors_fp(stdout);
250    
251     /* Seed the PRNG if we were asked to do so. */
252     if (seed) {
253     if (print) {
254     fprintf(stderr, "Seeding PRNG.\n");
255     }
256     RAND_add(message, message_len, message_len);
257     ERR_print_errors_fp(stdout);
258     }
259    
260     /* Turn on a hardware crypto device if asked to do so. */
261     #ifdef USE_ENGINE
262     if (engine) {
263     #if OPENSSL_VERSION_NUMBER >= 0x0090700fL
264     ENGINE_load_builtin_engines();
265     #endif
266     if (print) {
267     fprintf(stderr, "Initializing \"%s\" engine.\n",
268     engine);
269     }
270     e = ENGINE_by_id(engine);
271     ERR_print_errors_fp(stdout);
272     if (e) {
273     i = ENGINE_init(e);
274     ERR_print_errors_fp(stdout);
275     i = ENGINE_set_default_RSA(e);
276     ERR_print_errors_fp(stdout);
277     }
278     }
279     #endif
280    
281     /* Compute the digest for the signature. */
282     if (print) {
283     fprintf(stderr, "Computing digest.\n");
284     }
285     digest = malloc(digest_len = MD5_DIGEST_LENGTH);
286     MD5_Init(&md5);
287     MD5_Update(&md5, message, message_len);
288     MD5_Final(digest, &md5);
289    
290     /* Generate a signing key. */
291     if (print) {
292     fprintf(stderr, "Generating key.\n");
293     }
294     rsa = RSA_generate_key(4096, 3, NULL, NULL);
295     ERR_print_errors_fp(stdout);
296     if (rsa == NULL) {
297     _exit(1);
298     }
299    
300     /* Sign the data. */
301     correct_siglen = RSA_size(rsa);
302     correct_signature = malloc(correct_siglen);
303     for (i = 0; i < MAIN_COUNT; i++) {
304     if (print) {
305     fprintf(stderr, "Signing data (%d).\n", i);
306     }
307     ret = RSA_check_key(rsa);
308     ERR_print_errors_fp(stdout);
309     if (ret != 1) {
310     failure();
311     }
312     correct_siglen = RSA_size(rsa);
313     ret = RSA_sign(NID_md5, digest, digest_len,
314     correct_signature, &correct_siglen,
315     rsa);
316     ERR_print_errors_fp(stdout);
317     if (ret != 1) {
318     _exit(2);
319     }
320     if (print) {
321     fprintf(stderr, "Verifying data (%d).\n", i);
322     }
323     ret = RSA_verify(NID_md5, digest, digest_len,
324     correct_signature, correct_siglen,
325     rsa);
326     if (ret != 1) {
327     _exit(2);
328     }
329     }
330    
331     /* Collect up the inforamtion which other threads will need for
332     * comparing their signature results with ours. */
333     master_args.rsa = rsa;
334     master_args.digest_type = NID_md5;
335     master_args.digest = digest;
336     master_args.digest_len = digest_len;
337     master_args.signature = correct_signature;
338     master_args.signature_len = correct_siglen;
339     master_args.main_thread = pthread_self();
340    
341     fprintf(stdout, "Performing %d signatures in each of %d threads "
342     "(%d, %d).\n", ITERATION_COUNT, thread_count,
343     digest_len, correct_siglen);
344     fflush(NULL);
345    
346     /* Start up all of the threads. */
347     for (i = 0; i < thread_count; i++) {
348     args = malloc(sizeof(struct thread_args));
349     args->rsa = RSAPrivateKey_dup(master_args.rsa);
350     args->digest_type = master_args.digest_type;
351     args->digest_len = master_args.digest_len;
352     args->digest = xmemdup(master_args.digest, args->digest_len);
353     args->signature_len = master_args.signature_len;
354     args->signature = xmemdup(master_args.signature,
355     args->signature_len);
356     args->main_thread = pthread_self();
357     ret = pthread_create(&threads[i], NULL, thread_main, args);
358     while ((ret != 0) && (errno == EAGAIN)) {
359     ret = pthread_create(&threads[i], NULL,
360     thread_main, &args);
361     fprintf(stderr, "Thread limit hit at %d.\n", i);
362     }
363     if (ret != 0) {
364     fprintf(stderr, "Unable to create thread %d: %s.\n",
365     i, strerror(errno));
366     threads[i] = -1;
367     } else {
368     if (sync) {
369     ret = pthread_join(threads[i], NULL);
370     assert(ret == 0);
371     }
372     if (print) {
373     fprintf(stderr, "%d\n", i);
374     }
375     }
376     }
377    
378     /* Wait for all threads to complete. So long as we can find an
379     * unjoined thread, keep joining threads. */
380     do {
381     again = 0;
382     for (i = 0; i < thread_count; i++) {
383     /* If we have an unterminated thread, join it. */
384     if (threads[i] != -1) {
385     again = 1;
386     if (print) {
387     fprintf(stderr, "Joining thread %d.\n",
388     i);
389     }
390     pthread_join(threads[i], NULL);
391     threads[i] = -1;
392     break;
393     }
394     }
395     } while (again == 1);
396    
397     fprintf(stderr, "%ld failures\n", failure_count);
398    
399     return (failure_count != 0);
400     }

admin@koozali.org
ViewVC Help
Powered by ViewVC 1.2.1 RSS 2.0 feed