1 /*
2  * 'OpenSSL for Ruby' project
3  * Copyright (C) 2001-2002  Michal Rokos <m.rokos@sh.cvut.cz>
4  * All rights reserved.
5  */
6 /*
7  * This program is licensed under the same licence as Ruby.
8  * (See the file 'LICENCE'.)
9  */
10 #include "ossl.h"
11 
12 #define NewX509(klass) \
13     TypedData_Wrap_Struct((klass), &ossl_x509_type, 0)
14 #define SetX509(obj, x509) do { \
15     if (!(x509)) { \
16 	ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
17     } \
18     RTYPEDDATA_DATA(obj) = (x509); \
19 } while (0)
20 #define GetX509(obj, x509) do { \
21     TypedData_Get_Struct((obj), X509, &ossl_x509_type, (x509)); \
22     if (!(x509)) { \
23 	ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
24     } \
25 } while (0)
26 
27 /*
28  * Classes
29  */
30 VALUE cX509Cert;
31 VALUE eX509CertError;
32 
33 static void
ossl_x509_free(void * ptr)34 ossl_x509_free(void *ptr)
35 {
36     X509_free(ptr);
37 }
38 
39 static const rb_data_type_t ossl_x509_type = {
40     "OpenSSL/X509",
41     {
42 	0, ossl_x509_free,
43     },
44     0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
45 };
46 
47 /*
48  * Public
49  */
50 VALUE
ossl_x509_new(X509 * x509)51 ossl_x509_new(X509 *x509)
52 {
53     X509 *new;
54     VALUE obj;
55 
56     obj = NewX509(cX509Cert);
57     if (!x509) {
58 	new = X509_new();
59     } else {
60 	new = X509_dup(x509);
61     }
62     if (!new) {
63 	ossl_raise(eX509CertError, NULL);
64     }
65     SetX509(obj, new);
66 
67     return obj;
68 }
69 
70 X509 *
GetX509CertPtr(VALUE obj)71 GetX509CertPtr(VALUE obj)
72 {
73     X509 *x509;
74 
75     GetX509(obj, x509);
76 
77     return x509;
78 }
79 
80 X509 *
DupX509CertPtr(VALUE obj)81 DupX509CertPtr(VALUE obj)
82 {
83     X509 *x509;
84 
85     GetX509(obj, x509);
86 
87     X509_up_ref(x509);
88 
89     return x509;
90 }
91 
92 /*
93  * Private
94  */
95 static VALUE
ossl_x509_alloc(VALUE klass)96 ossl_x509_alloc(VALUE klass)
97 {
98     X509 *x509;
99     VALUE obj;
100 
101     obj = NewX509(klass);
102     x509 = X509_new();
103     if (!x509) ossl_raise(eX509CertError, NULL);
104     SetX509(obj, x509);
105 
106     return obj;
107 }
108 
109 /*
110  * call-seq:
111  *    Certificate.new => cert
112  *    Certificate.new(string) => cert
113  */
114 static VALUE
ossl_x509_initialize(int argc,VALUE * argv,VALUE self)115 ossl_x509_initialize(int argc, VALUE *argv, VALUE self)
116 {
117     BIO *in;
118     X509 *x509, *x = DATA_PTR(self);
119     VALUE arg;
120 
121     if (rb_scan_args(argc, argv, "01", &arg) == 0) {
122 	/* create just empty X509Cert */
123 	return self;
124     }
125     arg = ossl_to_der_if_possible(arg);
126     in = ossl_obj2bio(&arg);
127     x509 = PEM_read_bio_X509(in, &x, NULL, NULL);
128     DATA_PTR(self) = x;
129     if (!x509) {
130 	OSSL_BIO_reset(in);
131 	x509 = d2i_X509_bio(in, &x);
132 	DATA_PTR(self) = x;
133     }
134     BIO_free(in);
135     if (!x509) ossl_raise(eX509CertError, NULL);
136 
137     return self;
138 }
139 
140 static VALUE
ossl_x509_copy(VALUE self,VALUE other)141 ossl_x509_copy(VALUE self, VALUE other)
142 {
143     X509 *a, *b, *x509;
144 
145     rb_check_frozen(self);
146     if (self == other) return self;
147 
148     GetX509(self, a);
149     GetX509(other, b);
150 
151     x509 = X509_dup(b);
152     if (!x509) ossl_raise(eX509CertError, NULL);
153 
154     DATA_PTR(self) = x509;
155     X509_free(a);
156 
157     return self;
158 }
159 
160 /*
161  * call-seq:
162  *    cert.to_der => string
163  */
164 static VALUE
ossl_x509_to_der(VALUE self)165 ossl_x509_to_der(VALUE self)
166 {
167     X509 *x509;
168     VALUE str;
169     long len;
170     unsigned char *p;
171 
172     GetX509(self, x509);
173     if ((len = i2d_X509(x509, NULL)) <= 0)
174 	ossl_raise(eX509CertError, NULL);
175     str = rb_str_new(0, len);
176     p = (unsigned char *)RSTRING_PTR(str);
177     if (i2d_X509(x509, &p) <= 0)
178 	ossl_raise(eX509CertError, NULL);
179     ossl_str_adjust(str, p);
180 
181     return str;
182 }
183 
184 /*
185  * call-seq:
186  *    cert.to_pem => string
187  */
188 static VALUE
ossl_x509_to_pem(VALUE self)189 ossl_x509_to_pem(VALUE self)
190 {
191     X509 *x509;
192     BIO *out;
193     VALUE str;
194 
195     GetX509(self, x509);
196     out = BIO_new(BIO_s_mem());
197     if (!out) ossl_raise(eX509CertError, NULL);
198 
199     if (!PEM_write_bio_X509(out, x509)) {
200 	BIO_free(out);
201 	ossl_raise(eX509CertError, NULL);
202     }
203     str = ossl_membio2str(out);
204 
205     return str;
206 }
207 
208 /*
209  * call-seq:
210  *    cert.to_text => string
211  */
212 static VALUE
ossl_x509_to_text(VALUE self)213 ossl_x509_to_text(VALUE self)
214 {
215     X509 *x509;
216     BIO *out;
217     VALUE str;
218 
219     GetX509(self, x509);
220 
221     out = BIO_new(BIO_s_mem());
222     if (!out) ossl_raise(eX509CertError, NULL);
223 
224     if (!X509_print(out, x509)) {
225 	BIO_free(out);
226 	ossl_raise(eX509CertError, NULL);
227     }
228     str = ossl_membio2str(out);
229 
230     return str;
231 }
232 
233 #if 0
234 /*
235  * Makes from X509 X509_REQuest
236  */
237 static VALUE
238 ossl_x509_to_req(VALUE self)
239 {
240     X509 *x509;
241     X509_REQ *req;
242     VALUE obj;
243 
244     GetX509(self, x509);
245     if (!(req = X509_to_X509_REQ(x509, NULL, EVP_md5()))) {
246 	ossl_raise(eX509CertError, NULL);
247     }
248     obj = ossl_x509req_new(req);
249     X509_REQ_free(req);
250 
251     return obj;
252 }
253 #endif
254 
255 /*
256  * call-seq:
257  *    cert.version => integer
258  */
259 static VALUE
ossl_x509_get_version(VALUE self)260 ossl_x509_get_version(VALUE self)
261 {
262     X509 *x509;
263 
264     GetX509(self, x509);
265 
266     return LONG2NUM(X509_get_version(x509));
267 }
268 
269 /*
270  * call-seq:
271  *    cert.version = integer => integer
272  */
273 static VALUE
ossl_x509_set_version(VALUE self,VALUE version)274 ossl_x509_set_version(VALUE self, VALUE version)
275 {
276     X509 *x509;
277     long ver;
278 
279     if ((ver = NUM2LONG(version)) < 0) {
280 	ossl_raise(eX509CertError, "version must be >= 0!");
281     }
282     GetX509(self, x509);
283     if (!X509_set_version(x509, ver)) {
284 	ossl_raise(eX509CertError, NULL);
285     }
286 
287     return version;
288 }
289 
290 /*
291  * call-seq:
292  *    cert.serial => integer
293  */
294 static VALUE
ossl_x509_get_serial(VALUE self)295 ossl_x509_get_serial(VALUE self)
296 {
297     X509 *x509;
298 
299     GetX509(self, x509);
300 
301     return asn1integer_to_num(X509_get_serialNumber(x509));
302 }
303 
304 /*
305  * call-seq:
306  *    cert.serial = integer => integer
307  */
308 static VALUE
ossl_x509_set_serial(VALUE self,VALUE num)309 ossl_x509_set_serial(VALUE self, VALUE num)
310 {
311     X509 *x509;
312 
313     GetX509(self, x509);
314     X509_set_serialNumber(x509, num_to_asn1integer(num, X509_get_serialNumber(x509)));
315 
316     return num;
317 }
318 
319 /*
320  * call-seq:
321  *    cert.signature_algorithm => string
322  */
323 static VALUE
ossl_x509_get_signature_algorithm(VALUE self)324 ossl_x509_get_signature_algorithm(VALUE self)
325 {
326     X509 *x509;
327     BIO *out;
328     VALUE str;
329 
330     GetX509(self, x509);
331     out = BIO_new(BIO_s_mem());
332     if (!out) ossl_raise(eX509CertError, NULL);
333 
334     if (!i2a_ASN1_OBJECT(out, X509_get0_tbs_sigalg(x509)->algorithm)) {
335 	BIO_free(out);
336 	ossl_raise(eX509CertError, NULL);
337     }
338     str = ossl_membio2str(out);
339 
340     return str;
341 }
342 
343 /*
344  * call-seq:
345  *    cert.subject => name
346  */
347 static VALUE
ossl_x509_get_subject(VALUE self)348 ossl_x509_get_subject(VALUE self)
349 {
350     X509 *x509;
351     X509_NAME *name;
352 
353     GetX509(self, x509);
354     if (!(name = X509_get_subject_name(x509))) { /* NO DUP - don't free! */
355 	ossl_raise(eX509CertError, NULL);
356     }
357 
358     return ossl_x509name_new(name);
359 }
360 
361 /*
362  * call-seq:
363  *    cert.subject = name => name
364  */
365 static VALUE
ossl_x509_set_subject(VALUE self,VALUE subject)366 ossl_x509_set_subject(VALUE self, VALUE subject)
367 {
368     X509 *x509;
369 
370     GetX509(self, x509);
371     if (!X509_set_subject_name(x509, GetX509NamePtr(subject))) { /* DUPs name */
372 	ossl_raise(eX509CertError, NULL);
373     }
374 
375     return subject;
376 }
377 
378 /*
379  * call-seq:
380  *    cert.issuer => name
381  */
382 static VALUE
ossl_x509_get_issuer(VALUE self)383 ossl_x509_get_issuer(VALUE self)
384 {
385     X509 *x509;
386     X509_NAME *name;
387 
388     GetX509(self, x509);
389     if(!(name = X509_get_issuer_name(x509))) { /* NO DUP - don't free! */
390 	ossl_raise(eX509CertError, NULL);
391     }
392 
393     return ossl_x509name_new(name);
394 }
395 
396 /*
397  * call-seq:
398  *    cert.issuer = name => name
399  */
400 static VALUE
ossl_x509_set_issuer(VALUE self,VALUE issuer)401 ossl_x509_set_issuer(VALUE self, VALUE issuer)
402 {
403     X509 *x509;
404 
405     GetX509(self, x509);
406     if (!X509_set_issuer_name(x509, GetX509NamePtr(issuer))) { /* DUPs name */
407 	ossl_raise(eX509CertError, NULL);
408     }
409 
410     return issuer;
411 }
412 
413 /*
414  * call-seq:
415  *    cert.not_before => time
416  */
417 static VALUE
ossl_x509_get_not_before(VALUE self)418 ossl_x509_get_not_before(VALUE self)
419 {
420     X509 *x509;
421     const ASN1_TIME *asn1time;
422 
423     GetX509(self, x509);
424     if (!(asn1time = X509_get0_notBefore(x509))) {
425 	ossl_raise(eX509CertError, NULL);
426     }
427 
428     return asn1time_to_time(asn1time);
429 }
430 
431 /*
432  * call-seq:
433  *    cert.not_before = time => time
434  */
435 static VALUE
ossl_x509_set_not_before(VALUE self,VALUE time)436 ossl_x509_set_not_before(VALUE self, VALUE time)
437 {
438     X509 *x509;
439     ASN1_TIME *asn1time;
440 
441     GetX509(self, x509);
442     asn1time = ossl_x509_time_adjust(NULL, time);
443     if (!X509_set1_notBefore(x509, asn1time)) {
444 	ASN1_TIME_free(asn1time);
445 	ossl_raise(eX509CertError, "X509_set_notBefore");
446     }
447     ASN1_TIME_free(asn1time);
448 
449     return time;
450 }
451 
452 /*
453  * call-seq:
454  *    cert.not_after => time
455  */
456 static VALUE
ossl_x509_get_not_after(VALUE self)457 ossl_x509_get_not_after(VALUE self)
458 {
459     X509 *x509;
460     const ASN1_TIME *asn1time;
461 
462     GetX509(self, x509);
463     if (!(asn1time = X509_get0_notAfter(x509))) {
464 	ossl_raise(eX509CertError, NULL);
465     }
466 
467     return asn1time_to_time(asn1time);
468 }
469 
470 /*
471  * call-seq:
472  *    cert.not_after = time => time
473  */
474 static VALUE
ossl_x509_set_not_after(VALUE self,VALUE time)475 ossl_x509_set_not_after(VALUE self, VALUE time)
476 {
477     X509 *x509;
478     ASN1_TIME *asn1time;
479 
480     GetX509(self, x509);
481     asn1time = ossl_x509_time_adjust(NULL, time);
482     if (!X509_set1_notAfter(x509, asn1time)) {
483 	ASN1_TIME_free(asn1time);
484 	ossl_raise(eX509CertError, "X509_set_notAfter");
485     }
486     ASN1_TIME_free(asn1time);
487 
488     return time;
489 }
490 
491 /*
492  * call-seq:
493  *    cert.public_key => key
494  */
495 static VALUE
ossl_x509_get_public_key(VALUE self)496 ossl_x509_get_public_key(VALUE self)
497 {
498     X509 *x509;
499     EVP_PKEY *pkey;
500 
501     GetX509(self, x509);
502     if (!(pkey = X509_get_pubkey(x509))) { /* adds an reference */
503 	ossl_raise(eX509CertError, NULL);
504     }
505 
506     return ossl_pkey_new(pkey); /* NO DUP - OK */
507 }
508 
509 /*
510  * call-seq:
511  *    cert.public_key = key
512  */
513 static VALUE
ossl_x509_set_public_key(VALUE self,VALUE key)514 ossl_x509_set_public_key(VALUE self, VALUE key)
515 {
516     X509 *x509;
517     EVP_PKEY *pkey;
518 
519     GetX509(self, x509);
520     pkey = GetPKeyPtr(key);
521     ossl_pkey_check_public_key(pkey);
522     if (!X509_set_pubkey(x509, pkey))
523 	ossl_raise(eX509CertError, "X509_set_pubkey");
524     return key;
525 }
526 
527 /*
528  * call-seq:
529  *    cert.sign(key, digest) => self
530  */
531 static VALUE
ossl_x509_sign(VALUE self,VALUE key,VALUE digest)532 ossl_x509_sign(VALUE self, VALUE key, VALUE digest)
533 {
534     X509 *x509;
535     EVP_PKEY *pkey;
536     const EVP_MD *md;
537 
538     pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
539     md = ossl_evp_get_digestbyname(digest);
540     GetX509(self, x509);
541     if (!X509_sign(x509, pkey, md)) {
542 	ossl_raise(eX509CertError, NULL);
543     }
544 
545     return self;
546 }
547 
548 /*
549  * call-seq:
550  *    cert.verify(key) => true | false
551  *
552  * Verifies the signature of the certificate, with the public key _key_. _key_
553  * must be an instance of OpenSSL::PKey.
554  */
555 static VALUE
ossl_x509_verify(VALUE self,VALUE key)556 ossl_x509_verify(VALUE self, VALUE key)
557 {
558     X509 *x509;
559     EVP_PKEY *pkey;
560 
561     GetX509(self, x509);
562     pkey = GetPKeyPtr(key);
563     ossl_pkey_check_public_key(pkey);
564     switch (X509_verify(x509, pkey)) {
565       case 1:
566 	return Qtrue;
567       case 0:
568 	ossl_clear_error();
569 	return Qfalse;
570       default:
571 	ossl_raise(eX509CertError, NULL);
572     }
573 }
574 
575 /*
576  * call-seq:
577  *    cert.check_private_key(key) -> true | false
578  *
579  * Returns +true+ if _key_ is the corresponding private key to the Subject
580  * Public Key Information, +false+ otherwise.
581  */
582 static VALUE
ossl_x509_check_private_key(VALUE self,VALUE key)583 ossl_x509_check_private_key(VALUE self, VALUE key)
584 {
585     X509 *x509;
586     EVP_PKEY *pkey;
587 
588     /* not needed private key, but should be */
589     pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
590     GetX509(self, x509);
591     if (!X509_check_private_key(x509, pkey)) {
592 	ossl_clear_error();
593 	return Qfalse;
594     }
595 
596     return Qtrue;
597 }
598 
599 /*
600  * call-seq:
601  *    cert.extensions => [extension...]
602  */
603 static VALUE
ossl_x509_get_extensions(VALUE self)604 ossl_x509_get_extensions(VALUE self)
605 {
606     X509 *x509;
607     int count, i;
608     X509_EXTENSION *ext;
609     VALUE ary;
610 
611     GetX509(self, x509);
612     count = X509_get_ext_count(x509);
613     if (count < 0) {
614 	return rb_ary_new();
615     }
616     ary = rb_ary_new2(count);
617     for (i=0; i<count; i++) {
618 	ext = X509_get_ext(x509, i); /* NO DUP - don't free! */
619 	rb_ary_push(ary, ossl_x509ext_new(ext));
620     }
621 
622     return ary;
623 }
624 
625 /*
626  * call-seq:
627  *    cert.extensions = [ext...] => [ext...]
628  */
629 static VALUE
ossl_x509_set_extensions(VALUE self,VALUE ary)630 ossl_x509_set_extensions(VALUE self, VALUE ary)
631 {
632     X509 *x509;
633     X509_EXTENSION *ext;
634     long i;
635 
636     Check_Type(ary, T_ARRAY);
637     /* All ary's members should be X509Extension */
638     for (i=0; i<RARRAY_LEN(ary); i++) {
639 	OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
640     }
641     GetX509(self, x509);
642     while ((ext = X509_delete_ext(x509, 0)))
643 	X509_EXTENSION_free(ext);
644     for (i=0; i<RARRAY_LEN(ary); i++) {
645 	ext = GetX509ExtPtr(RARRAY_AREF(ary, i));
646 	if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext */
647 	    ossl_raise(eX509CertError, NULL);
648 	}
649     }
650 
651     return ary;
652 }
653 
654 /*
655  * call-seq:
656  *    cert.add_extension(extension) => extension
657  */
658 static VALUE
ossl_x509_add_extension(VALUE self,VALUE extension)659 ossl_x509_add_extension(VALUE self, VALUE extension)
660 {
661     X509 *x509;
662     X509_EXTENSION *ext;
663 
664     GetX509(self, x509);
665     ext = GetX509ExtPtr(extension);
666     if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext - FREE it */
667 	ossl_raise(eX509CertError, NULL);
668     }
669 
670     return extension;
671 }
672 
673 static VALUE
ossl_x509_inspect(VALUE self)674 ossl_x509_inspect(VALUE self)
675 {
676     return rb_sprintf("#<%"PRIsVALUE": subject=%+"PRIsVALUE", "
677 		      "issuer=%+"PRIsVALUE", serial=%+"PRIsVALUE", "
678 		      "not_before=%+"PRIsVALUE", not_after=%+"PRIsVALUE">",
679 		      rb_obj_class(self),
680 		      ossl_x509_get_subject(self),
681 		      ossl_x509_get_issuer(self),
682 		      ossl_x509_get_serial(self),
683 		      ossl_x509_get_not_before(self),
684 		      ossl_x509_get_not_after(self));
685 }
686 
687 /*
688  * call-seq:
689  *    cert1 == cert2 -> true | false
690  *
691  * Compares the two certificates. Note that this takes into account all fields,
692  * not just the issuer name and the serial number.
693  */
694 static VALUE
ossl_x509_eq(VALUE self,VALUE other)695 ossl_x509_eq(VALUE self, VALUE other)
696 {
697     X509 *a, *b;
698 
699     GetX509(self, a);
700     if (!rb_obj_is_kind_of(other, cX509Cert))
701 	return Qfalse;
702     GetX509(other, b);
703 
704     return !X509_cmp(a, b) ? Qtrue : Qfalse;
705 }
706 
707 /*
708  * INIT
709  */
710 void
Init_ossl_x509cert(void)711 Init_ossl_x509cert(void)
712 {
713 #if 0
714     mOSSL = rb_define_module("OpenSSL");
715     eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
716     mX509 = rb_define_module_under(mOSSL, "X509");
717 #endif
718 
719     eX509CertError = rb_define_class_under(mX509, "CertificateError", eOSSLError);
720 
721     /* Document-class: OpenSSL::X509::Certificate
722      *
723      * Implementation of an X.509 certificate as specified in RFC 5280.
724      * Provides access to a certificate's attributes and allows certificates
725      * to be read from a string, but also supports the creation of new
726      * certificates from scratch.
727      *
728      * === Reading a certificate from a file
729      *
730      * Certificate is capable of handling DER-encoded certificates and
731      * certificates encoded in OpenSSL's PEM format.
732      *
733      *   raw = File.read "cert.cer" # DER- or PEM-encoded
734      *   certificate = OpenSSL::X509::Certificate.new raw
735      *
736      * === Saving a certificate to a file
737      *
738      * A certificate may be encoded in DER format
739      *
740      *   cert = ...
741      *   File.open("cert.cer", "wb") { |f| f.print cert.to_der }
742      *
743      * or in PEM format
744      *
745      *   cert = ...
746      *   File.open("cert.pem", "wb") { |f| f.print cert.to_pem }
747      *
748      * X.509 certificates are associated with a private/public key pair,
749      * typically a RSA, DSA or ECC key (see also OpenSSL::PKey::RSA,
750      * OpenSSL::PKey::DSA and OpenSSL::PKey::EC), the public key itself is
751      * stored within the certificate and can be accessed in form of an
752      * OpenSSL::PKey. Certificates are typically used to be able to associate
753      * some form of identity with a key pair, for example web servers serving
754      * pages over HTTPs use certificates to authenticate themselves to the user.
755      *
756      * The public key infrastructure (PKI) model relies on trusted certificate
757      * authorities ("root CAs") that issue these certificates, so that end
758      * users need to base their trust just on a selected few authorities
759      * that themselves again vouch for subordinate CAs issuing their
760      * certificates to end users.
761      *
762      * The OpenSSL::X509 module provides the tools to set up an independent
763      * PKI, similar to scenarios where the 'openssl' command line tool is
764      * used for issuing certificates in a private PKI.
765      *
766      * === Creating a root CA certificate and an end-entity certificate
767      *
768      * First, we need to create a "self-signed" root certificate. To do so,
769      * we need to generate a key first. Please note that the choice of "1"
770      * as a serial number is considered a security flaw for real certificates.
771      * Secure choices are integers in the two-digit byte range and ideally
772      * not sequential but secure random numbers, steps omitted here to keep
773      * the example concise.
774      *
775      *   root_key = OpenSSL::PKey::RSA.new 2048 # the CA's public/private key
776      *   root_ca = OpenSSL::X509::Certificate.new
777      *   root_ca.version = 2 # cf. RFC 5280 - to make it a "v3" certificate
778      *   root_ca.serial = 1
779      *   root_ca.subject = OpenSSL::X509::Name.parse "/DC=org/DC=ruby-lang/CN=Ruby CA"
780      *   root_ca.issuer = root_ca.subject # root CA's are "self-signed"
781      *   root_ca.public_key = root_key.public_key
782      *   root_ca.not_before = Time.now
783      *   root_ca.not_after = root_ca.not_before + 2 * 365 * 24 * 60 * 60 # 2 years validity
784      *   ef = OpenSSL::X509::ExtensionFactory.new
785      *   ef.subject_certificate = root_ca
786      *   ef.issuer_certificate = root_ca
787      *   root_ca.add_extension(ef.create_extension("basicConstraints","CA:TRUE",true))
788      *   root_ca.add_extension(ef.create_extension("keyUsage","keyCertSign, cRLSign", true))
789      *   root_ca.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
790      *   root_ca.add_extension(ef.create_extension("authorityKeyIdentifier","keyid:always",false))
791      *   root_ca.sign(root_key, OpenSSL::Digest::SHA256.new)
792      *
793      * The next step is to create the end-entity certificate using the root CA
794      * certificate.
795      *
796      *   key = OpenSSL::PKey::RSA.new 2048
797      *   cert = OpenSSL::X509::Certificate.new
798      *   cert.version = 2
799      *   cert.serial = 2
800      *   cert.subject = OpenSSL::X509::Name.parse "/DC=org/DC=ruby-lang/CN=Ruby certificate"
801      *   cert.issuer = root_ca.subject # root CA is the issuer
802      *   cert.public_key = key.public_key
803      *   cert.not_before = Time.now
804      *   cert.not_after = cert.not_before + 1 * 365 * 24 * 60 * 60 # 1 years validity
805      *   ef = OpenSSL::X509::ExtensionFactory.new
806      *   ef.subject_certificate = cert
807      *   ef.issuer_certificate = root_ca
808      *   cert.add_extension(ef.create_extension("keyUsage","digitalSignature", true))
809      *   cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
810      *   cert.sign(root_key, OpenSSL::Digest::SHA256.new)
811      *
812      */
813     cX509Cert = rb_define_class_under(mX509, "Certificate", rb_cObject);
814 
815     rb_define_alloc_func(cX509Cert, ossl_x509_alloc);
816     rb_define_method(cX509Cert, "initialize", ossl_x509_initialize, -1);
817     rb_define_method(cX509Cert, "initialize_copy", ossl_x509_copy, 1);
818 
819     rb_define_method(cX509Cert, "to_der", ossl_x509_to_der, 0);
820     rb_define_method(cX509Cert, "to_pem", ossl_x509_to_pem, 0);
821     rb_define_alias(cX509Cert, "to_s", "to_pem");
822     rb_define_method(cX509Cert, "to_text", ossl_x509_to_text, 0);
823     rb_define_method(cX509Cert, "version", ossl_x509_get_version, 0);
824     rb_define_method(cX509Cert, "version=", ossl_x509_set_version, 1);
825     rb_define_method(cX509Cert, "signature_algorithm", ossl_x509_get_signature_algorithm, 0);
826     rb_define_method(cX509Cert, "serial", ossl_x509_get_serial, 0);
827     rb_define_method(cX509Cert, "serial=", ossl_x509_set_serial, 1);
828     rb_define_method(cX509Cert, "subject", ossl_x509_get_subject, 0);
829     rb_define_method(cX509Cert, "subject=", ossl_x509_set_subject, 1);
830     rb_define_method(cX509Cert, "issuer", ossl_x509_get_issuer, 0);
831     rb_define_method(cX509Cert, "issuer=", ossl_x509_set_issuer, 1);
832     rb_define_method(cX509Cert, "not_before", ossl_x509_get_not_before, 0);
833     rb_define_method(cX509Cert, "not_before=", ossl_x509_set_not_before, 1);
834     rb_define_method(cX509Cert, "not_after", ossl_x509_get_not_after, 0);
835     rb_define_method(cX509Cert, "not_after=", ossl_x509_set_not_after, 1);
836     rb_define_method(cX509Cert, "public_key", ossl_x509_get_public_key, 0);
837     rb_define_method(cX509Cert, "public_key=", ossl_x509_set_public_key, 1);
838     rb_define_method(cX509Cert, "sign", ossl_x509_sign, 2);
839     rb_define_method(cX509Cert, "verify", ossl_x509_verify, 1);
840     rb_define_method(cX509Cert, "check_private_key", ossl_x509_check_private_key, 1);
841     rb_define_method(cX509Cert, "extensions", ossl_x509_get_extensions, 0);
842     rb_define_method(cX509Cert, "extensions=", ossl_x509_set_extensions, 1);
843     rb_define_method(cX509Cert, "add_extension", ossl_x509_add_extension, 1);
844     rb_define_method(cX509Cert, "inspect", ossl_x509_inspect, 0);
845     rb_define_method(cX509Cert, "==", ossl_x509_eq, 1);
846 }
847