• 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 

Generated on Thu Sep 8 2011 03:50:34 for Ruby by  doxygen 1.7.1