Client RequestChannels and folly/python/futures.h
[folly.git] / folly / ssl / OpenSSLHash.h
1 /*
2  * Copyright 2017 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #pragma once
18
19 #include <folly/io/async/ssl/OpenSSLPtrTypes.h>
20 #include <folly/portability/OpenSSL.h>
21 #include <openssl/evp.h>
22 #include <openssl/hmac.h>
23 #include <openssl/sha.h>
24
25 #include <folly/Range.h>
26 #include <folly/io/IOBuf.h>
27
28 namespace folly {
29 namespace ssl {
30
31 /// Warning:
32 /// These functions are not thread-safe unless you initialize OpenSSL.
33 class OpenSSLHash {
34  public:
35
36   class Digest {
37    public:
38     Digest() : ctx_(EVP_MD_CTX_new()) {}
39
40     void hash_init(const EVP_MD* md) {
41       md_ = md;
42       check_libssl_result(1, EVP_DigestInit_ex(ctx_.get(), md, nullptr));
43     }
44     void hash_update(ByteRange data) {
45       check_libssl_result(
46           1, EVP_DigestUpdate(ctx_.get(), data.data(), data.size()));
47     }
48     void hash_update(const IOBuf& data) {
49       for (auto r : data) {
50         hash_update(r);
51       }
52     }
53     void hash_final(MutableByteRange out) {
54       const auto size = EVP_MD_size(md_);
55       check_out_size(size_t(size), out);
56       unsigned int len = 0;
57       check_libssl_result(1, EVP_DigestFinal_ex(ctx_.get(), out.data(), &len));
58       check_libssl_result(size, int(len));
59       md_ = nullptr;
60     }
61    private:
62     const EVP_MD* md_ = nullptr;
63     EvpMdCtxUniquePtr ctx_{nullptr};
64   };
65
66   static void hash(
67       MutableByteRange out,
68       const EVP_MD* md,
69       ByteRange data) {
70     Digest hash;
71     hash.hash_init(md);
72     hash.hash_update(data);
73     hash.hash_final(out);
74   }
75   static void hash(
76       MutableByteRange out,
77       const EVP_MD* md,
78       const IOBuf& data) {
79     Digest hash;
80     hash.hash_init(md);
81     hash.hash_update(data);
82     hash.hash_final(out);
83   }
84   static void sha1(MutableByteRange out, ByteRange data) {
85     hash(out, EVP_sha1(), data);
86   }
87   static void sha1(MutableByteRange out, const IOBuf& data) {
88     hash(out, EVP_sha1(), data);
89   }
90   static void sha256(MutableByteRange out, ByteRange data) {
91     hash(out, EVP_sha256(), data);
92   }
93   static void sha256(MutableByteRange out, const IOBuf& data) {
94     hash(out, EVP_sha256(), data);
95   }
96
97   class Hmac {
98    public:
99     Hmac() : ctx_(HMAC_CTX_new()) {}
100
101     void hash_init(const EVP_MD* md, ByteRange key) {
102       md_ = md;
103       check_libssl_result(
104           1,
105           HMAC_Init_ex(ctx_.get(), key.data(), int(key.size()), md_, nullptr));
106     }
107     void hash_update(ByteRange data) {
108       check_libssl_result(1, HMAC_Update(ctx_.get(), data.data(), data.size()));
109     }
110     void hash_update(const IOBuf& data) {
111       for (auto r : data) {
112         hash_update(r);
113       }
114     }
115     void hash_final(MutableByteRange out) {
116       const auto size = EVP_MD_size(md_);
117       check_out_size(size_t(size), out);
118       unsigned int len = 0;
119       check_libssl_result(1, HMAC_Final(ctx_.get(), out.data(), &len));
120       check_libssl_result(size, int(len));
121       md_ = nullptr;
122     }
123    private:
124     const EVP_MD* md_ = nullptr;
125     HmacCtxUniquePtr ctx_{nullptr};
126   };
127
128   static void hmac(
129       MutableByteRange out,
130       const EVP_MD* md,
131       ByteRange key,
132       ByteRange data) {
133     Hmac hmac;
134     hmac.hash_init(md, key);
135     hmac.hash_update(data);
136     hmac.hash_final(out);
137   }
138   static void hmac(
139       MutableByteRange out,
140       const EVP_MD* md,
141       ByteRange key,
142       const IOBuf& data) {
143     Hmac hmac;
144     hmac.hash_init(md, key);
145     hmac.hash_update(data);
146     hmac.hash_final(out);
147   }
148   static void hmac_sha1(
149       MutableByteRange out, ByteRange key, ByteRange data) {
150     hmac(out, EVP_sha1(), key, data);
151   }
152   static void hmac_sha1(
153       MutableByteRange out, ByteRange key, const IOBuf& data) {
154     hmac(out, EVP_sha1(), key, data);
155   }
156   static void hmac_sha256(
157       MutableByteRange out, ByteRange key, ByteRange data) {
158     hmac(out, EVP_sha256(), key, data);
159   }
160   static void hmac_sha256(
161       MutableByteRange out, ByteRange key, const IOBuf& data) {
162     hmac(out, EVP_sha256(), key, data);
163   }
164
165  private:
166   static inline void check_out_size(size_t size, MutableByteRange out) {
167     if (LIKELY(size == out.size())) {
168       return;
169     }
170     check_out_size_throw(size, out);
171   }
172   [[noreturn]] static void check_out_size_throw(
173       size_t size,
174       MutableByteRange out);
175
176   static inline void check_libssl_result(int expected, int result) {
177     if (LIKELY(result == expected)) {
178       return;
179     }
180     check_libssl_result_throw();
181   }
182   [[noreturn]] static void check_libssl_result_throw();
183 };
184
185 }
186 }