asn1.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007 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., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020 
00021 #include <stdint.h>
00022 #include <stddef.h>
00023 #include <errno.h>
00024 #include <gpxe/asn1.h>
00025 
00026 /** @file
00027  *
00028  * ASN.1 encoding
00029  *
00030  */
00031 
00032 /**
00033  * Start parsing ASN.1 object
00034  *
00035  * @v cursor            ASN.1 object cursor
00036  * @v type              Expected type
00037  * @ret len             Length of object body, or negative error
00038  *
00039  * The object cursor will be updated to point to the start of the
00040  * object body (i.e. the first byte following the length byte(s)), and
00041  * the length of the object body (i.e. the number of bytes until the
00042  * following object tag, if any) is returned.
00043  *
00044  * If any error occurs (i.e. if the object is not of the expected
00045  * type, or if we overflow beyond the end of the ASN.1 object), then
00046  * the cursor will be invalidated and a negative value will be
00047  * returned.
00048  */
00049 static int asn1_start ( struct asn1_cursor *cursor,
00050                                unsigned int type ) {
00051         unsigned int len_len;
00052         unsigned int len;
00053         int rc;
00054 
00055         /* Sanity check */
00056         if ( cursor->len < 2 /* Tag byte and first length byte */ ) {
00057                 if ( cursor->len )
00058                         DBGC ( cursor, "ASN1 %p too short\n", cursor );
00059                 rc = -EINVAL;
00060                 goto notfound;
00061         }
00062 
00063         /* Check the tag byte */
00064         if ( *( ( uint8_t * ) cursor->data ) != type ) {
00065                 DBGC ( cursor, "ASN1 %p type mismatch (expected %d, got %d)\n",
00066                        cursor, type, *( ( uint8_t * ) cursor->data ) );
00067                 rc = -ENXIO;
00068                 goto notfound;
00069         }
00070         cursor->data++;
00071         cursor->len--;
00072 
00073         /* Extract length of the length field and sanity check */
00074         len_len = *( ( uint8_t * ) cursor->data );
00075         if ( len_len & 0x80 ) {
00076                 len_len = ( len_len & 0x7f );
00077                 cursor->data++;
00078                 cursor->len--;
00079         } else {
00080                 len_len = 1;
00081         }
00082         if ( cursor->len < len_len ) {
00083                 DBGC ( cursor, "ASN1 %p bad length field length %d (max "
00084                        "%zd)\n", cursor, len_len, cursor->len );
00085                 rc = -EINVAL;
00086                 goto notfound;
00087         }
00088 
00089         /* Extract the length and sanity check */
00090         for ( len = 0 ; len_len ; len_len-- ) {
00091                 len <<= 8;
00092                 len |= *( ( uint8_t * ) cursor->data );
00093                 cursor->data++;
00094                 cursor->len--;
00095         }
00096         if ( cursor->len < len ) {
00097                 DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n",
00098                        cursor, len, cursor->len );
00099                 rc = -EINVAL;
00100                 goto notfound;
00101         }
00102 
00103         return len;
00104 
00105  notfound:
00106         cursor->data = NULL;
00107         cursor->len = 0;
00108         return rc;
00109 }
00110 
00111 /**
00112  * Enter ASN.1 object
00113  *
00114  * @v cursor            ASN.1 object cursor
00115  * @v type              Expected type
00116  * @ret rc              Return status code
00117  *
00118  * The object cursor will be updated to point to the body of the
00119  * current ASN.1 object.  If any error occurs, the object cursor will
00120  * be invalidated.
00121  */
00122 int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
00123         int len;
00124 
00125         len = asn1_start ( cursor, type );
00126         if ( len < 0 )
00127                 return len;
00128 
00129         cursor->len = len;
00130         DBGC ( cursor, "ASN1 %p entered object type %02x (len %x)\n",
00131                cursor, type, len );
00132 
00133         return 0;
00134 }
00135 
00136 /**
00137  * Skip ASN.1 object
00138  *
00139  * @v cursor            ASN.1 object cursor
00140  * @v type              Expected type
00141  * @ret rc              Return status code
00142  *
00143  * The object cursor will be updated to point to the next ASN.1
00144  * object.  If any error occurs, the object cursor will be
00145  * invalidated.
00146  */
00147 int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
00148         int len;
00149 
00150         len = asn1_start ( cursor, type );
00151         if ( len < 0 )
00152                 return len;
00153 
00154         cursor->data += len;
00155         cursor->len -= len;
00156         DBGC ( cursor, "ASN1 %p skipped object type %02x (len %x)\n",
00157                cursor, type, len );
00158 
00159         if ( ! cursor->len ) {
00160                 DBGC ( cursor, "ASN1 %p reached end of object\n", cursor );
00161                 cursor->data = NULL;
00162                 return -ENOENT;
00163         }
00164 
00165         return 0;
00166 }

Generated on Tue Apr 6 20:00:52 2010 for gPXE by  doxygen 1.5.7.1