Esempio n. 1
0
int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len) {
  CBB cbb;

  /* First, do a quick walk to find any indefinite-length elements. Most of the
   * time we hope that there aren't any and thus we can quickly return. */
  char conversion_needed;
  if (!cbs_find_ber(in, &conversion_needed, 0)) {
    return 0;
  }

  if (!conversion_needed) {
    *out = NULL;
    *out_len = 0;
    return 1;
  }

  if (!CBB_init(&cbb, CBS_len(in)) ||
      !cbs_convert_ber(in, &cbb, 0, 0, 0) ||
      !CBB_finish(&cbb, out, out_len)) {
    CBB_cleanup(&cbb);
    return 0;
  }

  return 1;
}
Esempio n. 2
0
/* cbs_find_ber walks an ASN.1 structure in |orig_in| and sets |*ber_found|
 * depending on whether an indefinite length element was found. The value of
 * |in| is not changed. It returns one on success (i.e. |*ber_found| was set)
 * and zero on error. */
static int cbs_find_ber(CBS *orig_in, char *ber_found, unsigned depth) {
  CBS in;

  if (depth > kMaxDepth) {
    return 0;
  }

  CBS_init(&in, CBS_data(orig_in), CBS_len(orig_in));
  *ber_found = 0;

  while (CBS_len(&in) > 0) {
    CBS contents;
    unsigned tag;
    size_t header_len;

    if (!CBS_get_any_ber_asn1_element(&in, &contents, &tag, &header_len)) {
      return 0;
    }
    if (CBS_len(&contents) == header_len &&
        header_len > 0 &&
        CBS_data(&contents)[header_len-1] == 0x80) {
      *ber_found = 1;
      return 1;
    }
    if (tag & CBS_ASN1_CONSTRUCTED) {
      if (!CBS_skip(&contents, header_len) ||
          !cbs_find_ber(&contents, ber_found, depth + 1)) {
        return 0;
      }
    }
  }

  return 1;
}
Esempio n. 3
0
/* cbs_find_ber walks an ASN.1 structure in |orig_in| and sets |*ber_found|
 * depending on whether an indefinite length element or constructed string was
 * found. The value of |orig_in| is not changed. It returns one on success (i.e.
 * |*ber_found| was set) and zero on error. */
static int cbs_find_ber(const CBS *orig_in, char *ber_found, unsigned depth) {
  CBS in;

  if (depth > kMaxDepth) {
    return 0;
  }

  CBS_init(&in, CBS_data(orig_in), CBS_len(orig_in));
  *ber_found = 0;

  while (CBS_len(&in) > 0) {
    CBS contents;
    unsigned tag;
    size_t header_len;

    if (!CBS_get_any_ber_asn1_element(&in, &contents, &tag, &header_len)) {
      return 0;
    }
    if (CBS_len(&contents) == header_len &&
        header_len > 0 &&
        CBS_data(&contents)[header_len-1] == 0x80) {
      /* Found an indefinite-length element. */
      *ber_found = 1;
      return 1;
    }
    if (tag & CBS_ASN1_CONSTRUCTED) {
      if (is_string_type(tag)) {
        /* Constructed strings are only legal in BER and require conversion. */
        *ber_found = 1;
        return 1;
      }
      if (!CBS_skip(&contents, header_len) ||
          !cbs_find_ber(&contents, ber_found, depth + 1)) {
        return 0;
      }
    }
  }

  return 1;
}