krypt-core 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/LICENSE +20 -0
  2. data/ext/krypt/core/Makefile +221 -0
  3. data/ext/krypt/core/binyo-error.h +40 -0
  4. data/ext/krypt/core/binyo-io-buffer.h +54 -0
  5. data/ext/krypt/core/binyo-io.h +131 -0
  6. data/ext/krypt/core/extconf.h +8 -0
  7. data/ext/krypt/core/extconf.rb +80 -0
  8. data/ext/krypt/core/krypt-core.c +110 -0
  9. data/ext/krypt/core/krypt-core.h +97 -0
  10. data/ext/krypt/core/krypt-core.o +0 -0
  11. data/ext/krypt/core/krypt-provider.h +86 -0
  12. data/ext/krypt/core/krypt_asn1-internal.c +681 -0
  13. data/ext/krypt/core/krypt_asn1-internal.h +117 -0
  14. data/ext/krypt/core/krypt_asn1-internal.o +0 -0
  15. data/ext/krypt/core/krypt_asn1.c +2109 -0
  16. data/ext/krypt/core/krypt_asn1.h +88 -0
  17. data/ext/krypt/core/krypt_asn1.o +0 -0
  18. data/ext/krypt/core/krypt_asn1_codec.c +973 -0
  19. data/ext/krypt/core/krypt_asn1_codec.o +0 -0
  20. data/ext/krypt/core/krypt_asn1_in_adapter.c +178 -0
  21. data/ext/krypt/core/krypt_asn1_in_adapter.o +0 -0
  22. data/ext/krypt/core/krypt_asn1_in_chunked.c +292 -0
  23. data/ext/krypt/core/krypt_asn1_in_chunked.o +0 -0
  24. data/ext/krypt/core/krypt_asn1_in_definite.c +156 -0
  25. data/ext/krypt/core/krypt_asn1_in_definite.o +0 -0
  26. data/ext/krypt/core/krypt_asn1_parser.c +592 -0
  27. data/ext/krypt/core/krypt_asn1_parser.o +0 -0
  28. data/ext/krypt/core/krypt_asn1_template-internal.h +185 -0
  29. data/ext/krypt/core/krypt_asn1_template.c +459 -0
  30. data/ext/krypt/core/krypt_asn1_template.h +56 -0
  31. data/ext/krypt/core/krypt_asn1_template.o +0 -0
  32. data/ext/krypt/core/krypt_asn1_template_encoder.c +76 -0
  33. data/ext/krypt/core/krypt_asn1_template_encoder.o +0 -0
  34. data/ext/krypt/core/krypt_asn1_template_parser.c +1176 -0
  35. data/ext/krypt/core/krypt_asn1_template_parser.o +0 -0
  36. data/ext/krypt/core/krypt_b64-internal.h +38 -0
  37. data/ext/krypt/core/krypt_b64.c +391 -0
  38. data/ext/krypt/core/krypt_b64.h +41 -0
  39. data/ext/krypt/core/krypt_b64.o +0 -0
  40. data/ext/krypt/core/krypt_digest.c +391 -0
  41. data/ext/krypt/core/krypt_digest.h +51 -0
  42. data/ext/krypt/core/krypt_digest.o +0 -0
  43. data/ext/krypt/core/krypt_error.c +221 -0
  44. data/ext/krypt/core/krypt_error.h +46 -0
  45. data/ext/krypt/core/krypt_error.o +0 -0
  46. data/ext/krypt/core/krypt_hex-internal.h +36 -0
  47. data/ext/krypt/core/krypt_hex.c +255 -0
  48. data/ext/krypt/core/krypt_hex.h +41 -0
  49. data/ext/krypt/core/krypt_hex.o +0 -0
  50. data/ext/krypt/core/krypt_io.c +65 -0
  51. data/ext/krypt/core/krypt_io.h +56 -0
  52. data/ext/krypt/core/krypt_io.o +0 -0
  53. data/ext/krypt/core/krypt_io_in_pem.c +397 -0
  54. data/ext/krypt/core/krypt_io_in_pem.o +0 -0
  55. data/ext/krypt/core/krypt_missing.c +238 -0
  56. data/ext/krypt/core/krypt_missing.h +62 -0
  57. data/ext/krypt/core/krypt_missing.o +0 -0
  58. data/ext/krypt/core/krypt_pem.c +171 -0
  59. data/ext/krypt/core/krypt_pem.o +0 -0
  60. data/ext/krypt/core/krypt_provider-internal.h +40 -0
  61. data/ext/krypt/core/krypt_provider.c +136 -0
  62. data/ext/krypt/core/krypt_provider.o +0 -0
  63. data/ext/krypt/core/kryptcore.so +0 -0
  64. data/ext/krypt/core/mkmf.log +130 -0
  65. data/lib/krypt-core/version.rb +3 -0
  66. data/lib/krypt-core.rb +35 -0
  67. data/lib/kryptcore.so +0 -0
  68. data/spec/README +2 -0
  69. data/test/README +2 -0
  70. data/test/res/certificate.cer +0 -0
  71. data/test/resources.rb +48 -0
  72. data/test/scratch.rb +17 -0
  73. metadata +150 -0
Binary file
@@ -0,0 +1,178 @@
1
+ /*
2
+ * krypt-core API - C implementation
3
+ *
4
+ * Copyright (c) 2011-2013
5
+ * Hiroshi Nakamura <nahi@ruby-lang.org>
6
+ * Martin Bosslet <martin.bosslet@gmail.com>
7
+ * All rights reserved.
8
+ *
9
+ * Permission is hereby granted, free of charge, to any person obtaining
10
+ * a copy of this software and associated documentation files (the
11
+ * "Software"), to deal in the Software without restriction, including
12
+ * without limitation the rights to use, copy, modify, merge, publish,
13
+ * distribute, sublicense, and/or sell copies of the Software, and to
14
+ * permit persons to whom the Software is furnished to do so, subject to
15
+ * the following conditions:
16
+ *
17
+ * The above copyright notice and this permission notice shall be
18
+ * included in all copies or substantial portions of the Software.
19
+ *
20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
+ */
28
+
29
+ #include "krypt-core.h"
30
+
31
+ VALUE cKryptASN1Instream;
32
+
33
+ typedef struct krypt_instream_adapter_st {
34
+ binyo_instream *in;
35
+ } krypt_instream_adapter;
36
+
37
+ static void
38
+ int_instream_adapter_mark(krypt_instream_adapter *adapter)
39
+ {
40
+ if (!adapter) return;
41
+
42
+ binyo_instream_mark(adapter->in);
43
+ }
44
+
45
+ static void
46
+ int_instream_adapter_free(krypt_instream_adapter *adapter)
47
+ {
48
+ if (!adapter) return;
49
+
50
+ binyo_instream_free(adapter->in);
51
+ xfree(adapter);
52
+ }
53
+
54
+ #define int_krypt_instream_adapter_set(klass, obj, adapter) \
55
+ do { \
56
+ if (!(adapter)) { \
57
+ rb_raise(eKryptError, "Uninitialized Adapter"); \
58
+ } \
59
+ (obj) = Data_Wrap_Struct((klass), int_instream_adapter_mark, int_instream_adapter_free, (adapter)); \
60
+ } while (0)
61
+
62
+ #define int_krypt_instream_adapter_get(obj, adapter) \
63
+ do { \
64
+ Data_Get_Struct((obj), krypt_instream_adapter, (adapter)); \
65
+ if (!(adapter)) { \
66
+ rb_raise(eKryptError, "Uninitialized Adapter"); \
67
+ } \
68
+ } while (0)
69
+
70
+ VALUE
71
+ krypt_instream_adapter_new(binyo_instream *in)
72
+ {
73
+ VALUE obj;
74
+ krypt_instream_adapter *adapter;
75
+
76
+ adapter = ALLOC(krypt_instream_adapter);
77
+ adapter->in = in;
78
+ int_krypt_instream_adapter_set(cKryptASN1Instream, obj, adapter);
79
+ return obj;
80
+ }
81
+
82
+ /**
83
+ * call-seq:
84
+ * in.read([len=nil], [buf=nil]) -> String or nil
85
+ *
86
+ * Please see IO#read for details.
87
+ */
88
+ static VALUE
89
+ krypt_instream_adapter_read(int argc, VALUE *argv, VALUE self)
90
+ {
91
+ krypt_instream_adapter *adapter;
92
+ VALUE ret;
93
+ VALUE vlen = Qnil;
94
+ VALUE vbuf = Qnil;
95
+
96
+ rb_scan_args(argc, argv, "02", &vlen, &vbuf);
97
+
98
+ int_krypt_instream_adapter_get(self, adapter);
99
+
100
+ if (binyo_instream_rb_read(adapter->in, vlen, vbuf, &ret) == BINYO_ERR)
101
+ rb_raise(eKryptError, "Error reading stream");
102
+ return ret;
103
+ }
104
+
105
+ static int
106
+ int_whence_for(VALUE vwhence)
107
+ {
108
+ ID whence;
109
+
110
+ if (!SYMBOL_P(vwhence))
111
+ rb_raise(rb_eArgError, "whence must be a Symbol");
112
+
113
+ whence = SYM2ID(vwhence);
114
+ if (whence == sBinyo_ID_SEEK_CUR)
115
+ return SEEK_CUR;
116
+ else if (whence == sBinyo_ID_SEEK_SET)
117
+ return SEEK_SET;
118
+ else if (whence == sBinyo_ID_SEEK_END)
119
+ return SEEK_END;
120
+ else
121
+ rb_raise(eKryptASN1ParseError, "Unknown whence");
122
+
123
+ return Qnil; /* dummy */
124
+ }
125
+
126
+ /**
127
+ * call-seq:
128
+ * in.seek(n, [whence=:SEEK_SET]) -> 0
129
+ *
130
+ * Please see IO#seek for details.
131
+ */
132
+ static VALUE
133
+ krypt_instream_adapter_seek(int argc, VALUE *argv, VALUE self)
134
+ {
135
+ VALUE n, vwhence = sBinyo_ID_SEEK_SET;
136
+ int whence;
137
+ krypt_instream_adapter *adapter;
138
+
139
+ rb_scan_args(argc, argv, "11", &n, &whence);
140
+
141
+ int_krypt_instream_adapter_get(self, adapter);
142
+ whence = int_whence_for(vwhence);
143
+ if (binyo_instream_seek(adapter->in, NUM2INT(n), whence) == BINYO_ERR)
144
+ rb_raise(eKryptASN1ParseError, "Seek failed");
145
+
146
+ return INT2FIX(0); /* same as rb_io_seek */
147
+ }
148
+
149
+ void
150
+ Init_krypt_instream_adapter(void)
151
+ {
152
+ #if 0
153
+ mKrypt = rb_define_module("Krypt");
154
+ mKryptASN1 = rb_define_module_under(mKrypt, "ASN1"); /* Let RDoc know */
155
+ #endif
156
+
157
+ /**
158
+ * Document-class: Krypt::ASN1::Instream
159
+ *
160
+ * Acts as a drop-in replacement for an IO. It cannot be instantiated on
161
+ * its own, instances may be obtained by calling Header#value_io. Instream
162
+ * supports a reduced subset of the interface defined by IO.
163
+ *
164
+ * == Example usage
165
+ *
166
+ * === Reading the contents of an Instream
167
+ * der_io = # some IO representing a DER-encoded ASN.1 value
168
+ * parser = Krypt::ASN1::Parser.new
169
+ * token = parser.next(der_io)
170
+ * instream = token.value_io
171
+ * value = instream.read # contains the raw bytes of the token's value
172
+ */
173
+ cKryptASN1Instream = rb_define_class_under(mKryptASN1, "Instream", rb_cObject);
174
+ rb_define_method(cKryptASN1Instream, "read", krypt_instream_adapter_read, -1);
175
+ rb_define_method(cKryptASN1Instream, "seek", krypt_instream_adapter_seek, -1);
176
+ rb_undef_method(CLASS_OF(cKryptASN1Instream), "new"); /* private constructor */
177
+ }
178
+
@@ -0,0 +1,292 @@
1
+ /*
2
+ * krypt-core API - C implementation
3
+ *
4
+ * Copyright (c) 2011-2013
5
+ * Hiroshi Nakamura <nahi@ruby-lang.org>
6
+ * Martin Bosslet <martin.bosslet@gmail.com>
7
+ * All rights reserved.
8
+ *
9
+ * Permission is hereby granted, free of charge, to any person obtaining
10
+ * a copy of this software and associated documentation files (the
11
+ * "Software"), to deal in the Software without restriction, including
12
+ * without limitation the rights to use, copy, modify, merge, publish,
13
+ * distribute, sublicense, and/or sell copies of the Software, and to
14
+ * permit persons to whom the Software is furnished to do so, subject to
15
+ * the following conditions:
16
+ *
17
+ * The above copyright notice and this permission notice shall be
18
+ * included in all copies or substantial portions of the Software.
19
+ *
20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
+ */
28
+
29
+ #include "krypt-core.h"
30
+ #include "krypt_asn1-internal.h"
31
+
32
+ enum krypt_chunked_state {
33
+ NEW_HEADER = 0,
34
+ PROCESS_TAG,
35
+ PROCESS_LENGTH,
36
+ PROCESS_VALUE,
37
+ DONE
38
+ };
39
+
40
+ typedef struct krypt_instream_chunked {
41
+ binyo_instream_interface *methods;
42
+ binyo_instream *inner;
43
+ int values_only;
44
+ enum krypt_chunked_state state;
45
+ krypt_asn1_header *cur_header;
46
+ binyo_instream *cur_value_stream;
47
+ size_t header_offset;
48
+ } krypt_instream_chunked;
49
+
50
+ #define int_safe_cast(out, in) binyo_safe_cast_instream((out), (in), KRYPT_INSTREAM_TYPE_CHUNKED, krypt_instream_chunked)
51
+
52
+ static krypt_instream_chunked* int_chunked_alloc(void);
53
+ static ssize_t int_chunked_read(binyo_instream *in, uint8_t *buf, size_t len);
54
+ static int int_chunked_seek(binyo_instream *in, off_t offset, int whence);
55
+ static void int_chunked_mark(binyo_instream *in);
56
+ static void int_chunked_free(binyo_instream *in);
57
+
58
+ static binyo_instream_interface krypt_interface_chunked = {
59
+ KRYPT_INSTREAM_TYPE_CHUNKED,
60
+ int_chunked_read,
61
+ NULL,
62
+ NULL,
63
+ int_chunked_seek,
64
+ int_chunked_mark,
65
+ int_chunked_free
66
+ };
67
+
68
+ binyo_instream *
69
+ krypt_instream_new_chunked(binyo_instream *original, int values_only)
70
+ {
71
+ krypt_instream_chunked *in;
72
+
73
+ in = int_chunked_alloc();
74
+ in->inner = original;
75
+ in->values_only = values_only;
76
+ in->state = NEW_HEADER;
77
+ return (binyo_instream *) in;
78
+ }
79
+
80
+ static krypt_instream_chunked*
81
+ int_chunked_alloc(void)
82
+ {
83
+ krypt_instream_chunked *ret;
84
+ ret = ALLOC(krypt_instream_chunked);
85
+ memset(ret, 0, sizeof(krypt_instream_chunked));
86
+ ret->methods = &krypt_interface_chunked;
87
+ return ret;
88
+ }
89
+
90
+ static int
91
+ int_read_new_header(krypt_instream_chunked *in)
92
+ {
93
+ int ret;
94
+ krypt_asn1_header *next;
95
+
96
+ ret = krypt_asn1_next_header(in->inner, &next);
97
+ if (ret == KRYPT_ASN1_EOF) {
98
+ krypt_error_add("Premature end of value detected");
99
+ return BINYO_ERR;
100
+ }
101
+ if (ret == KRYPT_ERR) {
102
+ krypt_error_add("An error occured while reading the ASN.1 header");
103
+ return BINYO_ERR;
104
+ }
105
+
106
+ if (in->cur_header)
107
+ krypt_asn1_header_free(in->cur_header);
108
+ in->cur_header = next;
109
+ in->state = PROCESS_TAG;
110
+ in->header_offset = 0;
111
+ return BINYO_OK;
112
+ }
113
+
114
+ static size_t
115
+ int_read_header_bytes(krypt_instream_chunked *in,
116
+ uint8_t * bytes,
117
+ size_t bytes_len,
118
+ enum krypt_chunked_state next_state,
119
+ uint8_t *buf,
120
+ size_t len)
121
+ {
122
+ size_t to_read;
123
+ size_t available = bytes_len - in->header_offset;
124
+
125
+ if (len < available) {
126
+ in->header_offset += len;
127
+ to_read = len;
128
+ }
129
+ else {
130
+ in->state = next_state;
131
+ in->header_offset = 0;
132
+ to_read = available;
133
+ }
134
+
135
+ memcpy(buf, bytes, to_read);
136
+ return to_read;
137
+ }
138
+
139
+ static ssize_t
140
+ int_read_value(krypt_instream_chunked *in, uint8_t *buf, size_t len)
141
+ {
142
+ ssize_t read;
143
+
144
+ if (!in->cur_value_stream)
145
+ in->cur_value_stream = krypt_asn1_get_value_stream(in->inner, in->cur_header, in->values_only);
146
+
147
+ read = binyo_instream_read(in->cur_value_stream, buf, len);
148
+ if (read == BINYO_ERR) return BINYO_ERR;
149
+
150
+ if (read == BINYO_IO_EOF) {
151
+ if (in->state != DONE)
152
+ in->state = NEW_HEADER;
153
+ binyo_instream_free(in->cur_value_stream);
154
+ in->cur_value_stream = NULL;
155
+ read = 0;
156
+ }
157
+
158
+ return read;
159
+ }
160
+
161
+ /* If state is PROCESS_VALUE, this means that the tag bytes
162
+ * have been consumed. As an EOC contains no value, we are
163
+ * done.
164
+ */
165
+ #define int_check_done(in) \
166
+ do { \
167
+ if ((in)->cur_header->tag == TAGS_END_OF_CONTENTS && \
168
+ (in)->cur_header->tag_class == TAG_CLASS_UNIVERSAL && \
169
+ (in)->state == PROCESS_VALUE) { \
170
+ (in)->state = DONE; \
171
+ } \
172
+ } while (0)
173
+
174
+ /* TODO: check overflow */
175
+ static ssize_t
176
+ int_read_single_element(krypt_instream_chunked *in, uint8_t *buf, size_t len)
177
+ {
178
+ ssize_t read = 0;
179
+ size_t total = 0;
180
+
181
+ #define add_header_bytes() \
182
+ do { \
183
+ if (!in->values_only) { \
184
+ total += read; \
185
+ if (total == len || in->state == DONE) \
186
+ return (ssize_t) total; \
187
+ if (total > len) return BINYO_ERR; \
188
+ buf += read; \
189
+ } \
190
+ } while (0)
191
+
192
+ switch (in->state) {
193
+ case NEW_HEADER:
194
+ if (!int_read_new_header(in))
195
+ return BINYO_ERR;
196
+ /* fallthrough */
197
+ case PROCESS_TAG:
198
+ read = int_read_header_bytes(in,
199
+ in->cur_header->tag_bytes,
200
+ in->cur_header->tag_len,
201
+ PROCESS_LENGTH,
202
+ buf,
203
+ len);
204
+ add_header_bytes();
205
+ /* fallthrough */
206
+ case PROCESS_LENGTH:
207
+ read = int_read_header_bytes(in,
208
+ in->cur_header->length_bytes,
209
+ in->cur_header->length_len,
210
+ PROCESS_VALUE,
211
+ buf,
212
+ len);
213
+ int_check_done(in);
214
+ add_header_bytes();
215
+ /* fallthrough */
216
+ case PROCESS_VALUE:
217
+ read = int_read_value(in, buf, len);
218
+ if (read == BINYO_ERR) return BINYO_ERR;
219
+ total += read;
220
+ buf += read;
221
+ return (ssize_t) total;
222
+ default:
223
+ krypt_error_add("Internal error");
224
+ return BINYO_ERR; /* dummy */
225
+ }
226
+ }
227
+
228
+ static ssize_t
229
+ int_read(krypt_instream_chunked *in, uint8_t *buf, size_t len)
230
+ {
231
+ ssize_t read = 0;
232
+ size_t total = 0;
233
+
234
+ while (total != len && in->state != DONE) {
235
+ read = int_read_single_element(in, buf, len);
236
+ if (read == BINYO_ERR) return BINYO_ERR;
237
+ if (total > (size_t) (SSIZE_MAX - read)) {
238
+ krypt_error_add("Stream too large");
239
+ return BINYO_ERR;
240
+ }
241
+ total += read;
242
+ buf += read;
243
+ }
244
+ return total;
245
+ }
246
+
247
+ static ssize_t
248
+ int_chunked_read(binyo_instream *instream, uint8_t *buf, size_t len)
249
+ {
250
+ krypt_instream_chunked *in;
251
+
252
+ int_safe_cast(in, instream);
253
+
254
+ if (!buf) return BINYO_ERR;
255
+ if (in->state == DONE)
256
+ return BINYO_IO_EOF;
257
+
258
+ return int_read(in, buf, len);
259
+ }
260
+
261
+ static int
262
+ int_chunked_seek(binyo_instream *instream, off_t offset, int whence)
263
+ {
264
+ /* int_instream_chunked *in;
265
+
266
+ int_safe_cast(in, instream); */
267
+
268
+ return BINYO_OK;
269
+ /* TODO */
270
+ }
271
+
272
+ static void
273
+ int_chunked_mark(binyo_instream *instream)
274
+ {
275
+ krypt_instream_chunked *in;
276
+
277
+ if (!instream) return;
278
+ int_safe_cast(in, instream);
279
+ binyo_instream_mark(in->inner);
280
+ }
281
+
282
+ static void
283
+ int_chunked_free(binyo_instream *instream)
284
+ {
285
+ krypt_instream_chunked *in;
286
+
287
+ if (!instream) return;
288
+ int_safe_cast(in, instream);
289
+ if (in->cur_header)
290
+ krypt_asn1_header_free(in->cur_header);
291
+ }
292
+
@@ -0,0 +1,156 @@
1
+ /*
2
+ * krypt-core API - C implementation
3
+ *
4
+ * Copyright (c) 2011-2013
5
+ * Hiroshi Nakamura <nahi@ruby-lang.org>
6
+ * Martin Bosslet <martin.bosslet@gmail.com>
7
+ * All rights reserved.
8
+ *
9
+ * Permission is hereby granted, free of charge, to any person obtaining
10
+ * a copy of this software and associated documentation files (the
11
+ * "Software"), to deal in the Software without restriction, including
12
+ * without limitation the rights to use, copy, modify, merge, publish,
13
+ * distribute, sublicense, and/or sell copies of the Software, and to
14
+ * permit persons to whom the Software is furnished to do so, subject to
15
+ * the following conditions:
16
+ *
17
+ * The above copyright notice and this permission notice shall be
18
+ * included in all copies or substantial portions of the Software.
19
+ *
20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
+ */
28
+
29
+ #include "krypt-core.h"
30
+
31
+ typedef struct krypt_instream_definite_st {
32
+ binyo_instream_interface *methods;
33
+ binyo_instream *inner;
34
+ size_t max_read;
35
+ size_t num_read;
36
+ } krypt_instream_definite;
37
+
38
+ #define int_safe_cast(out, in) binyo_safe_cast_instream((out), (in), KRYPT_INSTREAM_TYPE_DEFINITE, krypt_instream_definite)
39
+
40
+ static krypt_instream_definite* int_definite_alloc(void);
41
+ static ssize_t int_definite_read(binyo_instream *in, uint8_t *buf, size_t len);
42
+ static int int_definite_seek(binyo_instream *in, off_t offset, int whence);
43
+ static void int_definite_mark(binyo_instream *in);
44
+ static void int_definite_free(binyo_instream *in);
45
+
46
+ static binyo_instream_interface krypt_interface_definite = {
47
+ KRYPT_INSTREAM_TYPE_DEFINITE,
48
+ int_definite_read,
49
+ NULL,
50
+ NULL,
51
+ int_definite_seek,
52
+ int_definite_mark,
53
+ int_definite_free
54
+ };
55
+
56
+ binyo_instream *
57
+ krypt_instream_new_definite(binyo_instream *original, size_t len)
58
+ {
59
+ krypt_instream_definite *in;
60
+
61
+ in = int_definite_alloc();
62
+ in->inner = original;
63
+ in->max_read = len;
64
+ return (binyo_instream *) in;
65
+ }
66
+
67
+ static krypt_instream_definite*
68
+ int_definite_alloc(void)
69
+ {
70
+ krypt_instream_definite *ret;
71
+ ret = ALLOC(krypt_instream_definite);
72
+ memset(ret, 0, sizeof(krypt_instream_definite));
73
+ ret->methods = &krypt_interface_definite;
74
+ return ret;
75
+ }
76
+
77
+ static ssize_t
78
+ int_definite_read(binyo_instream *instream, uint8_t *buf, size_t len)
79
+ {
80
+ krypt_instream_definite *in;
81
+ size_t to_read;
82
+ ssize_t r;
83
+
84
+ int_safe_cast(in, instream);
85
+
86
+ if (!buf) return BINYO_ERR;
87
+
88
+ if (in->num_read == in->max_read)
89
+ return BINYO_IO_EOF;
90
+
91
+ if (in->max_read - in->num_read < len)
92
+ to_read = in->max_read - in->num_read;
93
+ else
94
+ to_read = len;
95
+
96
+ r = binyo_instream_read(in->inner, buf, to_read);
97
+ if (r == BINYO_ERR || r == BINYO_IO_EOF) return BINYO_ERR;
98
+ if (in->num_read >= SIZE_MAX - r) {
99
+ krypt_error_add("Stream too large");
100
+ return BINYO_ERR;
101
+ }
102
+
103
+ in->num_read += r;
104
+ return r;
105
+ }
106
+
107
+ static int
108
+ int_definite_seek(binyo_instream *instream, off_t offset, int whence)
109
+ {
110
+ off_t real_off;
111
+ long numread;
112
+ krypt_instream_definite *in;
113
+
114
+ int_safe_cast(in, instream);
115
+
116
+ switch (whence) {
117
+ case SEEK_CUR:
118
+ real_off = offset;
119
+ break;
120
+ case SEEK_SET:
121
+ real_off = offset - in->num_read;
122
+ break;
123
+ case SEEK_END:
124
+ real_off = offset + in->max_read - in->num_read;
125
+ break;
126
+ default:
127
+ krypt_error_add("Unknown whence: %d", whence);
128
+ return BINYO_ERR;
129
+ }
130
+
131
+ numread = in->num_read;
132
+ if (numread + real_off < 0 || numread + real_off >= (long)in->max_read) {
133
+ krypt_error_add("Invalid seek position: %ld", numread + real_off);
134
+ return BINYO_ERR;
135
+ }
136
+
137
+ return binyo_instream_seek(in->inner, offset, whence);
138
+ }
139
+
140
+ static void
141
+ int_definite_mark(binyo_instream *instream)
142
+ {
143
+ krypt_instream_definite *in;
144
+
145
+ if (!instream) return;
146
+ int_safe_cast(in, instream);
147
+ binyo_instream_mark(in->inner);
148
+ }
149
+
150
+
151
+ static void
152
+ int_definite_free(binyo_instream *instream)
153
+ {
154
+ /* do not free the inner stream */
155
+ }
156
+