forked from facebookincubator/fizz
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add utility functions for reading/writing combined PEM
Summary: Utility functions for reading/writing a combined Cert + Delegated Credential (and it's corresponding key) Reviewed By: mingtaoy Differential Revision: D55970428 fbshipit-source-id: 5dcd19d375fed7bdf95a0dfe23f207feeb68d9da
- Loading branch information
1 parent
a1260a6
commit 19dca4c
Showing
7 changed files
with
305 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 67 additions & 0 deletions
67
fizz/extensions/delegatedcred/DelegatedCredentialPemUtils.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
#include <fizz/extensions/delegatedcred/DelegatedCredentialPemUtils.h> | ||
#include <fizz/extensions/delegatedcred/DelegatedCredentialUtils.h> | ||
#include <folly/Format.h> | ||
#include <folly/Range.h> | ||
#include <folly/base64.h> | ||
|
||
namespace fizz { | ||
namespace extensions { | ||
|
||
namespace { | ||
static constexpr folly::StringPiece kDCHeader = | ||
"-----BEGIN FIZZ DELEGATED CREDENTIAL-----\n"; | ||
static constexpr folly::StringPiece kDCFooter = | ||
"-----END FIZZ DELEGATED CREDENTIAL-----\n"; | ||
} // namespace | ||
|
||
std::string generateDelegatedCredentialPEM( | ||
DelegatedCredential credential, | ||
std::string certData, | ||
std::string credKeyData) { | ||
auto encodedCred = fizz::extensions::encodeExtension(credential); | ||
std::string pemData; | ||
pemData += kDCHeader; | ||
pemData += folly::base64Encode( | ||
encodedCred.extension_data->moveToFbString().toStdString()); | ||
pemData += "\n"; | ||
pemData += kDCFooter; | ||
pemData += credKeyData; | ||
pemData += certData; | ||
return pemData; | ||
} | ||
|
||
std::unique_ptr<SelfDelegatedCredential> loadDCFromPEM( | ||
std::string combinedPemData) { | ||
auto certs = folly::ssl::OpenSSLCertUtils::readCertsFromBuffer( | ||
folly::StringPiece(combinedPemData)); | ||
auto privKey = fizz::CertUtils::readPrivateKeyFromBuffer(combinedPemData); | ||
auto credDataPtr = combinedPemData.find(kDCHeader); | ||
auto credDataEndPtr = combinedPemData.find(kDCFooter); | ||
if (!(credDataPtr != std::string::npos && | ||
credDataEndPtr != std::string::npos)) { | ||
throw std::runtime_error(folly::sformat( | ||
"Failed to load delegated credential from pem, expected label {} which was not found", | ||
kDCHeader)); | ||
} | ||
folly::Optional<DelegatedCredential> cred; | ||
try { | ||
auto credData = folly::base64Decode(combinedPemData.substr( | ||
credDataPtr + kDCHeader.size(), | ||
credDataEndPtr - credDataPtr - kDCHeader.size() - 1)); | ||
|
||
std::vector<Extension> credVec; | ||
credVec.emplace_back(Extension{ | ||
ExtensionType::delegated_credential, | ||
folly::IOBuf::copyBuffer(std::move(credData))}); | ||
cred = getExtension<DelegatedCredential>(std::move(credVec)); | ||
} catch (const std::exception& e) { | ||
throw std::runtime_error(folly::sformat( | ||
"Failed to decode delegated credential with exception {}", e.what())); | ||
} | ||
// Note we currently only support P256 this will throw if there is a mismatch | ||
// in the delegated creds expected verification aglorithm | ||
return std::make_unique<SelfDelegatedCredentialImpl<KeyType::P256>>( | ||
std::move(certs), std::move(privKey), std::move(*cred)); | ||
} | ||
} // namespace extensions | ||
} // namespace fizz |
29 changes: 29 additions & 0 deletions
29
fizz/extensions/delegatedcred/DelegatedCredentialPemUtils.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#include <fizz/extensions/delegatedcred/SelfDelegatedCredential.h> | ||
#include <fizz/extensions/delegatedcred/Types.h> | ||
|
||
#pragma once | ||
|
||
namespace fizz { | ||
namespace extensions { | ||
/* | ||
* We expect certData and credKeyData to already be in PEM format with their | ||
* associated labels. We simply append the cert and key data so we expect these | ||
* to be non combined pems. This returns one combined pem | ||
*/ | ||
std::string generateDelegatedCredentialPEM( | ||
DelegatedCredential credential, | ||
std::string certData, | ||
std::string credKeyData); | ||
/* | ||
* Takes in a string which we expect to be the Combined PEM including | ||
* the leaf cert, the credential private key and the credential itself. | ||
* Will return a cert that has the credential in its extensions. | ||
* This currently only supports P256 Delegated credentials. | ||
* If we use a different signature algorithm or the pem does not contain | ||
* a valid delegated credentail this will throw, otherwise this will return | ||
* a valid non null ptr; | ||
*/ | ||
std::unique_ptr<SelfDelegatedCredential> loadDCFromPEM( | ||
std::string combinedPemData); | ||
} // namespace extensions | ||
} // namespace fizz |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
160 changes: 160 additions & 0 deletions
160
fizz/extensions/delegatedcred/test/DelegatedCredentialPemUtilsTest.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
/* | ||
* Copyright (c) 2019-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
#include <fizz/extensions/delegatedcred/DelegatedCredentialPemUtils.h> | ||
#include <folly/base64.h> | ||
#include <folly/portability/GMock.h> | ||
#include <folly/portability/GTest.h> | ||
|
||
using namespace folly; | ||
|
||
using namespace testing; | ||
|
||
namespace fizz { | ||
namespace extensions { | ||
namespace test { | ||
|
||
// @lint-ignore-every PRIVATEKEY | ||
|
||
// clang-format off | ||
/* | ||
* Delegated credential certificate generated by kP256CredCertKey | ||
* Prerequisites: | ||
* - P133567922 in config.cfg | ||
* - kP256CredCertKey in p256_key.pem | ||
* Command: openssl req -new -key p256_key.pem -x509 -nodes -days {days} -config config.cfg | ||
* Current cert set to expire in 2119. | ||
* Output: Self-signed delegation certificate | ||
*/ | ||
// clang-format on | ||
StringPiece kP256CredCert = R"( | ||
-----BEGIN CERTIFICATE----- | ||
MIICKzCCAdGgAwIBAgIJAPi2vMRfOVd0MAoGCCqGSM49BAMCMGIxCzAJBgNVBAYT | ||
AlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQgQ29t | ||
cGFueSBMdGQxHjAcBgNVBAMMFXJldnByb3h5LWRlbGVnYXRlZC1lYzAgFw0xOTA5 | ||
MjMwMjAyMzVaGA8yMTE5MDgzMDAyMDIzNVowYjELMAkGA1UEBhMCWFgxFTATBgNV | ||
BAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UECgwTRGVmYXVsdCBDb21wYW55IEx0ZDEe | ||
MBwGA1UEAwwVcmV2cHJveHktZGVsZWdhdGVkLWVjMFkwEwYHKoZIzj0CAQYIKoZI | ||
zj0DAQcDQgAE7EbZMKds65EYciaSULFH4wZKt/OThiUL4uQW9cybr2HIzK68corO | ||
JCeHXOsV3lpYS46b39SBZr1GZprFHH5gHaNuMGwwHQYDVR0OBBYEFMLkRMB4SclK | ||
8K8uYMQBaYw0gNP7MB8GA1UdIwQYMBaAFMLkRMB4SclK8K8uYMQBaYw0gNP7MAwG | ||
A1UdEwQFMAMBAf8wCwYDVR0PBAQDAgHmMA8GCSsGAQQBgtpLLAQCBQAwCgYIKoZI | ||
zj0EAwIDSAAwRQIgB2EWbwWohYziQ2LmY8Qmn8y0WKR6Mbm5aad0rUBvtK4CIQCv | ||
0U6Z/gFrVr0Cb2kc7M37KD9z5eeTwkQuGqs5GXF8Ow== | ||
-----END CERTIFICATE----- | ||
)"; | ||
|
||
/* | ||
* Randomly generated ECDSA-openssl::P256 private key | ||
* Command: openssl ecparam -name secp256r1 -genkey | ||
* Output: Randomly generated ECDSA-openssl::P256 private key | ||
*/ | ||
StringPiece kP256DelegatedCredKey = R"( | ||
-----BEGIN EC PARAMETERS----- | ||
BggqhkjOPQMBBw== | ||
-----END EC PARAMETERS----- | ||
-----BEGIN EC PRIVATE KEY----- | ||
MHcCAQEEIA8/keRkilh8bwUPxH9jiP5SsP4QiZtfofayTsRSI59poAoGCCqGSM49 | ||
AwEHoUQDQgAE8mV/wDAabnJbPLuF/qd/FMIWHDlrJI97cwq4obtPHyKFF2ukoG+6 | ||
/pXOUrEbsIH+/QBpZsnRHjvxryib97Ay+Q== | ||
-----END EC PRIVATE KEY----- | ||
)"; | ||
|
||
// clang-format off | ||
/* | ||
* Delegated credential generated using kP256CredCert, kP256CredCertKey & kP256DelegatedCredKey | ||
* Prerequisites: | ||
* - kP256CredCert in cert.pem | ||
* - kP256CredCertKey in p256_key.pem | ||
* - kP256DelegatedCredKey in p256_dc_key.pem | ||
* Command: buck run //fizz/tool:fizz -- gendc -cert cert.pem -key p256_key.pem -credkey p256_dc_key.pem | xxd -p | ||
* Output: Hex-encoded delegated credential | ||
*/ | ||
// clang-format on | ||
|
||
StringPiece kP256DelegatedCredNoLabel = { | ||
"CI61NAQDAABbMFkwEwYHKoZIzj0CAQYIKoZIzj0" | ||
"DAQcDQgAE8mV/wDAabnJbPLuF/qd/FMIWHDlrJI" | ||
"97cwq4obtPHyKFF2ukoG+6/pXOUrEbsIH+/QBpZ" | ||
"snRHjvxryib97Ay+QQDAEcwRQIgUrbmZ9uq07B0" | ||
"Myg06hZj0uUq2f04eI4Ci0VIRP7XGhACIQDqckz" | ||
"1AUqrX1gEw5DVBK8WQ3Q6pYSF4WI4gxIpvcCMEQ=="}; | ||
|
||
StringPiece kP256DelegatedCred = { | ||
"-----BEGIN FIZZ DELEGATED CREDENTIAL-----\n" | ||
"CI61NAQDAABbMFkwEwYHKoZIzj0CAQYIKoZIzj0" | ||
"DAQcDQgAE8mV/wDAabnJbPLuF/qd/FMIWHDlrJI" | ||
"97cwq4obtPHyKFF2ukoG+6/pXOUrEbsIH+/QBpZ" | ||
"snRHjvxryib97Ay+QQDAEcwRQIgUrbmZ9uq07B0" | ||
"Myg06hZj0uUq2f04eI4Ci0VIRP7XGhACIQDqckz" | ||
"1AUqrX1gEw5DVBK8WQ3Q6pYSF4WI4gxIpvcCMEQ==\n" | ||
"-----END FIZZ DELEGATED CREDENTIAL-----\n"}; | ||
|
||
StringPiece kP256DelegatedCredBadLabel = { | ||
"-----BEGIN DC-----\n" | ||
"CI61NAQDAABbMFkwEwYHKoZIzj0CAQYIKoZIzj0" | ||
"DAQcDQgAE8mV/wDAabnJbPLuF/qd/FMIWHDlrJI" | ||
"97cwq4obtPHyKFF2ukoG+6/pXOUrEbsIH+/QBpZ" | ||
"snRHjvxryib97Ay+QQDAEcwRQIgUrbmZ9uq07B0" | ||
"Myg06hZj0uUq2f04eI4Ci0VIRP7XGhACIQDqckz" | ||
"1AUqrX1gEw5DVBK8WQ3Q6pYSF4WI4gxIpvcCMEQ==\n" | ||
"-----END DC-----\n"}; | ||
|
||
StringPiece kP384DelegatedCred = { | ||
"-----BEGIN FIZZ DELEGATED CREDENTIAL-----\n" | ||
"CKpfvQUDAAB4MHYwEAYHKoZIzj0CAQYFK4EEACID" | ||
"YgAEfDkvSAjmCrrxRNEkpA52igKI5pnE9q/MiKHTJ" | ||
"/gfmJfhwK3IGI21+zs4DHvR2iowHSa5Ul+J5Fai9o" | ||
"Nr32wTLUgQyrygUfhwNMuS4ucnd3Lz/EEJUBdkbEL" | ||
"NnfY98HJcBAMARjBEAiBmz7fIOTsAXTQG55zdTxBy" | ||
"QiUv7Ub3qtyYnJMaJKmx9gIgQiv40UZcP8GZkvDfg" | ||
"D/EqLaFsDaP4Fl2PGH9NgXkyo8=\n" | ||
"-----END FIZZ DELEGATED CREDENTIAL-----\n"}; | ||
|
||
TEST(PemUtilsTest, testValidReadFromPem) { | ||
auto combinedPem = kP256DelegatedCred.toString() + | ||
kP256DelegatedCredKey.toString() + kP256CredCert.toString(); | ||
auto dc = loadDCFromPEM(combinedPem); | ||
EXPECT_NE(dc, nullptr); | ||
EXPECT_EQ( | ||
dc->getSigSchemes(), | ||
std::vector<SignatureScheme>{SignatureScheme::ecdsa_secp256r1_sha256}); | ||
} | ||
|
||
TEST(PemUtilsTest, BadLabel) { | ||
auto combinedPem = kP256DelegatedCredBadLabel.toString() + | ||
kP256DelegatedCredKey.toString() + kP256CredCert.toString(); | ||
EXPECT_THROW(loadDCFromPEM(combinedPem), std::runtime_error); | ||
} | ||
|
||
TEST(PemUtilsTest, P384DC) { | ||
auto combinedPem = kP256DelegatedCredBadLabel.toString() + | ||
kP256DelegatedCredKey.toString() + kP256CredCert.toString(); | ||
EXPECT_THROW(loadDCFromPEM(combinedPem), std::runtime_error); | ||
} | ||
|
||
TEST(PemUtilsTest, TestBuildCombinedPEM) { | ||
auto credData = folly::base64Decode(kP256DelegatedCredNoLabel.toString()); | ||
std::vector<Extension> credVec; | ||
credVec.emplace_back(Extension{ | ||
ExtensionType::delegated_credential, | ||
folly::IOBuf::copyBuffer(std::move(credData))}); | ||
auto cred = getExtension<DelegatedCredential>(std::move(credVec)); | ||
|
||
auto combinedPem = kP256DelegatedCred.toString() + | ||
kP256DelegatedCredKey.toString() + kP256CredCert.toString(); | ||
EXPECT_EQ( | ||
combinedPem, | ||
generateDelegatedCredentialPEM( | ||
std::move(*cred), | ||
kP256CredCert.toString(), | ||
kP256DelegatedCredKey.toString())); | ||
} | ||
} // namespace test | ||
} // namespace extensions | ||
} // namespace fizz |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters