security/nss/lib/util/derdec.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "secder.h"
     6 #include "secerr.h"
     8 static PRUint32
     9 der_indefinite_length(unsigned char *buf, unsigned char *end)
    10 {
    11     PRUint32 len, ret, dataLen;
    12     unsigned char tag, lenCode;
    13     int dataLenLen;
    15     len = 0;
    16     while ( 1 ) {
    17 	if ((buf + 2) > end) {
    18 	    return(0);
    19 	}
    21 	tag = *buf++;
    22 	lenCode = *buf++;
    23 	len += 2;
    25 	if ( ( tag == 0 ) && ( lenCode == 0 ) ) {
    26 	    return(len);
    27 	}
    29 	if ( lenCode == 0x80 ) {	/* indefinite length */
    30 	    ret = der_indefinite_length(buf, end); /* recurse to find length */
    31 	    if (ret == 0)
    32 		return 0;
    33 	    len += ret;
    34 	    buf += ret;
    35 	} else {			/* definite length */
    36 	    if (lenCode & 0x80) {
    37 		/* Length of data is in multibyte format */
    38 		dataLenLen = lenCode & 0x7f;
    39 		switch (dataLenLen) {
    40 		  case 1:
    41 		    dataLen = buf[0];
    42 		    break;
    43 		  case 2:
    44 		    dataLen = (buf[0]<<8)|buf[1];
    45 		    break;
    46 		  case 3:
    47 		    dataLen = ((unsigned long)buf[0]<<16)|(buf[1]<<8)|buf[2];
    48 		    break;
    49 		  case 4:
    50 		    dataLen = ((unsigned long)buf[0]<<24)|
    51 			((unsigned long)buf[1]<<16)|(buf[2]<<8)|buf[3];
    52 		    break;
    53 		  default:
    54 		    PORT_SetError(SEC_ERROR_BAD_DER);
    55 		    return SECFailure;
    56 		}
    57 	    } else {
    58 		/* Length of data is in single byte */
    59 		dataLen = lenCode;
    60 		dataLenLen = 0;
    61 	    }
    63 	    /* skip this item */
    64 	    buf = buf + dataLenLen + dataLen;
    65 	    len = len + dataLenLen + dataLen;
    66 	}
    67     }
    68 }
    70 /*
    71 ** Capture the next thing in the buffer.
    72 ** Returns the length of the header and the length of the contents.
    73 */
    74 static SECStatus
    75 der_capture(unsigned char *buf, unsigned char *end,
    76 	    int *header_len_p, PRUint32 *contents_len_p)
    77 {
    78     unsigned char *bp;
    79     unsigned char whole_tag;
    80     PRUint32 contents_len;
    81     int tag_number;
    83     if ((buf + 2) > end) {
    84 	*header_len_p = 0;
    85 	*contents_len_p = 0;
    86 	if (buf == end)
    87 	    return SECSuccess;
    88 	return SECFailure;
    89     }
    91     bp = buf;
    93     /* Get tag and verify that it is ok. */
    94     whole_tag = *bp++;
    95     tag_number = whole_tag & DER_TAGNUM_MASK;
    97     /*
    98      * XXX This code does not (yet) handle the high-tag-number form!
    99      */
   100     if (tag_number == DER_HIGH_TAG_NUMBER) {
   101 	PORT_SetError(SEC_ERROR_BAD_DER);
   102 	return SECFailure;
   103     }
   105     if ((whole_tag & DER_CLASS_MASK) == DER_UNIVERSAL) {
   106 	/* Check that the universal tag number is one we implement.  */
   107 	switch (tag_number) {
   108 	  case DER_BOOLEAN:
   109 	  case DER_INTEGER:
   110 	  case DER_BIT_STRING:
   111 	  case DER_OCTET_STRING:
   112 	  case DER_NULL:
   113 	  case DER_OBJECT_ID:
   114 	  case DER_SEQUENCE:
   115 	  case DER_SET:
   116 	  case DER_PRINTABLE_STRING:
   117 	  case DER_T61_STRING:
   118 	  case DER_IA5_STRING:
   119 	  case DER_VISIBLE_STRING:
   120 	  case DER_UTC_TIME:
   121 	  case 0:			/* end-of-contents tag */
   122 	    break;
   123 	  default:
   124 	    PORT_SetError(SEC_ERROR_BAD_DER);
   125 	    return SECFailure;
   126 	}
   127     }
   129     /*
   130      * Get first byte of length code (might contain entire length, might not).
   131      */
   132     contents_len = *bp++;
   134     /*
   135      * If the high bit is set, then the length is in multibyte format,
   136      * or the thing has an indefinite-length.
   137      */
   138     if (contents_len & 0x80) {
   139 	int bytes_of_encoded_len;
   141 	bytes_of_encoded_len = contents_len & 0x7f;
   142 	contents_len = 0;
   144 	switch (bytes_of_encoded_len) {
   145 	  case 4:
   146 	    contents_len |= *bp++;
   147 	    contents_len <<= 8;
   148 	    /* fallthru */
   149 	  case 3:
   150 	    contents_len |= *bp++;
   151 	    contents_len <<= 8;
   152 	    /* fallthru */
   153 	  case 2:
   154 	    contents_len |= *bp++;
   155 	    contents_len <<= 8;
   156 	    /* fallthru */
   157 	  case 1:
   158 	    contents_len |= *bp++;
   159 	    break;
   161 	  case 0:
   162 	    contents_len = der_indefinite_length (bp, end);
   163 	    if (contents_len)
   164 		break;
   165 	    /* fallthru */
   166 	  default:
   167 	    PORT_SetError(SEC_ERROR_BAD_DER);
   168 	    return SECFailure;
   169 	}
   170     }
   172     if ((bp + contents_len) > end) {
   173 	/* Ran past end of buffer */
   174 	PORT_SetError(SEC_ERROR_BAD_DER);
   175 	return SECFailure;
   176     }
   178     *header_len_p = bp - buf;
   179     *contents_len_p = contents_len;
   181     return SECSuccess;
   182 }
   184 SECStatus
   185 DER_Lengths(SECItem *item, int *header_len_p, PRUint32 *contents_len_p)
   186 {
   187     return(der_capture(item->data, &item->data[item->len], header_len_p,
   188 		       contents_len_p));
   189 }

mercurial