Exemplo n.º 1
0
static int do_ber_convert(const char *name,
                          const uint8_t *der_expected, size_t der_len,
                          const uint8_t *ber, size_t ber_len) {
  CBS in;
  uint8_t *out;
  size_t out_len;

  CBS_init(&in, ber, ber_len);
  if (!CBS_asn1_ber_to_der(&in, &out, &out_len)) {
    fprintf(stderr, "%s: CBS_asn1_ber_to_der failed.\n", name);
    return 0;
  }

  if (out == NULL) {
    if (ber_len != der_len ||
        memcmp(der_expected, ber, ber_len) != 0) {
      fprintf(stderr, "%s: incorrect unconverted result.\n", name);
      return 0;
    }

    return 1;
  }

  if (out_len != der_len ||
      memcmp(out, der_expected, der_len) != 0) {
    fprintf(stderr, "%s: incorrect converted result.\n", name);
    return 0;
  }

  free(out);
  return 1;
}
Exemplo n.º 2
0
/* pkcs7_parse_header reads the non-certificate/non-CRL prefix of a PKCS#7
 * SignedData blob from |cbs| and sets |*out| to point to the rest of the
 * input. If the input is in BER format, then |*der_bytes| will be set to a
 * pointer that needs to be freed by the caller once they have finished
 * processing |*out| (which will be pointing into |*der_bytes|).
 *
 * It returns one on success or zero on error. On error, |*der_bytes| is
 * NULL. */
static int pkcs7_parse_header(uint8_t **der_bytes, CBS *out, CBS *cbs) {
  size_t der_len;
  CBS in, content_info, content_type, wrapped_signed_data, signed_data;
  uint64_t version;

  /* The input may be in BER format. */
  *der_bytes = NULL;
  if (!CBS_asn1_ber_to_der(cbs, der_bytes, &der_len)) {
    return 0;
  }
  if (*der_bytes != NULL) {
    CBS_init(&in, *der_bytes, der_len);
  } else {
    CBS_init(&in, CBS_data(cbs), CBS_len(cbs));
  }

  /* See https://tools.ietf.org/html/rfc2315#section-7 */
  if (!CBS_get_asn1(&in, &content_info, CBS_ASN1_SEQUENCE) ||
      !CBS_get_asn1(&content_info, &content_type, CBS_ASN1_OBJECT)) {
    goto err;
  }

  if (OBJ_cbs2nid(&content_type) != NID_pkcs7_signed) {
    OPENSSL_PUT_ERROR(X509, pkcs7_parse_header,
                      X509_R_NOT_PKCS7_SIGNED_DATA);
    goto err;
  }

  /* See https://tools.ietf.org/html/rfc2315#section-9.1 */
  if (!CBS_get_asn1(&content_info, &wrapped_signed_data,
                    CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
      !CBS_get_asn1(&wrapped_signed_data, &signed_data, CBS_ASN1_SEQUENCE) ||
      !CBS_get_asn1_uint64(&signed_data, &version) ||
      !CBS_get_asn1(&signed_data, NULL /* digests */, CBS_ASN1_SET) ||
      !CBS_get_asn1(&signed_data, NULL /* content */, CBS_ASN1_SEQUENCE)) {
    goto err;
  }

  if (version < 1) {
    OPENSSL_PUT_ERROR(X509, pkcs7_parse_header,
                      X509_R_BAD_PKCS7_VERSION);
    goto err;
  }

  CBS_init(out, CBS_data(&signed_data), CBS_len(&signed_data));
  return 1;

err:
  if (*der_bytes) {
    OPENSSL_free(*der_bytes);
    *der_bytes = NULL;
  }

  return 0;
}
Exemplo n.º 3
0
/* PKCS12_handle_content_infos parses a series of PKCS#7 ContentInfos in a
 * SEQUENCE. */
static int PKCS12_handle_content_infos(CBS *content_infos,
                                       unsigned depth,
                                       struct pkcs12_context *ctx) {
  uint8_t *der_bytes = NULL;
  size_t der_len;
  CBS in;
  int ret = 0;

  /* Generally we only expect depths 0 (the top level, with a
   * pkcs7-encryptedData and a pkcs7-data) and depth 1 (the various PKCS#12
   * bags). */
  if (depth > 3) {
    OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_infos,
                      PKCS8_R_PKCS12_TOO_DEEPLY_NESTED);
    return 0;
  }

  /* Although a BER->DER conversion is done at the beginning of |PKCS12_parse|,
   * the ASN.1 data gets wrapped in OCTETSTRINGs and/or encrypted and the
   * conversion cannot see through those wrappings. So each time we step
   * through one we need to convert to DER again. */
  if (!CBS_asn1_ber_to_der(content_infos, &der_bytes, &der_len)) {
    return 0;
  }

  if (der_bytes != NULL) {
    CBS_init(&in, der_bytes, der_len);
  } else {
    CBS_init(&in, CBS_data(content_infos), CBS_len(content_infos));
  }

  if (!CBS_get_asn1(&in, &in, CBS_ASN1_SEQUENCE)) {
    OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_infos,
                      PKCS8_R_BAD_PKCS12_DATA);
    goto err;
  }

  while (CBS_len(&in) > 0) {
    CBS content_info;
    if (!CBS_get_asn1(&in, &content_info, CBS_ASN1_SEQUENCE)) {
      OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_infos,
                        PKCS8_R_BAD_PKCS12_DATA);
      goto err;
    }

    if (!PKCS12_handle_content_info(&content_info, depth + 1, ctx)) {
      goto err;
    }
  }

  /* NSS includes additional data after the SEQUENCE, but it's an (unwrapped)
   * copy of the same encrypted private key (with the same IV and
   * ciphertext)! */

  ret = 1;

err:
  if (der_bytes != NULL) {
    OPENSSL_free(der_bytes);
  }
  return ret;
}