aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/base/scan_name.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/base/scan_name.cpp')
-rw-r--r--src/lib/base/scan_name.cpp221
1 files changed, 221 insertions, 0 deletions
diff --git a/src/lib/base/scan_name.cpp b/src/lib/base/scan_name.cpp
new file mode 100644
index 000000000..4b0c95004
--- /dev/null
+++ b/src/lib/base/scan_name.cpp
@@ -0,0 +1,221 @@
+/*
+* SCAN Name Abstraction
+* (C) 2008-2009,2015 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/scan_name.h>
+#include <botan/parsing.h>
+#include <botan/exceptn.h>
+#include <stdexcept>
+
+namespace Botan {
+
+namespace {
+
+std::string make_arg(
+ const std::vector<std::pair<size_t, std::string> >& name, size_t start)
+ {
+ std::string output = name[start].second;
+ size_t level = name[start].first;
+
+ size_t paren_depth = 0;
+
+ for(size_t i = start + 1; i != name.size(); ++i)
+ {
+ if(name[i].first <= name[start].first)
+ break;
+
+ if(name[i].first > level)
+ {
+ output += '(' + name[i].second;
+ ++paren_depth;
+ }
+ else if(name[i].first < level)
+ {
+ output += ")," + name[i].second;
+ --paren_depth;
+ }
+ else
+ {
+ if(output[output.size() - 1] != '(')
+ output += ",";
+ output += name[i].second;
+ }
+
+ level = name[i].first;
+ }
+
+ for(size_t i = 0; i != paren_depth; ++i)
+ output += ')';
+
+ return output;
+ }
+
+std::pair<size_t, std::string>
+deref_aliases(const std::pair<size_t, std::string>& in)
+ {
+ return std::make_pair(in.first,
+ SCAN_Name::deref_alias(in.second));
+ }
+
+}
+
+SCAN_Name::SCAN_Name(std::string algo_spec, const std::string& extra) : SCAN_Name(algo_spec)
+ {
+ alg_name += extra;
+ }
+
+SCAN_Name::SCAN_Name(const char* algo_spec) : SCAN_Name(std::string(algo_spec))
+ {
+ }
+
+SCAN_Name::SCAN_Name(std::string algo_spec)
+ {
+ orig_algo_spec = algo_spec;
+
+ std::vector<std::pair<size_t, std::string> > name;
+ size_t level = 0;
+ std::pair<size_t, std::string> accum = std::make_pair(level, "");
+
+ const std::string decoding_error = "Bad SCAN name '" + algo_spec + "': ";
+
+ algo_spec = SCAN_Name::deref_alias(algo_spec);
+
+ for(size_t i = 0; i != algo_spec.size(); ++i)
+ {
+ char c = algo_spec[i];
+
+ if(c == '/' || c == ',' || c == '(' || c == ')')
+ {
+ if(c == '(')
+ ++level;
+ else if(c == ')')
+ {
+ if(level == 0)
+ throw Decoding_Error(decoding_error + "Mismatched parens");
+ --level;
+ }
+
+ if(c == '/' && level > 0)
+ accum.second.push_back(c);
+ else
+ {
+ if(accum.second != "")
+ name.push_back(deref_aliases(accum));
+ accum = std::make_pair(level, "");
+ }
+ }
+ else
+ accum.second.push_back(c);
+ }
+
+ if(accum.second != "")
+ name.push_back(deref_aliases(accum));
+
+ if(level != 0)
+ throw Decoding_Error(decoding_error + "Missing close paren");
+
+ if(name.size() == 0)
+ throw Decoding_Error(decoding_error + "Empty name");
+
+ alg_name = name[0].second;
+
+ bool in_modes = false;
+
+ for(size_t i = 1; i != name.size(); ++i)
+ {
+ if(name[i].first == 0)
+ {
+ mode_info.push_back(make_arg(name, i));
+ in_modes = true;
+ }
+ else if(name[i].first == 1 && !in_modes)
+ args.push_back(make_arg(name, i));
+ }
+ }
+
+std::string SCAN_Name::all_arguments() const
+ {
+ std::string out;
+ if(arg_count())
+ {
+ out += '(';
+ for(size_t i = 0; i != arg_count(); ++i)
+ {
+ out += arg(i);
+ if(i != arg_count() - 1)
+ out += ',';
+ }
+ out += ')';
+ }
+ return out;
+ }
+
+std::string SCAN_Name::arg(size_t i) const
+ {
+ if(i >= arg_count())
+ throw std::range_error("SCAN_Name::arg " + std::to_string(i) +
+ " out of range for '" + as_string() + "'");
+ return args[i];
+ }
+
+std::string SCAN_Name::arg(size_t i, const std::string& def_value) const
+ {
+ if(i >= arg_count())
+ return def_value;
+ return args[i];
+ }
+
+size_t SCAN_Name::arg_as_integer(size_t i, size_t def_value) const
+ {
+ if(i >= arg_count())
+ return def_value;
+ return to_u32bit(args[i]);
+ }
+
+std::mutex SCAN_Name::g_alias_map_mutex;
+std::map<std::string, std::string> SCAN_Name::g_alias_map = {
+ { "3DES", "TripleDES" },
+ { "ARC4", "RC4" },
+ { "CAST5", "CAST-128" },
+ { "DES-EDE", "TripleDES" },
+ { "EME-OAEP", "OAEP" },
+ { "EME-PKCS1-v1_5", "PKCS1v15" },
+ { "EME1", "OAEP" },
+ { "EMSA-PKCS1-v1_5", "EMSA_PKCS1" },
+ { "EMSA-PSS", "PSSR" },
+ { "EMSA2", "EMSA_X931" },
+ { "EMSA3", "EMSA_PKCS1" },
+ { "EMSA4", "PSSR" },
+ { "GOST-34.11", "GOST-R-34.11-94" },
+ { "MARK-4", "RC4(256)" },
+ { "OMAC", "CMAC" },
+ { "PSS-MGF1", "PSSR" },
+ { "SHA-1", "SHA-160" },
+ { "SHA1", "SHA-160" },
+ { "X9.31", "EMSA2" }
+};
+
+void SCAN_Name::add_alias(const std::string& alias, const std::string& basename)
+ {
+ std::lock_guard<std::mutex> lock(g_alias_map_mutex);
+
+ if(g_alias_map.find(alias) == g_alias_map.end())
+ g_alias_map[alias] = basename;
+ }
+
+std::string SCAN_Name::deref_alias(const std::string& alias)
+ {
+ std::lock_guard<std::mutex> lock(g_alias_map_mutex);
+
+ std::string name = alias;
+
+ for(auto i = g_alias_map.find(name); i != g_alias_map.end(); i = g_alias_map.find(name))
+ name = i->second;
+
+ return name;
+ }
+
+}