[ksba][PATCH 2/2] Merge functions that convert from sexp to der
Dmitry Eremin-Solenikov
dbaryshkov at gmail.com
Mon Jan 20 01:33:35 CET 2014
* src/keyinfo.c (cryptval_from_sexp): New. Contains code merged from
_ksba_keyinfo_from_sexp and _ksba_algoinfo_from_sexp functions.
* src/keyinfo.c (_ksba_algoinfo_from_sexp, _ksba_keyinfo_from_sexp): Use
cryptval_from_sexp function.
Merge two functions translating S-expressions to DER representation.
They share great amount of code, so merge is benefitable.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
src/keyinfo.c | 454 +++++++++++++---------------------------------------------
1 file changed, 99 insertions(+), 355 deletions(-)
diff --git a/src/keyinfo.c b/src/keyinfo.c
index 0f4f95f..cdea1e6 100644
--- a/src/keyinfo.c
+++ b/src/keyinfo.c
@@ -702,12 +702,11 @@ oid_from_buffer (const unsigned char *buf, int buflen, int *oidlen,
return pk_algo_table[i].oid;
}
-
-/* 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)
+/* Mode 0: work with public key
+ Mode 1: work with signature */
+static gpg_error_t
+cryptval_from_sexp (int mode, ksba_const_sexp_t sexp,
+ unsigned char **r_der, size_t *r_derlen)
{
gpg_error_t err;
const unsigned char *s;
@@ -748,9 +747,13 @@ _ksba_keyinfo_from_sexp (ksba_const_sexp_t sexp,
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))
+ if (n == 7 && !memcmp (s, "sig-val", 7))
+ s += 7;
+ else if (n == 10 && !memcmp (s, "public-key", 10))
+ s += 10;
+ else
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++;
@@ -761,7 +764,7 @@ _ksba_keyinfo_from_sexp (ksba_const_sexp_t sexp,
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, 0);
+ oid = oid_from_buffer (s, n, &oidlen, &pkalgo, mode);
if (!oid)
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
s += n;
@@ -809,9 +812,9 @@ _ksba_keyinfo_from_sexp (ksba_const_sexp_t sexp,
algoparmdesc = NULL;
switch (pkalgo)
{
- case PKALGO_RSA: parmdesc = "ne"; break;
- case PKALGO_DSA: parmdesc = "y" ; algoparmdesc = "pqg"; break;
- case PKALGO_ECC: parmdesc = "Cq"; break;
+ case PKALGO_RSA: parmdesc = mode ? "" : "ne"; break;
+ case PKALGO_DSA: parmdesc = mode ? "" : "y" ; algoparmdesc = "pqg"; break;
+ case PKALGO_ECC: parmdesc = mode ? "C" : "Cq"; break;
default: return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
}
@@ -868,71 +871,74 @@ _ksba_keyinfo_from_sexp (ksba_const_sexp_t sexp,
2. We create the outer sequence include the algorithm identifier
and the bit string from step 1.
*/
- if (pkalgo == PKALGO_ECC)
+ if (!mode)
{
- /* 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++ )
+ if (pkalgo == PKALGO_ECC)
{
- n += _ksba_ber_count_tl (TYPE_INTEGER, CLASS_UNIVERSAL, 0,
- parm[idxtbl[i]].valuelen);
- n += parm[idxtbl[i]].valuelen;
- }
+ /* 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;
- n1 = 1; /* # of unused bits. */
- if (idxtbllen > 1)
- n1 += _ksba_ber_count_tl (TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
- n1 += n;
+ }
+ 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;
+ }
- /* 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;
+ n1 = 1; /* # of unused bits. */
+ if (idxtbllen > 1)
+ n1 += _ksba_ber_count_tl (TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
+ n1 += n;
- /* 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);
+ /* 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, parm[idxtbl[i]].value,
- parm[idxtbl[i]].valuelen);
+ 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;
+ /* 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,
@@ -1017,14 +1023,17 @@ _ksba_keyinfo_from_sexp (ksba_const_sexp_t sexp,
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;
+ if (!mode)
+ {
+ 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 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);
@@ -1058,9 +1067,12 @@ _ksba_keyinfo_from_sexp (ksba_const_sexp_t sexp,
goto leave;
/* Append the pre-constructed bit string. */
- err = ksba_writer_write (writer, bitstr_value, bitstr_len);
- if (err)
- goto leave;
+ if (!mode)
+ {
+ 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);
@@ -1074,6 +1086,15 @@ _ksba_keyinfo_from_sexp (ksba_const_sexp_t sexp,
return err;
}
+/* 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)
+{
+ return cryptval_from_sexp (0, sexp, r_der, r_derlen);
+}
+
/* Take a sig-val s-expression and convert it into a DER encoded
algorithmInfo. Unfortunately this function clones a lot of code
@@ -1082,284 +1103,7 @@ gpg_error_t
_ksba_algoinfo_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;
- 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;
-
- 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 == 7 && !memcmp (s, "sig-val", 7))
- s += 7;
- else if (n == 10 && !memcmp (s, "public-key", 10))
- s += 10;
- else
- return gpg_error (GPG_ERR_UNKNOWN_SEXP);
-
- 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, 1);
- 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 = ""; break;
- case PKALGO_DSA: parmdesc = "" ; algoparmdesc = "pqg"; break;
- case PKALGO_ECC: parmdesc = "C"; 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;
-
- /* Create the sequence of the algorithm identifier. */
-
- /* 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;
- }
-
- /* 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 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);
- }
-
- /* Write the sequence. */
- err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
- if (err)
- goto leave;
-
- /* Write 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;
-
- /* Write the parameters. */
- if (algoparmseq_len)
- {
- err = ksba_writer_write (writer, algoparmseq_value, algoparmseq_len);
- }
- else if (pkalgo == PKALGO_ECC)
- {
- /* We only support the namedCuve choice for ECC parameters. */
- 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;
-
- /* 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 (curve_oid);
- return err;
+ return cryptval_from_sexp (1, sexp, r_der, r_derlen);
}
--
1.8.5.2
More information about the Gnupg-devel
mailing list