/* * 'OpenSSL for Ruby' project * Copyright (C) 2001-2002 Michal Rokos * All rights reserved. */ /* * This program is licensed under the same licence as Ruby. * (See the file 'LICENCE'.) */ #if !defined(_OSSL_OPENSSL_MISSING_H_) #define _OSSL_OPENSSL_MISSING_H_ //TAU #include "ruby.h" #include "ruby/intern.h" #include "ruby/defines.h" #include "ruby/node.h" #include "ruby/config.h" /* added in 0.9.8X */ #if !defined(HAVE_EVP_CIPHER_CTX_NEW) EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void); #endif #if !defined(HAVE_EVP_CIPHER_CTX_FREE) void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx); #endif /* added in 1.0.0 */ #if !defined(HAVE_EVP_PKEY_BASE_ID) # define EVP_PKEY_base_id(pkey) EVP_PKEY_type((pkey)->type) #endif #if !defined(HAVE_EVP_CIPHER_CTX_COPY) int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in); #endif #if !defined(HAVE_HMAC_CTX_COPY) int HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in); #endif #if !defined(HAVE_X509_STORE_CTX_GET0_CURRENT_CRL) # define X509_STORE_CTX_get0_current_crl(x) ((x)->current_crl) #endif #if !defined(HAVE_X509_STORE_SET_VERIFY_CB) # define X509_STORE_set_verify_cb X509_STORE_set_verify_cb_func #endif #if !defined(HAVE_I2D_ASN1_SET_ANY) # define i2d_ASN1_SET_ANY(sk, x) i2d_ASN1_SET_OF_ASN1_TYPE((sk), (x), \ i2d_ASN1_TYPE, V_ASN1_SET, V_ASN1_UNIVERSAL, 0) #endif /* added in 1.0.2 */ #if !defined(OPENSSL_NO_EC) #if !defined(HAVE_EC_CURVE_NIST2NID) int EC_curve_nist2nid(const char *); #endif #endif #if !defined(HAVE_X509_REVOKED_DUP) # define X509_REVOKED_dup(rev) (X509_REVOKED *)ASN1_dup((i2d_of_void *)i2d_X509_REVOKED, \ (d2i_of_void *)d2i_X509_REVOKED, (char *)(rev)) #endif #if !defined(HAVE_X509_STORE_CTX_GET0_STORE) # define X509_STORE_CTX_get0_store(x) ((x)->ctx) #endif #if !defined(HAVE_SSL_IS_SERVER) # define SSL_is_server(s) ((s)->server) #endif /* added in 1.1.0 */ #if !defined(HAVE_BN_GENCB_NEW) # define BN_GENCB_new() ((BN_GENCB *)OPENSSL_malloc(sizeof(BN_GENCB))) #endif #if !defined(HAVE_BN_GENCB_FREE) # define BN_GENCB_free(cb) OPENSSL_free(cb) #endif #if !defined(HAVE_BN_GENCB_GET_ARG) # define BN_GENCB_get_arg(cb) (cb)->arg #endif #if !defined(HAVE_EVP_MD_CTX_NEW) # define EVP_MD_CTX_new EVP_MD_CTX_create #endif #if !defined(HAVE_EVP_MD_CTX_FREE) # define EVP_MD_CTX_free EVP_MD_CTX_destroy #endif #if !defined(HAVE_HMAC_CTX_NEW) HMAC_CTX *HMAC_CTX_new(void); #endif #if !defined(HAVE_HMAC_CTX_FREE) void HMAC_CTX_free(HMAC_CTX *ctx); #endif #if !defined(HAVE_X509_STORE_GET_EX_DATA) # define X509_STORE_get_ex_data(x, idx) \ CRYPTO_get_ex_data(&(x)->ex_data, (idx)) #endif #if !defined(HAVE_X509_STORE_SET_EX_DATA) # define X509_STORE_set_ex_data(x, idx, data) \ CRYPTO_set_ex_data(&(x)->ex_data, (idx), (data)) # define X509_STORE_get_ex_new_index(l, p, newf, dupf, freef) \ CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE, (l), (p), \ (newf), (dupf), (freef)) #endif #if !defined(HAVE_X509_CRL_GET0_SIGNATURE) void X509_CRL_get0_signature(const X509_CRL *, const ASN1_BIT_STRING **, const X509_ALGOR **); #endif #if !defined(HAVE_X509_REQ_GET0_SIGNATURE) void X509_REQ_get0_signature(const X509_REQ *, const ASN1_BIT_STRING **, const X509_ALGOR **); #endif #if !defined(HAVE_X509_REVOKED_GET0_SERIALNUMBER) # define X509_REVOKED_get0_serialNumber(x) ((x)->serialNumber) #endif #if !defined(HAVE_X509_REVOKED_GET0_REVOCATIONDATE) # define X509_REVOKED_get0_revocationDate(x) ((x)->revocationDate) #endif #if !defined(HAVE_X509_GET0_TBS_SIGALG) # define X509_get0_tbs_sigalg(x) ((x)->cert_info->signature) #endif #if !defined(HAVE_X509_STORE_CTX_GET0_UNTRUSTED) # define X509_STORE_CTX_get0_untrusted(x) ((x)->untrusted) #endif #if !defined(HAVE_X509_STORE_CTX_GET0_CERT) # define X509_STORE_CTX_get0_cert(x) ((x)->cert) #endif #if !defined(HAVE_X509_STORE_CTX_GET0_CHAIN) # define X509_STORE_CTX_get0_chain(ctx) X509_STORE_CTX_get_chain(ctx) #endif #if !defined(HAVE_OCSP_SINGLERESP_GET0_ID) # define OCSP_SINGLERESP_get0_id(s) ((s)->certId) #endif #if !defined(HAVE_SSL_CTX_GET_CIPHERS) # define SSL_CTX_get_ciphers(ctx) ((ctx)->cipher_list) #endif #if !defined(HAVE_X509_UP_REF) # define X509_up_ref(x) \ CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_X509) #endif #if !defined(HAVE_X509_CRL_UP_REF) # define X509_CRL_up_ref(x) \ CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_X509_CRL); #endif #if !defined(HAVE_X509_STORE_UP_REF) # define X509_STORE_up_ref(x) \ CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_X509_STORE); #endif #if !defined(HAVE_SSL_SESSION_UP_REF) # define SSL_SESSION_up_ref(x) \ CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_SSL_SESSION); #endif #if !defined(HAVE_EVP_PKEY_UP_REF) # define EVP_PKEY_up_ref(x) \ CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_EVP_PKEY); #endif #if !defined(HAVE_OPAQUE_OPENSSL) #define IMPL_PKEY_GETTER(_type, _name) \ static inline _type *EVP_PKEY_get0_##_type(EVP_PKEY *pkey) { \ return pkey->pkey._name; } #define IMPL_KEY_ACCESSOR2(_type, _group, a1, a2, _fail_cond) \ static inline void _type##_get0_##_group(_type *obj, const BIGNUM **a1, const BIGNUM **a2) { \ if (a1) *a1 = obj->a1; \ if (a2) *a2 = obj->a2; } \ static inline int _type##_set0_##_group(_type *obj, BIGNUM *a1, BIGNUM *a2) { \ if (_fail_cond) return 0; \ BN_clear_free(obj->a1); obj->a1 = a1; \ BN_clear_free(obj->a2); obj->a2 = a2; \ return 1; } #define IMPL_KEY_ACCESSOR3(_type, _group, a1, a2, a3, _fail_cond) \ static inline void _type##_get0_##_group(_type *obj, const BIGNUM **a1, const BIGNUM **a2, const BIGNUM **a3) { \ if (a1) *a1 = obj->a1; \ if (a2) *a2 = obj->a2; \ if (a3) *a3 = obj->a3; } \ static inline int _type##_set0_##_group(_type *obj, BIGNUM *a1, BIGNUM *a2, BIGNUM *a3) { \ if (_fail_cond) return 0; \ BN_clear_free(obj->a1); obj->a1 = a1; \ BN_clear_free(obj->a2); obj->a2 = a2; \ BN_clear_free(obj->a3); obj->a3 = a3; \ return 1; } #if !defined(OPENSSL_NO_RSA) IMPL_PKEY_GETTER(RSA, rsa) IMPL_KEY_ACCESSOR3(RSA, key, n, e, d, (n == obj->n || e == obj->e || (obj->d && d == obj->d))) IMPL_KEY_ACCESSOR2(RSA, factors, p, q, (p == obj->p || q == obj->q)) IMPL_KEY_ACCESSOR3(RSA, crt_params, dmp1, dmq1, iqmp, (dmp1 == obj->dmp1 || dmq1 == obj->dmq1 || iqmp == obj->iqmp)) #endif #if !defined(OPENSSL_NO_DSA) IMPL_PKEY_GETTER(DSA, dsa) IMPL_KEY_ACCESSOR2(DSA, key, pub_key, priv_key, (pub_key == obj->pub_key || (obj->priv_key && priv_key == obj->priv_key))) IMPL_KEY_ACCESSOR3(DSA, pqg, p, q, g, (p == obj->p || q == obj->q || g == obj->g)) #endif #if !defined(OPENSSL_NO_DH) IMPL_PKEY_GETTER(DH, dh) IMPL_KEY_ACCESSOR2(DH, key, pub_key, priv_key, (pub_key == obj->pub_key || (obj->priv_key && priv_key == obj->priv_key))) IMPL_KEY_ACCESSOR3(DH, pqg, p, q, g, (p == obj->p || obj->q && q == obj->q || g == obj->g)) static inline ENGINE *DH_get0_engine(DH *dh) { return dh->engine; } #endif #if !defined(OPENSSL_NO_EC) IMPL_PKEY_GETTER(EC_KEY, ec) #endif #undef IMPL_PKEY_GETTER #undef IMPL_KEY_ACCESSOR2 #undef IMPL_KEY_ACCESSOR3 #endif /* HAVE_OPAQUE_OPENSSL */ #if defined(HAVE_AUTHENTICATED_ENCRYPTION) && !defined(EVP_CTRL_AEAD_GET_TAG) # define EVP_CTRL_AEAD_GET_TAG EVP_CTRL_GCM_GET_TAG # define EVP_CTRL_AEAD_SET_TAG EVP_CTRL_GCM_SET_TAG # define EVP_CTRL_AEAD_SET_IVLEN EVP_CTRL_GCM_SET_IVLEN #endif #if !defined(HAVE_X509_GET0_NOTBEFORE) # define X509_get0_notBefore(x) X509_get_notBefore(x) # define X509_get0_notAfter(x) X509_get_notAfter(x) # define X509_CRL_get0_lastUpdate(x) X509_CRL_get_lastUpdate(x) # define X509_CRL_get0_nextUpdate(x) X509_CRL_get_nextUpdate(x) #endif //TAU #ifndef ASSUME # ifdef UNREACHABLE # define ASSUME(x) (RB_LIKELY(!!(x)) ? (void)0 : UNREACHABLE) # else # define ASSUME(x) ((void)(x)) # endif #endif #ifndef UNREACHABLE # define UNREACHABLE ((void)0) /* unreachable */ #endif #define RUBY_PRI_VALUE_MARK "\v" #if defined PRIdPTR && !defined PRI_VALUE_PREFIX #define PRIsVALUE PRIiPTR"" RUBY_PRI_VALUE_MARK #else #define PRIsVALUE PRI_VALUE_PREFIX"i" RUBY_PRI_VALUE_MARK #endif #define RB_FIXNUM_P(f) (((int)(SIGNED_VALUE)(f))&RUBY_FIXNUM_FLAG) #define RSTRING_GETMEM(str, ptrvar, lenvar) \ (!(RBASIC(str)->flags & RSTRING_NOEMBED) ? \ ((ptrvar) = RSTRING(str)->as.ary, (lenvar) = RSTRING_EMBED_LEN(str)) : \ ((ptrvar) = RSTRING(str)->as.heap.ptr, (lenvar) = RSTRING(str)->as.heap.len)) #define RHASH_SET_IFNONE(h, ifnone) rb_hash_set_ifnone((VALUE)h, ifnone) #define RUBY_TYPED_FREE_IMMEDIATELY 1 /* likely */ #if __GNUC__ >= 3 #define RB_LIKELY(x) (__builtin_expect(!!(x), 1)) #define RB_UNLIKELY(x) (__builtin_expect(!!(x), 0)) #else /* __GNUC__ >= 3 */ #define RB_LIKELY(x) (x) #define RB_UNLIKELY(x) (x) #endif /* __GNUC__ >= 3 */ //#ifndef BDIGIT #if SIZEOF_INT*2 <= SIZEOF_LONG_LONG #define SIZEOF_BDIGIT SIZEOF_INT #elif SIZEOF_INT*2 <= SIZEOF_LONG #define SIZEOF_BDIGIT SIZEOF_INT #elif SIZEOF_SHORT*2 <= SIZEOF_LONG #define SIZEOF_BDIGIT SIZEOF_SHORT #else #define SIZEOF_BDIGIT (SIZEOF_LONG/2) #endif //#endif #ifndef SIZEOF_ACTUAL_BDIGIT # define SIZEOF_ACTUAL_BDIGIT SIZEOF_BDIGIT #endif //TAU #define BIGNUM_EMBED_LEN_NUMBITS 3 #ifndef BIGNUM_EMBED_LEN_MAX # if (SIZEOF_VALUE*3/SIZEOF_ACTUAL_BDIGIT) < (1 << BIGNUM_EMBED_LEN_NUMBITS)-1 # define BIGNUM_EMBED_LEN_MAX (SIZEOF_VALUE*3/SIZEOF_ACTUAL_BDIGIT) # else # define BIGNUM_EMBED_LEN_MAX ((1 << BIGNUM_EMBED_LEN_NUMBITS)-1) # endif #endif #define BIGNUM_EMBED_FLAG FL_USER2 #define BIGNUM_EMBED_LEN_MASK (FL_USER5|FL_USER4|FL_USER3) #define BIGNUM_EMBED_LEN_SHIFT (FL_USHIFT+BIGNUM_EMBED_LEN_NUMBITS) #define BIGNUM_LEN(b) \ ((RBASIC(b)->flags & BIGNUM_EMBED_FLAG) ? \ (long)((RBASIC(b)->flags >> BIGNUM_EMBED_LEN_SHIFT) & \ (BIGNUM_EMBED_LEN_MASK >> BIGNUM_EMBED_LEN_SHIFT)) : \ RBIGNUM(b)->as.heap.len) #define BIGNUM_SIGN_BIT FL_USER1 /* sign: positive:1, negative:0 */ #define BIGNUM_SIGN(b) ((RBASIC(b)->flags & BIGNUM_SIGN_BIT) != 0) #define BIGNUM_SET_SIGN(b,sign) \ ((sign) ? (RBASIC(b)->flags |= BIGNUM_SIGN_BIT) \ : (RBASIC(b)->flags &= ~BIGNUM_SIGN_BIT)) #define BIGNUM_POSITIVE_P(b) BIGNUM_SIGN(b) #define BIGNUM_NEGATIVE_P(b) (!BIGNUM_SIGN(b)) #define BIGNUM_NEGATE(b) (RBASIC(b)->flags ^= BIGNUM_SIGN_BIT) #define RUBY_BLOCK_CALL_FUNC_TAKES_BLOCKARG 0 #define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg) \ VALUE yielded_arg, VALUE callback_arg, int argc, const VALUE *argv //TAU # define RUBY_ATTR_ALLOC_SIZE(params) __attribute__ ((alloc_size params)) void *rb_alloc_tmp_buffer(volatile VALUE *store, long len) RUBY_ATTR_ALLOC_SIZE((2)); void *rb_alloc_tmp_buffer_with_count(volatile VALUE *store, size_t len,size_t count) RUBY_ATTR_ALLOC_SIZE((2,3)); void rb_free_tmp_buffer(volatile VALUE *store); NORETURN(void ruby_malloc_size_overflow(size_t, size_t)); #if HAVE_LONG_LONG && SIZEOF_SIZE_T * 2 <= SIZEOF_LONG_LONG # define DSIZE_T unsigned LONG_LONG #elif defined(HAVE_INT128_T) # define DSIZE_T uint128_t #endif static inline int rb_mul_size_overflow(size_t a, size_t b, size_t max, size_t *c) { #ifdef DSIZE_T # ifdef __GNUC__ __extension__ # endif DSIZE_T c2 = (DSIZE_T)a * (DSIZE_T)b; if (c2 > max) return 1; *c = (size_t)c2; #else if (b != 0 && a > max / b) return 1; *c = a * b; #endif return 0; } static inline void * rb_alloc_tmp_buffer2(volatile VALUE *store, long count, size_t elsize) { size_t cnt = (size_t)count; if (elsize % sizeof(VALUE) == 0) { if (RB_UNLIKELY(cnt > LONG_MAX / sizeof(VALUE))) { ruby_malloc_size_overflow(cnt, elsize); } } else { size_t size, max = LONG_MAX - sizeof(VALUE) + 1; if (RB_UNLIKELY(rb_mul_size_overflow(count, elsize, max, &size))) { ruby_malloc_size_overflow(cnt, elsize); } cnt = (size + sizeof(VALUE) - 1) / sizeof(VALUE); } return rb_alloc_tmp_buffer_with_count(store, cnt * sizeof(VALUE), cnt); } /* allocates _n_ bytes temporary buffer and stores VALUE including it * in _v_. _n_ may be evaluated twice. */ #ifdef C_ALLOCA # define RB_ALLOCV(v, n) rb_alloc_tmp_buffer(&(v), (n)) # define RB_ALLOCV_N(type, v, n) \ rb_alloc_tmp_buffer2(&(v), (n), sizeof(type)))) #else # define RUBY_ALLOCV_LIMIT 1024 # define RB_ALLOCV(v, n) ((n) < RUBY_ALLOCV_LIMIT ? \ (RB_GC_GUARD(v) = 0, alloca(n)) : \ rb_alloc_tmp_buffer(&(v), (n))) # define RB_ALLOCV_N(type, v, n) \ ((type*)(((size_t)(n) < RUBY_ALLOCV_LIMIT / sizeof(type)) ? \ (RB_GC_GUARD(v) = 0, alloca((n) * sizeof(type))) : \ rb_alloc_tmp_buffer2(&(v), (n), sizeof(type)))) #endif #define RB_ALLOCV_END(v) rb_free_tmp_buffer(&(v)) #define ALLOCV(v, n) RB_ALLOCV(v, n) #define ALLOCV_N(type, v, n) RB_ALLOCV_N(type, v, n) #define ALLOCV_END(v) RB_ALLOCV_END(v) #ifndef RB_UNUSED_VAR # ifdef __GNUC__ # define RB_UNUSED_VAR(x) x __attribute__ ((unused)) # else # define RB_UNUSED_VAR(x) x # endif #endif static inline VALUE rb_obj_written(VALUE a, RB_UNUSED_VAR(VALUE oldv), VALUE b, RB_UNUSED_VAR(const char *filename), RB_UNUSED_VAR(int line)) { /* #ifdef RGENGC_LOGGING_OBJ_WRITTEN RGENGC_LOGGING_OBJ_WRITTEN(a, oldv, b, filename, line); #endif #if USE_RGENGC if (!RB_SPECIAL_CONST_P(b)) { rb_gc_writebarrier(a, b); } #endif */ return a; } static inline VALUE rb_obj_write(VALUE a, VALUE *slot, VALUE b, RB_UNUSED_VAR(const char *filename), RB_UNUSED_VAR(int line)) { /* #ifdef RGENGC_LOGGING_WRITE RGENGC_LOGGING_WRITE(a, slot, b, filename, line); #endif */ *slot = b; //#if USE_RGENGC // rb_obj_written(a, Qundef /* ignore `oldv' now */, b, filename, line); //#endif return a; } /* Write barrier (WB) interfaces: * - RB_OBJ_WRITE(a, slot, b): WB for new reference from `a' to `b'. * Write `b' into `*slot'. `slot' is a pointer in `a'. * - RB_OBJ_WRITTEN(a, oldv, b): WB for new reference from `a' to `b'. * This doesn't write any values, but only a WB declaration. * `oldv' is replaced value with `b' (not used in current Ruby). * * NOTE: The following core interfaces can be changed in the future. * Please catch up if you want to insert WB into C-extensions * correctly. */ #define RB_OBJ_WRITE(a, slot, b) rb_obj_write((VALUE)(a), (VALUE *)(slot), (VALUE)(b), __FILE__, __LINE__) #define RB_OBJ_WRITTEN(a, oldv, b) rb_obj_written((VALUE)(a), (VALUE)(oldv), (VALUE)(b), __FILE__, __LINE__) #if defined(__fcc__) || defined(__fcc_version) || \ defined(__FCC__) || defined(__FCC_VERSION) /* workaround for old version of Fujitsu C Compiler (fcc) */ # define FIX_CONST_VALUE_PTR(x) ((const VALUE *)(x)) #else # define FIX_CONST_VALUE_PTR(x) (x) #endif static inline const VALUE * rb_array_const_ptr(VALUE a) { return FIX_CONST_VALUE_PTR((RBASIC(a)->flags & RARRAY_EMBED_FLAG) ? RARRAY(a)->as.ary : RARRAY(a)->as.heap.ptr); } #define RARRAY_PTR_USE_START(a) ((VALUE *)RARRAY_CONST_PTR(a)) #define RARRAY_PTR_USE_END(a) /* */ #define RARRAY_CONST_PTR(a) rb_array_const_ptr(a) #define RARRAY_AREF(a, i) (RARRAY_CONST_PTR(a)[i]) #define RARRAY_ASET(a, i, v) do { \ const VALUE _ary = (a); \ VALUE *ptr = (VALUE *)RARRAY_PTR_USE_START(_ary); \ RB_OBJ_WRITE(_ary, &ptr[i], (v)); \ RARRAY_PTR_USE_END(_ary); \ } while (0) /* For rb_integer_pack and rb_integer_unpack: */ /* "MS" in MSWORD and MSBYTE means "most significant" */ /* "LS" in LSWORD and LSBYTE means "least significant" */ #define INTEGER_PACK_MSWORD_FIRST 0x01 #define INTEGER_PACK_LSWORD_FIRST 0x02 #define INTEGER_PACK_MSBYTE_FIRST 0x10 #define INTEGER_PACK_LSBYTE_FIRST 0x20 #define INTEGER_PACK_NATIVE_BYTE_ORDER 0x40 #define INTEGER_PACK_2COMP 0x80 #define INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION 0x400 /* For rb_integer_unpack: */ #define INTEGER_PACK_FORCE_BIGNUM 0x100 #define INTEGER_PACK_NEGATIVE 0x200 /* Combinations: */ #define INTEGER_PACK_LITTLE_ENDIAN \ (INTEGER_PACK_LSWORD_FIRST | \ INTEGER_PACK_LSBYTE_FIRST) #define INTEGER_PACK_BIG_ENDIAN \ (INTEGER_PACK_MSWORD_FIRST | \ INTEGER_PACK_MSBYTE_FIRST) int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags); VALUE rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags); size_t rb_absint_size(VALUE val, int *nlz_bits_ret); size_t rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret); int rb_absint_singlebit_p(VALUE val); #endif /* _OSSL_OPENSSL_MISSING_H_ */