summaryrefslogtreecommitdiffstats
path: root/security/nss/gtests/pk11_gtest/json_reader.cc
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/gtests/pk11_gtest/json_reader.cc')
-rw-r--r--security/nss/gtests/pk11_gtest/json_reader.cc230
1 files changed, 230 insertions, 0 deletions
diff --git a/security/nss/gtests/pk11_gtest/json_reader.cc b/security/nss/gtests/pk11_gtest/json_reader.cc
new file mode 100644
index 0000000000..da8920240c
--- /dev/null
+++ b/security/nss/gtests/pk11_gtest/json_reader.cc
@@ -0,0 +1,230 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "json_reader.h"
+
+#include "pk11pub.h"
+
+JsonReader::JsonReader(const std::string& n) : buf_(), available_(0), i_(0) {
+ f_.reset(PR_Open(n.c_str(), PR_RDONLY, 00600));
+ EXPECT_TRUE(f_) << "error opening vectors from: " << n;
+ buf_[0] = 0;
+}
+
+uint64_t JsonReader::ReadInt() {
+ SkipWhitespace();
+ uint8_t c = peek();
+ uint64_t v = 0;
+ while (c >= '0' && c <= '9') {
+ v = v * 10 + c - '0';
+ next();
+ c = peek();
+ }
+ return v;
+}
+
+// No input checking, no unicode, no escaping (not even \"), just read ASCII.
+std::string JsonReader::ReadString() {
+ SkipWhitespace();
+ if (peek() != '"') {
+ return "";
+ }
+ next();
+
+ std::string s;
+ uint8_t c = take();
+ while (c != '"') {
+ s.push_back(c);
+ c = take();
+ }
+ return s;
+}
+
+std::string JsonReader::ReadLabel() {
+ std::string s = ReadString();
+ SkipWhitespace();
+ EXPECT_EQ(take(), ':');
+ return s;
+}
+
+std::vector<uint8_t> JsonReader::ReadHex() {
+ SkipWhitespace();
+ uint8_t c = take();
+ EXPECT_EQ(c, '"');
+ std::vector<uint8_t> v;
+ c = take();
+ while (c != '"') {
+ v.push_back(JsonReader::Hex(c) << 4 | JsonReader::Hex(take()));
+ c = take();
+ }
+ return v;
+}
+
+SECOidTag JsonReader::ReadHash() {
+ std::string s = ReadString();
+ if (s == "SHA-1") {
+ return SEC_OID_SHA1;
+ }
+ if (s == "SHA-224") {
+ return SEC_OID_SHA224;
+ }
+ if (s == "SHA-256") {
+ return SEC_OID_SHA256;
+ }
+ if (s == "SHA-384") {
+ return SEC_OID_SHA384;
+ }
+ if (s == "SHA-512") {
+ return SEC_OID_SHA512;
+ }
+ ADD_FAILURE() << "unsupported hash";
+ return SEC_OID_UNKNOWN;
+}
+
+bool JsonReader::NextItem(uint8_t h, uint8_t t) {
+ SkipWhitespace();
+ switch (uint8_t c = take()) {
+ case ',':
+ return true;
+ case '{':
+ case '[':
+ EXPECT_EQ(c, h);
+ SkipWhitespace();
+ if (peek() == t) {
+ next();
+ return false;
+ }
+ return true;
+ case '}':
+ case ']':
+ EXPECT_EQ(c, t);
+ return false;
+ default:
+ ADD_FAILURE() << "Unexpected '" << c << "'";
+ }
+ return false;
+}
+
+void JsonReader::SkipValue() {
+ SkipWhitespace();
+
+ uint8_t c = take();
+ if (c == '"') {
+ do {
+ c = take();
+ } while (c != '"');
+
+ } else if (c >= '0' && c <= '9') {
+ c = peek();
+ while (c >= '0' && c <= '9') {
+ next();
+ c = peek();
+ }
+
+ } else if (c == '[') {
+ do {
+ SkipWhitespace();
+ if (peek() != ']') {
+ SkipValue();
+ }
+ } while (NextItemArray());
+
+ } else if (c == '{') {
+ do {
+ SkipWhitespace();
+ if (peek() == '}') {
+ continue;
+ }
+
+ std::string n = ReadLabel();
+ if (n == "") {
+ break;
+ }
+ SkipValue();
+ } while (NextItem());
+
+ } else {
+ ADD_FAILURE() << "No idea how to skip '" << c << "'";
+ }
+}
+
+void JsonReader::TopUp() {
+ if (available_ > i_) {
+ return;
+ }
+ i_ = 0;
+ if (!f_) {
+ return;
+ }
+ PRInt32 res = PR_Read(f_.get(), buf_, sizeof(buf_));
+ if (res > 0) {
+ available_ = static_cast<size_t>(res);
+ } else {
+ available_ = 1;
+ f_.reset(nullptr);
+ buf_[0] = 0;
+ }
+}
+
+void JsonReader::SkipWhitespace() {
+ uint8_t c = peek();
+ while (c && (c == ' ' || c == '\t' || c == '\r' || c == '\n')) {
+ next();
+ c = peek();
+ }
+}
+
+// This only handles lowercase.
+uint8_t JsonReader::Hex(uint8_t c) {
+ if (c >= '0' && c <= '9') {
+ return c - '0';
+ }
+ EXPECT_TRUE(c >= 'a' && c <= 'f');
+ return c - 'a' + 10;
+}
+
+extern std::string g_source_dir;
+
+void WycheproofHeader(const std::string& name, const std::string& algorithm,
+ const std::string& schema,
+ std::function<void(JsonReader& r)> group_handler) {
+ std::string basename = name + "_test.json";
+ std::string dir = ::g_source_dir + "/../common/wycheproof/source_vectors/";
+ std::cout << "Reading tests from: " << basename << std::endl;
+
+ JsonReader r(dir + basename);
+ while (r.NextItem()) {
+ std::string n = r.ReadLabel();
+ if (n == "") {
+ break;
+ }
+ if (n == "algorithm") {
+ ASSERT_EQ(algorithm, r.ReadString());
+ } else if (n == "generatorVersion" || n == "numberOfTests") {
+ r.SkipValue();
+ } else if (n == "header") {
+ while (r.NextItemArray()) {
+ std::cout << " " << r.ReadString() << std::endl;
+ }
+ } else if (n == "notes") {
+ while (r.NextItem()) {
+ std::string note = r.ReadLabel();
+ if (note == "") {
+ break;
+ }
+ std::cout << " " << note << ": " << r.ReadString() << std::endl;
+ }
+ } else if (n == "schema") {
+ ASSERT_EQ(schema, r.ReadString());
+ } else if (n == "testGroups") {
+ while (r.NextItemArray()) {
+ group_handler(r);
+ }
+ } else {
+ FAIL() << "unknown value in header";
+ }
+ }
+}