Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / ot-br-posix / repo / third_party / Simple-web-server / repo / crypto.hpp
1 #ifndef CRYPTO_HPP
2 #define CRYPTO_HPP
3
4 #include <string>
5 #include <cmath>
6 #include <sstream>
7 #include <iomanip>
8 #include <istream>
9 #include <vector>
10
11 //Moving these to a seperate namespace for minimal global namespace cluttering does not work with clang++
12 #include <openssl/evp.h>
13 #include <openssl/buffer.h>
14 #include <openssl/sha.h>
15 #include <openssl/md5.h>
16
17 namespace SimpleWeb {
18     //TODO 2017: remove workaround for MSVS 2012
19     #if _MSC_VER == 1700 //MSVS 2012 has no definition for round()
20         inline double round(double x) { //custom definition of round() for positive numbers
21             return floor(x + 0.5);
22         }
23     #endif
24
25     class Crypto {
26         const static size_t buffer_size=131072;
27     public:
28         class Base64 {
29         public:
30             static std::string encode(const std::string &ascii) {
31                 std::string base64;
32                 
33                 BIO *bio, *b64;
34                 BUF_MEM *bptr=BUF_MEM_new();
35
36                 b64 = BIO_new(BIO_f_base64());
37                 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
38                 bio = BIO_new(BIO_s_mem());
39                 BIO_push(b64, bio);
40                 BIO_set_mem_buf(b64, bptr, BIO_CLOSE);
41                 
42                 //Write directly to base64-buffer to avoid copy
43                 int base64_length=static_cast<int>(round(4*ceil((double)ascii.size()/3.0)));
44                 base64.resize(base64_length);
45                 bptr->length=0;
46                 bptr->max=base64_length+1;
47                 bptr->data=(char*)&base64[0];
48
49                 BIO_write(b64, &ascii[0], static_cast<int>(ascii.size()));
50                 BIO_flush(b64);
51
52                 //To keep &base64[0] through BIO_free_all(b64)
53                 bptr->length=0;
54                 bptr->max=0;
55                 bptr->data=nullptr;
56
57                 BIO_free_all(b64);
58                 
59                 return base64;
60             }
61             
62             static std::string decode(const std::string &base64) {
63                 std::string ascii;
64                 
65                 //Resize ascii, however, the size is a up to two bytes too large.
66                 ascii.resize((6*base64.size())/8);
67                 BIO *b64, *bio;
68
69                 b64 = BIO_new(BIO_f_base64());
70                 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
71                 bio = BIO_new_mem_buf((char*)&base64[0], static_cast<int>(base64.size()));
72                 bio = BIO_push(b64, bio);
73
74                 int decoded_length = BIO_read(bio, &ascii[0], static_cast<int>(ascii.size()));
75                 ascii.resize(decoded_length);
76
77                 BIO_free_all(b64);
78                 
79                 return ascii;
80             }
81         };
82         
83         /// Return hex string from bytes in input string.
84         static std::string to_hex_string(const std::string &input) {
85           std::stringstream hex_stream;
86           hex_stream << std::hex << std::internal << std::setfill('0');
87           for (auto &byte : input)
88             hex_stream << std::setw(2) << static_cast<int>(static_cast<unsigned char>(byte));
89           return hex_stream.str();
90         }
91         
92         static std::string md5(const std::string &input, size_t iterations=1) {
93             std::string hash;
94             
95             hash.resize(128 / 8);
96             MD5(reinterpret_cast<const unsigned char*>(&input[0]), input.size(), reinterpret_cast<unsigned char*>(&hash[0]));
97             
98             for (size_t c = 1; c < iterations; ++c)
99               MD5(reinterpret_cast<const unsigned char*>(&hash[0]), hash.size(), reinterpret_cast<unsigned char*>(&hash[0]));
100             
101             return hash;
102         }
103         
104         static std::string md5(std::istream &stream, size_t iterations=1) {
105             MD5_CTX context;
106             MD5_Init(&context);
107             std::streamsize read_length;
108             std::vector<char> buffer(buffer_size);
109             while((read_length=stream.read(&buffer[0], buffer_size).gcount())>0)
110                 MD5_Update(&context, buffer.data(), read_length);
111             std::string hash;
112             hash.resize(128 / 8);
113             MD5_Final(reinterpret_cast<unsigned char*>(&hash[0]), &context);
114             
115             for (size_t c = 1; c < iterations; ++c)
116               MD5(reinterpret_cast<const unsigned char*>(&hash[0]), hash.size(), reinterpret_cast<unsigned char*>(&hash[0]));
117             
118             return hash;
119         }
120
121         static std::string sha1(const std::string &input, size_t iterations=1) {
122             std::string hash;
123             
124             hash.resize(160 / 8);
125             SHA1(reinterpret_cast<const unsigned char*>(&input[0]), input.size(), reinterpret_cast<unsigned char*>(&hash[0]));
126             
127             for (size_t c = 1; c < iterations; ++c)
128               SHA1(reinterpret_cast<const unsigned char*>(&hash[0]), hash.size(), reinterpret_cast<unsigned char*>(&hash[0]));
129             
130             return hash;
131         }
132         
133         static std::string sha1(std::istream &stream, size_t iterations=1) {
134             SHA_CTX context;
135             SHA1_Init(&context);
136             std::streamsize read_length;
137             std::vector<char> buffer(buffer_size);
138             while((read_length=stream.read(&buffer[0], buffer_size).gcount())>0)
139                 SHA1_Update(&context, buffer.data(), read_length);
140             std::string hash;
141             hash.resize(160 / 8);
142             SHA1_Final(reinterpret_cast<unsigned char*>(&hash[0]), &context);
143             
144             for (size_t c = 1; c < iterations; ++c)
145               SHA1(reinterpret_cast<const unsigned char*>(&hash[0]), hash.size(), reinterpret_cast<unsigned char*>(&hash[0]));
146             
147             return hash;
148         }
149
150         static std::string sha256(const std::string &input, size_t iterations=1) {
151             std::string hash;
152             
153             hash.resize(256 / 8);
154             SHA256(reinterpret_cast<const unsigned char*>(&input[0]), input.size(), reinterpret_cast<unsigned char*>(&hash[0]));
155             
156             for (size_t c = 1; c < iterations; ++c)
157               SHA256(reinterpret_cast<const unsigned char*>(&hash[0]), hash.size(), reinterpret_cast<unsigned char*>(&hash[0]));
158             
159             return hash;
160         }
161         
162         static std::string sha256(std::istream &stream, size_t iterations=1) {
163             SHA256_CTX context;
164             SHA256_Init(&context);
165             std::streamsize read_length;
166             std::vector<char> buffer(buffer_size);
167             while((read_length=stream.read(&buffer[0], buffer_size).gcount())>0)
168                 SHA256_Update(&context, buffer.data(), read_length);
169             std::string hash;
170             hash.resize(256 / 8);
171             SHA256_Final(reinterpret_cast<unsigned char*>(&hash[0]), &context);
172             
173             for (size_t c = 1; c < iterations; ++c)
174               SHA256(reinterpret_cast<const unsigned char*>(&hash[0]), hash.size(), reinterpret_cast<unsigned char*>(&hash[0]));
175             
176             return hash;
177         }
178
179         static std::string sha512(const std::string &input, size_t iterations=1) {
180             std::string hash;
181             
182             hash.resize(512 / 8);
183             SHA512(reinterpret_cast<const unsigned char*>(&input[0]), input.size(), reinterpret_cast<unsigned char*>(&hash[0]));
184             
185             for (size_t c = 1; c < iterations; ++c)
186               SHA512(reinterpret_cast<const unsigned char*>(&hash[0]), hash.size(), reinterpret_cast<unsigned char*>(&hash[0]));
187             
188             return hash;
189         }
190         
191         static std::string sha512(std::istream &stream, size_t iterations=1) {
192             SHA512_CTX context;
193             SHA512_Init(&context);
194             std::streamsize read_length;
195             std::vector<char> buffer(buffer_size);
196             while((read_length=stream.read(&buffer[0], buffer_size).gcount())>0)
197                 SHA512_Update(&context, buffer.data(), read_length);
198             std::string hash;
199             hash.resize(512 / 8);
200             SHA512_Final(reinterpret_cast<unsigned char*>(&hash[0]), &context);
201             
202             for (size_t c = 1; c < iterations; ++c)
203               SHA512(reinterpret_cast<const unsigned char*>(&hash[0]), hash.size(), reinterpret_cast<unsigned char*>(&hash[0]));
204             
205             return hash;
206         }
207         
208         /// key_size is number of bytes of the returned key.
209         static std::string pbkdf2(const std::string &password, const std::string &salt, int iterations, int key_size) {
210           std::string key;
211           key.resize(key_size);
212           PKCS5_PBKDF2_HMAC_SHA1(password.c_str(), password.size(),
213                                  reinterpret_cast<const unsigned char*>(salt.c_str()), salt.size(), iterations,
214                                  key_size, reinterpret_cast<unsigned char*>(&key[0]));
215           return key;
216         }
217     };
218 }
219 #endif  /* CRYPTO_HPP */
220