Branch data Line data Source code
1 : : /*-
2 : : * Copyright (c) 2021 Kyle Evans <kevans@FreeBSD.org>
3 : : *
4 : : * Redistribution and use in source and binary forms, with or without
5 : : * modification, are permitted provided that the following conditions
6 : : * are met:
7 : : * 1. Redistributions of source code must retain the above copyright
8 : : * notice, this list of conditions and the following disclaimer
9 : : * in this position and unchanged.
10 : : * 2. Redistributions in binary form must reproduce the above copyright
11 : : * notice, this list of conditions and the following disclaimer in the
12 : : * documentation and/or other materials provided with the distribution.
13 : : *
14 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 : : * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 : : */
25 : :
26 : : #include <sys/cdefs.h>
27 : :
28 : : #include <assert.h>
29 : : #include <errno.h>
30 : : #include <stdlib.h>
31 : : #include <string.h>
32 : :
33 : : #include "private/pkg.h"
34 : : #include "private/pkgsign.h"
35 : : #include "pkghash.h"
36 : : #include "xmalloc.h"
37 : :
38 : : /* Other parts of libpkg should use pkgsign instead of rsa directly. */
39 : : extern const struct pkgsign_ops pkgsign_ossl;
40 : : extern const struct pkgsign_ops pkgsign_ecc;
41 : :
42 : : static pkghash *pkgsign_verifiers;
43 : :
44 : : /*
45 : : * The eventual goal is to allow plugins to register their own pkgsign
46 : : * implementations as needed. The initial sketch was to add a constructor
47 : : * to register the builtin pkgsign implementations since there should only be
48 : : * a couple of them, but this is saved for later work.
49 : : */
50 : : static struct pkgsign_impl {
51 : : const char *pi_name;
52 : : const struct pkgsign_ops *pi_ops;
53 : : int pi_refs; /* XXX */
54 : : } pkgsign_builtins[] = {
55 : : {
56 : : .pi_name = "rsa",
57 : : .pi_ops = &pkgsign_ossl,
58 : : },
59 : : {
60 : : .pi_name = "ecc",
61 : : .pi_ops = &pkgsign_ecc,
62 : : },
63 : : {
64 : : .pi_name = "ecdsa",
65 : : .pi_ops = &pkgsign_ecc,
66 : : },
67 : : {
68 : : .pi_name = "eddsa",
69 : : .pi_ops = &pkgsign_ecc,
70 : : },
71 : : };
72 : :
73 : : static int
74 : 26 : pkgsign_new(const char *name, struct pkgsign_ctx **ctx)
75 : : {
76 : : struct pkgsign_impl *impl;
77 : : const struct pkgsign_ops *ops;
78 : : struct pkgsign_ctx *nctx;
79 : : size_t ctx_size;
80 : : int ret;
81 : :
82 [ + - ]: 26 : assert(*ctx == NULL);
83 : :
84 : 26 : ops = NULL;
85 [ - + ]: 51 : for (size_t i = 0; i < NELEM(pkgsign_builtins); i++) {
86 : 51 : impl = &pkgsign_builtins[i];
87 [ + + ]: 51 : if (STREQ(name, impl->pi_name)) {
88 : 26 : ops = impl->pi_ops;
89 : 26 : break;
90 : : }
91 : 25 : }
92 : :
93 [ + - ]: 26 : if (ops == NULL)
94 : 0 : return (EPKG_FATAL);
95 : :
96 : 26 : ctx_size = ops->pkgsign_ctx_size;
97 [ + - + - ]: 26 : assert(ctx_size == 0 || ctx_size >= sizeof(struct pkgsign_ctx));
98 [ + - ]: 26 : if (ctx_size == 0)
99 : 0 : ctx_size = sizeof(struct pkgsign_ctx);
100 : :
101 : 26 : nctx = xcalloc(1, ctx_size);
102 : 26 : nctx->impl = impl;
103 : :
104 : 26 : ret = EPKG_OK;
105 [ - + ]: 26 : if (ops->pkgsign_new != NULL)
106 : 26 : ret = (*ops->pkgsign_new)(name, nctx);
107 : :
108 [ - + ]: 26 : if (ret != EPKG_OK) {
109 : 0 : free(nctx);
110 : 0 : return (ret);
111 : : }
112 : :
113 : 26 : impl->pi_refs++;
114 : 26 : *ctx = nctx;
115 : 26 : return (EPKG_OK);
116 : 26 : }
117 : :
118 : : int
119 : 7 : pkgsign_new_verify(const char *name, const struct pkgsign_ctx **octx)
120 : : {
121 : : struct pkgsign_ctx *ctx;
122 : : pkghash_entry *entry;
123 : : int ret;
124 : :
125 : 7 : entry = pkghash_get(pkgsign_verifiers, name);
126 [ - + ]: 7 : if (entry != NULL) {
127 : 0 : *octx = entry->value;
128 : 0 : return (EPKG_OK);
129 : : }
130 : :
131 : 7 : ctx = NULL;
132 [ - + ]: 7 : if ((ret = pkgsign_new(name, &ctx)) != EPKG_OK)
133 : 0 : return (ret);
134 : :
135 [ - + # # ]: 7 : pkghash_safe_add(pkgsign_verifiers, name, ctx, NULL);
136 : 7 : *octx = ctx;
137 : 7 : return (EPKG_OK);
138 : 7 : }
139 : :
140 : : int
141 : 19 : pkgsign_new_sign(const char *name, struct pkgsign_ctx **ctx)
142 : : {
143 : :
144 : 19 : return (pkgsign_new(name, ctx));
145 : : }
146 : :
147 : : void
148 : 19 : pkgsign_set(struct pkgsign_ctx *sctx, pkg_password_cb *cb, const char *keyfile)
149 : : {
150 : :
151 : 19 : sctx->pw_cb = cb;
152 : 19 : sctx->path = keyfile;
153 : 19 : }
154 : :
155 : : void
156 : 90 : pkgsign_free(struct pkgsign_ctx *ctx)
157 : : {
158 : : struct pkgsign_impl *impl;
159 : : const struct pkgsign_ops *ops;
160 : :
161 [ + + ]: 90 : if (ctx == NULL)
162 : 71 : return;
163 : 19 : impl = ctx->impl;
164 : 19 : ops = impl->pi_ops;
165 [ - + ]: 19 : if (ops->pkgsign_free != NULL)
166 : 19 : (*ops->pkgsign_free)(ctx);
167 : :
168 : 19 : impl->pi_refs--;
169 : 19 : free(ctx);
170 : 90 : }
171 : :
172 : : int
173 : 8 : pkgsign_sign(struct pkgsign_ctx *ctx, const char *path, unsigned char **sigret,
174 : : size_t *siglen)
175 : : {
176 : :
177 : 8 : return (*ctx->impl->pi_ops->pkgsign_sign)(ctx, path, sigret, siglen);
178 : : }
179 : :
180 : : int
181 : 4 : pkgsign_verify(const struct pkgsign_ctx *ctx, const char *key,
182 : : unsigned char *sig, size_t siglen, int fd)
183 : : {
184 : :
185 : 4 : return (*ctx->impl->pi_ops->pkgsign_verify)(ctx, key, sig, siglen, fd);
186 : : }
187 : :
188 : : int
189 : 3 : pkgsign_verify_cert(const struct pkgsign_ctx *ctx, unsigned char *key, size_t keylen,
190 : : unsigned char *sig, size_t siglen, int fd)
191 : : {
192 : :
193 : 6 : return (*ctx->impl->pi_ops->pkgsign_verify_cert)(ctx, key, keylen, sig,
194 : 3 : siglen, fd);
195 : : }
196 : :
197 : : const char *
198 : 11 : pkgsign_impl_name(const struct pkgsign_ctx *ctx)
199 : : {
200 : :
201 : 11 : return (ctx->impl->pi_name);
202 : : }
203 : :
204 : : int
205 : 12 : pkgsign_generate(struct pkgsign_ctx *ctx, const struct iovec *iov, int niov)
206 : : {
207 : :
208 [ + - ]: 12 : if (ctx->impl->pi_ops->pkgsign_generate == NULL)
209 : 0 : return (EPKG_OPNOTSUPP);
210 : 12 : return (*ctx->impl->pi_ops->pkgsign_generate)(ctx, iov, niov);
211 : 12 : }
212 : :
213 : : int
214 : 2 : pkgsign_sign_data(struct pkgsign_ctx *ctx, const unsigned char *msg, size_t msgsz,
215 : : unsigned char **sig, size_t *siglen)
216 : : {
217 : :
218 [ + - ]: 2 : if (ctx->impl->pi_ops->pkgsign_sign_data == NULL)
219 : 0 : return (EPKG_OPNOTSUPP);
220 : 2 : return (*ctx->impl->pi_ops->pkgsign_sign_data)(ctx, msg, msgsz, sig, siglen);
221 : 2 : }
222 : :
223 : : int
224 : 0 : pkgsign_keyinfo(struct pkgsign_ctx *ctx, struct iovec **iov, int *niov)
225 : : {
226 : :
227 [ # # ]: 0 : if (ctx->impl->pi_ops->pkgsign_keyinfo == NULL)
228 : 0 : return (EPKG_OPNOTSUPP);
229 : 0 : return (*ctx->impl->pi_ops->pkgsign_keyinfo)(ctx, iov, niov);
230 : 0 : }
231 : :
232 : : int
233 : 13 : pkgsign_pubkey(struct pkgsign_ctx *ctx, char **pubkey, size_t *pubkeylen)
234 : : {
235 : :
236 [ + - ]: 13 : if (ctx->impl->pi_ops->pkgsign_pubkey == NULL)
237 : 0 : return (EPKG_OPNOTSUPP);
238 : 13 : return (*ctx->impl->pi_ops->pkgsign_pubkey)(ctx, pubkey, pubkeylen);
239 : 13 : }
|