tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

oidstring.c (3847B)


      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/. */
      4 
      5 #include <string.h>
      6 #include "secitem.h"
      7 #include "secport.h"
      8 #include "secerr.h"
      9 
     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 */
     23 
     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];
     31 
     32    static const PRUint32 max_decimal = (0xffffffff / 10);
     33    static const char OIDstring[] = { "OID." };
     34 
     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((unsigned char)*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 }