annotate src/c/openssl.c @ 2166:8a01e8f21de9

Make OpenSSL usage thread-safe (closes #206) Enable OpenSSL?s multithreading support by defining locking and thread-ID callbacks. Remove a lock obviated by this change.
author Benjamin Barenblat <bbaren@mit.edu>
date Thu, 06 Aug 2015 10:15:53 -0400
parents 882556b3029d
children ce312cad5ecd c275bbc41194
rev   line source
adamc@1268 1 #include "config.h"
adamc@1268 2
bbaren@2166 3 #include <assert.h>
adam@1368 4 #include <stdlib.h>
adam@1368 5 #include <unistd.h>
adam@1368 6 #include <sys/types.h>
adam@1368 7 #include <sys/stat.h>
adamc@1145 8 #include <fcntl.h>
adam@1368 9 #include <stdio.h>
adam@1368 10 #include <string.h>
bbaren@2166 11 #include <pthread.h>
adamc@1104 12
bbaren@2166 13 #include <openssl/crypto.h>
adam@1368 14 #include <openssl/sha.h>
adam@2105 15 #include <openssl/rand.h>
adam@1368 16
adamc@1104 17 #define PASSSIZE 4
adamc@1104 18
bbaren@2166 19 // OpenSSL locks array. See threads(3SSL).
bbaren@2166 20 static pthread_mutex_t *openssl_locks;
bbaren@2166 21
adam@1368 22 int uw_hash_blocksize = 32;
adamc@1104 23
adamc@1104 24 static int password[PASSSIZE];
adamc@1104 25
adamc@1145 26 char *uw_sig_file = NULL;
adamc@1145 27
adamc@1145 28 static void random_password() {
adam@2105 29 if (!RAND_bytes((unsigned char *)password, sizeof password)) {
adam@2105 30 fprintf(stderr, "Error generating random password\n");
adam@2105 31 perror("RAND_bytes");
adam@2105 32 exit(1);
adam@2105 33 }
adamc@1145 34 }
adamc@1145 35
bbaren@2166 36 // OpenSSL callbacks
bbaren@2166 37 static void thread_id(CRYPTO_THREADID *const result) {
bbaren@2166 38 CRYPTO_THREADID_set_numeric(result, pthread_self());
bbaren@2166 39 }
bbaren@2166 40 static void lock_or_unlock(const int mode, const int type, const char *file,
bbaren@2166 41 const int line) {
bbaren@2166 42 pthread_mutex_t *const lock = &openssl_locks[type];
bbaren@2166 43 if (mode & CRYPTO_LOCK) {
bbaren@2166 44 if (pthread_mutex_lock(lock)) {
bbaren@2166 45 fprintf(stderr, "Can't take lock at %s:%d\n", file, line);
bbaren@2166 46 exit(1);
bbaren@2166 47 }
bbaren@2166 48 } else {
bbaren@2166 49 if (pthread_mutex_unlock(lock)) {
bbaren@2166 50 fprintf(stderr, "Can't release lock at %s:%d\n", file, line);
bbaren@2166 51 exit(1);
bbaren@2166 52 }
bbaren@2166 53 }
bbaren@2166 54 }
bbaren@2166 55
adamc@1104 56 void uw_init_crypto() {
bbaren@2166 57 int i;
bbaren@2166 58 // Set up OpenSSL.
bbaren@2166 59 assert(openssl_locks == NULL);
bbaren@2166 60 openssl_locks = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
bbaren@2166 61 if (!openssl_locks) {
bbaren@2166 62 perror("malloc");
bbaren@2166 63 exit(1);
bbaren@2166 64 }
bbaren@2166 65 for (i = 0; i < CRYPTO_num_locks(); ++i) {
bbaren@2166 66 pthread_mutex_init(&(openssl_locks[i]), NULL);
bbaren@2166 67 }
bbaren@2166 68 CRYPTO_THREADID_set_callback(thread_id);
bbaren@2166 69 CRYPTO_set_locking_callback(lock_or_unlock);
bbaren@2166 70 // Prepare signatures.
adamc@1145 71 if (uw_sig_file) {
adamc@1145 72 int fd;
adamc@1145 73
adamc@1155 74 if (access(uw_sig_file, F_OK)) {
adamc@1145 75 random_password();
adamc@1145 76
adamc@1145 77 if ((fd = open(uw_sig_file, O_WRONLY | O_CREAT, 0700)) < 0) {
adamc@1145 78 fprintf(stderr, "Can't open signature file %s\n", uw_sig_file);
adamc@1145 79 perror("open");
adamc@1145 80 exit(1);
adamc@1145 81 }
adamc@1145 82
adamc@1145 83 if (write(fd, &password, sizeof password) != sizeof password) {
adamc@1145 84 fprintf(stderr, "Error writing signature file\n");
adamc@1145 85 exit(1);
adamc@1145 86 }
adamc@1145 87
adamc@1145 88 close(fd);
adamc@1145 89 } else {
adamc@1145 90 if ((fd = open(uw_sig_file, O_RDONLY)) < 0) {
adamc@1145 91 fprintf(stderr, "Can't open signature file %s\n", uw_sig_file);
adamc@1145 92 perror("open");
adamc@1145 93 exit(1);
adamc@1145 94 }
adamc@1145 95
adamc@1145 96 if (read(fd, &password, sizeof password) != sizeof password) {
adamc@1145 97 fprintf(stderr, "Error reading signature file\n");
adamc@1145 98 exit(1);
adamc@1145 99 }
adamc@1145 100
adamc@1145 101 close(fd);
adamc@1145 102 }
adamc@1145 103 } else
adamc@1145 104 random_password();
adamc@1104 105 }
adamc@1104 106
adam@1368 107 void uw_sign(const char *in, unsigned char *out) {
adam@1368 108 SHA256_CTX c;
adamc@1104 109
adam@1368 110 SHA256_Init(&c);
adam@1368 111 SHA256_Update(&c, password, sizeof password);
adam@1368 112 SHA256_Update(&c, in, strlen(in));
adam@1368 113 SHA256_Final(out, &c);
adamc@1104 114 }