absl::Status EcdsaVerifyP1363()

in kmsp11/util/crypto_utils.cc [238:286]


absl::Status EcdsaVerifyP1363(EC_KEY* public_key, const EVP_MD* hash,
                              absl::Span<const uint8_t> digest,
                              absl::Span<const uint8_t> signature) {
  if (digest.length() != EVP_MD_size(hash)) {
    return NewInvalidArgumentError(
        absl::StrFormat("digest length mismatches expected (got %d, want %d)",
                        digest.length(), EVP_MD_size(hash)),
        CKR_DATA_LEN_RANGE, SOURCE_LOCATION);
  }

  if (signature.length() % 2 == 1) {
    return NewInvalidArgumentError(
        absl::StrFormat(
            "signature of length %d contains an uneven number of bytes",
            signature.length()),
        CKR_SIGNATURE_LEN_RANGE, SOURCE_LOCATION);
  }

  size_t max_len = EcdsaSigLengthP1363(EC_KEY_get0_group(public_key));
  if (signature.length() > max_len) {
    return NewInvalidArgumentError(
        absl::StrFormat(
            "provided signature length exceeds maximum (got %d, want <= %d)",
            signature.length(), max_len),
        CKR_SIGNATURE_LEN_RANGE, SOURCE_LOCATION);
  }

  bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new());
  int n_len = signature.length() / 2;

  bssl::UniquePtr<BIGNUM> r(BN_new());
  bssl::UniquePtr<BIGNUM> s(BN_new());
  if (!BN_bin2bn(&signature[0], n_len, r.get()) ||
      !BN_bin2bn(&signature[n_len], n_len, s.get()) ||
      !ECDSA_SIG_set0(sig.get(), r.release(), s.release())) {
    return NewInternalError(
        absl::StrCat("error parsing signature component: ", SslErrorToString()),
        SOURCE_LOCATION);
  }

  if (ECDSA_do_verify(digest.data(), digest.size(), sig.get(), public_key) !=
      1) {
    return NewInvalidArgumentError(
        absl::StrCat("verification failed: ", SslErrorToString()),
        CKR_SIGNATURE_INVALID, SOURCE_LOCATION);
  }

  return absl::OkStatus();
}