Back to index

lightning-sunbird  0.9+nobinonly
Functions | Variables
derenc.c File Reference
#include "secder.h"
#include "secerr.h"

Go to the source code of this file.

Functions

static int header_length (DERTemplate *dtemplate, uint32 contents_len)
static uint32 contents_length (DERTemplate *dtemplate, void *src)
static unsigned char * der_encode (unsigned char *buf, DERTemplate *dtemplate, void *src)
SECStatus DER_Encode (PRArenaPool *arena, SECItem *dest, DERTemplate *dtemplate, void *src)

Variables

DERTemplate SECAnyTemplate []
DERTemplate SECBitStringTemplate []
DERTemplate SECBooleanTemplate []
DERTemplate SECIA5StringTemplate []
DERTemplate SECIntegerTemplate []
DERTemplate SECNullTemplate []
DERTemplate SECObjectIDTemplate []
DERTemplate SECOctetStringTemplate []
DERTemplate SECPrintableStringTemplate []
DERTemplate SECT61StringTemplate []
DERTemplate SECUTCTimeTemplate []

Function Documentation

static uint32 contents_length ( DERTemplate *  dtemplate,
void src 
) [static]

Definition at line 183 of file derenc.c.

{
    uint32 len;
    unsigned long encode_kind, under_kind;
    PRBool universal;


    PORT_Assert (src != NULL);

    encode_kind = dtemplate->kind;

    universal = ((encode_kind & DER_CLASS_MASK) == DER_UNIVERSAL)
              ? PR_TRUE : PR_FALSE;
    encode_kind &= ~DER_OPTIONAL;

    if (encode_kind & DER_POINTER) {
       src = *(void **)src;
       if (src == NULL) {
           return 0;
       }
       if (dtemplate->sub != NULL) {
           dtemplate = dtemplate->sub;
           under_kind = dtemplate->kind;
           src = (void *)((char *)src + dtemplate->offset);
       } else if (universal) {
           under_kind = encode_kind & ~DER_POINTER;
       } else {
           under_kind = dtemplate->arg;
       }
    } else if (encode_kind & DER_INLINE) {
       PORT_Assert (dtemplate->sub != NULL);
       dtemplate = dtemplate->sub;
       under_kind = dtemplate->kind;
       src = (void *)((char *)src + dtemplate->offset);
    } else if (universal) {
       under_kind = encode_kind;
    } else {
       under_kind = dtemplate->arg;
    }

    /* Having any of these bits is not expected here...  */
    PORT_Assert ((under_kind & (DER_EXPLICIT | DER_INLINE | DER_OPTIONAL
                            | DER_POINTER | DER_SKIP)) == 0);

    /* This is only used in decoding; it plays no part in encoding.  */
    if (under_kind & DER_DERPTR)
       return 0;

    if (under_kind & DER_INDEFINITE) {
       uint32 sub_len;
       void   **indp = *(void ***)src;

       if (indp == NULL)
           return 0;

       len = 0;
       under_kind &= ~DER_INDEFINITE;

       if (under_kind == DER_SET || under_kind == DER_SEQUENCE) {
           DERTemplate *tmpt = dtemplate->sub;
           PORT_Assert (tmpt != NULL);

           for (; *indp != NULL; indp++) {
              void *sub_src = (void *)((char *)(*indp) + tmpt->offset);
              sub_len = contents_length (tmpt, sub_src);
              len += sub_len + header_length (tmpt, sub_len);
           }
       } else {
           /*
            * XXX Lisa is not sure this code (for handling, for example,
            * DER_INDEFINITE | DER_OCTET_STRING) is right.
            */
           for (; *indp != NULL; indp++) {
              SECItem *item = (SECItem *)(*indp);
              sub_len = item->len;
              if (under_kind == DER_BIT_STRING) {
                  sub_len = (sub_len + 7) >> 3;
                  /* bit string contents involve an extra octet */
                  if (sub_len)
                     sub_len++;
              }
              if (under_kind != DER_ANY)
                  len += 1 + DER_LengthLength (sub_len);
           }
       }

       return len;
    }

    switch (under_kind) {
      case DER_SEQUENCE:
      case DER_SET:
       {
           DERTemplate *tmpt;
           void *sub_src;
           uint32 sub_len;

           len = 0;
           for (tmpt = dtemplate + 1; tmpt->kind; tmpt++) {
              sub_src = (void *)((char *)src + tmpt->offset);
              sub_len = contents_length (tmpt, sub_src);
              len += sub_len + header_length (tmpt, sub_len);
           }
       }
       break;

      case DER_BIT_STRING:
       len = (((SECItem *)src)->len + 7) >> 3;
       /* bit string contents involve an extra octet */
       if (len)
           len++;
       break;

      default:
       len = ((SECItem *)src)->len;
       break;
    }

    return len;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static unsigned char* der_encode ( unsigned char *  buf,
DERTemplate *  dtemplate,
void src 
) [static]

Definition at line 306 of file derenc.c.

{
    int header_len;
    uint32 contents_len;
    unsigned long encode_kind, under_kind;
    PRBool explicit, optional, universal;


    /*
     * First figure out how long the encoding will be.  Do this by
     * traversing the template from top to bottom and accumulating
     * the length of each leaf item.
     */
    contents_len = contents_length (dtemplate, src);
    header_len = header_length (dtemplate, contents_len);

    /*
     * Enough smarts was involved already, so that if both the
     * header and the contents have a length of zero, then we
     * are not doing any encoding for this element.
     */
    if (header_len == 0 && contents_len == 0)
       return buf;

    encode_kind = dtemplate->kind;

    explicit = (encode_kind & DER_EXPLICIT) ? PR_TRUE : PR_FALSE;
    optional = (encode_kind & DER_OPTIONAL) ? PR_TRUE : PR_FALSE;
    encode_kind &= ~DER_OPTIONAL;
    universal = ((encode_kind & DER_CLASS_MASK) == DER_UNIVERSAL)
              ? PR_TRUE : PR_FALSE;

    if (encode_kind & DER_POINTER) {
       if (contents_len) {
           src = *(void **)src;
           PORT_Assert (src != NULL);
       }
       if (dtemplate->sub != NULL) {
           dtemplate = dtemplate->sub;
           under_kind = dtemplate->kind;
           if (universal) {
              encode_kind = under_kind;
           }
           src = (void *)((char *)src + dtemplate->offset);
       } else if (universal) {
           under_kind = encode_kind & ~DER_POINTER;
       } else {
           under_kind = dtemplate->arg;
       }
    } else if (encode_kind & DER_INLINE) {
       dtemplate = dtemplate->sub;
       under_kind = dtemplate->kind;
       if (universal) {
           encode_kind = under_kind;
       }
       src = (void *)((char *)src + dtemplate->offset);
    } else if (universal) {
       under_kind = encode_kind;
    } else {
       under_kind = dtemplate->arg;
    }

    if (explicit) {
       buf = DER_StoreHeader (buf, encode_kind,
                            (1 + DER_LengthLength(contents_len)
                            + contents_len));
       encode_kind = under_kind;
    }

    if ((encode_kind & DER_ANY) == 0) {   /* DER_ANY already contains header */
       buf = DER_StoreHeader (buf, encode_kind, contents_len);
    }

    /* If no real contents to encode, then we are done.  */
    if (contents_len == 0)
       return buf;

    if (under_kind & DER_INDEFINITE) {
       void **indp;

       indp = *(void ***)src;
       PORT_Assert (indp != NULL);

       under_kind &= ~DER_INDEFINITE;
       if (under_kind == DER_SET || under_kind == DER_SEQUENCE) {
           DERTemplate *tmpt = dtemplate->sub;
           PORT_Assert (tmpt != NULL);
           for (; *indp != NULL; indp++) {
              void *sub_src = (void *)((char *)(*indp) + tmpt->offset);
              buf = der_encode (buf, tmpt, sub_src);
           }
       } else {
           for (; *indp != NULL; indp++) {
              SECItem *item;
              int sub_len;

              item = (SECItem *)(*indp);
              sub_len = item->len;
              if (under_kind == DER_BIT_STRING) {
                  if (sub_len) {
                     int rem;

                     sub_len = (sub_len + 7) >> 3;
                     buf = DER_StoreHeader (buf, under_kind, sub_len + 1);
                     rem = (sub_len << 3) - item->len;
                     *buf++ = rem;        /* remaining bits */
                  } else {
                     buf = DER_StoreHeader (buf, under_kind, 0);
                  }
              } else if (under_kind != DER_ANY) {
                  buf = DER_StoreHeader (buf, under_kind, sub_len);
              }
              PORT_Memcpy (buf, item->data, sub_len);
              buf += sub_len;
           }
       }
       return buf;
    }

    switch (under_kind) {
      case DER_SEQUENCE:
      case DER_SET:
       {
           DERTemplate *tmpt;
           void *sub_src;

           for (tmpt = dtemplate + 1; tmpt->kind; tmpt++) {
              sub_src = (void *)((char *)src + tmpt->offset);
              buf = der_encode (buf, tmpt, sub_src);
           }
       }
       break;

      case DER_BIT_STRING:
       {
           SECItem *item;
           int rem;

           /*
            * The contents length includes our extra octet; subtract
            * it off so we just have the real string length there.
            */
           contents_len--;
           item = (SECItem *)src;
           PORT_Assert (contents_len == ((item->len + 7) >> 3));
           rem = (contents_len << 3) - item->len;
           *buf++ = rem;           /* remaining bits */
           PORT_Memcpy (buf, item->data, contents_len);
           buf += contents_len;
       }
       break;

      default:
       {
           SECItem *item;

           item = (SECItem *)src;
           PORT_Assert (contents_len == item->len);
           PORT_Memcpy (buf, item->data, contents_len);
           buf += contents_len;
       }
       break;
    }

    return buf;
}

Here is the call graph for this function:

Here is the caller graph for this function:

SECStatus DER_Encode ( PRArenaPool arena,
SECItem *  dest,
DERTemplate *  dtemplate,
void src 
)

Definition at line 475 of file derenc.c.

{
    unsigned int contents_len, header_len;

    src = (void **)((char *)src + dtemplate->offset);

    /*
     * First figure out how long the encoding will be. Do this by
     * traversing the template from top to bottom and accumulating
     * the length of each leaf item.
     */
    contents_len = contents_length (dtemplate, src);
    header_len = header_length (dtemplate, contents_len);

    dest->len = contents_len + header_len;

    /* Allocate storage to hold the encoding */
    dest->data = (unsigned char*) PORT_ArenaAlloc(arena, dest->len);
    if (dest->data == NULL) {
       PORT_SetError(SEC_ERROR_NO_MEMORY);
       return SECFailure;
    }

    /* Now encode into the buffer */
    (void) der_encode (dest->data, dtemplate, src);

    return SECSuccess;
}

Here is the caller graph for this function:

static int header_length ( DERTemplate *  dtemplate,
uint32  contents_len 
) [static]

Definition at line 100 of file derenc.c.

{
    uint32 len;
    unsigned long encode_kind, under_kind;
    PRBool explicit, optional, universal;

    encode_kind = dtemplate->kind;

    explicit = (encode_kind & DER_EXPLICIT) ? PR_TRUE : PR_FALSE;
    optional = (encode_kind & DER_OPTIONAL) ? PR_TRUE : PR_FALSE;
    universal = ((encode_kind & DER_CLASS_MASK) == DER_UNIVERSAL)
              ? PR_TRUE : PR_FALSE;

    PORT_Assert (!(explicit && universal));      /* bad templates */

    if (encode_kind & DER_POINTER) {
       if (dtemplate->sub != NULL) {
           under_kind = dtemplate->sub->kind;
           if (universal) {
              encode_kind = under_kind;
           }
       } else if (universal) {
           under_kind = encode_kind & ~DER_POINTER;
       } else {
           under_kind = dtemplate->arg;
       }
    } else if (encode_kind & DER_INLINE) {
       PORT_Assert (dtemplate->sub != NULL);
       under_kind = dtemplate->sub->kind;
       if (universal) {
           encode_kind = under_kind;
       }
    } else if (universal) {
       under_kind = encode_kind;
    } else {
       under_kind = dtemplate->arg;
    }

    /* This is only used in decoding; it plays no part in encoding.  */
    if (under_kind & DER_DERPTR)
       return 0;

    /* No header at all for an "empty" optional.  */
    if ((contents_len == 0) && optional)
       return 0;

    /* And no header for a full DER_ANY.  */
    if (encode_kind & DER_ANY)
       return 0;

    /*
     * The common case: one octet for identifier and as many octets
     * as necessary to hold the content length.
     */
    len = 1 + DER_LengthLength(contents_len);

    /* Account for the explicit wrapper, if necessary.  */
    if (explicit) {
#if 0         /*
               * Well, I was trying to do something useful, but these
               * assertions are too restrictive on valid templates.
               * I wanted to make sure that the top-level "kind" of
               * a template does not also specify DER_EXPLICIT, which
               * should only modify a component field.  Maybe later
               * I can figure out a better way to detect such a problem,
               * but for now I must remove these checks altogether.
               */
       /*
        * This modifier applies only to components of a set or sequence;
        * it should never be used on a set/sequence itself -- confirm.
        */
       PORT_Assert (under_kind != DER_SEQUENCE);
       PORT_Assert (under_kind != DER_SET);
#endif

       len += 1 + DER_LengthLength(len + contents_len);
    }

    return len;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

DERTemplate SECAnyTemplate[]
Initial value:
 {
    { DER_ANY,
         0, NULL, sizeof(SECItem) }
}

Definition at line 43 of file derenc.c.

DERTemplate SECBitStringTemplate[]
Initial value:
 {
    { DER_BIT_STRING,
         0, NULL, sizeof(SECItem) }
}

Definition at line 48 of file derenc.c.

DERTemplate SECBooleanTemplate[]
Initial value:
 {
    { DER_BOOLEAN,
         0, NULL, sizeof(SECItem) }
}

Definition at line 53 of file derenc.c.

DERTemplate SECIA5StringTemplate[]
Initial value:
 {
    { DER_IA5_STRING,
         0, NULL, sizeof(SECItem) }
}

Definition at line 58 of file derenc.c.

DERTemplate SECIntegerTemplate[]
Initial value:
 {
    { DER_INTEGER,
         0, NULL, sizeof(SECItem) }
}

Definition at line 63 of file derenc.c.

DERTemplate SECNullTemplate[]
Initial value:
 {
    { DER_NULL,
         0, NULL, sizeof(SECItem) }
}

Definition at line 68 of file derenc.c.

DERTemplate SECObjectIDTemplate[]
Initial value:
 {
    { DER_OBJECT_ID,
         0, NULL, sizeof(SECItem) }
}

Definition at line 73 of file derenc.c.

DERTemplate SECOctetStringTemplate[]
Initial value:
 {
    { DER_OCTET_STRING,
         0, NULL, sizeof(SECItem) }
}

Definition at line 78 of file derenc.c.

Initial value:
 {
    { DER_PRINTABLE_STRING,
         0, NULL, sizeof(SECItem) }
}

Definition at line 83 of file derenc.c.

DERTemplate SECT61StringTemplate[]
Initial value:
 {
    { DER_T61_STRING,
         0, NULL, sizeof(SECItem) }
}

Definition at line 88 of file derenc.c.

DERTemplate SECUTCTimeTemplate[]
Initial value:
 {
    { DER_UTC_TIME,
         0, NULL, sizeof(SECItem) }
}

Definition at line 93 of file derenc.c.