blob: 74af41393a5c1e66a1c0087134c6983c777c97f2 [file] [log] [blame]
tylerliu729212e2020-09-26 14:31:25 -07001/*
2 * Copyright (c) 2017-2020, Regents of the University of California.
3 *
4 * This file is part of ndncert, a certificate management system based on NDN.
5 *
6 * ndncert is free software: you can redistribute it and/or modify it under the terms
7 * of the GNU General Public License as published by the Free Software Foundation, either
8 * version 3 of the License, or (at your option) any later version.
9 *
10 * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY
11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
12 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
13 *
14 * You should have received copies of the GNU General Public License along with
15 * ndncert, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * See AUTHORS.md for complete list of ndncert authors and contributors.
18 */
19
20#include "challenge-private-key.hpp"
21
22#include <iostream>
23#include <ndn-cxx/security/verification-helpers.hpp>
24#include <ndn-cxx/util/io.hpp>
25
26#include "../logging.hpp"
27
28namespace ndn {
29namespace ndncert {
30
31_LOG_INIT(ndncert.ChallengePrivateKey);
32
33NDNCERT_REGISTER_CHALLENGE(ChallengePrivateKey, "Private");
34
35const std::string ChallengePrivateKey::FAILURE_INVALID_REQUEST_TYPE = "failure-invalid-request-type";
36const std::string ChallengePrivateKey::FAILURE_INVALID_FORMAT_SELF_SIGNED = "failure-cannot-parse-self-signed";
37const std::string ChallengePrivateKey::FAILURE_INVALID_CREDENTIAL = "failure-invalid-credential";
38const std::string ChallengePrivateKey::JSON_PROOF_OF_PRIVATE_KEY = "proof-of-private-key";
39
40ChallengePrivateKey::ChallengePrivateKey()
41 : ChallengeModule("PrivateKey")
42{
43}
44
45// For CA
46void
47ChallengePrivateKey::handleChallengeRequest(const Block& params, CertificateRequest& request)
48{
49 if (request.m_requestType == REQUEST_TYPE_NEW) {
50 _LOG_TRACE("Cannot use this private key challenge for new certificate request");
Zhiyi Zhang48f23782020-09-28 12:11:24 -070051 request.m_status = Status::FAILURE;
tylerliu729212e2020-09-26 14:31:25 -070052 request.m_challengeStatus = FAILURE_INVALID_REQUEST_TYPE;
53 updateRequestOnChallengeEnd(request);
54 }
55 params.parse();
56 shared_ptr<security::v2::Certificate> selfSigned;
57 auto& elements = params.elements();
58 for (size_t i = 0; i < elements.size(); i++) {
59 if (elements[i].type() == tlv_parameter_key) {
60 if (readString(elements[i]) == JSON_PROOF_OF_PRIVATE_KEY) {
61 std::istringstream ss(readString(params.elements()[i + 1]));
62 selfSigned = io::load<security::v2::Certificate>(ss);
63 if (selfSigned == nullptr) {
64 _LOG_ERROR("Cannot load credential parameter: cert");
Zhiyi Zhang48f23782020-09-28 12:11:24 -070065 request.m_status = Status::FAILURE;
tylerliu729212e2020-09-26 14:31:25 -070066 request.m_challengeStatus = FAILURE_INVALID_FORMAT_SELF_SIGNED;
67 updateRequestOnChallengeEnd(request);
68 return;
69 }
70 }
71 else {
72 continue;
73 }
74 }
75 }
76
77 // verify the credential and the self-signed cert
78 if (security::verifySignature(*selfSigned, request.m_cert) &&
79 readString(selfSigned->getContent()) == request.m_requestId) {
Zhiyi Zhang48f23782020-09-28 12:11:24 -070080 request.m_status = Status::PENDING;
tylerliu729212e2020-09-26 14:31:25 -070081 request.m_challengeStatus = CHALLENGE_STATUS_SUCCESS;
82 updateRequestOnChallengeEnd(request);
83 return;
84 }
85
86 _LOG_TRACE("Cannot verify the credential + self-signed Data + data content");
Zhiyi Zhang48f23782020-09-28 12:11:24 -070087 request.m_status = Status::FAILURE;
tylerliu729212e2020-09-26 14:31:25 -070088 request.m_challengeStatus = FAILURE_INVALID_CREDENTIAL;
89 updateRequestOnChallengeEnd(request);
90}
91
92// For Client
93JsonSection
Zhiyi Zhang48f23782020-09-28 12:11:24 -070094ChallengePrivateKey::getRequirementForChallenge(Status status, const std::string& challengeStatus)
tylerliu729212e2020-09-26 14:31:25 -070095{
96 JsonSection result;
Zhiyi Zhang48f23782020-09-28 12:11:24 -070097 if (status == Status::BEFORE_CHALLENGE && challengeStatus == "") {
tylerliu729212e2020-09-26 14:31:25 -070098 result.put(JSON_PROOF_OF_PRIVATE_KEY, "Please_copy_key_signed_request_id_data_here");
99 }
100 else {
101 _LOG_ERROR("Client's status and challenge status are wrong");
102 }
103 return result;
104}
105
106JsonSection
Zhiyi Zhang48f23782020-09-28 12:11:24 -0700107ChallengePrivateKey::genChallengeRequestJson(Status status, const std::string& challengeStatus, const JsonSection& params)
tylerliu729212e2020-09-26 14:31:25 -0700108{
109 JsonSection result;
Zhiyi Zhang48f23782020-09-28 12:11:24 -0700110 if (status == Status::BEFORE_CHALLENGE && challengeStatus == "") {
tylerliu729212e2020-09-26 14:31:25 -0700111 result.put(JSON_PROOF_OF_PRIVATE_KEY, params.get(JSON_PROOF_OF_PRIVATE_KEY, ""));
112 }
113 else {
114 _LOG_ERROR("Client's status and challenge status are wrong");
115 }
116 return result;
117}
118
119Block
Zhiyi Zhang48f23782020-09-28 12:11:24 -0700120ChallengePrivateKey::genChallengeRequestTLV(Status status, const std::string& challengeStatus, const JsonSection& params)
tylerliu729212e2020-09-26 14:31:25 -0700121{
122 Block request = makeEmptyBlock(tlv_encrypted_payload);
Zhiyi Zhang48f23782020-09-28 12:11:24 -0700123 if (status == Status::BEFORE_CHALLENGE && challengeStatus == "") {
tylerliu729212e2020-09-26 14:31:25 -0700124 request.push_back(makeStringBlock(tlv_selected_challenge, CHALLENGE_TYPE));
125 request.push_back(makeStringBlock(tlv_parameter_key, JSON_PROOF_OF_PRIVATE_KEY));
126 request.push_back(makeStringBlock(tlv_parameter_value, params.get(JSON_PROOF_OF_PRIVATE_KEY, "")));
127 }
128 else {
129 _LOG_ERROR("Client's status and challenge status are wrong");
130 }
131 request.encode();
132 return request;
133}
134} // namespace ndncert
135} // namespace ndn