LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib/x509 - time.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 164 197 83.2 %
Date: 2020-10-30 04:50:48 Functions: 9 9 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2003-2016 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2016 Red Hat, Inc.
       4             :  *
       5             :  * Author: Nikos Mavrogiannopoulos
       6             :  *
       7             :  * This file is part of GnuTLS.
       8             :  *
       9             :  * The GnuTLS is free software; you can redistribute it and/or
      10             :  * modify it under the terms of the GNU Lesser General Public License
      11             :  * as published by the Free Software Foundation; either version 2.1 of
      12             :  * the License, or (at your option) any later version.
      13             :  *
      14             :  * This library is distributed in the hope that it will be useful, but
      15             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17             :  * Lesser General Public License for more details.
      18             :  *
      19             :  * You should have received a copy of the GNU Lesser General Public License
      20             :  * along with this program.  If not, see <https://www.gnu.org/licenses/>
      21             :  *
      22             :  */
      23             : 
      24             : #include "gnutls_int.h"
      25             : #include <libtasn1.h>
      26             : #include <datum.h>
      27             : #include <global.h>
      28             : #include "errors.h"
      29             : #include <str.h>
      30             : #include <x509.h>
      31             : #include <num.h>
      32             : #include <x509_b64.h>
      33             : #include "x509_int.h"
      34             : #include "extras/hex.h"
      35             : #include <common.h>
      36             : #include <c-ctype.h>
      37             : 
      38             : time_t _gnutls_utcTime2gtime(const char *ttime);
      39             : 
      40             : /* TIME functions
      41             :  * Conversions between generalized or UTC time to time_t
      42             :  *
      43             :  */
      44             : 
      45             : /* This is an emulation of the struct tm.
      46             :  * Since we do not use libc's functions, we don't need to
      47             :  * depend on the libc structure.
      48             :  */
      49             : typedef struct fake_tm {
      50             :         int tm_mon;
      51             :         int tm_year;            /* FULL year - ie 1971 */
      52             :         int tm_mday;
      53             :         int tm_hour;
      54             :         int tm_min;
      55             :         int tm_sec;
      56             : } fake_tm;
      57             : 
      58             : /* The mktime_utc function is due to Russ Allbery (rra@stanford.edu),
      59             :  * who placed it under public domain:
      60             :  */
      61             : 
      62             : /* The number of days in each month.
      63             :  */
      64             : static const int MONTHDAYS[] = {
      65             :         31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
      66             : };
      67             : 
      68             :     /* Whether a given year is a leap year. */
      69             : #define ISLEAP(year) \
      70             :         (((year) % 4) == 0 && (((year) % 100) != 0 || ((year) % 400) == 0))
      71             : 
      72             : /*
      73             :  **  Given a struct tm representing a calendar time in UTC, convert it to
      74             :  **  seconds since epoch.  Returns (time_t) -1 if the time is not
      75             :  **  convertible.  Note that this function does not canonicalize the provided
      76             :  **  struct tm, nor does it allow out of range values or years before 1970.
      77             :  */
      78       80301 : static time_t mktime_utc(const struct fake_tm *tm)
      79             : {
      80       80301 :         time_t result = 0;
      81       80301 :         int i;
      82             : 
      83             : /* We do allow some ill-formed dates, but we don't do anything special
      84             :  * with them and our callers really shouldn't pass them to us.  Do
      85             :  * explicitly disallow the ones that would cause invalid array accesses
      86             :  * or other algorithm problems.
      87             :  */
      88       80301 :         if (tm->tm_mon < 0 || tm->tm_mon > 11 || tm->tm_year < 1970)
      89             :                 return (time_t) - 1;
      90             : 
      91             :         /* Check for "obvious" mistakes in dates */
      92       80189 :         if (tm->tm_sec > 60 || tm->tm_min > 59 || tm->tm_mday > 31 || tm->tm_mday < 1 || tm->tm_hour > 23)
      93             :                 return (time_t) - 1;
      94             : 
      95             : /* Convert to a time_t.
      96             :  */
      97   127383000 :         for (i = 1970; i < tm->tm_year; i++)
      98   223722000 :                 result += 365 + ISLEAP(i);
      99      582412 :         for (i = 0; i < tm->tm_mon; i++)
     100      502320 :                 result += MONTHDAYS[i];
     101       80092 :         if (tm->tm_mon > 1 && ISLEAP(tm->tm_year))
     102       13860 :                 result++;
     103       80092 :         result = 24 * (result + tm->tm_mday - 1) + tm->tm_hour;
     104       80092 :         result = 60 * result + tm->tm_min;
     105       80092 :         result = 60 * result + tm->tm_sec;
     106       80092 :         return result;
     107             : }
     108             : 
     109             : 
     110             : /* this one will parse dates of the form:
     111             :  * month|day|hour|minute|sec* (2 chars each)
     112             :  * and year is given. Returns a time_t date.
     113             :  */
     114       80600 : static time_t time2gtime(const char *ttime, int year)
     115             : {
     116       80600 :         char xx[4];
     117       80600 :         struct fake_tm etime;
     118             : 
     119       80600 :         if (strlen(ttime) < 8) {
     120           0 :                 gnutls_assert();
     121           0 :                 return (time_t) - 1;
     122             :         }
     123             : 
     124       80600 :         etime.tm_year = year;
     125             : 
     126             :         /* In order to work with 32 bit
     127             :          * time_t.
     128             :          */
     129       80600 :         if (sizeof(time_t) <= 4 && etime.tm_year >= 2038)
     130             :                 return (time_t) 2145914603;     /* 2037-12-31 23:23:23 */
     131             : 
     132       80600 :         if (etime.tm_year < 1970)
     133             :                 return (time_t) 0;
     134             : 
     135       80301 :         xx[2] = 0;
     136             : 
     137             : /* get the month
     138             :  */
     139       80301 :         memcpy(xx, ttime, 2);   /* month */
     140       80301 :         etime.tm_mon = atoi(xx) - 1;
     141       80301 :         ttime += 2;
     142             : 
     143             : /* get the day
     144             :  */
     145       80301 :         memcpy(xx, ttime, 2);   /* day */
     146       80301 :         etime.tm_mday = atoi(xx);
     147       80301 :         ttime += 2;
     148             : 
     149             : /* get the hour
     150             :  */
     151       80301 :         memcpy(xx, ttime, 2);   /* hour */
     152       80301 :         etime.tm_hour = atoi(xx);
     153       80301 :         ttime += 2;
     154             : 
     155             : /* get the minutes
     156             :  */
     157       80301 :         memcpy(xx, ttime, 2);   /* minutes */
     158       80301 :         etime.tm_min = atoi(xx);
     159       80301 :         ttime += 2;
     160             : 
     161       80301 :         if (strlen(ttime) >= 2) {
     162       80271 :                 memcpy(xx, ttime, 2);
     163       80271 :                 etime.tm_sec = atoi(xx);
     164             :         } else
     165          30 :                 etime.tm_sec = 0;
     166             : 
     167       80301 :         return mktime_utc(&etime);
     168             : }
     169             : 
     170             : 
     171             : /* returns a time_t value that contains the given time.
     172             :  * The given time is expressed as:
     173             :  * YEAR(2)|MONTH(2)|DAY(2)|HOUR(2)|MIN(2)|SEC(2)*
     174             :  *
     175             :  * (seconds are optional)
     176             :  */
     177       55655 : time_t _gnutls_utcTime2gtime(const char *ttime)
     178             : {
     179       55655 :         char xx[3];
     180       55655 :         int year, i;
     181       55655 :         int len = strlen(ttime);
     182             : 
     183       55655 :         if (len < 10) {
     184           0 :                 gnutls_assert();
     185           0 :                 return (time_t) - 1;
     186             :         }
     187             : 
     188             : #ifdef STRICT_DER_TIME
     189             :         /* Make sure everything else is digits. */
     190      723490 :         for (i = 0; i < len - 1; i++) {
     191      667835 :                 if (c_isdigit(ttime[i]))
     192      667835 :                         continue;
     193           0 :                 return gnutls_assert_val((time_t)-1);
     194             :         }
     195             : #endif
     196       55655 :         xx[2] = 0;
     197             : 
     198             : /* get the year
     199             :  */
     200       55655 :         memcpy(xx, ttime, 2);   /* year */
     201       55655 :         year = atoi(xx);
     202       55655 :         ttime += 2;
     203             : 
     204       55655 :         if (year > 49)
     205        2503 :                 year += 1900;
     206             :         else
     207       53152 :                 year += 2000;
     208             : 
     209       55655 :         return time2gtime(ttime, year);
     210             : }
     211             : 
     212             : /* returns a time_t value that contains the given time.
     213             :  * The given time is expressed as:
     214             :  * YEAR(4)|MONTH(2)|DAY(2)|HOUR(2)|MIN(2)|SEC(2)*
     215             :  */
     216       24959 : time_t _gnutls_x509_generalTime2gtime(const char *ttime)
     217             : {
     218       24959 :         char xx[5];
     219       24959 :         int year;
     220             : 
     221       24959 :         if (strlen(ttime) < 12) {
     222           0 :                 gnutls_assert();
     223           0 :                 return (time_t) - 1;
     224             :         }
     225             : 
     226       24959 :         if (strchr(ttime, 'Z') == 0) {
     227           0 :                 gnutls_assert();
     228             :                 /* required to be in GMT */
     229           0 :                 return (time_t) - 1;
     230             :         }
     231             : 
     232       24959 :         if (strchr(ttime, '.') != 0) {
     233          14 :                 gnutls_assert();
     234             :                 /* no fractional seconds allowed */
     235          14 :                 return (time_t) - 1;
     236             :         }
     237       24945 :         xx[4] = 0;
     238             : 
     239             : /* get the year
     240             :  */
     241       24945 :         memcpy(xx, ttime, 4);   /* year */
     242       24945 :         year = atoi(xx);
     243       24945 :         ttime += 4;
     244             : 
     245       24945 :         return time2gtime(ttime, year);
     246             : }
     247             : 
     248             : #pragma GCC diagnostic push
     249             : #pragma GCC diagnostic ignored "-Wformat-y2k"
     250             : /* tag will contain ASN1_TAG_UTCTime or ASN1_TAG_GENERALIZEDTime */
     251             : static int
     252         829 : gtime_to_suitable_time(time_t gtime, char *str_time, size_t str_time_size, unsigned *tag)
     253             : {
     254         829 :         size_t ret;
     255         829 :         struct tm _tm;
     256             : 
     257         829 :         if (gtime == (time_t)-1
     258             : #if SIZEOF_LONG == 8
     259         829 :                 || gtime >= 253402210800
     260             : #endif
     261             :          ) {
     262           6 :                 if (tag)
     263           6 :                         *tag = ASN1_TAG_GENERALIZEDTime;
     264           6 :                 snprintf(str_time, str_time_size, "99991231235959Z");
     265           6 :                 return 0;
     266             :         }
     267             : 
     268         823 :         if (!gmtime_r(&gtime, &_tm)) {
     269           0 :                 gnutls_assert();
     270           0 :                 return GNUTLS_E_INTERNAL_ERROR;
     271             :         }
     272             : 
     273         823 :         if (_tm.tm_year >= 150) {
     274         157 :                 if (tag)
     275         157 :                         *tag = ASN1_TAG_GENERALIZEDTime;
     276         157 :                 ret = strftime(str_time, str_time_size, "%Y%m%d%H%M%SZ", &_tm);
     277             :         } else {
     278         666 :                 if (tag)
     279         666 :                         *tag = ASN1_TAG_UTCTime;
     280         666 :                 ret = strftime(str_time, str_time_size, "%y%m%d%H%M%SZ", &_tm);
     281             :         }
     282             : 
     283         823 :         if (!ret) {
     284           0 :                 gnutls_assert();
     285           0 :                 return GNUTLS_E_SHORT_MEMORY_BUFFER;
     286             :         }
     287             : 
     288             :         return 0;
     289             : }
     290             : #pragma GCC diagnostic pop
     291             : 
     292             : static int
     293           2 : gtime_to_generalTime(time_t gtime, char *str_time, size_t str_time_size)
     294             : {
     295           2 :         size_t ret;
     296           2 :         struct tm _tm;
     297             : 
     298           2 :         if (gtime == (time_t)-1
     299             : #if SIZEOF_LONG == 8
     300           2 :                 || gtime >= 253402210800
     301             : #endif
     302             :          ) {
     303           0 :                 snprintf(str_time, str_time_size, "99991231235959Z");
     304           0 :                 return 0;
     305             :         }
     306             : 
     307           2 :         if (!gmtime_r(&gtime, &_tm)) {
     308           0 :                 gnutls_assert();
     309           0 :                 return GNUTLS_E_INTERNAL_ERROR;
     310             :         }
     311             : 
     312           2 :         ret = strftime(str_time, str_time_size, "%Y%m%d%H%M%SZ", &_tm);
     313           2 :         if (!ret) {
     314           0 :                 gnutls_assert();
     315           0 :                 return GNUTLS_E_SHORT_MEMORY_BUFFER;
     316             :         }
     317             : 
     318             :         return 0;
     319             : }
     320             : 
     321             : 
     322             : /* Extracts the time in time_t from the ASN1_TYPE given. When should
     323             :  * be something like "tbsCertList.thisUpdate".
     324             :  */
     325             : #define MAX_TIME 64
     326       79800 : time_t _gnutls_x509_get_time(ASN1_TYPE c2, const char *where, int force_general)
     327             : {
     328       79800 :         char ttime[MAX_TIME];
     329       79800 :         char name[128];
     330       79800 :         time_t c_time = (time_t) - 1;
     331       79800 :         int len, result;
     332             : 
     333       79800 :         len = sizeof(ttime) - 1;
     334       79800 :         result = asn1_read_value(c2, where, ttime, &len);
     335       79800 :         if (result != ASN1_SUCCESS) {
     336           4 :                 gnutls_assert();
     337           4 :                 return (time_t) (-1);
     338             :         }
     339             : 
     340       79796 :         if (force_general != 0) {
     341          16 :                 c_time = _gnutls_x509_generalTime2gtime(ttime);
     342             :         } else {
     343       79780 :                 _gnutls_str_cpy(name, sizeof(name), where);
     344             : 
     345             :                 /* choice */
     346       79780 :                 if (strcmp(ttime, "generalTime") == 0) {
     347       24124 :                         if (name[0] == 0)
     348           0 :                                 _gnutls_str_cpy(name, sizeof(name),
     349             :                                                 "generalTime");
     350             :                         else
     351       24124 :                                 _gnutls_str_cat(name, sizeof(name),
     352             :                                                 ".generalTime");
     353       24124 :                         len = sizeof(ttime) - 1;
     354       24124 :                         result = asn1_read_value(c2, name, ttime, &len);
     355       24124 :                         if (result == ASN1_SUCCESS)
     356       24124 :                                 c_time =
     357       24124 :                                     _gnutls_x509_generalTime2gtime(ttime);
     358             :                 } else {        /* UTCTIME */
     359       55656 :                         if (name[0] == 0)
     360          46 :                                 _gnutls_str_cpy(name, sizeof(name), "utcTime");
     361             :                         else
     362       55610 :                                 _gnutls_str_cat(name, sizeof(name), ".utcTime");
     363       55656 :                         len = sizeof(ttime) - 1;
     364       55656 :                         result = asn1_read_value(c2, name, ttime, &len);
     365       55656 :                         if (result == ASN1_SUCCESS)
     366       55653 :                                 c_time = _gnutls_utcTime2gtime(ttime);
     367             :                 }
     368             : 
     369             :                 /* We cannot handle dates after 2031 in 32 bit machines.
     370             :                  * a time_t of 64bits has to be used.
     371             :                  */
     372       79780 :                 if (result != ASN1_SUCCESS) {
     373           3 :                         gnutls_assert();
     374           3 :                         return (time_t) (-1);
     375             :                 }
     376             :         }
     377             : 
     378             :         return c_time;
     379             : }
     380             : 
     381             : /* Sets the time in time_t in the ASN1_TYPE given. Where should
     382             :  * be something like "tbsCertList.thisUpdate".
     383             :  */
     384             : int
     385         829 : _gnutls_x509_set_time(ASN1_TYPE c2, const char *where, time_t tim,
     386             :                       int force_general)
     387             : {
     388         829 :         char str_time[MAX_TIME];
     389         829 :         char name[128];
     390         829 :         int result, len;
     391         829 :         unsigned tag;
     392             : 
     393         829 :         if (force_general != 0) {
     394           2 :                 result =
     395           2 :                     gtime_to_generalTime(tim, str_time, sizeof(str_time));
     396           2 :                 if (result < 0)
     397           0 :                         return gnutls_assert_val(result);
     398           2 :                 len = strlen(str_time);
     399           2 :                 result = asn1_write_value(c2, where, str_time, len);
     400           2 :                 if (result != ASN1_SUCCESS)
     401           0 :                         return gnutls_assert_val(_gnutls_asn2err(result));
     402             : 
     403             :                 return 0;
     404             :         }
     405             : 
     406         827 :         result = gtime_to_suitable_time(tim, str_time, sizeof(str_time), &tag);
     407         827 :         if (result < 0) {
     408           0 :                 gnutls_assert();
     409           0 :                 return result;
     410             :         }
     411             : 
     412         827 :         _gnutls_str_cpy(name, sizeof(name), where);
     413         827 :         if (tag == ASN1_TAG_UTCTime) {
     414         664 :                 if ((result = asn1_write_value(c2, where, "utcTime", 1)) < 0) {
     415           0 :                         gnutls_assert();
     416           0 :                         return _gnutls_asn2err(result);
     417             :                 }
     418         664 :                 _gnutls_str_cat(name, sizeof(name), ".utcTime");
     419             :         } else {
     420         163 :                 if ((result = asn1_write_value(c2, where, "generalTime", 1)) < 0) {
     421           0 :                         gnutls_assert();
     422           0 :                         return _gnutls_asn2err(result);
     423             :                 }
     424         163 :                 _gnutls_str_cat(name, sizeof(name), ".generalTime");
     425             :         }
     426             : 
     427         827 :         len = strlen(str_time);
     428         827 :         result = asn1_write_value(c2, name, str_time, len);
     429         827 :         if (result != ASN1_SUCCESS) {
     430           0 :                 gnutls_assert();
     431           0 :                 return _gnutls_asn2err(result);
     432             :         }
     433             : 
     434             :         return 0;
     435             : }
     436             : 
     437             : /* This will set a DER encoded Time element. To be used in fields
     438             :  * which are of the ANY.
     439             :  */
     440             : int
     441           2 : _gnutls_x509_set_raw_time(ASN1_TYPE c2, const char *where, time_t tim)
     442             : {
     443           2 :         char str_time[MAX_TIME];
     444           2 :         uint8_t buf[128];
     445           2 :         int result, len, der_len;
     446           2 :         unsigned tag;
     447             : 
     448           2 :         result =
     449           2 :             gtime_to_suitable_time(tim, str_time, sizeof(str_time), &tag);
     450           2 :         if (result < 0)
     451           0 :                 return gnutls_assert_val(result);
     452           2 :         len = strlen(str_time);
     453             : 
     454           2 :         buf[0] = tag;
     455           2 :         asn1_length_der(len, buf+1, &der_len);
     456             : 
     457           2 :         if ((unsigned)len > sizeof(buf)-der_len-1) {
     458           0 :                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     459             :         }
     460             : 
     461           2 :         memcpy(buf+1+der_len, str_time, len);
     462             : 
     463           2 :         result = asn1_write_value(c2, where, buf, len+1+der_len);
     464           2 :         if (result != ASN1_SUCCESS)
     465           0 :                 return gnutls_assert_val(_gnutls_asn2err(result));
     466             :         return 0;
     467             : }
     468             : 

Generated by: LCOV version 1.14