1 #ifndef _IPXE_X509_H
2 #define _IPXE_X509_H
3 
4 /** @file
5  *
6  * X.509 certificates
7  *
8  */
9 
10 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11 
12 #include <stdint.h>
13 #include <stddef.h>
14 #include <time.h>
15 #include <ipxe/asn1.h>
16 #include <ipxe/refcnt.h>
17 #include <ipxe/list.h>
18 
19 struct image;
20 
21 /** An X.509 serial number */
22 struct x509_serial {
23 	/** Raw serial number */
24 	struct asn1_cursor raw;
25 };
26 
27 /** An X.509 issuer */
28 struct x509_issuer {
29 	/** Raw issuer */
30 	struct asn1_cursor raw;
31 };
32 
33 /** An X.509 time */
34 struct x509_time {
35 	/** Seconds since the Epoch */
36 	time_t time;
37 };
38 
39 /** An X.509 certificate validity period */
40 struct x509_validity {
41 	/** Not valid before */
42 	struct x509_time not_before;
43 	/** Not valid after */
44 	struct x509_time not_after;
45 };
46 
47 /** An X.509 certificate public key */
48 struct x509_public_key {
49 	/** Raw public key information */
50 	struct asn1_cursor raw;
51 	/** Public key algorithm */
52 	struct asn1_algorithm *algorithm;
53 	/** Raw public key bit string */
54 	struct asn1_bit_string raw_bits;
55 };
56 
57 /** An X.509 certificate subject */
58 struct x509_subject {
59 	/** Raw subject */
60 	struct asn1_cursor raw;
61 	/** Common name */
62 	struct asn1_cursor common_name;
63 	/** Public key information */
64 	struct x509_public_key public_key;
65 };
66 
67 /** An X.509 certificate signature */
68 struct x509_signature {
69 	/** Signature algorithm */
70 	struct asn1_algorithm *algorithm;
71 	/** Signature value */
72 	struct asn1_bit_string value;
73 };
74 
75 /** An X.509 certificate basic constraints set */
76 struct x509_basic_constraints {
77 	/** Subject is a CA */
78 	int ca;
79 	/** Path length */
80 	unsigned int path_len;
81 };
82 
83 /** Unlimited path length
84  *
85  * We use -2U, since this quantity represents one *fewer* than the
86  * maximum number of remaining certificates in a chain.
87  */
88 #define X509_PATH_LEN_UNLIMITED -2U
89 
90 /** An X.509 certificate key usage */
91 struct x509_key_usage {
92 	/** Key usage extension is present */
93 	int present;
94 	/** Usage bits */
95 	unsigned int bits;
96 };
97 
98 /** X.509 certificate key usage bits */
99 enum x509_key_usage_bits {
100 	X509_DIGITAL_SIGNATURE = 0x0080,
101 	X509_NON_REPUDIATION = 0x0040,
102 	X509_KEY_ENCIPHERMENT = 0x0020,
103 	X509_DATA_ENCIPHERMENT = 0x0010,
104 	X509_KEY_AGREEMENT = 0x0008,
105 	X509_KEY_CERT_SIGN = 0x0004,
106 	X509_CRL_SIGN = 0x0002,
107 	X509_ENCIPHER_ONLY = 0x0001,
108 	X509_DECIPHER_ONLY = 0x8000,
109 };
110 
111 /** An X.509 certificate extended key usage */
112 struct x509_extended_key_usage {
113 	/** Usage bits */
114 	unsigned int bits;
115 };
116 
117 /** X.509 certificate extended key usage bits
118  *
119  * Extended key usages are identified by OID; these bits are purely an
120  * internal definition.
121  */
122 enum x509_extended_key_usage_bits {
123 	X509_CODE_SIGNING = 0x0001,
124 	X509_OCSP_SIGNING = 0x0002,
125 };
126 
127 /** X.509 certificate OCSP responder */
128 struct x509_ocsp_responder {
129 	/** URI */
130 	struct asn1_cursor uri;
131 	/** OCSP status is good */
132 	int good;
133 };
134 
135 /** X.509 certificate authority information access */
136 struct x509_authority_info_access {
137 	/** OCSP responder */
138 	struct x509_ocsp_responder ocsp;
139 };
140 
141 /** X.509 certificate subject alternative name */
142 struct x509_subject_alt_name {
143 	/** Names */
144 	struct asn1_cursor names;
145 };
146 
147 /** X.509 certificate general name types */
148 enum x509_general_name_types {
149 	X509_GENERAL_NAME_DNS = ASN1_IMPLICIT_TAG ( 2 ),
150 	X509_GENERAL_NAME_URI = ASN1_IMPLICIT_TAG ( 6 ),
151 	X509_GENERAL_NAME_IP = ASN1_IMPLICIT_TAG ( 7 ),
152 };
153 
154 /** An X.509 certificate extensions set */
155 struct x509_extensions {
156 	/** Basic constraints */
157 	struct x509_basic_constraints basic;
158 	/** Key usage */
159 	struct x509_key_usage usage;
160 	/** Extended key usage */
161 	struct x509_extended_key_usage ext_usage;
162 	/** Authority information access */
163 	struct x509_authority_info_access auth_info;
164 	/** Subject alternative name */
165 	struct x509_subject_alt_name alt_name;
166 };
167 
168 /** A link in an X.509 certificate chain */
169 struct x509_link {
170 	/** List of links */
171 	struct list_head list;
172 	/** Certificate */
173 	struct x509_certificate *cert;
174 };
175 
176 /** An X.509 certificate chain */
177 struct x509_chain {
178 	/** Reference count */
179 	struct refcnt refcnt;
180 	/** List of links */
181 	struct list_head links;
182 };
183 
184 /** An X.509 certificate */
185 struct x509_certificate {
186 	/** Reference count */
187 	struct refcnt refcnt;
188 
189 	/** Link in certificate store */
190 	struct x509_link store;
191 
192 	/** Flags */
193 	unsigned int flags;
194 	/** Root against which certificate has been validated (if any) */
195 	struct x509_root *root;
196 	/** Maximum number of subsequent certificates in chain */
197 	unsigned int path_remaining;
198 
199 	/** Raw certificate */
200 	struct asn1_cursor raw;
201 	/** Version */
202 	unsigned int version;
203 	/** Serial number */
204 	struct x509_serial serial;
205 	/** Raw tbsCertificate */
206 	struct asn1_cursor tbs;
207 	/** Signature algorithm */
208 	struct asn1_algorithm *signature_algorithm;
209 	/** Issuer */
210 	struct x509_issuer issuer;
211 	/** Validity */
212 	struct x509_validity validity;
213 	/** Subject */
214 	struct x509_subject subject;
215 	/** Signature */
216 	struct x509_signature signature;
217 	/** Extensions */
218 	struct x509_extensions extensions;
219 };
220 
221 /** X.509 certificate flags */
222 enum x509_flags {
223 	/** Certificate was added at build time */
224 	X509_FL_PERMANENT = 0x0001,
225 	/** Certificate was added explicitly at run time */
226 	X509_FL_EXPLICIT = 0x0002,
227 };
228 
229 /**
230  * Get reference to X.509 certificate
231  *
232  * @v cert		X.509 certificate
233  * @ret cert		X.509 certificate
234  */
235 static inline __attribute__ (( always_inline )) struct x509_certificate *
x509_get(struct x509_certificate * cert)236 x509_get ( struct x509_certificate *cert ) {
237 	ref_get ( &cert->refcnt );
238 	return cert;
239 }
240 
241 /**
242  * Drop reference to X.509 certificate
243  *
244  * @v cert		X.509 certificate
245  */
246 static inline __attribute__ (( always_inline )) void
x509_put(struct x509_certificate * cert)247 x509_put ( struct x509_certificate *cert ) {
248 	ref_put ( &cert->refcnt );
249 }
250 
251 /**
252  * Get reference to X.509 certificate chain
253  *
254  * @v chain		X.509 certificate chain
255  * @ret chain		X.509 certificate chain
256  */
257 static inline __attribute__ (( always_inline )) struct x509_chain *
x509_chain_get(struct x509_chain * chain)258 x509_chain_get ( struct x509_chain *chain ) {
259 	ref_get ( &chain->refcnt );
260 	return chain;
261 }
262 
263 /**
264  * Drop reference to X.509 certificate chain
265  *
266  * @v chain		X.509 certificate chain
267  */
268 static inline __attribute__ (( always_inline )) void
x509_chain_put(struct x509_chain * chain)269 x509_chain_put ( struct x509_chain *chain ) {
270 	ref_put ( &chain->refcnt );
271 }
272 
273 /**
274  * Get first certificate in X.509 certificate chain
275  *
276  * @v chain		X.509 certificate chain
277  * @ret cert		X.509 certificate, or NULL
278  */
279 static inline __attribute__ (( always_inline )) struct x509_certificate *
x509_first(struct x509_chain * chain)280 x509_first ( struct x509_chain *chain ) {
281 	struct x509_link *link;
282 
283 	link = list_first_entry ( &chain->links, struct x509_link, list );
284 	return ( link ? link->cert : NULL );
285 }
286 
287 /**
288  * Get last certificate in X.509 certificate chain
289  *
290  * @v chain		X.509 certificate chain
291  * @ret cert		X.509 certificate, or NULL
292  */
293 static inline __attribute__ (( always_inline )) struct x509_certificate *
x509_last(struct x509_chain * chain)294 x509_last ( struct x509_chain *chain ) {
295 	struct x509_link *link;
296 
297 	link = list_last_entry ( &chain->links, struct x509_link, list );
298 	return ( link ? link->cert : NULL );
299 }
300 
301 /** An X.509 extension */
302 struct x509_extension {
303 	/** Name */
304 	const char *name;
305 	/** Object identifier */
306 	struct asn1_cursor oid;
307 	/** Parse extension
308 	 *
309 	 * @v cert		X.509 certificate
310 	 * @v raw		ASN.1 cursor
311 	 * @ret rc		Return status code
312 	 */
313 	int ( * parse ) ( struct x509_certificate *cert,
314 			  const struct asn1_cursor *raw );
315 };
316 
317 /** An X.509 key purpose */
318 struct x509_key_purpose {
319 	/** Name */
320 	const char *name;
321 	/** Object identifier */
322 	struct asn1_cursor oid;
323 	/** Extended key usage bits */
324 	unsigned int bits;
325 };
326 
327 /** An X.509 access method */
328 struct x509_access_method {
329 	/** Name */
330 	const char *name;
331 	/** Object identifier */
332 	struct asn1_cursor oid;
333 	/** Parse access method
334 	 *
335 	 * @v cert		X.509 certificate
336 	 * @v raw		ASN.1 cursor
337 	 * @ret rc		Return status code
338 	 */
339 	int ( * parse ) ( struct x509_certificate *cert,
340 			  const struct asn1_cursor *raw );
341 };
342 
343 /** An X.509 root certificate list */
344 struct x509_root {
345 	/** Reference count */
346 	struct refcnt refcnt;
347 	/** Fingerprint digest algorithm */
348 	struct digest_algorithm *digest;
349 	/** Number of certificates */
350 	unsigned int count;
351 	/** Certificate fingerprints */
352 	const void *fingerprints;
353 };
354 
355 /**
356  * Get reference to X.509 root certificate list
357  *
358  * @v root		X.509 root certificate list
359  * @ret root		X.509 root certificate list
360  */
361 static inline __attribute__ (( always_inline )) struct x509_root *
x509_root_get(struct x509_root * root)362 x509_root_get ( struct x509_root *root ) {
363 	ref_get ( &root->refcnt );
364 	return root;
365 }
366 
367 /**
368  * Drop reference to X.509 root certificate list
369  *
370  * @v root		X.509 root certificate list
371  */
372 static inline __attribute__ (( always_inline )) void
x509_root_put(struct x509_root * root)373 x509_root_put ( struct x509_root *root ) {
374 	ref_put ( &root->refcnt );
375 }
376 
377 extern const char * x509_name ( struct x509_certificate *cert );
378 extern int x509_parse ( struct x509_certificate *cert,
379 			const struct asn1_cursor *raw );
380 extern int x509_certificate ( const void *data, size_t len,
381 			      struct x509_certificate **cert );
382 extern int x509_is_valid ( struct x509_certificate *cert,
383 			   struct x509_root *root );
384 extern int x509_validate ( struct x509_certificate *cert,
385 			   struct x509_certificate *issuer,
386 			   time_t time, struct x509_root *root );
387 extern int x509_check_name ( struct x509_certificate *cert, const char *name );
388 
389 extern struct x509_chain * x509_alloc_chain ( void );
390 extern int x509_append ( struct x509_chain *chain,
391 			 struct x509_certificate *cert );
392 extern int x509_append_raw ( struct x509_chain *chain, const void *data,
393 			     size_t len );
394 extern int x509_auto_append ( struct x509_chain *chain,
395 			      struct x509_chain *certs );
396 extern int x509_validate_chain ( struct x509_chain *chain, time_t time,
397 				 struct x509_chain *store,
398 				 struct x509_root *root );
399 extern int image_x509 ( struct image *image, size_t offset,
400 			struct x509_certificate **cert );
401 
402 /* Functions exposed only for unit testing */
403 extern int x509_check_issuer ( struct x509_certificate *cert,
404 			       struct x509_certificate *issuer );
405 extern void x509_fingerprint ( struct x509_certificate *cert,
406 			       struct digest_algorithm *digest,
407 			       void *fingerprint );
408 extern int x509_check_root ( struct x509_certificate *cert,
409 			     struct x509_root *root );
410 extern int x509_check_time ( struct x509_certificate *cert, time_t time );
411 
412 /**
413  * Invalidate X.509 certificate
414  *
415  * @v cert		X.509 certificate
416  */
x509_invalidate(struct x509_certificate * cert)417 static inline void x509_invalidate ( struct x509_certificate *cert ) {
418 	x509_root_put ( cert->root );
419 	cert->root = NULL;
420 	cert->path_remaining = 0;
421 }
422 
423 /**
424  * Invalidate X.509 certificate chain
425  *
426  * @v chain		X.509 certificate chain
427  */
x509_invalidate_chain(struct x509_chain * chain)428 static inline void x509_invalidate_chain ( struct x509_chain *chain ) {
429 	struct x509_link *link;
430 
431 	list_for_each_entry ( link, &chain->links, list )
432 		x509_invalidate ( link->cert );
433 }
434 
435 #endif /* _IPXE_X509_H */
436