File indexing completed on 2024-05-12 04:45:15

0001 /*
0002 Copyright (C) 1999-2007 The Botan Project. All rights reserved.
0003 
0004 Redistribution and use in source and binary forms, for any use, with or without
0005 modification, is permitted provided that the following conditions are met:
0006 
0007 1. Redistributions of source code must retain the above copyright notice, this
0008 list of conditions, and the following disclaimer.
0009 
0010 2. Redistributions in binary form must reproduce the above copyright notice,
0011 this list of conditions, and the following disclaimer in the documentation
0012 and/or other materials provided with the distribution.
0013 
0014 THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) "AS IS" AND ANY EXPRESS OR IMPLIED
0015 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
0016 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
0017 
0018 IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE FOR ANY DIRECT,
0019 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
0020 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0021 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
0022 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
0023 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
0024 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0025 */
0026 // LICENSEHEADER_END
0027 namespace QCA { // WRAPNS_LINE
0028 /*************************************************
0029  * Parser Functions Source File                   *
0030  * (C) 1999-2007 The Botan Project                *
0031  *************************************************/
0032 
0033 } // WRAPNS_LINE
0034 #include <botan/parsing.h>
0035 namespace QCA { // WRAPNS_LINE
0036 } // WRAPNS_LINE
0037 #include <botan/exceptn.h>
0038 namespace QCA { // WRAPNS_LINE
0039 } // WRAPNS_LINE
0040 #include <botan/charset.h>
0041 namespace QCA { // WRAPNS_LINE
0042 
0043 namespace Botan {
0044 
0045 /*************************************************
0046  * Convert a string into an integer               *
0047  *************************************************/
0048 #ifndef BOTAN_TOOLS_ONLY
0049 u32bit to_u32bit(const std::string &number)
0050 {
0051     u32bit n = 0;
0052 
0053     for (std::string::const_iterator j = number.begin(); j != number.end(); ++j) {
0054         const u32bit OVERFLOW_MARK = 0xFFFFFFFF / 10;
0055 
0056         byte digit = Charset::char2digit(*j);
0057 
0058         if ((n > OVERFLOW_MARK) || (n == OVERFLOW_MARK && digit > 5))
0059             throw Decoding_Error("to_u32bit: Integer overflow");
0060         n *= 10;
0061         n += digit;
0062     }
0063     return n;
0064 }
0065 #endif
0066 
0067 /*************************************************
0068  * Convert an integer into a string               *
0069  *************************************************/
0070 std::string to_string(u64bit n, u32bit min_len)
0071 {
0072     std::string lenstr;
0073     if (n) {
0074         while (n > 0) {
0075             lenstr = Charset::digit2char(n % 10) + lenstr; // NOLINT(performance-inefficient-string-concatenation)
0076             n /= 10;
0077         }
0078     } else
0079         lenstr = "0";
0080 
0081     while (lenstr.size() < min_len)
0082         lenstr = "0" + lenstr; // NOLINT(performance-inefficient-string-concatenation)
0083 
0084     return lenstr;
0085 }
0086 
0087 #ifndef BOTAN_TOOLS_ONLY
0088 /*************************************************
0089  * Parse a SCAN-style algorithm name              *
0090  *************************************************/
0091 std::vector<std::string> parse_algorithm_name(const std::string &namex)
0092 {
0093     if (namex.find('(') == std::string::npos && namex.find(')') == std::string::npos)
0094         return std::vector<std::string>(1, namex);
0095 
0096     std::string              name = namex, substring;
0097     std::vector<std::string> elems;
0098     u32bit                   level = 0;
0099 
0100     elems.push_back(name.substr(0, name.find('(')));
0101     name = name.substr(name.find('('));
0102 
0103     for (std::string::const_iterator j = name.begin(); j != name.end(); ++j) {
0104         char c = *j;
0105 
0106         if (c == '(')
0107             ++level;
0108         if (c == ')') {
0109             if (level == 1 && j == name.end() - 1) {
0110                 if (elems.size() == 1)
0111                     elems.push_back(substring.substr(1));
0112                 else
0113                     elems.push_back(substring);
0114                 return elems;
0115             }
0116 
0117             if (level == 0 || (level == 1 && j != name.end() - 1))
0118                 throw Invalid_Algorithm_Name(namex);
0119             --level;
0120         }
0121 
0122         if (c == ',' && level == 1) {
0123             if (elems.size() == 1)
0124                 elems.push_back(substring.substr(1));
0125             else
0126                 elems.push_back(substring);
0127             substring.clear();
0128         } else
0129             substring += c;
0130     }
0131 
0132     if (substring != "")
0133         throw Invalid_Algorithm_Name(namex);
0134 
0135     return elems;
0136 }
0137 
0138 /*************************************************
0139  * Split the string on slashes                    *
0140  *************************************************/
0141 std::vector<std::string> split_on(const std::string &str, char delim)
0142 {
0143     std::vector<std::string> elems;
0144     if (str == "")
0145         return elems;
0146 
0147     std::string substr;
0148     for (std::string::const_iterator j = str.begin(); j != str.end(); ++j) {
0149         if (*j == delim) {
0150             if (substr != "")
0151                 elems.push_back(substr);
0152             substr.clear();
0153         } else
0154             substr += *j;
0155     }
0156 
0157     if (substr == "")
0158         throw Format_Error("Unable to split string: " + str);
0159     elems.push_back(substr);
0160 
0161     return elems;
0162 }
0163 
0164 /*************************************************
0165  * Parse an ASN.1 OID string                      *
0166  *************************************************/
0167 std::vector<u32bit> parse_asn1_oid(const std::string &oid)
0168 {
0169     std::string         substring;
0170     std::vector<u32bit> oid_elems;
0171 
0172     for (std::string::const_iterator j = oid.begin(); j != oid.end(); ++j) {
0173         char c = *j;
0174 
0175         if (c == '.') {
0176             if (substring == "")
0177                 throw Invalid_OID(oid);
0178             oid_elems.push_back(to_u32bit(substring));
0179             substring.clear();
0180         } else
0181             substring += c;
0182     }
0183 
0184     if (substring == "")
0185         throw Invalid_OID(oid);
0186     oid_elems.push_back(to_u32bit(substring));
0187 
0188     if (oid_elems.size() < 2)
0189         throw Invalid_OID(oid);
0190 
0191     return oid_elems;
0192 }
0193 
0194 /*************************************************
0195  * X.500 String Comparison                        *
0196  *************************************************/
0197 bool x500_name_cmp(const std::string &name1, const std::string &name2)
0198 {
0199     std::string::const_iterator p1 = name1.begin();
0200     std::string::const_iterator p2 = name2.begin();
0201 
0202     while ((p1 != name1.end()) && Charset::is_space(*p1))
0203         ++p1;
0204     while ((p2 != name2.end()) && Charset::is_space(*p2))
0205         ++p2;
0206 
0207     while (p1 != name1.end() && p2 != name2.end()) {
0208         if (Charset::is_space(*p1)) {
0209             if (!Charset::is_space(*p2))
0210                 return false;
0211 
0212             while ((p1 != name1.end()) && Charset::is_space(*p1))
0213                 ++p1;
0214             while ((p2 != name2.end()) && Charset::is_space(*p2))
0215                 ++p2;
0216 
0217             if (p1 == name1.end() && p2 == name2.end())
0218                 return true;
0219         }
0220 
0221         if (!Charset::caseless_cmp(*p1, *p2))
0222             return false;
0223         ++p1;
0224         ++p2;
0225     }
0226 
0227     while ((p1 != name1.end()) && Charset::is_space(*p1))
0228         ++p1;
0229     while ((p2 != name2.end()) && Charset::is_space(*p2))
0230         ++p2;
0231 
0232     if ((p1 != name1.end()) || (p2 != name2.end()))
0233         return false;
0234     return true;
0235 }
0236 
0237 /*************************************************
0238  * Parse and compute an arithmetic expression     *
0239  *************************************************/
0240 u32bit parse_expr(const std::string &expr)
0241 {
0242     const bool have_add = (expr.find('+') != std::string::npos);
0243     const bool have_mul = (expr.find('*') != std::string::npos);
0244 
0245     if (have_add) {
0246         std::vector<std::string> sub_expr = split_on(expr, '+');
0247         u32bit                   result   = 0;
0248         for (u32bit j = 0; j != sub_expr.size(); ++j)
0249             result += parse_expr(sub_expr[j]);
0250         return result;
0251     } else if (have_mul) {
0252         std::vector<std::string> sub_expr = split_on(expr, '*');
0253         u32bit                   result   = 1;
0254         for (u32bit j = 0; j != sub_expr.size(); ++j)
0255             result *= parse_expr(sub_expr[j]);
0256         return result;
0257     } else
0258         return to_u32bit(expr);
0259 }
0260 #endif
0261 
0262 }
0263 } // WRAPNS_LINE