2 #include "wvsslhacks.h"
4 #include "wvautoconf.h"
6 #include <openssl/pem.h>
7 #include <openssl/x509v3.h>
8 #include <openssl/err.h>
9 #include <openssl/ssl.h>
10 #include <openssl/sha.h>
11 #include <openssl/pkcs12.h>
17 AutoClose(FILE *fp
): fp(fp
) { }
24 operator FILE *() const
32 } // anomymous namespace...
35 WvX509Mgr::WvX509Mgr()
37 debug("X509 Manager", WvLog::Debug5
)
43 WvX509Mgr::WvX509Mgr(const WvX509Mgr
&x
)
45 debug("X509 Manager", WvLog::Debug5
)
52 WvX509Mgr::WvX509Mgr(WvStringParm _dname
, WvRSAKey
*_rsa
, bool ca
)
54 debug("X509 Manager", WvLog::Debug5
)
56 debug("Creating new certificate+key pair for %s.\n", _dname
);
61 create_selfissued(_dname
, ca
);
62 debug("Ok - Parameters set... now signing certificate.\n");
66 debug("Sorry, can't create an anonymous certificate.");
70 WvX509Mgr::WvX509Mgr(WvStringParm _dname
, int bits
, bool ca
)
72 debug("X509 Manager", WvLog::Debug5
)
74 debug("Creating new certificate+key pair for %s.\n", _dname
);
79 rsa
= new WvRSAKey(bits
);
80 create_selfissued(_dname
, ca
);
81 debug("Ok - Parameters set... now signing certificate.\n");
85 debug("Sorry, can't create an anonymous certificate.");
89 void WvX509Mgr::create_selfissued(WvStringParm dname
, bool is_ca
)
93 debug("Replacing already existant certificate...\n");
98 // double check RSA key
100 debug("RSA Key is fine.\n");
104 if ((cert
= X509_new()) == NULL
)
107 // Completely broken in my mind - this sets the version
108 // string to '3' (I guess version starts at 0)
111 // RFC2459 says that this number must be unique for each certificate
112 // issued by a CA. It may be that some web browsers get confused if
113 // more than one cert with the same name has the same serial number, so
120 set_lifetime(60*60*24*3650);
130 debug("Setting Extensions with CA Parameters.\n");
131 debug("Setting Key Usage.\n");
132 set_key_usage("critical, keyCertSign, cRLSign");
133 debug("Setting Basic Constraints.\n");
134 set_extension(NID_basic_constraints
, "critical, CA:TRUE");
135 debug("Setting Netscape Certificate Type.\n");
136 set_extension(NID_netscape_cert_type
,
137 "SSL CA, S/MIME CA, Object Signing CA");
139 // uncomment this to allow certificate to be used as
140 // an OCSP signer (seems too obscure to enable by default
142 set_ext_key_usage("OCSP Signing");
144 // debug("Setting Constraints.\n");
145 // set_constraints("requireExplicitPolicy");
149 debug("Setting Key Usage with normal server parameters\n");
151 set_key_usage("critical, digitalSignature, keyEncipherment, "
153 set_extension(NID_basic_constraints
, "CA:FALSE");
154 set_ext_key_usage("TLS Web Server Authentication,"
155 "TLS Web Client Authentication");
158 // we do not actually sign the certificate here: that must be done by the
159 // user (WvX509Mgr most likely)
161 debug("Certificate for %s created\n", dname
);
165 WvX509Mgr::~WvX509Mgr()
167 debug("Deleting.\n");
172 bool WvX509Mgr::isok() const
174 return WvX509::isok() && rsa
&& rsa
->isok() && test();
178 bool WvX509Mgr::operator! () const
184 WvString
WvX509Mgr::errstr() const
187 return WvX509::errstr();
190 return "No RSA key set.";
191 else if (!rsa
->isok())
192 return "RSA key not valid.";
194 return "RSA key and certificate do not match.";
196 return WvString::empty
;
200 bool WvX509Mgr::bind_ssl(SSL_CTX
*ctx
)
202 if (SSL_CTX_use_certificate(ctx
, get_cert()) <= 0)
206 debug("Certificate activated.\n");
208 if (SSL_CTX_use_RSAPrivateKey(ctx
, rsa
->rsa
) <= 0)
212 debug("RSA private key activated.\n");
217 bool WvX509Mgr::test() const
221 debug("No X509 certificate: test fails.\n");
227 EVP_PKEY
*pk
= EVP_PKEY_new();
230 if (!EVP_PKEY_set1_RSA(pk
, rsa
->rsa
))
232 debug("Error setting RSA keys: test fails.\n");
238 int verify_return
= X509_verify(cert
, pk
);
240 if (verify_return
!= 1) // only '1' means okay
242 // However let's double check:
243 WvString rsapub
= rsa
->encode(WvRSAKey::RsaPubPEM
);
244 WvRSAKey
*temprsa
= get_rsa_pub();
245 WvString certpub
= temprsa
->encode(WvRSAKey::RsaPubPEM
);
247 // debug("rsapub:\n%s\n", rsapub);
248 // debug("certpub:\n%s\n", certpub);
249 if (certpub
== rsapub
)
250 ; // do nothing, since OpenSSL is lying
253 // I guess that it really did fail.
254 debug("Certificate test failed: %s\n", wvssl_errstr());
267 WvString
WvX509Mgr::signreq(WvStringParm pkcs10req
) const
269 debug("Signing a certificate request with: %s\n", get_subject());
272 debug(WvLog::Warning
, "Asked to sign certificate request, but not ok! "
277 // Break this next part out into a de-pemify section, since that is what
278 // this part up until the FIXME: is about.
279 WvString
pkcs10(pkcs10req
);
281 BIO
*membuf
= BIO_new(BIO_s_mem());
282 BIO_write(membuf
, pkcs10req
, pkcs10req
.len());
284 X509_REQ
*certreq
= PEM_read_bio_X509_REQ(membuf
, NULL
, NULL
, NULL
);
285 BIO_free_all(membuf
);
289 WvX509
newcert(X509_new());
291 newcert
.set_subject(X509_REQ_get_subject_name(certreq
));
292 newcert
.set_version();
294 // Set the Serial Number for the certificate
297 newcert
.set_serial(serial
);
299 newcert
.set_lifetime(60*60*24*3650);
301 // The public key of the new cert should be the same as that from
303 EVP_PKEY
*pk
= X509_REQ_get_pubkey(certreq
);
304 X509_set_pubkey(newcert
.get_cert(), pk
);
307 // every good cert needs an ski+aki
309 newcert
.set_aki(*this);
311 // The Issuer name is the subject name of the current cert
312 newcert
.set_issuer(*this);
314 X509_EXTENSION
*ex
= NULL
;
315 // Set the RFC2459-mandated keyUsage field to critical, and restrict
316 // the usage of this cert to digital signature and key encipherment.
317 newcert
.set_key_usage("critical, digitalSignature, keyEncipherment");
319 // This could cause Netscape to barf because if we set
320 // basicConstraints to critical, we break RFC2459 compliance. Why
321 // they chose to enforce that bit, and not the rest is beyond me...
323 ex
= X509V3_EXT_conf_nid(NULL
, NULL
, NID_basic_constraints
,
326 X509_add_ext(newcert
.get_cert(), ex
, -1);
327 X509_EXTENSION_free(ex
);
329 newcert
.set_ext_key_usage("critical, TLS Web Client Authentication");
333 X509_REQ_free(certreq
);
334 return WvString(newcert
.encode(WvX509::CertPEM
));
338 debug("Can't decode Certificate Request\n");
339 return WvString::null
;
344 bool WvX509Mgr::signcert(WvX509
&unsignedcert
) const
348 debug(WvLog::Warning
, "Asked to sign certificate, but not ok! "
353 if (cert
== unsignedcert
.cert
)
355 debug("Self Signing!\n");
357 #ifdef HAVE_OPENSSL_POLICY_MAPPING
358 else if (!X509_check_ca(cert
))
360 debug("This certificate is not a CA, and is thus not allowed to sign "
365 else if (!((cert
->ex_flags
& EXFLAG_KUSAGE
) &&
366 (cert
->ex_kusage
& KU_KEY_CERT_SIGN
)))
368 debug("This Certificate is not allowed to sign certificates!\n");
372 debug("Ok, now sign the new cert with the current RSA key.\n");
373 EVP_PKEY
*certkey
= EVP_PKEY_new();
374 bool cakeyok
= EVP_PKEY_set1_RSA(certkey
, rsa
->rsa
);
377 X509_sign(unsignedcert
.get_cert(), certkey
, EVP_sha1());
381 debug("No keys??\n");
382 EVP_PKEY_free(certkey
);
386 EVP_PKEY_free(certkey
);
391 bool WvX509Mgr::signcrl(WvCRL
&crl
) const
393 if (!isok() || !crl
.isok())
395 debug(WvLog::Warning
, "Asked to sign CRL, but certificate or CRL (or "
396 "both) not ok! Aborting.\n");
399 #ifdef HAVE_OPENSSL_POLICY_MAPPING
400 else if (!X509_check_ca(cert
))
402 debug("This certificate is not a CA, and is thus not allowed to sign "
406 else if (!((cert
->ex_flags
& EXFLAG_KUSAGE
) &&
407 (cert
->ex_kusage
& KU_CRL_SIGN
)))
409 debug("Certificate not allowed to sign CRLs! (%s %s)\n",
410 (cert
->ex_flags
& EXFLAG_KUSAGE
),
411 (cert
->ex_kusage
& KU_CRL_SIGN
));
416 EVP_PKEY
*certkey
= EVP_PKEY_new();
417 bool cakeyok
= EVP_PKEY_set1_RSA(certkey
, rsa
->rsa
);
420 ASN1_TIME
*tmptm
= ASN1_TIME_new();
421 // Set the LastUpdate time to now.
422 X509_gmtime_adj(tmptm
, 0);
423 X509_CRL_set_lastUpdate(crl
.getcrl(), tmptm
);
424 // CRL's are valid for 30 days
425 X509_gmtime_adj(tmptm
, (long)60*60*24*30);
426 X509_CRL_set_nextUpdate(crl
.getcrl(), tmptm
);
427 ASN1_TIME_free(tmptm
);
429 // OK - now sign it...
430 X509_CRL_sign(crl
.getcrl(), certkey
, EVP_sha1());
434 debug(WvLog::Warning
, "Asked to sign CRL, but no RSA key associated "
435 "with certificate. Aborting.\n");
436 EVP_PKEY_free(certkey
);
439 EVP_PKEY_free(certkey
);
445 WvString
WvX509Mgr::sign(WvStringParm data
) const
453 WvString
WvX509Mgr::sign(WvBuf
&data
) const
458 unsigned char sig_buf
[4096];
460 EVP_PKEY
*pk
= EVP_PKEY_new();
463 if (!EVP_PKEY_set1_RSA(pk
, rsa
->rsa
))
465 debug("Error setting RSA keys.\n");
467 return WvString::null
;
470 EVP_SignInit(&sig_ctx
, EVP_sha1());
471 EVP_SignUpdate(&sig_ctx
, data
.peek(0, data
.used()), data
.used());
472 unsigned int sig_len
= sizeof(sig_buf
);
473 int sig_err
= EVP_SignFinal(&sig_ctx
, sig_buf
,
477 debug("Error while signing.\n");
479 return WvString::null
;
483 EVP_MD_CTX_cleanup(&sig_ctx
); // this isn't my fault ://
485 buf
.put(sig_buf
, sig_len
);
486 debug("Signature size: %s\n", buf
.used());
487 return WvBase64Encoder().strflushbuf(buf
, true);
491 bool WvX509Mgr::write_p12(WvStringParm _fname
, WvStringParm _pkcs12pass
) const
493 debug("Dumping RSA Key and X509 Cert to PKCS12 structure.\n");
495 AutoClose fp
= fopen(_fname
, "wb");
499 debug(WvLog::Warning
, "Unable to open file. Error: %s\n",
508 EVP_PKEY
*pk
= EVP_PKEY_new();
511 if (!EVP_PKEY_set1_RSA(pk
, rsa
->rsa
))
513 debug("Error setting RSA keys.\n");
519 WvString
pkcs12pass(_pkcs12pass
);
521 = PKCS12_create(pkcs12pass
.edit(), (char*)"foo", pk
,
526 debug("Writing the PKCS12 object out...\n");
527 i2d_PKCS12_fp(fp
, pkg
);
533 debug(WvLog::Warning
, "Unable to create PKCS12 object.");
541 debug(WvLog::Warning
,
542 "The RSA key or the certificate is not present.");
548 debug(WvLog::Warning
, "No password specified for PKCS12 dump.");
556 void WvX509Mgr::read_p12(WvStringParm _fname
, WvStringParm _pkcs12pass
)
558 debug("Reading Certificate and Private Key from PKCS12 file: %s\n",
564 AutoClose fp
= fopen(_fname
, "r");
568 debug("Unable to open file '%s'!\n", _fname
);
574 PKCS12
*pkg
= d2i_PKCS12_fp(fp
, NULL
);
579 // Parse out the bits out the PKCS12 package.
581 PKCS12_parse(pkg
, _pkcs12pass
, &pk
, &x
, NULL
);
585 debug("Could not decode pkcs12 file.\n");
592 // Now, cert should be OK, let's try and set up the RSA stuff
593 // since we've essentially got a PKEY, and not a WvRSAKey
594 // We need to create a new WvRSAKey from the PKEY...
595 rsa
= new WvRSAKey(EVP_PKEY_get1_RSA(pk
), true);
598 // Now that we have both, check to make sure that they match
601 debug("Could not fill in RSA and certificate with matching "
602 "values! Expect problems.\n");
608 debug("Read in of PKCS12 file '%s' failed", _fname
);
614 debug("No password specified for PKCS12 file\n");
620 WvString
WvX509Mgr::encode(const WvRSAKey::DumpMode mode
) const
623 return rsa
->encode(mode
);
628 WvString
WvX509Mgr::encode(const WvX509::DumpMode mode
) const
630 return WvX509::encode(mode
);
634 void WvX509Mgr::encode(const WvRSAKey::DumpMode mode
, WvBuf
&buf
) const
637 rsa
->encode(mode
, buf
);
641 void WvX509Mgr::encode(const WvX509::DumpMode mode
, WvBuf
&buf
) const
643 WvX509::encode(mode
, buf
);
647 void WvX509Mgr::decode(const WvRSAKey::DumpMode mode
, WvStringParm encoded
)
650 rsa
->decode(mode
, encoded
);
653 rsa
= new WvRSAKey();
654 rsa
->decode(mode
, encoded
);
659 void WvX509Mgr::decode(const WvX509::DumpMode mode
, WvStringParm encoded
)
661 WvX509::decode(mode
, encoded
);
665 void WvX509Mgr::decode(const WvRSAKey::DumpMode mode
, WvBuf
&encoded
)
668 rsa
->decode(mode
, encoded
);
671 rsa
= new WvRSAKey();
672 rsa
->decode(mode
, encoded
);
677 void WvX509Mgr::decode(const WvX509::DumpMode mode
, WvBuf
&encoded
)
679 WvX509::decode(mode
, encoded
);