xref: /aosp_15_r20/external/openscreen/util/crypto/pem_helpers.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #include "util/crypto/pem_helpers.h"
6*3f982cf4SFabien Sanglard 
7*3f982cf4SFabien Sanglard #include <openssl/bytestring.h>
8*3f982cf4SFabien Sanglard #include <openssl/pem.h>
9*3f982cf4SFabien Sanglard #include <openssl/rsa.h>
10*3f982cf4SFabien Sanglard #include <stdio.h>
11*3f982cf4SFabien Sanglard #include <string.h>
12*3f982cf4SFabien Sanglard 
13*3f982cf4SFabien Sanglard #include "absl/strings/match.h"
14*3f982cf4SFabien Sanglard #include "util/osp_logging.h"
15*3f982cf4SFabien Sanglard 
16*3f982cf4SFabien Sanglard namespace openscreen {
17*3f982cf4SFabien Sanglard 
ReadCertificatesFromPemFile(absl::string_view filename)18*3f982cf4SFabien Sanglard std::vector<std::string> ReadCertificatesFromPemFile(
19*3f982cf4SFabien Sanglard     absl::string_view filename) {
20*3f982cf4SFabien Sanglard   FILE* fp = fopen(filename.data(), "r");
21*3f982cf4SFabien Sanglard   if (!fp) {
22*3f982cf4SFabien Sanglard     return {};
23*3f982cf4SFabien Sanglard   }
24*3f982cf4SFabien Sanglard   std::vector<std::string> certs;
25*3f982cf4SFabien Sanglard   char* name;
26*3f982cf4SFabien Sanglard   char* header;
27*3f982cf4SFabien Sanglard   unsigned char* data;
28*3f982cf4SFabien Sanglard   long length;  // NOLINT
29*3f982cf4SFabien Sanglard   while (PEM_read(fp, &name, &header, &data, &length) == 1) {
30*3f982cf4SFabien Sanglard     if (absl::StartsWith(name, "CERTIFICATE")) {
31*3f982cf4SFabien Sanglard       certs.emplace_back(reinterpret_cast<char*>(data), length);
32*3f982cf4SFabien Sanglard     }
33*3f982cf4SFabien Sanglard     OPENSSL_free(name);
34*3f982cf4SFabien Sanglard     OPENSSL_free(header);
35*3f982cf4SFabien Sanglard     OPENSSL_free(data);
36*3f982cf4SFabien Sanglard   }
37*3f982cf4SFabien Sanglard   fclose(fp);
38*3f982cf4SFabien Sanglard   return certs;
39*3f982cf4SFabien Sanglard }
40*3f982cf4SFabien Sanglard 
ReadKeyFromPemFile(absl::string_view filename)41*3f982cf4SFabien Sanglard bssl::UniquePtr<EVP_PKEY> ReadKeyFromPemFile(absl::string_view filename) {
42*3f982cf4SFabien Sanglard   FILE* fp = fopen(filename.data(), "r");
43*3f982cf4SFabien Sanglard   if (!fp) {
44*3f982cf4SFabien Sanglard     return nullptr;
45*3f982cf4SFabien Sanglard   }
46*3f982cf4SFabien Sanglard   bssl::UniquePtr<EVP_PKEY> pkey;
47*3f982cf4SFabien Sanglard   char* name;
48*3f982cf4SFabien Sanglard   char* header;
49*3f982cf4SFabien Sanglard   unsigned char* data;
50*3f982cf4SFabien Sanglard   long length;  // NOLINT
51*3f982cf4SFabien Sanglard   while (PEM_read(fp, &name, &header, &data, &length) == 1) {
52*3f982cf4SFabien Sanglard     if (absl::StartsWith(name, "RSA PRIVATE KEY")) {
53*3f982cf4SFabien Sanglard       OSP_DCHECK(!pkey);
54*3f982cf4SFabien Sanglard       CBS cbs;
55*3f982cf4SFabien Sanglard       CBS_init(&cbs, data, length);
56*3f982cf4SFabien Sanglard       RSA* rsa = RSA_parse_private_key(&cbs);
57*3f982cf4SFabien Sanglard       if (rsa) {
58*3f982cf4SFabien Sanglard         pkey.reset(EVP_PKEY_new());
59*3f982cf4SFabien Sanglard         EVP_PKEY_assign_RSA(pkey.get(), rsa);
60*3f982cf4SFabien Sanglard       }
61*3f982cf4SFabien Sanglard     }
62*3f982cf4SFabien Sanglard     OPENSSL_free(name);
63*3f982cf4SFabien Sanglard     OPENSSL_free(header);
64*3f982cf4SFabien Sanglard     OPENSSL_free(data);
65*3f982cf4SFabien Sanglard   }
66*3f982cf4SFabien Sanglard   fclose(fp);
67*3f982cf4SFabien Sanglard   return pkey;
68*3f982cf4SFabien Sanglard }
69*3f982cf4SFabien Sanglard 
70*3f982cf4SFabien Sanglard }  // namespace openscreen
71