(linenum→info "unix/slp.c:2238")

openssl/0.9.8g/README.ASN1

    1: 
    2: OpenSSL ASN1 Revision
    3: =====================
    4: 
    5: This document describes some of the issues relating to the new ASN1 code.
    6: 
    7: Previous OpenSSL ASN1 problems
    8: =============================
    9: 
   10: OK why did the OpenSSL ASN1 code need revising in the first place? Well
   11: there are lots of reasons some of which are included below...
   12: 
   13: 1. The code is difficult to read and write. For every single ASN1 structure
   14: (e.g. SEQUENCE) four functions need to be written for new, free, encode and
   15: decode operations. This is a very painful and error prone operation. Very few
   16: people have ever written any OpenSSL ASN1 and those that have usually wish
   17: they hadn't.
   18: 
   19: 2. Partly because of 1. the code is bloated and takes up a disproportionate
   20: amount of space. The SEQUENCE encoder is particularly bad: it essentially
   21: contains two copies of the same operation, one to compute the SEQUENCE length
   22: and the other to encode it.
   23: 
   24: 3. The code is memory based: that is it expects to be able to read the whole
   25: structure from memory. This is fine for small structures but if you have a
   26: (say) 1Gb PKCS#7 signedData structure it isn't such a good idea...
   27: 
   28: 4. The code for the ASN1 IMPLICIT tag is evil. It is handled by temporarily
   29: changing the tag to the expected one, attempting to read it, then changing it
   30: back again. This means that decode buffers have to be writable even though they
   31: are ultimately unchanged. This gets in the way of constification.
   32: 
   33: 5. The handling of EXPLICIT isn't much better. It adds a chunk of code into 
   34: the decoder and encoder for every EXPLICIT tag.
   35: 
   36: 6. APPLICATION and PRIVATE tags aren't even supported at all.
   37: 
   38: 7. Even IMPLICIT isn't complete: there is no support for implicitly tagged
   39: types that are not OPTIONAL.
   40: 
   41: 8. Much of the code assumes that a tag will fit in a single octet. This is
   42: only true if the tag is 30 or less (mercifully tags over 30 are rare).
   43: 
   44: 9. The ASN1 CHOICE type has to be largely handled manually, there aren't any
   45: macros that properly support it.
   46: 
   47: 10. Encoders have no concept of OPTIONAL and have no error checking. If the
   48: passed structure contains a NULL in a mandatory field it will not be encoded,
   49: resulting in an invalid structure.
   50: 
   51: 11. It is tricky to add ASN1 encoders and decoders to external applications.
   52: 
   53: Template model
   54: ==============
   55: 
   56: One of the major problems with revision is the sheer volume of the ASN1 code.
   57: Attempts to change (for example) the IMPLICIT behaviour would result in a
   58: modification of *every* single decode function. 
   59: 
   60: I decided to adopt a template based approach. I'm using the term 'template'
   61: in a manner similar to SNACC templates: it has nothing to do with C++
   62: templates.
   63: 
   64: A template is a description of an ASN1 module as several constant C structures.
   65: It describes in a machine readable way exactly how the ASN1 structure should
   66: behave. If this template contains enough detail then it is possible to write
   67: versions of new, free, encode, decode (and possibly others operations) that
   68: operate on templates.
   69: 
   70: Instead of having to write code to handle each operation only a single
   71: template needs to be written. If new operations are needed (such as a 'print'
   72: operation) only a single new template based function needs to be written 
   73: which will then automatically handle all existing templates.
   74: 
   75: Plans for revision
   76: ==================
   77: 
   78: The revision will consist of the following steps. Other than the first two
   79: these can be handled in any order.
   80:  
   81: o Design and write template new, free, encode and decode operations, initially
   82: memory based. *DONE*
   83: 
   84: o Convert existing ASN1 code to template form. *IN PROGRESS*
   85: 
   86: o Convert an existing ASN1 compiler (probably SNACC) to output templates
   87: in OpenSSL form.
   88: 
   89: o Add support for BIO based ASN1 encoders and decoders to handle large
   90: structures, initially blocking I/O.
   91: 
   92: o Add support for non blocking I/O: this is quite a bit harder than blocking
   93: I/O.
   94: 
   95: o Add new ASN1 structures, such as OCSP, CRMF, S/MIME v3 (CMS), attribute
   96: certificates etc etc.
   97: 
   98: Description of major changes
   99: ============================
  100: 
  101: The BOOLEAN type now takes three values. 0xff is TRUE, 0 is FALSE and -1 is
  102: absent. The meaning of absent depends on the context. If for example the
  103: boolean type is DEFAULT FALSE (as in the case of the critical flag for
  104: certificate extensions) then -1 is FALSE, if DEFAULT TRUE then -1 is TRUE.
  105: Usually the value will only ever be read via an API which will hide this from
  106: an application.
  107: 
  108: There is an evil bug in the old ASN1 code that mishandles OPTIONAL with
  109: SEQUENCE OF or SET OF. These are both implemented as a STACK structure. The
  110: old code would omit the structure if the STACK was NULL (which is fine) or if
  111: it had zero elements (which is NOT OK). This causes problems because an empty
  112: SEQUENCE OF or SET OF will result in an empty STACK when it is decoded but when
  113: it is encoded it will be omitted resulting in different encodings. The new code
  114: only omits the encoding if the STACK is NULL, if it contains zero elements it
  115: is encoded and empty. There is an additional problem though: because an empty
  116: STACK was omitted, sometimes the corresponding *_new() function would
  117: initialize the STACK to empty so an application could immediately use it, if
  118: this is done with the new code (i.e. a NULL) it wont work. Therefore a new
  119: STACK should be allocated first. One instance of this is the X509_CRL list of
  120: revoked certificates: a helper function X509_CRL_add0_revoked() has been added
  121: for this purpose.
  122: 
  123: The X509_ATTRIBUTE structure used to have an element called 'set' which took
  124: the value 1 if the attribute value was a SET OF or 0 if it was a single. Due
  125: to the behaviour of CHOICE in the new code this has been changed to a field
  126: called 'single' which is 0 for a SET OF and 1 for single. The old field has
  127: been deleted to deliberately break source compatibility. Since this structure
  128: is normally accessed via higher level functions this shouldn't break too much.
  129: 
  130: The X509_REQ_INFO certificate request info structure no longer has a field
  131: called 'req_kludge'. This used to be set to 1 if the attributes field was
  132: (incorrectly) omitted. You can check to see if the field is omitted now by
  133: checking if the attributes field is NULL. Similarly if you need to omit
  134: the field then free attributes and set it to NULL.
  135: 
  136: The top level 'detached' field in the PKCS7 structure is no longer set when
  137: a PKCS#7 structure is read in. PKCS7_is_detached() should be called instead.
  138: The behaviour of PKCS7_get_detached() is unaffected.
  139: 
  140: The values of 'type' in the GENERAL_NAME structure have changed. This is
  141: because the old code use the ASN1 initial octet as the selector. The new
  142: code uses the index in the ASN1_CHOICE template.
  143: 
  144: The DIST_POINT_NAME structure has changed to be a true CHOICE type.
  145: 
  146: typedef struct DIST_POINT_NAME_st {
  147: int type;
  148: union {
  149:         STACK_OF(GENERAL_NAME) *fullname;
  150:         STACK_OF(X509_NAME_ENTRY) *relativename;
  151: } name;
  152: } DIST_POINT_NAME;
  153: 
  154: This means that name.fullname or name.relativename should be set
  155: and type reflects the option. That is if name.fullname is set then
  156: type is 0 and if name.relativename is set type is 1.
  157: 
  158: With the old code using the i2d functions would typically involve:
  159: 
  160: unsigned char *buf, *p;
  161: int len;
  162: /* Find length of encoding */
  163: len = i2d_SOMETHING(x, NULL);
  164: /* Allocate buffer */
  165: buf = OPENSSL_malloc(len);
  166: if(buf == NULL) {
  167:         /* Malloc error */
  168: }
  169: /* Use temp variable because &p gets updated to point to end of
  170:  * encoding.
  171:  */
  172: p = buf;
  173: i2d_SOMETHING(x, &p);
  174: 
  175: 
  176: Using the new i2d you can also do:
  177: 
  178: unsigned char *buf = NULL;
  179: int len;
  180: len = i2d_SOMETHING(x, &buf);
  181: if(len < 0) {
  182:         /* Malloc error */
  183: }
  184: 
  185: and it will automatically allocate and populate a buffer with the
  186: encoding. After this call 'buf' will point to the start of the
  187: encoding which is len bytes long.
Syntax (Markdown)