| // Copyright 2025 The BoringSSL Authors | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // https://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| #include <memory> | |
| #include <string> | |
| #include <string_view> | |
| #include <vector> | |
| #include <string.h> | |
| #include "../../../../crypto/fipsmodule/entropy/sha512.cc.inc" | |
| #include "../modulewrapper/modulewrapper.h" | |
| BSSL_NAMESPACE_BEGIN | |
| namespace acvp { | |
| static bool GetConfig(const Span<const uint8_t> args[], | |
| ReplyCallback write_reply) { | |
| static constexpr char kConfig[] = | |
| R"([ | |
| { | |
| "algorithm": "acvptool", | |
| "features": ["batch"] | |
| }, | |
| { | |
| "algorithm": "SHA2-384", | |
| "revision": "1.0", | |
| "messageLength": [{ | |
| "min": 0, "max": 65528, "increment": 8 | |
| }] | |
| } | |
| ])"; | |
| return write_reply({StringAsBytes(kConfig)}); | |
| } | |
| constexpr size_t DigestLength = 48; | |
| static void HashSHA384(uint8_t *out_digest, Span<const uint8_t> input) { | |
| entropy::SHA512_CTX ctx; | |
| entropy::SHA384_Init(&ctx); | |
| entropy::SHA384_Update(&ctx, input.data(), input.size()); | |
| entropy::SHA384_Final(out_digest, &ctx); | |
| } | |
| static bool SHA384(const Span<const uint8_t> args[], | |
| ReplyCallback write_reply) { | |
| uint8_t digest[DigestLength]; | |
| HashSHA384(digest, args[0]); | |
| return write_reply({Span<const uint8_t>(digest)}); | |
| } | |
| static bool SHA384MCT(const Span<const uint8_t> args[], | |
| ReplyCallback write_reply) { | |
| if (args[0].size() != DigestLength) { | |
| return false; | |
| } | |
| uint8_t buf[DigestLength * 3]; | |
| memcpy(buf, args[0].data(), DigestLength); | |
| memcpy(buf + DigestLength, args[0].data(), DigestLength); | |
| memcpy(buf + 2 * DigestLength, args[0].data(), DigestLength); | |
| for (size_t i = 0; i < 1000; i++) { | |
| uint8_t digest[DigestLength]; | |
| HashSHA384(digest, buf); | |
| memmove(buf, buf + DigestLength, DigestLength * 2); | |
| memcpy(buf + DigestLength * 2, digest, DigestLength); | |
| } | |
| return write_reply({Span(buf).subspan(2 * DigestLength, DigestLength)}); | |
| } | |
| static constexpr struct { | |
| char name[kMaxNameLength + 1]; | |
| uint8_t num_expected_args; | |
| bool (*handler)(const Span<const uint8_t> args[], ReplyCallback write_reply); | |
| } kFunctions[] = { | |
| {"getConfig", 0, GetConfig}, | |
| {"SHA2-384", 1, SHA384}, | |
| {"SHA2-384/MCT", 1, SHA384MCT}, | |
| }; | |
| Handler FindHandler(Span<const Span<const uint8_t>> args) { | |
| auto algorithm = BytesAsStringView(args[0]); | |
| for (const auto &func : kFunctions) { | |
| if (algorithm == func.name) { | |
| if (args.size() - 1 != func.num_expected_args) { | |
| fprintf(stderr, | |
| "\'%s\' operation received %zu arguments but expected %u.\n", | |
| func.name, args.size() - 1, func.num_expected_args); | |
| return nullptr; | |
| } | |
| return func.handler; | |
| } | |
| } | |
| fprintf(stderr, "Unknown operation: %s\n", std::string(algorithm).c_str()); | |
| return nullptr; | |
| } | |
| } // namespace acvp | |
| BSSL_NAMESPACE_END |