]>
Commit | Line | Data |
---|---|---|
2039c421 RS |
1 | /* |
2 | * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. | |
f6aed2cd | 3 | * |
2039c421 RS |
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 | |
f6aed2cd DSH |
8 | */ |
9 | ||
1d97c843 TH |
10 | /*- |
11 | * This is an implementation of the ASN1 Time structure which is: | |
f6aed2cd DSH |
12 | * Time ::= CHOICE { |
13 | * utcTime UTCTime, | |
14 | * generalTime GeneralizedTime } | |
f6aed2cd DSH |
15 | */ |
16 | ||
17 | #include <stdio.h> | |
18 | #include <time.h> | |
b39fc560 | 19 | #include "internal/cryptlib.h" |
9d6b1ce6 | 20 | #include <openssl/asn1t.h> |
1c455bc0 | 21 | #include "asn1_locl.h" |
f6aed2cd | 22 | |
9d6b1ce6 | 23 | IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME) |
08e9c1af | 24 | |
9d6b1ce6 | 25 | IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME) |
08e9c1af | 26 | |
6b691a5c | 27 | ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t) |
0f113f3e MC |
28 | { |
29 | return ASN1_TIME_adj(s, t, 0, 0); | |
30 | } | |
87d3a0cd DSH |
31 | |
32 | ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t, | |
0f113f3e MC |
33 | int offset_day, long offset_sec) |
34 | { | |
35 | struct tm *ts; | |
36 | struct tm data; | |
37 | ||
38 | ts = OPENSSL_gmtime(&t, &data); | |
39 | if (ts == NULL) { | |
40 | ASN1err(ASN1_F_ASN1_TIME_ADJ, ASN1_R_ERROR_GETTING_TIME); | |
41 | return NULL; | |
42 | } | |
43 | if (offset_day || offset_sec) { | |
44 | if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) | |
45 | return NULL; | |
46 | } | |
47 | if ((ts->tm_year >= 50) && (ts->tm_year < 150)) | |
48 | return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec); | |
49 | return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec); | |
50 | } | |
02e4fbed | 51 | |
359b0c9f | 52 | int ASN1_TIME_check(const ASN1_TIME *t) |
0f113f3e MC |
53 | { |
54 | if (t->type == V_ASN1_GENERALIZEDTIME) | |
55 | return ASN1_GENERALIZEDTIME_check(t); | |
56 | else if (t->type == V_ASN1_UTCTIME) | |
57 | return ASN1_UTCTIME_check(t); | |
58 | return 0; | |
59 | } | |
02e4fbed DSH |
60 | |
61 | /* Convert an ASN1_TIME structure to GeneralizedTime */ | |
9bfeeef8 | 62 | ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t, |
0f113f3e MC |
63 | ASN1_GENERALIZEDTIME **out) |
64 | { | |
4483e234 | 65 | ASN1_GENERALIZEDTIME *ret = NULL; |
0f113f3e MC |
66 | char *str; |
67 | int newlen; | |
68 | ||
69 | if (!ASN1_TIME_check(t)) | |
70 | return NULL; | |
71 | ||
75ebbd9a RS |
72 | if (out == NULL || *out == NULL) { |
73 | if ((ret = ASN1_GENERALIZEDTIME_new()) == NULL) | |
4483e234 | 74 | goto err; |
0f113f3e MC |
75 | } else |
76 | ret = *out; | |
77 | ||
78 | /* If already GeneralizedTime just copy across */ | |
79 | if (t->type == V_ASN1_GENERALIZEDTIME) { | |
80 | if (!ASN1_STRING_set(ret, t->data, t->length)) | |
4483e234 TS |
81 | goto err; |
82 | goto done; | |
0f113f3e MC |
83 | } |
84 | ||
85 | /* grow the string */ | |
86 | if (!ASN1_STRING_set(ret, NULL, t->length + 2)) | |
4483e234 | 87 | goto err; |
0f113f3e MC |
88 | /* ASN1_STRING_set() allocated 'len + 1' bytes. */ |
89 | newlen = t->length + 2 + 1; | |
90 | str = (char *)ret->data; | |
91 | /* Work out the century and prepend */ | |
92 | if (t->data[0] >= '5') | |
7644a9ae | 93 | OPENSSL_strlcpy(str, "19", newlen); |
0f113f3e | 94 | else |
7644a9ae | 95 | OPENSSL_strlcpy(str, "20", newlen); |
0f113f3e | 96 | |
4483e234 | 97 | OPENSSL_strlcat(str, (const char *)t->data, newlen); |
0f113f3e | 98 | |
4483e234 TS |
99 | done: |
100 | if (out != NULL && *out == NULL) | |
101 | *out = ret; | |
102 | return ret; | |
103 | ||
104 | err: | |
105 | if (out == NULL || *out != ret) | |
106 | ASN1_GENERALIZEDTIME_free(ret); | |
107 | return NULL; | |
0f113f3e | 108 | } |
33ab2e31 | 109 | |
4483e234 | 110 | |
33ab2e31 | 111 | int ASN1_TIME_set_string(ASN1_TIME *s, const char *str) |
0f113f3e MC |
112 | { |
113 | ASN1_TIME t; | |
114 | ||
115 | t.length = strlen(str); | |
116 | t.data = (unsigned char *)str; | |
117 | t.flags = 0; | |
118 | ||
119 | t.type = V_ASN1_UTCTIME; | |
120 | ||
121 | if (!ASN1_TIME_check(&t)) { | |
122 | t.type = V_ASN1_GENERALIZEDTIME; | |
123 | if (!ASN1_TIME_check(&t)) | |
124 | return 0; | |
125 | } | |
126 | ||
127 | if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t)) | |
128 | return 0; | |
129 | ||
130 | return 1; | |
131 | } | |
359b0c9f | 132 | |
1c455bc0 | 133 | static int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *t) |
0f113f3e MC |
134 | { |
135 | if (t == NULL) { | |
136 | time_t now_t; | |
137 | time(&now_t); | |
138 | if (OPENSSL_gmtime(&now_t, tm)) | |
139 | return 1; | |
140 | return 0; | |
141 | } | |
142 | ||
143 | if (t->type == V_ASN1_UTCTIME) | |
144 | return asn1_utctime_to_tm(tm, t); | |
145 | else if (t->type == V_ASN1_GENERALIZEDTIME) | |
146 | return asn1_generalizedtime_to_tm(tm, t); | |
147 | ||
148 | return 0; | |
149 | } | |
1c455bc0 | 150 | |
360ef676 | 151 | int ASN1_TIME_diff(int *pday, int *psec, |
0f113f3e MC |
152 | const ASN1_TIME *from, const ASN1_TIME *to) |
153 | { | |
154 | struct tm tm_from, tm_to; | |
155 | if (!asn1_time_to_tm(&tm_from, from)) | |
156 | return 0; | |
157 | if (!asn1_time_to_tm(&tm_to, to)) | |
158 | return 0; | |
159 | return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to); | |
160 | } | |
0d0099ea DSH |
161 | |
162 | int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm) | |
163 | { | |
164 | if (tm->type == V_ASN1_UTCTIME) | |
165 | return ASN1_UTCTIME_print(bp, tm); | |
166 | if (tm->type == V_ASN1_GENERALIZEDTIME) | |
167 | return ASN1_GENERALIZEDTIME_print(bp, tm); | |
168 | BIO_write(bp, "Bad time value", 14); | |
169 | return (0); | |
170 | } |