| // Copyright 2026 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 "testing/pem.h" |
| |
| #include <cstdint> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| |
| #include "absl/status/status.h" |
| #include "absl/status/status_macros.h" |
| #include "absl/status/statusor.h" |
| #include "absl/strings/string_view.h" |
| #include "openssl/bio.h" |
| #include "openssl/ec.h" |
| #include "openssl/ec_key.h" |
| #include "openssl/evp.h" |
| #include "openssl/mem.h" |
| #include "openssl/nid.h" |
| #include "openssl/obj.h" |
| #include "openssl/pem.h" |
| #include "openssl/x509.h" |
| #include "proto/common.pb.h" |
| #include "tink/cleartext_keyset_handle.h" |
| #include "tink/keyset_handle.h" |
| #include "tink/public_key_sign.h" |
| #include "tink/signature/config_v0.h" |
| #include "tink/signature/signature_pem_keyset_reader.h" |
| |
| namespace credentio { |
| |
| using ::crypto::tink::PemKeyParams; |
| using ::crypto::tink::PublicKeySign; |
| using ::crypto::tink::SignaturePemKeysetReaderBuilder; |
| |
| absl::StatusOr<std::unique_ptr<crypto::tink::PublicKeySign>> LoadTestKeyFromPem( |
| absl::string_view pem, const PemKeyParams& key_params) { |
| crypto::tink::SignaturePemKeysetReaderBuilder builder( |
| SignaturePemKeysetReaderBuilder::PemReaderType::PUBLIC_KEY_SIGN); |
| builder.Add({ |
| .serialized_key = std::string(pem), |
| .parameters = key_params, |
| }); |
| ABSL_ASSIGN_OR_RETURN(auto reader, builder.Build()); |
| ABSL_ASSIGN_OR_RETURN(auto handle, crypto::tink::CleartextKeysetHandle::Read( |
| std::move(reader))); |
| return handle->GetPrimitive<crypto::tink::PublicKeySign>( |
| crypto::tink::ConfigSignatureV0()); |
| } |
| |
| absl::StatusOr<std::string> LoadOcspResponseFromPem(absl::string_view pem) { |
| bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(pem.data(), pem.size())); |
| if (bio == nullptr) { |
| return absl::InternalError("Failed to create BIO."); |
| } |
| |
| std::string response; |
| bool found = false; |
| while (true) { |
| char* name = nullptr; |
| char* header = nullptr; |
| unsigned char* data = nullptr; |
| int64_t len = 0; |
| if (!PEM_read_bio(bio.get(), &name, &header, &data, &len)) { |
| break; |
| } |
| bssl::UniquePtr<char> name_ptr(name); |
| bssl::UniquePtr<char> header_ptr(header); |
| bssl::UniquePtr<unsigned char> data_ptr(data); |
| |
| if (absl::string_view(name) == "OCSP RESPONSE") { |
| if (found) { |
| return absl::InvalidArgumentError( |
| "Multiple OCSP RESPONSE blocks found; expected only one."); |
| } |
| response = std::string(reinterpret_cast<char*>(data), len); |
| found = true; |
| } |
| } |
| |
| if (!found) { |
| return absl::InvalidArgumentError("No OCSP RESPONSE block found."); |
| } |
| |
| return response; |
| } |
| |
| } // namespace credentio |