00001 #include "wvbase64.h"
00002 #include "wvsslhacks.h"
00003 #include "wvx509mgr.h"
00004 #include "wvautoconf.h"
00005
00006 #include <openssl/pem.h>
00007 #include <openssl/x509v3.h>
00008 #include <openssl/err.h>
00009 #include <openssl/ssl.h>
00010 #include <openssl/sha.h>
00011 #include <openssl/pkcs12.h>
00012
00013
00014 namespace {
00015 class AutoClose {
00016 public:
00017 AutoClose(FILE *fp): fp(fp) { }
00018 ~AutoClose()
00019 {
00020 if (fp)
00021 fclose(fp);
00022 }
00023
00024 operator FILE *() const
00025 {
00026 return fp;
00027 }
00028
00029 private:
00030 FILE *fp;
00031 };
00032 }
00033
00034
00035 WvX509Mgr::WvX509Mgr()
00036 : WvX509(),
00037 debug("X509 Manager", WvLog::Debug5)
00038 {
00039 rsa = NULL;
00040 }
00041
00042
00043 WvX509Mgr::WvX509Mgr(const WvX509Mgr &x)
00044 : WvX509(x),
00045 debug("X509 Manager", WvLog::Debug5)
00046 {
00047 rsa = NULL;
00048 set_rsa(x.rsa);
00049 }
00050
00051
00052 WvX509Mgr::WvX509Mgr(WvStringParm _dname, WvRSAKey *_rsa, bool ca)
00053 : WvX509(),
00054 debug("X509 Manager", WvLog::Debug5)
00055 {
00056 debug("Creating new certificate+key pair for %s.\n", _dname);
00057 rsa = _rsa;
00058
00059 if (!!_dname)
00060 {
00061 create_selfissued(_dname, ca);
00062 debug("Ok - Parameters set... now signing certificate.\n");
00063 signcert(*this);
00064 }
00065 else
00066 debug("Sorry, can't create an anonymous certificate.");
00067 }
00068
00069
00070 WvX509Mgr::WvX509Mgr(WvStringParm _dname, int bits, bool ca)
00071 : WvX509(),
00072 debug("X509 Manager", WvLog::Debug5)
00073 {
00074 debug("Creating new certificate+key pair for %s.\n", _dname);
00075 rsa = NULL;
00076
00077 if (!!_dname)
00078 {
00079 rsa = new WvRSAKey(bits);
00080 create_selfissued(_dname, ca);
00081 debug("Ok - Parameters set... now signing certificate.\n");
00082 signcert(*this);
00083 }
00084 else
00085 debug("Sorry, can't create an anonymous certificate.");
00086 }
00087
00088
00089 void WvX509Mgr::create_selfissued(WvStringParm dname, bool is_ca)
00090 {
00091 if (cert)
00092 {
00093 debug("Replacing already existant certificate...\n");
00094 X509_free(cert);
00095 cert = NULL;
00096 }
00097
00098
00099 if (rsa->isok())
00100 debug("RSA Key is fine.\n");
00101 else
00102 return;
00103
00104 if ((cert = X509_new()) == NULL)
00105 return;
00106
00107
00108
00109 set_version();
00110
00111
00112
00113
00114
00115 srand(time(NULL));
00116 int serial = rand();
00117 set_serial(serial);
00118
00119
00120 set_lifetime(60*60*24*3650);
00121
00122 set_pubkey(*rsa);
00123
00124 set_issuer(dname);
00125 set_subject(dname);
00126 set_ski();
00127
00128 if (is_ca)
00129 {
00130 debug("Setting Extensions with CA Parameters.\n");
00131 debug("Setting Key Usage.\n");
00132 set_key_usage("critical, keyCertSign, cRLSign");
00133 debug("Setting Basic Constraints.\n");
00134 set_extension(NID_basic_constraints, "critical, CA:TRUE");
00135 debug("Setting Netscape Certificate Type.\n");
00136 set_extension(NID_netscape_cert_type,
00137 "SSL CA, S/MIME CA, Object Signing CA");
00138 #if 0
00139
00140
00141
00142 set_ext_key_usage("OCSP Signing");
00143 #endif
00144
00145
00146 }
00147 else
00148 {
00149 debug("Setting Key Usage with normal server parameters\n");
00150 set_nsserver(dname);
00151 set_key_usage("critical, digitalSignature, keyEncipherment, "
00152 "keyAgreement");
00153 set_extension(NID_basic_constraints, "CA:FALSE");
00154 set_ext_key_usage("TLS Web Server Authentication,"
00155 "TLS Web Client Authentication");
00156 }
00157
00158
00159
00160
00161 debug("Certificate for %s created\n", dname);
00162 }
00163
00164
00165 WvX509Mgr::~WvX509Mgr()
00166 {
00167 debug("Deleting.\n");
00168 WVDELETE(rsa);
00169 }
00170
00171
00172 bool WvX509Mgr::isok() const
00173 {
00174 return WvX509::isok() && rsa && rsa->isok() && test();
00175 }
00176
00177
00178 bool WvX509Mgr::operator! () const
00179 {
00180 return !isok();
00181 }
00182
00183
00184 WvString WvX509Mgr::errstr() const
00185 {
00186 if (!WvX509::isok())
00187 return WvX509::errstr();
00188
00189 if (!rsa)
00190 return "No RSA key set.";
00191 else if (!rsa->isok())
00192 return "RSA key not valid.";
00193 else if (!test())
00194 return "RSA key and certificate do not match.";
00195
00196 return WvString::empty;
00197 }
00198
00199
00200 bool WvX509Mgr::bind_ssl(SSL_CTX *ctx)
00201 {
00202 if (SSL_CTX_use_certificate(ctx, get_cert()) <= 0)
00203 {
00204 return false;
00205 }
00206 debug("Certificate activated.\n");
00207
00208 if (SSL_CTX_use_RSAPrivateKey(ctx, rsa->rsa) <= 0)
00209 {
00210 return false;
00211 }
00212 debug("RSA private key activated.\n");
00213 return true;
00214 }
00215
00216
00217 bool WvX509Mgr::test() const
00218 {
00219 if (!cert)
00220 {
00221 debug("No X509 certificate: test fails.\n");
00222 return false;
00223 }
00224
00225 if (rsa)
00226 {
00227 EVP_PKEY *pk = EVP_PKEY_new();
00228 assert(pk);
00229
00230 if (!EVP_PKEY_set1_RSA(pk, rsa->rsa))
00231 {
00232 debug("Error setting RSA keys: test fails.\n");
00233 EVP_PKEY_free(pk);
00234 return false;
00235 }
00236
00237 bool bad = false;
00238 int verify_return = X509_verify(cert, pk);
00239
00240 if (verify_return != 1)
00241 {
00242
00243 WvString rsapub = rsa->encode(WvRSAKey::RsaPubPEM);
00244 WvRSAKey *temprsa = get_rsa_pub();
00245 WvString certpub = temprsa->encode(WvRSAKey::RsaPubPEM);
00246 delete temprsa;
00247
00248
00249 if (certpub == rsapub)
00250 ;
00251 else
00252 {
00253
00254 debug("Certificate test failed: %s\n", wvssl_errstr());
00255 bad = true;
00256 }
00257 }
00258
00259 EVP_PKEY_free(pk);
00260 return !bad;
00261 }
00262
00263 return false;
00264 }
00265
00266
00267 WvString WvX509Mgr::signreq(WvStringParm pkcs10req) const
00268 {
00269 debug("Signing a certificate request with: %s\n", get_subject());
00270 if (!isok())
00271 {
00272 debug(WvLog::Warning, "Asked to sign certificate request, but not ok! "
00273 "Aborting.\n");
00274 return false;
00275 }
00276
00277
00278
00279 WvString pkcs10(pkcs10req);
00280
00281 BIO *membuf = BIO_new(BIO_s_mem());
00282 BIO_write(membuf, pkcs10req, pkcs10req.len());
00283
00284 X509_REQ *certreq = PEM_read_bio_X509_REQ(membuf, NULL, NULL, NULL);
00285 BIO_free_all(membuf);
00286
00287 if (certreq)
00288 {
00289 WvX509 newcert(X509_new());
00290
00291 newcert.set_subject(X509_REQ_get_subject_name(certreq));
00292 newcert.set_version();
00293
00294
00295 srand(time(NULL));
00296 int serial = rand();
00297 newcert.set_serial(serial);
00298
00299 newcert.set_lifetime(60*60*24*3650);
00300
00301
00302
00303 EVP_PKEY *pk = X509_REQ_get_pubkey(certreq);
00304 X509_set_pubkey(newcert.get_cert(), pk);
00305 EVP_PKEY_free(pk);
00306
00307
00308 newcert.set_ski();
00309 newcert.set_aki(*this);
00310
00311
00312 newcert.set_issuer(*this);
00313
00314 X509_EXTENSION *ex = NULL;
00315
00316
00317 newcert.set_key_usage("critical, digitalSignature, keyEncipherment");
00318
00319
00320
00321
00322
00323 ex = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints,
00324 (char*)"CA:FALSE");
00325
00326 X509_add_ext(newcert.get_cert(), ex, -1);
00327 X509_EXTENSION_free(ex);
00328
00329 newcert.set_ext_key_usage("critical, TLS Web Client Authentication");
00330
00331 signcert(newcert);
00332
00333 X509_REQ_free(certreq);
00334 return WvString(newcert.encode(WvX509::CertPEM));
00335 }
00336 else
00337 {
00338 debug("Can't decode Certificate Request\n");
00339 return WvString::null;
00340 }
00341 }
00342
00343
00344 bool WvX509Mgr::signcert(WvX509 &unsignedcert) const
00345 {
00346 if (!isok())
00347 {
00348 debug(WvLog::Warning, "Asked to sign certificate, but not ok! "
00349 "Aborting.\n");
00350 return false;
00351 }
00352
00353 if (cert == unsignedcert.cert)
00354 {
00355 debug("Self Signing!\n");
00356 }
00357 #ifdef HAVE_OPENSSL_POLICY_MAPPING
00358 else if (!X509_check_ca(cert))
00359 {
00360 debug("This certificate is not a CA, and is thus not allowed to sign "
00361 "certificates!\n");
00362 return false;
00363 }
00364 #endif
00365 else if (!((cert->ex_flags & EXFLAG_KUSAGE) &&
00366 (cert->ex_kusage & KU_KEY_CERT_SIGN)))
00367 {
00368 debug("This Certificate is not allowed to sign certificates!\n");
00369 return false;
00370 }
00371
00372 debug("Ok, now sign the new cert with the current RSA key.\n");
00373 EVP_PKEY *certkey = EVP_PKEY_new();
00374 bool cakeyok = EVP_PKEY_set1_RSA(certkey, rsa->rsa);
00375 if (cakeyok)
00376 {
00377 X509_sign(unsignedcert.get_cert(), certkey, EVP_sha1());
00378 }
00379 else
00380 {
00381 debug("No keys??\n");
00382 EVP_PKEY_free(certkey);
00383 return false;
00384 }
00385
00386 EVP_PKEY_free(certkey);
00387 return true;
00388 }
00389
00390
00391 bool WvX509Mgr::signcrl(WvCRL &crl) const
00392 {
00393 if (!isok() || !crl.isok())
00394 {
00395 debug(WvLog::Warning, "Asked to sign CRL, but certificate or CRL (or "
00396 "both) not ok! Aborting.\n");
00397 return false;
00398 }
00399 #ifdef HAVE_OPENSSL_POLICY_MAPPING
00400 else if (!X509_check_ca(cert))
00401 {
00402 debug("This certificate is not a CA, and is thus not allowed to sign "
00403 "CRLs!\n");
00404 return false;
00405 }
00406 else if (!((cert->ex_flags & EXFLAG_KUSAGE) &&
00407 (cert->ex_kusage & KU_CRL_SIGN)))
00408 {
00409 debug("Certificate not allowed to sign CRLs! (%s %s)\n",
00410 (cert->ex_flags & EXFLAG_KUSAGE),
00411 (cert->ex_kusage & KU_CRL_SIGN));
00412 return false;
00413 }
00414 #endif
00415
00416 EVP_PKEY *certkey = EVP_PKEY_new();
00417 bool cakeyok = EVP_PKEY_set1_RSA(certkey, rsa->rsa);
00418 if (cakeyok)
00419 {
00420 ASN1_TIME *tmptm = ASN1_TIME_new();
00421
00422 X509_gmtime_adj(tmptm, 0);
00423 X509_CRL_set_lastUpdate(crl.getcrl(), tmptm);
00424
00425 X509_gmtime_adj(tmptm, (long)60*60*24*30);
00426 X509_CRL_set_nextUpdate(crl.getcrl(), tmptm);
00427 ASN1_TIME_free(tmptm);
00428
00429
00430 X509_CRL_sign(crl.getcrl(), certkey, EVP_sha1());
00431 }
00432 else
00433 {
00434 debug(WvLog::Warning, "Asked to sign CRL, but no RSA key associated "
00435 "with certificate. Aborting.\n");
00436 EVP_PKEY_free(certkey);
00437 return false;
00438 }
00439 EVP_PKEY_free(certkey);
00440
00441 return true;
00442 }
00443
00444
00445 WvString WvX509Mgr::sign(WvStringParm data) const
00446 {
00447 WvDynBuf buf;
00448 buf.putstr(data);
00449 return sign(buf);
00450 }
00451
00452
00453 WvString WvX509Mgr::sign(WvBuf &data) const
00454 {
00455 assert(rsa);
00456
00457 EVP_MD_CTX sig_ctx;
00458 unsigned char sig_buf[4096];
00459
00460 EVP_PKEY *pk = EVP_PKEY_new();
00461 assert(pk);
00462
00463 if (!EVP_PKEY_set1_RSA(pk, rsa->rsa))
00464 {
00465 debug("Error setting RSA keys.\n");
00466 EVP_PKEY_free(pk);
00467 return WvString::null;
00468 }
00469
00470 EVP_SignInit(&sig_ctx, EVP_sha1());
00471 EVP_SignUpdate(&sig_ctx, data.peek(0, data.used()), data.used());
00472 unsigned int sig_len = sizeof(sig_buf);
00473 int sig_err = EVP_SignFinal(&sig_ctx, sig_buf,
00474 &sig_len, pk);
00475 if (sig_err != 1)
00476 {
00477 debug("Error while signing.\n");
00478 EVP_PKEY_free(pk);
00479 return WvString::null;
00480 }
00481
00482 EVP_PKEY_free(pk);
00483 EVP_MD_CTX_cleanup(&sig_ctx);
00484 WvDynBuf buf;
00485 buf.put(sig_buf, sig_len);
00486 debug("Signature size: %s\n", buf.used());
00487 return WvBase64Encoder().strflushbuf(buf, true);
00488 }
00489
00490
00491 bool WvX509Mgr::write_p12(WvStringParm _fname, WvStringParm _pkcs12pass) const
00492 {
00493 debug("Dumping RSA Key and X509 Cert to PKCS12 structure.\n");
00494
00495 AutoClose fp = fopen(_fname, "wb");
00496
00497 if (!fp)
00498 {
00499 debug(WvLog::Warning, "Unable to open file. Error: %s\n",
00500 strerror(errno));
00501 return false;
00502 }
00503
00504 if (!!_pkcs12pass)
00505 {
00506 if (rsa && cert)
00507 {
00508 EVP_PKEY *pk = EVP_PKEY_new();
00509 assert(pk);
00510
00511 if (!EVP_PKEY_set1_RSA(pk, rsa->rsa))
00512 {
00513 debug("Error setting RSA keys.\n");
00514 EVP_PKEY_free(pk);
00515 return false;
00516 }
00517 else
00518 {
00519 WvString pkcs12pass(_pkcs12pass);
00520 PKCS12 *pkg
00521 = PKCS12_create(pkcs12pass.edit(), (char*)"foo", pk,
00522 cert, NULL, 0, 0, 0,
00523 0, 0);
00524 if (pkg)
00525 {
00526 debug("Writing the PKCS12 object out...\n");
00527 i2d_PKCS12_fp(fp, pkg);
00528 PKCS12_free(pkg);
00529 EVP_PKEY_free(pk);
00530 }
00531 else
00532 {
00533 debug(WvLog::Warning, "Unable to create PKCS12 object.");
00534 EVP_PKEY_free(pk);
00535 return false;
00536 }
00537 }
00538 }
00539 else
00540 {
00541 debug(WvLog::Warning,
00542 "The RSA key or the certificate is not present.");
00543 return false;
00544 }
00545 }
00546 else
00547 {
00548 debug(WvLog::Warning, "No password specified for PKCS12 dump.");
00549 return false;
00550 }
00551
00552 return true;
00553 }
00554
00555
00556 void WvX509Mgr::read_p12(WvStringParm _fname, WvStringParm _pkcs12pass)
00557 {
00558 debug("Reading Certificate and Private Key from PKCS12 file: %s\n",
00559 _fname);
00560
00561 if (rsa)
00562 WVDELETE(rsa);
00563
00564 AutoClose fp = fopen(_fname, "r");
00565
00566 if (!fp)
00567 {
00568 debug("Unable to open file '%s'!\n", _fname);
00569 return;
00570 }
00571
00572 if (!!_pkcs12pass)
00573 {
00574 PKCS12 *pkg = d2i_PKCS12_fp(fp, NULL);
00575 if (pkg)
00576 {
00577 EVP_PKEY *pk = NULL;
00578
00579
00580 X509 *x;
00581 PKCS12_parse(pkg, _pkcs12pass, &pk, &x, NULL);
00582 PKCS12_free(pkg);
00583 if (!pk || !x)
00584 {
00585 debug("Could not decode pkcs12 file.\n");
00586 EVP_PKEY_free(pk);
00587 return;
00588 }
00589
00590 cert = x;
00591
00592
00593
00594
00595 rsa = new WvRSAKey(EVP_PKEY_get1_RSA(pk), true);
00596 EVP_PKEY_free(pk);
00597
00598
00599 if (!test())
00600 {
00601 debug("Could not fill in RSA and certificate with matching "
00602 "values! Expect problems.\n");
00603 return;
00604 }
00605 }
00606 else
00607 {
00608 debug("Read in of PKCS12 file '%s' failed", _fname);
00609 return;
00610 }
00611 }
00612 else
00613 {
00614 debug("No password specified for PKCS12 file\n");
00615 return;
00616 }
00617 }
00618
00619
00620 WvString WvX509Mgr::encode(const WvRSAKey::DumpMode mode) const
00621 {
00622 if (rsa)
00623 return rsa->encode(mode);
00624 return "";
00625 }
00626
00627
00628 WvString WvX509Mgr::encode(const WvX509::DumpMode mode) const
00629 {
00630 return WvX509::encode(mode);
00631 }
00632
00633
00634 void WvX509Mgr::encode(const WvRSAKey::DumpMode mode, WvBuf &buf) const
00635 {
00636 if (rsa)
00637 rsa->encode(mode, buf);
00638 }
00639
00640
00641 void WvX509Mgr::encode(const WvX509::DumpMode mode, WvBuf &buf) const
00642 {
00643 WvX509::encode(mode, buf);
00644 }
00645
00646
00647 void WvX509Mgr::decode(const WvRSAKey::DumpMode mode, WvStringParm encoded)
00648 {
00649 if (rsa)
00650 rsa->decode(mode, encoded);
00651 else
00652 {
00653 rsa = new WvRSAKey();
00654 rsa->decode(mode, encoded);
00655 }
00656 }
00657
00658
00659 void WvX509Mgr::decode(const WvX509::DumpMode mode, WvStringParm encoded)
00660 {
00661 WvX509::decode(mode, encoded);
00662 }
00663
00664
00665 void WvX509Mgr::decode(const WvRSAKey::DumpMode mode, WvBuf &encoded)
00666 {
00667 if (rsa)
00668 rsa->decode(mode, encoded);
00669 else
00670 {
00671 rsa = new WvRSAKey();
00672 rsa->decode(mode, encoded);
00673 }
00674 }
00675
00676
00677 void WvX509Mgr::decode(const WvX509::DumpMode mode, WvBuf &encoded)
00678 {
00679 WvX509::decode(mode, encoded);
00680 }