Exemplo n.º 1
0
static int test_EVP_DigestVerifyInitFromAlgorithm(void) {
  int ret = 0;
  CBS cert, cert_body, tbs_cert, algorithm, signature;
  uint8_t padding;
  X509_ALGOR *algor = NULL;
  const uint8_t *derp;
  EVP_PKEY *pkey = NULL;
  EVP_MD_CTX md_ctx;

  EVP_MD_CTX_init(&md_ctx);

  CBS_init(&cert, kExamplePSSCert, sizeof(kExamplePSSCert));
  if (!CBS_get_asn1(&cert, &cert_body, CBS_ASN1_SEQUENCE) ||
      CBS_len(&cert) != 0 ||
      !CBS_get_any_asn1_element(&cert_body, &tbs_cert, NULL, NULL) ||
      !CBS_get_asn1_element(&cert_body, &algorithm, CBS_ASN1_SEQUENCE) ||
      !CBS_get_asn1(&cert_body, &signature, CBS_ASN1_BITSTRING) ||
      CBS_len(&cert_body) != 0) {
    fprintf(stderr, "Failed to parse certificate\n");
    goto out;
  }

  /* Signatures are BIT STRINGs, but they have are multiple of 8 bytes, so the
     leading phase byte is just a zero. */
  if (!CBS_get_u8(&signature, &padding) || padding != 0) {
    fprintf(stderr, "Invalid signature padding\n");
    goto out;
  }

  derp = CBS_data(&algorithm);
  if (!d2i_X509_ALGOR(&algor, &derp, CBS_len(&algorithm)) ||
      derp != CBS_data(&algorithm) + CBS_len(&algorithm)) {
    fprintf(stderr, "Failed to parse algorithm\n");
  }

  pkey = load_example_rsa_key();
  if (pkey == NULL ||
      !EVP_DigestVerifyInitFromAlgorithm(&md_ctx, algor, pkey) ||
      !EVP_DigestVerifyUpdate(&md_ctx, CBS_data(&tbs_cert),
                              CBS_len(&tbs_cert)) ||
      !EVP_DigestVerifyFinal(&md_ctx, CBS_data(&signature),
                             CBS_len(&signature))) {
    goto out;
  }
  ret = 1;

out:
  if (!ret) {
    BIO_print_errors_fp(stderr);
  }

  EVP_MD_CTX_cleanup(&md_ctx);
  if (pkey) {
    EVP_PKEY_free(pkey);
  }

  return ret;
}
Exemplo n.º 2
0
DSA *DSA_parse_private_key(CBS *cbs) {
  DSA *ret = DSA_new();
  if (ret == NULL) {
    return NULL;
  }

  CBS child;
  uint64_t version;
  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
      !CBS_get_asn1_uint64(&child, &version)) {
    OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
    goto err;
  }

  if (version != 0) {
    OPENSSL_PUT_ERROR(DSA, DSA_R_BAD_VERSION);
    goto err;
  }

  if (!parse_integer(&child, &ret->p) ||
      !parse_integer(&child, &ret->q) ||
      !parse_integer(&child, &ret->g) ||
      !parse_integer(&child, &ret->pub_key) ||
      !parse_integer(&child, &ret->priv_key) ||
      CBS_len(&child) != 0) {
    OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
    goto err;
  }
  return ret;

err:
  DSA_free(ret);
  return NULL;
}
Exemplo n.º 3
0
int CBS_get_asn1_implicit_string(CBS *in, CBS *out, uint8_t **out_storage,
                                 unsigned outer_tag, unsigned inner_tag) {
  assert(!(outer_tag & CBS_ASN1_CONSTRUCTED));
  assert(!(inner_tag & CBS_ASN1_CONSTRUCTED));
  assert(is_string_type(inner_tag));

  if (CBS_peek_asn1_tag(in, outer_tag)) {
    /* Normal implicitly-tagged string. */
    *out_storage = NULL;
    return CBS_get_asn1(in, out, outer_tag);
  }

  /* Otherwise, try to parse an implicitly-tagged constructed string.
   * |CBS_asn1_ber_to_der| is assumed to have run, so only allow one level deep
   * of nesting. */
  CBB result;
  CBS child;
  if (!CBB_init(&result, CBS_len(in)) ||
      !CBS_get_asn1(in, &child, outer_tag | CBS_ASN1_CONSTRUCTED)) {
    goto err;
  }

  while (CBS_len(&child) > 0) {
    CBS chunk;
    if (!CBS_get_asn1(&child, &chunk, inner_tag) ||
        !CBB_add_bytes(&result, CBS_data(&chunk), CBS_len(&chunk))) {
      goto err;
    }
  }

  uint8_t *data;
  size_t len;
  if (!CBB_finish(&result, &data, &len)) {
    goto err;
  }

  CBS_init(out, data, len);
  *out_storage = data;
  return 1;

err:
  CBB_cleanup(&result);
  return 0;
}
Exemplo n.º 4
0
EVP_PKEY *EVP_parse_public_key(CBS *cbs) {
  // Parse the SubjectPublicKeyInfo.
  CBS spki, algorithm, key;
  int type;
  uint8_t padding;
  if (!CBS_get_asn1(cbs, &spki, CBS_ASN1_SEQUENCE) ||
      !CBS_get_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
      !parse_key_type(&algorithm, &type) ||
      !CBS_get_asn1(&spki, &key, CBS_ASN1_BITSTRING) ||
      CBS_len(&spki) != 0 ||
      // Every key type defined encodes the key as a byte string with the same
      // conversion to BIT STRING.
      !CBS_get_u8(&key, &padding) ||
      padding != 0) {
    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
    return NULL;
  }

  // Set up an |EVP_PKEY| of the appropriate type.
  EVP_PKEY *ret = EVP_PKEY_new();
  if (ret == NULL ||
      !EVP_PKEY_set_type(ret, type)) {
    goto err;
  }

  // Call into the type-specific SPKI decoding function.
  if (ret->ameth->pub_decode == NULL) {
    OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
    goto err;
  }
  if (!ret->ameth->pub_decode(ret, &algorithm, &key)) {
    goto err;
  }

  return ret;

err:
  EVP_PKEY_free(ret);
  return NULL;
}
Exemplo n.º 5
0
EVP_PKEY *EVP_parse_private_key(CBS *cbs) {
  // Parse the PrivateKeyInfo.
  CBS pkcs8, algorithm, key;
  uint64_t version;
  int type;
  if (!CBS_get_asn1(cbs, &pkcs8, CBS_ASN1_SEQUENCE) ||
      !CBS_get_asn1_uint64(&pkcs8, &version) ||
      version != 0 ||
      !CBS_get_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
      !parse_key_type(&algorithm, &type) ||
      !CBS_get_asn1(&pkcs8, &key, CBS_ASN1_OCTETSTRING)) {
    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
    return NULL;
  }

  // A PrivateKeyInfo ends with a SET of Attributes which we ignore.

  // Set up an |EVP_PKEY| of the appropriate type.
  EVP_PKEY *ret = EVP_PKEY_new();
  if (ret == NULL ||
      !EVP_PKEY_set_type(ret, type)) {
    goto err;
  }

  // Call into the type-specific PrivateKeyInfo decoding function.
  if (ret->ameth->priv_decode == NULL) {
    OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
    goto err;
  }
  if (!ret->ameth->priv_decode(ret, &algorithm, &key)) {
    goto err;
  }

  return ret;

err:
  EVP_PKEY_free(ret);
  return NULL;
}
Exemplo n.º 6
0
RSA *RSA_parse_public_key(CBS *cbs) {
  RSA *ret = RSA_new();
  if (ret == NULL) {
    return NULL;
  }
  CBS child;
  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
      !parse_integer(&child, &ret->n) ||
      !parse_integer(&child, &ret->e) ||
      CBS_len(&child) != 0) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING);
    RSA_free(ret);
    return NULL;
  }
  return ret;
}
Exemplo n.º 7
0
DSA_SIG *DSA_SIG_parse(CBS *cbs) {
  DSA_SIG *ret = DSA_SIG_new();
  if (ret == NULL) {
    return NULL;
  }
  CBS child;
  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
      !parse_integer(&child, &ret->r) ||
      !parse_integer(&child, &ret->s) ||
      CBS_len(&child) != 0) {
    OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
    DSA_SIG_free(ret);
    return NULL;
  }
  return ret;
}
Exemplo n.º 8
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.º 9
0
ECDSA_SIG *ECDSA_SIG_parse(CBS *cbs) {
  ECDSA_SIG *ret = ECDSA_SIG_new();
  if (ret == NULL) {
    return NULL;
  }
  CBS child;
  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
      !BN_parse_asn1_unsigned(&child, ret->r) ||
      !BN_parse_asn1_unsigned(&child, ret->s) ||
      CBS_len(&child) != 0) {
    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE);
    ECDSA_SIG_free(ret);
    return NULL;
  }
  return ret;
}
Exemplo n.º 10
0
static int parse_key_type(CBS *cbs, int *out_type) {
  CBS oid;
  if (!CBS_get_asn1(cbs, &oid, CBS_ASN1_OBJECT)) {
    return 0;
  }

  for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(kASN1Methods); i++) {
    const EVP_PKEY_ASN1_METHOD *method = kASN1Methods[i];
    if (CBS_len(&oid) == method->oid_len &&
        OPENSSL_memcmp(CBS_data(&oid), method->oid, method->oid_len) == 0) {
      *out_type = method->pkey_id;
      return 1;
    }
  }

  return 0;
}
Exemplo n.º 11
0
DSA *DSA_parse_public_key(CBS *cbs) {
  DSA *ret = DSA_new();
  if (ret == NULL) {
    return NULL;
  }
  CBS child;
  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
      !parse_integer(&child, &ret->pub_key) ||
      !parse_integer(&child, &ret->p) ||
      !parse_integer(&child, &ret->q) ||
      !parse_integer(&child, &ret->g) ||
      CBS_len(&child) != 0) {
    OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
    DSA_free(ret);
    return NULL;
  }
  return ret;
}
Exemplo n.º 12
0
RSA *RSA_parse_private_key(CBS *cbs) {
  BN_CTX *ctx = NULL;
  RSA *ret = RSA_new();
  if (ret == NULL) {
    return NULL;
  }

  CBS child;
  uint64_t version;
  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
      !CBS_get_asn1_uint64(&child, &version)) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING);
    goto err;
  }

  if (version != kVersionTwoPrime) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_VERSION);
    goto err;
  }

  if (!parse_integer(&child, &ret->n) ||
      !parse_integer(&child, &ret->e) ||
      !parse_integer(&child, &ret->d) ||
      !parse_integer(&child, &ret->p) ||
      !parse_integer(&child, &ret->q) ||
      !parse_integer(&child, &ret->dmp1) ||
      !parse_integer(&child, &ret->dmq1) ||
      !parse_integer(&child, &ret->iqmp)) {
    goto err;
  }

  if (CBS_len(&child) != 0) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING);
    goto err;
  }

  BN_CTX_free(ctx);
  return ret;

err:
  BN_CTX_free(ctx);
  RSA_free(ret);
  return NULL;
}
Exemplo n.º 13
0
// num_elements parses one SEQUENCE from |in| and returns the number of elements
// in it. On parse error, it returns zero.
static size_t num_elements(const uint8_t *in, size_t in_len) {
  CBS cbs, sequence;
  CBS_init(&cbs, in, (size_t)in_len);

  if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE)) {
    return 0;
  }

  size_t count = 0;
  while (CBS_len(&sequence) > 0) {
    if (!CBS_get_any_asn1_element(&sequence, NULL, NULL, NULL)) {
      return 0;
    }

    count++;
  }

  return count;
}
Exemplo n.º 14
0
static int rsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
  // Per RFC 3447, A.1, the parameters have type NULL.
  CBS null;
  if (!CBS_get_asn1(params, &null, CBS_ASN1_NULL) ||
      CBS_len(&null) != 0 ||
      CBS_len(params) != 0) {
    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
    return 0;
  }

  RSA *rsa = RSA_parse_private_key(key);
  if (rsa == NULL || CBS_len(key) != 0) {
    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
    RSA_free(rsa);
    return 0;
  }

  EVP_PKEY_assign_RSA(out, rsa);
  return 1;
}
Exemplo n.º 15
0
/* rsa_parse_additional_prime parses a DER-encoded OtherPrimeInfo from |cbs| and
 * advances |cbs|. It returns a newly-allocated |RSA_additional_prime| on
 * success or NULL on error. The |r| and |mont| fields of the result are set to
 * NULL. */
static RSA_additional_prime *rsa_parse_additional_prime(CBS *cbs) {
  RSA_additional_prime *ret = OPENSSL_malloc(sizeof(RSA_additional_prime));
  if (ret == NULL) {
    OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
    return 0;
  }
  memset(ret, 0, sizeof(RSA_additional_prime));

  CBS child;
  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
      !parse_integer(&child, &ret->prime) ||
      !parse_integer(&child, &ret->exp) ||
      !parse_integer(&child, &ret->coeff) ||
      CBS_len(&child) != 0) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING);
    RSA_additional_prime_free(ret);
    return NULL;
  }

  return ret;
}
Exemplo n.º 16
0
static int rsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) {
  // See RFC 3279, section 2.3.1.

  // The parameters must be NULL.
  CBS null;
  if (!CBS_get_asn1(params, &null, CBS_ASN1_NULL) ||
      CBS_len(&null) != 0 ||
      CBS_len(params) != 0) {
    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
    return 0;
  }

  RSA *rsa = RSA_parse_public_key(key);
  if (rsa == NULL || CBS_len(key) != 0) {
    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
    RSA_free(rsa);
    return 0;
  }

  EVP_PKEY_assign_RSA(out, rsa);
  return 1;
}
Exemplo n.º 17
0
/* ssl_cert_skip_to_spki parses a DER-encoded, X.509 certificate from |in| and
 * positions |*out_tbs_cert| to cover the TBSCertificate, starting at the
 * subjectPublicKeyInfo. */
static int ssl_cert_skip_to_spki(const CBS *in, CBS *out_tbs_cert) {
  /* From RFC 5280, section 4.1
   *    Certificate  ::=  SEQUENCE  {
   *      tbsCertificate       TBSCertificate,
   *      signatureAlgorithm   AlgorithmIdentifier,
   *      signatureValue       BIT STRING  }

   * TBSCertificate  ::=  SEQUENCE  {
   *      version         [0]  EXPLICIT Version DEFAULT v1,
   *      serialNumber         CertificateSerialNumber,
   *      signature            AlgorithmIdentifier,
   *      issuer               Name,
   *      validity             Validity,
   *      subject              Name,
   *      subjectPublicKeyInfo SubjectPublicKeyInfo,
   *      ... } */
  CBS buf = *in;

  CBS toplevel;
  if (!CBS_get_asn1(&buf, &toplevel, CBS_ASN1_SEQUENCE) ||
      CBS_len(&buf) != 0 ||
      !CBS_get_asn1(&toplevel, out_tbs_cert, CBS_ASN1_SEQUENCE) ||
      /* version */
      !CBS_get_optional_asn1(
          out_tbs_cert, NULL, NULL,
          CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0) ||
      /* serialNumber */
      !CBS_get_asn1(out_tbs_cert, NULL, CBS_ASN1_INTEGER) ||
      /* signature algorithm */
      !CBS_get_asn1(out_tbs_cert, NULL, CBS_ASN1_SEQUENCE) ||
      /* issuer */
      !CBS_get_asn1(out_tbs_cert, NULL, CBS_ASN1_SEQUENCE) ||
      /* validity */
      !CBS_get_asn1(out_tbs_cert, NULL, CBS_ASN1_SEQUENCE) ||
      /* subject */
      !CBS_get_asn1(out_tbs_cert, NULL, CBS_ASN1_SEQUENCE)) {
    return 0;
  }

  return 1;
}
Exemplo n.º 18
0
int BN_cbs2unsigned(CBS *cbs, BIGNUM *ret) {
  CBS child;
  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_INTEGER) ||
      CBS_len(&child) == 0) {
    OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
    return 0;
  }

  if (CBS_data(&child)[0] & 0x80) {
    OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
    return 0;
  }

  /* INTEGERs must be minimal. */
  if (CBS_data(&child)[0] == 0x00 &&
      CBS_len(&child) > 1 &&
      !(CBS_data(&child)[1] & 0x80)) {
    OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
    return 0;
  }

  return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL;
}
Exemplo n.º 19
0
static RSA *parse_public_key(CBS *cbs, int buggy) {
  RSA *ret = RSA_new();
  if (ret == NULL) {
    return NULL;
  }
  CBS child;
  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
      !parse_integer_buggy(&child, &ret->n, buggy) ||
      !parse_integer(&child, &ret->e) ||
      CBS_len(&child) != 0) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING);
    RSA_free(ret);
    return NULL;
  }

  if (!BN_is_odd(ret->e) ||
      BN_num_bits(ret->e) < 2) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_RSA_PARAMETERS);
    RSA_free(ret);
    return NULL;
  }

  return ret;
}
Exemplo n.º 20
0
int ssl_cert_check_digital_signature_key_usage(const CBS *in) {
  CBS buf = *in;

  CBS tbs_cert, outer_extensions;
  int has_extensions;
  if (!ssl_cert_skip_to_spki(&buf, &tbs_cert) ||
      /* subjectPublicKeyInfo */
      !CBS_get_asn1(&tbs_cert, NULL, CBS_ASN1_SEQUENCE) ||
      /* issuerUniqueID */
      !CBS_get_optional_asn1(
          &tbs_cert, NULL, NULL,
          CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1) ||
      /* subjectUniqueID */
      !CBS_get_optional_asn1(
          &tbs_cert, NULL, NULL,
          CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 2) ||
      !CBS_get_optional_asn1(
          &tbs_cert, &outer_extensions, &has_extensions,
          CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3)) {
    goto parse_err;
  }

  if (!has_extensions) {
    return 1;
  }

  CBS extensions;
  if (!CBS_get_asn1(&outer_extensions, &extensions, CBS_ASN1_SEQUENCE)) {
    goto parse_err;
  }

  while (CBS_len(&extensions) > 0) {
    CBS extension, oid, contents;
    if (!CBS_get_asn1(&extensions, &extension, CBS_ASN1_SEQUENCE) ||
        !CBS_get_asn1(&extension, &oid, CBS_ASN1_OBJECT) ||
        (CBS_peek_asn1_tag(&extension, CBS_ASN1_BOOLEAN) &&
         !CBS_get_asn1(&extension, NULL, CBS_ASN1_BOOLEAN)) ||
        !CBS_get_asn1(&extension, &contents, CBS_ASN1_OCTETSTRING) ||
        CBS_len(&extension) != 0) {
      goto parse_err;
    }

    static const uint8_t kKeyUsageOID[3] = {0x55, 0x1d, 0x0f};
    if (CBS_len(&oid) != sizeof(kKeyUsageOID) ||
        OPENSSL_memcmp(CBS_data(&oid), kKeyUsageOID, sizeof(kKeyUsageOID)) !=
            0) {
      continue;
    }

    CBS bit_string;
    if (!CBS_get_asn1(&contents, &bit_string, CBS_ASN1_BITSTRING) ||
        CBS_len(&contents) != 0) {
      goto parse_err;
    }

    /* This is the KeyUsage extension. See
     * https://tools.ietf.org/html/rfc5280#section-4.2.1.3 */
    if (!CBS_is_valid_asn1_bitstring(&bit_string)) {
      goto parse_err;
    }

    if (!CBS_asn1_bitstring_has_bit(&bit_string, 0)) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_ECC_CERT_NOT_FOR_SIGNING);
      return 0;
    }

    return 1;
  }

  /* No KeyUsage extension found. */
  return 1;

parse_err:
  OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_PARSE_LEAF_CERT);
  return 0;
}
Exemplo n.º 21
0
/* PKCS12_handle_content_info parses a single PKCS#7 ContentInfo element in a
 * PKCS#12 structure. */
static int PKCS12_handle_content_info(CBS *content_info, unsigned depth,
                                      struct pkcs12_context *ctx) {
  CBS content_type, wrapped_contents, contents, content_infos;
  int nid, ret = 0;

  if (!CBS_get_asn1(content_info, &content_type, CBS_ASN1_OBJECT) ||
      !CBS_get_asn1(content_info, &wrapped_contents,
                        CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
    OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
    goto err;
  }

  nid = OBJ_cbs2nid(&content_type);
  if (nid == NID_pkcs7_encrypted) {
    /* See https://tools.ietf.org/html/rfc2315#section-13.
     *
     * PKCS#7 encrypted data inside a PKCS#12 structure is generally an
     * encrypted certificate bag and it's generally encrypted with 40-bit
     * RC2-CBC. */
    CBS version_bytes, eci, contents_type, ai, encrypted_contents;
    X509_ALGOR *algor = NULL;
    const uint8_t *inp;
    uint8_t *out;
    size_t out_len;

    if (!CBS_get_asn1(&wrapped_contents, &contents, CBS_ASN1_SEQUENCE) ||
        !CBS_get_asn1(&contents, &version_bytes, CBS_ASN1_INTEGER) ||
        /* EncryptedContentInfo, see
         * https://tools.ietf.org/html/rfc2315#section-10.1 */
        !CBS_get_asn1(&contents, &eci, CBS_ASN1_SEQUENCE) ||
        !CBS_get_asn1(&eci, &contents_type, CBS_ASN1_OBJECT) ||
        /* AlgorithmIdentifier, see
         * https://tools.ietf.org/html/rfc5280#section-4.1.1.2 */
        !CBS_get_asn1_element(&eci, &ai, CBS_ASN1_SEQUENCE) ||
        !CBS_get_asn1(&eci, &encrypted_contents,
                      CBS_ASN1_CONTEXT_SPECIFIC | 0)) {
      OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
                        PKCS8_R_BAD_PKCS12_DATA);
      goto err;
    }

    if (OBJ_cbs2nid(&contents_type) != NID_pkcs7_data) {
      OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
                        PKCS8_R_BAD_PKCS12_DATA);
      goto err;
    }

    inp = CBS_data(&ai);
    algor = d2i_X509_ALGOR(NULL, &inp, CBS_len(&ai));
    if (algor == NULL) {
      goto err;
    }
    if (inp != CBS_data(&ai) + CBS_len(&ai)) {
      X509_ALGOR_free(algor);
      OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
                        PKCS8_R_BAD_PKCS12_DATA);
      goto err;
    }

    if (!pbe_crypt(algor, ctx->password, ctx->password_len,
                   CBS_data(&encrypted_contents), CBS_len(&encrypted_contents),
                   &out, &out_len, 0 /* decrypt */)) {
      X509_ALGOR_free(algor);
      goto err;
    }
    X509_ALGOR_free(algor);

    CBS_init(&content_infos, out, out_len);
    ret = PKCS12_handle_content_infos(&content_infos, depth + 1, ctx);
    OPENSSL_free(out);
  } else if (nid == NID_pkcs7_data) {
    CBS octet_string_contents;

    if (!CBS_get_asn1(&wrapped_contents, &octet_string_contents,
                          CBS_ASN1_OCTETSTRING)) {
      OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
                        PKCS8_R_BAD_PKCS12_DATA);
      goto err;
    }

    ret = PKCS12_handle_content_infos(&octet_string_contents, depth + 1, ctx);
  } else if (nid == NID_pkcs8ShroudedKeyBag) {
    /* See ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf, section
     * 4.2.2. */
    const uint8_t *inp = CBS_data(&wrapped_contents);
    PKCS8_PRIV_KEY_INFO *pki = NULL;
    X509_SIG *encrypted = NULL;

    if (*ctx->out_key) {
      OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
                        PKCS8_R_MULTIPLE_PRIVATE_KEYS_IN_PKCS12);
      goto err;
    }

    /* encrypted isn't actually an X.509 signature, but it has the same
     * structure as one and so |X509_SIG| is reused to store it. */
    encrypted = d2i_X509_SIG(NULL, &inp, CBS_len(&wrapped_contents));
    if (encrypted == NULL) {
      OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
                        PKCS8_R_BAD_PKCS12_DATA);
      goto err;
    }
    if (inp != CBS_data(&wrapped_contents) + CBS_len(&wrapped_contents)) {
      OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
                        PKCS8_R_BAD_PKCS12_DATA);
      X509_SIG_free(encrypted);
      goto err;
    }

    pki = PKCS8_decrypt_pbe(encrypted, ctx->password, ctx->password_len);
    X509_SIG_free(encrypted);
    if (pki == NULL) {
      goto err;
    }

    *ctx->out_key = EVP_PKCS82PKEY(pki);
    PKCS8_PRIV_KEY_INFO_free(pki);

    if (ctx->out_key == NULL) {
      goto err;
    }
    ret = 1;
  } else if (nid == NID_certBag) {
    CBS cert_bag, cert_type, wrapped_cert, cert;

    if (!CBS_get_asn1(&wrapped_contents, &cert_bag, CBS_ASN1_SEQUENCE) ||
        !CBS_get_asn1(&cert_bag, &cert_type, CBS_ASN1_OBJECT) ||
        !CBS_get_asn1(&cert_bag, &wrapped_cert,
                      CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
        !CBS_get_asn1(&wrapped_cert, &cert, CBS_ASN1_OCTETSTRING)) {
      OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
                        PKCS8_R_BAD_PKCS12_DATA);
      goto err;
    }

    if (OBJ_cbs2nid(&cert_type) == NID_x509Certificate) {
      const uint8_t *inp = CBS_data(&cert);
      X509 *x509 = d2i_X509(NULL, &inp, CBS_len(&cert));
      if (!x509) {
        OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
                          PKCS8_R_BAD_PKCS12_DATA);
        goto err;
      }
      if (inp != CBS_data(&cert) + CBS_len(&cert)) {
        OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
                          PKCS8_R_BAD_PKCS12_DATA);
        X509_free(x509);
        goto err;
      }

      if (0 == sk_X509_push(ctx->out_certs, x509)) {
        X509_free(x509);
        goto err;
      }
    }
    ret = 1;
  } else {
    /* Unknown element type - ignore it. */
    ret = 1;
  }

err:
  return ret;
}
Exemplo n.º 22
0
RSA *RSA_parse_private_key(CBS *cbs) {
  BN_CTX *ctx = NULL;
  BIGNUM *product_of_primes_so_far = NULL;
  RSA *ret = RSA_new();
  if (ret == NULL) {
    return NULL;
  }

  CBS child;
  uint64_t version;
  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
      !CBS_get_asn1_uint64(&child, &version)) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING);
    goto err;
  }

  if (version != kVersionTwoPrime && version != kVersionMulti) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_VERSION);
    goto err;
  }

  if (!parse_integer(&child, &ret->n) ||
      !parse_integer(&child, &ret->e) ||
      !parse_integer(&child, &ret->d) ||
      !parse_integer(&child, &ret->p) ||
      !parse_integer(&child, &ret->q) ||
      !parse_integer(&child, &ret->dmp1) ||
      !parse_integer(&child, &ret->dmq1) ||
      !parse_integer(&child, &ret->iqmp)) {
    goto err;
  }

  if (version == kVersionMulti) {
    /* Although otherPrimeInfos is written as OPTIONAL in RFC 3447, it later
     * says "[otherPrimeInfos] shall be omitted if version is 0 and shall
     * contain at least one instance of OtherPrimeInfo if version is 1." The
     * OPTIONAL is just so both versions share a single definition. */
    CBS other_prime_infos;
    if (!CBS_get_asn1(&child, &other_prime_infos, CBS_ASN1_SEQUENCE) ||
        CBS_len(&other_prime_infos) == 0) {
      OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING);
      goto err;
    }
    ret->additional_primes = sk_RSA_additional_prime_new_null();
    if (ret->additional_primes == NULL) {
      OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
      goto err;
    }

    ctx = BN_CTX_new();
    product_of_primes_so_far = BN_new();
    if (ctx == NULL ||
        product_of_primes_so_far == NULL ||
        !BN_mul(product_of_primes_so_far, ret->p, ret->q, ctx)) {
      goto err;
    }

    while (CBS_len(&other_prime_infos) > 0) {
      RSA_additional_prime *ap = rsa_parse_additional_prime(&other_prime_infos);
      if (ap == NULL) {
        goto err;
      }
      if (!sk_RSA_additional_prime_push(ret->additional_primes, ap)) {
        OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
        RSA_additional_prime_free(ap);
        goto err;
      }
      ap->r = BN_dup(product_of_primes_so_far);
      if (ap->r == NULL ||
          !BN_mul(product_of_primes_so_far, product_of_primes_so_far,
                  ap->prime, ctx)) {
        goto err;
      }
    }
  }

  if (CBS_len(&child) != 0) {
    OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING);
    goto err;
  }

  BN_CTX_free(ctx);
  BN_free(product_of_primes_so_far);
  return ret;

err:
  BN_CTX_free(ctx);
  BN_free(product_of_primes_so_far);
  RSA_free(ret);
  return NULL;
}
Exemplo n.º 23
0
SSL_SESSION *
d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length)
{
	CBS cbs, session, cipher_suite, session_id, master_key, peer_cert;
	CBS hostname, ticket;
	uint64_t version, tls_version, stime, timeout, verify_result, lifetime;
	const unsigned char *peer_cert_bytes;
	uint16_t cipher_value;
	SSL_SESSION *s = NULL;
	size_t data_len;
	int present;

	if (a != NULL)
		s = *a;

	if (s == NULL) {
		if ((s = SSL_SESSION_new()) == NULL) {
			SSLerrorx(ERR_R_MALLOC_FAILURE);
			return (NULL);
		}
	}

	CBS_init(&cbs, *pp, length);

	if (!CBS_get_asn1(&cbs, &session, CBS_ASN1_SEQUENCE))
		goto err;

	/* Session ASN1 version. */
	if (!CBS_get_asn1_uint64(&session, &version))
		goto err;
	if (version != SSL_SESSION_ASN1_VERSION)
		goto err;

	/* TLS/SSL Protocol Version. */
	if (!CBS_get_asn1_uint64(&session, &tls_version))
		goto err;
	if (tls_version > INT_MAX)
		goto err;
	s->ssl_version = (int)tls_version;

	/* Cipher suite. */
	if (!CBS_get_asn1(&session, &cipher_suite, CBS_ASN1_OCTETSTRING))
		goto err;
	if (!CBS_get_u16(&cipher_suite, &cipher_value))
		goto err;
	if (CBS_len(&cipher_suite) != 0)
		goto err;

	/* XXX - populate cipher instead? */
	s->cipher = NULL;
	s->cipher_id = SSL3_CK_ID | cipher_value;

	/* Session ID. */
	if (!CBS_get_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING))
		goto err;
	if (!CBS_write_bytes(&session_id, s->session_id, sizeof(s->session_id),
	    &data_len))
		goto err;
	if (data_len > UINT_MAX)
		goto err;
	s->session_id_length = (unsigned int)data_len;

	/* Master key. */
	if (!CBS_get_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING))
		goto err;
	if (!CBS_write_bytes(&master_key, s->master_key, sizeof(s->master_key),
	    &data_len))
		goto err;
	if (data_len > INT_MAX)
		goto err;
	s->master_key_length = (int)data_len;

	/* Time [1]. */
	s->time = time(NULL);
	if (!CBS_get_optional_asn1_uint64(&session, &stime, SSLASN1_TIME_TAG,
	    0))
		goto err;
	if (stime > time_max())
		goto err;
	if (stime != 0)
		s->time = (time_t)stime;

	/* Timeout [2]. */
	s->timeout = 3;
	if (!CBS_get_optional_asn1_uint64(&session, &timeout,
	    SSLASN1_TIMEOUT_TAG, 0))
		goto err;
	if (timeout > LONG_MAX)
		goto err;
	if (timeout != 0)
		s->timeout = (long)timeout;
	
	/* Peer certificate [3]. */
	X509_free(s->peer);
	s->peer = NULL;
	if (!CBS_get_optional_asn1(&session, &peer_cert, &present,
	    SSLASN1_PEER_CERT_TAG))
		goto err;
	if (present) {
		data_len = CBS_len(&peer_cert);
		if (data_len > LONG_MAX)
			goto err;
		peer_cert_bytes = CBS_data(&peer_cert);
		if (d2i_X509(&s->peer, &peer_cert_bytes,
		    (long)data_len) == NULL)
			goto err;
	}

	/* Session ID context [4]. */
	s->sid_ctx_length = 0;
	if (!CBS_get_optional_asn1_octet_string(&session, &session_id, &present,
	    SSLASN1_SESSION_ID_CTX_TAG))
		goto err;
	if (present) {
		if (!CBS_write_bytes(&session_id, (uint8_t *)&s->sid_ctx,
		    sizeof(s->sid_ctx), &data_len))
			goto err;
		if (data_len > UINT_MAX)
			goto err;
		s->sid_ctx_length = (unsigned int)data_len;
	}

	/* Verify result [5]. */
	s->verify_result = X509_V_OK;
	if (!CBS_get_optional_asn1_uint64(&session, &verify_result,
	    SSLASN1_VERIFY_RESULT_TAG, X509_V_OK))
		goto err;
	if (verify_result > LONG_MAX)
		goto err;
	s->verify_result = (long)verify_result;

	/* Hostname [6]. */
	free(s->tlsext_hostname);
	s->tlsext_hostname = NULL;
	if (!CBS_get_optional_asn1_octet_string(&session, &hostname, &present,
	    SSLASN1_HOSTNAME_TAG))
		goto err;
	if (present) {
		if (CBS_contains_zero_byte(&hostname))
			goto err;
		if (!CBS_strdup(&hostname, &s->tlsext_hostname))
			goto err;
	}
	
	/* PSK identity hint [7]. */
	/* PSK identity [8]. */

	/* Ticket lifetime [9]. */
	s->tlsext_tick_lifetime_hint = 0;
	/* XXX - tlsext_ticklen is not yet set... */
	if (s->tlsext_ticklen > 0 && s->session_id_length > 0)
		s->tlsext_tick_lifetime_hint = -1;
	if (!CBS_get_optional_asn1_uint64(&session, &lifetime,
	    SSLASN1_LIFETIME_TAG, 0))
		goto err;
	if (lifetime > LONG_MAX)
		goto err;
	if (lifetime > 0)
		s->tlsext_tick_lifetime_hint = (long)lifetime;

	/* Ticket [10]. */
	free(s->tlsext_tick);
	s->tlsext_tick = NULL;
	if (!CBS_get_optional_asn1_octet_string(&session, &ticket, &present,
	    SSLASN1_TICKET_TAG))
		goto err;
	if (present) {
		if (!CBS_stow(&ticket, &s->tlsext_tick, &s->tlsext_ticklen))
			goto err;
	}

	/* Compression method [11]. */
	/* SRP username [12]. */

	*pp = CBS_data(&cbs);

	if (a != NULL)
		*a = s;

	return (s);

err:
	ERR_asprintf_error_data("offset=%d", (int)(CBS_data(&cbs) - *pp));

	if (s != NULL && (a == NULL || *a != s))
		SSL_SESSION_free(s);

	return (NULL);
}
Exemplo n.º 24
0
static int test_get_asn1(void) {
  static const uint8_t kData1[] = {0x30, 2, 1, 2};
  static const uint8_t kData2[] = {0x30, 3, 1, 2};
  static const uint8_t kData3[] = {0x30, 0x80};
  static const uint8_t kData4[] = {0x30, 0x81, 1, 1};
  static const uint8_t kData5[] = {0x30, 0x82, 0, 1, 1};
  static const uint8_t kData6[] = {0xa1, 3, 0x4, 1, 1};
  static const uint8_t kData7[] = {0xa1, 3, 0x4, 2, 1};
  static const uint8_t kData8[] = {0xa1, 3, 0x2, 1, 1};
  static const uint8_t kData9[] = {0xa1, 3, 0x2, 1, 0xff};

  CBS data, contents;
  int present;
  uint64_t value;

  CBS_init(&data, kData1, sizeof(kData1));
  if (CBS_peek_asn1_tag(&data, 0x1) ||
      !CBS_peek_asn1_tag(&data, 0x30)) {
    return 0;
  }
  if (!CBS_get_asn1(&data, &contents, 0x30) ||
      CBS_len(&contents) != 2 ||
      memcmp(CBS_data(&contents), "\x01\x02", 2) != 0) {
    return 0;
  }

  CBS_init(&data, kData2, sizeof(kData2));
  /* data is truncated */
  if (CBS_get_asn1(&data, &contents, 0x30)) {
    return 0;
  }

  CBS_init(&data, kData3, sizeof(kData3));
  /* zero byte length of length */
  if (CBS_get_asn1(&data, &contents, 0x30)) {
    return 0;
  }

  CBS_init(&data, kData4, sizeof(kData4));
  /* long form mistakenly used. */
  if (CBS_get_asn1(&data, &contents, 0x30)) {
    return 0;
  }

  CBS_init(&data, kData5, sizeof(kData5));
  /* length takes too many bytes. */
  if (CBS_get_asn1(&data, &contents, 0x30)) {
    return 0;
  }

  CBS_init(&data, kData1, sizeof(kData1));
  /* wrong tag. */
  if (CBS_get_asn1(&data, &contents, 0x31)) {
    return 0;
  }

  CBS_init(&data, NULL, 0);
  /* peek at empty data. */
  if (CBS_peek_asn1_tag(&data, 0x30)) {
    return 0;
  }

  CBS_init(&data, NULL, 0);
  /* optional elements at empty data. */
  if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) ||
      present ||
      !CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) ||
      present ||
      CBS_len(&contents) != 0 ||
      !CBS_get_optional_asn1_octet_string(&data, &contents, NULL, 0xa0) ||
      CBS_len(&contents) != 0 ||
      !CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) ||
      value != 42) {
    return 0;
  }

  CBS_init(&data, kData6, sizeof(kData6));
  /* optional element. */
  if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) ||
      present ||
      !CBS_get_optional_asn1(&data, &contents, &present, 0xa1) ||
      !present ||
      CBS_len(&contents) != 3 ||
      memcmp(CBS_data(&contents), "\x04\x01\x01", 3) != 0) {
    return 0;
  }

  CBS_init(&data, kData6, sizeof(kData6));
  /* optional octet string. */
  if (!CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) ||
      present ||
      CBS_len(&contents) != 0 ||
      !CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1) ||
      !present ||
      CBS_len(&contents) != 1 ||
      CBS_data(&contents)[0] != 1) {
    return 0;
  }

  CBS_init(&data, kData7, sizeof(kData7));
  /* invalid optional octet string. */
  if (CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1)) {
    return 0;
  }

  CBS_init(&data, kData8, sizeof(kData8));
  /* optional octet string. */
  if (!CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) ||
      value != 42 ||
      !CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42) ||
      value != 1) {
    return 0;
  }

  CBS_init(&data, kData9, sizeof(kData9));
  /* invalid optional integer. */
  if (CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42)) {
    return 0;
  }

  return 1;
}
Exemplo n.º 25
0
SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
                               CRYPTO_BUFFER_POOL *pool) {
  SSL_SESSION *ret = ssl_session_new(x509_method);
  if (ret == NULL) {
    goto err;
  }

  CBS session;
  uint64_t version, ssl_version;
  if (!CBS_get_asn1(cbs, &session, CBS_ASN1_SEQUENCE) ||
      !CBS_get_asn1_uint64(&session, &version) ||
      version != kVersion ||
      !CBS_get_asn1_uint64(&session, &ssl_version)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
    goto err;
  }
  ret->ssl_version = ssl_version;

  CBS cipher;
  uint16_t cipher_value;
  if (!CBS_get_asn1(&session, &cipher, CBS_ASN1_OCTETSTRING) ||
      !CBS_get_u16(&cipher, &cipher_value) ||
      CBS_len(&cipher) != 0) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
    goto err;
  }
  ret->cipher = SSL_get_cipher_by_value(cipher_value);
  if (ret->cipher == NULL) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_CIPHER);
    goto err;
  }

  CBS session_id, master_key;
  if (!CBS_get_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING) ||
      CBS_len(&session_id) > SSL3_MAX_SSL_SESSION_ID_LENGTH ||
      !CBS_get_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING) ||
      CBS_len(&master_key) > SSL_MAX_MASTER_KEY_LENGTH) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
    goto err;
  }
  OPENSSL_memcpy(ret->session_id, CBS_data(&session_id), CBS_len(&session_id));
  ret->session_id_length = CBS_len(&session_id);
  OPENSSL_memcpy(ret->master_key, CBS_data(&master_key), CBS_len(&master_key));
  ret->master_key_length = CBS_len(&master_key);

  CBS child;
  uint64_t timeout;
  if (!CBS_get_asn1(&session, &child, kTimeTag) ||
      !CBS_get_asn1_uint64(&child, &ret->time) ||
      !CBS_get_asn1(&session, &child, kTimeoutTag) ||
      !CBS_get_asn1_uint64(&child, &timeout) ||
      timeout > UINT32_MAX) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
    goto err;
  }

  ret->timeout = (uint32_t)timeout;

  CBS peer;
  int has_peer;
  if (!CBS_get_optional_asn1(&session, &peer, &has_peer, kPeerTag) ||
      (has_peer && CBS_len(&peer) == 0)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
    goto err;
  }
  /* |peer| is processed with the certificate chain. */

  if (!SSL_SESSION_parse_bounded_octet_string(
          &session, ret->sid_ctx, &ret->sid_ctx_length, sizeof(ret->sid_ctx),
          kSessionIDContextTag) ||
      !SSL_SESSION_parse_long(&session, &ret->verify_result, kVerifyResultTag,
                              X509_V_OK) ||
      !SSL_SESSION_parse_string(&session, &ret->tlsext_hostname,
                                kHostNameTag) ||
      !SSL_SESSION_parse_string(&session, &ret->psk_identity,
                                kPSKIdentityTag) ||
      !SSL_SESSION_parse_u32(&session, &ret->tlsext_tick_lifetime_hint,
                             kTicketLifetimeHintTag, 0) ||
      !SSL_SESSION_parse_octet_string(&session, &ret->tlsext_tick,
                                      &ret->tlsext_ticklen, kTicketTag)) {
    goto err;
  }

  if (CBS_peek_asn1_tag(&session, kPeerSHA256Tag)) {
    CBS peer_sha256;
    if (!CBS_get_asn1(&session, &child, kPeerSHA256Tag) ||
        !CBS_get_asn1(&child, &peer_sha256, CBS_ASN1_OCTETSTRING) ||
        CBS_len(&peer_sha256) != sizeof(ret->peer_sha256) ||
        CBS_len(&child) != 0) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
      goto err;
    }
    OPENSSL_memcpy(ret->peer_sha256, CBS_data(&peer_sha256),
                   sizeof(ret->peer_sha256));
    ret->peer_sha256_valid = 1;
  } else {
    ret->peer_sha256_valid = 0;
  }

  if (!SSL_SESSION_parse_bounded_octet_string(
          &session, ret->original_handshake_hash,
          &ret->original_handshake_hash_len,
          sizeof(ret->original_handshake_hash), kOriginalHandshakeHashTag) ||
      !SSL_SESSION_parse_octet_string(
          &session, &ret->tlsext_signed_cert_timestamp_list,
          &ret->tlsext_signed_cert_timestamp_list_length,
          kSignedCertTimestampListTag) ||
      !SSL_SESSION_parse_octet_string(
          &session, &ret->ocsp_response, &ret->ocsp_response_length,
          kOCSPResponseTag)) {
    goto err;
  }

  int extended_master_secret;
  if (!CBS_get_optional_asn1_bool(&session, &extended_master_secret,
                                  kExtendedMasterSecretTag,
                                  0 /* default to false */)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
    goto err;
  }
  ret->extended_master_secret = !!extended_master_secret;

  if (!SSL_SESSION_parse_u16(&session, &ret->group_id, kGroupIDTag, 0)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
    goto err;
  }

  CBS cert_chain;
  CBS_init(&cert_chain, NULL, 0);
  int has_cert_chain;
  if (!CBS_get_optional_asn1(&session, &cert_chain, &has_cert_chain,
                             kCertChainTag) ||
      (has_cert_chain && CBS_len(&cert_chain) == 0)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
    goto err;
  }
  if (has_cert_chain && !has_peer) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
    goto err;
  }
  if (has_peer || has_cert_chain) {
    ret->certs = sk_CRYPTO_BUFFER_new_null();
    if (ret->certs == NULL) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
      goto err;
    }

    if (has_peer) {
      /* TODO(agl): this should use the |SSL_CTX|'s pool. */
      CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&peer, pool);
      if (buffer == NULL ||
          !sk_CRYPTO_BUFFER_push(ret->certs, buffer)) {
        CRYPTO_BUFFER_free(buffer);
        OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
        goto err;
      }
    }

    while (CBS_len(&cert_chain) > 0) {
      CBS cert;
      if (!CBS_get_any_asn1_element(&cert_chain, &cert, NULL, NULL) ||
          CBS_len(&cert) == 0) {
        OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
        goto err;
      }

      /* TODO(agl): this should use the |SSL_CTX|'s pool. */
      CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&cert, pool);
      if (buffer == NULL ||
          !sk_CRYPTO_BUFFER_push(ret->certs, buffer)) {
        CRYPTO_BUFFER_free(buffer);
        OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
        goto err;
      }
    }
  }

  if (!x509_method->session_cache_objects(ret)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
    goto err;
  }

  CBS age_add;
  int age_add_present;
  if (!CBS_get_optional_asn1_octet_string(&session, &age_add, &age_add_present,
                                          kTicketAgeAddTag) ||
      (age_add_present &&
       !CBS_get_u32(&age_add, &ret->ticket_age_add)) ||
      CBS_len(&age_add) != 0) {
    goto err;
  }
  ret->ticket_age_add_valid = age_add_present;

  int is_server;
  if (!CBS_get_optional_asn1_bool(&session, &is_server, kIsServerTag,
                                  1 /* default to true */)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
    goto err;
  }
  /* TODO: in time we can include |is_server| for servers too, then we can
     enforce that client and server sessions are never mixed up. */

  ret->is_server = is_server;

  if (!SSL_SESSION_parse_u16(&session, &ret->peer_signature_algorithm,
                             kPeerSignatureAlgorithmTag, 0) ||
      !SSL_SESSION_parse_u32(&session, &ret->ticket_max_early_data,
                             kTicketMaxEarlyDataTag, 0) ||
      !SSL_SESSION_parse_u32(&session, &ret->auth_timeout, kAuthTimeoutTag,
                             ret->timeout) ||
      !SSL_SESSION_parse_octet_string(&session, &ret->early_alpn,
                                      &ret->early_alpn_len, kEarlyALPNTag) ||
      CBS_len(&session) != 0) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
    goto err;
  }

  return ret;

err:
  SSL_SESSION_free(ret);
  return NULL;
}
Exemplo n.º 26
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;
}