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