1 /*
2 * Copyright 2024-2026 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (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
8 */
9
10 #include <stdio.h>
11 #include <openssl/asn1t.h>
12 #include <openssl/x509v3.h>
13 #include <crypto/asn1.h>
14 #include "ext_dat.h"
15
16 static const char *WEEKDAY_NAMES[7] = {
17 "SUN",
18 "MON",
19 "TUE",
20 "WED",
21 "THU",
22 "FRI",
23 "SAT"
24 };
25
26 static const char *WEEK_NAMES[5] = {
27 "first",
28 "second",
29 "third",
30 "fourth",
31 "final"
32 };
33
34 static const char *MONTH_NAMES[12] = {
35 "JAN",
36 "FEB",
37 "MAR",
38 "APR",
39 "MAY",
40 "JUN",
41 "JUL",
42 "AUG",
43 "SEPT",
44 "OCT",
45 "NOV",
46 "DEC"
47 };
48
49 ASN1_SEQUENCE(OSSL_TIME_SPEC_ABSOLUTE) = {
50 ASN1_EXP_OPT(OSSL_TIME_SPEC_ABSOLUTE, startTime, ASN1_GENERALIZEDTIME, 0),
51 ASN1_EXP_OPT(OSSL_TIME_SPEC_ABSOLUTE, endTime, ASN1_GENERALIZEDTIME, 1),
52 } ASN1_SEQUENCE_END(OSSL_TIME_SPEC_ABSOLUTE)
53
54 ASN1_SEQUENCE(OSSL_DAY_TIME) = {
55 ASN1_EXP_OPT(OSSL_DAY_TIME, hour, ASN1_INTEGER, 0),
56 ASN1_EXP_OPT(OSSL_DAY_TIME, minute, ASN1_INTEGER, 1),
57 ASN1_EXP_OPT(OSSL_DAY_TIME, second, ASN1_INTEGER, 2),
58 } ASN1_SEQUENCE_END(OSSL_DAY_TIME)
59
60 ASN1_SEQUENCE(OSSL_DAY_TIME_BAND) = {
61 ASN1_EXP_OPT(OSSL_DAY_TIME_BAND, startDayTime, OSSL_DAY_TIME, 0),
62 ASN1_EXP_OPT(OSSL_DAY_TIME_BAND, endDayTime, OSSL_DAY_TIME, 1),
63 } ASN1_SEQUENCE_END(OSSL_DAY_TIME_BAND)
64
65 ASN1_CHOICE(OSSL_NAMED_DAY) = {
66 ASN1_SET_OF(OSSL_NAMED_DAY, choice.intNamedDays, ASN1_ENUMERATED),
67 ASN1_SIMPLE(OSSL_NAMED_DAY, choice.bitNamedDays, ASN1_BIT_STRING),
68 } ASN1_CHOICE_END(OSSL_NAMED_DAY)
69
70 ASN1_CHOICE(OSSL_TIME_SPEC_X_DAY_OF) = {
71 ASN1_EXP(OSSL_TIME_SPEC_X_DAY_OF, choice.first, OSSL_NAMED_DAY, 1),
72 ASN1_EXP(OSSL_TIME_SPEC_X_DAY_OF, choice.second, OSSL_NAMED_DAY, 2),
73 ASN1_EXP(OSSL_TIME_SPEC_X_DAY_OF, choice.third, OSSL_NAMED_DAY, 3),
74 ASN1_EXP(OSSL_TIME_SPEC_X_DAY_OF, choice.fourth, OSSL_NAMED_DAY, 4),
75 ASN1_EXP(OSSL_TIME_SPEC_X_DAY_OF, choice.fifth, OSSL_NAMED_DAY, 5),
76 } ASN1_CHOICE_END(OSSL_TIME_SPEC_X_DAY_OF)
77
78 ASN1_CHOICE(OSSL_TIME_SPEC_DAY) = {
79 ASN1_SET_OF(OSSL_TIME_SPEC_DAY, choice.intDay, ASN1_INTEGER),
80 ASN1_SIMPLE(OSSL_TIME_SPEC_DAY, choice.bitDay, ASN1_BIT_STRING),
81 ASN1_SIMPLE(OSSL_TIME_SPEC_DAY, choice.dayOf, OSSL_TIME_SPEC_X_DAY_OF),
82 } ASN1_CHOICE_END(OSSL_TIME_SPEC_DAY)
83
84 ASN1_CHOICE(OSSL_TIME_SPEC_WEEKS) = {
85 ASN1_SIMPLE(OSSL_TIME_SPEC_WEEKS, choice.allWeeks, ASN1_NULL),
86 ASN1_SET_OF(OSSL_TIME_SPEC_WEEKS, choice.intWeek, ASN1_INTEGER),
87 ASN1_SIMPLE(OSSL_TIME_SPEC_WEEKS, choice.bitWeek, ASN1_BIT_STRING),
88 } ASN1_CHOICE_END(OSSL_TIME_SPEC_WEEKS)
89
90 ASN1_CHOICE(OSSL_TIME_SPEC_MONTH) = {
91 ASN1_SIMPLE(OSSL_TIME_SPEC_MONTH, choice.allMonths, ASN1_NULL),
92 ASN1_SET_OF(OSSL_TIME_SPEC_MONTH, choice.intMonth, ASN1_INTEGER),
93 ASN1_SIMPLE(OSSL_TIME_SPEC_MONTH, choice.bitMonth, ASN1_BIT_STRING),
94 } ASN1_CHOICE_END(OSSL_TIME_SPEC_MONTH)
95
96 ASN1_SEQUENCE(OSSL_TIME_PERIOD) = {
97 ASN1_EXP_SET_OF_OPT(OSSL_TIME_PERIOD, timesOfDay, OSSL_DAY_TIME_BAND, 0),
98 ASN1_EXP_OPT(OSSL_TIME_PERIOD, days, OSSL_TIME_SPEC_DAY, 1),
99 ASN1_EXP_OPT(OSSL_TIME_PERIOD, weeks, OSSL_TIME_SPEC_WEEKS, 2),
100 ASN1_EXP_OPT(OSSL_TIME_PERIOD, months, OSSL_TIME_SPEC_MONTH, 3),
101 ASN1_EXP_SET_OF_OPT(OSSL_TIME_PERIOD, years, ASN1_INTEGER, 4),
102 } ASN1_SEQUENCE_END(OSSL_TIME_PERIOD)
103
104 ASN1_CHOICE(OSSL_TIME_SPEC_TIME) = {
105 ASN1_SIMPLE(OSSL_TIME_SPEC_TIME, choice.absolute, OSSL_TIME_SPEC_ABSOLUTE),
106 ASN1_SET_OF(OSSL_TIME_SPEC_TIME, choice.periodic, OSSL_TIME_PERIOD)
107 } ASN1_CHOICE_END(OSSL_TIME_SPEC_TIME)
108
109 ASN1_SEQUENCE(OSSL_TIME_SPEC) = {
110 ASN1_SIMPLE(OSSL_TIME_SPEC, time, OSSL_TIME_SPEC_TIME),
111 ASN1_OPT(OSSL_TIME_SPEC, notThisTime, ASN1_FBOOLEAN),
112 ASN1_OPT(OSSL_TIME_SPEC, timeZone, ASN1_INTEGER),
113 } ASN1_SEQUENCE_END(OSSL_TIME_SPEC)
114
115 IMPLEMENT_ASN1_FUNCTIONS(OSSL_DAY_TIME)
116 IMPLEMENT_ASN1_FUNCTIONS(OSSL_DAY_TIME_BAND)
117 IMPLEMENT_ASN1_FUNCTIONS(OSSL_TIME_SPEC_DAY)
118 IMPLEMENT_ASN1_FUNCTIONS(OSSL_TIME_SPEC_WEEKS)
119 IMPLEMENT_ASN1_FUNCTIONS(OSSL_TIME_SPEC_MONTH)
120 IMPLEMENT_ASN1_FUNCTIONS(OSSL_NAMED_DAY)
121 IMPLEMENT_ASN1_FUNCTIONS(OSSL_TIME_SPEC_X_DAY_OF)
122 IMPLEMENT_ASN1_FUNCTIONS(OSSL_TIME_SPEC_ABSOLUTE)
123 IMPLEMENT_ASN1_FUNCTIONS(OSSL_TIME_SPEC_TIME)
124 IMPLEMENT_ASN1_FUNCTIONS(OSSL_TIME_SPEC)
125 IMPLEMENT_ASN1_FUNCTIONS(OSSL_TIME_PERIOD)
126
127 static int i2r_OSSL_TIME_SPEC_ABSOLUTE(X509V3_EXT_METHOD *method,
128 OSSL_TIME_SPEC_ABSOLUTE *time,
129 BIO *out, int indent)
130 {
131 if (time->startTime != NULL && time->endTime != NULL) {
132 if (!BIO_puts(out, "Any time between "))
133 return 0;
134 if (!ossl_asn1_time_print_ex(out, time->startTime, 0))
135 return 0;
136 if (!BIO_puts(out, " and "))
137 return 0;
138 if (!ossl_asn1_time_print_ex(out, time->endTime, 0))
139 return 0;
140 } else if (time->startTime != NULL) {
141 if (!BIO_puts(out, "Any time after "))
142 return 0;
143 if (!ossl_asn1_time_print_ex(out, time->startTime, 0))
144 return 0;
145 if (BIO_printf(out, "%.*s", time->startTime->length, time->startTime->data) <= 0)
146 return 0;
147 } else if (time->endTime != NULL) {
148 if (!BIO_puts(out, "Any time until "))
149 return 0;
150 if (!ossl_asn1_time_print_ex(out, time->endTime, 0))
151 return 0;
152 } else { /* Invalid: there must be SOME time specified. */
153 return BIO_puts(out, "INVALID (EMPTY)");
154 }
155 return 1;
156 }
157
i2r_OSSL_DAY_TIME(X509V3_EXT_METHOD * method,OSSL_DAY_TIME * dt,BIO * out,int indent)158 static int i2r_OSSL_DAY_TIME(X509V3_EXT_METHOD *method,
159 OSSL_DAY_TIME *dt,
160 BIO *out, int indent)
161 {
162 int64_t h = 0;
163 int64_t m = 0;
164 int64_t s = 0;
165
166 if (!dt->hour || !ASN1_INTEGER_get_int64(&h, dt->hour))
167 return 0;
168 if (dt->minute && !ASN1_INTEGER_get_int64(&m, dt->minute))
169 return 0;
170 if (dt->second && !ASN1_INTEGER_get_int64(&s, dt->second))
171 return 0;
172 return BIO_printf(out, "%02lld:%02lld:%02lld",
173 (long long int)h, (long long int)m, (long long int)s)
174 > 0;
175 }
176
i2r_OSSL_DAY_TIME_BAND(X509V3_EXT_METHOD * method,OSSL_DAY_TIME_BAND * band,BIO * out,int indent)177 static int i2r_OSSL_DAY_TIME_BAND(X509V3_EXT_METHOD *method,
178 OSSL_DAY_TIME_BAND *band,
179 BIO *out, int indent)
180 {
181 if (band->startDayTime) {
182 if (!i2r_OSSL_DAY_TIME(method, band->startDayTime, out, indent))
183 return 0;
184 } else if (!BIO_puts(out, "00:00:00")) {
185 return 0;
186 }
187 if (!BIO_puts(out, " - "))
188 return 0;
189 if (band->endDayTime) {
190 if (!i2r_OSSL_DAY_TIME(method, band->endDayTime, out, indent))
191 return 0;
192 } else if (!BIO_puts(out, "23:59:59")) {
193 return 0;
194 }
195 return 1;
196 }
197
print_int_month(BIO * out,int64_t month)198 static int print_int_month(BIO *out, int64_t month)
199 {
200 switch (month) {
201 case (OSSL_TIME_SPEC_INT_MONTH_JAN):
202 return BIO_puts(out, "JAN");
203 case (OSSL_TIME_SPEC_INT_MONTH_FEB):
204 return BIO_puts(out, "FEB");
205 case (OSSL_TIME_SPEC_INT_MONTH_MAR):
206 return BIO_puts(out, "MAR");
207 case (OSSL_TIME_SPEC_INT_MONTH_APR):
208 return BIO_puts(out, "APR");
209 case (OSSL_TIME_SPEC_INT_MONTH_MAY):
210 return BIO_puts(out, "MAY");
211 case (OSSL_TIME_SPEC_INT_MONTH_JUN):
212 return BIO_puts(out, "JUN");
213 case (OSSL_TIME_SPEC_INT_MONTH_JUL):
214 return BIO_puts(out, "JUL");
215 case (OSSL_TIME_SPEC_INT_MONTH_AUG):
216 return BIO_puts(out, "AUG");
217 case (OSSL_TIME_SPEC_INT_MONTH_SEP):
218 return BIO_puts(out, "SEP");
219 case (OSSL_TIME_SPEC_INT_MONTH_OCT):
220 return BIO_puts(out, "OCT");
221 case (OSSL_TIME_SPEC_INT_MONTH_NOV):
222 return BIO_puts(out, "NOV");
223 case (OSSL_TIME_SPEC_INT_MONTH_DEC):
224 return BIO_puts(out, "DEC");
225 default:
226 return 0;
227 }
228 return 0;
229 }
230
print_bit_month(BIO * out,ASN1_BIT_STRING * bs)231 static int print_bit_month(BIO *out, ASN1_BIT_STRING *bs)
232 {
233 int i = OSSL_TIME_SPEC_BIT_MONTH_JAN;
234 int j = 0;
235
236 for (; i <= OSSL_TIME_SPEC_BIT_MONTH_DEC; i++) {
237 if (ASN1_BIT_STRING_get_bit(bs, i)) {
238 if (j > 0 && !BIO_puts(out, ", "))
239 return 0;
240 j++;
241 if (!BIO_puts(out, MONTH_NAMES[i]))
242 return 0;
243 }
244 }
245 return 1;
246 }
247
248 /*
249 * It might seem like you could just print the bits of the string numerically,
250 * but the fifth bit has the special meaning of "the final week" imputed to it
251 * by the text of ITU-T Recommendation X.520.
252 */
print_bit_week(BIO * out,ASN1_BIT_STRING * bs)253 static int print_bit_week(BIO *out, ASN1_BIT_STRING *bs)
254 {
255 int i = OSSL_TIME_SPEC_BIT_WEEKS_1;
256 int j = 0;
257
258 for (; i <= OSSL_TIME_SPEC_BIT_WEEKS_5; i++) {
259 if (ASN1_BIT_STRING_get_bit(bs, i)) {
260 if (j > 0 && !BIO_puts(out, ", "))
261 return 0;
262 j++;
263 if (!BIO_puts(out, WEEK_NAMES[i]))
264 return 0;
265 }
266 }
267 return 1;
268 }
269
print_day_of_week(BIO * out,ASN1_BIT_STRING * bs)270 static int print_day_of_week(BIO *out, ASN1_BIT_STRING *bs)
271 {
272 int i = OSSL_TIME_SPEC_DAY_BIT_SUN;
273 int j = 0;
274
275 for (; i <= OSSL_TIME_SPEC_DAY_BIT_SAT; i++) {
276 if (ASN1_BIT_STRING_get_bit(bs, i)) {
277 if (j > 0 && !BIO_puts(out, ", "))
278 return 0;
279 j++;
280 if (!BIO_puts(out, WEEKDAY_NAMES[i]))
281 return 0;
282 }
283 }
284 return 1;
285 }
286
print_int_day_of_week(BIO * out,int64_t dow)287 static int print_int_day_of_week(BIO *out, int64_t dow)
288 {
289 switch (dow) {
290 case (OSSL_TIME_SPEC_DAY_INT_SUN):
291 return BIO_puts(out, "SUN");
292 case (OSSL_TIME_SPEC_DAY_INT_MON):
293 return BIO_puts(out, "MON");
294 case (OSSL_TIME_SPEC_DAY_INT_TUE):
295 return BIO_puts(out, "TUE");
296 case (OSSL_TIME_SPEC_DAY_INT_WED):
297 return BIO_puts(out, "WED");
298 case (OSSL_TIME_SPEC_DAY_INT_THU):
299 return BIO_puts(out, "THU");
300 case (OSSL_TIME_SPEC_DAY_INT_FRI):
301 return BIO_puts(out, "FRI");
302 case (OSSL_TIME_SPEC_DAY_INT_SAT):
303 return BIO_puts(out, "SAT");
304 default:
305 return 0;
306 }
307 return 0;
308 }
309
print_int_named_day(BIO * out,int64_t nd)310 static int print_int_named_day(BIO *out, int64_t nd)
311 {
312 switch (nd) {
313 case (OSSL_NAMED_DAY_INT_SUN):
314 return BIO_puts(out, "SUN");
315 case (OSSL_NAMED_DAY_INT_MON):
316 return BIO_puts(out, "MON");
317 case (OSSL_NAMED_DAY_INT_TUE):
318 return BIO_puts(out, "TUE");
319 case (OSSL_NAMED_DAY_INT_WED):
320 return BIO_puts(out, "WED");
321 case (OSSL_NAMED_DAY_INT_THU):
322 return BIO_puts(out, "THU");
323 case (OSSL_NAMED_DAY_INT_FRI):
324 return BIO_puts(out, "FRI");
325 case (OSSL_NAMED_DAY_INT_SAT):
326 return BIO_puts(out, "SAT");
327 default:
328 return 0;
329 }
330 return 0;
331 }
332
print_bit_named_day(BIO * out,ASN1_BIT_STRING * bs)333 static int print_bit_named_day(BIO *out, ASN1_BIT_STRING *bs)
334 {
335 return print_day_of_week(out, bs);
336 }
337
i2r_OSSL_PERIOD(X509V3_EXT_METHOD * method,OSSL_TIME_PERIOD * p,BIO * out,int indent)338 static int i2r_OSSL_PERIOD(X509V3_EXT_METHOD *method,
339 OSSL_TIME_PERIOD *p,
340 BIO *out, int indent)
341 {
342 int i;
343 OSSL_DAY_TIME_BAND *band;
344 ASN1_INTEGER *big_val;
345 int64_t small_val;
346 OSSL_NAMED_DAY *nd;
347
348 if (BIO_printf(out, "%*sPeriod:\n", indent, "") <= 0)
349 return 0;
350 if (p->timesOfDay) {
351 if (BIO_printf(out, "%*sDaytime bands:\n", indent + 4, "") <= 0)
352 return 0;
353 for (i = 0; i < sk_OSSL_DAY_TIME_BAND_num(p->timesOfDay); i++) {
354 band = sk_OSSL_DAY_TIME_BAND_value(p->timesOfDay, i);
355 if (BIO_printf(out, "%*s", indent + 8, "") <= 0)
356 return 0;
357 if (!i2r_OSSL_DAY_TIME_BAND(method, band, out, indent + 8))
358 return 0;
359 if (!BIO_puts(out, "\n"))
360 return 0;
361 }
362 }
363 if (p->days) {
364 if (p->days->type == OSSL_TIME_SPEC_DAY_TYPE_INT) {
365 if (p->weeks != NULL) {
366 if (BIO_printf(out, "%*sDays of the week: ", indent + 4, "") <= 0)
367 return 0;
368 } else if (p->months != NULL) {
369 if (BIO_printf(out, "%*sDays of the month: ", indent + 4, "") <= 0)
370 return 0;
371 } else if (p->years != NULL) {
372 if (BIO_printf(out, "%*sDays of the year: ", indent + 4, "") <= 0)
373 return 0;
374 }
375 } else {
376 if (BIO_printf(out, "%*sDays: ", indent + 4, "") <= 0)
377 return 0;
378 }
379
380 switch (p->days->type) {
381 case (OSSL_TIME_SPEC_DAY_TYPE_INT):
382 for (i = 0; i < sk_ASN1_INTEGER_num(p->days->choice.intDay); i++) {
383 big_val = sk_ASN1_INTEGER_value(p->days->choice.intDay, i);
384 if (!ASN1_INTEGER_get_int64(&small_val, big_val))
385 return 0;
386 if (i > 0 && !BIO_puts(out, ", "))
387 return 0;
388 /* If weeks is defined, then print day of week by name. */
389 if (p->weeks != NULL) {
390 if (!print_int_day_of_week(out, small_val))
391 return 0;
392 } else if (BIO_printf(out, "%lld", (long long int)small_val) <= 0) {
393 return 0;
394 }
395 }
396 break;
397 case (OSSL_TIME_SPEC_DAY_TYPE_BIT):
398 if (!print_day_of_week(out, p->days->choice.bitDay))
399 return 0;
400 break;
401 case (OSSL_TIME_SPEC_DAY_TYPE_DAY_OF):
402 switch (p->days->choice.dayOf->type) {
403 case (OSSL_TIME_SPEC_X_DAY_OF_FIRST):
404 if (!BIO_puts(out, "FIRST "))
405 return 0;
406 nd = p->days->choice.dayOf->choice.first;
407 break;
408 case (OSSL_TIME_SPEC_X_DAY_OF_SECOND):
409 if (!BIO_puts(out, "SECOND "))
410 return 0;
411 nd = p->days->choice.dayOf->choice.second;
412 break;
413 case (OSSL_TIME_SPEC_X_DAY_OF_THIRD):
414 if (!BIO_puts(out, "THIRD "))
415 return 0;
416 nd = p->days->choice.dayOf->choice.third;
417 break;
418 case (OSSL_TIME_SPEC_X_DAY_OF_FOURTH):
419 if (!BIO_puts(out, "FOURTH "))
420 return 0;
421 nd = p->days->choice.dayOf->choice.fourth;
422 break;
423 case (OSSL_TIME_SPEC_X_DAY_OF_FIFTH):
424 if (!BIO_puts(out, "FIFTH "))
425 return 0;
426 nd = p->days->choice.dayOf->choice.fifth;
427 break;
428 default:
429 return 0;
430 }
431 switch (nd->type) {
432 case (OSSL_NAMED_DAY_TYPE_INT):
433 if (!ASN1_INTEGER_get_int64(&small_val, nd->choice.intNamedDays))
434 return 0;
435 if (!print_int_named_day(out, small_val))
436 return 0;
437 break;
438 case (OSSL_NAMED_DAY_TYPE_BIT):
439 if (!print_bit_named_day(out, nd->choice.bitNamedDays))
440 return 0;
441 break;
442 default:
443 return 0;
444 }
445 break;
446 default:
447 return 0;
448 }
449 if (!BIO_puts(out, "\n"))
450 return 0;
451 }
452 if (p->weeks) {
453 if (p->weeks->type == OSSL_TIME_SPEC_WEEKS_TYPE_INT) {
454 if (p->months != NULL) {
455 if (BIO_printf(out, "%*sWeeks of the month: ", indent + 4, "") <= 0)
456 return 0;
457 } else if (p->years != NULL) {
458 if (BIO_printf(out, "%*sWeeks of the year: ", indent + 4, "") <= 0)
459 return 0;
460 }
461 } else {
462 if (BIO_printf(out, "%*sWeeks: ", indent + 4, "") <= 0)
463 return 0;
464 }
465
466 switch (p->weeks->type) {
467 case (OSSL_TIME_SPEC_WEEKS_TYPE_ALL):
468 if (!BIO_puts(out, "ALL"))
469 return 0;
470 break;
471 case (OSSL_TIME_SPEC_WEEKS_TYPE_INT):
472 for (i = 0; i < sk_ASN1_INTEGER_num(p->weeks->choice.intWeek); i++) {
473 big_val = sk_ASN1_INTEGER_value(p->weeks->choice.intWeek, i);
474 if (!ASN1_INTEGER_get_int64(&small_val, big_val))
475 return 0;
476 if (i > 0 && !BIO_puts(out, ", "))
477 return 0;
478 if (!BIO_printf(out, "%lld", (long long int)small_val))
479 return 0;
480 }
481 break;
482 case (OSSL_TIME_SPEC_WEEKS_TYPE_BIT):
483 if (!print_bit_week(out, p->weeks->choice.bitWeek))
484 return 0;
485 break;
486 default:
487 return 0;
488 }
489 if (!BIO_puts(out, "\n"))
490 return 0;
491 }
492 if (p->months) {
493 if (BIO_printf(out, "%*sMonths: ", indent + 4, "") <= 0)
494 return 0;
495 switch (p->months->type) {
496 case (OSSL_TIME_SPEC_MONTH_TYPE_ALL):
497 if (!BIO_puts(out, "ALL"))
498 return 0;
499 break;
500 case (OSSL_TIME_SPEC_MONTH_TYPE_INT):
501 for (i = 0; i < sk_ASN1_INTEGER_num(p->months->choice.intMonth); i++) {
502 big_val = sk_ASN1_INTEGER_value(p->months->choice.intMonth, i);
503 if (!ASN1_INTEGER_get_int64(&small_val, big_val))
504 return 0;
505 if (i > 0 && !BIO_puts(out, ", "))
506 return 0;
507 if (!print_int_month(out, small_val))
508 return 0;
509 }
510 break;
511 case (OSSL_TIME_SPEC_MONTH_TYPE_BIT):
512 if (!print_bit_month(out, p->months->choice.bitMonth))
513 return 0;
514 break;
515 default:
516 return 0;
517 }
518 if (!BIO_puts(out, "\n"))
519 return 0;
520 }
521 if (p->years) {
522 if (BIO_printf(out, "%*sYears: ", indent + 4, "") <= 0)
523 return 0;
524 for (i = 0; i < sk_ASN1_INTEGER_num(p->years); i++) {
525 big_val = sk_ASN1_INTEGER_value(p->years, i);
526 if (!ASN1_INTEGER_get_int64(&small_val, big_val))
527 return 0;
528 if (i > 0 && !BIO_puts(out, ", "))
529 return 0;
530 if (BIO_printf(out, "%04lld", (long long int)small_val) <= 0)
531 return 0;
532 }
533 }
534 return 1;
535 }
536
i2r_OSSL_TIME_SPEC_TIME(X509V3_EXT_METHOD * method,OSSL_TIME_SPEC_TIME * time,BIO * out,int indent)537 static int i2r_OSSL_TIME_SPEC_TIME(X509V3_EXT_METHOD *method,
538 OSSL_TIME_SPEC_TIME *time,
539 BIO *out, int indent)
540 {
541 OSSL_TIME_PERIOD *tp;
542 int i;
543
544 switch (time->type) {
545 case (OSSL_TIME_SPEC_TIME_TYPE_ABSOLUTE):
546 if (BIO_printf(out, "%*sAbsolute: ", indent, "") <= 0)
547 return 0;
548 if (i2r_OSSL_TIME_SPEC_ABSOLUTE(method, time->choice.absolute, out, indent + 4) <= 0)
549 return 0;
550 return BIO_puts(out, "\n");
551 case (OSSL_TIME_SPEC_TIME_TYPE_PERIODIC):
552 if (BIO_printf(out, "%*sPeriodic:\n", indent, "") <= 0)
553 return 0;
554 for (i = 0; i < sk_OSSL_TIME_PERIOD_num(time->choice.periodic); i++) {
555 if (i > 0 && !BIO_puts(out, "\n"))
556 return 0;
557 tp = sk_OSSL_TIME_PERIOD_value(time->choice.periodic, i);
558 if (!i2r_OSSL_PERIOD(method, tp, out, indent + 4))
559 return 0;
560 }
561 return BIO_puts(out, "\n");
562 default:
563 return 0;
564 }
565 return 0;
566 }
567
i2r_OSSL_TIME_SPEC(X509V3_EXT_METHOD * method,OSSL_TIME_SPEC * time,BIO * out,int indent)568 static int i2r_OSSL_TIME_SPEC(X509V3_EXT_METHOD *method,
569 OSSL_TIME_SPEC *time,
570 BIO *out, int indent)
571 {
572 int64_t tz;
573
574 if (time->timeZone) {
575 if (ASN1_INTEGER_get_int64(&tz, time->timeZone) != 1)
576 return 0;
577 if (BIO_printf(out, "%*sTimezone: UTC%+03lld:00\n", indent, "", (long long int)tz) <= 0)
578 return 0;
579 }
580 if (time->notThisTime > 0) {
581 if (BIO_printf(out, "%*sNOT this time:\n", indent, "") <= 0)
582 return 0;
583 } else if (BIO_printf(out, "%*sTime:\n", indent, "") <= 0) {
584 return 0;
585 }
586 return i2r_OSSL_TIME_SPEC_TIME(method, time->time, out, indent + 4);
587 }
588
589 const X509V3_EXT_METHOD ossl_v3_time_specification = {
590 NID_time_specification, X509V3_EXT_MULTILINE,
591 ASN1_ITEM_ref(OSSL_TIME_SPEC),
592 0, 0, 0, 0,
593 0, 0,
594 0,
595 0,
596 (X509V3_EXT_I2R)i2r_OSSL_TIME_SPEC,
597 NULL,
598 NULL
599 };
600