155714Skris/* crypto/asn1/a_time.c */ 255714Skris/* ==================================================================== 355714Skris * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 455714Skris * 555714Skris * Redistribution and use in source and binary forms, with or without 655714Skris * modification, are permitted provided that the following conditions 755714Skris * are met: 855714Skris * 955714Skris * 1. Redistributions of source code must retain the above copyright 10280297Sjkim * notice, this list of conditions and the following disclaimer. 1155714Skris * 1255714Skris * 2. Redistributions in binary form must reproduce the above copyright 1355714Skris * notice, this list of conditions and the following disclaimer in 1455714Skris * the documentation and/or other materials provided with the 1555714Skris * distribution. 1655714Skris * 1755714Skris * 3. All advertising materials mentioning features or use of this 1855714Skris * software must display the following acknowledgment: 1955714Skris * "This product includes software developed by the OpenSSL Project 2055714Skris * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2155714Skris * 2255714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2355714Skris * endorse or promote products derived from this software without 2455714Skris * prior written permission. For written permission, please contact 2555714Skris * licensing@OpenSSL.org. 2655714Skris * 2755714Skris * 5. Products derived from this software may not be called "OpenSSL" 2855714Skris * nor may "OpenSSL" appear in their names without prior written 2955714Skris * permission of the OpenSSL Project. 3055714Skris * 3155714Skris * 6. Redistributions of any form whatsoever must retain the following 3255714Skris * acknowledgment: 3355714Skris * "This product includes software developed by the OpenSSL Project 3455714Skris * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3555714Skris * 3655714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 3755714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3855714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 3955714Skris * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4055714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4155714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4255714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4355714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4455714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4555714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 4655714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 4755714Skris * OF THE POSSIBILITY OF SUCH DAMAGE. 4855714Skris * ==================================================================== 4955714Skris * 5055714Skris * This product includes cryptographic software written by Eric Young 5155714Skris * (eay@cryptsoft.com). This product includes software written by Tim 5255714Skris * Hudson (tjh@cryptsoft.com). 5355714Skris * 5455714Skris */ 5555714Skris 56280297Sjkim/*- 57280297Sjkim * This is an implementation of the ASN1 Time structure which is: 5855714Skris * Time ::= CHOICE { 5955714Skris * utcTime UTCTime, 6055714Skris * generalTime GeneralizedTime } 6155714Skris * written by Steve Henson. 6255714Skris */ 6355714Skris 6455714Skris#include <stdio.h> 6555714Skris#include <time.h> 6655714Skris#include "cryptlib.h" 67109998Smarkm#include "o_time.h" 68109998Smarkm#include <openssl/asn1t.h> 69290207Sjkim#include "asn1_locl.h" 7055714Skris 71109998SmarkmIMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME) 7259191Skris 73109998SmarkmIMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME) 7459191Skris 75109998Smarkm#if 0 7655714Skrisint i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **pp) 77280297Sjkim{ 78280297Sjkim# ifdef CHARSET_EBCDIC 79280297Sjkim /* KLUDGE! We convert to ascii before writing DER */ 80280297Sjkim char tmp[24]; 81280297Sjkim ASN1_STRING tmpstr; 8255714Skris 83280297Sjkim if (a->type == V_ASN1_UTCTIME || a->type == V_ASN1_GENERALIZEDTIME) { 84280297Sjkim int len; 8555714Skris 86280297Sjkim tmpstr = *(ASN1_STRING *)a; 87280297Sjkim len = tmpstr.length; 88280297Sjkim ebcdic2ascii(tmp, tmpstr.data, 89331638Sjkim (len >= sizeof(tmp)) ? sizeof(tmp) : len); 90280297Sjkim tmpstr.data = tmp; 91280297Sjkim a = (ASN1_GENERALIZEDTIME *)&tmpstr; 92280297Sjkim } 93280297Sjkim# endif 94280297Sjkim if (a->type == V_ASN1_UTCTIME || a->type == V_ASN1_GENERALIZEDTIME) 95280297Sjkim return (i2d_ASN1_bytes((ASN1_STRING *)a, pp, 96280297Sjkim a->type, V_ASN1_UNIVERSAL)); 97280297Sjkim ASN1err(ASN1_F_I2D_ASN1_TIME, ASN1_R_EXPECTING_A_TIME); 98280297Sjkim return -1; 99280297Sjkim} 10055714Skris#endif 10155714Skris 10255714SkrisASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t) 103280297Sjkim{ 104280297Sjkim return ASN1_TIME_adj(s, t, 0, 0); 105280297Sjkim} 106238405Sjkim 107238405SjkimASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t, 108280297Sjkim int offset_day, long offset_sec) 109280297Sjkim{ 110280297Sjkim struct tm *ts; 111280297Sjkim struct tm data; 11255714Skris 113280297Sjkim ts = OPENSSL_gmtime(&t, &data); 114280297Sjkim if (ts == NULL) { 115280297Sjkim ASN1err(ASN1_F_ASN1_TIME_ADJ, ASN1_R_ERROR_GETTING_TIME); 116280297Sjkim return NULL; 117280297Sjkim } 118280297Sjkim if (offset_day || offset_sec) { 119280297Sjkim if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) 120280297Sjkim return NULL; 121280297Sjkim } 122280297Sjkim if ((ts->tm_year >= 50) && (ts->tm_year < 150)) 123280297Sjkim return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec); 124280297Sjkim return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec); 125280297Sjkim} 126109998Smarkm 127109998Smarkmint ASN1_TIME_check(ASN1_TIME *t) 128280297Sjkim{ 129280297Sjkim if (t->type == V_ASN1_GENERALIZEDTIME) 130280297Sjkim return ASN1_GENERALIZEDTIME_check(t); 131280297Sjkim else if (t->type == V_ASN1_UTCTIME) 132280297Sjkim return ASN1_UTCTIME_check(t); 133280297Sjkim return 0; 134280297Sjkim} 135109998Smarkm 136109998Smarkm/* Convert an ASN1_TIME structure to GeneralizedTime */ 137280297SjkimASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, 138280297Sjkim ASN1_GENERALIZEDTIME **out) 139280297Sjkim{ 140325335Sjkim ASN1_GENERALIZEDTIME *ret = NULL; 141280297Sjkim char *str; 142280297Sjkim int newlen; 143109998Smarkm 144280297Sjkim if (!ASN1_TIME_check(t)) 145280297Sjkim return NULL; 146109998Smarkm 147280297Sjkim if (!out || !*out) { 148280297Sjkim if (!(ret = ASN1_GENERALIZEDTIME_new())) 149325335Sjkim goto err; 150325335Sjkim } else { 151280297Sjkim ret = *out; 152325335Sjkim } 153109998Smarkm 154280297Sjkim /* If already GeneralizedTime just copy across */ 155280297Sjkim if (t->type == V_ASN1_GENERALIZEDTIME) { 156280297Sjkim if (!ASN1_STRING_set(ret, t->data, t->length)) 157325335Sjkim goto err; 158325335Sjkim goto done; 159280297Sjkim } 160109998Smarkm 161280297Sjkim /* grow the string */ 162280297Sjkim if (!ASN1_STRING_set(ret, NULL, t->length + 2)) 163325335Sjkim goto err; 164280297Sjkim /* ASN1_STRING_set() allocated 'len + 1' bytes. */ 165280297Sjkim newlen = t->length + 2 + 1; 166280297Sjkim str = (char *)ret->data; 167280297Sjkim /* Work out the century and prepend */ 168280297Sjkim if (t->data[0] >= '5') 169280297Sjkim BUF_strlcpy(str, "19", newlen); 170280297Sjkim else 171280297Sjkim BUF_strlcpy(str, "20", newlen); 172109998Smarkm 173280297Sjkim BUF_strlcat(str, (char *)t->data, newlen); 174109998Smarkm 175325335Sjkim done: 176325335Sjkim if (out != NULL && *out == NULL) 177325335Sjkim *out = ret; 178325335Sjkim return ret; 179325335Sjkim 180325335Sjkim err: 181325335Sjkim if (out == NULL || *out != ret) 182325335Sjkim ASN1_GENERALIZEDTIME_free(ret); 183325335Sjkim return NULL; 184280297Sjkim} 185238405Sjkim 186325335Sjkim 187238405Sjkimint ASN1_TIME_set_string(ASN1_TIME *s, const char *str) 188280297Sjkim{ 189280297Sjkim ASN1_TIME t; 190238405Sjkim 191280297Sjkim t.length = strlen(str); 192280297Sjkim t.data = (unsigned char *)str; 193280297Sjkim t.flags = 0; 194238405Sjkim 195280297Sjkim t.type = V_ASN1_UTCTIME; 196238405Sjkim 197280297Sjkim if (!ASN1_TIME_check(&t)) { 198280297Sjkim t.type = V_ASN1_GENERALIZEDTIME; 199280297Sjkim if (!ASN1_TIME_check(&t)) 200280297Sjkim return 0; 201280297Sjkim } 202280297Sjkim 203280297Sjkim if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t)) 204280297Sjkim return 0; 205280297Sjkim 206280297Sjkim return 1; 207280297Sjkim} 208290207Sjkim 209290207Sjkimstatic int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *t) 210290207Sjkim{ 211290207Sjkim if (t == NULL) { 212290207Sjkim time_t now_t; 213290207Sjkim time(&now_t); 214290207Sjkim if (OPENSSL_gmtime(&now_t, tm)) 215290207Sjkim return 1; 216290207Sjkim return 0; 217290207Sjkim } 218290207Sjkim 219290207Sjkim if (t->type == V_ASN1_UTCTIME) 220290207Sjkim return asn1_utctime_to_tm(tm, t); 221290207Sjkim else if (t->type == V_ASN1_GENERALIZEDTIME) 222290207Sjkim return asn1_generalizedtime_to_tm(tm, t); 223290207Sjkim 224290207Sjkim return 0; 225290207Sjkim} 226290207Sjkim 227290207Sjkimint ASN1_TIME_diff(int *pday, int *psec, 228290207Sjkim const ASN1_TIME *from, const ASN1_TIME *to) 229290207Sjkim{ 230290207Sjkim struct tm tm_from, tm_to; 231290207Sjkim if (!asn1_time_to_tm(&tm_from, from)) 232290207Sjkim return 0; 233290207Sjkim if (!asn1_time_to_tm(&tm_to, to)) 234290207Sjkim return 0; 235290207Sjkim return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to); 236290207Sjkim} 237