Francois Berder / TLS_axTLS

Dependents:   TLS_axTLS-Example HTTPSClientExample

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers CertificateManager.cpp Source File

CertificateManager.cpp

00001 #include "CertificateManager.h"
00002 #include "axTLS/crypto/bigint.h"
00003 #include "cert_manager.h"
00004 #include "axTLS/ssl/crypto_misc.h "
00005 
00006 CertificateManager::CertificateManager():
00007     files(),
00008     certs(NULL),
00009     precomputedCerts()
00010 {
00011 }
00012 
00013 CertificateManager::~CertificateManager()
00014 {
00015     clear();
00016 }
00017 
00018 CertificateManager& CertificateManager::instance()
00019 {
00020     static CertificateManager cm;
00021     return cm;
00022 }
00023 
00024 void CertificateManager::add(const char *fileName)
00025 {
00026     CertificateManager::instance().files.push_back(fileName);
00027 }
00028 
00029 bool CertificateManager::load(bool precompute)
00030 {
00031     if(precompute)
00032         return CertificateManager::instance().loadPrecomputeCertificates();
00033     else
00034         return CertificateManager::instance().loadCertificates();
00035 }
00036 
00037 bool CertificateManager::loadCertificates()
00038 {
00039     X509_CTX *cert = certs;
00040     for(std::list<std::string>::iterator itor = files.begin();
00041             itor != files.end();
00042             ++itor) {
00043         FILE *fp = fopen(itor->c_str(), "r");
00044         if(fp == NULL)
00045             return false;
00046 
00047         fseek(fp, 0, SEEK_END);
00048         int length = ftell(fp);
00049         fseek(fp, 0, SEEK_SET);
00050         uint8_t *data = new uint8_t[length];
00051         fread(data, sizeof(uint8_t), length, fp);
00052         fclose(fp);
00053 
00054         if(x509_new(data, NULL, &cert) != 0) {
00055             x509_free(certs);
00056             delete[] data;
00057             return false;
00058         }
00059 
00060         delete[] data;
00061         cert = cert->next;
00062     }
00063     files.clear();
00064     return true;
00065 }
00066 
00067 /* Check cert1 with cert2
00068 */
00069 bool CertificateManager::check(X509_CTX *cert1, X509_CTX* cert2)
00070 {
00071     if(asn1_compare_dn(cert1->ca_cert_dn, cert2->cert_dn))
00072         return false;
00073     if (time(NULL) < cert1->not_before)
00074         return false;
00075     if (time(NULL) > cert1->not_after)
00076         return false;
00077 
00078     /* Cannot check : takes too much memory
00079     BI_CTX *ctx = cert2->rsa_ctx->bi_ctx;
00080     bigint *mod = bi_clone(ctx, cert2->rsa_ctx->m);
00081     bigint *expn = bi_clone(ctx , cert2->rsa_ctx->e);
00082     bigint *digest = sig_verify(ctx, cert1->signature, cert1->sig_len, mod, expn);
00083     if(digest && cert1->digest)
00084     {
00085         if(bi_compare(digest, cert1->digest) != 0)
00086         {
00087             bi_free(ctx, digest);
00088             return false;
00089         }
00090         bi_free(ctx, digest);
00091     }
00092     else
00093         return false;
00094     */
00095     return true;
00096 }
00097 
00098 bool CertificateManager::loadPrecomputeCertificates()
00099 {
00100     if(files.size() < 2)
00101         return false;
00102     precomputedCerts.reserve(files.size()-1);
00103     X509_CTX *cert1 = NULL, *cert2 = NULL;
00104 
00105     // load cert1
00106     FILE *fp = fopen(files.front().c_str(), "r");
00107     if(fp == NULL) {
00108         printf("Could not open file %s\n", files.front().c_str());
00109         clear();
00110         return false;
00111     }
00112     files.pop_front();
00113 
00114     fseek(fp, 0, SEEK_END);
00115     int length = ftell(fp);
00116     fseek(fp, 0, SEEK_SET);
00117     uint8_t *data = new uint8_t[length];
00118     fread(data, sizeof(uint8_t), length, fp);
00119     fclose(fp);
00120 
00121     if(x509_new(data, NULL, &cert1) != 0) {
00122         delete[] data;
00123         clear();
00124         return false;
00125     }
00126     delete[] data;
00127 
00128     while(!files.empty()) {
00129         // load cert2
00130         fp = fopen(files.front().c_str(), "r");
00131         if(fp == NULL) {
00132             printf("Could not open file %s\n", files.front().c_str());
00133             x509_free(cert1);
00134             clear();
00135             return false;
00136         }
00137         files.pop_front();
00138 
00139         fseek(fp, 0, SEEK_END);
00140         length = ftell(fp);
00141         fseek(fp, 0, SEEK_SET);
00142         data = new uint8_t[length];
00143         fread(data, sizeof(uint8_t), length, fp);
00144         fclose(fp);
00145 
00146         if(x509_new(data, NULL, &cert2) != 0) {
00147             x509_free(cert1);
00148             delete[] data;
00149             clear();
00150             return false;
00151         }
00152         delete[] data;
00153 
00154 
00155         if(!check(cert1, cert2)) {
00156             printf("Certificates verification failed\n");
00157             x509_free(cert1);
00158             x509_free(cert2);
00159             clear();
00160             return false;
00161         }
00162 
00163 
00164         // Create certificate
00165         PrecomputedCertificate pc;
00166         memset(&pc, 0, sizeof(PrecomputedCertificate));
00167         for(int i = 0; i < X509_NUM_DN_TYPES; ++i) {
00168             if(cert1->ca_cert_dn[i] != NULL) {
00169                 pc.ca_cert_dn[i] = new char[strlen(cert1->ca_cert_dn[i])+1];
00170                 strcpy(pc.ca_cert_dn[i], cert1->ca_cert_dn[i]);
00171             }
00172             if(cert1->cert_dn[i] != NULL) {
00173                 pc.cert_dn[i] = new char[strlen(cert1->cert_dn[i])+1];
00174                 strcpy(pc.cert_dn[i], cert1->cert_dn[i]);
00175             }
00176         }
00177 
00178         uint8_t buffer[512];
00179         uint16_t paddingLength;
00180         bi_permanent(cert1->digest);
00181         bi_export(cert1->rsa_ctx->bi_ctx, cert1->digest, buffer, 512);
00182         bi_depermanent(cert1->digest);
00183 
00184         paddingLength = 0;
00185         while(buffer[paddingLength] == 0 && paddingLength < 512) paddingLength++;
00186         pc.digest_len = 512 - paddingLength;
00187         pc.digest = new uint8_t[pc.digest_len];
00188         memcpy(pc.digest, &buffer[paddingLength], pc.digest_len);
00189 
00190         bi_export(cert2->rsa_ctx->bi_ctx, cert2->rsa_ctx->m, buffer, 512);
00191 
00192         paddingLength = 0;
00193         while(buffer[paddingLength] == 0) paddingLength++;
00194         pc.mod_len = 512 - paddingLength;
00195         pc.mod = new uint8_t[pc.mod_len];
00196         memcpy(pc.mod, &buffer[paddingLength], pc.mod_len);
00197 
00198 
00199         bi_export(cert2->rsa_ctx->bi_ctx, cert2->rsa_ctx->e, buffer, 512);
00200         paddingLength = 0;
00201         while(buffer[paddingLength] == 0) paddingLength++;
00202         pc.expn_len = 512 - paddingLength;
00203         pc.expn = new uint8_t[pc.expn_len];
00204         memcpy(pc.expn, &buffer[paddingLength], pc.expn_len);
00205 
00206         pc.sig = new uint8_t[cert1->sig_len];
00207         pc.sig_len = cert1->sig_len;
00208         memcpy(pc.sig, cert1->signature, pc.sig_len);
00209 
00210 
00211         precomputedCerts.push_back(pc);
00212 
00213         x509_free(cert1);
00214         cert1 = cert2;
00215     }
00216     x509_free(cert2);
00217     certs = NULL;
00218     return true;
00219 }
00220 
00221 void CertificateManager::clear()
00222 {
00223     CertificateManager &cm = CertificateManager::instance();
00224     cm.files.clear();
00225     x509_free(cm.certs);
00226     cm.certs = NULL;
00227     for(int i = 0; i < cm.precomputedCerts.size(); ++i) {
00228         for(int j = 0; j < X509_NUM_DN_TYPES; ++j) {
00229             delete cm.precomputedCerts[i].cert_dn[j];
00230             delete cm.precomputedCerts[i].ca_cert_dn[j];
00231         }
00232 
00233         delete[] cm.precomputedCerts[i].sig;
00234         delete[] cm.precomputedCerts[i].mod;
00235         delete[] cm.precomputedCerts[i].expn;
00236         delete[] cm.precomputedCerts[i].digest;
00237     }
00238     cm.precomputedCerts.clear();
00239 }
00240 
00241 extern "C" char is_precomputed(void)
00242 {
00243     return CertificateManager::instance().precomputedCerts.size() > 0 ? 1 : 0;
00244 }
00245 
00246 extern "C" PrecomputedCertificate get_precomputed_cert(char *cert_dn[], char *ca_cert_dn[])
00247 {
00248     std::vector<PrecomputedCertificate> &precomputedCerts = CertificateManager::instance().precomputedCerts;
00249 
00250     for(int i = 0; i < precomputedCerts.size(); ++i) {
00251 
00252         PrecomputedCertificate pc = precomputedCerts[i];
00253         int j = 0;
00254         for(; j < X509_NUM_DN_TYPES; ++j) {
00255 
00256             if( (cert_dn[j] == NULL && pc.cert_dn[j] != NULL)
00257                     ||  (cert_dn[j] != NULL && pc.cert_dn[j] == NULL)
00258                     ||  (ca_cert_dn[j] == NULL && pc.ca_cert_dn[j] != NULL)
00259                     ||  (ca_cert_dn[j] != NULL && pc.ca_cert_dn[j] == NULL))
00260                 break;
00261 
00262             if(cert_dn[j] && pc.cert_dn[j]) {
00263                 if(strcmp(cert_dn[j], pc.cert_dn[j]))
00264                     break;
00265             }
00266 
00267             if(ca_cert_dn[j] && pc.ca_cert_dn[j]) {
00268                 if(strcmp(ca_cert_dn[j], pc.ca_cert_dn[j]))
00269                     break;
00270             }
00271         }
00272         if(j == X509_NUM_DN_TYPES)
00273             return pc;
00274     }
00275 
00276     PrecomputedCertificate pc;
00277     memset(&pc, 0, sizeof(PrecomputedCertificate));
00278     return pc;
00279 }
00280 
00281 
00282 extern "C" X509_CTX* get_cert(char *ca_cert_dn[])
00283 {
00284     X509_CTX *cert = CertificateManager::instance().certs;
00285 
00286     while(1) {
00287         if(cert == NULL)
00288             return NULL;
00289         int i = 0;
00290         for(; i < X509_NUM_DN_TYPES; ++i) {
00291             if(strcmp(ca_cert_dn[i], cert->cert_dn[i]))
00292                 break;
00293         }
00294         if(i == X509_NUM_DN_TYPES)
00295             return cert;
00296         cert = cert->next;
00297     }
00298 }
00299 
00300 
00301 extern "C" void cert_manager_clear(void)
00302 {
00303     CertificateManager::clear();
00304 }
00305 
00306 
00307