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