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

Commit d42cb6fa authored by David Drysdale's avatar David Drysdale Committed by Hasini Gunasinghe
Browse files

authgraph: add parallel session VTS tests

Test: VtsAidlAuthGraphSessionTest
Change-Id: Idcf79afe838fdbfb88bd7f43fe758ac03d9ba0d1
parent c8625a89
Loading
Loading
Loading
Loading
+165 −0
Original line number Diff line number Diff line
@@ -166,6 +166,171 @@ TEST_P(AuthGraphSessionTest, Mainline) {
    // encoded as `sink_info.sharedKeys` and `source_info.sharedKeys`.
}

TEST_P(AuthGraphSessionTest, ParallelSink) {
    std::shared_ptr<IAuthGraphKeyExchange> source = authNode_;
    std::shared_ptr<IAuthGraphKeyExchange> sink1 = authNode_;
    std::shared_ptr<IAuthGraphKeyExchange> sink2 = authNode_;

    // Step 1: create ephemeral ECDH keys at the source.
    SessionInitiationInfo source_init1_info;
    ASSERT_EQ(OK, GetReturnError(source->create(&source_init1_info)));
    ASSERT_TRUE(source_init1_info.key.pubKey.has_value());
    ASSERT_TRUE(source_init1_info.key.arcFromPBK.has_value());
    SessionInitiationInfo source_init2_info;
    ASSERT_EQ(OK, GetReturnError(source->create(&source_init2_info)));
    ASSERT_TRUE(source_init2_info.key.pubKey.has_value());
    ASSERT_TRUE(source_init2_info.key.arcFromPBK.has_value());

    // Step 2: pass the source's ECDH public keys and other session info to the sinks.
    KeInitResult init1_result;
    ASSERT_EQ(OK, GetReturnError(sink1->init(source_init1_info.key.pubKey.value(),
                                             source_init1_info.identity, source_init1_info.nonce,
                                             source_init1_info.version, &init1_result)));
    SessionInitiationInfo sink1_init_info = init1_result.sessionInitiationInfo;
    ASSERT_TRUE(sink1_init_info.key.pubKey.has_value());

    SessionInfo sink1_info = init1_result.sessionInfo;
    ASSERT_EQ((int)sink1_info.sharedKeys.size(), 2) << "Expect two symmetric keys from init()";
    ASSERT_GT((int)sink1_info.sessionId.size(), 0) << "Expect non-empty session ID from sink";
    std::vector<uint8_t> sink1_signing_key = SigningKeyFromIdentity(sink1_init_info.identity);
    CheckSignature(sink1_signing_key, sink1_info.sessionId, sink1_info.signature);
    KeInitResult init2_result;
    ASSERT_EQ(OK, GetReturnError(sink2->init(source_init2_info.key.pubKey.value(),
                                             source_init2_info.identity, source_init2_info.nonce,
                                             source_init2_info.version, &init2_result)));
    SessionInitiationInfo sink2_init_info = init2_result.sessionInitiationInfo;
    ASSERT_TRUE(sink2_init_info.key.pubKey.has_value());

    SessionInfo sink2_info = init2_result.sessionInfo;
    ASSERT_EQ((int)sink2_info.sharedKeys.size(), 2) << "Expect two symmetric keys from init()";
    ASSERT_GT((int)sink2_info.sessionId.size(), 0) << "Expect non-empty session ID from sink";
    std::vector<uint8_t> sink2_signing_key = SigningKeyFromIdentity(sink2_init_info.identity);
    CheckSignature(sink2_signing_key, sink2_info.sessionId, sink2_info.signature);

    // Step 3: pass each sink's ECDH public key and other session info to the source, so it can
    // calculate the same pair of symmetric keys.
    SessionInfo source_info1;
    ASSERT_EQ(OK, GetReturnError(source->finish(sink1_init_info.key.pubKey.value(),
                                                sink1_init_info.identity, sink1_info.signature,
                                                sink1_init_info.nonce, sink1_init_info.version,
                                                source_init1_info.key, &source_info1)));
    ASSERT_EQ((int)source_info1.sharedKeys.size(), 2) << "Expect two symmetric keys from finsh()";
    ASSERT_GT((int)source_info1.sessionId.size(), 0) << "Expect non-empty session ID from source";
    std::vector<uint8_t> source_signing_key1 = SigningKeyFromIdentity(source_init1_info.identity);
    CheckSignature(source_signing_key1, source_info1.sessionId, source_info1.signature);
    SessionInfo source_info2;
    ASSERT_EQ(OK, GetReturnError(source->finish(sink2_init_info.key.pubKey.value(),
                                                sink2_init_info.identity, sink2_info.signature,
                                                sink2_init_info.nonce, sink2_init_info.version,
                                                source_init2_info.key, &source_info2)));
    ASSERT_EQ((int)source_info2.sharedKeys.size(), 2) << "Expect two symmetric keys from finsh()";
    ASSERT_GT((int)source_info2.sessionId.size(), 0) << "Expect non-empty session ID from source";
    std::vector<uint8_t> source_signing_key2 = SigningKeyFromIdentity(source_init2_info.identity);
    CheckSignature(source_signing_key2, source_info2.sessionId, source_info2.signature);

    // Both ends should agree on the session ID.
    ASSERT_EQ(source_info1.sessionId, sink1_info.sessionId);
    ASSERT_EQ(source_info2.sessionId, sink2_info.sessionId);

    // Step 4: pass the source's session ID info back to the sink, so it can check it and
    // update the symmetric keys so they're marked as authentication complete.
    std::array<Arc, 2> auth_complete_result1;
    ASSERT_EQ(OK, GetReturnError(sink1->authenticationComplete(
                          source_info1.signature, sink1_info.sharedKeys, &auth_complete_result1)));
    ASSERT_EQ((int)auth_complete_result1.size(), 2)
            << "Expect two symmetric keys from authComplete()";
    sink1_info.sharedKeys = auth_complete_result1;
    std::array<Arc, 2> auth_complete_result2;
    ASSERT_EQ(OK, GetReturnError(sink2->authenticationComplete(
                          source_info2.signature, sink2_info.sharedKeys, &auth_complete_result2)));
    ASSERT_EQ((int)auth_complete_result2.size(), 2)
            << "Expect two symmetric keys from authComplete()";
    sink2_info.sharedKeys = auth_complete_result2;
}

TEST_P(AuthGraphSessionTest, ParallelSource) {
    std::shared_ptr<IAuthGraphKeyExchange> source1 = authNode_;
    std::shared_ptr<IAuthGraphKeyExchange> source2 = authNode_;
    std::shared_ptr<IAuthGraphKeyExchange> sink = authNode_;

    // Step 1: create an ephemeral ECDH key at each of the sources.
    SessionInitiationInfo source1_init_info;
    ASSERT_EQ(OK, GetReturnError(source1->create(&source1_init_info)));
    ASSERT_TRUE(source1_init_info.key.pubKey.has_value());
    ASSERT_TRUE(source1_init_info.key.arcFromPBK.has_value());
    SessionInitiationInfo source2_init_info;
    ASSERT_EQ(OK, GetReturnError(source1->create(&source2_init_info)));
    ASSERT_TRUE(source2_init_info.key.pubKey.has_value());
    ASSERT_TRUE(source2_init_info.key.arcFromPBK.has_value());

    // Step 2: pass each source's ECDH public key and other session info to the sink.
    KeInitResult init1_result;
    ASSERT_EQ(OK, GetReturnError(sink->init(source1_init_info.key.pubKey.value(),
                                            source1_init_info.identity, source1_init_info.nonce,
                                            source1_init_info.version, &init1_result)));
    SessionInitiationInfo sink_init1_info = init1_result.sessionInitiationInfo;
    ASSERT_TRUE(sink_init1_info.key.pubKey.has_value());

    SessionInfo sink_info1 = init1_result.sessionInfo;
    ASSERT_EQ((int)sink_info1.sharedKeys.size(), 2) << "Expect two symmetric keys from init()";
    ASSERT_GT((int)sink_info1.sessionId.size(), 0) << "Expect non-empty session ID from sink";
    std::vector<uint8_t> sink_signing_key1 = SigningKeyFromIdentity(sink_init1_info.identity);
    CheckSignature(sink_signing_key1, sink_info1.sessionId, sink_info1.signature);

    KeInitResult init2_result;
    ASSERT_EQ(OK, GetReturnError(sink->init(source2_init_info.key.pubKey.value(),
                                            source2_init_info.identity, source2_init_info.nonce,
                                            source2_init_info.version, &init2_result)));
    SessionInitiationInfo sink_init2_info = init2_result.sessionInitiationInfo;
    ASSERT_TRUE(sink_init2_info.key.pubKey.has_value());

    SessionInfo sink_info2 = init2_result.sessionInfo;
    ASSERT_EQ((int)sink_info2.sharedKeys.size(), 2) << "Expect two symmetric keys from init()";
    ASSERT_GT((int)sink_info2.sessionId.size(), 0) << "Expect non-empty session ID from sink";
    std::vector<uint8_t> sink_signing_key2 = SigningKeyFromIdentity(sink_init2_info.identity);
    CheckSignature(sink_signing_key2, sink_info2.sessionId, sink_info2.signature);

    // Step 3: pass the sink's ECDH public keys and other session info to the each of the sources.
    SessionInfo source1_info;
    ASSERT_EQ(OK, GetReturnError(source1->finish(sink_init1_info.key.pubKey.value(),
                                                 sink_init1_info.identity, sink_info1.signature,
                                                 sink_init1_info.nonce, sink_init1_info.version,
                                                 source1_init_info.key, &source1_info)));
    ASSERT_EQ((int)source1_info.sharedKeys.size(), 2) << "Expect two symmetric keys from finsh()";
    ASSERT_GT((int)source1_info.sessionId.size(), 0) << "Expect non-empty session ID from source";
    std::vector<uint8_t> source1_signing_key = SigningKeyFromIdentity(source1_init_info.identity);
    CheckSignature(source1_signing_key, source1_info.sessionId, source1_info.signature);

    SessionInfo source2_info;
    ASSERT_EQ(OK, GetReturnError(source2->finish(sink_init2_info.key.pubKey.value(),
                                                 sink_init2_info.identity, sink_info2.signature,
                                                 sink_init2_info.nonce, sink_init2_info.version,
                                                 source2_init_info.key, &source2_info)));
    ASSERT_EQ((int)source2_info.sharedKeys.size(), 2) << "Expect two symmetric keys from finsh()";
    ASSERT_GT((int)source2_info.sessionId.size(), 0) << "Expect non-empty session ID from source";
    std::vector<uint8_t> source2_signing_key = SigningKeyFromIdentity(source2_init_info.identity);
    CheckSignature(source2_signing_key, source2_info.sessionId, source2_info.signature);

    // Both ends should agree on the session ID.
    ASSERT_EQ(source1_info.sessionId, sink_info1.sessionId);
    ASSERT_EQ(source2_info.sessionId, sink_info2.sessionId);

    // Step 4: pass the each source's session ID info back to the sink, so it can check it and
    // update the symmetric keys so they're marked as authentication complete.
    std::array<Arc, 2> auth_complete_result1;
    ASSERT_EQ(OK, GetReturnError(sink->authenticationComplete(
                          source1_info.signature, sink_info1.sharedKeys, &auth_complete_result1)));
    ASSERT_EQ((int)auth_complete_result1.size(), 2)
            << "Expect two symmetric keys from authComplete()";
    sink_info1.sharedKeys = auth_complete_result1;
    std::array<Arc, 2> auth_complete_result2;
    ASSERT_EQ(OK, GetReturnError(sink->authenticationComplete(
                          source2_info.signature, sink_info2.sharedKeys, &auth_complete_result2)));
    ASSERT_EQ((int)auth_complete_result2.size(), 2)
            << "Expect two symmetric keys from authComplete()";
    sink_info2.sharedKeys = auth_complete_result2;
}

TEST_P(AuthGraphSessionTest, FreshNonces) {
    std::shared_ptr<IAuthGraphKeyExchange> source = authNode_;
    std::shared_ptr<IAuthGraphKeyExchange> sink = authNode_;