proxygen
Signature.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-present, Facebook, Inc.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree.
7  */
8 
11 
12 #include <folly/Conv.h>
13 #include <folly/ScopeGuard.h>
15 
16 using namespace folly;
17 using namespace folly::ssl;
18 
19 namespace fizz {
20 namespace detail {
21 
22 static const EVP_MD* getHash(int hashNid) {
23  const auto hash = EVP_get_digestbynid(hashNid);
24  if (!hash) {
25  throw std::runtime_error("Invalid hash. Have you initialized openssl?");
26  }
27  return hash;
28 }
29 
30 std::unique_ptr<folly::IOBuf> ecSign(
32  const folly::ssl::EvpPkeyUniquePtr& pkey,
33  int hashNid) {
35  if (!mdCtx) {
36  throw std::runtime_error(
37  to<std::string>("Could not allocate EVP_MD_CTX", getOpenSSLError()));
38  }
39 
40  auto hash = getHash(hashNid);
41 
42  if (EVP_SignInit(mdCtx.get(), hash) != 1) {
43  throw std::runtime_error("Could not initialize signature");
44  }
45  if (EVP_SignUpdate(mdCtx.get(), data.data(), data.size()) != 1) {
46  throw std::runtime_error(
47  to<std::string>("Could not sign data ", getOpenSSLError()));
48  }
49  auto out = folly::IOBuf::create(EVP_PKEY_size(pkey.get()));
50  unsigned int bytesWritten = 0;
51  if (EVP_SignFinal(
52  mdCtx.get(), out->writableData(), &bytesWritten, pkey.get()) != 1) {
53  throw std::runtime_error("Failed to sign");
54  }
55  out->append(bytesWritten);
56  return out;
57 }
58 
59 void ecVerify(
61  folly::ByteRange signature,
62  const folly::ssl::EvpPkeyUniquePtr& pkey,
63  int hashNid) {
64  auto hash = getHash(hashNid);
66  if (!mdCtx) {
67  throw std::runtime_error(
68  to<std::string>("Could not allocate EVP_MD_CTX", getOpenSSLError()));
69  }
70 
71  if (EVP_VerifyInit(mdCtx.get(), hash) != 1) {
72  throw std::runtime_error("Could not initialize verification");
73  }
74 
75  if (EVP_VerifyUpdate(mdCtx.get(), data.data(), data.size()) != 1) {
76  throw std::runtime_error("Could not update verification");
77  }
78 
79  if (EVP_VerifyFinal(
80  mdCtx.get(), signature.data(), signature.size(), pkey.get()) != 1) {
81  throw std::runtime_error("Signature verification failed");
82  }
83 }
84 
85 std::unique_ptr<folly::IOBuf> rsaPssSign(
87  const folly::ssl::EvpPkeyUniquePtr& pkey,
88  int hashNid) {
89  auto hash = getHash(hashNid);
91  if (!mdCtx) {
92  throw std::runtime_error(
93  to<std::string>("Could not allocate EVP_MD_CTX", getOpenSSLError()));
94  }
95 
96  EVP_PKEY_CTX* ctx;
97  if (EVP_DigestSignInit(mdCtx.get(), &ctx, hash, nullptr, pkey.get()) != 1) {
98  throw std::runtime_error("Could not initialize signature");
99  }
100 
101  if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0) {
102  throw std::runtime_error("Could not set pss padding");
103  }
104 
105  if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -1) <= 0) {
106  throw std::runtime_error("Could not set pss salt length");
107  }
108 
109  if (EVP_DigestSignUpdate(mdCtx.get(), data.data(), data.size()) != 1) {
110  throw std::runtime_error("Could not update signature");
111  }
112 
113  size_t bytesWritten = EVP_PKEY_size(pkey.get());
114  auto out = folly::IOBuf::create(bytesWritten);
115  if (EVP_DigestSignFinal(mdCtx.get(), out->writableData(), &bytesWritten) !=
116  1) {
117  throw std::runtime_error("Failed to sign");
118  }
119  out->append(bytesWritten);
120  return out;
121 }
122 
125  folly::ByteRange signature,
126  const folly::ssl::EvpPkeyUniquePtr& pkey,
127  int hashNid) {
128  auto hash = getHash(hashNid);
130  if (!mdCtx) {
131  throw std::runtime_error(
132  to<std::string>("Could not allocate EVP_MD_CTX", getOpenSSLError()));
133  }
134 
135  EVP_PKEY_CTX* ctx;
136  if (EVP_DigestVerifyInit(mdCtx.get(), &ctx, hash, nullptr, pkey.get()) != 1) {
137  throw std::runtime_error("Could not initialize verification");
138  }
139 
140  if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0) {
141  throw std::runtime_error("Could not set pss padding");
142  }
143 
144  if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -1) <= 0) {
145  throw std::runtime_error("Could not set pss salt length");
146  }
147 
148  if (EVP_DigestVerifyUpdate(mdCtx.get(), data.data(), data.size()) != 1) {
149  throw std::runtime_error("Could not update verification");
150  }
151 
152  if (EVP_DigestVerifyFinal(mdCtx.get(), signature.data(), signature.size()) !=
153  1) {
154  throw std::runtime_error("Signature verification failed");
155  }
156 }
157 } // namespace detail
158 } // namespace fizz
static std::unique_ptr< IOBuf > create(std::size_t capacity)
Definition: IOBuf.cpp:229
void rsaPssVerify(folly::ByteRange data, folly::ByteRange signature, const folly::ssl::EvpPkeyUniquePtr &pkey, int hashNid)
Definition: Signature.cpp:123
static const EVP_MD * getHash(int hashNid)
Definition: Signature.cpp:22
constexpr size_type size() const
Definition: Range.h:431
std::unique_ptr< EVP_PKEY, EvpPkeyDeleter > EvpPkeyUniquePtr
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
constexpr Iter data() const
Definition: Range.h:446
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
std::unique_ptr< folly::IOBuf > ecSign(folly::ByteRange data, const folly::ssl::EvpPkeyUniquePtr &pkey, int hashNid)
Definition: Signature.cpp:30
Definition: Actions.h:16
std::string getOpenSSLError()
void ecVerify(folly::ByteRange data, folly::ByteRange signature, const folly::ssl::EvpPkeyUniquePtr &pkey, int hashNid)
Definition: Signature.cpp:59
EVP_MD_CTX * EVP_MD_CTX_new()
Definition: OpenSSL.cpp:321
std::unique_ptr< EVP_MD_CTX, EvpMdCtxDeleter > EvpMdCtxUniquePtr
std::unique_ptr< folly::IOBuf > rsaPssSign(folly::ByteRange data, const folly::ssl::EvpPkeyUniquePtr &pkey, int hashNid)
Definition: Signature.cpp:85