CCF
Loading...
Searching...
No Matches
public_key.h
Go to the documentation of this file.
1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the Apache 2.0 License.
3#pragma once
4
6
7#include <openssl/evp.h>
8#include <stdexcept>
9#include <string>
10
11namespace ccf::crypto
12{
14 {
15 protected:
16 // The key is always owned by the PublicKey_OpenSSL instance
17 // even when passed to the constructor, and is disposed of
18 // by the PublicKey_OpenSSL destructor.
19 EVP_PKEY* key = nullptr;
20
21 public:
22 PublicKey_OpenSSL() = default;
23 PublicKey_OpenSSL(EVP_PKEY* key) : key(key) {}
25 {
26 OpenSSL::Unique_BIO mem(pem);
27 key = PEM_read_bio_PUBKEY(mem, nullptr, nullptr, nullptr);
28 if (key == nullptr)
29 {
30 throw std::runtime_error("could not parse PEM");
31 }
32 }
33
34 void check_is_cose_compatible(int cose_alg)
35 {
36 if (key == nullptr)
37 {
38 throw std::logic_error("Public key is not initialized");
39 }
40
41 const int key_type = EVP_PKEY_get_base_id(key);
42
43 if (key_type == EVP_PKEY_EC)
44 {
45 // Get the curve name
46 size_t gname_len = 0;
47 OpenSSL::CHECK1(EVP_PKEY_get_group_name(key, nullptr, 0, &gname_len));
48 std::string gname(gname_len + 1, '\0');
50 EVP_PKEY_get_group_name(key, gname.data(), gname.size(), &gname_len));
51 gname.resize(gname_len);
52
53 // Map curve to COSE algorithm
54 if (gname == SN_X9_62_prime256v1) // P-256
55 {
56 if (cose_alg != -7)
57 {
58 throw std::domain_error(fmt::format(
59 "secp256r1 key cannot be used with COSE algorithm {}", cose_alg));
60 }
61 }
62 else if (gname == SN_secp384r1) // P-384
63 {
64 if (cose_alg != -35)
65 {
66 throw std::domain_error(fmt::format(
67 "secp384r1 key cannot be used with COSE algorithm {}", cose_alg));
68 }
69 }
70 else if (gname == SN_secp521r1) // P-521
71 {
72 if (cose_alg != -36)
73 {
74 throw std::domain_error(fmt::format(
75 "secp521r1 key cannot be used with COSE algorithm {}", cose_alg));
76 }
77 }
78 else
79 {
80 throw std::domain_error(
81 fmt::format("Unsupported EC curve: {}", gname));
82 }
83 }
84 else if (key_type == EVP_PKEY_RSA || key_type == EVP_PKEY_RSA_PSS)
85 {
86 // It is RECOMMENDED although not required to match hash function and
87 // key sizes, so any of PS256(-37), PS384(-38), and PS512(-39) is
88 // acceptable.
89 //
90 // https://www.iana.org/assignments/cose/cose.xhtml
91 if (cose_alg != -37 && cose_alg != -38 && cose_alg != -39)
92 {
93 throw std::domain_error(
94 fmt::format("Incompatible cose algorithm {} for RSA", cose_alg));
95 }
96 }
97 else
98 {
99 throw std::domain_error(
100 fmt::format("Unsupported key type {}", key_type));
101 }
102 }
103
104 operator EVP_PKEY*() const
105 {
106 return key;
107 }
108
110 {
111 if (key != nullptr)
112 {
113 EVP_PKEY_free(key);
114 }
115 }
116 };
117}
Definition pem.h:18
Definition public_key.h:14
PublicKey_OpenSSL(const Pem &pem)
Definition public_key.h:24
virtual ~PublicKey_OpenSSL()
Definition public_key.h:109
void check_is_cose_compatible(int cose_alg)
Definition public_key.h:34
PublicKey_OpenSSL(EVP_PKEY *key)
Definition public_key.h:23
EVP_PKEY * key
Definition public_key.h:19
void CHECK1(int rc)
Throws if rc is not 1 and has error.
Definition openssl_wrappers.h:54
Definition base64.h:10
Definition openssl_wrappers.h:159