00001
00002
00003
00004
00005
00006
00007
00008
00009
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;
00018 long tv_usec;
00019 };
00020 #endif
00021
00022 static VALUE join_der(VALUE enumerable);
00023 static VALUE ossl_asn1_decode0(unsigned char **pp, long length, long *offset,
00024 int depth, int yield, long *num_read);
00025 static VALUE ossl_asn1_initialize(int argc, VALUE *argv, VALUE self);
00026 static VALUE ossl_asn1eoc_initialize(VALUE self);
00027
00028
00029
00030
00031 VALUE
00032 asn1time_to_time(ASN1_TIME *time)
00033 {
00034 struct tm tm;
00035 VALUE argv[6];
00036
00037 if (!time || !time->data) return Qnil;
00038 memset(&tm, 0, sizeof(struct tm));
00039
00040 switch (time->type) {
00041 case V_ASN1_UTCTIME:
00042 if (sscanf((const char *)time->data, "%2d%2d%2d%2d%2d%2dZ", &tm.tm_year, &tm.tm_mon,
00043 &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
00044 ossl_raise(rb_eTypeError, "bad UTCTIME format");
00045 }
00046 if (tm.tm_year < 69) {
00047 tm.tm_year += 2000;
00048 } else {
00049 tm.tm_year += 1900;
00050 }
00051 break;
00052 case V_ASN1_GENERALIZEDTIME:
00053 if (sscanf((const char *)time->data, "%4d%2d%2d%2d%2d%2dZ", &tm.tm_year, &tm.tm_mon,
00054 &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
00055 ossl_raise(rb_eTypeError, "bad GENERALIZEDTIME format" );
00056 }
00057 break;
00058 default:
00059 rb_warning("unknown time format");
00060 return Qnil;
00061 }
00062 argv[0] = INT2NUM(tm.tm_year);
00063 argv[1] = INT2NUM(tm.tm_mon);
00064 argv[2] = INT2NUM(tm.tm_mday);
00065 argv[3] = INT2NUM(tm.tm_hour);
00066 argv[4] = INT2NUM(tm.tm_min);
00067 argv[5] = INT2NUM(tm.tm_sec);
00068
00069 return rb_funcall2(rb_cTime, rb_intern("utc"), 6, argv);
00070 }
00071
00072
00073
00074
00075 extern struct timeval rb_time_timeval(VALUE);
00076
00077 time_t
00078 time_to_time_t(VALUE time)
00079 {
00080 return (time_t)NUM2LONG(rb_Integer(time));
00081 }
00082
00083
00084
00085
00086 VALUE
00087 asn1str_to_str(ASN1_STRING *str)
00088 {
00089 return rb_str_new((const char *)str->data, str->length);
00090 }
00091
00092
00093
00094
00095
00096 #define DO_IT_VIA_RUBY 0
00097 VALUE
00098 asn1integer_to_num(ASN1_INTEGER *ai)
00099 {
00100 BIGNUM *bn;
00101 #if DO_IT_VIA_RUBY
00102 char *txt;
00103 #endif
00104 VALUE num;
00105
00106 if (!ai) {
00107 ossl_raise(rb_eTypeError, "ASN1_INTEGER is NULL!");
00108 }
00109 if (!(bn = ASN1_INTEGER_to_BN(ai, NULL))) {
00110 ossl_raise(eOSSLError, NULL);
00111 }
00112 #if DO_IT_VIA_RUBY
00113 if (!(txt = BN_bn2dec(bn))) {
00114 BN_free(bn);
00115 ossl_raise(eOSSLError, NULL);
00116 }
00117 num = rb_cstr_to_inum(txt, 10, Qtrue);
00118 OPENSSL_free(txt);
00119 #else
00120 num = ossl_bn_new(bn);
00121 #endif
00122 BN_free(bn);
00123
00124 return num;
00125 }
00126
00127 #if DO_IT_VIA_RUBY
00128 ASN1_INTEGER *
00129 num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
00130 {
00131 BIGNUM *bn = NULL;
00132
00133 if (RTEST(rb_obj_is_kind_of(obj, cBN))) {
00134 bn = GetBNPtr(obj);
00135 } else {
00136 obj = rb_String(obj);
00137 if (!BN_dec2bn(&bn, StringValuePtr(obj))) {
00138 ossl_raise(eOSSLError, NULL);
00139 }
00140 }
00141 if (!(ai = BN_to_ASN1_INTEGER(bn, ai))) {
00142 BN_free(bn);
00143 ossl_raise(eOSSLError, NULL);
00144 }
00145 BN_free(bn);
00146 return ai;
00147 }
00148 #else
00149 ASN1_INTEGER *
00150 num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
00151 {
00152 BIGNUM *bn = GetBNPtr(obj);
00153
00154 if (!(ai = BN_to_ASN1_INTEGER(bn, ai))) {
00155 ossl_raise(eOSSLError, NULL);
00156 }
00157 return ai;
00158 }
00159 #endif
00160
00161
00162
00163
00164
00165 #define ossl_asn1_get_value(o) rb_attr_get((o),sivVALUE)
00166 #define ossl_asn1_get_tag(o) rb_attr_get((o),sivTAG)
00167 #define ossl_asn1_get_tagging(o) rb_attr_get((o),sivTAGGING)
00168 #define ossl_asn1_get_tag_class(o) rb_attr_get((o),sivTAG_CLASS)
00169 #define ossl_asn1_get_infinite_length(o) rb_attr_get((o),sivINFINITE_LENGTH)
00170
00171 #define ossl_asn1_set_value(o,v) rb_ivar_set((o),sivVALUE,(v))
00172 #define ossl_asn1_set_tag(o,v) rb_ivar_set((o),sivTAG,(v))
00173 #define ossl_asn1_set_tagging(o,v) rb_ivar_set((o),sivTAGGING,(v))
00174 #define ossl_asn1_set_tag_class(o,v) rb_ivar_set((o),sivTAG_CLASS,(v))
00175 #define ossl_asn1_set_infinite_length(o,v) rb_ivar_set((o),sivINFINITE_LENGTH,(v))
00176
00177 VALUE mASN1;
00178 VALUE eASN1Error;
00179
00180 VALUE cASN1Data;
00181 VALUE cASN1Primitive;
00182 VALUE cASN1Constructive;
00183
00184 VALUE cASN1EndOfContent;
00185 VALUE cASN1Boolean;
00186 VALUE cASN1Integer, cASN1Enumerated;
00187 VALUE cASN1BitString;
00188 VALUE cASN1OctetString, cASN1UTF8String;
00189 VALUE cASN1NumericString, cASN1PrintableString;
00190 VALUE cASN1T61String, cASN1VideotexString;
00191 VALUE cASN1IA5String, cASN1GraphicString;
00192 VALUE cASN1ISO64String, cASN1GeneralString;
00193 VALUE cASN1UniversalString, cASN1BMPString;
00194 VALUE cASN1Null;
00195 VALUE cASN1ObjectId;
00196 VALUE cASN1UTCTime, cASN1GeneralizedTime;
00197 VALUE cASN1Sequence, cASN1Set;
00198
00199 static ID sIMPLICIT, sEXPLICIT;
00200 static ID sUNIVERSAL, sAPPLICATION, sCONTEXT_SPECIFIC, sPRIVATE;
00201 static ID sivVALUE, sivTAG, sivTAG_CLASS, sivTAGGING, sivINFINITE_LENGTH, sivUNUSED_BITS;
00202
00203
00204
00205
00206
00207
00208 #if OPENSSL_VERSION_NUMBER < 0x00908000L
00209 #define ossl_asn1_object_size(cons, len, tag) (cons) == 2 ? (len) + ASN1_object_size((cons), 0, (tag)) : ASN1_object_size((cons), (len), (tag))
00210 #define ossl_asn1_put_object(pp, cons, len, tag, xc) (cons) == 2 ? ASN1_put_object((pp), (cons), 0, (tag), (xc)) : ASN1_put_object((pp), (cons), (len), (tag), (xc))
00211 #else
00212 #define ossl_asn1_object_size(cons, len, tag) ASN1_object_size((cons), (len), (tag))
00213 #define ossl_asn1_put_object(pp, cons, len, tag, xc) ASN1_put_object((pp), (cons), (len), (tag), (xc))
00214 #endif
00215
00216
00217
00218
00219 static ASN1_BOOLEAN
00220 obj_to_asn1bool(VALUE obj)
00221 {
00222 #if OPENSSL_VERSION_NUMBER < 0x00907000L
00223 return RTEST(obj) ? 0xff : 0x100;
00224 #else
00225 return RTEST(obj) ? 0xff : 0x0;
00226 #endif
00227 }
00228
00229 static ASN1_INTEGER*
00230 obj_to_asn1int(VALUE obj)
00231 {
00232 return num_to_asn1integer(obj, NULL);
00233 }
00234
00235 static ASN1_BIT_STRING*
00236 obj_to_asn1bstr(VALUE obj, long unused_bits)
00237 {
00238 ASN1_BIT_STRING *bstr;
00239
00240 if(unused_bits < 0) unused_bits = 0;
00241 StringValue(obj);
00242 if(!(bstr = ASN1_BIT_STRING_new()))
00243 ossl_raise(eASN1Error, NULL);
00244 ASN1_BIT_STRING_set(bstr, (unsigned char *)RSTRING_PTR(obj), RSTRING_LENINT(obj));
00245 bstr->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
00246 bstr->flags |= ASN1_STRING_FLAG_BITS_LEFT|(unused_bits&0x07);
00247
00248 return bstr;
00249 }
00250
00251 static ASN1_STRING*
00252 obj_to_asn1str(VALUE obj)
00253 {
00254 ASN1_STRING *str;
00255
00256 StringValue(obj);
00257 if(!(str = ASN1_STRING_new()))
00258 ossl_raise(eASN1Error, NULL);
00259 ASN1_STRING_set(str, RSTRING_PTR(obj), RSTRING_LENINT(obj));
00260
00261 return str;
00262 }
00263
00264 static ASN1_NULL*
00265 obj_to_asn1null(VALUE obj)
00266 {
00267 ASN1_NULL *null;
00268
00269 if(!NIL_P(obj))
00270 ossl_raise(eASN1Error, "nil expected");
00271 if(!(null = ASN1_NULL_new()))
00272 ossl_raise(eASN1Error, NULL);
00273
00274 return null;
00275 }
00276
00277 static ASN1_OBJECT*
00278 obj_to_asn1obj(VALUE obj)
00279 {
00280 ASN1_OBJECT *a1obj;
00281
00282 StringValue(obj);
00283 a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 0);
00284 if(!a1obj) a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 1);
00285 if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID");
00286
00287 return a1obj;
00288 }
00289
00290 static ASN1_UTCTIME*
00291 obj_to_asn1utime(VALUE time)
00292 {
00293 time_t sec;
00294 ASN1_UTCTIME *t;
00295
00296 sec = time_to_time_t(time);
00297 if(!(t = ASN1_UTCTIME_set(NULL, sec)))
00298 ossl_raise(eASN1Error, NULL);
00299
00300 return t;
00301 }
00302
00303 static ASN1_GENERALIZEDTIME*
00304 obj_to_asn1gtime(VALUE time)
00305 {
00306 time_t sec;
00307 ASN1_GENERALIZEDTIME *t;
00308
00309 sec = time_to_time_t(time);
00310 if(!(t =ASN1_GENERALIZEDTIME_set(NULL, sec)))
00311 ossl_raise(eASN1Error, NULL);
00312
00313 return t;
00314 }
00315
00316 static ASN1_STRING*
00317 obj_to_asn1derstr(VALUE obj)
00318 {
00319 ASN1_STRING *a1str;
00320 VALUE str;
00321
00322 str = ossl_to_der(obj);
00323 if(!(a1str = ASN1_STRING_new()))
00324 ossl_raise(eASN1Error, NULL);
00325 ASN1_STRING_set(a1str, RSTRING_PTR(str), RSTRING_LENINT(str));
00326
00327 return a1str;
00328 }
00329
00330
00331
00332
00333 static VALUE
00334 decode_bool(unsigned char* der, int length)
00335 {
00336 int val;
00337 const unsigned char *p;
00338
00339 p = der;
00340 if((val = d2i_ASN1_BOOLEAN(NULL, &p, length)) < 0)
00341 ossl_raise(eASN1Error, NULL);
00342
00343 return val ? Qtrue : Qfalse;
00344 }
00345
00346 static VALUE
00347 decode_int(unsigned char* der, int length)
00348 {
00349 ASN1_INTEGER *ai;
00350 const unsigned char *p;
00351 VALUE ret;
00352 int status = 0;
00353
00354 p = der;
00355 if(!(ai = d2i_ASN1_INTEGER(NULL, &p, length)))
00356 ossl_raise(eASN1Error, NULL);
00357 ret = rb_protect((VALUE(*)_((VALUE)))asn1integer_to_num,
00358 (VALUE)ai, &status);
00359 ASN1_INTEGER_free(ai);
00360 if(status) rb_jump_tag(status);
00361
00362 return ret;
00363 }
00364
00365 static VALUE
00366 decode_bstr(unsigned char* der, int length, long *unused_bits)
00367 {
00368 ASN1_BIT_STRING *bstr;
00369 const unsigned char *p;
00370 long len;
00371 VALUE ret;
00372
00373 p = der;
00374 if(!(bstr = d2i_ASN1_BIT_STRING(NULL, &p, length)))
00375 ossl_raise(eASN1Error, NULL);
00376 len = bstr->length;
00377 *unused_bits = 0;
00378 if(bstr->flags & ASN1_STRING_FLAG_BITS_LEFT)
00379 *unused_bits = bstr->flags & 0x07;
00380 ret = rb_str_new((const char *)bstr->data, len);
00381 ASN1_BIT_STRING_free(bstr);
00382
00383 return ret;
00384 }
00385
00386 static VALUE
00387 decode_enum(unsigned char* der, int length)
00388 {
00389 ASN1_ENUMERATED *ai;
00390 const unsigned char *p;
00391 VALUE ret;
00392 int status = 0;
00393
00394 p = der;
00395 if(!(ai = d2i_ASN1_ENUMERATED(NULL, &p, length)))
00396 ossl_raise(eASN1Error, NULL);
00397 ret = rb_protect((VALUE(*)_((VALUE)))asn1integer_to_num,
00398 (VALUE)ai, &status);
00399 ASN1_ENUMERATED_free(ai);
00400 if(status) rb_jump_tag(status);
00401
00402 return ret;
00403 }
00404
00405 static VALUE
00406 decode_null(unsigned char* der, int length)
00407 {
00408 ASN1_NULL *null;
00409 const unsigned char *p;
00410
00411 p = der;
00412 if(!(null = d2i_ASN1_NULL(NULL, &p, length)))
00413 ossl_raise(eASN1Error, NULL);
00414 ASN1_NULL_free(null);
00415
00416 return Qnil;
00417 }
00418
00419 static VALUE
00420 decode_obj(unsigned char* der, int length)
00421 {
00422 ASN1_OBJECT *obj;
00423 const unsigned char *p;
00424 VALUE ret;
00425 int nid;
00426 BIO *bio;
00427
00428 p = der;
00429 if(!(obj = d2i_ASN1_OBJECT(NULL, &p, length)))
00430 ossl_raise(eASN1Error, NULL);
00431 if((nid = OBJ_obj2nid(obj)) != NID_undef){
00432 ASN1_OBJECT_free(obj);
00433 ret = rb_str_new2(OBJ_nid2sn(nid));
00434 }
00435 else{
00436 if(!(bio = BIO_new(BIO_s_mem()))){
00437 ASN1_OBJECT_free(obj);
00438 ossl_raise(eASN1Error, NULL);
00439 }
00440 i2a_ASN1_OBJECT(bio, obj);
00441 ASN1_OBJECT_free(obj);
00442 ret = ossl_membio2str(bio);
00443 }
00444
00445 return ret;
00446 }
00447
00448 static VALUE
00449 decode_time(unsigned char* der, int length)
00450 {
00451 ASN1_TIME *time;
00452 const unsigned char *p;
00453 VALUE ret;
00454 int status = 0;
00455
00456 p = der;
00457 if(!(time = d2i_ASN1_TIME(NULL, &p, length)))
00458 ossl_raise(eASN1Error, NULL);
00459 ret = rb_protect((VALUE(*)_((VALUE)))asn1time_to_time,
00460 (VALUE)time, &status);
00461 ASN1_TIME_free(time);
00462 if(status) rb_jump_tag(status);
00463
00464 return ret;
00465 }
00466
00467 static VALUE
00468 decode_eoc(unsigned char *der, int length)
00469 {
00470 if (length != 2 || !(der[0] == 0x00 && der[1] == 0x00))
00471 ossl_raise(eASN1Error, NULL);
00472
00473 return rb_str_new("", 0);
00474 }
00475
00476
00477
00478 typedef struct {
00479 const char *name;
00480 VALUE *klass;
00481 } ossl_asn1_info_t;
00482
00483 static ossl_asn1_info_t ossl_asn1_info[] = {
00484 { "EOC", &cASN1EndOfContent, },
00485 { "BOOLEAN", &cASN1Boolean, },
00486 { "INTEGER", &cASN1Integer, },
00487 { "BIT_STRING", &cASN1BitString, },
00488 { "OCTET_STRING", &cASN1OctetString, },
00489 { "NULL", &cASN1Null, },
00490 { "OBJECT", &cASN1ObjectId, },
00491 { "OBJECT_DESCRIPTOR", NULL, },
00492 { "EXTERNAL", NULL, },
00493 { "REAL", NULL, },
00494 { "ENUMERATED", &cASN1Enumerated, },
00495 { "EMBEDDED_PDV", NULL, },
00496 { "UTF8STRING", &cASN1UTF8String, },
00497 { "RELATIVE_OID", NULL, },
00498 { "[UNIVERSAL 14]", NULL, },
00499 { "[UNIVERSAL 15]", NULL, },
00500 { "SEQUENCE", &cASN1Sequence, },
00501 { "SET", &cASN1Set, },
00502 { "NUMERICSTRING", &cASN1NumericString, },
00503 { "PRINTABLESTRING", &cASN1PrintableString, },
00504 { "T61STRING", &cASN1T61String, },
00505 { "VIDEOTEXSTRING", &cASN1VideotexString, },
00506 { "IA5STRING", &cASN1IA5String, },
00507 { "UTCTIME", &cASN1UTCTime, },
00508 { "GENERALIZEDTIME", &cASN1GeneralizedTime, },
00509 { "GRAPHICSTRING", &cASN1GraphicString, },
00510 { "ISO64STRING", &cASN1ISO64String, },
00511 { "GENERALSTRING", &cASN1GeneralString, },
00512 { "UNIVERSALSTRING", &cASN1UniversalString, },
00513 { "CHARACTER_STRING", NULL, },
00514 { "BMPSTRING", &cASN1BMPString, },
00515 };
00516
00517 int ossl_asn1_info_size = (sizeof(ossl_asn1_info)/sizeof(ossl_asn1_info[0]));
00518
00519 static VALUE class_tag_map;
00520
00521 static int ossl_asn1_default_tag(VALUE obj);
00522
00523 ASN1_TYPE*
00524 ossl_asn1_get_asn1type(VALUE obj)
00525 {
00526 ASN1_TYPE *ret;
00527 VALUE value, rflag;
00528 void *ptr;
00529 void (*free_func)();
00530 int tag, flag;
00531
00532 tag = ossl_asn1_default_tag(obj);
00533 value = ossl_asn1_get_value(obj);
00534 switch(tag){
00535 case V_ASN1_BOOLEAN:
00536 ptr = (void*)(VALUE)obj_to_asn1bool(value);
00537 free_func = NULL;
00538 break;
00539 case V_ASN1_INTEGER:
00540 case V_ASN1_ENUMERATED:
00541 ptr = obj_to_asn1int(value);
00542 free_func = ASN1_INTEGER_free;
00543 break;
00544 case V_ASN1_BIT_STRING:
00545 rflag = rb_attr_get(obj, sivUNUSED_BITS);
00546 flag = NIL_P(rflag) ? -1 : NUM2INT(rflag);
00547 ptr = obj_to_asn1bstr(value, flag);
00548 free_func = ASN1_BIT_STRING_free;
00549 break;
00550 case V_ASN1_NULL:
00551 ptr = obj_to_asn1null(value);
00552 free_func = ASN1_NULL_free;
00553 break;
00554 case V_ASN1_OCTET_STRING:
00555 case V_ASN1_UTF8STRING:
00556 case V_ASN1_NUMERICSTRING:
00557 case V_ASN1_PRINTABLESTRING:
00558 case V_ASN1_T61STRING:
00559 case V_ASN1_VIDEOTEXSTRING:
00560 case V_ASN1_IA5STRING:
00561 case V_ASN1_GRAPHICSTRING:
00562 case V_ASN1_ISO64STRING:
00563 case V_ASN1_GENERALSTRING:
00564 case V_ASN1_UNIVERSALSTRING:
00565 case V_ASN1_BMPSTRING:
00566 ptr = obj_to_asn1str(value);
00567 free_func = ASN1_STRING_free;
00568 break;
00569 case V_ASN1_OBJECT:
00570 ptr = obj_to_asn1obj(value);
00571 free_func = ASN1_OBJECT_free;
00572 break;
00573 case V_ASN1_UTCTIME:
00574 ptr = obj_to_asn1utime(value);
00575 free_func = ASN1_TIME_free;
00576 break;
00577 case V_ASN1_GENERALIZEDTIME:
00578 ptr = obj_to_asn1gtime(value);
00579 free_func = ASN1_TIME_free;
00580 break;
00581 case V_ASN1_SET:
00582 case V_ASN1_SEQUENCE:
00583 ptr = obj_to_asn1derstr(obj);
00584 free_func = ASN1_STRING_free;
00585 break;
00586 default:
00587 ossl_raise(eASN1Error, "unsupported ASN.1 type");
00588 }
00589 if(!(ret = OPENSSL_malloc(sizeof(ASN1_TYPE)))){
00590 if(free_func) free_func(ptr);
00591 ossl_raise(eASN1Error, "ASN1_TYPE alloc failure");
00592 }
00593 memset(ret, 0, sizeof(ASN1_TYPE));
00594 ASN1_TYPE_set(ret, tag, ptr);
00595
00596 return ret;
00597 }
00598
00599 static int
00600 ossl_asn1_default_tag(VALUE obj)
00601 {
00602 VALUE tmp_class, tag;
00603
00604 tmp_class = CLASS_OF(obj);
00605 while (tmp_class) {
00606 tag = rb_hash_lookup(class_tag_map, tmp_class);
00607 if (tag != Qnil) {
00608 return NUM2INT(tag);
00609 }
00610 tmp_class = rb_class_superclass(tmp_class);
00611 }
00612 ossl_raise(eASN1Error, "universal tag for %s not found",
00613 rb_class2name(CLASS_OF(obj)));
00614
00615 return -1;
00616 }
00617
00618 static int
00619 ossl_asn1_tag(VALUE obj)
00620 {
00621 VALUE tag;
00622
00623 tag = ossl_asn1_get_tag(obj);
00624 if(NIL_P(tag))
00625 ossl_raise(eASN1Error, "tag number not specified");
00626
00627 return NUM2INT(tag);
00628 }
00629
00630 static int
00631 ossl_asn1_is_explicit(VALUE obj)
00632 {
00633 VALUE s;
00634 int ret = -1;
00635
00636 s = ossl_asn1_get_tagging(obj);
00637 if(NIL_P(s)) return 0;
00638 else if(SYMBOL_P(s)){
00639 if (SYM2ID(s) == sIMPLICIT)
00640 ret = 0;
00641 else if (SYM2ID(s) == sEXPLICIT)
00642 ret = 1;
00643 }
00644 if(ret < 0){
00645 ossl_raise(eASN1Error, "invalid tag default");
00646 }
00647
00648 return ret;
00649 }
00650
00651 static int
00652 ossl_asn1_tag_class(VALUE obj)
00653 {
00654 VALUE s;
00655 int ret = -1;
00656
00657 s = ossl_asn1_get_tag_class(obj);
00658 if(NIL_P(s)) ret = V_ASN1_UNIVERSAL;
00659 else if(SYMBOL_P(s)){
00660 if (SYM2ID(s) == sUNIVERSAL)
00661 ret = V_ASN1_UNIVERSAL;
00662 else if (SYM2ID(s) == sAPPLICATION)
00663 ret = V_ASN1_APPLICATION;
00664 else if (SYM2ID(s) == sCONTEXT_SPECIFIC)
00665 ret = V_ASN1_CONTEXT_SPECIFIC;
00666 else if (SYM2ID(s) == sPRIVATE)
00667 ret = V_ASN1_PRIVATE;
00668 }
00669 if(ret < 0){
00670 ossl_raise(eASN1Error, "invalid tag class");
00671 }
00672
00673 return ret;
00674 }
00675
00676 static VALUE
00677 ossl_asn1_class2sym(int tc)
00678 {
00679 if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
00680 return ID2SYM(sPRIVATE);
00681 else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
00682 return ID2SYM(sCONTEXT_SPECIFIC);
00683 else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
00684 return ID2SYM(sAPPLICATION);
00685 else
00686 return ID2SYM(sUNIVERSAL);
00687 }
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705 static VALUE
00706 ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class)
00707 {
00708 if(!SYMBOL_P(tag_class))
00709 ossl_raise(eASN1Error, "invalid tag class");
00710 if((SYM2ID(tag_class) == sUNIVERSAL) && NUM2INT(tag) > 31)
00711 ossl_raise(eASN1Error, "tag number for Universal too large");
00712 ossl_asn1_set_tag(self, tag);
00713 ossl_asn1_set_value(self, value);
00714 ossl_asn1_set_tag_class(self, tag_class);
00715 ossl_asn1_set_infinite_length(self, Qfalse);
00716
00717 return self;
00718 }
00719
00720 static VALUE
00721 join_der_i(VALUE i, VALUE str)
00722 {
00723 i = ossl_to_der_if_possible(i);
00724 StringValue(i);
00725 rb_str_append(str, i);
00726 return Qnil;
00727 }
00728
00729 static VALUE
00730 join_der(VALUE enumerable)
00731 {
00732 VALUE str = rb_str_new(0, 0);
00733 rb_block_call(enumerable, rb_intern("each"), 0, 0, join_der_i, str);
00734 return str;
00735 }
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746 static VALUE
00747 ossl_asn1data_to_der(VALUE self)
00748 {
00749 VALUE value, der, inf_length;
00750 int tag, tag_class, is_cons = 0;
00751 long length;
00752 unsigned char *p;
00753
00754 value = ossl_asn1_get_value(self);
00755 if(rb_obj_is_kind_of(value, rb_cArray)){
00756 is_cons = 1;
00757 value = join_der(value);
00758 }
00759 StringValue(value);
00760
00761 tag = ossl_asn1_tag(self);
00762 tag_class = ossl_asn1_tag_class(self);
00763 inf_length = ossl_asn1_get_infinite_length(self);
00764 if (inf_length == Qtrue) {
00765 is_cons = 2;
00766 }
00767 if((length = ossl_asn1_object_size(is_cons, RSTRING_LENINT(value), tag)) <= 0)
00768 ossl_raise(eASN1Error, NULL);
00769 der = rb_str_new(0, length);
00770 p = (unsigned char *)RSTRING_PTR(der);
00771 ossl_asn1_put_object(&p, is_cons, RSTRING_LENINT(value), tag, tag_class);
00772 memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
00773 p += RSTRING_LEN(value);
00774 ossl_str_adjust(der, p);
00775
00776 return der;
00777 }
00778
00779 static VALUE
00780 int_ossl_asn1_decode0_prim(unsigned char **pp, long length, int hlen, int tag,
00781 VALUE tc, long *num_read)
00782 {
00783 VALUE value, asn1data;
00784 unsigned char *p;
00785 long flag = 0;
00786
00787 p = *pp;
00788
00789 if(tc == sUNIVERSAL && tag < ossl_asn1_info_size) {
00790 switch(tag){
00791 case V_ASN1_EOC:
00792 value = decode_eoc(p, hlen+length);
00793 break;
00794 case V_ASN1_BOOLEAN:
00795 value = decode_bool(p, hlen+length);
00796 break;
00797 case V_ASN1_INTEGER:
00798 value = decode_int(p, hlen+length);
00799 break;
00800 case V_ASN1_BIT_STRING:
00801 value = decode_bstr(p, hlen+length, &flag);
00802 break;
00803 case V_ASN1_NULL:
00804 value = decode_null(p, hlen+length);
00805 break;
00806 case V_ASN1_ENUMERATED:
00807 value = decode_enum(p, hlen+length);
00808 break;
00809 case V_ASN1_OBJECT:
00810 value = decode_obj(p, hlen+length);
00811 break;
00812 case V_ASN1_UTCTIME:
00813 case V_ASN1_GENERALIZEDTIME:
00814 value = decode_time(p, hlen+length);
00815 break;
00816 default:
00817
00818 p += hlen;
00819 value = rb_str_new((const char *)p, length);
00820 break;
00821 }
00822 }
00823 else {
00824 p += hlen;
00825 value = rb_str_new((const char *)p, length);
00826 }
00827
00828 *pp += hlen + length;
00829 *num_read = hlen + length;
00830
00831 if (tc == sUNIVERSAL && tag < ossl_asn1_info_size && ossl_asn1_info[tag].klass) {
00832 VALUE klass = *ossl_asn1_info[tag].klass;
00833 VALUE args[4];
00834 args[0] = value;
00835 args[1] = INT2NUM(tag);
00836 args[2] = Qnil;
00837 args[3] = ID2SYM(tc);
00838 asn1data = rb_obj_alloc(klass);
00839 ossl_asn1_initialize(4, args, asn1data);
00840 if(tag == V_ASN1_BIT_STRING){
00841 rb_ivar_set(asn1data, sivUNUSED_BITS, LONG2NUM(flag));
00842 }
00843 }
00844 else {
00845 asn1data = rb_obj_alloc(cASN1Data);
00846 ossl_asn1data_initialize(asn1data, value, INT2NUM(tag), ID2SYM(tc));
00847 }
00848
00849 return asn1data;
00850 }
00851
00852 static VALUE
00853 int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length,
00854 long *offset, int depth, int yield, int j,
00855 int tag, VALUE tc, long *num_read)
00856 {
00857 VALUE value, asn1data, ary;
00858 int infinite;
00859 long off = *offset;
00860
00861 infinite = (j == 0x21);
00862 ary = rb_ary_new();
00863
00864 while (length > 0 || infinite) {
00865 long inner_read = 0;
00866 value = ossl_asn1_decode0(pp, max_len, &off, depth + 1, yield, &inner_read);
00867 *num_read += inner_read;
00868 max_len -= inner_read;
00869 rb_ary_push(ary, value);
00870 if (length > 0)
00871 length -= inner_read;
00872
00873 if (infinite &&
00874 NUM2INT(ossl_asn1_get_tag(value)) == V_ASN1_EOC &&
00875 SYM2ID(ossl_asn1_get_tag_class(value)) == sUNIVERSAL) {
00876 break;
00877 }
00878 }
00879
00880 if (tc == sUNIVERSAL) {
00881 VALUE args[4];
00882 int not_sequence_or_set;
00883
00884 not_sequence_or_set = tag != V_ASN1_SEQUENCE && tag != V_ASN1_SET;
00885
00886 if (not_sequence_or_set) {
00887 if (infinite) {
00888 asn1data = rb_obj_alloc(cASN1Constructive);
00889 }
00890 else {
00891 ossl_raise(eASN1Error, "invalid non-infinite tag");
00892 return Qnil;
00893 }
00894 }
00895 else {
00896 VALUE klass = *ossl_asn1_info[tag].klass;
00897 asn1data = rb_obj_alloc(klass);
00898 }
00899 args[0] = ary;
00900 args[1] = INT2NUM(tag);
00901 args[2] = Qnil;
00902 args[3] = ID2SYM(tc);
00903 ossl_asn1_initialize(4, args, asn1data);
00904 }
00905 else {
00906 asn1data = rb_obj_alloc(cASN1Data);
00907 ossl_asn1data_initialize(asn1data, ary, INT2NUM(tag), ID2SYM(tc));
00908 }
00909
00910 if (infinite)
00911 ossl_asn1_set_infinite_length(asn1data, Qtrue);
00912 else
00913 ossl_asn1_set_infinite_length(asn1data, Qfalse);
00914
00915 *offset = off;
00916 return asn1data;
00917 }
00918
00919 static VALUE
00920 ossl_asn1_decode0(unsigned char **pp, long length, long *offset, int depth,
00921 int yield, long *num_read)
00922 {
00923 unsigned char *start, *p;
00924 const unsigned char *p0;
00925 long len = 0, inner_read = 0, off = *offset;
00926 int hlen, tag, tc, j;
00927 VALUE asn1data, tag_class;
00928
00929 p = *pp;
00930 start = p;
00931 p0 = p;
00932 j = ASN1_get_object(&p0, &len, &tag, &tc, length);
00933 p = (unsigned char *)p0;
00934 if(j & 0x80) ossl_raise(eASN1Error, NULL);
00935 if(len > length) ossl_raise(eASN1Error, "value is too short");
00936 if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
00937 tag_class = sPRIVATE;
00938 else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
00939 tag_class = sCONTEXT_SPECIFIC;
00940 else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
00941 tag_class = sAPPLICATION;
00942 else
00943 tag_class = sUNIVERSAL;
00944
00945 hlen = p - start;
00946
00947 if(yield) {
00948 VALUE arg = rb_ary_new();
00949 rb_ary_push(arg, LONG2NUM(depth));
00950 rb_ary_push(arg, LONG2NUM(*offset));
00951 rb_ary_push(arg, LONG2NUM(hlen));
00952 rb_ary_push(arg, LONG2NUM(len));
00953 rb_ary_push(arg, (j & V_ASN1_CONSTRUCTED) ? Qtrue : Qfalse);
00954 rb_ary_push(arg, ossl_asn1_class2sym(tc));
00955 rb_ary_push(arg, INT2NUM(tag));
00956 rb_yield(arg);
00957 }
00958
00959 if(j & V_ASN1_CONSTRUCTED) {
00960 *pp += hlen;
00961 off += hlen;
00962 asn1data = int_ossl_asn1_decode0_cons(pp, length, len, &off, depth, yield, j, tag, tag_class, &inner_read);
00963 inner_read += hlen;
00964 }
00965 else {
00966 if ((j & 0x01) && (len == 0)) ossl_raise(eASN1Error, "Infinite length for primitive value");
00967 asn1data = int_ossl_asn1_decode0_prim(pp, len, hlen, tag, tag_class, &inner_read);
00968 off += hlen + len;
00969 }
00970 if (num_read)
00971 *num_read = inner_read;
00972 if (len != 0 && inner_read != hlen + len) {
00973 ossl_raise(eASN1Error,
00974 "Type mismatch. Bytes read: %ld Bytes available: %ld",
00975 inner_read, hlen + len);
00976 }
00977
00978 *offset = off;
00979 return asn1data;
00980 }
00981
00982 static void
00983 int_ossl_decode_sanity_check(long len, long read, long offset)
00984 {
00985 if (len != 0 && (read != len || offset != len)) {
00986 ossl_raise(eASN1Error,
00987 "Type mismatch. Total bytes read: %ld Bytes available: %ld Offset: %ld",
00988 read, len, offset);
00989 }
00990 }
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013 static VALUE
01014 ossl_asn1_traverse(VALUE self, VALUE obj)
01015 {
01016 unsigned char *p;
01017 volatile VALUE tmp;
01018 long len, read = 0, offset = 0;
01019
01020 obj = ossl_to_der_if_possible(obj);
01021 tmp = rb_str_new4(StringValue(obj));
01022 p = (unsigned char *)RSTRING_PTR(tmp);
01023 len = RSTRING_LEN(tmp);
01024 ossl_asn1_decode0(&p, len, &offset, 0, 1, &read);
01025 int_ossl_decode_sanity_check(len, read, offset);
01026 return Qnil;
01027 }
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041 static VALUE
01042 ossl_asn1_decode(VALUE self, VALUE obj)
01043 {
01044 VALUE ret;
01045 unsigned char *p;
01046 volatile VALUE tmp;
01047 long len, read = 0, offset = 0;
01048
01049 obj = ossl_to_der_if_possible(obj);
01050 tmp = rb_str_new4(StringValue(obj));
01051 p = (unsigned char *)RSTRING_PTR(tmp);
01052 len = RSTRING_LEN(tmp);
01053 ret = ossl_asn1_decode0(&p, len, &offset, 0, 0, &read);
01054 int_ossl_decode_sanity_check(len, read, offset);
01055 return ret;
01056 }
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071 static VALUE
01072 ossl_asn1_decode_all(VALUE self, VALUE obj)
01073 {
01074 VALUE ary, val;
01075 unsigned char *p;
01076 long len, tmp_len = 0, read = 0, offset = 0;
01077 volatile VALUE tmp;
01078
01079 obj = ossl_to_der_if_possible(obj);
01080 tmp = rb_str_new4(StringValue(obj));
01081 p = (unsigned char *)RSTRING_PTR(tmp);
01082 len = RSTRING_LEN(tmp);
01083 tmp_len = len;
01084 ary = rb_ary_new();
01085 while (tmp_len > 0) {
01086 long tmp_read = 0;
01087 val = ossl_asn1_decode0(&p, tmp_len, &offset, 0, 0, &tmp_read);
01088 rb_ary_push(ary, val);
01089 read += tmp_read;
01090 tmp_len -= tmp_read;
01091 }
01092 int_ossl_decode_sanity_check(len, read, offset);
01093 return ary;
01094 }
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119 static VALUE
01120 ossl_asn1_initialize(int argc, VALUE *argv, VALUE self)
01121 {
01122 VALUE value, tag, tagging, tag_class;
01123
01124 rb_scan_args(argc, argv, "13", &value, &tag, &tagging, &tag_class);
01125 if(argc > 1){
01126 if(NIL_P(tag))
01127 ossl_raise(eASN1Error, "must specify tag number");
01128 if(!NIL_P(tagging) && !SYMBOL_P(tagging))
01129 ossl_raise(eASN1Error, "invalid tagging method");
01130 if(NIL_P(tag_class)) {
01131 if (NIL_P(tagging))
01132 tag_class = ID2SYM(sUNIVERSAL);
01133 else
01134 tag_class = ID2SYM(sCONTEXT_SPECIFIC);
01135 }
01136 if(!SYMBOL_P(tag_class))
01137 ossl_raise(eASN1Error, "invalid tag class");
01138 if(SYM2ID(tagging) == sIMPLICIT && NUM2INT(tag) > 31)
01139 ossl_raise(eASN1Error, "tag number for Universal too large");
01140 }
01141 else{
01142 tag = INT2NUM(ossl_asn1_default_tag(self));
01143 tagging = Qnil;
01144 tag_class = ID2SYM(sUNIVERSAL);
01145 }
01146 ossl_asn1_set_tag(self, tag);
01147 ossl_asn1_set_value(self, value);
01148 ossl_asn1_set_tagging(self, tagging);
01149 ossl_asn1_set_tag_class(self, tag_class);
01150 ossl_asn1_set_infinite_length(self, Qfalse);
01151
01152 return self;
01153 }
01154
01155 static VALUE
01156 ossl_asn1eoc_initialize(VALUE self) {
01157 VALUE tag, tagging, tag_class, value;
01158 tag = INT2NUM(ossl_asn1_default_tag(self));
01159 tagging = Qnil;
01160 tag_class = ID2SYM(sUNIVERSAL);
01161 value = rb_str_new("", 0);
01162 ossl_asn1_set_tag(self, tag);
01163 ossl_asn1_set_value(self, value);
01164 ossl_asn1_set_tagging(self, tagging);
01165 ossl_asn1_set_tag_class(self, tag_class);
01166 ossl_asn1_set_infinite_length(self, Qfalse);
01167 return self;
01168 }
01169
01170 static int
01171 ossl_i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **pp)
01172 {
01173 #if OPENSSL_VERSION_NUMBER < 0x00907000L
01174 if(!a) return 0;
01175 if(a->type == V_ASN1_BOOLEAN)
01176 return i2d_ASN1_BOOLEAN(a->value.boolean, pp);
01177 #endif
01178 return i2d_ASN1_TYPE(a, pp);
01179 }
01180
01181 static void
01182 ossl_ASN1_TYPE_free(ASN1_TYPE *a)
01183 {
01184 #if OPENSSL_VERSION_NUMBER < 0x00907000L
01185 if(!a) return;
01186 if(a->type == V_ASN1_BOOLEAN){
01187 OPENSSL_free(a);
01188 return;
01189 }
01190 #endif
01191 ASN1_TYPE_free(a);
01192 }
01193
01194
01195
01196
01197
01198
01199
01200 static VALUE
01201 ossl_asn1prim_to_der(VALUE self)
01202 {
01203 ASN1_TYPE *asn1;
01204 int tn, tc, explicit;
01205 long len, reallen;
01206 unsigned char *buf, *p;
01207 VALUE str;
01208
01209 tn = NUM2INT(ossl_asn1_get_tag(self));
01210 tc = ossl_asn1_tag_class(self);
01211 explicit = ossl_asn1_is_explicit(self);
01212 asn1 = ossl_asn1_get_asn1type(self);
01213
01214 len = ossl_asn1_object_size(1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn);
01215 if(!(buf = OPENSSL_malloc(len))){
01216 ossl_ASN1_TYPE_free(asn1);
01217 ossl_raise(eASN1Error, "cannot alloc buffer");
01218 }
01219 p = buf;
01220 if (tc == V_ASN1_UNIVERSAL) {
01221 ossl_i2d_ASN1_TYPE(asn1, &p);
01222 } else if (explicit) {
01223 ossl_asn1_put_object(&p, 1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn, tc);
01224 ossl_i2d_ASN1_TYPE(asn1, &p);
01225 } else {
01226 ossl_i2d_ASN1_TYPE(asn1, &p);
01227 *buf = tc | tn | (*buf & V_ASN1_CONSTRUCTED);
01228 }
01229 ossl_ASN1_TYPE_free(asn1);
01230 reallen = p - buf;
01231 assert(reallen <= len);
01232 str = ossl_buf2str((char *)buf, rb_long2int(reallen));
01233
01234 return str;
01235 }
01236
01237
01238
01239
01240
01241
01242
01243 static VALUE
01244 ossl_asn1cons_to_der(VALUE self)
01245 {
01246 int tag, tn, tc, explicit, constructed = 1;
01247 int found_prim = 0, seq_len;
01248 long length;
01249 unsigned char *p;
01250 VALUE value, str, inf_length;
01251
01252 tn = NUM2INT(ossl_asn1_get_tag(self));
01253 tc = ossl_asn1_tag_class(self);
01254 inf_length = ossl_asn1_get_infinite_length(self);
01255 if (inf_length == Qtrue) {
01256 VALUE ary, example;
01257 constructed = 2;
01258 if (CLASS_OF(self) == cASN1Sequence ||
01259 CLASS_OF(self) == cASN1Set) {
01260 tag = ossl_asn1_default_tag(self);
01261 }
01262 else {
01263 ary = ossl_asn1_get_value(self);
01264 if (!rb_obj_is_kind_of(ary, rb_cArray))
01265 ossl_raise(eASN1Error, "Constructive value must be an Array");
01266
01267
01268
01269
01270 while (!found_prim){
01271 example = rb_ary_entry(ary, 0);
01272 if (rb_obj_is_kind_of(example, cASN1Primitive)){
01273 found_prim = 1;
01274 }
01275 else {
01276
01277 if (!rb_obj_is_kind_of(example, cASN1Constructive)){
01278 ossl_raise(eASN1Error, "invalid constructed encoding");
01279 return Qnil;
01280 }
01281 ary = ossl_asn1_get_value(example);
01282 }
01283 }
01284 tag = ossl_asn1_default_tag(example);
01285 }
01286 }
01287 else {
01288 if (CLASS_OF(self) == cASN1Constructive)
01289 ossl_raise(eASN1Error, "Constructive shall only be used with infinite length");
01290 tag = ossl_asn1_default_tag(self);
01291 }
01292 explicit = ossl_asn1_is_explicit(self);
01293 value = join_der(ossl_asn1_get_value(self));
01294
01295 seq_len = ossl_asn1_object_size(constructed, RSTRING_LENINT(value), tag);
01296 length = ossl_asn1_object_size(constructed, seq_len, tn);
01297 str = rb_str_new(0, length);
01298 p = (unsigned char *)RSTRING_PTR(str);
01299 if(tc == V_ASN1_UNIVERSAL)
01300 ossl_asn1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc);
01301 else{
01302 if(explicit){
01303 ossl_asn1_put_object(&p, constructed, seq_len, tn, tc);
01304 ossl_asn1_put_object(&p, constructed, RSTRING_LENINT(value), tag, V_ASN1_UNIVERSAL);
01305 }
01306 else{
01307 ossl_asn1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc);
01308 }
01309 }
01310 memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
01311 p += RSTRING_LEN(value);
01312
01313
01314
01315
01316
01317
01318 if (explicit && inf_length == Qtrue) {
01319 ASN1_put_eoc(&p);
01320 }
01321 ossl_str_adjust(str, p);
01322
01323 return str;
01324 }
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339 static VALUE
01340 ossl_asn1cons_each(VALUE self)
01341 {
01342 rb_ary_each(ossl_asn1_get_value(self));
01343 return self;
01344 }
01345
01346 static VALUE
01347 ossl_asn1obj_s_register(VALUE self, VALUE oid, VALUE sn, VALUE ln)
01348 {
01349 StringValue(oid);
01350 StringValue(sn);
01351 StringValue(ln);
01352
01353 if(!OBJ_create(RSTRING_PTR(oid), RSTRING_PTR(sn), RSTRING_PTR(ln)))
01354 ossl_raise(eASN1Error, NULL);
01355
01356 return Qtrue;
01357 }
01358
01359 static VALUE
01360 ossl_asn1obj_get_sn(VALUE self)
01361 {
01362 VALUE val, ret = Qnil;
01363 int nid;
01364
01365 val = ossl_asn1_get_value(self);
01366 if ((nid = OBJ_txt2nid(StringValuePtr(val))) != NID_undef)
01367 ret = rb_str_new2(OBJ_nid2sn(nid));
01368
01369 return ret;
01370 }
01371
01372 static VALUE
01373 ossl_asn1obj_get_ln(VALUE self)
01374 {
01375 VALUE val, ret = Qnil;
01376 int nid;
01377
01378 val = ossl_asn1_get_value(self);
01379 if ((nid = OBJ_txt2nid(StringValuePtr(val))) != NID_undef)
01380 ret = rb_str_new2(OBJ_nid2ln(nid));
01381
01382 return ret;
01383 }
01384
01385 static VALUE
01386 ossl_asn1obj_get_oid(VALUE self)
01387 {
01388 VALUE val;
01389 ASN1_OBJECT *a1obj;
01390 char buf[128];
01391
01392 val = ossl_asn1_get_value(self);
01393 a1obj = obj_to_asn1obj(val);
01394 OBJ_obj2txt(buf, sizeof(buf), a1obj, 1);
01395 ASN1_OBJECT_free(a1obj);
01396
01397 return rb_str_new2(buf);
01398 }
01399
01400 #define OSSL_ASN1_IMPL_FACTORY_METHOD(klass) \
01401 static VALUE ossl_asn1_##klass(int argc, VALUE *argv, VALUE self)\
01402 { return rb_funcall3(cASN1##klass, rb_intern("new"), argc, argv); }
01403
01404 OSSL_ASN1_IMPL_FACTORY_METHOD(Boolean)
01405 OSSL_ASN1_IMPL_FACTORY_METHOD(Integer)
01406 OSSL_ASN1_IMPL_FACTORY_METHOD(Enumerated)
01407 OSSL_ASN1_IMPL_FACTORY_METHOD(BitString)
01408 OSSL_ASN1_IMPL_FACTORY_METHOD(OctetString)
01409 OSSL_ASN1_IMPL_FACTORY_METHOD(UTF8String)
01410 OSSL_ASN1_IMPL_FACTORY_METHOD(NumericString)
01411 OSSL_ASN1_IMPL_FACTORY_METHOD(PrintableString)
01412 OSSL_ASN1_IMPL_FACTORY_METHOD(T61String)
01413 OSSL_ASN1_IMPL_FACTORY_METHOD(VideotexString)
01414 OSSL_ASN1_IMPL_FACTORY_METHOD(IA5String)
01415 OSSL_ASN1_IMPL_FACTORY_METHOD(GraphicString)
01416 OSSL_ASN1_IMPL_FACTORY_METHOD(ISO64String)
01417 OSSL_ASN1_IMPL_FACTORY_METHOD(GeneralString)
01418 OSSL_ASN1_IMPL_FACTORY_METHOD(UniversalString)
01419 OSSL_ASN1_IMPL_FACTORY_METHOD(BMPString)
01420 OSSL_ASN1_IMPL_FACTORY_METHOD(Null)
01421 OSSL_ASN1_IMPL_FACTORY_METHOD(ObjectId)
01422 OSSL_ASN1_IMPL_FACTORY_METHOD(UTCTime)
01423 OSSL_ASN1_IMPL_FACTORY_METHOD(GeneralizedTime)
01424 OSSL_ASN1_IMPL_FACTORY_METHOD(Sequence)
01425 OSSL_ASN1_IMPL_FACTORY_METHOD(Set)
01426 OSSL_ASN1_IMPL_FACTORY_METHOD(EndOfContent)
01427
01428 void
01429 Init_ossl_asn1()
01430 {
01431 VALUE ary;
01432 int i;
01433
01434 #if 0
01435 mOSSL = rb_define_module("OpenSSL");
01436 #endif
01437
01438 sUNIVERSAL = rb_intern("UNIVERSAL");
01439 sCONTEXT_SPECIFIC = rb_intern("CONTEXT_SPECIFIC");
01440 sAPPLICATION = rb_intern("APPLICATION");
01441 sPRIVATE = rb_intern("PRIVATE");
01442 sEXPLICIT = rb_intern("EXPLICIT");
01443 sIMPLICIT = rb_intern("IMPLICIT");
01444
01445 sivVALUE = rb_intern("@value");
01446 sivTAG = rb_intern("@tag");
01447 sivTAGGING = rb_intern("@tagging");
01448 sivTAG_CLASS = rb_intern("@tag_class");
01449 sivINFINITE_LENGTH = rb_intern("@infinite_length");
01450 sivUNUSED_BITS = rb_intern("@unused_bits");
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578 mASN1 = rb_define_module_under(mOSSL, "ASN1");
01579
01580
01581
01582
01583
01584
01585 eASN1Error = rb_define_class_under(mASN1, "ASN1Error", eOSSLError);
01586 rb_define_module_function(mASN1, "traverse", ossl_asn1_traverse, 1);
01587 rb_define_module_function(mASN1, "decode", ossl_asn1_decode, 1);
01588 rb_define_module_function(mASN1, "decode_all", ossl_asn1_decode_all, 1);
01589 ary = rb_ary_new();
01590
01591
01592
01593
01594 rb_define_const(mASN1, "UNIVERSAL_TAG_NAME", ary);
01595 for(i = 0; i < ossl_asn1_info_size; i++){
01596 if(ossl_asn1_info[i].name[0] == '[') continue;
01597 rb_define_const(mASN1, ossl_asn1_info[i].name, INT2NUM(i));
01598 rb_ary_store(ary, i, rb_str_new2(ossl_asn1_info[i].name));
01599 }
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688 cASN1Data = rb_define_class_under(mASN1, "ASN1Data", rb_cObject);
01689
01690
01691
01692
01693
01694 rb_attr(cASN1Data, rb_intern("value"), 1, 1, 0);
01695
01696
01697
01698 rb_attr(cASN1Data, rb_intern("tag"), 1, 1, 0);
01699
01700
01701
01702
01703 rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, 0);
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721 rb_attr(cASN1Data, rb_intern("infinite_length"), 1, 1, 0);
01722 rb_define_method(cASN1Data, "initialize", ossl_asn1data_initialize, 3);
01723 rb_define_method(cASN1Data, "to_der", ossl_asn1data_to_der, 0);
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785 cASN1Primitive = rb_define_class_under(mASN1, "Primitive", cASN1Data);
01786
01787
01788
01789
01790
01791
01792 rb_attr(cASN1Primitive, rb_intern("tagging"), 1, 1, Qtrue);
01793 rb_undef_method(cASN1Primitive, "infinite_length=");
01794 rb_define_method(cASN1Primitive, "initialize", ossl_asn1_initialize, -1);
01795 rb_define_method(cASN1Primitive, "to_der", ossl_asn1prim_to_der, 0);
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859 cASN1Constructive = rb_define_class_under(mASN1,"Constructive", cASN1Data);
01860 rb_include_module(cASN1Constructive, rb_mEnumerable);
01861
01862
01863
01864
01865
01866
01867 rb_attr(cASN1Constructive, rb_intern("tagging"), 1, 1, Qtrue);
01868 rb_define_method(cASN1Constructive, "initialize", ossl_asn1_initialize, -1);
01869 rb_define_method(cASN1Constructive, "to_der", ossl_asn1cons_to_der, 0);
01870 rb_define_method(cASN1Constructive, "each", ossl_asn1cons_each, 0);
01871
01872 #define OSSL_ASN1_DEFINE_CLASS(name, super) \
01873 do{\
01874 cASN1##name = rb_define_class_under(mASN1, #name, cASN1##super);\
01875 rb_define_module_function(mASN1, #name, ossl_asn1_##name, -1);\
01876 }while(0)
01877
01878 OSSL_ASN1_DEFINE_CLASS(Boolean, Primitive);
01879 OSSL_ASN1_DEFINE_CLASS(Integer, Primitive);
01880 OSSL_ASN1_DEFINE_CLASS(Enumerated, Primitive);
01881 OSSL_ASN1_DEFINE_CLASS(BitString, Primitive);
01882 OSSL_ASN1_DEFINE_CLASS(OctetString, Primitive);
01883 OSSL_ASN1_DEFINE_CLASS(UTF8String, Primitive);
01884 OSSL_ASN1_DEFINE_CLASS(NumericString, Primitive);
01885 OSSL_ASN1_DEFINE_CLASS(PrintableString, Primitive);
01886 OSSL_ASN1_DEFINE_CLASS(T61String, Primitive);
01887 OSSL_ASN1_DEFINE_CLASS(VideotexString, Primitive);
01888 OSSL_ASN1_DEFINE_CLASS(IA5String, Primitive);
01889 OSSL_ASN1_DEFINE_CLASS(GraphicString, Primitive);
01890 OSSL_ASN1_DEFINE_CLASS(ISO64String, Primitive);
01891 OSSL_ASN1_DEFINE_CLASS(GeneralString, Primitive);
01892 OSSL_ASN1_DEFINE_CLASS(UniversalString, Primitive);
01893 OSSL_ASN1_DEFINE_CLASS(BMPString, Primitive);
01894 OSSL_ASN1_DEFINE_CLASS(Null, Primitive);
01895 OSSL_ASN1_DEFINE_CLASS(ObjectId, Primitive);
01896 OSSL_ASN1_DEFINE_CLASS(UTCTime, Primitive);
01897 OSSL_ASN1_DEFINE_CLASS(GeneralizedTime, Primitive);
01898
01899 OSSL_ASN1_DEFINE_CLASS(Sequence, Constructive);
01900 OSSL_ASN1_DEFINE_CLASS(Set, Constructive);
01901
01902 OSSL_ASN1_DEFINE_CLASS(EndOfContent, Data);
01903
01904 rb_define_singleton_method(cASN1ObjectId, "register", ossl_asn1obj_s_register, 3);
01905 rb_define_method(cASN1ObjectId, "sn", ossl_asn1obj_get_sn, 0);
01906 rb_define_method(cASN1ObjectId, "ln", ossl_asn1obj_get_ln, 0);
01907 rb_define_method(cASN1ObjectId, "oid", ossl_asn1obj_get_oid, 0);
01908 rb_define_alias(cASN1ObjectId, "short_name", "sn");
01909 rb_define_alias(cASN1ObjectId, "long_name", "ln");
01910 rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, 0);
01911
01912 rb_define_method(cASN1EndOfContent, "initialize", ossl_asn1eoc_initialize, 0);
01913
01914 class_tag_map = rb_hash_new();
01915 rb_hash_aset(class_tag_map, cASN1EndOfContent, INT2NUM(V_ASN1_EOC));
01916 rb_hash_aset(class_tag_map, cASN1Boolean, INT2NUM(V_ASN1_BOOLEAN));
01917 rb_hash_aset(class_tag_map, cASN1Integer, INT2NUM(V_ASN1_INTEGER));
01918 rb_hash_aset(class_tag_map, cASN1BitString, INT2NUM(V_ASN1_BIT_STRING));
01919 rb_hash_aset(class_tag_map, cASN1OctetString, INT2NUM(V_ASN1_OCTET_STRING));
01920 rb_hash_aset(class_tag_map, cASN1Null, INT2NUM(V_ASN1_NULL));
01921 rb_hash_aset(class_tag_map, cASN1ObjectId, INT2NUM(V_ASN1_OBJECT));
01922 rb_hash_aset(class_tag_map, cASN1Enumerated, INT2NUM(V_ASN1_ENUMERATED));
01923 rb_hash_aset(class_tag_map, cASN1UTF8String, INT2NUM(V_ASN1_UTF8STRING));
01924 rb_hash_aset(class_tag_map, cASN1Sequence, INT2NUM(V_ASN1_SEQUENCE));
01925 rb_hash_aset(class_tag_map, cASN1Set, INT2NUM(V_ASN1_SET));
01926 rb_hash_aset(class_tag_map, cASN1NumericString, INT2NUM(V_ASN1_NUMERICSTRING));
01927 rb_hash_aset(class_tag_map, cASN1PrintableString, INT2NUM(V_ASN1_PRINTABLESTRING));
01928 rb_hash_aset(class_tag_map, cASN1T61String, INT2NUM(V_ASN1_T61STRING));
01929 rb_hash_aset(class_tag_map, cASN1VideotexString, INT2NUM(V_ASN1_VIDEOTEXSTRING));
01930 rb_hash_aset(class_tag_map, cASN1IA5String, INT2NUM(V_ASN1_IA5STRING));
01931 rb_hash_aset(class_tag_map, cASN1UTCTime, INT2NUM(V_ASN1_UTCTIME));
01932 rb_hash_aset(class_tag_map, cASN1GeneralizedTime, INT2NUM(V_ASN1_GENERALIZEDTIME));
01933 rb_hash_aset(class_tag_map, cASN1GraphicString, INT2NUM(V_ASN1_GRAPHICSTRING));
01934 rb_hash_aset(class_tag_map, cASN1ISO64String, INT2NUM(V_ASN1_ISO64STRING));
01935 rb_hash_aset(class_tag_map, cASN1GeneralString, INT2NUM(V_ASN1_GENERALSTRING));
01936 rb_hash_aset(class_tag_map, cASN1UniversalString, INT2NUM(V_ASN1_UNIVERSALSTRING));
01937 rb_hash_aset(class_tag_map, cASN1BMPString, INT2NUM(V_ASN1_BMPSTRING));
01938 rb_global_variable(&class_tag_map);
01939 }
01940