1 // Copyright 2016 The Chromium Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "encode_values.h"
16 
17 #include "parse_values.h"
18 
19 #include <openssl/posix_time.h>
20 
21 BSSL_NAMESPACE_BEGIN
22 namespace der {
23 
24 namespace {
25 
WriteFourDigit(uint16_t value,uint8_t out[4])26 bool WriteFourDigit(uint16_t value, uint8_t out[4]) {
27   if (value >= 10000) {
28     return false;
29   }
30   out[3] = '0' + (value % 10);
31   value /= 10;
32   out[2] = '0' + (value % 10);
33   value /= 10;
34   out[1] = '0' + (value % 10);
35   value /= 10;
36   out[0] = '0' + value;
37   return true;
38 }
39 
WriteTwoDigit(uint8_t value,uint8_t out[2])40 bool WriteTwoDigit(uint8_t value, uint8_t out[2]) {
41   if (value >= 100) {
42     return false;
43   }
44   out[0] = '0' + (value / 10);
45   out[1] = '0' + (value % 10);
46   return true;
47 }
48 
49 }  // namespace
50 
EncodePosixTimeAsGeneralizedTime(int64_t posix_time,GeneralizedTime * generalized_time)51 bool EncodePosixTimeAsGeneralizedTime(int64_t posix_time,
52                                       GeneralizedTime *generalized_time) {
53   struct tm tmp_tm;
54   if (!OPENSSL_posix_to_tm(posix_time, &tmp_tm)) {
55     return false;
56   }
57 
58   generalized_time->year = tmp_tm.tm_year + 1900;
59   generalized_time->month = tmp_tm.tm_mon + 1;
60   generalized_time->day = tmp_tm.tm_mday;
61   generalized_time->hours = tmp_tm.tm_hour;
62   generalized_time->minutes = tmp_tm.tm_min;
63   generalized_time->seconds = tmp_tm.tm_sec;
64   return true;
65 }
66 
GeneralizedTimeToPosixTime(const der::GeneralizedTime & generalized,int64_t * result)67 bool GeneralizedTimeToPosixTime(const der::GeneralizedTime &generalized,
68                                 int64_t *result) {
69   struct tm tmp_tm;
70   tmp_tm.tm_year = generalized.year - 1900;
71   tmp_tm.tm_mon = generalized.month - 1;
72   tmp_tm.tm_mday = generalized.day;
73   tmp_tm.tm_hour = generalized.hours;
74   tmp_tm.tm_min = generalized.minutes;
75   tmp_tm.tm_sec = generalized.seconds;
76   // BoringSSL POSIX time, like POSIX itself, does not support leap seconds.
77   // Collapse to previous second.
78   if (tmp_tm.tm_sec == 60) {
79     tmp_tm.tm_sec = 59;
80   }
81   return OPENSSL_tm_to_posix(&tmp_tm, result);
82 }
83 
EncodeGeneralizedTime(const GeneralizedTime & time,uint8_t out[kGeneralizedTimeLength])84 bool EncodeGeneralizedTime(const GeneralizedTime &time,
85                            uint8_t out[kGeneralizedTimeLength]) {
86   if (!WriteFourDigit(time.year, out) || !WriteTwoDigit(time.month, out + 4) ||
87       !WriteTwoDigit(time.day, out + 6) ||
88       !WriteTwoDigit(time.hours, out + 8) ||
89       !WriteTwoDigit(time.minutes, out + 10) ||
90       !WriteTwoDigit(time.seconds, out + 12)) {
91     return false;
92   }
93   out[14] = 'Z';
94   return true;
95 }
96 
EncodeUTCTime(const GeneralizedTime & time,uint8_t out[kUTCTimeLength])97 bool EncodeUTCTime(const GeneralizedTime &time, uint8_t out[kUTCTimeLength]) {
98   if (!time.InUTCTimeRange()) {
99     return false;
100   }
101 
102   uint16_t year = time.year - 1900;
103   if (year >= 100) {
104     year -= 100;
105   }
106 
107   if (!WriteTwoDigit(year, out) || !WriteTwoDigit(time.month, out + 2) ||
108       !WriteTwoDigit(time.day, out + 4) ||
109       !WriteTwoDigit(time.hours, out + 6) ||
110       !WriteTwoDigit(time.minutes, out + 8) ||
111       !WriteTwoDigit(time.seconds, out + 10)) {
112     return false;
113   }
114   out[12] = 'Z';
115   return true;
116 }
117 
118 }  // namespace der
119 BSSL_NAMESPACE_END
120