/* * * Copyright (c) 2021-2022 Project CHIP Authors * Copyright (c) 2013-2017 Nest Labs, Inc. * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @file * This file implements the command handler for the 'chip-cert' tool * that converts a CHIP certificate between CHIP TLV and X.509 * formats. * */ #include "chip-cert.h" namespace { using namespace chip::ArgParser; using namespace chip::Credentials; #define CMD_NAME "chip-cert convert-cert" bool HandleOption(const char * progName, OptionSet * optSet, int id, const char * name, const char * arg); bool HandleNonOptionArgs(const char * progName, int argc, char * const argv[]); // clang-format off OptionDef gCmdOptionDefs[] = { { "x509-pem", kNoArgument, 'p' }, { "x509-der", kNoArgument, 'd' }, { "x509-hex", kNoArgument, 'X' }, { "chip", kNoArgument, 'c' }, { "chip-hex", kNoArgument, 'x' }, { "chip-b64", kNoArgument, 'b' }, { } }; const char * const gCmdOptionHelp = " -p, --x509-pem\n" "\n" " Output certificate in X.509 PEM format.\n" "\n" " -d, --x509-der\n" "\n" " Output certificate in X.509 DER format.\n" "\n" " -X, --x509-hex\n" "\n" " Output certificate in X.509 DER hex encoded format.\n" "\n" " -c, --chip\n" "\n" " Output certificate in raw CHIP TLV format.\n" "\n" " -x, --chip-hex\n" "\n" " Output certificate in CHIP TLV hexadecimal format.\n" "\n" " -b --chip-b64\n" "\n" " Output certificate in CHIP TLV base-64 encoded format.\n" " This is the default.\n" "\n" ; OptionSet gCmdOptions = { HandleOption, gCmdOptionDefs, "COMMAND OPTIONS", gCmdOptionHelp }; HelpOptions gHelpOptions( CMD_NAME, "Usage: " CMD_NAME " [ ] \n", CHIP_VERSION_STRING "\n" COPYRIGHT_STRING, "Convert operational certificate between CHIP and X.509 formats.\n" "\n" "ARGUMENTS\n" "\n" " \n" "\n" " File or string containing certificate to be converted.\n" " The format of the input certificate is auto-detected and can be any of:\n" " X.509 PEM, X.509 DER, X.509 HEX, CHIP base-64, CHIP raw TLV or CHIP HEX.\n" "\n" " \n" "\n" " The output certificate file name, or '-' to write to stdout.\n" "\n" ); OptionSet * gCmdOptionSets[] = { &gCmdOptions, &gHelpOptions, nullptr }; // clang-format on const char * gInFileNameOrStr = nullptr; const char * gOutFileName = nullptr; CertFormat gOutCertFormat = kCertFormat_Default; bool HandleOption(const char * progName, OptionSet * optSet, int id, const char * name, const char * arg) { switch (id) { case 'p': gOutCertFormat = kCertFormat_X509_PEM; break; case 'd': gOutCertFormat = kCertFormat_X509_DER; break; case 'X': gOutCertFormat = kCertFormat_X509_Hex; break; case 'x': gOutCertFormat = kCertFormat_Chip_Hex; break; case 'b': gOutCertFormat = kCertFormat_Chip_Base64; break; case 'c': gOutCertFormat = kCertFormat_Chip_Raw; break; default: PrintArgError("%s: Unhandled option: %s\n", progName, name); return false; } return true; } bool HandleNonOptionArgs(const char * progName, int argc, char * const argv[]) { if (argc == 0) { PrintArgError("%s: Please specify the name of the input certificate file or the certificate string.\n", progName); return false; } if (argc == 1) { PrintArgError("%s: Please specify the name of the output certificate file, or - for stdout\n", progName); return false; } if (argc > 2) { PrintArgError("%s: Unexpected argument: %s\n", progName, argv[2]); return false; } gInFileNameOrStr = argv[0]; gOutFileName = argv[1]; return true; } } // namespace bool Cmd_ConvertCert(int argc, char * argv[]) { bool res = true; std::unique_ptr cert(nullptr, &X509_free); if (argc == 1) { gHelpOptions.PrintBriefUsage(stderr); ExitNow(res = true); } res = ParseArgs(CMD_NAME, argc, argv, gCmdOptionSets, HandleNonOptionArgs); VerifyTrueOrExit(res); res = InitOpenSSL(); VerifyTrueOrExit(res); res = ReadCert(gInFileNameOrStr, cert); VerifyTrueOrExit(res); res = WriteCert(gOutFileName, cert.get(), gOutCertFormat); VerifyTrueOrExit(res); exit: return res; }