quic/server/handshake/TokenGenerator.cpp (40 lines of code) (raw):
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <folly/io/IOBuf.h>
#include <quic/server/handshake/TokenGenerator.h>
#include <folly/Range.h>
#include <quic/codec/Decode.h>
namespace {
const std::vector<std::string> kCipherContexts = {"RetryToken_V2"};
} // namespace
namespace quic {
TokenGenerator::TokenGenerator(TokenSecret secret) : cipher_(kCipherContexts) {
std::vector<folly::ByteRange> secrets;
secrets.emplace_back(folly::range(secret));
cipher_.setSecrets(secrets);
}
folly::Optional<Buf> TokenGenerator::encryptToken(
const QuicAddrValidationToken& token) {
// Generate the retry token in plaintext
auto plainTextToken = token.getPlaintextToken();
// Try to encrypt it
auto maybeEncryptedToken = cipher_.encrypt(
std::move(plainTextToken), token.genAeadAssocData().get());
if (!maybeEncryptedToken) {
LOG(ERROR) << "Failed to encypt addr validation token with IP "
<< token.clientIp.str();
}
// If the encryption failed, this will be empty optional
return maybeEncryptedToken;
}
uint64_t TokenGenerator::decryptToken(Buf encryptedToken, Buf aeadAssocData) {
auto maybeDecryptedToken =
cipher_.decrypt(std::move(encryptedToken), aeadAssocData.get());
if (!maybeDecryptedToken) {
return 0;
}
// Try to parse the decrypted token
auto decryptedToken = (*maybeDecryptedToken).get();
folly::io::Cursor cursor(decryptedToken);
auto parseResult = parsePlaintextRetryOrNewToken(cursor);
if (parseResult.hasError()) {
LOG(ERROR) << "Failed to parse decrypted retry token";
return 0;
}
return parseResult.value();
}
} // namespace quic