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