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