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