Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eb02bf25 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Perform sanity checks on generated P256 points" into main am: 83ef19fb am: a251c1a2

parents b1ce274f a251c1a2
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -2232,6 +2232,33 @@ void KeyMintAidlTestBase::assert_mgf_digests_present_or_not_in_key_characteristi

namespace {

std::optional<std::string> validateP256Point(const std::vector<uint8_t>& x_buffer,
                                             const std::vector<uint8_t>& y_buffer) {
    auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
    if (group.get() == nullptr) {
        return "Error creating EC group by curve name for prime256v1";
    }

    auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
    BIGNUM_Ptr x(BN_bin2bn(x_buffer.data(), x_buffer.size(), nullptr));
    BIGNUM_Ptr y(BN_bin2bn(y_buffer.data(), y_buffer.size(), nullptr));
    if (!EC_POINT_set_affine_coordinates_GFp(group.get(), point.get(), x.get(), y.get(), nullptr)) {
        return "Failed to set affine coordinates.";
    }
    if (!EC_POINT_is_on_curve(group.get(), point.get(), nullptr)) {
        return "Point is not on curve.";
    }
    if (EC_POINT_is_at_infinity(group.get(), point.get())) {
        return "Point is at infinity.";
    }
    const auto* generator = EC_GROUP_get0_generator(group.get());
    if (!EC_POINT_cmp(group.get(), generator, point.get(), nullptr)) {
        return "Point is equal to generator.";
    }

    return std::nullopt;
}

void check_cose_key(const vector<uint8_t>& data, bool testMode) {
    auto [parsedPayload, __, payloadParseErr] = cppbor::parse(data);
    ASSERT_TRUE(parsedPayload) << "Key parse failed: " << payloadParseErr;
@@ -2265,6 +2292,24 @@ void check_cose_key(const vector<uint8_t>& data, bool testMode) {
                             "  -3 : \\{(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}\\},\n"  // pub_y: data
                             "\\}"));
    }

    ASSERT_TRUE(parsedPayload->asMap()) << "CBOR item was not a map";

    ASSERT_TRUE(parsedPayload->asMap()->get(CoseKey::Label::PUBKEY_X))
            << "CBOR map did not contain x coordinate of public key";
    ASSERT_TRUE(parsedPayload->asMap()->get(CoseKey::Label::PUBKEY_X)->asBstr())
            << "x coordinate of public key was not a bstr";
    const auto& x = parsedPayload->asMap()->get(CoseKey::Label::PUBKEY_X)->asBstr()->value();

    ASSERT_TRUE(parsedPayload->asMap()->get(CoseKey::Label::PUBKEY_Y))
            << "CBOR map did not contain y coordinate of public key";
    ASSERT_TRUE(parsedPayload->asMap()->get(CoseKey::Label::PUBKEY_Y)->asBstr())
            << "y coordinate of public key was not a bstr";
    const auto& y = parsedPayload->asMap()->get(CoseKey::Label::PUBKEY_Y)->asBstr()->value();

    auto errorMessage = validateP256Point(x, y);
    EXPECT_EQ(errorMessage, std::nullopt)
            << *errorMessage << " x: " << bin2hex(x) << " y: " << bin2hex(y);
}

}  // namespace
+26 −0
Original line number Diff line number Diff line
@@ -416,6 +416,32 @@ TEST_P(GenerateKeyTests, generateEcdsaP256Key_testMode) {
    check_maced_pubkey(macedPubKey, testMode, nullptr);
}

/**
 * Generate and validate at most 2**16 production-mode keys. This aims to catch issues that do not
 * deterministically show up. In practice, this will test far fewer keys, but a certain number are
 * tested at a minimum.
 */
TEST_P(GenerateKeyTests, generateManyEcdsaP256KeysInProdMode) {
    const auto start = std::chrono::steady_clock::now();
    const auto time_bound = std::chrono::seconds(5);
    const auto upper_bound = 1 << 16;
    const auto lower_bound = 1 << 8;
    for (auto iteration = 0; iteration < upper_bound; iteration++) {
        MacedPublicKey macedPubKey;
        bytevec privateKeyBlob;
        bool testMode = false;
        auto status =
                provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
        ASSERT_TRUE(status.isOk());
        vector<uint8_t> coseKeyData;
        check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
        const auto current_time = std::chrono::steady_clock::now() - start;
        if (iteration >= lower_bound && current_time >= time_bound) {
            break;
        }
    }
}

class CertificateRequestTestBase : public VtsRemotelyProvisionedComponentTests {
  protected:
    CertificateRequestTestBase()