]> WPIA git - cassiopeia.git/blob - src/crypto/sslUtil.cpp
cln: Move code around, cleanup structure
[cassiopeia.git] / src / crypto / sslUtil.cpp
1 #include "sslUtil.h"
2
3 #include <sys/types.h>
4 #include <termios.h>
5 #include <unistd.h>
6 #include <iostream>
7
8 std::shared_ptr<int> ssl_lib_ref(
9     new int( SSL_library_init() ),
10     []( int* ref ) {
11         delete ref;
12
13         EVP_cleanup();
14         CRYPTO_cleanup_all_ex_data();
15     } );
16
17 std::shared_ptr<X509> loadX509FromFile( std::string filename ) {
18     FILE* f = fopen( filename.c_str(), "r" );
19
20     if( !f ) {
21         return std::shared_ptr<X509>();
22     }
23
24     X509* key = PEM_read_X509( f, NULL, NULL, 0 );
25     fclose( f );
26
27     if( !key ) {
28         return std::shared_ptr<X509>();
29     }
30
31     return std::shared_ptr<X509>(
32         key,
33         []( X509 * ref ) {
34             X509_free( ref );
35         } );
36 }
37
38 std::shared_ptr<EVP_PKEY> loadPkeyFromFile( std::string filename ) {
39     FILE* f = fopen( filename.c_str(), "r" );
40
41     if( !f ) {
42         return std::shared_ptr<EVP_PKEY>();
43     }
44
45     EVP_PKEY* key = PEM_read_PrivateKey( f, NULL, NULL, 0 );
46     fclose( f );
47
48     if( !key ) {
49         return std::shared_ptr<EVP_PKEY>();
50     }
51
52     return std::shared_ptr<EVP_PKEY>(
53         key,
54         []( EVP_PKEY * ref ) {
55             EVP_PKEY_free( ref );
56         } );
57 }
58
59 int gencb( int a, int b, BN_GENCB* g ) {
60     ( void ) a;
61     ( void ) b;
62     ( void ) g;
63     std::cout << ( a == 0 ? "." : "+" ) << std::flush;
64     return 1;
65 }
66
67 static int verify_callback( int preverify_ok, X509_STORE_CTX* ctx ) {
68     if( !preverify_ok ) {
69         //auto cert = X509_STORE_CTX_get_current_cert(ctx);
70         //BIO *o = BIO_new_fp(stdout,BIO_NOCLOSE);
71         //X509_print_ex(o, cert, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
72         //BIO_free(o);
73
74         std::cout << "Verification failed: " << preverify_ok << " because " << X509_STORE_CTX_get_error( ctx ) << std::endl;
75     }
76
77     return preverify_ok;
78 }
79
80 static std::shared_ptr<DH> dh_param;
81
82 std::shared_ptr<SSL_CTX> generateSSLContext( bool server ) {
83     std::shared_ptr<SSL_CTX> ctx = std::shared_ptr<SSL_CTX>( SSL_CTX_new( TLSv1_2_method() ), []( SSL_CTX * p ) {
84         SSL_CTX_free( p );
85     } );
86
87     if( !SSL_CTX_set_cipher_list( ctx.get(), "HIGH:+CAMELLIA256:!eNull:!aNULL:!ADH:!MD5:-RSA+AES+SHA1:!RC4:!DES:!3DES:!SEED:!EXP:!AES128:!CAMELLIA128" ) ) {
88         throw "Cannot set cipher list. Your source is broken.";
89     }
90
91     SSL_CTX_set_verify( ctx.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback );
92     SSL_CTX_use_certificate_file( ctx.get(), server ? "keys/signer_server.crt" : "keys/signer_client.crt", SSL_FILETYPE_PEM );
93     SSL_CTX_use_PrivateKey_file( ctx.get(), server ? "keys/signer_server.key" : "keys/signer_client.key", SSL_FILETYPE_PEM );
94     SSL_CTX_load_verify_locations( ctx.get(), "keys/ca.crt", 0 );
95
96     if( server ) {
97         STACK_OF( X509_NAME ) *names = SSL_load_client_CA_file( "keys/env.crt" );
98
99         if( names ) {
100             SSL_CTX_set_client_CA_list( ctx.get(), names );
101         } else {
102             // error
103         }
104
105         if( !dh_param ) {
106             FILE* paramfile = fopen( "dh_param.pem", "r" );
107
108             if( paramfile ) {
109                 dh_param = std::shared_ptr<DH>( PEM_read_DHparams( paramfile, NULL, NULL, NULL ), DH_free );
110                 fclose( paramfile );
111             } else {
112                 dh_param = std::shared_ptr<DH>( DH_new(), DH_free );
113                 std::cout << "Generating DH params" << std::endl;
114                 BN_GENCB cb;
115                 cb.ver = 2;
116                 cb.arg = 0;
117                 cb.cb.cb_2 = gencb;
118
119                 if( !DH_generate_parameters_ex( dh_param.get(), 2048, 5, &cb ) ) {
120                     throw "DH generation failed";
121                 }
122
123                 std::cout << std::endl;
124                 paramfile = fopen( "dh_param.pem", "w" );
125
126                 if( paramfile ) {
127                     PEM_write_DHparams( paramfile, dh_param.get() );
128                     fclose( paramfile );
129                 }
130             }
131         }
132
133         if( !SSL_CTX_set_tmp_dh( ctx.get(), dh_param.get() ) ) {
134             throw "Cannot set tmp dh.";
135         }
136     }
137
138     return ctx;
139 }
140
141 void setupSerial( FILE* f ) {
142     struct termios attr;
143
144     if( tcgetattr( fileno( f ), &attr ) ) {
145         throw "failed to get attrs";
146     }
147
148     attr.c_iflag &= ~( IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON );
149     attr.c_oflag &= ~OPOST;
150     attr.c_lflag &= ~( ECHO | ECHONL | ICANON | ISIG | IEXTEN );
151     attr.c_cflag &= ~( CSIZE | PARENB );
152     attr.c_cflag |= CS8;
153
154     cfsetispeed( &attr, B115200 );
155     cfsetospeed( &attr, B115200 );
156
157     if( tcsetattr( fileno( f ), TCSANOW, &attr ) ) {
158         throw "failed to get attrs";
159     }
160 }
161
162 std::shared_ptr<BIO> openSerial( const std::string name ) {
163     FILE* f = fopen( name.c_str(), "r+" );
164
165     if( !f ) {
166         std::cout << "Opening serial device failed" << std::endl;
167         return std::shared_ptr<BIO>();
168     }
169
170     setupSerial( f );
171
172     std::shared_ptr<BIO> b( BIO_new_fd( fileno( f ), 0 ), BIO_free );
173     return b;
174 }
175
176 CAConfig::CAConfig( std::string name ) {
177     this->name = name;
178     this->path = "ca/" + name;
179     ca = loadX509FromFile( path + "/ca.crt" );
180     caKey = loadPkeyFromFile( path + "/ca.key" );
181 }