VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/asn1/asn1-ut-time.cpp@ 74762

Last change on this file since 74762 was 70895, checked in by vboxsync, 7 years ago

IPRT: Added RTTimeCompare and made use of it in the RTAsn1Time methods instead of the range limited RTTimeSpecCompare. Makes certificates with expire time beyond year 3000 found on windows 10 insider builds (??) work.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.3 KB
Line 
1/* $Id: asn1-ut-time.cpp 70895 2018-02-07 23:14:02Z vboxsync $ */
2/** @file
3 * IPRT - ASN.1, UTC TIME and GENERALIZED TIME Types.
4 */
5
6/*
7 * Copyright (C) 2006-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include "internal/iprt.h"
32#include <iprt/asn1.h>
33
34#include <iprt/ctype.h>
35#include <iprt/err.h>
36#include <iprt/string.h>
37#include <iprt/uni.h>
38
39#include <iprt/formats/asn1.h>
40
41
42/*********************************************************************************************************************************
43* Global Variables *
44*********************************************************************************************************************************/
45/** The UTC TIME encoding of the IPRT epoch time. */
46static const char g_szEpochUtc[] = "700101000000Z";
47/** The GENERALIZED TIME encoding of the IPRT epoch time. */
48static const char g_szEpochGeneralized[] = "19700101000000Z";
49
50
51/*
52 * ASN.1 TIME - Special Methods.
53 */
54
55RTDECL(int) RTAsn1Time_InitEx(PRTASN1TIME pThis, uint32_t uTag, PCRTASN1ALLOCATORVTABLE pAllocator)
56{
57 RT_NOREF_PV(pAllocator);
58 AssertReturn(uTag == ASN1_TAG_UTC_TIME || uTag == ASN1_TAG_GENERALIZED_TIME, VERR_INVALID_PARAMETER);
59 RTAsn1Core_InitEx(&pThis->Asn1Core,
60 uTag,
61 ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_PRIMITIVE,
62 &g_RTAsn1Time_Vtable,
63 RTASN1CORE_F_PRESENT | RTASN1CORE_F_PRIMITE_TAG_STRUCT);
64 if (uTag == ASN1_TAG_UTC_TIME)
65 {
66 pThis->Asn1Core.cb = sizeof(g_szEpochUtc) - 1;
67 pThis->Asn1Core.uData.pv = &g_szEpochUtc[0];
68 }
69 else
70 {
71 pThis->Asn1Core.cb = sizeof(g_szEpochGeneralized) - 1;
72 pThis->Asn1Core.uData.pv = &g_szEpochGeneralized[0];
73 }
74 return VINF_SUCCESS;
75}
76
77
78RTDECL(int) RTAsn1Time_CompareWithTimeSpec(PCRTASN1TIME pLeft, PCRTTIMESPEC pTsRight)
79{
80 int iDiff = RTAsn1Time_IsPresent(pLeft) ? 0 : -1;
81 if (!iDiff)
82 {
83 RTTIME RightTime;
84 iDiff = RTTimeCompare(&pLeft->Time, RTTimeExplode(&RightTime, pTsRight));
85 }
86
87 return iDiff;
88}
89
90
91/*
92 * ASN.1 TIME - Standard Methods.
93 */
94
95RT_DECL_DATA_CONST(RTASN1COREVTABLE const) g_RTAsn1Time_Vtable =
96{
97 "RTAsn1Time",
98 sizeof(RTASN1TIME),
99 UINT8_MAX,
100 ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_PRIMITIVE,
101 0,
102 (PFNRTASN1COREVTDTOR)RTAsn1Time_Delete,
103 NULL,
104 (PFNRTASN1COREVTCLONE)RTAsn1Time_Clone,
105 (PFNRTASN1COREVTCOMPARE)RTAsn1Time_Compare,
106 (PFNRTASN1COREVTCHECKSANITY)RTAsn1Time_CheckSanity,
107 NULL,
108 NULL
109};
110
111
112RTDECL(int) RTAsn1Time_Init(PRTASN1TIME pThis, PCRTASN1ALLOCATORVTABLE pAllocator)
113{
114 /* Using UTC TIME since epoch would be encoded using UTC TIME following
115 X.509 Validity / Whatever time tag guidelines. */
116 return RTAsn1Time_InitEx(pThis, ASN1_TAG_UTC_TIME, pAllocator);
117}
118
119
120RTDECL(int) RTAsn1Time_Clone(PRTASN1TIME pThis, PCRTASN1TIME pSrc, PCRTASN1ALLOCATORVTABLE pAllocator)
121{
122 AssertPtr(pSrc); AssertPtr(pThis); AssertPtr(pAllocator);
123 RT_ZERO(*pThis);
124 if (RTAsn1Time_IsPresent(pSrc))
125 {
126 AssertReturn(pSrc->Asn1Core.pOps == &g_RTAsn1Time_Vtable, VERR_INTERNAL_ERROR_3);
127
128 int rc = RTAsn1Core_CloneContent(&pThis->Asn1Core, &pSrc->Asn1Core, pAllocator);
129 if (RT_SUCCESS(rc))
130 {
131 pThis->Time = pSrc->Time;
132 return VINF_SUCCESS;
133 }
134 return rc;
135 }
136 return VINF_SUCCESS;
137}
138
139
140RTDECL(void) RTAsn1Time_Delete(PRTASN1TIME pThis)
141{
142 if ( pThis
143 && RTAsn1Time_IsPresent(pThis))
144 {
145 Assert(pThis->Asn1Core.pOps == &g_RTAsn1Time_Vtable);
146
147 RTAsn1ContentFree(&pThis->Asn1Core);
148 RT_ZERO(*pThis);
149 }
150}
151
152
153RTDECL(int) RTAsn1Time_Enum(PRTASN1TIME pThis, PFNRTASN1ENUMCALLBACK pfnCallback, uint32_t uDepth, void *pvUser)
154{
155 RT_NOREF_PV(pThis); RT_NOREF_PV(pfnCallback); RT_NOREF_PV(uDepth); RT_NOREF_PV(pvUser);
156 Assert(pThis && (!RTAsn1Time_IsPresent(pThis) || pThis->Asn1Core.pOps == &g_RTAsn1Time_Vtable));
157
158 /* No children to enumerate. */
159 return VINF_SUCCESS;
160}
161
162
163RTDECL(int) RTAsn1Time_Compare(PCRTASN1TIME pLeft, PCRTASN1TIME pRight)
164{
165 Assert(pLeft && (!RTAsn1Time_IsPresent(pLeft) || pLeft->Asn1Core.pOps == &g_RTAsn1Time_Vtable));
166 Assert(pRight && (!RTAsn1Time_IsPresent(pRight) || pRight->Asn1Core.pOps == &g_RTAsn1Time_Vtable));
167
168 int iDiff;
169 if (RTAsn1Time_IsPresent(pLeft))
170 {
171 if (RTAsn1Time_IsPresent(pRight))
172 iDiff = RTTimeCompare(&pLeft->Time, &pRight->Time);
173 else
174 iDiff = -1;
175 }
176 else
177 iDiff = 0 - (int)RTAsn1Time_IsPresent(pRight);
178 return iDiff;
179}
180
181
182RTDECL(int) RTAsn1Time_CheckSanity(PCRTASN1TIME pThis, uint32_t fFlags, PRTERRINFO pErrInfo, const char *pszErrorTag)
183{
184 RT_NOREF_PV(fFlags);
185 if (RT_UNLIKELY(!RTAsn1Time_IsPresent(pThis)))
186 return RTErrInfoSetF(pErrInfo, VERR_ASN1_NOT_PRESENT, "%s: Missing (TIME).", pszErrorTag);
187 return VINF_SUCCESS;
188}
189
190
191/*
192 * Generate code for the tag specific methods.
193 * Note! This is very similar to what we're doing in asn1-ut-string.cpp.
194 */
195#define RTASN1TIME_IMPL(a_uTag, a_szTag, a_Api) \
196 \
197 RTDECL(int) RT_CONCAT(a_Api,_Init)(PRTASN1TIME pThis, PCRTASN1ALLOCATORVTABLE pAllocator) \
198 { \
199 return RTAsn1Time_InitEx(pThis, a_uTag, pAllocator); \
200 } \
201 \
202 RTDECL(int) RT_CONCAT(a_Api,_Clone)(PRTASN1TIME pThis, PCRTASN1TIME pSrc, PCRTASN1ALLOCATORVTABLE pAllocator) \
203 { \
204 AssertReturn(RTASN1CORE_GET_TAG(&pSrc->Asn1Core) == a_uTag || !RTAsn1Time_IsPresent(pSrc), \
205 VERR_ASN1_TIME_TAG_MISMATCH); \
206 return RTAsn1Time_Clone(pThis, pSrc, pAllocator); \
207 } \
208 \
209 RTDECL(void) RT_CONCAT(a_Api,_Delete)(PRTASN1TIME pThis) \
210 { \
211 Assert( !pThis \
212 || !RTAsn1Time_IsPresent(pThis) \
213 || ( pThis->Asn1Core.pOps == &g_RTAsn1Time_Vtable \
214 && RTASN1CORE_GET_TAG(&pThis->Asn1Core) == a_uTag) ); \
215 RTAsn1Time_Delete(pThis); \
216 } \
217 \
218 RTDECL(int) RT_CONCAT(a_Api,_Enum)(PRTASN1TIME pThis, PFNRTASN1ENUMCALLBACK pfnCallback, uint32_t uDepth, void *pvUser) \
219 { \
220 RT_NOREF_PV(pThis); RT_NOREF_PV(pfnCallback); RT_NOREF_PV(uDepth); RT_NOREF_PV(pvUser); \
221 Assert( pThis \
222 && ( !RTAsn1Time_IsPresent(pThis) \
223 || ( pThis->Asn1Core.pOps == &g_RTAsn1Time_Vtable \
224 && RTASN1CORE_GET_TAG(&pThis->Asn1Core) == a_uTag) ) ); \
225 /* No children to enumerate. */ \
226 return VINF_SUCCESS; \
227 } \
228 \
229 RTDECL(int) RT_CONCAT(a_Api,_Compare)(PCRTASN1TIME pLeft, PCRTASN1TIME pRight) \
230 { \
231 int iDiff = RTAsn1Time_Compare(pLeft, pRight); \
232 if (!iDiff && RTAsn1Time_IsPresent(pLeft)) \
233 { \
234 if (RTASN1CORE_GET_TAG(&pLeft->Asn1Core) == RTASN1CORE_GET_TAG(&pRight->Asn1Core)) \
235 { \
236 if (RTASN1CORE_GET_TAG(&pLeft->Asn1Core) != a_uTag) \
237 iDiff = RTASN1CORE_GET_TAG(&pLeft->Asn1Core) < a_uTag ? -1 : 1; \
238 } \
239 else \
240 iDiff = RTASN1CORE_GET_TAG(&pLeft->Asn1Core) < RTASN1CORE_GET_TAG(&pRight->Asn1Core) ? -1 : 1; \
241 } \
242 return iDiff; \
243 } \
244 \
245 RTDECL(int) RT_CONCAT(a_Api,_CheckSanity)(PCRTASN1TIME pThis, uint32_t fFlags, \
246 PRTERRINFO pErrInfo, const char *pszErrorTag) \
247 { \
248 if (RTASN1CORE_GET_TAG(&pThis->Asn1Core) != a_uTag && RTAsn1Time_IsPresent(pThis)) \
249 return RTErrInfoSetF(pErrInfo, VERR_ASN1_TIME_TAG_MISMATCH, "%s: uTag=%#x, expected %#x (%s)", \
250 pszErrorTag, RTASN1CORE_GET_TAG(&pThis->Asn1Core), a_uTag, a_szTag); \
251 return RTAsn1Time_CheckSanity(pThis, fFlags, pErrInfo, pszErrorTag); \
252 }
253
254#include "asn1-ut-time-template2.h"
255
256
257/*
258 * Generate code for the associated collection types.
259 */
260#define RTASN1TMPL_TEMPLATE_FILE "../common/asn1/asn1-ut-time-template.h"
261#include <iprt/asn1-generator-internal-header.h>
262#include <iprt/asn1-generator-core.h>
263#include <iprt/asn1-generator-init.h>
264#include <iprt/asn1-generator-sanity.h>
265
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette