]> WPIA git - cassiopeia.git/blob - src/crypto/CRL.cpp
fix: resource (fd) leak in CRL class
[cassiopeia.git] / src / crypto / CRL.cpp
1 #include "CRL.h"
2
3 #include <openssl/ssl.h>
4 #include <log/logger.hpp>
5
6 CRL::CRL( std::string path ) {
7     std::shared_ptr<BIO> bio( BIO_new_file( path.c_str(), "r" ), BIO_free );
8     crl = std::shared_ptr<X509_CRL>( PEM_read_bio_X509_CRL( bio.get(), 0, NULL, 0 ), X509_CRL_free );
9
10     if( !crl ) {
11         crl = std::shared_ptr<X509_CRL>( X509_CRL_new(), X509_CRL_free );
12     }
13 }
14
15 std::string CRL::revoke( std::string serial, std::string time ) {
16     BIGNUM* serBN = 0;
17
18     logger::note("parsing serial");
19     if( ! BN_hex2bn( &serBN, serial.c_str() ) ) {
20         throw "hex2bn malloc fail";
21     }
22
23     std::shared_ptr<BIGNUM> serBNP( serBN, BN_free );
24     std::shared_ptr<ASN1_INTEGER> ser( BN_to_ASN1_INTEGER( serBN, NULL ), ASN1_INTEGER_free );
25
26     if( !ser ) {
27         throw "BN Malloc fail";
28     }
29
30     logger::note("building current time");
31     std::shared_ptr<ASN1_TIME> tmptm( ASN1_TIME_new(), ASN1_TIME_free );
32
33     if( !tmptm ) {
34         throw "ASN1-Time Malloc fail";
35     }
36
37     X509_gmtime_adj( tmptm.get(), 0 );
38
39     logger::note("creating entry");
40     X509_REVOKED* rev = X509_REVOKED_new();
41     X509_REVOKED_set_serialNumber( rev, ser.get() );
42
43     if( time != "" ) {
44         const unsigned char* data = ( unsigned char* )( time.data() );
45         d2i_ASN1_TIME( &rev->revocationDate, &data, time.size() );
46     } else {
47         X509_REVOKED_set_revocationDate( rev, tmptm.get() );
48     }
49
50     X509_CRL_add0_revoked( crl.get(), rev );
51
52     int len = i2d_ASN1_TIME( tmptm.get(), NULL );
53     unsigned char* buffer = ( unsigned char* ) OPENSSL_malloc( len );
54     unsigned char* pos = buffer;
55     i2d_ASN1_TIME( tmptm.get(), &pos );
56     std::string rettime = std::string( ( char* ) buffer, len );
57     OPENSSL_free( buffer );
58     return rettime;
59 }
60
61 void CRL::sign( std::shared_ptr<CAConfig> ca ) {
62     // Updating necessary CRL props
63     std::shared_ptr<ASN1_TIME> tmptm( ASN1_TIME_new(), ASN1_TIME_free );
64
65     if( !tmptm ) {
66         throw "ASN1-Time Malloc fail";
67     }
68
69     X509_gmtime_adj( tmptm.get(), 0 );
70
71     logger::note("setting issuer");
72     if( !X509_CRL_set_issuer_name( crl.get(), X509_get_subject_name( ca->ca.get() ) ) ) {
73         throw "Setting issuer failed";
74     }
75
76     logger::note("setting update");
77     X509_CRL_set_lastUpdate( crl.get(), tmptm.get() );
78
79     if( !X509_time_adj_ex( tmptm.get(), 1, 10, NULL ) ) {
80         throw "Updating time failed";
81     }
82
83     logger::note("setting next update");
84     X509_CRL_set_nextUpdate( crl.get(), tmptm.get() );
85
86     logger::note("sorting");
87     // Sorting and signing
88     X509_CRL_sort( crl.get() );
89     logger::note("signing");
90     X509_CRL_sign( crl.get(), ca->caKey.get(), EVP_sha256() );
91 }
92
93 bool CRL::verify( std::shared_ptr<CAConfig> ca ) {
94     std::shared_ptr<EVP_PKEY> pk( X509_get_pubkey( ca->ca.get() ), EVP_PKEY_free );
95     return X509_CRL_verify( crl.get(), pk.get() ) > 0;
96 }
97
98 std::string CRL::toString() {
99     // Write out the new CRL
100     std::shared_ptr<BIO> mem( BIO_new( BIO_s_mem() ), BIO_free );
101     PEM_write_bio_X509_CRL( mem.get(), crl.get() );
102     BUF_MEM* bptr;
103     BIO_get_mem_ptr( mem.get(), &bptr );
104     std::string newCRL( bptr->data, bptr->length );
105     return newCRL;
106 }
107
108 std::string CRL::getSignature() {
109     int len = i2d_X509_ALGOR( crl->sig_alg, NULL );
110     len += i2d_ASN1_BIT_STRING( crl->signature, NULL );
111     len += i2d_ASN1_TIME( crl->crl->lastUpdate, NULL );
112     len += i2d_ASN1_TIME( crl->crl->nextUpdate, NULL );
113
114     unsigned char* buffer = ( unsigned char* ) OPENSSL_malloc( len );
115     unsigned char* pos = buffer;
116     i2d_X509_ALGOR( crl->sig_alg, &pos );
117     i2d_ASN1_BIT_STRING( crl->signature, &pos );
118     i2d_ASN1_TIME( crl->crl->lastUpdate, &pos );
119     i2d_ASN1_TIME( crl->crl->nextUpdate, &pos );
120     std::string res = std::string( ( char* ) buffer, len );
121     OPENSSL_free( buffer );
122
123     return res;
124 }
125
126 void CRL::setSignature( std::string signature ) {
127     X509_CRL_sort( crl.get() );
128     const unsigned char* data = ( unsigned char* )( signature.data() );
129     const unsigned char* buffer = data;
130     d2i_X509_ALGOR( &crl->sig_alg, &buffer, signature.size() );
131     d2i_ASN1_BIT_STRING( &crl->signature, &buffer, signature.size() + data - buffer );
132     d2i_ASN1_TIME( &crl->crl->lastUpdate, &buffer, signature.size() + data - buffer );
133     d2i_ASN1_TIME( &crl->crl->nextUpdate, &buffer, signature.size() + data - buffer );
134 }
135
136 bool CRL::needsResign() {
137     time_t current;
138     time( &current );
139     current += 60 * 60;// 1 hour
140     auto time = X509_CRL_get_nextUpdate( crl.get() );
141
142     if( !time ) {
143         return true;
144     }
145
146     int cmp =  X509_cmp_time( time, &current );
147     return cmp < 0;
148 }