proxygen
TokenBindingConstructor.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 
9 // Copyright 2004-present Facebook. All Rights Reserved.
10 
12 
13 #include <fizz/crypto/Sha256.h>
16 
17 using namespace folly;
18 using namespace folly::io;
19 using namespace folly::ssl;
20 
21 namespace fizz {
22 namespace extensions {
23 
24 TokenBinding TokenBindingConstructor::createTokenBinding(
25  EVP_PKEY& keyPair,
26  const Buf& ekm,
27  TokenBindingKeyParameters negotiatedParameters,
29  if (negotiatedParameters != TokenBindingKeyParameters::ecdsap256) {
30  throw std::runtime_error(folly::to<std::string>(
31  "key params not implemented: ", negotiatedParameters));
32  }
33 
34  EcKeyUniquePtr ecKey(EVP_PKEY_get1_EC_KEY(&keyPair));
35  if (!ecKey) {
36  throw std::runtime_error("Unable to retrieve EC Key");
37  }
38 
39  TokenBinding binding;
40  binding.tokenbinding_type = type;
41  binding.extensions = folly::IOBuf::create(0);
42 
43  auto message =
44  TokenBindingUtils::constructMessage(type, negotiatedParameters, ekm);
45  binding.signature = signWithEcKey(ecKey, message);
46 
47  TokenBindingID id;
48  id.key_parameters = negotiatedParameters;
49  id.key = encodeEcKey(ecKey);
50  binding.tokenbindingid = std::move(id);
51  return binding;
52 }
53 
54 Buf TokenBindingConstructor::signWithEcKey(
55  const EcKeyUniquePtr& key,
56  const Buf& message) {
57  std::array<uint8_t, fizz::Sha256::HashLen> hashedMessage;
59  *message,
60  folly::MutableByteRange(hashedMessage.data(), hashedMessage.size()));
61 
62  EcdsaSigUniquePtr ecSignature(
63  ECDSA_do_sign(hashedMessage.data(), hashedMessage.size(), key.get()));
64  if (!ecSignature.get()) {
65  throw std::runtime_error("Unable to sign message with EC Key");
66  }
67 
68  return encodeEcdsaSignature(ecSignature);
69 }
70 
71 Buf TokenBindingConstructor::encodeEcdsaSignature(
72  const EcdsaSigUniquePtr& signature) {
73  BIGNUM* r;
74  BIGNUM* s;
75  ECDSA_SIG_get0(signature.get(), (const BIGNUM**)&r, (const BIGNUM**)&s);
76  if (!r || !s) {
77  throw std::runtime_error("Unable to retrieve Bignum from ECDSA sig");
78  }
79 
80  Buf encodedSignature =
81  folly::IOBuf::create(TokenBindingUtils::kP256EcKeySize);
82  addBignumToSignature(encodedSignature, r);
83  addBignumToSignature(encodedSignature, s);
84  return encodedSignature;
85 }
86 
87 void TokenBindingConstructor::addBignumToSignature(
88  const Buf& signature,
89  BIGNUM* bigNum) {
90  auto length = BN_num_bytes(bigNum);
91  if (length > TokenBindingUtils::kP256EcKeySize / 2) {
92  throw std::runtime_error("ECDSA sig bignum is of incorrect size");
93  }
94  // if a bignum is less than 32 bytes long, it has a most significant byte
95  // of 0, so we have to pad the buffer
96  size_t padding = (TokenBindingUtils::kP256EcKeySize / 2) - length;
97  std::memset(signature->writableTail(), 0x00, padding);
98  signature->append(padding);
99 
100  auto lenActual = BN_bn2bin(bigNum, signature->writableTail());
101  signature->append(lenActual);
102  if (lenActual != length) {
103  throw std::runtime_error("bn2bin returned unexpected value");
104  }
105 }
106 
107 Buf TokenBindingConstructor::encodeEcKey(const EcKeyUniquePtr& ecKey) {
108  auto ecKeyBuf = detail::encodeECPublicKey(ecKey);
109  if (ecKeyBuf->isChained() ||
110  ecKeyBuf->length() != TokenBindingUtils::kP256EcKeySize + 1) {
111  throw std::runtime_error("Incorrect encoded EC Key Length");
112  }
113  ecKeyBuf->writableData()[0] = TokenBindingUtils::kP256EcKeySize;
114  return ecKeyBuf;
115 }
116 } // namespace extensions
117 } // namespace fizz
Definition: test.c:42
void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
Definition: OpenSSL.cpp:417
static std::unique_ptr< IOBuf > create(std::size_t capacity)
Definition: IOBuf.cpp:229
PskType type
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
TokenBindingType tokenbinding_type
Definition: Types.h:57
TokenBindingKeyParameters
Definition: Types.h:33
std::unique_ptr< ECDSA_SIG, EcdsaSigDeleter > EcdsaSigUniquePtr
std::unique_ptr< EC_KEY, EcKeyDeleter > EcKeyUniquePtr
Definition: Actions.h:16
static void hash(const folly::IOBuf &in, folly::MutableByteRange out)
TokenBindingKeyParameters key_parameters
Definition: Types.h:47
TokenBindingID tokenbindingid
Definition: Types.h:58
std::unique_ptr< folly::IOBuf > Buf
Definition: Types.h:22
static set< string > s
std::unique_ptr< folly::IOBuf > encodeECPublicKey(const folly::ssl::EvpPkeyUniquePtr &key)