Skip to content

Commit

Permalink
Merge branch 'master' of github.com:emboss/krypt-core
Browse files Browse the repository at this point in the history
  • Loading branch information
emboss committed Jan 31, 2012
2 parents cf748d8 + ab71e01 commit 0eebcf2
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 11 deletions.
1 change: 1 addition & 0 deletions ext/krypt/core/extconf.rb
Expand Up @@ -36,6 +36,7 @@

have_header("ruby/io.h")
have_func("rb_io_check_byte_readable")
have_func("rb_big_pack")


create_header
Expand Down
2 changes: 2 additions & 0 deletions ext/krypt/core/krypt_asn1.c
Expand Up @@ -185,6 +185,8 @@ int_determine_class(krypt_asn1_header *header)
if (header->tag_class == TAG_CLASS_UNIVERSAL) {
if (header->tag > 30)
rb_raise(eKryptASN1Error, "Universal tag too large: %d", header->tag);
if (!krypt_asn1_infos[header->tag].klass)
rb_raise(eKryptASN1Error, "Unsupported tag number: %d", header->tag);
return *(krypt_asn1_infos[header->tag].klass);
}
else {
Expand Down
77 changes: 66 additions & 11 deletions ext/krypt/core/krypt_asn1_codec.c
Expand Up @@ -54,9 +54,11 @@ static VALUE int_parse_utc_time(unsigned char *, size_t);
static VALUE int_parse_generalized_time(unsigned char *, size_t);
static size_t int_encode_utc_time(VALUE, unsigned char **);
static size_t int_encode_generalized_time(VALUE, unsigned char **);
static size_t int_encode_integer_bignum(VALUE, unsigned char **);
static size_t int_encode_integer(long, unsigned char **);
static VALUE int_decode_integer(unsigned char *, size_t);
#if defined(HAVE_RB_BIG_PACK)
static size_t int_encode_integer_bignum(VALUE, unsigned char **);
#endif

#define sanity_check(b) \
do { \
Expand Down Expand Up @@ -124,12 +126,12 @@ int_asn1_encode_integer(VALUE self, VALUE value, unsigned char **out)
{
long num;

#if defined(HAVE_RB_BIG_PACK)
if (TYPE(value) == T_BIGNUM) {
return int_encode_integer_bignum(value, out);
}

#endif
num = NUM2LONG(value);

return int_encode_integer(num, out);
}

Expand All @@ -140,6 +142,13 @@ int_asn1_decode_integer(VALUE self, unsigned char *bytes, size_t len)
rb_raise(eKryptASN1Error, "Size 0 for integer value");
sanity_check(bytes);

#if !defined(HAVE_RB_BIG_PACK)
if ((bytes[0] == 0x0 && len > sizeof(long) + 1) ||
(bytes[0] != 0x0 && len > sizeof(long))) {
rb_raise(eKryptASN1Error, "Size of integer too long: %ld", len);
}
#endif

return int_decode_integer(bytes, len);
}

Expand Down Expand Up @@ -668,14 +677,7 @@ int_parse_generalized_time(unsigned char *bytes, size_t len)
return rb_funcall2(rb_cTime, rb_intern("utc"), 6, argv);
}

#define int_long_byte_len(ret, l) \
do { \
unsigned long tmp = (unsigned long) (l); \
(ret) = 1; \
while (tmp >>= CHAR_BIT) \
(ret)++; \
} while (0)

#if defined(HAVE_RB_BIG_PACK)
/* TODO: This function uses rb_big_pack which is in intern.h. We need to
* implement String <-> binary converter by ourselves for Rubinius support.
*/
Expand Down Expand Up @@ -727,6 +729,7 @@ int_encode_integer_bignum(VALUE big, unsigned char **out) {

return ptr - bytes;
}
#endif

static size_t
int_encode_integer(long num, unsigned char **out)
Expand Down Expand Up @@ -763,6 +766,7 @@ int_encode_integer(long num, unsigned char **out)
return ptr - bytes;
}

#if defined(HAVE_RB_BIG_PACK)
/* TODO: This function uses rb_big_unpack which is in intern.h. We need to
* implement String <-> binary converter by ourselves for Rubinius support.
*
Expand Down Expand Up @@ -797,5 +801,56 @@ int_decode_integer(unsigned char *bytes, size_t len)
if (TYPE(value) == T_BIGNUM) {
RBIGNUM_SET_SIGN(value, !sign);
}
xfree(longs);
return value;
}

#else

static VALUE
int_decode_positive_integer(unsigned char *bytes, size_t len)
{
unsigned long num = 0;
size_t i;

for (i = 0; i < len; i++)
num |= bytes[i] << ((len - i - 1) * CHAR_BIT);

if (num > LONG_MAX)
rb_raise(eKryptASN1Error, "Integer too large: %lu", num);

return LONG2NUM((long)num);
}

static VALUE
int_decode_negative_integer(unsigned char *bytes, size_t len)
{
long num = 0;
size_t i;
unsigned char b;
size_t size = sizeof(long);

/* Fill with 0xff from MSB down to len-th byte, then
* fill with bytes in successive order */
for (i = 0; i < size; i++) {
b = i < size - len ? 0xff : bytes[i - (size - len)];
num |= b << ((size - i - 1) * CHAR_BIT);
}

return LONG2NUM(num);
}

static VALUE
int_decode_integer(unsigned char *bytes, size_t len)
{
if (bytes[0] & 0x80) {
return int_decode_negative_integer(bytes, len);
}
else {
if (bytes[0] == 0x0)
return int_decode_positive_integer(bytes + 1, len - 1);
else
return int_decode_positive_integer(bytes, len);
}
}
#endif

0 comments on commit 0eebcf2

Please sign in to comment.