• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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