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

Generated on Wed Sep 8 2010 21:53:58 for Ruby by  doxygen 1.7.1