예제 #1
0
static int SSL_SESSION_parse_u16(CBS *cbs, uint16_t *out, unsigned tag,
                                 uint16_t default_value) {
  uint64_t value;
  if (!CBS_get_optional_asn1_uint64(cbs, &value, tag,
                                    (uint64_t)default_value) ||
      value > 0xffff) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
    return 0;
  }
  *out = (uint16_t)value;
  return 1;
}
예제 #2
0
static int SSL_SESSION_parse_long(CBS *cbs, long *out, unsigned tag,
                                  long default_value) {
  uint64_t value;
  if (!CBS_get_optional_asn1_uint64(cbs, &value, tag,
                                    (uint64_t)default_value) ||
      value > LONG_MAX) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
    return 0;
  }
  *out = (long)value;
  return 1;
}
예제 #3
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);
}
예제 #4
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;
}