Skip to content

Commit

Permalink
keychain: mustCopy
Browse files Browse the repository at this point in the history
  • Loading branch information
yoursunny committed Jun 27, 2020
1 parent dc26fd2 commit 21946d0
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 57 deletions.
90 changes: 57 additions & 33 deletions src/ndnph/keychain/certificate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,69 +49,93 @@ isCertName(const Name& name)
return name[-4] == getKeyComponent();
}

/** @brief Get subject name from subject name, key name, or certificate name. */
/**
* @brief Convert to subject name.
* @param region where to allocate memory if needed.
* @param input subject name, key name, or certificate name.
* @param mustCopy if true, the returned name is always copied and does not reference input;
* otherwise, the returned name may reference input name.
* @return subject name, or an empty name upon failure.
*/
inline Name
toSubjectName(Region&, const Name& input)
toSubjectName(Region& region, const Name& input, bool mustCopy = false)
{
Name result;
if (isKeyName(input)) {
return input.getPrefix(-2);
result = input.getPrefix(-2);
} else if (isCertName(input)) {
result = input.getPrefix(-4);
} else {
result = input;
}
if (isCertName(input)) {
return input.getPrefix(-4);

if (mustCopy) {
return result.clone(region);
}
return input;
return result;
}

/**
* @brief Get key name from subject name, key name, or certificate name.
*
* If the input is a subject name, the keyId component is randomly generated,
* and the key name is allocated in the region.
* @brief Convert to key name.
* @param region where to allocate memory if needed.
* @param input subject name, key name, or certificate name.
* @param mustCopy if true, the returned name is always copied and does not reference input;
* otherwise, the returned name may reference input name.
* @return key name, or an empty name upon failure.
* If @p input does not contain keyId component, it is randomly generated.
*/
inline Name
toKeyName(Region& region, const Name& input)
toKeyName(Region& region, const Name& input, bool mustCopy = false)
{
Name result;
if (isKeyName(input)) {
return input;
result = input;
} else if (isCertName(input)) {
result = input.getPrefix(-2);
} else {
auto keyId = detail::makeRandomComponent(region);
if (!keyId) {
return Name();
}
return input.append(region, { getKeyComponent(), keyId });
}

if (isCertName(input)) {
return input.getPrefix(-2);
if (mustCopy) {
return result.clone(region);
}

auto keyId = detail::makeRandomComponent(region);
if (!keyId) {
return Name();
}
return input.append(region, { getKeyComponent(), keyId });
return result;
}

/**
* @brief Get key name from subject name, key name, or certificate name.
*
* If the input is a subject name, the keyId component is randomly generated.
* If the input is a key name, the issuerId is set to 'NDNph', and the version component
* is randomly generated.
* In both cases, the cert name is allocated in the region.
* @brief Convert to certificate name.
* @param region where to allocate memory if needed.
* @param input subject name, key name, or certificate name.
* @param mustCopy if true, the returned name is always copied and does not reference input;
* otherwise, the returned name may reference input name.
* @return certificate name, or an empty name upon failure.
* If @p input does not contain keyId or version components, they are randomly generated.
* If @p input does not contain issuerId component, it is set to 'NDNph'.
*/
inline Name
toCertName(Region& region, const Name& input)
toCertName(Region& region, const Name& input, bool mustCopy = false)
{
if (isCertName(input)) {
if (mustCopy) {
return input.clone(region);
}
return input;
}

auto version = detail::makeRandomComponent(region, TT::VersionNameComponent);
if (!version) {
return Name();
}
if (isKeyName(input)) {
auto version = detail::makeRandomComponent(region, TT::VersionNameComponent);
if (!version) {
return Name();
}
return input.append(region, { getIssuerDefault(), version });
}

auto keyId = detail::makeRandomComponent(region);
auto version = detail::makeRandomComponent(region, TT::VersionNameComponent);
if (!keyId || !version) {
if (!keyId) {
return Name();
}
return input.append(region, { getKeyComponent(), keyId, getIssuerDefault(), version });
Expand Down
55 changes: 31 additions & 24 deletions src/ndnph/keychain/ec.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,6 @@ findPublicKeyInCertificate(const Data& data)
return content.end() - PubLen::value;
}

/** @brief Key pair stored in KeyChain. */
struct StoredKeyPair
{
uint8_t pvt[PvtLen::value];
uint8_t pub[PubLen::value];
};

} // namespace detail

/** @brief EC public key. */
Expand Down Expand Up @@ -278,29 +271,27 @@ generateRaw(uint8_t pvt[EcPrivateKey::KeyLen::value], uint8_t pub[EcPublicKey::K
return port::Ec::generateKey(pvt, pub);
}

/**
* @brief Generate key pair.
* @param region where to allocate key name.
* @param name subject name or key name; may be referenced.
* @param[out] pvt the private key.
* @param[out] pub the public key.
* @param keyChain for internal use.
* @param id for internal use.
* @return whether success.
*/
namespace detail {

/** @brief Key pair stored in KeyChain. */
struct StoredKeyPair
{
uint8_t pvt[PvtLen::value];
uint8_t pub[PubLen::value];
};

inline bool
generate(Region& region, const Name& name, EcPrivateKey& pvt, EcPublicKey& pub,
KeyChain* keyChain = nullptr, const char* id = nullptr)
generate(Region& region, const Name& name, EcPrivateKey& pvt, EcPublicKey& pub, KeyChain* keyChain,
const char* id)
{
Name keyName = certificate::toKeyName(region, name);
Name keyName = certificate::toKeyName(region, name, true);
if (!keyName) {
return false;
}

Encoder encoder(region);
encoder.prepend(keyName);
auto stored =
reinterpret_cast<detail::StoredKeyPair*>(encoder.prependRoom(sizeof(detail::StoredKeyPair)));
auto stored = reinterpret_cast<StoredKeyPair*>(encoder.prependRoom(sizeof(StoredKeyPair)));
bool ok = stored != nullptr && generateRaw(stored->pvt, stored->pub) &&
pvt.import(keyName, stored->pvt) && pub.import(keyName, stored->pub);

Expand All @@ -311,10 +302,26 @@ generate(Region& region, const Name& name, EcPrivateKey& pvt, EcPublicKey& pub,
return ok;
}

} // namespace detail

/**
* @brief Generate key pair.
* @param region where to allocate key name.
* @param name subject name or key name; can be released afterwards.
* @param[out] pvt the private key.
* @param[out] pub the public key.
* @return whether success.
*/
inline bool
generate(Region& region, const Name& name, EcPrivateKey& pvt, EcPublicKey& pub)
{
return detail::generate(region, name, pvt, pub, nullptr, nullptr);
}

/**
* @brief Generate key pair and save in KeyChain.
* @param region where to allocate key name.
* @param name subject name or key name; may be referenced.
* @param name subject name or key name; can be released afterwards.
* @param[out] pvt the private key.
* @param[out] pub the public key.
* @param keyChain where to save the key pair.
Expand All @@ -325,7 +332,7 @@ inline bool
generate(Region& region, const Name& name, EcPrivateKey& pvt, EcPublicKey& pub, KeyChain& keyChain,
const char* id)
{
return generate(region, name, pvt, pub, &keyChain, id);
return detail::generate(region, name, pvt, pub, &keyChain, id);
}

/**
Expand Down

0 comments on commit 21946d0

Please sign in to comment.