/* * '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'.) */ //TAU #if defined(WIN32) || defined (WINCE) #include "windows/extconf.h" #elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) #include #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR #include "iphone/extconf.h" #else #include "macosx/extconf.h" #endif #elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) #elif defined(ANDROID) #include "android/extconf.h" #endif //TAU #include /* memcpy() */ #if !defined(OPENSSL_NO_ENGINE) # include #endif #if !defined(OPENSSL_NO_HMAC) # include #endif #include #include "ossl.h" #include "openssl_missing.h" //TAU //TAU //array.c # define ARY_SHARED_P(ary) \ (assert(!FL_TEST(ary, ELTS_SHARED) || !FL_TEST(ary, RARRAY_EMBED_FLAG)), \ FL_TEST(ary,ELTS_SHARED)!=0) # define ARY_EMBED_P(ary) \ (assert(!FL_TEST(ary, ELTS_SHARED) || !FL_TEST(ary, RARRAY_EMBED_FLAG)), \ FL_TEST(ary, RARRAY_EMBED_FLAG)!=0) #define ARY_SET_PTR(ary, p) do { \ assert(!ARY_EMBED_P(ary)); \ assert(!OBJ_FROZEN(ary)); \ RARRAY(ary)->as.heap.ptr = (p); \ } while (0) #define ARY_SET_EMBED_LEN(ary, n) do { \ long tmp_n = n; \ assert(ARY_EMBED_P(ary)); \ assert(!OBJ_FROZEN(ary)); \ RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \ RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \ } while (0) #define ARY_SET_HEAP_LEN(ary, n) do { \ assert(!ARY_EMBED_P(ary)); \ RARRAY(ary)->as.heap.len = n; \ } while (0) #define ARY_SET_PTR(ary, p) do { \ assert(!ARY_EMBED_P(ary)); \ assert(!OBJ_FROZEN(ary)); \ RARRAY(ary)->as.heap.ptr = (p); \ } while (0) #define ARY_SET_LEN(ary, n) do { \ if (ARY_EMBED_P(ary)) { \ ARY_SET_EMBED_LEN(ary, n); \ } \ else { \ ARY_SET_HEAP_LEN(ary, n); \ } \ assert(RARRAY_LEN(ary) == n); \ } while (0) #define ARY_SET(a, i, v) RARRAY_ASET((assert(!ARY_SHARED_P(a)), (a)), (i), (v)) VALUE (rb_ary_new_from_args)(long n, ...) { va_list ar; VALUE ary; long i; ary = rb_ary_new2(n); va_start(ar, n); for (i=0; i>8)&0xFF))) #endif #ifndef swap32 # ifdef HAVE_BUILTIN___BUILTIN_BSWAP32 # define swap32(x) __builtin_bswap32(x) # endif #endif #ifndef swap32 # define swap32(x) ((uint32_t)((((x)&0xFF)<<24) \ |(((x)>>24)&0xFF) \ |(((x)&0x0000FF00)<<8) \ |(((x)&0x00FF0000)>>8) )) #endif #ifndef swap64 # ifdef HAVE_BUILTIN___BUILTIN_BSWAP64 # define swap64(x) __builtin_bswap64(x) # endif #endif #ifndef swap64 # ifdef HAVE_INT64_T # define byte_in_64bit(n) ((uint64_t)0xff << (n)) # define swap64(x) ((uint64_t)((((x)&byte_in_64bit(0))<<56) \ |(((x)>>56)&0xFF) \ |(((x)&byte_in_64bit(8))<<40) \ |(((x)&byte_in_64bit(48))>>40) \ |(((x)&byte_in_64bit(16))<<24) \ |(((x)&byte_in_64bit(40))>>24) \ |(((x)&byte_in_64bit(24))<<8) \ |(((x)&byte_in_64bit(32))>>8))) # endif #endif #if SIZEOF_BDIGIT == 2 # define swap_bdigit(x) swap16(x) #elif SIZEOF_BDIGIT == 4 # define swap_bdigit(x) swap32(x) #elif SIZEOF_BDIGIT == 8 # define swap_bdigit(x) swap64(x) #endif #define roomof(x, y) (((x) + (y) - 1) / (y)) #define numberof(array) ((int)(sizeof(array) / sizeof((array)[0]))) #define bdigit_roomof(n) roomof(n, SIZEOF_BDIGIT) #define ALIGNOF(type) ((int)offsetof(struct { char f1; type f2; }, f2)) #define LSHIFTABLE(d, n) ((n) < sizeof(d) * CHAR_BIT) #define LSHIFTX(d, n) (!LSHIFTABLE(d, n) ? 0 : ((d) << (!LSHIFTABLE(d, n) ? 0 : (n)))) #define CLEAR_LOWBITS(d, numbits) ((d) & LSHIFTX(~((d)*0), (numbits))) #define FILL_LOWBITS(d, numbits) ((d) | (LSHIFTX(((d)*0+1), (numbits))-1)) #define POW2_P(x) (((x)&((x)-1))==0) #define BDIGITS_ZERO(ptr, n) do { \ BDIGIT *bdigitz_zero_ptr = (ptr); \ size_t bdigitz_zero_n = (n); \ while (bdigitz_zero_n) { \ *bdigitz_zero_ptr++ = 0; \ bdigitz_zero_n--; \ } \ } while (0) #ifdef WORDS_BIGENDIAN # define HOST_BIGENDIAN_P 1 #else # define HOST_BIGENDIAN_P 0 #endif #define INTEGER_PACK_WORDORDER_MASK \ (INTEGER_PACK_MSWORD_FIRST | \ INTEGER_PACK_LSWORD_FIRST) #define INTEGER_PACK_BYTEORDER_MASK \ (INTEGER_PACK_MSBYTE_FIRST | \ INTEGER_PACK_LSBYTE_FIRST | \ INTEGER_PACK_NATIVE_BYTE_ORDER) static void integer_pack_loop_setup( size_t numwords, size_t wordsize, size_t nails, int flags, size_t *word_num_fullbytes_ret, int *word_num_partialbits_ret, size_t *word_start_ret, ssize_t *word_step_ret, size_t *word_last_ret, size_t *byte_start_ret, int *byte_step_ret) { int wordorder_bits = flags & INTEGER_PACK_WORDORDER_MASK; int byteorder_bits = flags & INTEGER_PACK_BYTEORDER_MASK; size_t word_num_fullbytes; int word_num_partialbits; size_t word_start; ssize_t word_step; size_t word_last; size_t byte_start; int byte_step; word_num_partialbits = CHAR_BIT - (int)(nails % CHAR_BIT); if (word_num_partialbits == CHAR_BIT) word_num_partialbits = 0; word_num_fullbytes = wordsize - (nails / CHAR_BIT); if (word_num_partialbits != 0) { word_num_fullbytes--; } if (wordorder_bits == INTEGER_PACK_MSWORD_FIRST) { word_start = wordsize*(numwords-1); word_step = -(ssize_t)wordsize; word_last = 0; } else { word_start = 0; word_step = wordsize; word_last = wordsize*(numwords-1); } if (byteorder_bits == INTEGER_PACK_NATIVE_BYTE_ORDER) { #ifdef WORDS_BIGENDIAN byteorder_bits = INTEGER_PACK_MSBYTE_FIRST; #else byteorder_bits = INTEGER_PACK_LSBYTE_FIRST; #endif } if (byteorder_bits == INTEGER_PACK_MSBYTE_FIRST) { byte_start = wordsize-1; byte_step = -1; } else { byte_start = 0; byte_step = 1; } *word_num_partialbits_ret = word_num_partialbits; *word_num_fullbytes_ret = word_num_fullbytes; *word_start_ret = word_start; *word_step_ret = word_step; *word_last_ret = word_last; *byte_start_ret = byte_start; *byte_step_ret = byte_step; } #define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT) static inline void integer_pack_fill_dd(BDIGIT **dpp, BDIGIT **dep, BDIGIT_DBL *ddp, int *numbits_in_dd_p) { if (*dpp < *dep && BITSPERDIG <= (int)sizeof(*ddp) * CHAR_BIT - *numbits_in_dd_p) { *ddp |= (BDIGIT_DBL)(*(*dpp)++) << *numbits_in_dd_p; *numbits_in_dd_p += BITSPERDIG; } else if (*dpp == *dep) { /* higher bits are infinity zeros */ *numbits_in_dd_p = (int)sizeof(*ddp) * CHAR_BIT; } } static inline BDIGIT_DBL integer_pack_take_lowbits(int n, BDIGIT_DBL *ddp, int *numbits_in_dd_p) { BDIGIT_DBL ret; ret = (*ddp) & (((BDIGIT_DBL)1 << n) - 1); *ddp >>= n; *numbits_in_dd_p -= n; return ret; } static void validate_integer_pack_format(size_t numwords, size_t wordsize, size_t nails, int flags, int supported_flags) { int wordorder_bits = flags & INTEGER_PACK_WORDORDER_MASK; int byteorder_bits = flags & INTEGER_PACK_BYTEORDER_MASK; if (flags & ~supported_flags) { rb_raise(rb_eArgError, "unsupported flags specified"); } if (wordorder_bits == 0) { if (1 < numwords) rb_raise(rb_eArgError, "word order not specified"); } else if (wordorder_bits != INTEGER_PACK_MSWORD_FIRST && wordorder_bits != INTEGER_PACK_LSWORD_FIRST) rb_raise(rb_eArgError, "unexpected word order"); if (byteorder_bits == 0) { rb_raise(rb_eArgError, "byte order not specified"); } else if (byteorder_bits != INTEGER_PACK_MSBYTE_FIRST && byteorder_bits != INTEGER_PACK_LSBYTE_FIRST && byteorder_bits != INTEGER_PACK_NATIVE_BYTE_ORDER) rb_raise(rb_eArgError, "unexpected byte order"); if (wordsize == 0) rb_raise(rb_eArgError, "invalid wordsize: %"PRI_SIZE_PREFIX"u", wordsize); if (SSIZE_MAX < wordsize) rb_raise(rb_eArgError, "too big wordsize: %"PRI_SIZE_PREFIX"u", wordsize); if (wordsize <= nails / CHAR_BIT) rb_raise(rb_eArgError, "too big nails: %"PRI_SIZE_PREFIX"u", nails); if (SIZE_MAX / wordsize < numwords) rb_raise(rb_eArgError, "too big numwords * wordsize: %"PRI_SIZE_PREFIX"u * %"PRI_SIZE_PREFIX"u", numwords, wordsize); } #if !defined(WORDS_BIGENDIAN) static int bytes_2comp(unsigned char *buf, size_t len) { size_t i; for (i = 0; i < len; i++) buf[i] = ~buf[i]; for (i = 0; i < len; i++) { buf[i]++; if (buf[i] != 0) return 0; } return 1; } #endif static int bary_2comp(BDIGIT *ds, size_t n) { size_t i; i = 0; for (i = 0; i < n; i++) { if (ds[i] != 0) { goto non_zero; } } return 1; non_zero: ds[i] = BIGLO(~ds[i] + 1); i++; for (; i < n; i++) { ds[i] = BIGLO(~ds[i]); } return 0; } static void bary_swap(BDIGIT *ds, size_t num_bdigits) { BDIGIT *p1 = ds; BDIGIT *p2 = ds + num_bdigits - 1; for (; p1 < p2; p1++, p2--) { BDIGIT tmp = *p1; *p1 = *p2; *p2 = tmp; } } static int bary_pack(int sign, BDIGIT *ds, size_t num_bdigits, void *words, size_t numwords, size_t wordsize, size_t nails, int flags) { BDIGIT *dp, *de; unsigned char *buf, *bufend; dp = ds; de = ds + num_bdigits; validate_integer_pack_format(numwords, wordsize, nails, flags, INTEGER_PACK_MSWORD_FIRST| INTEGER_PACK_LSWORD_FIRST| INTEGER_PACK_MSBYTE_FIRST| INTEGER_PACK_LSBYTE_FIRST| INTEGER_PACK_NATIVE_BYTE_ORDER| INTEGER_PACK_2COMP| INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION); while (dp < de && de[-1] == 0) de--; if (dp == de) { sign = 0; } if (!(flags & INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION)) { if (sign == 0) { MEMZERO(words, unsigned char, numwords * wordsize); return 0; } if (nails == 0 && numwords == 1) { int need_swap = wordsize != 1 && (flags & INTEGER_PACK_BYTEORDER_MASK) != INTEGER_PACK_NATIVE_BYTE_ORDER && ((flags & INTEGER_PACK_MSBYTE_FIRST) ? !HOST_BIGENDIAN_P : HOST_BIGENDIAN_P); if (0 < sign || !(flags & INTEGER_PACK_2COMP)) { BDIGIT d; if (wordsize == 1) { *((unsigned char *)words) = (unsigned char)(d = dp[0]); return ((1 < de - dp || CLEAR_LOWBITS(d, 8) != 0) ? 2 : 1) * sign; } #if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGIT if (wordsize == 2 && (uintptr_t)words % ALIGNOF(uint16_t) == 0) { uint16_t u = (uint16_t)(d = dp[0]); if (need_swap) u = swap16(u); *((uint16_t *)words) = u; return ((1 < de - dp || CLEAR_LOWBITS(d, 16) != 0) ? 2 : 1) * sign; } #endif #if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGIT if (wordsize == 4 && (uintptr_t)words % ALIGNOF(uint32_t) == 0) { uint32_t u = (uint32_t)(d = dp[0]); if (need_swap) u = swap32(u); *((uint32_t *)words) = u; return ((1 < de - dp || CLEAR_LOWBITS(d, 32) != 0) ? 2 : 1) * sign; } #endif #if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGIT if (wordsize == 8 && (uintptr_t)words % ALIGNOF(uint64_t) == 0) { uint64_t u = (uint64_t)(d = dp[0]); if (need_swap) u = swap64(u); *((uint64_t *)words) = u; return ((1 < de - dp || CLEAR_LOWBITS(d, 64) != 0) ? 2 : 1) * sign; } #endif } else { /* sign < 0 && (flags & INTEGER_PACK_2COMP) */ BDIGIT_DBL_SIGNED d; if (wordsize == 1) { *((unsigned char *)words) = (unsigned char)(d = -(BDIGIT_DBL_SIGNED)dp[0]); return (1 < de - dp || FILL_LOWBITS(d, 8) != -1) ? -2 : -1; } #if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGIT if (wordsize == 2 && (uintptr_t)words % ALIGNOF(uint16_t) == 0) { uint16_t u = (uint16_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]); if (need_swap) u = swap16(u); *((uint16_t *)words) = u; return (wordsize == SIZEOF_BDIGIT && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 : (1 < de - dp || FILL_LOWBITS(d, 16) != -1) ? -2 : -1; } #endif #if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGIT if (wordsize == 4 && (uintptr_t)words % ALIGNOF(uint32_t) == 0) { uint32_t u = (uint32_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]); if (need_swap) u = swap32(u); *((uint32_t *)words) = u; return (wordsize == SIZEOF_BDIGIT && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 : (1 < de - dp || FILL_LOWBITS(d, 32) != -1) ? -2 : -1; } #endif #if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGIT if (wordsize == 8 && (uintptr_t)words % ALIGNOF(uint64_t) == 0) { uint64_t u = (uint64_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]); if (need_swap) u = swap64(u); *((uint64_t *)words) = u; return (wordsize == SIZEOF_BDIGIT && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 : (1 < de - dp || FILL_LOWBITS(d, 64) != -1) ? -2 : -1; } #endif } } #if !defined(WORDS_BIGENDIAN) if (nails == 0 && SIZEOF_BDIGIT == sizeof(BDIGIT) && (flags & INTEGER_PACK_WORDORDER_MASK) == INTEGER_PACK_LSWORD_FIRST && (flags & INTEGER_PACK_BYTEORDER_MASK) != INTEGER_PACK_MSBYTE_FIRST) { size_t src_size = (de - dp) * SIZEOF_BDIGIT; size_t dst_size = numwords * wordsize; int overflow = 0; while (0 < src_size && ((unsigned char *)ds)[src_size-1] == 0) src_size--; if (src_size <= dst_size) { MEMCPY(words, dp, char, src_size); MEMZERO((char*)words + src_size, char, dst_size - src_size); } else { MEMCPY(words, dp, char, dst_size); overflow = 1; } if (sign < 0 && (flags & INTEGER_PACK_2COMP)) { int zero_p = bytes_2comp(words, dst_size); if (zero_p && overflow) { unsigned char *p = (unsigned char *)dp; if (dst_size == src_size-1 && p[dst_size] == 1) { overflow = 0; } } } if (overflow) sign *= 2; return sign; } #endif if (nails == 0 && SIZEOF_BDIGIT == sizeof(BDIGIT) && wordsize % SIZEOF_BDIGIT == 0 && (uintptr_t)words % ALIGNOF(BDIGIT) == 0) { size_t bdigits_per_word = wordsize / SIZEOF_BDIGIT; size_t src_num_bdigits = de - dp; size_t dst_num_bdigits = numwords * bdigits_per_word; int overflow = 0; int mswordfirst_p = (flags & INTEGER_PACK_MSWORD_FIRST) != 0; int msbytefirst_p = (flags & INTEGER_PACK_NATIVE_BYTE_ORDER) ? HOST_BIGENDIAN_P : (flags & INTEGER_PACK_MSBYTE_FIRST) != 0; if (src_num_bdigits <= dst_num_bdigits) { MEMCPY(words, dp, BDIGIT, src_num_bdigits); BDIGITS_ZERO((BDIGIT*)words + src_num_bdigits, dst_num_bdigits - src_num_bdigits); } else { MEMCPY(words, dp, BDIGIT, dst_num_bdigits); overflow = 1; } if (sign < 0 && (flags & INTEGER_PACK_2COMP)) { int zero_p = bary_2comp(words, dst_num_bdigits); if (zero_p && overflow && dst_num_bdigits == src_num_bdigits-1 && dp[dst_num_bdigits] == 1) overflow = 0; } if (msbytefirst_p != HOST_BIGENDIAN_P) { size_t i; for (i = 0; i < dst_num_bdigits; i++) { BDIGIT d = ((BDIGIT*)words)[i]; ((BDIGIT*)words)[i] = swap_bdigit(d); } } if (mswordfirst_p ? !msbytefirst_p : msbytefirst_p) { size_t i; BDIGIT *p = words; for (i = 0; i < numwords; i++) { bary_swap(p, bdigits_per_word); p += bdigits_per_word; } } if (mswordfirst_p) { bary_swap(words, dst_num_bdigits); } if (overflow) sign *= 2; return sign; } } buf = words; bufend = buf + numwords * wordsize; if (buf == bufend) { /* overflow if non-zero*/ if (!(flags & INTEGER_PACK_2COMP) || 0 <= sign) sign *= 2; else { if (de - dp == 1 && dp[0] == 1) sign = -1; /* val == -1 == -2**(numwords*(wordsize*CHAR_BIT-nails)) */ else sign = -2; /* val < -1 == -2**(numwords*(wordsize*CHAR_BIT-nails)) */ } } else if (dp == de) { memset(buf, '\0', bufend - buf); } else if (dp < de && buf < bufend) { int word_num_partialbits; size_t word_num_fullbytes; ssize_t word_step; size_t byte_start; int byte_step; size_t word_start, word_last; unsigned char *wordp, *last_wordp; BDIGIT_DBL dd; int numbits_in_dd; integer_pack_loop_setup(numwords, wordsize, nails, flags, &word_num_fullbytes, &word_num_partialbits, &word_start, &word_step, &word_last, &byte_start, &byte_step); wordp = buf + word_start; last_wordp = buf + word_last; dd = 0; numbits_in_dd = 0; #define FILL_DD \ integer_pack_fill_dd(&dp, &de, &dd, &numbits_in_dd) #define TAKE_LOWBITS(n) \ integer_pack_take_lowbits(n, &dd, &numbits_in_dd) while (1) { size_t index_in_word = 0; unsigned char *bytep = wordp + byte_start; while (index_in_word < word_num_fullbytes) { FILL_DD; *bytep = TAKE_LOWBITS(CHAR_BIT); bytep += byte_step; index_in_word++; } if (word_num_partialbits) { FILL_DD; *bytep = TAKE_LOWBITS(word_num_partialbits); bytep += byte_step; index_in_word++; } while (index_in_word < wordsize) { *bytep = 0; bytep += byte_step; index_in_word++; } if (wordp == last_wordp) break; wordp += word_step; } FILL_DD; /* overflow tests */ if (dp != de || 1 < dd) { /* 2**(numwords*(wordsize*CHAR_BIT-nails)+1) <= abs(val) */ sign *= 2; } else if (dd == 1) { /* 2**(numwords*(wordsize*CHAR_BIT-nails)) <= abs(val) < 2**(numwords*(wordsize*CHAR_BIT-nails)+1) */ if (!(flags & INTEGER_PACK_2COMP) || 0 <= sign) sign *= 2; else { /* overflow_2comp && sign == -1 */ /* test lower bits are all zero. */ dp = ds; while (dp < de && *dp == 0) dp++; if (de - dp == 1 && /* only one non-zero word. */ POW2_P(*dp)) /* *dp contains only one bit set. */ sign = -1; /* val == -2**(numwords*(wordsize*CHAR_BIT-nails)) */ else sign = -2; /* val < -2**(numwords*(wordsize*CHAR_BIT-nails)) */ } } } if ((flags & INTEGER_PACK_2COMP) && (sign < 0 && numwords != 0)) { unsigned char *buf; int word_num_partialbits; size_t word_num_fullbytes; ssize_t word_step; size_t byte_start; int byte_step; size_t word_start, word_last; unsigned char *wordp, *last_wordp; unsigned int partialbits_mask; int carry; integer_pack_loop_setup(numwords, wordsize, nails, flags, &word_num_fullbytes, &word_num_partialbits, &word_start, &word_step, &word_last, &byte_start, &byte_step); partialbits_mask = (1 << word_num_partialbits) - 1; buf = words; wordp = buf + word_start; last_wordp = buf + word_last; carry = 1; while (1) { size_t index_in_word = 0; unsigned char *bytep = wordp + byte_start; while (index_in_word < word_num_fullbytes) { carry += (unsigned char)~*bytep; *bytep = (unsigned char)carry; carry >>= CHAR_BIT; bytep += byte_step; index_in_word++; } if (word_num_partialbits) { carry += (*bytep & partialbits_mask) ^ partialbits_mask; *bytep = carry & partialbits_mask; carry >>= word_num_partialbits; bytep += byte_step; index_in_word++; } if (wordp == last_wordp) break; wordp += word_step; } } return sign; #undef FILL_DD #undef TAKE_LOWBITS } static int nlz(BDIGIT x) { BDIGIT y; int n = BITSPERDIG; #if BITSPERDIG > 64 y = x >> 64; if (y) {n -= 64; x = y;} #endif #if BITSPERDIG > 32 y = x >> 32; if (y) {n -= 32; x = y;} #endif #if BITSPERDIG > 16 y = x >> 16; if (y) {n -= 16; x = y;} #endif y = x >> 8; if (y) {n -= 8; x = y;} y = x >> 4; if (y) {n -= 4; x = y;} y = x >> 2; if (y) {n -= 2; x = y;} y = x >> 1; if (y) {return n - 2;} return n - x; } /* * Calculate the number of bytes to be required to represent * the absolute value of the integer given as _val_. * * [val] an integer. * [nlz_bits_ret] number of leading zero bits in the most significant byte is returned if not NULL. * * This function returns ((val_numbits * CHAR_BIT + CHAR_BIT - 1) / CHAR_BIT) * where val_numbits is the number of bits of abs(val). * This function should not overflow. * * If nlz_bits_ret is not NULL, * (return_value * CHAR_BIT - val_numbits) is stored in *nlz_bits_ret. * In this case, 0 <= *nlz_bits_ret < CHAR_BIT. * */ size_t rb_absint_size(VALUE val, int *nlz_bits_ret) { BDIGIT *dp; BDIGIT *de; BDIGIT fixbuf[bdigit_roomof(sizeof(long))]; int num_leading_zeros; val = rb_to_int(val); if (FIXNUM_P(val)) { long v = FIX2LONG(val); if (v < 0) { v = -v; } #if SIZEOF_BDIGIT >= SIZEOF_LONG fixbuf[0] = v; #else { int i; for (i = 0; i < numberof(fixbuf); i++) { fixbuf[i] = BIGLO(v); v = BIGDN(v); } } #endif dp = fixbuf; de = fixbuf + numberof(fixbuf); } else { dp = BDIGITS(val); de = dp + BIGNUM_LEN(val); } while (dp < de && de[-1] == 0) de--; if (dp == de) { if (nlz_bits_ret) *nlz_bits_ret = 0; return 0; } num_leading_zeros = nlz(de[-1]); if (nlz_bits_ret) *nlz_bits_ret = num_leading_zeros % CHAR_BIT; return (de - dp) * SIZEOF_BDIGIT - num_leading_zeros / CHAR_BIT; } /* * Export an integer into a buffer. * * This function fills the buffer specified by _words_ and _numwords_ as * val in the format specified by _wordsize_, _nails_ and _flags_. * * [val] Fixnum, Bignum or another integer like object which has to_int method. * [words] buffer to export abs(val). * [numwords] the size of given buffer as number of words. * [wordsize] the size of word as number of bytes. * [nails] number of padding bits in a word. * Most significant nails bits of each word are filled by zero. * [flags] bitwise or of constants which name starts "INTEGER_PACK_". * * flags: * [INTEGER_PACK_MSWORD_FIRST] Store the most significant word as the first word. * [INTEGER_PACK_LSWORD_FIRST] Store the least significant word as the first word. * [INTEGER_PACK_MSBYTE_FIRST] Store the most significant byte in a word as the first byte in the word. * [INTEGER_PACK_LSBYTE_FIRST] Store the least significant byte in a word as the first byte in the word. * [INTEGER_PACK_NATIVE_BYTE_ORDER] INTEGER_PACK_MSBYTE_FIRST or INTEGER_PACK_LSBYTE_FIRST corresponding to the host's endian. * [INTEGER_PACK_2COMP] Use 2's complement representation. * [INTEGER_PACK_LITTLE_ENDIAN] Same as INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_LSBYTE_FIRST * [INTEGER_PACK_BIG_ENDIAN] Same as INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_MSBYTE_FIRST * [INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION] Use generic implementation (for test and debug). * * This function fills the buffer specified by _words_ * as abs(val) if INTEGER_PACK_2COMP is not specified in _flags_. * If INTEGER_PACK_2COMP is specified, 2's complement representation of val is * filled in the buffer. * * This function returns the signedness and overflow condition. * The overflow condition depends on INTEGER_PACK_2COMP. * * INTEGER_PACK_2COMP is not specified: * -2 : negative overflow. val <= -2**(numwords*(wordsize*CHAR_BIT-nails)) * -1 : negative without overflow. -2**(numwords*(wordsize*CHAR_BIT-nails)) < val < 0 * 0 : zero. val == 0 * 1 : positive without overflow. 0 < val < 2**(numwords*(wordsize*CHAR_BIT-nails)) * 2 : positive overflow. 2**(numwords*(wordsize*CHAR_BIT-nails)) <= val * * INTEGER_PACK_2COMP is specified: * -2 : negative overflow. val < -2**(numwords*(wordsize*CHAR_BIT-nails)) * -1 : negative without overflow. -2**(numwords*(wordsize*CHAR_BIT-nails)) <= val < 0 * 0 : zero. val == 0 * 1 : positive without overflow. 0 < val < 2**(numwords*(wordsize*CHAR_BIT-nails)) * 2 : positive overflow. 2**(numwords*(wordsize*CHAR_BIT-nails)) <= val * * The value, -2**(numwords*(wordsize*CHAR_BIT-nails)), is representable * in 2's complement representation but not representable in absolute value. * So -1 is returned for the value if INTEGER_PACK_2COMP is specified * but returns -2 if INTEGER_PACK_2COMP is not specified. * * The least significant words are filled in the buffer when overflow occur. */ int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags) { int sign; BDIGIT *ds; size_t num_bdigits; BDIGIT fixbuf[bdigit_roomof(sizeof(long))]; RB_GC_GUARD(val) = rb_to_int(val); if (FIXNUM_P(val)) { long v = FIX2LONG(val); if (v < 0) { sign = -1; v = -v; } else { sign = 1; } #if SIZEOF_BDIGIT >= SIZEOF_LONG fixbuf[0] = v; #else { int i; for (i = 0; i < numberof(fixbuf); i++) { fixbuf[i] = BIGLO(v); v = BIGDN(v); } } #endif ds = fixbuf; num_bdigits = numberof(fixbuf); } else { sign = BIGNUM_POSITIVE_P(val) ? 1 : -1; ds = BDIGITS(val); num_bdigits = BIGNUM_LEN(val); } return bary_pack(sign, ds, num_bdigits, words, numwords, wordsize, nails, flags); } //gc.c //TAU # define ATOMIC_EXCHANGE(var, val) ruby_atomic_exchange(&(var), (val)) # ifndef ATOMIC_VALUE_EXCHANGE # define ATOMIC_VALUE_EXCHANGE(var, val) ATOMIC_EXCHANGE(var, val) # endif # ifndef ATOMIC_PTR_EXCHANGE # define ATOMIC_PTR_EXCHANGE(var, val) ATOMIC_EXCHANGE(var, val) # endif void rb_free_tmp_buffer(volatile VALUE *store) { VALUE s = ATOMIC_VALUE_EXCHANGE(*store, 0); if (s) { void *ptr = ATOMIC_PTR_EXCHANGE(RNODE(s)->u1.node, 0); RNODE(s)->u3.cnt = 0; ruby_xfree(ptr); } } void ruby_malloc_size_overflow(size_t count, size_t elsize) { rb_raise(rb_eArgError, "malloc: possible integer overflow (%"PRIdSIZE"*%"PRIdSIZE")", count, elsize); } static void * ruby_xmalloc0(size_t size) { //TAU return ruby_xmalloc(size); //return objspace_xmalloc0(&rb_objspace, size); } void * rb_alloc_tmp_buffer_with_count(volatile VALUE *store, size_t size, size_t cnt) { NODE *s; void *ptr; s = rb_node_newnode(NODE_ALLOCA, 0, 0, 0); ptr = ruby_xmalloc0(size); s->u1.value = (VALUE)ptr; s->u3.cnt = cnt; *store = (VALUE)s; return ptr; } //hash.c //TAU VALUE rb_hash_set_ifnone(VALUE hash, VALUE ifnone) { RB_OBJ_WRITE(hash, (&RHASH(hash)->ifnone), ifnone); return hash; } // //signal.c //TAU #ifdef _WIN32 typedef LONG rb_atomic_t; # define ATOMIC_TEST(var) InterlockedExchange(&(var), 0) # define ATOMIC_SET(var, val) InterlockedExchange(&(var), (val)) # define ATOMIC_INC(var) InterlockedIncrement(&(var)) # define ATOMIC_DEC(var) InterlockedDecrement(&(var)) #else typedef int rb_atomic_t; # define ATOMIC_TEST(var) ((var) ? ((var) = 0, 1) : 0) # define ATOMIC_SET(var, val) ((var) = (val)) # define ATOMIC_INC(var) (++(var)) # define ATOMIC_DEC(var) (--(var)) #endif rb_atomic_t ruby_atomic_exchange(rb_atomic_t *ptr, rb_atomic_t val) { rb_atomic_t old = *ptr; *ptr = val; return old; } //TAU /* added in 0.9.8X */ #if !defined(HAVE_EVP_CIPHER_CTX_NEW) EVP_CIPHER_CTX * EVP_CIPHER_CTX_new(void) { EVP_CIPHER_CTX *ctx = OPENSSL_malloc(sizeof(EVP_CIPHER_CTX)); if (!ctx) return NULL; EVP_CIPHER_CTX_init(ctx); return ctx; } #endif #if !defined(HAVE_EVP_CIPHER_CTX_FREE) void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx) { if (ctx) { EVP_CIPHER_CTX_cleanup(ctx); OPENSSL_free(ctx); } } #endif /* added in 1.0.0 */ #if !defined(HAVE_EVP_CIPHER_CTX_COPY) /* * this function does not exist in OpenSSL yet... or ever?. * a future version may break this function. * tested on 0.9.7d. */ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in) { memcpy(out, in, sizeof(EVP_CIPHER_CTX)); #if !defined(OPENSSL_NO_ENGINE) if (in->engine) ENGINE_add(out->engine); if (in->cipher_data) { out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size); memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size); } #endif return 1; } #endif #if !defined(OPENSSL_NO_HMAC) #if !defined(HAVE_HMAC_CTX_COPY) int HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in) { if (!out || !in) return 0; memcpy(out, in, sizeof(HMAC_CTX)); EVP_MD_CTX_copy(&out->md_ctx, &in->md_ctx); EVP_MD_CTX_copy(&out->i_ctx, &in->i_ctx); EVP_MD_CTX_copy(&out->o_ctx, &in->o_ctx); return 1; } #endif /* HAVE_HMAC_CTX_COPY */ #endif /* NO_HMAC */ /* added in 1.0.2 */ #if !defined(OPENSSL_NO_EC) #if !defined(HAVE_EC_CURVE_NIST2NID) static struct { const char *name; int nid; } nist_curves[] = { {"B-163", NID_sect163r2}, {"B-233", NID_sect233r1}, {"B-283", NID_sect283r1}, {"B-409", NID_sect409r1}, {"B-571", NID_sect571r1}, {"K-163", NID_sect163k1}, {"K-233", NID_sect233k1}, {"K-283", NID_sect283k1}, {"K-409", NID_sect409k1}, {"K-571", NID_sect571k1}, {"P-192", NID_X9_62_prime192v1}, {"P-224", NID_secp224r1}, {"P-256", NID_X9_62_prime256v1}, {"P-384", NID_secp384r1}, {"P-521", NID_secp521r1} }; int EC_curve_nist2nid(const char *name) { size_t i; for (i = 0; i < (sizeof(nist_curves) / sizeof(nist_curves[0])); i++) { if (!strcmp(nist_curves[i].name, name)) return nist_curves[i].nid; } return NID_undef; } #endif #endif /*** added in 1.1.0 ***/ #if !defined(HAVE_HMAC_CTX_NEW) HMAC_CTX * HMAC_CTX_new(void) { HMAC_CTX *ctx = OPENSSL_malloc(sizeof(HMAC_CTX)); if (!ctx) return NULL; HMAC_CTX_init(ctx); return ctx; } #endif #if !defined(HAVE_HMAC_CTX_FREE) void HMAC_CTX_free(HMAC_CTX *ctx) { if (ctx) { HMAC_CTX_cleanup(ctx); OPENSSL_free(ctx); } } #endif #if !defined(HAVE_X509_CRL_GET0_SIGNATURE) void X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig, const X509_ALGOR **palg) { if (psig != NULL) *psig = crl->signature; if (palg != NULL) *palg = crl->sig_alg; } #endif #if !defined(HAVE_X509_REQ_GET0_SIGNATURE) void X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig, const X509_ALGOR **palg) { if (psig != NULL) *psig = req->signature; if (palg != NULL) *palg = req->sig_alg; } #endif