Permalink
Browse files

Add full PEM support. Revisit C namespaces again.

ASN.1 now fully supports PEM decoding, too. There's also a separate Krypt::PEM.decode that allows to treat PEM data with multiple values easily.
Correctly namespaced typedefs and globals now, too.
  • Loading branch information...
1 parent 0eebcf2 commit 685443010fdc31cf2b21ff62bebcc559ce2a97c9 @emboss committed Feb 7, 2012
View
2 .gitignore
@@ -12,4 +12,4 @@ ext/krypt/core/doc
*.so
*.o
.rbx/
-
+nbproject
View
4 Rakefile
@@ -54,6 +54,10 @@ task 'coverage' => ['enable-coverage', 'compile', 'spec', 'report-coverage']
task :build => :compile
+namespace :build do
+ task :debug => ['enable-coverage', 'build']
+end
+
Rake::RDocTask.new("doc") do |rdoc|
rdoc.rdoc_dir = 'doc'
rdoc.title = "Krypt-Core API: Version #{Krypt::CORE_VERSION}"
View
6 ext/krypt/core/extconf.rb
@@ -25,7 +25,7 @@
message "=== krypt-core API - C version ===\n"
if debug && CONFIG['GCC'] == 'yes'
- flags = "--coverage -g -fprofile-arcs -ftest-coverage"
+ flags = "--coverage -g3 -fprofile-arcs -ftest-coverage"
message "!! set #{flags} for coverage !!"
$CFLAGS += " #{flags}"
$DLDFLAGS += " #{flags}"
@@ -37,7 +37,9 @@
have_header("ruby/io.h")
have_func("rb_io_check_byte_readable")
have_func("rb_big_pack")
-
+have_func("rb_block_call")
+have_func("rb_enumeratorize")
+have_func("rb_str_encode")
create_header
create_makefile("kryptcore")
View
12 ext/krypt/core/krypt-core.c
@@ -15,15 +15,15 @@
VALUE mKrypt;
VALUE eKryptError;
-ID sID_TO_DER;
-ID sID_EACH;
+ID sKrypt_ID_TO_DER;
+ID sKrypt_ID_EACH;
VALUE
krypt_to_der(VALUE obj)
{
VALUE tmp;
- tmp = rb_funcall(obj, sID_TO_DER, 0);
+ tmp = rb_funcall(obj, sKrypt_ID_TO_DER, 0);
StringValue(tmp);
return tmp;
@@ -32,7 +32,7 @@ krypt_to_der(VALUE obj)
VALUE
krypt_to_der_if_possible(VALUE obj)
{
- if(rb_respond_to(obj, sID_TO_DER))
+ if(rb_respond_to(obj, sKrypt_ID_TO_DER))
return krypt_to_der(obj);
return obj;
}
@@ -44,8 +44,8 @@ Init_kryptcore(void)
eKryptError = rb_define_class_under(mKrypt, "KryptError", rb_eStandardError);
- sID_TO_DER = rb_intern("to_der");
- sID_EACH = rb_intern("each");
+ sKrypt_ID_TO_DER = rb_intern("to_der");
+ sKrypt_ID_EACH = rb_intern("each");
/* Init components */
Init_krypt_io();
View
10 ext/krypt/core/krypt-core.h
@@ -39,8 +39,8 @@ extern VALUE mKrypt;
extern VALUE eKryptError;
-extern ID sID_TO_DER;
-extern ID sID_EACH;
+extern ID sKrypt_ID_TO_DER;
+extern ID sKrypt_ID_EACH;
/** krypt-core headers **/
#include "krypt_missing.h"
@@ -50,6 +50,12 @@ extern ID sID_EACH;
VALUE krypt_to_der_if_possible(VALUE);
VALUE krypt_to_der(VALUE);
+/* internal Base64 en-/decoder */
+size_t krypt_base64_encode(unsigned char *bytes, size_t len, int cols, unsigned char **out);
+void krypt_base64_buffer_encode_to(krypt_outstream *out, unsigned char *bytes, size_t off, size_t len, int cols);
+size_t krypt_base64_decode(unsigned char *bytes, size_t len, unsigned char **out);
+void krypt_base64_buffer_decode_to(krypt_outstream *out, unsigned char *bytes, size_t off, size_t len);
+
void Init_kryptcore(void);
void Init_krypt_io(void);
void InitVM_krypt_io(void);
View
77 ext/krypt/core/krypt_asn1-internal.c
@@ -14,13 +14,13 @@
#include "krypt-core.h"
#include "krypt_asn1-internal.h"
-static const int TAG_LIMIT = INT_MAX >> CHAR_BIT_MINUS_ONE;
-static const size_t LENGTH_LIMIT = SIZE_MAX >> CHAR_BIT;
+static const int KRYPT_ASN1_TAG_LIMIT = INT_MAX >> CHAR_BIT_MINUS_ONE;
+static const size_t KRYPT_ASN1_LENGTH_LIMIT = SIZE_MAX >> CHAR_BIT;
#define int_next_byte(in, b) \
do { \
if (krypt_instream_read((in), &(b), 1) != 1) \
- rb_raise(eKryptParseError, "Error while parsing."); \
+ rb_raise(eKryptASN1ParseError, "Error while parsing."); \
} while (0) \
static void int_parse_complex_tag(unsigned char b, krypt_instream *in, krypt_asn1_header *out);
@@ -58,21 +58,21 @@ krypt_asn1_next_header(krypt_instream *in, krypt_asn1_header **out)
unsigned char b;
krypt_asn1_header *header;
- if (!in) rb_raise(eKryptParseError, "Stream is not initialized");
+ if (!in) rb_raise(eKryptASN1ParseError, "Stream is not initialized");
read = krypt_instream_read(in, &b, 1);
if (read == -1)
return 0;
if (read != 1)
- rb_raise(eKryptParseError, "Error when parsing stream");
+ rb_raise(eKryptASN1ParseError, "Error when parsing stream");
header = krypt_asn1_header_new();
int_parse_tag(b, in, header);
int_parse_length(in, header);
if (header->is_infinite && !header->is_constructed)
- rb_raise(eKryptParseError, "Infinite length values must be constructed");
+ rb_raise(eKryptASN1ParseError, "Infinite length values must be constructed");
*out = header;
return 1;
@@ -211,57 +211,6 @@ krypt_asn1_object_encode(krypt_outstream *out, krypt_asn1_object *object)
}
/**
- * Returns an ID representing the Symbol that stands for the corresponding
- * tag class.
- *
- * @param tag_class The raw tag class value
- * @return A Ruby Symbol representing the tag class, e.g.
- * :UNIVERSAL
- * @raises Krypt::ASN1::ASN1Error if tag_class is unknown
- */
-ID
-krypt_asn1_tag_class_for_int(int tag_class)
-{
- switch (tag_class) {
- case TAG_CLASS_UNIVERSAL:
- return sTC_UNIVERSAL;
- case TAG_CLASS_APPLICATION:
- return sTC_APPLICATION;
- case TAG_CLASS_CONTEXT_SPECIFIC:
- return sTC_CONTEXT_SPECIFIC;
- case TAG_CLASS_PRIVATE:
- return sTC_PRIVATE;
- default:
- rb_raise(eKryptASN1Error, "Unknown tag class");
- return Qnil;
- }
-}
-
-/**
- * Returns an integer representing the tag class of the corresponding
- * symbol.
- *
- * @param tag_class The tag class ID
- * @return An integer representing the tag class
- * @raises Krypt::ASN1::ASN1Error if tag_class is unknown
- */
-int
-krypt_asn1_tag_class_for_id(ID tag_class)
-{
- if (tag_class == sTC_UNIVERSAL)
- return TAG_CLASS_UNIVERSAL;
- else if (tag_class == sTC_APPLICATION)
- return TAG_CLASS_APPLICATION;
- else if (tag_class == sTC_CONTEXT_SPECIFIC)
- return TAG_CLASS_CONTEXT_SPECIFIC;
- else if (tag_class == sTC_PRIVATE)
- return TAG_CLASS_PRIVATE;
-
- rb_raise(eKryptASN1Error, "Unknown tag class");
- return Qnil;
-}
-
-/**
* Creates a new krypt_asn1_header struct.
* @return a newly allocated krypt_asn1_header
* @raises NoMemoryError when allocation fails
@@ -374,14 +323,14 @@ int_parse_primitive_tag(unsigned char b, krypt_instream *in, krypt_asn1_header *
do { \
krypt_buffer_write((buf), &(b), 1); \
if ((out)->header_length == SIZE_MAX) \
- rb_raise(eKryptParseError, "Complex tag too long"); \
+ rb_raise(eKryptASN1ParseError, "Complex tag too long"); \
(out)->header_length++; \
} while (0)
#define int_check_tag(t) \
do { \
- if ((t) > TAG_LIMIT) \
- rb_raise(eKryptParseError, "Complex tag too long"); \
+ if ((t) > KRYPT_ASN1_TAG_LIMIT) \
+ rb_raise(eKryptASN1ParseError, "Complex tag too long"); \
} while (0)
static void
@@ -455,7 +404,7 @@ int_parse_complex_definite_length(unsigned char b, krypt_instream *in, krypt_asn
num_bytes = b & 0x7f;
if (num_bytes + 1 > sizeof(size_t))
- rb_raise(eKryptParseError, "Definite value length too long");
+ rb_raise(eKryptASN1ParseError, "Definite value length too long");
out->length_bytes = ALLOC_N(unsigned char, num_bytes + 1);
out->length_bytes[offset++] = b;
@@ -465,8 +414,8 @@ int_parse_complex_definite_length(unsigned char b, krypt_instream *in, krypt_asn
out->header_length++;
len <<= CHAR_BIT;
len |= b;
- if (len > LENGTH_LIMIT || offset == SIZE_MAX || out->header_length == SIZE_MAX)
- rb_raise(eKryptParseError, "Complex length too long");
+ if (len > KRYPT_ASN1_LENGTH_LIMIT || offset == SIZE_MAX || out->header_length == SIZE_MAX)
+ rb_raise(eKryptASN1ParseError, "Complex length too long");
out->length_bytes[offset++] = b;
}
@@ -490,7 +439,7 @@ int_parse_read_exactly(krypt_instream *in, size_t n)
while (offset != n) {
read = krypt_instream_read(in, p, n - offset);
if (read == -1) {
- rb_raise(eKryptParseError, "Premature EOF detected.");
+ rb_raise(eKryptASN1ParseError, "Premature EOF detected.");
return NULL; /* dummy */
}
p += read;
View
225 ext/krypt/core/krypt_asn1.c
@@ -14,7 +14,7 @@
#include "krypt_asn1-internal.h"
VALUE mKryptASN1;
-VALUE eKryptASN1Error, eKryptParseError, eKryptSerializeError;
+VALUE eKryptASN1Error, eKryptASN1ParseError, eKryptASN1SerializeError;
VALUE cKryptASN1Data;
VALUE cKryptASN1Primitive;
@@ -38,9 +38,9 @@ VALUE cKryptASN1UTCTime, cKryptASN1GeneralizedTime; /* TIME */
/* CONSTRUCTIVE */
VALUE cKryptASN1Sequence, cKryptASN1Set;
-ID sTC_UNIVERSAL, sTC_APPLICATION, sTC_CONTEXT_SPECIFIC, sTC_PRIVATE;
+ID sKrypt_TC_UNIVERSAL, sKrypt_TC_APPLICATION, sKrypt_TC_CONTEXT_SPECIFIC, sKrypt_TC_PRIVATE;
-ID sIV_TAG, sIV_TAG_CLASS, sIV_INF_LEN, sIV_VALUE, sIV_UNUSED_BITS;
+ID sKrypt_IV_TAG, sKrypt_IV_TAG_CLASS, sKrypt_IV_INF_LEN, sKrypt_IV_VALUE, sKrypt_IV_UNUSED_BITS;
typedef struct krypt_asn1_info_st {
const char *name;
@@ -85,11 +85,11 @@ static int krypt_asn1_infos_size = (sizeof(krypt_asn1_infos)/sizeof(krypt_asn1_i
struct krypt_asn1_data_st;
typedef struct krypt_asn1_data_st krypt_asn1_data;
-typedef void (*int_asn1_codec_cb)(krypt_asn1_data *);
+typedef void (*krypt_asn1_codec_cb)(krypt_asn1_data *);
struct krypt_asn1_data_st {
krypt_asn1_object *object;
- int_asn1_codec_cb codec_cb;
+ krypt_asn1_codec_cb codec_cb;
krypt_asn1_codec *codec;
unsigned short is_decoded;
};
@@ -146,15 +146,15 @@ do { \
} \
} while (0)
-#define int_asn1_data_get_tag(o) rb_ivar_get((o), sIV_TAG)
-#define int_asn1_data_get_tag_class(o) rb_ivar_get((o), sIV_TAG_CLASS)
-#define int_asn1_data_get_infinite_length(o) rb_ivar_get((o), sIV_INF_LEN)
-#define int_asn1_data_get_value(o) rb_ivar_get((o), sIV_VALUE)
+#define int_asn1_data_get_tag(o) rb_ivar_get((o), sKrypt_IV_TAG)
+#define int_asn1_data_get_tag_class(o) rb_ivar_get((o), sKrypt_IV_TAG_CLASS)
+#define int_asn1_data_get_infinite_length(o) rb_ivar_get((o), sKrypt_IV_INF_LEN)
+#define int_asn1_data_get_value(o) rb_ivar_get((o), sKrypt_IV_VALUE)
-#define int_asn1_data_set_tag(o, v) rb_ivar_set((o), sIV_TAG, (v))
-#define int_asn1_data_set_tag_class(o, v) rb_ivar_set((o), sIV_TAG_CLASS, (v))
-#define int_asn1_data_set_infinite_length(o, v) rb_ivar_set((o), sIV_INF_LEN, (v))
-#define int_asn1_data_set_value(o, v) rb_ivar_set((o), sIV_VALUE, (v))
+#define int_asn1_data_set_tag(o, v) rb_ivar_set((o), sKrypt_IV_TAG, (v))
+#define int_asn1_data_set_tag_class(o, v) rb_ivar_set((o), sKrypt_IV_TAG_CLASS, (v))
+#define int_asn1_data_set_infinite_length(o, v) rb_ivar_set((o), sKrypt_IV_INF_LEN, (v))
+#define int_asn1_data_set_value(o, v) rb_ivar_set((o), sKrypt_IV_VALUE, (v))
/* Declaration of en-/decode callbacks */
static VALUE int_asn1_data_value_decode(VALUE self, krypt_asn1_data *data);
@@ -171,7 +171,7 @@ int_handle_class_specifics(VALUE self, krypt_asn1_header *header)
if (header->tag_class == TAG_CLASS_UNIVERSAL) {
switch (header->tag) {
case TAGS_BIT_STRING:
- rb_ivar_set(self, sIV_UNUSED_BITS, INT2NUM(0));
+ rb_ivar_set(self, sKrypt_IV_UNUSED_BITS, INT2NUM(0));
break;
default:
break;
@@ -301,10 +301,10 @@ krypt_asn1_data_initialize(VALUE self, VALUE value, VALUE vtag, VALUE vtag_class
int_validate_tag_and_class(vtag, vtag_class);
tag = NUM2INT(vtag);
stag_class = SYM2ID(vtag_class);
- if (stag_class == sTC_UNIVERSAL && tag > 30)
+ if (stag_class == sKrypt_TC_UNIVERSAL && tag > 30)
rb_raise(eKryptASN1Error, "Tag too large for UNIVERSAL tag class");
tag_class = krypt_asn1_tag_class_for_id(stag_class);
- is_constructed = rb_respond_to(value, sID_EACH);
+ is_constructed = rb_respond_to(value, sKrypt_ID_EACH);
int_asn1_data_initialize(self, tag, tag_class, is_constructed, 0);
@@ -334,11 +334,11 @@ int_asn1_default_initialize(VALUE self,
int_validate_tag_and_class(vtag, vtag_class);
tag = NUM2INT(vtag);
stag_class = SYM2ID(vtag_class);
- if (stag_class == sTC_UNIVERSAL && tag > 30)
+ if (stag_class == sKrypt_TC_UNIVERSAL && tag > 30)
rb_raise(eKryptASN1Error, "Tag too large for UNIVERSAL tag class");
tag_class = krypt_asn1_tag_class_for_id(stag_class);
- is_constructed = rb_respond_to(value, sID_EACH);
+ is_constructed = rb_respond_to(value, sKrypt_ID_EACH);
int_asn1_data_initialize(self,
tag,
@@ -372,9 +372,9 @@ do { \
if ((argc) == 3) \
rb_raise(eKryptASN1Error, "Tag class must be a Symbol"); \
if (NIL_P((tag))) \
- (tc) = ID2SYM(sTC_UNIVERSAL); \
+ (tc) = ID2SYM(sKrypt_TC_UNIVERSAL); \
else \
- (tc) = ID2SYM(sTC_CONTEXT_SPECIFIC); \
+ (tc) = ID2SYM(sKrypt_TC_CONTEXT_SPECIFIC); \
} \
if (NIL_P((tag))) { \
(tag) = INT2NUM((defaulttag)); \
@@ -403,7 +403,7 @@ krypt_asn1_end_of_contents_initialize(int argc, VALUE *argv, VALUE self)
}
tag = INT2NUM(TAGS_END_OF_CONTENTS);
- tag_class = ID2SYM(sTC_UNIVERSAL);
+ tag_class = ID2SYM(sKrypt_TC_UNIVERSAL);
return int_asn1_default_initialize(self,
value,
tag,
@@ -421,7 +421,7 @@ krypt_asn1_null_initialize(int argc, VALUE *argv, VALUE self)
if (argc == 0) {
value = Qnil;
tag = INT2NUM(TAGS_NULL);
- tag_class = ID2SYM(sTC_UNIVERSAL);
+ tag_class = ID2SYM(sKrypt_TC_UNIVERSAL);
}
else {
rb_scan_args(argc, argv, "12", &value, &tag, &tag_class);
@@ -453,7 +453,7 @@ krypt_asn1_bit_string_initialize(int argc, VALUE *argv, VALUE self)
TAGS_BIT_STRING,
tag_class);
- rb_ivar_set(self, sIV_UNUSED_BITS, INT2NUM(0));
+ rb_ivar_set(self, sKrypt_IV_UNUSED_BITS, INT2NUM(0));
return self;
}
@@ -725,7 +725,7 @@ krypt_asn1_data_set_value(VALUE self, VALUE value)
/* Free data that is now stale */
object = data->object;
int_invalidate_value(object);
- is_constructed = rb_respond_to(value, sID_EACH);
+ is_constructed = rb_respond_to(value, sKrypt_ID_EACH);
if (object->header->is_constructed != is_constructed) {
object->header->is_constructed = is_constructed;
int_invalidate_tag(object->header);
@@ -846,11 +846,13 @@ krypt_asn1_cons_each(VALUE self)
{
VALUE enumerable = krypt_asn1_data_get_value(self);
+#ifdef HAVE_RB_ENUMERATORIZE
RETURN_ENUMERATOR(enumerable, 0, 0);
+#endif
if (rb_obj_is_kind_of(enumerable, rb_cArray))
rb_ary_each(krypt_asn1_data_get_value(self));
else
- rb_block_call(enumerable, sID_EACH, 0, 0, int_cons_each_i, 0);
+ rb_block_call(enumerable, sKrypt_ID_EACH, 0, 0, int_cons_each_i, 0);
return enumerable;
}
@@ -917,7 +919,7 @@ int_cons_encode_sub_elems(krypt_outstream *out, VALUE enumerable)
else {
VALUE wrapped_out;
wrapped_out = Data_Wrap_Struct(rb_cObject, 0, 0, out);
- rb_block_call(enumerable, sID_EACH, 0, 0, int_cons_encode_sub_elems_i, wrapped_out);
+ rb_block_call(enumerable, sKrypt_ID_EACH, 0, 0, int_cons_encode_sub_elems_i, wrapped_out);
}
}
@@ -993,7 +995,7 @@ int_asn1_prim_encode_to(VALUE self, krypt_outstream *out, VALUE value, krypt_asn
static VALUE
krypt_asn1_bit_string_set_unused_bits(VALUE self, VALUE unused_bits)
{
- rb_ivar_set(self, sIV_UNUSED_BITS, unused_bits);
+ rb_ivar_set(self, sKrypt_IV_UNUSED_BITS, unused_bits);
return unused_bits;
}
@@ -1006,11 +1008,63 @@ static VALUE
krypt_asn1_bit_string_get_unused_bits(VALUE self)
{
int_asn1_decode_value(self);
- return rb_ivar_get(self, sIV_UNUSED_BITS);
+ return rb_ivar_get(self, sKrypt_IV_UNUSED_BITS);
}
/* End ASN1Primitive methods */
+static VALUE
+int_asn1_decode(krypt_instream *in)
+{
+ krypt_asn1_header *header;
+
+ if (krypt_asn1_next_header(in, &header) == 0) {
+ rb_raise(eKryptASN1ParseError, "Could not parse data");
+ }
+
+ return krypt_asn1_data_new(in, header);
+}
+
+static VALUE
+int_asn1_rewind_stream(krypt_instream *in)
+{
+ krypt_instream_seek(in, 0, SEEK_SET);
+ return Qnil;
+}
+
+static VALUE
+int_asn1_fallback_decode(krypt_instream *in, krypt_instream *cache)
+{
+ VALUE ret;
+ unsigned char *lookahead = NULL;
+ size_t la_size;
+ krypt_instream *seq;
+ krypt_instream *bytes;
+ krypt_instream *pem;
+ int state = 0;
+
+ ret = rb_protect((VALUE(*)_((VALUE)))int_asn1_rewind_stream, (VALUE)in, &state);
+ if (!state) {
+ xfree(cache); /* do not use krypt_instream_free, would free in too */
+ pem = krypt_instream_new_pem(in);
+ }
+ else {
+ la_size = krypt_instream_cache_get_bytes(cache, &lookahead);
+ xfree(cache); /* do not use krypt_instream_free, would free in too */
+ bytes = krypt_instream_new_bytes(lookahead, la_size);
+ seq = krypt_instream_new_seq(bytes, in);
+ pem = krypt_instream_new_pem(seq);
+ }
+ ret = rb_protect((VALUE(*)_((VALUE)))int_asn1_decode, (VALUE)pem, &state);
+ if (lookahead)
+ xfree(lookahead);
+ krypt_instream_free(pem);
+ if (state) {
+ rb_jump_tag(state);
+ }
+ return ret;
+}
+
/**
* call-seq:
* ASN1.decode(der) -> ASN1Data
@@ -1043,18 +1097,98 @@ static VALUE
krypt_asn1_decode(VALUE self, VALUE obj)
{
krypt_instream *in;
- krypt_asn1_header *header;
+ krypt_instream *cache;
VALUE ret;
-
+ int state = 0;
+
in = krypt_instream_new_value(obj);
- if (krypt_asn1_next_header(in, &header) == 0)
- rb_raise(eKryptParseError, "Premature EOF detected");
+ cache = krypt_instream_new_cache(in);
+ ret = rb_protect((VALUE(*)_((VALUE)))int_asn1_decode, (VALUE)cache, &state);
+ if (state) {
+ return int_asn1_fallback_decode(in, cache);
+ }
+ krypt_instream_free(cache); /* also frees in */
+ return ret;
+}
- ret = krypt_asn1_data_new(in, header);
+static VALUE
+krypt_asn1_decode_der(VALUE self, VALUE obj)
+{
+ VALUE ret;
+ int state = 0;
+ krypt_instream *in = krypt_instream_new_value(obj);
+ ret = rb_protect((VALUE(*)_((VALUE)))int_asn1_decode, (VALUE)in, &state);
krypt_instream_free(in);
+ if (state)
+ rb_jump_tag(state);
+ return ret;
+}
+
+static VALUE
+krypt_asn1_decode_pem(VALUE self, VALUE obj)
+{
+ VALUE ret;
+ int state = 0;
+ krypt_instream *pem;
+ pem = krypt_instream_new_pem(krypt_instream_new_value(obj));
+ ret = rb_protect((VALUE(*)_((VALUE)))int_asn1_decode, (VALUE)pem, &state);
+ krypt_instream_free(pem);
+ if (state)
+ rb_jump_tag(state);
return ret;
}
+/**
+ * Returns an ID representing the Symbol that stands for the corresponding
+ * tag class.
+ *
+ * @param tag_class The raw tag class value
+ * @return A Ruby Symbol representing the tag class, e.g.
+ * :UNIVERSAL
+ * @raises Krypt::ASN1::ASN1Error if tag_class is unknown
+ */
+ID
+krypt_asn1_tag_class_for_int(int tag_class)
+{
+ switch (tag_class) {
+ case TAG_CLASS_UNIVERSAL:
+ return sKrypt_TC_UNIVERSAL;
+ case TAG_CLASS_APPLICATION:
+ return sKrypt_TC_APPLICATION;
+ case TAG_CLASS_CONTEXT_SPECIFIC:
+ return sKrypt_TC_CONTEXT_SPECIFIC;
+ case TAG_CLASS_PRIVATE:
+ return sKrypt_TC_PRIVATE;
+ default:
+ rb_raise(eKryptASN1Error, "Unknown tag class");
+ return Qnil;
+ }
+}
+
+/**
+ * Returns an integer representing the tag class of the corresponding
+ * symbol.
+ *
+ * @param tag_class The tag class ID
+ * @return An integer representing the tag class
+ * @raises Krypt::ASN1::ASN1Error if tag_class is unknown
+ */
+int
+krypt_asn1_tag_class_for_id(ID tag_class)
+{
+ if (tag_class == sKrypt_TC_UNIVERSAL)
+ return TAG_CLASS_UNIVERSAL;
+ else if (tag_class == sKrypt_TC_CONTEXT_SPECIFIC)
+ return TAG_CLASS_CONTEXT_SPECIFIC;
+ else if (tag_class == sKrypt_TC_APPLICATION)
+ return TAG_CLASS_APPLICATION;
+ else if (tag_class == sKrypt_TC_PRIVATE)
+ return TAG_CLASS_PRIVATE;
+
+ rb_raise(eKryptASN1Error, "Unknown tag class");
+ return Qnil;
+}
+
void
Init_krypt_asn1(void)
{
@@ -1065,16 +1199,16 @@ Init_krypt_asn1(void)
VALUE ary;
int i;
- sTC_UNIVERSAL = rb_intern("UNIVERSAL");
- sTC_APPLICATION = rb_intern("APPLICATION");
- sTC_CONTEXT_SPECIFIC = rb_intern("CONTEXT_SPECIFIC");
- sTC_PRIVATE = rb_intern("PRIVATE");
+ sKrypt_TC_UNIVERSAL = rb_intern("UNIVERSAL");
+ sKrypt_TC_APPLICATION = rb_intern("APPLICATION");
+ sKrypt_TC_CONTEXT_SPECIFIC = rb_intern("CONTEXT_SPECIFIC");
+ sKrypt_TC_PRIVATE = rb_intern("PRIVATE");
- sIV_TAG = rb_intern("@tag");
- sIV_TAG_CLASS = rb_intern("@tag_class");
- sIV_INF_LEN = rb_intern("@infinite_length");
- sIV_VALUE = rb_intern("@value");
- sIV_UNUSED_BITS = rb_intern("@unused_bits");
+ sKrypt_IV_TAG = rb_intern("@tag");
+ sKrypt_IV_TAG_CLASS = rb_intern("@tag_class");
+ sKrypt_IV_INF_LEN = rb_intern("@infinite_length");
+ sKrypt_IV_VALUE = rb_intern("@value");
+ sKrypt_IV_UNUSED_BITS = rb_intern("@unused_bits");
/*
* Document-module: Krypt::ASN1
@@ -1211,14 +1345,14 @@ Init_krypt_asn1(void)
* Generic error class for all errors raised while parsing from a stream
* with Krypt::ASN1::Parser or Krypt::ASN1::Header.
*/
- eKryptParseError = rb_define_class_under(mKryptASN1, "ParseError", eKryptASN1Error);
+ eKryptASN1ParseError = rb_define_class_under(mKryptASN1, "ParseError", eKryptASN1Error);
/* Document-class: Krypt::ASN1::SerializeError
*
* Generic error class for all errors raised while writing to a stream
* with Krypt::ASN1::Header#encode_to.
*/
- eKryptSerializeError = rb_define_class_under(mKryptASN1, "SerializeError", eKryptASN1Error);
+ eKryptASN1SerializeError = rb_define_class_under(mKryptASN1, "SerializeError", eKryptASN1Error);
ary = rb_ary_new();
/*
@@ -1232,6 +1366,8 @@ Init_krypt_asn1(void)
}
rb_define_module_function(mKryptASN1, "decode", krypt_asn1_decode, 1);
+ rb_define_module_function(mKryptASN1, "decode_der", krypt_asn1_decode_der, 1);
+ rb_define_module_function(mKryptASN1, "decode_pem", krypt_asn1_decode_pem, 1);
/* Document-class: Krypt::ASN1::ASN1Data
*
@@ -1478,5 +1614,6 @@ Init_krypt_asn1(void)
Init_krypt_asn1_parser();
Init_krypt_instream_adapter();
+ Init_krypt_pem();
}
View
18 ext/krypt/core/krypt_asn1.h
@@ -55,19 +55,23 @@ extern krypt_asn1_codec KRYPT_DEFAULT_CODEC;
extern krypt_asn1_codec krypt_asn1_codecs[];
extern VALUE eKryptASN1Error;
-extern VALUE eKryptParseError;
-extern VALUE eKryptSerializeError;
+extern VALUE eKryptASN1ParseError;
+extern VALUE eKryptASN1SerializeError;
-extern ID sTC_UNIVERSAL;
-extern ID sTC_APPLICATION;
-extern ID sTC_CONTEXT_SPECIFIC;
-extern ID sTC_PRIVATE;
+extern VALUE mKryptPEM;
+extern VALUE eKryptPEMError;
-extern ID sIV_TAG, sIV_TAG_CLASS, sIV_INF_LEN, sIV_VALUE, sIV_UNUSED_BITS;
+extern ID sKrypt_TC_UNIVERSAL;
+extern ID sKrypt_TC_APPLICATION;
+extern ID sKrypt_TC_CONTEXT_SPECIFIC;
+extern ID sKrypt_TC_PRIVATE;
+
+extern ID sKrypt_IV_TAG, sKrypt_IV_TAG_CLASS, sKrypt_IV_INF_LEN, sKrypt_IV_VALUE, sKrypt_IV_UNUSED_BITS;
void Init_krypt_asn1(void);
void Init_krypt_asn1_parser(void);
void Init_krypt_instream_adapter(void);
+void Init_krypt_pem(void);
VALUE krypt_instream_adapter_new(krypt_instream *in);
View
9 ext/krypt/core/krypt_asn1_codec.c
@@ -172,7 +172,7 @@ int_asn1_encode_bit_string(VALUE self, VALUE value, unsigned char **out)
size_t len;
unsigned char *bytes;
- unused_bits = NUM2INT(rb_ivar_get(self, sIV_UNUSED_BITS));
+ unused_bits = NUM2INT(rb_ivar_get(self, sKrypt_IV_UNUSED_BITS));
int_check_unused_bits(unused_bits);
StringValue(value);
@@ -197,7 +197,7 @@ int_asn1_decode_bit_string(VALUE self, unsigned char *bytes, size_t len)
unused_bits = bytes[0];
int_check_unused_bits(unused_bits);
ret = int_asn1_decode_default(self, bytes + 1, len - 1);
- rb_ivar_set(self, sIV_UNUSED_BITS, INT2NUM(unused_bits));
+ rb_ivar_set(self, sKrypt_IV_UNUSED_BITS, INT2NUM(unused_bits));
return ret;
}
@@ -259,7 +259,12 @@ int_asn1_encode_utf8_string(VALUE self, VALUE value, unsigned char **out)
return int_asn1_encode_default(self, value, out);
}
else {
+#ifdef HAVE_RB_STR_ENCODE
VALUE encoded = rb_str_encode(value, rb_enc_from_encoding(rb_utf8_encoding()), 0, Qnil);
+#else
+ VALUE encoded = value;
+ rb_enc_associate(encoded, rb_utf8_encoding());
+#endif
return int_asn1_encode_default(self, encoded, out);
}
}
View
10 ext/krypt/core/krypt_asn1_in_adapter.c
@@ -92,14 +92,14 @@ int_whence_for(VALUE vwhence)
rb_raise(rb_eArgError, "whence must be a Symbol");
whence = SYM2ID(vwhence);
- if (whence == ID_SEEK_CUR)
+ if (whence == sKrypt_ID_SEEK_CUR)
return SEEK_CUR;
- else if (whence == ID_SEEK_SET)
+ else if (whence == sKrypt_ID_SEEK_SET)
return SEEK_SET;
- else if (whence == ID_SEEK_END)
+ else if (whence == sKrypt_ID_SEEK_END)
return SEEK_END;
else
- rb_raise(eKryptParseError, "Unknown whence");
+ rb_raise(eKryptASN1ParseError, "Unknown whence");
return Qnil; /* dummy */
}
@@ -113,7 +113,7 @@ int_whence_for(VALUE vwhence)
static VALUE
krypt_instream_adapter_seek(int argc, VALUE *argv, VALUE self)
{
- VALUE n, vwhence = ID_SEEK_SET;
+ VALUE n, vwhence = sKrypt_ID_SEEK_SET;
int whence;
krypt_instream_adapter *adapter;
View
53 ext/krypt/core/krypt_asn1_in_chunked.c
@@ -13,36 +13,37 @@
#include "krypt-core.h"
#include "krypt_asn1-internal.h"
-enum int_state {
+enum krypt_chunked_state {
NEW_HEADER = 0,
PROCESS_TAG,
PROCESS_LENGTH,
PROCESS_VALUE,
DONE
};
-typedef struct int_instream_chunked {
+typedef struct krypt_instream_chunked {
krypt_instream_interface *methods;
krypt_instream *inner;
int values_only;
- enum int_state state;
+ enum krypt_chunked_state state;
krypt_asn1_header *cur_header;
krypt_instream *cur_value_stream;
size_t header_offset;
-} int_instream_chunked;
+} krypt_instream_chunked;
-#define int_safe_cast(out, in) krypt_safe_cast_instream((out), (in), INSTREAM_TYPE_CHUNKED, int_instream_chunked)
+#define int_safe_cast(out, in) krypt_safe_cast_instream((out), (in), KRYPT_INSTREAM_TYPE_CHUNKED, krypt_instream_chunked)
-static int_instream_chunked* int_chunked_alloc(void);
+static krypt_instream_chunked* int_chunked_alloc(void);
static ssize_t int_chunked_read(krypt_instream *in, unsigned char *buf, size_t len);
static void int_chunked_seek(krypt_instream *in, off_t offset, int whence);
static void int_chunked_mark(krypt_instream *in);
static void int_chunked_free(krypt_instream *in);
-static krypt_instream_interface interface_chunked = {
- INSTREAM_TYPE_CHUNKED,
+static krypt_instream_interface krypt_interface_chunked = {
+ KRYPT_INSTREAM_TYPE_CHUNKED,
int_chunked_read,
NULL,
+ NULL,
int_chunked_seek,
int_chunked_mark,
int_chunked_free
@@ -51,7 +52,7 @@ static krypt_instream_interface interface_chunked = {
krypt_instream *
krypt_instream_new_chunked(krypt_instream *original, int values_only)
{
- int_instream_chunked *in;
+ krypt_instream_chunked *in;
in = int_chunked_alloc();
in->inner = original;
@@ -60,26 +61,26 @@ krypt_instream_new_chunked(krypt_instream *original, int values_only)
return (krypt_instream *) in;
}
-static int_instream_chunked*
+static krypt_instream_chunked*
int_chunked_alloc(void)
{
- int_instream_chunked *ret;
- ret = ALLOC(int_instream_chunked);
- memset(ret, 0, sizeof(int_instream_chunked));
- ret->methods = &interface_chunked;
+ krypt_instream_chunked *ret;
+ ret = ALLOC(krypt_instream_chunked);
+ memset(ret, 0, sizeof(krypt_instream_chunked));
+ ret->methods = &krypt_interface_chunked;
return ret;
}
static void
-int_read_new_header(int_instream_chunked *in)
+int_read_new_header(krypt_instream_chunked *in)
{
int ret;
krypt_asn1_header *next;
ret = krypt_asn1_next_header(in->inner, &next);
if (ret == 0) {
xfree(next);
- rb_raise(eKryptParseError, "Premature end of value detected");
+ rb_raise(eKryptASN1ParseError, "Premature end of value detected");
}
else {
if (in->cur_header)
@@ -91,10 +92,10 @@ int_read_new_header(int_instream_chunked *in)
}
static size_t
-int_read_header_bytes(int_instream_chunked *in,
+int_read_header_bytes(krypt_instream_chunked *in,
unsigned char* bytes,
size_t bytes_len,
- enum int_state next_state,
+ enum krypt_chunked_state next_state,
unsigned char *buf,
size_t len)
{
@@ -116,7 +117,7 @@ int_read_header_bytes(int_instream_chunked *in,
}
static size_t
-int_read_value(int_instream_chunked *in, unsigned char *buf, size_t len)
+int_read_value(krypt_instream_chunked *in, unsigned char *buf, size_t len)
{
ssize_t read;
@@ -150,7 +151,7 @@ do { \
/* TODO: check overflow */
static size_t
-int_read_single_element(int_instream_chunked *in, unsigned char *buf, size_t len)
+int_read_single_element(krypt_instream_chunked *in, unsigned char *buf, size_t len)
{
size_t read = 0, total = 0;
@@ -192,13 +193,13 @@ int_read_single_element(int_instream_chunked *in, unsigned char *buf, size_t len
buf += read;
return total;
default:
- rb_raise(eKryptParseError, "Internal error");
+ rb_raise(eKryptASN1ParseError, "Internal error");
return 0; /* dummy */
}
}
static size_t
-int_read(int_instream_chunked *in, unsigned char *buf, size_t len)
+int_read(krypt_instream_chunked *in, unsigned char *buf, size_t len)
{
size_t read = 0, total = 0;
@@ -215,13 +216,13 @@ int_read(int_instream_chunked *in, unsigned char *buf, size_t len)
static ssize_t
int_chunked_read(krypt_instream *instream, unsigned char *buf, size_t len)
{
- int_instream_chunked *in;
+ krypt_instream_chunked *in;
size_t read;
int_safe_cast(in, instream);
if (!buf)
- rb_raise(rb_eArgError, "Buffer not initialized or length negative");
+ rb_raise(rb_eArgError, "Buffer not initialized");
if (in->state == DONE)
return -1;
@@ -246,7 +247,7 @@ int_chunked_seek(krypt_instream *instream, off_t offset, int whence)
static void
int_chunked_mark(krypt_instream *instream)
{
- int_instream_chunked *in;
+ krypt_instream_chunked *in;
if (!instream) return;
int_safe_cast(in, instream);
@@ -256,7 +257,7 @@ int_chunked_mark(krypt_instream *instream)
static void
int_chunked_free(krypt_instream *instream)
{
- int_instream_chunked *in;
+ krypt_instream_chunked *in;
if (!instream) return;
int_safe_cast(in, instream);
View
37 ext/krypt/core/krypt_asn1_in_definite.c
@@ -12,25 +12,26 @@
#include "krypt-core.h"
-typedef struct int_instream_definite_st {
+typedef struct krypt_instream_definite_st {
krypt_instream_interface *methods;
krypt_instream *inner;
size_t max_read;
size_t num_read;
-} int_instream_definite;
+} krypt_instream_definite;
-#define int_safe_cast(out, in) krypt_safe_cast_instream((out), (in), INSTREAM_TYPE_DEFINITE, int_instream_definite)
+#define int_safe_cast(out, in) krypt_safe_cast_instream((out), (in), KRYPT_INSTREAM_TYPE_DEFINITE, krypt_instream_definite)
-static int_instream_definite* int_definite_alloc(void);
+static krypt_instream_definite* int_definite_alloc(void);
static ssize_t int_definite_read(krypt_instream *in, unsigned char *buf, size_t len);
static void int_definite_seek(krypt_instream *in, off_t offset, int whence);
static void int_definite_mark(krypt_instream *in);
static void int_definite_free(krypt_instream *in);
-static krypt_instream_interface interface_definite = {
- INSTREAM_TYPE_DEFINITE,
+static krypt_instream_interface krypt_interface_definite = {
+ KRYPT_INSTREAM_TYPE_DEFINITE,
int_definite_read,
NULL,
+ NULL,
int_definite_seek,
int_definite_mark,
int_definite_free
@@ -39,28 +40,28 @@ static krypt_instream_interface interface_definite = {
krypt_instream *
krypt_instream_new_definite(krypt_instream *original, size_t len)
{
- int_instream_definite *in;
+ krypt_instream_definite *in;
in = int_definite_alloc();
in->inner = original;
in->max_read = len;
return (krypt_instream *) in;
}
-static int_instream_definite*
+static krypt_instream_definite*
int_definite_alloc(void)
{
- int_instream_definite *ret;
- ret = ALLOC(int_instream_definite);
- memset(ret, 0, sizeof(int_instream_definite));
- ret->methods = &interface_definite;
+ krypt_instream_definite *ret;
+ ret = ALLOC(krypt_instream_definite);
+ memset(ret, 0, sizeof(krypt_instream_definite));
+ ret->methods = &krypt_interface_definite;
return ret;
}
static ssize_t
int_definite_read(krypt_instream *instream, unsigned char *buf, size_t len)
{
- int_instream_definite *in;
+ krypt_instream_definite *in;
size_t to_read;
ssize_t r;
@@ -78,7 +79,7 @@ int_definite_read(krypt_instream *instream, unsigned char *buf, size_t len)
r = krypt_instream_read(in->inner, buf, to_read);
if (r == -1)
- rb_raise(eKryptParseError, "Premature end of value detected");
+ rb_raise(eKryptASN1ParseError, "Premature end of value detected");
if (in->num_read >= SIZE_MAX - r)
rb_raise(rb_eRuntimeError, "Size of stream too large");
@@ -92,7 +93,7 @@ int_definite_seek(krypt_instream *instream, off_t offset, int whence)
{
off_t real_off;
long numread;
- int_instream_definite *in;
+ krypt_instream_definite *in;
int_safe_cast(in, instream);
@@ -107,20 +108,20 @@ int_definite_seek(krypt_instream *instream, off_t offset, int whence)
real_off = offset + in->max_read - in->num_read;
break;
default:
- rb_raise(eKryptParseError, "Unknown 'whence': %d", whence);
+ rb_raise(eKryptASN1ParseError, "Unknown 'whence': %d", whence);
}
numread = in->num_read;
if (numread + real_off < 0 || numread + real_off >= (long)in->max_read)
- rb_raise(eKryptParseError, "Unreachable seek position");
+ rb_raise(eKryptASN1ParseError, "Unreachable seek position");
krypt_instream_seek(in->inner, offset, whence);
}
static void
int_definite_mark(krypt_instream *instream)
{
- int_instream_definite *in;
+ krypt_instream_definite *in;
if (!instream) return;
int_safe_cast(in, instream);
View
8 ext/krypt/core/krypt_asn1_parser.c
@@ -183,7 +183,7 @@ int_krypt_outstream_new(VALUE io)
if (type == T_FILE) {
return krypt_outstream_new_fd_io(io);
}
- else if (rb_respond_to(io, ID_WRITE)) {
+ else if (rb_respond_to(io, sKrypt_ID_WRITE)) {
return krypt_outstream_new_io_generic(io);
}
else {
@@ -281,7 +281,7 @@ krypt_asn1_header_value(VALUE self)
int_krypt_asn1_parsed_header_get(self, header);
if (header->consumed && header->cached_stream != Qnil)
- rb_raise(eKryptParseError, "The stream has already been consumed");
+ rb_raise(eKryptASN1ParseError, "The stream has already been consumed");
/* TODO: sync */
if (!header->consumed && header->value == Qnil) {
@@ -334,7 +334,7 @@ krypt_asn1_header_value_io(int argc, VALUE *argv, VALUE self)
int_krypt_asn1_parsed_header_get(self, header);
if (header->consumed && header->cached_stream == Qnil)
- rb_raise(eKryptParseError, "The stream has already been consumed");
+ rb_raise(eKryptASN1ParseError, "The stream has already been consumed");
/*TODO: synchronization */
if (header->cached_stream == Qnil) {
@@ -397,7 +397,7 @@ int_krypt_instream_new(VALUE io)
if (type == T_FILE) {
return krypt_instream_new_fd_io(io);
}
- else if (rb_respond_to(io, ID_READ)) {
+ else if (rb_respond_to(io, sKrypt_ID_READ)) {
return krypt_instream_new_io_generic(io);
}
else {
View
215 ext/krypt/core/krypt_b64.c
@@ -0,0 +1,215 @@
+/*
+* krypt-core API - C version
+*
+* Copyright (C) 2011
+* Hiroshi Nakamura <nahi@ruby-lang.org>
+* Martin Bosslet <martin.bosslet@googlemail.com>
+* All rights reserved.
+*
+* This software is distributed under the same license as Ruby.
+* See the file 'LICENSE' for further details.
+*/
+
+#include "krypt-core.h"
+
+static const char krypt_b64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char krypt_b64_table_inv[] = {
+-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1,-1,
+0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,
+-1,-1,-1,-1,-1,-1,
+26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};
+static unsigned char krypt_b64_separator[] = { '\r', '\n' };
+
+static unsigned char krypt_b64_out_buf[4];
+static unsigned char krypt_b64_in_buf[3];
+
+
+#define int_compute_int(res, b, i) \
+do { \
+ (res) = ((b)[(i)] << 16) | ((b)[(i)+1] << 8) | ((b)[(i)+2]); \
+} while(0)
+
+static void
+int_write_int(krypt_outstream *out, int n)
+{
+ krypt_b64_out_buf[0] = krypt_b64_table[(n >> 18) & 0x3f];
+ krypt_b64_out_buf[1] = krypt_b64_table[(n >> 12) & 0x3f];
+ krypt_b64_out_buf[2] = krypt_b64_table[(n >> 16) & 0x3f];
+ krypt_b64_out_buf[3] = krypt_b64_table[n & 0x3f];
+ krypt_outstream_write(out, krypt_b64_out_buf, 4);
+}
+
+static void
+int_encode_update(krypt_outstream *out, unsigned char *bytes, size_t off, size_t len)
+{
+ size_t i;
+ int n;
+
+ for (i=0; i < len; i+=3) {
+ int_compute_int(n, bytes, off + i);
+ int_write_int(out, n);
+ }
+}
+
+static void
+int_encode_update_cols(krypt_outstream *out, unsigned char *bytes, size_t off, size_t len, int cols)
+{
+ size_t i;
+ int n, linepos = 0;
+
+ for (i=0; i < len; i+=3) {
+ int_compute_int(n, bytes, off + i);
+ int_write_int(out, n);
+ linepos += 4;
+ if (linepos >= cols) {
+ krypt_outstream_write(out, krypt_b64_separator, 2);
+ linepos = 0;
+ }
+ }
+}
+
+static void
+int_encode_final(krypt_outstream *out, unsigned char *bytes, size_t off, size_t len, int remainder, int crlf)
+{
+ off = off + len - remainder;
+ if (remainder) {
+ int n;
+
+ n = (bytes[off] << 16) | (remainder == 2 ? bytes[off + 1] << 8 : 0);
+ krypt_b64_out_buf[0] = krypt_b64_table[(n >> 18) & 0x3f];
+ krypt_b64_out_buf[1] = krypt_b64_table[(n >> 12) & 0x3f];
+ krypt_b64_out_buf[2] = remainder == 2 ? krypt_b64_table[(n >> 6) & 0x3f] : '=';
+ krypt_b64_out_buf[3] = '=';
+ krypt_outstream_write(out, krypt_b64_out_buf, 4);
+ }
+ if (crlf) {
+ krypt_outstream_write(out, krypt_b64_separator, 2);
+ }
+}
+
+void
+krypt_base64_buffer_encode_to(krypt_outstream *out, unsigned char *bytes, size_t off, size_t len, int cols)
+{
+ int remainder;
+
+ if (!bytes || !out)
+ rb_raise(rb_eRuntimeError, "params null");
+
+ remainder = len % 3;
+ if (cols < 0)
+ int_encode_update(out, bytes, off, len - remainder);
+ else
+ int_encode_update_cols(out, bytes, off, len - remainder, cols);
+
+ int_encode_final(out, bytes, off, len, remainder, cols > 0);
+}
+
+size_t
+krypt_base64_encode(unsigned char *bytes, size_t len, int cols, unsigned char **out)
+{
+ size_t retlen;
+ krypt_outstream *outstream;
+
+ if (!bytes)
+ rb_raise(rb_eRuntimeError, "bytes null");
+ if ( (len / 3 + 1) > (SIZE_MAX / 4) )
+ rb_raise(rb_eRuntimeError, "buffer too large");
+
+ /* this is the maximum value, no exactness needed, we'll resize anyway */
+ retlen = 4.0 * (len / 3 + 1);
+
+ /* Add the number of new line characters */
+ if (cols > 0) {
+ if ( (len / cols * 2) > SIZE_MAX - retlen )
+ rb_raise(rb_eRuntimeError, "buffer too large");
+ retlen += len / cols * 2;
+ }
+
+ outstream = krypt_outstream_new_bytes_size(retlen);
+ krypt_base64_buffer_encode_to(outstream, bytes, 0, len, cols);
+ retlen = krypt_outstream_bytes_get_bytes_free(outstream, out);
+ krypt_outstream_free(outstream);
+ return retlen;
+}
+
+static void
+int_decode_int(krypt_outstream *out, int n)
+{
+ krypt_b64_in_buf[0] = (n >> 16) & 0xff;
+ krypt_b64_in_buf[1] = (n >> 8) & 0xff;
+ krypt_b64_in_buf[2] = n & 0xff;
+ krypt_outstream_write(out, krypt_b64_in_buf, 3);
+}
+
+static void
+int_decode_final_int(krypt_outstream *out, int n, int remainder)
+{
+ switch (remainder) {
+ /* 2 of 4 bytes are to be discarded.
+ * 2 bytes represent 12 bits of meaningful data -> 1 byte plus 4 bits to be dropped */
+ case 2:
+ krypt_b64_in_buf[0] = (n >> 4) & 0xff;
+ krypt_outstream_write(out, krypt_b64_in_buf, 1);
+ break;
+ /* 1 of 4 bytes are to be discarded.
+ * 3 bytes represent 18 bits of meaningful data -> 2 bytes plus 2 bits to be dropped */
+ case 3:
+ n >>= 2;
+ krypt_b64_in_buf[0] = (n >> 8) & 0xff;
+ krypt_b64_in_buf[1] = n & 0xff;
+ krypt_outstream_write(out, krypt_b64_in_buf, 2);
+ break;
+ }
+}
+
+void
+krypt_base64_buffer_decode_to(krypt_outstream *out, unsigned char *bytes, size_t off, size_t len)
+{
+ size_t i;
+ int n = 0;
+ int remainder = 0;
+ char inv;
+
+ if (len > SIZE_MAX - off)
+ rb_raise(rb_eRuntimeError, "Invalid length");
+
+ for (i=0; i < len; i++) {
+ unsigned char b = bytes[off + i];
+ if (b == '=')
+ break;
+ if (b >= 123)
+ continue;
+ inv = krypt_b64_table_inv[b];
+ if (inv < 0)
+ continue;
+ n = (n << 6) | inv;
+ remainder = (remainder + 1) % 4;
+ if (remainder == 0) {
+ int_decode_int(out, n);
+ }
+ }
+
+ int_decode_final_int(out, n, remainder);
+}
+
+size_t
+krypt_base64_decode(unsigned char *bytes, size_t len, unsigned char **out)
+{
+ size_t retlen;
+ krypt_outstream *outstream;
+
+ if (!bytes)
+ rb_raise(rb_eRuntimeError, "bytes null");
+
+ /* Approximate, will resize anyway */
+ retlen = len / 4 * 3;
+
+ outstream = krypt_outstream_new_bytes_size(retlen);
+ krypt_base64_buffer_decode_to(outstream, bytes, 0, len);
+ retlen = krypt_outstream_bytes_get_bytes_free(outstream, out);
+ krypt_outstream_free(outstream);
+ return retlen;
+}
+
View
68 ext/krypt/core/krypt_io.c
@@ -13,13 +13,13 @@
#include "krypt-core.h"
#define int_check_stream(io) if (!(io) || !(io)->methods) \
- rb_raise(eKryptParseError, "Stream not initialized properly")
+ rb_raise(eKryptASN1ParseError, "Stream not initialized properly")
#define int_check_stream_has(io, m) if (!(io) || !(io)->methods || !(io)->methods->m) \
- rb_raise(eKryptParseError, "Stream not initialized properly")
+ rb_raise(eKryptASN1ParseError, "Stream not initialized properly")
-VALUE ID_SEEK_CUR, ID_SEEK_SET, ID_SEEK_END;
-ID ID_READ, ID_SEEK, ID_WRITE;
+VALUE sKrypt_ID_SEEK_CUR, sKrypt_ID_SEEK_SET, sKrypt_ID_SEEK_END;
+ID sKrypt_ID_READ, sKrypt_ID_SEEK, sKrypt_ID_WRITE;
void
krypt_raise_io_error(VALUE klass)
@@ -115,6 +115,50 @@ krypt_instream_read(krypt_instream *in, unsigned char *buf, size_t len)
return in->methods->read(in, buf, len);
}
+static ssize_t
+int_gets_generic(krypt_instream *in, char *line, size_t len)
+{
+ ssize_t ret = 0, r = 0;
+ char *p = line;
+ char *end = line + len - 1;
+
+ if (!line)
+ rb_raise(rb_eArgError, "Buffer not initialized");
+
+ while (p < end) {
+ if ((r = in->methods->read(in, (unsigned char *) p, 1)) == -1)
+ break;
+ if (r == 1) {
+ if (*p == '\n')
+ break;
+ p++;
+ ret++;
+ }
+ }
+
+ *p = '\0';
+ ret++;
+
+ if (line[0] == '\0' && r == -1)
+ return -1;
+
+ return ret;
+}
+
+ssize_t
+krypt_instream_gets(krypt_instream *in, char *line, size_t len)
+{
+ int_check_stream(in);
+ if (len > SSIZE_MAX)
+ rb_raise(rb_eRuntimeError, "Length too large");
+ if (in->methods->gets) {
+ return in->methods->gets(in, line, len);
+ }
+ else {
+ return int_gets_generic(in, line, len);
+ }
+}
+
void
krypt_instream_seek(krypt_instream *in, off_t offset, int whence)
{
@@ -152,7 +196,7 @@ krypt_instream_new_value(VALUE value)
if (type == T_FILE) {
return krypt_instream_new_fd_io(value);
}
- else if (rb_respond_to(value, ID_READ)) {
+ else if (rb_respond_to(value, sKrypt_ID_READ)) {
ID id_string;
id_string = rb_intern("string");
if (rb_respond_to(value, id_string)) { /* StringIO */
@@ -221,7 +265,7 @@ krypt_outstream_new_value(VALUE value)
if (type == T_FILE)
return krypt_outstream_new_fd_io(value);
- else if (rb_respond_to(value, ID_WRITE))
+ else if (rb_respond_to(value, sKrypt_ID_WRITE))
return krypt_outstream_new_io_generic(value);
else
rb_raise(rb_eArgError, "Argument must be an IO");
@@ -233,16 +277,16 @@ krypt_outstream_new_value(VALUE value)
void
Init_krypt_io(void)
{
- ID_SEEK = rb_intern("seek");
- ID_READ = rb_intern("read");
- ID_WRITE = rb_intern("write");
+ sKrypt_ID_SEEK = rb_intern("seek");
+ sKrypt_ID_READ = rb_intern("read");
+ sKrypt_ID_WRITE = rb_intern("write");
}
void
InitVM_krypt_io(void)
{
- ID_SEEK_CUR = rb_const_get(rb_cIO, rb_intern("SEEK_CUR"));
- ID_SEEK_SET = rb_const_get(rb_cIO, rb_intern("SEEK_SET"));
- ID_SEEK_END = rb_const_get(rb_cIO, rb_intern("SEEK_END"));
+ sKrypt_ID_SEEK_CUR = rb_const_get(rb_cIO, rb_intern("SEEK_CUR"));
+ sKrypt_ID_SEEK_SET = rb_const_get(rb_cIO, rb_intern("SEEK_SET"));
+ sKrypt_ID_SEEK_END = rb_const_get(rb_cIO, rb_intern("SEEK_END"));
}
View
37 ext/krypt/core/krypt_io.h
@@ -15,20 +15,23 @@
#include "krypt_io_buffer.h"
-extern ID ID_READ, ID_SEEK, ID_WRITE;
-extern VALUE ID_SEEK_CUR, ID_SEEK_SET, ID_SEEK_END;
+extern ID sKrypt_ID_READ, sKrypt_ID_SEEK, sKrypt_ID_WRITE;
+extern VALUE sKrypt_ID_SEEK_CUR, sKrypt_ID_SEEK_SET, sKrypt_ID_SEEK_END;
#define KRYPT_IO_BUF_SIZE 8092
-#define INSTREAM_TYPE_FD 0
-#define INSTREAM_TYPE_BYTES 1
-#define INSTREAM_TYPE_IO_GENERIC 2
-#define INSTREAM_TYPE_DEFINITE 3
-#define INSTREAM_TYPE_CHUNKED 4
+#define KRYPT_INSTREAM_TYPE_FD 0
+#define KRYPT_INSTREAM_TYPE_BYTES 1
+#define KRYPT_INSTREAM_TYPE_IO_GENERIC 2
+#define KRYPT_INSTREAM_TYPE_DEFINITE 3
+#define KRYPT_INSTREAM_TYPE_CHUNKED 4
+#define KRYPT_INSTREAM_TYPE_PEM 5
+#define KRYPT_INSTREAM_TYPE_SEQ 6
+#define KRYPT_INSTREAM_TYPE_CACHE 7
-#define OUTSTREAM_TYPE_FD 10
-#define OUTSTREAM_TYPE_BYTES 11
-#define OUTSTREAM_TYPE_IO_GENERIC 12
+#define KRYPT_OUTSTREAM_TYPE_FD 10
+#define KRYPT_OUTSTREAM_TYPE_BYTES 11
+#define KRYPT_OUTSTREAM_TYPE_IO_GENERIC 12
typedef struct krypt_instream_interface_st krypt_instream_interface;
typedef struct krypt_outstream_interface_st krypt_outstream_interface;
@@ -46,6 +49,7 @@ struct krypt_instream_interface_st {
ssize_t (*read)(krypt_instream*, unsigned char*, size_t);
VALUE (*rb_read)(krypt_instream*, VALUE, VALUE);
+ ssize_t (*gets)(krypt_instream*, char *, size_t);
void (*seek)(krypt_instream*, off_t, int);
void (*mark)(krypt_instream*);
void (*free)(krypt_instream*);
@@ -82,6 +86,7 @@ void krypt_instream_rb_size_buffer(VALUE *str, size_t len);
ssize_t krypt_instream_read(krypt_instream *in, unsigned char *buf, size_t len);
VALUE krypt_instream_rb_read(krypt_instream *in, VALUE vlen, VALUE vbuf);
+ssize_t krypt_instream_gets(krypt_instream *in, char *line, size_t len);
void krypt_instream_seek(krypt_instream *in, off_t offset, int whence);
#define krypt_instream_skip(in, n) krypt_instream_seek((in), (n), SEEK_CUR)
void krypt_instream_mark(krypt_instream *in);
@@ -94,6 +99,14 @@ krypt_instream *krypt_instream_new_io_generic(VALUE io);
krypt_instream *krypt_instream_new_value(VALUE value);
krypt_instream *krypt_instream_new_chunked(krypt_instream *in, int values_only);
krypt_instream *krypt_instream_new_definite(krypt_instream *in, size_t length);
+krypt_instream *krypt_instream_new_seq(krypt_instream *in1, krypt_instream *in2);
+krypt_instream *krypt_instream_new_seq_n(int num, krypt_instream *in1, krypt_instream *in2, ...);
+krypt_instream *krypt_instream_new_cache(krypt_instream *original);
+krypt_instream *krypt_instream_new_pem(krypt_instream *original);
+
+size_t krypt_instream_cache_get_bytes(krypt_instream *in, unsigned char **out);
+size_t krypt_pem_get_last_name(krypt_instream *instream, unsigned char **out);
+void krypt_pem_continue_stream(krypt_instream *instream);
size_t krypt_outstream_write(krypt_outstream *out, unsigned char *buf, size_t len);
VALUE krypt_outstream_rb_write(krypt_outstream *out, VALUE vbuf);
@@ -104,7 +117,9 @@ size_t krypt_outstream_bytes_get_bytes_free(krypt_outstream *outstream, unsigned
krypt_outstream *krypt_outstream_new_fd(int fd);
krypt_outstream *krypt_outstream_new_fd_io(VALUE io);
-krypt_outstream *krypt_outstream_new_bytes();
+krypt_outstream *krypt_outstream_new_bytes(void);
+krypt_outstream *krypt_outstream_new_bytes_size(size_t size);
+krypt_outstream *krypt_outstream_new_bytes_prealloc(unsigned char *b, size_t len);
krypt_outstream *krypt_outstream_new_io_generic(VALUE io);
krypt_outstream *krypt_outstream_new_value(VALUE value);
View
43 ext/krypt/core/krypt_io_buffer.c
@@ -12,32 +12,58 @@
#include "krypt_io_buffer.h"
-krypt_byte_buffer *krypt_buffer_new(void)
+krypt_byte_buffer *
+krypt_buffer_new(void)
{
krypt_byte_buffer *ret;
ret = ALLOC(krypt_byte_buffer);
memset(ret, 0, sizeof(krypt_byte_buffer));
return ret;
}
-static const size_t BUF_MAX = SIZE_MAX / KRYPT_BYTE_BUFFER_GROWTH_FACTOR;
+krypt_byte_buffer *
+krypt_buffer_new_size(size_t size)
+{
+ krypt_byte_buffer *ret;
+ ret = ALLOC(krypt_byte_buffer);
+ memset(ret, 0, sizeof(krypt_byte_buffer));
+ ret->init_size = size;
+ return ret;
+}
+
+krypt_byte_buffer *
+krypt_buffer_new_prealloc(unsigned char *b, size_t len)
+{
+ krypt_byte_buffer *ret;
+ ret = krypt_buffer_new();
+ ret->data = b;
+ ret->limit = len;
+ ret->prealloc = 1;
+ return ret;
+}
+
+static const size_t KRYPT_BUF_MAX = SIZE_MAX / KRYPT_BYTE_BUFFER_GROWTH_FACTOR;
static void
int_buffer_grow(krypt_byte_buffer *buffer, size_t cur_len)
{
size_t new_size;
+ if (buffer->prealloc)
+ rb_raise(rb_eRuntimeError, "Cannot grow preallocated buffer");
+
if (buffer->data == NULL) {
- buffer->data = ALLOC_N(unsigned char, cur_len);
- buffer->limit = cur_len;
+ size_t alloc_size = buffer->init_size > cur_len ? buffer->init_size : cur_len;
+ buffer->data = ALLOC_N(unsigned char, alloc_size);
+ buffer->limit = alloc_size;
return;
}
/* avoid infinite loop for limit == 1 */
new_size = buffer->limit == 1 ? 2 : buffer->limit;
while (new_size - buffer->size < cur_len) {
- if (new_size >= BUF_MAX)
+ if (new_size >= KRYPT_BUF_MAX)
rb_raise(rb_eRuntimeError, "Cannot grow buffer");
new_size *= KRYPT_BYTE_BUFFER_GROWTH_FACTOR;
}
@@ -50,7 +76,10 @@ size_t
krypt_buffer_write(krypt_byte_buffer *buffer, unsigned char *b, size_t len)
{
if (!b)
- rb_raise(rb_eArgError, "Buffer not initialized or length negative");
+ rb_raise(rb_eArgError, "Buffer not initialized");
+
+ if (len == 0)
+ return 0;
if (buffer->limit - buffer->size < len)
int_buffer_grow(buffer, len);
@@ -73,7 +102,7 @@ void
krypt_buffer_free(krypt_byte_buffer *buffer)
{
if (!buffer) return;
- if (buffer->data)
+ if (buffer->data && (!buffer->prealloc))
xfree(buffer->data);
xfree(buffer);
}
View
4 ext/krypt/core/krypt_io_buffer.h
@@ -21,11 +21,15 @@ typedef struct krypt_byte_buffer_st {
size_t size;
size_t limit;
unsigned char *data;
+ size_t init_size;
+ int prealloc; /* whether the buffer was already preallocated */
} krypt_byte_buffer;
#define krypt_buffer_get_data(b) (b)->data
#define krypt_buffer_get_size(b) (b)->size
krypt_byte_buffer *krypt_buffer_new(void);
+krypt_byte_buffer *krypt_buffer_new_size(size_t size);
+krypt_byte_buffer *krypt_buffer_new_prealloc(unsigned char *b, size_t len);
size_t krypt_buffer_write(krypt_byte_buffer *buffer, unsigned char *b, size_t len);
void krypt_buffer_free_secure(krypt_byte_buffer *buffer);
void krypt_buffer_free(krypt_byte_buffer *buffer);
View
90 ext/krypt/core/krypt_io_in_bytes.c
@@ -17,23 +17,25 @@ struct krypt_byte_ary_st {
size_t len;
};
-typedef struct int_instream_bytes_st {
+typedef struct krypt_instream_bytes_st {
krypt_instream_interface *methods;
struct krypt_byte_ary_st *src;
size_t num_read;
-} int_instream_bytes;
+} krypt_instream_bytes;
-#define int_safe_cast(out, in) krypt_safe_cast_instream((out), (in), INSTREAM_TYPE_BYTES, int_instream_bytes)
+#define int_safe_cast(out, in) krypt_safe_cast_instream((out), (in), KRYPT_INSTREAM_TYPE_BYTES, krypt_instream_bytes)
-static int_instream_bytes* int_bytes_alloc(void);
+static krypt_instream_bytes* int_bytes_alloc(void);
static ssize_t int_bytes_read(krypt_instream *in, unsigned char *buf, size_t len);
+static ssize_t int_bytes_gets(krypt_instream *in, char *line, size_t len);
static void int_bytes_seek(krypt_instream *in, off_t offset, int whence);
static void int_bytes_free(krypt_instream *in);
-static krypt_instream_interface interface_bytes = {
- INSTREAM_TYPE_BYTES,
+static krypt_instream_interface krypt_interface_bytes = {
+ KRYPT_INSTREAM_TYPE_BYTES,
int_bytes_read,
NULL,
+ int_bytes_gets,
int_bytes_seek,
NULL,
int_bytes_free
@@ -42,7 +44,7 @@ static krypt_instream_interface interface_bytes = {
krypt_instream *
krypt_instream_new_bytes(unsigned char *bytes, size_t len)
{
- int_instream_bytes *in;
+ krypt_instream_bytes *in;
struct krypt_byte_ary_st *byte_ary;
in = int_bytes_alloc();
@@ -53,13 +55,13 @@ krypt_instream_new_bytes(unsigned char *bytes, size_t len)
return (krypt_instream *) in;
}
-static int_instream_bytes*
+static krypt_instream_bytes*
int_bytes_alloc(void)
{
- int_instream_bytes *ret;
- ret = ALLOC(int_instream_bytes);
- memset(ret, 0, sizeof(int_instream_bytes));
- ret->methods = &interface_bytes;
+ krypt_instream_bytes *ret;
+ ret = ALLOC(krypt_instream_bytes);
+ memset(ret, 0, sizeof(krypt_instream_bytes));
+ ret->methods = &krypt_interface_bytes;
return ret;
}
@@ -68,35 +70,69 @@ int_bytes_read(krypt_instream *instream, unsigned char *buf, size_t len)
{
struct krypt_byte_ary_st *src;
size_t to_read;
- int_instream_bytes *in;
+ krypt_instream_bytes *in;
int_safe_cast(in, instream);
if (!buf)
- rb_raise(rb_eArgError, "Buffer not initialized or length negative");
+ rb_raise(rb_eArgError, "Buffer not initialized");
src = in->src;
if (in->num_read == src->len)
return -1;
- if (src->len - in->num_read < len)
- to_read = src->len - in->num_read;
- else
- to_read = len;
-
+ to_read = src->len - in->num_read < len ? src->len - in->num_read : len;
memcpy(buf, src->p, to_read);
src->p += to_read;
in->num_read += to_read;
return to_read;
}
+static ssize_t
+int_bytes_gets(krypt_instream *instream, char *line, size_t len)
+{
+ struct krypt_byte_ary_st *src;
+ krypt_instream_bytes *in;
+ ssize_t ret = 0;
+ size_t to_read;
+ char *d;
+ char *end;
+
+ int_safe_cast(in, instream);
+ src = in->src;
+
+ if (in->num_read == src->len)
+ return -1;
+
+ d = line;
+ to_read = src->len - in->num_read < len ? src->len - in->num_read : len - 1; /* due to '\0' */
+ end = d + to_read;
+
+ while (d < end) {
+ *d = *(src->p);
+ src->p++;
+ if (*d == '\n')
+ break;
+ d++;
+ ret++;
+ }
+ in->num_read += ret;
+
+ *d = '\0';
+ ret++;
+ return ret;
+}
+
static inline void
-int_bytes_set_pos(struct krypt_byte_ary_st *src, off_t offset, size_t num_read)
+int_bytes_set_pos(krypt_instream_bytes *in, off_t offset, size_t num_read)
{
+ struct krypt_byte_ary_st *src = in->src;
+
if (src->len - offset <= num_read)
- rb_raise(eKryptParseError, "Unreachable seek position");
+ rb_raise(eKryptASN1ParseError, "Unreachable seek position");
src->p += offset;
+ in->num_read += offset;
}
/* TODO check overflow */
@@ -105,7 +141,7 @@ int_bytes_seek(krypt_instream *instream, off_t offset, int whence)
{
struct krypt_byte_ary_st *src;
size_t num_read;
- int_instream_bytes *in;
+ krypt_instream_bytes *in;
int_safe_cast(in, instream);
@@ -114,23 +150,23 @@ int_bytes_seek(krypt_instream *instream, off_t offset, int whence)
switch (whence) {
case SEEK_CUR:
- int_bytes_set_pos(src, offset, num_read);
+ int_bytes_set_pos(in, offset, num_read);
break;
case SEEK_SET:
- int_bytes_set_pos(src, offset - num_read, num_read);
+ int_bytes_set_pos(in, offset - num_read, num_read);
break;
case SEEK_END:
- int_bytes_set_pos(src, offset + src->len - num_read, num_read);
+ int_bytes_set_pos(in, offset + src->len - num_read, num_read);
break;
default:
- rb_raise(eKryptParseError, "Unknown 'whence': %d", whence);
+ rb_raise(eKryptASN1ParseError, "Unknown 'whence': %d", whence);
}
}
static void
int_bytes_free(krypt_instream *instream)
{
- int_instream_bytes *in;
+ krypt_instream_bytes *in;
if (!instream) return;
int_safe_cast(in, instream);
View
116 ext/krypt/core/krypt_io_in_cache.c
@@ -0,0 +1,116 @@
+/*
+* krypt-core API - C version
+*
+* Copyright (C) 2011
+* Hiroshi Nakamura <nahi@ruby-lang.org>
+* Martin Bosslet <martin.bosslet@googlemail.com>
+* All rights reserved.
+*
+* This software is distributed under the same license as Ruby.
+* See the file 'LICENSE' for further details.
+*/
+
+#include "krypt-core.h"
+
+typedef struct krypt_instream_cache_st {
+ krypt_instream_interface *methods;
+ krypt_instream *inner;
+ krypt_outstream *bytes;
+} krypt_instream_cache;
+
+#define int_safe_cast(out, in) krypt_safe_cast_instream((out), (in), KRYPT_INSTREAM_TYPE_CACHE, krypt_instream_cache)
+
+static krypt_instream_cache* int_cache_alloc(void);
+static ssize_t int_cache_read(krypt_instream *in, unsigned char *buf, size_t len);
+static void int_cache_seek(krypt_instream *in, off_t offset, int whence);
+static void int_cache_mark(krypt_instream *in);
+static void int_cache_free(krypt_instream *in);
+
+static krypt_instream_interface krypt_interface_cache = {
+ KRYPT_INSTREAM_TYPE_CACHE,
+ int_cache_read,
+ NULL,
+ NULL,
+ int_cache_seek,
+ int_cache_mark,
+ int_cache_free
+};
+
+krypt_instream *
+krypt_instream_new_cache(krypt_instream *original)
+{
+ krypt_instream_cache *in;
+
+ in = int_cache_alloc();
+ in->inner = original;
+ in->bytes = krypt_outstream_new_bytes();
+ return (krypt_instream *) in;
+}
+
+size_t
+krypt_instream_cache_get_bytes(krypt_instream *instream, unsigned char **out)
+{
+ krypt_instream_cache *in;
+ size_t ret;
+
+ int_safe_cast(in, instream);
+ ret = krypt_outstream_bytes_get_bytes_free(in->bytes, out);
+ in->bytes = krypt_outstream_new_bytes();
+ return ret;
+}
+
+static krypt_instream_cache*
+int_cache_alloc(void)
+{
+ krypt_instream_cache *ret;
+ ret = ALLOC(krypt_instream_cache);
+ memset(ret, 0, sizeof(krypt_instream_cache));
+ ret->methods = &krypt_interface_cache;
+ return ret;
+}
+
+static ssize_t
+int_cache_read(krypt_instream *instream, unsigned char *buf, size_t len)
+{
+ ssize_t read;
+ krypt_instream_cache *in;
+
+ int_safe_cast(in, instream);
+
+ if (!buf)
+ rb_raise(rb_eArgError, "Buffer not initialized");
+
+ read = krypt_instream_read(in->inner, buf, len);
+ if (read > 0)
+ krypt_outstream_write(in->bytes, buf, read);
+ return read;
+}
+
+static void
+int_cache_seek(krypt_instream *instream, off_t offset, int whence)
+{
+ krypt_instream_cache *in;
+
+ int_safe_cast(in, instream);
+ krypt_instream_seek(in->inner, offset, whence);
+}
+
+static void
+int_cache_mark(krypt_instream *instream)
+{
+ krypt_instream_cache *in;
+
+ int_safe_cast(in, instream);
+ krypt_instream_mark(in->inner);
+}
+
+static void
+int_cache_free(krypt_instream *instream)
+{
+ krypt_instream_cache *in;
+
+ int_safe_cast(in, instream);
+ krypt_instream_free(in->inner);
+ krypt_outstream_free(in->bytes);
+}
+
View
74 ext/krypt/core/krypt_io_in_fd.c
@@ -14,22 +14,24 @@
#include <errno.h>
#include "krypt-core.h"
-typedef struct int_instream_fd_st {
+typedef struct krypt_instream_fd_st {
krypt_instream_interface *methods;
int fd;
-} int_instream_fd;
+} krypt_instream_fd;
-#define int_safe_cast(out, in) krypt_safe_cast_instream((out), (in), INSTREAM_TYPE_FD, int_instream_fd)
+#define int_safe_cast(out, in) krypt_safe_cast_instream((out), (in), KRYPT_INSTREAM_TYPE_FD, krypt_instream_fd)
-static int_instream_fd *int_fd_alloc(void);
-static ssize_t int_fd_read(krypt_instream *in, unsigned char *, size_t len);
+static krypt_instream_fd *int_fd_alloc(void);
+static ssize_t int_fd_read(krypt_instream *in, unsigned char *buf, size_t len);
+static ssize_t int_fd_gets(krypt_instream *in, char *line, size_t len);
static void int_fd_seek(krypt_instream *in, off_t offset, int whence);
static void int_fd_free(krypt_instream *in);
-static krypt_instream_interface interface_fd = {
- INSTREAM_TYPE_FD,
+static krypt_instream_interface krypt_interface_fd = {
+ KRYPT_INSTREAM_TYPE_FD,
int_fd_read,
NULL,
+ int_fd_gets,
int_fd_seek,
NULL,
int_fd_free
@@ -47,20 +49,20 @@ krypt_instream_new_fd_io(VALUE value)
krypt_instream *
krypt_instream_new_fd(int fd)
{
- int_instream_fd *in;
+ krypt_instream_fd *in;
in = int_fd_alloc();
in->fd = fd;
return (krypt_instream *) in;
}
-static int_instream_fd*
+static krypt_instream_fd*
int_fd_alloc(void)
{
- int_instream_fd *ret;
- ret = ALLOC(int_instream_fd);
- memset(ret, 0, sizeof(int_instream_fd));
- ret->methods = &interface_fd;
+ krypt_instream_fd *ret;
+ ret = ALLOC(krypt_instream_fd);
+ memset(ret, 0, sizeof(krypt_instream_fd));
+ ret->methods = &krypt_interface_fd;
return ret;
}
@@ -69,18 +71,18 @@ int_fd_read(krypt_instream *instream, unsigned char *buf, size_t len)
{
int fd;
ssize_t r;
- int_instream_fd *in;
+ krypt_instream_fd *in;
int_safe_cast(in, instream);
if (!buf)
- rb_raise(rb_eArgError, "Buffer not initialized or length negative");
+ rb_raise(rb_eArgError, "Buffer not initialized");
fd = in->fd;
krypt_clear_sys_error();
r = read(fd, buf, len);
if (r == -1) {
- krypt_raise_io_error(eKryptParseError);
+ krypt_raise_io_error(eKryptASN1ParseError);
return 0; /* dummy */
}
else if (r == 0) {
@@ -91,19 +93,55 @@ int_fd_read(krypt_instream *instream, unsigned char *buf, size_t len)
}
}
+static ssize_t
+int_fd_gets(krypt_instream *instream, char *line, size_t len)
+{
+ int fd;
+ krypt_instream_fd *in;
+ ssize_t ret = 0, r = 0;
+ char *p = line;
+ char *end = line + len - 1;
+
+ int_safe_cast(in, instream);
+ if (!line)
+ rb_raise(rb_eArgError, "Buffer not initialized");
+
+ fd = in->fd;
+ krypt_clear_sys_error();
+
+ while ( (p < end) &&
+ ((r = read(fd, p, 1)) == 1) &&
+ (*p != '\n') ) {
+ p++;
+ ret++;
+ }
+
+ if (r == -1) {
+ krypt_raise_io_error(eKryptASN1ParseError);
+ }
+
+ *p = '\0';
+ ret++;
+
+ if (line[0] == '\0' && r == 0)
+ return -1;
+
+ return ret;
+}
+
static void
int_fd_seek(krypt_instream *instream, off_t offset, int whence)
{
int fd;
long off;
- int_instream_fd *in;
+ krypt_instream_fd *in;
int_safe_cast(in, instream);
fd = in->fd;
off = lseek(fd, offset, whence);
if (off == -1)
- krypt_raise_io_error(eKryptParseError);
+ krypt_raise_io_error(eKryptASN1ParseError);
}
static void
View
49 ext/krypt/core/krypt_io_in_generic.c
@@ -12,25 +12,26 @@
#include "krypt-core.h"
-typedef struct int_instream_io_st {
+typedef struct krypt_instream_io_st {
krypt_instream_interface *methods;
VALUE io;
VALUE vbuf;
-} int_instream_io;
+} krypt_instream_io;
-#define int_safe_cast(out, in) krypt_safe_cast_instream((out), (in), INSTREAM_TYPE_IO_GENERIC, int_instream_io)
+#define int_safe_cast(out, in) krypt_safe_cast_instream((out), (in), KRYPT_INSTREAM_TYPE_IO_GENERIC, krypt_instream_io)
-static int_instream_io* int_io_alloc(void);
+static krypt_instream_io* int_io_alloc(void);
static ssize_t int_io_read(krypt_instream *in, unsigned char *buf, size_t len);
static VALUE int_io_rb_read(krypt_instream *in, VALUE vlen, VALUE vbuf);
static void int_io_seek(krypt_instream *in, off_t offset, int whence);
static void int_io_mark(krypt_instream *in);
static void int_io_free(krypt_instream *in);
-static krypt_instream_interface interface_io_generic = {
- INSTREAM_TYPE_IO_GENERIC,
+static krypt_instream_interface krypt_interface_io_generic = {