* first pass

* part2

* part3

* part 5

* pre PR

* updated tests

* fix test

* clangs

* updated changelog
This commit is contained in:
George Arama 2023-01-13 11:00:46 -08:00 committed by GitHub
parent 41e3e89cf8
commit 275f6f8077
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 222 additions and 15 deletions

View File

@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "cpp",
"TagPrefix": "cpp/keyvault",
"Tag": "cpp/keyvault_ea82152bd3"
"Tag": "cpp/keyvault_fd91dfe00e"
}

View File

@ -4,6 +4,8 @@
### Features Added
- Support for OKP keys.
### Breaking Changes
### Bugs Fixed

View File

@ -39,6 +39,9 @@ namespace Azure {
* @brief Construct a new Key Client Options object.
*
*/
CryptographyClientOptions() : Azure::Core::_internal::ClientOptions() { Version = "7.3"; }
CryptographyClientOptions() : Azure::Core::_internal::ClientOptions()
{
Version = "7.4-preview.1";
}
};
}}}}} // namespace Azure::Security::KeyVault::Keys::Cryptography

View File

@ -173,6 +173,23 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
CreateOctKeyOptions const& octKeyOptions,
Azure::Core::Context const& context = Azure::Core::Context()) const;
/**
* @brief Creates and stores a new OKP key in Key Vault.
*
* @remark If the named key already exists, Azure Key Vault creates a new version of the
* key.
*
* @remark This operation requires the keys/create permission.
*
* @param okpKeyOptions The key options object containing information about the OKP key
* being created.
* @param context A #Azure::Core::Context controlling the request lifetime.
* @return The Key wrapped in the Response.
*/
Azure::Response<KeyVaultKey> CreateOkpKey(
CreateOkpKeyOptions const& okpKeyOptions,
Azure::Core::Context const& context = Azure::Core::Context()) const;
/**
* @brief Get a single page with the properties of all keys in the specified vault. You can
* use the returned #KeyProperties.Name in subsequent calls to #GetKey.

View File

@ -214,6 +214,18 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
*
*/
AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const KeyVaultKeyType OctHsm;
/**
* @brief An OKP cryptographic algorithm.
*
*/
AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const KeyVaultKeyType Okp;
/**
* @brief An OKP cryptographic algorithm backed by a Hardware Security Module (HSM).
*
*/
AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const KeyVaultKeyType OkpHsm;
};
/**
@ -297,6 +309,16 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
*
*/
AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const KeyCurveName P521;
/**
* @brief Gets the Ed25519 Edwards curve.
*
* @remark For more information, see
* <a href="https://docs.microsoft.com/azure/key-vault/keys/about-keys#curve-types">Curve
* types</a>.
*
*/
AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const KeyCurveName Ed25519;
};
/**
@ -400,14 +422,14 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
/// The RSA secret prime.
std::vector<uint8_t> Q;
/// The RSA private exponent or EC private key.
/// The RSA private exponent or EC private key, or OKP private key.
std::vector<uint8_t> D;
/// Gets the symmetric key.
std::vector<uint8_t> K;
/// Gets the protected key used with "Bring Your Own Key".
std::vector<uint8_t> T;
/// Gets the X coordinate of the elliptic curve point.
/// Gets the X coordinate of the elliptic curve point, or OKP public key.
std::vector<uint8_t> X;
/// Gets the Y coordinate for the elliptic curve point.
std::vector<uint8_t> Y;

View File

@ -53,7 +53,7 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
* @brief Service Version used.
*
*/
const std::string ApiVersion{"7.3"};
const std::string ApiVersion{"7.4-preview.1"};
};
/**
@ -326,6 +326,80 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
bool GetHardwareProtected() const { return m_hardwareProtected; }
};
/**
* @brief The properties needed to create an OKP key.
*
*/
class CreateOkpKeyOptions final : public CreateKeyOptions {
private:
std::string m_name;
bool m_hardwareProtected;
KeyVaultKeyType m_keyType;
public:
/**
* @brief Gets or sets the key size in bits, such as 2048, 3072, or 4096.
*
* @remark If null, the service default is used.
*
*/
Azure::Nullable<int64_t> KeySize;
/**
* @brief Gets or sets the elliptic curve name.
*
* @remark See #KeyCurveName for possible values.
*
* @remark If null, the service default is used.
*
*/
Azure::Nullable<KeyCurveName> CurveName;
/**
* @brief Create a OKP Key Options object.
*
* @param name Name of the key to create.
* @param hardwareProtected `true` to create hardware-protected key in a hardware security
* module (HSM). The default is false to create a software key.
*/
explicit CreateOkpKeyOptions(std::string const& name, bool hardwareProtected = false)
: m_hardwareProtected(hardwareProtected)
{
if (name.empty())
{
throw std::invalid_argument("The name can't be empty");
}
m_name = name;
if (hardwareProtected)
{
m_keyType = KeyVaultKeyType::OkpHsm;
}
else
{
m_keyType = KeyVaultKeyType::Okp;
}
}
/**
* @brief Gets the name of the key to create.
*
*/
std::string const& GetName() const { return m_name; }
/**
* @brief Gets the key type to create, including Okp and OkpHsm.
*
*/
KeyVaultKeyType GetKeyType() const { return m_keyType; }
/**
* @brief Gets a value indicating whether to create a hardware-protected key in a hardware
* security module (HSM).
*
*/
bool GetHardwareProtected() const { return m_hardwareProtected; }
};
/**
* @brief A key resource and its properties.
*

View File

@ -167,6 +167,27 @@ Azure::Response<KeyVaultKey> KeyClient::CreateRsaKey(
return Azure::Response<KeyVaultKey>(std::move(value), std::move(rawResponse));
}
Azure::Response<KeyVaultKey> KeyClient::CreateOkpKey(
CreateOkpKeyOptions const& okpKeyOptions,
Azure::Core::Context const& context) const
{
// Payload for the request
std::string const& keyName = okpKeyOptions.GetName();
std::string payload = _detail ::KeyRequestParameters(okpKeyOptions).Serialize();
Azure::Core::IO::MemoryBodyStream payloadStream(
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
// Request and settings
auto request
= CreateRequest(HttpMethod::Post, {_detail::KeysPath, keyName, CreateValue}, &payloadStream);
request.SetHeader(HttpShared::ContentType, HttpShared::ApplicationJson);
// Send and parse respone
auto rawResponse = SendRequest(request, context);
auto value = _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(keyName, *rawResponse);
return Azure::Response<KeyVaultKey>(std::move(value), std::move(rawResponse));
}
Azure::Response<KeyVaultKey> KeyClient::CreateOctKey(
CreateOctKeyOptions const& octKeyOptions,
Azure::Core::Context const& context) const

View File

@ -14,4 +14,6 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
const KeyCurveName KeyCurveName::P521(_detail::P521Value);
const KeyCurveName KeyCurveName::Ed25519(_detail::Ed25519Value);
}}}} // namespace Azure::Security::KeyVault::Keys

View File

@ -24,15 +24,12 @@ std::string KeyRequestParameters::Serialize() const
return type.ToString();
});
json attributes;
// attributes
JsonOptional::SetFromNullable(
m_options.Enabled, payload[_detail::AttributesPropertyName], _detail::EnabledPropertyName);
JsonOptional::SetFromNullable(m_options.Enabled, attributes, _detail::EnabledPropertyName);
// exportable attribute
JsonOptional::SetFromNullable(
m_options.Exportable,
payload[_detail::AttributesPropertyName],
_detail::ExportablePropertyName);
JsonOptional::SetFromNullable(m_options.Exportable, attributes, _detail::ExportablePropertyName);
/* Optional */
// key_size
@ -46,16 +43,23 @@ std::string KeyRequestParameters::Serialize() const
// attributes
JsonOptional::SetFromNullable<Azure::DateTime, int64_t>(
m_options.ExpiresOn,
payload[_detail::AttributesPropertyName],
attributes,
_detail::ExpPropertyName,
PosixTimeConverter::DateTimeToPosixTime);
JsonOptional::SetFromNullable<Azure::DateTime, int64_t>(
m_options.NotBefore,
payload[_detail::AttributesPropertyName],
attributes,
_detail::NbfPropertyName,
PosixTimeConverter::DateTimeToPosixTime);
// in order to avoid creating the "attributes":null json field.
// The service deserializer on HSM really does not like that
if (!attributes.empty())
{
payload[_detail::AttributesPropertyName] = attributes;
}
// tags
for (auto tag : m_options.Tags)
{

View File

@ -14,3 +14,5 @@ const KeyVaultKeyType KeyVaultKeyType::Rsa(_detail::RsaValue);
const KeyVaultKeyType KeyVaultKeyType::RsaHsm(_detail::RsaHsmValue);
const KeyVaultKeyType KeyVaultKeyType::Oct(_detail::OctValue);
const KeyVaultKeyType KeyVaultKeyType::OctHsm(_detail::OctHsmValue);
const KeyVaultKeyType KeyVaultKeyType::Okp(_detail::OkpValue);
const KeyVaultKeyType KeyVaultKeyType::OkpHsm(_detail::OkpHsmValue);

View File

@ -19,9 +19,9 @@ std::unique_ptr<Azure::Core::Http::RawResponse> _detail::KeyVaultKeysCommonReque
{
auto response = pipeline.Send(request, context);
auto responseCode = response->GetStatusCode();
switch (responseCode)
{
// 200, 2001, 202, 204 are accepted responses
case Azure::Core::Http::HttpStatusCode::Ok:
case Azure::Core::Http::HttpStatusCode::Created:

View File

@ -60,6 +60,8 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { nam
constexpr static const char RsaHsmValue[] = "RSA-HSM";
constexpr static const char OctValue[] = "oct";
constexpr static const char OctHsmValue[] = "oct-HSM";
constexpr static const char OkpValue[] = "OKP";
constexpr static const char OkpHsmValue[] = "OKP-HSM";
/***************** Deleted Key *****************/
constexpr static const char RecoveryIdPropertyName[] = "recoveryId";
@ -71,6 +73,7 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { nam
constexpr static const char P256KValue[] = "P-256K";
constexpr static const char P384Value[] = "P-384";
constexpr static const char P521Value[] = "P-521";
constexpr static const char Ed25519Value[] = "Ed25519";
constexpr static const char P256OidValue[] = "1.2.840.10045.3.1.7";
constexpr static const char P256KOidValue[] = "1.3.132.0.10";

View File

@ -104,6 +104,15 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { nam
}
}
explicit KeyRequestParameters(CreateOkpKeyOptions const& okpKey)
: KeyRequestParameters(okpKey.GetKeyType(), okpKey)
{
if (okpKey.CurveName.HasValue())
{
Curve = okpKey.CurveName.Value();
}
}
std::string Serialize() const override;
};
}}}}} // namespace Azure::Security::KeyVault::Keys::_detail

View File

@ -130,6 +130,54 @@ TEST_F(KeyVaultKeyClient, CreateEcKey)
}
}
/********************************* Create key overloads *********************************/
TEST_F(KeyVaultKeyClient, CreateOkpKey)
{
auto const keyName = GetTestName();
// This client requires an HSM client
CreateHsmClient();
auto const& client = GetClientForTest(keyName);
{
auto okpKey = Azure::Security::KeyVault::Keys::CreateOkpKeyOptions(keyName);
auto keyResponse = client.CreateOkpKey(okpKey);
CheckValidResponse(keyResponse);
auto keyVaultKey = keyResponse.Value;
EXPECT_EQ(keyVaultKey.Name(), keyName);
}
{
// Now get the key
auto keyResponse = client.GetKey(keyName);
CheckValidResponse(keyResponse);
auto keyVaultKey = keyResponse.Value;
EXPECT_EQ(keyVaultKey.Name(), keyName);
}
}
TEST_F(KeyVaultKeyClient, CreateOkpHSMKey)
{
auto const keyName = GetTestName();
// This client requires an HSM client
CreateHsmClient();
auto const& client = GetClientForTest(keyName);
{
auto okpKey = Azure::Security::KeyVault::Keys::CreateOkpKeyOptions(keyName, true);
auto keyResponse = client.CreateOkpKey(okpKey);
CheckValidResponse(keyResponse);
auto keyVaultKey = keyResponse.Value;
EXPECT_EQ(keyVaultKey.Name(), keyName);
EXPECT_EQ(keyVaultKey.GetKeyType(), KeyVaultKeyType::OkpHsm);
EXPECT_EQ(keyVaultKey.Key.CurveName.Value(), KeyCurveName::Ed25519);
}
{
// Now get the key
auto keyResponse = client.GetKey(keyName);
CheckValidResponse(keyResponse);
auto keyVaultKey = keyResponse.Value;
EXPECT_EQ(keyVaultKey.Name(), keyName);
}
}
TEST_F(KeyVaultKeyClient, CreateEcKeyWithCurve)
{
auto const keyName = GetTestName();

View File

@ -35,7 +35,7 @@ TEST(KeyVaultKeyClientUnitTest, ServiceVersion)
// 7.3
EXPECT_NO_THROW(auto options = KeyClientOptions();
KeyClient keyClient("http://account.vault.azure.net", credential, options);
EXPECT_EQ(options.ApiVersion, "7.3"););
EXPECT_EQ(options.ApiVersion, "7.4-preview.1"););
}
TEST(KeyVaultKeyClientUnitTest, GetUrl)