iPXE
der.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2016 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 <assert.h>
00029 #include <ipxe/asn1.h>
00030 #include <ipxe/der.h>
00031 #include <ipxe/uaccess.h>
00032 #include <ipxe/image.h>
00033 
00034 /** @file
00035  *
00036  * DER-encoded ASN.1 data
00037  *
00038  */
00039 
00040 /**
00041  * Extract ASN.1 object from image
00042  *
00043  * @v image             DER image
00044  * @v offset            Offset within image
00045  * @v cursor            ASN.1 cursor to fill in
00046  * @ret next            Offset to next image, or negative error
00047  *
00048  * The caller is responsible for eventually calling free() on the
00049  * allocated ASN.1 cursor.
00050  */
00051 static int der_asn1 ( struct image *image, size_t offset __unused,
00052                       struct asn1_cursor **cursor ) {
00053         void *data;
00054 
00055         /* Allocate cursor and data buffer */
00056         *cursor = malloc ( sizeof ( **cursor ) + image->len );
00057         if ( ! *cursor )
00058                 return -ENOMEM;
00059         data = ( ( ( void * ) *cursor ) + sizeof ( **cursor ) );
00060 
00061         /* Populate cursor and data buffer */
00062         (*cursor)->data = data;
00063         (*cursor)->len = image->len;
00064         copy_from_user ( data, image->data, 0, image->len );
00065 
00066         return image->len;
00067 }
00068 
00069 /**
00070  * Probe DER image
00071  *
00072  * @v image             DER image
00073  * @ret rc              Return status code
00074  */
00075 static int der_probe ( struct image *image ) {
00076         struct asn1_cursor cursor;
00077         uint8_t buf[8];
00078         size_t extra;
00079         size_t total;
00080         int len;
00081         int rc;
00082 
00083         /* Sanity check: no realistic DER image can be smaller than this */
00084         if ( image->len < sizeof ( buf ) )
00085                 return -ENOEXEC;
00086 
00087         /* Prepare partial cursor */
00088         cursor.data = buf;
00089         cursor.len = sizeof ( buf );
00090         copy_from_user ( buf, image->data, 0, sizeof ( buf ) );
00091         extra = ( image->len - sizeof ( buf ) );
00092 
00093         /* Get length of ASN.1 sequence */
00094         len = asn1_start ( &cursor, ASN1_SEQUENCE, extra );
00095         if ( len < 0 ) {
00096                 rc = len;
00097                 DBGC ( image, "DER %s is not valid ASN.1: %s\n",
00098                        image->name, strerror ( rc ) );
00099                 return rc;
00100         }
00101 
00102         /* Add length of tag and length bytes consumed by asn1_start() */
00103         total = ( len + ( cursor.data - ( ( void * ) buf ) ) );
00104         assert ( total <= image->len );
00105 
00106         /* Check that image comprises a single well-formed ASN.1 object */
00107         if ( total != image->len ) {
00108                 DBGC ( image, "DER %s is not single ASN.1\n", image->name );
00109                 return -ENOEXEC;
00110         }
00111 
00112         return 0;
00113 }
00114 
00115 /** DER image type */
00116 struct image_type der_image_type __image_type ( PROBE_NORMAL ) = {
00117         .name = "DER",
00118         .probe = der_probe,
00119         .asn1 = der_asn1,
00120 };