1 #include "extension.h"
2
3 #include <errno.h>
4 #include "common.h"
5 #include "log.h"
6 #include "nid.h"
7 #include "thread_var.h"
8 #include "crypto/hash.h"
9
10 static struct extension_metadata IR2 = {
11 "Amended IP Resources",
12 -1,
13 true,
14 };
15
16 static struct extension_metadata AR2 = {
17 "Amended AS Resources",
18 -1,
19 true,
20 };
21
extension_init(void)22 int extension_init(void)
23 {
24 IR2.nid = nid_ipAddrBlocksv2();
25 AR2.nid = nid_autonomousSysIdsv2();
26 return 0;
27 }
28
ext_bc(void)29 struct extension_metadata const *ext_bc(void)
30 {
31 static const struct extension_metadata BC = {
32 "Basic Constraints",
33 NID_basic_constraints,
34 true,
35 };
36 return &BC;
37 }
38
ext_ski(void)39 struct extension_metadata const *ext_ski(void)
40 {
41 static const struct extension_metadata SKI = {
42 "Subject Key Identifier",
43 NID_subject_key_identifier,
44 false,
45 };
46 return &SKI;
47 }
48
ext_aki(void)49 struct extension_metadata const *ext_aki(void)
50 {
51 static const struct extension_metadata AKI = {
52 "Authority Key Identifier",
53 NID_authority_key_identifier,
54 false,
55 };
56 return &AKI;
57 }
58
ext_ku(void)59 struct extension_metadata const *ext_ku(void)
60 {
61 static const struct extension_metadata KU = {
62 "Key Usage",
63 NID_key_usage,
64 true,
65 };
66 return &KU;
67 }
68
ext_cdp(void)69 struct extension_metadata const *ext_cdp(void)
70 {
71 static const struct extension_metadata CDP = {
72 "CRL Distribution Points",
73 NID_crl_distribution_points,
74 false,
75 };
76 return &CDP;
77 }
78
ext_aia(void)79 struct extension_metadata const *ext_aia(void)
80 {
81 static const struct extension_metadata AIA = {
82 "Authority Information Access",
83 NID_info_access,
84 false,
85 };
86 return &AIA;
87 }
88
ext_sia(void)89 struct extension_metadata const *ext_sia(void)
90 {
91 static const struct extension_metadata SIA = {
92 "Subject Information Access",
93 NID_sinfo_access ,
94 false,
95 };
96 return &SIA;
97 }
98
ext_cp(void)99 struct extension_metadata const *ext_cp(void)
100 {
101 static const struct extension_metadata CP = {
102 "Certificate Policies",
103 NID_certificate_policies,
104 true,
105 };
106 return &CP;
107 }
108
ext_ir(void)109 struct extension_metadata const *ext_ir(void)
110 {
111 static const struct extension_metadata IR = {
112 "IP Resources",
113 NID_sbgp_ipAddrBlock,
114 true,
115 };
116 return &IR;
117 }
118
ext_ar(void)119 struct extension_metadata const *ext_ar(void)
120 {
121 static const struct extension_metadata AR = {
122 "AS Resources",
123 NID_sbgp_autonomousSysNum,
124 true,
125 };
126 return &AR;
127 }
128
ext_ir2(void)129 struct extension_metadata const *ext_ir2(void)
130 {
131 return &IR2;
132 }
133
ext_ar2(void)134 struct extension_metadata const *ext_ar2(void)
135 {
136 return &AR2;
137 }
138
ext_cn(void)139 struct extension_metadata const *ext_cn(void)
140 {
141 static const struct extension_metadata CN = {
142 "CRL Number",
143 NID_crl_number,
144 false,
145 };
146 return &CN;
147 }
148
ext_eku(void)149 struct extension_metadata const *ext_eku(void)
150 {
151 static const struct extension_metadata EKU = {
152 "Extended Key Usage",
153 NID_ext_key_usage,
154 false,
155 };
156 return &EKU;
157 }
158
159 static int
handle_extension(struct extension_handler * handlers,X509_EXTENSION * ext)160 handle_extension(struct extension_handler *handlers, X509_EXTENSION *ext)
161 {
162 struct extension_handler *handler;
163 int nid;
164
165 nid = OBJ_obj2nid(X509_EXTENSION_get_object(ext));
166
167 for (handler = handlers; handler->meta != NULL; handler++) {
168 if (handler->meta->nid == nid) {
169 if (handler->found)
170 goto dupe;
171 handler->found = true;
172
173 if (handler->meta->critical) {
174 if (!X509_EXTENSION_get_critical(ext))
175 goto not_critical;
176 } else {
177 if (X509_EXTENSION_get_critical(ext))
178 goto critical;
179 }
180
181 return handler->cb(ext, handler->arg);
182 }
183 }
184
185 if (!X509_EXTENSION_get_critical(ext))
186 return 0; /* Unknown and not critical; ignore it. */
187
188 /*
189 * TODO (next iteration?) print the NID as string.
190 * Also "unknown" is misleading. I think it's only "unknown" if the NID
191 * is -1 or something like that.
192 */
193 return pr_val_err("Certificate has unknown extension. (Extension NID: %d)",
194 nid);
195 dupe:
196 return pr_val_err("Certificate has more than one '%s' extension.",
197 handler->meta->name);
198 not_critical:
199 return pr_val_err("Extension '%s' is supposed to be marked critical.",
200 handler->meta->name);
201 critical:
202 return pr_val_err("Extension '%s' is not supposed to be marked critical.",
203 handler->meta->name);
204 }
205
206 int
handle_extensions(struct extension_handler * handlers,STACK_OF (X509_EXTENSION)const * extensions)207 handle_extensions(struct extension_handler *handlers,
208 STACK_OF(X509_EXTENSION) const *extensions)
209 {
210 struct extension_handler *handler;
211 int e;
212 int error;
213
214 for (e = 0; e < sk_X509_EXTENSION_num(extensions); e++) {
215 error = handle_extension(handlers,
216 sk_X509_EXTENSION_value(extensions, e));
217 if (error)
218 return error;
219 }
220
221 for (handler = handlers; handler->meta != NULL; handler++) {
222 if (handler->mandatory && !handler->found)
223 return pr_val_err("Certificate is missing the '%s' extension.",
224 handler->meta->name);
225 }
226
227 return 0;
228 }
229
230 int
cannot_decode(struct extension_metadata const * meta)231 cannot_decode(struct extension_metadata const *meta)
232 {
233 return pr_val_err("Extension '%s' seems to be malformed. Cannot decode.",
234 meta->name);
235 }
236
237 /**
238 * Returns 0 if the identifier (ie. SHA-1 hash) of @cert's public key is @hash.
239 * Otherwise returns error code.
240 */
241 int
validate_public_key_hash(X509 * cert,ASN1_OCTET_STRING * hash)242 validate_public_key_hash(X509 *cert, ASN1_OCTET_STRING *hash)
243 {
244 X509_PUBKEY *pubkey;
245 const unsigned char *spk;
246 int spk_len;
247 int ok;
248 int error;
249
250 /*
251 * I really can't tell if this validation needs to be performed.
252 * Probably not.
253 *
254 * "Applications are not required to verify that key identifiers match
255 * when performing certification path validation."
256 * (rfc5280#section-4.2.1.2)
257 *
258 * From its context, my reading is that the quote refers to the
259 * "parent's SKI must equal the children's AKI" requirement, not the
260 * "child's SKI must equal the SHA-1 of its own's SPK" requirement. So
261 * I think that we're only supposed to check the SHA-1. Or nothing at
262 * all, because we only care about the keys, not their identifiers.
263 *
264 * But the two requirements actually have a lot in common:
265 *
266 * The quote is from 5280, not 6487. 6487 chooses to enforce the SKI's
267 * "SHA-1 as identifier" option, even for the AKI. And if I'm validating
268 * the AKI's SHA-1, then I'm also indirectly checking the children vs
269 * parent relationship.
270 *
271 * Also, what's with using a hash as identifier? That's an accident
272 * waiting to happen...
273 *
274 * Bottom line, I don't know. But better be safe than sorry, so here's
275 * the validation.
276 *
277 * Shit. I feel like I'm losing so much performance because the RFCs
278 * are so wishy-washy about what is our realm and what is not.
279 */
280
281 /* Get the SPK (ask libcrypto) */
282 pubkey = X509_get_X509_PUBKEY(cert);
283 if (pubkey == NULL)
284 return val_crypto_err("X509_get_X509_PUBKEY() returned NULL");
285
286 ok = X509_PUBKEY_get0_param(NULL, &spk, &spk_len, NULL, pubkey);
287 if (!ok)
288 return val_crypto_err("X509_PUBKEY_get0_param() returned %d", ok);
289
290 /* Hash the SPK, compare SPK hash with the SKI */
291 if (hash->length < 0 || SIZE_MAX < hash->length) {
292 return pr_val_err("%s length (%d) is out of bounds. (0-%zu)",
293 ext_ski()->name, hash->length, SIZE_MAX);
294 }
295 if (spk_len < 0 || SIZE_MAX < spk_len) {
296 return pr_val_err("Subject Public Key length (%d) is out of bounds. (0-%zu)",
297 spk_len, SIZE_MAX);
298 }
299
300 error = hash_validate("sha1", hash->data, hash->length, spk, spk_len);
301 if (error) {
302 pr_val_err("The Subject Public Key's hash does not match the %s.",
303 ext_ski()->name);
304 }
305
306 return error;
307 }
308
309 int
handle_aki(X509_EXTENSION * ext,void * arg)310 handle_aki(X509_EXTENSION *ext, void *arg)
311 {
312 AUTHORITY_KEYID *aki;
313 struct validation *state;
314 X509 *parent;
315 int error;
316
317 aki = X509V3_EXT_d2i(ext);
318 if (aki == NULL)
319 return cannot_decode(ext_aki());
320
321 if (aki->issuer != NULL) {
322 error = pr_val_err("%s extension contains an authorityCertIssuer.",
323 ext_aki()->name);
324 goto end;
325 }
326 if (aki->serial != NULL) {
327 error = pr_val_err("%s extension contains an authorityCertSerialNumber.",
328 ext_aki()->name);
329 goto end;
330 }
331
332 state = state_retrieve();
333 if (state == NULL) {
334 error = -EINVAL;
335 goto end;
336 }
337
338 parent = x509stack_peek(validation_certstack(state));
339 if (parent == NULL) {
340 error = pr_val_err("Certificate has no parent.");
341 goto end;
342 }
343
344 error = validate_public_key_hash(parent, aki->keyid);
345
346 end:
347 AUTHORITY_KEYID_free(aki);
348 return error;
349 }
350