annotate src/c/openssl.c @ 2174:ce312cad5ecd

Use correct OpenSSL thread safety macros on OS X (closes #209) Create an Autoconf test to determine if pthread_t is a pointer or scalar type, and use the appropriate CRYPTO_THREADID_set macro based on the result.
author Benjamin Barenblat <bbaren at mit.edu>
date Sun, 20 Sep 2015 17:46:07 -0400
parents 8a01e8f21de9
children dfadb5effdc0
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@2174 37 #ifdef PTHREAD_T_IS_POINTER
bbaren@2174 38 # define CRYPTO_THREADID_SET CRYPTO_THREADID_set_pointer
bbaren@2174 39 #else
bbaren@2174 40 # define CRYPTO_THREADID_SET CRYPTO_THREADID_set_numeric
bbaren@2174 41 #endif
bbaren@2166 42 static void thread_id(CRYPTO_THREADID *const result) {
bbaren@2174 43 CRYPTO_THREADID_SET(result, pthread_self());
bbaren@2166 44 }
bbaren@2174 45 #undef CRYPTO_THREADID_SET
bbaren@2166 46 static void lock_or_unlock(const int mode, const int type, const char *file,
bbaren@2166 47 const int line) {
bbaren@2166 48 pthread_mutex_t *const lock = &openssl_locks[type];
bbaren@2166 49 if (mode & CRYPTO_LOCK) {
bbaren@2166 50 if (pthread_mutex_lock(lock)) {
bbaren@2166 51 fprintf(stderr, "Can't take lock at %s:%d\n", file, line);
bbaren@2166 52 exit(1);
bbaren@2166 53 }
bbaren@2166 54 } else {
bbaren@2166 55 if (pthread_mutex_unlock(lock)) {
bbaren@2166 56 fprintf(stderr, "Can't release lock at %s:%d\n", file, line);
bbaren@2166 57 exit(1);
bbaren@2166 58 }
bbaren@2166 59 }
bbaren@2166 60 }
bbaren@2166 61
adamc@1104 62 void uw_init_crypto() {
bbaren@2166 63 int i;
bbaren@2166 64 // Set up OpenSSL.
bbaren@2166 65 assert(openssl_locks == NULL);
bbaren@2166 66 openssl_locks = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
bbaren@2166 67 if (!openssl_locks) {
bbaren@2166 68 perror("malloc");
bbaren@2166 69 exit(1);
bbaren@2166 70 }
bbaren@2166 71 for (i = 0; i < CRYPTO_num_locks(); ++i) {
bbaren@2166 72 pthread_mutex_init(&(openssl_locks[i]), NULL);
bbaren@2166 73 }
bbaren@2166 74 CRYPTO_THREADID_set_callback(thread_id);
bbaren@2166 75 CRYPTO_set_locking_callback(lock_or_unlock);
bbaren@2166 76 // Prepare signatures.
adamc@1145 77 if (uw_sig_file) {
adamc@1145 78 int fd;
adamc@1145 79
adamc@1155 80 if (access(uw_sig_file, F_OK)) {
adamc@1145 81 random_password();
adamc@1145 82
adamc@1145 83 if ((fd = open(uw_sig_file, O_WRONLY | O_CREAT, 0700)) < 0) {
adamc@1145 84 fprintf(stderr, "Can't open signature file %s\n", uw_sig_file);
adamc@1145 85 perror("open");
adamc@1145 86 exit(1);
adamc@1145 87 }
adamc@1145 88
adamc@1145 89 if (write(fd, &password, sizeof password) != sizeof password) {
adamc@1145 90 fprintf(stderr, "Error writing signature file\n");
adamc@1145 91 exit(1);
adamc@1145 92 }
adamc@1145 93
adamc@1145 94 close(fd);
adamc@1145 95 } else {
adamc@1145 96 if ((fd = open(uw_sig_file, O_RDONLY)) < 0) {
adamc@1145 97 fprintf(stderr, "Can't open signature file %s\n", uw_sig_file);
adamc@1145 98 perror("open");
adamc@1145 99 exit(1);
adamc@1145 100 }
adamc@1145 101
adamc@1145 102 if (read(fd, &password, sizeof password) != sizeof password) {
adamc@1145 103 fprintf(stderr, "Error reading signature file\n");
adamc@1145 104 exit(1);
adamc@1145 105 }
adamc@1145 106
adamc@1145 107 close(fd);
adamc@1145 108 }
adamc@1145 109 } else
adamc@1145 110 random_password();
adamc@1104 111 }
adamc@1104 112
adam@1368 113 void uw_sign(const char *in, unsigned char *out) {
adam@1368 114 SHA256_CTX c;
adamc@1104 115
adam@1368 116 SHA256_Init(&c);
adam@1368 117 SHA256_Update(&c, password, sizeof password);
adam@1368 118 SHA256_Update(&c, in, strlen(in));
adam@1368 119 SHA256_Final(out, &c);
adamc@1104 120 }