1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/der/encode_values.h"
6
7 #include "base/time/time.h"
8 #include "net/der/parse_values.h"
9
10 #include "third_party/boringssl/src/include/openssl/time.h"
11
12 namespace net::der {
13
14 namespace {
15
WriteFourDigit(uint16_t value,uint8_t out[4])16 bool WriteFourDigit(uint16_t value, uint8_t out[4]) {
17 if (value >= 10000)
18 return false;
19 out[3] = '0' + (value % 10);
20 value /= 10;
21 out[2] = '0' + (value % 10);
22 value /= 10;
23 out[1] = '0' + (value % 10);
24 value /= 10;
25 out[0] = '0' + value;
26 return true;
27 }
28
WriteTwoDigit(uint8_t value,uint8_t out[2])29 bool WriteTwoDigit(uint8_t value, uint8_t out[2]) {
30 if (value >= 100)
31 return false;
32 out[0] = '0' + (value / 10);
33 out[1] = '0' + (value % 10);
34 return true;
35 }
36
37 } // namespace
38
EncodeTimeAsGeneralizedTime(const base::Time & time,GeneralizedTime * generalized_time)39 bool EncodeTimeAsGeneralizedTime(const base::Time& time,
40 GeneralizedTime* generalized_time) {
41 base::Time::Exploded exploded;
42 time.UTCExplode(&exploded);
43 if (!exploded.HasValidValues())
44 return false;
45
46 generalized_time->year = exploded.year;
47 generalized_time->month = exploded.month;
48 generalized_time->day = exploded.day_of_month;
49 generalized_time->hours = exploded.hour;
50 generalized_time->minutes = exploded.minute;
51 generalized_time->seconds = exploded.second;
52 return true;
53 }
54
EncodePosixTimeAsGeneralizedTime(int64_t posix_time,GeneralizedTime * generalized_time)55 bool EncodePosixTimeAsGeneralizedTime(int64_t posix_time,
56 GeneralizedTime* generalized_time) {
57 struct tm tmp_tm;
58 if (!OPENSSL_posix_to_tm(posix_time, &tmp_tm)) {
59 return false;
60 }
61
62 generalized_time->year = tmp_tm.tm_year + 1900;
63 generalized_time->month = tmp_tm.tm_mon + 1;
64 generalized_time->day = tmp_tm.tm_mday;
65 generalized_time->hours = tmp_tm.tm_hour;
66 generalized_time->minutes = tmp_tm.tm_min;
67 generalized_time->seconds = tmp_tm.tm_sec;
68 return true;
69 }
70
GeneralizedTimeToTime(const der::GeneralizedTime & generalized,base::Time * result)71 bool GeneralizedTimeToTime(const der::GeneralizedTime& generalized,
72 base::Time* result) {
73 base::Time::Exploded exploded = {0};
74 exploded.year = generalized.year;
75 exploded.month = generalized.month;
76 exploded.day_of_month = generalized.day;
77 exploded.hour = generalized.hours;
78 exploded.minute = generalized.minutes;
79 exploded.second = generalized.seconds;
80
81 if (base::Time::FromUTCExploded(exploded, result))
82 return true;
83
84 // Fail on obviously bad dates.
85 if (!exploded.HasValidValues())
86 return false;
87
88 // TODO(mattm): consider consolidating this with
89 // SaturatedTimeFromUTCExploded from cookie_util.cc
90 if (static_cast<int>(generalized.year) > base::Time::kExplodedMaxYear) {
91 *result = base::Time::Max();
92 return true;
93 }
94 if (static_cast<int>(generalized.year) < base::Time::kExplodedMinYear) {
95 *result = base::Time::Min();
96 return true;
97 }
98 return false;
99 }
100
GeneralizedTimeToPosixTime(const der::GeneralizedTime & generalized,int64_t * result)101 bool GeneralizedTimeToPosixTime(const der::GeneralizedTime& generalized,
102 int64_t* result) {
103 struct tm tmp_tm;
104 tmp_tm.tm_year = generalized.year - 1900;
105 tmp_tm.tm_mon = generalized.month - 1;
106 tmp_tm.tm_mday = generalized.day;
107 tmp_tm.tm_hour = generalized.hours;
108 tmp_tm.tm_min = generalized.minutes;
109 tmp_tm.tm_sec = generalized.seconds;
110 // BoringSSL POSIX time, like POSIX itself, does not support leap seconds.
111 // Collapse to previous second.
112 if (tmp_tm.tm_sec == 60) {
113 tmp_tm.tm_sec = 59;
114 }
115 return OPENSSL_tm_to_posix(&tmp_tm, result);
116 }
117
EncodeGeneralizedTime(const GeneralizedTime & time,uint8_t out[kGeneralizedTimeLength])118 bool EncodeGeneralizedTime(const GeneralizedTime& time,
119 uint8_t out[kGeneralizedTimeLength]) {
120 if (!WriteFourDigit(time.year, out) || !WriteTwoDigit(time.month, out + 4) ||
121 !WriteTwoDigit(time.day, out + 6) ||
122 !WriteTwoDigit(time.hours, out + 8) ||
123 !WriteTwoDigit(time.minutes, out + 10) ||
124 !WriteTwoDigit(time.seconds, out + 12)) {
125 return false;
126 }
127 out[14] = 'Z';
128 return true;
129 }
130
EncodeUTCTime(const GeneralizedTime & time,uint8_t out[kUTCTimeLength])131 bool EncodeUTCTime(const GeneralizedTime& time, uint8_t out[kUTCTimeLength]) {
132 if (!time.InUTCTimeRange())
133 return false;
134
135 uint16_t year = time.year - 1900;
136 if (year >= 100)
137 year -= 100;
138
139 if (!WriteTwoDigit(year, out) || !WriteTwoDigit(time.month, out + 2) ||
140 !WriteTwoDigit(time.day, out + 4) ||
141 !WriteTwoDigit(time.hours, out + 6) ||
142 !WriteTwoDigit(time.minutes, out + 8) ||
143 !WriteTwoDigit(time.seconds, out + 10)) {
144 return false;
145 }
146 out[12] = 'Z';
147 return true;
148 }
149
150 } // namespace net::der
151