Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chip-cert: Updated Tool to Support Command Line Key/Cert Inputs #22436

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 45 additions & 39 deletions src/tools/chip-cert/CertUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -508,51 +508,52 @@ bool AddAuthorityKeyId(X509 * cert, X509 * caCert)
return res;
}

bool ReadCertPEM(const char * fileName, X509 * cert)
{
bool res = true;
FILE * file = nullptr;

res = OpenFile(fileName, file);
VerifyTrueOrExit(res);

if (PEM_read_X509(file, &cert, nullptr, nullptr) == nullptr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is PEM support preserved with this update?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All various certificate formats are handled by the ReadCert() call. I believe there was some historical redundancy in this code...

{
ReportOpenSSLErrorAndExit("PEM_read_X509", res = false);
}

exit:
CloseFile(file);
return res;
}

} // namespace

bool ReadCert(const char * fileName, X509 * cert)
bool ReadCert(const char * fileNameOrStr, X509 * cert)
{
CertFormat origCertFmt;
return ReadCert(fileName, cert, origCertFmt);
return ReadCert(fileNameOrStr, cert, origCertFmt);
}

bool ReadCert(const char * fileName, X509 * cert, CertFormat & certFmt)
bool ReadCert(const char * fileNameOrStr, X509 * cert, CertFormat & certFmt)
{
bool res = true;
uint32_t certLen = 0;
std::unique_ptr<uint8_t[]> certBuf;

res = ReadFileIntoMem(fileName, nullptr, certLen);
VerifyTrueOrExit(res);
// If fileNameOrStr is a file name
if (access(fileNameOrStr, R_OK) == 0)
{
res = ReadFileIntoMem(fileNameOrStr, nullptr, certLen);
VerifyTrueOrExit(res);

certBuf = std::unique_ptr<uint8_t[]>(new uint8_t[certLen]);
certBuf = std::unique_ptr<uint8_t[]>(new uint8_t[certLen]);

res = ReadFileIntoMem(fileName, certBuf.get(), certLen);
VerifyTrueOrExit(res);
res = ReadFileIntoMem(fileNameOrStr, certBuf.get(), certLen);
VerifyTrueOrExit(res);

certFmt = DetectCertFormat(certBuf.get(), certLen);
if (certFmt == kCertFormat_Unknown)
certFmt = DetectCertFormat(certBuf.get(), certLen);
if (certFmt == kCertFormat_Unknown)
{
fprintf(stderr, "Unrecognized Cert Format in File: %s\n", fileNameOrStr);
return false;
}
}
// Otherwise, treat fileNameOrStr as a pointer to the certificate string
else
{
fprintf(stderr, "Unrecognized Cert Format in File: %s\n", fileName);
return false;
certLen = static_cast<uint32_t>(strlen(fileNameOrStr));

certFmt = DetectCertFormat(reinterpret_cast<const uint8_t *>(fileNameOrStr), certLen);
if (certFmt == kCertFormat_Unknown)
{
fprintf(stderr, "Unrecognized Cert Format in the Input Argument: %s\n", fileNameOrStr);
return false;
}

certBuf = std::unique_ptr<uint8_t[]>(new uint8_t[certLen]);
memcpy(certBuf.get(), fileNameOrStr, certLen);
}

if ((certFmt == kCertFormat_X509_Hex) || (certFmt == kCertFormat_Chip_Hex))
Expand All @@ -565,8 +566,15 @@ bool ReadCert(const char * fileName, X509 * cert, CertFormat & certFmt)

if (certFmt == kCertFormat_X509_PEM)
{
res = ReadCertPEM(fileName, cert);
VerifyTrueOrExit(res);
VerifyOrReturnError(chip::CanCastTo<int>(certLen), false);

std::unique_ptr<BIO, void (*)(BIO *)> certBIO(
BIO_new_mem_buf(static_cast<const void *>(certBuf.get()), static_cast<int>(certLen)), &BIO_free_all);

if (PEM_read_bio_X509(certBIO.get(), &cert, nullptr, nullptr) == nullptr)
{
ReportOpenSSLErrorAndExit("PEM_read_bio_X509", res = false);
}
}
else if ((certFmt == kCertFormat_X509_DER) || (certFmt == kCertFormat_X509_Hex))
{
Expand Down Expand Up @@ -612,12 +620,12 @@ bool ReadCert(const char * fileName, X509 * cert, CertFormat & certFmt)
return res;
}

bool ReadCertDERRaw(const char * fileName, MutableByteSpan & cert)
bool ReadCertDER(const char * fileNameOrStr, MutableByteSpan & cert)
{
bool res = true;
std::unique_ptr<X509, void (*)(X509 *)> certX509(X509_new(), &X509_free);

VerifyOrReturnError(ReadCertPEM(fileName, certX509.get()) == true, false);
VerifyOrReturnError(ReadCert(fileNameOrStr, certX509.get()), false);

uint8_t * certPtr = cert.data();
int certLen = i2d_X509(certX509.get(), &certPtr);
Expand Down Expand Up @@ -660,14 +668,14 @@ bool X509ToChipCert(X509 * cert, MutableByteSpan & chipCert)
return res;
}

bool LoadChipCert(const char * fileName, bool isTrused, ChipCertificateSet & certSet, MutableByteSpan & chipCert)
bool LoadChipCert(const char * fileNameOrStr, bool isTrused, ChipCertificateSet & certSet, MutableByteSpan & chipCert)
{
bool res = true;
CHIP_ERROR err;
BitFlags<CertDecodeFlags> decodeFlags;
std::unique_ptr<X509, void (*)(X509 *)> cert(X509_new(), &X509_free);

res = ReadCert(fileName, cert.get());
res = ReadCert(fileNameOrStr, cert.get());
VerifyTrueOrExit(res);

res = X509ToChipCert(cert.get(), chipCert);
Expand All @@ -685,7 +693,7 @@ bool LoadChipCert(const char * fileName, bool isTrused, ChipCertificateSet & cer
err = certSet.LoadCert(chipCert, decodeFlags);
if (err != CHIP_NO_ERROR)
{
fprintf(stderr, "Error reading %s\n%s\n", fileName, chip::ErrorStr(err));
fprintf(stderr, "Error reading %s\n%s\n", fileNameOrStr, chip::ErrorStr(err));
ExitNow(res = false);
}

Expand Down Expand Up @@ -747,8 +755,6 @@ bool WriteCert(const char * fileName, X509 * cert, CertFormat certFmt)
ExitNow(res = false);
}

printf("\r\n");

exit:
OPENSSL_free(derCert);
CloseFile(file);
Expand Down
30 changes: 15 additions & 15 deletions src/tools/chip-cert/Cmd_ConvertCert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,21 +87,21 @@ OptionSet gCmdOptions =

HelpOptions gHelpOptions(
CMD_NAME,
"Usage: " CMD_NAME " [ <options...> ] <in-file> <out-file>\n",
"Usage: " CMD_NAME " [ <options...> ] <in-file/str> <out-file/stdout>\n",
CHIP_VERSION_STRING "\n" COPYRIGHT_STRING,
"Convert a certificate between CHIP and X509 forms.\n"
"Convert operational certificate between CHIP and X.509 formats.\n"
"\n"
"ARGUMENTS\n"
"\n"
" <in-file>\n"
" <in-file/str>\n"
"\n"
" The input certificate file name, or - to read from stdin. The\n"
" format of the input certificate is auto-detected and can be any\n"
" of: X.509 PEM, X.509 DER, CHIP base-64 or CHIP raw TLV.\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"
" <out-file>\n"
" <out-file/stdout>\n"
"\n"
" The output certificate file name, or - to write to stdout.\n"
" The output certificate file name, or '-' to write to stdout.\n"
"\n"
);

Expand All @@ -113,9 +113,9 @@ OptionSet * gCmdOptionSets[] =
};
// clang-format on

const char * gInFileName = nullptr;
const char * gOutFileName = nullptr;
CertFormat gOutCertFormat = kCertFormat_Default;
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)
{
Expand Down Expand Up @@ -151,7 +151,7 @@ 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 - for stdin.\n", progName);
PrintArgError("%s: Please specify the name of the input certificate file or the certificate string.\n", progName);
return false;
}

Expand All @@ -167,8 +167,8 @@ bool HandleNonOptionArgs(const char * progName, int argc, char * const argv[])
return false;
}

gInFileName = argv[0];
gOutFileName = argv[1];
gInFileNameOrStr = argv[0];
gOutFileName = argv[1];

return true;
}
Expand All @@ -192,7 +192,7 @@ bool Cmd_ConvertCert(int argc, char * argv[])
res = InitOpenSSL();
VerifyTrueOrExit(res);

res = ReadCert(gInFileName, cert.get());
res = ReadCert(gInFileNameOrStr, cert.get());
VerifyTrueOrExit(res);

res = WriteCert(gOutFileName, cert.get(), gOutCertFormat);
Expand Down
27 changes: 16 additions & 11 deletions src/tools/chip-cert/Cmd_ConvertKey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,21 +110,26 @@ OptionSet gCmdOptions =

HelpOptions gHelpOptions(
CMD_NAME,
"Usage: " CMD_NAME " [ <options...> ] <in-file> <out-file>\n",
"Usage: " CMD_NAME " [ <options...> ] <in-file/str> <out-file/stdout>\n",
CHIP_VERSION_STRING "\n" COPYRIGHT_STRING,
"Convert a private key between CHIP and PEM/DER forms."
"Convert private/public key between CHIP and X.509 formats.\n"
"\n"
"ARGUMENTS\n"
"\n"
" <in-file>\n"
" <in-file/str>\n"
"\n"
" The input private key file name, or - to read from stdin. The\n"
" format of the input key is auto-detected and can be any\n"
" of: PEM, DER, CHIP base-64 or CHIP raw.\n"
" File or string containing private/public key to be converted.\n"
" The format of the input key 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"
" <out-file>\n"
" Note: the private key formats include both private and public keys, while\n"
" the public key formats include only public keys. Therefore, conversion from any\n"
" private key format to public key is supported but conversion from public key\n"
" to private CANNOT be done.\n"
"\n"
" The output private key file name, or - to write to stdout.\n"
" <out-file/stdout>\n"
"\n"
" The output private key file name, or '-' to write to stdout.\n"
"\n"
);

Expand All @@ -136,7 +141,7 @@ OptionSet *gCmdOptionSets[] =
};
// clang-ormat on

const char * gInFileName = nullptr;
const char * gInFileNameOrStr = nullptr;
const char * gOutFileName = nullptr;
KeyFormat gOutFormat = kKeyFormat_Chip_Base64;

Expand Down Expand Up @@ -203,7 +208,7 @@ bool HandleNonOptionArgs(const char * progName, int argc, char * const argv[])
return false;
}

gInFileName = argv[0];
gInFileNameOrStr = argv[0];
gOutFileName = argv[1];

return true;
Expand All @@ -228,7 +233,7 @@ bool Cmd_ConvertKey(int argc, char * argv[])
res = InitOpenSSL();
VerifyTrueOrExit(res);

res = ReadKey(gInFileName, key);
res = ReadKey(gInFileNameOrStr, key);
VerifyTrueOrExit(res);

if (IsPrivateKeyFormat(gOutFormat) && EC_KEY_get0_private_key(EVP_PKEY_get1_EC_KEY(key.get())) == nullptr)
Expand Down
Loading