blob: cd20c515edf355ff22a2377a1e51c796ac3f96c8 [file] [log] [blame]
Zhiyi Zhang65ba9322017-01-19 14:15:03 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -07003 * Copyright (c) 2017-2019, Regents of the University of California.
Zhiyi Zhang65ba9322017-01-19 14:15:03 -08004 *
5 * This file is part of ndncert, a certificate management system based on NDN.
6 *
7 * ndncert is free software: you can redistribute it and/or modify it under the terms
8 * of the GNU General Public License as published by the Free Software Foundation, either
9 * version 3 of the License, or (at your option) any later version.
10 *
11 * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License along with
16 * ndncert, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * See AUTHORS.md for complete list of ndncert authors and contributors.
19 */
20
21#include "challenge-pin.hpp"
Zhiyi Zhang46049832020-09-28 17:08:12 -070022
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080023#include <ndn-cxx/util/random.hpp>
24
Zhiyi Zhang46049832020-09-28 17:08:12 -070025#include "logging.hpp"
26
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080027namespace ndn {
28namespace ndncert {
29
Zhiyi Zhang46049832020-09-28 17:08:12 -070030_LOG_INIT(ndncert.challenge.pin);
Zhiyi Zhang36706832019-07-04 21:33:03 -070031NDNCERT_REGISTER_CHALLENGE(ChallengePin, "pin");
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080032
33const std::string ChallengePin::NEED_CODE = "need-code";
34const std::string ChallengePin::WRONG_CODE = "wrong-code";
Zhiyi Zhang46049832020-09-28 17:08:12 -070035const std::string ChallengePin::PARAMETER_KEY_CODE = "pin-code";
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080036
37ChallengePin::ChallengePin(const size_t& maxAttemptTimes, const time::seconds& secretLifetime)
Zhiyi Zhang46049832020-09-28 17:08:12 -070038 : ChallengeModule("pin")
39 , m_secretLifetime(secretLifetime)
40 , m_maxAttemptTimes(maxAttemptTimes)
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080041{
42}
43
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070044// For CA
Zhiyi Zhang46049832020-09-28 17:08:12 -070045std::tuple<Error, std::string>
Suyong Won19fba4d2020-05-09 13:39:46 -070046ChallengePin::handleChallengeRequest(const Block& params, CertificateRequest& request)
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080047{
Suyong Won44d0cce2020-05-10 04:07:43 -070048 params.parse();
Zhiyi Zhang8da54d62019-11-21 00:03:05 -080049 auto currentTime = time::system_clock::now();
Zhiyi Zhang46049832020-09-28 17:08:12 -070050 if (request.m_status == Status::BEFORE_CHALLENGE) {
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070051 _LOG_TRACE("Challenge Interest arrives. Init the challenge");
52 // for the first time, init the challenge
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070053 std::string secretCode = generateSecretCode();
54 JsonSection secretJson;
Zhiyi Zhang46049832020-09-28 17:08:12 -070055 secretJson.add(PARAMETER_KEY_CODE, secretCode);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070056 _LOG_TRACE("Secret for request " << request.m_requestId << " : " << secretCode);
Zhiyi Zhang46049832020-09-28 17:08:12 -070057 return returnWithNewChallengeStatus(request, NEED_CODE, std::move(secretJson), m_maxAttemptTimes, m_secretLifetime.count());
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080058 }
Zhiyi Zhang46049832020-09-28 17:08:12 -070059
60 if (request.m_challengeStatus == NEED_CODE || request.m_challengeStatus == WRONG_CODE) {
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070061 _LOG_TRACE("Challenge Interest arrives. Challenge Status: " << request.m_challengeStatus);
62 // the incoming interest should bring the pin code
Suyong Won19fba4d2020-05-09 13:39:46 -070063 std::string givenCode = readString(params.get(tlv_parameter_value));
Zhiyi Zhang46049832020-09-28 17:08:12 -070064 auto secret = request.m_challengeSecrets;
Zhiyi Zhang8da54d62019-11-21 00:03:05 -080065 if (currentTime - time::fromIsoString(request.m_challengeTp) >= m_secretLifetime) {
Zhiyi Zhang46049832020-09-28 17:08:12 -070066 return returnWithError(request, Error::OUT_OF_TIME, "Secret expired.");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070067 }
Zhiyi Zhang46049832020-09-28 17:08:12 -070068 if (givenCode == secret.get<std::string>(PARAMETER_KEY_CODE)) {
69 _LOG_TRACE("Correct PIN code. Challenge succeeded.");
70 return returnWithSuccess(request);
71 }
72 // check rest attempt times
73 if (request.m_remainingTries > 1) {
74 auto remainTime = m_secretLifetime - (currentTime - time::fromIsoString(request.m_challengeTp));
75 _LOG_TRACE("Wrong PIN code provided. Remaining Tries - 1.");
76 return returnWithNewChallengeStatus(request, WRONG_CODE, std::move(secret), request.m_remainingTries - 1, remainTime.count());
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080077 }
78 else {
Zhiyi Zhang46049832020-09-28 17:08:12 -070079 // run out times
80 _LOG_TRACE("Wrong PIN code provided. Ran out tires. Challenge failed.");
81 return returnWithError(request, Error::OUT_OF_TRIES, "Ran out tires.");
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080082 }
83 }
Zhiyi Zhang46049832020-09-28 17:08:12 -070084 return returnWithError(request, Error::INVALID_PARAMETER, "Unexpected status or challenge status");
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070085}
86
87// For Client
Zhiyi Zhang46049832020-09-28 17:08:12 -070088std::vector<std::tuple<std::string, std::string>>
89ChallengePin::getRequestedParameterList(Status status, const std::string& challengeStatus)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070090{
Zhiyi Zhang46049832020-09-28 17:08:12 -070091 std::vector<std::tuple<std::string, std::string>> result;
92 if (status == Status::BEFORE_CHALLENGE) {
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070093 // do nothing
94 }
Zhiyi Zhang48f23782020-09-28 12:11:24 -070095 else if (status == Status::CHALLENGE && challengeStatus == NEED_CODE) {
Zhiyi Zhang46049832020-09-28 17:08:12 -070096 result.push_back(std::make_tuple(PARAMETER_KEY_CODE, "Please input your PIN code"));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070097 }
Zhiyi Zhang48f23782020-09-28 12:11:24 -070098 else if (status == Status::CHALLENGE && challengeStatus == WRONG_CODE) {
Zhiyi Zhang46049832020-09-28 17:08:12 -070099 result.push_back(std::make_tuple(PARAMETER_KEY_CODE, "Incorrect PIN code, please try again"));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700100 }
101 else {
Zhiyi Zhang46049832020-09-28 17:08:12 -0700102 BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected status or challenge status."));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700103 }
Zhiyi Zhangf72c0542017-03-16 14:45:30 -0700104 return result;
105}
106
Suyong Won19fba4d2020-05-09 13:39:46 -0700107Block
Zhiyi Zhang46049832020-09-28 17:08:12 -0700108ChallengePin::genChallengeRequestTLV(Status status, const std::string& challengeStatus, std::vector<std::tuple<std::string, std::string>>&& params)
Suyong Won19fba4d2020-05-09 13:39:46 -0700109{
110 Block request = makeEmptyBlock(tlv_encrypted_payload);
Zhiyi Zhang46049832020-09-28 17:08:12 -0700111 if (status == Status::BEFORE_CHALLENGE) {
Suyong Won19fba4d2020-05-09 13:39:46 -0700112 request.push_back(makeStringBlock(tlv_selected_challenge, CHALLENGE_TYPE));
113 }
Zhiyi Zhang46049832020-09-28 17:08:12 -0700114 else if (status == Status::CHALLENGE && (challengeStatus == NEED_CODE || challengeStatus == WRONG_CODE)) {
115 if (params.size() != 1 || std::get<0>(params[0]) != PARAMETER_KEY_CODE) {
116 BOOST_THROW_EXCEPTION(std::runtime_error("Wrong parameter provided."));
117 }
Suyong Won19fba4d2020-05-09 13:39:46 -0700118 request.push_back(makeStringBlock(tlv_selected_challenge, CHALLENGE_TYPE));
Zhiyi Zhang46049832020-09-28 17:08:12 -0700119 request.push_back(makeStringBlock(tlv_parameter_key, PARAMETER_KEY_CODE));
120 request.push_back(makeStringBlock(tlv_parameter_value, std::get<1>(params[0])));
Suyong Won19fba4d2020-05-09 13:39:46 -0700121 }
122 else {
Zhiyi Zhang46049832020-09-28 17:08:12 -0700123 BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected status or challenge status."));
Suyong Won19fba4d2020-05-09 13:39:46 -0700124 }
Suyong Won44d0cce2020-05-10 04:07:43 -0700125 request.encode();
Suyong Won19fba4d2020-05-09 13:39:46 -0700126 return request;
127}
Zhiyi Zhang46049832020-09-28 17:08:12 -0700128} // namespace ndncert
129} // namespace ndn