krypt-core 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/LICENSE +20 -0
  2. data/ext/krypt/core/Makefile +221 -0
  3. data/ext/krypt/core/binyo-error.h +40 -0
  4. data/ext/krypt/core/binyo-io-buffer.h +54 -0
  5. data/ext/krypt/core/binyo-io.h +131 -0
  6. data/ext/krypt/core/extconf.h +8 -0
  7. data/ext/krypt/core/extconf.rb +80 -0
  8. data/ext/krypt/core/krypt-core.c +110 -0
  9. data/ext/krypt/core/krypt-core.h +97 -0
  10. data/ext/krypt/core/krypt-core.o +0 -0
  11. data/ext/krypt/core/krypt-provider.h +86 -0
  12. data/ext/krypt/core/krypt_asn1-internal.c +681 -0
  13. data/ext/krypt/core/krypt_asn1-internal.h +117 -0
  14. data/ext/krypt/core/krypt_asn1-internal.o +0 -0
  15. data/ext/krypt/core/krypt_asn1.c +2109 -0
  16. data/ext/krypt/core/krypt_asn1.h +88 -0
  17. data/ext/krypt/core/krypt_asn1.o +0 -0
  18. data/ext/krypt/core/krypt_asn1_codec.c +973 -0
  19. data/ext/krypt/core/krypt_asn1_codec.o +0 -0
  20. data/ext/krypt/core/krypt_asn1_in_adapter.c +178 -0
  21. data/ext/krypt/core/krypt_asn1_in_adapter.o +0 -0
  22. data/ext/krypt/core/krypt_asn1_in_chunked.c +292 -0
  23. data/ext/krypt/core/krypt_asn1_in_chunked.o +0 -0
  24. data/ext/krypt/core/krypt_asn1_in_definite.c +156 -0
  25. data/ext/krypt/core/krypt_asn1_in_definite.o +0 -0
  26. data/ext/krypt/core/krypt_asn1_parser.c +592 -0
  27. data/ext/krypt/core/krypt_asn1_parser.o +0 -0
  28. data/ext/krypt/core/krypt_asn1_template-internal.h +185 -0
  29. data/ext/krypt/core/krypt_asn1_template.c +459 -0
  30. data/ext/krypt/core/krypt_asn1_template.h +56 -0
  31. data/ext/krypt/core/krypt_asn1_template.o +0 -0
  32. data/ext/krypt/core/krypt_asn1_template_encoder.c +76 -0
  33. data/ext/krypt/core/krypt_asn1_template_encoder.o +0 -0
  34. data/ext/krypt/core/krypt_asn1_template_parser.c +1176 -0
  35. data/ext/krypt/core/krypt_asn1_template_parser.o +0 -0
  36. data/ext/krypt/core/krypt_b64-internal.h +38 -0
  37. data/ext/krypt/core/krypt_b64.c +391 -0
  38. data/ext/krypt/core/krypt_b64.h +41 -0
  39. data/ext/krypt/core/krypt_b64.o +0 -0
  40. data/ext/krypt/core/krypt_digest.c +391 -0
  41. data/ext/krypt/core/krypt_digest.h +51 -0
  42. data/ext/krypt/core/krypt_digest.o +0 -0
  43. data/ext/krypt/core/krypt_error.c +221 -0
  44. data/ext/krypt/core/krypt_error.h +46 -0
  45. data/ext/krypt/core/krypt_error.o +0 -0
  46. data/ext/krypt/core/krypt_hex-internal.h +36 -0
  47. data/ext/krypt/core/krypt_hex.c +255 -0
  48. data/ext/krypt/core/krypt_hex.h +41 -0
  49. data/ext/krypt/core/krypt_hex.o +0 -0
  50. data/ext/krypt/core/krypt_io.c +65 -0
  51. data/ext/krypt/core/krypt_io.h +56 -0
  52. data/ext/krypt/core/krypt_io.o +0 -0
  53. data/ext/krypt/core/krypt_io_in_pem.c +397 -0
  54. data/ext/krypt/core/krypt_io_in_pem.o +0 -0
  55. data/ext/krypt/core/krypt_missing.c +238 -0
  56. data/ext/krypt/core/krypt_missing.h +62 -0
  57. data/ext/krypt/core/krypt_missing.o +0 -0
  58. data/ext/krypt/core/krypt_pem.c +171 -0
  59. data/ext/krypt/core/krypt_pem.o +0 -0
  60. data/ext/krypt/core/krypt_provider-internal.h +40 -0
  61. data/ext/krypt/core/krypt_provider.c +136 -0
  62. data/ext/krypt/core/krypt_provider.o +0 -0
  63. data/ext/krypt/core/kryptcore.so +0 -0
  64. data/ext/krypt/core/mkmf.log +130 -0
  65. data/lib/krypt-core/version.rb +3 -0
  66. data/lib/krypt-core.rb +35 -0
  67. data/lib/kryptcore.so +0 -0
  68. data/spec/README +2 -0
  69. data/test/README +2 -0
  70. data/test/res/certificate.cer +0 -0
  71. data/test/resources.rb +48 -0
  72. data/test/scratch.rb +17 -0
  73. metadata +150 -0
@@ -0,0 +1,973 @@
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 <time.h>
32
+
33
+ #define CHAR_BIT_MINUS_ONE (CHAR_BIT - 1)
34
+
35
+ static int
36
+ int_asn1_encode_default(VALUE self, VALUE value, uint8_t **out, size_t *len)
37
+ {
38
+ size_t l;
39
+ uint8_t *ret;
40
+
41
+ if (NIL_P(value)) {
42
+ *out = NULL;
43
+ *len = 0;
44
+ return KRYPT_OK;
45
+ }
46
+
47
+ StringValue(value);
48
+ l = RSTRING_LEN(value);
49
+ ret = ALLOC_N(uint8_t, l);
50
+ memcpy(ret, RSTRING_PTR(value), l);
51
+ *out = ret;
52
+ *len = l;
53
+ return KRYPT_OK;
54
+ }
55
+
56
+ static int
57
+ int_asn1_decode_default(VALUE self, uint8_t *bytes, size_t len, VALUE *out)
58
+ {
59
+ if (len == 0 || bytes == NULL)
60
+ *out = rb_str_new2("");
61
+ else
62
+ *out = rb_str_new((const char *)bytes, len);
63
+ return KRYPT_OK;
64
+ }
65
+
66
+ static int
67
+ int_asn1_validate_default(VALUE self, VALUE value)
68
+ {
69
+ if (NIL_P(value)) return KRYPT_OK;
70
+
71
+ if (TYPE(value) != T_STRING) {
72
+ krypt_error_add("ASN.1 type must be a String");
73
+ return KRYPT_ERR;
74
+ }
75
+ return KRYPT_OK;
76
+ }
77
+
78
+ static const long SUB_ID_LIMIT_ENCODE = LONG_MAX / 10;
79
+ static const long SUB_ID_LIMIT_PARSE = LONG_MAX >> CHAR_BIT_MINUS_ONE;
80
+ static const size_t MAX_LONG_DIGITS = sizeof(long) * 2 * 1.21f + 1; /* times 2 -> hex representation, 1.21 ~ log10(16) */
81
+
82
+ static int int_encode_object_id(uint8_t*, size_t, uint8_t **, size_t *);
83
+ static int int_decode_object_id(uint8_t*, size_t, VALUE *);
84
+ static int int_parse_utc_time(uint8_t *, size_t, VALUE *);
85
+ static int int_parse_generalized_time(uint8_t *, size_t, VALUE *);
86
+ static int int_encode_utc_time(VALUE, uint8_t **, size_t *);
87
+ static int int_encode_generalized_time(VALUE, uint8_t **, size_t *);
88
+ static int int_decode_integer(uint8_t *, size_t, VALUE *);
89
+
90
+ #define sanity_check(b) if (!b) return KRYPT_ERR;
91
+
92
+ static int
93
+ int_asn1_encode_eoc(VALUE self, VALUE value, uint8_t **out, size_t *len)
94
+ {
95
+ *out = NULL;
96
+ *len = 0;
97
+ return KRYPT_OK;
98
+ }
99
+
100
+ static int
101
+ int_asn1_decode_eoc(VALUE self, uint8_t *bytes, size_t len, VALUE *out)
102
+ {
103
+ if (len != 0) {
104
+ krypt_error_add("Invalid encoding for END OF CONTENTS found - must be empty");
105
+ return KRYPT_ERR;
106
+ }
107
+ *out = Qnil;
108
+ return KRYPT_OK;
109
+ }
110
+
111
+ static int
112
+ int_asn1_validate_eoc(VALUE self, VALUE value)
113
+ {
114
+ if (!NIL_P(value)) {
115
+ krypt_error_add("Value for END OF CONTENTS must be nil");
116
+ return KRYPT_ERR;
117
+ }
118
+ return KRYPT_OK;
119
+ }
120
+
121
+ static int
122
+ int_asn1_encode_boolean(VALUE self, VALUE value, uint8_t **out, size_t *len)
123
+ {
124
+ uint8_t *b;
125
+
126
+ b = ALLOC(uint8_t);
127
+ *b = RTEST(value) ? 0xff : 0x0;
128
+ *out = b;
129
+ *len = 1;
130
+ return KRYPT_OK;
131
+ }
132
+
133
+ static int
134
+ int_asn1_decode_boolean(VALUE self, uint8_t *bytes, size_t len, VALUE *out)
135
+ {
136
+ uint8_t b;
137
+
138
+ sanity_check(bytes);
139
+ if (len != 1) {
140
+ krypt_error_add("Boolean value with length != 1 found");
141
+ return KRYPT_ERR;
142
+ }
143
+ b = *bytes;
144
+ if (b == 0x0)
145
+ *out = Qfalse;
146
+ else
147
+ *out = Qtrue;
148
+ return KRYPT_OK;
149
+ }
150
+
151
+ static int
152
+ int_asn1_validate_boolean(VALUE self, VALUE value)
153
+ {
154
+ if (!(value == Qfalse || value == Qtrue)) {
155
+ krypt_error_add("Value for BOOLEAN must be either true or false");
156
+ return KRYPT_ERR;
157
+ }
158
+ return KRYPT_OK;
159
+ }
160
+
161
+ static int
162
+ int_asn1_encode_integer(VALUE self, VALUE value, uint8_t **out, size_t *len)
163
+ {
164
+ long num;
165
+
166
+ if (TYPE(value) == T_BIGNUM) {
167
+ if (krypt_asn1_encode_bignum(value, out, len) == KRYPT_ERR) {
168
+ krypt_error_add("Error while encoding Bignum INTEGER");
169
+ return KRYPT_ERR;
170
+ }
171
+ return KRYPT_OK;
172
+ }
173
+
174
+ num = NUM2LONG(value);
175
+ *len = krypt_asn1_encode_integer(num, out);
176
+ return KRYPT_OK;
177
+ }
178
+
179
+ static int
180
+ int_asn1_decode_integer(VALUE self, uint8_t *bytes, size_t len, VALUE *out)
181
+ {
182
+ if (len == 0) {
183
+ krypt_error_add("Invalid zero length value for INTEGER found");
184
+ return KRYPT_ERR;
185
+ }
186
+ sanity_check(bytes);
187
+
188
+ /* Even if in the range of long, high numbers may already have to
189
+ * be represented as Bignums in Ruby. To be safe, call the Bignum
190
+ * decoder for all of these cases. */
191
+ if ((bytes[0] == 0x0 && len > sizeof(long)) ||
192
+ (bytes[0] != 0x0 && len >= sizeof(long))) {
193
+ if (krypt_asn1_decode_bignum(bytes, len, out) == KRYPT_ERR) {
194
+ krypt_error_add("Error while decoding Bignum INTEGER");
195
+ return KRYPT_ERR;
196
+ }
197
+ return KRYPT_OK;
198
+ }
199
+
200
+ if (int_decode_integer(bytes, len, out) == KRYPT_ERR) {
201
+ krypt_error_add("Error while decoding INTEGER");
202
+ return KRYPT_ERR;
203
+ }
204
+ return KRYPT_OK;
205
+ }
206
+
207
+ static int
208
+ int_asn1_validate_integer(VALUE self, VALUE value)
209
+ {
210
+ if (!(FIXNUM_P(value) || rb_obj_is_kind_of(value, rb_cBignum))) {
211
+ krypt_error_add("Value for INTEGER must be an integer number");
212
+ return KRYPT_ERR;
213
+ }
214
+ return KRYPT_OK;
215
+ }
216
+
217
+ #define int_check_unused_bits(b) if ((b) < 0 || (b) > 7) return KRYPT_ERR;
218
+
219
+ static int
220
+ int_asn1_encode_bit_string(VALUE self, VALUE value, uint8_t **out, size_t *len)
221
+ {
222
+ int unused_bits;
223
+ size_t l;
224
+ uint8_t *bytes;
225
+
226
+ unused_bits = NUM2INT(rb_ivar_get(self, sKrypt_IV_UNUSED_BITS));
227
+ int_check_unused_bits(unused_bits);
228
+
229
+ StringValue(value);
230
+ l = RSTRING_LEN(value);
231
+ if (l == SIZE_MAX) {
232
+ krypt_error_add("Size of BIT STRING too long: %ld", l);
233
+ return KRYPT_ERR;
234
+ }
235
+ bytes = ALLOC_N(uint8_t, l + 1);
236
+ bytes[0] = unused_bits & 0xff;
237
+ memcpy(bytes + 1, RSTRING_PTR(value), l);
238
+ *out = bytes;
239
+ *len = l + 1;
240
+ return KRYPT_OK;
241
+ }
242
+
243
+ static int
244
+ int_asn1_decode_bit_string(VALUE self, uint8_t *bytes, size_t len, VALUE *out)
245
+ {
246
+ int unused_bits;
247
+
248
+ sanity_check(bytes);
249
+ unused_bits = bytes[0];
250
+ int_check_unused_bits(unused_bits);
251
+ if (int_asn1_decode_default(self, bytes + 1, len - 1, out) == KRYPT_ERR) {
252
+ krypt_error_add("Error while decoding BIT STRING");
253
+ return KRYPT_ERR;
254
+ }
255
+ rb_ivar_set(self, sKrypt_IV_UNUSED_BITS, INT2NUM(unused_bits));
256
+ return KRYPT_OK;
257
+ }
258
+
259
+ static int
260
+ int_asn1_validate_bit_string(VALUE self, VALUE value)
261
+ {
262
+ if (NIL_P(value)) {
263
+ krypt_error_add("BIT STRING value cannot be empty");
264
+ return KRYPT_ERR;
265
+ }
266
+ return int_asn1_validate_default(self, value);
267
+ }
268
+
269
+ static int
270
+ int_asn1_encode_null(VALUE self, VALUE value, uint8_t **out, size_t *len)
271
+ {
272
+ *out = NULL;
273
+ *len = 0;
274
+ return KRYPT_OK;
275
+ }
276
+
277
+ static int
278
+ int_asn1_decode_null(VALUE self, uint8_t *bytes, size_t len, VALUE *out)
279
+ {
280
+ if (len != 0) {
281
+ krypt_error_add("Invalid encoding for NULL value found - must be empty");
282
+ return KRYPT_ERR;
283
+ }
284
+ *out = Qnil;
285
+ return KRYPT_OK;
286
+ }
287
+
288
+ static int
289
+ int_asn1_validate_null(VALUE self, VALUE value)
290
+ {
291
+ if (!NIL_P(value)) {
292
+ krypt_error_add("Value for NULL must be nil");
293
+ return KRYPT_ERR;
294
+ }
295
+ return KRYPT_OK;
296
+ }
297
+
298
+ static int
299
+ int_asn1_encode_object_id(VALUE self, VALUE value, uint8_t **out, size_t *len)
300
+ {
301
+ uint8_t *str;
302
+
303
+ StringValue(value);
304
+ str = (uint8_t *)RSTRING_PTR(value);
305
+ if (int_encode_object_id(str, RSTRING_LEN(value), out, len) == KRYPT_ERR) {
306
+ krypt_error_add("Encoding OBJECT IDENTIFIER failed");
307
+ return KRYPT_ERR;
308
+ }
309
+ return KRYPT_OK;
310
+ }
311
+
312
+ static int
313
+ int_asn1_decode_object_id(VALUE self, uint8_t *bytes, size_t len, VALUE *out)
314
+ {
315
+ sanity_check(bytes);
316
+ if (int_decode_object_id(bytes, len, out) == KRYPT_ERR) {
317
+ krypt_error_add("Decoding OBJECT IDENTIFIER failed");
318
+ return KRYPT_ERR;
319
+ }
320
+ return KRYPT_OK;
321
+ }
322
+
323
+ static int
324
+ int_asn1_validate_object_id(VALUE self, VALUE value)
325
+ {
326
+ if (TYPE(value) != T_STRING) {
327
+ krypt_error_add("Value for OBJECT IDENTIFIER must be a String");
328
+ return KRYPT_ERR;
329
+ }
330
+ return KRYPT_OK;
331
+ }
332
+
333
+ static int
334
+ int_asn1_encode_utf8_string(VALUE self, VALUE value, uint8_t **out, size_t *len)
335
+ {
336
+ rb_encoding *src_encoding;
337
+
338
+ if (NIL_P(value)) {
339
+ *out = NULL;
340
+ *len = 0;
341
+ return KRYPT_OK;
342
+ }
343
+
344
+ src_encoding = rb_enc_get(value);
345
+ if (rb_enc_asciicompat(src_encoding)) {
346
+ rb_enc_associate(value, rb_utf8_encoding());
347
+ if (int_asn1_encode_default(self, value, out, len) == KRYPT_ERR) {
348
+ krypt_error_add("Encoding UTF8 STRING failed");
349
+ return KRYPT_ERR;
350
+ }
351
+ }
352
+ else {
353
+ /* TODO rb_protect */
354
+ VALUE encoded = rb_str_encode(value, rb_enc_from_encoding(rb_utf8_encoding()), 0, Qnil);
355
+ if (int_asn1_encode_default(self, encoded, out, len) == KRYPT_ERR) {
356
+ krypt_error_add("Encoding UTF8 STRING failed");
357
+ return KRYPT_ERR;
358
+ }
359
+ }
360
+ return KRYPT_OK;
361
+ }
362
+
363
+ static int
364
+ int_asn1_decode_utf8_string(VALUE self, uint8_t *bytes, size_t len, VALUE *out)
365
+ {
366
+ if (int_asn1_decode_default(self, bytes, len, out) == KRYPT_ERR) {
367
+ krypt_error_add("Decoding UTF8 STRING failed");
368
+ return KRYPT_ERR;
369
+ }
370
+ /* TODO rb_protect */
371
+ rb_enc_associate(*out, rb_utf8_encoding());
372
+ return KRYPT_OK;
373
+ }
374
+
375
+ static int
376
+ int_asn1_encode_utc_time(VALUE self, VALUE value, uint8_t **out, size_t *len)
377
+ {
378
+ if (int_encode_utc_time(value, out, len) == KRYPT_ERR) {
379
+ krypt_error_add("Encoding UTC TIME failed");
380
+ return KRYPT_ERR;
381
+ }
382
+ return KRYPT_OK;
383
+ }
384
+
385
+ static int
386
+ int_asn1_decode_utc_time(VALUE self, uint8_t *bytes, size_t len, VALUE *out)
387
+ {
388
+ sanity_check(bytes);
389
+ if (int_parse_utc_time(bytes, len, out) == KRYPT_ERR) {
390
+ krypt_error_add("Decoding UTC TIME failed");
391
+ return KRYPT_ERR;
392
+ }
393
+ return KRYPT_OK;
394
+ }
395
+
396
+ static int
397
+ int_asn1_validate_time(VALUE self, VALUE value)
398
+ {
399
+ int type = TYPE(value);
400
+ if (!(rb_obj_is_kind_of(value, rb_cTime) ||
401
+ type == T_FIXNUM ||
402
+ type == T_BIGNUM ||
403
+ type == T_STRING)) {
404
+ krypt_error_add("Time value must be either a String or an integer Number");
405
+ return KRYPT_ERR;
406
+ }
407
+ if (type == T_STRING && RSTRING_LEN(value) == 0) {
408
+ krypt_error_add("Time value cannot be an empty String");
409
+ return KRYPT_ERR;
410
+ }
411
+ return KRYPT_OK;
412
+ }
413
+
414
+ static int
415
+ int_asn1_encode_generalized_time(VALUE self, VALUE value, uint8_t **out, size_t *len)
416
+ {
417
+ if (int_encode_generalized_time(value, out, len) == KRYPT_ERR) {
418
+ krypt_error_add("Encoding GENERALIZED TIME failed");
419
+ return KRYPT_ERR;
420
+ }
421
+ return KRYPT_OK;
422
+ }
423
+
424
+ static int
425
+ int_asn1_decode_generalized_time(VALUE self, uint8_t *bytes, size_t len, VALUE *out)
426
+ {
427
+ sanity_check(bytes);
428
+ if (int_parse_generalized_time(bytes, len, out) == KRYPT_ERR) {
429
+ krypt_error_add("Decoding GENERALIZED TIME failed");
430
+ return KRYPT_ERR;
431
+ }
432
+ return KRYPT_OK;
433
+ }
434
+
435
+ krypt_asn1_codec KRYPT_DEFAULT_CODEC = { int_asn1_encode_default, int_asn1_decode_default, int_asn1_validate_default };
436
+
437
+ krypt_asn1_codec krypt_asn1_codecs[] = {
438
+ { int_asn1_encode_eoc, int_asn1_decode_eoc , int_asn1_validate_eoc },
439
+ { int_asn1_encode_boolean, int_asn1_decode_boolean , int_asn1_validate_boolean },
440
+ { int_asn1_encode_integer, int_asn1_decode_integer , int_asn1_validate_integer },
441
+ { int_asn1_encode_bit_string, int_asn1_decode_bit_string , int_asn1_validate_bit_string },
442
+ { int_asn1_encode_default, int_asn1_decode_default , int_asn1_validate_default },
443
+ { int_asn1_encode_null, int_asn1_decode_null , int_asn1_validate_null },
444
+ { int_asn1_encode_object_id, int_asn1_decode_object_id , int_asn1_validate_object_id },
445
+ { int_asn1_encode_default, int_asn1_decode_default , int_asn1_validate_default },
446
+ { int_asn1_encode_default, int_asn1_decode_default , int_asn1_validate_default },
447
+ { int_asn1_encode_default, int_asn1_decode_default , int_asn1_validate_default },
448
+ { int_asn1_encode_integer, int_asn1_decode_integer , int_asn1_validate_integer },
449
+ { int_asn1_encode_default, int_asn1_decode_default , int_asn1_validate_default },
450
+ { int_asn1_encode_utf8_string, int_asn1_decode_utf8_string , int_asn1_validate_default },
451
+ { int_asn1_encode_default, int_asn1_decode_default , int_asn1_validate_default },
452
+ { int_asn1_encode_default, int_asn1_decode_default , int_asn1_validate_default },
453
+ { int_asn1_encode_default, int_asn1_decode_default , int_asn1_validate_default },
454
+ { int_asn1_encode_default, int_asn1_decode_default , int_asn1_validate_default },
455
+ { int_asn1_encode_default, int_asn1_decode_default , int_asn1_validate_default },
456
+ { int_asn1_encode_default, int_asn1_decode_default , int_asn1_validate_default },
457
+ { int_asn1_encode_default, int_asn1_decode_default , int_asn1_validate_default },
458
+ { int_asn1_encode_default, int_asn1_decode_default , int_asn1_validate_default },
459
+ { int_asn1_encode_default, int_asn1_decode_default , int_asn1_validate_default },
460
+ { int_asn1_encode_default, int_asn1_decode_default , int_asn1_validate_default },
461
+ { int_asn1_encode_utc_time, int_asn1_decode_utc_time , int_asn1_validate_time },
462
+ { int_asn1_encode_generalized_time, int_asn1_decode_generalized_time, int_asn1_validate_time },
463
+ { int_asn1_encode_default, int_asn1_decode_default , int_asn1_validate_default },
464
+ { int_asn1_encode_default, int_asn1_decode_default , int_asn1_validate_default },
465
+ { int_asn1_encode_default, int_asn1_decode_default , int_asn1_validate_default },
466
+ { int_asn1_encode_default, int_asn1_decode_default , int_asn1_validate_default },
467
+ { int_asn1_encode_default, int_asn1_decode_default , int_asn1_validate_default },
468
+ { int_asn1_encode_default, int_asn1_decode_default , int_asn1_validate_default },
469
+ };
470
+
471
+ #define int_check_offset(off) \
472
+ do { \
473
+ if ((off) + 1 == SIZE_MAX) { \
474
+ krypt_error_add("OBJECT IDENTIFIER value too large"); \
475
+ return KRYPT_ERR; \
476
+ } \
477
+ } while (0)
478
+
479
+ static long
480
+ int_get_sub_id(uint8_t *str, size_t len, size_t *offset)
481
+ {
482
+ uint8_t c;
483
+ ssize_t ret = 0;
484
+ size_t off = *offset;
485
+
486
+ if (off >= len) return KRYPT_ASN1_EOF;
487
+
488
+ c = str[off];
489
+ if (c == '.') {
490
+ krypt_error_add("OBJECT IDENTIFIER cannot start with '.'");
491
+ return KRYPT_ERR;
492
+ }
493
+
494
+ while (off < len && (c = str[off]) != '.') {
495
+ if (c < '0' || c > '9') {
496
+ krypt_error_add("Invalid OBJECT IDENTIFIER character detected: %x", c);
497
+ return KRYPT_ERR;
498
+ }
499
+ if (ret > SUB_ID_LIMIT_ENCODE) {
500
+ krypt_error_add("Sub OBJECT IDENTIFIER too large");
501
+ return KRYPT_ERR;
502
+ }
503
+ int_check_offset(off);
504
+ ret *= 10;
505
+ ret += c - '0';
506
+ off++;
507
+ }
508
+
509
+ int_check_offset(off);
510
+ *offset = ++off; /* skip '.' */
511
+ return ret;
512
+ }
513
+
514
+ #define int_determine_num_shifts(i, value, by) \
515
+ do { \
516
+ long tmp = (value); \
517
+ for ((i) = 0; tmp > 0; (i)++) { \
518
+ tmp >>= (by); \
519
+ } \
520
+ } while (0)
521
+
522
+
523
+ static int
524
+ int_write_long(binyo_byte_buffer *buf, long cur)
525
+ {
526
+ int num_shifts, i, ret;
527
+ uint8_t b;
528
+ uint8_t *bytes;
529
+
530
+ if (cur == 0) {
531
+ b = 0x0;
532
+ if (binyo_buffer_write(buf, &b, 1) == BINYO_ERR) {
533
+ krypt_error_add("Writing to buffer failed");
534
+ return KRYPT_ERR;
535
+ }
536
+ return KRYPT_OK;
537
+ }
538
+
539
+ int_determine_num_shifts(num_shifts, cur, CHAR_BIT_MINUS_ONE);
540
+ bytes = ALLOC_N(uint8_t, num_shifts);
541
+
542
+ for (i = num_shifts - 1; i >= 0; i--) {
543
+ b = cur & 0x7f;
544
+ if (i < num_shifts - 1)
545
+ b |= 0x80;
546
+ bytes[i] = b;
547
+ cur >>= CHAR_BIT_MINUS_ONE;
548
+ }
549
+
550
+ if (binyo_buffer_write(buf, bytes, num_shifts) == BINYO_ERR) {
551
+ krypt_error_add("Writing to buffer failed");
552
+ ret = KRYPT_ERR;
553
+ } else {
554
+ ret = KRYPT_OK;
555
+ }
556
+ xfree(bytes);
557
+ return ret;
558
+ }
559
+
560
+ #define int_check_first_sub_id(first) \
561
+ do { \
562
+ if ((first) > 2) { \
563
+ krypt_error_add("First sub id must be 0..2"); \
564
+ goto error; \
565
+ } \
566
+ } while (0)
567
+
568
+ #define int_check_second_sub_id(sec) \
569
+ do { \
570
+ if ((sec) > 39) { \
571
+ krypt_error_add("Second sub id must be 0..39"); \
572
+ goto error; \
573
+ } \
574
+ } while (0)
575
+
576
+ static int
577
+ int_encode_object_id(uint8_t *str, size_t len, uint8_t **out, size_t *outlen)
578
+ {
579
+ size_t offset = 0;
580
+ long first, second, cur;
581
+ binyo_byte_buffer *buffer;
582
+
583
+ buffer = binyo_buffer_new();
584
+ if ((first = int_get_sub_id(str, len, &offset)) < 0) goto error;
585
+ int_check_first_sub_id(first);
586
+ if ((second = int_get_sub_id(str, len, &offset)) < 0) goto error;
587
+ int_check_second_sub_id(second);
588
+
589
+ cur = 40 * first + second;
590
+ if (int_write_long(buffer, cur) == KRYPT_ERR) goto error;
591
+
592
+ while ((cur = int_get_sub_id(str, len, &offset)) >= 0) {
593
+ if (int_write_long(buffer, cur) == KRYPT_ERR) goto error;
594
+ }
595
+ if (cur == KRYPT_ERR) goto error;
596
+
597
+ *outlen = binyo_buffer_get_bytes_free(buffer, out);
598
+ return KRYPT_OK;
599
+
600
+ error:
601
+ binyo_buffer_free(buffer);
602
+ return KRYPT_ERR;
603
+ }
604
+
605
+ static long
606
+ int_parse_sub_id(uint8_t* bytes, size_t len, size_t *offset)
607
+ {
608
+ long num = 0;
609
+ size_t off = *offset;
610
+
611
+ if (off >= len) return KRYPT_ASN1_EOF;
612
+
613
+ while (bytes[off] & 0x80) {
614
+ if (num > SUB_ID_LIMIT_PARSE) {
615
+ krypt_error_add("Sub identifier too large");
616
+ return KRYPT_ERR;
617
+ }
618
+ num <<= CHAR_BIT_MINUS_ONE;
619
+ num |= bytes[off++] & 0x7f;
620
+ if (off >= len) {
621
+ krypt_error_add("Invalid OBJECT IDENTIFIER encoding");
622
+ return KRYPT_ERR;
623
+ }
624
+ }
625
+
626
+ num <<= CHAR_BIT_MINUS_ONE;
627
+ num |= bytes[off++];
628
+ *offset = off;
629
+ return num;
630
+ }
631
+
632
+ static void
633
+ int_set_first_sub_ids(long combined, long *first, long *second)
634
+ {
635
+ long f = 1;
636
+
637
+ while (40 * f <= combined)
638
+ f++;
639
+
640
+ *first = f - 1;
641
+ *second = combined - 40 * (f - 1);
642
+ }
643
+
644
+ #define int_append_num(buf, cur, numbuf) \
645
+ do { \
646
+ int nl; \
647
+ uint8_t b = (uint8_t)'.'; \
648
+ if (binyo_buffer_write((buf), &b, 1) == BINYO_ERR) { \
649
+ krypt_error_add("Writing to buffer failed"); \
650
+ goto error; \
651
+ } \
652
+ nl = sprintf((char *) (numbuf), "%ld", (cur)); \
653
+ if (binyo_buffer_write((buf), (numbuf), nl) == BINYO_ERR) { \
654
+ krypt_error_add("Writing to buffer failed"); \
655
+ goto error; \
656
+ } \
657
+ } while (0)
658
+
659
+ static int
660
+ int_decode_object_id(uint8_t *bytes, size_t len, VALUE *out)
661
+ {
662
+ long cur, first, second;
663
+ size_t offset = 0;
664
+ binyo_byte_buffer *buffer;
665
+ int numlen;
666
+ uint8_t numbuf[MAX_LONG_DIGITS];
667
+ uint8_t *retbytes;
668
+ size_t retlen;
669
+
670
+ sanity_check(bytes);
671
+
672
+ buffer = binyo_buffer_new();
673
+ if ((cur = int_parse_sub_id(bytes, len, &offset)) < 0) {
674
+ krypt_error_add("Decoding OBJECT IDENTIFIER failed");
675
+ goto error;
676
+ }
677
+ if (cur > 40 * 2 + 39) {
678
+ krypt_error_add("Illegal first octet, value too large");
679
+ goto error;
680
+ }
681
+ int_set_first_sub_ids(cur, &first, &second);
682
+ int_check_first_sub_id(first);
683
+ int_check_second_sub_id(second);
684
+
685
+ numlen = sprintf((char *)numbuf, "%ld", first);
686
+ if (binyo_buffer_write(buffer, numbuf, numlen) == BINYO_ERR) {
687
+ krypt_error_add("Writing to buffer failed");
688
+ goto error;
689
+ }
690
+ int_append_num(buffer, second, numbuf);
691
+
692
+ while ((cur = int_parse_sub_id(bytes, len, &offset)) >= 0) {
693
+ int_append_num(buffer, cur, numbuf);
694
+ }
695
+ if (cur == KRYPT_ERR) goto error;
696
+
697
+ retlen = binyo_buffer_get_bytes_free(buffer, &retbytes);
698
+ *out = rb_str_new((const char *)retbytes, retlen);
699
+ xfree(retbytes);
700
+ return KRYPT_OK;
701
+
702
+ error:
703
+ binyo_buffer_free(buffer);
704
+ return KRYPT_ERR;
705
+ }
706
+
707
+ #define int_as_time_t(t, time) \
708
+ do { \
709
+ int state = 0; \
710
+ VALUE coerced; \
711
+ long tmp; \
712
+ coerced = rb_protect(rb_Integer, time, &state); \
713
+ if (state) { \
714
+ krypt_error_add("Invalid Time argument"); \
715
+ return KRYPT_ERR; \
716
+ } \
717
+ tmp = (long) rb_protect((VALUE(*)_((VALUE)))rb_num2long, coerced, &state); \
718
+ if (state) { \
719
+ krypt_error_add("Invalid Time argument"); \
720
+ return KRYPT_ERR; \
721
+ } \
722
+ if (tmp < 0) { \
723
+ krypt_error_add("Negative Time value given"); \
724
+ return KRYPT_ERR; \
725
+ } \
726
+ (t) = (time_t) tmp; \
727
+ } while (0)
728
+
729
+ #define int_raw_time_to_cstring(bytes, len, out) \
730
+ do { \
731
+ /* make sure input to sscanf is a zero-terminated string */ \
732
+ int i; \
733
+ (out) = ALLOCA_N(char, (len) + 1); \
734
+ for (i=0; i < (len) + 1; i++) { \
735
+ (out)[i] = (char) (bytes)[i]; \
736
+ } \
737
+ (out)[(len)] = '\0'; \
738
+ } while (0)
739
+
740
+ static int
741
+ int_encode_utc_time(VALUE value, uint8_t **out, size_t *len)
742
+ {
743
+ time_t time;
744
+ struct tm tm;
745
+ char *ret;
746
+ int r;
747
+
748
+ int_as_time_t(time, value);
749
+ if (!(gmtime_r(&time, &tm))) return KRYPT_ERR;
750
+
751
+ ret = ALLOC_N(char, 20);
752
+
753
+ r = snprintf(ret, 20,
754
+ "%02d%02d%02d%02d%02d%02dZ",
755
+ tm.tm_year%100,
756
+ tm.tm_mon+1,
757
+ tm.tm_mday,
758
+ tm.tm_hour,
759
+ tm.tm_min,
760
+ tm.tm_sec);
761
+
762
+ if (r > 20) {
763
+ krypt_error_add("Encoding into UTC format failed");
764
+ xfree(ret);
765
+ return KRYPT_ERR;
766
+ }
767
+
768
+ *out = (uint8_t *) ret;
769
+ *len = 13;
770
+ return KRYPT_OK;
771
+ }
772
+
773
+ static int
774
+ int_parse_utc_time(uint8_t *bytes, size_t len, VALUE *out)
775
+ {
776
+ VALUE argv[6];
777
+ char *cstr;
778
+ struct tm tm = { 0 };
779
+
780
+ if (len != 13) {
781
+ krypt_error_add("Invalid UTC TIME format. Must be 13 characters long");
782
+ return KRYPT_ERR;
783
+ }
784
+
785
+ int_raw_time_to_cstring(bytes, 13, cstr);
786
+
787
+ if (sscanf((const char *) cstr,
788
+ "%2d%2d%2d%2d%2d%2dZ",
789
+ &tm.tm_year,
790
+ &tm.tm_mon,
791
+ &tm.tm_mday,
792
+ &tm.tm_hour,
793
+ &tm.tm_min,
794
+ &tm.tm_sec) != 6) {
795
+ return KRYPT_ERR;
796
+ }
797
+ if (tm.tm_year < 69)
798
+ tm.tm_year += 2000;
799
+ else
800
+ tm.tm_year += 1900;
801
+
802
+ argv[0] = INT2NUM(tm.tm_year);
803
+ argv[1] = INT2NUM(tm.tm_mon);
804
+ argv[2] = INT2NUM(tm.tm_mday);
805
+ argv[3] = INT2NUM(tm.tm_hour);
806
+ argv[4] = INT2NUM(tm.tm_min);
807
+ argv[5] = INT2NUM(tm.tm_sec);
808
+
809
+ *out = rb_funcall2(rb_cTime, rb_intern("utc"), 6, argv);
810
+ return KRYPT_OK;
811
+ }
812
+
813
+ static int
814
+ int_encode_generalized_time(VALUE value, uint8_t **out, size_t *len)
815
+ {
816
+ time_t time;
817
+ struct tm tm;
818
+ char *ret;
819
+ int r;
820
+
821
+ int_as_time_t(time, value);
822
+ gmtime_r(&time, &tm);
823
+ if (!(gmtime_r(&time, &tm))) return KRYPT_ERR;
824
+
825
+ ret = ALLOC_N(char, 20);
826
+
827
+ r = snprintf(ret, 20,
828
+ "%04d%02d%02d%02d%02d%02dZ",
829
+ tm.tm_year + 1900,
830
+ tm.tm_mon+1,
831
+ tm.tm_mday,
832
+ tm.tm_hour,
833
+ tm.tm_min,
834
+ tm.tm_sec);
835
+ if (r > 20) {
836
+ krypt_error_add("Encoding into GENERALIZED format failed");
837
+ xfree(ret);
838
+ return KRYPT_ERR;
839
+ }
840
+
841
+ *out = (uint8_t *)ret;
842
+ *len = 15;
843
+ return KRYPT_OK;
844
+ }
845
+
846
+ static int
847
+ int_parse_generalized_time(uint8_t *bytes, size_t len, VALUE *out)
848
+ {
849
+ VALUE argv[6];
850
+ char *cstr;
851
+ struct tm tm = { 0 };
852
+
853
+ if (len != 15) {
854
+ krypt_error_add("Invalid GENERALIZED TIME format. Must be 15 characters long");
855
+ return KRYPT_ERR;
856
+ }
857
+
858
+ int_raw_time_to_cstring(bytes, 15, cstr);
859
+
860
+ if (sscanf((const char *)cstr,
861
+ "%4d%2d%2d%2d%2d%2dZ",
862
+ &tm.tm_year,
863
+ &tm.tm_mon,
864
+ &tm.tm_mday,
865
+ &tm.tm_hour,
866
+ &tm.tm_min,
867
+ &tm.tm_sec) != 6) {
868
+ return KRYPT_ERR;
869
+ }
870
+
871
+ argv[0] = INT2NUM(tm.tm_year);
872
+ argv[1] = INT2NUM(tm.tm_mon);
873
+ argv[2] = INT2NUM(tm.tm_mday);
874
+ argv[3] = INT2NUM(tm.tm_hour);
875
+ argv[4] = INT2NUM(tm.tm_min);
876
+ argv[5] = INT2NUM(tm.tm_sec);
877
+
878
+ *out = rb_funcall2(rb_cTime, rb_intern("utc"), 6, argv);
879
+ return KRYPT_OK;
880
+ }
881
+
882
+ size_t
883
+ krypt_asn1_encode_integer(long num, uint8_t **out)
884
+ {
885
+ int len, i, need_extra_byte = 0;
886
+ int sign = num >= 0;
887
+ uint8_t *bytes;
888
+ uint8_t *ptr;
889
+ uint8_t numbytes[SIZEOF_LONG];
890
+
891
+ for (i = 0; i < SIZEOF_LONG; ++i) {
892
+ numbytes[i] = num & 0xff;
893
+ num >>= CHAR_BIT;
894
+ /* ASN.1 expects the shortest length of representation */
895
+ if ((sign && num <= 0) || (!sign && num >= -1)) {
896
+ need_extra_byte = (sign == ((numbytes[i] & 0x80) == 0x80));
897
+ break;
898
+ }
899
+ }
900
+ len = i + 1;
901
+ if (need_extra_byte) {
902
+ bytes = ALLOC_N(uint8_t, len + 1);
903
+ ptr = bytes;
904
+ *ptr++ = sign ? 0x00 : 0xff;
905
+ }
906
+ else {
907
+ bytes = ALLOC_N(uint8_t, len);
908
+ ptr = bytes;
909
+ }
910
+ while (len > 0) {
911
+ *ptr++ = numbytes[--len];
912
+ }
913
+ *out = bytes;
914
+ return ptr - bytes;
915
+ }
916
+
917
+ static int
918
+ int_decode_integer_to_long(uint8_t *bytes, size_t len, long *out)
919
+ {
920
+ unsigned long num = 0;
921
+ size_t i;
922
+
923
+ for (i = 0; i < len; i++)
924
+ num |= bytes[i] << ((len - i - 1) * CHAR_BIT);
925
+
926
+ if (num > LONG_MAX) {
927
+ krypt_error_add("Integer value too large");
928
+ return KRYPT_ERR;
929
+ }
930
+ *out = (long) num;
931
+ return KRYPT_OK;
932
+ }
933
+
934
+ static int
935
+ int_decode_positive_integer(uint8_t *bytes, size_t len, VALUE *out)
936
+ {
937
+ long num;
938
+
939
+ if (int_decode_integer_to_long(bytes, len, &num) == KRYPT_ERR) return KRYPT_ERR;
940
+ *out = LONG2NUM(num);
941
+ return KRYPT_OK;
942
+ }
943
+
944
+ static int
945
+ int_decode_negative_integer(uint8_t *bytes, size_t len, VALUE *out)
946
+ {
947
+ long num;
948
+ uint8_t *copy;
949
+ int result;
950
+
951
+ copy = ALLOC_N(uint8_t, len);
952
+ krypt_compute_twos_complement(copy, bytes, len);
953
+ result = int_decode_integer_to_long(copy, len, &num);
954
+ xfree(copy);
955
+ if (result == KRYPT_ERR) return KRYPT_ERR;
956
+ *out = LONG2NUM(-num);
957
+ return KRYPT_OK;
958
+ }
959
+
960
+ static int
961
+ int_decode_integer(uint8_t *bytes, size_t len, VALUE *out)
962
+ {
963
+ if (bytes[0] & 0x80) {
964
+ return int_decode_negative_integer(bytes, len, out);
965
+ }
966
+ else {
967
+ if (bytes[0] == 0x0)
968
+ return int_decode_positive_integer(bytes + 1, len - 1, out);
969
+ else
970
+ return int_decode_positive_integer(bytes, len, out);
971
+ }
972
+ }
973
+