security/nss/lib/util/oidstring.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/util/oidstring.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,114 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#include <string.h>
     1.9 +#include "secitem.h"
    1.10 +#include "secport.h"
    1.11 +#include "secerr.h"
    1.12 +
    1.13 +/* if to->data is not NULL, and to->len is large enough to hold the result,
    1.14 + * then the resultant OID will be copyed into to->data, and to->len will be
    1.15 + * changed to show the actual OID length.
    1.16 + * Otherwise, memory for the OID will be allocated (from the caller's 
    1.17 + * PLArenaPool, if pool is non-NULL) and to->data will receive the address
    1.18 + * of the allocated data, and to->len will receive the OID length.
    1.19 + * The original value of to->data is not freed when a new buffer is allocated.
    1.20 + * 
    1.21 + * The input string may begin with "OID." and this still be ignored.
    1.22 + * The length of the input string is given in len.  If len == 0, then 
    1.23 + * len will be computed as strlen(from), meaning it must be NUL terminated.
    1.24 + * It is an error if from == NULL, or if *from == '\0'.
    1.25 + */
    1.26 +
    1.27 +SECStatus
    1.28 +SEC_StringToOID(PLArenaPool *pool, SECItem *to, const char *from, PRUint32 len)
    1.29 +{
    1.30 +    PRUint32 decimal_numbers = 0;
    1.31 +    PRUint32 result_bytes = 0;
    1.32 +    SECStatus rv;
    1.33 +    PRUint8 result[1024];
    1.34 +
    1.35 +    static const PRUint32 max_decimal = (0xffffffff / 10);
    1.36 +    static const char OIDstring[] = {"OID."};
    1.37 +
    1.38 +    if (!from || !to) {
    1.39 +    	PORT_SetError(SEC_ERROR_INVALID_ARGS);
    1.40 +	return SECFailure;
    1.41 +    }
    1.42 +    if (!len) {
    1.43 +    	len = PL_strlen(from);
    1.44 +    }
    1.45 +    if (len >= 4 && !PL_strncasecmp(from, OIDstring, 4)) {
    1.46 +    	from += 4; /* skip leading "OID." if present */
    1.47 +	len  -= 4;
    1.48 +    }
    1.49 +    if (!len) {
    1.50 +bad_data:
    1.51 +    	PORT_SetError(SEC_ERROR_BAD_DATA);
    1.52 +	return SECFailure;
    1.53 +    }
    1.54 +    do {
    1.55 +	PRUint32 decimal = 0;
    1.56 +        while (len > 0 && isdigit(*from)) {
    1.57 +	    PRUint32 addend = (*from++ - '0');
    1.58 +	    --len;
    1.59 +	    if (decimal > max_decimal)  /* overflow */
    1.60 +		goto bad_data;
    1.61 +	    decimal = (decimal * 10) + addend;
    1.62 +	    if (decimal < addend)	/* overflow */
    1.63 +		goto bad_data;
    1.64 +	}
    1.65 +	if (len != 0 && *from != '.') {
    1.66 +	    goto bad_data;
    1.67 +	}
    1.68 +	if (decimal_numbers == 0) {
    1.69 +	    if (decimal > 2)
    1.70 +	    	goto bad_data;
    1.71 +	    result[0] = decimal * 40;
    1.72 +	    result_bytes = 1;
    1.73 +	} else if (decimal_numbers == 1) {
    1.74 +	    if (decimal > 40)
    1.75 +	    	goto bad_data;
    1.76 +	    result[0] += decimal;
    1.77 +	} else {
    1.78 +	    /* encode the decimal number,  */
    1.79 +	    PRUint8 * rp;
    1.80 +	    PRUint32 num_bytes = 0;
    1.81 +	    PRUint32 tmp = decimal;
    1.82 +	    while (tmp) {
    1.83 +	        num_bytes++;
    1.84 +		tmp >>= 7;
    1.85 +	    }
    1.86 +	    if (!num_bytes )
    1.87 +	    	++num_bytes;  /* use one byte for a zero value */
    1.88 +	    if (num_bytes + result_bytes > sizeof result)
    1.89 +	    	goto bad_data;
    1.90 +	    tmp = num_bytes;
    1.91 +	    rp = result + result_bytes - 1;
    1.92 +	    rp[tmp] = (PRUint8)(decimal & 0x7f);
    1.93 +	    decimal >>= 7;
    1.94 +	    while (--tmp > 0) {
    1.95 +		rp[tmp] = (PRUint8)(decimal | 0x80);
    1.96 +		decimal >>= 7;
    1.97 +	    }
    1.98 +	    result_bytes += num_bytes;
    1.99 +	}
   1.100 +	++decimal_numbers;
   1.101 +	if (len > 0) { /* skip trailing '.' */
   1.102 +	    ++from;
   1.103 +	    --len;
   1.104 +	}
   1.105 +    } while (len > 0);
   1.106 +    /* now result contains result_bytes of data */
   1.107 +    if (to->data && to->len >= result_bytes) {
   1.108 +    	PORT_Memcpy(to->data, result, to->len = result_bytes);
   1.109 +	rv = SECSuccess;
   1.110 +    } else {
   1.111 +    	SECItem result_item = {siBuffer, NULL, 0 };
   1.112 +	result_item.data = result;
   1.113 +	result_item.len  = result_bytes;
   1.114 +	rv = SECITEM_CopyItem(pool, to, &result_item);
   1.115 +    }
   1.116 +    return rv;
   1.117 +}

mercurial