]> WPIA git - cassiopeia.git/blob - src/crypto/CRL.cpp
fmt: run format script excluding lambdas
[cassiopeia.git] / src / crypto / CRL.cpp
1 #include "CRL.h"
2
3 #include <openssl/ssl.h>
4 #include <log/logger.hpp>
5 #include <exception>
6
7 CRL::CRL( std::string path ) {
8     std::shared_ptr<BIO> bio( BIO_new_file( path.c_str(), "r" ), BIO_free );
9     crl = std::shared_ptr<X509_CRL>( PEM_read_bio_X509_CRL( bio.get(), 0, NULL, 0 ), X509_CRL_free );
10
11     if( !crl ) {
12         crl = std::shared_ptr<X509_CRL>( X509_CRL_new(), X509_CRL_free );
13     }
14 }
15
16 std::string CRL::revoke( std::string serial, std::string time ) {
17     BIGNUM *serBN = 0;
18
19     logger::note( "parsing serial" );
20
21     if( ! BN_hex2bn( &serBN, serial.c_str() ) ) {
22         throw std::runtime_error( "hex2bn malloc fail" );
23     }
24
25     std::shared_ptr<BIGNUM> serBNP( serBN, BN_free );
26     std::shared_ptr<ASN1_INTEGER> ser( BN_to_ASN1_INTEGER( serBN, NULL ), ASN1_INTEGER_free );
27
28     if( !ser ) {
29         throw std::runtime_error( "BN Malloc fail" );
30     }
31
32     logger::note( "building current time" );
33     std::shared_ptr<ASN1_TIME> tmptm( ASN1_TIME_new(), ASN1_TIME_free );
34
35     if( !tmptm ) {
36         throw std::runtime_error( "ASN1-Time Malloc fail" );
37     }
38
39     X509_gmtime_adj( tmptm.get(), 0 );
40
41     logger::note( "creating entry" );
42     X509_REVOKED *rev = X509_REVOKED_new();
43     X509_REVOKED_set_serialNumber( rev, ser.get() );
44
45     if( time != "" ) {
46         ASN1_TIME_set_string( tmptm.get(), time.data() );
47     }
48
49     X509_REVOKED_set_revocationDate( rev, tmptm.get() );
50
51     X509_CRL_add0_revoked( crl.get(), rev );
52
53     int len = i2d_ASN1_TIME( tmptm.get(), NULL );
54     unsigned char *buffer = ( unsigned char * ) OPENSSL_malloc( len );
55     unsigned char *pos = buffer;
56     i2d_ASN1_TIME( tmptm.get(), &pos );
57     std::string rettime = std::string( ( char * ) buffer, len );
58     OPENSSL_free( buffer );
59     return rettime;
60 }
61
62 void CRL::sign( std::shared_ptr<CAConfig> ca ) {
63     if( !ca->caKey ) {
64         throw new std::invalid_argument( "Cannot sign CRL with CA " + ca->name + " because it has no private key." );
65     }
66
67     // Updating necessary CRL props
68     std::shared_ptr<ASN1_TIME> tmptm( ASN1_TIME_new(), ASN1_TIME_free );
69
70     if( !tmptm ) {
71         throw std::runtime_error( "ASN1-Time Malloc fail" );
72     }
73
74     X509_gmtime_adj( tmptm.get(), 0 );
75
76     logger::note( "setting issuer" );
77
78     if( !X509_CRL_set_issuer_name( crl.get(), X509_get_subject_name( ca->ca.get() ) ) ) {
79         throw std::runtime_error( "Setting issuer failed" );
80     }
81
82     logger::note( "setting update" );
83     X509_CRL_set_lastUpdate( crl.get(), tmptm.get() );
84
85     if( !X509_time_adj_ex( tmptm.get(), 1, 10, NULL ) ) {
86         throw std::runtime_error( "Updating time failed" );
87     }
88
89     logger::note( "setting next update" );
90     X509_CRL_set_nextUpdate( crl.get(), tmptm.get() );
91
92     logger::note( "sorting" );
93     // Sorting and signing
94     X509_CRL_sort( crl.get() );
95     logger::note( "signing" );
96     X509_CRL_sign( crl.get(), ca->caKey.get(), EVP_sha256() );
97 }
98
99 bool CRL::verify( std::shared_ptr<CAConfig> ca ) {
100     std::shared_ptr<EVP_PKEY> pk( X509_get_pubkey( ca->ca.get() ), EVP_PKEY_free );
101     return X509_CRL_verify( crl.get(), pk.get() ) > 0;
102 }
103
104 std::string CRL::toString() {
105     // Write out the new CRL
106     std::shared_ptr<BIO> mem( BIO_new( BIO_s_mem() ), BIO_free );
107     PEM_write_bio_X509_CRL( mem.get(), crl.get() );
108     BUF_MEM *bptr;
109     BIO_get_mem_ptr( mem.get(), &bptr );
110     std::string newCRL( bptr->data, bptr->length );
111     return newCRL;
112 }
113
114 std::string CRL::getSignature() {
115     const X509_ALGOR *palg;
116     const ASN1_BIT_STRING *psig;
117
118     X509_CRL_get0_signature( crl.get(), &psig, &palg );
119     int len = i2d_X509_ALGOR( const_cast<X509_ALGOR *>( palg ), NULL );
120     len += i2d_ASN1_BIT_STRING( const_cast<ASN1_BIT_STRING *>( psig ), NULL );
121     len += i2d_ASN1_TIME( const_cast<ASN1_TIME *>( X509_CRL_get0_lastUpdate( crl.get() ) ), NULL );
122     len += i2d_ASN1_TIME( const_cast<ASN1_TIME *>( X509_CRL_get0_nextUpdate( crl.get() ) ), NULL );
123
124     unsigned char *buffer = ( unsigned char * ) OPENSSL_malloc( len );
125     unsigned char *pos = buffer;
126     i2d_X509_ALGOR( const_cast<X509_ALGOR *>( palg ), &pos );
127     i2d_ASN1_BIT_STRING( const_cast<ASN1_BIT_STRING *>( psig ), &pos );
128     i2d_ASN1_TIME( const_cast<ASN1_TIME *>( X509_CRL_get0_lastUpdate( crl.get() ) ), &pos );
129     i2d_ASN1_TIME( const_cast<ASN1_TIME *>( X509_CRL_get0_nextUpdate( crl.get() ) ), &pos );
130     std::string res = std::string( ( char * ) buffer, len );
131     OPENSSL_free( buffer );
132
133     return res;
134 }
135
136 void CRL::setSignature( std::string signature ) {
137     X509_CRL_sort( crl.get() );
138     X509_ALGOR *palg;
139     ASN1_BIT_STRING *psig;
140     // this is not intended use of the OPENSSL-API but API-limitations leave us with no other options.
141     X509_CRL_get0_signature( crl.get(), const_cast<const ASN1_BIT_STRING **>( &psig ), const_cast<const X509_ALGOR **>( &palg ) );
142
143     const unsigned char *data = ( unsigned char * )( signature.data() );
144     const unsigned char *buffer = data;
145     X509_ALGOR *alg = d2i_X509_ALGOR( NULL, &buffer, signature.size() );
146     ASN1_BIT_STRING *sig = d2i_ASN1_BIT_STRING( NULL, &buffer, signature.size() + data - buffer );
147     ASN1_TIME *a1 = d2i_ASN1_TIME( NULL, &buffer, signature.size() + data - buffer );
148     ASN1_TIME *a2 = d2i_ASN1_TIME( NULL, &buffer, signature.size() + data - buffer );
149     std::swap( *palg, *alg );
150     std::swap( *psig, *sig );
151     X509_CRL_set1_lastUpdate( crl.get(), a1 );
152     X509_CRL_set1_nextUpdate( crl.get(), a2 );
153
154     X509_ALGOR_free( alg );
155     ASN1_BIT_STRING_free( sig );
156     ASN1_TIME_free( a1 );
157     ASN1_TIME_free( a2 );
158 }
159
160 bool CRL::needsResign() {
161     time_t current;
162     time( &current );
163     current += 60 * 60;// 1 hour
164     auto time = X509_CRL_get0_nextUpdate( crl.get() );
165
166     if( !time ) {
167         return true;
168     }
169
170     int cmp =  X509_cmp_time( time, &current );
171     return cmp < 0;
172 }