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