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.
- data/LICENSE +20 -0
- data/ext/krypt/core/Makefile +221 -0
- data/ext/krypt/core/binyo-error.h +40 -0
- data/ext/krypt/core/binyo-io-buffer.h +54 -0
- data/ext/krypt/core/binyo-io.h +131 -0
- data/ext/krypt/core/extconf.h +8 -0
- data/ext/krypt/core/extconf.rb +80 -0
- data/ext/krypt/core/krypt-core.c +110 -0
- data/ext/krypt/core/krypt-core.h +97 -0
- data/ext/krypt/core/krypt-core.o +0 -0
- data/ext/krypt/core/krypt-provider.h +86 -0
- data/ext/krypt/core/krypt_asn1-internal.c +681 -0
- data/ext/krypt/core/krypt_asn1-internal.h +117 -0
- data/ext/krypt/core/krypt_asn1-internal.o +0 -0
- data/ext/krypt/core/krypt_asn1.c +2109 -0
- data/ext/krypt/core/krypt_asn1.h +88 -0
- data/ext/krypt/core/krypt_asn1.o +0 -0
- data/ext/krypt/core/krypt_asn1_codec.c +973 -0
- data/ext/krypt/core/krypt_asn1_codec.o +0 -0
- data/ext/krypt/core/krypt_asn1_in_adapter.c +178 -0
- data/ext/krypt/core/krypt_asn1_in_adapter.o +0 -0
- data/ext/krypt/core/krypt_asn1_in_chunked.c +292 -0
- data/ext/krypt/core/krypt_asn1_in_chunked.o +0 -0
- data/ext/krypt/core/krypt_asn1_in_definite.c +156 -0
- data/ext/krypt/core/krypt_asn1_in_definite.o +0 -0
- data/ext/krypt/core/krypt_asn1_parser.c +592 -0
- data/ext/krypt/core/krypt_asn1_parser.o +0 -0
- data/ext/krypt/core/krypt_asn1_template-internal.h +185 -0
- data/ext/krypt/core/krypt_asn1_template.c +459 -0
- data/ext/krypt/core/krypt_asn1_template.h +56 -0
- data/ext/krypt/core/krypt_asn1_template.o +0 -0
- data/ext/krypt/core/krypt_asn1_template_encoder.c +76 -0
- data/ext/krypt/core/krypt_asn1_template_encoder.o +0 -0
- data/ext/krypt/core/krypt_asn1_template_parser.c +1176 -0
- data/ext/krypt/core/krypt_asn1_template_parser.o +0 -0
- data/ext/krypt/core/krypt_b64-internal.h +38 -0
- data/ext/krypt/core/krypt_b64.c +391 -0
- data/ext/krypt/core/krypt_b64.h +41 -0
- data/ext/krypt/core/krypt_b64.o +0 -0
- data/ext/krypt/core/krypt_digest.c +391 -0
- data/ext/krypt/core/krypt_digest.h +51 -0
- data/ext/krypt/core/krypt_digest.o +0 -0
- data/ext/krypt/core/krypt_error.c +221 -0
- data/ext/krypt/core/krypt_error.h +46 -0
- data/ext/krypt/core/krypt_error.o +0 -0
- data/ext/krypt/core/krypt_hex-internal.h +36 -0
- data/ext/krypt/core/krypt_hex.c +255 -0
- data/ext/krypt/core/krypt_hex.h +41 -0
- data/ext/krypt/core/krypt_hex.o +0 -0
- data/ext/krypt/core/krypt_io.c +65 -0
- data/ext/krypt/core/krypt_io.h +56 -0
- data/ext/krypt/core/krypt_io.o +0 -0
- data/ext/krypt/core/krypt_io_in_pem.c +397 -0
- data/ext/krypt/core/krypt_io_in_pem.o +0 -0
- data/ext/krypt/core/krypt_missing.c +238 -0
- data/ext/krypt/core/krypt_missing.h +62 -0
- data/ext/krypt/core/krypt_missing.o +0 -0
- data/ext/krypt/core/krypt_pem.c +171 -0
- data/ext/krypt/core/krypt_pem.o +0 -0
- data/ext/krypt/core/krypt_provider-internal.h +40 -0
- data/ext/krypt/core/krypt_provider.c +136 -0
- data/ext/krypt/core/krypt_provider.o +0 -0
- data/ext/krypt/core/kryptcore.so +0 -0
- data/ext/krypt/core/mkmf.log +130 -0
- data/lib/krypt-core/version.rb +3 -0
- data/lib/krypt-core.rb +35 -0
- data/lib/kryptcore.so +0 -0
- data/spec/README +2 -0
- data/test/README +2 -0
- data/test/res/certificate.cer +0 -0
- data/test/resources.rb +48 -0
- data/test/scratch.rb +17 -0
- 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
|
+
|