1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
| #include <asn1/asn1.h>
#include <asn1/asn1_parser.h>
#define INTEGER_SIZE 32
static chunk_t chunk_to_asn1(chunk_t chunk)
{
chunk_t x;
chunk_t y;
chunk_t hash;
chunk_t content;
chunk_t asn1;
x.ptr = chunk.ptr;
x.len = INTEGER_SIZE;
y.ptr = chunk.ptr + INTEGER_SIZE;
y.len = INTEGER_SIZE;
content.ptr = y.ptr + INTEGER_SIZE;
content.len = chunk.len - INTEGER_SIZE * 3;
hash.ptr = content.ptr + content.len;
hash.len = INTEGER_SIZE;
asn1 = asn1_wrap(ASN1_SEQUENCE, "mmmm",
asn1_integer("c", x),
asn1_integer("c", y),
asn1_simple_object(ASN1_OCTET_STRING, hash),
asn1_simple_object(ASN1_OCTET_STRING, content));
chunk_free(&chunk);
return asn1;
}
static const asn1Object_t patterns[] = {
{ 0, "seq", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
{ 1, "x", ASN1_INTEGER, ASN1_BODY }, /* 1 */
{ 1, "y", ASN1_INTEGER, ASN1_BODY }, /* 2 */
{ 1, "hash", ASN1_OCTET_STRING, ASN1_BODY }, /* 3 */
{ 1, "content", ASN1_OCTET_STRING, ASN1_BODY }, /* 4 */
{ 0, "exit", ASN1_EOC, ASN1_EXIT }
};
#define PATTERN_KEY_X 1
#define PATTERN_KEY_Y 2
#define PATTERN_KEY_HASH 3
#define PATTERN_KEY_CONTENT 4
static chunk_t correct_integer(chunk_t chunk)
{
if (chunk.len == INTEGER_SIZE + 1)
return chunk_skip(chunk, 1);
return chunk;
}
static bool parse_asn1(chunk_t asn1, chunk_t* x, chunk_t* y, chunk_t* hash, chunk_t* content)
{
chunk_t object;
asn1_parser_t *parser;
bool success = FALSE;
int object_id, oid, i;
parser = asn1_parser_create(patterns, asn1);
while (parser->iterate(parser, &object_id, &object))
{
switch (object_id)
{
case PATTERN_KEY_X:
*x = correct_integer(object);
break;
case PATTERN_KEY_Y:
*y = correct_integer(object);
break;
case PATTERN_KEY_HASH:
*hash = object;
break;
case PATTERN_KEY_CONTENT:
*content = object;
break;
}
}
success = parser->success(parser);
parser->destroy(parser);
return success;
}
static bool chunk_from_asn1(chunk_t* chunk, chunk_t asn1)
{
chunk_t x;
chunk_t y;
chunk_t hash;
chunk_t content;
if (!parse_asn1(asn1, &x, &y, &hash, &content))
return false;
*chunk = chunk_cat("cccc", x, y, content, hash);
return true;
}
static void random_data(chunk_t chunk)
{
int fd = open("/dev/urandom", O_RDONLY);
read(fd, chunk.ptr, chunk.len);
close(fd);
}
int test()
{
bool is_ok;
chunk_t result;
chunk_t asn1;
chunk_t total = chunk_alloc(INTEGER_SIZE * 3 + 345);
random_data(total);
asn1 = chunk_to_asn1(total);
is_ok = chunk_from_asn1(&result, asn1);
chunk_free(&result);
chunk_free(&asn1);
chunk_free(&total);
return is_ok;
} |