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 #include <fizz/server/ServerProtocol.h>
10 
11 #include <fizz/crypto/Utils.h>
12 #include <fizz/protocol/CertificateVerifier.h>
13 #include <fizz/protocol/Protocol.h>
14 #include <fizz/protocol/StateMachine.h>
15 #include <fizz/protocol/ech/Decrypter.h>
16 #include <fizz/record/Extensions.h>
17 #include <fizz/record/PlaintextRecordLayer.h>
18 #include <fizz/server/AsyncSelfCert.h>
19 #include <fizz/server/Negotiator.h>
20 #include <fizz/server/ReplayCache.h>
21 #include <fizz/util/Workarounds.h>
22 #include <folly/Overload.h>
23 #include <algorithm>
24 
25 using folly::Future;
26 using folly::Optional;
27 
28 using namespace fizz::server;
29 using namespace fizz::server::detail;
30 
31 // We only ever use the first PSK sent.
32 static constexpr uint16_t kPskIndex = 0;
33 
34 namespace fizz {
35 namespace sm {
36 
37 FIZZ_DECLARE_EVENT_HANDLER(
38     ServerTypes,
39     StateEnum::Uninitialized,
40     Event::Accept,
41     StateEnum::ExpectingClientHello);
42 
43 FIZZ_DECLARE_EVENT_HANDLER(
44     ServerTypes,
45     StateEnum::ExpectingClientHello,
46     Event::ClientHello,
47     StateEnum::ExpectingClientHello,
48     StateEnum::ExpectingCertificate,
49     StateEnum::ExpectingFinished,
50     StateEnum::AcceptingEarlyData,
51     StateEnum::Error);
52 
53 FIZZ_DECLARE_EVENT_HANDLER(
54     ServerTypes,
55     StateEnum::AcceptingEarlyData,
56     Event::AppData,
57     StateEnum::Error);
58 
59 FIZZ_DECLARE_EVENT_HANDLER(
60     ServerTypes,
61     StateEnum::AcceptingEarlyData,
62     Event::AppWrite,
63     StateEnum::Error);
64 
65 FIZZ_DECLARE_EVENT_HANDLER(
66     ServerTypes,
67     StateEnum::AcceptingEarlyData,
68     Event::EndOfEarlyData,
69     StateEnum::ExpectingFinished);
70 
71 FIZZ_DECLARE_EVENT_HANDLER(
72     ServerTypes,
73     StateEnum::ExpectingCertificate,
74     Event::Certificate,
75     StateEnum::ExpectingCertificateVerify,
76     StateEnum::ExpectingFinished)
77 
78 FIZZ_DECLARE_EVENT_HANDLER(
79     ServerTypes,
80     StateEnum::ExpectingCertificateVerify,
81     Event::CertificateVerify,
82     StateEnum::ExpectingFinished);
83 
84 FIZZ_DECLARE_EVENT_HANDLER(
85     ServerTypes,
86     StateEnum::ExpectingFinished,
87     Event::AppWrite,
88     StateEnum::Error);
89 
90 FIZZ_DECLARE_EVENT_HANDLER(
91     ServerTypes,
92     StateEnum::ExpectingFinished,
93     Event::Finished,
94     StateEnum::AcceptingData);
95 
96 FIZZ_DECLARE_EVENT_HANDLER(
97     ServerTypes,
98     StateEnum::AcceptingData,
99     Event::WriteNewSessionTicket,
100     StateEnum::Error);
101 
102 FIZZ_DECLARE_EVENT_HANDLER(
103     ServerTypes,
104     StateEnum::AcceptingData,
105     Event::AppData,
106     StateEnum::Error);
107 
108 FIZZ_DECLARE_EVENT_HANDLER(
109     ServerTypes,
110     StateEnum::AcceptingData,
111     Event::AppWrite,
112     StateEnum::Error);
113 
114 FIZZ_DECLARE_EVENT_HANDLER(
115     ServerTypes,
116     StateEnum::AcceptingData,
117     Event::KeyUpdate,
118     StateEnum::AcceptingData);
119 
120 FIZZ_DECLARE_EVENT_HANDLER(
121     ServerTypes,
122     StateEnum::AcceptingData,
123     Event::CloseNotify,
124     StateEnum::Closed);
125 
126 FIZZ_DECLARE_EVENT_HANDLER(
127     ServerTypes,
128     StateEnum::ExpectingCloseNotify,
129     Event::CloseNotify,
130     StateEnum::Closed);
131 } // namespace sm
132 
133 namespace server {
134 
processAccept(const State & state,folly::Executor * executor,std::shared_ptr<const FizzServerContext> context,const std::shared_ptr<ServerExtensions> & extensions)135 AsyncActions ServerStateMachine::processAccept(
136     const State& state,
137     folly::Executor* executor,
138     std::shared_ptr<const FizzServerContext> context,
139     const std::shared_ptr<ServerExtensions>& extensions) {
140   Accept accept;
141   accept.executor = executor;
142   accept.context = std::move(context);
143   accept.extensions = extensions;
144   return detail::processEvent(state, std::move(accept));
145 }
146 
processSocketData(const State & state,folly::IOBufQueue & buf,Aead::AeadOptions options)147 AsyncActions ServerStateMachine::processSocketData(
148     const State& state,
149     folly::IOBufQueue& buf,
150     Aead::AeadOptions options) {
151   try {
152     if (!state.readRecordLayer()) {
153       return detail::handleError(
154           state,
155           ReportError("attempting to process data without record layer"),
156           folly::none);
157     }
158     auto param = state.readRecordLayer()->readEvent(buf, std::move(options));
159     if (!param.has_value()) {
160       return actions(WaitForData{param.sizeHint});
161     }
162     return detail::processEvent(state, std::move(*param));
163   } catch (const FizzException& e) {
164     return detail::handleError(
165         state,
166         ReportError(folly::exception_wrapper(std::current_exception(), e)),
167         e.getAlert());
168   } catch (const std::exception& e) {
169     return detail::handleError(
170         state,
171         ReportError(folly::make_exception_wrapper<FizzException>(
172             folly::to<std::string>(
173                 "error decoding record in state ",
174                 toString(state.state()),
175                 ": ",
176                 e.what()),
177             AlertDescription::decode_error)),
178         AlertDescription::decode_error);
179   }
180 }
181 
processWriteNewSessionTicket(const State & state,WriteNewSessionTicket write)182 AsyncActions ServerStateMachine::processWriteNewSessionTicket(
183     const State& state,
184     WriteNewSessionTicket write) {
185   return detail::processEvent(state, std::move(write));
186 }
187 
processAppWrite(const State & state,AppWrite write)188 AsyncActions ServerStateMachine::processAppWrite(
189     const State& state,
190     AppWrite write) {
191   return detail::processEvent(state, std::move(write));
192 }
193 
processEarlyAppWrite(const State & state,EarlyAppWrite write)194 AsyncActions ServerStateMachine::processEarlyAppWrite(
195     const State& state,
196     EarlyAppWrite write) {
197   return detail::processEvent(state, std::move(write));
198 }
199 
processAppClose(const State & state)200 Actions ServerStateMachine::processAppClose(const State& state) {
201   return detail::handleAppClose(state);
202 }
203 
processAppCloseImmediate(const State & state)204 Actions ServerStateMachine::processAppCloseImmediate(const State& state) {
205   return detail::handleAppCloseImmediate(state);
206 }
207 
208 namespace detail {
209 
processEvent(const State & state,Param param)210 AsyncActions processEvent(const State& state, Param param) {
211   auto event = EventVisitor()(param);
212   // We can have an exception directly in the handler or in a future so we need
213   // to handle both types.
214   try {
215     auto actions = sm::StateMachine<ServerTypes>::getHandler(
216         state.state(), event)(state, std::move(param));
217 
218     return folly::variant_match(
219         actions,
220         ::fizz::detail::result_type<AsyncActions>(),
221         [&state](folly::Future<Actions>& futureActions) -> AsyncActions {
222           return std::move(futureActions)
223               .thenError([&state](folly::exception_wrapper ew) {
224                 auto ex = ew.get_exception<FizzException>();
225                 if (ex) {
226                   return detail::handleError(
227                       state, ReportError(std::move(ew)), ex->getAlert());
228                 }
229                 return detail::handleError(
230                     state,
231                     ReportError(std::move(ew)),
232                     AlertDescription::unexpected_message);
233               });
234         },
235         [](Actions& immediateActions) -> AsyncActions {
236           return std::move(immediateActions);
237         });
238   } catch (const FizzException& e) {
239     return detail::handleError(
240         state,
241         ReportError(folly::exception_wrapper(std::current_exception(), e)),
242         e.getAlert());
243   } catch (const std::exception& e) {
244     return detail::handleError(
245         state,
246         ReportError(folly::exception_wrapper(std::current_exception(), e)),
247         AlertDescription::unexpected_message);
248   }
249 }
250 
handleError(const State & state,ReportError error,Optional<AlertDescription> alertDesc)251 Actions handleError(
252     const State& state,
253     ReportError error,
254     Optional<AlertDescription> alertDesc) {
255   if (state.state() == StateEnum::Error) {
256     return Actions();
257   }
258   MutateState transition([](State& newState) {
259     newState.state() = StateEnum::Error;
260     newState.writeRecordLayer() = nullptr;
261     newState.readRecordLayer() = nullptr;
262   });
263   if (alertDesc && state.writeRecordLayer()) {
264     Alert alert(*alertDesc);
265     WriteToSocket write;
266     write.contents.emplace_back(
267         state.writeRecordLayer()->writeAlert(std::move(alert)));
268     return actions(std::move(transition), std::move(write), std::move(error));
269   } else {
270     return actions(std::move(transition), std::move(error));
271   }
272 }
273 
handleAppCloseImmediate(const State & state)274 Actions handleAppCloseImmediate(const State& state) {
275   MutateState transition([](State& newState) {
276     newState.state() = StateEnum::Closed;
277     newState.readRecordLayer() = nullptr;
278     newState.writeRecordLayer() = nullptr;
279   });
280 
281   if (state.writeRecordLayer()) {
282     Alert alert(AlertDescription::close_notify);
283     WriteToSocket write;
284     write.contents.emplace_back(
285         state.writeRecordLayer()->writeAlert(std::move(alert)));
286     return actions(std::move(transition), std::move(write));
287   } else {
288     return actions(std::move(transition));
289   }
290 }
291 
handleAppClose(const State & state)292 Actions handleAppClose(const State& state) {
293   if (state.writeRecordLayer()) {
294     MutateState transition([](State& newState) {
295       newState.state() = StateEnum::ExpectingCloseNotify;
296       newState.writeRecordLayer() = nullptr;
297     });
298 
299     Alert alert(AlertDescription::close_notify);
300     WriteToSocket write;
301     write.contents.emplace_back(
302         state.writeRecordLayer()->writeAlert(std::move(alert)));
303     return actions(std::move(transition), std::move(write));
304   } else {
305     MutateState transition([](State& newState) {
306       newState.state() = StateEnum::Closed;
307       newState.writeRecordLayer() = nullptr;
308       newState.readRecordLayer() = nullptr;
309     });
310     return actions(std::move(transition));
311   }
312 }
313 
handleInvalidEvent(const State & state,Event event,Param param)314 Actions handleInvalidEvent(const State& state, Event event, Param param) {
315   if (event == Event::Alert) {
316     auto& alert = *param.asAlert();
317     throw FizzException(
318         folly::to<std::string>(
319             "received alert: ",
320             toString(alert.description),
321             ", in state ",
322             toString(state.state())),
323         folly::none);
324   } else {
325     throw FizzException(
326         folly::to<std::string>(
327             "invalid event: ",
328             toString(event),
329             ", in state ",
330             toString(state.state())),
331         AlertDescription::unexpected_message);
332   }
333 }
334 
335 template <typename T, typename F>
336 folly::Future<
337     typename folly::futures::detail::valueCallableResult<T, F>::value_type>
runOnCallerIfComplete(folly::Executor * executor,folly::Future<T> future,F && func)338 runOnCallerIfComplete(
339     folly::Executor* executor,
340     folly::Future<T> future,
341     F&& func) {
342   if (future.isReady()) {
343     return func(std::move(future).get());
344   } else {
345     return future.via(executor).thenValue(std::forward<F>(func));
346   }
347 }
348 
349 } // namespace detail
350 } // namespace server
351 
352 namespace sm {
353 
ensureNoUnparsedHandshakeData(const State & state,Event event)354 static void ensureNoUnparsedHandshakeData(const State& state, Event event) {
355   if (state.readRecordLayer()->hasUnparsedHandshakeData()) {
356     throw FizzException(
357         folly::to<std::string>(
358             "unprocessed handshake data while handling event ",
359             toString(event),
360             " in state ",
361             toString(state.state())),
362         AlertDescription::unexpected_message);
363   }
364 }
365 
366 AsyncActions
handle(const State &,Param param)367 EventHandler<ServerTypes, StateEnum::Uninitialized, Event::Accept>::handle(
368     const State& /*state*/,
369     Param param) {
370   auto& accept = *param.asAccept();
371   auto factory = accept.context->getFactory();
372   auto readRecordLayer = factory->makePlaintextReadRecordLayer();
373   auto writeRecordLayer = factory->makePlaintextWriteRecordLayer();
374   auto handshakeLogging = std::make_unique<HandshakeLogging>();
375   return actions(
376       MutateState([executor = accept.executor,
377                    rrl = std::move(readRecordLayer),
378                    wrl = std::move(writeRecordLayer),
379                    context = std::move(accept.context),
380                    handshakeLogging = std::move(handshakeLogging),
381                    extensions = accept.extensions](State& newState) mutable {
382         newState.executor() = executor;
383         newState.context() = std::move(context);
384         newState.readRecordLayer() = std::move(rrl);
385         newState.writeRecordLayer() = std::move(wrl);
386         newState.handshakeLogging() = std::move(handshakeLogging);
387         newState.extensions() = std::move(extensions);
388       }),
389       MutateState(&Transition<StateEnum::ExpectingClientHello>));
390 }
391 
addHandshakeLogging(const State & state,const ClientHello & chlo)392 static void addHandshakeLogging(const State& state, const ClientHello& chlo) {
393   auto logging = state.handshakeLogging();
394   if (!logging) {
395     return;
396   }
397   logging->populateFromClientHello(chlo);
398   auto plaintextReadRecord =
399       dynamic_cast<PlaintextReadRecordLayer*>(state.readRecordLayer());
400   if (plaintextReadRecord) {
401     logging->clientRecordVersion =
402         plaintextReadRecord->getReceivedRecordVersion();
403   }
404 }
405 
validateClientHello(const ClientHello & chlo)406 static void validateClientHello(const ClientHello& chlo) {
407   if (chlo.legacy_compression_methods.size() != 1 ||
408       chlo.legacy_compression_methods.front() != 0x00) {
409     throw FizzException(
410         "client compression methods not exactly NULL",
411         AlertDescription::illegal_parameter);
412   }
413   Protocol::checkDuplicateExtensions(chlo.extensions);
414 }
415 
negotiateVersion(const ClientHello & chlo,const std::vector<ProtocolVersion> & versions)416 static Optional<ProtocolVersion> negotiateVersion(
417     const ClientHello& chlo,
418     const std::vector<ProtocolVersion>& versions) {
419   const auto& clientVersions = getExtension<SupportedVersions>(chlo.extensions);
420   if (!clientVersions) {
421     return folly::none;
422   }
423   auto version = negotiate(versions, clientVersions->versions);
424   if (!version) {
425     return folly::none;
426   }
427   return version;
428 }
429 
getCookieState(const ClientHello & chlo,ProtocolVersion version,CipherSuite cipher,const CookieCipher * cookieCipher)430 static Optional<CookieState> getCookieState(
431     const ClientHello& chlo,
432     ProtocolVersion version,
433     CipherSuite cipher,
434     const CookieCipher* cookieCipher) {
435   auto cookieExt = getExtension<Cookie>(chlo.extensions);
436   if (!cookieExt) {
437     return folly::none;
438   }
439 
440   // If the client sent a cookie we can't use we have to consider it a fatal
441   // error since we can't reconstruct the handshake transcript.
442   if (!cookieCipher) {
443     throw FizzException(
444         "no cookie cipher", AlertDescription::unsupported_extension);
445   }
446 
447   auto cookieState = cookieCipher->decrypt(std::move(cookieExt->cookie));
448 
449   if (!cookieState) {
450     throw FizzException(
451         "could not decrypt cookie", AlertDescription::decrypt_error);
452   }
453 
454   if (cookieState->version != version) {
455     throw FizzException(
456         "version mismatch with cookie", AlertDescription::protocol_version);
457   }
458 
459   if (cookieState->cipher != cipher) {
460     throw FizzException(
461         "cipher mismatch with cookie", AlertDescription::handshake_failure);
462   }
463 
464   return cookieState;
465 }
466 
467 namespace {
468 struct ResumptionStateResult {
ResumptionStateResultfizz::sm::__anonfebae84f0911::ResumptionStateResult469   explicit ResumptionStateResult(
470       Future<std::pair<PskType, Optional<ResumptionState>>> futureResStateArg,
471       Optional<PskKeyExchangeMode> pskModeArg = folly::none,
472       Optional<uint32_t> obfuscatedAgeArg = folly::none)
473       : futureResState(std::move(futureResStateArg)),
474         pskMode(std::move(pskModeArg)),
475         obfuscatedAge(std::move(obfuscatedAgeArg)) {}
476 
477   Future<std::pair<PskType, Optional<ResumptionState>>> futureResState;
478   Optional<PskKeyExchangeMode> pskMode;
479   Optional<uint32_t> obfuscatedAge;
480 };
481 } // namespace
482 
getResumptionState(const ClientHello & chlo,const TicketCipher * ticketCipher,const std::vector<PskKeyExchangeMode> & supportedModes)483 static ResumptionStateResult getResumptionState(
484     const ClientHello& chlo,
485     const TicketCipher* ticketCipher,
486     const std::vector<PskKeyExchangeMode>& supportedModes) {
487   auto psks = getExtension<ClientPresharedKey>(chlo.extensions);
488   auto clientModes = getExtension<PskKeyExchangeModes>(chlo.extensions);
489   if (psks && !clientModes) {
490     throw FizzException("no psk modes", AlertDescription::missing_extension);
491   }
492 
493   Optional<PskKeyExchangeMode> pskMode;
494   if (clientModes) {
495     pskMode = negotiate(supportedModes, clientModes->modes);
496   }
497   if (!psks && !pskMode) {
498     return ResumptionStateResult(
499         std::make_pair(PskType::NotSupported, folly::none));
500   } else if (!psks || psks->identities.size() <= kPskIndex) {
501     return ResumptionStateResult(
502         std::make_pair(PskType::NotAttempted, folly::none));
503   } else if (!ticketCipher) {
504     VLOG(8) << "No ticket cipher, rejecting PSK.";
505     return ResumptionStateResult(
506         std::make_pair(PskType::Rejected, folly::none));
507   } else if (!pskMode) {
508     VLOG(8) << "No psk mode match, rejecting PSK.";
509     return ResumptionStateResult(
510         std::make_pair(PskType::Rejected, folly::none));
511   } else {
512     const auto& ident = psks->identities[kPskIndex].psk_identity;
513     return ResumptionStateResult(
514         ticketCipher->decrypt(ident->clone()),
515         pskMode,
516         psks->identities[kPskIndex].obfuscated_ticket_age);
517   }
518 }
519 
getReplayCacheResult(const ClientHello & chlo,bool zeroRttEnabled,ReplayCache * replayCache)520 static Future<ReplayCacheResult> getReplayCacheResult(
521     const ClientHello& chlo,
522     bool zeroRttEnabled,
523     ReplayCache* replayCache) {
524   if (!zeroRttEnabled || !replayCache ||
525       !getExtension<ClientEarlyData>(chlo.extensions)) {
526     return ReplayCacheResult::NotChecked;
527   }
528 
529   return replayCache->check(folly::range(chlo.random));
530 }
531 
validateResumptionState(const ResumptionState & resState,PskKeyExchangeMode,ProtocolVersion version,CipherSuite cipher)532 static bool validateResumptionState(
533     const ResumptionState& resState,
534     PskKeyExchangeMode /* mode */,
535     ProtocolVersion version,
536     CipherSuite cipher) {
537   if (resState.version != version) {
538     VLOG(8) << "Protocol version mismatch, rejecting PSK.";
539     return false;
540   }
541 
542   if (getHashFunction(resState.cipher) != getHashFunction(cipher)) {
543     VLOG(8) << "Hash mismatch, rejecting PSK.";
544     return false;
545   }
546 
547   return true;
548 }
549 
negotiateCipher(const ClientHello & chlo,const std::vector<std::vector<CipherSuite>> & supportedCiphers)550 static CipherSuite negotiateCipher(
551     const ClientHello& chlo,
552     const std::vector<std::vector<CipherSuite>>& supportedCiphers) {
553   auto cipher = negotiate(supportedCiphers, chlo.cipher_suites);
554   if (!cipher) {
555     throw FizzException("no cipher match", AlertDescription::handshake_failure);
556   }
557   return *cipher;
558 }
559 
560 /*
561  * Sets up a KeyScheduler and HandshakeContext for the connection. The
562  * KeyScheduler will have the early secret derived if applicable, and the
563  * ClientHello will be added to the HandshakeContext. This also verifies the
564  * PSK binder if applicable.
565  *
566  * If the passed in handshakeContext is non-null it is used instead of a new
567  * context. This is used after a HelloRetryRequest when there is already a
568  * handshake transcript before the current ClientHello.
569  */
570 static std::
571     pair<std::unique_ptr<KeyScheduler>, std::unique_ptr<HandshakeContext>>
setupSchedulerAndContext(const Factory & factory,CipherSuite cipher,const ClientHello & chlo,const Optional<ResumptionState> & resState,const Optional<CookieState> & cookieState,PskType pskType,std::unique_ptr<HandshakeContext> handshakeContext,ProtocolVersion)572     setupSchedulerAndContext(
573         const Factory& factory,
574         CipherSuite cipher,
575         const ClientHello& chlo,
576         const Optional<ResumptionState>& resState,
577         const Optional<CookieState>& cookieState,
578         PskType pskType,
579         std::unique_ptr<HandshakeContext> handshakeContext,
580         ProtocolVersion /*version*/) {
581   auto scheduler = factory.makeKeyScheduler(cipher);
582 
583   if (cookieState) {
584     if (handshakeContext) {
585       throw FizzException(
586           "cookie after statefull hrr", AlertDescription::illegal_parameter);
587     }
588 
589     handshakeContext = factory.makeHandshakeContext(cipher);
590 
591     message_hash chloHash;
592     chloHash.hash = cookieState->chloHash->clone();
593     handshakeContext->appendToTranscript(encodeHandshake(std::move(chloHash)));
594 
595     auto cookie = getExtension<Cookie>(chlo.extensions);
596     handshakeContext->appendToTranscript(getStatelessHelloRetryRequest(
597         cookieState->version,
598         cookieState->cipher,
599         cookieState->group,
600         std::move(cookie->cookie)));
601   } else if (!handshakeContext) {
602     handshakeContext = factory.makeHandshakeContext(cipher);
603   }
604 
605   if (resState) {
606     scheduler->deriveEarlySecret(resState->resumptionSecret->coalesce());
607 
608     auto binderKey = scheduler
609                          ->getSecret(
610                              pskType == PskType::External
611                                  ? EarlySecrets::ExternalPskBinder
612                                  : EarlySecrets::ResumptionPskBinder,
613                              handshakeContext->getBlankContext())
614                          .secret;
615 
616     folly::IOBufQueue chloQueue(folly::IOBufQueue::cacheChainLength());
617     chloQueue.append((*chlo.originalEncoding)->clone());
618     auto chloPrefix =
619         chloQueue.split(chloQueue.chainLength() - getBinderLength(chlo));
620     handshakeContext->appendToTranscript(chloPrefix);
621 
622     const auto& psks = getExtension<ClientPresharedKey>(chlo.extensions);
623     if (!psks || psks->binders.size() <= kPskIndex) {
624       throw FizzException("no binders", AlertDescription::illegal_parameter);
625     }
626     auto expectedBinder =
627         handshakeContext->getFinishedData(folly::range(binderKey));
628     if (!CryptoUtils::equal(
629             expectedBinder->coalesce(),
630             psks->binders[kPskIndex].binder->coalesce())) {
631       throw FizzException(
632           "binder does not match", AlertDescription::bad_record_mac);
633     }
634 
635     handshakeContext->appendToTranscript(chloQueue.move());
636     return std::make_pair(std::move(scheduler), std::move(handshakeContext));
637   } else {
638     handshakeContext->appendToTranscript(*chlo.originalEncoding);
639     return std::make_pair(std::move(scheduler), std::move(handshakeContext));
640   }
641 }
642 
validateGroups(const std::vector<KeyShareEntry> & client_shares)643 static void validateGroups(const std::vector<KeyShareEntry>& client_shares) {
644   std::set<NamedGroup> setOfNamedGroups;
645 
646   for (const auto& share : client_shares) {
647     if (setOfNamedGroups.find(share.group) != setOfNamedGroups.end()) {
648       throw FizzException(
649           "duplicate client key share", AlertDescription::illegal_parameter);
650     }
651 
652     setOfNamedGroups.insert(share.group);
653   }
654 }
655 
negotiateGroup(ProtocolVersion version,const ClientHello & chlo,const std::vector<NamedGroup> & supportedGroups)656 static std::tuple<NamedGroup, Optional<Buf>> negotiateGroup(
657     ProtocolVersion version,
658     const ClientHello& chlo,
659     const std::vector<NamedGroup>& supportedGroups) {
660   auto groups = getExtension<SupportedGroups>(chlo.extensions);
661   if (!groups) {
662     throw FizzException("no named groups", AlertDescription::missing_extension);
663   }
664   auto group = negotiate(supportedGroups, groups->named_group_list);
665   if (!group) {
666     throw FizzException("no group match", AlertDescription::handshake_failure);
667   }
668   auto clientShares = getExtension<ClientKeyShare>(chlo.extensions);
669   if (!clientShares) {
670     throw FizzException(
671         "no client shares", AlertDescription::missing_extension);
672   }
673 
674   validateGroups(clientShares->client_shares);
675   for (const auto& share : clientShares->client_shares) {
676     if (share.group == *group) {
677       return std::make_tuple(*group, share.key_exchange->clone());
678     }
679   }
680   return std::make_tuple(*group, folly::none);
681 }
682 
doKex(const Factory & factory,NamedGroup group,const Buf & clientShare,KeyScheduler & scheduler)683 static Buf doKex(
684     const Factory& factory,
685     NamedGroup group,
686     const Buf& clientShare,
687     KeyScheduler& scheduler) {
688   auto kex = factory.makeKeyExchange(group);
689   kex->generateKeyPair();
690   auto sharedSecret = kex->generateSharedSecret(clientShare->coalesce());
691   scheduler.deriveHandshakeSecret(sharedSecret->coalesce());
692   return kex->getKeyShare();
693 }
694 
getHelloRetryRequest(ProtocolVersion version,CipherSuite cipher,NamedGroup group,Buf legacySessionId,HandshakeContext & handshakeContext)695 static Buf getHelloRetryRequest(
696     ProtocolVersion version,
697     CipherSuite cipher,
698     NamedGroup group,
699     Buf legacySessionId,
700     HandshakeContext& handshakeContext) {
701   HelloRetryRequest hrr;
702   hrr.legacy_version = ProtocolVersion::tls_1_2;
703   hrr.legacy_session_id_echo = std::move(legacySessionId);
704   hrr.cipher_suite = cipher;
705   ServerSupportedVersions versionExt;
706   versionExt.selected_version = version;
707   hrr.extensions.push_back(encodeExtension(std::move(versionExt)));
708   HelloRetryRequestKeyShare keyShare;
709   keyShare.selected_group = group;
710   hrr.extensions.push_back(encodeExtension(std::move(keyShare)));
711   auto encodedHelloRetryRequest = encodeHandshake(std::move(hrr));
712 
713   handshakeContext.appendToTranscript(encodedHelloRetryRequest);
714   return encodedHelloRetryRequest;
715 }
716 
getServerHello(ProtocolVersion version,Random random,CipherSuite cipher,bool psk,Optional<NamedGroup> group,Optional<Buf> serverShare,Buf legacySessionId,HandshakeContext & handshakeContext)717 static Buf getServerHello(
718     ProtocolVersion version,
719     Random random,
720     CipherSuite cipher,
721     bool psk,
722     Optional<NamedGroup> group,
723     Optional<Buf> serverShare,
724     Buf legacySessionId,
725     HandshakeContext& handshakeContext) {
726   ServerHello serverHello;
727 
728   serverHello.legacy_version = ProtocolVersion::tls_1_2;
729   ServerSupportedVersions versionExt;
730   versionExt.selected_version = version;
731   serverHello.extensions.push_back(encodeExtension(std::move(versionExt)));
732   serverHello.legacy_session_id_echo = std::move(legacySessionId);
733 
734   serverHello.random = std::move(random);
735   serverHello.cipher_suite = cipher;
736   if (group) {
737     ServerKeyShare serverKeyShare;
738     serverKeyShare.server_share.group = *group;
739     serverKeyShare.server_share.key_exchange = std::move(*serverShare);
740 
741     serverHello.extensions.push_back(
742         encodeExtension(std::move(serverKeyShare)));
743   }
744   if (psk) {
745     ServerPresharedKey serverPsk;
746     serverPsk.selected_identity = kPskIndex;
747     serverHello.extensions.push_back(encodeExtension(std::move(serverPsk)));
748   }
749   auto encodedServerHello = encodeHandshake(std::move(serverHello));
750   handshakeContext.appendToTranscript(encodedServerHello);
751   return encodedServerHello;
752 }
753 
negotiateAlpn(const ClientHello & chlo,folly::Optional<std::string> zeroRttAlpn,const FizzServerContext & context)754 static Optional<std::string> negotiateAlpn(
755     const ClientHello& chlo,
756     folly::Optional<std::string> zeroRttAlpn,
757     const FizzServerContext& context) {
758   auto ext = getExtension<ProtocolNameList>(chlo.extensions);
759   std::vector<std::string> clientProtocols;
760   // Check whether client supports ALPN
761   if (ext) {
762     for (auto& protocol : ext->protocol_name_list) {
763       clientProtocols.push_back(protocol.name->moveToFbString().toStdString());
764     }
765   } else {
766     VLOG(6) << "Client did not send ALPN extension";
767     if (context.getAlpnMode() == AlpnMode::Required) {
768       throw FizzException(
769           "ALPN is required", AlertDescription::no_application_protocol);
770     }
771     return folly::none;
772   }
773 
774   // Since both support ALPN, check whether the protocols match.
775   // Server's support for ALPN is to be enforced at the configuration.
776   auto selected = context.negotiateAlpn(clientProtocols, zeroRttAlpn);
777   if (!selected) {
778     VLOG(6) << "ALPN mismatch";
779     if (context.getAlpnMode() != AlpnMode::AllowMismatch) {
780       auto msg = context.getAlpnMode() == AlpnMode::Optional
781           ? "Unable to negotiate ALPN, as required by policy. policy=AlpnMode::Optional"
782           : "Unable to negotiate ALPN, as required by policy. policy=AlpnMode::Required";
783       throw FizzException(msg, AlertDescription::no_application_protocol);
784     }
785   } else {
786     VLOG(6) << "ALPN: " << *selected;
787   }
788   return selected;
789 }
790 
getClockSkew(const Optional<ResumptionState> & psk,Optional<uint32_t> obfuscatedAge,const std::chrono::system_clock::time_point & currentTime)791 static Optional<std::chrono::milliseconds> getClockSkew(
792     const Optional<ResumptionState>& psk,
793     Optional<uint32_t> obfuscatedAge,
794     const std::chrono::system_clock::time_point& currentTime) {
795   if (!psk || !obfuscatedAge) {
796     return folly::none;
797   }
798 
799   auto age = std::chrono::milliseconds(
800       static_cast<uint32_t>(*obfuscatedAge - psk->ticketAgeAdd));
801 
802   auto expected = std::chrono::duration_cast<std::chrono::milliseconds>(
803       currentTime - psk->ticketIssueTime);
804 
805   return std::chrono::milliseconds(age - expected);
806 }
807 
getAppToken(const Optional<ResumptionState> & psk)808 static Optional<Buf> getAppToken(const Optional<ResumptionState>& psk) {
809   if (!psk.has_value() || !psk->appToken) {
810     return folly::none;
811   }
812   return psk->appToken->clone();
813 }
814 
negotiateEarlyDataType(bool acceptEarlyData,const ClientHello & chlo,const Optional<ResumptionState> & psk,CipherSuite cipher,Optional<KeyExchangeType> keyExchangeType,const Optional<CookieState> & cookieState,Optional<std::string> alpn,ReplayCacheResult replayCacheResult,Optional<std::chrono::milliseconds> clockSkew,ClockSkewTolerance clockSkewTolerance,const AppTokenValidator * appTokenValidator)815 static EarlyDataType negotiateEarlyDataType(
816     bool acceptEarlyData,
817     const ClientHello& chlo,
818     const Optional<ResumptionState>& psk,
819     CipherSuite cipher,
820     Optional<KeyExchangeType> keyExchangeType,
821     const Optional<CookieState>& cookieState,
822     Optional<std::string> alpn,
823     ReplayCacheResult replayCacheResult,
824     Optional<std::chrono::milliseconds> clockSkew,
825     ClockSkewTolerance clockSkewTolerance,
826     const AppTokenValidator* appTokenValidator) {
827   if (!getExtension<ClientEarlyData>(chlo.extensions)) {
828     return EarlyDataType::NotAttempted;
829   }
830 
831   if (!acceptEarlyData) {
832     VLOG(5) << "Rejecting early data: disabled";
833     return EarlyDataType::Rejected;
834   }
835 
836   if (!psk) {
837     VLOG(5) << "Rejected early data: psk rejected";
838     return EarlyDataType::Rejected;
839   }
840 
841   if (psk->cipher != cipher) {
842     VLOG(5) << "Rejected early data: cipher mismatch";
843     return EarlyDataType::Rejected;
844   }
845 
846   if (psk->alpn != alpn) {
847     VLOG(5) << "Rejecting early data: alpn mismatch";
848     return EarlyDataType::Rejected;
849   }
850 
851   if (keyExchangeType &&
852       *keyExchangeType == KeyExchangeType::HelloRetryRequest) {
853     VLOG(5) << "Rejecting early data: HelloRetryRequest";
854     return EarlyDataType::Rejected;
855   }
856 
857   if (cookieState) {
858     VLOG(5) << "Rejecting early data: Cookie";
859     return EarlyDataType::Rejected;
860   }
861 
862   if (replayCacheResult != ReplayCacheResult::NotReplay) {
863     VLOG(5) << "Rejecting early data: replay";
864     return EarlyDataType::Rejected;
865   }
866 
867   if (!clockSkew || *clockSkew < clockSkewTolerance.before ||
868       *clockSkew > clockSkewTolerance.after) {
869     VLOG(5) << "Rejecting early data: clock skew clockSkew="
870             << (clockSkew ? folly::to<std::string>(clockSkew->count())
871                           : "(none)")
872             << " toleranceBefore=" << clockSkewTolerance.before.count()
873             << " toleranceAfter=" << clockSkewTolerance.after.count();
874     return EarlyDataType::Rejected;
875   }
876 
877   if (appTokenValidator && !appTokenValidator->validate(*psk)) {
878     VLOG(5) << "Rejecting early data: invalid app token";
879     return EarlyDataType::Rejected;
880   }
881 
882   return EarlyDataType::Accepted;
883 }
884 
getEncryptedExt(HandshakeContext & handshakeContext,const folly::Optional<std::string> & selectedAlpn,EarlyDataType earlyData,std::vector<Extension> otherExtensions)885 static Buf getEncryptedExt(
886     HandshakeContext& handshakeContext,
887     const folly::Optional<std::string>& selectedAlpn,
888     EarlyDataType earlyData,
889     std::vector<Extension> otherExtensions) {
890   EncryptedExtensions encryptedExt;
891   if (selectedAlpn) {
892     ProtocolNameList alpn;
893     ProtocolName protocol;
894     protocol.name = folly::IOBuf::copyBuffer(*selectedAlpn);
895     alpn.protocol_name_list.push_back(std::move(protocol));
896     encryptedExt.extensions.push_back(encodeExtension(std::move(alpn)));
897   }
898 
899   if (earlyData == EarlyDataType::Accepted) {
900     encryptedExt.extensions.push_back(encodeExtension(ServerEarlyData()));
901   }
902 
903   for (auto& ext : otherExtensions) {
904     encryptedExt.extensions.push_back(std::move(ext));
905   }
906   auto encodedEncryptedExt =
907       encodeHandshake<EncryptedExtensions>(std::move(encryptedExt));
908   handshakeContext.appendToTranscript(encodedEncryptedExt);
909   return encodedEncryptedExt;
910 }
911 
chooseCert(const FizzServerContext & context,const ClientHello & chlo)912 static std::pair<std::shared_ptr<SelfCert>, SignatureScheme> chooseCert(
913     const FizzServerContext& context,
914     const ClientHello& chlo) {
915   const auto& clientSigSchemes =
916       getExtension<SignatureAlgorithms>(chlo.extensions);
917   if (!clientSigSchemes) {
918     throw FizzException("no sig schemes", AlertDescription::missing_extension);
919   }
920   Optional<std::string> sni;
921   auto serverNameList = getExtension<ServerNameList>(chlo.extensions);
922   if (serverNameList && !serverNameList->server_name_list.empty()) {
923     sni = serverNameList->server_name_list.front()
924               .hostname->moveToFbString()
925               .toStdString();
926   }
927 
928   auto certAndScheme = context.getCert(
929       sni, clientSigSchemes->supported_signature_algorithms, chlo.extensions);
930   if (!certAndScheme) {
931     throw FizzException(
932         "could not find suitable cert", AlertDescription::handshake_failure);
933   }
934   return *certAndScheme;
935 }
936 
937 static std::tuple<Buf, folly::Optional<CertificateCompressionAlgorithm>>
getCertificate(const std::shared_ptr<const SelfCert> & serverCert,const FizzServerContext & context,const ClientHello & chlo,HandshakeContext & handshakeContext)938 getCertificate(
939     const std::shared_ptr<const SelfCert>& serverCert,
940     const FizzServerContext& context,
941     const ClientHello& chlo,
942     HandshakeContext& handshakeContext) {
943   // Check for compression support first, and if so, send compressed.
944   Buf encodedCertificate;
945   folly::Optional<CertificateCompressionAlgorithm> algo;
946   auto compAlgos =
947       getExtension<CertificateCompressionAlgorithms>(chlo.extensions);
948   if (compAlgos && !context.getSupportedCompressionAlgorithms().empty()) {
949     algo = negotiate(
950         context.getSupportedCompressionAlgorithms(), compAlgos->algorithms);
951   }
952 
953   if (algo) {
954     encodedCertificate = encodeHandshake(serverCert->getCompressedCert(*algo));
955   } else {
956     encodedCertificate = encodeHandshake(serverCert->getCertMessage());
957   }
958   handshakeContext.appendToTranscript(encodedCertificate);
959   return std::make_tuple(std::move(encodedCertificate), std::move(algo));
960 }
961 
getCertificateVerify(SignatureScheme sigScheme,Buf signature,HandshakeContext & handshakeContext)962 static Buf getCertificateVerify(
963     SignatureScheme sigScheme,
964     Buf signature,
965     HandshakeContext& handshakeContext) {
966   CertificateVerify verify;
967   verify.algorithm = sigScheme;
968   verify.signature = std::move(signature);
969   auto encodedCertificateVerify = encodeHandshake(std::move(verify));
970   handshakeContext.appendToTranscript(encodedCertificateVerify);
971   return encodedCertificateVerify;
972 }
973 
getCertificateRequest(const std::vector<SignatureScheme> & acceptableSigSchemes,const CertificateVerifier * const verifier,HandshakeContext & handshakeContext)974 static Buf getCertificateRequest(
975     const std::vector<SignatureScheme>& acceptableSigSchemes,
976     const CertificateVerifier* const verifier,
977     HandshakeContext& handshakeContext) {
978   CertificateRequest request;
979   SignatureAlgorithms algos;
980   algos.supported_signature_algorithms = acceptableSigSchemes;
981   request.extensions.push_back(encodeExtension(std::move(algos)));
982   if (verifier) {
983     auto verifierExtensions = verifier->getCertificateRequestExtensions();
984     for (auto& ext : verifierExtensions) {
985       request.extensions.push_back(std::move(ext));
986     }
987   }
988   auto encodedCertificateRequest = encodeHandshake(std::move(request));
989   handshakeContext.appendToTranscript(encodedCertificateRequest);
990   return encodedCertificateRequest;
991 }
992 
updateClientHelloIfECH(std::shared_ptr<ech::Decrypter> decrypter,ClientHello & chlo)993 static void updateClientHelloIfECH(
994     std::shared_ptr<ech::Decrypter> decrypter,
995     ClientHello& chlo) {
996   if (decrypter) {
997     auto gotChlo = decrypter->decryptClientHello(chlo);
998     if (gotChlo.has_value()) {
999       chlo = std::move(gotChlo.value());
1000     }
1001   }
1002 }
1003 
1004 AsyncActions
1005 EventHandler<ServerTypes, StateEnum::ExpectingClientHello, Event::ClientHello>::
handle(const State & state,Param param)1006     handle(const State& state, Param param) {
1007   ClientHello chlo = std::move(*param.asClientHello());
1008 
1009   // Update the client hello if we are using ECH
1010   updateClientHelloIfECH(state.context()->getECHDecrypter(), chlo);
1011 
1012   addHandshakeLogging(state, chlo);
1013 
1014   if (state.readRecordLayer()->hasUnparsedHandshakeData()) {
1015     throw FizzException(
1016         "data after client hello", AlertDescription::unexpected_message);
1017   }
1018 
1019   auto version =
1020       negotiateVersion(chlo, state.context()->getSupportedVersions());
1021 
1022   if (state.version().has_value() &&
1023       (!version || *version != *state.version())) {
1024     throw FizzException(
1025         "version mismatch with previous negotiation",
1026         AlertDescription::illegal_parameter);
1027   }
1028 
1029   if (!version) {
1030     if (getExtension<ClientEarlyData>(chlo.extensions)) {
1031       throw FizzException(
1032           "supported version mismatch with early data",
1033           AlertDescription::protocol_version);
1034     }
1035     if (state.context()->getVersionFallbackEnabled()) {
1036       AttemptVersionFallback fallback;
1037       // Re-encode to put the record layer header back on. This won't
1038       // necessarily preserve it byte-for-byte, but it isn't authenticated so
1039       // should be ok.
1040       fallback.clientHello =
1041           PlaintextWriteRecordLayer()
1042               .writeInitialClientHello(std::move(*chlo.originalEncoding))
1043               .data;
1044       return actions(
1045           MutateState(&Transition<StateEnum::Error>), std::move(fallback));
1046     } else {
1047       throw FizzException(
1048           "supported version mismatch", AlertDescription::protocol_version);
1049     }
1050   }
1051 
1052   state.writeRecordLayer()->setProtocolVersion(*version);
1053 
1054   validateClientHello(chlo);
1055 
1056   auto cipher = negotiateCipher(chlo, state.context()->getSupportedCiphers());
1057 
1058   auto cookieState = getCookieState(
1059       chlo, *version, cipher, state.context()->getCookieCipher());
1060 
1061   auto resStateResult = getResumptionState(
1062       chlo,
1063       state.context()->getTicketCipher(),
1064       state.context()->getSupportedPskModes());
1065 
1066   auto replayCacheResultFuture = getReplayCacheResult(
1067       chlo,
1068       state.context()->getAcceptEarlyData(*version),
1069       state.context()->getReplayCache());
1070 
1071   auto results =
1072       collectAllUnsafe(resStateResult.futureResState, replayCacheResultFuture);
1073 
1074   using FutureResultType = std::tuple<
1075       folly::Try<std::pair<PskType, Optional<ResumptionState>>>,
1076       folly::Try<ReplayCacheResult>>;
1077   return runOnCallerIfComplete(
1078       state.executor(),
1079       std::move(results),
1080       [&state,
1081        chlo = std::move(chlo),
1082        cookieState = std::move(cookieState),
1083        version = *version,
1084        cipher,
1085        pskMode = resStateResult.pskMode,
1086        obfuscatedAge =
1087            resStateResult.obfuscatedAge](FutureResultType result) mutable {
1088         auto& resumption = *std::get<0>(result);
1089         auto pskType = resumption.first;
1090         auto resState = std::move(resumption.second);
1091         auto replayCacheResult = *std::get<1>(result);
1092 
1093         if (resState) {
1094           if (!validateResumptionState(*resState, *pskMode, version, cipher)) {
1095             pskType = PskType::Rejected;
1096             pskMode = folly::none;
1097             resState = folly::none;
1098           }
1099         } else {
1100           pskMode = folly::none;
1101         }
1102 
1103         auto legacySessionId = chlo.legacy_session_id->clone();
1104 
1105         // If we successfully resumed, set the handshake time to the ticket's
1106         // handshake time to preserve it across ticket updates. If not, set it
1107         // to now.
1108         std::chrono::system_clock::time_point handshakeTime;
1109         if (resState) {
1110           handshakeTime = resState->handshakeTime;
1111         } else {
1112           handshakeTime = state.context()->getClock().getCurrentTime();
1113         }
1114 
1115         std::unique_ptr<KeyScheduler> scheduler;
1116         std::unique_ptr<HandshakeContext> handshakeContext;
1117         std::tie(scheduler, handshakeContext) = setupSchedulerAndContext(
1118             *state.context()->getFactory(),
1119             cipher,
1120             chlo,
1121             resState,
1122             cookieState,
1123             pskType,
1124             std::move(state.handshakeContext()),
1125             version);
1126 
1127         if (state.cipher().has_value() && cipher != *state.cipher()) {
1128           throw FizzException(
1129               "cipher mismatch with previous negotiation",
1130               AlertDescription::illegal_parameter);
1131         }
1132 
1133         auto alpn = negotiateAlpn(chlo, folly::none, *state.context());
1134 
1135         auto clockSkew = getClockSkew(
1136             resState,
1137             obfuscatedAge,
1138             state.context()->getClock().getCurrentTime());
1139 
1140         auto appToken = getAppToken(resState);
1141 
1142         auto earlyDataType = negotiateEarlyDataType(
1143             state.context()->getAcceptEarlyData(version),
1144             chlo,
1145             resState,
1146             cipher,
1147             state.keyExchangeType(),
1148             cookieState,
1149             alpn,
1150             replayCacheResult,
1151             clockSkew,
1152             state.context()->getClockSkewTolerance(),
1153             state.appTokenValidator());
1154 
1155         std::unique_ptr<EncryptedReadRecordLayer> earlyReadRecordLayer;
1156         Buf earlyExporterMaster;
1157         folly::Optional<SecretAvailable> earlyReadSecretAvailable;
1158         if (earlyDataType == EarlyDataType::Accepted) {
1159           auto earlyContext = handshakeContext->getHandshakeContext();
1160           auto earlyReadSecret = scheduler->getSecret(
1161               EarlySecrets::ClientEarlyTraffic, earlyContext->coalesce());
1162           if (!state.context()->getOmitEarlyRecordLayer()) {
1163             earlyReadRecordLayer =
1164                 state.context()->getFactory()->makeEncryptedReadRecordLayer(
1165                     EncryptionLevel::EarlyData);
1166             earlyReadRecordLayer->setProtocolVersion(version);
1167 
1168             Protocol::setAead(
1169                 *earlyReadRecordLayer,
1170                 cipher,
1171                 folly::range(earlyReadSecret.secret),
1172                 *state.context()->getFactory(),
1173                 *scheduler);
1174           }
1175 
1176           earlyReadSecretAvailable =
1177               SecretAvailable(std::move(earlyReadSecret));
1178           earlyExporterMaster = folly::IOBuf::copyBuffer(
1179               scheduler
1180                   ->getSecret(
1181                       EarlySecrets::EarlyExporter, earlyContext->coalesce())
1182                   .secret);
1183         }
1184 
1185         Optional<NamedGroup> group;
1186         Optional<Buf> serverShare;
1187         KeyExchangeType keyExchangeType;
1188         if (!pskMode || *pskMode != PskKeyExchangeMode::psk_ke) {
1189           Optional<Buf> clientShare;
1190           std::tie(group, clientShare) = negotiateGroup(
1191               version, chlo, state.context()->getSupportedGroups());
1192           if (!clientShare) {
1193             VLOG(8) << "Did not find key share for " << toString(*group);
1194             if (state.group().has_value() || cookieState) {
1195               throw FizzException(
1196                   "key share not found for already negotiated group",
1197                   AlertDescription::illegal_parameter);
1198             }
1199 
1200             // If we were otherwise going to accept early data we now need to
1201             // reject it. It's a little ugly to change our previous early data
1202             // decision, but doing it this way allows us to move the key
1203             // schedule forward as we do the key exchange.
1204             if (earlyDataType == EarlyDataType::Accepted) {
1205               earlyDataType = EarlyDataType::Rejected;
1206             }
1207 
1208             message_hash chloHash;
1209             chloHash.hash = handshakeContext->getHandshakeContext();
1210             handshakeContext =
1211                 state.context()->getFactory()->makeHandshakeContext(cipher);
1212             handshakeContext->appendToTranscript(
1213                 encodeHandshake(std::move(chloHash)));
1214 
1215             auto encodedHelloRetryRequest = getHelloRetryRequest(
1216                 version,
1217                 cipher,
1218                 *group,
1219                 legacySessionId ? legacySessionId->clone() : nullptr,
1220                 *handshakeContext);
1221 
1222             WriteToSocket serverFlight;
1223             serverFlight.contents.emplace_back(
1224                 state.writeRecordLayer()->writeHandshake(
1225                     std::move(encodedHelloRetryRequest)));
1226 
1227             if (legacySessionId && !legacySessionId->empty()) {
1228               TLSContent writeCCS;
1229               writeCCS.encryptionLevel = EncryptionLevel::Plaintext;
1230               writeCCS.contentType = ContentType::change_cipher_spec;
1231               writeCCS.data = folly::IOBuf::wrapBuffer(FakeChangeCipherSpec);
1232               serverFlight.contents.emplace_back(std::move(writeCCS));
1233             }
1234 
1235             // Create a new record layer in case we need to skip early data.
1236             auto newReadRecordLayer =
1237                 state.context()->getFactory()->makePlaintextReadRecordLayer();
1238             newReadRecordLayer->setSkipEncryptedRecords(
1239                 earlyDataType == EarlyDataType::Rejected);
1240 
1241             return Future<Actions>(actions(
1242                 MutateState([handshakeContext = std::move(handshakeContext),
1243                              version,
1244                              cipher,
1245                              group,
1246                              earlyDataType,
1247                              replayCacheResult,
1248                              newReadRecordLayer = std::move(
1249                                  newReadRecordLayer)](State& newState) mutable {
1250                   // Save some information about the current state to be
1251                   // validated when we get the second client hello. We don't
1252                   // validate that the second client hello matches the first
1253                   // as strictly as we could according to the spec however.
1254                   newState.handshakeContext() = std::move(handshakeContext);
1255                   newState.version() = version;
1256                   newState.cipher() = cipher;
1257                   newState.group() = group;
1258                   newState.keyExchangeType() =
1259                       KeyExchangeType::HelloRetryRequest;
1260                   newState.earlyDataType() = earlyDataType;
1261                   newState.replayCacheResult() = replayCacheResult;
1262                   newState.readRecordLayer() = std::move(newReadRecordLayer);
1263                 }),
1264                 std::move(serverFlight),
1265                 MutateState(&Transition<StateEnum::ExpectingClientHello>)));
1266           }
1267 
1268           if (state.keyExchangeType().has_value()) {
1269             keyExchangeType = *state.keyExchangeType();
1270           } else {
1271             keyExchangeType = KeyExchangeType::OneRtt;
1272           }
1273 
1274           serverShare = doKex(
1275               *state.context()->getFactory(), *group, *clientShare, *scheduler);
1276         } else {
1277           keyExchangeType = KeyExchangeType::None;
1278           scheduler->deriveHandshakeSecret();
1279         }
1280 
1281         std::vector<Extension> additionalExtensions;
1282         if (state.extensions()) {
1283           additionalExtensions = state.extensions()->getExtensions(chlo);
1284         }
1285 
1286         if (state.group().has_value() && (!group || *group != *state.group())) {
1287           throw FizzException(
1288               "group mismatch with previous negotiation",
1289               AlertDescription::illegal_parameter);
1290         }
1291 
1292         // Cookies are not required to have already negotiated the group but if
1293         // they did it must match (psk_ke is still allowed as we may not know if
1294         // we are accepting the psk when sending the cookie).
1295         if (cookieState && cookieState->group && group &&
1296             *group != *cookieState->group) {
1297           throw FizzException(
1298               "group mismatch with cookie",
1299               AlertDescription::illegal_parameter);
1300         }
1301 
1302         auto encodedServerHello = getServerHello(
1303             version,
1304             state.context()->getFactory()->makeRandom(),
1305             cipher,
1306             resState.has_value(),
1307             group,
1308             std::move(serverShare),
1309             legacySessionId ? legacySessionId->clone() : nullptr,
1310             *handshakeContext);
1311 
1312         // Derive handshake keys.
1313         auto handshakeWriteRecordLayer =
1314             state.context()->getFactory()->makeEncryptedWriteRecordLayer(
1315                 EncryptionLevel::Handshake);
1316         handshakeWriteRecordLayer->setProtocolVersion(version);
1317         auto handshakeWriteSecret = scheduler->getSecret(
1318             HandshakeSecrets::ServerHandshakeTraffic,
1319             handshakeContext->getHandshakeContext()->coalesce());
1320         Protocol::setAead(
1321             *handshakeWriteRecordLayer,
1322             cipher,
1323             folly::range(handshakeWriteSecret.secret),
1324             *state.context()->getFactory(),
1325             *scheduler);
1326 
1327         auto handshakeReadRecordLayer =
1328             state.context()->getFactory()->makeEncryptedReadRecordLayer(
1329                 EncryptionLevel::Handshake);
1330         handshakeReadRecordLayer->setProtocolVersion(version);
1331         handshakeReadRecordLayer->setSkipFailedDecryption(
1332             earlyDataType == EarlyDataType::Rejected);
1333         auto handshakeReadSecret = scheduler->getSecret(
1334             HandshakeSecrets::ClientHandshakeTraffic,
1335             handshakeContext->getHandshakeContext()->coalesce());
1336         Protocol::setAead(
1337             *handshakeReadRecordLayer,
1338             cipher,
1339             folly::range(handshakeReadSecret.secret),
1340             *state.context()->getFactory(),
1341             *scheduler);
1342         auto clientHandshakeSecret =
1343             folly::IOBuf::copyBuffer(handshakeReadSecret.secret);
1344 
1345         auto encodedEncryptedExt = getEncryptedExt(
1346             *handshakeContext,
1347             alpn,
1348             earlyDataType,
1349             std::move(additionalExtensions));
1350 
1351         /*
1352          * Determine we are requesting client auth.
1353          * If yes, add CertificateRequest to handshake write and transcript.
1354          */
1355         bool requestClientAuth =
1356             state.context()->getClientAuthMode() != ClientAuthMode::None &&
1357             !resState;
1358         Optional<Buf> encodedCertRequest;
1359         if (requestClientAuth) {
1360           encodedCertRequest = getCertificateRequest(
1361               state.context()->getSupportedSigSchemes(),
1362               state.context()->getClientCertVerifier().get(),
1363               *handshakeContext);
1364         }
1365 
1366         /*
1367          * Set the cert and signature scheme we are using.
1368          * If sending new cert, add Certificate to handshake write and
1369          * transcript.
1370          */
1371         Optional<Buf> encodedCertificate;
1372         Future<Optional<Buf>> signature = folly::none;
1373         Optional<SignatureScheme> sigScheme;
1374         Optional<std::shared_ptr<const Cert>> serverCert;
1375         std::shared_ptr<const Cert> clientCert;
1376         Optional<CertificateCompressionAlgorithm> certCompressionAlgo;
1377         if (!resState) { // TODO or reauth
1378           std::shared_ptr<const SelfCert> originalSelfCert;
1379           std::tie(originalSelfCert, sigScheme) =
1380               chooseCert(*state.context(), chlo);
1381 
1382           std::tie(encodedCertificate, certCompressionAlgo) = getCertificate(
1383               originalSelfCert, *state.context(), chlo, *handshakeContext);
1384 
1385           auto toBeSigned = handshakeContext->getHandshakeContext();
1386           auto asyncSelfCert =
1387               dynamic_cast<const AsyncSelfCert*>(originalSelfCert.get());
1388           if (asyncSelfCert) {
1389             signature = asyncSelfCert->signFuture(
1390                 *sigScheme,
1391                 CertificateVerifyContext::Server,
1392                 toBeSigned->coalesce());
1393           } else {
1394             signature = originalSelfCert->sign(
1395                 *sigScheme,
1396                 CertificateVerifyContext::Server,
1397                 toBeSigned->coalesce());
1398           }
1399           serverCert = std::move(originalSelfCert);
1400         } else {
1401           serverCert = std::move(resState->serverCert);
1402           clientCert = std::move(resState->clientCert);
1403         }
1404 
1405         auto clientRandom = std::move(chlo.random);
1406         return runOnCallerIfComplete(
1407             state.executor(),
1408             std::move(signature),
1409             [&state,
1410              scheduler = std::move(scheduler),
1411              handshakeContext = std::move(handshakeContext),
1412              cipher,
1413              clientRandom = std::move(clientRandom),
1414              group,
1415              encodedServerHello = std::move(encodedServerHello),
1416              handshakeWriteRecordLayer = std::move(handshakeWriteRecordLayer),
1417              handshakeWriteSecret = std::move(handshakeWriteSecret),
1418              handshakeReadRecordLayer = std::move(handshakeReadRecordLayer),
1419              handshakeReadSecret = std::move(handshakeReadSecret),
1420              earlyReadRecordLayer = std::move(earlyReadRecordLayer),
1421              earlyReadSecretAvailable = std::move(earlyReadSecretAvailable),
1422              earlyExporterMaster = std::move(earlyExporterMaster),
1423              clientHandshakeSecret = std::move(clientHandshakeSecret),
1424              encodedEncryptedExt = std::move(encodedEncryptedExt),
1425              encodedCertificate = std::move(encodedCertificate),
1426              encodedCertRequest = std::move(encodedCertRequest),
1427              requestClientAuth,
1428              pskType,
1429              pskMode,
1430              sigScheme,
1431              version,
1432              keyExchangeType,
1433              earlyDataType,
1434              replayCacheResult,
1435              serverCert = std::move(serverCert),
1436              clientCert = std::move(clientCert),
1437              alpn = std::move(alpn),
1438              clockSkew,
1439              appToken = std::move(appToken),
1440              legacySessionId = std::move(legacySessionId),
1441              serverCertCompAlgo = certCompressionAlgo,
1442              handshakeTime](Optional<Buf> sig) mutable {
1443               Optional<Buf> encodedCertificateVerify;
1444               if (sig) {
1445                 encodedCertificateVerify = getCertificateVerify(
1446                     *sigScheme, std::move(*sig), *handshakeContext);
1447               }
1448 
1449               auto encodedFinished = Protocol::getFinished(
1450                   folly::range(handshakeWriteSecret.secret), *handshakeContext);
1451 
1452               folly::IOBufQueue combined;
1453               if (encodedCertificate) {
1454                 if (encodedCertRequest) {
1455                   combined.append(std::move(encodedEncryptedExt));
1456                   combined.append(std::move(*encodedCertRequest));
1457                   combined.append(std::move(*encodedCertificate));
1458                   combined.append(std::move(*encodedCertificateVerify));
1459                   combined.append(std::move(encodedFinished));
1460                 } else {
1461                   combined.append(std::move(encodedEncryptedExt));
1462                   combined.append(std::move(*encodedCertificate));
1463                   combined.append(std::move(*encodedCertificateVerify));
1464                   combined.append(std::move(encodedFinished));
1465                 }
1466               } else {
1467                 combined.append(std::move(encodedEncryptedExt));
1468                 combined.append(std::move(encodedFinished));
1469               }
1470 
1471               // Some middleboxes appear to break if the first encrypted record
1472               // is larger than ~1300 bytes (likely if it does not fit in the
1473               // first packet).
1474               auto serverEncrypted = handshakeWriteRecordLayer->writeHandshake(
1475                   combined.splitAtMost(1000));
1476               if (!combined.empty()) {
1477                 auto splitRecord =
1478                     handshakeWriteRecordLayer->writeHandshake(combined.move());
1479                 // Split record must have the same encryption level as the main
1480                 // handshake.
1481                 DCHECK(
1482                     splitRecord.encryptionLevel ==
1483                     serverEncrypted.encryptionLevel);
1484                 serverEncrypted.data->prependChain(std::move(splitRecord.data));
1485               }
1486 
1487               WriteToSocket serverFlight;
1488               serverFlight.contents.emplace_back(
1489                   state.writeRecordLayer()->writeHandshake(
1490                       std::move(encodedServerHello)));
1491               if (legacySessionId && !legacySessionId->empty()) {
1492                 TLSContent ccsWrite;
1493                 ccsWrite.encryptionLevel = EncryptionLevel::Plaintext;
1494                 ccsWrite.contentType = ContentType::change_cipher_spec;
1495                 ccsWrite.data = folly::IOBuf::wrapBuffer(FakeChangeCipherSpec);
1496                 serverFlight.contents.emplace_back(std::move(ccsWrite));
1497               }
1498               serverFlight.contents.emplace_back(std::move(serverEncrypted));
1499 
1500               scheduler->deriveMasterSecret();
1501               auto clientFinishedContext =
1502                   handshakeContext->getHandshakeContext();
1503               auto exporterMasterVector = scheduler->getSecret(
1504                   MasterSecrets::ExporterMaster,
1505                   clientFinishedContext->coalesce());
1506               auto exporterMaster = folly::IOBuf::copyBuffer(
1507                   folly::range(exporterMasterVector.secret));
1508 
1509               scheduler->deriveAppTrafficSecrets(
1510                   clientFinishedContext->coalesce());
1511               auto appTrafficWriteRecordLayer =
1512                   state.context()->getFactory()->makeEncryptedWriteRecordLayer(
1513                       EncryptionLevel::AppTraffic);
1514               appTrafficWriteRecordLayer->setProtocolVersion(version);
1515               auto writeSecret =
1516                   scheduler->getSecret(AppTrafficSecrets::ServerAppTraffic);
1517               Protocol::setAead(
1518                   *appTrafficWriteRecordLayer,
1519                   cipher,
1520                   folly::range(writeSecret.secret),
1521                   *state.context()->getFactory(),
1522                   *scheduler);
1523 
1524               // If we have previously dealt with early data (before a
1525               // HelloRetryRequest), don't overwrite the previous result.
1526               auto earlyDataTypeSave = state.earlyDataType()
1527                   ? *state.earlyDataType()
1528                   : earlyDataType;
1529 
1530               SecretAvailable handshakeReadSecretAvailable(
1531                   std::move(handshakeReadSecret));
1532               SecretAvailable handshakeWriteSecretAvailable(
1533                   std::move(handshakeWriteSecret));
1534               SecretAvailable appWriteSecretAvailable(std::move(writeSecret));
1535 
1536               // Save all the necessary state except for the read record layer,
1537               // which is done separately as it varies if early data was
1538               // accepted.
1539               MutateState saveState(
1540                   [appTrafficWriteRecordLayer =
1541                        std::move(appTrafficWriteRecordLayer),
1542                    handshakeContext = std::move(handshakeContext),
1543                    scheduler = std::move(scheduler),
1544                    exporterMaster = std::move(exporterMaster),
1545                    serverCert = std::move(serverCert),
1546                    clientCert = std::move(clientCert),
1547                    cipher,
1548                    group,
1549                    sigScheme,
1550                    clientHandshakeSecret = std::move(clientHandshakeSecret),
1551                    pskType,
1552                    pskMode,
1553                    version,
1554                    keyExchangeType,
1555                    alpn = std::move(alpn),
1556                    earlyDataTypeSave,
1557                    replayCacheResult,
1558                    clockSkew,
1559                    appToken = std::move(appToken),
1560                    serverCertCompAlgo,
1561                    clientRandom = std::move(clientRandom),
1562                    handshakeTime =
1563                        std::move(handshakeTime)](State& newState) mutable {
1564                     newState.writeRecordLayer() =
1565                         std::move(appTrafficWriteRecordLayer);
1566                     newState.handshakeContext() = std::move(handshakeContext);
1567                     newState.keyScheduler() = std::move(scheduler);
1568                     newState.exporterMasterSecret() = std::move(exporterMaster);
1569                     newState.serverCert() = std::move(*serverCert);
1570                     newState.clientCert() = std::move(clientCert);
1571                     newState.version() = version;
1572                     newState.cipher() = cipher;
1573                     newState.group() = group;
1574                     newState.sigScheme() = sigScheme;
1575                     newState.clientHandshakeSecret() =
1576                         std::move(clientHandshakeSecret);
1577                     newState.pskType() = pskType;
1578                     newState.pskMode() = pskMode;
1579                     newState.keyExchangeType() = keyExchangeType;
1580                     newState.earlyDataType() = earlyDataTypeSave;
1581                     newState.replayCacheResult() = replayCacheResult;
1582                     newState.alpn() = std::move(alpn);
1583                     newState.clientClockSkew() = clockSkew;
1584                     newState.appToken() = std::move(appToken);
1585                     newState.serverCertCompAlgo() = serverCertCompAlgo;
1586                     newState.handshakeTime() = std::move(handshakeTime);
1587                     newState.clientRandom() = std::move(clientRandom);
1588                   });
1589 
1590               if (earlyDataType == EarlyDataType::Accepted) {
1591                 if (state.context()->getOmitEarlyRecordLayer()) {
1592                   return actions(
1593                       MutateState([handshakeReadRecordLayer =
1594                                        std::move(handshakeReadRecordLayer),
1595                                    earlyExporterMaster =
1596                                        std::move(earlyExporterMaster)](
1597                                       State& newState) mutable {
1598                         newState.readRecordLayer() =
1599                             std::move(handshakeReadRecordLayer);
1600                         newState.earlyExporterMasterSecret() =
1601                             std::move(earlyExporterMaster);
1602                       }),
1603                       std::move(saveState),
1604                       std::move(*earlyReadSecretAvailable),
1605                       std::move(handshakeReadSecretAvailable),
1606                       std::move(handshakeWriteSecretAvailable),
1607                       std::move(appWriteSecretAvailable),
1608                       std::move(serverFlight),
1609                       MutateState(&Transition<StateEnum::ExpectingFinished>),
1610                       ReportEarlyHandshakeSuccess());
1611 
1612                 } else {
1613                   return actions(
1614                       MutateState([handshakeReadRecordLayer =
1615                                        std::move(handshakeReadRecordLayer),
1616                                    earlyReadRecordLayer =
1617                                        std::move(earlyReadRecordLayer),
1618                                    earlyExporterMaster =
1619                                        std::move(earlyExporterMaster)](
1620                                       State& newState) mutable {
1621                         newState.readRecordLayer() =
1622                             std::move(earlyReadRecordLayer);
1623                         newState.handshakeReadRecordLayer() =
1624                             std::move(handshakeReadRecordLayer);
1625                         newState.earlyExporterMasterSecret() =
1626                             std::move(earlyExporterMaster);
1627                       }),
1628                       std::move(saveState),
1629                       std::move(*earlyReadSecretAvailable),
1630                       std::move(handshakeReadSecretAvailable),
1631                       std::move(handshakeWriteSecretAvailable),
1632                       std::move(appWriteSecretAvailable),
1633                       std::move(serverFlight),
1634                       MutateState(&Transition<StateEnum::AcceptingEarlyData>),
1635                       ReportEarlyHandshakeSuccess());
1636                 }
1637               } else {
1638                 auto transition = requestClientAuth
1639                     ? Transition<StateEnum::ExpectingCertificate>
1640                     : Transition<StateEnum::ExpectingFinished>;
1641                 return actions(
1642                     MutateState([handshakeReadRecordLayer =
1643                                      std::move(handshakeReadRecordLayer)](
1644                                     State& newState) mutable {
1645                       newState.readRecordLayer() =
1646                           std::move(handshakeReadRecordLayer);
1647                     }),
1648                     std::move(saveState),
1649                     std::move(handshakeReadSecretAvailable),
1650                     std::move(handshakeWriteSecretAvailable),
1651                     std::move(appWriteSecretAvailable),
1652                     std::move(serverFlight),
1653                     MutateState(transition));
1654               }
1655             });
1656       });
1657 }
1658 
1659 AsyncActions
1660 EventHandler<ServerTypes, StateEnum::AcceptingEarlyData, Event::AppData>::
handle(const State &,Param param)1661     handle(const State&, Param param) {
1662   auto& appData = *param.asAppData();
1663 
1664   return actions(DeliverAppData{std::move(appData.data)});
1665 }
1666 
1667 AsyncActions
1668 EventHandler<ServerTypes, StateEnum::AcceptingEarlyData, Event::AppWrite>::
handle(const State & state,Param param)1669     handle(const State& state, Param param) {
1670   auto& appWrite = *param.asAppWrite();
1671 
1672   WriteToSocket write;
1673   write.callback = appWrite.callback;
1674   write.contents.emplace_back(state.writeRecordLayer()->writeAppData(
1675       std::move(appWrite.data), appWrite.aeadOptions));
1676   write.flags = appWrite.flags;
1677 
1678   return actions(std::move(write));
1679 }
1680 
1681 AsyncActions EventHandler<
1682     ServerTypes,
1683     StateEnum::AcceptingEarlyData,
handle(const State & state,Param param)1684     Event::EndOfEarlyData>::handle(const State& state, Param param) {
1685   auto& eoed = *param.asEndOfEarlyData();
1686 
1687   if (state.readRecordLayer()->hasUnparsedHandshakeData()) {
1688     throw FizzException(
1689         "data after eoed", AlertDescription::unexpected_message);
1690   }
1691 
1692   state.handshakeContext()->appendToTranscript(*eoed.originalEncoding);
1693 
1694   auto readRecordLayer = std::move(state.handshakeReadRecordLayer());
1695 
1696   return actions(
1697       MutateState([readRecordLayer =
1698                        std::move(readRecordLayer)](State& newState) mutable {
1699         newState.readRecordLayer() = std::move(readRecordLayer);
1700       }),
1701       MutateState(&Transition<StateEnum::ExpectingFinished>));
1702 }
1703 
1704 AsyncActions
1705 EventHandler<ServerTypes, StateEnum::ExpectingFinished, Event::AppWrite>::
handle(const State & state,Param param)1706     handle(const State& state, Param param) {
1707   auto& appWrite = *param.asAppWrite();
1708 
1709   WriteToSocket write;
1710   write.callback = appWrite.callback;
1711   write.contents.emplace_back(state.writeRecordLayer()->writeAppData(
1712       std::move(appWrite.data), appWrite.aeadOptions));
1713   write.flags = appWrite.flags;
1714 
1715   return actions(std::move(write));
1716 }
1717 
writeNewSessionTicket(const FizzServerContext & context,const WriteRecordLayer & recordLayer,std::chrono::seconds ticketLifetime,uint32_t ticketAgeAdd,Buf nonce,Buf ticket,ProtocolVersion version)1718 static WriteToSocket writeNewSessionTicket(
1719     const FizzServerContext& context,
1720     const WriteRecordLayer& recordLayer,
1721     std::chrono::seconds ticketLifetime,
1722     uint32_t ticketAgeAdd,
1723     Buf nonce,
1724     Buf ticket,
1725     ProtocolVersion version) {
1726   NewSessionTicket nst;
1727   nst.ticket_lifetime = ticketLifetime.count();
1728   nst.ticket_age_add = ticketAgeAdd;
1729   nst.ticket_nonce = std::move(nonce);
1730   nst.ticket = std::move(ticket);
1731 
1732   if (context.getAcceptEarlyData(version)) {
1733     TicketEarlyData early;
1734     early.max_early_data_size = context.getMaxEarlyDataSize();
1735     nst.extensions.push_back(encodeExtension(std::move(early)));
1736   }
1737 
1738   auto encodedNst = encodeHandshake(std::move(nst));
1739   WriteToSocket nstWrite;
1740   nstWrite.contents.emplace_back(
1741       recordLayer.writeHandshake(std::move(encodedNst)));
1742   return nstWrite;
1743 }
1744 
generateTicket(const State & state,const std::vector<uint8_t> & resumptionMasterSecret,Buf appToken=nullptr)1745 static Future<Optional<WriteToSocket>> generateTicket(
1746     const State& state,
1747     const std::vector<uint8_t>& resumptionMasterSecret,
1748     Buf appToken = nullptr) {
1749   auto ticketCipher = state.context()->getTicketCipher();
1750 
1751   if (!ticketCipher || *state.pskType() == PskType::NotSupported) {
1752     return folly::none;
1753   }
1754 
1755   Buf resumptionSecret;
1756   auto ticketNonce = folly::IOBuf::create(0);
1757   resumptionSecret = state.keyScheduler()->getResumptionSecret(
1758       folly::range(resumptionMasterSecret), ticketNonce->coalesce());
1759 
1760   ResumptionState resState;
1761   resState.version = *state.version();
1762   resState.cipher = *state.cipher();
1763   resState.resumptionSecret = std::move(resumptionSecret);
1764   resState.serverCert = state.serverCert();
1765   resState.clientCert = state.clientCert();
1766   resState.alpn = state.alpn();
1767   resState.ticketAgeAdd = state.context()->getFactory()->makeTicketAgeAdd();
1768   resState.ticketIssueTime = state.context()->getClock().getCurrentTime();
1769   resState.appToken = std::move(appToken);
1770   resState.handshakeTime = *state.handshakeTime();
1771 
1772   auto ticketFuture = ticketCipher->encrypt(std::move(resState));
1773   return runOnCallerIfComplete(
1774       state.executor(),
1775       std::move(ticketFuture),
1776       [&state,
1777        ticketAgeAdd = resState.ticketAgeAdd,
1778        ticketNonce = std::move(ticketNonce)](
1779           Optional<std::pair<Buf, std::chrono::seconds>> ticket) mutable
1780       -> Optional<WriteToSocket> {
1781         if (!ticket) {
1782           return folly::none;
1783         }
1784         return writeNewSessionTicket(
1785             *state.context(),
1786             *state.writeRecordLayer(),
1787             ticket->second,
1788             ticketAgeAdd,
1789             std::move(ticketNonce),
1790             std::move(ticket->first),
1791             *state.version());
1792       });
1793 }
1794 
1795 AsyncActions
1796 EventHandler<ServerTypes, StateEnum::ExpectingCertificate, Event::Certificate>::
handle(const State & state,Param param)1797     handle(const State& state, Param param) {
1798   auto certMsg = std::move(*param.asCertificateMsg());
1799 
1800   state.handshakeContext()->appendToTranscript(*certMsg.originalEncoding);
1801 
1802   if (!certMsg.certificate_request_context->empty()) {
1803     throw FizzException(
1804         "certificate request context must be empty",
1805         AlertDescription::illegal_parameter);
1806   }
1807 
1808   std::vector<std::shared_ptr<const PeerCert>> clientCerts;
1809   bool leaf = true;
1810   for (auto& certEntry : certMsg.certificate_list) {
1811     // We don't request any extensions, so this ought to be empty
1812     if (!certEntry.extensions.empty()) {
1813       throw FizzException(
1814           "certificate extensions must be empty",
1815           AlertDescription::illegal_parameter);
1816     }
1817 
1818     clientCerts.emplace_back(state.context()->getFactory()->makePeerCert(
1819         std::move(certEntry), leaf));
1820     leaf = false;
1821   }
1822 
1823   if (clientCerts.empty()) {
1824     if (state.context()->getClientAuthMode() == ClientAuthMode::Optional) {
1825       VLOG(6) << "Client authentication not sent";
1826       return actions(
1827           MutateState([](State& newState) {
1828             newState.unverifiedCertChain() = folly::none;
1829           }),
1830           MutateState(&Transition<StateEnum::ExpectingFinished>));
1831     } else {
1832       throw FizzException(
1833           "certificate requested but none received",
1834           AlertDescription::certificate_required);
1835     }
1836   } else {
1837     return actions(
1838         MutateState([certs = std::move(clientCerts)](State& newState) mutable {
1839           newState.unverifiedCertChain() = std::move(certs);
1840         }),
1841         MutateState(&Transition<StateEnum::ExpectingCertificateVerify>));
1842   }
1843 }
1844 
1845 AsyncActions EventHandler<
1846     ServerTypes,
1847     StateEnum::ExpectingCertificateVerify,
handle(const State & state,Param param)1848     Event::CertificateVerify>::handle(const State& state, Param param) {
1849   auto certVerify = std::move(*param.asCertificateVerify());
1850 
1851   if (std::find(
1852           state.context()->getSupportedSigSchemes().begin(),
1853           state.context()->getSupportedSigSchemes().end(),
1854           certVerify.algorithm) ==
1855       state.context()->getSupportedSigSchemes().end()) {
1856     throw FizzException(
1857         folly::to<std::string>(
1858             "client chose unsupported sig scheme: ",
1859             toString(certVerify.algorithm)),
1860         AlertDescription::handshake_failure);
1861   }
1862 
1863   const auto& certs = *state.unverifiedCertChain();
1864   auto leafCert = certs.front();
1865   leafCert->verify(
1866       certVerify.algorithm,
1867       CertificateVerifyContext::Client,
1868       state.handshakeContext()->getHandshakeContext()->coalesce(),
1869       certVerify.signature->coalesce());
1870 
1871   try {
1872     const auto& verifier = state.context()->getClientCertVerifier();
1873     if (verifier) {
1874       verifier->verify(certs);
1875     }
1876   } catch (const FizzException&) {
1877     throw;
1878   } catch (const std::exception& e) {
1879     throw FizzVerificationException(
1880         folly::to<std::string>("client certificate failure: ", e.what()),
1881         AlertDescription::bad_certificate);
1882   }
1883 
1884   state.handshakeContext()->appendToTranscript(*certVerify.originalEncoding);
1885 
1886   return actions(
1887       MutateState([cert = std::move(leafCert)](State& newState) {
1888         newState.unverifiedCertChain() = folly::none;
1889         newState.clientCert() = std::move(cert);
1890       }),
1891       MutateState(&Transition<StateEnum::ExpectingFinished>));
1892 }
1893 
1894 AsyncActions
1895 EventHandler<ServerTypes, StateEnum::ExpectingFinished, Event::Finished>::
handle(const State & state,Param param)1896     handle(const State& state, Param param) {
1897   auto& finished = *param.asFinished();
1898 
1899   auto expectedFinished = state.handshakeContext()->getFinishedData(
1900       state.clientHandshakeSecret()->coalesce());
1901   if (!CryptoUtils::equal(
1902           expectedFinished->coalesce(), finished.verify_data->coalesce())) {
1903     throw FizzException("client finished verify failure", folly::none);
1904   }
1905 
1906   if (state.readRecordLayer()->hasUnparsedHandshakeData()) {
1907     throw FizzException("data after finished", folly::none);
1908   }
1909 
1910   auto readRecordLayer =
1911       state.context()->getFactory()->makeEncryptedReadRecordLayer(
1912           EncryptionLevel::AppTraffic);
1913   readRecordLayer->setProtocolVersion(*state.version());
1914   auto readSecret =
1915       state.keyScheduler()->getSecret(AppTrafficSecrets::ClientAppTraffic);
1916   Protocol::setAead(
1917       *readRecordLayer,
1918       *state.cipher(),
1919       folly::range(readSecret.secret),
1920       *state.context()->getFactory(),
1921       *state.keyScheduler());
1922 
1923   state.handshakeContext()->appendToTranscript(*finished.originalEncoding);
1924 
1925   auto resumptionMasterSecret =
1926       state.keyScheduler()
1927           ->getSecret(
1928               MasterSecrets::ResumptionMaster,
1929               state.handshakeContext()->getHandshakeContext()->coalesce())
1930           .secret;
1931   state.keyScheduler()->clearMasterSecret();
1932 
1933   MutateState saveState([readRecordLayer = std::move(readRecordLayer),
1934                          resumptionMasterSecret](State& newState) mutable {
1935     newState.readRecordLayer() = std::move(readRecordLayer);
1936     newState.resumptionMasterSecret() = std::move(resumptionMasterSecret);
1937   });
1938 
1939   SecretAvailable appReadTrafficSecretAvailable(std::move(readSecret));
1940 
1941   if (!state.context()->getSendNewSessionTicket()) {
1942     return actions(
1943         std::move(saveState),
1944         std::move(appReadTrafficSecretAvailable),
1945         MutateState(&Transition<StateEnum::AcceptingData>),
1946         ReportHandshakeSuccess());
1947   } else {
1948     auto ticketFuture = generateTicket(state, resumptionMasterSecret);
1949     return runOnCallerIfComplete(
1950         state.executor(),
1951         std::move(ticketFuture),
1952         [saveState = std::move(saveState),
1953          appReadTrafficSecretAvailable =
1954              std::move(appReadTrafficSecretAvailable)](
1955             Optional<WriteToSocket> nstWrite) mutable {
1956           if (!nstWrite) {
1957             return actions(
1958                 std::move(saveState),
1959                 MutateState(&Transition<StateEnum::AcceptingData>),
1960                 std::move(appReadTrafficSecretAvailable),
1961                 ReportHandshakeSuccess());
1962           }
1963 
1964           return actions(
1965               std::move(saveState),
1966               MutateState(&Transition<StateEnum::AcceptingData>),
1967               std::move(appReadTrafficSecretAvailable),
1968               std::move(*nstWrite),
1969               ReportHandshakeSuccess());
1970         });
1971   }
1972 }
1973 
1974 AsyncActions EventHandler<
1975     ServerTypes,
1976     StateEnum::AcceptingData,
handle(const State & state,Param param)1977     Event::WriteNewSessionTicket>::handle(const State& state, Param param) {
1978   auto& writeNewSessionTicket = *param.asWriteNewSessionTicket();
1979   auto ticketFuture = generateTicket(
1980       state,
1981       state.resumptionMasterSecret(),
1982       std::move(writeNewSessionTicket.appToken));
1983   return runOnCallerIfComplete(
1984       state.executor(),
1985       std::move(ticketFuture),
1986       [](Optional<WriteToSocket> nstWrite) {
1987         if (!nstWrite) {
1988           return Actions();
1989         }
1990         return actions(std::move(*nstWrite));
1991       });
1992 }
1993 
1994 AsyncActions
handle(const State &,Param param)1995 EventHandler<ServerTypes, StateEnum::AcceptingData, Event::AppData>::handle(
1996     const State& /*state*/,
1997     Param param) {
1998   auto& appData = *param.asAppData();
1999 
2000   return actions(DeliverAppData{std::move(appData.data)});
2001 }
2002 
2003 AsyncActions
handle(const State & state,Param param)2004 EventHandler<ServerTypes, StateEnum::AcceptingData, Event::AppWrite>::handle(
2005     const State& state,
2006     Param param) {
2007   auto& appWrite = *param.asAppWrite();
2008 
2009   WriteToSocket write;
2010   write.callback = appWrite.callback;
2011   write.contents.emplace_back(state.writeRecordLayer()->writeAppData(
2012       std::move(appWrite.data), appWrite.aeadOptions));
2013   write.flags = appWrite.flags;
2014 
2015   return actions(std::move(write));
2016 }
2017 
2018 AsyncActions
handle(const State & state,Param param)2019 EventHandler<ServerTypes, StateEnum::AcceptingData, Event::KeyUpdate>::handle(
2020     const State& state,
2021     Param param) {
2022   auto& keyUpdate = *param.asKeyUpdate();
2023 
2024   if (state.readRecordLayer()->hasUnparsedHandshakeData()) {
2025     throw FizzException("data after key_update", folly::none);
2026   }
2027   state.keyScheduler()->clientKeyUpdate();
2028   auto readRecordLayer =
2029       state.context()->getFactory()->makeEncryptedReadRecordLayer(
2030           EncryptionLevel::AppTraffic);
2031   readRecordLayer->setProtocolVersion(*state.version());
2032   auto readSecret =
2033       state.keyScheduler()->getSecret(AppTrafficSecrets::ClientAppTraffic);
2034   Protocol::setAead(
2035       *readRecordLayer,
2036       *state.cipher(),
2037       folly::range(readSecret.secret),
2038       *state.context()->getFactory(),
2039       *state.keyScheduler());
2040 
2041   if (keyUpdate.request_update == KeyUpdateRequest::update_not_requested) {
2042     return actions(
2043         MutateState([rRecordLayer =
2044                          std::move(readRecordLayer)](State& newState) mutable {
2045           newState.readRecordLayer() = std::move(rRecordLayer);
2046         }),
2047         SecretAvailable(std::move(readSecret)));
2048   }
2049 
2050   auto encodedKeyUpdated =
2051       Protocol::getKeyUpdated(KeyUpdateRequest::update_not_requested);
2052   WriteToSocket write;
2053   write.contents.emplace_back(
2054       state.writeRecordLayer()->writeHandshake(std::move(encodedKeyUpdated)));
2055 
2056   state.keyScheduler()->serverKeyUpdate();
2057 
2058   auto writeRecordLayer =
2059       state.context()->getFactory()->makeEncryptedWriteRecordLayer(
2060           EncryptionLevel::AppTraffic);
2061   writeRecordLayer->setProtocolVersion(*state.version());
2062   auto writeSecret =
2063       state.keyScheduler()->getSecret(AppTrafficSecrets::ServerAppTraffic);
2064   Protocol::setAead(
2065       *writeRecordLayer,
2066       *state.cipher(),
2067       folly::range(writeSecret.secret),
2068       *state.context()->getFactory(),
2069       *state.keyScheduler());
2070 
2071   return actions(
2072       MutateState([rRecordLayer = std::move(readRecordLayer),
2073                    wRecordLayer =
2074                        std::move(writeRecordLayer)](State& newState) mutable {
2075         newState.readRecordLayer() = std::move(rRecordLayer);
2076         newState.writeRecordLayer() = std::move(wRecordLayer);
2077       }),
2078       SecretAvailable(std::move(writeSecret)),
2079       SecretAvailable(std::move(readSecret)),
2080       std::move(write));
2081 }
2082 
2083 AsyncActions
handle(const State & state,Param param)2084 EventHandler<ServerTypes, StateEnum::AcceptingData, Event::CloseNotify>::handle(
2085     const State& state,
2086     Param param) {
2087   ensureNoUnparsedHandshakeData(state, Event::CloseNotify);
2088   auto& closenotify = *param.asCloseNotify();
2089   auto eod = EndOfData(std::move(closenotify.ignoredPostCloseData));
2090 
2091   MutateState clearRecordLayers([](State& newState) {
2092     newState.writeRecordLayer() = nullptr;
2093     newState.readRecordLayer() = nullptr;
2094   });
2095 
2096   WriteToSocket write;
2097   write.contents.emplace_back(state.writeRecordLayer()->writeAlert(
2098       Alert(AlertDescription::close_notify)));
2099   return actions(
2100       std::move(write),
2101       std::move(clearRecordLayers),
2102       MutateState(&Transition<StateEnum::Closed>),
2103       std::move(eod));
2104 }
2105 
2106 AsyncActions
2107 EventHandler<ServerTypes, StateEnum::ExpectingCloseNotify, Event::CloseNotify>::
handle(const State & state,Param param)2108     handle(const State& state, Param param) {
2109   ensureNoUnparsedHandshakeData(state, Event::CloseNotify);
2110   auto& closenotify = *param.asCloseNotify();
2111   auto eod = EndOfData(std::move(closenotify.ignoredPostCloseData));
2112 
2113   MutateState clearRecordLayers([](State& newState) {
2114     newState.readRecordLayer() = nullptr;
2115     newState.writeRecordLayer() = nullptr;
2116   });
2117   return actions(
2118       std::move(clearRecordLayers),
2119       MutateState(&Transition<StateEnum::Closed>),
2120       std::move(eod));
2121 }
2122 
2123 } // namespace sm
2124 } // namespace fizz
2125