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