1 
/* Copyright (c) 2002 The OpenEvidence Project. All rights reserved. 

2 
* 

3 
* Redistribution and use in source and binary forms, with or without 

4 
* modification, are permitted provided that the following conditions 

5 
* are met: 

6 
* 

7 
* 1. Redistributions of source code must retain the above copyright 

8 
* notice, this list of conditions, the following disclaimer, 

9 
* and the original OpenSSL and SSLeay Licences below. 

10 
* 

11 
* 2. Redistributions in binary form must reproduce the above copyright 

12 
* notice, this list of conditions, the following disclaimer 

13 
* and the original OpenSSL and SSLeay Licences below in 

14 
* the documentation and/or other materials provided with the 

15 
* distribution. 

16 
* 

17 
* 3. All advertising materials mentioning features or use of this 

18 
* software must display the following acknowledgments: 

19 
* "This product includes software developed by the Openevidence Project 

20 
* for use in the OpenEvidence Toolkit. (http://www.openevidence.org/)" 

21 
* This product includes software developed by the OpenSSL Project 

22 
* for use in the OpenSSL Toolkit (http://www.openssl.org/)" 

23 
* This product includes cryptographic software written by Eric Young 

24 
* (eay@cryptsoft.com). This product includes software written by Tim 

25 
* Hudson (tjh@cryptsoft.com)." 

26 
* 

27 
* 4. The names "OpenEvidence Toolkit" and "OpenEvidence Project" must not be 

28 
* used to endorse or promote products derived from this software without 

29 
* prior written permission. For written permission, please contact 

30 
* openevidencecore@openevidence.org. 

31 
* 

32 
* 5. Products derived from this software may not be called "OpenEvidence" 

33 
* nor may "OpenEvidence" appear in their names without prior written 

34 
* permission of the OpenEvidence Project. 

35 
* 

36 
* 6. Redistributions of any form whatsoever must retain the following 

37 
* acknowledgments: 

38 
* "This product includes software developed by the OpenEvidence Project 

39 
* for use in the OpenEvidence Toolkit (http://www.openevidence.org/) 

40 
* This product includes software developed by the OpenSSL Project 

41 
* for use in the OpenSSL Toolkit (http://www.openssl.org/)" 

42 
* This product includes cryptographic software written by Eric Young 

43 
* (eay@cryptsoft.com). This product includes software written by Tim 

44 
* Hudson (tjh@cryptsoft.com)." 

45 
* 

46 
* THIS SOFTWARE IS PROVIDED BY THE OpenEvidence PROJECT ``AS IS'' AND ANY 

47 
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 

48 
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 

49 
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenEvidence PROJECT OR 

50 
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 

51 
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 

52 
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

53 
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 

54 
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 

55 
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 

56 
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 

57 
* OF THE POSSIBILITY OF SUCH DAMAGE. 

58 
* ==================================================================== 

59 
* 

60 
* This product includes software developed by the OpenSSL Project 

61 
* for use in the OpenSSL Toolkit (http://www.openssl.org/)" 

62 
* This product includes cryptographic software written by Eric Young 

63 
* (eay@cryptsoft.com). This product includes software written by Tim 

64 
* Hudson (tjh@cryptsoft.com). 

65 
*/ 

66 


67 
#include <time.h> 

68 
#include <openssl/x509.h> 

69 


70 
static char days[2][12] = { 

71 
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, 

72 
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } 

73 
}; 

74 


75 
static int pint(const char **s, int n, int min, int max, int *e) 

76 
{ 

77 
int retval = 0; 

78 
while (n) { 

79 
if (**s < '0'  **s > '9') { *e = 1; return 0; } 

80 
retval *= 10; 

81 
retval += **s  '0'; 

82 
n; ++(*s); 

83 
} 

84 
if (retval < min  retval > max) *e = 1; 

85 
return retval; 

86 
} 

87 


88 
time_t OETS_ASN1_TIME_get(ASN1_TIME *a, int *err) 

89 
{ 

90 
int dummy; 

91 
const char *s; 

92 
int generalized; 

93 
struct tm t; 

94 
int i, year, isleap, offset; 

95 
time_t retval; 

96 


97 
if (err == NULL) err = &dummy; 

98 
if (a>type == V_ASN1_GENERALIZEDTIME) { 

99 
generalized = 1; 

100 
} else if (a>type == V_ASN1_UTCTIME) { 

101 
generalized = 0; 

102 
} else { 

103 
*err = 1; 

104 
return 0; 

105 
} 

106 
s = (char *)a>data; // Data should be always null terminated 

107 
if (s == NULL  s[a>length] != '\0') { 

108 
*err = 1; 

109 
return 0; 

110 
} 

111 


112 
*err = 0; 

113 
if (generalized) { 

114 
t.tm_year = pint(&s, 4, 0, 9999, err)  1900; 

115 
} else { 

116 
t.tm_year = pint(&s, 2, 0, 99, err); 

117 
if (t.tm_year < 50) t.tm_year += 100; 

118 
} 

119 
t.tm_mon = pint(&s, 2, 1, 12, err)  1; 

120 
t.tm_mday = pint(&s, 2, 1, 31, err); 

121 
// NOTE: It's not yet clear, if this implementation is 100% correct 

122 
// for GeneralizedTime... but at least misinterpretation is 

123 
// impossible  we just throw an exception 

124 
t.tm_hour = pint(&s, 2, 0, 23, err); 

125 
t.tm_min = pint(&s, 2, 0, 59, err); 

126 
if (*s >= '0' && *s <= '9') { 

127 
t.tm_sec = pint(&s, 2, 0, 59, err); 

128 
} else { 

129 
t.tm_sec = 0; 

130 
} 

131 
if (*err) return 0; // Format violation 

132 
if (generalized) { 

133 
// skip fractional seconds if any 

134 
while (*s == '.'  *s == ','  (*s >= '0' && *s <= '9')) ++s; 

135 
// special treatment for local time 

136 
if (*s == 0) { 

137 
t.tm_isdst = 1; 

138 
retval = mktime(&t); // Local time is easy :) 

139 
if (retval == (time_t)1) { 

140 
*err = 2; 

141 
retval = 0; 

142 
} 

143 
return retval; 

144 
} 

145 
} 

146 
if (*s == 'Z') { 

147 
offset = 0; 

148 
++s; 

149 
} else if (*s == ''  *s == '+') { 

150 
i = (*s++ == ''); 

151 
offset = pint(&s, 2, 0, 12, err); 

152 
offset *= 60; 

153 
offset += pint(&s, 2, 0, 59, err); 

154 
if (*err) return 0; // Format violation 

155 
if (i) offset = offset; 

156 
} else { 

157 
*err = 1; 

158 
return 0; 

159 
} 

160 
if (*s) { 

161 
*err = 1; 

162 
return 0; 

163 
} 

164 


165 
// And here comes the hard part  there's no standard function to 

166 
// convert struct tm containing UTC time into time_t without 

167 
// messing global timezone settings (breaks multithreading and may 

168 
// cause other problems) and thus we have to do this "by hand" 

169 
// 

170 
// NOTE: Overflow check does not detect too big overflows, but is 

171 
// sufficient thanks to the fact that year numbers are limited to four 

172 
// digit nonnegative values. 

173 
retval = t.tm_sec; 

174 
retval += (t.tm_min  offset) * 60; 

175 
retval += t.tm_hour * 3600; 

176 
retval += (t.tm_mday  1) * 86400; 

177 
year = t.tm_year + 1900; 

178 
if (sizeof(time_t) == 4) { 

179 
// This is just to avoid too big overflows being undetected, finer 

180 
// overflow detection is done below. 

181 
if (year < 1900  year > 2040) *err = 2; 

182 
} 

183 
// FIXME: Does POSIX really say, that all years divisible by 4 are 

184 
// leap years (for consistency)??? Fortunately, this problem does 

185 
// not exist for 32bit time_t and we should'nt be worried about 

186 
// this until the year of 2100 :) 

187 
isleap = ((year % 4 == 0) && (year % 100 != 0))  (year % 400 == 0); 

188 
for (i = t.tm_mon  1; i >= 0; i) retval += days[isleap][i] * 86400; 

189 
retval += (year  1970) * 31536000; 

190 
if (year < 1970) { 

191 
retval = ((1970  year + 2) / 4) * 86400; 

192 
if (sizeof(time_t) > 4) { 

193 
for (i = 1900; i >= year; i = 100) { 

194 
if (i % 400 == 0) continue; 

195 
retval += 86400; 

196 
} 

197 
} 

198 
if (retval >= 0) *err = 2; 

199 
} else { 

200 
retval += ((year  1970 + 1) / 4) * 86400; 

201 
if (sizeof(time_t) > 4) { 

202 
for (i = 2100; i < year; i += 100) { 

203 
// The following condition is the reason to 

204 
// start with 2100 instead of 2000 

205 
if (i % 400 == 0) continue; 

206 
retval = 86400; 

207 
} 

208 
} 

209 
if (retval < 0) *err = 2; 

210 
} 

211 


212 
if (*err) retval = 0; 

213 
return retval; 

214 
} 
