Skip to content

Commit

Permalink
Upstream merge 2024 08 23 (#1799)
Browse files Browse the repository at this point in the history
### Description of changes: 
* Merge changes from BoringSSL. See internal docs.


By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.
  • Loading branch information
justsmth authored Aug 30, 2024
2 parents 0f782c2 + 46cdb75 commit 9d2f9d2
Show file tree
Hide file tree
Showing 38 changed files with 521 additions and 624 deletions.
89 changes: 87 additions & 2 deletions crypto/asn1/asn1_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1194,8 +1194,8 @@ TEST(ASN1Test, AdjTime) {
struct tm tm1, tm2;
int days, secs;

OPENSSL_posix_to_tm(0, &tm1);
OPENSSL_posix_to_tm(0, &tm2);
EXPECT_TRUE(OPENSSL_posix_to_tm(0, &tm1));
EXPECT_TRUE(OPENSSL_posix_to_tm(0, &tm2));
// Test values that are too large and should be rejected.
EXPECT_FALSE(OPENSSL_gmtime_adj(&tm1, INT_MIN, INT_MIN));
EXPECT_FALSE(OPENSSL_gmtime_adj(&tm1, INT_MAX, INT_MAX));
Expand Down Expand Up @@ -2480,6 +2480,91 @@ TEST(ASN1Test, ASN1Dup) {
0);
}

static std::tuple<int, int, int, int, int, int> TimeToTuple(const tm &t) {
return std::make_tuple(t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min,
t.tm_sec);
}

TEST(ASN1Test, TimeOverflow) {
// Input time is out of range and may overflow internal calculations to shift
// |tm_year| and |tm_mon| to a more normal value.
tm overflow_year;
OPENSSL_memset(&overflow_year, 0, sizeof(overflow_year));
overflow_year.tm_year = INT_MAX - 1899;
overflow_year.tm_mday = 1;
tm overflow_month;
OPENSSL_memset(&overflow_month, 0, sizeof(overflow_month));
overflow_month.tm_mon = INT_MAX;
overflow_month.tm_mday = 1;
int64_t posix_u64;
EXPECT_FALSE(OPENSSL_tm_to_posix(&overflow_year, &posix_u64));
EXPECT_FALSE(OPENSSL_tm_to_posix(&overflow_month, &posix_u64));
time_t posix;
EXPECT_FALSE(OPENSSL_timegm(&overflow_year, &posix));
EXPECT_FALSE(OPENSSL_timegm(&overflow_month, &posix));
EXPECT_FALSE(
OPENSSL_gmtime_adj(&overflow_year, /*offset_day=*/0, /*offset_sec=*/0));
EXPECT_FALSE(
OPENSSL_gmtime_adj(&overflow_month, /*offset_day=*/0, /*offset_sec=*/0));
int days, secs;
EXPECT_FALSE(
OPENSSL_gmtime_diff(&days, &secs, &overflow_year, &overflow_year));
EXPECT_FALSE(
OPENSSL_gmtime_diff(&days, &secs, &overflow_month, &overflow_month));

// Input time is in range, but even adding one second puts it out of range.
tm max_time;
OPENSSL_memset(&max_time, 0, sizeof(max_time));
max_time.tm_year = 9999 - 1900;
max_time.tm_mon = 12 - 1;
max_time.tm_mday = 31;
max_time.tm_hour = 23;
max_time.tm_min = 59;
max_time.tm_sec = 59;
tm copy = max_time;
EXPECT_TRUE(OPENSSL_gmtime_adj(&copy, /*offset_day=*/0, /*offset_sec=*/0));
EXPECT_EQ(TimeToTuple(copy), TimeToTuple(max_time));
EXPECT_FALSE(OPENSSL_gmtime_adj(&copy, /*offset_day=*/0, /*offset_sec=*/1));

// Likewise for the earliest representable time.
tm min_time;
OPENSSL_memset(&min_time, 0, sizeof(min_time));
min_time.tm_year = 0 - 1900;
min_time.tm_mon = 1 - 1;
min_time.tm_mday = 1;
min_time.tm_hour = 0;
min_time.tm_min = 0;
min_time.tm_sec = 0;
copy = min_time;
EXPECT_TRUE(OPENSSL_gmtime_adj(&copy, /*offset_day=*/0, /*offset_sec=*/0));
EXPECT_EQ(TimeToTuple(copy), TimeToTuple(min_time));
EXPECT_FALSE(OPENSSL_gmtime_adj(&copy, /*offset_day=*/0, /*offset_sec=*/-1));

// Test we can offset between the minimum and maximum times.
const int64_t kValidTimeRange = 315569519999;
copy = min_time;
EXPECT_TRUE(OPENSSL_gmtime_adj(&copy, /*offset_day=*/0, kValidTimeRange));
EXPECT_EQ(TimeToTuple(copy), TimeToTuple(max_time));
EXPECT_TRUE(OPENSSL_gmtime_adj(&copy, /*offset_day=*/0, -kValidTimeRange));
EXPECT_EQ(TimeToTuple(copy), TimeToTuple(min_time));

// The second offset may even exceed kValidTimeRange if it is canceled out by
// offset_day.
EXPECT_TRUE(OPENSSL_gmtime_adj(&copy, /*offset_day=*/-1,
kValidTimeRange + 24 * 3600));
EXPECT_EQ(TimeToTuple(copy), TimeToTuple(max_time));
EXPECT_TRUE(OPENSSL_gmtime_adj(&copy, /*offset_day=*/1,
-kValidTimeRange - 24 * 3600));
EXPECT_EQ(TimeToTuple(copy), TimeToTuple(min_time));

// Make sure the internal calculations for |OPENSSL_gmtime_adj| stay in
// bounds.
copy = max_time;
EXPECT_FALSE(OPENSSL_gmtime_adj(&copy, INT_MAX, LONG_MAX));
copy = min_time;
EXPECT_FALSE(OPENSSL_gmtime_adj(&copy, INT_MIN, LONG_MIN));
}

// The ASN.1 macros do not work on Windows shared library builds, where usage of
// |OPENSSL_EXPORT| is a bit stricter.
#if !defined(OPENSSL_WINDOWS) || !defined(BORINGSSL_SHARED_LIBRARY)
Expand Down
21 changes: 4 additions & 17 deletions crypto/asn1/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@

#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/posix_time.h>

#include "../internal.h"

#if defined(__cplusplus)
extern "C" {
Expand All @@ -71,33 +74,17 @@ extern "C" {

// Wrapper functions for time functions.

// OPENSSL_posix_to_tm converts a int64_t POSIX time value in |time| which must
// be in the range of year 0000 to 9999 to a broken out time value in |tm|. It
// returns one on success and zero on error.
OPENSSL_EXPORT int OPENSSL_posix_to_tm(int64_t time, struct tm *out_tm);

// OPENSSL_tm_to_posix converts a time value between the years 0 and 9999 in
// |tm| to a POSIX time value in |out|. One is returned on success, zero is
// returned on failure. It is a failure if the tm contains out of range values.
OPENSSL_EXPORT int OPENSSL_tm_to_posix(const struct tm *tm, int64_t *out);

// OPENSSL_gmtime converts a time_t value in |time| which must be in the range
// of year 0000 to 9999 to a broken out time value in |tm|. On success |tm| is
// returned. On failure NULL is returned.
OPENSSL_EXPORT struct tm *OPENSSL_gmtime(const time_t *time, struct tm *result);

// OPENSSL_timegm converts a time value between the years 0 and 9999 in |tm| to
// a time_t value in |out|. One is returned on success, zero is returned on
// failure. It is a failure if the converted time can not be represented in a
// time_t, or if the tm contains out of range values.
OPENSSL_EXPORT int OPENSSL_timegm(const struct tm *tm, time_t *out);

// OPENSSL_gmtime_adj returns one on success, and updates |tm| by adding
// |offset_day| days and |offset_sec| seconds. It returns zero on failure. |tm|
// must be in the range of year 0000 to 9999 both before and after the update or
// a failure will be returned.
OPENSSL_EXPORT int OPENSSL_gmtime_adj(struct tm *tm, int offset_day,
long offset_sec);
int64_t offset_sec);

// OPENSSL_gmtime_diff calculates the difference between |from| and |to|. It
// returns one, and outputs the difference as a number of days and seconds in
Expand Down
91 changes: 51 additions & 40 deletions crypto/asn1/posix_time.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,15 @@
#include <string.h>
#include <time.h>

#include "../internal.h"
#include "internal.h"

#define SECS_PER_HOUR (60 * 60)
#define SECS_PER_DAY (24 * SECS_PER_HOUR)
#define SECS_PER_DAY (INT64_C(24) * SECS_PER_HOUR)


// Is a year/month/day combination valid, in the range from year 0000
// to 9999?
static int is_valid_date(int year, int month, int day) {
static int is_valid_date(int64_t year, int64_t month, int64_t day) {
if (day < 1 || month < 1 || year < 0 || year > 9999) {
return 0;
}
Expand Down Expand Up @@ -61,25 +60,30 @@ static int is_valid_date(int year, int month, int day) {

// Is a time valid? Leap seconds of 60 are not considered valid, as
// the POSIX time in seconds does not include them.
static int is_valid_time(int hours, int minutes, int seconds) {
static int is_valid_time(int64_t hours, int64_t minutes, int64_t seconds) {
if (hours < 0 || minutes < 0 || seconds < 0 || hours > 23 || minutes > 59 ||
seconds > 59) {
return 0;
}
return 1;
}

// Is a int64 time representing a time within our expected range?
static int is_valid_epoch_time(int64_t time) {
// 0000-01-01 00:00:00 UTC to 9999-12-31 23:59:59 UTC
return (int64_t)-62167219200 <= time && time <= (int64_t)253402300799;
// 0000-01-01 00:00:00 UTC
#define MIN_POSIX_TIME INT64_C(-62167219200)
// 9999-12-31 23:59:59 UTC
#define MAX_POSIX_TIME INT64_C(253402300799)

// Is an int64 time within our expected range?
static int is_valid_posix_time(int64_t time) {
return MIN_POSIX_TIME <= time && time <= MAX_POSIX_TIME;
}

// Inspired by algorithms presented in
// https://howardhinnant.github.io/date_algorithms.html
// (Public Domain)
static int posix_time_from_utc(int year, int month, int day, int hours,
int minutes, int seconds, int64_t *out_time) {
static int posix_time_from_utc(int64_t year, int64_t month, int64_t day,
int64_t hours, int64_t minutes, int64_t seconds,
int64_t *out_time) {
if (!is_valid_date(year, month, day) ||
!is_valid_time(hours, minutes, seconds)) {
return 0;
Expand Down Expand Up @@ -107,7 +111,7 @@ static int posix_time_from_utc(int year, int month, int day, int hours,
static int utc_from_posix_time(int64_t time, int *out_year, int *out_month,
int *out_day, int *out_hours, int *out_minutes,
int *out_seconds) {
if (!is_valid_epoch_time(time)) {
if (!is_valid_posix_time(time)) {
return 0;
}
int64_t days = time / SECS_PER_DAY;
Expand Down Expand Up @@ -142,23 +146,26 @@ static int utc_from_posix_time(int64_t time, int *out_year, int *out_month,
}

int OPENSSL_tm_to_posix(const struct tm *tm, int64_t *out) {
return posix_time_from_utc(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec, out);
return posix_time_from_utc(tm->tm_year + INT64_C(1900),
tm->tm_mon + INT64_C(1), tm->tm_mday, tm->tm_hour,
tm->tm_min, tm->tm_sec, out);
}

int OPENSSL_posix_to_tm(int64_t time, struct tm *out_tm) {
if (out_tm == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
OPENSSL_memset(out_tm, 0, sizeof(struct tm));
if (!utc_from_posix_time(time, &out_tm->tm_year, &out_tm->tm_mon,
&out_tm->tm_mday, &out_tm->tm_hour, &out_tm->tm_min,
&out_tm->tm_sec)) {
struct tm tmp_tm;
OPENSSL_memset(&tmp_tm, 0, sizeof(tmp_tm));
if (!utc_from_posix_time(time, &tmp_tm.tm_year, &tmp_tm.tm_mon,
&tmp_tm.tm_mday, &tmp_tm.tm_hour, &tmp_tm.tm_min,
&tmp_tm.tm_sec)) {
return 0;
}
out_tm->tm_year -= 1900;
out_tm->tm_mon -= 1;
tmp_tm.tm_year -= 1900;
tmp_tm.tm_mon -= 1;
*out_tm = tmp_tm;

return 1;
}
Expand Down Expand Up @@ -190,43 +197,47 @@ struct tm *OPENSSL_gmtime(const time_t *time, struct tm *out_tm) {
return out_tm;
}

int OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec) {
int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, int64_t offset_sec) {
int64_t posix_time;
if (!posix_time_from_utc(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec, &posix_time)) {
if (!OPENSSL_tm_to_posix(tm, &posix_time)) {
return 0;
}
OPENSSL_STATIC_ASSERT(INT_MAX <= INT64_MAX / SECS_PER_DAY,
day_offset_in_seconds_cannot_overflow)
OPENSSL_STATIC_ASSERT(MAX_POSIX_TIME <= INT64_MAX - INT_MAX * SECS_PER_DAY,
addition_cannot_overflow)
OPENSSL_STATIC_ASSERT(MIN_POSIX_TIME >= INT64_MIN - INT_MIN * SECS_PER_DAY,
addition_cannot_underflow)
posix_time += offset_day * SECS_PER_DAY;
if (posix_time > 0 && offset_sec > INT64_MAX - posix_time) {
return 0;
}
if (!utc_from_posix_time(
posix_time + (int64_t)off_day * SECS_PER_DAY + offset_sec,
&tm->tm_year, &tm->tm_mon, &tm->tm_mday, &tm->tm_hour, &tm->tm_min,
&tm->tm_sec)) {
if (posix_time < 0 && offset_sec < INT64_MIN - posix_time) {
return 0;
}
posix_time += offset_sec;

if (!OPENSSL_posix_to_tm(posix_time, tm)) {
return 0;
}
tm->tm_year -= 1900;
tm->tm_mon -= 1;

return 1;
}

int OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from,
const struct tm *to) {
int64_t time_to;
if (!posix_time_from_utc(to->tm_year + 1900, to->tm_mon + 1, to->tm_mday,
to->tm_hour, to->tm_min, to->tm_sec, &time_to)) {
return 0;
}
int64_t time_from;
if (!posix_time_from_utc(from->tm_year + 1900, from->tm_mon + 1,
from->tm_mday, from->tm_hour, from->tm_min,
from->tm_sec, &time_from)) {
int64_t time_to, time_from;
if (!OPENSSL_tm_to_posix(to, &time_to) ||
!OPENSSL_tm_to_posix(from, &time_from)) {
return 0;
}
// Times are in range, so these calculations can not overflow.
OPENSSL_STATIC_ASSERT(SECS_PER_DAY <= INT_MAX, seconds_per_day_does_not_fit_in_int)
OPENSSL_STATIC_ASSERT((MAX_POSIX_TIME - MIN_POSIX_TIME) / SECS_PER_DAY <= INT_MAX,
range_of_valid_POSIX_times_in_days_does_not_fit_in_int)
int64_t timediff = time_to - time_from;
int64_t daydiff = timediff / SECS_PER_DAY;
timediff %= SECS_PER_DAY;
if (daydiff > INT_MAX || daydiff < INT_MIN) {
return 0;
}
*out_secs = (int)timediff;
*out_days = (int)daydiff;
return 1;
Expand Down
4 changes: 2 additions & 2 deletions crypto/bio/bio.c
Original file line number Diff line number Diff line change
Expand Up @@ -504,11 +504,11 @@ int BIO_set_close(BIO *bio, int close_flag) {
return (int)BIO_ctrl(bio, BIO_CTRL_SET_CLOSE, close_flag, NULL);
}

OPENSSL_EXPORT size_t BIO_number_read(const BIO *bio) {
OPENSSL_EXPORT uint64_t BIO_number_read(const BIO *bio) {
return bio->num_read;
}

OPENSSL_EXPORT size_t BIO_number_written(const BIO *bio) {
OPENSSL_EXPORT uint64_t BIO_number_written(const BIO *bio) {
return bio->num_write;
}

Expand Down
Loading

0 comments on commit 9d2f9d2

Please sign in to comment.