krypt-core 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+