1 /* $OpenBSD$ */ 2 /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL 3 * project 2001. 4 */ 5 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 6 * project 2008. 7 */ 8 /* ==================================================================== 9 * Copyright (c) 2001 The OpenSSL Project. All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in 20 * the documentation and/or other materials provided with the 21 * distribution. 22 * 23 * 3. All advertising materials mentioning features or use of this 24 * software must display the following acknowledgment: 25 * "This product includes software developed by the OpenSSL Project 26 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 27 * 28 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 29 * endorse or promote products derived from this software without 30 * prior written permission. For written permission, please contact 31 * licensing@OpenSSL.org. 32 * 33 * 5. Products derived from this software may not be called "OpenSSL" 34 * nor may "OpenSSL" appear in their names without prior written 35 * permission of the OpenSSL Project. 36 * 37 * 6. Redistributions of any form whatsoever must retain the following 38 * acknowledgment: 39 * "This product includes software developed by the OpenSSL Project 40 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 41 * 42 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 43 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 45 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 46 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 47 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 48 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 49 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 51 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 52 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 53 * OF THE POSSIBILITY OF SUCH DAMAGE. 54 * ==================================================================== 55 * 56 * This product includes cryptographic software written by Eric Young 57 * (eay@cryptsoft.com). This product includes software written by Tim 58 * Hudson (tjh@cryptsoft.com). 59 * 60 */ 61 62 #include <string.h> 63 64 #include "o_time.h" 65 66 /* Take a tm structure and add an offset to it. This avoids any OS issues 67 * with restricted date types and overflows which cause the year 2038 68 * problem. 69 */ 70 71 #define SECS_PER_DAY (24 * 60 * 60) 72 73 static long date_to_julian(int y, int m, int d); 74 static void julian_to_date(long jd, int *y, int *m, int *d); 75 76 int 77 OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec) 78 { 79 int offset_hms, offset_day; 80 long time_jd; 81 int time_year, time_month, time_day; 82 /* split offset into days and day seconds */ 83 offset_day = offset_sec / SECS_PER_DAY; 84 /* Avoid sign issues with % operator */ 85 offset_hms = offset_sec - (offset_day * SECS_PER_DAY); 86 offset_day += off_day; 87 /* Add current time seconds to offset */ 88 offset_hms += tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec; 89 /* Adjust day seconds if overflow */ 90 if (offset_hms >= SECS_PER_DAY) { 91 offset_day++; 92 offset_hms -= SECS_PER_DAY; 93 } else if (offset_hms < 0) { 94 offset_day--; 95 offset_hms += SECS_PER_DAY; 96 } 97 98 /* Convert date of time structure into a Julian day number. 99 */ 100 101 time_year = tm->tm_year + 1900; 102 time_month = tm->tm_mon + 1; 103 time_day = tm->tm_mday; 104 105 time_jd = date_to_julian(time_year, time_month, time_day); 106 107 /* Work out Julian day of new date */ 108 time_jd += offset_day; 109 110 if (time_jd < 0) 111 return 0; 112 113 /* Convert Julian day back to date */ 114 115 julian_to_date(time_jd, &time_year, &time_month, &time_day); 116 117 if (time_year < 1900 || time_year > 9999) 118 return 0; 119 120 /* Update tm structure */ 121 122 tm->tm_year = time_year - 1900; 123 tm->tm_mon = time_month - 1; 124 tm->tm_mday = time_day; 125 126 tm->tm_hour = offset_hms / 3600; 127 tm->tm_min = (offset_hms / 60) % 60; 128 tm->tm_sec = offset_hms % 60; 129 130 return 1; 131 132 } 133 134 /* Convert date to and from julian day 135 * Uses Fliegel & Van Flandern algorithm 136 */ 137 static long 138 date_to_julian(int y, int m, int d) 139 { 140 return (1461 * (y + 4800 + (m - 14) / 12)) / 4 + 141 (367 * (m - 2 - 12 * ((m - 14) / 12))) / 12 - 142 (3 * ((y + 4900 + (m - 14) / 12) / 100)) / 4 + 143 d - 32075; 144 } 145 146 static void 147 julian_to_date(long jd, int *y, int *m, int *d) 148 { 149 long L = jd + 68569; 150 long n = (4 * L) / 146097; 151 long i, j; 152 153 L = L - (146097 * n + 3) / 4; 154 i = (4000 * (L + 1)) / 1461001; 155 L = L - (1461 * i) / 4 + 31; 156 j = (80 * L) / 2447; 157 *d = L - (2447 * j) / 80; 158 L = j / 11; 159 *m = j + 2 - (12 * L); 160 *y = 100 * (n - 49) + i + L; 161 } 162