blob: e809213bbe4500acf435e0ef9272621980d52a7d [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 Zhang08e0e982017-03-01 10:10:42 -080022#include "logging.hpp"
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080023#include <ndn-cxx/util/random.hpp>
24
25namespace ndn {
26namespace ndncert {
27
Zhiyi Zhang08e0e982017-03-01 10:10:42 -080028_LOG_INIT(ndncert.challenge-pin);
29
Zhiyi Zhang36706832019-07-04 21:33:03 -070030NDNCERT_REGISTER_CHALLENGE(ChallengePin, "pin");
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080031
32const std::string ChallengePin::NEED_CODE = "need-code";
33const std::string ChallengePin::WRONG_CODE = "wrong-code";
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070034const std::string ChallengePin::JSON_PIN_CODE = "pin-code";
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080035
36ChallengePin::ChallengePin(const size_t& maxAttemptTimes, const time::seconds& secretLifetime)
Zhiyi Zhang36706832019-07-04 21:33:03 -070037 : ChallengeModule("pin")
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080038 , m_secretLifetime(secretLifetime)
39 , m_maxAttemptTimes(maxAttemptTimes)
40{
41}
42
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070043// For CA
44void
Suyong Won19fba4d2020-05-09 13:39:46 -070045ChallengePin::handleChallengeRequest(const Block& params, CertificateRequest& request)
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080046{
Suyong Won44d0cce2020-05-10 04:07:43 -070047 params.parse();
Zhiyi Zhang8da54d62019-11-21 00:03:05 -080048 auto currentTime = time::system_clock::now();
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070049 if (request.m_challengeStatus == "") {
50 _LOG_TRACE("Challenge Interest arrives. Init the challenge");
51 // for the first time, init the challenge
52 request.m_status = STATUS_CHALLENGE;
53 request.m_challengeStatus = NEED_CODE;
54 request.m_challengeType = CHALLENGE_TYPE;
55 std::string secretCode = generateSecretCode();
56 JsonSection secretJson;
57 secretJson.add(JSON_PIN_CODE, secretCode);
58 request.m_challengeSecrets = secretJson;
Zhiyi Zhang8da54d62019-11-21 00:03:05 -080059 request.m_challengeTp = time::toIsoString(currentTime);
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070060 request.m_remainingTime = m_secretLifetime.count();
61 request.m_remainingTries = m_maxAttemptTimes;
62 _LOG_TRACE("Secret for request " << request.m_requestId << " : " << secretCode);
63 return;
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080064 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070065 else if (request.m_challengeStatus == NEED_CODE || request.m_challengeStatus == WRONG_CODE) {
66 _LOG_TRACE("Challenge Interest arrives. Challenge Status: " << request.m_challengeStatus);
67 // the incoming interest should bring the pin code
Suyong Won19fba4d2020-05-09 13:39:46 -070068 std::string givenCode = readString(params.get(tlv_parameter_value));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070069 const auto realCode = request.m_challengeSecrets.get<std::string>(JSON_PIN_CODE);
Zhiyi Zhang8da54d62019-11-21 00:03:05 -080070 if (currentTime - time::fromIsoString(request.m_challengeTp) >= m_secretLifetime) {
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070071 // secret expires
72 request.m_status = STATUS_FAILURE;
73 request.m_challengeStatus = CHALLENGE_STATUS_FAILURE_TIMEOUT;
74 updateRequestOnChallengeEnd(request);
75 _LOG_TRACE("Secret expired. Challenge failed.");
76 return;
77 }
78 else if (givenCode == realCode) {
79 // the code is correct
80 request.m_status = STATUS_PENDING;
81 request.m_challengeStatus = CHALLENGE_STATUS_SUCCESS;
82 updateRequestOnChallengeEnd(request);
83 _LOG_TRACE("PIN code matched. Challenge succeeded.");
84 return;
Zhiyi Zhang65ba9322017-01-19 14:15:03 -080085 }
86 else {
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070087 // check rest attempt times
88 if (request.m_remainingTries > 1) {
89 request.m_challengeStatus = WRONG_CODE;
90 request.m_remainingTries = request.m_remainingTries - 1;
Zhiyi Zhang8da54d62019-11-21 00:03:05 -080091 auto remainTime = m_secretLifetime - (currentTime - time::fromIsoString(request.m_challengeTp));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070092 request.m_remainingTime = remainTime.count();
93 _LOG_TRACE("PIN code didn't match. Remaining Tries - 1.");
94 return;
95 }
96 else {
97 // run out times
98 request.m_status = STATUS_FAILURE;
99 request.m_challengeStatus = CHALLENGE_STATUS_FAILURE_MAXRETRY;
100 updateRequestOnChallengeEnd(request);
101 _LOG_TRACE("PIN code didn't match. Ran out tires. Challenge failed.");
102 return;
103 }
Zhiyi Zhang65ba9322017-01-19 14:15:03 -0800104 }
105 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700106 else {
107 _LOG_ERROR("The challenge status is wrong");
108 request.m_status = STATUS_FAILURE;
109 return;
Zhiyi Zhang65ba9322017-01-19 14:15:03 -0800110 }
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700111}
112
113// For Client
114JsonSection
115ChallengePin::getRequirementForChallenge(int status, const std::string& challengeStatus)
116{
117 JsonSection result;
118 if (status == STATUS_BEFORE_CHALLENGE && challengeStatus == "") {
119 // do nothing
120 }
121 else if (status == STATUS_CHALLENGE && challengeStatus == NEED_CODE) {
122 result.put(JSON_PIN_CODE, "Please_input_your_verification_code");
123 }
124 else if (status == STATUS_CHALLENGE && challengeStatus == WRONG_CODE) {
125 result.put(JSON_PIN_CODE, "Incorrect_PIN_code_please_try_again");
126 }
127 else {
128 _LOG_ERROR("Client's status and challenge status are wrong");
Zhiyi Zhang65ba9322017-01-19 14:15:03 -0800129 }
130 return result;
131}
132
133JsonSection
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700134ChallengePin::genChallengeRequestJson(int status, const std::string& challengeStatus, const JsonSection& params)
Zhiyi Zhang65ba9322017-01-19 14:15:03 -0800135{
136 JsonSection result;
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700137 if (status == STATUS_BEFORE_CHALLENGE && challengeStatus == "") {
138 // do nothing
139 result.put(JSON_CLIENT_SELECTED_CHALLENGE, CHALLENGE_TYPE);
140 }
141 else if (status == STATUS_CHALLENGE && challengeStatus == NEED_CODE) {
142 result.put(JSON_CLIENT_SELECTED_CHALLENGE, CHALLENGE_TYPE);
Zhiyi Zhang8da54d62019-11-21 00:03:05 -0800143 result.put(JSON_PIN_CODE, params.get(JSON_PIN_CODE, ""));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700144 }
145 else if (status == STATUS_CHALLENGE && challengeStatus == WRONG_CODE) {
146 result.put(JSON_CLIENT_SELECTED_CHALLENGE, CHALLENGE_TYPE);
Zhiyi Zhang8da54d62019-11-21 00:03:05 -0800147 result.put(JSON_PIN_CODE, params.get(JSON_PIN_CODE, ""));
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700148 }
149 else {
150 _LOG_ERROR("Client's status and challenge status are wrong");
151 }
Zhiyi Zhangf72c0542017-03-16 14:45:30 -0700152 return result;
153}
154
Suyong Won19fba4d2020-05-09 13:39:46 -0700155Block
156ChallengePin::genChallengeRequestTLV(int status, const std::string& challengeStatus, const JsonSection& params)
157{
158 Block request = makeEmptyBlock(tlv_encrypted_payload);
159 if (status == STATUS_BEFORE_CHALLENGE && challengeStatus == "") {
160 // do nothing
161 request.push_back(makeStringBlock(tlv_selected_challenge, CHALLENGE_TYPE));
162 }
163 else if (status == STATUS_CHALLENGE && challengeStatus == NEED_CODE) {
164 request.push_back(makeStringBlock(tlv_selected_challenge, CHALLENGE_TYPE));
165 request.push_back(makeStringBlock(tlv_parameter_key, JSON_PIN_CODE));
166 request.push_back(makeStringBlock(tlv_parameter_value, params.get(JSON_PIN_CODE,"")));
167 }
168 else if (status == STATUS_CHALLENGE && challengeStatus == WRONG_CODE) {
169 request.push_back(makeStringBlock(tlv_selected_challenge, CHALLENGE_TYPE));
170 request.push_back(makeStringBlock(tlv_parameter_key, JSON_PIN_CODE));
171 request.push_back(makeStringBlock(tlv_parameter_value, params.get(JSON_PIN_CODE,"")));
172 }
173 else {
174 _LOG_ERROR("Client's status and challenge status are wrong");
175 }
Suyong Won44d0cce2020-05-10 04:07:43 -0700176 request.encode();
Suyong Won19fba4d2020-05-09 13:39:46 -0700177 return request;
178}
Zhiyi Zhang65ba9322017-01-19 14:15:03 -0800179} // namespace ndncert
180} // namespace ndn