aboutsummaryrefslogtreecommitdiffstats
path: root/libtransport/src/security/signer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libtransport/src/security/signer.cc')
-rw-r--r--libtransport/src/security/signer.cc187
1 files changed, 187 insertions, 0 deletions
diff --git a/libtransport/src/security/signer.cc b/libtransport/src/security/signer.cc
new file mode 100644
index 000000000..314c3ea82
--- /dev/null
+++ b/libtransport/src/security/signer.cc
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright 2017 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hicn/transport/errors/malformed_ahpacket_exception.h>
+#include <hicn/transport/security/key_id.h>
+#include <hicn/transport/security/signer.h>
+#include <hicn/transport/utils/membuf.h>
+
+extern "C" {
+#ifndef _WIN32
+TRANSPORT_CLANG_DISABLE_WARNING("-Wextern-c-compat")
+#endif
+#include <hicn/hicn.h>
+#include <parc/security/parc_PublicKeySigner.h>
+#include <parc/security/parc_Security.h>
+#include <parc/security/parc_SymmetricKeySigner.h>
+}
+
+#include <chrono>
+
+#define ALLOW_UNALIGNED_READS 1
+
+namespace utils {
+
+uint8_t Signer::zeros[200] = {0};
+
+/*One signer_ per Private Key*/
+Signer::Signer(PARCKeyStore *keyStore, CryptoSuite suite) {
+ parcSecurity_Init();
+
+ switch (suite) {
+ case CryptoSuite::DSA_SHA256:
+ case CryptoSuite::RSA_SHA256:
+ case CryptoSuite::RSA_SHA512:
+ case CryptoSuite::ECDSA_256K1: {
+ this->signer_ =
+ parcSigner_Create(parcPublicKeySigner_Create(
+ keyStore, static_cast<PARCCryptoSuite>(suite)),
+ PARCPublicKeySignerAsSigner);
+ break;
+ }
+ case CryptoSuite::HMAC_SHA256:
+ case CryptoSuite::HMAC_SHA512: {
+ this->signer_ =
+ parcSigner_Create(parcSymmetricKeySigner_Create(
+ (PARCSymmetricKeyStore *)keyStore,
+ parcCryptoSuite_GetCryptoHash(
+ static_cast<PARCCryptoSuite>(suite))),
+ PARCSymmetricKeySignerAsSigner);
+ break;
+ }
+ default: { return; }
+ }
+
+ suite_ = suite;
+ key_id_ = parcSigner_CreateKeyId(this->signer_);
+ signature_length_ = parcSigner_GetSignatureSize(this->signer_);
+}
+
+Signer::Signer(const std::string &passphrase, CryptoSuite suite) {
+ parcSecurity_Init();
+
+ switch (suite) {
+ case CryptoSuite::HMAC_SHA256:
+ case CryptoSuite::HMAC_SHA512: {
+ composer_ = parcBufferComposer_Create();
+ parcBufferComposer_PutString(composer_, passphrase.c_str());
+ key_buffer_ = parcBufferComposer_ProduceBuffer(composer_);
+ symmetricKeyStore_ = parcSymmetricKeyStore_Create(key_buffer_);
+ this->signer_ = parcSigner_Create(
+ parcSymmetricKeySigner_Create(
+ symmetricKeyStore_, parcCryptoSuite_GetCryptoHash(
+ static_cast<PARCCryptoSuite>(suite))),
+ PARCSymmetricKeySignerAsSigner);
+ break;
+ }
+ default: { return; }
+ }
+
+ suite_ = suite;
+ key_id_ = parcSigner_CreateKeyId(this->signer_);
+ signature_length_ = parcSigner_GetSignatureSize(this->signer_);
+}
+
+Signer::Signer(const PARCSigner *signer, CryptoSuite suite)
+ : signer_(parcSigner_Acquire(signer)),
+ key_id_(parcSigner_CreateKeyId(this->signer_)),
+ suite_(suite),
+ signature_length_(parcSigner_GetSignatureSize(this->signer_)) {
+ parcSecurity_Init();
+}
+
+Signer::Signer(const PARCSigner *signer)
+ : Signer(signer, CryptoSuite::UNKNOWN) {}
+
+Signer::~Signer() {
+ if (signature_) parcSignature_Release(&signature_);
+ if (symmetricKeyStore_) parcSymmetricKeyStore_Release(&symmetricKeyStore_);
+ if (key_buffer_) parcBuffer_Release(&key_buffer_);
+ if (composer_) parcBufferComposer_Release(&composer_);
+ if (signer_) parcSigner_Release(&signer_);
+ if (key_id_) parcKeyId_Release(&key_id_);
+ parcSecurity_Fini();
+}
+
+void Signer::sign(Packet &packet) {
+ // header chain points to the IP + TCP hicn header + AH Header
+ MemBuf *header_chain = packet.header_head_;
+ MemBuf *payload_chain = packet.payload_head_;
+ uint8_t *hicn_packet = (uint8_t *)header_chain->writableData();
+ Packet::Format format = packet.getFormat();
+
+ if (!(format & HFO_AH)) {
+ throw errors::MalformedAHPacketException();
+ }
+
+ packet.setSignatureSize(signature_length_);
+
+ // Copy IP+TCP/ICMP header before zeroing them
+ hicn_header_t header_copy;
+ hicn_packet_copy_header(format, (const hicn_header_t *)packet.packet_start_,
+ &header_copy, false);
+
+ std::size_t header_len = Packet::getHeaderSizeFromFormat(format);
+
+ packet.resetForHash();
+
+ /* Fill the hicn_ah header */
+ using namespace std::chrono;
+ auto now = duration_cast<milliseconds>(system_clock::now().time_since_epoch())
+ .count();
+ packet.setSignatureTimestamp(now);
+ packet.setValidationAlgorithm(suite_);
+
+ KeyId key_id;
+ key_id.first = (uint8_t *)parcBuffer_Overlay(
+ (PARCBuffer *)parcKeyId_GetKeyId(this->key_id_), 0);
+ packet.setKeyId(key_id);
+
+ // Calculate hash
+ CryptoHasher hasher(parcSigner_GetCryptoHasher(signer_));
+ hasher.init();
+ hasher.updateBytes(hicn_packet, header_len + signature_length_);
+
+ for (MemBuf *current = payload_chain; current != header_chain;
+ current = current->next()) {
+ hasher.updateBytes(current->data(), current->length());
+ }
+
+ CryptoHash hash = hasher.finalize();
+
+ signature_ = parcSigner_SignDigestNoAlloc(this->signer_, hash.hash_,
+ packet.getSignature(),
+ (uint32_t)signature_length_);
+ PARCBuffer *buffer = parcSignature_GetSignature(signature_);
+
+ size_t bytes_len = parcBuffer_Remaining(buffer);
+
+ if (bytes_len > signature_length_) {
+ throw errors::MalformedAHPacketException();
+ }
+
+ hicn_packet_copy_header(format, &header_copy,
+ (hicn_header_t *)packet.packet_start_, false);
+}
+
+size_t Signer::getSignatureLength() { return signature_length_; }
+
+PARCKeyStore *Signer::getKeyStore() {
+ return parcSigner_GetKeyStore(this->signer_);
+}
+
+} // namespace utils