Browse Source

[tls] Add full X.509 certificate parsing

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
4d3b5473f8
5 changed files with 1443 additions and 38 deletions
  1. 50
    0
      src/crypto/rootcert.c
  2. 1156
    23
      src/crypto/x509.c
  3. 16
    0
      src/include/ipxe/rootcert.h
  4. 209
    5
      src/include/ipxe/x509.h
  5. 12
    10
      src/net/tls.c

+ 50
- 0
src/crypto/rootcert.c View File

@@ -0,0 +1,50 @@
1
+/*
2
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+FILE_LICENCE ( GPL2_OR_LATER );
20
+
21
+#include <ipxe/crypto.h>
22
+#include <ipxe/sha256.h>
23
+#include <ipxe/x509.h>
24
+#include <ipxe/rootcert.h>
25
+
26
+/** @file
27
+ *
28
+ * Root certificate store
29
+ *
30
+ */
31
+
32
+/* Use iPXE root CA if no trusted certificates are explicitly specified */
33
+#ifndef TRUSTED
34
+#define TRUSTED								\
35
+	/* iPXE root CA */						\
36
+	0x9f, 0xaf, 0x71, 0x7b, 0x7f, 0x8c, 0xa2, 0xf9, 0x3c, 0x25,	\
37
+	0x6c, 0x79, 0xf8, 0xac, 0x55, 0x91, 0x89, 0x5d, 0x66, 0xd1,	\
38
+	0xff, 0x3b, 0xee, 0x63, 0x97, 0xa7, 0x0d, 0x29, 0xc6, 0x5e,	\
39
+	0xed, 0x1a,
40
+#endif
41
+
42
+/** Root certificate fingerprints */
43
+static const uint8_t fingerprints[] = { TRUSTED };
44
+
45
+/** Root certificates */
46
+struct x509_root root_certificates = {
47
+	.digest = &sha256_algorithm,
48
+	.count = ( sizeof ( fingerprints ) / SHA256_DIGEST_SIZE ),
49
+	.fingerprints = fingerprints,
50
+};

+ 1156
- 23
src/crypto/x509.c
File diff suppressed because it is too large
View File


+ 16
- 0
src/include/ipxe/rootcert.h View File

@@ -0,0 +1,16 @@
1
+#ifndef _IPXE_ROOTCERT_H
2
+#define _IPXE_ROOTCERT_H
3
+
4
+/** @file
5
+ *
6
+ * Root certificate store
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER );
11
+
12
+#include <ipxe/x509.h>
13
+
14
+extern struct x509_root root_certificates;
15
+
16
+#endif /* _IPXE_ROOTCERT_H */

+ 209
- 5
src/include/ipxe/x509.h View File

@@ -10,16 +10,220 @@
10 10
 FILE_LICENCE ( GPL2_OR_LATER );
11 11
 
12 12
 #include <stdint.h>
13
-#include <stdlib.h>
13
+#include <stddef.h>
14 14
 #include <ipxe/asn1.h>
15 15
 
16
-/** An X.509 RSA public key */
17
-struct x509_rsa_public_key {
16
+/** ASN.1 OID for joint-iso-itu-t(2) ds(5) attributeType(4) */
17
+#define ASN1_OID_ATTRIBUTE_TYPE \
18
+	ASN1_OID_DIRECTORY_SERVICES, ASN1_OID_SINGLE ( 4 )
19
+
20
+/** ASN.1 OID for joint-iso-itu-t(2) ds(5) attributeType(4) commonName(3) */
21
+#define ASN1_OID_COMMON_NAME ASN1_OID_ATTRIBUTE_TYPE, ASN1_OID_SINGLE ( 3 )
22
+
23
+/** ASN.1 OID for id-ce */
24
+#define ASN1_OID_CE ASN1_OID_DIRECTORY_SERVICES, ASN1_OID_SINGLE ( 29 )
25
+
26
+/** ASN.1 OID for id-ce-keyUsage */
27
+#define ASN1_OID_KEYUSAGE ASN1_OID_CE, ASN1_OID_SINGLE ( 15 )
28
+
29
+/** ASN.1 OID for id-ce-basicConstraints */
30
+#define ASN1_OID_BASICCONSTRAINTS ASN1_OID_CE, ASN1_OID_SINGLE ( 19 )
31
+
32
+/** An X.509 algorithm */
33
+struct x509_algorithm {
34
+	/** Name */
35
+	const char *name;
36
+	/** Object identifier */
37
+	struct asn1_cursor oid;
38
+	/** Public-key algorithm */
39
+	struct pubkey_algorithm *pubkey;
40
+	/** Digest algorithm (if applicable) */
41
+	struct digest_algorithm *digest;
42
+};
43
+
44
+/**
45
+ * Test if X.509 algorithm is a signature algorithm
46
+ *
47
+ * @v algorithm		Algorithm
48
+ * @ret is_signature	Algorithm is a signature algorithm
49
+ */
50
+static inline __attribute__ (( always_inline )) int
51
+x509_is_signature_algorithm ( struct x509_algorithm *algorithm ) {
52
+	return ( algorithm->digest != NULL );
53
+}
54
+
55
+/** An X.509 bit string */
56
+struct x509_bit_string {
57
+	/** Data */
58
+	const void *data;
59
+	/** Length */
60
+	size_t len;
61
+	/** Unused bits at end of data */
62
+	unsigned int unused;
63
+};
64
+
65
+/** An X.509 issuer */
66
+struct x509_issuer {
67
+	/** Raw issuer */
68
+	struct asn1_cursor raw;
69
+};
70
+
71
+/** An X.509 time */
72
+struct x509_time {
73
+	/** Year */
74
+	uint16_t year;
75
+	/** Month */
76
+	uint8_t month;
77
+	/** Day */
78
+	uint8_t day;
79
+	/** Hour */
80
+	uint8_t hour;
81
+	/** Minute */
82
+	uint8_t minute;
83
+	/** Second */
84
+	uint8_t second;
85
+};
86
+
87
+/** An X.509 certificate validity period */
88
+struct x509_validity {
89
+	/** Not valid before */
90
+	struct x509_time not_before;
91
+	/** Not valid after */
92
+	struct x509_time not_after;
93
+};
94
+
95
+/** An X.509 name */
96
+struct x509_name {
97
+	/** Name (not NUL-terminated) */
98
+	const void *data;
99
+	/** Length of name */
100
+	size_t len;
101
+};
102
+
103
+/** An X.509 certificate public key */
104
+struct x509_public_key {
18 105
 	/** Raw public key */
19 106
 	struct asn1_cursor raw;
107
+	/** Public key algorithm */
108
+	struct x509_algorithm *algorithm;
109
+};
110
+
111
+/** An X.509 certificate subject */
112
+struct x509_subject {
113
+	/** Raw subject */
114
+	struct asn1_cursor raw;
115
+	/** Common name */
116
+	struct x509_name name;
117
+	/** Public key information */
118
+	struct x509_public_key public_key;
119
+};
120
+
121
+/** An X.509 certificate signature */
122
+struct x509_signature {
123
+	/** Signature algorithm */
124
+	struct x509_algorithm *algorithm;
125
+	/** Signature value */
126
+	struct x509_bit_string value;
127
+};
128
+
129
+/** An X.509 certificate basic constraints set */
130
+struct x509_basic_constraints {
131
+	/** Subject is a CA */
132
+	int ca;
133
+	/** Path length */
134
+	unsigned int path_len;
135
+};
136
+
137
+/** An X.509 certificate key usage */
138
+struct x509_key_usage {
139
+	/** Key usage extension is present */
140
+	int present;
141
+	/** Usage bits */
142
+	unsigned int bits;
143
+};
144
+
145
+/** X.509 certificate key usage bits */
146
+enum x509_key_usage_bits {
147
+	X509_DIGITAL_SIGNATURE = 0x0080,
148
+	X509_NON_REPUDIATION = 0x0040,
149
+	X509_KEY_ENCIPHERMENT = 0x0020,
150
+	X509_DATA_ENCIPHERMENT = 0x0010,
151
+	X509_KEY_AGREEMENT = 0x0008,
152
+	X509_KEY_CERT_SIGN = 0x0004,
153
+	X509_CRL_SIGN = 0x0002,
154
+	X509_ENCIPHER_ONLY = 0x0001,
155
+	X509_DECIPHER_ONLY = 0x8000,
156
+};
157
+
158
+/** An X.509 certificate extensions set */
159
+struct x509_extensions {
160
+	/** Basic constraints */
161
+	struct x509_basic_constraints basic;
162
+	/** Key usage */
163
+	struct x509_key_usage usage;
164
+};
165
+
166
+/** An X.509 certificate */
167
+struct x509_certificate {
168
+	/** Raw certificate */
169
+	struct asn1_cursor raw;
170
+	/** Version */
171
+	unsigned int version;
172
+	/** Raw tbsCertificate */
173
+	struct asn1_cursor tbs;
174
+	/** Signature algorithm */
175
+	struct x509_algorithm *signature_algorithm;
176
+	/** Issuer */
177
+	struct x509_issuer issuer;
178
+	/** Validity */
179
+	struct x509_validity validity;
180
+	/** Subject */
181
+	struct x509_subject subject;
182
+	/** Signature */
183
+	struct x509_signature signature;
184
+	/** Extensions */
185
+	struct x509_extensions extensions;
186
+};
187
+
188
+/** An X.509 extension */
189
+struct x509_extension {
190
+	/** Name */
191
+	const char *name;
192
+	/** Object identifier */
193
+	struct asn1_cursor oid;
194
+	/** Parse extension
195
+	 *
196
+	 * @v cert		X.509 certificate
197
+	 * @v raw		ASN.1 cursor
198
+	 * @ret rc		Return status code
199
+	 */
200
+	int ( * parse ) ( struct x509_certificate *cert,
201
+			  const struct asn1_cursor *raw );
202
+};
203
+
204
+/** An X.509 root certificate store */
205
+struct x509_root {
206
+	/** Fingerprint digest algorithm */
207
+	struct digest_algorithm *digest;
208
+	/** Number of certificates */
209
+	unsigned int count;
210
+	/** Certificate fingerprints */
211
+	const void *fingerprints;
20 212
 };
21 213
 
22
-extern int x509_rsa_public_key ( const struct asn1_cursor *certificate,
23
-				 struct x509_rsa_public_key *rsa_pubkey );
214
+extern int x509_parse ( struct x509_certificate *cert,
215
+			const void *data, size_t len );
216
+extern int x509_validate ( struct x509_certificate *cert,
217
+			   struct x509_certificate *issuer );
218
+extern void x509_fingerprint ( struct x509_certificate *cert,
219
+			       struct digest_algorithm *digest,
220
+			       void *fingerprint );
221
+extern int x509_validate_root ( struct x509_certificate *cert,
222
+				struct x509_root *root );
223
+extern int x509_validate_chain ( int ( * parse_next )
224
+				 ( struct x509_certificate *cert,
225
+				   void *context ),
226
+				 void *context, struct x509_root *root,
227
+				 struct x509_certificate *first );
24 228
 
25 229
 #endif /* _IPXE_X509_H */

+ 12
- 10
src/net/tls.c View File

@@ -1026,8 +1026,10 @@ static int tls_new_certificate ( struct tls_session *tls,
1026 1026
 	const void *end = ( certificate->certificates + elements_len );
1027 1027
 	struct tls_cipherspec *cipherspec = &tls->tx_cipherspec_pending;
1028 1028
 	struct pubkey_algorithm *pubkey = cipherspec->suite->pubkey;
1029
-	struct asn1_cursor cursor;
1030
-	struct x509_rsa_public_key key;
1029
+	struct x509_certificate cert;
1030
+	struct x509_public_key *key = &cert.subject.public_key;
1031
+	const void *cert_data;
1032
+	size_t cert_len;
1031 1033
 	int rc;
1032 1034
 
1033 1035
 	/* Sanity check */
@@ -1040,9 +1042,9 @@ static int tls_new_certificate ( struct tls_session *tls,
1040 1042
 
1041 1043
 	/* Traverse certificate chain */
1042 1044
 	do {
1043
-		cursor.data = element->certificate;
1044
-		cursor.len = tls_uint24 ( element->length );
1045
-		if ( ( cursor.data + cursor.len ) > end ) {
1045
+		cert_data = element->certificate;
1046
+		cert_len = tls_uint24 ( element->length );
1047
+		if ( ( cert_data + cert_len ) > end ) {
1046 1048
 			DBGC ( tls, "TLS %p received corrupt Server "
1047 1049
 			       "Certificate\n", tls );
1048 1050
 			DBGC_HD ( tls, data, len );
@@ -1050,23 +1052,23 @@ static int tls_new_certificate ( struct tls_session *tls,
1050 1052
 		}
1051 1053
 
1052 1054
 		// HACK
1053
-		if ( ( rc = x509_rsa_public_key ( &cursor, &key ) ) != 0 ) {
1054
-			DBGC ( tls, "TLS %p cannot parse public key: %s\n",
1055
+
1056
+		/* Parse certificate */
1057
+		if ( ( rc = x509_parse ( &cert, cert_data, cert_len ) ) != 0 ) {
1058
+			DBGC ( tls, "TLS %p cannot parse certificate: %s\n",
1055 1059
 			       tls, strerror ( rc ) );
1056 1060
 			return rc;
1057 1061
 		}
1058 1062
 
1059 1063
 		/* Initialise public key algorithm */
1060 1064
 		if ( ( rc = pubkey_init ( pubkey, cipherspec->pubkey_ctx,
1061
-					  key.raw.data, key.raw.len ) ) != 0){
1065
+					  key->raw.data, key->raw.len ) ) != 0){
1062 1066
 			DBGC ( tls, "TLS %p cannot initialise public key: %s\n",
1063 1067
 			       tls, strerror ( rc ) );
1064 1068
 			return rc;
1065 1069
 		}
1066 1070
 
1067 1071
 		return 0;
1068
-
1069
-		element = ( cursor.data + cursor.len );
1070 1072
 	} while ( element != end );
1071 1073
 
1072 1074
 	return -EINVAL;

Loading…
Cancel
Save