1/*
2 * $Id: ossl_asn1.c 44659 2014-01-19 16:28:53Z nagachika $
3 * 'OpenSSL for Ruby' team members
4 * Copyright (C) 2003
5 * All rights reserved.
6 */
7/*
8 * This program is licenced under the same licence as Ruby.
9 * (See the file 'LICENCE'.)
10 */
11#include "ossl.h"
12
13#if defined(HAVE_SYS_TIME_H)
14#  include <sys/time.h>
15#elif !defined(NT) && !defined(_WIN32)
16struct timeval {
17    long tv_sec;	/* seconds */
18    long tv_usec;	/* and microseconds */
19};
20#endif
21
22static VALUE join_der(VALUE enumerable);
23static VALUE ossl_asn1_decode0(unsigned char **pp, long length, long *offset,
24			       int depth, int yield, long *num_read);
25static VALUE ossl_asn1_initialize(int argc, VALUE *argv, VALUE self);
26static VALUE ossl_asn1eoc_initialize(VALUE self);
27
28/*
29 * DATE conversion
30 */
31VALUE
32asn1time_to_time(ASN1_TIME *time)
33{
34    struct tm tm;
35    VALUE argv[6];
36    int count;
37
38    if (!time || !time->data) return Qnil;
39    memset(&tm, 0, sizeof(struct tm));
40
41    switch (time->type) {
42    case V_ASN1_UTCTIME:
43	count = sscanf((const char *)time->data, "%2d%2d%2d%2d%2d%2dZ",
44		&tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min,
45		&tm.tm_sec);
46
47	if (count == 5) {
48	    tm.tm_sec = 0;
49	} else if (count != 6) {
50	    ossl_raise(rb_eTypeError, "bad UTCTIME format: \"%s\"",
51		    time->data);
52	}
53	if (tm.tm_year < 69) {
54	    tm.tm_year += 2000;
55	} else {
56	    tm.tm_year += 1900;
57	}
58	break;
59    case V_ASN1_GENERALIZEDTIME:
60	if (sscanf((const char *)time->data, "%4d%2d%2d%2d%2d%2dZ", &tm.tm_year, &tm.tm_mon,
61    		&tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
62	    ossl_raise(rb_eTypeError, "bad GENERALIZEDTIME format" );
63	}
64	break;
65    default:
66	rb_warning("unknown time format");
67        return Qnil;
68    }
69    argv[0] = INT2NUM(tm.tm_year);
70    argv[1] = INT2NUM(tm.tm_mon);
71    argv[2] = INT2NUM(tm.tm_mday);
72    argv[3] = INT2NUM(tm.tm_hour);
73    argv[4] = INT2NUM(tm.tm_min);
74    argv[5] = INT2NUM(tm.tm_sec);
75
76    return rb_funcall2(rb_cTime, rb_intern("utc"), 6, argv);
77}
78
79/*
80 * This function is not exported in Ruby's *.h
81 */
82extern struct timeval rb_time_timeval(VALUE);
83
84time_t
85time_to_time_t(VALUE time)
86{
87    return (time_t)NUM2LONG(rb_Integer(time));
88}
89
90/*
91 * STRING conversion
92 */
93VALUE
94asn1str_to_str(ASN1_STRING *str)
95{
96    return rb_str_new((const char *)str->data, str->length);
97}
98
99/*
100 * ASN1_INTEGER conversions
101 * TODO: Make a decision what's the right way to do this.
102 */
103#define DO_IT_VIA_RUBY 0
104VALUE
105asn1integer_to_num(ASN1_INTEGER *ai)
106{
107    BIGNUM *bn;
108#if DO_IT_VIA_RUBY
109    char *txt;
110#endif
111    VALUE num;
112
113    if (!ai) {
114	ossl_raise(rb_eTypeError, "ASN1_INTEGER is NULL!");
115    }
116    if (!(bn = ASN1_INTEGER_to_BN(ai, NULL))) {
117	ossl_raise(eOSSLError, NULL);
118    }
119#if DO_IT_VIA_RUBY
120    if (!(txt = BN_bn2dec(bn))) {
121	BN_free(bn);
122	ossl_raise(eOSSLError, NULL);
123    }
124    num = rb_cstr_to_inum(txt, 10, Qtrue);
125    OPENSSL_free(txt);
126#else
127    num = ossl_bn_new(bn);
128#endif
129    BN_free(bn);
130
131    return num;
132}
133
134#if DO_IT_VIA_RUBY
135ASN1_INTEGER *
136num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
137{
138    BIGNUM *bn = NULL;
139
140    if (RTEST(rb_obj_is_kind_of(obj, cBN))) {
141	bn = GetBNPtr(obj);
142    } else {
143	obj = rb_String(obj);
144	if (!BN_dec2bn(&bn, StringValuePtr(obj))) {
145	    ossl_raise(eOSSLError, NULL);
146	}
147    }
148    if (!(ai = BN_to_ASN1_INTEGER(bn, ai))) {
149	BN_free(bn);
150	ossl_raise(eOSSLError, NULL);
151    }
152    BN_free(bn);
153    return ai;
154}
155#else
156ASN1_INTEGER *
157num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
158{
159    BIGNUM *bn;
160
161    if (NIL_P(obj))
162	ossl_raise(rb_eTypeError, "Can't convert nil into Integer");
163
164    bn = GetBNPtr(obj);
165
166    if (!(ai = BN_to_ASN1_INTEGER(bn, ai)))
167	ossl_raise(eOSSLError, NULL);
168
169    return ai;
170}
171#endif
172
173/********/
174/*
175 * ASN1 module
176 */
177#define ossl_asn1_get_value(o)           rb_attr_get((o),sivVALUE)
178#define ossl_asn1_get_tag(o)             rb_attr_get((o),sivTAG)
179#define ossl_asn1_get_tagging(o)         rb_attr_get((o),sivTAGGING)
180#define ossl_asn1_get_tag_class(o)       rb_attr_get((o),sivTAG_CLASS)
181#define ossl_asn1_get_infinite_length(o) rb_attr_get((o),sivINFINITE_LENGTH)
182
183#define ossl_asn1_set_value(o,v)           rb_ivar_set((o),sivVALUE,(v))
184#define ossl_asn1_set_tag(o,v)             rb_ivar_set((o),sivTAG,(v))
185#define ossl_asn1_set_tagging(o,v)         rb_ivar_set((o),sivTAGGING,(v))
186#define ossl_asn1_set_tag_class(o,v)       rb_ivar_set((o),sivTAG_CLASS,(v))
187#define ossl_asn1_set_infinite_length(o,v) rb_ivar_set((o),sivINFINITE_LENGTH,(v))
188
189VALUE mASN1;
190VALUE eASN1Error;
191
192VALUE cASN1Data;
193VALUE cASN1Primitive;
194VALUE cASN1Constructive;
195
196VALUE cASN1EndOfContent;
197VALUE cASN1Boolean;                           /* BOOLEAN           */
198VALUE cASN1Integer, cASN1Enumerated;          /* INTEGER           */
199VALUE cASN1BitString;                         /* BIT STRING        */
200VALUE cASN1OctetString, cASN1UTF8String;      /* STRINGs           */
201VALUE cASN1NumericString, cASN1PrintableString;
202VALUE cASN1T61String, cASN1VideotexString;
203VALUE cASN1IA5String, cASN1GraphicString;
204VALUE cASN1ISO64String, cASN1GeneralString;
205VALUE cASN1UniversalString, cASN1BMPString;
206VALUE cASN1Null;                              /* NULL              */
207VALUE cASN1ObjectId;                          /* OBJECT IDENTIFIER */
208VALUE cASN1UTCTime, cASN1GeneralizedTime;     /* TIME              */
209VALUE cASN1Sequence, cASN1Set;                /* CONSTRUCTIVE      */
210
211static ID sIMPLICIT, sEXPLICIT;
212static ID sUNIVERSAL, sAPPLICATION, sCONTEXT_SPECIFIC, sPRIVATE;
213static ID sivVALUE, sivTAG, sivTAG_CLASS, sivTAGGING, sivINFINITE_LENGTH, sivUNUSED_BITS;
214
215/*
216 * We need to implement these for backward compatibility
217 * reasons, behavior of ASN1_put_object and ASN1_object_size
218 * for infinite length values is different in OpenSSL <= 0.9.7
219 */
220#if OPENSSL_VERSION_NUMBER < 0x00908000L
221#define ossl_asn1_object_size(cons, len, tag)		(cons) == 2 ? (len) + ASN1_object_size((cons), 0, (tag)) : ASN1_object_size((cons), (len), (tag))
222#define ossl_asn1_put_object(pp, cons, len, tag, xc)	(cons) == 2 ? ASN1_put_object((pp), (cons), 0, (tag), (xc)) : ASN1_put_object((pp), (cons), (len), (tag), (xc))
223#else
224#define ossl_asn1_object_size(cons, len, tag)		ASN1_object_size((cons), (len), (tag))
225#define ossl_asn1_put_object(pp, cons, len, tag, xc)	ASN1_put_object((pp), (cons), (len), (tag), (xc))
226#endif
227
228/*
229 * Ruby to ASN1 converters
230 */
231static ASN1_BOOLEAN
232obj_to_asn1bool(VALUE obj)
233{
234    if (NIL_P(obj))
235	ossl_raise(rb_eTypeError, "Can't convert nil into Boolean");
236
237#if OPENSSL_VERSION_NUMBER < 0x00907000L
238     return RTEST(obj) ? 0xff : 0x100;
239#else
240     return RTEST(obj) ? 0xff : 0x0;
241#endif
242}
243
244static ASN1_INTEGER*
245obj_to_asn1int(VALUE obj)
246{
247    return num_to_asn1integer(obj, NULL);
248}
249
250static ASN1_BIT_STRING*
251obj_to_asn1bstr(VALUE obj, long unused_bits)
252{
253    ASN1_BIT_STRING *bstr;
254
255    if(unused_bits < 0) unused_bits = 0;
256    StringValue(obj);
257    if(!(bstr = ASN1_BIT_STRING_new()))
258	ossl_raise(eASN1Error, NULL);
259    ASN1_BIT_STRING_set(bstr, (unsigned char *)RSTRING_PTR(obj), RSTRING_LENINT(obj));
260    bstr->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */
261    bstr->flags |= ASN1_STRING_FLAG_BITS_LEFT|(unused_bits&0x07);
262
263    return bstr;
264}
265
266static ASN1_STRING*
267obj_to_asn1str(VALUE obj)
268{
269    ASN1_STRING *str;
270
271    StringValue(obj);
272    if(!(str = ASN1_STRING_new()))
273	ossl_raise(eASN1Error, NULL);
274    ASN1_STRING_set(str, RSTRING_PTR(obj), RSTRING_LENINT(obj));
275
276    return str;
277}
278
279static ASN1_NULL*
280obj_to_asn1null(VALUE obj)
281{
282    ASN1_NULL *null;
283
284    if(!NIL_P(obj))
285	ossl_raise(eASN1Error, "nil expected");
286    if(!(null = ASN1_NULL_new()))
287	ossl_raise(eASN1Error, NULL);
288
289    return null;
290}
291
292static ASN1_OBJECT*
293obj_to_asn1obj(VALUE obj)
294{
295    ASN1_OBJECT *a1obj;
296
297    StringValue(obj);
298    a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 0);
299    if(!a1obj) a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 1);
300    if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID");
301
302    return a1obj;
303}
304
305static ASN1_UTCTIME*
306obj_to_asn1utime(VALUE time)
307{
308    time_t sec;
309    ASN1_UTCTIME *t;
310
311    sec = time_to_time_t(time);
312    if(!(t = ASN1_UTCTIME_set(NULL, sec)))
313        ossl_raise(eASN1Error, NULL);
314
315    return t;
316}
317
318static ASN1_GENERALIZEDTIME*
319obj_to_asn1gtime(VALUE time)
320{
321    time_t sec;
322    ASN1_GENERALIZEDTIME *t;
323
324    sec = time_to_time_t(time);
325    if(!(t =ASN1_GENERALIZEDTIME_set(NULL, sec)))
326        ossl_raise(eASN1Error, NULL);
327
328    return t;
329}
330
331static ASN1_STRING*
332obj_to_asn1derstr(VALUE obj)
333{
334    ASN1_STRING *a1str;
335    VALUE str;
336
337    str = ossl_to_der(obj);
338    if(!(a1str = ASN1_STRING_new()))
339	ossl_raise(eASN1Error, NULL);
340    ASN1_STRING_set(a1str, RSTRING_PTR(str), RSTRING_LENINT(str));
341
342    return a1str;
343}
344
345/*
346 * DER to Ruby converters
347 */
348static VALUE
349decode_bool(unsigned char* der, long length)
350{
351    int val;
352    const unsigned char *p;
353
354    p = der;
355    if((val = d2i_ASN1_BOOLEAN(NULL, &p, length)) < 0)
356	ossl_raise(eASN1Error, NULL);
357
358    return val ? Qtrue : Qfalse;
359}
360
361static VALUE
362decode_int(unsigned char* der, long length)
363{
364    ASN1_INTEGER *ai;
365    const unsigned char *p;
366    VALUE ret;
367    int status = 0;
368
369    p = der;
370    if(!(ai = d2i_ASN1_INTEGER(NULL, &p, length)))
371	ossl_raise(eASN1Error, NULL);
372    ret = rb_protect((VALUE(*)_((VALUE)))asn1integer_to_num,
373		     (VALUE)ai, &status);
374    ASN1_INTEGER_free(ai);
375    if(status) rb_jump_tag(status);
376
377    return ret;
378}
379
380static VALUE
381decode_bstr(unsigned char* der, long length, long *unused_bits)
382{
383    ASN1_BIT_STRING *bstr;
384    const unsigned char *p;
385    long len;
386    VALUE ret;
387
388    p = der;
389    if(!(bstr = d2i_ASN1_BIT_STRING(NULL, &p, length)))
390	ossl_raise(eASN1Error, NULL);
391    len = bstr->length;
392    *unused_bits = 0;
393    if(bstr->flags & ASN1_STRING_FLAG_BITS_LEFT)
394	*unused_bits = bstr->flags & 0x07;
395    ret = rb_str_new((const char *)bstr->data, len);
396    ASN1_BIT_STRING_free(bstr);
397
398    return ret;
399}
400
401static VALUE
402decode_enum(unsigned char* der, long length)
403{
404    ASN1_ENUMERATED *ai;
405    const unsigned char *p;
406    VALUE ret;
407    int status = 0;
408
409    p = der;
410    if(!(ai = d2i_ASN1_ENUMERATED(NULL, &p, length)))
411	ossl_raise(eASN1Error, NULL);
412    ret = rb_protect((VALUE(*)_((VALUE)))asn1integer_to_num,
413		     (VALUE)ai, &status);
414    ASN1_ENUMERATED_free(ai);
415    if(status) rb_jump_tag(status);
416
417    return ret;
418}
419
420static VALUE
421decode_null(unsigned char* der, long length)
422{
423    ASN1_NULL *null;
424    const unsigned char *p;
425
426    p = der;
427    if(!(null = d2i_ASN1_NULL(NULL, &p, length)))
428	ossl_raise(eASN1Error, NULL);
429    ASN1_NULL_free(null);
430
431    return Qnil;
432}
433
434static VALUE
435decode_obj(unsigned char* der, long length)
436{
437    ASN1_OBJECT *obj;
438    const unsigned char *p;
439    VALUE ret;
440    int nid;
441    BIO *bio;
442
443    p = der;
444    if(!(obj = d2i_ASN1_OBJECT(NULL, &p, length)))
445	ossl_raise(eASN1Error, NULL);
446    if((nid = OBJ_obj2nid(obj)) != NID_undef){
447	ASN1_OBJECT_free(obj);
448	ret = rb_str_new2(OBJ_nid2sn(nid));
449    }
450    else{
451	if(!(bio = BIO_new(BIO_s_mem()))){
452	    ASN1_OBJECT_free(obj);
453	    ossl_raise(eASN1Error, NULL);
454	}
455	i2a_ASN1_OBJECT(bio, obj);
456	ASN1_OBJECT_free(obj);
457	ret = ossl_membio2str(bio);
458    }
459
460    return ret;
461}
462
463static VALUE
464decode_time(unsigned char* der, long length)
465{
466    ASN1_TIME *time;
467    const unsigned char *p;
468    VALUE ret;
469    int status = 0;
470
471    p = der;
472    if(!(time = d2i_ASN1_TIME(NULL, &p, length)))
473	ossl_raise(eASN1Error, NULL);
474    ret = rb_protect((VALUE(*)_((VALUE)))asn1time_to_time,
475		     (VALUE)time, &status);
476    ASN1_TIME_free(time);
477    if(status) rb_jump_tag(status);
478
479    return ret;
480}
481
482static VALUE
483decode_eoc(unsigned char *der, long length)
484{
485    if (length != 2 || !(der[0] == 0x00 && der[1] == 0x00))
486	ossl_raise(eASN1Error, NULL);
487
488    return rb_str_new("", 0);
489}
490
491/********/
492
493typedef struct {
494    const char *name;
495    VALUE *klass;
496} ossl_asn1_info_t;
497
498static ossl_asn1_info_t ossl_asn1_info[] = {
499    { "EOC",               &cASN1EndOfContent,    },  /*  0 */
500    { "BOOLEAN",           &cASN1Boolean,         },  /*  1 */
501    { "INTEGER",           &cASN1Integer,         },  /*  2 */
502    { "BIT_STRING",        &cASN1BitString,       },  /*  3 */
503    { "OCTET_STRING",      &cASN1OctetString,     },  /*  4 */
504    { "NULL",              &cASN1Null,            },  /*  5 */
505    { "OBJECT",            &cASN1ObjectId,        },  /*  6 */
506    { "OBJECT_DESCRIPTOR", NULL,                  },  /*  7 */
507    { "EXTERNAL",          NULL,                  },  /*  8 */
508    { "REAL",              NULL,                  },  /*  9 */
509    { "ENUMERATED",        &cASN1Enumerated,      },  /* 10 */
510    { "EMBEDDED_PDV",      NULL,                  },  /* 11 */
511    { "UTF8STRING",        &cASN1UTF8String,      },  /* 12 */
512    { "RELATIVE_OID",      NULL,                  },  /* 13 */
513    { "[UNIVERSAL 14]",    NULL,                  },  /* 14 */
514    { "[UNIVERSAL 15]",    NULL,                  },  /* 15 */
515    { "SEQUENCE",          &cASN1Sequence,        },  /* 16 */
516    { "SET",               &cASN1Set,             },  /* 17 */
517    { "NUMERICSTRING",     &cASN1NumericString,   },  /* 18 */
518    { "PRINTABLESTRING",   &cASN1PrintableString, },  /* 19 */
519    { "T61STRING",         &cASN1T61String,       },  /* 20 */
520    { "VIDEOTEXSTRING",    &cASN1VideotexString,  },  /* 21 */
521    { "IA5STRING",         &cASN1IA5String,       },  /* 22 */
522    { "UTCTIME",           &cASN1UTCTime,         },  /* 23 */
523    { "GENERALIZEDTIME",   &cASN1GeneralizedTime, },  /* 24 */
524    { "GRAPHICSTRING",     &cASN1GraphicString,   },  /* 25 */
525    { "ISO64STRING",       &cASN1ISO64String,     },  /* 26 */
526    { "GENERALSTRING",     &cASN1GeneralString,   },  /* 27 */
527    { "UNIVERSALSTRING",   &cASN1UniversalString, },  /* 28 */
528    { "CHARACTER_STRING",  NULL,                  },  /* 29 */
529    { "BMPSTRING",         &cASN1BMPString,       },  /* 30 */
530};
531
532int ossl_asn1_info_size = (sizeof(ossl_asn1_info)/sizeof(ossl_asn1_info[0]));
533
534static VALUE class_tag_map;
535
536static int ossl_asn1_default_tag(VALUE obj);
537
538ASN1_TYPE*
539ossl_asn1_get_asn1type(VALUE obj)
540{
541    ASN1_TYPE *ret;
542    VALUE value, rflag;
543    void *ptr;
544    void (*free_func)();
545    int tag, flag;
546
547    tag = ossl_asn1_default_tag(obj);
548    value = ossl_asn1_get_value(obj);
549    switch(tag){
550    case V_ASN1_BOOLEAN:
551	ptr = (void*)(VALUE)obj_to_asn1bool(value);
552	free_func = NULL;
553	break;
554    case V_ASN1_INTEGER:         /* FALLTHROUGH */
555    case V_ASN1_ENUMERATED:
556	ptr = obj_to_asn1int(value);
557	free_func = ASN1_INTEGER_free;
558	break;
559    case V_ASN1_BIT_STRING:
560        rflag = rb_attr_get(obj, sivUNUSED_BITS);
561        flag = NIL_P(rflag) ? -1 : NUM2INT(rflag);
562	ptr = obj_to_asn1bstr(value, flag);
563	free_func = ASN1_BIT_STRING_free;
564	break;
565    case V_ASN1_NULL:
566	ptr = obj_to_asn1null(value);
567	free_func = ASN1_NULL_free;
568	break;
569    case V_ASN1_OCTET_STRING:    /* FALLTHROUGH */
570    case V_ASN1_UTF8STRING:      /* FALLTHROUGH */
571    case V_ASN1_NUMERICSTRING:   /* FALLTHROUGH */
572    case V_ASN1_PRINTABLESTRING: /* FALLTHROUGH */
573    case V_ASN1_T61STRING:       /* FALLTHROUGH */
574    case V_ASN1_VIDEOTEXSTRING:  /* FALLTHROUGH */
575    case V_ASN1_IA5STRING:       /* FALLTHROUGH */
576    case V_ASN1_GRAPHICSTRING:   /* FALLTHROUGH */
577    case V_ASN1_ISO64STRING:     /* FALLTHROUGH */
578    case V_ASN1_GENERALSTRING:   /* FALLTHROUGH */
579    case V_ASN1_UNIVERSALSTRING: /* FALLTHROUGH */
580    case V_ASN1_BMPSTRING:
581	ptr = obj_to_asn1str(value);
582	free_func = ASN1_STRING_free;
583	break;
584    case V_ASN1_OBJECT:
585	ptr = obj_to_asn1obj(value);
586	free_func = ASN1_OBJECT_free;
587	break;
588    case V_ASN1_UTCTIME:
589	ptr = obj_to_asn1utime(value);
590	free_func = ASN1_TIME_free;
591	break;
592    case V_ASN1_GENERALIZEDTIME:
593	ptr = obj_to_asn1gtime(value);
594	free_func = ASN1_TIME_free;
595	break;
596    case V_ASN1_SET:             /* FALLTHROUGH */
597    case V_ASN1_SEQUENCE:
598	ptr = obj_to_asn1derstr(obj);
599	free_func = ASN1_STRING_free;
600	break;
601    default:
602	ossl_raise(eASN1Error, "unsupported ASN.1 type");
603    }
604    if(!(ret = OPENSSL_malloc(sizeof(ASN1_TYPE)))){
605	if(free_func) free_func(ptr);
606	ossl_raise(eASN1Error, "ASN1_TYPE alloc failure");
607    }
608    memset(ret, 0, sizeof(ASN1_TYPE));
609    ASN1_TYPE_set(ret, tag, ptr);
610
611    return ret;
612}
613
614static int
615ossl_asn1_default_tag(VALUE obj)
616{
617    VALUE tmp_class, tag;
618
619    tmp_class = CLASS_OF(obj);
620    while (tmp_class) {
621	tag = rb_hash_lookup(class_tag_map, tmp_class);
622	if (tag != Qnil) {
623       	    return NUM2INT(tag);
624      	}
625    	tmp_class = rb_class_superclass(tmp_class);
626    }
627    ossl_raise(eASN1Error, "universal tag for %"PRIsVALUE" not found",
628	       rb_obj_class(obj));
629
630    return -1; /* dummy */
631}
632
633static int
634ossl_asn1_tag(VALUE obj)
635{
636    VALUE tag;
637
638    tag = ossl_asn1_get_tag(obj);
639    if(NIL_P(tag))
640	ossl_raise(eASN1Error, "tag number not specified");
641
642    return NUM2INT(tag);
643}
644
645static int
646ossl_asn1_is_explicit(VALUE obj)
647{
648    VALUE s;
649    int ret = -1;
650
651    s = ossl_asn1_get_tagging(obj);
652    if(NIL_P(s)) return 0;
653    else if(SYMBOL_P(s)){
654	if (SYM2ID(s) == sIMPLICIT)
655	    ret = 0;
656	else if (SYM2ID(s) == sEXPLICIT)
657	    ret = 1;
658    }
659    if(ret < 0){
660	ossl_raise(eASN1Error, "invalid tag default");
661    }
662
663    return ret;
664}
665
666static int
667ossl_asn1_tag_class(VALUE obj)
668{
669    VALUE s;
670    int ret = -1;
671
672    s = ossl_asn1_get_tag_class(obj);
673    if(NIL_P(s)) ret = V_ASN1_UNIVERSAL;
674    else if(SYMBOL_P(s)){
675	if (SYM2ID(s) == sUNIVERSAL)
676	    ret = V_ASN1_UNIVERSAL;
677	else if (SYM2ID(s) == sAPPLICATION)
678	    ret = V_ASN1_APPLICATION;
679	else if (SYM2ID(s) == sCONTEXT_SPECIFIC)
680	    ret = V_ASN1_CONTEXT_SPECIFIC;
681	else if (SYM2ID(s) == sPRIVATE)
682	    ret = V_ASN1_PRIVATE;
683    }
684    if(ret < 0){
685	ossl_raise(eASN1Error, "invalid tag class");
686    }
687
688    return ret;
689}
690
691static VALUE
692ossl_asn1_class2sym(int tc)
693{
694    if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
695	return ID2SYM(sPRIVATE);
696    else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
697	return ID2SYM(sCONTEXT_SPECIFIC);
698    else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
699	return ID2SYM(sAPPLICATION);
700    else
701	return ID2SYM(sUNIVERSAL);
702}
703
704/*
705 * call-seq:
706 *    OpenSSL::ASN1::ASN1Data.new(value, tag, tag_class) => ASN1Data
707 *
708 * +value+: Please have a look at Constructive and Primitive to see how Ruby
709 * types are mapped to ASN.1 types and vice versa.
710 *
711 * +tag+: A +Number+ indicating the tag number.
712 *
713 * +tag_class+: A +Symbol+ indicating the tag class. Please cf. ASN1 for
714 * possible values.
715 *
716 * == Example
717 *   asn1_int = OpenSSL::ASN1Data.new(42, 2, :UNIVERSAL) # => Same as OpenSSL::ASN1::Integer.new(42)
718 *   tagged_int = OpenSSL::ASN1Data.new(42, 0, :CONTEXT_SPECIFIC) # implicitly 0-tagged INTEGER
719 */
720static VALUE
721ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class)
722{
723    if(!SYMBOL_P(tag_class))
724	ossl_raise(eASN1Error, "invalid tag class");
725    if((SYM2ID(tag_class) == sUNIVERSAL) && NUM2INT(tag) > 31)
726	ossl_raise(eASN1Error, "tag number for Universal too large");
727    ossl_asn1_set_tag(self, tag);
728    ossl_asn1_set_value(self, value);
729    ossl_asn1_set_tag_class(self, tag_class);
730    ossl_asn1_set_infinite_length(self, Qfalse);
731
732    return self;
733}
734
735static VALUE
736join_der_i(VALUE i, VALUE str)
737{
738    i = ossl_to_der_if_possible(i);
739    StringValue(i);
740    rb_str_append(str, i);
741    return Qnil;
742}
743
744static VALUE
745join_der(VALUE enumerable)
746{
747    VALUE str = rb_str_new(0, 0);
748    rb_block_call(enumerable, rb_intern("each"), 0, 0, join_der_i, str);
749    return str;
750}
751
752/*
753 * call-seq:
754 *    asn1.to_der => DER-encoded String
755 *
756 * Encodes this ASN1Data into a DER-encoded String value. The result is
757 * DER-encoded except for the possibility of infinite length encodings.
758 * Infinite length encodings are not allowed in strict DER, so strictly
759 * speaking the result of such an encoding would be a BER-encoding.
760 */
761static VALUE
762ossl_asn1data_to_der(VALUE self)
763{
764    VALUE value, der, inf_length;
765    int tag, tag_class, is_cons = 0;
766    long length;
767    unsigned char *p;
768
769    value = ossl_asn1_get_value(self);
770    if(rb_obj_is_kind_of(value, rb_cArray)){
771	is_cons = 1;
772	value = join_der(value);
773    }
774    StringValue(value);
775
776    tag = ossl_asn1_tag(self);
777    tag_class = ossl_asn1_tag_class(self);
778    inf_length = ossl_asn1_get_infinite_length(self);
779    if (inf_length == Qtrue) {
780	is_cons = 2;
781    }
782    if((length = ossl_asn1_object_size(is_cons, RSTRING_LENINT(value), tag)) <= 0)
783	ossl_raise(eASN1Error, NULL);
784    der = rb_str_new(0, length);
785    p = (unsigned char *)RSTRING_PTR(der);
786    ossl_asn1_put_object(&p, is_cons, RSTRING_LENINT(value), tag, tag_class);
787    memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
788    p += RSTRING_LEN(value);
789    ossl_str_adjust(der, p);
790
791    return der;
792}
793
794static VALUE
795int_ossl_asn1_decode0_prim(unsigned char **pp, long length, long hlen, int tag,
796			   VALUE tc, long *num_read)
797{
798    VALUE value, asn1data;
799    unsigned char *p;
800    long flag = 0;
801
802    p = *pp;
803
804    if(tc == sUNIVERSAL && tag < ossl_asn1_info_size) {
805	switch(tag){
806	case V_ASN1_EOC:
807	    value = decode_eoc(p, hlen+length);
808	    break;
809	case V_ASN1_BOOLEAN:
810	    value = decode_bool(p, hlen+length);
811	    break;
812	case V_ASN1_INTEGER:
813	    value = decode_int(p, hlen+length);
814	    break;
815	case V_ASN1_BIT_STRING:
816	    value = decode_bstr(p, hlen+length, &flag);
817	    break;
818	case V_ASN1_NULL:
819	    value = decode_null(p, hlen+length);
820	    break;
821	case V_ASN1_ENUMERATED:
822	    value = decode_enum(p, hlen+length);
823	    break;
824	case V_ASN1_OBJECT:
825	    value = decode_obj(p, hlen+length);
826	    break;
827	case V_ASN1_UTCTIME:           /* FALLTHROUGH */
828	case V_ASN1_GENERALIZEDTIME:
829	    value = decode_time(p, hlen+length);
830	    break;
831	default:
832	    /* use original value */
833	    p += hlen;
834	    value = rb_str_new((const char *)p, length);
835	    break;
836	}
837    }
838    else {
839	p += hlen;
840	value = rb_str_new((const char *)p, length);
841    }
842
843    *pp += hlen + length;
844    *num_read = hlen + length;
845
846    if (tc == sUNIVERSAL && tag < ossl_asn1_info_size && ossl_asn1_info[tag].klass) {
847	VALUE klass = *ossl_asn1_info[tag].klass;
848	VALUE args[4];
849	args[0] = value;
850	args[1] = INT2NUM(tag);
851	args[2] = Qnil;
852	args[3] = ID2SYM(tc);
853	asn1data = rb_obj_alloc(klass);
854	ossl_asn1_initialize(4, args, asn1data);
855	if(tag == V_ASN1_BIT_STRING){
856	    rb_ivar_set(asn1data, sivUNUSED_BITS, LONG2NUM(flag));
857	}
858    }
859    else {
860	asn1data = rb_obj_alloc(cASN1Data);
861	ossl_asn1data_initialize(asn1data, value, INT2NUM(tag), ID2SYM(tc));
862    }
863
864    return asn1data;
865}
866
867static VALUE
868int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length,
869			   long *offset, int depth, int yield, int j,
870			   int tag, VALUE tc, long *num_read)
871{
872    VALUE value, asn1data, ary;
873    int infinite;
874    long off = *offset;
875
876    infinite = (j == 0x21);
877    ary = rb_ary_new();
878
879    while (length > 0 || infinite) {
880	long inner_read = 0;
881	value = ossl_asn1_decode0(pp, max_len, &off, depth + 1, yield, &inner_read);
882	*num_read += inner_read;
883	max_len -= inner_read;
884	rb_ary_push(ary, value);
885	if (length > 0)
886	    length -= inner_read;
887
888	if (infinite &&
889	    NUM2INT(ossl_asn1_get_tag(value)) == V_ASN1_EOC &&
890	    SYM2ID(ossl_asn1_get_tag_class(value)) == sUNIVERSAL) {
891	    break;
892	}
893    }
894
895    if (tc == sUNIVERSAL) {
896	VALUE args[4];
897	int not_sequence_or_set;
898
899	not_sequence_or_set = tag != V_ASN1_SEQUENCE && tag != V_ASN1_SET;
900
901	if (not_sequence_or_set) {
902	    if (infinite) {
903		asn1data = rb_obj_alloc(cASN1Constructive);
904	    }
905	    else {
906		ossl_raise(eASN1Error, "invalid non-infinite tag");
907		return Qnil;
908	    }
909	}
910	else {
911	    VALUE klass = *ossl_asn1_info[tag].klass;
912	    asn1data = rb_obj_alloc(klass);
913	}
914	args[0] = ary;
915	args[1] = INT2NUM(tag);
916	args[2] = Qnil;
917	args[3] = ID2SYM(tc);
918	ossl_asn1_initialize(4, args, asn1data);
919    }
920    else {
921	asn1data = rb_obj_alloc(cASN1Data);
922	ossl_asn1data_initialize(asn1data, ary, INT2NUM(tag), ID2SYM(tc));
923    }
924
925    if (infinite)
926	ossl_asn1_set_infinite_length(asn1data, Qtrue);
927    else
928	ossl_asn1_set_infinite_length(asn1data, Qfalse);
929
930    *offset = off;
931    return asn1data;
932}
933
934static VALUE
935ossl_asn1_decode0(unsigned char **pp, long length, long *offset, int depth,
936		  int yield, long *num_read)
937{
938    unsigned char *start, *p;
939    const unsigned char *p0;
940    long len = 0, inner_read = 0, off = *offset, hlen;
941    int tag, tc, j;
942    VALUE asn1data, tag_class;
943
944    p = *pp;
945    start = p;
946    p0 = p;
947    j = ASN1_get_object(&p0, &len, &tag, &tc, length);
948    p = (unsigned char *)p0;
949    if(j & 0x80) ossl_raise(eASN1Error, NULL);
950    if(len > length) ossl_raise(eASN1Error, "value is too short");
951    if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
952	tag_class = sPRIVATE;
953    else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
954	tag_class = sCONTEXT_SPECIFIC;
955    else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
956	tag_class = sAPPLICATION;
957    else
958	tag_class = sUNIVERSAL;
959
960    hlen = p - start;
961
962    if(yield) {
963	VALUE arg = rb_ary_new();
964	rb_ary_push(arg, LONG2NUM(depth));
965	rb_ary_push(arg, LONG2NUM(*offset));
966	rb_ary_push(arg, LONG2NUM(hlen));
967	rb_ary_push(arg, LONG2NUM(len));
968	rb_ary_push(arg, (j & V_ASN1_CONSTRUCTED) ? Qtrue : Qfalse);
969	rb_ary_push(arg, ossl_asn1_class2sym(tc));
970	rb_ary_push(arg, INT2NUM(tag));
971	rb_yield(arg);
972    }
973
974    if(j & V_ASN1_CONSTRUCTED) {
975	*pp += hlen;
976	off += hlen;
977	asn1data = int_ossl_asn1_decode0_cons(pp, length, len, &off, depth, yield, j, tag, tag_class, &inner_read);
978	inner_read += hlen;
979    }
980    else {
981    	if ((j & 0x01) && (len == 0)) ossl_raise(eASN1Error, "Infinite length for primitive value");
982	asn1data = int_ossl_asn1_decode0_prim(pp, len, hlen, tag, tag_class, &inner_read);
983	off += hlen + len;
984    }
985    if (num_read)
986	*num_read = inner_read;
987    if (len != 0 && inner_read != hlen + len) {
988	ossl_raise(eASN1Error,
989		   "Type mismatch. Bytes read: %ld Bytes available: %ld",
990		   inner_read, hlen + len);
991    }
992
993    *offset = off;
994    return asn1data;
995}
996
997static void
998int_ossl_decode_sanity_check(long len, long read, long offset)
999{
1000    if (len != 0 && (read != len || offset != len)) {
1001	ossl_raise(eASN1Error,
1002		   "Type mismatch. Total bytes read: %ld Bytes available: %ld Offset: %ld",
1003		   read, len, offset);
1004    }
1005}
1006
1007/*
1008 * call-seq:
1009 *    OpenSSL::ASN1.traverse(asn1) -> nil
1010 *
1011 * If a block is given, it prints out each of the elements encountered.
1012 * Block parameters are (in that order):
1013 * * depth: The recursion depth, plus one with each constructed value being encountered (Number)
1014 * * offset: Current byte offset (Number)
1015 * * header length: Combined length in bytes of the Tag and Length headers. (Number)
1016 * * length: The overall remaining length of the entire data (Number)
1017 * * constructed: Whether this value is constructed or not (Boolean)
1018 * * tag_class: Current tag class (Symbol)
1019 * * tag: The current tag (Number)
1020 *
1021 * == Example
1022 *   der = File.binread('asn1data.der')
1023 *   OpenSSL::ASN1.traverse(der) do | depth, offset, header_len, length, constructed, tag_class, tag|
1024 *     puts "Depth: #{depth} Offset: #{offset} Length: #{length}"
1025 *     puts "Header length: #{header_len} Tag: #{tag} Tag class: #{tag_class} Constructed: #{constructed}"
1026 *   end
1027 */
1028static VALUE
1029ossl_asn1_traverse(VALUE self, VALUE obj)
1030{
1031    unsigned char *p;
1032    volatile VALUE tmp;
1033    long len, read = 0, offset = 0;
1034
1035    obj = ossl_to_der_if_possible(obj);
1036    tmp = rb_str_new4(StringValue(obj));
1037    p = (unsigned char *)RSTRING_PTR(tmp);
1038    len = RSTRING_LEN(tmp);
1039    ossl_asn1_decode0(&p, len, &offset, 0, 1, &read);
1040    int_ossl_decode_sanity_check(len, read, offset);
1041    return Qnil;
1042}
1043
1044/*
1045 * call-seq:
1046 *    OpenSSL::ASN1.decode(der) -> ASN1Data
1047 *
1048 * Decodes a BER- or DER-encoded value and creates an ASN1Data instance. +der+
1049 * may be a +String+ or any object that features a +#to_der+ method transforming
1050 * it into a BER-/DER-encoded +String+.
1051 *
1052 * == Example
1053 *   der = File.binread('asn1data')
1054 *   asn1 = OpenSSL::ASN1.decode(der)
1055 */
1056static VALUE
1057ossl_asn1_decode(VALUE self, VALUE obj)
1058{
1059    VALUE ret;
1060    unsigned char *p;
1061    volatile VALUE tmp;
1062    long len, read = 0, offset = 0;
1063
1064    obj = ossl_to_der_if_possible(obj);
1065    tmp = rb_str_new4(StringValue(obj));
1066    p = (unsigned char *)RSTRING_PTR(tmp);
1067    len = RSTRING_LEN(tmp);
1068    ret = ossl_asn1_decode0(&p, len, &offset, 0, 0, &read);
1069    int_ossl_decode_sanity_check(len, read, offset);
1070    return ret;
1071}
1072
1073/*
1074 * call-seq:
1075 *    OpenSSL::ASN1.decode_all(der) -> Array of ASN1Data
1076 *
1077 * Similar to +decode+ with the difference that +decode+ expects one
1078 * distinct value represented in +der+. +decode_all+ on the contrary
1079 * decodes a sequence of sequential BER/DER values lined up in +der+
1080 * and returns them as an array.
1081 *
1082 * == Example
1083 *   ders = File.binread('asn1data_seq')
1084 *   asn1_ary = OpenSSL::ASN1.decode_all(ders)
1085 */
1086static VALUE
1087ossl_asn1_decode_all(VALUE self, VALUE obj)
1088{
1089    VALUE ary, val;
1090    unsigned char *p;
1091    long len, tmp_len = 0, read = 0, offset = 0;
1092    volatile VALUE tmp;
1093
1094    obj = ossl_to_der_if_possible(obj);
1095    tmp = rb_str_new4(StringValue(obj));
1096    p = (unsigned char *)RSTRING_PTR(tmp);
1097    len = RSTRING_LEN(tmp);
1098    tmp_len = len;
1099    ary = rb_ary_new();
1100    while (tmp_len > 0) {
1101	long tmp_read = 0;
1102	val = ossl_asn1_decode0(&p, tmp_len, &offset, 0, 0, &tmp_read);
1103	rb_ary_push(ary, val);
1104	read += tmp_read;
1105	tmp_len -= tmp_read;
1106    }
1107    int_ossl_decode_sanity_check(len, read, offset);
1108    return ary;
1109}
1110
1111/*
1112 * call-seq:
1113 *    OpenSSL::ASN1::Primitive.new( value [, tag, tagging, tag_class ]) => Primitive
1114 *
1115 * +value+: is mandatory.
1116 *
1117 * +tag+: optional, may be specified for tagged values. If no +tag+ is
1118 * specified, the UNIVERSAL tag corresponding to the Primitive sub-class
1119 * is used by default.
1120 *
1121 * +tagging+: may be used as an encoding hint to encode a value either
1122 * explicitly or implicitly, see ASN1 for possible values.
1123 *
1124 * +tag_class+: if +tag+ and +tagging+ are +nil+ then this is set to
1125 * +:UNIVERSAL+ by default. If either +tag+ or +tagging+ are set then
1126 * +:CONTEXT_SPECIFIC+ is used as the default. For possible values please
1127 * cf. ASN1.
1128 *
1129 * == Example
1130 *   int = OpenSSL::ASN1::Integer.new(42)
1131 *   zero_tagged_int = OpenSSL::ASN1::Integer.new(42, 0, :IMPLICIT)
1132 *   private_explicit_zero_tagged_int = OpenSSL::ASN1::Integer.new(42, 0, :EXPLICIT, :PRIVATE)
1133 */
1134static VALUE
1135ossl_asn1_initialize(int argc, VALUE *argv, VALUE self)
1136{
1137    VALUE value, tag, tagging, tag_class;
1138
1139    rb_scan_args(argc, argv, "13", &value, &tag, &tagging, &tag_class);
1140    if(argc > 1){
1141	if(NIL_P(tag))
1142	    ossl_raise(eASN1Error, "must specify tag number");
1143	if(!NIL_P(tagging) && !SYMBOL_P(tagging))
1144	    ossl_raise(eASN1Error, "invalid tagging method");
1145	if(NIL_P(tag_class)) {
1146	    if (NIL_P(tagging))
1147		tag_class = ID2SYM(sUNIVERSAL);
1148	    else
1149		tag_class = ID2SYM(sCONTEXT_SPECIFIC);
1150	}
1151	if(!SYMBOL_P(tag_class))
1152	    ossl_raise(eASN1Error, "invalid tag class");
1153	if(SYM2ID(tagging) == sIMPLICIT && NUM2INT(tag) > 31)
1154	    ossl_raise(eASN1Error, "tag number for Universal too large");
1155    }
1156    else{
1157	tag = INT2NUM(ossl_asn1_default_tag(self));
1158	tagging = Qnil;
1159	tag_class = ID2SYM(sUNIVERSAL);
1160    }
1161    ossl_asn1_set_tag(self, tag);
1162    ossl_asn1_set_value(self, value);
1163    ossl_asn1_set_tagging(self, tagging);
1164    ossl_asn1_set_tag_class(self, tag_class);
1165    ossl_asn1_set_infinite_length(self, Qfalse);
1166
1167    return self;
1168}
1169
1170static VALUE
1171ossl_asn1eoc_initialize(VALUE self) {
1172    VALUE tag, tagging, tag_class, value;
1173    tag = INT2NUM(ossl_asn1_default_tag(self));
1174    tagging = Qnil;
1175    tag_class = ID2SYM(sUNIVERSAL);
1176    value = rb_str_new("", 0);
1177    ossl_asn1_set_tag(self, tag);
1178    ossl_asn1_set_value(self, value);
1179    ossl_asn1_set_tagging(self, tagging);
1180    ossl_asn1_set_tag_class(self, tag_class);
1181    ossl_asn1_set_infinite_length(self, Qfalse);
1182    return self;
1183}
1184
1185static int
1186ossl_i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **pp)
1187{
1188#if OPENSSL_VERSION_NUMBER < 0x00907000L
1189    if(!a) return 0;
1190    if(a->type == V_ASN1_BOOLEAN)
1191        return i2d_ASN1_BOOLEAN(a->value.boolean, pp);
1192#endif
1193    return i2d_ASN1_TYPE(a, pp);
1194}
1195
1196static void
1197ossl_ASN1_TYPE_free(ASN1_TYPE *a)
1198{
1199#if OPENSSL_VERSION_NUMBER < 0x00907000L
1200    if(!a) return;
1201    if(a->type == V_ASN1_BOOLEAN){
1202        OPENSSL_free(a);
1203        return;
1204    }
1205#endif
1206    ASN1_TYPE_free(a);
1207}
1208
1209/*
1210 * call-seq:
1211 *    asn1.to_der => DER-encoded String
1212 *
1213 * See ASN1Data#to_der for details. *
1214 */
1215static VALUE
1216ossl_asn1prim_to_der(VALUE self)
1217{
1218    ASN1_TYPE *asn1;
1219    int tn, tc, explicit;
1220    long len, reallen;
1221    unsigned char *buf, *p;
1222    VALUE str;
1223
1224    tn = NUM2INT(ossl_asn1_get_tag(self));
1225    tc = ossl_asn1_tag_class(self);
1226    explicit = ossl_asn1_is_explicit(self);
1227    asn1 = ossl_asn1_get_asn1type(self);
1228
1229    len = ossl_asn1_object_size(1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn);
1230    if(!(buf = OPENSSL_malloc(len))){
1231	ossl_ASN1_TYPE_free(asn1);
1232	ossl_raise(eASN1Error, "cannot alloc buffer");
1233    }
1234    p = buf;
1235    if (tc == V_ASN1_UNIVERSAL) {
1236        ossl_i2d_ASN1_TYPE(asn1, &p);
1237    } else if (explicit) {
1238        ossl_asn1_put_object(&p, 1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn, tc);
1239        ossl_i2d_ASN1_TYPE(asn1, &p);
1240    } else {
1241        ossl_i2d_ASN1_TYPE(asn1, &p);
1242        *buf = tc | tn | (*buf & V_ASN1_CONSTRUCTED);
1243    }
1244    ossl_ASN1_TYPE_free(asn1);
1245    reallen = p - buf;
1246    assert(reallen <= len);
1247    str = ossl_buf2str((char *)buf, rb_long2int(reallen)); /* buf will be free in ossl_buf2str */
1248
1249    return str;
1250}
1251
1252/*
1253 * call-seq:
1254 *    asn1.to_der => DER-encoded String
1255 *
1256 * See ASN1Data#to_der for details.
1257 */
1258static VALUE
1259ossl_asn1cons_to_der(VALUE self)
1260{
1261    int tag, tn, tc, explicit, constructed = 1;
1262    int found_prim = 0, seq_len;
1263    long length;
1264    unsigned char *p;
1265    VALUE value, str, inf_length;
1266
1267    tn = NUM2INT(ossl_asn1_get_tag(self));
1268    tc = ossl_asn1_tag_class(self);
1269    inf_length = ossl_asn1_get_infinite_length(self);
1270    if (inf_length == Qtrue) {
1271	VALUE ary, example;
1272	constructed = 2;
1273	if (CLASS_OF(self) == cASN1Sequence ||
1274	    CLASS_OF(self) == cASN1Set) {
1275	    tag = ossl_asn1_default_tag(self);
1276	}
1277	else { /* must be a constructive encoding of a primitive value */
1278	    ary = ossl_asn1_get_value(self);
1279	    if (!rb_obj_is_kind_of(ary, rb_cArray))
1280		ossl_raise(eASN1Error, "Constructive value must be an Array");
1281	    /* Recursively descend until a primitive value is found.
1282	    The overall value of the entire constructed encoding
1283	    is of the type of the first primitive encoding to be
1284	    found. */
1285	    while (!found_prim){
1286		example = rb_ary_entry(ary, 0);
1287		if (rb_obj_is_kind_of(example, cASN1Primitive)){
1288		    found_prim = 1;
1289		}
1290		else {
1291		    /* example is another ASN1Constructive */
1292		    if (!rb_obj_is_kind_of(example, cASN1Constructive)){
1293			ossl_raise(eASN1Error, "invalid constructed encoding");
1294			return Qnil; /* dummy */
1295		    }
1296		    ary = ossl_asn1_get_value(example);
1297		}
1298	    }
1299	    tag = ossl_asn1_default_tag(example);
1300	}
1301    }
1302    else {
1303	if (CLASS_OF(self) == cASN1Constructive)
1304	    ossl_raise(eASN1Error, "Constructive shall only be used with infinite length");
1305	tag = ossl_asn1_default_tag(self);
1306    }
1307    explicit = ossl_asn1_is_explicit(self);
1308    value = join_der(ossl_asn1_get_value(self));
1309
1310    seq_len = ossl_asn1_object_size(constructed, RSTRING_LENINT(value), tag);
1311    length = ossl_asn1_object_size(constructed, seq_len, tn);
1312    str = rb_str_new(0, length);
1313    p = (unsigned char *)RSTRING_PTR(str);
1314    if(tc == V_ASN1_UNIVERSAL)
1315	ossl_asn1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc);
1316    else{
1317	if(explicit){
1318	    ossl_asn1_put_object(&p, constructed, seq_len, tn, tc);
1319	    ossl_asn1_put_object(&p, constructed, RSTRING_LENINT(value), tag, V_ASN1_UNIVERSAL);
1320	}
1321	else{
1322	    ossl_asn1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc);
1323	}
1324    }
1325    memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
1326    p += RSTRING_LEN(value);
1327
1328    /* In this case we need an additional EOC (one for the explicit part and
1329     * one for the Constructive itself. The EOC for the Constructive is
1330     * supplied by the user, but that for the "explicit wrapper" must be
1331     * added here.
1332     */
1333    if (explicit && inf_length == Qtrue) {
1334	ASN1_put_eoc(&p);
1335    }
1336    ossl_str_adjust(str, p);
1337
1338    return str;
1339}
1340
1341/*
1342 * call-seq:
1343 *    asn1_ary.each { |asn1| block } => asn1_ary
1344 *
1345 * Calls <i>block</i> once for each element in +self+, passing that element
1346 * as parameter +asn1+. If no block is given, an enumerator is returned
1347 * instead.
1348 *
1349 * == Example
1350 *   asn1_ary.each do |asn1|
1351 *     puts asn1
1352 *   end
1353 */
1354static VALUE
1355ossl_asn1cons_each(VALUE self)
1356{
1357    rb_ary_each(ossl_asn1_get_value(self));
1358    return self;
1359}
1360
1361static VALUE
1362ossl_asn1obj_s_register(VALUE self, VALUE oid, VALUE sn, VALUE ln)
1363{
1364    StringValue(oid);
1365    StringValue(sn);
1366    StringValue(ln);
1367
1368    if(!OBJ_create(RSTRING_PTR(oid), RSTRING_PTR(sn), RSTRING_PTR(ln)))
1369	ossl_raise(eASN1Error, NULL);
1370
1371    return Qtrue;
1372}
1373
1374static VALUE
1375ossl_asn1obj_get_sn(VALUE self)
1376{
1377    VALUE val, ret = Qnil;
1378    int nid;
1379
1380    val = ossl_asn1_get_value(self);
1381    if ((nid = OBJ_txt2nid(StringValuePtr(val))) != NID_undef)
1382	ret = rb_str_new2(OBJ_nid2sn(nid));
1383
1384    return ret;
1385}
1386
1387static VALUE
1388ossl_asn1obj_get_ln(VALUE self)
1389{
1390    VALUE val, ret = Qnil;
1391    int nid;
1392
1393    val = ossl_asn1_get_value(self);
1394    if ((nid = OBJ_txt2nid(StringValuePtr(val))) != NID_undef)
1395	ret = rb_str_new2(OBJ_nid2ln(nid));
1396
1397    return ret;
1398}
1399
1400static VALUE
1401ossl_asn1obj_get_oid(VALUE self)
1402{
1403    VALUE val;
1404    ASN1_OBJECT *a1obj;
1405    char buf[128];
1406
1407    val = ossl_asn1_get_value(self);
1408    a1obj = obj_to_asn1obj(val);
1409    OBJ_obj2txt(buf, sizeof(buf), a1obj, 1);
1410    ASN1_OBJECT_free(a1obj);
1411
1412    return rb_str_new2(buf);
1413}
1414
1415#define OSSL_ASN1_IMPL_FACTORY_METHOD(klass) \
1416static VALUE ossl_asn1_##klass(int argc, VALUE *argv, VALUE self)\
1417{ return rb_funcall3(cASN1##klass, rb_intern("new"), argc, argv); }
1418
1419OSSL_ASN1_IMPL_FACTORY_METHOD(Boolean)
1420OSSL_ASN1_IMPL_FACTORY_METHOD(Integer)
1421OSSL_ASN1_IMPL_FACTORY_METHOD(Enumerated)
1422OSSL_ASN1_IMPL_FACTORY_METHOD(BitString)
1423OSSL_ASN1_IMPL_FACTORY_METHOD(OctetString)
1424OSSL_ASN1_IMPL_FACTORY_METHOD(UTF8String)
1425OSSL_ASN1_IMPL_FACTORY_METHOD(NumericString)
1426OSSL_ASN1_IMPL_FACTORY_METHOD(PrintableString)
1427OSSL_ASN1_IMPL_FACTORY_METHOD(T61String)
1428OSSL_ASN1_IMPL_FACTORY_METHOD(VideotexString)
1429OSSL_ASN1_IMPL_FACTORY_METHOD(IA5String)
1430OSSL_ASN1_IMPL_FACTORY_METHOD(GraphicString)
1431OSSL_ASN1_IMPL_FACTORY_METHOD(ISO64String)
1432OSSL_ASN1_IMPL_FACTORY_METHOD(GeneralString)
1433OSSL_ASN1_IMPL_FACTORY_METHOD(UniversalString)
1434OSSL_ASN1_IMPL_FACTORY_METHOD(BMPString)
1435OSSL_ASN1_IMPL_FACTORY_METHOD(Null)
1436OSSL_ASN1_IMPL_FACTORY_METHOD(ObjectId)
1437OSSL_ASN1_IMPL_FACTORY_METHOD(UTCTime)
1438OSSL_ASN1_IMPL_FACTORY_METHOD(GeneralizedTime)
1439OSSL_ASN1_IMPL_FACTORY_METHOD(Sequence)
1440OSSL_ASN1_IMPL_FACTORY_METHOD(Set)
1441OSSL_ASN1_IMPL_FACTORY_METHOD(EndOfContent)
1442
1443void
1444Init_ossl_asn1()
1445{
1446    VALUE ary;
1447    int i;
1448
1449#if 0
1450    mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
1451#endif
1452
1453    sUNIVERSAL = rb_intern("UNIVERSAL");
1454    sCONTEXT_SPECIFIC = rb_intern("CONTEXT_SPECIFIC");
1455    sAPPLICATION = rb_intern("APPLICATION");
1456    sPRIVATE = rb_intern("PRIVATE");
1457    sEXPLICIT = rb_intern("EXPLICIT");
1458    sIMPLICIT = rb_intern("IMPLICIT");
1459
1460    sivVALUE = rb_intern("@value");
1461    sivTAG = rb_intern("@tag");
1462    sivTAGGING = rb_intern("@tagging");
1463    sivTAG_CLASS = rb_intern("@tag_class");
1464    sivINFINITE_LENGTH = rb_intern("@infinite_length");
1465    sivUNUSED_BITS = rb_intern("@unused_bits");
1466
1467    /*
1468     * Document-module: OpenSSL::ASN1
1469     *
1470     * Abstract Syntax Notation One (or ASN.1) is a notation syntax to
1471     * describe data structures and is defined in ITU-T X.680. ASN.1 itself
1472     * does not mandate any encoding or parsing rules, but usually ASN.1 data
1473     * structures are encoded using the Distinguished Encoding Rules (DER) or
1474     * less often the Basic Encoding Rules (BER) described in ITU-T X.690. DER
1475     * and BER encodings are binary Tag-Length-Value (TLV) encodings that are
1476     * quite concise compared to other popular data description formats such
1477     * as XML, JSON etc.
1478     * ASN.1 data structures are very common in cryptographic applications,
1479     * e.g. X.509 public key certificates or certificate revocation lists
1480     * (CRLs) are all defined in ASN.1 and DER-encoded. ASN.1, DER and BER are
1481     * the building blocks of applied cryptography.
1482     * The ASN1 module provides the necessary classes that allow generation
1483     * of ASN.1 data structures and the methods to encode them using a DER
1484     * encoding. The decode method allows parsing arbitrary BER-/DER-encoded
1485     * data to a Ruby object that can then be modified and re-encoded at will.
1486     *
1487     * == ASN.1 class hierarchy
1488     *
1489     * The base class representing ASN.1 structures is ASN1Data. ASN1Data offers
1490     * attributes to read and set the +tag+, the +tag_class+ and finally the
1491     * +value+ of a particular ASN.1 item. Upon parsing, any tagged values
1492     * (implicit or explicit) will be represented by ASN1Data instances because
1493     * their "real type" can only be determined using out-of-band information
1494     * from the ASN.1 type declaration. Since this information is normally
1495     * known when encoding a type, all sub-classes of ASN1Data offer an
1496     * additional attribute +tagging+ that allows to encode a value implicitly
1497     * (+:IMPLICIT+) or explicitly (+:EXPLICIT+).
1498     *
1499     * === Constructive
1500     *
1501     * Constructive is, as its name implies, the base class for all
1502     * constructed encodings, i.e. those that consist of several values,
1503     * opposed to "primitive" encodings with just one single value.
1504     * Primitive values that are encoded with "infinite length" are typically
1505     * constructed (their values come in multiple chunks) and are therefore
1506     * represented by instances of Constructive. The value of an Constructive
1507     * is always an Array.
1508     *
1509     * ==== ASN1::Set and ASN1::Sequence
1510     *
1511     * The most common constructive encodings are SETs and SEQUENCEs, which is
1512     * why there are two sub-classes of Constructive representing each of
1513     * them.
1514     *
1515     * === Primitive
1516     *
1517     * This is the super class of all primitive values. Primitive
1518     * itself is not used when parsing ASN.1 data, all values are either
1519     * instances of a corresponding sub-class of Primitive or they are
1520     * instances of ASN1Data if the value was tagged implicitly or explicitly.
1521     * Please cf. Primitive documentation for details on sub-classes and
1522     * their respective mappings of ASN.1 data types to Ruby objects.
1523     *
1524     * == Possible values for +tagging+
1525     *
1526     * When constructing an ASN1Data object the ASN.1 type definition may
1527     * require certain elements to be either implicitly or explicitly tagged.
1528     * This can be achieved by setting the +tagging+ attribute manually for
1529     * sub-classes of ASN1Data. Use the symbol +:IMPLICIT+ for implicit
1530     * tagging and +:EXPLICIT+ if the element requires explicit tagging.
1531     *
1532     * == Possible values for +tag_class+
1533     *
1534     * It is possible to create arbitrary ASN1Data objects that also support
1535     * a PRIVATE or APPLICATION tag class. Possible values for the +tag_class+
1536     * attribute are:
1537     * * +:UNIVERSAL+ (the default for untagged values)
1538     * * +:CONTEXT_SPECIFIC+ (the default for tagged values)
1539     * * +:APPLICATION+
1540     * * +:PRIVATE+
1541     *
1542     * == Tag constants
1543     *
1544     * There is a constant defined for each universal tag:
1545     * * OpenSSL::ASN1::EOC (0)
1546     * * OpenSSL::ASN1::BOOLEAN (1)
1547     * * OpenSSL::ASN1::INTEGER (2)
1548     * * OpenSSL::ASN1::BIT_STRING (3)
1549     * * OpenSSL::ASN1::OCTET_STRING (4)
1550     * * OpenSSL::ASN1::NULL (5)
1551     * * OpenSSL::ASN1::OBJECT (6)
1552     * * OpenSSL::ASN1::ENUMERATED (10)
1553     * * OpenSSL::ASN1::UTF8STRING (12)
1554     * * OpenSSL::ASN1::SEQUENCE (16)
1555     * * OpenSSL::ASN1::SET (17)
1556     * * OpenSSL::ASN1::NUMERICSTRING (18)
1557     * * OpenSSL::ASN1::PRINTABLESTRING (19)
1558     * * OpenSSL::ASN1::T61STRING (20)
1559     * * OpenSSL::ASN1::VIDEOTEXSTRING (21)
1560     * * OpenSSL::ASN1::IA5STRING (22)
1561     * * OpenSSL::ASN1::UTCTIME (23)
1562     * * OpenSSL::ASN1::GENERALIZEDTIME (24)
1563     * * OpenSSL::ASN1::GRAPHICSTRING (25)
1564     * * OpenSSL::ASN1::ISO64STRING (26)
1565     * * OpenSSL::ASN1::GENERALSTRING (27)
1566     * * OpenSSL::ASN1::UNIVERSALSTRING (28)
1567     * * OpenSSL::ASN1::BMPSTRING (30)
1568     *
1569     * == UNIVERSAL_TAG_NAME constant
1570     *
1571     * An Array that stores the name of a given tag number. These names are
1572     * the same as the name of the tag constant that is additionally defined,
1573     * e.g. UNIVERSAL_TAG_NAME[2] = "INTEGER" and OpenSSL::ASN1::INTEGER = 2.
1574     *
1575     * == Example usage
1576     *
1577     * === Decoding and viewing a DER-encoded file
1578     *   require 'openssl'
1579     *   require 'pp'
1580     *   der = File.binread('data.der')
1581     *   asn1 = OpenSSL::ASN1.decode(der)
1582     *   pp der
1583     *
1584     * === Creating an ASN.1 structure and DER-encoding it
1585     *   require 'openssl'
1586     *   version = OpenSSL::ASN1::Integer.new(1)
1587     *   # Explicitly 0-tagged implies context-specific tag class
1588     *   serial = OpenSSL::ASN1::Integer.new(12345, 0, :EXPLICIT, :CONTEXT_SPECIFIC)
1589     *   name = OpenSSL::ASN1::PrintableString.new('Data 1')
1590     *   sequence = OpenSSL::ASN1::Sequence.new( [ version, serial, name ] )
1591     *   der = sequence.to_der
1592     */
1593    mASN1 = rb_define_module_under(mOSSL, "ASN1");
1594
1595    /* Document-class: OpenSSL::ASN1::ASN1Error
1596     *
1597     * Generic error class for all errors raised in ASN1 and any of the
1598     * classes defined in it.
1599     */
1600    eASN1Error = rb_define_class_under(mASN1, "ASN1Error", eOSSLError);
1601    rb_define_module_function(mASN1, "traverse", ossl_asn1_traverse, 1);
1602    rb_define_module_function(mASN1, "decode", ossl_asn1_decode, 1);
1603    rb_define_module_function(mASN1, "decode_all", ossl_asn1_decode_all, 1);
1604    ary = rb_ary_new();
1605
1606    /*
1607     * Array storing tag names at the tag's index.
1608     */
1609    rb_define_const(mASN1, "UNIVERSAL_TAG_NAME", ary);
1610    for(i = 0; i < ossl_asn1_info_size; i++){
1611	if(ossl_asn1_info[i].name[0] == '[') continue;
1612	rb_define_const(mASN1, ossl_asn1_info[i].name, INT2NUM(i));
1613	rb_ary_store(ary, i, rb_str_new2(ossl_asn1_info[i].name));
1614    }
1615
1616    /* Document-class: OpenSSL::ASN1::ASN1Data
1617     *
1618     * The top-level class representing any ASN.1 object. When parsed by
1619     * ASN1.decode, tagged values are always represented by an instance
1620     * of ASN1Data.
1621     *
1622     * == The role of ASN1Data for parsing tagged values
1623     *
1624     * When encoding an ASN.1 type it is inherently clear what original
1625     * type (e.g. INTEGER, OCTET STRING etc.) this value has, regardless
1626     * of its tagging.
1627     * But opposed to the time an ASN.1 type is to be encoded, when parsing
1628     * them it is not possible to deduce the "real type" of tagged
1629     * values. This is why tagged values are generally parsed into ASN1Data
1630     * instances, but with a different outcome for implicit and explicit
1631     * tagging.
1632     *
1633     * === Example of a parsed implicitly tagged value
1634     *
1635     * An implicitly 1-tagged INTEGER value will be parsed as an
1636     * ASN1Data with
1637     * * +tag+ equal to 1
1638     * * +tag_class+ equal to +:CONTEXT_SPECIFIC+
1639     * * +value+ equal to a +String+ that carries the raw encoding
1640     *   of the INTEGER.
1641     * This implies that a subsequent decoding step is required to
1642     * completely decode implicitly tagged values.
1643     *
1644     * === Example of a parsed explicitly tagged value
1645     *
1646     * An explicitly 1-tagged INTEGER value will be parsed as an
1647     * ASN1Data with
1648     * * +tag+ equal to 1
1649     * * +tag_class+ equal to +:CONTEXT_SPECIFIC+
1650     * * +value+ equal to an +Array+ with one single element, an
1651     *   instance of OpenSSL::ASN1::Integer, i.e. the inner element
1652     *   is the non-tagged primitive value, and the tagging is represented
1653     *   in the outer ASN1Data
1654     *
1655     * == Example - Decoding an implicitly tagged INTEGER
1656     *   int = OpenSSL::ASN1::Integer.new(1, 0, :IMPLICIT) # implicit 0-tagged
1657     *   seq = OpenSSL::ASN1::Sequence.new( [int] )
1658     *   der = seq.to_der
1659     *   asn1 = OpenSSL::ASN1.decode(der)
1660     *   # pp asn1 => #<OpenSSL::ASN1::Sequence:0x87326e0
1661     *   #              @infinite_length=false,
1662     *   #              @tag=16,
1663     *   #              @tag_class=:UNIVERSAL,
1664     *   #              @tagging=nil,
1665     *   #              @value=
1666     *   #                [#<OpenSSL::ASN1::ASN1Data:0x87326f4
1667     *   #                   @infinite_length=false,
1668     *   #                   @tag=0,
1669     *   #                   @tag_class=:CONTEXT_SPECIFIC,
1670     *   #                   @value="\x01">]>
1671     *   raw_int = asn1.value[0]
1672     *   # manually rewrite tag and tag class to make it an UNIVERSAL value
1673     *   raw_int.tag = OpenSSL::ASN1::INTEGER
1674     *   raw_int.tag_class = :UNIVERSAL
1675     *   int2 = OpenSSL::ASN1.decode(raw_int)
1676     *   puts int2.value # => 1
1677     *
1678     * == Example - Decoding an explicitly tagged INTEGER
1679     *   int = OpenSSL::ASN1::Integer.new(1, 0, :EXPLICIT) # explicit 0-tagged
1680     *   seq = OpenSSL::ASN1::Sequence.new( [int] )
1681     *   der = seq.to_der
1682     *   asn1 = OpenSSL::ASN1.decode(der)
1683     *   # pp asn1 => #<OpenSSL::ASN1::Sequence:0x87326e0
1684     *   #              @infinite_length=false,
1685     *   #              @tag=16,
1686     *   #              @tag_class=:UNIVERSAL,
1687     *   #              @tagging=nil,
1688     *   #              @value=
1689     *   #                [#<OpenSSL::ASN1::ASN1Data:0x87326f4
1690     *   #                   @infinite_length=false,
1691     *   #                   @tag=0,
1692     *   #                   @tag_class=:CONTEXT_SPECIFIC,
1693     *   #                   @value=
1694     *   #                     [#<OpenSSL::ASN1::Integer:0x85bf308
1695     *   #                        @infinite_length=false,
1696     *   #                        @tag=2,
1697     *   #                        @tag_class=:UNIVERSAL
1698     *   #                        @tagging=nil,
1699     *   #                        @value=1>]>]>
1700     *   int2 = asn1.value[0].value[0]
1701     *   puts int2.value # => 1
1702     */
1703    cASN1Data = rb_define_class_under(mASN1, "ASN1Data", rb_cObject);
1704    /*
1705     * Carries the value of a ASN.1 type.
1706     * Please confer Constructive and Primitive for the mappings between
1707     * ASN.1 data types and Ruby classes.
1708     */
1709    rb_attr(cASN1Data, rb_intern("value"), 1, 1, 0);
1710    /*
1711     * A +Number+ representing the tag number of this ASN1Data. Never +nil+.
1712     */
1713    rb_attr(cASN1Data, rb_intern("tag"), 1, 1, 0);
1714    /*
1715     * A +Symbol+ representing the tag class of this ASN1Data. Never +nil+.
1716     * See ASN1Data for possible values.
1717     */
1718    rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, 0);
1719    /*
1720     * Never +nil+. A +Boolean+ indicating whether the encoding was infinite
1721     * length (in the case of parsing) or whether an infinite length encoding
1722     * shall be used (in the encoding case).
1723     * In DER, every value has a finite length associated with it. But in
1724     * scenarios where large amounts of data need to be transferred it
1725     * might be desirable to have some kind of streaming support available.
1726     * For example, huge OCTET STRINGs are preferably sent in smaller-sized
1727     * chunks, each at a time.
1728     * This is possible in BER by setting the length bytes of an encoding
1729     * to zero and by this indicating that the following value will be
1730     * sent in chunks. Infinite length encodings are always constructed.
1731     * The end of such a stream of chunks is indicated by sending a EOC
1732     * (End of Content) tag. SETs and SEQUENCEs may use an infinite length
1733     * encoding, but also primitive types such as e.g. OCTET STRINGS or
1734     * BIT STRINGS may leverage this functionality (cf. ITU-T X.690).
1735     */
1736    rb_attr(cASN1Data, rb_intern("infinite_length"), 1, 1, 0);
1737    rb_define_method(cASN1Data, "initialize", ossl_asn1data_initialize, 3);
1738    rb_define_method(cASN1Data, "to_der", ossl_asn1data_to_der, 0);
1739
1740    /* Document-class: OpenSSL::ASN1::Primitive
1741     *
1742     * The parent class for all primitive encodings. Attributes are the same as
1743     * for ASN1Data, with the addition of +tagging+.
1744     * Primitive values can never be infinite length encodings, thus it is not
1745     * possible to set the +infinite_length+ attribute for Primitive and its
1746     * sub-classes.
1747     *
1748     * == Primitive sub-classes and their mapping to Ruby classes
1749     * * OpenSSL::ASN1::EndOfContent    <=> +value+ is always +nil+
1750     * * OpenSSL::ASN1::Boolean         <=> +value+ is a +Boolean+
1751     * * OpenSSL::ASN1::Integer         <=> +value+ is a +Number+
1752     * * OpenSSL::ASN1::BitString       <=> +value+ is a +String+
1753     * * OpenSSL::ASN1::OctetString     <=> +value+ is a +String+
1754     * * OpenSSL::ASN1::Null            <=> +value+ is always +nil+
1755     * * OpenSSL::ASN1::Object          <=> +value+ is a +String+
1756     * * OpenSSL::ASN1::Enumerated      <=> +value+ is a +Number+
1757     * * OpenSSL::ASN1::UTF8String      <=> +value+ is a +String+
1758     * * OpenSSL::ASN1::NumericString   <=> +value+ is a +String+
1759     * * OpenSSL::ASN1::PrintableString <=> +value+ is a +String+
1760     * * OpenSSL::ASN1::T61String       <=> +value+ is a +String+
1761     * * OpenSSL::ASN1::VideotexString  <=> +value+ is a +String+
1762     * * OpenSSL::ASN1::IA5String       <=> +value+ is a +String+
1763     * * OpenSSL::ASN1::UTCTime         <=> +value+ is a +Time+
1764     * * OpenSSL::ASN1::GeneralizedTime <=> +value+ is a +Time+
1765     * * OpenSSL::ASN1::GraphicString   <=> +value+ is a +String+
1766     * * OpenSSL::ASN1::ISO64String     <=> +value+ is a +String+
1767     * * OpenSSL::ASN1::GeneralString   <=> +value+ is a +String+
1768     * * OpenSSL::ASN1::UniversalString <=> +value+ is a +String+
1769     * * OpenSSL::ASN1::BMPString       <=> +value+ is a +String+
1770     *
1771     * == OpenSSL::ASN1::BitString
1772     *
1773     * === Additional attributes
1774     * +unused_bits+: if the underlying BIT STRING's
1775     * length is a multiple of 8 then +unused_bits+ is 0. Otherwise
1776     * +unused_bits+ indicates the number of bits that are to be ignored in
1777     * the final octet of the +BitString+'s +value+.
1778     *
1779     * == OpenSSL::ASN1::ObjectId
1780     *
1781     * === Additional attributes
1782     * * +sn+: the short name as defined in <openssl/objects.h>.
1783     * * +ln+: the long name as defined in <openssl/objects.h>.
1784     * * +oid+: the object identifier as a +String+, e.g. "1.2.3.4.5"
1785     * * +short_name+: alias for +sn+.
1786     * * +long_name+: alias for +ln+.
1787     *
1788     * == Examples
1789     * With the Exception of OpenSSL::ASN1::EndOfContent, each Primitive class
1790     * constructor takes at least one parameter, the +value+.
1791     *
1792     * === Creating EndOfContent
1793     *   eoc = OpenSSL::ASN1::EndOfContent.new
1794     *
1795     * === Creating any other Primitive
1796     *   prim = <class>.new(value) # <class> being one of the sub-classes except EndOfContent
1797     *   prim_zero_tagged_implicit = <class>.new(value, 0, :IMPLICIT)
1798     *   prim_zero_tagged_explicit = <class>.new(value, 0, :EXPLICIT)
1799     */
1800    cASN1Primitive = rb_define_class_under(mASN1, "Primitive", cASN1Data);
1801    /*
1802     * May be used as a hint for encoding a value either implicitly or
1803     * explicitly by setting it either to +:IMPLICIT+ or to +:EXPLICIT+.
1804     * +tagging+ is not set when a ASN.1 structure is parsed using
1805     * OpenSSL::ASN1.decode.
1806     */
1807    rb_attr(cASN1Primitive, rb_intern("tagging"), 1, 1, Qtrue);
1808    rb_undef_method(cASN1Primitive, "infinite_length=");
1809    rb_define_method(cASN1Primitive, "initialize", ossl_asn1_initialize, -1);
1810    rb_define_method(cASN1Primitive, "to_der", ossl_asn1prim_to_der, 0);
1811
1812    /* Document-class: OpenSSL::ASN1::Constructive
1813     *
1814     * The parent class for all constructed encodings. The +value+ attribute
1815     * of a Constructive is always an +Array+. Attributes are the same as
1816     * for ASN1Data, with the addition of +tagging+.
1817     *
1818     * == SET and SEQUENCE
1819     *
1820     * Most constructed encodings come in the form of a SET or a SEQUENCE.
1821     * These encodings are represented by one of the two sub-classes of
1822     * Constructive:
1823     * * OpenSSL::ASN1::Set
1824     * * OpenSSL::ASN1::Sequence
1825     * Please note that tagged sequences and sets are still parsed as
1826     * instances of ASN1Data. Find further details on tagged values
1827     * there.
1828     *
1829     * === Example - constructing a SEQUENCE
1830     *   int = OpenSSL::ASN1::Integer.new(1)
1831     *   str = OpenSSL::ASN1::PrintableString.new('abc')
1832     *   sequence = OpenSSL::ASN1::Sequence.new( [ int, str ] )
1833     *
1834     * === Example - constructing a SET
1835     *   int = OpenSSL::ASN1::Integer.new(1)
1836     *   str = OpenSSL::ASN1::PrintableString.new('abc')
1837     *   set = OpenSSL::ASN1::Set.new( [ int, str ] )
1838     *
1839     * == Infinite length primitive values
1840     *
1841     * The only case where Constructive is used directly is for infinite
1842     * length encodings of primitive values. These encodings are always
1843     * constructed, with the contents of the +value+ +Array+ being either
1844     * UNIVERSAL non-infinite length partial encodings of the actual value
1845     * or again constructive encodings with infinite length (i.e. infinite
1846     * length primitive encodings may be constructed recursively with another
1847     * infinite length value within an already infinite length value). Each
1848     * partial encoding must be of the same UNIVERSAL type as the overall
1849     * encoding. The value of the overall encoding consists of the
1850     * concatenation of each partial encoding taken in sequence. The +value+
1851     * array of the outer infinite length value must end with a
1852     * OpenSSL::ASN1::EndOfContent instance.
1853     *
1854     * Please note that it is not possible to encode Constructive without
1855     * the +infinite_length+ attribute being set to +true+, use
1856     * OpenSSL::ASN1::Sequence or OpenSSL::ASN1::Set in these cases instead.
1857     *
1858     * === Example - Infinite length OCTET STRING
1859     *   partial1 = OpenSSL::ASN1::OctetString.new("\x01")
1860     *   partial2 = OpenSSL::ASN1::OctetString.new("\x02")
1861     *   inf_octets = OpenSSL::ASN1::Constructive.new( [ partial1,
1862     *                                                   partial2,
1863     *                                                   OpenSSL::ASN1::EndOfContent.new ],
1864     *                                                 OpenSSL::ASN1::OCTET_STRING,
1865     *                                                 nil,
1866     *                                                 :UNIVERSAL )
1867     *   # The real value of inf_octets is "\x01\x02", i.e. the concatenation
1868     *   # of partial1 and partial2
1869     *   inf_octets.infinite_length = true
1870     *   der = inf_octets.to_der
1871     *   asn1 = OpenSSL::ASN1.decode(der)
1872     *   puts asn1.infinite_length # => true
1873     */
1874    cASN1Constructive = rb_define_class_under(mASN1,"Constructive", cASN1Data);
1875    rb_include_module(cASN1Constructive, rb_mEnumerable);
1876    /*
1877     * May be used as a hint for encoding a value either implicitly or
1878     * explicitly by setting it either to +:IMPLICIT+ or to +:EXPLICIT+.
1879     * +tagging+ is not set when a ASN.1 structure is parsed using
1880     * OpenSSL::ASN1.decode.
1881     */
1882    rb_attr(cASN1Constructive, rb_intern("tagging"), 1, 1, Qtrue);
1883    rb_define_method(cASN1Constructive, "initialize", ossl_asn1_initialize, -1);
1884    rb_define_method(cASN1Constructive, "to_der", ossl_asn1cons_to_der, 0);
1885    rb_define_method(cASN1Constructive, "each", ossl_asn1cons_each, 0);
1886
1887#define OSSL_ASN1_DEFINE_CLASS(name, super) \
1888do{\
1889    cASN1##name = rb_define_class_under(mASN1, #name, cASN1##super);\
1890    rb_define_module_function(mASN1, #name, ossl_asn1_##name, -1);\
1891}while(0)
1892
1893    OSSL_ASN1_DEFINE_CLASS(Boolean, Primitive);
1894    OSSL_ASN1_DEFINE_CLASS(Integer, Primitive);
1895    OSSL_ASN1_DEFINE_CLASS(Enumerated, Primitive);
1896    OSSL_ASN1_DEFINE_CLASS(BitString, Primitive);
1897    OSSL_ASN1_DEFINE_CLASS(OctetString, Primitive);
1898    OSSL_ASN1_DEFINE_CLASS(UTF8String, Primitive);
1899    OSSL_ASN1_DEFINE_CLASS(NumericString, Primitive);
1900    OSSL_ASN1_DEFINE_CLASS(PrintableString, Primitive);
1901    OSSL_ASN1_DEFINE_CLASS(T61String, Primitive);
1902    OSSL_ASN1_DEFINE_CLASS(VideotexString, Primitive);
1903    OSSL_ASN1_DEFINE_CLASS(IA5String, Primitive);
1904    OSSL_ASN1_DEFINE_CLASS(GraphicString, Primitive);
1905    OSSL_ASN1_DEFINE_CLASS(ISO64String, Primitive);
1906    OSSL_ASN1_DEFINE_CLASS(GeneralString, Primitive);
1907    OSSL_ASN1_DEFINE_CLASS(UniversalString, Primitive);
1908    OSSL_ASN1_DEFINE_CLASS(BMPString, Primitive);
1909    OSSL_ASN1_DEFINE_CLASS(Null, Primitive);
1910    OSSL_ASN1_DEFINE_CLASS(ObjectId, Primitive);
1911    OSSL_ASN1_DEFINE_CLASS(UTCTime, Primitive);
1912    OSSL_ASN1_DEFINE_CLASS(GeneralizedTime, Primitive);
1913
1914    OSSL_ASN1_DEFINE_CLASS(Sequence, Constructive);
1915    OSSL_ASN1_DEFINE_CLASS(Set, Constructive);
1916
1917    OSSL_ASN1_DEFINE_CLASS(EndOfContent, Data);
1918
1919
1920#if 0
1921    cASN1ObjectId = rb_define_class_under(mASN1, "ObjectId", cASN1Primitive);  /* let rdoc know */
1922#endif
1923    rb_define_singleton_method(cASN1ObjectId, "register", ossl_asn1obj_s_register, 3);
1924    rb_define_method(cASN1ObjectId, "sn", ossl_asn1obj_get_sn, 0);
1925    rb_define_method(cASN1ObjectId, "ln", ossl_asn1obj_get_ln, 0);
1926    rb_define_method(cASN1ObjectId, "oid", ossl_asn1obj_get_oid, 0);
1927    rb_define_alias(cASN1ObjectId, "short_name", "sn");
1928    rb_define_alias(cASN1ObjectId, "long_name", "ln");
1929    rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, 0);
1930
1931    rb_define_method(cASN1EndOfContent, "initialize", ossl_asn1eoc_initialize, 0);
1932
1933    class_tag_map = rb_hash_new();
1934    rb_hash_aset(class_tag_map, cASN1EndOfContent, INT2NUM(V_ASN1_EOC));
1935    rb_hash_aset(class_tag_map, cASN1Boolean, INT2NUM(V_ASN1_BOOLEAN));
1936    rb_hash_aset(class_tag_map, cASN1Integer, INT2NUM(V_ASN1_INTEGER));
1937    rb_hash_aset(class_tag_map, cASN1BitString, INT2NUM(V_ASN1_BIT_STRING));
1938    rb_hash_aset(class_tag_map, cASN1OctetString, INT2NUM(V_ASN1_OCTET_STRING));
1939    rb_hash_aset(class_tag_map, cASN1Null, INT2NUM(V_ASN1_NULL));
1940    rb_hash_aset(class_tag_map, cASN1ObjectId, INT2NUM(V_ASN1_OBJECT));
1941    rb_hash_aset(class_tag_map, cASN1Enumerated, INT2NUM(V_ASN1_ENUMERATED));
1942    rb_hash_aset(class_tag_map, cASN1UTF8String, INT2NUM(V_ASN1_UTF8STRING));
1943    rb_hash_aset(class_tag_map, cASN1Sequence, INT2NUM(V_ASN1_SEQUENCE));
1944    rb_hash_aset(class_tag_map, cASN1Set, INT2NUM(V_ASN1_SET));
1945    rb_hash_aset(class_tag_map, cASN1NumericString, INT2NUM(V_ASN1_NUMERICSTRING));
1946    rb_hash_aset(class_tag_map, cASN1PrintableString, INT2NUM(V_ASN1_PRINTABLESTRING));
1947    rb_hash_aset(class_tag_map, cASN1T61String, INT2NUM(V_ASN1_T61STRING));
1948    rb_hash_aset(class_tag_map, cASN1VideotexString, INT2NUM(V_ASN1_VIDEOTEXSTRING));
1949    rb_hash_aset(class_tag_map, cASN1IA5String, INT2NUM(V_ASN1_IA5STRING));
1950    rb_hash_aset(class_tag_map, cASN1UTCTime, INT2NUM(V_ASN1_UTCTIME));
1951    rb_hash_aset(class_tag_map, cASN1GeneralizedTime, INT2NUM(V_ASN1_GENERALIZEDTIME));
1952    rb_hash_aset(class_tag_map, cASN1GraphicString, INT2NUM(V_ASN1_GRAPHICSTRING));
1953    rb_hash_aset(class_tag_map, cASN1ISO64String, INT2NUM(V_ASN1_ISO64STRING));
1954    rb_hash_aset(class_tag_map, cASN1GeneralString, INT2NUM(V_ASN1_GENERALSTRING));
1955    rb_hash_aset(class_tag_map, cASN1UniversalString, INT2NUM(V_ASN1_UNIVERSALSTRING));
1956    rb_hash_aset(class_tag_map, cASN1BMPString, INT2NUM(V_ASN1_BMPSTRING));
1957    rb_global_variable(&class_tag_map);
1958}
1959