Ruby 1.9.3p327(2012-11-10revision37606)
ext/openssl/ossl_x509cert.c
Go to the documentation of this file.
00001 /*
00002  * $Id: ossl_x509cert.c 35191 2012-03-31 03:12:47Z emboss $
00003  * 'OpenSSL for Ruby' project
00004  * Copyright (C) 2001-2002  Michal Rokos <m.rokos@sh.cvut.cz>
00005  * All rights reserved.
00006  */
00007 /*
00008  * This program is licenced under the same licence as Ruby.
00009  * (See the file 'LICENCE'.)
00010  */
00011 #include "ossl.h"
00012 
00013 #define WrapX509(klass, obj, x509) do { \
00014     if (!(x509)) { \
00015         ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
00016     } \
00017     (obj) = Data_Wrap_Struct((klass), 0, X509_free, (x509)); \
00018 } while (0)
00019 #define GetX509(obj, x509) do { \
00020     Data_Get_Struct((obj), X509, (x509)); \
00021     if (!(x509)) { \
00022         ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
00023     } \
00024 } while (0)
00025 #define SafeGetX509(obj, x509) do { \
00026     OSSL_Check_Kind((obj), cX509Cert); \
00027     GetX509((obj), (x509)); \
00028 } while (0)
00029 
00030 /*
00031  * Classes
00032  */
00033 VALUE cX509Cert;
00034 VALUE eX509CertError;
00035 
00036 /*
00037  * Public
00038  */
00039 VALUE
00040 ossl_x509_new(X509 *x509)
00041 {
00042     X509 *new;
00043     VALUE obj;
00044 
00045     if (!x509) {
00046         new = X509_new();
00047     } else {
00048         new = X509_dup(x509);
00049     }
00050     if (!new) {
00051         ossl_raise(eX509CertError, NULL);
00052     }
00053     WrapX509(cX509Cert, obj, new);
00054 
00055     return obj;
00056 }
00057 
00058 VALUE
00059 ossl_x509_new_from_file(VALUE filename)
00060 {
00061     X509 *x509;
00062     FILE *fp;
00063     VALUE obj;
00064 
00065     SafeStringValue(filename);
00066     if (!(fp = fopen(RSTRING_PTR(filename), "r"))) {
00067         ossl_raise(eX509CertError, "%s", strerror(errno));
00068     }
00069     x509 = PEM_read_X509(fp, NULL, NULL, NULL);
00070     /*
00071      * prepare for DER...
00072 #if !defined(OPENSSL_NO_FP_API)
00073     if (!x509) {
00074         (void)ERR_get_error();
00075         rewind(fp);
00076 
00077         x509 = d2i_X509_fp(fp, NULL);
00078     }
00079 #endif
00080     */
00081     fclose(fp);
00082     if (!x509) {
00083         ossl_raise(eX509CertError, NULL);
00084     }
00085     WrapX509(cX509Cert, obj, x509);
00086 
00087     return obj;
00088 }
00089 
00090 X509 *
00091 GetX509CertPtr(VALUE obj)
00092 {
00093     X509 *x509;
00094 
00095     SafeGetX509(obj, x509);
00096 
00097     return x509;
00098 }
00099 
00100 X509 *
00101 DupX509CertPtr(VALUE obj)
00102 {
00103     X509 *x509;
00104 
00105     SafeGetX509(obj, x509);
00106 
00107     CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509);
00108 
00109     return x509;
00110 }
00111 
00112 /*
00113  * Private
00114  */
00115 static VALUE
00116 ossl_x509_alloc(VALUE klass)
00117 {
00118     X509 *x509;
00119     VALUE obj;
00120 
00121     x509 = X509_new();
00122     if (!x509) ossl_raise(eX509CertError, NULL);
00123 
00124     WrapX509(klass, obj, x509);
00125 
00126     return obj;
00127 }
00128 
00129 /*
00130  * call-seq:
00131  *    Certificate.new => cert
00132  *    Certificate.new(string) => cert
00133  */
00134 static VALUE
00135 ossl_x509_initialize(int argc, VALUE *argv, VALUE self)
00136 {
00137     BIO *in;
00138     X509 *x509, *x = DATA_PTR(self);
00139     VALUE arg;
00140 
00141     if (rb_scan_args(argc, argv, "01", &arg) == 0) {
00142         /* create just empty X509Cert */
00143         return self;
00144     }
00145     arg = ossl_to_der_if_possible(arg);
00146     in = ossl_obj2bio(arg);
00147     x509 = PEM_read_bio_X509(in, &x, NULL, NULL);
00148     DATA_PTR(self) = x;
00149     if (!x509) {
00150         OSSL_BIO_reset(in);
00151         x509 = d2i_X509_bio(in, &x);
00152         DATA_PTR(self) = x;
00153     }
00154     BIO_free(in);
00155     if (!x509) ossl_raise(eX509CertError, NULL);
00156 
00157     return self;
00158 }
00159 
00160 static VALUE
00161 ossl_x509_copy(VALUE self, VALUE other)
00162 {
00163     X509 *a, *b, *x509;
00164 
00165     rb_check_frozen(self);
00166     if (self == other) return self;
00167 
00168     GetX509(self, a);
00169     SafeGetX509(other, b);
00170 
00171     x509 = X509_dup(b);
00172     if (!x509) ossl_raise(eX509CertError, NULL);
00173 
00174     DATA_PTR(self) = x509;
00175     X509_free(a);
00176 
00177     return self;
00178 }
00179 
00180 /*
00181  * call-seq:
00182  *    cert.to_der => string
00183  */
00184 static VALUE
00185 ossl_x509_to_der(VALUE self)
00186 {
00187     X509 *x509;
00188     VALUE str;
00189     long len;
00190     unsigned char *p;
00191 
00192     GetX509(self, x509);
00193     if ((len = i2d_X509(x509, NULL)) <= 0)
00194         ossl_raise(eX509CertError, NULL);
00195     str = rb_str_new(0, len);
00196     p = (unsigned char *)RSTRING_PTR(str);
00197     if (i2d_X509(x509, &p) <= 0)
00198         ossl_raise(eX509CertError, NULL);
00199     ossl_str_adjust(str, p);
00200 
00201     return str;
00202 }
00203 
00204 /*
00205  * call-seq:
00206  *    cert.to_pem => string
00207  */
00208 static VALUE
00209 ossl_x509_to_pem(VALUE self)
00210 {
00211     X509 *x509;
00212     BIO *out;
00213     VALUE str;
00214 
00215     GetX509(self, x509);
00216     out = BIO_new(BIO_s_mem());
00217     if (!out) ossl_raise(eX509CertError, NULL);
00218 
00219     if (!PEM_write_bio_X509(out, x509)) {
00220         BIO_free(out);
00221         ossl_raise(eX509CertError, NULL);
00222     }
00223     str = ossl_membio2str(out);
00224 
00225     return str;
00226 }
00227 
00228 /*
00229  * call-seq:
00230  *    cert.to_text => string
00231  */
00232 static VALUE
00233 ossl_x509_to_text(VALUE self)
00234 {
00235     X509 *x509;
00236     BIO *out;
00237     VALUE str;
00238 
00239     GetX509(self, x509);
00240 
00241     out = BIO_new(BIO_s_mem());
00242     if (!out) ossl_raise(eX509CertError, NULL);
00243 
00244     if (!X509_print(out, x509)) {
00245         BIO_free(out);
00246         ossl_raise(eX509CertError, NULL);
00247     }
00248     str = ossl_membio2str(out);
00249 
00250     return str;
00251 }
00252 
00253 #if 0
00254 /*
00255  * Makes from X509 X509_REQuest
00256  */
00257 static VALUE
00258 ossl_x509_to_req(VALUE self)
00259 {
00260     X509 *x509;
00261     X509_REQ *req;
00262     VALUE obj;
00263 
00264     GetX509(self, x509);
00265     if (!(req = X509_to_X509_REQ(x509, NULL, EVP_md5()))) {
00266         ossl_raise(eX509CertError, NULL);
00267     }
00268     obj = ossl_x509req_new(req);
00269     X509_REQ_free(req);
00270 
00271     return obj;
00272 }
00273 #endif
00274 
00275 /*
00276  * call-seq:
00277  *    cert.version => integer
00278  */
00279 static VALUE
00280 ossl_x509_get_version(VALUE self)
00281 {
00282     X509 *x509;
00283 
00284     GetX509(self, x509);
00285 
00286     return LONG2NUM(X509_get_version(x509));
00287 }
00288 
00289 /*
00290  * call-seq:
00291  *    cert.version = integer => integer
00292  */
00293 static VALUE
00294 ossl_x509_set_version(VALUE self, VALUE version)
00295 {
00296     X509 *x509;
00297     long ver;
00298 
00299     if ((ver = NUM2LONG(version)) < 0) {
00300         ossl_raise(eX509CertError, "version must be >= 0!");
00301     }
00302     GetX509(self, x509);
00303     if (!X509_set_version(x509, ver)) {
00304         ossl_raise(eX509CertError, NULL);
00305     }
00306 
00307     return version;
00308 }
00309 
00310 /*
00311  * call-seq:
00312  *    cert.serial => integer
00313  */
00314 static VALUE
00315 ossl_x509_get_serial(VALUE self)
00316 {
00317     X509 *x509;
00318 
00319     GetX509(self, x509);
00320 
00321     return asn1integer_to_num(X509_get_serialNumber(x509));
00322 }
00323 
00324 /*
00325  * call-seq:
00326  *    cert.serial = integer => integer
00327  */
00328 static VALUE
00329 ossl_x509_set_serial(VALUE self, VALUE num)
00330 {
00331     X509 *x509;
00332 
00333     GetX509(self, x509);
00334 
00335     x509->cert_info->serialNumber =
00336         num_to_asn1integer(num, X509_get_serialNumber(x509));
00337 
00338     return num;
00339 }
00340 
00341 /*
00342  * call-seq:
00343  *    cert.signature_algorithm => string
00344  */
00345 static VALUE
00346 ossl_x509_get_signature_algorithm(VALUE self)
00347 {
00348     X509 *x509;
00349     BIO *out;
00350     VALUE str;
00351 
00352     GetX509(self, x509);
00353     out = BIO_new(BIO_s_mem());
00354     if (!out) ossl_raise(eX509CertError, NULL);
00355 
00356     if (!i2a_ASN1_OBJECT(out, x509->cert_info->signature->algorithm)) {
00357         BIO_free(out);
00358         ossl_raise(eX509CertError, NULL);
00359     }
00360     str = ossl_membio2str(out);
00361 
00362     return str;
00363 }
00364 
00365 /*
00366  * call-seq:
00367  *    cert.subject => name
00368  */
00369 static VALUE
00370 ossl_x509_get_subject(VALUE self)
00371 {
00372     X509 *x509;
00373     X509_NAME *name;
00374 
00375     GetX509(self, x509);
00376     if (!(name = X509_get_subject_name(x509))) { /* NO DUP - don't free! */
00377         ossl_raise(eX509CertError, NULL);
00378     }
00379 
00380     return ossl_x509name_new(name);
00381 }
00382 
00383 /*
00384  * call-seq:
00385  *    cert.subject = name => name
00386  */
00387 static VALUE
00388 ossl_x509_set_subject(VALUE self, VALUE subject)
00389 {
00390     X509 *x509;
00391 
00392     GetX509(self, x509);
00393     if (!X509_set_subject_name(x509, GetX509NamePtr(subject))) { /* DUPs name */
00394         ossl_raise(eX509CertError, NULL);
00395     }
00396 
00397     return subject;
00398 }
00399 
00400 /*
00401  * call-seq:
00402  *    cert.issuer => name
00403  */
00404 static VALUE
00405 ossl_x509_get_issuer(VALUE self)
00406 {
00407     X509 *x509;
00408     X509_NAME *name;
00409 
00410     GetX509(self, x509);
00411     if(!(name = X509_get_issuer_name(x509))) { /* NO DUP - don't free! */
00412         ossl_raise(eX509CertError, NULL);
00413     }
00414 
00415     return ossl_x509name_new(name);
00416 }
00417 
00418 /*
00419  * call-seq:
00420  *    cert.issuer = name => name
00421  */
00422 static VALUE
00423 ossl_x509_set_issuer(VALUE self, VALUE issuer)
00424 {
00425     X509 *x509;
00426 
00427     GetX509(self, x509);
00428     if (!X509_set_issuer_name(x509, GetX509NamePtr(issuer))) { /* DUPs name */
00429         ossl_raise(eX509CertError, NULL);
00430     }
00431 
00432     return issuer;
00433 }
00434 
00435 /*
00436  * call-seq:
00437  *    cert.not_before => time
00438  */
00439 static VALUE
00440 ossl_x509_get_not_before(VALUE self)
00441 {
00442     X509 *x509;
00443     ASN1_UTCTIME *asn1time;
00444 
00445     GetX509(self, x509);
00446     if (!(asn1time = X509_get_notBefore(x509))) { /* NO DUP - don't free! */
00447         ossl_raise(eX509CertError, NULL);
00448     }
00449 
00450     return asn1time_to_time(asn1time);
00451 }
00452 
00453 /*
00454  * call-seq:
00455  *    cert.not_before = time => time
00456  */
00457 static VALUE
00458 ossl_x509_set_not_before(VALUE self, VALUE time)
00459 {
00460     X509 *x509;
00461     time_t sec;
00462 
00463     sec = time_to_time_t(time);
00464     GetX509(self, x509);
00465     if (!X509_time_adj(X509_get_notBefore(x509), 0, &sec)) {
00466         ossl_raise(eX509CertError, NULL);
00467     }
00468 
00469     return time;
00470 }
00471 
00472 /*
00473  * call-seq:
00474  *    cert.not_after => time
00475  */
00476 static VALUE
00477 ossl_x509_get_not_after(VALUE self)
00478 {
00479     X509 *x509;
00480     ASN1_TIME *asn1time;
00481 
00482     GetX509(self, x509);
00483     if (!(asn1time = X509_get_notAfter(x509))) { /* NO DUP - don't free! */
00484         ossl_raise(eX509CertError, NULL);
00485     }
00486 
00487     return asn1time_to_time(asn1time);
00488 }
00489 
00490 /*
00491  * call-seq:
00492  *    cert.not_after = time => time
00493  */
00494 static VALUE
00495 ossl_x509_set_not_after(VALUE self, VALUE time)
00496 {
00497     X509 *x509;
00498     time_t sec;
00499 
00500     sec = time_to_time_t(time);
00501     GetX509(self, x509);
00502     if (!X509_time_adj(X509_get_notAfter(x509), 0, &sec)) {
00503         ossl_raise(eX509CertError, NULL);
00504     }
00505 
00506     return time;
00507 }
00508 
00509 /*
00510  * call-seq:
00511  *    cert.public_key => key
00512  */
00513 static VALUE
00514 ossl_x509_get_public_key(VALUE self)
00515 {
00516     X509 *x509;
00517     EVP_PKEY *pkey;
00518 
00519     GetX509(self, x509);
00520     if (!(pkey = X509_get_pubkey(x509))) { /* adds an reference */
00521         ossl_raise(eX509CertError, NULL);
00522     }
00523 
00524     return ossl_pkey_new(pkey); /* NO DUP - OK */
00525 }
00526 
00527 /*
00528  * call-seq:
00529  *    cert.public_key = key => key
00530  */
00531 static VALUE
00532 ossl_x509_set_public_key(VALUE self, VALUE key)
00533 {
00534     X509 *x509;
00535 
00536     GetX509(self, x509);
00537     if (!X509_set_pubkey(x509, GetPKeyPtr(key))) { /* DUPs pkey */
00538         ossl_raise(eX509CertError, NULL);
00539     }
00540 
00541     return key;
00542 }
00543 
00544 /*
00545  * call-seq:
00546  *    cert.sign(key, digest) => self
00547  */
00548 static VALUE
00549 ossl_x509_sign(VALUE self, VALUE key, VALUE digest)
00550 {
00551     X509 *x509;
00552     EVP_PKEY *pkey;
00553     const EVP_MD *md;
00554 
00555     pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
00556     md = GetDigestPtr(digest);
00557     GetX509(self, x509);
00558     if (!X509_sign(x509, pkey, md)) {
00559         ossl_raise(eX509CertError, NULL);
00560     }
00561 
00562     return self;
00563 }
00564 
00565 /*
00566  * call-seq:
00567  *    cert.verify(key) => true | false
00568  *
00569  * Checks that cert signature is made with PRIVversion of this PUBLIC 'key'
00570  */
00571 static VALUE
00572 ossl_x509_verify(VALUE self, VALUE key)
00573 {
00574     X509 *x509;
00575     EVP_PKEY *pkey;
00576     int i;
00577 
00578     pkey = GetPKeyPtr(key); /* NO NEED TO DUP */
00579     GetX509(self, x509);
00580     if ((i = X509_verify(x509, pkey)) < 0) {
00581         ossl_raise(eX509CertError, NULL);
00582     }
00583     if (i > 0) {
00584         return Qtrue;
00585     }
00586 
00587     return Qfalse;
00588 }
00589 
00590 /*
00591  * call-seq:
00592  *    cert.check_private_key(key)
00593  *
00594  * Checks if 'key' is PRIV key for this cert
00595  */
00596 static VALUE
00597 ossl_x509_check_private_key(VALUE self, VALUE key)
00598 {
00599     X509 *x509;
00600     EVP_PKEY *pkey;
00601 
00602     /* not needed private key, but should be */
00603     pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
00604     GetX509(self, x509);
00605     if (!X509_check_private_key(x509, pkey)) {
00606         OSSL_Warning("Check private key:%s", OSSL_ErrMsg());
00607         return Qfalse;
00608     }
00609 
00610     return Qtrue;
00611 }
00612 
00613 /*
00614  * call-seq:
00615  *    cert.extensions => [extension...]
00616  */
00617 static VALUE
00618 ossl_x509_get_extensions(VALUE self)
00619 {
00620     X509 *x509;
00621     int count, i;
00622     X509_EXTENSION *ext;
00623     VALUE ary;
00624 
00625     GetX509(self, x509);
00626     count = X509_get_ext_count(x509);
00627     if (count < 0) {
00628         return rb_ary_new();
00629     }
00630     ary = rb_ary_new2(count);
00631     for (i=0; i<count; i++) {
00632         ext = X509_get_ext(x509, i); /* NO DUP - don't free! */
00633         rb_ary_push(ary, ossl_x509ext_new(ext));
00634     }
00635 
00636     return ary;
00637 }
00638 
00639 /*
00640  * call-seq:
00641  *    cert.extensions = [ext...] => [ext...]
00642  */
00643 static VALUE
00644 ossl_x509_set_extensions(VALUE self, VALUE ary)
00645 {
00646     X509 *x509;
00647     X509_EXTENSION *ext;
00648     int i;
00649 
00650     Check_Type(ary, T_ARRAY);
00651     /* All ary's members should be X509Extension */
00652     for (i=0; i<RARRAY_LEN(ary); i++) {
00653         OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Ext);
00654     }
00655     GetX509(self, x509);
00656     sk_X509_EXTENSION_pop_free(x509->cert_info->extensions, X509_EXTENSION_free);
00657     x509->cert_info->extensions = NULL;
00658     for (i=0; i<RARRAY_LEN(ary); i++) {
00659         ext = DupX509ExtPtr(RARRAY_PTR(ary)[i]);
00660 
00661         if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext - FREE it */
00662             X509_EXTENSION_free(ext);
00663             ossl_raise(eX509CertError, NULL);
00664         }
00665         X509_EXTENSION_free(ext);
00666     }
00667 
00668     return ary;
00669 }
00670 
00671 /*
00672  * call-seq:
00673  *    cert.add_extension(extension) => extension
00674  */
00675 static VALUE
00676 ossl_x509_add_extension(VALUE self, VALUE extension)
00677 {
00678     X509 *x509;
00679     X509_EXTENSION *ext;
00680 
00681     GetX509(self, x509);
00682     ext = DupX509ExtPtr(extension);
00683     if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext - FREE it */
00684         X509_EXTENSION_free(ext);
00685         ossl_raise(eX509CertError, NULL);
00686     }
00687     X509_EXTENSION_free(ext);
00688 
00689     return extension;
00690 }
00691 
00692 static VALUE
00693 ossl_x509_inspect(VALUE self)
00694 {
00695     VALUE str;
00696     const char *cname = rb_class2name(rb_obj_class(self));
00697 
00698     str = rb_str_new2("#<");
00699     rb_str_cat2(str, cname);
00700     rb_str_cat2(str, " ");
00701 
00702     rb_str_cat2(str, "subject=");
00703     rb_str_append(str, rb_inspect(ossl_x509_get_subject(self)));
00704     rb_str_cat2(str, ", ");
00705 
00706     rb_str_cat2(str, "issuer=");
00707     rb_str_append(str, rb_inspect(ossl_x509_get_issuer(self)));
00708     rb_str_cat2(str, ", ");
00709 
00710     rb_str_cat2(str, "serial=");
00711     rb_str_append(str, rb_inspect(ossl_x509_get_serial(self)));
00712     rb_str_cat2(str, ", ");
00713 
00714     rb_str_cat2(str, "not_before=");
00715     rb_str_append(str, rb_inspect(ossl_x509_get_not_before(self)));
00716     rb_str_cat2(str, ", ");
00717 
00718     rb_str_cat2(str, "not_after=");
00719     rb_str_append(str, rb_inspect(ossl_x509_get_not_after(self)));
00720 
00721     str = rb_str_cat2(str, ">");
00722 
00723     return str;
00724 }
00725 
00726 /*
00727  * INIT
00728  */
00729 void
00730 Init_ossl_x509cert()
00731 {
00732 
00733 #if 0
00734     mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
00735     mX509 = rb_define_module_under(mOSSL, "X509");
00736 #endif
00737 
00738     eX509CertError = rb_define_class_under(mX509, "CertificateError", eOSSLError);
00739 
00740     /* Document-class: OpenSSL::X509::Certificate
00741      *
00742      * Implementation of an X.509 certificate as specified in RFC 5280.
00743      * Provides access to a certificate's attributes and allows certificates
00744      * to be read from a string, but also supports the creation of new
00745      * certificates from scratch.
00746      *
00747      * === Reading a certificate from a file
00748      *
00749      * Certificate is capable of handling DER-encoded certificates and
00750      * certificates encoded in OpenSSL's PEM format.
00751      *
00752      *   raw = File.read "cert.cer" # DER- or PEM-encoded
00753      *   certificate = OpenSSL::X509::Certificate.new raw
00754      *
00755      * === Saving a certificate to a file
00756      *
00757      * A certificate may be encoded in DER format
00758      *
00759      *   cert = ...
00760      *   File.open("cert.cer", "wb") { |f| f.print cert.to_der }
00761      *
00762      * or in PEM format
00763      *
00764      *   cert = ...
00765      *   File.open("cert.pem", "wb") { |f| f.print cert.to_pem }
00766      *
00767      * X.509 certificates are associated with a private/public key pair,
00768      * typically a RSA, DSA or ECC key (see also OpenSSL::PKey::RSA,
00769      * OpenSSL::PKey::DSA and OpenSSL::PKey::EC), the public key itself is
00770      * stored within the certificate and can be accessed in form of an
00771      * OpenSSL::PKey. Certificates are typically used to be able to associate
00772      * some form of identity with a key pair, for example web servers serving
00773      * pages over HTTPs use certificates to authenticate themselves to the user.
00774      *
00775      * The public key infrastructure (PKI) model relies on trusted certificate
00776      * authorities ("root CAs") that issue these certificates, so that end
00777      * users need to base their trust just on a selected few authorities
00778      * that themselves again vouch for subordinate CAs issuing their
00779      * certificates to end users.
00780      *
00781      * The OpenSSL::X509 module provides the tools to set up an independent
00782      * PKI, similar to scenarios where the 'openssl' command line tool is
00783      * used for issuing certificates in a private PKI.
00784      *
00785      * === Creating a root CA certificate and an end-entity certificate
00786      *
00787      * First, we need to create a "self-signed" root certificate. To do so,
00788      * we need to generate a key first. Please note that the choice of "1"
00789      * as a serial number is considered a security flaw for real certificates.
00790      * Secure choices are integers in the two-digit byte range and ideally
00791      * not sequential but secure random numbers, steps omitted here to keep
00792      * the example concise.
00793      *
00794      *   root_key = OpenSSL::PKey::RSA.new 2048 # the CA's public/private key
00795      *   root_ca = OpenSSL::X509::Certificate.new
00796      *   root_ca.version = 2 # cf. RFC 5280 - to make it a "v3" certificate
00797      *   root_ca.serial = 1
00798      *   root_ca.subject = OpenSSL::X509::Name.parse "/DC=org/DC=ruby-lang/CN=Ruby CA"
00799      *   root_ca.issuer = root_ca.subject # root CA's are "self-signed"
00800      *   root_ca.public_key = root_key.public_key
00801      *   root_ca.not_before = Time.now
00802      *   root_ca.not_after = root_ca.not_before + 2 * 365 * 24 * 60 * 60 # 2 years validity
00803      *   ef = OpenSSL::X509::ExtensionFactory.new
00804      *   ef.subject_certificate = root_ca
00805      *   ef.issuer_certificate = root_ca
00806      *   root_ca.add_extension(ef.create_extension("basicConstraints","CA:TRUE",true))
00807      *   root_ca.add_extension(ef.create_extension("keyUsage","keyCertSign, cRLSign", true))
00808      *   root_ca.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
00809      *   root_ca.add_extension(ef.create_extension("authorityKeyIdentifier","keyid:always",false))
00810      *   root_ca.sign(root_key, OpenSSL::Digest::SHA256.new)
00811      *
00812      * The next step is to create the end-entity certificate using the root CA
00813      * certificate.
00814      *
00815      *   key = OpenSSL::PKey::RSA.new 2048
00816      *   cert = OpenSSL::X509::Certificate.new
00817      *   cert.version = 2
00818      *   cert.serial = 2
00819      *   cert.subject = OpenSSL::X509::Name.parse "/DC=org/DC=ruby-lang/CN=Ruby certificate"
00820      *   cert.issuer = root_ca.subject # root CA is the issuer
00821      *   cert.public_key = key.public_key
00822      *   cert.not_before = Time.now
00823      *   cert.not_after = cert.not_before + 1 * 365 * 24 * 60 * 60 # 1 years validity
00824      *   ef = OpenSSL::X509::ExtensionFactory.new
00825      *   ef.subject_certificate = cert
00826      *   ef.issuer_certificate = root_ca
00827      *   cert.add_extension(ef.create_extension("keyUsage","digitalSignature", true))
00828      *   cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
00829      *   cert.sign(root_key, OpenSSL::Digest::SHA256.new)
00830      *
00831      */
00832 
00833     eX509CertError = rb_define_class_under(mX509, "CertificateError", eOSSLError);
00834 
00835     cX509Cert = rb_define_class_under(mX509, "Certificate", rb_cObject);
00836 
00837     rb_define_alloc_func(cX509Cert, ossl_x509_alloc);
00838     rb_define_method(cX509Cert, "initialize", ossl_x509_initialize, -1);
00839     rb_define_copy_func(cX509Cert, ossl_x509_copy);
00840 
00841     rb_define_method(cX509Cert, "to_der", ossl_x509_to_der, 0);
00842     rb_define_method(cX509Cert, "to_pem", ossl_x509_to_pem, 0);
00843     rb_define_alias(cX509Cert, "to_s", "to_pem");
00844     rb_define_method(cX509Cert, "to_text", ossl_x509_to_text, 0);
00845     rb_define_method(cX509Cert, "version", ossl_x509_get_version, 0);
00846     rb_define_method(cX509Cert, "version=", ossl_x509_set_version, 1);
00847     rb_define_method(cX509Cert, "signature_algorithm", ossl_x509_get_signature_algorithm, 0);
00848     rb_define_method(cX509Cert, "serial", ossl_x509_get_serial, 0);
00849     rb_define_method(cX509Cert, "serial=", ossl_x509_set_serial, 1);
00850     rb_define_method(cX509Cert, "subject", ossl_x509_get_subject, 0);
00851     rb_define_method(cX509Cert, "subject=", ossl_x509_set_subject, 1);
00852     rb_define_method(cX509Cert, "issuer", ossl_x509_get_issuer, 0);
00853     rb_define_method(cX509Cert, "issuer=", ossl_x509_set_issuer, 1);
00854     rb_define_method(cX509Cert, "not_before", ossl_x509_get_not_before, 0);
00855     rb_define_method(cX509Cert, "not_before=", ossl_x509_set_not_before, 1);
00856     rb_define_method(cX509Cert, "not_after", ossl_x509_get_not_after, 0);
00857     rb_define_method(cX509Cert, "not_after=", ossl_x509_set_not_after, 1);
00858     rb_define_method(cX509Cert, "public_key", ossl_x509_get_public_key, 0);
00859     rb_define_method(cX509Cert, "public_key=", ossl_x509_set_public_key, 1);
00860     rb_define_method(cX509Cert, "sign", ossl_x509_sign, 2);
00861     rb_define_method(cX509Cert, "verify", ossl_x509_verify, 1);
00862     rb_define_method(cX509Cert, "check_private_key", ossl_x509_check_private_key, 1);
00863     rb_define_method(cX509Cert, "extensions", ossl_x509_get_extensions, 0);
00864     rb_define_method(cX509Cert, "extensions=", ossl_x509_set_extensions, 1);
00865     rb_define_method(cX509Cert, "add_extension", ossl_x509_add_extension, 1);
00866     rb_define_method(cX509Cert, "inspect", ossl_x509_inspect, 0);
00867 }
00868 
00869