/* Take the OID at NODE and return it in string format */ char * _ksba_oid_node_to_str (const unsigned char *image, AsnNode node) { if (!node || node->type != TYPE_OBJECT_ID || node->off == -1) return NULL; return ksba_oid_to_str (image+node->off + node->nhdr, node->len); }
int main (int argc, char **argv) { gpg_error_t err; if (argc) { argc--; argv++; } if (!argc) { test_oid_to_str (); } else if (!strcmp (*argv, "--from-str")) { unsigned char *buffer; size_t n, buflen; for (argv++,argc-- ; argc; argc--, argv++) { err = ksba_oid_from_str (*argv, &buffer, &buflen); if (err) { fprintf (stderr, "can't convert `%s': %s\n", *argv, gpg_strerror (err)); return 1; } printf ("%s ->", *argv); for (n=0; n < buflen; n++) printf (" %02X", buffer[n]); putchar ('\n'); free (buffer); } } else if (!strcmp (*argv, "--to-str")) { char *buffer; size_t buflen; char *result; argv++;argc--; buffer = read_into_buffer (stdin, &buflen); result = ksba_oid_to_str (buffer, buflen); free (buffer); printf ("%s\n", result? result:"[malloc failed]"); free (result); } else { fputs ("usage: "PGM" [--from-str|--to-str]\n", stderr); return 1; } return 0; }
gpg_error_t _ksba_keyinfo_to_sexp (const unsigned char *der, size_t derlen, ksba_sexp_t *r_string) { gpg_error_t err; int c; size_t nread, off, len, parm_off, parm_len; int parm_type; char *parm_oid = NULL; int algoidx; int is_bitstr; const unsigned char *parmder = NULL; size_t parmderlen = 0; const unsigned char *ctrl; const char *elem; struct stringbuf sb; *r_string = NULL; /* check the outer sequence */ if (!derlen) return gpg_error (GPG_ERR_INV_KEYINFO); c = *der++; derlen--; if ( c != 0x30 ) return gpg_error (GPG_ERR_UNEXPECTED_TAG); /* not a SEQUENCE */ TLV_LENGTH(der); /* and now the inner part */ err = get_algorithm (1, der, derlen, &nread, &off, &len, &is_bitstr, &parm_off, &parm_len, &parm_type); if (err) return err; /* look into our table of supported algorithms */ for (algoidx=0; pk_algo_table[algoidx].oid; algoidx++) { if ( len == pk_algo_table[algoidx].oidlen && !memcmp (der+off, pk_algo_table[algoidx].oid, len)) break; } if (!pk_algo_table[algoidx].oid) return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM); if (!pk_algo_table[algoidx].supported) return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); if (parm_off && parm_len && parm_type == TYPE_OBJECT_ID) parm_oid = ksba_oid_to_str (der+parm_off, parm_len); else if (parm_off && parm_len) { parmder = der + parm_off; parmderlen = parm_len; } der += nread; derlen -= nread; if (is_bitstr) { /* Funny: X.509 defines the signature value as a bit string but CMS as an octet string - for ease of implementation we always allow both */ if (!derlen) { xfree (parm_oid); return gpg_error (GPG_ERR_INV_KEYINFO); } c = *der++; derlen--; if (c) fprintf (stderr, "warning: number of unused bits is not zero\n"); } /* fixme: we should calculate the initial length form the size of the sequence, so that we don't need a realloc later */ init_stringbuf (&sb, 100); put_stringbuf (&sb, "(10:public-key("); /* fixme: we can also use the oidstring here and prefix it with "oid." - this way we can pass more information into Libgcrypt or whatever library is used */ put_stringbuf_sexp (&sb, pk_algo_table[algoidx].algo_string); /* Insert the curve name for ECC. */ if (pk_algo_table[algoidx].pkalgo == PKALGO_ECC && parm_oid) { put_stringbuf (&sb, "("); put_stringbuf_sexp (&sb, "curve"); put_stringbuf_sexp (&sb, parm_oid); put_stringbuf (&sb, ")"); } /* If parameters are given and we have a description for them, parse them. */ if (parmder && parmderlen && pk_algo_table[algoidx].parmelem_string && pk_algo_table[algoidx].parmctrl_string) { elem = pk_algo_table[algoidx].parmelem_string; ctrl = pk_algo_table[algoidx].parmctrl_string; for (; *elem; ctrl++, elem++) { int is_int; if ( (*ctrl & 0x80) && !elem[1] ) { /* Hack to allow reading a raw value. */ is_int = 1; len = parmderlen; } else { if (!parmderlen) { xfree (parm_oid); return gpg_error (GPG_ERR_INV_KEYINFO); } c = *parmder++; parmderlen--; if ( c != *ctrl ) { xfree (parm_oid); return gpg_error (GPG_ERR_UNEXPECTED_TAG); } is_int = c == 0x02; TLV_LENGTH (parmder); } if (is_int && *elem != '-') /* Take this integer. */ { char tmp[2]; put_stringbuf (&sb, "("); tmp[0] = *elem; tmp[1] = 0; put_stringbuf_sexp (&sb, tmp); put_stringbuf_mem_sexp (&sb, parmder, len); parmder += len; parmderlen -= len; put_stringbuf (&sb, ")"); } } } /* FIXME: We don't release the stringbuf in case of error better let the macro jump to a label */ elem = pk_algo_table[algoidx].elem_string; ctrl = pk_algo_table[algoidx].ctrl_string; for (; *elem; ctrl++, elem++) { int is_int; if ( (*ctrl & 0x80) && !elem[1] ) { /* Hack to allow reading a raw value. */ is_int = 1; len = derlen; } else { if (!derlen) { xfree (parm_oid); return gpg_error (GPG_ERR_INV_KEYINFO); } c = *der++; derlen--; if ( c != *ctrl ) { xfree (parm_oid); return gpg_error (GPG_ERR_UNEXPECTED_TAG); } is_int = c == 0x02; TLV_LENGTH (der); } if (is_int && *elem != '-') /* Take this integer. */ { char tmp[2]; put_stringbuf (&sb, "("); tmp[0] = *elem; tmp[1] = 0; put_stringbuf_sexp (&sb, tmp); put_stringbuf_mem_sexp (&sb, der, len); der += len; derlen -= len; put_stringbuf (&sb, ")"); } } put_stringbuf (&sb, "))"); xfree (parm_oid); *r_string = get_stringbuf (&sb); if (!*r_string) return gpg_error (GPG_ERR_ENOMEM); return 0; }
gpg_error_t _ksba_parse_algorithm_identifier2 (const unsigned char *der, size_t derlen, size_t *r_nread, char **r_oid, char **r_parm, size_t *r_parmlen) { gpg_error_t err; int is_bitstr; size_t nread, off, len, off2, len2; int parm_type; /* fixme: get_algorithm might return the error invalid keyinfo - this should be invalid algorithm identifier */ *r_oid = NULL; *r_nread = 0; off2 = len2 = 0; err = get_algorithm (0, der, derlen, &nread, &off, &len, &is_bitstr, &off2, &len2, &parm_type); if (err) return err; *r_nread = nread; *r_oid = ksba_oid_to_str (der+off, len); if (!*r_oid) return gpg_error (GPG_ERR_ENOMEM); /* Special hack for ecdsaWithSpecified. We replace the returned OID by the one in the parameter. */ if (off2 && len2 && parm_type == TYPE_SEQUENCE && !strcmp (*r_oid, "1.2.840.10045.4.3")) { xfree (*r_oid); *r_oid = NULL; err = get_algorithm (0, der+off2, len2, &nread, &off, &len, &is_bitstr, NULL, NULL, NULL); if (err) { *r_nread = 0; return err; } *r_oid = ksba_oid_to_str (der+off2+off, len); if (!*r_oid) { *r_nread = 0; return gpg_error (GPG_ERR_ENOMEM); } off2 = len2 = 0; /* So that R_PARM is set to NULL. */ } if (r_parm && r_parmlen) { if (off2 && len2) { *r_parm = xtrymalloc (len2); if (!*r_parm) { xfree (*r_oid); *r_oid = NULL; return gpg_error (GPG_ERR_ENOMEM); } memcpy (*r_parm, der+off2, len2); *r_parmlen = len2; } else { *r_parm = NULL; *r_parmlen = 0; } } return 0; }
static void test_oid_to_str (void) { struct { unsigned int binlen; unsigned char *bin; char *str; } tests[] = { { 7, "\x02\x82\x06\x01\x0A\x0C\x00", "0.2.262.1.10.12.0" }, { 7, "\x02\x82\x06\x01\x0A\x0C\x01", "0.2.262.1.10.12.1" }, { 7, "\x2A\x86\x48\xCE\x38\x04\x01", "1.2.840.10040.4.1" }, { 7, "\x2A\x86\x48\xCE\x38\x04\x03", "1.2.840.10040.4.3" }, { 10, "\x2B\x06\x01\x04\x01\xDA\x47\x02\x01\x01", "1.3.6.1.4.1.11591.2.1.1" }, { 3, "\x55\x1D\x0E", "2.5.29.14" }, { 9, "\x80\x02\x70\x50\x25\x46\xfd\x0c\xc0", BADOID }, { 1, "\x80", BADOID }, { 2, "\x81\x00", "2.48" }, { 2, "\x81\x01", "2.49" }, { 2, "\x81\x7f", "2.175" }, { 2, "\x81\x80", /* legal encoding? */ "2.48" }, { 2, "\x81\x81\x01", /* legal encoding? */ "2.49" }, { 0, "", "" }, { 0, NULL, NULL } }; int tidx; char *str; for (tidx=0; tests[tidx].bin; tidx++) { str = ksba_oid_to_str (tests[tidx].bin, tests[tidx].binlen); if (!str) { perror ("ksba_oid_to_str failed"); exit (1); } if (strcmp (tests[tidx].str, str)) { fprintf (stderr, "ksba_oid_to_str test %d failed\n", tidx); fprintf (stderr, " got=%s\n", str); fprintf (stderr, " want=%s\n", tests[tidx].str); exit (1); } } }