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=1dcec8780775e5afcc6ffd7dca00ce3f95afa00f;hb=1cc0de54f0eeaf7535c7a6e9189dc0f75eeab7e7;hpb=2df635bb1dc3925aa10c35ef4a91239eb93dc7ff diff --git a/d0_bignum-openssl.c b/d0_bignum-openssl.c index 1dcec87..8b52eb2 100644 --- a/d0_bignum-openssl.c +++ b/d0_bignum-openssl.c @@ -1,27 +1,57 @@ /* -Blind-ID library for user identification using RSA blind signatures -Copyright (C) 2010 Rudolf Polzer - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ + * FILE: d0_bignum-openssl.c + * AUTHOR: Rudolf Polzer - divVerent@xonotic.org + * + * Copyright (c) 2010, Rudolf Polzer + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Format:commit %H$ + * $Id$ + */ + +/* NOTE: this file links against openssl (http://www.openssl.org), which is + * under the OpenSSL License. You may have to abide to its terms too if you use + * this file. + * To alternatively link to GMP, provide the option --without-openssl to + * ./configure. + */ #include "d0_bignum.h" #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 { @@ -30,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); @@ -82,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; } @@ -145,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; } @@ -233,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; } @@ -241,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) @@ -251,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 @@ -260,33 +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) { - return BN_is_prime(&r->z, param, NULL, ctx, NULL); + int ret; + d0_lockmutex(tempmutex); + if(param <= 0) + ret = BN_is_prime_fasttest(&r->z, 1, NULL, ctx, NULL, 1); + else + 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) @@ -297,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; }