1#ifndef NDNPH_APP_NDNCERT_SERVER_HPP
2#define NDNPH_APP_NDNCERT_SERVER_HPP
5#include "../../face/packet-handler.hpp"
49using ChallengeList = std::array<Challenge*, detail::MaxChallenges::value>;
73 if (!encoder || !name || !data) {
80 return data.
sign(signer);
89 return name.
size() == profile.prefix.size() + 3 && profile.prefix.isPrefixOf(name) &&
103 EvDecoder::def<TT::EcdhPub>(&ecdhPub),
104 EvDecoder::def<TT::CertRequest>([&](
const Decoder::Tlv& d) {
105 certRequest = region.create<Data>();
106 return !!certRequest && d.vd().decode(certRequest) &&
107 pub.import(region, certRequest);
136 [&challenges](
Encoder& encoder) {
137 for (
auto it = challenges.rbegin(); it != challenges.rend(); ++it) {
147 if (!encoder || !data || !newRequest) {
153 return data.
sign(signer);
162 return name.
size() == profile.prefix.size() + 4 && profile.prefix.isPrefixOf(name) &&
165 name[-2].
length() == detail::RequestIdLen::value &&
174 return isName(profile, name) ? name[-2].
value() :
nullptr;
187 if (actualRequestId ==
nullptr ||
188 !std::equal(requestId, requestId + detail::RequestIdLen::value, actualRequestId) ||
195 return !!decrypted &&
197 decrypted.makeDecoder(),
198 EvDecoder::def<TT::SelectedChallenge, false, 1>([&](
const Decoder::Tlv& d) {
199 for (const auto& ch : challenges) {
203 if (ch->getId() == tlv::Value(d.value, d.length)) {
210 EvDecoder::def<TT::ParameterKey, true, 2>(
211 [&](
const Decoder::Tlv& d) {
return paramsParser.parseKey(d); }),
212 EvDecoder::def<TT::ParameterValue, true, 2>(
213 [&](
const Decoder::Tlv& d) {
return paramsParser.parseValue(d); })) &&
214 challenge !=
nullptr;
231 case Status::FAILURE:
233 case Status::SUCCESS:
235 [
this](
Encoder& encoder) { encoder.
prependTlv(TT::IssuedCertName, issuedCertName); },
236 [
this](
Encoder& encoder) { detail::encodeFwHint(encoder, fwHint); });
240 [
this](
Encoder& encoder) { encoder.
prependTlv(TT::ChallengeStatus, challengeStatus); },
243 uint64_t remainingTime =
244 std::max<int>(0, port::Clock::sub(expireTime, port::Clock::now())) / 1000;
258 if (!encrypted || !data || !challengeRequest) {
264 return data.
sign(signer);
276 if (!encoder || !data || !interest) {
282 return data.
sign(signer);
293 , m_challenges(challenges)
294 , m_signingPolicy(detail::makeISigPolicy()) {
304 if (!m_newRequest.fromInterest(m_region, interest, m_profile, m_signingPolicy)) {
306 return makeError(packetRegion, interest, ErrorCode::BadParameterFormat, m_signer);
312 if (mbedtls_ecdh_gen_public(mbedtls::P256::group(), ecdhPvt, m_newResponse.ecdhPub,
313 mbedtls::rng,
nullptr) != 0 ||
314 !port::RandomSource::generate(m_newResponse.salt,
sizeof(m_newResponse.salt)) ||
315 !port::RandomSource::generate(m_newResponse.requestId,
sizeof(m_newResponse.requestId)) ||
316 !m_sessionKey.makeKey(ecdhPvt, m_newRequest.ecdhPub, m_newResponse.salt,
317 m_newResponse.requestId)) {
323 return m_newResponse.toData(packetRegion, interest, m_challenges, m_signer);
327 m_challengeRegion->reset();
328 Challenge* prevChallenge = m_challengeRequest.challenge;
329 if (!m_challengeRequest.fromInterest(*m_challengeRegion, interest, m_profile,
330 m_newResponse.requestId, m_sessionKey, m_newRequest.pub,
331 m_challenges, m_signingPolicy)) {
333 return makeError(packetRegion, interest, ErrorCode::BadParameterFormat, m_signer);
336 auto now = port::Clock::now();
337 if (prevChallenge ==
nullptr) {
338 m_challengeResponse.status = Status::CHALLENGE;
339 m_challengeResponse.remainingTries = m_challengeRequest.challenge->getRetryLimit();
340 m_challengeResponse.expireTime =
341 port::Clock::add(now, m_challengeRequest.challenge->getTimeLimit());
342 }
else if (m_challengeRequest.challenge != prevChallenge) {
344 return makeError(packetRegion, interest, ErrorCode::OutOfTries, m_signer);
347 if (m_challengeResponse.remainingTries == 0) {
349 return makeError(packetRegion, interest, ErrorCode::OutOfTries, m_signer);
351 if (port::Clock::isBefore(m_challengeResponse.expireTime, now)) {
353 return makeError(packetRegion, interest, ErrorCode::OutOfTime, m_signer);
357 m_challengeRequest.challenge->process(*m_challengeRegion, m_challengeRequest);
359 m_challengeResponse.params = result.
params;
361 m_issuedCert = m_region.create<
Data>();
362 auto validity = certificate::getValidity(m_newRequest.certRequest);
363 if (m_issuedCert.decodeFrom(m_newRequest.pub.buildCertificate(
364 m_region, m_newRequest.pub.getName(), validity, m_signer)) &&
365 !!(m_challengeResponse.issuedCertName = m_issuedCert.getFullName(m_region))) {
366 m_challengeResponse.status = Status::SUCCESS;
367 m_challengeResponse.fwHint = m_profile.prefix.append(m_region,
getCaComponent());
370 m_challengeResponse.status = Status::PENDING;
374 --m_challengeResponse.remainingTries;
380 return m_challengeResponse.toData(packetRegion, interest, m_newResponse.requestId, m_sessionKey,
385 return m_challengeResponse.issuedCertName;
394 Region* m_challengeRegion =
nullptr;
426 , m_profile(opts.profile)
427 , m_challenges(opts.challenges)
428 , m_signer(opts.signer) {}
433 const Name& interestName = interest.getName();
434 if (NewRequest::isName(m_profile, interestName)) {
435 m_session.reset(
new Session(m_profile, m_signer, m_challenges));
436 reply(m_session->handleNewRequest(packetRegion, interest));
438 }
else if (m_session !=
nullptr && ChallengeRequest::isName(m_profile, interestName)) {
439 reply(m_session->handleChallengeRequest(packetRegion, interest));
441 }
else if (m_session !=
nullptr && m_session->getIssuedCertName() == interestName) {
442 reply(m_session->getIssuedCert());
452 std::unique_ptr<Session> m_session;
459 return challenge_consts::nop();
483 return challenge_consts::possession();
499 tlv::Value proof = request.params.get(challenge_consts::proof());
501 return process0(request);
505 result.
success = process1(proof);
512 m_cert = request.params.get(challenge_consts::issuedcert());
519 if (!(m_cert.makeDecoder().decode(data) && m_pub.import(temp, data) &&
520 certificate::getValidity(data).includesUnix())) {
527 ChallengeResult result;
528 if (!port::RandomSource::generate(m_nonce,
sizeof(m_nonce))) {
530 result.decrementRetry =
true;
531 result.challengeStatus =
"server-error";
535 result.challengeStatus =
"need-proof";
536 result.params.set(challenge_consts::nonce(),
tlv::Value(m_nonce,
sizeof(m_nonce)));
540 bool process1(tlv::Value proof) {
545 StaticRegion<256> m_region;
#define NDNPH_NDNCERT_LOG(...)
Definition common.hpp:15
Data packet.
Definition data.hpp:136
detail::SignedDataRef Signed
Result of Data::sign operation.
Definition data.hpp:246
void setContent(tlv::Value v)
Definition data.hpp:176
void setName(const Name &v)
Definition data.hpp:144
Signed sign(const PrivateKey &key, DSigInfo sigInfo=DSigInfo()) const
Sign the packet with a private key.
Definition data.hpp:254
void setFreshnessPeriod(uint32_t v)
Definition data.hpp:160
void setIsFinalBlock(bool v)
Definition data.hpp:168
Decoded TLV.
Definition decoder.hpp:13
TLV encoder that accepts items in reverse order.
Definition encoder.hpp:10
bool prepend(const First &first, const Arg &... arg)
Prepend a sequence of values.
Definition encoder.hpp:123
void trim() const
Release unused space to the Region.
Definition encoder.hpp:58
bool prependTlv(uint32_t type, OmitEmptyTag omitEmpty, const Arg &... arg)
Prepend TLV, measuring TLV-LENGTH automatically.
Definition encoder.hpp:143
static bool decodeValue(const Decoder &input, const E &... defs)
Decode input TLV-VALUE with a sequence of element definitions.
Definition ev-decoder.hpp:126
Network layer face.
Definition face.hpp:12
Interest packet.
Definition interest.hpp:284
const ISigInfo * getSigInfo() const
Retrieve SignatureInfo.
Definition interest.hpp:332
bool verify(const PublicKey &key) const
Verify the packet with a public key.
Definition interest.hpp:476
tlv::Value getAppParameters() const
Retrieve AppParameters.
Definition interest.hpp:321
Name.
Definition name.hpp:14
size_t length() const
Definition name.hpp:77
size_t size() const
Get number of components.
Definition name.hpp:86
const uint8_t * value() const
Definition name.hpp:81
Name append(Region ®ion, const C &... comps) const
Append a sequence of components.
Definition name.hpp:183
Base class to receive packets from Face.
Definition packet-handler.hpp:10
Region-based memory allocator thats owns memory of NDNph objects.
Definition region.hpp:9
RefType create(Arg &&... arg)
Allocate and create an object, and return its reference.
Definition region.hpp:90
Region with statically allocated memory.
Definition region.hpp:143
Indicate that TLV-VALUE should be a timestamp.
Definition convention.hpp:27
Definition convention.hpp:74
const Name & getName() const
Definition interest.hpp:68
EC private key.
Definition ec.hpp:180
EC public key.
Definition ec.hpp:65
bool check(const ISigInfo &si)
Check that SigInfo fields fulfill current policy.
Definition sig-info.hpp:285
Multi-Precision Integer.
Definition mbed-common.hpp:102
Symmetric key used in CHALLENGE step.
Definition common.hpp:33
tlv::Value decrypt(Region ®ion, tlv::Value message, const uint8_t *requestId)
Decrypt from encrypted-message.
Definition common.hpp:53
tlv::Value encrypt(Region ®ion, tlv::Value plaintext, const uint8_t *requestId)
Encrypt to encrypted-message.
Definition common.hpp:48
CA profile packet.
Definition server.hpp:52
Data::Signed toData(Region ®ion, const EcPrivateKey &signer) const
Build CA profile packet.
Definition server.hpp:59
CHALLENGE request packet.
Definition server.hpp:158
bool fromInterest(Region ®ion, const Interest &interest, const CaProfile &profile, const uint8_t *requestId, detail::SessionKey &sessionKey, const EcPublicKey &verifier, const ChallengeList &challenges, detail::ISigPolicy &signingPolicy)
Extract CHALLENGE request from Interest packet.
Definition server.hpp:182
static bool isName(const CaProfile &profile, const Name &name)
Determine whether name is a valid CHALLENGE request packet name.
Definition server.hpp:161
static const uint8_t * parseName(const CaProfile &profile, const Name &name)
Extract requestId from Interest name.
Definition server.hpp:173
CHALLENGE response packet.
Definition server.hpp:219
Data::Signed toData(Region ®ion, const Interest &challengeRequest, const uint8_t *requestId, detail::SessionKey &sessionKey, const EcPrivateKey &signer) const
Build CHALLENGE response packet.
Definition server.hpp:227
Server side of a challenge.
Definition server.hpp:29
virtual tlv::Value getId() const =0
virtual ChallengeResult process(Region ®ion, const ChallengeRequest &request)=0
Process a CHALLENGE request packet.
virtual int getRetryLimit() const =0
virtual ~Challenge()=default
virtual void clear()=0
Clear state and prepare the challenge for new session.
virtual int getTimeLimit() const =0
NEW request packet.
Definition server.hpp:85
EcPublicKey pub
Requester public key.
Definition server.hpp:114
bool fromInterest(Region ®ion, const Interest &interest, const CaProfile &profile, detail::ISigPolicy &signingPolicy)
Extract NEW request from Interest packet.
Definition server.hpp:99
static bool isName(const CaProfile &profile, const Name &name)
Determine whether name is a valid NEW request packet name.
Definition server.hpp:88
NEW response packet.
Definition server.hpp:118
Data::Signed toData(Region ®ion, const Interest &newRequest, const ChallengeList &challenges, const EcPrivateKey &signer) const
Build NEW response packet.
Definition server.hpp:127
The "nop" challenge where the server would approve every request.
Definition server.hpp:456
ChallengeResult process(Region &, const ChallengeRequest &) override
Process a CHALLENGE request packet.
Definition server.hpp:472
int getRetryLimit() const override
Definition server.hpp:466
tlv::Value getId() const override
Definition server.hpp:458
void clear() override
Clear state and prepare the challenge for new session.
Definition server.hpp:470
int getTimeLimit() const override
Definition server.hpp:462
The "possession" challenge where client must present an existing certificate.
Definition server.hpp:480
int getRetryLimit() const override
Definition server.hpp:490
tlv::Value getId() const override
Definition server.hpp:482
void clear() override
Clear state and prepare the challenge for new session.
Definition server.hpp:494
ChallengeResult process(Region &, const ChallengeRequest &request) override
Process a CHALLENGE request packet.
Definition server.hpp:498
int getTimeLimit() const override
Definition server.hpp:486
Server application.
Definition server.hpp:408
Server(const Options &opts)
Definition server.hpp:424
bool processInterest(Interest interest) final
Override to receive Interest packets.
Definition server.hpp:431
Server session logic.
Definition server.hpp:286
Data::Signed handleChallengeRequest(Region &packetRegion, const Interest &interest)
Definition server.hpp:326
const Data & getIssuedCert() const
Definition server.hpp:388
Session(const CaProfile &profile, const EcPrivateKey &signer, const ChallengeList &challenges)
Definition server.hpp:288
const Name & getIssuedCertName() const
Definition server.hpp:384
Data::Signed handleNewRequest(Region &packetRegion, const Interest &interest)
Definition server.hpp:303
NonNegativeInteger encoding.
Definition nni.hpp:118
Encode to a TLV element where TLV-VALUE is a NonNegativeInteger.
Definition nni.hpp:170
A sequence of bytes, usually TLV-VALUE.
Definition value.hpp:11
Decoder makeDecoder() const
Create a Decoder over this value buffer.
Definition value.hpp:64
const uint8_t * begin() const
Definition value.hpp:38
size_t size() const
Definition value.hpp:46
#define NDNPH_ASSERT(x)
Definition common.hpp:30
@ GenericNameComponent
Definition an.hpp:20
detail::TypedNumber< TT::SegmentNameComponent > Segment
SegmentNameComponent convention.
Definition convention.hpp:209
detail::TypedNumber< TT::VersionNameComponent > Version
VersionNameComponent convention.
Definition convention.hpp:223
@ Salt
Definition an.hpp:23
@ ErrorCode
Definition an.hpp:34
@ MaxValidityPeriod
Definition an.hpp:18
@ Challenge
Definition an.hpp:25
@ CaInfo
Definition an.hpp:14
@ ErrorInfo
Definition an.hpp:35
@ RequestId
Definition an.hpp:24
@ CaCertificate
Definition an.hpp:17
@ CaPrefix
Definition an.hpp:13
@ EcdhPub
Definition an.hpp:21
tlv::Value proof()
Definition an.hpp:136
Data::Signed makeError(Region ®ion, const Interest &interest, uint8_t errorCode, const EcPrivateKey &signer)
Definition server.hpp:269
std::array< Challenge *, detail::MaxChallenges::value > ChallengeList
Definition server.hpp:49
Component getInfoComponent()
Return 'INFO' component.
Definition an.hpp:53
Component getCaComponent()
Return 'CA' component.
Definition an.hpp:45
Component getNewComponent()
Return 'NEW' component.
Definition an.hpp:69
Component getChallengeComponent()
Return 'CHALLENGE' component.
Definition an.hpp:77
Region * makeSubRegion(Region &parent, size_t capacity)
Create Region inside a parent Region.
Definition region.hpp:173
ec::EcPublicKey EcPublicKey
Definition ec.hpp:325
packet_struct::ParameterKV params
Definition server.hpp:20
bool success
Definition server.hpp:17
const char * challengeStatus
Definition server.hpp:19
bool decrementRetry
Definition server.hpp:18
Definition server.hpp:410
const EcPrivateKey & signer
CA private key.
Definition server.hpp:421
const CaProfile & profile
CA profile.
Definition server.hpp:415
const ChallengeList & challenges
List of offered challenges.
Definition server.hpp:418
Face & face
Face for communication.
Definition server.hpp:412