summaryrefslogtreecommitdiffstats
path: root/src/msg/async/crypto_onwire.h
blob: 55f7550868fbeca48b8938b7d9b1529f849e33de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */


#ifndef CEPH_CRYPTO_ONWIRE_H
#define CEPH_CRYPTO_ONWIRE_H

#include <cstdint>
#include <memory>

#include "auth/Auth.h"
#include "include/buffer.h"

namespace ceph::math {

// TODO
template <typename T>
class always_aligned_t {
  T val;

  template <class... Args>
  always_aligned_t(Args&&... args)
    : val(std::forward<Args>(args)...) {
  }
};

} // namespace ceph::math

namespace ceph::crypto::onwire {

struct MsgAuthError : public std::runtime_error {
  MsgAuthError()
    : runtime_error("message signature mismatch") {
  }
};

struct TxHandlerError : public std::runtime_error {
  TxHandlerError(const char* what)
    : std::runtime_error(std::string("tx handler error: ") + what) {}
};

struct TxHandler {
  virtual ~TxHandler() = default;

  // Instance of TxHandler must be reset before doing any encrypt-update
  // step. This applies also to situation when encrypt-final was already
  // called and another round of update-...-update-final will take place.
  //
  // The input parameter informs implementation how the -update sequence
  // is fragmented and allows to make concious decision about allocation
  // or reusage of provided memory. One implementation could do in-place
  // encryption while other might prefer one huge output buffer.
  //
  // It's undefined what will happen if client doesn't follow the order.
  //
  // TODO: switch to always_aligned_t
  virtual void reset_tx_handler(const uint32_t* first,
                                const uint32_t* last) = 0;

  void reset_tx_handler(std::initializer_list<uint32_t> update_size_sequence) {
    if (update_size_sequence.size() > 0) {
      const uint32_t* first = &*update_size_sequence.begin();
      reset_tx_handler(first, first + update_size_sequence.size());
    } else {
      reset_tx_handler(nullptr, nullptr);
    }
  }

  // Perform encryption. Client gives full ownership right to provided
  // bufferlist. The method MUST NOT be called after _final() if there
  // was no call to _reset().
  virtual void authenticated_encrypt_update(
    const ceph::bufferlist& plaintext) = 0;

  // Generates authentication signature and returns bufferlist crafted
  // basing on plaintext from preceding call to _update().
  virtual ceph::bufferlist authenticated_encrypt_final() = 0;
};

class RxHandler {
public:
  virtual ~RxHandler() = default;

  // Transmitter can append extra bytes of ciphertext at the -final step.
  // This method return how much was added, and thus let client translate
  // plaintext size into ciphertext size to grab from wire.
  virtual std::uint32_t get_extra_size_at_final() = 0;

  // Instance of RxHandler must be reset before doing any decrypt-update
  // step. This applies also to situation when decrypt-final was already
  // called and another round of update-...-update-final will take place.
  virtual void reset_rx_handler() = 0;

  // Perform decryption ciphertext must be ALWAYS aligned to 16 bytes.
  virtual void authenticated_decrypt_update(ceph::bufferlist& bl) = 0;

  // Perform decryption of last cipertext's portion and verify signature
  // for overall decryption sequence.
  // Throws on integrity/authenticity checks
  virtual void authenticated_decrypt_update_final(ceph::bufferlist& bl) = 0;
};

struct rxtx_t {
  //rxtx_t(rxtx_t&& r) : rx(std::move(rx)), tx(std::move(tx)) {}
  // Each peer can use different handlers.
  // Hmm, isn't that too much flexbility?
  std::unique_ptr<RxHandler> rx;
  std::unique_ptr<TxHandler> tx;

  static rxtx_t create_handler_pair(
    CephContext* ctx,
    const class AuthConnectionMeta& auth_meta,
    bool new_nonce_format,
    bool crossed);
};

} // namespace ceph::crypto::onwire

#endif // CEPH_CRYPTO_ONWIRE_H