xref: /freebsd/contrib/libder/tests/test_privkey.c (revision f3087bef11543b42e0d69b708f367097a4118d24)
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
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
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
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