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