chromium/third_party/private_membership/src/internal/crypto_utils.cc

// Copyright 2020 Google LLC
//
// 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 "third_party/private_membership/src/internal/crypto_utils.h"

#include <string>

#include "third_party/private_membership/src/internal/aes_ctr_256_with_fixed_iv.h"
#include "third_party/private_membership/src/internal/id_utils.h"
#include "third_party/shell-encryption/src/status_macros.h"

namespace private_membership {
namespace {

std::string LengthToBytes(uint32_t length) {
  uint8_t ret[4];
  ret[0] = length & 0xFF;
  ret[1] = (length >> 8) & 0xFF;
  ret[2] = (length >> 16) & 0xFF;
  ret[3] = (length >> 24) & 0xFF;
  return std::string(ret, ret + 4);
}

::rlwe::StatusOr<uint32_t> BytesToLength(absl::string_view bytes) {
  if (bytes.size() != 4) {
    return absl::InvalidArgumentError("Invalid byte size of length encoding.");
  }
  uint32_t ret = 0;
  ret += static_cast<uint8_t>(bytes[0]);
  ret += (static_cast<uint8_t>(bytes[1]) << 8);
  ret += (static_cast<uint8_t>(bytes[2]) << 16);
  ret += (static_cast<uint8_t>(bytes[3]) << 24);
  return ret;
}

}  // namespace

::rlwe::StatusOr<std::string> Pad(absl::string_view bytes,
                                  int max_byte_length) {
  if (max_byte_length < bytes.length()) {
    return absl::InvalidArgumentError(
        "max_byte_length smaller than the input bytes length.");
  }
  // Prepend byte length of value into the first four bytes. This limits the
  // maximum length of the value to at most 2^32 bytes or ~4.3 gigabytes.
  std::string length_in_byte = LengthToBytes(bytes.length());
  std::string padded_bytes =
      std::string(bytes).append(max_byte_length - bytes.length(), 0);
  return absl::StrCat(length_in_byte, padded_bytes);
}

::rlwe::StatusOr<std::string> Unpad(absl::string_view bytes) {
  if (bytes.length() < 4) {
    return absl::InvalidArgumentError("Invalid bytes does not encode length.");
  }
  RLWE_ASSIGN_OR_RETURN(uint32_t bytes_length,
                        BytesToLength(bytes.substr(0, 4)));
  if (bytes_length + 4 > bytes.length()) {
    return absl::InvalidArgumentError("Incorrect bytes length.");
  }
  return std::string(bytes.substr(4, bytes_length));
}

std::string HashEncryptedId(absl::string_view encrypted_id,
                            ::private_join_and_compute::Context* ctx) {
  // Salt used in SHA256 hash function for creating sensitive matching
  // identifier. Randomly generated salt forcing adversaries to re-compute
  // rainbow tables.
  static constexpr unsigned char kSensitiveIdHashSalt[] = {
      0x3C, 0xD1, 0xF3, 0x69, 0x2B, 0x57, 0x40, 0xEA, 0xD8, 0xE4, 0xF4,
      0x4A, 0xB2, 0x5F, 0x7B, 0xAD, 0xC8, 0x10, 0xAA, 0x3D, 0x4C, 0x6E,
      0xCA, 0x57, 0x78, 0x5C, 0x5A, 0xED, 0x06, 0x81, 0x14, 0x7C};
  return ctx->Sha256String(absl::StrCat(
      std::string(reinterpret_cast<const char*>(kSensitiveIdHashSalt), 32),
      encrypted_id));
}

::rlwe::StatusOr<std::string> GetValueEncryptionKey(
    absl::string_view encrypted_id, ::private_join_and_compute::Context* ctx) {
  // Salt user in SHA256 hash function to generate value encryption key.
  // Randomly generated salt forcing adversaries to re-compute rainbow tables.
  static constexpr unsigned char kValueEncryptionKeyHashSalt[] = {
      0x89, 0xC3, 0x67, 0xA7, 0x8A, 0x68, 0x2B, 0xE8, 0xC6, 0xB2, 0x22,
      0xB7, 0xE0, 0xB7, 0x4A, 0x37, 0x63, 0x8F, 0x10, 0x79, 0x98, 0x91,
      0x31, 0x94, 0x44, 0x03, 0xB6, 0x76, 0x8F, 0x70, 0xEB, 0xBF};
  // AES key length in bytes.
  static constexpr int kRequiredAesKeyLength = 32;
  return PadOrTruncate(
      ctx->Sha256String(absl::StrCat(
          std::string(
              reinterpret_cast<const char*>(kValueEncryptionKeyHashSalt), 32),
          encrypted_id)),
      kRequiredAesKeyLength);
}

::rlwe::StatusOr<std::string> EncryptValue(absl::string_view encrypted_id,
                                           absl::string_view value,
                                           uint32_t max_value_byte_length,
                                           ::private_join_and_compute::Context* ctx) {
  if (value.length() > max_value_byte_length) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Length of value ", value.length(), " larger than maximum value byte ",
        "length ", max_value_byte_length, "."));
  }
  RLWE_ASSIGN_OR_RETURN(auto value_encryption_key,
                        GetValueEncryptionKey(encrypted_id, ctx));
  RLWE_ASSIGN_OR_RETURN(auto aes_ctr,
                        AesCtr256WithFixedIV::Create(value_encryption_key));
  RLWE_ASSIGN_OR_RETURN(std::string plaintext,
                        Pad(value, max_value_byte_length));
  return aes_ctr->Encrypt(plaintext);
}

::rlwe::StatusOr<std::string> DecryptValue(absl::string_view encrypted_id,
                                           absl::string_view encrypted_value,
                                           ::private_join_and_compute::Context* ctx) {
  RLWE_ASSIGN_OR_RETURN(auto value_encryption_key,
                        GetValueEncryptionKey(encrypted_id, ctx));
  return DecryptValueWithKey(value_encryption_key, encrypted_value, ctx);
}

::rlwe::StatusOr<std::string> DecryptValueWithKey(
    absl::string_view encryption_key, absl::string_view encrypted_value,
    ::private_join_and_compute::Context* ctx) {
  RLWE_ASSIGN_OR_RETURN(auto aes_ctr,
                        AesCtr256WithFixedIV::Create(encryption_key));
  RLWE_ASSIGN_OR_RETURN(std::string plaintext,
                        aes_ctr->Decrypt(encrypted_value));
  return Unpad(plaintext);
}

}  // namespace private_membership