Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / crypto / certstore.c
1 /*
2  * Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  */
19
20 FILE_LICENCE ( GPL2_OR_LATER );
21
22 #include <string.h>
23 #include <stdlib.h>
24 #include <ipxe/init.h>
25 #include <ipxe/dhcp.h>
26 #include <ipxe/settings.h>
27 #include <ipxe/malloc.h>
28 #include <ipxe/crypto.h>
29 #include <ipxe/asn1.h>
30 #include <ipxe/x509.h>
31 #include <ipxe/certstore.h>
32
33 /** @file
34  *
35  * Certificate store
36  *
37  */
38
39 /** Raw certificate data for all permanent stored certificates */
40 #undef CERT
41 #define CERT( _index, _path )                                           \
42         extern char stored_cert_ ## _index ## _data[];                  \
43         extern char stored_cert_ ## _index ## _len[];                   \
44         __asm__ ( ".section \".rodata\", \"a\", @progbits\n\t"          \
45                   "\nstored_cert_" #_index "_data:\n\t"                 \
46                   ".incbin \"" _path "\"\n\t"                           \
47                   "\nstored_cert_" #_index "_end:\n\t"                  \
48                   ".equ stored_cert_" #_index "_len, "                  \
49                         "( stored_cert_" #_index "_end - "              \
50                         "  stored_cert_" #_index "_data )\n\t"          \
51                   ".previous\n\t" );
52 CERT_ALL
53
54 /** Raw certificate cursors for all permanent stored certificates */
55 #undef CERT
56 #define CERT( _index, _path ) {                                         \
57         .data = stored_cert_ ## _index ## _data,                        \
58         .len = ( size_t ) stored_cert_ ## _index ## _len,               \
59 },
60 static struct asn1_cursor certstore_raw[] = {
61         CERT_ALL
62 };
63
64 /** X.509 certificate structures for all permanent stored certificates */
65 static struct x509_certificate certstore_certs[ sizeof ( certstore_raw ) /
66                                                 sizeof ( certstore_raw[0] ) ];
67
68 /** Certificate store */
69 struct x509_chain certstore = {
70         .refcnt = REF_INIT ( ref_no_free ),
71         .links = LIST_HEAD_INIT ( certstore.links ),
72 };
73
74 /**
75  * Mark stored certificate as most recently used
76  *
77  * @v cert              X.509 certificate
78  * @ret cert            X.509 certificate
79  */
80 static struct x509_certificate *
81 certstore_found ( struct x509_certificate *cert ) {
82
83         /* Mark as most recently used */
84         list_del ( &cert->store.list );
85         list_add ( &cert->store.list, &certstore.links );
86         DBGC2 ( &certstore, "CERTSTORE found certificate %s\n",
87                 x509_name ( cert ) );
88
89         return cert;
90 }
91
92 /**
93  * Find certificate in store
94  *
95  * @v raw               Raw certificate data
96  * @ret cert            X.509 certificate, or NULL if not found
97  */
98 struct x509_certificate * certstore_find ( struct asn1_cursor *raw ) {
99         struct x509_certificate *cert;
100
101         /* Search for certificate within store */
102         list_for_each_entry ( cert, &certstore.links, store.list ) {
103                 if ( asn1_compare ( raw, &cert->raw ) == 0 )
104                         return certstore_found ( cert );
105         }
106         return NULL;
107 }
108
109 /**
110  * Find certificate in store corresponding to a private key
111  *
112  * @v key               Private key
113  * @ret cert            X.509 certificate, or NULL if not found
114  */
115 struct x509_certificate * certstore_find_key ( struct asn1_cursor *key ) {
116         struct x509_certificate *cert;
117
118         /* Search for certificate within store */
119         list_for_each_entry ( cert, &certstore.links, store.list ) {
120                 if ( pubkey_match ( cert->signature_algorithm->pubkey,
121                                     key->data, key->len,
122                                     cert->subject.public_key.raw.data,
123                                     cert->subject.public_key.raw.len ) == 0 )
124                         return certstore_found ( cert );
125         }
126         return NULL;
127 }
128
129 /**
130  * Add certificate to store
131  *
132  * @v cert              X.509 certificate
133  */
134 void certstore_add ( struct x509_certificate *cert ) {
135
136         /* Add certificate to store */
137         cert->store.cert = cert;
138         x509_get ( cert );
139         list_add ( &cert->store.list, &certstore.links );
140         DBGC ( &certstore, "CERTSTORE added certificate %s\n",
141                x509_name ( cert ) );
142 }
143
144 /**
145  * Discard a stored certificate
146  *
147  * @ret discarded       Number of cached items discarded
148  */
149 static unsigned int certstore_discard ( void ) {
150         struct x509_certificate *cert;
151
152         /* Discard the least recently used certificate for which the
153          * only reference is held by the store itself.
154          */
155         list_for_each_entry_reverse ( cert, &certstore.links, store.list ) {
156                 if ( cert->refcnt.count == 0 ) {
157                         DBGC ( &certstore, "CERTSTORE discarded certificate "
158                                "%s\n", x509_name ( cert ) );
159                         list_del ( &cert->store.list );
160                         x509_put ( cert );
161                         return 1;
162                 }
163         }
164         return 0;
165 }
166
167 /** Certificate store cache discarder */
168 struct cache_discarder certstore_discarder __cache_discarder ( CACHE_NORMAL ) ={
169         .discard = certstore_discard,
170 };
171
172 /**
173  * Construct permanent certificate store
174  *
175  */
176 static void certstore_init ( void ) {
177         struct asn1_cursor *raw;
178         struct x509_certificate *cert;
179         int i;
180         int rc;
181
182         /* Skip if we have no permanent stored certificates */
183         if ( ! sizeof ( certstore_raw ) )
184                 return;
185
186         /* Add certificates */
187         for ( i = 0 ; i < ( int ) ( sizeof ( certstore_raw ) /
188                                     sizeof ( certstore_raw[0] ) ) ; i++ ) {
189
190                 /* Skip if certificate already present in store */
191                 raw = &certstore_raw[i];
192                 if ( ( cert = certstore_find ( raw ) ) != NULL ) {
193                         DBGC ( &certstore, "CERTSTORE permanent certificate %d "
194                                "is a duplicate of %s\n", i, x509_name ( cert ));
195                         continue;
196                 }
197
198                 /* Parse certificate */
199                 cert = &certstore_certs[i];
200                 ref_init ( &cert->refcnt, ref_no_free );
201                 if ( ( rc = x509_parse ( cert, raw ) ) != 0 ) {
202                         DBGC ( &certstore, "CERTSTORE could not parse "
203                                "permanent certificate %d: %s\n",
204                                i, strerror ( rc ) );
205                         continue;
206                 }
207
208                 /* Add certificate to store.  Certificate will never
209                  * be discarded from the store, since we retain a
210                  * permanent reference to it.
211                  */
212                 certstore_add ( cert );
213                 DBGC ( &certstore, "CERTSTORE permanent certificate %d is %s\n",
214                        i, x509_name ( cert ) );
215         }
216 }
217
218 /** Certificate store initialisation function */
219 struct init_fn certstore_init_fn __init_fn ( INIT_LATE ) = {
220         .initialise = certstore_init,
221 };
222
223 /** Additional certificate setting */
224 static struct setting cert_setting __setting ( SETTING_CRYPTO, cert ) = {
225         .name = "cert",
226         .description = "Certificate",
227         .tag = DHCP_EB_CERT,
228         .type = &setting_type_hex,
229 };
230
231 /**
232  * Apply certificate store configuration settings
233  *
234  * @ret rc              Return status code
235  */
236 static int certstore_apply_settings ( void ) {
237         static struct x509_certificate *cert = NULL;
238         struct x509_certificate *old_cert;
239         void *cert_data;
240         int len;
241         int rc;
242
243         /* Record any existing additional certificate */
244         old_cert = cert;
245         cert = NULL;
246
247         /* Add additional certificate, if any */
248         if ( ( len = fetch_raw_setting_copy ( NULL, &cert_setting,
249                                               &cert_data ) ) >= 0 ) {
250                 if ( ( rc = x509_certificate ( cert_data, len, &cert ) ) == 0 ){
251                         DBGC ( &certstore, "CERTSTORE added additional "
252                                "certificate %s\n", x509_name ( cert ) );
253                 } else {
254                         DBGC ( &certstore, "CERTSTORE could not parse "
255                                "additional certificate: %s\n",
256                                strerror ( rc ) );
257                         /* Do not fail; leave as an unusable certificate */
258                 }
259                 free ( cert_data );
260         }
261
262         /* Free old additional certificiate.  Do this after reparsing
263          * the additional certificate; in the common case that the
264          * certificate has not changed, this will allow the stored
265          * certificate to be reused.
266          */
267         x509_put ( old_cert );
268
269         return 0;
270 }
271
272 /** Certificate store settings applicator */
273 struct settings_applicator certstore_applicator __settings_applicator = {
274         .apply = certstore_apply_settings,
275 };