blob: 207100e44aa276634cbcc96d950e2b95cb3b2691 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07002/**
Alexander Afanasyev4c9a3d52017-01-03 17:45:19 -08003 * Copyright (c) 2013-2017 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library 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 Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070020 *
21 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
Yingdi Yu8d7468f2014-02-21 14:49:45 -080022 */
23
Alexander Afanasyevd7db8bf2015-01-04 15:31:02 -080024#ifndef NDN_TOOLS_NDNSEC_DSK_GEN_HPP
25#define NDN_TOOLS_NDNSEC_DSK_GEN_HPP
Yingdi Yu8d7468f2014-02-21 14:49:45 -080026
Alexander Afanasyevd7db8bf2015-01-04 15:31:02 -080027#include "util.hpp"
Yingdi Yu8d7468f2014-02-21 14:49:45 -080028
Yingdi Yub61f5402014-02-26 17:46:11 -080029int
Yingdi Yu8d7468f2014-02-21 14:49:45 -080030ndnsec_dsk_gen(int argc, char** argv)
31{
32 using namespace ndn;
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070033 using namespace ndn::security;
Yingdi Yu8d7468f2014-02-21 14:49:45 -080034 namespace po = boost::program_options;
35
36 std::string identityName;
37 char keyType = 'r';
Yingdi Yu8d7468f2014-02-21 14:49:45 -080038
Alexander Afanasyevace74452014-11-30 22:28:24 -080039 po::options_description description("General Usage\n"
40 " ndnsec dsk-gen [-h] [-t keyType] identity\n"
41 "General options");
Yingdi Yub61f5402014-02-26 17:46:11 -080042 description.add_options()
Yingdi Yu8d7468f2014-02-21 14:49:45 -080043 ("help,h", "produce help message")
Alexander Afanasyevace74452014-11-30 22:28:24 -080044 ("identity,i", po::value<std::string>(&identityName),
45 "identity name, for example, /ndn/ucla.edu/alice")
46 ("type,t", po::value<char>(&keyType)->default_value('r'),
47 "optional, key type, r for RSA key (default), e for ECDSA key.")
48 // ("size,s", po::value<int>(&keySize)->default_value(2048),
49 // "optional, key size, 2048 (default)")
Yingdi Yu8d7468f2014-02-21 14:49:45 -080050 ;
51
52 po::positional_options_description p;
53 p.add("identity", 1);
54
55 po::variables_map vm;
Alexander Afanasyevace74452014-11-30 22:28:24 -080056 try {
57 po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(), vm);
58 po::notify(vm);
59 }
60 catch (const std::exception& e) {
61 std::cerr << "ERROR: " << e.what() << std::endl;
62 std::cerr << description << std::endl;
63 return 1;
64 }
Yingdi Yub61f5402014-02-26 17:46:11 -080065
Alexander Afanasyevace74452014-11-30 22:28:24 -080066 if (vm.count("help") != 0) {
67 std::cerr << description << std::endl;
68 return 0;
69 }
Yingdi Yu8d7468f2014-02-21 14:49:45 -080070
Alexander Afanasyevace74452014-11-30 22:28:24 -080071 if (vm.count("identity") == 0) {
72 std::cerr << "identity must be specified" << std::endl;
73 std::cerr << description << std::endl;
74 return 1;
75 }
Yingdi Yu8d7468f2014-02-21 14:49:45 -080076
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070077 shared_ptr<v1::IdentityCertificate> kskCert;
Yingdi Yu8d7468f2014-02-21 14:49:45 -080078 Name signingCertName;
Yingdi Yub61f5402014-02-26 17:46:11 -080079
Alexander Afanasyev4c9a3d52017-01-03 17:45:19 -080080 ndn::security::v1::KeyChain keyChain;
Yingdi Yub61f5402014-02-26 17:46:11 -080081
Alexander Afanasyevace74452014-11-30 22:28:24 -080082 try {
83 Name defaultCertName = keyChain.getDefaultCertificateNameForIdentity(identityName);
84 bool isDefaultDsk = false;
85 std::string keyUsageTag = defaultCertName.get(-3).toUri().substr(0,4);
86 if (keyUsageTag == "ksk-")
87 isDefaultDsk = false;
88 else if (keyUsageTag == "dsk-")
89 isDefaultDsk = true;
90 else {
91 std::cerr << "ERROR: Unknown key usage tag: " << keyUsageTag << std::endl;
92 return 1;
Yingdi Yu8d7468f2014-02-21 14:49:45 -080093 }
Alexander Afanasyevace74452014-11-30 22:28:24 -080094
95 if (isDefaultDsk) {
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070096 shared_ptr<v1::IdentityCertificate> dskCert = keyChain.getCertificate(defaultCertName);
Alexander Afanasyevace74452014-11-30 22:28:24 -080097
98 if (static_cast<bool>(dskCert)) {
99 SignatureSha256WithRsa sha256sig(dskCert->getSignature());
100
101 Name keyLocatorName = sha256sig.getKeyLocator().getName();
102
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700103 Name kskName = v1::IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
Alexander Afanasyevace74452014-11-30 22:28:24 -0800104 Name kskCertName = keyChain.getDefaultCertificateNameForKey(kskName);
105 signingCertName = kskCertName;
106 kskCert = keyChain.getCertificate(kskCertName);
107 }
108 else {
109 std::cerr << "ERROR: The default certificate is missing." << std::endl;
110 return 1;
111 }
112 }
113 else {
Yingdi Yub61f5402014-02-26 17:46:11 -0800114 signingCertName = defaultCertName;
115 kskCert = keyChain.getCertificate(defaultCertName);
Yingdi Yu8d7468f2014-02-21 14:49:45 -0800116 }
117
Alexander Afanasyevace74452014-11-30 22:28:24 -0800118 if (!static_cast<bool>(kskCert)) {
119 std::cerr << "ERROR: KSK certificate is missing." << std::endl;
Yingdi Yu8d7468f2014-02-21 14:49:45 -0800120 return 1;
121 }
122
Alexander Afanasyevace74452014-11-30 22:28:24 -0800123 Name newKeyName;
124 switch (keyType) {
Yingdi Yub61f5402014-02-26 17:46:11 -0800125 case 'r':
126 {
Alexander Afanasyevace74452014-11-30 22:28:24 -0800127 RsaKeyParams params;
128 newKeyName = keyChain.generateRsaKeyPair(Name(identityName), false, params.getKeySize());
129 if (0 == newKeyName.size()) {
130 std::cerr << "ERROR: Fail to generate RSA key!" << std::endl;
131 return 1;
132 }
133 break;
134 }
135 case 'e':
136 {
137 EcdsaKeyParams params;
138 newKeyName = keyChain.generateEcdsaKeyPair(Name(identityName), false, params.getKeySize());
139 if (0 == newKeyName.size()) {
140 std::cerr << "ERROR: Fail to generate ECDSA key!" << std::endl;
141 return 1;
142 }
Yingdi Yub61f5402014-02-26 17:46:11 -0800143 break;
144 }
145 default:
Alexander Afanasyevace74452014-11-30 22:28:24 -0800146 std::cerr << "ERROR: Unrecongized key type" << "\n";
Yingdi Yub61f5402014-02-26 17:46:11 -0800147 std::cerr << description << std::endl;
Yingdi Yu8d7468f2014-02-21 14:49:45 -0800148 return 1;
149 }
Yingdi Yub61f5402014-02-26 17:46:11 -0800150
Alexander Afanasyevace74452014-11-30 22:28:24 -0800151 Name certName = newKeyName.getPrefix(-1);
152 certName.append("KEY")
153 .append(newKeyName.get(-1))
154 .append("ID-CERT")
155 .appendVersion();
Yingdi Yub61f5402014-02-26 17:46:11 -0800156
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700157 shared_ptr<v1::IdentityCertificate> certificate =
Alexander Afanasyevace74452014-11-30 22:28:24 -0800158 keyChain.prepareUnsignedIdentityCertificate(newKeyName,
159 Name(identityName),
160 kskCert->getNotBefore(),
161 kskCert->getNotAfter(),
162 kskCert->getSubjectDescriptionList());
Yingdi Yub61f5402014-02-26 17:46:11 -0800163
Alexander Afanasyevace74452014-11-30 22:28:24 -0800164 if (static_cast<bool>(certificate))
165 certificate->encode();
166 else {
167 std::cerr << "ERROR: Cannot format the certificate of the requested dsk." << "\n";
168 return 1;
169 }
Yingdi Yub61f5402014-02-26 17:46:11 -0800170
Yingdi Yu1b0311c2015-06-10 14:58:47 -0700171 keyChain.sign(*certificate,
172 security::SigningInfo(security::SigningInfo::SIGNER_TYPE_CERT, signingCertName));
Yingdi Yub61f5402014-02-26 17:46:11 -0800173
Alexander Afanasyevace74452014-11-30 22:28:24 -0800174 keyChain.addCertificateAsIdentityDefault(*certificate);
Yingdi Yub61f5402014-02-26 17:46:11 -0800175
Alexander Afanasyevace74452014-11-30 22:28:24 -0800176 std::cerr << "OK: dsk certificate with name [" << certificate->getName() <<
177 "] has been successfully installed\n";
178 return 0;
179 }
180 catch (std::runtime_error& e) {
181 std::cerr << "ERROR: other runtime errors: " << e.what() << "\n";
182 return 1;
183 }
Yingdi Yu8d7468f2014-02-21 14:49:45 -0800184}
185
Alexander Afanasyevd7db8bf2015-01-04 15:31:02 -0800186#endif // NDN_TOOLS_NDNSEC_DSK_GEN_HPP