security/nss/lib/util/oidstring.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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 <string.h>
     6 #include "secitem.h"
     7 #include "secport.h"
     8 #include "secerr.h"
    10 /* if to->data is not NULL, and to->len is large enough to hold the result,
    11  * then the resultant OID will be copyed into to->data, and to->len will be
    12  * changed to show the actual OID length.
    13  * Otherwise, memory for the OID will be allocated (from the caller's 
    14  * PLArenaPool, if pool is non-NULL) and to->data will receive the address
    15  * of the allocated data, and to->len will receive the OID length.
    16  * The original value of to->data is not freed when a new buffer is allocated.
    17  * 
    18  * The input string may begin with "OID." and this still be ignored.
    19  * The length of the input string is given in len.  If len == 0, then 
    20  * len will be computed as strlen(from), meaning it must be NUL terminated.
    21  * It is an error if from == NULL, or if *from == '\0'.
    22  */
    24 SECStatus
    25 SEC_StringToOID(PLArenaPool *pool, SECItem *to, const char *from, PRUint32 len)
    26 {
    27     PRUint32 decimal_numbers = 0;
    28     PRUint32 result_bytes = 0;
    29     SECStatus rv;
    30     PRUint8 result[1024];
    32     static const PRUint32 max_decimal = (0xffffffff / 10);
    33     static const char OIDstring[] = {"OID."};
    35     if (!from || !to) {
    36     	PORT_SetError(SEC_ERROR_INVALID_ARGS);
    37 	return SECFailure;
    38     }
    39     if (!len) {
    40     	len = PL_strlen(from);
    41     }
    42     if (len >= 4 && !PL_strncasecmp(from, OIDstring, 4)) {
    43     	from += 4; /* skip leading "OID." if present */
    44 	len  -= 4;
    45     }
    46     if (!len) {
    47 bad_data:
    48     	PORT_SetError(SEC_ERROR_BAD_DATA);
    49 	return SECFailure;
    50     }
    51     do {
    52 	PRUint32 decimal = 0;
    53         while (len > 0 && isdigit(*from)) {
    54 	    PRUint32 addend = (*from++ - '0');
    55 	    --len;
    56 	    if (decimal > max_decimal)  /* overflow */
    57 		goto bad_data;
    58 	    decimal = (decimal * 10) + addend;
    59 	    if (decimal < addend)	/* overflow */
    60 		goto bad_data;
    61 	}
    62 	if (len != 0 && *from != '.') {
    63 	    goto bad_data;
    64 	}
    65 	if (decimal_numbers == 0) {
    66 	    if (decimal > 2)
    67 	    	goto bad_data;
    68 	    result[0] = decimal * 40;
    69 	    result_bytes = 1;
    70 	} else if (decimal_numbers == 1) {
    71 	    if (decimal > 40)
    72 	    	goto bad_data;
    73 	    result[0] += decimal;
    74 	} else {
    75 	    /* encode the decimal number,  */
    76 	    PRUint8 * rp;
    77 	    PRUint32 num_bytes = 0;
    78 	    PRUint32 tmp = decimal;
    79 	    while (tmp) {
    80 	        num_bytes++;
    81 		tmp >>= 7;
    82 	    }
    83 	    if (!num_bytes )
    84 	    	++num_bytes;  /* use one byte for a zero value */
    85 	    if (num_bytes + result_bytes > sizeof result)
    86 	    	goto bad_data;
    87 	    tmp = num_bytes;
    88 	    rp = result + result_bytes - 1;
    89 	    rp[tmp] = (PRUint8)(decimal & 0x7f);
    90 	    decimal >>= 7;
    91 	    while (--tmp > 0) {
    92 		rp[tmp] = (PRUint8)(decimal | 0x80);
    93 		decimal >>= 7;
    94 	    }
    95 	    result_bytes += num_bytes;
    96 	}
    97 	++decimal_numbers;
    98 	if (len > 0) { /* skip trailing '.' */
    99 	    ++from;
   100 	    --len;
   101 	}
   102     } while (len > 0);
   103     /* now result contains result_bytes of data */
   104     if (to->data && to->len >= result_bytes) {
   105     	PORT_Memcpy(to->data, result, to->len = result_bytes);
   106 	rv = SECSuccess;
   107     } else {
   108     	SECItem result_item = {siBuffer, NULL, 0 };
   109 	result_item.data = result;
   110 	result_item.len  = result_bytes;
   111 	rv = SECITEM_CopyItem(pool, to, &result_item);
   112     }
   113     return rv;
   114 }

mercurial