1 #ifndef NDNPH_APP_NDNCERT_CLIENT_HPP
2 #define NDNPH_APP_NDNCERT_CLIENT_HPP
5 #include "../../face/packet-handler.hpp"
45 void (*cb)(
void*,
bool),
void* arg) = 0;
48 using ChallengeList = std::array<Challenge*, detail::MaxChallenges::value>;
69 EvDecoder::def<TT::CaPrefix>([&](
const Decoder::Tlv& d) {
70 if (!d.vd().decode(prefix) || data.getName().getPrefix(-4) != prefix) {
76 EvDecoder::defIgnore<TT::CaInfo>(), EvDecoder::defIgnore<TT::ParameterKey, true>(),
78 EvDecoder::def<TT::CaCertificate>([&](
const Decoder::Tlv& d) {
108 if (!encoder || !name || !interest) {
128 hasChallenge.reset();
132 EvDecoder::def<TT::Salt>([
this](
const Decoder::Tlv& d) {
133 if (d.length == sizeof(salt)) {
134 std::copy_n(d.value, d.length, salt);
139 EvDecoder::def<TT::RequestId>([
this](
const Decoder::Tlv& d) {
140 if (d.
length ==
sizeof(requestId)) {
141 std::copy_n(d.value, d.length, requestId);
146 EvDecoder::def<TT::Challenge, true>([
this, &challenges](
const Decoder::Tlv& d) {
147 for (
size_t i = 0; i < challenges.size(); ++i) {
189 Component(region, detail::RequestIdLen::value, requestId));
191 if (!encrypted || !name || !interest) {
196 return interest.
parameterize(encrypted).
sign(signer, region, signingPolicy);
215 uint32_t remainingTime = 0;
219 decrypted.makeDecoder(), EvDecoder::defNni<TT::Status, tlv::NNI, 1>(&status),
220 EvDecoder::def<TT::ChallengeStatus, false, 2>(&challengeStatus),
221 EvDecoder::defNni<TT::RemainingTries, tlv::NNI, 3>(&remainingTries),
222 EvDecoder::defNni<TT::RemainingTime, tlv::NNI, 4>(&remainingTime),
223 EvDecoder::def<TT::ParameterKey, true, 5>(
224 [&](
const Decoder::Tlv& d) { return paramsParser.parseKey(d); }),
225 EvDecoder::def<TT::ParameterValue, true, 5>(
226 [&](
const Decoder::Tlv& d) { return paramsParser.parseValue(d); }),
227 EvDecoder::def<TT::IssuedCertName, false, 6>(
228 [
this](
const Decoder::Tlv& d) { return d.vd().decode(issuedCertName); }),
229 EvDecoder::def<TT::ForwardingHint, false, 7>([
this](
const Decoder::Tlv& d) {
230 return detail::decodeFwHint(d, &fwHint);
283 SendChallengeRequest,
284 WaitChallengeResponse,
293 explicit GotoState(
Client* client)
294 : m_client(client) {}
296 bool operator()(State state) {
298 static_cast<int>(state));
299 m_client->m_state = state;
307 static_cast<int>(State::Failure));
308 m_client->m_state = State::Failure;
313 Client* m_client =
nullptr;
317 explicit Client(
const Options& opts)
318 : PacketHandler(opts.face)
320 , m_profile(opts.profile)
321 , m_challenges(opts.challenges)
324 , m_cbCtx(opts.ctx) {
325 sendNewRequest(opts.pub);
330 case State::SendChallengeRequest: {
331 sendChallengeRequest();
334 case State::FetchIssuedCert: {
338 case State::WaitNewResponse:
339 case State::WaitChallengeResponse:
340 case State::WaitIssuedCert: {
341 if (m_pending.expired()) {
342 m_state = State::Failure;
346 case State::Success: {
350 case State::Failure: {
351 m_cb(m_cbCtx,
Data());
360 bool processData(
Data data)
final {
361 if (!m_pending.matchPitToken()) {
366 case State::WaitNewResponse: {
367 return handleNewResponse(data);
369 case State::WaitChallengeResponse: {
370 return handleChallengeResponse(data);
372 case State::WaitIssuedCert: {
373 return handleIssuedCert(data);
382 StaticRegion<2048> region;
383 GotoState gotoState(
this);
393 if (!validity.includesUnix()) {
398 auto cert = pub.selfSign(m_region, validity, m_pvt);
399 m_newRequest.certRequest = m_region.create<
Data>();
400 if (!m_newRequest.certRequest || !m_newRequest.certRequest.decodeFrom(cert)) {
405 m_pending.send(m_newRequest.toInterest(region, m_profile, m_signingPolicy, m_pvt)) &&
406 gotoState(State::WaitNewResponse);
409 bool handleNewResponse(
Data data) {
410 bool ok = m_newResponse.fromData(m_region, data, m_profile, m_challenges);
416 GotoState gotoState(
this);
417 for (
size_t i = 0; i < m_newResponse.hasChallenge.size(); ++i) {
418 if (m_newResponse.hasChallenge.test(i)) {
419 m_challengeRequest.challenge = m_challenges[i];
423 if (m_challengeRequest.challenge ==
nullptr) {
428 ok = m_sessionKey.makeKey(m_ecdhPvt, m_newResponse.ecdhPub, m_newResponse.salt,
429 m_newResponse.requestId);
434 prepareChallengeRequest(gotoState);
438 static void challengeCallback(
void*
self,
bool ok) {
439 static_cast<Client*
>(
self)->m_state = ok ? State::SendChallengeRequest : State::Failure;
442 void prepareChallengeRequest(GotoState& gotoState) {
443 gotoState(State::ExecuteChallenge);
444 m_challengeRequest.params.clear();
446 m_challengeRequest.challenge->start(m_challengeRegion, m_challengeRequest, challengeCallback,
449 m_challengeRequest.challenge->next(m_challengeRegion, m_challengeResponse, m_challengeRequest,
450 challengeCallback,
this);
454 void sendChallengeRequest() {
455 StaticRegion<2048> region;
456 GotoState gotoState(
this);
457 m_pending.send(m_challengeRequest.toInterest(region, m_profile, m_newResponse.requestId,
458 m_sessionKey, m_signingPolicy, m_pvt)) &&
459 gotoState(State::WaitChallengeResponse);
462 bool handleChallengeResponse(
Data data) {
463 m_challengeRegion.reset();
464 bool ok = m_challengeResponse.fromData(m_challengeRegion, data, m_profile,
465 m_newResponse.requestId, m_sessionKey);
471 GotoState gotoState(
this);
472 switch (m_challengeResponse.status) {
474 prepareChallengeRequest(gotoState);
477 return gotoState(State::FetchIssuedCert);
484 void sendFetchInterest() {
486 GotoState gotoState(
this);
489 interest.setName(m_challengeResponse.issuedCertName);
490 interest.setFwHint(m_challengeResponse.fwHint);
491 m_pending.send(interest) && gotoState(State::WaitIssuedCert);
494 bool handleIssuedCert(
Data data) {
496 if (data.getFullName(region) != m_challengeResponse.issuedCertName) {
501 GotoState gotoState(
this);
507 return gotoState(State::Success);
511 OutgoingPendingInterest m_pending;
512 State m_state = State::SendNewRequest;
514 const CaProfile& m_profile;
520 StaticRegion<2048> m_region;
521 StaticRegion<512> m_challengeRegion;
523 mbedtls::Mpi m_ecdhPvt;
524 NewRequest m_newRequest;
525 NewResponse m_newResponse;
526 detail::SessionKey m_sessionKey;
527 ChallengeRequest m_challengeRequest;
528 ChallengeResponse m_challengeResponse;
543 void* arg)
override {
552 : m_cert(std::move(cert))
553 , m_signer(signer) {}
560 void* arg)
override {
575 void (*cb)(
void*,
bool),
void* arg)
override {
577 uint8_t* sig = region.
alloc(m_signer.getMaxSigLen());
578 if (
nonce.
size() != 16 || sig ==
nullptr) {
584 ssize_t sigLen = m_signer.sign({
nonce}, sig);
#define NDNPH_NDNCERT_LOG(...)
Definition: common.hpp:15
Name component.
Definition: component.hpp:16
Data packet.
Definition: data.hpp:136
tlv::Value getContent() const
Definition: data.hpp:172
const Name & getName() const
Definition: data.hpp:140
bool verify(const PublicKey &key) const
Verify the packet with a public key.
Definition: data.hpp:263
bool decodeFrom(const Decoder::Tlv &input)
Decode packet.
Definition: data.hpp:201
Decoded TLV.
Definition: decoder.hpp:13
size_t length
Definition: decoder.hpp:39
const uint8_t * value
Definition: decoder.hpp:40
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
Signed sign(const PrivateKey &key, ISigInfo sigInfo=ISigInfo()) const
Definition: interest.hpp:350
Interest packet.
Definition: interest.hpp:284
Parameterized parameterize(tlv::Value appParameters) const
Add AppParameters to the packet.
Definition: interest.hpp:374
void setMustBeFresh(bool v)
Definition: interest.hpp:296
detail::SignedInterestRef Signed
Result of Interest::sign operation.
Definition: interest.hpp:343
void setName(const Name &v)
Definition: interest.hpp:288
Name.
Definition: name.hpp:14
size_t size() const
Get number of components.
Definition: name.hpp:86
Name append(Region ®ion, const C &... comps) const
Append a sequence of components.
Definition: name.hpp:183
Name clone(Region ®ion) const
Clone TLV-VALUE into given region.
Definition: name.hpp:203
Base class to receive packets from Face.
Definition: packet-handler.hpp:10
Private key.
Definition: private-key.hpp:9
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
uint8_t * alloc(size_t size)
Allocate a buffer with no alignment requirement.
Definition: region.hpp:27
static ValidityPeriod secondsFromNow(uint64_t seconds)
Get a ValidityPeriod from now until seconds later.
Definition: validity-period.hpp:45
ValidityPeriod intersect(const ValidityPeriod &other) const
Calculate the intersection of this and other ValidityPeriod.
Definition: validity-period.hpp:72
Definition: convention.hpp:111
Definition: interest.hpp:206
EC private key.
Definition: ec.hpp:180
EC public key.
Definition: ec.hpp:65
bool import(const Name &name, const uint8_t raw[KeyLen::value])
Import from raw key bits.
Definition: ec.hpp:80
static mbedtls_ecp_group * group()
Definition: mbed-common.hpp:240
CA profile packet.
Definition: client.hpp:51
static bool isName(const Name &name)
Determine whether name is a valid CA profile packet name.
Definition: client.hpp:54
bool fromData(Region ®ion, const Data &data)
Extract CA profile from Data packet.
Definition: client.hpp:65
EcPublicKey pub
CA public key.
Definition: client.hpp:88
CHALLENGE request packet.
Definition: client.hpp:166
Interest::Signed toInterest(Region ®ion, const CaProfile &profile, const uint8_t *requestId, detail::SessionKey &sessionKey, detail::ISigPolicy &signingPolicy, const EcPrivateKey &signer) const
Build CHALLENGE request packet.
Definition: client.hpp:174
CHALLENGE response packet.
Definition: client.hpp:201
bool fromData(Region ®ion, const Data &data, const CaProfile &profile, const uint8_t *requestId, detail::SessionKey &sessionKey)
Extract CHALLENGE response from Data packet.
Definition: client.hpp:208
Client side of a challenge.
Definition: client.hpp:22
virtual void start(Region ®ion, ChallengeRequest &request, void(*cb)(void *, bool), void *arg)=0
Create a message to select and start the challenge.
virtual ~Challenge()=default
virtual tlv::Value getId() const =0
Return challenge identifier.
virtual void next(Region ®ion, const ChallengeResponse &response, ChallengeRequest &request, void(*cb)(void *, bool), void *arg)=0
Create a message to continue the challenge.
Client application.
Definition: client.hpp:241
static void requestCertificate(const Options &opts)
Request a certificate.
Definition: client.hpp:274
void(*)(void *ctx, Data cert) Callback
Callback to be invoked upon completion of a certificate request procedure.
Definition: client.hpp:248
NEW request packet.
Definition: client.hpp:92
Interest::Signed toInterest(Region ®ion, const CaProfile &profile, detail::ISigPolicy &signingPolicy, const EcPrivateKey &signer) const
Build NEW request packet.
Definition: client.hpp:99
NEW response packet.
Definition: client.hpp:118
std::bitset< detail::MaxChallenges::value > hasChallenge
List of client challenges offered by server.
Definition: client.hpp:162
bool fromData(Region &, const Data &data, const CaProfile &profile, const ChallengeList &challenges)
Extract NEW response from Data packet.
Definition: client.hpp:126
The "nop" challenge where the server would approve every request.
Definition: client.hpp:532
void start(Region &, ChallengeRequest &, void(*cb)(void *, bool), void *arg) override
Create a message to select and start the challenge.
Definition: client.hpp:538
void next(Region &, const ChallengeResponse &, ChallengeRequest &, void(*cb)(void *, bool), void *arg) override
Create a message to continue the challenge.
Definition: client.hpp:542
tlv::Value getId() const override
Return challenge identifier.
Definition: client.hpp:534
The "possession" challenge where client must present an existing certificate.
Definition: client.hpp:549
void start(Region ®ion, ChallengeRequest &request, void(*cb)(void *, bool), void *arg) override
Create a message to select and start the challenge.
Definition: client.hpp:559
void next(Region ®ion, const ChallengeResponse &response, ChallengeRequest &request, void(*cb)(void *, bool), void *arg) override
Create a message to continue the challenge.
Definition: client.hpp:574
tlv::Value getId() const override
Return challenge identifier.
Definition: client.hpp:555
PossessionChallenge(Data cert, const PrivateKey &signer)
Definition: client.hpp:551
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
Definition: common.hpp:85
bool set(tlv::Value key, tlv::Value value)
Set a parameter.
Definition: common.hpp:126
tlv::Value get(tlv::Value key) const
Retrieve parameter value by parameter key.
Definition: common.hpp:116
static Time now()
Definition: ino.hpp:21
static Time add(Time t, int ms)
Definition: ino.hpp:27
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
size_t size() const
Definition: value.hpp:46
#define NDNPH_ASSERT(x)
Definition: common.hpp:30
@ Data
Definition: an.hpp:41
ValidityPeriod getValidity(const Data &data)
Definition: certificate.hpp:184
bool isCertificate(const Data &data)
Determine if the Data packet is a certificate that contains an EC public key.
Definition: ec.hpp:319
int rng(void *, uint8_t *output, size_t count)
Random number generator for various Mbed TLS library functions.
Definition: mbed-common.hpp:30
@ CHALLENGE
Definition: an.hpp:87
@ BEFORE_CHALLENGE
Definition: an.hpp:86
@ SUCCESS
Definition: an.hpp:89
@ Challenge
Definition: an.hpp:25
@ SelectedChallenge
Definition: an.hpp:29
@ CertRequest
Definition: an.hpp:22
@ EcdhPub
Definition: an.hpp:21
tlv::Value proof()
Definition: an.hpp:136
tlv::Value nonce()
Definition: an.hpp:130
tlv::Value nop()
Definition: an.hpp:112
tlv::Value possession()
Definition: an.hpp:118
tlv::Value issuedcert()
Definition: an.hpp:124
std::array< Challenge *, detail::MaxChallenges::value > ChallengeList
Definition: client.hpp:48
isig::Policy< isig::Nonce<>, isig::Time<> > ISigPolicy
Definition: common.hpp:73
Component getInfoComponent()
Return 'INFO' component.
Definition: an.hpp:53
client::Client Client
Definition: client.hpp:602
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
ec::EcPrivateKey EcPrivateKey
Definition: ec.hpp:326
ec::EcPublicKey EcPublicKey
Definition: ec.hpp:325
Definition: client.hpp:250
Face & face
Face for communication.
Definition: client.hpp:252
void * ctx
Context pointer.
Definition: client.hpp:270
const EcPrivateKey & pvt
Corresponding private key.
Definition: client.hpp:264
Callback cb
Completion callback.
Definition: client.hpp:267
const EcPublicKey & pub
Public key to appear in the certificate.
Definition: client.hpp:261
const ChallengeList & challenges
List of acceptable challenges.
Definition: client.hpp:258
const CaProfile & profile
CA profile.
Definition: client.hpp:255
Definition: common.hpp:157
Name prefix
CA prefix.
Definition: common.hpp:159
uint32_t maxValidityPeriod
Maximum ValidityPeriod duration in seconds.
Definition: common.hpp:162
Data cert
CA certificate.
Definition: common.hpp:165
Definition: common.hpp:188
ParameterKV params
Parameter key-value pairs.
Definition: common.hpp:193
Definition: common.hpp:196
ParameterKV params
Parameter key-value pairs.
Definition: common.hpp:210
Definition: common.hpp:168
Definition: common.hpp:176