예제 #1
0
/* Take a public-key S-Exp and convert it into a DER encoded
   publicKeyInfo */
gpg_error_t
_ksba_keyinfo_from_sexp (ksba_const_sexp_t sexp,
                         unsigned char **r_der, size_t *r_derlen)
{
  gpg_error_t err;
  const unsigned char *s;
  char *endp;
  unsigned long n, n1;
  const unsigned char *oid;
  int oidlen;
  unsigned char *curve_oid = NULL;
  size_t curve_oidlen;
  pkalgo_t pkalgo;
  int i;
  struct {
    const char *name;
    int namelen;
    const unsigned char *value;
    int valuelen;
  } parm[10]; 
  int parmidx;
  int idxtbl[10];
  int idxtbllen;
  const char *parmdesc, *algoparmdesc;
  ksba_writer_t writer = NULL;
  void *algoparmseq_value = NULL;
  size_t algoparmseq_len;
  void *bitstr_value = NULL;
  size_t bitstr_len;

  if (!sexp)
    return gpg_error (GPG_ERR_INV_VALUE);

  s = sexp;
  if (*s != '(')
    return gpg_error (GPG_ERR_INV_SEXP);
  s++;

  n = strtoul (s, &endp, 10);
  s = endp;
  if (!n || *s != ':')
    return gpg_error (GPG_ERR_INV_SEXP); /* we don't allow empty lengths */
  s++;
  if (n != 10 || memcmp (s, "public-key", 10))
    return gpg_error (GPG_ERR_UNKNOWN_SEXP);
  s += 10;
  if (*s != '(')
    return gpg_error (digitp (s)? GPG_ERR_UNKNOWN_SEXP : GPG_ERR_INV_SEXP);
  s++;

  /* Break out the algorithm ID */
  n = strtoul (s, &endp, 10);
  s = endp;
  if (!n || *s != ':')
    return gpg_error (GPG_ERR_INV_SEXP); /* we don't allow empty lengths */
  s++;
  oid = oid_from_buffer (s, n, &oidlen, &pkalgo);
  if (!oid)
    return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
  s += n;

  /* Collect all the values */
  for (parmidx = 0; *s != ')' ; parmidx++)
    {
      if (parmidx >= DIM(parm))
        return gpg_error (GPG_ERR_GENERAL);
      if (*s != '(')
        return gpg_error (digitp(s)? GPG_ERR_UNKNOWN_SEXP:GPG_ERR_INV_SEXP);
      s++;
      n = strtoul (s, &endp, 10);
      s = endp;
      if (!n || *s != ':')
        return gpg_error (GPG_ERR_INV_SEXP); 
      s++;
      parm[parmidx].name = s;
      parm[parmidx].namelen = n;
      s += n; 
      if (!digitp(s))
        return gpg_error (GPG_ERR_UNKNOWN_SEXP); /* ... or invalid S-Exp. */

      n = strtoul (s, &endp, 10);
      s = endp;
      if (!n || *s != ':')
        return gpg_error (GPG_ERR_INV_SEXP); 
      s++;
      parm[parmidx].value = s;
      parm[parmidx].valuelen = n;
      s += n;
      if ( *s != ')')
        return gpg_error (GPG_ERR_UNKNOWN_SEXP); /* ... or invalid S-Exp. */
      s++;
    }
  s++;
  /* We need another closing parenthesis. */
  if ( *s != ')' )
    return gpg_error (GPG_ERR_INV_SEXP); 

  /* Describe the parameters in the order we want them and construct
     IDXTBL to access them.  For DSA wie also set algoparmdesc so
     that we can later build the parameters for the
     algorithmIdentifier.  */
  algoparmdesc = NULL;
  switch (pkalgo)
    {
    case PKALGO_RSA: parmdesc = "ne"; break;
    case PKALGO_DSA: parmdesc = "y" ; algoparmdesc = "pqg"; break;
    case PKALGO_ECC: parmdesc = "Cq"; break;
    default: return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
    }      

  idxtbllen = 0;
  for (s = parmdesc; *s; s++)
    {
      for (i=0; i < parmidx; i++)
        {
          assert (idxtbllen < DIM (idxtbl));
          switch (*s)
            {
            case 'C': /* Magic value for "curve".  */
              if (parm[i].namelen == 5 && !memcmp (parm[i].name, "curve", 5))
                {
                  idxtbl[idxtbllen++] = i;
                  i = parmidx; /* Break inner loop.  */
                }
              break;
            default:
              if (parm[i].namelen == 1 && parm[i].name[0] == *s)
                {
                  idxtbl[idxtbllen++] = i;
                  i = parmidx; /* Break inner loop.  */
                }
              break;
            }
        }
    }
  if (idxtbllen != strlen (parmdesc))
    return gpg_error (GPG_ERR_UNKNOWN_SEXP);

  if (pkalgo == PKALGO_ECC)
    {
      curve_oid = get_ecc_curve_oid (parm[idxtbl[0]].value,
                                     parm[idxtbl[0]].valuelen,
                                     &curve_oidlen);
      if (!curve_oid)
        return gpg_error (GPG_ERR_UNKNOWN_SEXP);
    }

      
  /* Create write object. */
  err = ksba_writer_new (&writer);
  if (err)
    goto leave;
  err = ksba_writer_set_mem (writer, 1024);
  if (err)
    goto leave;
  
  /* We create the keyinfo in 2 steps:
     
     1. We build the inner one and encapsulate it in a bit string.
  
     2. We create the outer sequence include the algorithm identifier
        and the bit string from step 1. 
   */
  if (pkalgo == PKALGO_ECC)
    {
      /* Write the bit string header and the number of unused bits. */
      err = _ksba_ber_write_tl (writer, TYPE_BIT_STRING, CLASS_UNIVERSAL, 
                                0, parm[idxtbl[1]].valuelen + 1);
      if (!err)
        err = ksba_writer_write (writer, "", 1);
      /* And the actual raw value.  */
      if (!err)
        err = ksba_writer_write (writer, parm[idxtbl[1]].value,
                                 parm[idxtbl[1]].valuelen);
      if (err)
        goto leave;

    }
  else /* RSA and DSA */
    {
      /* Calculate the size of the sequence value and the size of the
         bit string value.  NOt ethat in case there is only one
         integer to write, no sequence is used.  */
      for (n=0, i=0; i < idxtbllen; i++ )
        {
          n += _ksba_ber_count_tl (TYPE_INTEGER, CLASS_UNIVERSAL, 0,
                                   parm[idxtbl[i]].valuelen);
          n += parm[idxtbl[i]].valuelen;
        }
  
      n1 = 1; /* # of unused bits.  */
      if (idxtbllen > 1)
        n1 += _ksba_ber_count_tl (TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
      n1 += n;
  
      /* Write the bit string header and the number of unused bits. */
      err = _ksba_ber_write_tl (writer, TYPE_BIT_STRING, CLASS_UNIVERSAL, 
                                0, n1);
      if (!err)
        err = ksba_writer_write (writer, "", 1);
      if (err)
        goto leave;
      
      /* Write the sequence tag and the integers. */
      if (idxtbllen > 1)
        err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1,n);
      if (err)
        goto leave;
      for (i=0; i < idxtbllen; i++)
        {
          /* fixme: we should make sure that the integer conforms to the
             ASN.1 encoding rules. */
          err  = _ksba_ber_write_tl (writer, TYPE_INTEGER, CLASS_UNIVERSAL, 0, 
                                     parm[idxtbl[i]].valuelen);
          if (!err)
            err = ksba_writer_write (writer, parm[idxtbl[i]].value, 
                                     parm[idxtbl[i]].valuelen);
          if (err)
            goto leave;
        }
    }

  /* Get the encoded bit string. */
  bitstr_value = ksba_writer_snatch_mem (writer, &bitstr_len);
  if (!bitstr_value)
    {
      err = gpg_error (GPG_ERR_ENOMEM);
      goto leave;
    }
  
  /* If the algorithmIdentifier requires a sequence with parameters,
     build them now.  We can reuse the IDXTBL for that.  */
  if (algoparmdesc)
    {
      idxtbllen = 0;
      for (s = algoparmdesc; *s; s++)
        {
          for (i=0; i < parmidx; i++)
            {
              assert (idxtbllen < DIM (idxtbl));
              if (parm[i].namelen == 1 && parm[i].name[0] == *s)
                {
                  idxtbl[idxtbllen++] = i;
                  break;
                }
            }
        }
      if (idxtbllen != strlen (algoparmdesc))
        return gpg_error (GPG_ERR_UNKNOWN_SEXP);

      err = ksba_writer_set_mem (writer, 1024);
      if (err)
        goto leave;

      /* Calculate the size of the sequence.  */
      for (n=0, i=0; i < idxtbllen; i++ )
        {
          n += _ksba_ber_count_tl (TYPE_INTEGER, CLASS_UNIVERSAL, 0,
                                   parm[idxtbl[i]].valuelen);
          n += parm[idxtbl[i]].valuelen;
        }
      //      n += _ksba_ber_count_tl (TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
  
      /* Write the sequence tag followed by the integers. */
      err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
      if (err)
        goto leave;
      for (i=0; i < idxtbllen; i++)
        {
          err = _ksba_ber_write_tl (writer, TYPE_INTEGER, CLASS_UNIVERSAL, 0, 
                                    parm[idxtbl[i]].valuelen);
          if (!err)
            err = ksba_writer_write (writer, parm[idxtbl[i]].value, 
                                     parm[idxtbl[i]].valuelen);
          if (err)
            goto leave;
        }

      /* Get the encoded sequence.  */
      algoparmseq_value = ksba_writer_snatch_mem (writer, &algoparmseq_len);
      if (!algoparmseq_value)
        {
          err = gpg_error (GPG_ERR_ENOMEM);
          goto leave;
        }
    }
  else
    algoparmseq_len = 0;

  /* Reinitialize the buffer to create the outer sequence. */
  err = ksba_writer_set_mem (writer, 1024);
  if (err)
    goto leave;

  /* Calulate lengths. */
  n  = _ksba_ber_count_tl (TYPE_OBJECT_ID, CLASS_UNIVERSAL, 0, oidlen);
  n += oidlen;
  if (algoparmseq_len)
    {
      n += algoparmseq_len;
    }
  else if (pkalgo == PKALGO_ECC)
    {
      n += _ksba_ber_count_tl (TYPE_OBJECT_ID, CLASS_UNIVERSAL,
                               0, curve_oidlen);
      n += curve_oidlen;
    }
  else if (pkalgo == PKALGO_RSA)
    {
      n += _ksba_ber_count_tl (TYPE_NULL, CLASS_UNIVERSAL, 0, 0);
    }

  n1 = n;
  n1 += _ksba_ber_count_tl (TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
  n1 += bitstr_len;

  /* The outer sequence.  */
  err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n1);
  if (err)
    goto leave;

  /* The sequence.  */
  err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
  if (err)
    goto leave;

  /* The object id.  */
  err = _ksba_ber_write_tl (writer, TYPE_OBJECT_ID,CLASS_UNIVERSAL, 0, oidlen);
  if (!err)
    err = ksba_writer_write (writer, oid, oidlen);
  if (err)
    goto leave;

  /* The parameter. */
  if (algoparmseq_len)
    {
      err = ksba_writer_write (writer, algoparmseq_value, algoparmseq_len);
    }
  else if (pkalgo == PKALGO_ECC)
    {
      err = _ksba_ber_write_tl (writer, TYPE_OBJECT_ID, CLASS_UNIVERSAL,
                                0, curve_oidlen);
      if (!err)
        err = ksba_writer_write (writer, curve_oid, curve_oidlen);
    }
  else if (pkalgo == PKALGO_RSA)
    {
      err = _ksba_ber_write_tl (writer, TYPE_NULL, CLASS_UNIVERSAL, 0, 0);
    }
  if (err)
    goto leave;

  /* Append the pre-constructed bit string.  */
  err = ksba_writer_write (writer, bitstr_value, bitstr_len);
  if (err)
    goto leave;
  
  /* Get the result. */
  *r_der = ksba_writer_snatch_mem (writer, r_derlen);
  if (!*r_der)
    err = gpg_error (GPG_ERR_ENOMEM);

 leave:
  ksba_writer_release (writer);
  xfree (bitstr_value);
  xfree (curve_oid);
  return err;
}
예제 #2
0
파일: certreq.c 프로젝트: GroovIM/transport
/* The user has calculated the signatures and we can now write
   the signature */
static gpg_error_t
sign_and_write (ksba_certreq_t cr)
{
  gpg_error_t err;
  ksba_writer_t writer;
  void *value = NULL;
  size_t valuelen;

  err = ksba_writer_new (&writer);
  if (err)
    goto leave;
  err = ksba_writer_set_mem (writer, 2048);
  if (err)
    goto leave;

  /* store the cri */
  if (!cr->cri.der)
    {
      err = gpg_error (GPG_ERR_MISSING_VALUE);
      goto leave;
    }
  err = ksba_writer_write (writer, cr->cri.der, cr->cri.derlen);
  if (err)
    goto leave;

  /* store the signatureAlgorithm */
  if (!cr->sig_val.algo)
    return gpg_error (GPG_ERR_MISSING_VALUE);
  err = _ksba_der_write_algorithm_identifier (writer,
                                              cr->sig_val.algo, NULL, 0);
  if (err)
    goto leave;

  /* write the signature */
  err = _ksba_ber_write_tl (writer, TYPE_BIT_STRING, CLASS_UNIVERSAL, 0,
                            1 + cr->sig_val.valuelen);
  if (!err)
    err = ksba_writer_write (writer, "", 1);
  if (!err)
    err = ksba_writer_write (writer, cr->sig_val.value, cr->sig_val.valuelen);
  if (err)
    goto leave;

  /* pack it into the outer sequence */
  value = ksba_writer_snatch_mem (writer, &valuelen);
  if (!value)
    {
      err = gpg_error (GPG_ERR_ENOMEM);
      goto leave;
    }
  err = ksba_writer_set_mem (writer, valuelen+10);
  if (err)
    goto leave;
  /* write outer sequence */
  err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL,
                            1, valuelen);
  if (!err)
    err = ksba_writer_write (writer, value, valuelen);
  if (err)
    goto leave;

  /* and finally write the result */
  xfree (value);
  value = ksba_writer_snatch_mem (writer, &valuelen);
  if (!value)
    err = gpg_error (GPG_ERR_ENOMEM);
  else if (!cr->writer)
    err = gpg_error (GPG_ERR_MISSING_ACTION);
  else
    err = ksba_writer_write (cr->writer, value, valuelen);

 leave:
  ksba_writer_release (writer);
  xfree (value);
  return err;
}
예제 #3
0
파일: certreq.c 프로젝트: GroovIM/transport
/* Build the extension block and return it in R_DER and R_DERLEN.  IF
   CERTMODE is true build X.509 certificate extension instead.  */
static gpg_error_t
build_extensions (ksba_certreq_t cr, int certmode,
                  void **r_der, size_t *r_derlen)
{
  gpg_error_t err;
  ksba_writer_t writer, w=NULL;
  struct extn_list_s *e;
  unsigned char *value = NULL;
  size_t valuelen;
  unsigned char *p;
  size_t n;

  *r_der = NULL;
  *r_derlen = 0;
  err = ksba_writer_new (&writer);
  if (err)
    goto leave;
  err = ksba_writer_set_mem (writer, 2048);
  if (err)
    goto leave;
  err = ksba_writer_new (&w);
  if (err)
    goto leave;

  for (e=cr->extn_list; e; e = e->next)
    {
      err = ksba_writer_set_mem (w, e->derlen + 100);
      if (err)
        goto leave;

      err = ksba_oid_from_str (e->oid, &p, &n);
      if(err)
        goto leave;
      err = _ksba_ber_write_tl (w, TYPE_OBJECT_ID, CLASS_UNIVERSAL, 0, n);
      if (!err)
        err = ksba_writer_write (w, p, n);
      xfree (p);

      if (e->critical)
        {
          err = _ksba_ber_write_tl (w, TYPE_BOOLEAN, CLASS_UNIVERSAL, 0, 1);
          if (!err)
            err = ksba_writer_write (w, "\xff", 1);
          if(err)
            goto leave;
        }

      err = _ksba_ber_write_tl (w, TYPE_OCTET_STRING, CLASS_UNIVERSAL,
                                0, e->derlen);
      if (!err)
        err = ksba_writer_write (w, e->der, e->derlen);
      if(err)
        goto leave;

      p = ksba_writer_snatch_mem (w, &n);
      if (!p)
        {
          err = gpg_error (GPG_ERR_ENOMEM);
          goto leave;
        }
      err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL,
                                1, n);
      if (!err)
        err = ksba_writer_write (writer, p, n);
      xfree (p); p = NULL;
      if (err)
        goto leave;
    }

  /* Embed all the sequences into another sequence */
  value = ksba_writer_snatch_mem (writer, &valuelen);
  if (!value)
    {
      err = gpg_error (GPG_ERR_ENOMEM);
      goto leave;
    }
  err = ksba_writer_set_mem (writer, valuelen+10);
  if (err)
    goto leave;
  err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL,
                            1, valuelen);
  if (!err)
    err = ksba_writer_write (writer, value, valuelen);
  if (err)
    goto leave;

  xfree (value);
  value = ksba_writer_snatch_mem (writer, &valuelen);
  if (!value)
    {
      err = gpg_error (GPG_ERR_ENOMEM);
      goto leave;
    }

  if (!certmode)
    {
      /* Now create the extension request sequence content */
      err = ksba_writer_set_mem (writer, valuelen+100);
      if (err)
        goto leave;
      err = ksba_oid_from_str (oidstr_extensionReq, &p, &n);
      if(err)
        goto leave;
      err = _ksba_ber_write_tl (writer, TYPE_OBJECT_ID, CLASS_UNIVERSAL, 0, n);
      if (!err)
        err = ksba_writer_write (writer, p, n);
      xfree (p); p = NULL;
      if (err)
        return err;
      err = _ksba_ber_write_tl (writer, TYPE_SET, CLASS_UNIVERSAL, 1, valuelen);
      if (!err)
        err = ksba_writer_write (writer, value, valuelen);

      /* Put this all into a SEQUENCE */
      xfree (value);
      value = ksba_writer_snatch_mem (writer, &valuelen);
      if (!value)
        {
          err = gpg_error (GPG_ERR_ENOMEM);
          goto leave;
        }
      err = ksba_writer_set_mem (writer, valuelen+10);
      if (err)
        goto leave;
      err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL,
                                1, valuelen);
      if (!err)
        err = ksba_writer_write (writer, value, valuelen);
      if (err)
        goto leave;

      xfree (value);
      value = ksba_writer_snatch_mem (writer, &valuelen);
      if (!value)
        {
          err = gpg_error (GPG_ERR_ENOMEM);
          goto leave;
        }
    }

  *r_der = value;
  *r_derlen = valuelen;
  value = NULL;


 leave:
  ksba_writer_release (writer);
  ksba_writer_release (w);
  xfree (value);
  return err;
}
예제 #4
0
파일: certreq.c 프로젝트: GroovIM/transport
/* Build a value tree from the already stored values. */
static gpg_error_t
build_cri (ksba_certreq_t cr)
{
  gpg_error_t err;
  ksba_writer_t writer;
  void *value = NULL;
  size_t valuelen;
  int certmode;

  /* If a serial number has been set, we don't create a CSR but a
     proper certificate.  */
  certmode = !!cr->x509.serial.der;

  err = ksba_writer_new (&writer);
  if (err)
    goto leave;
  err = ksba_writer_set_mem (writer, 2048);
  if (err)
    goto leave;

  if (!cr->key.der)
    {
      err = gpg_error (GPG_ERR_MISSING_VALUE);
      goto leave;
    }

  /* We write all stuff out to a temporary writer object, then use
     this object to create the cri and store the cri image */

  if (certmode)
    {
      /* Store the version structure; version is 3 (encoded as 2):
         [0] { INTEGER 2 }  */
      err = ksba_writer_write (writer, "\xa0\x03\x02\x01\x02", 5);
    }
  else
    {
      /* Store version v1 (which is a 0).  */
      err = _ksba_ber_write_tl (writer, TYPE_INTEGER, CLASS_UNIVERSAL, 0, 1);
      if (!err)
        err = ksba_writer_write (writer, "", 1);
    }
  if (err)
    goto leave;

  /* For a certificate we need to store the s/n, the signature
     algorithm identifier, the issuer DN and the validity.  */
  if (certmode)
    {
      /* Store the serial number. */
      err = _ksba_ber_write_tl (writer, TYPE_INTEGER, CLASS_UNIVERSAL, 0,
                                cr->x509.serial.derlen);
      if (!err)
        err = ksba_writer_write (writer,
                                 cr->x509.serial.der, cr->x509.serial.derlen);
      if (err)
        goto leave;

      /* Store the signature algorithm identifier.  */
      if (!cr->x509.siginfo.der)
        err = gpg_error (GPG_ERR_MISSING_VALUE);
      else
        err = ksba_writer_write (writer,
                                 cr->x509.siginfo.der, cr->x509.siginfo.derlen);
      if (err)
        goto leave;


      /* Store the issuer DN.  If no issuer DN has been set we use the
         subject DN.  */
      if (cr->x509.issuer.der)
        err = ksba_writer_write (writer,
                                 cr->x509.issuer.der, cr->x509.issuer.derlen);
      else if (cr->subject.der)
        err = ksba_writer_write (writer, cr->subject.der, cr->subject.derlen);
      else
        err = gpg_error (GPG_ERR_MISSING_VALUE);
      if (err)
        goto leave;

      /* Store the Validity.  */
      {
        unsigned char templ[36];
        unsigned char *tp;

        tp = templ;
        *tp++ = 0x30;
        *tp++ = 0x22;

        *tp++ = TYPE_GENERALIZED_TIME;
        *tp++ = 15;
        if (cr->x509.not_before[0])
          {
            if (_ksba_cmp_time (cr->x509.not_before, "20500101T000000") >= 0)
              {
                memcpy (tp, cr->x509.not_before, 8);
                tp += 8;
                memcpy (tp, cr->x509.not_before+9, 6);
                tp += 6;
              }
            else
              {
                tp[-2] = TYPE_UTC_TIME;
                tp[-1] = 13;
                memcpy (tp, cr->x509.not_before+2, 6);
                tp += 6;
                memcpy (tp, cr->x509.not_before+9, 6);
                tp += 6;
              }
          }
        else
          {
            tp[-2] = TYPE_UTC_TIME;
            tp[-1] = 13;
            memcpy (tp, "110101000000", 12);
            tp += 12;
          }
        *tp++ = 'Z';

        *tp++ = TYPE_GENERALIZED_TIME;
        *tp++ = 15;
        if (cr->x509.not_after[0])
          {
            if (_ksba_cmp_time (cr->x509.not_after, "20500101T000000") >= 0)
              {
                memcpy (tp, cr->x509.not_after, 8);
                tp += 8;
                memcpy (tp, cr->x509.not_after+9, 6);
                tp += 6;
              }
            else
              {
                tp[-2] = TYPE_UTC_TIME;
                tp[-1] = 13;
                memcpy (tp, cr->x509.not_after+2, 6);
                tp += 6;
                memcpy (tp, cr->x509.not_after+9, 6);
                tp += 6;
              }
          }
        else
          {
            memcpy (tp,"20630405170000", 14);
            tp += 14;
          }
        *tp++ = 'Z';
        assert (tp - templ <= 36);
        templ[1] = tp - templ - 2;  /* Fixup the sequence length.  */

        err = ksba_writer_write (writer, templ, tp - templ);
        if (err)
          goto leave;
      }
    }

  /* store the subject */
  if (!cr->subject.der)
    {
      err = gpg_error (GPG_ERR_MISSING_VALUE);
      goto leave;
    }
  err = ksba_writer_write (writer, cr->subject.der, cr->subject.derlen);
  if (err)
    goto leave;

  /* store the public key info */
  err = ksba_writer_write (writer, cr->key.der, cr->key.derlen);
  if (err)
    goto leave;

  /* Copy generalNames objects to the extension list. */
  if (cr->subject_alt_names)
    {
      err = add_general_names_to_extn (cr, cr->subject_alt_names,
                                       oidstr_subjectAltName);
      if (err)
        goto leave;
      while (cr->subject_alt_names)
        {
          struct general_names_s *tmp = cr->subject_alt_names->next;
          xfree (cr->subject_alt_names);
          cr->subject_alt_names = tmp;
        }
      cr->subject_alt_names = NULL;
    }


  /* Write the extensions.  Note that the implicit SET OF is REQUIRED */
  xfree (value); value = NULL;
  valuelen = 0;
  if (cr->extn_list)
    {
      err = build_extensions (cr, certmode, &value, &valuelen);
      if (err)
        goto leave;
      err = _ksba_ber_write_tl (writer, certmode? 3:0,
                                CLASS_CONTEXT, 1, valuelen);
      if (!err)
        err = ksba_writer_write (writer, value, valuelen);
      if (err)
        goto leave;
    }
  else
    { /* We can't write an object of length zero using our ber_write
         function.  So we must open encode it. */
      err = ksba_writer_write (writer,
                               certmode? "\xa3\x02\x30":"\xa0\x02\x30", 4);
      if (err)
        goto leave;
    }


  /* pack it into the sequence */
  xfree (value);
  value = ksba_writer_snatch_mem (writer, &valuelen);
  if (!value)
    {
      err = gpg_error (GPG_ERR_ENOMEM);
      goto leave;
    }
  /* reinitialize the buffer to create the outer sequence */
  err = ksba_writer_set_mem (writer, valuelen+10);
  if (err)
    goto leave;
  /* write outer sequence */
  err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL,
                            1, valuelen);
  if (!err)
    err = ksba_writer_write (writer, value, valuelen);
  if (err)
    goto leave;

  /* and store the final result */
  cr->cri.der = ksba_writer_snatch_mem (writer, &cr->cri.derlen);
  if (!cr->cri.der)
    err = gpg_error (GPG_ERR_ENOMEM);

 leave:
  ksba_writer_release (writer);
  xfree (value);
  return err;
}
예제 #5
0
/* Build a value tree from the already stored values. */
static gpg_error_t
build_cri (ksba_certreq_t cr)
{
  gpg_error_t err;
  ksba_writer_t writer;
  void *value = NULL;
  size_t valuelen;

  err = ksba_writer_new (&writer);
  if (err)
    goto leave;
  err = ksba_writer_set_mem (writer, 2048);
  if (err)
    goto leave;

  /* We write all stuff out to a temporary writer object, then use
     this object to create the cri and store the cri image */

  /* store version v1 (which is a 0) */
  err = _ksba_ber_write_tl (writer, TYPE_INTEGER, CLASS_UNIVERSAL, 0, 1);
  if (!err)
    err = ksba_writer_write (writer, "", 1);
  if (err)
    goto leave;

  /* store the subject */
  if (!cr->subject.der)
    {
      err = gpg_error (GPG_ERR_MISSING_VALUE);
      goto leave;
    }
  err = ksba_writer_write (writer, cr->subject.der, cr->subject.derlen);
  if (err)
    goto leave;

  /* store the public key info */
  if (!cr->key.der)
    {
      err = gpg_error (GPG_ERR_MISSING_VALUE);
      goto leave;
    }
  err = ksba_writer_write (writer, cr->key.der, cr->key.derlen);
  if (err)
    goto leave;

  /* Copy generalNames objects to the extension list. */
  if (cr->subject_alt_names)
    {
      err = add_general_names_to_extn (cr, cr->subject_alt_names, 
                                       oidstr_subjectAltName);
      if (err)
        goto leave;
      while (cr->subject_alt_names)
        {
          struct general_names_s *tmp = cr->subject_alt_names->next;
          xfree (cr->subject_alt_names);
          cr->subject_alt_names = tmp;
        }
      cr->subject_alt_names = NULL;
    }
  

  /* Write the extensions.  Note that the implicit SET OF is REQUIRED */
  xfree (value); value = NULL;
  valuelen = 0;
  if (cr->extn_list)
    {
      err = build_extensions (cr, &value, &valuelen);
      if (err)
        goto leave;
      err = _ksba_ber_write_tl (writer, 0, CLASS_CONTEXT, 1, valuelen);
      if (!err)
        err = ksba_writer_write (writer, value, valuelen);
      if (err)
        goto leave;
    }
  else
    { /* We can't write an object of length zero using our ber_write
         function.  So we must open encode it. */
      err = ksba_writer_write (writer, "\xa0\x02\x30", 4);
      if (err)
        goto leave;
    }


  /* pack it into the sequence */
  xfree (value); 
  value = ksba_writer_snatch_mem (writer, &valuelen);
  if (!value)
    {
      err = gpg_error (GPG_ERR_ENOMEM);
      goto leave;
    }
  /* reinitialize the buffer to create the outer sequence */
  err = ksba_writer_set_mem (writer, valuelen+10);
  if (err)
    goto leave;
  /* write outer sequence */
  err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL,
                            1, valuelen);
  if (!err)
    err = ksba_writer_write (writer, value, valuelen);
  if (err)
    goto leave;
  
  /* and store the final result */
  cr->cri.der = ksba_writer_snatch_mem (writer, &cr->cri.derlen);
  if (!cr->cri.der)
    err = gpg_error (GPG_ERR_ENOMEM);

 leave:
  ksba_writer_release (writer);
  xfree (value);
  return err;
}