iPXE
imgtrust.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 #include <stdlib.h>
00027 #include <errno.h>
00028 #include <time.h>
00029 #include <syslog.h>
00030 #include <ipxe/uaccess.h>
00031 #include <ipxe/image.h>
00032 #include <ipxe/cms.h>
00033 #include <ipxe/validator.h>
00034 #include <ipxe/monojob.h>
00035 #include <usr/imgtrust.h>
00036 
00037 /** @file
00038  *
00039  * Image trust management
00040  *
00041  */
00042 
00043 /**
00044  * Verify image using downloaded signature
00045  *
00046  * @v image             Image to verify
00047  * @v signature         Image containing signature
00048  * @v name              Required common name, or NULL to allow any name
00049  * @ret rc              Return status code
00050  */
00051 int imgverify ( struct image *image, struct image *signature,
00052                 const char *name ) {
00053         struct asn1_cursor *data;
00054         struct cms_signature *sig;
00055         struct cms_signer_info *info;
00056         time_t now;
00057         int next;
00058         int rc;
00059 
00060         /* Mark image as untrusted */
00061         image_untrust ( image );
00062 
00063         /* Get raw signature data */
00064         next = image_asn1 ( signature, 0, &data );
00065         if ( next < 0 ) {
00066                 rc = next;
00067                 goto err_asn1;
00068         }
00069 
00070         /* Parse signature */
00071         if ( ( rc = cms_signature ( data->data, data->len, &sig ) ) != 0 )
00072                 goto err_parse;
00073 
00074         /* Free raw signature data */
00075         free ( data );
00076         data = NULL;
00077 
00078         /* Complete all certificate chains */
00079         list_for_each_entry ( info, &sig->info, list ) {
00080                 if ( ( rc = create_validator ( &monojob, info->chain ) ) != 0 )
00081                         goto err_create_validator;
00082                 if ( ( rc = monojob_wait ( NULL, 0 ) ) != 0 )
00083                         goto err_validator_wait;
00084         }
00085 
00086         /* Use signature to verify image */
00087         now = time ( NULL );
00088         if ( ( rc = cms_verify ( sig, image->data, image->len,
00089                                  name, now, NULL, NULL ) ) != 0 )
00090                 goto err_verify;
00091 
00092         /* Drop reference to signature */
00093         cms_put ( sig );
00094         sig = NULL;
00095 
00096         /* Mark image as trusted */
00097         image_trust ( image );
00098         syslog ( LOG_NOTICE, "Image \"%s\" signature OK\n", image->name );
00099 
00100         return 0;
00101 
00102  err_verify:
00103  err_validator_wait:
00104  err_create_validator:
00105         cms_put ( sig );
00106  err_parse:
00107         free ( data );
00108  err_asn1:
00109         syslog ( LOG_ERR, "Image \"%s\" signature bad: %s\n",
00110                  image->name, strerror ( rc ) );
00111         return rc;
00112 }