Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# ext/openssl/ossl_asn1.c

Go to the documentation of this file.

    00001 /*
    00002  * $Id: ossl_asn1.c 29389 2010-10-02 11:20:01Z yugui $
    00003  * 'OpenSSL for Ruby' team members
    00004  * Copyright (C) 2003
    00005  * All rights reserved.
    00006  */
    00007 /*
    00008  * This program is licenced under the same licence as Ruby.
    00009  * (See the file 'LICENCE'.)
    00010  */
    00011 #include "ossl.h"
    00012
    00013 #if defined(HAVE_SYS_TIME_H)
    00014 #  include <sys/time.h>
    00015 #elif !defined(NT) && !defined(_WIN32)
    00016 struct timeval {
    00017     long tv_sec;        /* seconds */
    00018     long tv_usec;       /* and microseconds */
    00019 };
    00020 #endif
    00021
    00022 /*
    00023  * DATE conversion
    00024  */
    00025 VALUE
    00026 asn1time_to_time(ASN1_TIME *time)
    00027 {
    00028     struct tm tm;
    00029     VALUE argv[6];
    00030
    00031     if (!time || !time->data) return Qnil;
    00032     memset(&tm, 0, sizeof(struct tm));
    00033
    00034     switch (time->type) {
    00035     case V_ASN1_UTCTIME:
    00036         if (sscanf((const char *)time->data, "%2d%2d%2d%2d%2d%2dZ", &tm.tm_year, &tm.tm_mon,
    00037                 &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
    00038             ossl_raise(rb_eTypeError, "bad UTCTIME format");
    00039         }
    00040         if (tm.tm_year < 69) {
    00041             tm.tm_year += 2000;
    00042         } else {
    00043             tm.tm_year += 1900;
    00044         }
    00045         break;
    00046     case V_ASN1_GENERALIZEDTIME:
    00047         if (sscanf((const char *)time->data, "%4d%2d%2d%2d%2d%2dZ", &tm.tm_year, &tm.tm_mon,
    00048                 &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
    00049             ossl_raise(rb_eTypeError, "bad GENERALIZEDTIME format" );
    00050         }
    00051         break;
    00052     default:
    00053         rb_warning("unknown time format");
    00054         return Qnil;
    00055     }
    00056     argv[0] = INT2NUM(tm.tm_year);
    00057     argv[1] = INT2NUM(tm.tm_mon);
    00058     argv[2] = INT2NUM(tm.tm_mday);
    00059     argv[3] = INT2NUM(tm.tm_hour);
    00060     argv[4] = INT2NUM(tm.tm_min);
    00061     argv[5] = INT2NUM(tm.tm_sec);
    00062
    00063     return rb_funcall2(rb_cTime, rb_intern("utc"), 6, argv);
    00064 }
    00065
    00066 /*
    00067  * This function is not exported in Ruby's *.h
    00068  */
    00069 extern struct timeval rb_time_timeval(VALUE);
    00070
    00071 time_t
    00072 time_to_time_t(VALUE time)
    00073 {
    00074     return (time_t)NUM2LONG(rb_Integer(time));
    00075 }
    00076
    00077 /*
    00078  * STRING conversion
    00079  */
    00080 VALUE
    00081 asn1str_to_str(ASN1_STRING *str)
    00082 {
    00083     return rb_str_new((const char *)str->data, str->length);
    00084 }
    00085
    00086 /*
    00087  * ASN1_INTEGER conversions
    00088  * TODO: Make a decision what's the right way to do this.
    00089  */
    00090 #define DO_IT_VIA_RUBY 0
    00091 VALUE
    00092 asn1integer_to_num(ASN1_INTEGER *ai)
    00093 {
    00094     BIGNUM *bn;
    00095 #if DO_IT_VIA_RUBY
    00096     char *txt;
    00097 #endif
    00098     VALUE num;
    00099
    00100     if (!ai) {
    00101         ossl_raise(rb_eTypeError, "ASN1_INTEGER is NULL!");
    00102     }
    00103     if (!(bn = ASN1_INTEGER_to_BN(ai, NULL))) {
    00104         ossl_raise(eOSSLError, NULL);
    00105     }
    00106 #if DO_IT_VIA_RUBY
    00107     if (!(txt = BN_bn2dec(bn))) {
    00108         BN_free(bn);
    00109         ossl_raise(eOSSLError, NULL);
    00110     }
    00111     num = rb_cstr_to_inum(txt, 10, Qtrue);
    00112     OPENSSL_free(txt);
    00113 #else
    00114     num = ossl_bn_new(bn);
    00115 #endif
    00116     BN_free(bn);
    00117
    00118     return num;
    00119 }
    00120
    00121 #if DO_IT_VIA_RUBY
    00122 ASN1_INTEGER *
    00123 num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
    00124 {
    00125     BIGNUM *bn = NULL;
    00126
    00127     if (RTEST(rb_obj_is_kind_of(obj, cBN))) {
    00128         bn = GetBNPtr(obj);
    00129     } else {
    00130         obj = rb_String(obj);
    00131         if (!BN_dec2bn(&bn, StringValuePtr(obj))) {
    00132             ossl_raise(eOSSLError, NULL);
    00133         }
    00134     }
    00135     if (!(ai = BN_to_ASN1_INTEGER(bn, ai))) {
    00136         BN_free(bn);
    00137         ossl_raise(eOSSLError, NULL);
    00138     }
    00139     BN_free(bn);
    00140     return ai;
    00141 }
    00142 #else
    00143 ASN1_INTEGER *
    00144 num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
    00145 {
    00146     BIGNUM *bn = GetBNPtr(obj);
    00147
    00148     if (!(ai = BN_to_ASN1_INTEGER(bn, ai))) {
    00149         ossl_raise(eOSSLError, NULL);
    00150     }
    00151     return ai;
    00152 }
    00153 #endif
    00154
    00155 /********/
    00156 /*
    00157  * ASN1 module
    00158  */
    00159 #define ossl_asn1_get_value(o)       rb_attr_get((o),rb_intern("@value"))
    00160 #define ossl_asn1_get_tag(o)         rb_attr_get((o),rb_intern("@tag"))
    00161 #define ossl_asn1_get_tagging(o)     rb_attr_get((o),rb_intern("@tagging"))
    00162 #define ossl_asn1_get_tag_class(o)   rb_attr_get((o),rb_intern("@tag_class"))
    00163
    00164 #define ossl_asn1_set_value(o,v)     rb_iv_set((o),"@value",(v))
    00165 #define ossl_asn1_set_tag(o,v)       rb_iv_set((o),"@tag",(v))
    00166 #define ossl_asn1_set_tagging(o,v)   rb_iv_set((o),"@tagging",(v))
    00167 #define ossl_asn1_set_tag_class(o,v) rb_iv_set((o),"@tag_class",(v))
    00168
    00169 VALUE mASN1;
    00170 VALUE eASN1Error;
    00171
    00172 VALUE cASN1Data;
    00173 VALUE cASN1Primitive;
    00174 VALUE cASN1Constructive;
    00175
    00176 VALUE cASN1Boolean;                           /* BOOLEAN           */
    00177 VALUE cASN1Integer, cASN1Enumerated;          /* INTEGER           */
    00178 VALUE cASN1BitString;                         /* BIT STRING        */
    00179 VALUE cASN1OctetString, cASN1UTF8String;      /* STRINGs           */
    00180 VALUE cASN1NumericString, cASN1PrintableString;
    00181 VALUE cASN1T61String, cASN1VideotexString;
    00182 VALUE cASN1IA5String, cASN1GraphicString;
    00183 VALUE cASN1ISO64String, cASN1GeneralString;
    00184 VALUE cASN1UniversalString, cASN1BMPString;
    00185 VALUE cASN1Null;                              /* NULL              */
    00186 VALUE cASN1ObjectId;                          /* OBJECT IDENTIFIER */
    00187 VALUE cASN1UTCTime, cASN1GeneralizedTime;     /* TIME              */
    00188 VALUE cASN1Sequence, cASN1Set;                /* CONSTRUCTIVE      */
    00189
    00190 static ID sIMPLICIT, sEXPLICIT;
    00191 static ID sUNIVERSAL, sAPPLICATION, sCONTEXT_SPECIFIC, sPRIVATE;
    00192
    00193 /*
    00194  * Ruby to ASN1 converters
    00195  */
    00196 static ASN1_BOOLEAN
    00197 obj_to_asn1bool(VALUE obj)
    00198 {
    00199 #if OPENSSL_VERSION_NUMBER < 0x00907000L
    00200      return RTEST(obj) ? 0xff : 0x100;
    00201 #else
    00202      return RTEST(obj) ? 0xff : 0x0;
    00203 #endif
    00204 }
    00205
    00206 static ASN1_INTEGER*
    00207 obj_to_asn1int(VALUE obj)
    00208 {
    00209     return num_to_asn1integer(obj, NULL);
    00210 }
    00211
    00212 static ASN1_BIT_STRING*
    00213 obj_to_asn1bstr(VALUE obj, long unused_bits)
    00214 {
    00215     ASN1_BIT_STRING *bstr;
    00216
    00217     if(unused_bits < 0) unused_bits = 0;
    00218     StringValue(obj);
    00219     if(!(bstr = ASN1_BIT_STRING_new()))
    00220         ossl_raise(eASN1Error, NULL);
    00221     ASN1_BIT_STRING_set(bstr, (unsigned char *)RSTRING_PTR(obj), RSTRING_LEN(obj));
    00222     bstr->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */
    00223     bstr->flags |= ASN1_STRING_FLAG_BITS_LEFT|(unused_bits&0x07);
    00224
    00225     return bstr;
    00226 }
    00227
    00228 static ASN1_STRING*
    00229 obj_to_asn1str(VALUE obj)
    00230 {
    00231     ASN1_STRING *str;
    00232
    00233     StringValue(obj);
    00234     if(!(str = ASN1_STRING_new()))
    00235         ossl_raise(eASN1Error, NULL);
    00236     ASN1_STRING_set(str, RSTRING_PTR(obj), RSTRING_LEN(obj));
    00237
    00238     return str;
    00239 }
    00240
    00241 static ASN1_NULL*
    00242 obj_to_asn1null(VALUE obj)
    00243 {
    00244     ASN1_NULL *null;
    00245
    00246     if(!NIL_P(obj))
    00247         ossl_raise(eASN1Error, "nil expected");
    00248     if(!(null = ASN1_NULL_new()))
    00249         ossl_raise(eASN1Error, NULL);
    00250
    00251     return null;
    00252 }
    00253
    00254 static ASN1_OBJECT*
    00255 obj_to_asn1obj(VALUE obj)
    00256 {
    00257     ASN1_OBJECT *a1obj;
    00258
    00259     StringValue(obj);
    00260     a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 0);
    00261     if(!a1obj) a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 1);
    00262     if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID");
    00263
    00264     return a1obj;
    00265 }
    00266
    00267 static ASN1_UTCTIME*
    00268 obj_to_asn1utime(VALUE time)
    00269 {
    00270     time_t sec;
    00271     ASN1_UTCTIME *t;
    00272
    00273     sec = time_to_time_t(time);
    00274     if(!(t = ASN1_UTCTIME_set(NULL, sec)))
    00275         ossl_raise(eASN1Error, NULL);
    00276
    00277     return t;
    00278 }
    00279
    00280 static ASN1_GENERALIZEDTIME*
    00281 obj_to_asn1gtime(VALUE time)
    00282 {
    00283     time_t sec;
    00284     ASN1_GENERALIZEDTIME *t;
    00285
    00286     sec = time_to_time_t(time);
    00287     if(!(t =ASN1_GENERALIZEDTIME_set(NULL, sec)))
    00288         ossl_raise(eASN1Error, NULL);
    00289
    00290     return t;
    00291 }
    00292
    00293 static ASN1_STRING*
    00294 obj_to_asn1derstr(VALUE obj)
    00295 {
    00296     ASN1_STRING *a1str;
    00297     VALUE str;
    00298
    00299     str = ossl_to_der(obj);
    00300     if(!(a1str = ASN1_STRING_new()))
    00301         ossl_raise(eASN1Error, NULL);
    00302     ASN1_STRING_set(a1str, RSTRING_PTR(str), RSTRING_LEN(str));
    00303
    00304     return a1str;
    00305 }
    00306
    00307 /*
    00308  * DER to Ruby converters
    00309  */
    00310 static VALUE
    00311 decode_bool(unsigned char* der, int length)
    00312 {
    00313     int val;
    00314     const unsigned char *p;
    00315
    00316     p = der;
    00317     if((val = d2i_ASN1_BOOLEAN(NULL, &p, length)) < 0)
    00318         ossl_raise(eASN1Error, NULL);
    00319
    00320     return val ? Qtrue : Qfalse;
    00321 }
    00322
    00323 static VALUE
    00324 decode_int(unsigned char* der, int length)
    00325 {
    00326     ASN1_INTEGER *ai;
    00327     const unsigned char *p;
    00328     VALUE ret;
    00329     int status = 0;
    00330
    00331     p = der;
    00332     if(!(ai = d2i_ASN1_INTEGER(NULL, &p, length)))
    00333         ossl_raise(eASN1Error, NULL);
    00334     ret = rb_protect((VALUE(*)_((VALUE)))asn1integer_to_num,
    00335                      (VALUE)ai, &status);
    00336     ASN1_INTEGER_free(ai);
    00337     if(status) rb_jump_tag(status);
    00338
    00339     return ret;
    00340 }
    00341
    00342 static VALUE
    00343 decode_bstr(unsigned char* der, int length, long *unused_bits)
    00344 {
    00345     ASN1_BIT_STRING *bstr;
    00346     const unsigned char *p;
    00347     long len;
    00348     VALUE ret;
    00349
    00350     p = der;
    00351     if(!(bstr = d2i_ASN1_BIT_STRING(NULL, &p, length)))
    00352         ossl_raise(eASN1Error, NULL);
    00353     len = bstr->length;
    00354     *unused_bits = 0;
    00355     if(bstr->flags & ASN1_STRING_FLAG_BITS_LEFT)
    00356         *unused_bits = bstr->flags & 0x07;
    00357     ret = rb_str_new((const char *)bstr->data, len);
    00358     ASN1_BIT_STRING_free(bstr);
    00359
    00360     return ret;
    00361 }
    00362
    00363 static VALUE
    00364 decode_enum(unsigned char* der, int length)
    00365 {
    00366     ASN1_ENUMERATED *ai;
    00367     const unsigned char *p;
    00368     VALUE ret;
    00369     int status = 0;
    00370
    00371     p = der;
    00372     if(!(ai = d2i_ASN1_ENUMERATED(NULL, &p, length)))
    00373         ossl_raise(eASN1Error, NULL);
    00374     ret = rb_protect((VALUE(*)_((VALUE)))asn1integer_to_num,
    00375                      (VALUE)ai, &status);
    00376     ASN1_ENUMERATED_free(ai);
    00377     if(status) rb_jump_tag(status);
    00378
    00379     return ret;
    00380 }
    00381
    00382 static VALUE
    00383 decode_null(unsigned char* der, int length)
    00384 {
    00385     ASN1_NULL *null;
    00386     const unsigned char *p;
    00387
    00388     p = der;
    00389     if(!(null = d2i_ASN1_NULL(NULL, &p, length)))
    00390         ossl_raise(eASN1Error, NULL);
    00391     ASN1_NULL_free(null);
    00392
    00393     return Qnil;
    00394 }
    00395
    00396 static VALUE
    00397 decode_obj(unsigned char* der, int length)
    00398 {
    00399     ASN1_OBJECT *obj;
    00400     const unsigned char *p;
    00401     VALUE ret;
    00402     int nid;
    00403     BIO *bio;
    00404
    00405     p = der;
    00406     if(!(obj = d2i_ASN1_OBJECT(NULL, &p, length)))
    00407         ossl_raise(eASN1Error, NULL);
    00408     if((nid = OBJ_obj2nid(obj)) != NID_undef){
    00409         ASN1_OBJECT_free(obj);
    00410         ret = rb_str_new2(OBJ_nid2sn(nid));
    00411     }
    00412     else{
    00413         if(!(bio = BIO_new(BIO_s_mem()))){
    00414             ASN1_OBJECT_free(obj);
    00415             ossl_raise(eASN1Error, NULL);
    00416         }
    00417         i2a_ASN1_OBJECT(bio, obj);
    00418         ASN1_OBJECT_free(obj);
    00419         ret = ossl_membio2str(bio);
    00420     }
    00421
    00422     return ret;
    00423 }
    00424
    00425 static VALUE
    00426 decode_time(unsigned char* der, int length)
    00427 {
    00428     ASN1_TIME *time;
    00429     const unsigned char *p;
    00430     VALUE ret;
    00431     int status = 0;
    00432
    00433     p = der;
    00434     if(!(time = d2i_ASN1_TIME(NULL, &p, length)))
    00435         ossl_raise(eASN1Error, NULL);
    00436     ret = rb_protect((VALUE(*)_((VALUE)))asn1time_to_time,
    00437                      (VALUE)time, &status);
    00438     ASN1_TIME_free(time);
    00439     if(status) rb_jump_tag(status);
    00440
    00441     return ret;
    00442 }
    00443
    00444 /********/
    00445
    00446 typedef struct {
    00447     const char *name;
    00448     VALUE *klass;
    00449 } ossl_asn1_info_t;
    00450
    00451 static ossl_asn1_info_t ossl_asn1_info[] = {
    00452     { "EOC",               NULL,                  },  /*  0 */
    00453     { "BOOLEAN",           &cASN1Boolean,         },  /*  1 */
    00454     { "INTEGER",           &cASN1Integer,         },  /*  2 */
    00455     { "BIT_STRING",        &cASN1BitString,       },  /*  3 */
    00456     { "OCTET_STRING",      &cASN1OctetString,     },  /*  4 */
    00457     { "NULL",              &cASN1Null,            },  /*  5 */
    00458     { "OBJECT",            &cASN1ObjectId,        },  /*  6 */
    00459     { "OBJECT_DESCRIPTOR", NULL,                  },  /*  7 */
    00460     { "EXTERNAL",          NULL,                  },  /*  8 */
    00461     { "REAL",              NULL,                  },  /*  9 */
    00462     { "ENUMERATED",        &cASN1Enumerated,      },  /* 10 */
    00463     { "EMBEDDED_PDV",      NULL,                  },  /* 11 */
    00464     { "UTF8STRING",        &cASN1UTF8String,      },  /* 12 */
    00465     { "RELATIVE_OID",      NULL,                  },  /* 13 */
    00466     { "[UNIVERSAL 14]",    NULL,                  },  /* 14 */
    00467     { "[UNIVERSAL 15]",    NULL,                  },  /* 15 */
    00468     { "SEQUENCE",          &cASN1Sequence,        },  /* 16 */
    00469     { "SET",               &cASN1Set,             },  /* 17 */
    00470     { "NUMERICSTRING",     &cASN1NumericString,   },  /* 18 */
    00471     { "PRINTABLESTRING",   &cASN1PrintableString, },  /* 19 */
    00472     { "T61STRING",         &cASN1T61String,       },  /* 20 */
    00473     { "VIDEOTEXSTRING",    &cASN1VideotexString,  },  /* 21 */
    00474     { "IA5STRING",         &cASN1IA5String,       },  /* 22 */
    00475     { "UTCTIME",           &cASN1UTCTime,         },  /* 23 */
    00476     { "GENERALIZEDTIME",   &cASN1GeneralizedTime, },  /* 24 */
    00477     { "GRAPHICSTRING",     &cASN1GraphicString,   },  /* 25 */
    00478     { "ISO64STRING",       &cASN1ISO64String,     },  /* 26 */
    00479     { "GENERALSTRING",     &cASN1GeneralString,   },  /* 27 */
    00480     { "UNIVERSALSTRING",   &cASN1UniversalString, },  /* 28 */
    00481     { "CHARACTER_STRING",  NULL,                  },  /* 29 */
    00482     { "BMPSTRING",         &cASN1BMPString,       },  /* 30 */
    00483 };
    00484
    00485 int ossl_asn1_info_size = (sizeof(ossl_asn1_info)/sizeof(ossl_asn1_info[0]));
    00486
    00487 static int ossl_asn1_default_tag(VALUE obj);
    00488
    00489 ASN1_TYPE*
    00490 ossl_asn1_get_asn1type(VALUE obj)
    00491 {
    00492     ASN1_TYPE *ret;
    00493     VALUE value, rflag;
    00494     void *ptr;
    00495     void (*free_func)();
    00496     long tag, flag;
    00497
    00498     tag = ossl_asn1_default_tag(obj);
    00499     value = ossl_asn1_get_value(obj);
    00500     switch(tag){
    00501     case V_ASN1_BOOLEAN:
    00502         ptr = (void*)(VALUE)obj_to_asn1bool(value);
    00503         free_func = NULL;
    00504         break;
    00505     case V_ASN1_INTEGER:         /* FALLTHROUGH */
    00506     case V_ASN1_ENUMERATED:
    00507         ptr = obj_to_asn1int(value);
    00508         free_func = ASN1_INTEGER_free;
    00509         break;
    00510     case V_ASN1_BIT_STRING:
    00511         rflag = rb_attr_get(obj, rb_intern("@unused_bits"));
    00512         flag = NIL_P(rflag) ? -1 : NUM2INT(rflag);
    00513         ptr = obj_to_asn1bstr(value, flag);
    00514         free_func = ASN1_BIT_STRING_free;
    00515         break;
    00516     case V_ASN1_NULL:
    00517         ptr = obj_to_asn1null(value);
    00518         free_func = ASN1_NULL_free;
    00519         break;
    00520     case V_ASN1_OCTET_STRING:    /* FALLTHROUGH */
    00521     case V_ASN1_UTF8STRING:      /* FALLTHROUGH */
    00522     case V_ASN1_NUMERICSTRING:   /* FALLTHROUGH */
    00523     case V_ASN1_PRINTABLESTRING: /* FALLTHROUGH */
    00524     case V_ASN1_T61STRING:       /* FALLTHROUGH */
    00525     case V_ASN1_VIDEOTEXSTRING:  /* FALLTHROUGH */
    00526     case V_ASN1_IA5STRING:       /* FALLTHROUGH */
    00527     case V_ASN1_GRAPHICSTRING:   /* FALLTHROUGH */
    00528     case V_ASN1_ISO64STRING:     /* FALLTHROUGH */
    00529     case V_ASN1_GENERALSTRING:   /* FALLTHROUGH */
    00530     case V_ASN1_UNIVERSALSTRING: /* FALLTHROUGH */
    00531     case V_ASN1_BMPSTRING:
    00532         ptr = obj_to_asn1str(value);
    00533         free_func = ASN1_STRING_free;
    00534         break;
    00535     case V_ASN1_OBJECT:
    00536         ptr = obj_to_asn1obj(value);
    00537         free_func = ASN1_OBJECT_free;
    00538         break;
    00539     case V_ASN1_UTCTIME:
    00540         ptr = obj_to_asn1utime(value);
    00541         free_func = ASN1_TIME_free;
    00542         break;
    00543     case V_ASN1_GENERALIZEDTIME:
    00544         ptr = obj_to_asn1gtime(value);
    00545         free_func = ASN1_TIME_free;
    00546         break;
    00547     case V_ASN1_SET:             /* FALLTHROUGH */
    00548     case V_ASN1_SEQUENCE:
    00549         ptr = obj_to_asn1derstr(obj);
    00550         free_func = ASN1_STRING_free;
    00551         break;
    00552     default:
    00553         ossl_raise(eASN1Error, "unsupported ASN.1 type");
    00554     }
    00555     if(!(ret = OPENSSL_malloc(sizeof(ASN1_TYPE)))){
    00556         if(free_func) free_func(ptr);
    00557         ossl_raise(eASN1Error, "ASN1_TYPE alloc failure");
    00558     }
    00559     memset(ret, 0, sizeof(ASN1_TYPE));
    00560     ASN1_TYPE_set(ret, tag, ptr);
    00561
    00562     return ret;
    00563 }
    00564
    00565 static int
    00566 ossl_asn1_default_tag(VALUE obj)
    00567 {
    00568     int i;
    00569
    00570     for(i = 0; i < ossl_asn1_info_size; i++){
    00571         if(ossl_asn1_info[i].klass &&
    00572            rb_obj_is_kind_of(obj, *ossl_asn1_info[i].klass)){
    00573             return i;
    00574         }
    00575     }
    00576     ossl_raise(eASN1Error, "universal tag for %s not found",
    00577                rb_class2name(CLASS_OF(obj)));
    00578
    00579     return -1; /* dummy */
    00580 }
    00581
    00582 static int
    00583 ossl_asn1_tag(VALUE obj)
    00584 {
    00585     VALUE tag;
    00586
    00587     tag = ossl_asn1_get_tag(obj);
    00588     if(NIL_P(tag))
    00589         ossl_raise(eASN1Error, "tag number not specified");
    00590
    00591     return NUM2INT(tag);
    00592 }
    00593
    00594 static int
    00595 ossl_asn1_is_explicit(VALUE obj)
    00596 {
    00597     VALUE s;
    00598     int ret = -1;
    00599
    00600     s = ossl_asn1_get_tagging(obj);
    00601     if(NIL_P(s)) return 0;
    00602     else if(SYMBOL_P(s)){
    00603         if (SYM2ID(s) == sIMPLICIT)
    00604             ret = 0;
    00605         else if (SYM2ID(s) == sEXPLICIT)
    00606             ret = 1;
    00607     }
    00608     if(ret < 0){
    00609         ossl_raise(eASN1Error, "invalid tag default");
    00610     }
    00611
    00612     return ret;
    00613 }
    00614
    00615 static int
    00616 ossl_asn1_tag_class(VALUE obj)
    00617 {
    00618     VALUE s;
    00619     int ret = -1;
    00620
    00621     s = ossl_asn1_get_tag_class(obj);
    00622     if(NIL_P(s)) ret = V_ASN1_UNIVERSAL;
    00623     else if(SYMBOL_P(s)){
    00624         if (SYM2ID(s) == sUNIVERSAL)
    00625             ret = V_ASN1_UNIVERSAL;
    00626         else if (SYM2ID(s) == sAPPLICATION)
    00627             ret = V_ASN1_APPLICATION;
    00628         else if (SYM2ID(s) == sCONTEXT_SPECIFIC)
    00629             ret = V_ASN1_CONTEXT_SPECIFIC;
    00630         else if (SYM2ID(s) == sPRIVATE)
    00631             ret = V_ASN1_PRIVATE;
    00632     }
    00633     if(ret < 0){
    00634         ossl_raise(eASN1Error, "invalid tag class");
    00635     }
    00636
    00637     return ret;
    00638 }
    00639
    00640 static VALUE
    00641 ossl_asn1_class2sym(int tc)
    00642 {
    00643     if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
    00644         return ID2SYM(sPRIVATE);
    00645     else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
    00646         return ID2SYM(sCONTEXT_SPECIFIC);
    00647     else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
    00648         return ID2SYM(sAPPLICATION);
    00649     else
    00650         return ID2SYM(sUNIVERSAL);
    00651 }
    00652
    00653 static VALUE
    00654 ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class)
    00655 {
    00656     if(!SYMBOL_P(tag_class))
    00657         ossl_raise(eASN1Error, "invalid tag class");
    00658     if((SYM2ID(tag_class) == sUNIVERSAL) && NUM2INT(tag) > 31)
    00659         ossl_raise(eASN1Error, "tag number for Universal too large");
    00660     ossl_asn1_set_tag(self, tag);
    00661     ossl_asn1_set_value(self, value);
    00662     ossl_asn1_set_tag_class(self, tag_class);
    00663
    00664     return self;
    00665 }
    00666
    00667 static VALUE
    00668 join_der_i(VALUE i, VALUE str)
    00669 {
    00670     i = ossl_to_der_if_possible(i);
    00671     StringValue(i);
    00672     rb_str_append(str, i);
    00673     return Qnil;
    00674 }
    00675
    00676 static VALUE
    00677 join_der(VALUE enumerable)
    00678 {
    00679     VALUE str = rb_str_new(0, 0);
    00680     rb_block_call(enumerable, rb_intern("each"), 0, 0, join_der_i, str);
    00681     return str;
    00682 }
    00683
    00684 static VALUE
    00685 ossl_asn1data_to_der(VALUE self)
    00686 {
    00687     VALUE value, der;
    00688     int tag, tag_class, is_cons = 0;
    00689     long length;
    00690     unsigned char *p;
    00691
    00692     value = ossl_asn1_get_value(self);
    00693     if(rb_obj_is_kind_of(value, rb_cArray)){
    00694         is_cons = 1;
    00695         value = join_der(value);
    00696     }
    00697     StringValue(value);
    00698
    00699     tag = ossl_asn1_tag(self);
    00700     tag_class = ossl_asn1_tag_class(self);
    00701     if((length = ASN1_object_size(1, RSTRING_LEN(value), tag)) <= 0)
    00702         ossl_raise(eASN1Error, NULL);
    00703     der = rb_str_new(0, length);
    00704     p = (unsigned char *)RSTRING_PTR(der);
    00705     ASN1_put_object(&p, is_cons, RSTRING_LEN(value), tag, tag_class);
    00706     memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
    00707     p += RSTRING_LEN(value);
    00708     ossl_str_adjust(der, p);
    00709
    00710     return der;
    00711 }
    00712
    00713 static VALUE
    00714 ossl_asn1_decode0(unsigned char **pp, long length, long *offset, long depth,
    00715                   int once, int yield)
    00716 {
    00717     unsigned char *start, *p;
    00718     const unsigned char *p0;
    00719     long len, off = *offset;
    00720     int hlen, tag, tc, j;
    00721     VALUE ary, asn1data, value, tag_class;
    00722
    00723     ary = rb_ary_new();
    00724     p = *pp;
    00725     while(length > 0){
    00726         start = p;
    00727         p0 = p;
    00728         j = ASN1_get_object(&p0, &len, &tag, &tc, length);
    00729         p = (unsigned char *)p0;
    00730         if(j & 0x80) ossl_raise(eASN1Error, NULL);
    00731         hlen = p - start;
    00732         if(yield){
    00733             VALUE arg = rb_ary_new();
    00734             rb_ary_push(arg, LONG2NUM(depth));
    00735             rb_ary_push(arg, LONG2NUM(off));
    00736             rb_ary_push(arg, LONG2NUM(hlen));
    00737             rb_ary_push(arg, LONG2NUM(len));
    00738             rb_ary_push(arg, (j & V_ASN1_CONSTRUCTED) ? Qtrue : Qfalse);
    00739             rb_ary_push(arg, ossl_asn1_class2sym(tc));
    00740             rb_ary_push(arg, INT2NUM(tag));
    00741             rb_yield(arg);
    00742         }
    00743         length -= hlen;
    00744         off += hlen;
    00745         if(len > length) ossl_raise(eASN1Error, "value is too short");
    00746         if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
    00747             tag_class = sPRIVATE;
    00748         else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
    00749             tag_class = sCONTEXT_SPECIFIC;
    00750         else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
    00751             tag_class = sAPPLICATION;
    00752         else
    00753             tag_class = sUNIVERSAL;
    00754         if(j & V_ASN1_CONSTRUCTED){
    00755             /* TODO: if j == 0x21 it is indefinite length object. */
    00756             if((j == 0x21) && (len == 0)){
    00757                 long lastoff = off;
    00758                 value = ossl_asn1_decode0(&p, length, &off, depth+1, 0, yield);
    00759                 len = off - lastoff;
    00760             }
    00761             else value = ossl_asn1_decode0(&p, len, &off, depth+1, 0, yield);
    00762         }
    00763         else{
    00764             value = rb_str_new((const char *)p, len);
    00765             p += len;
    00766             off += len;
    00767         }
    00768         if(tag_class == sUNIVERSAL &&
    00769            tag < ossl_asn1_info_size && ossl_asn1_info[tag].klass){
    00770             VALUE klass = *ossl_asn1_info[tag].klass;
    00771             long flag = 0;
    00772             if(!rb_obj_is_kind_of(value, rb_cArray)){
    00773                 switch(tag){
    00774                 case V_ASN1_BOOLEAN:
    00775                     value = decode_bool(start, hlen+len);
    00776                     break;
    00777                 case V_ASN1_INTEGER:
    00778                     value = decode_int(start, hlen+len);
    00779                     break;
    00780                 case V_ASN1_BIT_STRING:
    00781                     value = decode_bstr(start, hlen+len, &flag);
    00782                     break;
    00783                 case V_ASN1_NULL:
    00784                     value = decode_null(start, hlen+len);
    00785                     break;
    00786                 case V_ASN1_ENUMERATED:
    00787                     value = decode_enum(start, hlen+len);
    00788                     break;
    00789                 case V_ASN1_OBJECT:
    00790                     value = decode_obj(start, hlen+len);
    00791                     break;
    00792                 case V_ASN1_UTCTIME:           /* FALLTHROUGH */
    00793                 case V_ASN1_GENERALIZEDTIME:
    00794                     value = decode_time(start, hlen+len);
    00795                     break;
    00796                 default:
    00797                     /* use original value */
    00798                     break;
    00799                 }
    00800             }
    00801             asn1data = rb_funcall(klass, rb_intern("new"), 1, value);
    00802             if(tag == V_ASN1_BIT_STRING){
    00803                 rb_iv_set(asn1data, "@unused_bits", LONG2NUM(flag));
    00804             }
    00805         }
    00806         else{
    00807             asn1data = rb_funcall(cASN1Data, rb_intern("new"), 3,
    00808                                   value, INT2NUM(tag), ID2SYM(tag_class));
    00809         }
    00810         rb_ary_push(ary, asn1data);
    00811         length -= len;
    00812         if(once) break;
    00813     }
    00814     *pp = p;
    00815     *offset = off;
    00816
    00817     return ary;
    00818 }
    00819
    00820 static VALUE
    00821 ossl_asn1_traverse(VALUE self, VALUE obj)
    00822 {
    00823     unsigned char *p;
    00824     long offset = 0;
    00825     volatile VALUE tmp;
    00826
    00827     obj = ossl_to_der_if_possible(obj);
    00828     tmp = rb_str_new4(StringValue(obj));
    00829     p = (unsigned char *)RSTRING_PTR(tmp);
    00830     ossl_asn1_decode0(&p, RSTRING_LEN(tmp), &offset, 0, 0, 1);
    00831
    00832     return Qnil;
    00833 }
    00834
    00835 static VALUE
    00836 ossl_asn1_decode(VALUE self, VALUE obj)
    00837 {
    00838     VALUE ret, ary;
    00839     unsigned char *p;
    00840     long offset = 0;
    00841     volatile VALUE tmp;
    00842
    00843     obj = ossl_to_der_if_possible(obj);
    00844     tmp = rb_str_new4(StringValue(obj));
    00845     p = (unsigned char *)RSTRING_PTR(tmp);
    00846     ary = ossl_asn1_decode0(&p, RSTRING_LEN(tmp), &offset, 0, 1, 0);
    00847     ret = rb_ary_entry(ary, 0);
    00848
    00849     return ret;
    00850 }
    00851
    00852 static VALUE
    00853 ossl_asn1_decode_all(VALUE self, VALUE obj)
    00854 {
    00855     VALUE ret;
    00856     unsigned char *p;
    00857     long offset = 0;
    00858     volatile VALUE tmp;
    00859
    00860     obj = ossl_to_der_if_possible(obj);
    00861     tmp = rb_str_new4(StringValue(obj));
    00862     p = (unsigned char *)RSTRING_PTR(tmp);
    00863     ret = ossl_asn1_decode0(&p, RSTRING_LEN(tmp), &offset, 0, 0, 0);
    00864
    00865     return ret;
    00866 }
    00867
    00868 static VALUE
    00869 ossl_asn1_initialize(int argc, VALUE *argv, VALUE self)
    00870 {
    00871     VALUE value, tag, tagging, tag_class;
    00872
    00873     rb_scan_args(argc, argv, "13", &value, &tag, &tagging, &tag_class);
    00874     if(argc > 1){
    00875         if(NIL_P(tag))
    00876             ossl_raise(eASN1Error, "must specify tag number");
    00877         if(NIL_P(tagging))
    00878             tagging = ID2SYM(sEXPLICIT);
    00879         if(!SYMBOL_P(tagging))
    00880             ossl_raise(eASN1Error, "invalid tag default");
    00881         if(NIL_P(tag_class))
    00882             tag_class = ID2SYM(sCONTEXT_SPECIFIC);
    00883         if(!SYMBOL_P(tag_class))
    00884             ossl_raise(eASN1Error, "invalid tag class");
    00885         if(SYM2ID(tagging) == sIMPLICIT && NUM2INT(tag) > 31)
    00886             ossl_raise(eASN1Error, "tag number for Universal too large");
    00887     }
    00888     else{
    00889         tag = INT2NUM(ossl_asn1_default_tag(self));
    00890         tagging = Qnil;
    00891         tag_class = ID2SYM(sUNIVERSAL);
    00892     }
    00893     ossl_asn1_set_tag(self, tag);
    00894     ossl_asn1_set_value(self, value);
    00895     ossl_asn1_set_tagging(self, tagging);
    00896     ossl_asn1_set_tag_class(self, tag_class);
    00897
    00898     return self;
    00899 }
    00900
    00901 static int
    00902 ossl_i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **pp)
    00903 {
    00904 #if OPENSSL_VERSION_NUMBER < 0x00907000L
    00905     if(!a) return 0;
    00906     if(a->type == V_ASN1_BOOLEAN)
    00907         return i2d_ASN1_BOOLEAN(a->value.boolean, pp);
    00908 #endif
    00909     return i2d_ASN1_TYPE(a, pp);
    00910 }
    00911
    00912 static void
    00913 ossl_ASN1_TYPE_free(ASN1_TYPE *a)
    00914 {
    00915 #if OPENSSL_VERSION_NUMBER < 0x00907000L
    00916     if(!a) return;
    00917     if(a->type == V_ASN1_BOOLEAN){
    00918         OPENSSL_free(a);
    00919         return;
    00920     }
    00921 #endif
    00922     ASN1_TYPE_free(a);
    00923 }
    00924
    00925 static VALUE
    00926 ossl_asn1prim_to_der(VALUE self)
    00927 {
    00928     ASN1_TYPE *asn1;
    00929     int tn, tc, explicit;
    00930     long len, reallen;
    00931     unsigned char *buf, *p;
    00932     VALUE str;
    00933
    00934     tn = NUM2INT(ossl_asn1_get_tag(self));
    00935     tc = ossl_asn1_tag_class(self);
    00936     explicit = ossl_asn1_is_explicit(self);
    00937     asn1 = ossl_asn1_get_asn1type(self);
    00938
    00939     len = ASN1_object_size(1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn);
    00940     if(!(buf = OPENSSL_malloc(len))){
    00941         ossl_ASN1_TYPE_free(asn1);
    00942         ossl_raise(eASN1Error, "cannot alloc buffer");
    00943     }
    00944     p = buf;
    00945     if (tc == V_ASN1_UNIVERSAL) {
    00946         ossl_i2d_ASN1_TYPE(asn1, &p);
    00947     } else if (explicit) {
    00948         ASN1_put_object(&p, 1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn, tc);
    00949         ossl_i2d_ASN1_TYPE(asn1, &p);
    00950     } else {
    00951         ossl_i2d_ASN1_TYPE(asn1, &p);
    00952         *buf = tc | tn | (*buf & V_ASN1_CONSTRUCTED);
    00953     }
    00954     ossl_ASN1_TYPE_free(asn1);
    00955     reallen = p - buf;
    00956     assert(reallen <= len);
    00957     str = ossl_buf2str((char *)buf, reallen); /* buf will be free in ossl_buf2str */
    00958
    00959     return str;
    00960 }
    00961
    00962 static VALUE
    00963 ossl_asn1cons_to_der(VALUE self)
    00964 {
    00965     int tag, tn, tc, explicit;
    00966     long seq_len, length;
    00967     unsigned char *p;
    00968     VALUE value, str;
    00969
    00970     tag = ossl_asn1_default_tag(self);
    00971     tn = NUM2INT(ossl_asn1_get_tag(self));
    00972     tc = ossl_asn1_tag_class(self);
    00973     explicit = ossl_asn1_is_explicit(self);
    00974     value = join_der(ossl_asn1_get_value(self));
    00975
    00976     seq_len = ASN1_object_size(1, RSTRING_LEN(value), tag);
    00977     length = ASN1_object_size(1, seq_len, tn);
    00978     str = rb_str_new(0, length);
    00979     p = (unsigned char *)RSTRING_PTR(str);
    00980     if(tc == V_ASN1_UNIVERSAL)
    00981         ASN1_put_object(&p, 1, RSTRING_LEN(value), tn, tc);
    00982     else{
    00983         if(explicit){
    00984             ASN1_put_object(&p, 1, seq_len, tn, tc);
    00985             ASN1_put_object(&p, 1, RSTRING_LEN(value), tag, V_ASN1_UNIVERSAL);
    00986         }
    00987         else ASN1_put_object(&p, 1, RSTRING_LEN(value), tn, tc);
    00988     }
    00989     memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
    00990     p += RSTRING_LEN(value);
    00991     ossl_str_adjust(str, p);
    00992
    00993     return str;
    00994 }
    00995
    00996 static VALUE
    00997 ossl_asn1cons_each(VALUE self)
    00998 {
    00999     rb_ary_each(ossl_asn1_get_value(self));
    01000     return self;
    01001 }
    01002
    01003 static VALUE
    01004 ossl_asn1obj_s_register(VALUE self, VALUE oid, VALUE sn, VALUE ln)
    01005 {
    01006     StringValue(oid);
    01007     StringValue(sn);
    01008     StringValue(ln);
    01009
    01010     if(!OBJ_create(RSTRING_PTR(oid), RSTRING_PTR(sn), RSTRING_PTR(ln)))
    01011         ossl_raise(eASN1Error, NULL);
    01012
    01013     return Qtrue;
    01014 }
    01015
    01016 static VALUE
    01017 ossl_asn1obj_get_sn(VALUE self)
    01018 {
    01019     VALUE val, ret = Qnil;
    01020     int nid;
    01021
    01022     val = ossl_asn1_get_value(self);
    01023     if ((nid = OBJ_txt2nid(StringValuePtr(val))) != NID_undef)
    01024         ret = rb_str_new2(OBJ_nid2sn(nid));
    01025
    01026     return ret;
    01027 }
    01028
    01029 static VALUE
    01030 ossl_asn1obj_get_ln(VALUE self)
    01031 {
    01032     VALUE val, ret = Qnil;
    01033     int nid;
    01034
    01035     val = ossl_asn1_get_value(self);
    01036     if ((nid = OBJ_txt2nid(StringValuePtr(val))) != NID_undef)
    01037         ret = rb_str_new2(OBJ_nid2ln(nid));
    01038
    01039     return ret;
    01040 }
    01041
    01042 static VALUE
    01043 ossl_asn1obj_get_oid(VALUE self)
    01044 {
    01045     VALUE val;
    01046     ASN1_OBJECT *a1obj;
    01047     char buf[128];
    01048
    01049     val = ossl_asn1_get_value(self);
    01050     a1obj = obj_to_asn1obj(val);
    01051     OBJ_obj2txt(buf, sizeof(buf), a1obj, 1);
    01052     ASN1_OBJECT_free(a1obj);
    01053
    01054     return rb_str_new2(buf);
    01055 }
    01056
    01057 #define OSSL_ASN1_IMPL_FACTORY_METHOD(klass) \
    01058 static VALUE ossl_asn1_##klass(int argc, VALUE *argv, VALUE self)\
    01059 { return rb_funcall3(cASN1##klass, rb_intern("new"), argc, argv); }
    01060
    01061 OSSL_ASN1_IMPL_FACTORY_METHOD(Boolean)
    01062 OSSL_ASN1_IMPL_FACTORY_METHOD(Integer)
    01063 OSSL_ASN1_IMPL_FACTORY_METHOD(Enumerated)
    01064 OSSL_ASN1_IMPL_FACTORY_METHOD(BitString)
    01065 OSSL_ASN1_IMPL_FACTORY_METHOD(OctetString)
    01066 OSSL_ASN1_IMPL_FACTORY_METHOD(UTF8String)
    01067 OSSL_ASN1_IMPL_FACTORY_METHOD(NumericString)
    01068 OSSL_ASN1_IMPL_FACTORY_METHOD(PrintableString)
    01069 OSSL_ASN1_IMPL_FACTORY_METHOD(T61String)
    01070 OSSL_ASN1_IMPL_FACTORY_METHOD(VideotexString)
    01071 OSSL_ASN1_IMPL_FACTORY_METHOD(IA5String)
    01072 OSSL_ASN1_IMPL_FACTORY_METHOD(GraphicString)
    01073 OSSL_ASN1_IMPL_FACTORY_METHOD(ISO64String)
    01074 OSSL_ASN1_IMPL_FACTORY_METHOD(GeneralString)
    01075 OSSL_ASN1_IMPL_FACTORY_METHOD(UniversalString)
    01076 OSSL_ASN1_IMPL_FACTORY_METHOD(BMPString)
    01077 OSSL_ASN1_IMPL_FACTORY_METHOD(Null)
    01078 OSSL_ASN1_IMPL_FACTORY_METHOD(ObjectId)
    01079 OSSL_ASN1_IMPL_FACTORY_METHOD(UTCTime)
    01080 OSSL_ASN1_IMPL_FACTORY_METHOD(GeneralizedTime)
    01081 OSSL_ASN1_IMPL_FACTORY_METHOD(Sequence)
    01082 OSSL_ASN1_IMPL_FACTORY_METHOD(Set)
    01083
    01084 void
    01085 Init_ossl_asn1()
    01086 {
    01087     VALUE ary;
    01088     int i;
    01089
    01090 #if 0 /* let rdoc know about mOSSL */
    01091     mOSSL = rb_define_module("OpenSSL");
    01092 #endif
    01093
    01094     sUNIVERSAL = rb_intern("UNIVERSAL");
    01095     sCONTEXT_SPECIFIC = rb_intern("CONTEXT_SPECIFIC");
    01096     sAPPLICATION = rb_intern("APPLICATION");
    01097     sPRIVATE = rb_intern("PRIVATE");
    01098     sEXPLICIT = rb_intern("EXPLICIT");
    01099     sIMPLICIT = rb_intern("IMPLICIT");
    01100
    01101     mASN1 = rb_define_module_under(mOSSL, "ASN1");
    01102     eASN1Error = rb_define_class_under(mASN1, "ASN1Error", eOSSLError);
    01103     rb_define_module_function(mASN1, "traverse", ossl_asn1_traverse, 1);
    01104     rb_define_module_function(mASN1, "decode", ossl_asn1_decode, 1);
    01105     rb_define_module_function(mASN1, "decode_all", ossl_asn1_decode_all, 1);
    01106     ary = rb_ary_new();
    01107     rb_define_const(mASN1, "UNIVERSAL_TAG_NAME", ary);
    01108     for(i = 0; i < ossl_asn1_info_size; i++){
    01109         if(ossl_asn1_info[i].name[0] == '[') continue;
    01110         rb_define_const(mASN1, ossl_asn1_info[i].name, INT2NUM(i));
    01111         rb_ary_store(ary, i, rb_str_new2(ossl_asn1_info[i].name));
    01112     }
    01113
    01114     cASN1Data = rb_define_class_under(mASN1, "ASN1Data", rb_cObject);
    01115     rb_attr(cASN1Data, rb_intern("value"), 1, 1, 0);
    01116     rb_attr(cASN1Data, rb_intern("tag"), 1, 1, 0);
    01117     rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, 0);
    01118     rb_define_method(cASN1Data, "initialize", ossl_asn1data_initialize, 3);
    01119     rb_define_method(cASN1Data, "to_der", ossl_asn1data_to_der, 0);
    01120
    01121     cASN1Primitive = rb_define_class_under(mASN1, "Primitive", cASN1Data);
    01122     rb_attr(cASN1Primitive, rb_intern("tagging"), 1, 1, Qtrue);
    01123     rb_define_method(cASN1Primitive, "initialize", ossl_asn1_initialize, -1);
    01124     rb_define_method(cASN1Primitive, "to_der", ossl_asn1prim_to_der, 0);
    01125
    01126     cASN1Constructive = rb_define_class_under(mASN1,"Constructive", cASN1Data);
    01127     rb_include_module(cASN1Constructive, rb_mEnumerable);
    01128     rb_attr(cASN1Constructive, rb_intern("tagging"), 1, 1, Qtrue);
    01129     rb_define_method(cASN1Constructive, "initialize", ossl_asn1_initialize, -1);
    01130     rb_define_method(cASN1Constructive, "to_der", ossl_asn1cons_to_der, 0);
    01131     rb_define_method(cASN1Constructive, "each", ossl_asn1cons_each, 0);
    01132
    01133 #define OSSL_ASN1_DEFINE_CLASS(name, super) \
    01134 do{\
    01135     cASN1##name = rb_define_class_under(mASN1, #name, cASN1##super);\
    01136     rb_define_module_function(mASN1, #name, ossl_asn1_##name, -1);\
    01137 }while(0)
    01138
    01139     OSSL_ASN1_DEFINE_CLASS(Boolean, Primitive);
    01140     OSSL_ASN1_DEFINE_CLASS(Integer, Primitive);
    01141     OSSL_ASN1_DEFINE_CLASS(Enumerated, Primitive);
    01142     OSSL_ASN1_DEFINE_CLASS(BitString, Primitive);
    01143     OSSL_ASN1_DEFINE_CLASS(OctetString, Primitive);
    01144     OSSL_ASN1_DEFINE_CLASS(UTF8String, Primitive);
    01145     OSSL_ASN1_DEFINE_CLASS(NumericString, Primitive);
    01146     OSSL_ASN1_DEFINE_CLASS(PrintableString, Primitive);
    01147     OSSL_ASN1_DEFINE_CLASS(T61String, Primitive);
    01148     OSSL_ASN1_DEFINE_CLASS(VideotexString, Primitive);
    01149     OSSL_ASN1_DEFINE_CLASS(IA5String, Primitive);
    01150     OSSL_ASN1_DEFINE_CLASS(GraphicString, Primitive);
    01151     OSSL_ASN1_DEFINE_CLASS(ISO64String, Primitive);
    01152     OSSL_ASN1_DEFINE_CLASS(GeneralString, Primitive);
    01153     OSSL_ASN1_DEFINE_CLASS(UniversalString, Primitive);
    01154     OSSL_ASN1_DEFINE_CLASS(BMPString, Primitive);
    01155     OSSL_ASN1_DEFINE_CLASS(Null, Primitive);
    01156     OSSL_ASN1_DEFINE_CLASS(ObjectId, Primitive);
    01157     OSSL_ASN1_DEFINE_CLASS(UTCTime, Primitive);
    01158     OSSL_ASN1_DEFINE_CLASS(GeneralizedTime, Primitive);
    01159
    01160     OSSL_ASN1_DEFINE_CLASS(Sequence, Constructive);
    01161     OSSL_ASN1_DEFINE_CLASS(Set, Constructive);
    01162
    01163     rb_define_singleton_method(cASN1ObjectId, "register", ossl_asn1obj_s_register, 3);
    01164     rb_define_method(cASN1ObjectId, "sn", ossl_asn1obj_get_sn, 0);
    01165     rb_define_method(cASN1ObjectId, "ln", ossl_asn1obj_get_ln, 0);
    01166     rb_define_method(cASN1ObjectId, "oid", ossl_asn1obj_get_oid, 0);
    01167     rb_define_alias(cASN1ObjectId, "short_name", "sn");
    01168     rb_define_alias(cASN1ObjectId, "long_name", "ln");
    01169     rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, 0);
    01170 }
    01171