X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fd0_blind_id.git;a=blobdiff_plain;f=d0_bignum-openssl.c;h=8b52eb28ae3db54492ae5df2001658696b30c5b2;hp=c8316906f6b9a0b2d9327cbf852221934b6d2819;hb=12bad60b19ff0ce5c90b319118a6a2cc142a60f8;hpb=0d9c60c64a7628d79882fd8ceb8d3aafc3548688 diff --git a/d0_bignum-openssl.c b/d0_bignum-openssl.c index c831690..8b52eb2 100644 --- a/d0_bignum-openssl.c +++ b/d0_bignum-openssl.c @@ -45,6 +45,13 @@ #include #include #include +#include + +// for stupid OpenSSL versions in Mac OS X +#ifndef BN_is_negative +#define BN_is_negative(a) ((a)->neg != 0) +#define BN_set_negative(a,n) ((a)->neg = ((n) && !BN_is_zero(a))) +#endif struct d0_bignum_s { @@ -53,48 +60,190 @@ struct d0_bignum_s static d0_bignum_t temp; static BN_CTX *ctx; +static unsigned char numbuf[65536]; +static void *tempmutex = NULL; // hold this mutex when using ctx or temp or numbuf #include #include -WARN_UNUSED_RESULT BOOL d0_bignum_INITIALIZE(void) +static void **locks; + +void locking_function(int mode, int l, const char *file, int line) +{ + void *m = locks[l]; + if(mode & CRYPTO_LOCK) + d0_lockmutex(m); + else + d0_unlockmutex(m); +} + +typedef struct CRYPTO_dynlock_value +{ + void *m; +}; + +struct CRYPTO_dynlock_value *dyn_create_function(const char *file, int line) +{ + return (struct CRYPTO_dynlock_value *) d0_createmutex(); +} + +void dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line) +{ + void *m = (void *) l; + if(mode & CRYPTO_LOCK) + d0_lockmutex(m); + else + d0_unlockmutex(m); +} + +void dyn_destroy_function(struct CRYPTO_dynlock_value *l, const char *file, int line) { + void *m = (void *) l; + d0_destroymutex(l); +} + +D0_WARN_UNUSED_RESULT D0_BOOL d0_bignum_INITIALIZE(void) +{ + FILE *f; + D0_BOOL ret = 1; + unsigned char buf[256]; + int i, n; + + tempmutex = d0_createmutex(); + d0_lockmutex(tempmutex); + + n = CRYPTO_num_locks(); + locks = d0_malloc(n * sizeof(*locks)); + for(i = 0; i < n; ++i) + locks[i] = d0_createmutex(); + + CRYPTO_set_locking_callback(locking_function); + CRYPTO_set_dynlock_create_callback(dyn_create_function); + CRYPTO_set_dynlock_lock_callback(dyn_lock_function); + CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function); + ctx = BN_CTX_new(); d0_bignum_init(&temp); + +#ifdef WIN32 + { + HCRYPTPROV hCryptProv; + if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) + { + if(!CryptGenRandom(hCryptProv, sizeof(buf), (PBYTE) &buf[0])) + { + fprintf(stderr, "WARNING: could not initialize random number generator (CryptGenRandom failed)\n"); + ret = 0; + } + CryptReleaseContext(hCryptProv, 0); + } + else if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_NEWKEYSET)) + { + if(!CryptGenRandom(hCryptProv, sizeof(buf), (PBYTE) &buf[0])) + { + fprintf(stderr, "WARNING: could not initialize random number generator (CryptGenRandom failed)\n"); + ret = 0; + } + CryptReleaseContext(hCryptProv, 0); + } + else + { + fprintf(stderr, "WARNING: could not initialize random number generator (CryptAcquireContext failed)\n"); + ret = 0; + } + } +#else + f = fopen("/dev/urandom", "rb"); + if(!f) + f = fopen("/dev/random", "rb"); + if(f) + { + setbuf(f, NULL); + if(fread(buf, sizeof(buf), 1, f) != 1) + { + fprintf(stderr, "WARNING: could not initialize random number generator (read from random device failed)\n"); + ret = 0; + } + fclose(f); + } + else + { + fprintf(stderr, "WARNING: could not initialize random number generator (no random device found)\n"); + ret = 0; + } +#endif + RAND_add(buf, sizeof(buf), sizeof(buf)); + + d0_unlockmutex(tempmutex); + return 1; + // FIXME initialize the RNG on Windows on UNIX it is done right already } void d0_bignum_SHUTDOWN(void) { + int i, n; + + d0_lockmutex(tempmutex); + d0_bignum_clear(&temp); BN_CTX_free(ctx); ctx = NULL; + + n = CRYPTO_num_locks(); + for(i = 0; i < n; ++i) + d0_destroymutex(locks[i]); + d0_free(locks); + + d0_unlockmutex(tempmutex); + d0_destroymutex(tempmutex); + tempmutex = NULL; } -BOOL d0_iobuf_write_bignum(d0_iobuf_t *buf, const d0_bignum_t *bignum) +D0_BOOL d0_iobuf_write_bignum(d0_iobuf_t *buf, const d0_bignum_t *bignum) { - static unsigned char numbuf[65536]; + D0_BOOL ret; size_t count = 0; + + d0_lockmutex(tempmutex); numbuf[0] = BN_is_zero(&bignum->z) ? 0 : BN_is_negative(&bignum->z) ? 3 : 1; if((numbuf[0] & 3) != 0) // nonzero { count = BN_num_bytes(&bignum->z); if(count > sizeof(numbuf) - 1) + { + d0_unlockmutex(tempmutex); return 0; + } BN_bn2bin(&bignum->z, numbuf+1); } - return d0_iobuf_write_packet(buf, numbuf, count + 1); + ret = d0_iobuf_write_packet(buf, numbuf, count + 1); + d0_unlockmutex(tempmutex); + return ret; } d0_bignum_t *d0_iobuf_read_bignum(d0_iobuf_t *buf, d0_bignum_t *bignum) { - static unsigned char numbuf[65536]; size_t count = sizeof(numbuf); + + d0_lockmutex(tempmutex); if(!d0_iobuf_read_packet(buf, numbuf, &count)) + { + d0_unlockmutex(tempmutex); return NULL; + } if(count < 1) + { + d0_unlockmutex(tempmutex); return NULL; - if(!bignum) bignum = d0_bignum_new(); if(!bignum) return NULL; + } + if(!bignum) + bignum = d0_bignum_new(); + if(!bignum) + { + d0_unlockmutex(tempmutex); + return NULL; + } if(numbuf[0] & 3) // nonzero { BN_bin2bn(numbuf+1, count-1, &bignum->z); @@ -105,6 +254,7 @@ d0_bignum_t *d0_iobuf_read_bignum(d0_iobuf_t *buf, d0_bignum_t *bignum) { BN_zero(&bignum->z); } + d0_unlockmutex(tempmutex); return bignum; } @@ -168,8 +318,10 @@ int d0_bignum_cmp(const d0_bignum_t *a, const d0_bignum_t *b) d0_bignum_t *d0_bignum_rand_range(d0_bignum_t *r, const d0_bignum_t *min, const d0_bignum_t *max) { if(!r) r = d0_bignum_new(); if(!r) return NULL; + d0_lockmutex(tempmutex); BN_sub(&temp.z, &max->z, &min->z); BN_rand_range(&r->z, &temp.z); + d0_unlockmutex(tempmutex); BN_add(&r->z, &r->z, &min->z); return r; } @@ -256,7 +408,9 @@ d0_bignum_t *d0_bignum_sub(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum d0_bignum_t *d0_bignum_mul(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *b) { if(!r) r = d0_bignum_new(); if(!r) return NULL; + d0_lockmutex(tempmutex); BN_mul(&r->z, &a->z, &b->z, ctx); + d0_unlockmutex(tempmutex); return r; } @@ -264,6 +418,7 @@ d0_bignum_t *d0_bignum_divmod(d0_bignum_t *q, d0_bignum_t *m, const d0_bignum_t { if(!q && !m) m = d0_bignum_new(); + d0_lockmutex(tempmutex); if(q) { if(m) @@ -274,6 +429,7 @@ d0_bignum_t *d0_bignum_divmod(d0_bignum_t *q, d0_bignum_t *m, const d0_bignum_t } else BN_nnmod(&m->z, &a->z, &b->z, ctx); + d0_unlockmutex(tempmutex); if(m) return m; else @@ -283,36 +439,59 @@ d0_bignum_t *d0_bignum_divmod(d0_bignum_t *q, d0_bignum_t *m, const d0_bignum_t d0_bignum_t *d0_bignum_mod_add(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *b, const d0_bignum_t *m) { if(!r) r = d0_bignum_new(); if(!r) return NULL; + d0_lockmutex(tempmutex); BN_mod_add(&r->z, &a->z, &b->z, &m->z, ctx); + d0_unlockmutex(tempmutex); + return r; +} + +d0_bignum_t *d0_bignum_mod_sub(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *b, const d0_bignum_t *m) +{ + if(!r) r = d0_bignum_new(); if(!r) return NULL; + d0_lockmutex(tempmutex); + BN_mod_sub(&r->z, &a->z, &b->z, &m->z, ctx); + d0_unlockmutex(tempmutex); return r; } d0_bignum_t *d0_bignum_mod_mul(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *b, const d0_bignum_t *m) { if(!r) r = d0_bignum_new(); if(!r) return NULL; + d0_lockmutex(tempmutex); BN_mod_mul(&r->z, &a->z, &b->z, &m->z, ctx); + d0_unlockmutex(tempmutex); return r; } d0_bignum_t *d0_bignum_mod_pow(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *b, const d0_bignum_t *m) { if(!r) r = d0_bignum_new(); if(!r) return NULL; + d0_lockmutex(tempmutex); BN_mod_exp(&r->z, &a->z, &b->z, &m->z, ctx); + d0_unlockmutex(tempmutex); return r; } -BOOL d0_bignum_mod_inv(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *m) +D0_BOOL d0_bignum_mod_inv(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *m) { // here, r MUST be set, as otherwise we cannot return error state! - return !!BN_mod_inverse(&r->z, &a->z, &m->z, ctx); + int ret; + d0_lockmutex(tempmutex); + ret = !!BN_mod_inverse(&r->z, &a->z, &m->z, ctx); + d0_unlockmutex(tempmutex); + return ret; } -int d0_bignum_isprime(d0_bignum_t *r, int param) +int d0_bignum_isprime(const d0_bignum_t *r, int param) { + int ret; + d0_lockmutex(tempmutex); if(param <= 0) - return BN_is_prime_fasttest(&r->z, 1, NULL, ctx, NULL, 1); + ret = BN_is_prime_fasttest(&r->z, 1, NULL, ctx, NULL, 1); else - return BN_is_prime(&r->z, param, NULL, ctx, NULL); + ret = BN_is_prime(&r->z, param, NULL, ctx, NULL); + d0_unlockmutex(tempmutex); + return ret; } d0_bignum_t *d0_bignum_gcd(d0_bignum_t *r, d0_bignum_t *s, d0_bignum_t *t, const d0_bignum_t *a, const d0_bignum_t *b) @@ -323,16 +502,28 @@ d0_bignum_t *d0_bignum_gcd(d0_bignum_t *r, d0_bignum_t *s, d0_bignum_t *t, const else if(t) assert(!"Extended gcd not implemented"); else + { + d0_lockmutex(tempmutex); BN_gcd(&r->z, &a->z, &b->z, ctx); + d0_unlockmutex(tempmutex); + } return r; } char *d0_bignum_tostring(const d0_bignum_t *x, unsigned int base) { + char *s = NULL; + char *s2; + size_t n; if(base == 10) - return BN_bn2dec(&x->z); + s = BN_bn2dec(&x->z); else if(base == 16) - return BN_bn2hex(&x->z); + s = BN_bn2hex(&x->z); else assert(!"Other bases not implemented"); + n = strlen(s) + 1; + s2 = d0_malloc(n); + memcpy(s2, s, n); + OPENSSL_free(s); + return s2; }