summaryrefslogtreecommitdiff
path: root/src/mongo/crypto/symmetric_crypto.h
blob: d739fbe9c074a7bad8f5ba02b3f4787cf422f5ee (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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/**
 *    Copyright (C) 2019-present MongoDB, Inc.
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the Server Side Public License, version 1,
 *    as published by MongoDB, Inc.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    Server Side Public License for more details.
 *
 *    You should have received a copy of the Server Side Public License
 *    along with this program. If not, see
 *    <http://www.mongodb.com/licensing/server-side-public-license>.
 *
 *    As a special exception, the copyright holders give permission to link the
 *    code of portions of this program with the OpenSSL library under certain
 *    conditions as described in each individual source file and distribute
 *    linked combinations including the program with the OpenSSL library. You
 *    must comply with the Server Side Public License in all respects for
 *    all of the code used other than as permitted herein. If you modify file(s)
 *    with this exception, you may extend this exception to your version of the
 *    file(s), but you are not obligated to do so. If you do not wish to do so,
 *    delete this exception statement from your version. If you delete this
 *    exception statement from all source files in the program, then also delete
 *    it in the license file.
 */

#pragma once

#include <cstddef>
#include <cstdint>
#include <set>
#include <string>

#include "mongo/base/data_range.h"
#include "mongo/base/status.h"
#include "mongo/base/status_with.h"
#include "mongo/crypto/symmetric_key.h"

namespace mongo {
namespace crypto {

/**
 * Encryption algorithm identifiers and block sizes
 */
constexpr uint8_t aesAlgorithm = 0x1;

/**
 * Block and key sizes
 */
constexpr size_t aesBlockSize = 16;
constexpr size_t sym256KeySize = 32;

/**
 * Min and max symmetric key lengths
 */
constexpr size_t minKeySize = 16;
constexpr size_t maxKeySize = 32;

/**
 * CBC fixed constants
 */
constexpr size_t aesCBCIVSize = aesBlockSize;

/**
 * GCM tunable parameters
 */
constexpr size_t aesGCMTagSize = 12;
constexpr size_t aesGCMIVSize = 12;

/**
 * CTR tunable parameters
 */
constexpr size_t aesCTRIVSize = 16;

/**
 * Encryption mode identifiers
 */
enum class aesMode : uint8_t { cbc, gcm, ctr };

/**
 * Algorithm names which this module recognizes
 */
const std::string aes256CBCName = "AES256-CBC";
const std::string aes256GCMName = "AES256-GCM";
const std::string aes256CTRName = "AES256-CTR";

aesMode getCipherModeFromString(const std::string& mode);
std::string getStringFromCipherMode(aesMode);

/**
 * Generates a new, random, symmetric key for use with AES.
 */
SymmetricKey aesGenerate(size_t keySize, SymmetricKeyId keyId);

/* Platform specific engines should implement these. */

/**
 * Interface to a symmetric cryptography engine.
 * For use with encrypting payloads.
 */
class SymmetricEncryptor {
public:
    virtual ~SymmetricEncryptor() = default;

    /**
     * Process a chunk of data from <in> and store the ciphertext in <out>.
     * Returns the number of bytes written to <out> which will not exceed <out.length()>.
     * Because <in.length()> for this and/or previous calls may not lie on a block boundary,
     * the number of bytes written to <out> may be more or less than <in.length()>.
     */
    virtual StatusWith<std::size_t> update(ConstDataRange in, DataRange out) = 0;

    /**
     * Append Additional AuthenticatedData (AAD) to a GCM encryption stream.
     */
    virtual Status addAuthenticatedData(ConstDataRange authData) = 0;

    /**
     * Finish an encryption by flushing any buffered bytes for a partial cipherblock to <out>.
     * Returns the number of bytes written, not to exceed <out.length()>.
     */
    virtual StatusWith<std::size_t> finalize(DataRange out) = 0;

    /**
     * For aesMode::gcm, writes the GCM tag to <out>.
     * Returns the number of bytes used, not to exceed <out.length()>.
     */
    virtual StatusWith<std::size_t> finalizeTag(DataRange out) = 0;

    /**
     * Create an instance of a SymmetricEncryptor object from the currently available
     * cipher engine (e.g. OpenSSL).
     */
    static StatusWith<std::unique_ptr<SymmetricEncryptor>> create(const SymmetricKey& key,
                                                                  aesMode mode,
                                                                  ConstDataRange iv);
};

/**
 * Interface to a symmetric cryptography engine.
 * For use with encrypting payloads.
 */
class SymmetricDecryptor {
public:
    virtual ~SymmetricDecryptor() = default;

    /**
     * Process a chunk of data from <in> and store the decrypted text in <out>.
     * Returns the number of bytes written to <out> which will not exceed <out.length()>.
     * Because <in.length()> for this and/or previous calls may not lie on a block boundary,
     * the number of bytes written to <out> may be more or less than <in.length()>.
     */
    virtual StatusWith<std::size_t> update(ConstDataRange in, DataRange out) = 0;

    /**
     * For aesMode::gcm, inform the cipher engine of additional authenticated data (AAD).
     */
    virtual Status addAuthenticatedData(ConstDataRange authData) = 0;

    /**
     * For aesMode::gcm, informs the cipher engine of the GCM tag associated with this data stream.
     */
    virtual Status updateTag(ConstDataRange tag) = 0;

    /**
     * Finish an decryption by flushing any buffered bytes for a partial cipherblock to <out>.
     * Returns the number of bytes written, not to exceed <out.length()>.
     */
    virtual StatusWith<std::size_t> finalize(DataRange out) = 0;

    /**
     * Create an instance of a SymmetricDecryptor object from the currently available
     * cipher engine (e.g. OpenSSL).
     */
    static StatusWith<std::unique_ptr<SymmetricDecryptor>> create(const SymmetricKey& key,
                                                                  aesMode mode,
                                                                  ConstDataRange iv);
};

/**
 * Returns a list of cipher modes supported by the cipher engine.
 * e.g. {"AES256-CBC", "AES256-GCM"}
 */
std::set<std::string> getSupportedSymmetricAlgorithms();

/**
 * Generate a quantity of random bytes from the cipher engine.
 */
Status engineRandBytes(DataRange buffer);

}  // namespace crypto
}  // namespace mongo