A local copy of OpenSSL from GitHub
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

267 lines
7.1 KiB

  1. /*
  2. * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the OpenSSL license (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. * GENERALIZEDTIME implementation. Based on UTCTIME
  11. */
  12. #include <stdio.h>
  13. #include <time.h>
  14. #include "internal/cryptlib.h"
  15. #include <openssl/asn1.h>
  16. #include "asn1_locl.h"
  17. int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d)
  18. {
  19. static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 };
  20. static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 };
  21. char *a;
  22. int n, i, l, o;
  23. if (d->type != V_ASN1_GENERALIZEDTIME)
  24. return (0);
  25. l = d->length;
  26. a = (char *)d->data;
  27. o = 0;
  28. /*
  29. * GENERALIZEDTIME is similar to UTCTIME except the year is represented
  30. * as YYYY. This stuff treats everything as a two digit field so make
  31. * first two fields 00 to 99
  32. */
  33. if (l < 13)
  34. goto err;
  35. for (i = 0; i < 7; i++) {
  36. if ((i == 6) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
  37. i++;
  38. if (tm)
  39. tm->tm_sec = 0;
  40. break;
  41. }
  42. if ((a[o] < '0') || (a[o] > '9'))
  43. goto err;
  44. n = a[o] - '0';
  45. if (++o > l)
  46. goto err;
  47. if ((a[o] < '0') || (a[o] > '9'))
  48. goto err;
  49. n = (n * 10) + a[o] - '0';
  50. if (++o > l)
  51. goto err;
  52. if ((n < min[i]) || (n > max[i]))
  53. goto err;
  54. if (tm) {
  55. switch (i) {
  56. case 0:
  57. tm->tm_year = n * 100 - 1900;
  58. break;
  59. case 1:
  60. tm->tm_year += n;
  61. break;
  62. case 2:
  63. tm->tm_mon = n - 1;
  64. break;
  65. case 3:
  66. tm->tm_mday = n;
  67. break;
  68. case 4:
  69. tm->tm_hour = n;
  70. break;
  71. case 5:
  72. tm->tm_min = n;
  73. break;
  74. case 6:
  75. tm->tm_sec = n;
  76. break;
  77. }
  78. }
  79. }
  80. /*
  81. * Optional fractional seconds: decimal point followed by one or more
  82. * digits.
  83. */
  84. if (a[o] == '.') {
  85. if (++o > l)
  86. goto err;
  87. i = o;
  88. while ((a[o] >= '0') && (a[o] <= '9') && (o <= l))
  89. o++;
  90. /* Must have at least one digit after decimal point */
  91. if (i == o)
  92. goto err;
  93. }
  94. if (a[o] == 'Z')
  95. o++;
  96. else if ((a[o] == '+') || (a[o] == '-')) {
  97. int offsign = a[o] == '-' ? -1 : 1, offset = 0;
  98. o++;
  99. if (o + 4 > l)
  100. goto err;
  101. for (i = 7; i < 9; i++) {
  102. if ((a[o] < '0') || (a[o] > '9'))
  103. goto err;
  104. n = a[o] - '0';
  105. o++;
  106. if ((a[o] < '0') || (a[o] > '9'))
  107. goto err;
  108. n = (n * 10) + a[o] - '0';
  109. if ((n < min[i]) || (n > max[i]))
  110. goto err;
  111. if (tm) {
  112. if (i == 7)
  113. offset = n * 3600;
  114. else if (i == 8)
  115. offset += n * 60;
  116. }
  117. o++;
  118. }
  119. if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
  120. return 0;
  121. } else if (a[o]) {
  122. /* Missing time zone information. */
  123. goto err;
  124. }
  125. return (o == l);
  126. err:
  127. return (0);
  128. }
  129. int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d)
  130. {
  131. return asn1_generalizedtime_to_tm(NULL, d);
  132. }
  133. int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str)
  134. {
  135. ASN1_GENERALIZEDTIME t;
  136. t.type = V_ASN1_GENERALIZEDTIME;
  137. t.length = strlen(str);
  138. t.data = (unsigned char *)str;
  139. if (ASN1_GENERALIZEDTIME_check(&t)) {
  140. if (s != NULL) {
  141. if (!ASN1_STRING_set((ASN1_STRING *)s,
  142. (unsigned char *)str, t.length))
  143. return 0;
  144. s->type = V_ASN1_GENERALIZEDTIME;
  145. }
  146. return (1);
  147. } else
  148. return (0);
  149. }
  150. ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,
  151. time_t t)
  152. {
  153. return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0);
  154. }
  155. ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
  156. time_t t, int offset_day,
  157. long offset_sec)
  158. {
  159. char *p;
  160. struct tm *ts;
  161. struct tm data;
  162. size_t len = 20;
  163. if (s == NULL)
  164. s = ASN1_GENERALIZEDTIME_new();
  165. if (s == NULL)
  166. return (NULL);
  167. ts = OPENSSL_gmtime(&t, &data);
  168. if (ts == NULL)
  169. return (NULL);
  170. if (offset_day || offset_sec) {
  171. if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
  172. return NULL;
  173. }
  174. p = (char *)s->data;
  175. if ((p == NULL) || ((size_t)s->length < len)) {
  176. p = OPENSSL_malloc(len);
  177. if (p == NULL) {
  178. ASN1err(ASN1_F_ASN1_GENERALIZEDTIME_ADJ, ERR_R_MALLOC_FAILURE);
  179. return (NULL);
  180. }
  181. OPENSSL_free(s->data);
  182. s->data = (unsigned char *)p;
  183. }
  184. BIO_snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ", ts->tm_year + 1900,
  185. ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min,
  186. ts->tm_sec);
  187. s->length = strlen(p);
  188. s->type = V_ASN1_GENERALIZEDTIME;
  189. #ifdef CHARSET_EBCDIC_not
  190. ebcdic2ascii(s->data, s->data, s->length);
  191. #endif
  192. return (s);
  193. }
  194. const char *_asn1_mon[12] = {
  195. "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  196. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  197. };
  198. int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm)
  199. {
  200. char *v;
  201. int gmt = 0;
  202. int i;
  203. int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0;
  204. char *f = NULL;
  205. int f_len = 0;
  206. i = tm->length;
  207. v = (char *)tm->data;
  208. if (i < 12)
  209. goto err;
  210. if (v[i - 1] == 'Z')
  211. gmt = 1;
  212. for (i = 0; i < 12; i++)
  213. if ((v[i] > '9') || (v[i] < '0'))
  214. goto err;
  215. y = (v[0] - '0') * 1000 + (v[1] - '0') * 100
  216. + (v[2] - '0') * 10 + (v[3] - '0');
  217. M = (v[4] - '0') * 10 + (v[5] - '0');
  218. if ((M > 12) || (M < 1))
  219. goto err;
  220. d = (v[6] - '0') * 10 + (v[7] - '0');
  221. h = (v[8] - '0') * 10 + (v[9] - '0');
  222. m = (v[10] - '0') * 10 + (v[11] - '0');
  223. if (tm->length >= 14 &&
  224. (v[12] >= '0') && (v[12] <= '9') &&
  225. (v[13] >= '0') && (v[13] <= '9')) {
  226. s = (v[12] - '0') * 10 + (v[13] - '0');
  227. /* Check for fractions of seconds. */
  228. if (tm->length >= 15 && v[14] == '.') {
  229. int l = tm->length;
  230. f = &v[14]; /* The decimal point. */
  231. f_len = 1;
  232. while (14 + f_len < l && f[f_len] >= '0' && f[f_len] <= '9')
  233. ++f_len;
  234. }
  235. }
  236. if (BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s",
  237. _asn1_mon[M - 1], d, h, m, s, f_len, f, y,
  238. (gmt) ? " GMT" : "") <= 0)
  239. return (0);
  240. else
  241. return (1);
  242. err:
  243. BIO_write(bp, "Bad time value", 14);
  244. return (0);
  245. }