|
|
1.1 ! root 1: /* ! 2: * Copyright (C) 2007 Michael Brown <[email protected]>. ! 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., 675 Mass Ave, Cambridge, MA 02139, USA. ! 17: */ ! 18: ! 19: FILE_LICENCE ( GPL2_OR_LATER ); ! 20: ! 21: #include <stdint.h> ! 22: #include <stddef.h> ! 23: #include <errno.h> ! 24: #include <ipxe/asn1.h> ! 25: ! 26: /** @file ! 27: * ! 28: * ASN.1 encoding ! 29: * ! 30: */ ! 31: ! 32: /** ! 33: * Start parsing ASN.1 object ! 34: * ! 35: * @v cursor ASN.1 object cursor ! 36: * @v type Expected type ! 37: * @ret len Length of object body, or negative error ! 38: * ! 39: * The object cursor will be updated to point to the start of the ! 40: * object body (i.e. the first byte following the length byte(s)), and ! 41: * the length of the object body (i.e. the number of bytes until the ! 42: * following object tag, if any) is returned. ! 43: * ! 44: * If any error occurs (i.e. if the object is not of the expected ! 45: * type, or if we overflow beyond the end of the ASN.1 object), then ! 46: * the cursor will be invalidated and a negative value will be ! 47: * returned. ! 48: */ ! 49: static int asn1_start ( struct asn1_cursor *cursor, ! 50: unsigned int type ) { ! 51: unsigned int len_len; ! 52: unsigned int len; ! 53: int rc; ! 54: ! 55: /* Sanity check */ ! 56: if ( cursor->len < 2 /* Tag byte and first length byte */ ) { ! 57: if ( cursor->len ) ! 58: DBGC ( cursor, "ASN1 %p too short\n", cursor ); ! 59: rc = -EINVAL; ! 60: goto notfound; ! 61: } ! 62: ! 63: /* Check the tag byte */ ! 64: if ( *( ( uint8_t * ) cursor->data ) != type ) { ! 65: DBGC ( cursor, "ASN1 %p type mismatch (expected %d, got %d)\n", ! 66: cursor, type, *( ( uint8_t * ) cursor->data ) ); ! 67: rc = -ENXIO; ! 68: goto notfound; ! 69: } ! 70: cursor->data++; ! 71: cursor->len--; ! 72: ! 73: /* Extract length of the length field and sanity check */ ! 74: len_len = *( ( uint8_t * ) cursor->data ); ! 75: if ( len_len & 0x80 ) { ! 76: len_len = ( len_len & 0x7f ); ! 77: cursor->data++; ! 78: cursor->len--; ! 79: } else { ! 80: len_len = 1; ! 81: } ! 82: if ( cursor->len < len_len ) { ! 83: DBGC ( cursor, "ASN1 %p bad length field length %d (max " ! 84: "%zd)\n", cursor, len_len, cursor->len ); ! 85: rc = -EINVAL; ! 86: goto notfound; ! 87: } ! 88: ! 89: /* Extract the length and sanity check */ ! 90: for ( len = 0 ; len_len ; len_len-- ) { ! 91: len <<= 8; ! 92: len |= *( ( uint8_t * ) cursor->data ); ! 93: cursor->data++; ! 94: cursor->len--; ! 95: } ! 96: if ( cursor->len < len ) { ! 97: DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n", ! 98: cursor, len, cursor->len ); ! 99: rc = -EINVAL; ! 100: goto notfound; ! 101: } ! 102: ! 103: return len; ! 104: ! 105: notfound: ! 106: cursor->data = NULL; ! 107: cursor->len = 0; ! 108: return rc; ! 109: } ! 110: ! 111: /** ! 112: * Enter ASN.1 object ! 113: * ! 114: * @v cursor ASN.1 object cursor ! 115: * @v type Expected type ! 116: * @ret rc Return status code ! 117: * ! 118: * The object cursor will be updated to point to the body of the ! 119: * current ASN.1 object. If any error occurs, the object cursor will ! 120: * be invalidated. ! 121: */ ! 122: int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) { ! 123: int len; ! 124: ! 125: len = asn1_start ( cursor, type ); ! 126: if ( len < 0 ) ! 127: return len; ! 128: ! 129: cursor->len = len; ! 130: DBGC ( cursor, "ASN1 %p entered object type %02x (len %x)\n", ! 131: cursor, type, len ); ! 132: ! 133: return 0; ! 134: } ! 135: ! 136: /** ! 137: * Skip ASN.1 object ! 138: * ! 139: * @v cursor ASN.1 object cursor ! 140: * @v type Expected type ! 141: * @ret rc Return status code ! 142: * ! 143: * The object cursor will be updated to point to the next ASN.1 ! 144: * object. If any error occurs, the object cursor will be ! 145: * invalidated. ! 146: */ ! 147: int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) { ! 148: int len; ! 149: ! 150: len = asn1_start ( cursor, type ); ! 151: if ( len < 0 ) ! 152: return len; ! 153: ! 154: cursor->data += len; ! 155: cursor->len -= len; ! 156: DBGC ( cursor, "ASN1 %p skipped object type %02x (len %x)\n", ! 157: cursor, type, len ); ! 158: ! 159: if ( ! cursor->len ) { ! 160: DBGC ( cursor, "ASN1 %p reached end of object\n", cursor ); ! 161: cursor->data = NULL; ! 162: return -ENOENT; ! 163: } ! 164: ! 165: return 0; ! 166: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.