Botan
1.11.15
|
00001 /* 00002 * SCAN Name Abstraction 00003 * (C) 2008-2009,2015 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/scan_name.h> 00009 #include <botan/parsing.h> 00010 #include <botan/exceptn.h> 00011 #include <stdexcept> 00012 00013 namespace Botan { 00014 00015 namespace { 00016 00017 std::string make_arg( 00018 const std::vector<std::pair<size_t, std::string> >& name, size_t start) 00019 { 00020 std::string output = name[start].second; 00021 size_t level = name[start].first; 00022 00023 size_t paren_depth = 0; 00024 00025 for(size_t i = start + 1; i != name.size(); ++i) 00026 { 00027 if(name[i].first <= name[start].first) 00028 break; 00029 00030 if(name[i].first > level) 00031 { 00032 output += '(' + name[i].second; 00033 ++paren_depth; 00034 } 00035 else if(name[i].first < level) 00036 { 00037 output += ")," + name[i].second; 00038 --paren_depth; 00039 } 00040 else 00041 { 00042 if(output[output.size() - 1] != '(') 00043 output += ","; 00044 output += name[i].second; 00045 } 00046 00047 level = name[i].first; 00048 } 00049 00050 for(size_t i = 0; i != paren_depth; ++i) 00051 output += ')'; 00052 00053 return output; 00054 } 00055 00056 std::pair<size_t, std::string> 00057 deref_aliases(const std::pair<size_t, std::string>& in) 00058 { 00059 return std::make_pair(in.first, 00060 SCAN_Name::deref_alias(in.second)); 00061 } 00062 00063 } 00064 00065 SCAN_Name::SCAN_Name(std::string algo_spec, const std::string& extra) : SCAN_Name(algo_spec) 00066 { 00067 alg_name += extra; 00068 } 00069 00070 SCAN_Name::SCAN_Name(const char* algo_spec) : SCAN_Name(std::string(algo_spec)) 00071 { 00072 } 00073 00074 SCAN_Name::SCAN_Name(std::string algo_spec) 00075 { 00076 orig_algo_spec = algo_spec; 00077 00078 std::vector<std::pair<size_t, std::string> > name; 00079 size_t level = 0; 00080 std::pair<size_t, std::string> accum = std::make_pair(level, ""); 00081 00082 const std::string decoding_error = "Bad SCAN name '" + algo_spec + "': "; 00083 00084 algo_spec = SCAN_Name::deref_alias(algo_spec); 00085 00086 for(size_t i = 0; i != algo_spec.size(); ++i) 00087 { 00088 char c = algo_spec[i]; 00089 00090 if(c == '/' || c == ',' || c == '(' || c == ')') 00091 { 00092 if(c == '(') 00093 ++level; 00094 else if(c == ')') 00095 { 00096 if(level == 0) 00097 throw Decoding_Error(decoding_error + "Mismatched parens"); 00098 --level; 00099 } 00100 00101 if(c == '/' && level > 0) 00102 accum.second.push_back(c); 00103 else 00104 { 00105 if(accum.second != "") 00106 name.push_back(deref_aliases(accum)); 00107 accum = std::make_pair(level, ""); 00108 } 00109 } 00110 else 00111 accum.second.push_back(c); 00112 } 00113 00114 if(accum.second != "") 00115 name.push_back(deref_aliases(accum)); 00116 00117 if(level != 0) 00118 throw Decoding_Error(decoding_error + "Missing close paren"); 00119 00120 if(name.size() == 0) 00121 throw Decoding_Error(decoding_error + "Empty name"); 00122 00123 alg_name = name[0].second; 00124 00125 bool in_modes = false; 00126 00127 for(size_t i = 1; i != name.size(); ++i) 00128 { 00129 if(name[i].first == 0) 00130 { 00131 mode_info.push_back(make_arg(name, i)); 00132 in_modes = true; 00133 } 00134 else if(name[i].first == 1 && !in_modes) 00135 args.push_back(make_arg(name, i)); 00136 } 00137 } 00138 00139 std::string SCAN_Name::all_arguments() const 00140 { 00141 std::string out; 00142 if(arg_count()) 00143 { 00144 out += '('; 00145 for(size_t i = 0; i != arg_count(); ++i) 00146 { 00147 out += arg(i); 00148 if(i != arg_count() - 1) 00149 out += ','; 00150 } 00151 out += ')'; 00152 } 00153 return out; 00154 } 00155 00156 std::string SCAN_Name::arg(size_t i) const 00157 { 00158 if(i >= arg_count()) 00159 throw std::range_error("SCAN_Name::arg " + std::to_string(i) + 00160 " out of range for '" + as_string() + "'"); 00161 return args[i]; 00162 } 00163 00164 std::string SCAN_Name::arg(size_t i, const std::string& def_value) const 00165 { 00166 if(i >= arg_count()) 00167 return def_value; 00168 return args[i]; 00169 } 00170 00171 size_t SCAN_Name::arg_as_integer(size_t i, size_t def_value) const 00172 { 00173 if(i >= arg_count()) 00174 return def_value; 00175 return to_u32bit(args[i]); 00176 } 00177 00178 std::mutex SCAN_Name::g_alias_map_mutex; 00179 std::map<std::string, std::string> SCAN_Name::g_alias_map = { 00180 { "3DES", "TripleDES" }, 00181 { "ARC4", "RC4" }, 00182 { "CAST5", "CAST-128" }, 00183 { "DES-EDE", "TripleDES" }, 00184 { "EME-OAEP", "OAEP" }, 00185 { "EME-PKCS1-v1_5", "PKCS1v15" }, 00186 { "EME1", "OAEP" }, 00187 { "EMSA-PKCS1-v1_5", "EMSA_PKCS1" }, 00188 { "EMSA-PSS", "PSSR" }, 00189 { "EMSA2", "EMSA_X931" }, 00190 { "EMSA3", "EMSA_PKCS1" }, 00191 { "EMSA4", "PSSR" }, 00192 { "GOST-34.11", "GOST-R-34.11-94" }, 00193 { "MARK-4", "RC4(256)" }, 00194 { "OMAC", "CMAC" }, 00195 { "PSS-MGF1", "PSSR" }, 00196 { "SHA-1", "SHA-160" }, 00197 { "SHA1", "SHA-160" }, 00198 { "X9.31", "EMSA2" } 00199 }; 00200 00201 void SCAN_Name::add_alias(const std::string& alias, const std::string& basename) 00202 { 00203 std::lock_guard<std::mutex> lock(g_alias_map_mutex); 00204 00205 if(g_alias_map.find(alias) == g_alias_map.end()) 00206 g_alias_map[alias] = basename; 00207 } 00208 00209 std::string SCAN_Name::deref_alias(const std::string& alias) 00210 { 00211 std::lock_guard<std::mutex> lock(g_alias_map_mutex); 00212 00213 std::string name = alias; 00214 00215 for(auto i = g_alias_map.find(name); i != g_alias_map.end(); i = g_alias_map.find(name)) 00216 name = i->second; 00217 00218 return name; 00219 } 00220 00221 }