chromium/device/fido/win/logging.cc

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "device/fido/win/logging.h"

#include <string>
#include <string_view>

#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "components/device_event_log/device_event_log.h"

namespace {

constexpr char kSep[] = ", ";

// Quoted wraps |in| in double quotes and backslash-escapes all other double
// quote characters.
std::string Quoted(std::string_view in) {
  std::string result;
  base::ReplaceChars(in, "\\", "\\\\", &result);
  base::ReplaceChars(result, "\"", "\\\"", &result);
  return "\"" + result + "\"";
}

std::wstring Quoted(std::wstring_view in) {
  std::wstring result;
  base::ReplaceChars(in, L"\\", L"\\\\", &result);
  base::ReplaceChars(result, L"\"", L"\\\"", &result);
  return L"\"" + result + L"\"";
}

std::wstring Quoted(const wchar_t* in) {
  return Quoted(std::wstring_view(in ? in : L""));
}

}  // namespace

std::ostream& operator<<(std::ostream& out,
                         const WEBAUTHN_RP_ENTITY_INFORMATION& in) {
  return out << "{" << in.dwVersion << kSep << Quoted(in.pwszId) << kSep
             << Quoted(in.pwszName) << "}";
}

std::ostream& operator<<(std::ostream& out,
                         const WEBAUTHN_USER_ENTITY_INFORMATION& in) {
  return out << "{" << in.dwVersion << kSep << base::HexEncode(in.pbId, in.cbId)
             << kSep << Quoted(in.pwszName) << kSep
             << Quoted(in.pwszDisplayName) << "}";
}

std::ostream& operator<<(std::ostream& out,
                         const WEBAUTHN_COSE_CREDENTIAL_PARAMETER& in) {
  return out << "{" << in.dwVersion << kSep << Quoted(in.pwszCredentialType)
             << kSep << in.lAlg << "}";
}

std::ostream& operator<<(std::ostream& out,
                         const WEBAUTHN_COSE_CREDENTIAL_PARAMETERS& in) {
  out << "{" << in.cCredentialParameters << ", &[";
  for (size_t i = 0; i < in.cCredentialParameters; ++i) {
    out << (i ? kSep : "") << in.pCredentialParameters[i];
  }
  return out << "]}";
}

std::ostream& operator<<(std::ostream& out, const WEBAUTHN_CLIENT_DATA& in) {
  return out << "{" << in.dwVersion << kSep
             << Quoted({reinterpret_cast<char*>(in.pbClientDataJSON),
                        in.cbClientDataJSON})
             << kSep << Quoted(in.pwszHashAlgId) << "}";
}

std::ostream& operator<<(std::ostream& out, const WEBAUTHN_CREDENTIAL& in) {
  return out << "{" << in.dwVersion << kSep << base::HexEncode(in.pbId, in.cbId)
             << kSep << Quoted(in.pwszCredentialType) << "}";
}

std::ostream& operator<<(std::ostream& out, const WEBAUTHN_CREDENTIALS& in) {
  out << "{" << in.cCredentials << ", &[";
  for (size_t i = 0; i < in.cCredentials; ++i) {
    out << (i ? kSep : "") << in.pCredentials[i];
  }
  return out << "]}";
}

std::ostream& operator<<(std::ostream& out, const WEBAUTHN_CREDENTIAL_EX& in) {
  return out << "{" << in.dwVersion << kSep << base::HexEncode(in.pbId, in.cbId)
             << kSep << Quoted(in.pwszCredentialType) << kSep << in.dwTransports
             << "}";
}

std::ostream& operator<<(std::ostream& out,
                         const WEBAUTHN_CREDENTIAL_LIST& in) {
  out << "{" << in.cCredentials << ", &[";
  for (size_t i = 0; i < in.cCredentials; ++i) {
    out << (i ? kSep : "") << "&" << *in.ppCredentials[i];
  }
  return out << "]}";
}

std::ostream& operator<<(std::ostream& out, const WEBAUTHN_EXTENSION& in) {
  return out << "{" << Quoted(in.pwszExtensionIdentifier) << kSep
             << base::HexEncode(in.pvExtension, in.cbExtension) << "}";
}

std::ostream& operator<<(std::ostream& out, const WEBAUTHN_EXTENSIONS& in) {
  out << "{" << in.cExtensions << ", &[";
  for (size_t i = 0; i < in.cExtensions; ++i) {
    out << (i ? kSep : "") << in.pExtensions[i];
  }
  return out << "]}";
}

std::ostream& operator<<(std::ostream& out,
                         const WEBAUTHN_HMAC_SECRET_SALT& in) {
  // The salts may be considered sensitive, and this structure is also reused
  // for the outputs, so only the lengths are logged.
  return out << "{[" << in.cbFirst << "]" << kSep << "[" << in.cbSecond << "]}";
}

std::ostream& operator<<(std::ostream& out,
                         const WEBAUTHN_CRED_WITH_HMAC_SECRET_SALT& in) {
  return out << "{" << base::HexEncode(in.pbCredID, in.cbCredID) << kSep << "&"
             << *in.pHmacSecretSalt << "}";
}

std::ostream& operator<<(std::ostream& out,
                         const WEBAUTHN_HMAC_SECRET_SALT_VALUES& in) {
  out << "{";
  if (in.pGlobalHmacSalt) {
    out << "&" << *in.pGlobalHmacSalt;
  } else {
    out << "(null)";
  }
  out << kSep << "[";
  for (DWORD i = 0; i < in.cCredWithHmacSecretSaltList; i++) {
    out << (i ? kSep : "") << in.pCredWithHmacSecretSaltList[i];
  }
  return out << "]}";
}

std::ostream& operator<<(
    std::ostream& out,
    const WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS& in) {
  out << "{" << in.dwVersion << kSep << in.dwTimeoutMilliseconds << kSep
      << in.CredentialList << kSep << in.Extensions << kSep
      << in.dwAuthenticatorAttachment << kSep
      << in.dwUserVerificationRequirement << kSep << in.dwFlags;
  if (in.dwVersion < WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_2) {
    return out << "}";
  }
  out << kSep << Quoted(in.pwszU2fAppId);
  if (in.pbU2fAppId) {
    out << ", &" << *in.pbU2fAppId;
  } else {
    out << ", (null)";
  }
  if (in.dwVersion < WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_3) {
    return out << "}";
  }
  if (in.pAllowCredentialList) {
    out << ", &" << *in.pAllowCredentialList;
  } else {
    out << ", (null)";
  }
  if (in.dwVersion < WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_5) {
    return out << "}";
  }
  out << kSep << in.dwCredLargeBlobOperation << "(";
  if (in.cbCredLargeBlob) {
    out << base::HexEncode(in.pbCredLargeBlob, in.cbCredLargeBlob) << ")";
  } else {
    out << "null)";
  }
  if (in.dwVersion < WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_6) {
    return out << "}";
  }
  if (in.pHmacSecretSaltValues) {
    out << ", &" << *in.pHmacSecretSaltValues;
  } else {
    out << ", (null)";
  }
  return out << "}";
}

std::ostream& operator<<(
    std::ostream& out,
    const WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS& in) {
  out << "{" << in.dwVersion << kSep << in.dwTimeoutMilliseconds << kSep
      << in.CredentialList << kSep << in.Extensions << kSep
      << in.dwAuthenticatorAttachment << kSep << in.bRequireResidentKey << kSep
      << in.dwUserVerificationRequirement << kSep
      << in.dwAttestationConveyancePreference << kSep << in.dwFlags;
  if (in.dwVersion < WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_2) {
    return out << "}";
  }
  out << kSep << in.pCancellationId;
  if (in.dwVersion < WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_3) {
    return out << "}";
  }
  if (in.pExcludeCredentialList) {
    out << ", &" << *in.pExcludeCredentialList;
  } else {
    out << ", (null)";
  }
  if (in.dwVersion < WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_4) {
    return out << "}";
  }
  out << kSep << in.dwLargeBlobSupport;
  return out << "}";
}

std::ostream& operator<<(std::ostream& out,
                         const WEBAUTHN_CREDENTIAL_ATTESTATION& in) {
  out << "{" << in.dwVersion << kSep << Quoted(in.pwszFormatType) << kSep
      << base::HexEncode(in.pbAuthenticatorData, in.cbAuthenticatorData) << kSep
      << base::HexEncode(in.pbAttestation, in.cbAttestation) << kSep
      << in.dwAttestationDecodeType << kSep
      << base::HexEncode(in.pbAttestationObject, in.cbAttestationObject) << kSep
      << base::HexEncode(in.pbCredentialId, in.cbCredentialId);
  if (in.dwVersion < WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_2) {
    return out << "}";
  }
  out << kSep << in.Extensions;
  if (in.dwVersion < WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_3) {
    return out << "}";
  }
  out << kSep << in.dwUsedTransport;
  if (in.dwVersion < WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_4) {
    return out << "}";
  }
  out << kSep << in.bLargeBlobSupported;
  return out << "}";
}

std::ostream& operator<<(std::ostream& out, const WEBAUTHN_ASSERTION& in) {
  out << "{" << in.dwVersion << kSep
      << base::HexEncode(in.pbAuthenticatorData, in.cbAuthenticatorData) << kSep
      << base::HexEncode(in.pbSignature, in.cbSignature) << kSep
      << in.Credential << kSep << base::HexEncode(in.pbUserId, in.cbUserId);
  if (in.dwVersion < WEBAUTHN_ASSERTION_VERSION_2) {
    return out << "}";
  }
  out << in.Extensions;
  out << kSep << in.dwCredLargeBlobStatus << " (";
  if (in.pbCredLargeBlob) {
    out << base::HexEncode(in.pbCredLargeBlob, in.cbCredLargeBlob) << ")";
  } else {
    out << "null)";
  }
  if (in.dwVersion < WEBAUTHN_ASSERTION_VERSION_3) {
    return out << "}";
  }
  if (in.pHmacSecret) {
    out << kSep << "&" << *in.pHmacSecret;
  } else {
    out << ", (null)";
  }
  return out << "}";
}

std::ostream& operator<<(std::ostream& out,
                         const WEBAUTHN_GET_CREDENTIALS_OPTIONS& in) {
  out << "{" << in.dwVersion << kSep;
  if (in.pwszRpId) {
    out << in.pwszRpId;
  } else {
    out << "(null)";
  }
  return out << kSep << in.bBrowserInPrivateMode << "}";
}