update crypto helper
Change-Id: I59718964ce305888a8fc3947cde68c937a3ba64a
diff --git a/src/detail/ca-sqlite.cpp b/src/detail/ca-sqlite.cpp
index b0d6af5..468fd2c 100644
--- a/src/detail/ca-sqlite.cpp
+++ b/src/detail/ca-sqlite.cpp
@@ -66,7 +66,8 @@
remaining_tries INTEGER,
remaining_time INTEGER,
challenge_secrets TEXT,
- encryption_key BLOB NOT NULL
+ encryption_key BLOB NOT NULL,
+ aes_block_counter INTEGER
);
CREATE UNIQUE INDEX IF NOT EXISTS
CaStateIdIndex ON CaStates(request_id);
@@ -128,7 +129,8 @@
R"_SQLTEXT_(SELECT id, ca_name, status,
challenge_status, cert_request,
challenge_type, challenge_secrets,
- challenge_tp, remaining_tries, remaining_time, request_type, encryption_key
+ challenge_tp, remaining_tries, remaining_time,
+ request_type, encryption_key, aes_block_counter
FROM CaStates where request_id = ?)_SQLTEXT_");
statement.bind(1, requestId, SQLITE_TRANSIENT);
@@ -144,11 +146,12 @@
auto remainingTime = statement.getInt(9);
auto requestType = static_cast<RequestType>(statement.getInt(10));
auto encryptionKey = statement.getBlock(11);
+ auto aesCounter = statement.getInt(12);
if (challengeType != "") {
return CaState(caName, requestId, requestType, status, cert,
challengeType, challengeStatus, time::fromIsoString(challengeTp),
remainingTries, time::seconds(remainingTime),
- convertString2Json(challengeSecrets), encryptionKey);
+ convertString2Json(challengeSecrets), encryptionKey, aesCounter);
}
else {
return CaState(caName, requestId, requestType, status, cert, encryptionKey);
@@ -166,14 +169,15 @@
m_database,
R"_SQLTEXT_(INSERT OR ABORT INTO CaStates (request_id, ca_name, status, request_type,
cert_request, challenge_type, challenge_status, challenge_secrets,
- challenge_tp, remaining_tries, remaining_time, encryption_key)
- values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?))_SQLTEXT_");
+ challenge_tp, remaining_tries, remaining_time, encryption_key, aes_block_counter)
+ values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?))_SQLTEXT_");
statement.bind(1, request.m_requestId, SQLITE_TRANSIENT);
statement.bind(2, request.m_caPrefix.wireEncode(), SQLITE_TRANSIENT);
statement.bind(3, static_cast<int>(request.m_status));
statement.bind(4, static_cast<int>(request.m_requestType));
statement.bind(5, request.m_cert.wireEncode(), SQLITE_TRANSIENT);
statement.bind(12, request.m_encryptionKey, SQLITE_TRANSIENT);
+ statement.bind(13, request.m_aesBlockCounter);
if (request.m_challengeState) {
statement.bind(6, request.m_challengeType, SQLITE_TRANSIENT);
statement.bind(7, request.m_challengeState->m_challengeStatus, SQLITE_TRANSIENT);
@@ -194,7 +198,7 @@
Sqlite3Statement statement(m_database,
R"_SQLTEXT_(UPDATE CaStates
SET status = ?, challenge_type = ?, challenge_status = ?, challenge_secrets = ?,
- challenge_tp = ?, remaining_tries = ?, remaining_time = ?
+ challenge_tp = ?, remaining_tries = ?, remaining_time = ?, aes_block_counter = ?
WHERE request_id = ?)_SQLTEXT_");
statement.bind(1, static_cast<int>(request.m_status));
statement.bind(2, request.m_challengeType, SQLITE_TRANSIENT);
@@ -212,7 +216,8 @@
statement.bind(6, 0);
statement.bind(7, 0);
}
- statement.bind(8, request.m_requestId, SQLITE_TRANSIENT);
+ statement.bind(8, request.m_aesBlockCounter);
+ statement.bind(9, request.m_requestId, SQLITE_TRANSIENT);
if (statement.step() != SQLITE_DONE) {
addRequest(request);
@@ -225,7 +230,8 @@
std::list<CaState> result;
Sqlite3Statement statement(m_database, R"_SQLTEXT_(SELECT id, request_id, ca_name, status,
challenge_status, cert_request, challenge_type, challenge_secrets,
- challenge_tp, remaining_tries, remaining_time, request_type, encryption_key
+ challenge_tp, remaining_tries, remaining_time, request_type,
+ encryption_key, aes_block_counter
FROM CaStates)_SQLTEXT_");
while (statement.step() == SQLITE_ROW) {
auto requestId = statement.getString(1);
@@ -240,14 +246,15 @@
auto remainingTime = statement.getInt(10);
auto requestType = static_cast<RequestType>(statement.getInt(11));
auto encryptionKey = statement.getBlock(12);
+ auto aesBlockCounter = statement.getInt(13);
if (challengeType != "") {
result.push_back(CaState(caName, requestId, requestType, status, cert,
challengeType, challengeStatus, time::fromIsoString(challengeTp),
remainingTries, time::seconds(remainingTime),
- convertString2Json(challengeSecrets), encryptionKey));
+ convertString2Json(challengeSecrets), encryptionKey, aesBlockCounter));
}
else {
- result.push_back(CaState(caName, requestId, requestType, status, cert, encryptionKey));
+ result.push_back(CaState(caName, requestId, requestType, status, cert, encryptionKey, aesBlockCounter));
}
}
return result;
@@ -260,7 +267,8 @@
Sqlite3Statement statement(m_database,
R"_SQLTEXT_(SELECT id, request_id, ca_name, status,
challenge_status, cert_request, challenge_type, challenge_secrets,
- challenge_tp, remaining_tries, remaining_time, request_type, encryption_key
+ challenge_tp, remaining_tries, remaining_time, request_type,
+ encryption_key, aes_block_counter
FROM CaStates WHERE ca_name = ?)_SQLTEXT_");
statement.bind(1, caName.wireEncode(), SQLITE_TRANSIENT);
@@ -277,14 +285,15 @@
auto remainingTime = statement.getInt(10);
auto requestType = static_cast<RequestType>(statement.getInt(11));
auto encryptionKey = statement.getBlock(12);
+ auto aesBlockCounter = statement.getInt(13);
if (challengeType != "") {
result.push_back(CaState(caName, requestId, requestType, status, cert,
challengeType, challengeStatus, time::fromIsoString(challengeTp),
remainingTries, time::seconds(remainingTime),
- convertString2Json(challengeSecrets), encryptionKey));
+ convertString2Json(challengeSecrets), encryptionKey, aesBlockCounter));
}
else {
- result.push_back(CaState(caName, requestId, requestType, status, cert, encryptionKey));
+ result.push_back(CaState(caName, requestId, requestType, status, cert, encryptionKey, aesBlockCounter));
}
}
return result;
diff --git a/src/detail/ca-state.cpp b/src/detail/ca-state.cpp
index 185fbdd..334429a 100644
--- a/src/detail/ca-state.cpp
+++ b/src/detail/ca-state.cpp
@@ -65,13 +65,14 @@
}
CaState::CaState(const Name& caName, const std::string& requestId, RequestType requestType, Status status,
- const security::Certificate& cert, Block encryptionKey)
+ const security::Certificate& cert, Block encryptionKey, uint32_t aesBlockCounter)
: m_caPrefix(caName)
, m_requestId(requestId)
, m_requestType(requestType)
, m_status(status)
, m_cert(cert)
, m_encryptionKey(std::move(encryptionKey))
+ , m_aesBlockCounter(aesBlockCounter)
{
}
@@ -79,13 +80,14 @@
const security::Certificate& cert, const std::string& challengeType,
const std::string& challengeStatus, const time::system_clock::TimePoint& challengeTp,
size_t remainingTries, time::seconds remainingTime, JsonSection&& challengeSecrets,
- Block encryptionKey)
+ Block encryptionKey, uint32_t aesBlockCounter)
: m_caPrefix(caName)
, m_requestId(requestId)
, m_requestType(requestType)
, m_status(status)
, m_cert(cert)
, m_encryptionKey(std::move(encryptionKey))
+ , m_aesBlockCounter(aesBlockCounter)
, m_challengeType(challengeType)
, m_challengeState(ChallengeState(challengeStatus, challengeTp, remainingTries, remainingTime, std::move(challengeSecrets)))
{
diff --git a/src/detail/ca-state.hpp b/src/detail/ca-state.hpp
index 2204f1c..9f30b6d 100644
--- a/src/detail/ca-state.hpp
+++ b/src/detail/ca-state.hpp
@@ -66,12 +66,12 @@
public:
CaState();
CaState(const Name& caName, const std::string& requestId, RequestType requestType, Status status,
- const security::Certificate& cert, Block m_encryptionKey);
+ const security::Certificate& cert, Block m_encryptionKey, uint32_t aesBlockCounter = 0);
CaState(const Name& caName, const std::string& requestId, RequestType requestType, Status status,
const security::Certificate& cert, const std::string& challengeType,
const std::string& challengeStatus, const time::system_clock::TimePoint& challengeTp,
size_t remainingTries, time::seconds remainingTime, JsonSection&& challengeSecrets,
- Block m_encryptionKey);
+ Block m_encryptionKey, uint32_t aesBlockCounter);
public:
Name m_caPrefix;
@@ -80,6 +80,7 @@
Status m_status;
security::Certificate m_cert;
Block m_encryptionKey;
+ uint32_t m_aesBlockCounter = 0;
std::string m_challengeType;
boost::optional<ChallengeState> m_challengeState;
diff --git a/src/detail/crypto-helper.cpp b/src/detail/crypto-helper.cpp
index 1cd974a..86970f9 100644
--- a/src/detail/crypto-helper.cpp
+++ b/src/detail/crypto-helper.cpp
@@ -19,6 +19,7 @@
*/
#include "crypto-helper.hpp"
+#include <cmath>
#include <openssl/err.h>
#include <openssl/hmac.h>
#include <openssl/pem.h>
@@ -31,6 +32,7 @@
#include <ndn-cxx/security/transform/buffer-source.hpp>
#include <ndn-cxx/security/transform/stream-sink.hpp>
#include <ndn-cxx/util/random.hpp>
+#include <boost/endian/conversion.hpp>
namespace ndn {
namespace ndncert {
@@ -206,24 +208,31 @@
{
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr);
if (EVP_PKEY_derive_init(pctx) <= 0) {
+ EVP_PKEY_CTX_free(pctx);
NDN_THROW(std::runtime_error("HKDF: Cannot init ctx when calling EVP_PKEY_derive_init()."));
}
if (EVP_PKEY_CTX_set_hkdf_md(pctx, EVP_sha256()) <= 0) {
+ EVP_PKEY_CTX_free(pctx);
NDN_THROW(std::runtime_error("HKDF: Cannot set md when calling EVP_PKEY_CTX_set_hkdf_md()."));
}
if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt, salt_len) <= 0) {
+ EVP_PKEY_CTX_free(pctx);
NDN_THROW(std::runtime_error("HKDF: Cannot set salt when calling EVP_PKEY_CTX_set1_hkdf_salt()."));
}
if (EVP_PKEY_CTX_set1_hkdf_key(pctx, secret, secret_len) <= 0) {
+ EVP_PKEY_CTX_free(pctx);
NDN_THROW(std::runtime_error("HKDF: Cannot set secret when calling EVP_PKEY_CTX_set1_hkdf_key()."));
}
if (EVP_PKEY_CTX_add1_hkdf_info(pctx, info, info_len) <= 0) {
+ EVP_PKEY_CTX_free(pctx);
NDN_THROW(std::runtime_error("HKDF: Cannot set info when calling EVP_PKEY_CTX_add1_hkdf_info()."));
}
size_t outLen = output_len;
if (EVP_PKEY_derive(pctx, output, &outLen) <= 0) {
+ EVP_PKEY_CTX_free(pctx);
NDN_THROW(std::runtime_error("HKDF: Cannot derive result when calling EVP_PKEY_derive()."));
}
+ EVP_PKEY_CTX_free(pctx);
return (int)outLen;
}
@@ -350,22 +359,32 @@
Block
encodeBlockWithAesGcm128(uint32_t tlv_type, const uint8_t* key, const uint8_t* payload, size_t payloadSize,
- const uint8_t* associatedData, size_t associatedDataSize)
+ const uint8_t* associatedData, size_t associatedDataSize, uint32_t& counter)
{
- Buffer iv;
- iv.resize(12);
+ Buffer iv(12);
random::generateSecureBytes(iv.data(), iv.size());
+ if (tlv_type == ndn::tlv::ApplicationParameters) {
+ // requester
+ iv[0] &= ~(1UL << 7);
+ }
+ else {
+ // CA
+ iv[0] |= 1UL << 7;
+ }
+ uint32_t temp = counter;
+ boost::endian::native_to_big_inplace(temp);
+ std::memcpy(&iv[8], reinterpret_cast<const uint8_t*>(&temp), 4);
+ counter += std::ceil(payloadSize / 8);
- uint8_t* encryptedPayload = new uint8_t[payloadSize];
+ Buffer encryptedPayload(payloadSize);
uint8_t tag[16];
size_t encryptedPayloadLen = aes_gcm_128_encrypt(payload, payloadSize, associatedData, associatedDataSize,
- key, iv.data(), encryptedPayload, tag);
+ key, iv.data(), encryptedPayload.data(), tag);
auto content = makeEmptyBlock(tlv_type);
content.push_back(makeBinaryBlock(tlv::InitializationVector, iv.data(), iv.size()));
content.push_back(makeBinaryBlock(tlv::AuthenticationTag, tag, 16));
- content.push_back(makeBinaryBlock(tlv::EncryptedPayload, encryptedPayload, encryptedPayloadLen));
+ content.push_back(makeBinaryBlock(tlv::EncryptedPayload, encryptedPayload.data(), encryptedPayloadLen));
content.encode();
- delete[] encryptedPayload;
return content;
}
diff --git a/src/detail/crypto-helper.hpp b/src/detail/crypto-helper.hpp
index 2e8f7af..8463eb6 100644
--- a/src/detail/crypto-helper.hpp
+++ b/src/detail/crypto-helper.hpp
@@ -134,11 +134,12 @@
* @param payloadSize The size of the plaintext payload.
* @param associatedData The associated data used for authentication.
* @param associatedDataSize The size of associated data.
+ * @param counter The counter of blocks that have been encrypted by the requester/CA.
* @return Block The TLV block with @param tlv_type TLV TYPE.
*/
Block
encodeBlockWithAesGcm128(uint32_t tlv_type, const uint8_t* key, const uint8_t* payload, size_t payloadSize,
- const uint8_t* associatedData, size_t associatedDataSize);
+ const uint8_t* associatedData, size_t associatedDataSize, uint32_t& counter);
/**
* @brief Decode the payload from TLV block with Authenticated GCM 128 Encryption.