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
37 debug(
"X509 Manager",
WvLog::Debug5)
45 debug(
"X509 Manager",
WvLog::Debug5)
54 debug(
"X509 Manager",
WvLog::Debug5)
56 debug(
"Creating new certificate+key pair for %s.\n", _dname);
62 debug(
"Ok - Parameters set... now signing certificate.\n");
66 debug(
"Sorry, can't create an anonymous certificate.");
72 debug(
"X509 Manager",
WvLog::Debug5)
74 debug(
"Creating new certificate+key pair for %s.\n", _dname);
81 debug(
"Ok - Parameters set... now signing certificate.\n");
85 debug(
"Sorry, can't create an anonymous certificate.");
93 debug(
"Replacing already existant certificate...\n");
100 debug(
"RSA Key is fine.\n");
104 if ((cert = X509_new()) == NULL)
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");
142 set_ext_key_usage(
"OCSP Signing");
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");
161 debug(
"Certificate for %s created\n", dname);
167 debug(
"Deleting.\n");
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;
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");
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)
249 if (certpub == rsapub)
254 debug(
"Certificate test failed: %s\n", wvssl_errstr());
269 debug(
"Signing a certificate request with: %s\n",
get_subject());
272 debug(WvLog::Warning,
"Asked to sign certificate request, but not ok! "
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));
297 newcert.set_serial(serial);
303 EVP_PKEY *pk = X509_REQ_get_pubkey(
certreq);
304 X509_set_pubkey(newcert.
get_cert(), pk);
309 newcert.set_aki(*
this);
312 newcert.set_issuer(*
this);
314 X509_EXTENSION *ex = NULL;
317 newcert.set_key_usage(
"critical, digitalSignature, keyEncipherment");
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");
338 debug(
"Can't decode Certificate Request\n");
339 return WvString::null;
348 debug(WvLog::Warning,
"Asked to sign certificate, but not ok! "
353 uint32_t ex_flags = X509_get_extension_flags(cert);
354 uint32_t ex_kusage = X509_get_key_usage(cert);
355 if (cert == unsignedcert.cert)
357 debug(
"Self Signing!\n");
359 #ifdef HAVE_OPENSSL_POLICY_MAPPING
360 else if (!X509_check_ca(cert))
362 debug(
"This certificate is not a CA, and is thus not allowed to sign "
367 else if (!((ex_flags & EXFLAG_KUSAGE) &&
368 (ex_kusage & KU_KEY_CERT_SIGN)))
370 debug(
"This Certificate is not allowed to sign certificates!\n");
374 debug(
"Ok, now sign the new cert with the current RSA key.\n");
375 EVP_PKEY *certkey = EVP_PKEY_new();
376 bool cakeyok = EVP_PKEY_set1_RSA(certkey, rsa->rsa);
379 X509_sign(unsignedcert.
get_cert(), certkey, EVP_sha1());
383 debug(
"No keys??\n");
384 EVP_PKEY_free(certkey);
388 EVP_PKEY_free(certkey);
395 uint32_t ex_flags = X509_get_extension_flags(cert);
396 uint32_t ex_kusage = X509_get_key_usage(cert);
399 debug(WvLog::Warning,
"Asked to sign CRL, but certificate or CRL (or "
400 "both) not ok! Aborting.\n");
403 #ifdef HAVE_OPENSSL_POLICY_MAPPING
404 else if (!X509_check_ca(cert))
406 debug(
"This certificate is not a CA, and is thus not allowed to sign "
410 else if (!((ex_flags & EXFLAG_KUSAGE) &&
411 (ex_kusage & KU_CRL_SIGN)))
413 debug(
"Certificate not allowed to sign CRLs! (%s %s)\n",
414 (ex_flags & EXFLAG_KUSAGE),
415 (ex_kusage & KU_CRL_SIGN));
420 EVP_PKEY *certkey = EVP_PKEY_new();
421 bool cakeyok = EVP_PKEY_set1_RSA(certkey, rsa->rsa);
424 ASN1_TIME *tmptm = ASN1_TIME_new();
426 X509_gmtime_adj(tmptm, 0);
427 X509_CRL_set_lastUpdate(crl.
getcrl(), tmptm);
429 X509_gmtime_adj(tmptm, (
long)60*60*24*30);
430 X509_CRL_set_nextUpdate(crl.
getcrl(), tmptm);
431 ASN1_TIME_free(tmptm);
434 X509_CRL_sign(crl.
getcrl(), certkey, EVP_sha1());
438 debug(WvLog::Warning,
"Asked to sign CRL, but no RSA key associated "
439 "with certificate. Aborting.\n");
440 EVP_PKEY_free(certkey);
443 EVP_PKEY_free(certkey);
461 unsigned char sig_buf[4096];
463 EVP_PKEY *pk = EVP_PKEY_new();
466 if (!EVP_PKEY_set1_RSA(pk, rsa->rsa))
468 debug(
"Error setting RSA keys.\n");
470 return WvString::null;
473 EVP_MD_CTX *sig_ctx = EVP_MD_CTX_new();
474 EVP_SignInit(sig_ctx, EVP_sha1());
475 EVP_SignUpdate(sig_ctx, data.
peek(0, data.
used()), data.
used());
476 unsigned int sig_len =
sizeof(sig_buf);
477 int sig_err = EVP_SignFinal(sig_ctx, sig_buf,
481 debug(
"Error while signing.\n");
483 EVP_MD_CTX_free(sig_ctx);
484 return WvString::null;
488 EVP_MD_CTX_free(sig_ctx);
490 buf.put(sig_buf, sig_len);
491 debug(
"Signature size: %s\n", buf.
used());
498 debug(
"Dumping RSA Key and X509 Cert to PKCS12 structure.\n");
500 AutoClose fp = fopen(_fname,
"wb");
504 debug(WvLog::Warning,
"Unable to open file. Error: %s\n",
513 EVP_PKEY *pk = EVP_PKEY_new();
516 if (!EVP_PKEY_set1_RSA(pk, rsa->rsa))
518 debug(
"Error setting RSA keys.\n");
526 = PKCS12_create(pkcs12pass.
edit(), (
char*)
"foo", pk,
531 debug(
"Writing the PKCS12 object out...\n");
532 i2d_PKCS12_fp(fp, pkg);
538 debug(WvLog::Warning,
"Unable to create PKCS12 object.");
546 debug(WvLog::Warning,
547 "The RSA key or the certificate is not present.");
553 debug(WvLog::Warning,
"No password specified for PKCS12 dump.");
563 debug(
"Reading Certificate and Private Key from PKCS12 file: %s\n",
569 AutoClose fp = fopen(_fname,
"r");
573 debug(
"Unable to open file '%s'!\n", _fname);
579 PKCS12 *pkg = d2i_PKCS12_fp(fp, NULL);
586 PKCS12_parse(pkg, _pkcs12pass, &pk, &x, NULL);
590 debug(
"Could not decode pkcs12 file.\n");
600 rsa =
new WvRSAKey(EVP_PKEY_get1_RSA(pk),
true);
606 debug(
"Could not fill in RSA and certificate with matching "
607 "values! Expect problems.\n");
613 debug(
"Read in of PKCS12 file '%s' failed", _fname);
619 debug(
"No password specified for PKCS12 file\n");
655 rsa->
decode(mode, encoded);
659 rsa->
decode(mode, encoded);
673 rsa->
decode(mode, encoded);
677 rsa->
decode(mode, encoded);
const T * peek(int offset, size_t count)
Returns a const pointer into the buffer at the specified offset to the specified number of elements w...
size_t used() const
Returns the number of elements in the buffer currently available for reading.
Specialization of WvBufBase for unsigned char type buffers intended for use with raw memory buffers.
void putstr(WvStringParm str)
Copies a WvString into the buffer, excluding the null-terminator.
CRL Class to handle certificate revocation lists and their related functions.
X509_CRL * getcrl()
Accessor for CRL.
bool isok() const
Do we have any errors...
WvString strflushbuf(WvBuf &inbuf, bool finish=false)
Flushes data through the encoder from a buffer to a string.
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's.
An RSA public key or public/private key pair that can be used for encryption.
virtual WvString encode(const DumpMode mode) const
Return the information requested by mode.
DumpMode
Type for the encode() and decode() methods.
virtual void decode(const DumpMode mode, WvStringParm encoded)
Load the information from the format requested by mode into the class - this overwrites the certifica...
WvString is an implementation of a simple and efficient printable-string class.
char * edit()
make the string editable, and return a non-const (char*)
virtual void decode(const WvX509::DumpMode mode, WvStringParm encoded)
Load the information from the format requested by mode into the class - this overwrites the certifica...
virtual WvString errstr() const
Says what the error is, if isok() is not true.
bool bind_ssl(SSL_CTX *ctx)
Avoid a lot of ugliness by having it so that we are binding to the SSL context, and not the other way...
void read_p12(WvStringParm _fname, WvStringParm _pkcs12pass)
And this reads from the file specified in filename using the password "_pkcs12pass",...
bool signcrl(WvCRL &unsignedcrl) const
Sign the CRL with the rsa key associated with this class.
bool write_p12(WvStringParm _fname, WvStringParm _pkcs12pass) const
This writes the certificate and RSA keys in PKCS12 format to the file specified by filename,...
WvX509Mgr()
Constructor to create a blank certificate + keypair (useful if, for example, you were going to load t...
WvString sign(WvBuf &data) const
Sign the contents of data and return the signature as a BASE64 string.
virtual WvString encode(const WvX509::DumpMode mode) const
Encodes the information requested by mode into a buffer.
bool test() const
Test to make sure that a certificate and a keypair go together.
bool signcert(WvX509 &unsignedcert) const
Sign the certificate with the rsa key associated with this class.
WvString signreq(WvStringParm pkcs10req) const
Take the PKCS#10 request in the string pkcs10req, sign it with the private key in rsa,...
bool operator!() const
The not operator returns true if !isok()
virtual ~WvX509Mgr()
Destructor.
void create_selfissued(WvStringParm dname, bool is_ca=false)
Given the Distinguished Name dname and an already generated keypair in rsa, return a Self Signed Cert...
virtual bool isok() const
Says if this certificate+key pair is good for use.
X509 Class to handle certificates and their related functions.
virtual WvString errstr() const
Returns an error string if isok() is not true.
void set_version()
Set the Certificate to use X509v3, since that's all modern PKI uses anyways :)
WvString get_subject() const
get and set the Subject field of the certificate
DumpMode
Type for the encode() and decode() methods.
void set_lifetime(long seconds)
Set the lifetime to be used for this certificate...
void set_pubkey(WvRSAKey &rsa_pubkey)
Set the public key of the certificate to the public key rsa_pubkey.
virtual void decode(const DumpMode mode, WvStringParm str)
Load the information from the format requested by mode into the class - this overwrites the certifica...
static WvString certreq(WvStringParm subject, const WvRSAKey &rsa)
Create a certificate request (PKCS#10) using this function.
WvString encode(const DumpMode mode) const
Return the information requested by mode.
X509 * get_cert()
Allow us to access the certificate member - this will be going away eventually, but for now,...
virtual bool isok() const
Is the certificate object valid?