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
@@ -0,0 +1,1176 @@
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
+ #include "krypt_asn1_template-internal.h"
32
+
33
+ struct krypt_asn1_template_match_ctx {
34
+ krypt_asn1_object *object;
35
+ krypt_asn1_header *header;
36
+ int free_header;
37
+ };
38
+
39
+ struct krypt_asn1_template_parse_ctx {
40
+ int (*match)(VALUE recv, struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_definition *def);
41
+ int (*parse)(VALUE recv, krypt_asn1_object *obj, krypt_asn1_definition *def, int *dont_free);
42
+ int (*decode)(VALUE recv, krypt_asn1_object *object, krypt_asn1_definition *def, VALUE *out);
43
+ };
44
+
45
+ static int int_match_prim(VALUE self, struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_definition *def);
46
+ static int int_parse_assign(VALUE self, krypt_asn1_object *object, krypt_asn1_definition *def, int *dont_free);
47
+ static int int_decode_prim(VALUE self, krypt_asn1_object *object, krypt_asn1_definition *def, VALUE *out);
48
+
49
+ static int int_match_sequence(VALUE self, struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_definition *def);
50
+ static int int_match_set(VALUE self, struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_definition *def);
51
+ static int int_parse_cons(VALUE self, krypt_asn1_object *object, krypt_asn1_definition *def, int *dont_free);
52
+
53
+ static int int_match_template(VALUE self, struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_definition *def);
54
+ static int int_parse_template(VALUE self, krypt_asn1_object *object, krypt_asn1_definition *def, int *dont_free);
55
+
56
+ static int int_match_seq_of(VALUE self, struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_definition *def);
57
+ static int int_match_set_of(VALUE self, struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_definition *def);
58
+ static int int_decode_cons_of(VALUE self, krypt_asn1_object *object, krypt_asn1_definition *def, VALUE *out);
59
+
60
+ static int int_match_any(VALUE self, struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_definition *def);
61
+ static int int_decode_any(VALUE self, krypt_asn1_object *object, krypt_asn1_definition *def, VALUE *out);
62
+
63
+ static int int_match_choice(VALUE self, struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_definition *def);
64
+ static int int_parse_choice(VALUE self, krypt_asn1_object *object, krypt_asn1_definition *def, int *dont_free);
65
+
66
+ static int krypt_asn1_template_parse_stream(binyo_instream *in, VALUE klass, VALUE *out);
67
+
68
+ static struct krypt_asn1_template_parse_ctx krypt_template_primitive_ctx= {
69
+ int_match_prim,
70
+ int_parse_assign,
71
+ int_decode_prim
72
+ };
73
+
74
+ static struct krypt_asn1_template_parse_ctx krypt_template_sequence_ctx= {
75
+ int_match_sequence,
76
+ int_parse_cons,
77
+ NULL
78
+ };
79
+
80
+ static struct krypt_asn1_template_parse_ctx krypt_template_set_ctx= {
81
+ int_match_set,
82
+ int_parse_cons,
83
+ NULL
84
+ };
85
+
86
+ static struct krypt_asn1_template_parse_ctx krypt_template_template_ctx= {
87
+ int_match_template,
88
+ int_parse_template,
89
+ NULL
90
+ };
91
+
92
+ static struct krypt_asn1_template_parse_ctx krypt_template_seq_of_ctx= {
93
+ int_match_seq_of,
94
+ int_parse_assign,
95
+ int_decode_cons_of
96
+ };
97
+
98
+ static struct krypt_asn1_template_parse_ctx krypt_template_set_of_ctx= {
99
+ int_match_set_of,
100
+ int_parse_assign,
101
+ int_decode_cons_of
102
+ };
103
+
104
+ static struct krypt_asn1_template_parse_ctx krypt_template_any_ctx= {
105
+ int_match_any,
106
+ int_parse_assign,
107
+ int_decode_any
108
+ };
109
+
110
+ static struct krypt_asn1_template_parse_ctx krypt_template_choice_ctx= {
111
+ int_match_choice,
112
+ int_parse_choice,
113
+ NULL
114
+ };
115
+
116
+ static struct krypt_asn1_template_parse_ctx *
117
+ int_get_parse_ctx_for_codec(ID codec) {
118
+ if (codec == sKrypt_ID_PRIMITIVE)
119
+ return &krypt_template_primitive_ctx;
120
+ else if (codec == sKrypt_ID_SEQUENCE)
121
+ return &krypt_template_sequence_ctx;
122
+ else if (codec == sKrypt_ID_TEMPLATE)
123
+ return &krypt_template_template_ctx;
124
+ else if (codec == sKrypt_ID_SET)
125
+ return &krypt_template_set_ctx;
126
+ else if (codec == sKrypt_ID_SEQUENCE_OF)
127
+ return &krypt_template_seq_of_ctx;
128
+ else if (codec == sKrypt_ID_SET_OF)
129
+ return &krypt_template_set_of_ctx;
130
+ else if (codec == sKrypt_ID_ANY)
131
+ return &krypt_template_any_ctx;
132
+ else if (codec == sKrypt_ID_CHOICE)
133
+ return &krypt_template_choice_ctx;
134
+ else {
135
+ krypt_error_add("Unknown codec: %s", rb_id2name(codec));
136
+ return NULL;
137
+ }
138
+ }
139
+
140
+ #define INT_KRYPT_MATCH 1
141
+ #define INT_KRYPT_NO_MATCH 0
142
+ #define INT_KRYPT_MATCH_ERR -1
143
+ #define INT_KRYPT_MATCH_DEFAULT_APPLIED -2
144
+
145
+ static void
146
+ int_match_ctx_init(struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_object *object)
147
+ {
148
+ ctx->object = object;
149
+ ctx->header = object->header;
150
+ ctx->free_header = 0;
151
+ }
152
+
153
+ static int
154
+ int_match_ctx_skip_header(struct krypt_asn1_template_match_ctx *ctx)
155
+ {
156
+ krypt_asn1_header *next;
157
+ binyo_instream *in = binyo_instream_new_bytes(ctx->object->bytes, ctx->object->bytes_len);
158
+ if (krypt_asn1_next_header(in, &next) != KRYPT_OK) {
159
+ binyo_instream_free(in);
160
+ return KRYPT_ERR;
161
+ }
162
+ ctx->header = next;
163
+ ctx->free_header = 1;
164
+ binyo_instream_free(in);
165
+
166
+ return KRYPT_OK;
167
+ }
168
+
169
+ static void
170
+ int_match_ctx_cleanup(struct krypt_asn1_template_match_ctx *ctx)
171
+ {
172
+ if (ctx->free_header)
173
+ xfree(ctx->header);
174
+ }
175
+
176
+ static int
177
+ int_expected_tag(VALUE tag, int default_tag)
178
+ {
179
+ if (NIL_P(tag))
180
+ return default_tag;
181
+ else
182
+ return NUM2INT(tag);
183
+ }
184
+
185
+ static int
186
+ int_expected_tag_class(VALUE tag_class)
187
+ {
188
+ if (NIL_P(tag_class))
189
+ return TAG_CLASS_UNIVERSAL;
190
+ else
191
+ return krypt_asn1_tag_class_for_id(SYM2ID(tag_class));
192
+ }
193
+
194
+ static int
195
+ int_match_tag(krypt_asn1_header *header, VALUE tag, int default_tag)
196
+ {
197
+ if (header->tag == int_expected_tag(tag, default_tag))
198
+ return INT_KRYPT_MATCH;
199
+ else
200
+ return INT_KRYPT_NO_MATCH;
201
+ }
202
+
203
+ static int
204
+ int_match_class(krypt_asn1_header *header, VALUE tag_class)
205
+ {
206
+ int expected_tc;
207
+
208
+ if ((expected_tc = int_expected_tag_class(tag_class)) == KRYPT_ERR) return INT_KRYPT_NO_MATCH;
209
+ if (header->tag_class == expected_tc)
210
+ return INT_KRYPT_MATCH;
211
+ else
212
+ return INT_KRYPT_NO_MATCH;
213
+ }
214
+
215
+ static int
216
+ int_tag_and_class_mismatch(krypt_asn1_header *header, VALUE tag, VALUE tagging, int default_tag, const char *name)
217
+ {
218
+ int expected_tag = int_expected_tag(tag, default_tag);
219
+ int expected_tag_class = int_expected_tag_class(tagging);
220
+
221
+ if (name)
222
+ krypt_error_add("Could not parse %s", name);
223
+ if (header->tag != expected_tag)
224
+ krypt_error_add("Tag mismatch. Expected: %d Got: %d", expected_tag, header->tag);
225
+ if (header->tag_class != expected_tag_class) {
226
+ ID expected = krypt_asn1_tag_class_for_int(expected_tag_class);
227
+ ID got = krypt_asn1_tag_class_for_int(header->tag_class);
228
+ krypt_error_add("Tag class mismatch. Expected: %s Got: %s", rb_id2name(expected), rb_id2name(got));
229
+ }
230
+ return INT_KRYPT_MATCH_ERR;
231
+ }
232
+
233
+ static int
234
+ int_match_tag_and_class(krypt_asn1_header *header, VALUE tag, VALUE tagging, int default_tag)
235
+ {
236
+ if (int_match_tag(header, tag, default_tag) == INT_KRYPT_NO_MATCH) return INT_KRYPT_NO_MATCH;
237
+ if (int_match_class(header, tagging) == INT_KRYPT_NO_MATCH) return INT_KRYPT_NO_MATCH;
238
+ return INT_KRYPT_MATCH;
239
+ }
240
+
241
+ static krypt_asn1_header *
242
+ int_parse_explicit_header(krypt_asn1_object *object)
243
+ {
244
+ krypt_asn1_header *header;
245
+ binyo_instream *in = binyo_instream_new_bytes(object->bytes, object->bytes_len);
246
+
247
+ if (krypt_asn1_next_header(in, &header) != KRYPT_OK) {
248
+ krypt_error_add("Could not unpack explicitly tagged value");
249
+ return NULL;
250
+ }
251
+ binyo_instream_free(in);
252
+ return header;
253
+ }
254
+
255
+ static krypt_asn1_header *
256
+ int_unpack_explicit(VALUE tagging, krypt_asn1_object *object, uint8_t **pp, size_t *len, int *free_header)
257
+ {
258
+
259
+ if (NIL_P(tagging) || SYM2ID(tagging) != sKrypt_TC_EXPLICIT) {
260
+ *pp = object->bytes;
261
+ *len = object->bytes_len;
262
+ *free_header = 0;
263
+ return object->header;
264
+ } else {
265
+ int header_len;
266
+ krypt_asn1_header *header;
267
+
268
+ if (!object->header->is_constructed) {
269
+ krypt_error_add("Constructive bit not set for explicitly tagged value");
270
+ return NULL;
271
+ }
272
+ if(!(header = int_parse_explicit_header(object))) return NULL;
273
+ header_len = header->tag_len + header->length_len;
274
+ *pp = object->bytes + header_len;
275
+ *len = object->bytes_len - header_len;
276
+ *free_header = 1;
277
+ return header;
278
+ }
279
+ }
280
+
281
+ static int
282
+ int_next_object(binyo_instream *in, krypt_asn1_object **out)
283
+ {
284
+ krypt_asn1_header *next = NULL;
285
+ krypt_asn1_object *next_object = NULL;
286
+ int result;
287
+ size_t value_len;
288
+ uint8_t *value = NULL;
289
+
290
+ result = krypt_asn1_next_header(in, &next);
291
+ if (result == KRYPT_ASN1_EOF) return KRYPT_ASN1_EOF;
292
+ if (result == KRYPT_ERR) goto error;
293
+
294
+ if (krypt_asn1_get_value(in, next, &value, &value_len) == KRYPT_ERR) goto error;
295
+ if (!(next_object = krypt_asn1_object_new_value(next, value, value_len))) goto error;
296
+
297
+ *out = next_object;
298
+ return KRYPT_OK;
299
+
300
+ error:
301
+ if (next) krypt_asn1_header_free(next);
302
+ krypt_error_add("Error while trying to read next value");
303
+ return KRYPT_ERR;
304
+ }
305
+
306
+ static int
307
+ int_parse_eoc(binyo_instream *in)
308
+ {
309
+ krypt_asn1_header *next;
310
+ int result = krypt_asn1_next_header(in, &next);
311
+ int ret;
312
+
313
+ if (result == KRYPT_ASN1_EOF || result == KRYPT_ERR) return KRYPT_ERR;
314
+ if (!(next->tag == TAGS_END_OF_CONTENTS && next->tag_class == TAG_CLASS_UNIVERSAL))
315
+ ret = KRYPT_ERR;
316
+ else
317
+ ret = KRYPT_OK;
318
+ krypt_asn1_header_free(next);
319
+ return ret;
320
+ }
321
+
322
+ static int
323
+ int_ensure_stream_is_consumed(binyo_instream *in)
324
+ {
325
+ uint8_t b;
326
+ int result;
327
+
328
+ result = binyo_instream_read(in, &b, 1);
329
+ if (result == BINYO_OK) {
330
+ krypt_error_add("Data left that could not be parsed");
331
+ return KRYPT_ERR;
332
+ } else if (result != BINYO_IO_EOF) {
333
+ return KRYPT_ERR;
334
+ }
335
+ return KRYPT_OK;
336
+ }
337
+
338
+ static int
339
+ int_try_match_cons(struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_definition *def, int default_tag)
340
+ {
341
+ krypt_asn1_header *header = ctx->header;
342
+ VALUE tag = krypt_definition_get_tag(def);
343
+ VALUE tagging = krypt_definition_get_tagging(def);
344
+
345
+ if (header->is_constructed &&
346
+ int_match_tag_and_class(header, tag, tagging, default_tag) == INT_KRYPT_MATCH) return INT_KRYPT_MATCH;
347
+
348
+ if (!header->is_constructed && !krypt_definition_is_optional(def)) {
349
+ krypt_error_add("Constructive bit not set");
350
+ return INT_KRYPT_MATCH_ERR;
351
+ }
352
+ return INT_KRYPT_NO_MATCH;
353
+ }
354
+
355
+ static ID
356
+ int_determine_name(VALUE name)
357
+ {
358
+ if (NIL_P(name))
359
+ return sKrypt_IV_VALUE; /* CHOICE values have no name */
360
+ else
361
+ return SYM2ID(name);
362
+ }
363
+
364
+ static void
365
+ int_set_default_value(VALUE self, krypt_asn1_definition *def)
366
+ {
367
+ ID name;
368
+ VALUE obj, def_value;
369
+ krypt_asn1_template *template;
370
+
371
+ name = int_determine_name(krypt_definition_get_name(def));
372
+ /* set the default value, no more decoding needed */
373
+ def_value = krypt_definition_get_default_value(def);
374
+ template = krypt_asn1_template_new_value(def_value);
375
+ krypt_asn1_template_set(cKryptASN1TemplateValue, obj, template);
376
+ rb_ivar_set(self, name, obj);
377
+ }
378
+
379
+ static int
380
+ int_check_optional_or_default(VALUE self, struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_definition *def, int default_tag)
381
+ {
382
+ krypt_asn1_header *header = ctx->header;
383
+ VALUE tag = krypt_definition_get_tag(def);
384
+ VALUE tagging = krypt_definition_get_tagging(def);
385
+
386
+ if (!krypt_definition_is_optional(def)) {
387
+ const char *str;
388
+ ID name = int_determine_name(krypt_definition_get_name(def));
389
+ str = rb_id2name(name);
390
+ krypt_error_add("Mandatory value %s is missing", str);
391
+ return int_tag_and_class_mismatch(header, tag, tagging, default_tag, str);
392
+ }
393
+
394
+ if (krypt_definition_has_default(def)) {
395
+ int_set_default_value(self, def);
396
+ return INT_KRYPT_MATCH_DEFAULT_APPLIED;
397
+ }
398
+
399
+ return INT_KRYPT_NO_MATCH;
400
+ }
401
+
402
+ static int
403
+ int_match_prim(VALUE self, struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_definition *def)
404
+ {
405
+ VALUE tag, tagging, vdef_tag;
406
+ krypt_asn1_header *header = ctx->header;
407
+ int default_tag;
408
+
409
+ get_or_raise(vdef_tag, krypt_definition_get_type(def), "'type is missing in ASN.1 definition");
410
+ default_tag = NUM2INT(vdef_tag);
411
+ tag = krypt_definition_get_tag(def);
412
+ tagging = krypt_definition_get_tagging(def);
413
+
414
+ if (int_match_tag_and_class(header, tag, tagging, default_tag) == INT_KRYPT_MATCH) return INT_KRYPT_MATCH;
415
+
416
+ return int_check_optional_or_default(self, ctx, def, default_tag);
417
+ }
418
+
419
+ static int
420
+ int_parse_assign(VALUE self, krypt_asn1_object *object, krypt_asn1_definition *def, int *dont_free)
421
+ {
422
+ ID name;
423
+ VALUE instance;
424
+ krypt_asn1_template *t;
425
+
426
+ name = int_determine_name(krypt_definition_get_name(def));
427
+ t = krypt_asn1_template_new(object, krypt_definition_get_definition(def), krypt_definition_get_options(def));
428
+ krypt_asn1_template_set(cKryptASN1TemplateValue, instance, t);
429
+ rb_ivar_set(self, name, instance);
430
+ krypt_asn1_template_set_parsed(t, 1);
431
+ *dont_free = 1;
432
+ return KRYPT_OK;
433
+ }
434
+
435
+ /* TODO */
436
+ static int
437
+ int_decode_prim_inf(VALUE tvalue, krypt_asn1_object *obj, krypt_asn1_definition *def, VALUE *out)
438
+ {
439
+ rb_raise(rb_eNotImpError, "Not implemented yet");
440
+ }
441
+
442
+ static int
443
+ int_decode_prim(VALUE tvalue, krypt_asn1_object *object, krypt_asn1_definition *def, VALUE *out)
444
+ {
445
+ VALUE value, vtype, tagging;
446
+ krypt_asn1_header *header = object->header;
447
+ int free_header = 0, default_tag;
448
+ uint8_t *p;
449
+ size_t len;
450
+
451
+ if (header->is_infinite)
452
+ return int_decode_prim_inf(tvalue, object, def, out);
453
+
454
+ get_or_raise(vtype, krypt_definition_get_type(def), "'type' missing in ASN.1 definition");
455
+ tagging = krypt_definition_get_tagging(def);
456
+ default_tag = NUM2INT(vtype);
457
+
458
+ if (!(header = int_unpack_explicit(tagging, object, &p, &len, &free_header))) return KRYPT_ERR;
459
+ if (header->is_constructed) {
460
+ krypt_error_add("Constructed bit set");
461
+ goto error;
462
+ }
463
+
464
+ if (!krypt_asn1_codecs[default_tag].decoder) {
465
+ int default_tag = NUM2INT(vtype);
466
+ krypt_error_add("No codec available for default tag %d", default_tag);
467
+ goto error;
468
+ }
469
+ if (krypt_asn1_codecs[default_tag].decoder(tvalue, p, len, &value) == KRYPT_ERR) {
470
+ goto error;
471
+ }
472
+
473
+ if (free_header) krypt_asn1_header_free(header);
474
+ *out = value;
475
+ return KRYPT_OK;
476
+
477
+ error: {
478
+ ID name = int_determine_name(krypt_definition_get_name(def));
479
+ krypt_error_add("Error while decoding value %s", rb_id2name(name));
480
+ if (free_header) krypt_asn1_header_free(header);
481
+ return KRYPT_ERR;
482
+ }
483
+ }
484
+
485
+ static int
486
+ int_match_cons(VALUE self, struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_definition *def, int default_tag)
487
+ {
488
+ int match = int_try_match_cons(ctx, def, default_tag);
489
+
490
+ if (match == INT_KRYPT_MATCH || match == INT_KRYPT_MATCH_ERR) return match;
491
+
492
+ if (!krypt_definition_is_optional(def)) {
493
+ VALUE tag = krypt_definition_get_tag(def);
494
+ VALUE tagging = krypt_definition_get_tagging(def);
495
+ krypt_error_add("Mandatory sequence value not found");
496
+ return int_tag_and_class_mismatch(ctx->header, tag, tagging, default_tag, "Constructed");
497
+ }
498
+ return INT_KRYPT_NO_MATCH;
499
+ }
500
+
501
+ static int
502
+ int_match_sequence(VALUE self, struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_definition *def)
503
+ {
504
+ return int_match_cons(self, ctx, def, TAGS_SEQUENCE);
505
+ }
506
+
507
+ static int
508
+ int_match_set(VALUE self, struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_definition *def)
509
+ {
510
+ return int_match_cons(self, ctx, def, TAGS_SET);
511
+ }
512
+
513
+ static int
514
+ int_ensure_rest_is_optional(VALUE self, VALUE layout, long index)
515
+ {
516
+ long i, size;
517
+
518
+ size = RARRAY_LEN(layout);
519
+ for (i=index; i < size; ++i) {
520
+ krypt_asn1_definition def;
521
+ VALUE cur_def = rb_ary_entry(layout, i);
522
+
523
+ krypt_definition_init(&def, cur_def, krypt_hash_get_options(cur_def));
524
+ if (!krypt_definition_is_optional(&def)) {
525
+ ID name = int_determine_name(krypt_definition_get_name(&def));
526
+ krypt_error_add("Mandatory value %s not found", rb_id2name(name));
527
+ return KRYPT_ERR;
528
+ }
529
+ if (krypt_definition_has_default(&def)) {
530
+ int_set_default_value(self, &def);
531
+ }
532
+ }
533
+ return KRYPT_OK;
534
+ }
535
+
536
+ static int
537
+ int_parse_cons(VALUE self, krypt_asn1_object *object, krypt_asn1_definition *def, int *dont_free)
538
+ {
539
+ binyo_instream *in;
540
+ VALUE layout, vmin_size, tagging;
541
+ long num_parsed = 0, layout_size, min_size, i;
542
+ krypt_asn1_header *header = object->header;
543
+ krypt_asn1_object *cur_object = NULL;
544
+ int object_consumed = 0, free_header = 0;
545
+ uint8_t *p;
546
+ size_t len;
547
+
548
+ get_or_raise(layout, krypt_definition_get_layout(def), "'layout' missing in ASN.1 definition");
549
+ get_or_raise(vmin_size, krypt_definition_get_min_size(def), "'min_size' is missing in ASN.1 definition");
550
+ min_size = NUM2LONG(vmin_size);
551
+ tagging = krypt_definition_get_tagging(def);
552
+ layout_size = RARRAY_LEN(layout);
553
+
554
+ if(!(header = int_unpack_explicit(tagging, object, &p, &len, &free_header))) return KRYPT_ERR;
555
+ if (!header->is_constructed) {
556
+ krypt_error_add("Constructed bit not set");
557
+ return KRYPT_ERR;
558
+ }
559
+
560
+ in = binyo_instream_new_bytes(p, len);
561
+ if (int_next_object(in, &cur_object) != KRYPT_OK) goto error;
562
+
563
+ for (i=0; i < layout_size; ++i) {
564
+ ID codec;
565
+ int result;
566
+ krypt_asn1_definition inner_def;
567
+ struct krypt_asn1_template_parse_ctx *parser;
568
+ struct krypt_asn1_template_match_ctx ctx;
569
+ VALUE cur_def = rb_ary_entry(layout, i);
570
+
571
+ krypt_error_clear();
572
+ krypt_definition_init(&inner_def, cur_def, krypt_hash_get_options(cur_def));
573
+ codec = SYM2ID(krypt_hash_get_codec(cur_def));
574
+ parser = int_get_parse_ctx_for_codec(codec);
575
+ int_match_ctx_init(&ctx, cur_object);
576
+
577
+ if ((result = parser->match(self, &ctx, &inner_def)) != INT_KRYPT_MATCH_ERR) {
578
+ if (result == INT_KRYPT_MATCH) {
579
+ int inner_dont_free;
580
+ if (parser->parse(self, cur_object, &inner_def, &inner_dont_free) == KRYPT_ERR) goto error;
581
+ if (!inner_dont_free) krypt_asn1_object_free(cur_object);
582
+ object_consumed = 1;
583
+ num_parsed++;
584
+ if (i < layout_size - 1) {
585
+ int has_more = int_next_object(in, &cur_object);
586
+ if (has_more == KRYPT_ERR) goto error;
587
+ if (has_more == KRYPT_ASN1_EOF) {
588
+ if (int_ensure_rest_is_optional(self, layout, i+1) == KRYPT_ERR) goto error;
589
+ break; /* EOF reached */
590
+ }
591
+ }
592
+ } /* else -> didn't match or default value was set */
593
+ } else {
594
+ goto error;
595
+ }
596
+ }
597
+
598
+ if (num_parsed < min_size) {
599
+ krypt_error_add("Expected %d..%d values. Got: %d", min_size, layout_size, num_parsed);
600
+ goto error;
601
+ }
602
+ if (header->is_infinite) {
603
+ if(int_parse_eoc(in) == KRYPT_ERR) {
604
+ krypt_error_add("No closing END OF CONTENTS found for constructive value");
605
+ goto error;
606
+ }
607
+ }
608
+ if (int_ensure_stream_is_consumed(in) == KRYPT_ERR) goto error;
609
+
610
+ binyo_instream_free(in);
611
+ if (free_header) krypt_asn1_header_free(header);
612
+ *dont_free = 0;
613
+ return KRYPT_OK;
614
+
615
+ error:
616
+ binyo_instream_free(in);
617
+ if (cur_object && !object_consumed) krypt_asn1_object_free(cur_object);
618
+ if (free_header) krypt_asn1_header_free(header);
619
+ return KRYPT_ERR;
620
+ }
621
+
622
+ static int
623
+ int_match_template(VALUE self, struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_definition *def)
624
+ {
625
+ ID codec;
626
+ VALUE type, type_def;
627
+ krypt_asn1_definition new_def;
628
+ struct krypt_asn1_template_parse_ctx *parser;
629
+ int match;
630
+
631
+ get_or_raise(type, krypt_definition_get_type(def), "'type' missing in ASN.1 definition");
632
+ if (NIL_P((type_def = krypt_definition_get(type)))) {
633
+ krypt_error_add("Type %s has no ASN.1 definition", rb_class2name(type));
634
+ return INT_KRYPT_MATCH_ERR;
635
+ }
636
+ krypt_definition_init(&new_def, type_def, krypt_definition_get_options(def));
637
+ codec = SYM2ID(krypt_hash_get_codec(type_def));
638
+ parser = int_get_parse_ctx_for_codec(codec);
639
+ match = parser->match(self, ctx, &new_def);
640
+ if (match == INT_KRYPT_NO_MATCH) {
641
+ if (krypt_definition_has_default(def)) {
642
+ int_set_default_value(self, def);
643
+ return INT_KRYPT_MATCH_DEFAULT_APPLIED;
644
+ }
645
+ }
646
+ return match;
647
+ }
648
+
649
+ static int
650
+ int_parse_template(VALUE self, krypt_asn1_object *object, krypt_asn1_definition *def, int *dont_free)
651
+ {
652
+ ID name;
653
+ VALUE container, instance;
654
+ VALUE type, type_def, options;
655
+ krypt_asn1_template *container_template, *value_template;
656
+
657
+ get_or_raise(type, krypt_definition_get_type(def), "'type' missing in ASN.1 definition");
658
+ name = int_determine_name(krypt_definition_get_name(def));
659
+ if (NIL_P((type_def = krypt_definition_get(type)))) {
660
+ krypt_error_add("Type %s has no ASN.1 definition", rb_class2name(type));
661
+ return KRYPT_ERR;
662
+ }
663
+
664
+ options = krypt_definition_get_options(def);
665
+ value_template = krypt_asn1_template_new(object, type_def, options);
666
+ krypt_asn1_template_set(type, instance, value_template);
667
+
668
+ container_template = krypt_asn1_template_new_value(instance);
669
+ krypt_asn1_template_set_definition(container_template, krypt_definition_get_definition(def));
670
+ krypt_asn1_template_set_options(container_template, options);
671
+ krypt_asn1_template_set(cKryptASN1TemplateValue, container, container_template);
672
+
673
+ rb_ivar_set(self, name, container);
674
+ *dont_free = 1;
675
+ return KRYPT_OK;
676
+ }
677
+
678
+ static int
679
+ int_match_cons_of(VALUE self, struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_definition *def, int default_tag)
680
+ {
681
+ int match = int_try_match_cons(ctx, def, default_tag);
682
+
683
+ if (match == INT_KRYPT_MATCH || match == INT_KRYPT_MATCH_ERR) return match;
684
+ return int_check_optional_or_default(self, ctx, def, default_tag);
685
+ }
686
+
687
+ static int
688
+ int_match_seq_of(VALUE self, struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_definition *def)
689
+ {
690
+ return int_match_cons_of(self, ctx, def, TAGS_SEQUENCE);
691
+ }
692
+
693
+ static int
694
+ int_match_set_of(VALUE self, struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_definition *def)
695
+ {
696
+ return int_match_cons_of(self, ctx, def, TAGS_SET);
697
+ }
698
+
699
+ static int
700
+ int_decode_cons_of_templates(binyo_instream *in, VALUE type, VALUE *out)
701
+ {
702
+ VALUE cur;
703
+ VALUE ary = rb_ary_new();
704
+ int result;
705
+
706
+ while ((result = krypt_asn1_template_parse_stream(in, type, &cur)) == KRYPT_OK) {
707
+ rb_ary_push(ary, cur);
708
+ }
709
+ if (result == KRYPT_ERR) return KRYPT_ERR;
710
+ *out = ary;
711
+ return KRYPT_OK;
712
+ }
713
+
714
+ static int
715
+ int_decode_cons_of_prim(binyo_instream *in, VALUE type, VALUE *out)
716
+ {
717
+ VALUE cur;
718
+ VALUE ary = rb_ary_new();
719
+ int result;
720
+
721
+ while ((result = krypt_asn1_decode_stream(in, &cur)) == KRYPT_OK) {
722
+ if (!rb_obj_is_kind_of(cur, type)) {
723
+ krypt_error_add("Expected %s but got %s instead", rb_class2name(type), rb_class2name(CLASS_OF(cur)));
724
+ return KRYPT_ERR;
725
+ }
726
+ rb_ary_push(ary, cur);
727
+ }
728
+ if (result == KRYPT_ERR) return KRYPT_ERR;
729
+ *out = ary;
730
+ return KRYPT_OK;
731
+ }
732
+
733
+ static int
734
+ int_decode_cons_of(VALUE self, krypt_asn1_object *object, krypt_asn1_definition *def, VALUE *out)
735
+ {
736
+ ID name;
737
+ binyo_instream *in;
738
+ VALUE type, tagging, val_ary, mod_p;
739
+ uint8_t *p;
740
+ size_t len;
741
+ int free_header = 0;
742
+ krypt_asn1_header *header = object->header;
743
+
744
+ get_or_raise(type, krypt_definition_get_type(def), "'type' missing in ASN.1 definition");
745
+ name = int_determine_name(krypt_definition_get_name(def));
746
+ tagging = krypt_definition_get_tagging(def);
747
+
748
+ if (!(header = int_unpack_explicit(tagging, object, &p, &len, &free_header))) return KRYPT_ERR;
749
+ if (!header->is_constructed) {
750
+ krypt_error_add("Constructed bit not set");
751
+ return KRYPT_ERR;
752
+ }
753
+
754
+ in = binyo_instream_new_bytes(p, len);
755
+
756
+ mod_p = rb_funcall(type, rb_intern("include?"), 1, mKryptASN1Template);
757
+ if (RTEST(mod_p)) {
758
+ if (int_decode_cons_of_templates(in, type, &val_ary) == KRYPT_ERR) return KRYPT_ERR;
759
+ }
760
+ else {
761
+ if (int_decode_cons_of_prim(in, type, &val_ary) == KRYPT_ERR) return KRYPT_ERR;
762
+ }
763
+
764
+ if (RARRAY_LEN(val_ary) == 0 && !krypt_definition_is_optional(def)) {
765
+ krypt_error_add("Mandatory value %s could not be parsed. Sequence is empty", rb_id2name(name));
766
+ goto error;
767
+ }
768
+
769
+ if (header->is_infinite) {
770
+ if(int_parse_eoc(in) == KRYPT_ERR) {
771
+ krypt_error_add("No closing END OF CONTENTS found for %s", rb_id2name(name));
772
+ goto error;
773
+ }
774
+ }
775
+ if (int_ensure_stream_is_consumed(in) == KRYPT_ERR) goto error;
776
+
777
+ *out = val_ary;
778
+ binyo_instream_free(in);
779
+ if (free_header) krypt_asn1_header_free(header);
780
+ return KRYPT_OK;
781
+
782
+ error:
783
+ binyo_instream_free(in);
784
+ if (free_header) krypt_asn1_header_free(header);
785
+ return KRYPT_ERR;
786
+ }
787
+
788
+ static int
789
+ int_match_any(VALUE self, struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_definition *def)
790
+ {
791
+ if (krypt_definition_is_optional(def)) {
792
+ VALUE tagging;
793
+ krypt_asn1_header *header;
794
+ int pseudo_default;
795
+ VALUE tag = krypt_definition_get_tag(def);
796
+
797
+ if (NIL_P(tag)) {
798
+ return INT_KRYPT_MATCH;
799
+ }
800
+ tagging = krypt_definition_get_tagging(def);
801
+ header = ctx->header;
802
+ pseudo_default = NUM2INT(tag);
803
+ if (!int_match_tag_and_class(header, tag, tagging, pseudo_default)) {
804
+ if (krypt_definition_has_default(def)) {
805
+ int_set_default_value(self, def);
806
+ return INT_KRYPT_MATCH_DEFAULT_APPLIED;
807
+ }
808
+ return INT_KRYPT_NO_MATCH;
809
+ }
810
+ }
811
+ return INT_KRYPT_MATCH;
812
+ }
813
+
814
+ static int
815
+ int_decode_any(VALUE self, krypt_asn1_object *object, krypt_asn1_definition *def, VALUE *out)
816
+ {
817
+ VALUE value, tagging;
818
+ binyo_instream *in, *seq_a, *seq_b, *seq_c;
819
+ krypt_asn1_header *header = object->header;
820
+ int free_header = 0;
821
+ uint8_t *p;
822
+ size_t len;
823
+
824
+ tagging = krypt_definition_get_tagging(def);
825
+
826
+ if(!(header = int_unpack_explicit(tagging, object, &p, &len, &free_header))) return KRYPT_ERR;
827
+
828
+ seq_a = binyo_instream_new_bytes(header->tag_bytes, header->tag_len);
829
+ seq_b = binyo_instream_new_bytes(header->length_bytes, header->length_len);
830
+ seq_c = binyo_instream_new_bytes(p, len);
831
+ in = binyo_instream_new_seq_n(3, seq_a, seq_b, seq_c);
832
+ if (krypt_asn1_decode_stream(in, &value) != KRYPT_OK) goto error;
833
+
834
+ binyo_instream_free(in);
835
+ if (free_header) krypt_asn1_header_free(header);
836
+ *out = value;
837
+ return KRYPT_OK;
838
+
839
+ error: {
840
+ ID name = int_determine_name(krypt_definition_get_name(def));
841
+ binyo_instream_free(in);
842
+ krypt_error_add("Error while decoding value %s", rb_id2name(name));
843
+ if (free_header) krypt_asn1_header_free(header);
844
+ return KRYPT_ERR;
845
+ }
846
+ }
847
+
848
+ static int
849
+ int_enforce_explicit_tagging(krypt_asn1_definition *def, VALUE *tagging)
850
+ {
851
+ VALUE tc = krypt_definition_get_tagging(def);
852
+ if (!(NIL_P(tc) || SYM2ID(tc) == sKrypt_TC_EXPLICIT)) {
853
+ krypt_error_add("Only explicit tagging is allowed for CHOICEs");
854
+ return KRYPT_ERR;
855
+ }
856
+ *tagging = tc;
857
+ return KRYPT_OK;
858
+ }
859
+
860
+ static int
861
+ int_match_choice(VALUE self, struct krypt_asn1_template_match_ctx *ctx, krypt_asn1_definition *def)
862
+ {
863
+ VALUE layout, tagging;
864
+ long i, layout_size, first_any = -1;
865
+ struct krypt_asn1_template_match_ctx inner_ctx;
866
+
867
+ get_or_raise(layout, krypt_definition_get_layout(def), "'layout' missing in ASN.1 definition");
868
+ if (int_enforce_explicit_tagging(def, &tagging) == KRYPT_ERR) return INT_KRYPT_MATCH_ERR;
869
+ int_match_ctx_init(&inner_ctx, ctx->object);
870
+ /* No match if tagging was explicit but we can't skip the header */
871
+ if (!(NIL_P(tagging) || int_match_ctx_skip_header(&inner_ctx) == KRYPT_OK))
872
+ return INT_KRYPT_NO_MATCH;
873
+
874
+ layout_size = RARRAY_LEN(layout);
875
+ for (i=0; i < layout_size; ++i) {
876
+ ID codec;
877
+ int result;
878
+ krypt_asn1_definition inner_def;
879
+ struct krypt_asn1_template_parse_ctx *parser;
880
+ VALUE options;
881
+ VALUE cur_def = rb_ary_entry(layout, i);
882
+
883
+ krypt_error_clear();
884
+ options = krypt_hash_get_options(cur_def);
885
+ krypt_definition_init(&inner_def, cur_def, options);
886
+ codec = SYM2ID(krypt_hash_get_codec(cur_def));
887
+ parser = int_get_parse_ctx_for_codec(codec);
888
+ if (codec == sKrypt_ID_ANY && first_any == -1) {
889
+ first_any = i;
890
+ }
891
+
892
+ if ((result = parser->match(self, &inner_ctx, &inner_def)) == INT_KRYPT_MATCH) {
893
+ int_match_ctx_cleanup(&inner_ctx);
894
+ krypt_definition_set_matched_layout(def, i);
895
+ return INT_KRYPT_MATCH;
896
+ }
897
+
898
+ if (result == INT_KRYPT_MATCH_DEFAULT_APPLIED) {
899
+ int_match_ctx_cleanup(&inner_ctx);
900
+ return INT_KRYPT_MATCH_DEFAULT_APPLIED;
901
+ }
902
+ /* else -> didn't match */
903
+ }
904
+
905
+ int_match_ctx_cleanup(&inner_ctx);
906
+
907
+ if (first_any != -1) {
908
+ krypt_definition_set_matched_layout(def, first_any); /*the first ANY value matches if no other will */
909
+ return INT_KRYPT_MATCH;
910
+ }
911
+
912
+ if (!krypt_definition_is_optional(def)) {
913
+ krypt_error_add("Mandatory CHOICE value not found");
914
+ return INT_KRYPT_MATCH_ERR;
915
+ }
916
+ return INT_KRYPT_NO_MATCH;
917
+ }
918
+
919
+ static krypt_asn1_object *
920
+ int_skip_explicit_choice_header(VALUE tagging, krypt_asn1_object *object, int *new_object)
921
+ {
922
+ binyo_instream *in;
923
+ krypt_asn1_object *next_object = NULL;
924
+
925
+ if (NIL_P(tagging)) {
926
+ *new_object = 0;
927
+ return object;
928
+ }
929
+
930
+ in = binyo_instream_new_bytes(object->bytes, object->bytes_len);
931
+ if (int_next_object(in, &next_object) != KRYPT_OK) {
932
+ binyo_instream_free(in);
933
+ krypt_error_add("Error while trying to read next value");
934
+ return NULL;
935
+ }
936
+
937
+ binyo_instream_free(in);
938
+ *new_object = 1;
939
+ return next_object;
940
+ }
941
+
942
+ static int
943
+ int_parse_choice(VALUE self, krypt_asn1_object *object, krypt_asn1_definition *def, int *dont_free)
944
+ {
945
+ ID codec;
946
+ struct krypt_asn1_template_parse_ctx *parser;
947
+ struct krypt_asn1_template_match_ctx ctx;
948
+ VALUE layout, matched_def, matched_opts, tagging, type;
949
+ krypt_asn1_object *unpacked;
950
+ krypt_asn1_definition inner_def;
951
+ long matched_index;
952
+ int new_object, inner_dont_free;
953
+
954
+ get_or_raise(layout, krypt_definition_get_layout(def), "'layout' missing in ASN.1 definition");
955
+ if (int_enforce_explicit_tagging(def, &tagging) == KRYPT_ERR) return KRYPT_ERR;
956
+
957
+ /* determine the matching index */
958
+ int_match_ctx_init(&ctx, object);
959
+ if (int_match_choice(self, &ctx, def) != INT_KRYPT_MATCH) {
960
+ krypt_error_add("Matching value not found");
961
+ return KRYPT_ERR;
962
+ }
963
+ matched_index = krypt_definition_get_matched_layout(def);
964
+ matched_def = rb_ary_entry(layout, matched_index);
965
+ matched_opts = krypt_hash_get_options(matched_def);
966
+
967
+ /* Set up a temporary inner definition for actual parsing, using the matching definition */
968
+ krypt_definition_init(&inner_def, matched_def, matched_opts);
969
+ get_or_raise(type, krypt_definition_get_type(&inner_def), "'type' missing in inner choice definition");
970
+
971
+ if (!(unpacked = int_skip_explicit_choice_header(tagging, object, &new_object))) return KRYPT_ERR;
972
+
973
+ codec = SYM2ID(krypt_hash_get_codec(matched_def));
974
+ parser = int_get_parse_ctx_for_codec(codec);
975
+ if (parser->parse(self, unpacked, &inner_def, &inner_dont_free) == KRYPT_ERR) return KRYPT_ERR;
976
+
977
+ rb_ivar_set(self, sKrypt_IV_TYPE, type);
978
+ rb_ivar_set(self, sKrypt_IV_TAG, INT2NUM(unpacked->header->tag));
979
+
980
+ /* complicated cleanup */
981
+ if (!inner_dont_free) {
982
+ if (new_object)
983
+ krypt_asn1_object_free(unpacked); /* free the unpacked object also, since bytes were copied in inner processing */
984
+ *dont_free = 0; /* free the argument object in any case */
985
+ } else {
986
+ if (new_object)
987
+ *dont_free = 0; /* we unpacked the explicit tag, so free the argument object */
988
+ else
989
+ *dont_free = 1; /* the original object was consumed as is within, so don't free it */
990
+ }
991
+
992
+ return KRYPT_OK;
993
+ }
994
+
995
+ static int
996
+ int_template_parse(VALUE self, krypt_asn1_template *t)
997
+ {
998
+ ID codec;
999
+ VALUE definition;
1000
+ krypt_asn1_definition def;
1001
+ struct krypt_asn1_template_parse_ctx *parser;
1002
+ int dont_free = 0;
1003
+
1004
+ definition = krypt_asn1_template_get_definition(t);
1005
+ krypt_definition_init(&def, definition, krypt_asn1_template_get_options(t));
1006
+ codec = SYM2ID(krypt_hash_get_codec(definition));
1007
+ parser = int_get_parse_ctx_for_codec(codec);
1008
+
1009
+ if (parser->parse(self, t->object, &def, &dont_free) == KRYPT_ERR) return KRYPT_ERR;
1010
+ krypt_asn1_template_set_parsed(t, 1);
1011
+ krypt_asn1_template_set_decoded(t, 1);
1012
+
1013
+ /* Invalidate the cached template encoding */
1014
+ /* If dont_free is 0 this means that the encoding bytes were copied and
1015
+ * processed further inside -> we can free the template's object */
1016
+ if (!dont_free) {
1017
+ krypt_asn1_object_free(t->object);
1018
+ }
1019
+ t->object = NULL;
1020
+ return KRYPT_OK;
1021
+ }
1022
+
1023
+ static int
1024
+ int_value_decode(VALUE self, krypt_asn1_template *t)
1025
+ {
1026
+ ID codec;
1027
+ VALUE definition, value;
1028
+ krypt_asn1_definition def;
1029
+ struct krypt_asn1_template_parse_ctx *parser;
1030
+
1031
+ definition = krypt_asn1_template_get_definition(t);
1032
+ krypt_definition_init(&def, definition, krypt_asn1_template_get_options(t));
1033
+ codec = SYM2ID(krypt_hash_get_codec(definition));
1034
+ parser = int_get_parse_ctx_for_codec(codec);
1035
+ if (!parser->decode) return KRYPT_OK;
1036
+ if (parser->decode(self, t->object, &def, &value) == KRYPT_ERR) return KRYPT_ERR;
1037
+ krypt_asn1_template_set_decoded(t, 1);
1038
+ krypt_asn1_template_set_value(t, value);
1039
+ return KRYPT_OK;
1040
+ }
1041
+
1042
+ static int
1043
+ int_get_inner_value(VALUE self, ID ivname, VALUE *out)
1044
+ {
1045
+ krypt_asn1_template *template;
1046
+
1047
+ krypt_asn1_template_get(self, template);
1048
+ if (!(krypt_asn1_template_is_parsed(template))) {
1049
+ if (int_template_parse(self, template) == KRYPT_ERR) return KRYPT_ERR;
1050
+ }
1051
+
1052
+ *out = rb_ivar_get(self, ivname);
1053
+ return KRYPT_OK;
1054
+ }
1055
+
1056
+ int
1057
+ krypt_asn1_template_get_cb_value(VALUE self, ID ivname, VALUE *out)
1058
+ {
1059
+ krypt_asn1_template *value_template;
1060
+ VALUE value = Qnil;
1061
+
1062
+ if (int_get_inner_value(self, ivname, &value) == KRYPT_ERR) return KRYPT_ERR;
1063
+ if (NIL_P(value)) {
1064
+ *out = Qnil;
1065
+ return KRYPT_OK;
1066
+ }
1067
+
1068
+ krypt_asn1_template_get(value, value_template);
1069
+
1070
+ if (!krypt_asn1_template_is_decoded(value_template)) {
1071
+ if (int_value_decode(value, value_template) == KRYPT_ERR) return KRYPT_ERR;
1072
+ }
1073
+
1074
+ *out = krypt_asn1_template_get_value(value_template);
1075
+ return KRYPT_OK;
1076
+ }
1077
+
1078
+ void
1079
+ krypt_asn1_template_set_cb_value(VALUE self, ID ivname, VALUE value)
1080
+ {
1081
+ VALUE container;
1082
+ krypt_asn1_template *template, *value_template;
1083
+
1084
+ container = rb_ivar_get(self, ivname);
1085
+ krypt_asn1_template_get(self, template);
1086
+
1087
+ if (NIL_P(container)) {
1088
+ VALUE obj;
1089
+ value_template = krypt_asn1_template_new_value(value);
1090
+ krypt_asn1_template_set(cKryptASN1TemplateValue, obj, value_template);
1091
+ rb_ivar_set(self, ivname, obj);
1092
+ } else {
1093
+ krypt_asn1_template_get(container, value_template);
1094
+ }
1095
+
1096
+ krypt_asn1_template_set_modified(template, 1);
1097
+ krypt_asn1_template_set_value(value_template, value);
1098
+ }
1099
+
1100
+ static VALUE
1101
+ int_rb_template_new_initial(VALUE klass, binyo_instream *in, krypt_asn1_header *header)
1102
+ {
1103
+ ID codec;
1104
+ VALUE obj;
1105
+ VALUE definition;
1106
+ krypt_asn1_template *template;
1107
+ krypt_asn1_definition def;
1108
+ struct krypt_asn1_template_match_ctx ctx;
1109
+ struct krypt_asn1_template_parse_ctx *parser;
1110
+
1111
+ if (NIL_P((definition = krypt_definition_get(klass)))) {
1112
+ krypt_error_add("%s has no ASN.1 definition", rb_class2name(klass));
1113
+ return Qnil;
1114
+ }
1115
+
1116
+ if (!(template = krypt_asn1_template_new_from_stream(in, header, definition, krypt_hash_get_options(definition)))) {
1117
+ krypt_error_add("Error while reading data");
1118
+ return Qnil;
1119
+ }
1120
+
1121
+ /* ensure it matches */
1122
+ krypt_definition_init(&def, definition, Qnil); /* top-level definition has no options */
1123
+ codec = SYM2ID(krypt_hash_get_codec(definition));
1124
+ parser = int_get_parse_ctx_for_codec(codec);
1125
+ int_match_ctx_init(&ctx, template->object);
1126
+ obj = rb_obj_alloc(klass);
1127
+ if (parser->match(obj, &ctx, &def) != INT_KRYPT_MATCH) {
1128
+ krypt_error_add("Type mismatch");
1129
+ return Qnil;
1130
+ }
1131
+
1132
+ krypt_asn1_template_set(klass, obj, template);
1133
+ return obj;
1134
+ }
1135
+
1136
+ static int
1137
+ krypt_asn1_template_parse_stream(binyo_instream *in, VALUE klass, VALUE *out)
1138
+ {
1139
+ krypt_asn1_header *header;
1140
+ VALUE ret;
1141
+ int result;
1142
+
1143
+ result = krypt_asn1_next_header(in, &header);
1144
+ if (result == KRYPT_ASN1_EOF || result == KRYPT_ERR) return result;
1145
+
1146
+ ret = int_rb_template_new_initial(klass, in, header);
1147
+ if (NIL_P(ret)) {
1148
+ krypt_asn1_header_free(header);
1149
+ return KRYPT_ERR;
1150
+ }
1151
+ *out = ret;
1152
+ return KRYPT_OK;
1153
+ }
1154
+
1155
+ VALUE
1156
+ krypt_asn1_template_parse_der(VALUE klass, VALUE der)
1157
+ {
1158
+ VALUE ret = Qnil;
1159
+ int result;
1160
+ binyo_instream *in = krypt_instream_new_value_der(der);
1161
+
1162
+ result = krypt_asn1_template_parse_stream(in, klass, &ret);
1163
+ binyo_instream_free(in);
1164
+ if (result == KRYPT_ASN1_EOF || result == KRYPT_ERR)
1165
+ krypt_error_raise(eKryptASN1Error, "Parsing the value failed");
1166
+ return ret;
1167
+ }
1168
+
1169
+ void
1170
+ Init_krypt_asn1_template_parser(void)
1171
+ {
1172
+ VALUE mParser = rb_define_module_under(mKryptASN1Template, "Parser");
1173
+ rb_define_method(mParser, "parse_der", krypt_asn1_template_parse_der, 1);
1174
+ rb_define_alias(mParser, "decode_der", "parse_der");
1175
+ }
1176
+