a_time.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  1. /*
  2. * Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. /*-
  10. * This is an implementation of the ASN1 Time structure which is:
  11. * Time ::= CHOICE {
  12. * utcTime UTCTime,
  13. * generalTime GeneralizedTime }
  14. */
  15. #include <stdio.h>
  16. #include <time.h>
  17. #include "crypto/asn1.h"
  18. #include "crypto/ctype.h"
  19. #include "internal/cryptlib.h"
  20. #include <openssl/asn1t.h>
  21. #include "asn1_local.h"
  22. IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME)
  23. IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME)
  24. IMPLEMENT_ASN1_DUP_FUNCTION(ASN1_TIME)
  25. static int is_utc(const int year)
  26. {
  27. if (50 <= year && year <= 149)
  28. return 1;
  29. return 0;
  30. }
  31. static int leap_year(const int year)
  32. {
  33. if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
  34. return 1;
  35. return 0;
  36. }
  37. /*
  38. * Compute the day of the week and the day of the year from the year, month
  39. * and day. The day of the year is straightforward, the day of the week uses
  40. * a form of Zeller's congruence. For this months start with March and are
  41. * numbered 4 through 15.
  42. */
  43. static void determine_days(struct tm *tm)
  44. {
  45. static const int ydays[12] = {
  46. 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
  47. };
  48. int y = tm->tm_year + 1900;
  49. int m = tm->tm_mon;
  50. int d = tm->tm_mday;
  51. int c;
  52. tm->tm_yday = ydays[m] + d - 1;
  53. if (m >= 2) {
  54. /* March and onwards can be one day further into the year */
  55. tm->tm_yday += leap_year(y);
  56. m += 2;
  57. } else {
  58. /* Treat January and February as part of the previous year */
  59. m += 14;
  60. y--;
  61. }
  62. c = y / 100;
  63. y %= 100;
  64. /* Zeller's congruence */
  65. tm->tm_wday = (d + (13 * m) / 5 + y + y / 4 + c / 4 + 5 * c + 6) % 7;
  66. }
  67. int ossl_asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
  68. {
  69. static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 };
  70. static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 };
  71. static const int mdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  72. char *a;
  73. int n, i, i2, l, o, min_l = 11, strict = 0, end = 6, btz = 5, md;
  74. struct tm tmp;
  75. #if defined(CHARSET_EBCDIC)
  76. const char upper_z = 0x5A, num_zero = 0x30, period = 0x2E, minus = 0x2D, plus = 0x2B;
  77. #else
  78. const char upper_z = 'Z', num_zero = '0', period = '.', minus = '-', plus = '+';
  79. #endif
  80. /*
  81. * ASN1_STRING_FLAG_X509_TIME is used to enforce RFC 5280
  82. * time string format, in which:
  83. *
  84. * 1. "seconds" is a 'MUST'
  85. * 2. "Zulu" timezone is a 'MUST'
  86. * 3. "+|-" is not allowed to indicate a timezone
  87. */
  88. if (d->type == V_ASN1_UTCTIME) {
  89. if (d->flags & ASN1_STRING_FLAG_X509_TIME) {
  90. min_l = 13;
  91. strict = 1;
  92. }
  93. } else if (d->type == V_ASN1_GENERALIZEDTIME) {
  94. end = 7;
  95. btz = 6;
  96. if (d->flags & ASN1_STRING_FLAG_X509_TIME) {
  97. min_l = 15;
  98. strict = 1;
  99. } else {
  100. min_l = 13;
  101. }
  102. } else {
  103. return 0;
  104. }
  105. l = d->length;
  106. a = (char *)d->data;
  107. o = 0;
  108. memset(&tmp, 0, sizeof(tmp));
  109. /*
  110. * GENERALIZEDTIME is similar to UTCTIME except the year is represented
  111. * as YYYY. This stuff treats everything as a two digit field so make
  112. * first two fields 00 to 99
  113. */
  114. if (l < min_l)
  115. goto err;
  116. for (i = 0; i < end; i++) {
  117. if (!strict && (i == btz) && ((a[o] == upper_z) || (a[o] == plus) || (a[o] == minus))) {
  118. i++;
  119. break;
  120. }
  121. if (!ossl_ascii_isdigit(a[o]))
  122. goto err;
  123. n = a[o] - num_zero;
  124. /* incomplete 2-digital number */
  125. if (++o == l)
  126. goto err;
  127. if (!ossl_ascii_isdigit(a[o]))
  128. goto err;
  129. n = (n * 10) + a[o] - num_zero;
  130. /* no more bytes to read, but we haven't seen time-zone yet */
  131. if (++o == l)
  132. goto err;
  133. i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i;
  134. if ((n < min[i2]) || (n > max[i2]))
  135. goto err;
  136. switch (i2) {
  137. case 0:
  138. /* UTC will never be here */
  139. tmp.tm_year = n * 100 - 1900;
  140. break;
  141. case 1:
  142. if (d->type == V_ASN1_UTCTIME)
  143. tmp.tm_year = n < 50 ? n + 100 : n;
  144. else
  145. tmp.tm_year += n;
  146. break;
  147. case 2:
  148. tmp.tm_mon = n - 1;
  149. break;
  150. case 3:
  151. /* check if tm_mday is valid in tm_mon */
  152. if (tmp.tm_mon == 1) {
  153. /* it's February */
  154. md = mdays[1] + leap_year(tmp.tm_year + 1900);
  155. } else {
  156. md = mdays[tmp.tm_mon];
  157. }
  158. if (n > md)
  159. goto err;
  160. tmp.tm_mday = n;
  161. determine_days(&tmp);
  162. break;
  163. case 4:
  164. tmp.tm_hour = n;
  165. break;
  166. case 5:
  167. tmp.tm_min = n;
  168. break;
  169. case 6:
  170. tmp.tm_sec = n;
  171. break;
  172. }
  173. }
  174. /*
  175. * Optional fractional seconds: decimal point followed by one or more
  176. * digits.
  177. */
  178. if (d->type == V_ASN1_GENERALIZEDTIME && a[o] == period) {
  179. if (strict)
  180. /* RFC 5280 forbids fractional seconds */
  181. goto err;
  182. if (++o == l)
  183. goto err;
  184. i = o;
  185. while ((o < l) && ossl_ascii_isdigit(a[o]))
  186. o++;
  187. /* Must have at least one digit after decimal point */
  188. if (i == o)
  189. goto err;
  190. /* no more bytes to read, but we haven't seen time-zone yet */
  191. if (o == l)
  192. goto err;
  193. }
  194. /*
  195. * 'o' will never point to '\0' at this point, the only chance
  196. * 'o' can point to '\0' is either the subsequent if or the first
  197. * else if is true.
  198. */
  199. if (a[o] == upper_z) {
  200. o++;
  201. } else if (!strict && ((a[o] == plus) || (a[o] == minus))) {
  202. int offsign = a[o] == minus ? 1 : -1;
  203. int offset = 0;
  204. o++;
  205. /*
  206. * if not equal, no need to do subsequent checks
  207. * since the following for-loop will add 'o' by 4
  208. * and the final return statement will check if 'l'
  209. * and 'o' are equal.
  210. */
  211. if (o + 4 != l)
  212. goto err;
  213. for (i = end; i < end + 2; i++) {
  214. if (!ossl_ascii_isdigit(a[o]))
  215. goto err;
  216. n = a[o] - num_zero;
  217. o++;
  218. if (!ossl_ascii_isdigit(a[o]))
  219. goto err;
  220. n = (n * 10) + a[o] - num_zero;
  221. i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i;
  222. if ((n < min[i2]) || (n > max[i2]))
  223. goto err;
  224. /* if tm is NULL, no need to adjust */
  225. if (tm != NULL) {
  226. if (i == end)
  227. offset = n * 3600;
  228. else if (i == end + 1)
  229. offset += n * 60;
  230. }
  231. o++;
  232. }
  233. if (offset && !OPENSSL_gmtime_adj(&tmp, 0, offset * offsign))
  234. goto err;
  235. } else {
  236. /* not Z, or not +/- in non-strict mode */
  237. goto err;
  238. }
  239. if (o == l) {
  240. /* success, check if tm should be filled */
  241. if (tm != NULL)
  242. *tm = tmp;
  243. return 1;
  244. }
  245. err:
  246. return 0;
  247. }
  248. ASN1_TIME *ossl_asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type)
  249. {
  250. char* p;
  251. ASN1_TIME *tmps = NULL;
  252. const size_t len = 20;
  253. if (type == V_ASN1_UNDEF) {
  254. if (is_utc(ts->tm_year))
  255. type = V_ASN1_UTCTIME;
  256. else
  257. type = V_ASN1_GENERALIZEDTIME;
  258. } else if (type == V_ASN1_UTCTIME) {
  259. if (!is_utc(ts->tm_year))
  260. goto err;
  261. } else if (type != V_ASN1_GENERALIZEDTIME) {
  262. goto err;
  263. }
  264. if (s == NULL)
  265. tmps = ASN1_STRING_new();
  266. else
  267. tmps = s;
  268. if (tmps == NULL)
  269. return NULL;
  270. if (!ASN1_STRING_set(tmps, NULL, len))
  271. goto err;
  272. tmps->type = type;
  273. p = (char*)tmps->data;
  274. if (type == V_ASN1_GENERALIZEDTIME)
  275. tmps->length = BIO_snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ",
  276. ts->tm_year + 1900, ts->tm_mon + 1,
  277. ts->tm_mday, ts->tm_hour, ts->tm_min,
  278. ts->tm_sec);
  279. else
  280. tmps->length = BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ",
  281. ts->tm_year % 100, ts->tm_mon + 1,
  282. ts->tm_mday, ts->tm_hour, ts->tm_min,
  283. ts->tm_sec);
  284. #ifdef CHARSET_EBCDIC
  285. ebcdic2ascii(tmps->data, tmps->data, tmps->length);
  286. #endif
  287. return tmps;
  288. err:
  289. if (tmps != s)
  290. ASN1_STRING_free(tmps);
  291. return NULL;
  292. }
  293. ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t)
  294. {
  295. return ASN1_TIME_adj(s, t, 0, 0);
  296. }
  297. ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t,
  298. int offset_day, long offset_sec)
  299. {
  300. struct tm *ts;
  301. struct tm data;
  302. ts = OPENSSL_gmtime(&t, &data);
  303. if (ts == NULL) {
  304. ERR_raise(ERR_LIB_ASN1, ASN1_R_ERROR_GETTING_TIME);
  305. return NULL;
  306. }
  307. if (offset_day || offset_sec) {
  308. if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
  309. return NULL;
  310. }
  311. return ossl_asn1_time_from_tm(s, ts, V_ASN1_UNDEF);
  312. }
  313. int ASN1_TIME_check(const ASN1_TIME *t)
  314. {
  315. if (t->type == V_ASN1_GENERALIZEDTIME)
  316. return ASN1_GENERALIZEDTIME_check(t);
  317. else if (t->type == V_ASN1_UTCTIME)
  318. return ASN1_UTCTIME_check(t);
  319. return 0;
  320. }
  321. /* Convert an ASN1_TIME structure to GeneralizedTime */
  322. ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t,
  323. ASN1_GENERALIZEDTIME **out)
  324. {
  325. ASN1_GENERALIZEDTIME *ret = NULL;
  326. struct tm tm;
  327. if (!ASN1_TIME_to_tm(t, &tm))
  328. return NULL;
  329. if (out != NULL)
  330. ret = *out;
  331. ret = ossl_asn1_time_from_tm(ret, &tm, V_ASN1_GENERALIZEDTIME);
  332. if (out != NULL && ret != NULL)
  333. *out = ret;
  334. return ret;
  335. }
  336. int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
  337. {
  338. /* Try UTC, if that fails, try GENERALIZED */
  339. if (ASN1_UTCTIME_set_string(s, str))
  340. return 1;
  341. return ASN1_GENERALIZEDTIME_set_string(s, str);
  342. }
  343. int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str)
  344. {
  345. ASN1_TIME t;
  346. struct tm tm;
  347. int rv = 0;
  348. t.length = strlen(str);
  349. t.data = (unsigned char *)str;
  350. t.flags = ASN1_STRING_FLAG_X509_TIME;
  351. t.type = V_ASN1_UTCTIME;
  352. if (!ASN1_TIME_check(&t)) {
  353. t.type = V_ASN1_GENERALIZEDTIME;
  354. if (!ASN1_TIME_check(&t))
  355. goto out;
  356. }
  357. /*
  358. * Per RFC 5280 (section 4.1.2.5.), the valid input time
  359. * strings should be encoded with the following rules:
  360. *
  361. * 1. UTC: YYMMDDHHMMSSZ, if YY < 50 (20YY) --> UTC: YYMMDDHHMMSSZ
  362. * 2. UTC: YYMMDDHHMMSSZ, if YY >= 50 (19YY) --> UTC: YYMMDDHHMMSSZ
  363. * 3. G'd: YYYYMMDDHHMMSSZ, if YYYY >= 2050 --> G'd: YYYYMMDDHHMMSSZ
  364. * 4. G'd: YYYYMMDDHHMMSSZ, if YYYY < 2050 --> UTC: YYMMDDHHMMSSZ
  365. *
  366. * Only strings of the 4th rule should be reformatted, but since a
  367. * UTC can only present [1950, 2050), so if the given time string
  368. * is less than 1950 (e.g. 19230419000000Z), we do nothing...
  369. */
  370. if (s != NULL && t.type == V_ASN1_GENERALIZEDTIME) {
  371. if (!ossl_asn1_time_to_tm(&tm, &t))
  372. goto out;
  373. if (is_utc(tm.tm_year)) {
  374. t.length -= 2;
  375. /*
  376. * it's OK to let original t.data go since that's assigned
  377. * to a piece of memory allocated outside of this function.
  378. * new t.data would be freed after ASN1_STRING_copy is done.
  379. */
  380. t.data = OPENSSL_zalloc(t.length + 1);
  381. if (t.data == NULL)
  382. goto out;
  383. memcpy(t.data, str + 2, t.length);
  384. t.type = V_ASN1_UTCTIME;
  385. }
  386. }
  387. if (s == NULL || ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t))
  388. rv = 1;
  389. if (t.data != (unsigned char *)str)
  390. OPENSSL_free(t.data);
  391. out:
  392. return rv;
  393. }
  394. int ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm)
  395. {
  396. if (s == NULL) {
  397. time_t now_t;
  398. time(&now_t);
  399. memset(tm, 0, sizeof(*tm));
  400. if (OPENSSL_gmtime(&now_t, tm) != NULL)
  401. return 1;
  402. return 0;
  403. }
  404. return ossl_asn1_time_to_tm(tm, s);
  405. }
  406. int ASN1_TIME_diff(int *pday, int *psec,
  407. const ASN1_TIME *from, const ASN1_TIME *to)
  408. {
  409. struct tm tm_from, tm_to;
  410. if (!ASN1_TIME_to_tm(from, &tm_from))
  411. return 0;
  412. if (!ASN1_TIME_to_tm(to, &tm_to))
  413. return 0;
  414. return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to);
  415. }
  416. static const char _asn1_mon[12][4] = {
  417. "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  418. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  419. };
  420. /* prints the time with the default date format (RFC 822) */
  421. int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
  422. {
  423. return ASN1_TIME_print_ex(bp, tm, ASN1_DTFLGS_RFC822);
  424. }
  425. /* returns 1 on success, 0 on BIO write error or parse failure */
  426. int ASN1_TIME_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags)
  427. {
  428. return ossl_asn1_time_print_ex(bp, tm, flags) > 0;
  429. }
  430. /* prints the time with the date format of ISO 8601 */
  431. /* returns 0 on BIO write error, else -1 in case of parse failure, else 1 */
  432. int ossl_asn1_time_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags)
  433. {
  434. char *v;
  435. int gmt = 0, l;
  436. struct tm stm;
  437. const char upper_z = 0x5A, period = 0x2E;
  438. /* ossl_asn1_time_to_tm will check the time type */
  439. if (!ossl_asn1_time_to_tm(&stm, tm))
  440. return BIO_write(bp, "Bad time value", 14) ? -1 : 0;
  441. l = tm->length;
  442. v = (char *)tm->data;
  443. if (v[l - 1] == upper_z)
  444. gmt = 1;
  445. if (tm->type == V_ASN1_GENERALIZEDTIME) {
  446. char *f = NULL;
  447. int f_len = 0;
  448. /*
  449. * Try to parse fractional seconds. '14' is the place of
  450. * 'fraction point' in a GeneralizedTime string.
  451. */
  452. if (tm->length > 15 && v[14] == period) {
  453. f = &v[14];
  454. f_len = 1;
  455. while (14 + f_len < l && ossl_ascii_isdigit(f[f_len]))
  456. ++f_len;
  457. }
  458. if ((flags & ASN1_DTFLGS_TYPE_MASK) == ASN1_DTFLGS_ISO8601) {
  459. return BIO_printf(bp, "%4d-%02d-%02d %02d:%02d:%02d%.*s%s",
  460. stm.tm_year + 1900, stm.tm_mon + 1,
  461. stm.tm_mday, stm.tm_hour,
  462. stm.tm_min, stm.tm_sec, f_len, f,
  463. (gmt ? "Z" : "")) > 0;
  464. }
  465. else {
  466. return BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s",
  467. _asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour,
  468. stm.tm_min, stm.tm_sec, f_len, f, stm.tm_year + 1900,
  469. (gmt ? " GMT" : "")) > 0;
  470. }
  471. } else {
  472. if ((flags & ASN1_DTFLGS_TYPE_MASK) == ASN1_DTFLGS_ISO8601) {
  473. return BIO_printf(bp, "%4d-%02d-%02d %02d:%02d:%02d%s",
  474. stm.tm_year + 1900, stm.tm_mon + 1,
  475. stm.tm_mday, stm.tm_hour,
  476. stm.tm_min, stm.tm_sec,
  477. (gmt ? "Z" : "")) > 0;
  478. }
  479. else {
  480. return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s",
  481. _asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour,
  482. stm.tm_min, stm.tm_sec, stm.tm_year + 1900,
  483. (gmt ? " GMT" : "")) > 0;
  484. }
  485. }
  486. }
  487. int ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t)
  488. {
  489. struct tm stm, ttm;
  490. int day, sec;
  491. if (!ASN1_TIME_to_tm(s, &stm))
  492. return -2;
  493. if (!OPENSSL_gmtime(&t, &ttm))
  494. return -2;
  495. if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
  496. return -2;
  497. if (day > 0 || sec > 0)
  498. return 1;
  499. if (day < 0 || sec < 0)
  500. return -1;
  501. return 0;
  502. }
  503. int ASN1_TIME_normalize(ASN1_TIME *t)
  504. {
  505. struct tm tm;
  506. if (t == NULL || !ASN1_TIME_to_tm(t, &tm))
  507. return 0;
  508. return ossl_asn1_time_from_tm(t, &tm, V_ASN1_UNDEF) != NULL;
  509. }
  510. int ASN1_TIME_compare(const ASN1_TIME *a, const ASN1_TIME *b)
  511. {
  512. int day, sec;
  513. if (!ASN1_TIME_diff(&day, &sec, b, a))
  514. return -2;
  515. if (day > 0 || sec > 0)
  516. return 1;
  517. if (day < 0 || sec < 0)
  518. return -1;
  519. return 0;
  520. }
  521. /*
  522. * tweak for Windows
  523. */
  524. #ifdef WIN32
  525. # define timezone _timezone
  526. #endif
  527. #if defined(__FreeBSD__) || defined(__wasi__)
  528. # define USE_TIMEGM
  529. #endif
  530. time_t ossl_asn1_string_to_time_t(const char *asn1_string)
  531. {
  532. ASN1_TIME *timestamp_asn1 = NULL;
  533. struct tm *timestamp_tm = NULL;
  534. #if defined(__DJGPP__)
  535. char *tz = NULL;
  536. #elif !defined(USE_TIMEGM)
  537. time_t timestamp_local;
  538. #endif
  539. time_t timestamp_utc;
  540. timestamp_asn1 = ASN1_TIME_new();
  541. if (!ASN1_TIME_set_string(timestamp_asn1, asn1_string))
  542. {
  543. ASN1_TIME_free(timestamp_asn1);
  544. return -1;
  545. }
  546. timestamp_tm = OPENSSL_malloc(sizeof(*timestamp_tm));
  547. if (timestamp_tm == NULL) {
  548. ASN1_TIME_free(timestamp_asn1);
  549. return -1;
  550. }
  551. if (!(ASN1_TIME_to_tm(timestamp_asn1, timestamp_tm))) {
  552. OPENSSL_free(timestamp_tm);
  553. ASN1_TIME_free(timestamp_asn1);
  554. return -1;
  555. }
  556. ASN1_TIME_free(timestamp_asn1);
  557. #if defined(__DJGPP__)
  558. /*
  559. * This is NOT thread-safe. Do not use this method for platforms other
  560. * than djgpp.
  561. */
  562. tz = getenv("TZ");
  563. if (tz != NULL) {
  564. tz = OPENSSL_strdup(tz);
  565. if (tz == NULL) {
  566. OPENSSL_free(timestamp_tm);
  567. return -1;
  568. }
  569. }
  570. setenv("TZ", "UTC", 1);
  571. timestamp_utc = mktime(timestamp_tm);
  572. if (tz != NULL) {
  573. setenv("TZ", tz, 1);
  574. OPENSSL_free(tz);
  575. } else {
  576. unsetenv("TZ");
  577. }
  578. #elif defined(USE_TIMEGM)
  579. timestamp_utc = timegm(timestamp_tm);
  580. #else
  581. timestamp_local = mktime(timestamp_tm);
  582. timestamp_utc = timestamp_local - timezone;
  583. #endif
  584. OPENSSL_free(timestamp_tm);
  585. return timestamp_utc;
  586. }