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 +}