1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  *
7  */
8 
9 #include <quic/fizz/server/handshake/FizzServerHandshake.h>
10 
11 #include <quic/fizz/handshake/FizzBridge.h>
12 #include <quic/fizz/server/handshake/AppToken.h>
13 #include <quic/fizz/server/handshake/FizzServerQuicHandshakeContext.h>
14 
15 #include <fizz/protocol/Protocol.h>
16 #include <fizz/server/State.h>
17 
18 // This is necessary for the conversion between QuicServerConnectionState and
19 // QuicConnectionStateBase and can be removed once ServerHandshake accepts
20 // QuicServerConnectionState.
21 #include <quic/server/state/ServerStateMachine.h>
22 
23 namespace fizz {
24 namespace server {
25 struct ResumptionState;
26 } // namespace server
27 } // namespace fizz
28 
29 namespace {
30 class FailingAppTokenValidator : public fizz::server::AppTokenValidator {
validate(const fizz::server::ResumptionState &) const31   bool validate(const fizz::server::ResumptionState&) const override {
32     return false;
33   }
34 };
35 } // namespace
36 
37 namespace quic {
38 
FizzServerHandshake(QuicServerConnectionState * conn,std::shared_ptr<FizzServerQuicHandshakeContext> fizzContext,std::unique_ptr<CryptoFactory> cryptoFactory)39 FizzServerHandshake::FizzServerHandshake(
40     QuicServerConnectionState* conn,
41     std::shared_ptr<FizzServerQuicHandshakeContext> fizzContext,
42     std::unique_ptr<CryptoFactory> cryptoFactory)
43     : ServerHandshake(conn), fizzContext_(std::move(fizzContext)) {
44   CryptoFactory* cryptoFactoryPtr = cryptoFactory.release();
45   auto* fizzCryptoFactoryPtr =
46       dynamic_cast<FizzCryptoFactory*>(cryptoFactoryPtr);
47   if (!fizzCryptoFactoryPtr) {
48     cryptoFactory_ = std::make_unique<FizzCryptoFactory>();
49   } else {
50     cryptoFactory_.reset(fizzCryptoFactoryPtr);
51   }
52   CHECK(cryptoFactory_ && cryptoFactory_->getFizzFactory());
53 }
54 
initializeImpl(HandshakeCallback * callback,std::unique_ptr<fizz::server::AppTokenValidator> validator)55 void FizzServerHandshake::initializeImpl(
56     HandshakeCallback* callback,
57     std::unique_ptr<fizz::server::AppTokenValidator> validator) {
58   auto context = std::make_shared<fizz::server::FizzServerContext>(
59       *fizzContext_->getContext());
60   context->setFactory(cryptoFactory_->getFizzFactory());
61   context->setSupportedCiphers({{fizz::CipherSuite::TLS_AES_128_GCM_SHA256}});
62   context->setVersionFallbackEnabled(false);
63   // Since Draft-17, client won't sent EOED
64   context->setOmitEarlyRecordLayer(true);
65   state_.context() = std::move(context);
66   callback_ = callback;
67 
68   if (validator) {
69     state_.appTokenValidator() = std::move(validator);
70   } else {
71     state_.appTokenValidator() = std::make_unique<FailingAppTokenValidator>();
72   }
73 }
74 
getCryptoFactory() const75 const CryptoFactory& FizzServerHandshake::getCryptoFactory() const {
76   return *cryptoFactory_;
77 }
78 
getContext() const79 const fizz::server::FizzServerContext* FizzServerHandshake::getContext() const {
80   return state_.context();
81 }
82 
getReadRecordLayerEncryptionLevel()83 EncryptionLevel FizzServerHandshake::getReadRecordLayerEncryptionLevel() {
84   return getEncryptionLevelFromFizz(
85       state_.readRecordLayer()->getEncryptionLevel());
86 }
87 
processSocketData(folly::IOBufQueue & queue)88 void FizzServerHandshake::processSocketData(folly::IOBufQueue& queue) {
89   startActions(
90       machine_.processSocketData(state_, queue, fizz::Aead::AeadOptions()));
91 }
92 
93 std::pair<std::unique_ptr<Aead>, std::unique_ptr<PacketNumberCipher>>
buildCiphers(folly::ByteRange secret)94 FizzServerHandshake::buildCiphers(folly::ByteRange secret) {
95   auto aead = FizzAead::wrap(fizz::Protocol::deriveRecordAeadWithLabel(
96       *state_.context()->getFactory(),
97       *state_.keyScheduler(),
98       *state_.cipher(),
99       secret,
100       kQuicKeyLabel,
101       kQuicIVLabel));
102   auto headerCipher = cryptoFactory_->makePacketNumberCipher(secret);
103 
104   return {std::move(aead), std::move(headerCipher)};
105 }
106 
processAccept()107 void FizzServerHandshake::processAccept() {
108   addProcessingActions(machine_.processAccept(
109       state_, executor_, state_.context(), transportParams_));
110 }
111 
processPendingCryptoEvent()112 bool FizzServerHandshake::processPendingCryptoEvent() {
113   if (pendingEvents_.empty()) {
114     return false;
115   }
116 
117   auto write = std::move(pendingEvents_.front());
118   pendingEvents_.pop_front();
119   startActions(machine_.processWriteNewSessionTicket(state_, std::move(write)));
120   return true;
121 }
122 
writeNewSessionTicketToCrypto(const AppToken & appToken)123 void FizzServerHandshake::writeNewSessionTicketToCrypto(
124     const AppToken& appToken) {
125   fizz::WriteNewSessionTicket writeNST;
126   writeNST.appToken = encodeAppToken(appToken);
127   pendingEvents_.push_back(std::move(writeNST));
128 }
129 
130 } // namespace quic
131