openCACAO / cocoa-issues

接触確認アプリ COCOA に関するIssues用レポジトリです
Creative Commons Zero v1.0 Universal
8 stars 0 forks source link

偽装RPI問題 #30

Open moonmile opened 4 years ago

moonmile commented 4 years ago

参照先

moonmile commented 4 years ago

あたりをチェック。

moonmile commented 4 years ago

I hava a question that

https://github.com/google/exposure-notifications-internals/blob/main/exposurenotification/src/main/cpp/matching_helper.cc#L116 in MatchingHelper::Matching

          if (GenerateIds(key->key_data.bytes,
                          static_cast<uint32_t>(key->rolling_start_interval_number),
                          ids)) {

ここで暗号化した RPis が ids に入る

https://github.com/google/exposure-notifications-internals/blob/main/exposurenotification/src/main/cpp/matching_helper.cc#L90 in MatchingHelper::GenerateIds

      return EVP_EncryptUpdate(&context, ids, &out_length, aesInputStorage,
                               kIdPerKey * kIdLength) == 1;

ids is 144*16-byte. So ids[j] is RPI_j = 16-bytes. encrypted by AES128.

ids は 144*15 バイトの暗号化後のデータ

https://github.com/google/exposure-notifications-internals/blob/main/exposurenotification/src/main/cpp/matching_helper.cc#L119 in MatchingHelper::Matching

            for (int j = 0; j < kIdPerKey * kIdLength; j += kIdLength) {
              if (prefix_key_map->GetIdIndex(&ids[j]) >= 0) {   // top of ids[j]
                matched_keys.emplace_back(std::move(key));
                break;
              }
            }

ids を使って、scan_records と比較する。 scan_records は、Bluetooth で取得したデータ。先頭の2バイトに通番(時刻?)が入っているらしい。

https://github.com/google/exposure-notifications-internals/blob/main/exposurenotification/src/main/cpp/prefix_id_map.cc#L69 in prefix_id_map.cc

    int PrefixIdMap::GetIdIndex(const uint8_t *id) {
      int prefix = GetPrefix(id);     // prefix is *(uint16_t*)ids[j] ???
      int start_index = (prefix > 0) ? prefix_end_index[prefix - 1] : 0;
      int end_index = prefix_end_index[prefix];
      for (; start_index < end_index; start_index++) {
        if (memcmp(id, scan_records[start_index].data(), exposure::kIdLength) ==
            0) {
          return start_index;
        }
      }
      return -1;
    }

Why do it compare 'prefix' and (uint16_t)&ids[j] ??? ids[j] is RPI_j encrypted by AES128.

なので、GetIdIndex で prefix というのは、RPI の先頭2バイトを取ってきているだけなんだが、 ここのコードの意味がわかりません。

ひょっとして、ids[j] の先頭の2バイトに scan_records のように2バイトの番号が入っていると想定している?

moonmile commented 4 years ago

仮に matching_helper.cc が古くて、prefix_id_map.cc が新しいと仮定しても,

prefix_id_map.cc

        if (memcmp(id, scan_records[start_index].data(), exposure::kIdLength) ==
            0) {
          return start_index;
        }

のところで、exposure::kIdLength = 16 なので、何故か先頭を含めて16バイトで比較しているし、挙動が謎過ぎる。

moonmile commented 4 years ago

ひとまず、Android のほうは大丈夫そう、という結論で一旦締め。 Apple のほうは、念のため該当コードのチェック。

ドイツで似た感じのツールを作っている方がいたので、参考まで。