1 /*
2  * Copyright 2012, 2014 Andrew Ayer
3  *
4  * This file is part of git-crypt.
5  *
6  * git-crypt is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * git-crypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with git-crypt.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  * Additional permission under GNU GPL version 3 section 7:
20  *
21  * If you modify the Program, or any covered work, by linking or
22  * combining it with the OpenSSL project's OpenSSL library (or a
23  * modified version of that library), containing parts covered by the
24  * terms of the OpenSSL or SSLeay licenses, the licensors of the Program
25  * grant you additional permission to convey the resulting work.
26  * Corresponding Source for a non-source form of such a combination
27  * shall include the source code for the parts of OpenSSL used as well
28  * as that of the covered work.
29  */
30 
31 #include <openssl/opensslconf.h>
32 
33 #if !defined(OPENSSL_API_COMPAT)
34 
35 #include "crypto.hpp"
36 #include "key.hpp"
37 #include "util.hpp"
38 #include <openssl/aes.h>
39 #include <openssl/sha.h>
40 #include <openssl/hmac.h>
41 #include <openssl/evp.h>
42 #include <openssl/rand.h>
43 #include <openssl/err.h>
44 #include <sstream>
45 #include <cstring>
46 
init_crypto()47 void init_crypto ()
48 {
49 	ERR_load_crypto_strings();
50 }
51 
52 struct Aes_ecb_encryptor::Aes_impl {
53 	AES_KEY key;
54 };
55 
Aes_ecb_encryptor(const unsigned char * raw_key)56 Aes_ecb_encryptor::Aes_ecb_encryptor (const unsigned char* raw_key)
57 : impl(new Aes_impl)
58 {
59 	if (AES_set_encrypt_key(raw_key, KEY_LEN * 8, &(impl->key)) != 0) {
60 		throw Crypto_error("Aes_ctr_encryptor::Aes_ctr_encryptor", "AES_set_encrypt_key failed");
61 	}
62 }
63 
~Aes_ecb_encryptor()64 Aes_ecb_encryptor::~Aes_ecb_encryptor ()
65 {
66 	// Note: Explicit destructor necessary because class contains an unique_ptr
67 	// which contains an incomplete type when the unique_ptr is declared.
68 
69 	explicit_memset(&impl->key, '\0', sizeof(impl->key));
70 }
71 
encrypt(const unsigned char * plain,unsigned char * cipher)72 void Aes_ecb_encryptor::encrypt(const unsigned char* plain, unsigned char* cipher)
73 {
74 	AES_encrypt(plain, cipher, &(impl->key));
75 }
76 
77 struct Hmac_sha1_state::Hmac_impl {
78 	HMAC_CTX ctx;
79 };
80 
Hmac_sha1_state(const unsigned char * key,size_t key_len)81 Hmac_sha1_state::Hmac_sha1_state (const unsigned char* key, size_t key_len)
82 : impl(new Hmac_impl)
83 {
84 	HMAC_Init(&(impl->ctx), key, key_len, EVP_sha1());
85 }
86 
~Hmac_sha1_state()87 Hmac_sha1_state::~Hmac_sha1_state ()
88 {
89 	// Note: Explicit destructor necessary because class contains an unique_ptr
90 	// which contains an incomplete type when the unique_ptr is declared.
91 
92 	HMAC_cleanup(&(impl->ctx));
93 }
94 
add(const unsigned char * buffer,size_t buffer_len)95 void Hmac_sha1_state::add (const unsigned char* buffer, size_t buffer_len)
96 {
97 	HMAC_Update(&(impl->ctx), buffer, buffer_len);
98 }
99 
get(unsigned char * digest)100 void Hmac_sha1_state::get (unsigned char* digest)
101 {
102 	unsigned int len;
103 	HMAC_Final(&(impl->ctx), digest, &len);
104 }
105 
106 
random_bytes(unsigned char * buffer,size_t len)107 void random_bytes (unsigned char* buffer, size_t len)
108 {
109 	if (RAND_bytes(buffer, len) != 1) {
110 		std::ostringstream	message;
111 		while (unsigned long code = ERR_get_error()) {
112 			char		error_string[120];
113 			ERR_error_string_n(code, error_string, sizeof(error_string));
114 			message << "OpenSSL Error: " << error_string << "; ";
115 		}
116 		throw Crypto_error("random_bytes", message.str());
117 	}
118 }
119 
120 #endif
121