summaryrefslogtreecommitdiffstats
path: root/src/rgw/rgw_cksum_digest.h
blob: ba7e3bd58c6f82a6a17eab9b81a77e4b07c64f0a (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
131
132
133
134
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2019 Red Hat, Inc.
 *
 * 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.
 *
 */

#pragma once

#include <boost/variant.hpp>
#include <boost/blank.hpp>
#include "common/ceph_crypto.h"
#include "rgw_blake3_digest.h"
#include "rgw_crc_digest.h"
#include "rgw_xxh_digest.h"

#include "rgw_cksum.h"

namespace rgw { namespace cksum {

  class Digest {
  public:
    virtual void Restart() = 0;
    virtual void Update (const unsigned char *input, size_t length) = 0;
    virtual void Update(const ceph::buffer::list& bl) = 0;
    virtual void Final (unsigned char *digest) = 0;
    virtual ~Digest() {}
  };

  template<class T>
  class TDigest : public Digest
  {
    T d;
  public:
    TDigest() {}
    TDigest(TDigest&& rhs) noexcept
      : d(std::move(rhs.d))
    {}
    void Restart() override { d.Restart(); }
    void Update(const unsigned char* data, uint64_t len) override {
      d.Update(data, len);
    }
    void Update(const ceph::buffer::list& bl) {
      for (auto& p : bl.buffers()) {
	d.Update((const unsigned char *)p.c_str(), p.length());
      }
    }
    void Final(unsigned char* digest) override {
      d.Final(digest);
    }
  };

  typedef TDigest<rgw::digest::Blake3> Blake3;
  typedef TDigest<rgw::digest::Crc32> Crc32;
  typedef TDigest<rgw::digest::Crc32c> Crc32c;
  typedef TDigest<rgw::digest::XXH3> XXH3;
  typedef TDigest<ceph::crypto::SHA1> SHA1;
  typedef TDigest<ceph::crypto::SHA256> SHA256;
  typedef TDigest<ceph::crypto::SHA512> SHA512;

  typedef boost::variant<boost::blank,
			 Blake3,
			 Crc32,
			 Crc32c,
			 XXH3,
			 SHA1,
			 SHA256,
			 SHA512> DigestVariant;

  struct get_digest_ptr : public boost::static_visitor<Digest*>
  {
    get_digest_ptr() {};
    Digest* operator()(const boost::blank& b) const { return nullptr; }
    Digest* operator()(Blake3& digest) const { return &digest; }
    Digest* operator()(Crc32& digest) const { return &digest; }
    Digest* operator()(Crc32c& digest) const { return &digest; }
    Digest* operator()(XXH3& digest) const { return &digest; }
    Digest* operator()(SHA1& digest) const { return &digest; }
    Digest* operator()(SHA256& digest) const { return &digest; }
    Digest* operator()(SHA512& digest) const { return &digest; }
  };

  static inline Digest* get_digest(DigestVariant& ev)
  {
    return boost::apply_visitor(get_digest_ptr{}, ev);
  }

  static inline DigestVariant digest_factory(const Type cksum_type)
  {
    switch (cksum_type) {
    case Type::blake3:
      return Blake3();
      break;
    case Type::sha256:
      return SHA256();
      break;
    case Type::crc32:
      return Crc32();
      break;
    case Type::crc32c:
      return Crc32c();
      break;
    case Type::xxh3:
      return XXH3();
      break;
    case Type::sha512:
      return SHA512();
      break;
    case Type::sha1:
      return SHA1();
      break;
    case Type::none:
      break;
    };
    return boost::blank();
  } /* digest_factory */

  static inline Cksum finalize_digest(Digest* digest, Type type)
  {
    Cksum cksum(type);
    if (digest) {
      auto data = cksum.digest.data();
      digest->Final(data);
    }
    return cksum;
  }

}} /* namespace */