]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
msg/async, v2: round up segments to CRYPTO_BLOCK_SIZE in secure mode.
authorRadoslaw Zarzynski <rzarzyns@redhat.com>
Mon, 4 Mar 2019 15:21:47 +0000 (16:21 +0100)
committerRadoslaw Zarzynski <rzarzyns@redhat.com>
Mon, 4 Mar 2019 19:58:47 +0000 (20:58 +0100)
Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
src/msg/async/ProtocolV2.cc
src/msg/async/frames_v2.h

index bc16aacd4bfc57016f6d4a53bba920eb32afccce..4c41991f7cd15ca2dd2c3ccbc066af9f1bea584d 100644 (file)
@@ -677,8 +677,12 @@ bool ProtocolV2::is_queued() {
   return !out_queue.empty() || connection->is_queued();
 }
 
-uint32_t ProtocolV2::get_onwire_size(uint32_t logical_size) const {
-  return logical_size;
+uint32_t ProtocolV2::get_onwire_size(const uint32_t logical_size) const {
+  if (session_stream_handlers.rx) {
+    return segment_onwire_size(logical_size);
+  } else {
+    return logical_size;
+  }
 }
 
 uint32_t ProtocolV2::get_epilogue_size() const {
@@ -1154,8 +1158,15 @@ CtPtr ProtocolV2::handle_read_frame_segment(char *buffer, int r) {
 
     auto& new_seg = rx_segments_data.back();
     if (new_seg.length()) {
-      new_seg = session_stream_handlers.rx->authenticated_decrypt_update(
+      auto padded = session_stream_handlers.rx->authenticated_decrypt_update(
           std::move(new_seg), segment_t::DEFAULT_ALIGNMENT);
+      const auto idx = rx_segments_data.size() - 1;
+      new_seg.clear();
+      padded.splice(0, rx_segments_desc[idx].length, &new_seg);
+
+      ldout(cct, 20) << __func__
+                     << " unpadded new_seg.length()=" << new_seg.length()
+                     << dendl;
     }
   }
 
index a1205096c4632125685905ce88dc4d9b6bae6ee8..7093e244a2657bd45a0e41585f32920255525b85 100644 (file)
@@ -148,6 +148,30 @@ static constexpr uint32_t FRAME_SECURE_EPILOGUE_SIZE =
 
 #define FRAME_FLAGS_LATEABRT      (1<<0)   /* frame was aborted after txing data */
 
+static uint32_t segment_onwire_size(const uint32_t logical_size)
+{
+  return p2roundup(logical_size, CRYPTO_BLOCK_SIZE);
+}
+
+static ceph::bufferlist segment_onwire_bufferlist(ceph::bufferlist&& bl)
+{
+  const auto padding_size = segment_onwire_size(bl.length()) - bl.length();
+  if (padding_size) {
+    bl.append_zero(padding_size);
+  }
+  return bl;
+}
+
+static ceph::bufferlist segment_onwire_bufferlist(const ceph::bufferlist &bl)
+{
+  ceph::bufferlist ret(bl);
+  const auto padding_size = segment_onwire_size(bl.length()) - bl.length();
+  if (padding_size) {
+    ret.append_zero(padding_size);
+  }
+  return ret;
+}
+
 template <class T>
 struct Frame {
 protected:
@@ -389,12 +413,12 @@ struct SignedEncryptedFrame : public PayloadFrame<T, Args...> {
   static T Encode(ceph::crypto::onwire::rxtx_t &session_stream_handlers,
                   const Args &... args) {
     T c = PayloadFrame<T, Args...>::Encode(args...);
-    // FIXME: plainsize -> ciphersize; for AES-GCM they are equall apart
-    // from auth tag size
     c.fill_preamble({segment_t{c.payload.length() - FRAME_PREAMBLE_SIZE,
                      segment_t::DEFAULT_ALIGNMENT}});
 
     if (session_stream_handlers.tx) {
+      c.payload = segment_onwire_bufferlist(std::move(c.payload));
+
       epilogue_secure_block_t epilogue;
       ::memset(&epilogue, 0, sizeof(epilogue));
       c.payload.append(reinterpret_cast<const char*>(&epilogue), sizeof(epilogue));
@@ -631,7 +655,7 @@ struct MessageHeaderFrame
                                    const ceph::bufferlist& data) {
     MessageHeaderFrame f =
         PayloadFrame<MessageHeaderFrame, ceph_msg_header2>::Encode(msg_header);
-    // FIXME: plainsize -> ciphersize; for AES-GCM they are equall apart from auth tag size
+
     f.fill_preamble({
       segment_t{ f.payload.length() - FRAME_PREAMBLE_SIZE,
                 segment_t::DEFAULT_ALIGNMENT },
@@ -640,16 +664,21 @@ struct MessageHeaderFrame
       segment_t{ data.length(), segment_t::PAGE_SIZE_ALIGNMENT },
     });
 
-    // FIXME: plainsize -> ciphersize; for AES-GCM they are equall apart from auth tag size
     if (session_stream_handlers.tx) {
+      // we're padding segments to biggest cipher's block size. Although
+      // AES-GCM can live without that as it's a stream cipher, we don't
+      // to be fixed to stream ciphers only.
+      f.payload = segment_onwire_bufferlist(std::move(f.payload));
+      auto front_padded = segment_onwire_bufferlist(front);
+      auto middle_padded = segment_onwire_bufferlist(middle);
+      auto data_padded = segment_onwire_bufferlist(data);
+
       // let's cipher allocate one huge buffer for entire ciphertext.
-      // NOTE: ultimately we'll align these sizes to cipher's block size.
-      // AES-GCM can live without that as it's basically stream cipher.
       session_stream_handlers.tx->reset_tx_handler({
         f.payload.length(),
-        front.length(),
-        middle.length(),
-        data.length()
+        front_padded.length(),
+        middle_padded.length(),
+        data_padded.length()
       });
 
       ceph_assert(f.payload.length());
@@ -658,13 +687,13 @@ struct MessageHeaderFrame
 
       // TODO: switch TxHandler from `bl&&` to `const bl&`.
       if (front.length()) {
-        session_stream_handlers.tx->authenticated_encrypt_update(front);
+        session_stream_handlers.tx->authenticated_encrypt_update(front_padded);
       }
       if (middle.length()) {
-        session_stream_handlers.tx->authenticated_encrypt_update(middle);
+        session_stream_handlers.tx->authenticated_encrypt_update(middle_padded);
       }
       if (data.length()) {
-        session_stream_handlers.tx->authenticated_encrypt_update(data);
+        session_stream_handlers.tx->authenticated_encrypt_update(data_padded);
       }
 
       // craft the secure's mode epilogue