3 * 'OpenSSL for Ruby' team members
8 * This program is licenced under the same licence as Ruby.
9 * (See the file 'LICENCE'.)
13 #if defined(HAVE_SYS_TIME_H)
14 # include <sys/time.h>
15 #elif !defined(NT) && !defined(_WIN32)
17 long tv_sec
; /* seconds */
18 long tv_usec
; /* and microseconds */
26 asn1time_to_time(ASN1_TIME
*time
)
31 if (!time
|| !time
->data
) return Qnil
;
32 memset(&tm
, 0, sizeof(struct tm
));
36 if (sscanf((const char *)time
->data
, "%2d%2d%2d%2d%2d%2dZ", &tm
.tm_year
, &tm
.tm_mon
,
37 &tm
.tm_mday
, &tm
.tm_hour
, &tm
.tm_min
, &tm
.tm_sec
) != 6) {
38 ossl_raise(rb_eTypeError
, "bad UTCTIME format");
40 if (tm
.tm_year
< 69) {
46 case V_ASN1_GENERALIZEDTIME
:
47 if (sscanf((const char *)time
->data
, "%4d%2d%2d%2d%2d%2dZ", &tm
.tm_year
, &tm
.tm_mon
,
48 &tm
.tm_mday
, &tm
.tm_hour
, &tm
.tm_min
, &tm
.tm_sec
) != 6) {
49 ossl_raise(rb_eTypeError
, "bad GENERALIZEDTIME format" );
53 rb_warning("unknown time format");
56 argv
[0] = INT2NUM(tm
.tm_year
);
57 argv
[1] = INT2NUM(tm
.tm_mon
);
58 argv
[2] = INT2NUM(tm
.tm_mday
);
59 argv
[3] = INT2NUM(tm
.tm_hour
);
60 argv
[4] = INT2NUM(tm
.tm_min
);
61 argv
[5] = INT2NUM(tm
.tm_sec
);
63 return rb_funcall2(rb_cTime
, rb_intern("utc"), 6, argv
);
67 * This function is not exported in Ruby's *.h
69 extern struct timeval
rb_time_timeval(VALUE
);
72 time_to_time_t(VALUE time
)
74 return (time_t)NUM2LONG(rb_Integer(time
));
81 asn1str_to_str(ASN1_STRING
*str
)
83 return rb_str_new((const char *)str
->data
, str
->length
);
87 * ASN1_INTEGER conversions
88 * TODO: Make a decision what's the right way to do this.
90 #define DO_IT_VIA_RUBY 0
92 asn1integer_to_num(ASN1_INTEGER
*ai
)
101 ossl_raise(rb_eTypeError
, "ASN1_INTEGER is NULL!");
103 if (!(bn
= ASN1_INTEGER_to_BN(ai
, NULL
))) {
104 ossl_raise(eOSSLError
, NULL
);
107 if (!(txt
= BN_bn2dec(bn
))) {
109 ossl_raise(eOSSLError
, NULL
);
111 num
= rb_cstr_to_inum(txt
, 10, Qtrue
);
114 num
= ossl_bn_new(bn
);
123 num_to_asn1integer(VALUE obj
, ASN1_INTEGER
*ai
)
127 if (RTEST(rb_obj_is_kind_of(obj
, cBN
))) {
130 obj
= rb_String(obj
);
131 if (!BN_dec2bn(&bn
, StringValuePtr(obj
))) {
132 ossl_raise(eOSSLError
, NULL
);
135 if (!(ai
= BN_to_ASN1_INTEGER(bn
, ai
))) {
137 ossl_raise(eOSSLError
, NULL
);
144 num_to_asn1integer(VALUE obj
, ASN1_INTEGER
*ai
)
146 BIGNUM
*bn
= GetBNPtr(obj
);
148 if (!(ai
= BN_to_ASN1_INTEGER(bn
, ai
))) {
149 ossl_raise(eOSSLError
, NULL
);
159 #define ossl_asn1_get_value(o) rb_attr_get((o),rb_intern("@value"))
160 #define ossl_asn1_get_tag(o) rb_attr_get((o),rb_intern("@tag"))
161 #define ossl_asn1_get_tagging(o) rb_attr_get((o),rb_intern("@tagging"))
162 #define ossl_asn1_get_tag_class(o) rb_attr_get((o),rb_intern("@tag_class"))
164 #define ossl_asn1_set_value(o,v) rb_iv_set((o),"@value",(v))
165 #define ossl_asn1_set_tag(o,v) rb_iv_set((o),"@tag",(v))
166 #define ossl_asn1_set_tagging(o,v) rb_iv_set((o),"@tagging",(v))
167 #define ossl_asn1_set_tag_class(o,v) rb_iv_set((o),"@tag_class",(v))
173 VALUE cASN1Primitive
;
174 VALUE cASN1Constructive
;
176 VALUE cASN1Boolean
; /* BOOLEAN */
177 VALUE cASN1Integer
, cASN1Enumerated
; /* INTEGER */
178 VALUE cASN1BitString
; /* BIT STRING */
179 VALUE cASN1OctetString
, cASN1UTF8String
; /* STRINGs */
180 VALUE cASN1NumericString
, cASN1PrintableString
;
181 VALUE cASN1T61String
, cASN1VideotexString
;
182 VALUE cASN1IA5String
, cASN1GraphicString
;
183 VALUE cASN1ISO64String
, cASN1GeneralString
;
184 VALUE cASN1UniversalString
, cASN1BMPString
;
185 VALUE cASN1Null
; /* NULL */
186 VALUE cASN1ObjectId
; /* OBJECT IDENTIFIER */
187 VALUE cASN1UTCTime
, cASN1GeneralizedTime
; /* TIME */
188 VALUE cASN1Sequence
, cASN1Set
; /* CONSTRUCTIVE */
190 static ID sIMPLICIT
, sEXPLICIT
;
191 static ID sUNIVERSAL
, sAPPLICATION
, sCONTEXT_SPECIFIC
, sPRIVATE
;
194 * Ruby to ASN1 converters
197 obj_to_asn1bool(VALUE obj
)
199 return RTEST(obj
) ? 0xff : 0x100;
203 obj_to_asn1int(VALUE obj
)
205 return num_to_asn1integer(obj
, NULL
);
208 static ASN1_BIT_STRING
*
209 obj_to_asn1bstr(VALUE obj
, long unused_bits
)
211 ASN1_BIT_STRING
*bstr
;
213 if(unused_bits
< 0) unused_bits
= 0;
215 if(!(bstr
= ASN1_BIT_STRING_new()))
216 ossl_raise(eASN1Error
, NULL
);
217 ASN1_BIT_STRING_set(bstr
, (unsigned char *)RSTRING_PTR(obj
), RSTRING_LEN(obj
));
218 bstr
->flags
&= ~(ASN1_STRING_FLAG_BITS_LEFT
|0x07); /* clear */
219 bstr
->flags
|= ASN1_STRING_FLAG_BITS_LEFT
|(unused_bits
&0x07);
225 obj_to_asn1str(VALUE obj
)
230 if(!(str
= ASN1_STRING_new()))
231 ossl_raise(eASN1Error
, NULL
);
232 ASN1_STRING_set(str
, RSTRING_PTR(obj
), RSTRING_LEN(obj
));
238 obj_to_asn1null(VALUE obj
)
243 ossl_raise(eASN1Error
, "nil expected");
244 if(!(null
= ASN1_NULL_new()))
245 ossl_raise(eASN1Error
, NULL
);
251 obj_to_asn1obj(VALUE obj
)
256 a1obj
= OBJ_txt2obj(RSTRING_PTR(obj
), 0);
257 if(!a1obj
) a1obj
= OBJ_txt2obj(RSTRING_PTR(obj
), 1);
258 if(!a1obj
) ossl_raise(eASN1Error
, "invalid OBJECT ID");
264 obj_to_asn1utime(VALUE time
)
269 sec
= time_to_time_t(time
);
270 if(!(t
= ASN1_UTCTIME_set(NULL
, sec
)))
271 ossl_raise(eASN1Error
, NULL
);
276 static ASN1_GENERALIZEDTIME
*
277 obj_to_asn1gtime(VALUE time
)
280 ASN1_GENERALIZEDTIME
*t
;
282 sec
= time_to_time_t(time
);
283 if(!(t
=ASN1_GENERALIZEDTIME_set(NULL
, sec
)))
284 ossl_raise(eASN1Error
, NULL
);
290 obj_to_asn1derstr(VALUE obj
)
295 str
= ossl_to_der(obj
);
296 if(!(a1str
= ASN1_STRING_new()))
297 ossl_raise(eASN1Error
, NULL
);
298 ASN1_STRING_set(a1str
, RSTRING_PTR(str
), RSTRING_LEN(str
));
304 * DER to Ruby converters
307 decode_bool(unsigned char* der
, int length
)
310 const unsigned char *p
;
313 if((bool = d2i_ASN1_BOOLEAN(NULL
, &p
, length
)) < 0)
314 ossl_raise(eASN1Error
, NULL
);
316 return bool ? Qtrue
: Qfalse
;
320 decode_int(unsigned char* der
, int length
)
323 const unsigned char *p
;
328 if(!(ai
= d2i_ASN1_INTEGER(NULL
, &p
, length
)))
329 ossl_raise(eASN1Error
, NULL
);
330 ret
= rb_protect((VALUE(*)_((VALUE
)))asn1integer_to_num
,
332 ASN1_INTEGER_free(ai
);
333 if(status
) rb_jump_tag(status
);
339 decode_bstr(unsigned char* der
, int length
, long *unused_bits
)
341 ASN1_BIT_STRING
*bstr
;
342 const unsigned char *p
;
347 if(!(bstr
= d2i_ASN1_BIT_STRING(NULL
, &p
, length
)))
348 ossl_raise(eASN1Error
, NULL
);
351 if(bstr
->flags
& ASN1_STRING_FLAG_BITS_LEFT
)
352 *unused_bits
= bstr
->flags
& 0x07;
353 ret
= rb_str_new((const char *)bstr
->data
, len
);
354 ASN1_BIT_STRING_free(bstr
);
360 decode_enum(unsigned char* der
, int length
)
363 const unsigned char *p
;
368 if(!(ai
= d2i_ASN1_ENUMERATED(NULL
, &p
, length
)))
369 ossl_raise(eASN1Error
, NULL
);
370 ret
= rb_protect((VALUE(*)_((VALUE
)))asn1integer_to_num
,
372 ASN1_ENUMERATED_free(ai
);
373 if(status
) rb_jump_tag(status
);
379 decode_null(unsigned char* der
, int length
)
382 const unsigned char *p
;
385 if(!(null
= d2i_ASN1_NULL(NULL
, &p
, length
)))
386 ossl_raise(eASN1Error
, NULL
);
387 ASN1_NULL_free(null
);
393 decode_obj(unsigned char* der
, int length
)
396 const unsigned char *p
;
402 if(!(obj
= d2i_ASN1_OBJECT(NULL
, &p
, length
)))
403 ossl_raise(eASN1Error
, NULL
);
404 if((nid
= OBJ_obj2nid(obj
)) != NID_undef
){
405 ASN1_OBJECT_free(obj
);
406 ret
= rb_str_new2(OBJ_nid2sn(nid
));
409 if(!(bio
= BIO_new(BIO_s_mem()))){
410 ASN1_OBJECT_free(obj
);
411 ossl_raise(eASN1Error
, NULL
);
413 i2a_ASN1_OBJECT(bio
, obj
);
414 ASN1_OBJECT_free(obj
);
415 ret
= ossl_membio2str(bio
);
422 decode_time(unsigned char* der
, int length
)
425 const unsigned char *p
;
430 if(!(time
= d2i_ASN1_TIME(NULL
, &p
, length
)))
431 ossl_raise(eASN1Error
, NULL
);
432 ret
= rb_protect((VALUE(*)_((VALUE
)))asn1time_to_time
,
433 (VALUE
)time
, &status
);
434 ASN1_TIME_free(time
);
435 if(status
) rb_jump_tag(status
);
447 static ossl_asn1_info_t ossl_asn1_info
[] = {
448 { "EOC", NULL
, }, /* 0 */
449 { "BOOLEAN", &cASN1Boolean
, }, /* 1 */
450 { "INTEGER", &cASN1Integer
, }, /* 2 */
451 { "BIT_STRING", &cASN1BitString
, }, /* 3 */
452 { "OCTET_STRING", &cASN1OctetString
, }, /* 4 */
453 { "NULL", &cASN1Null
, }, /* 5 */
454 { "OBJECT", &cASN1ObjectId
, }, /* 6 */
455 { "OBJECT_DESCRIPTOR", NULL
, }, /* 7 */
456 { "EXTERNAL", NULL
, }, /* 8 */
457 { "REAL", NULL
, }, /* 9 */
458 { "ENUMERATED", &cASN1Enumerated
, }, /* 10 */
459 { "EMBEDDED_PDV", NULL
, }, /* 11 */
460 { "UTF8STRING", &cASN1UTF8String
, }, /* 12 */
461 { "RELATIVE_OID", NULL
, }, /* 13 */
462 { "[UNIVERSAL 14]", NULL
, }, /* 14 */
463 { "[UNIVERSAL 15]", NULL
, }, /* 15 */
464 { "SEQUENCE", &cASN1Sequence
, }, /* 16 */
465 { "SET", &cASN1Set
, }, /* 17 */
466 { "NUMERICSTRING", &cASN1NumericString
, }, /* 18 */
467 { "PRINTABLESTRING", &cASN1PrintableString
, }, /* 19 */
468 { "T61STRING", &cASN1T61String
, }, /* 20 */
469 { "VIDEOTEXSTRING", &cASN1VideotexString
, }, /* 21 */
470 { "IA5STRING", &cASN1IA5String
, }, /* 22 */
471 { "UTCTIME", &cASN1UTCTime
, }, /* 23 */
472 { "GENERALIZEDTIME", &cASN1GeneralizedTime
, }, /* 24 */
473 { "GRAPHICSTRING", &cASN1GraphicString
, }, /* 25 */
474 { "ISO64STRING", &cASN1ISO64String
, }, /* 26 */
475 { "GENERALSTRING", &cASN1GeneralString
, }, /* 27 */
476 { "UNIVERSALSTRING", &cASN1UniversalString
, }, /* 28 */
477 { "CHARACTER_STRING", NULL
, }, /* 29 */
478 { "BMPSTRING", &cASN1BMPString
, }, /* 30 */
481 int ossl_asn1_info_size
= (sizeof(ossl_asn1_info
)/sizeof(ossl_asn1_info
[0]));
483 static int ossl_asn1_default_tag(VALUE obj
);
486 ossl_asn1_get_asn1type(VALUE obj
)
494 tag
= ossl_asn1_default_tag(obj
);
495 value
= ossl_asn1_get_value(obj
);
498 ptr
= (void*)(VALUE
)obj_to_asn1bool(value
);
501 case V_ASN1_INTEGER
: /* FALLTHROUGH */
502 case V_ASN1_ENUMERATED
:
503 ptr
= obj_to_asn1int(value
);
504 free_func
= ASN1_INTEGER_free
;
506 case V_ASN1_BIT_STRING
:
507 rflag
= rb_attr_get(obj
, rb_intern("@unused_bits"));
508 flag
= NIL_P(rflag
) ? -1 : NUM2INT(rflag
);
509 ptr
= obj_to_asn1bstr(value
, flag
);
510 free_func
= ASN1_BIT_STRING_free
;
513 ptr
= obj_to_asn1null(value
);
514 free_func
= ASN1_NULL_free
;
516 case V_ASN1_OCTET_STRING
: /* FALLTHROUGH */
517 case V_ASN1_UTF8STRING
: /* FALLTHROUGH */
518 case V_ASN1_NUMERICSTRING
: /* FALLTHROUGH */
519 case V_ASN1_PRINTABLESTRING
: /* FALLTHROUGH */
520 case V_ASN1_T61STRING
: /* FALLTHROUGH */
521 case V_ASN1_VIDEOTEXSTRING
: /* FALLTHROUGH */
522 case V_ASN1_IA5STRING
: /* FALLTHROUGH */
523 case V_ASN1_GRAPHICSTRING
: /* FALLTHROUGH */
524 case V_ASN1_ISO64STRING
: /* FALLTHROUGH */
525 case V_ASN1_GENERALSTRING
: /* FALLTHROUGH */
526 case V_ASN1_UNIVERSALSTRING
: /* FALLTHROUGH */
527 case V_ASN1_BMPSTRING
:
528 ptr
= obj_to_asn1str(value
);
529 free_func
= ASN1_STRING_free
;
532 ptr
= obj_to_asn1obj(value
);
533 free_func
= ASN1_OBJECT_free
;
536 ptr
= obj_to_asn1utime(value
);
537 free_func
= ASN1_TIME_free
;
539 case V_ASN1_GENERALIZEDTIME
:
540 ptr
= obj_to_asn1gtime(value
);
541 free_func
= ASN1_TIME_free
;
543 case V_ASN1_SET
: /* FALLTHROUGH */
544 case V_ASN1_SEQUENCE
:
545 ptr
= obj_to_asn1derstr(obj
);
546 free_func
= ASN1_STRING_free
;
549 ossl_raise(eASN1Error
, "unsupported ASN.1 type");
551 if(!(ret
= OPENSSL_malloc(sizeof(ASN1_TYPE
)))){
552 if(free_func
) free_func(ptr
);
553 ossl_raise(eASN1Error
, "ASN1_TYPE alloc failure");
555 memset(ret
, 0, sizeof(ASN1_TYPE
));
556 ASN1_TYPE_set(ret
, tag
, ptr
);
562 ossl_asn1_default_tag(VALUE obj
)
566 for(i
= 0; i
< ossl_asn1_info_size
; i
++){
567 if(ossl_asn1_info
[i
].klass
&&
568 rb_obj_is_kind_of(obj
, *ossl_asn1_info
[i
].klass
)){
572 ossl_raise(eASN1Error
, "universal tag for %s not found",
573 rb_class2name(CLASS_OF(obj
)));
575 return -1; /* dummy */
579 ossl_asn1_tag(VALUE obj
)
583 tag
= ossl_asn1_get_tag(obj
);
585 ossl_raise(eASN1Error
, "tag number not specified");
591 ossl_asn1_is_explicit(VALUE obj
)
596 s
= ossl_asn1_get_tagging(obj
);
597 if(NIL_P(s
)) return 0;
598 else if(SYMBOL_P(s
)){
599 if (SYM2ID(s
) == sIMPLICIT
)
601 else if (SYM2ID(s
) == sEXPLICIT
)
605 ossl_raise(eASN1Error
, "invalid tag default");
612 ossl_asn1_tag_class(VALUE obj
)
617 s
= ossl_asn1_get_tag_class(obj
);
618 if(NIL_P(s
)) ret
= V_ASN1_UNIVERSAL
;
619 else if(SYMBOL_P(s
)){
620 if (SYM2ID(s
) == sUNIVERSAL
)
621 ret
= V_ASN1_UNIVERSAL
;
622 else if (SYM2ID(s
) == sAPPLICATION
)
623 ret
= V_ASN1_APPLICATION
;
624 else if (SYM2ID(s
) == sCONTEXT_SPECIFIC
)
625 ret
= V_ASN1_CONTEXT_SPECIFIC
;
626 else if (SYM2ID(s
) == sPRIVATE
)
627 ret
= V_ASN1_PRIVATE
;
630 ossl_raise(eASN1Error
, "invalid tag class");
637 ossl_asn1_class2sym(int tc
)
639 if((tc
& V_ASN1_PRIVATE
) == V_ASN1_PRIVATE
)
640 return ID2SYM(sPRIVATE
);
641 else if((tc
& V_ASN1_CONTEXT_SPECIFIC
) == V_ASN1_CONTEXT_SPECIFIC
)
642 return ID2SYM(sCONTEXT_SPECIFIC
);
643 else if((tc
& V_ASN1_APPLICATION
) == V_ASN1_APPLICATION
)
644 return ID2SYM(sAPPLICATION
);
646 return ID2SYM(sUNIVERSAL
);
650 ossl_asn1data_initialize(VALUE self
, VALUE value
, VALUE tag
, VALUE tag_class
)
652 if(!SYMBOL_P(tag_class
))
653 ossl_raise(eASN1Error
, "invalid tag class");
654 if((SYM2ID(tag_class
) == sUNIVERSAL
) && NUM2INT(tag
) > 31)
655 ossl_raise(eASN1Error
, "tag number for Universal too large");
656 ossl_asn1_set_tag(self
, tag
);
657 ossl_asn1_set_value(self
, value
);
658 ossl_asn1_set_tag_class(self
, tag_class
);
664 join_der_i(VALUE i
, VALUE str
)
666 i
= ossl_to_der_if_possible(i
);
668 rb_str_append(str
, i
);
673 join_der(VALUE enumerable
)
675 VALUE str
= rb_str_new(0, 0);
676 rb_block_call(enumerable
, rb_intern("each"), 0, 0, join_der_i
, str
);
681 ossl_asn1data_to_der(VALUE self
)
684 int tag
, tag_class
, is_cons
= 0;
688 value
= ossl_asn1_get_value(self
);
689 if(rb_obj_is_kind_of(value
, rb_cArray
)){
691 value
= join_der(value
);
695 tag
= ossl_asn1_tag(self
);
696 tag_class
= ossl_asn1_tag_class(self
);
697 if((length
= ASN1_object_size(1, RSTRING_LEN(value
), tag
)) <= 0)
698 ossl_raise(eASN1Error
, NULL
);
699 der
= rb_str_new(0, length
);
700 p
= (unsigned char *)RSTRING_PTR(der
);
701 ASN1_put_object(&p
, is_cons
, RSTRING_LEN(value
), tag
, tag_class
);
702 memcpy(p
, RSTRING_PTR(value
), RSTRING_LEN(value
));
703 p
+= RSTRING_LEN(value
);
704 ossl_str_adjust(der
, p
);
710 ossl_asn1_decode0(unsigned char **pp
, long length
, long *offset
, long depth
,
713 unsigned char *start
, *p
;
714 const unsigned char *p0
;
715 long len
, off
= *offset
;
716 int hlen
, tag
, tc
, j
;
717 VALUE ary
, asn1data
, value
, tag_class
;
724 j
= ASN1_get_object(&p0
, &len
, &tag
, &tc
, length
);
725 p
= (unsigned char *)p0
;
726 if(j
& 0x80) ossl_raise(eASN1Error
, NULL
);
729 VALUE arg
= rb_ary_new();
730 rb_ary_push(arg
, LONG2NUM(depth
));
731 rb_ary_push(arg
, LONG2NUM(off
));
732 rb_ary_push(arg
, LONG2NUM(hlen
));
733 rb_ary_push(arg
, LONG2NUM(len
));
734 rb_ary_push(arg
, (j
& V_ASN1_CONSTRUCTED
) ? Qtrue
: Qfalse
);
735 rb_ary_push(arg
, ossl_asn1_class2sym(tc
));
736 rb_ary_push(arg
, INT2NUM(tag
));
741 if(len
> length
) ossl_raise(eASN1Error
, "value is too short");
742 if((tc
& V_ASN1_PRIVATE
) == V_ASN1_PRIVATE
)
743 tag_class
= sPRIVATE
;
744 else if((tc
& V_ASN1_CONTEXT_SPECIFIC
) == V_ASN1_CONTEXT_SPECIFIC
)
745 tag_class
= sCONTEXT_SPECIFIC
;
746 else if((tc
& V_ASN1_APPLICATION
) == V_ASN1_APPLICATION
)
747 tag_class
= sAPPLICATION
;
749 tag_class
= sUNIVERSAL
;
750 if(j
& V_ASN1_CONSTRUCTED
){
751 /* TODO: if j == 0x21 it is indefinite length object. */
752 if((j
== 0x21) && (len
== 0)){
754 value
= ossl_asn1_decode0(&p
, length
, &off
, depth
+1, 0, yield
);
757 else value
= ossl_asn1_decode0(&p
, len
, &off
, depth
+1, 0, yield
);
760 value
= rb_str_new((const char *)p
, len
);
764 if(tag_class
== sUNIVERSAL
&&
765 tag
< ossl_asn1_info_size
&& ossl_asn1_info
[tag
].klass
){
766 VALUE klass
= *ossl_asn1_info
[tag
].klass
;
768 if(!rb_obj_is_kind_of(value
, rb_cArray
)){
771 value
= decode_bool(start
, hlen
+len
);
774 value
= decode_int(start
, hlen
+len
);
776 case V_ASN1_BIT_STRING
:
777 value
= decode_bstr(start
, hlen
+len
, &flag
);
780 value
= decode_null(start
, hlen
+len
);
782 case V_ASN1_ENUMERATED
:
783 value
= decode_enum(start
, hlen
+len
);
786 value
= decode_obj(start
, hlen
+len
);
788 case V_ASN1_UTCTIME
: /* FALLTHROUGH */
789 case V_ASN1_GENERALIZEDTIME
:
790 value
= decode_time(start
, hlen
+len
);
793 /* use original value */
797 asn1data
= rb_funcall(klass
, rb_intern("new"), 1, value
);
798 if(tag
== V_ASN1_BIT_STRING
){
799 rb_iv_set(asn1data
, "@unused_bits", LONG2NUM(flag
));
803 asn1data
= rb_funcall(cASN1Data
, rb_intern("new"), 3,
804 value
, INT2NUM(tag
), ID2SYM(tag_class
));
806 rb_ary_push(ary
, asn1data
);
817 ossl_asn1_traverse(VALUE self
, VALUE obj
)
823 obj
= ossl_to_der_if_possible(obj
);
824 tmp
= rb_str_new4(StringValue(obj
));
825 p
= (unsigned char *)RSTRING_PTR(tmp
);
826 ossl_asn1_decode0(&p
, RSTRING_LEN(tmp
), &offset
, 0, 0, 1);
832 ossl_asn1_decode(VALUE self
, VALUE obj
)
839 obj
= ossl_to_der_if_possible(obj
);
840 tmp
= rb_str_new4(StringValue(obj
));
841 p
= (unsigned char *)RSTRING_PTR(tmp
);
842 ary
= ossl_asn1_decode0(&p
, RSTRING_LEN(tmp
), &offset
, 0, 1, 0);
843 ret
= rb_ary_entry(ary
, 0);
849 ossl_asn1_decode_all(VALUE self
, VALUE obj
)
856 obj
= ossl_to_der_if_possible(obj
);
857 tmp
= rb_str_new4(StringValue(obj
));
858 p
= (unsigned char *)RSTRING_PTR(tmp
);
859 ret
= ossl_asn1_decode0(&p
, RSTRING_LEN(tmp
), &offset
, 0, 0, 0);
865 ossl_asn1_initialize(int argc
, VALUE
*argv
, VALUE self
)
867 VALUE value
, tag
, tagging
, tag_class
;
869 rb_scan_args(argc
, argv
, "13", &value
, &tag
, &tagging
, &tag_class
);
872 ossl_raise(eASN1Error
, "must specify tag number");
874 tagging
= ID2SYM(sEXPLICIT
);
875 if(!SYMBOL_P(tagging
))
876 ossl_raise(eASN1Error
, "invalid tag default");
878 tag_class
= ID2SYM(sCONTEXT_SPECIFIC
);
879 if(!SYMBOL_P(tag_class
))
880 ossl_raise(eASN1Error
, "invalid tag class");
881 if(SYM2ID(tagging
) == sIMPLICIT
&& NUM2INT(tag
) > 31)
882 ossl_raise(eASN1Error
, "tag number for Universal too large");
885 tag
= INT2NUM(ossl_asn1_default_tag(self
));
887 tag_class
= ID2SYM(sUNIVERSAL
);
889 ossl_asn1_set_tag(self
, tag
);
890 ossl_asn1_set_value(self
, value
);
891 ossl_asn1_set_tagging(self
, tagging
);
892 ossl_asn1_set_tag_class(self
, tag_class
);
898 ossl_i2d_ASN1_TYPE(ASN1_TYPE
*a
, unsigned char **pp
)
900 #if OPENSSL_VERSION_NUMBER < 0x00907000L
902 if(a
->type
== V_ASN1_BOOLEAN
)
903 return i2d_ASN1_BOOLEAN(a
->value
.boolean
, pp
);
905 return i2d_ASN1_TYPE(a
, pp
);
909 ossl_ASN1_TYPE_free(ASN1_TYPE
*a
)
911 #if OPENSSL_VERSION_NUMBER < 0x00907000L
913 if(a
->type
== V_ASN1_BOOLEAN
){
922 ossl_asn1prim_to_der(VALUE self
)
925 int tn
, tc
, explicit;
927 unsigned char *buf
, *p
;
930 tn
= NUM2INT(ossl_asn1_get_tag(self
));
931 tc
= ossl_asn1_tag_class(self
);
932 explicit = ossl_asn1_is_explicit(self
);
933 asn1
= ossl_asn1_get_asn1type(self
);
935 len
= ASN1_object_size(1, ossl_i2d_ASN1_TYPE(asn1
, NULL
), tn
);
936 if(!(buf
= OPENSSL_malloc(len
))){
937 ossl_ASN1_TYPE_free(asn1
);
938 ossl_raise(eASN1Error
, "cannot alloc buffer");
941 if (tc
== V_ASN1_UNIVERSAL
) {
942 ossl_i2d_ASN1_TYPE(asn1
, &p
);
943 } else if (explicit) {
944 ASN1_put_object(&p
, 1, ossl_i2d_ASN1_TYPE(asn1
, NULL
), tn
, tc
);
945 ossl_i2d_ASN1_TYPE(asn1
, &p
);
947 ossl_i2d_ASN1_TYPE(asn1
, &p
);
948 *buf
= tc
| tn
| (*buf
& V_ASN1_CONSTRUCTED
);
950 ossl_ASN1_TYPE_free(asn1
);
952 assert(reallen
<= len
);
953 str
= ossl_buf2str((char *)buf
, reallen
); /* buf will be free in ossl_buf2str */
959 ossl_asn1cons_to_der(VALUE self
)
961 int tag
, tn
, tc
, explicit;
962 long seq_len
, length
;
966 tag
= ossl_asn1_default_tag(self
);
967 tn
= NUM2INT(ossl_asn1_get_tag(self
));
968 tc
= ossl_asn1_tag_class(self
);
969 explicit = ossl_asn1_is_explicit(self
);
970 value
= join_der(ossl_asn1_get_value(self
));
972 seq_len
= ASN1_object_size(1, RSTRING_LEN(value
), tag
);
973 length
= ASN1_object_size(1, seq_len
, tn
);
974 str
= rb_str_new(0, length
);
975 p
= (unsigned char *)RSTRING_PTR(str
);
976 if(tc
== V_ASN1_UNIVERSAL
)
977 ASN1_put_object(&p
, 1, RSTRING_LEN(value
), tn
, tc
);
980 ASN1_put_object(&p
, 1, seq_len
, tn
, tc
);
981 ASN1_put_object(&p
, 1, RSTRING_LEN(value
), tag
, V_ASN1_UNIVERSAL
);
983 else ASN1_put_object(&p
, 1, RSTRING_LEN(value
), tn
, tc
);
985 memcpy(p
, RSTRING_PTR(value
), RSTRING_LEN(value
));
986 p
+= RSTRING_LEN(value
);
987 ossl_str_adjust(str
, p
);
993 ossl_asn1cons_each(VALUE self
)
995 rb_ary_each(ossl_asn1_get_value(self
));
1000 ossl_asn1obj_s_register(VALUE self
, VALUE oid
, VALUE sn
, VALUE ln
)
1006 if(!OBJ_create(RSTRING_PTR(oid
), RSTRING_PTR(sn
), RSTRING_PTR(ln
)))
1007 ossl_raise(eASN1Error
, NULL
);
1013 ossl_asn1obj_get_sn(VALUE self
)
1015 VALUE val
, ret
= Qnil
;
1018 val
= ossl_asn1_get_value(self
);
1019 if ((nid
= OBJ_txt2nid(StringValuePtr(val
))) != NID_undef
)
1020 ret
= rb_str_new2(OBJ_nid2sn(nid
));
1026 ossl_asn1obj_get_ln(VALUE self
)
1028 VALUE val
, ret
= Qnil
;
1031 val
= ossl_asn1_get_value(self
);
1032 if ((nid
= OBJ_txt2nid(StringValuePtr(val
))) != NID_undef
)
1033 ret
= rb_str_new2(OBJ_nid2ln(nid
));
1039 ossl_asn1obj_get_oid(VALUE self
)
1045 val
= ossl_asn1_get_value(self
);
1046 a1obj
= obj_to_asn1obj(val
);
1047 OBJ_obj2txt(buf
, sizeof(buf
), a1obj
, 1);
1048 ASN1_OBJECT_free(a1obj
);
1050 return rb_str_new2(buf
);
1053 #define OSSL_ASN1_IMPL_FACTORY_METHOD(klass) \
1054 static VALUE ossl_asn1_##klass(int argc, VALUE *argv, VALUE self)\
1055 { return rb_funcall3(cASN1##klass, rb_intern("new"), argc, argv); }
1057 OSSL_ASN1_IMPL_FACTORY_METHOD(Boolean
)
1058 OSSL_ASN1_IMPL_FACTORY_METHOD(Integer
)
1059 OSSL_ASN1_IMPL_FACTORY_METHOD(Enumerated
)
1060 OSSL_ASN1_IMPL_FACTORY_METHOD(BitString
)
1061 OSSL_ASN1_IMPL_FACTORY_METHOD(OctetString
)
1062 OSSL_ASN1_IMPL_FACTORY_METHOD(UTF8String
)
1063 OSSL_ASN1_IMPL_FACTORY_METHOD(NumericString
)
1064 OSSL_ASN1_IMPL_FACTORY_METHOD(PrintableString
)
1065 OSSL_ASN1_IMPL_FACTORY_METHOD(T61String
)
1066 OSSL_ASN1_IMPL_FACTORY_METHOD(VideotexString
)
1067 OSSL_ASN1_IMPL_FACTORY_METHOD(IA5String
)
1068 OSSL_ASN1_IMPL_FACTORY_METHOD(GraphicString
)
1069 OSSL_ASN1_IMPL_FACTORY_METHOD(ISO64String
)
1070 OSSL_ASN1_IMPL_FACTORY_METHOD(GeneralString
)
1071 OSSL_ASN1_IMPL_FACTORY_METHOD(UniversalString
)
1072 OSSL_ASN1_IMPL_FACTORY_METHOD(BMPString
)
1073 OSSL_ASN1_IMPL_FACTORY_METHOD(Null
)
1074 OSSL_ASN1_IMPL_FACTORY_METHOD(ObjectId
)
1075 OSSL_ASN1_IMPL_FACTORY_METHOD(UTCTime
)
1076 OSSL_ASN1_IMPL_FACTORY_METHOD(GeneralizedTime
)
1077 OSSL_ASN1_IMPL_FACTORY_METHOD(Sequence
)
1078 OSSL_ASN1_IMPL_FACTORY_METHOD(Set
)
1086 #if 0 /* let rdoc know about mOSSL */
1087 mOSSL
= rb_define_module("OpenSSL");
1090 sUNIVERSAL
= rb_intern("UNIVERSAL");
1091 sCONTEXT_SPECIFIC
= rb_intern("CONTEXT_SPECIFIC");
1092 sAPPLICATION
= rb_intern("APPLICATION");
1093 sPRIVATE
= rb_intern("PRIVATE");
1094 sEXPLICIT
= rb_intern("EXPLICIT");
1095 sIMPLICIT
= rb_intern("IMPLICIT");
1097 mASN1
= rb_define_module_under(mOSSL
, "ASN1");
1098 eASN1Error
= rb_define_class_under(mASN1
, "ASN1Error", eOSSLError
);
1099 rb_define_module_function(mASN1
, "traverse", ossl_asn1_traverse
, 1);
1100 rb_define_module_function(mASN1
, "decode", ossl_asn1_decode
, 1);
1101 rb_define_module_function(mASN1
, "decode_all", ossl_asn1_decode_all
, 1);
1103 rb_define_const(mASN1
, "UNIVERSAL_TAG_NAME", ary
);
1104 for(i
= 0; i
< ossl_asn1_info_size
; i
++){
1105 if(ossl_asn1_info
[i
].name
[0] == '[') continue;
1106 rb_define_const(mASN1
, ossl_asn1_info
[i
].name
, INT2NUM(i
));
1107 rb_ary_store(ary
, i
, rb_str_new2(ossl_asn1_info
[i
].name
));
1110 cASN1Data
= rb_define_class_under(mASN1
, "ASN1Data", rb_cObject
);
1111 rb_attr(cASN1Data
, rb_intern("value"), 1, 1, 0);
1112 rb_attr(cASN1Data
, rb_intern("tag"), 1, 1, 0);
1113 rb_attr(cASN1Data
, rb_intern("tag_class"), 1, 1, 0);
1114 rb_define_method(cASN1Data
, "initialize", ossl_asn1data_initialize
, 3);
1115 rb_define_method(cASN1Data
, "to_der", ossl_asn1data_to_der
, 0);
1117 cASN1Primitive
= rb_define_class_under(mASN1
, "Primitive", cASN1Data
);
1118 rb_attr(cASN1Primitive
, rb_intern("tagging"), 1, 1, Qtrue
);
1119 rb_define_method(cASN1Primitive
, "initialize", ossl_asn1_initialize
, -1);
1120 rb_define_method(cASN1Primitive
, "to_der", ossl_asn1prim_to_der
, 0);
1122 cASN1Constructive
= rb_define_class_under(mASN1
,"Constructive", cASN1Data
);
1123 rb_include_module(cASN1Constructive
, rb_mEnumerable
);
1124 rb_attr(cASN1Constructive
, rb_intern("tagging"), 1, 1, Qtrue
);
1125 rb_define_method(cASN1Constructive
, "initialize", ossl_asn1_initialize
, -1);
1126 rb_define_method(cASN1Constructive
, "to_der", ossl_asn1cons_to_der
, 0);
1127 rb_define_method(cASN1Constructive
, "each", ossl_asn1cons_each
, 0);
1129 #define OSSL_ASN1_DEFINE_CLASS(name, super) \
1131 cASN1##name = rb_define_class_under(mASN1, #name, cASN1##super);\
1132 rb_define_module_function(mASN1, #name, ossl_asn1_##name, -1);\
1135 OSSL_ASN1_DEFINE_CLASS(Boolean
, Primitive
);
1136 OSSL_ASN1_DEFINE_CLASS(Integer
, Primitive
);
1137 OSSL_ASN1_DEFINE_CLASS(Enumerated
, Primitive
);
1138 OSSL_ASN1_DEFINE_CLASS(BitString
, Primitive
);
1139 OSSL_ASN1_DEFINE_CLASS(OctetString
, Primitive
);
1140 OSSL_ASN1_DEFINE_CLASS(UTF8String
, Primitive
);
1141 OSSL_ASN1_DEFINE_CLASS(NumericString
, Primitive
);
1142 OSSL_ASN1_DEFINE_CLASS(PrintableString
, Primitive
);
1143 OSSL_ASN1_DEFINE_CLASS(T61String
, Primitive
);
1144 OSSL_ASN1_DEFINE_CLASS(VideotexString
, Primitive
);
1145 OSSL_ASN1_DEFINE_CLASS(IA5String
, Primitive
);
1146 OSSL_ASN1_DEFINE_CLASS(GraphicString
, Primitive
);
1147 OSSL_ASN1_DEFINE_CLASS(ISO64String
, Primitive
);
1148 OSSL_ASN1_DEFINE_CLASS(GeneralString
, Primitive
);
1149 OSSL_ASN1_DEFINE_CLASS(UniversalString
, Primitive
);
1150 OSSL_ASN1_DEFINE_CLASS(BMPString
, Primitive
);
1151 OSSL_ASN1_DEFINE_CLASS(Null
, Primitive
);
1152 OSSL_ASN1_DEFINE_CLASS(ObjectId
, Primitive
);
1153 OSSL_ASN1_DEFINE_CLASS(UTCTime
, Primitive
);
1154 OSSL_ASN1_DEFINE_CLASS(GeneralizedTime
, Primitive
);
1156 OSSL_ASN1_DEFINE_CLASS(Sequence
, Constructive
);
1157 OSSL_ASN1_DEFINE_CLASS(Set
, Constructive
);
1159 rb_define_singleton_method(cASN1ObjectId
, "register", ossl_asn1obj_s_register
, 3);
1160 rb_define_method(cASN1ObjectId
, "sn", ossl_asn1obj_get_sn
, 0);
1161 rb_define_method(cASN1ObjectId
, "ln", ossl_asn1obj_get_ln
, 0);
1162 rb_define_method(cASN1ObjectId
, "oid", ossl_asn1obj_get_oid
, 0);
1163 rb_define_alias(cASN1ObjectId
, "short_name", "sn");
1164 rb_define_alias(cASN1ObjectId
, "long_name", "ln");
1165 rb_attr(cASN1BitString
, rb_intern("unused_bits"), 1, 1, 0);