1 /*-
2 * Copyright (c) 2024 Kyle Evans <kevans@FreeBSD.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7 #include <sys/stat.h>
8
9 #include <assert.h>
10 #include <fcntl.h>
11 #include <inttypes.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16
17 #include <libder.h>
18
19 #include "test_common.h"
20
21 /*
22 * Note that the choice of secp112r1 is completely arbitrary. I was mainly
23 * shooting for something pretty weak to avoid people trying to "catch me"
24 * checking in private key material, even though it's very incredibly clearly
25 * just for a test case.
26 */
27 static const uint8_t oid_secp112r1[] =
28 { 0x2b, 0x81, 0x04, 0x00, 0x06 };
29
30 static const uint8_t privdata[] = { 0xa5, 0xf5, 0x2a, 0x56, 0x61, 0xe3, 0x58,
31 0x76, 0x5c, 0x4f, 0xd6, 0x8d, 0x60, 0x54 };
32
33 static const uint8_t pubdata[] = { 0x00, 0x04, 0xae, 0x69, 0x41, 0x0d, 0x9c,
34 0x9b, 0xf2, 0x34, 0xf6, 0x2d, 0x7c, 0x91, 0xe1, 0xc7, 0x7f, 0x23, 0xa0,
35 0x84, 0x34, 0x5c, 0x38, 0x26, 0xd8, 0xcf, 0xbe, 0xf7, 0xdc, 0x8a };
36
37 static void
test_interface(struct libder_object * root)38 test_interface(struct libder_object *root)
39 {
40 const uint8_t *data;
41 size_t datasz;
42 struct libder_object *keystring, *oid;
43
44 /* Grab the oid first. */
45 oid = libder_obj_child(root, 2);
46 assert(oid != NULL); /* Actually just the container... */
47 assert(libder_obj_type_simple(oid) == 0xa0);
48
49 oid = libder_obj_child(oid, 0);
50 assert(oid != NULL); /* Now *that*'s an OID. */
51 assert(libder_obj_type_simple(oid) == BT_OID);
52 data = libder_obj_data(oid, &datasz);
53 assert(datasz == sizeof(oid_secp112r1));
54 assert(memcmp(oid_secp112r1, data, datasz) == 0);
55
56 keystring = libder_obj_child(root, 1);
57 assert(keystring != NULL);
58 assert(libder_obj_type_simple(keystring) == BT_OCTETSTRING);
59
60 data = libder_obj_data(keystring, &datasz);
61 assert(datasz == sizeof(privdata));
62 assert(memcmp(privdata, data, datasz) == 0);
63 }
64
65 /* buf and bufszs are just our reference */
66 static void
test_construction(struct libder_ctx * ctx,const uint8_t * buf,size_t bufsz)67 test_construction(struct libder_ctx *ctx, const uint8_t *buf, size_t bufsz)
68 {
69 uint8_t *out;
70 struct libder_object *obj, *oidp, *pubp, *root;
71 struct libder_object *keystring;
72 size_t outsz;
73 uint8_t data;
74
75 root = libder_obj_alloc_simple(ctx, BT_SEQUENCE, NULL, 0);
76 assert(root != NULL);
77
78 data = 1;
79 obj = libder_obj_alloc_simple(ctx, BT_INTEGER, &data, 1);
80 assert(obj != NULL);
81 assert(libder_obj_append(root, obj));
82
83 /* Private key material */
84 obj = libder_obj_alloc_simple(ctx, BT_OCTETSTRING, privdata, sizeof(privdata));
85 assert(obj != NULL);
86 assert(libder_obj_append(root, obj));
87
88 /* Now throw in the OID and pubkey containers */
89 oidp = libder_obj_alloc_simple(ctx,
90 (BC_CONTEXT << 6) | BER_TYPE_CONSTRUCTED_MASK | 0, NULL, 0);
91 assert(oidp != NULL);
92 assert(libder_obj_append(root, oidp));
93
94 pubp = libder_obj_alloc_simple(ctx,
95 (BC_CONTEXT << 6) | BER_TYPE_CONSTRUCTED_MASK | 1, NULL, 0);
96 assert(pubp != NULL);
97 assert(libder_obj_append(root, pubp));
98
99 /* Actually add the OID */
100 obj = libder_obj_alloc_simple(ctx, BT_OID, oid_secp112r1, sizeof(oid_secp112r1));
101 assert(obj != NULL);
102 assert(libder_obj_append(oidp, obj));
103
104 /* Finally, add the pubkey */
105 obj = libder_obj_alloc_simple(ctx, BT_BITSTRING, pubdata, sizeof(pubdata));
106 assert(obj != NULL);
107 assert(libder_obj_append(pubp, obj));
108
109 out = NULL;
110 outsz = 0;
111 out = libder_write(ctx, root, out, &outsz);
112 assert(out != NULL);
113 assert(outsz == bufsz);
114
115 assert(memcmp(out, buf, bufsz) == 0);
116
117 libder_obj_free(root);
118 free(out);
119 }
120
121 int
main(int argc,char * argv[])122 main(int argc, char *argv[])
123 {
124 struct stat sb;
125 struct libder_ctx *ctx;
126 struct libder_object *root;
127 uint8_t *buf, *out;
128 size_t bufsz, outsz, rootsz;
129 ssize_t readsz;
130 int dfd, error, fd;
131
132 dfd = open_progdir(argv[0]);
133
134 fd = openat(dfd, "repo.priv", O_RDONLY);
135 assert(fd >= 0);
136
137 close(dfd);
138 dfd = -1;
139
140 error = fstat(fd, &sb);
141 assert(error == 0);
142
143 bufsz = sb.st_size;
144 buf = malloc(bufsz);
145 assert(buf != NULL);
146
147 readsz = read(fd, buf, bufsz);
148 close(fd);
149
150 assert(readsz == bufsz);
151
152 ctx = libder_open();
153 rootsz = bufsz;
154 libder_set_verbose(ctx, 2);
155 root = libder_read(ctx, buf, &rootsz);
156
157 assert(root != NULL);
158 assert(rootsz == bufsz);
159
160 test_interface(root);
161 test_construction(ctx, buf, bufsz);
162
163 outsz = 0;
164 out = NULL;
165 out = libder_write(ctx, root, out, &outsz);
166 assert(out != NULL);
167 assert(outsz == bufsz);
168
169 assert(memcmp(buf, out, outsz) == 0);
170
171 free(out);
172 free(buf);
173 libder_obj_free(root);
174 libder_close(ctx);
175 }
176