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
@@ -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
+