1 /*
2 * Copyright 2024 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->minute && !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) > 0;
174 }
175
i2r_OSSL_DAY_TIME_BAND(X509V3_EXT_METHOD * method,OSSL_DAY_TIME_BAND * band,BIO * out,int indent)176 static int i2r_OSSL_DAY_TIME_BAND(X509V3_EXT_METHOD *method,
177 OSSL_DAY_TIME_BAND *band,
178 BIO *out, int indent)
179 {
180 if (band->startDayTime) {
181 if (!i2r_OSSL_DAY_TIME(method, band->startDayTime, out, indent))
182 return 0;
183 } else if (!BIO_puts(out, "00:00:00")) {
184 return 0;
185 }
186 if (!BIO_puts(out, " - "))
187 return 0;
188 if (band->endDayTime) {
189 if (!i2r_OSSL_DAY_TIME(method, band->endDayTime, out, indent))
190 return 0;
191 } else if (!BIO_puts(out, "23:59:59")) {
192 return 0;
193 }
194 return 1;
195 }
196
print_int_month(BIO * out,int64_t month)197 static int print_int_month(BIO *out, int64_t month)
198 {
199 switch (month) {
200 case (OSSL_TIME_SPEC_INT_MONTH_JAN):
201 return BIO_puts(out, "JAN");
202 case (OSSL_TIME_SPEC_INT_MONTH_FEB):
203 return BIO_puts(out, "FEB");
204 case (OSSL_TIME_SPEC_INT_MONTH_MAR):
205 return BIO_puts(out, "MAR");
206 case (OSSL_TIME_SPEC_INT_MONTH_APR):
207 return BIO_puts(out, "APR");
208 case (OSSL_TIME_SPEC_INT_MONTH_MAY):
209 return BIO_puts(out, "MAY");
210 case (OSSL_TIME_SPEC_INT_MONTH_JUN):
211 return BIO_puts(out, "JUN");
212 case (OSSL_TIME_SPEC_INT_MONTH_JUL):
213 return BIO_puts(out, "JUL");
214 case (OSSL_TIME_SPEC_INT_MONTH_AUG):
215 return BIO_puts(out, "AUG");
216 case (OSSL_TIME_SPEC_INT_MONTH_SEP):
217 return BIO_puts(out, "SEP");
218 case (OSSL_TIME_SPEC_INT_MONTH_OCT):
219 return BIO_puts(out, "OCT");
220 case (OSSL_TIME_SPEC_INT_MONTH_NOV):
221 return BIO_puts(out, "NOV");
222 case (OSSL_TIME_SPEC_INT_MONTH_DEC):
223 return BIO_puts(out, "DEC");
224 default:
225 return 0;
226 }
227 return 0;
228 }
229
print_bit_month(BIO * out,ASN1_BIT_STRING * bs)230 static int print_bit_month(BIO *out, ASN1_BIT_STRING *bs)
231 {
232 int i = OSSL_TIME_SPEC_BIT_MONTH_JAN;
233 int j = 0;
234
235 for (; i <= OSSL_TIME_SPEC_BIT_MONTH_DEC; i++) {
236 if (ASN1_BIT_STRING_get_bit(bs, i)) {
237 if (j > 0 && !BIO_puts(out, ", "))
238 return 0;
239 j++;
240 if (!BIO_puts(out, MONTH_NAMES[i]))
241 return 0;
242 }
243 }
244 return 1;
245 }
246
247 /*
248 * It might seem like you could just print the bits of the string numerically,
249 * but the fifth bit has the special meaning of "the final week" imputed to it
250 * by the text of ITU-T Recommendation X.520.
251 */
print_bit_week(BIO * out,ASN1_BIT_STRING * bs)252 static int print_bit_week(BIO *out, ASN1_BIT_STRING *bs)
253 {
254 int i = OSSL_TIME_SPEC_BIT_WEEKS_1;
255 int j = 0;
256
257 for (; i <= OSSL_TIME_SPEC_BIT_WEEKS_5; i++) {
258 if (ASN1_BIT_STRING_get_bit(bs, i)) {
259 if (j > 0 && !BIO_puts(out, ", "))
260 return 0;
261 j++;
262 if (!BIO_puts(out, WEEK_NAMES[i]))
263 return 0;
264 }
265 }
266 return 1;
267 }
268
print_day_of_week(BIO * out,ASN1_BIT_STRING * bs)269 static int print_day_of_week(BIO *out, ASN1_BIT_STRING *bs)
270 {
271 int i = OSSL_TIME_SPEC_DAY_BIT_SUN;
272 int j = 0;
273
274 for (; i <= OSSL_TIME_SPEC_DAY_BIT_SAT; i++) {
275 if (ASN1_BIT_STRING_get_bit(bs, i)) {
276 if (j > 0 && !BIO_puts(out, ", "))
277 return 0;
278 j++;
279 if (!BIO_puts(out, WEEKDAY_NAMES[i]))
280 return 0;
281 }
282 }
283 return 1;
284 }
285
print_int_day_of_week(BIO * out,int64_t dow)286 static int print_int_day_of_week(BIO *out, int64_t dow)
287 {
288 switch (dow) {
289 case (OSSL_TIME_SPEC_DAY_INT_SUN):
290 return BIO_puts(out, "SUN");
291 case (OSSL_TIME_SPEC_DAY_INT_MON):
292 return BIO_puts(out, "MON");
293 case (OSSL_TIME_SPEC_DAY_INT_TUE):
294 return BIO_puts(out, "TUE");
295 case (OSSL_TIME_SPEC_DAY_INT_WED):
296 return BIO_puts(out, "WED");
297 case (OSSL_TIME_SPEC_DAY_INT_THU):
298 return BIO_puts(out, "THU");
299 case (OSSL_TIME_SPEC_DAY_INT_FRI):
300 return BIO_puts(out, "FRI");
301 case (OSSL_TIME_SPEC_DAY_INT_SAT):
302 return BIO_puts(out, "SAT");
303 default:
304 return 0;
305 }
306 return 0;
307 }
308
print_int_named_day(BIO * out,int64_t nd)309 static int print_int_named_day(BIO *out, int64_t nd)
310 {
311 switch (nd) {
312 case (OSSL_NAMED_DAY_INT_SUN):
313 return BIO_puts(out, "SUN");
314 case (OSSL_NAMED_DAY_INT_MON):
315 return BIO_puts(out, "MON");
316 case (OSSL_NAMED_DAY_INT_TUE):
317 return BIO_puts(out, "TUE");
318 case (OSSL_NAMED_DAY_INT_WED):
319 return BIO_puts(out, "WED");
320 case (OSSL_NAMED_DAY_INT_THU):
321 return BIO_puts(out, "THU");
322 case (OSSL_NAMED_DAY_INT_FRI):
323 return BIO_puts(out, "FRI");
324 case (OSSL_NAMED_DAY_INT_SAT):
325 return BIO_puts(out, "SAT");
326 default:
327 return 0;
328 }
329 return 0;
330 }
331
print_bit_named_day(BIO * out,ASN1_BIT_STRING * bs)332 static int print_bit_named_day(BIO *out, ASN1_BIT_STRING *bs)
333 {
334 return print_day_of_week(out, bs);
335 }
336
i2r_OSSL_PERIOD(X509V3_EXT_METHOD * method,OSSL_TIME_PERIOD * p,BIO * out,int indent)337 static int i2r_OSSL_PERIOD(X509V3_EXT_METHOD *method,
338 OSSL_TIME_PERIOD *p,
339 BIO *out, int indent)
340 {
341 int i;
342 OSSL_DAY_TIME_BAND *band;
343 ASN1_INTEGER *big_val;
344 int64_t small_val;
345 OSSL_NAMED_DAY *nd;
346
347 if (BIO_printf(out, "%*sPeriod:\n", indent, "") <= 0)
348 return 0;
349 if (p->timesOfDay) {
350 if (BIO_printf(out, "%*sDaytime bands:\n", indent + 4, "") <= 0)
351 return 0;
352 for (i = 0; i < sk_OSSL_DAY_TIME_BAND_num(p->timesOfDay); i++) {
353 band = sk_OSSL_DAY_TIME_BAND_value(p->timesOfDay, i);
354 if (BIO_printf(out, "%*s", indent + 8, "") <= 0)
355 return 0;
356 if (!i2r_OSSL_DAY_TIME_BAND(method, band, out, indent + 8))
357 return 0;
358 if (!BIO_puts(out, "\n"))
359 return 0;
360 }
361 }
362 if (p->days) {
363 if (p->days->type == OSSL_TIME_SPEC_DAY_TYPE_INT) {
364 if (p->weeks != NULL) {
365 if (BIO_printf(out, "%*sDays of the week: ", indent + 4, "") <= 0)
366 return 0;
367 } else if (p->months != NULL) {
368 if (BIO_printf(out, "%*sDays of the month: ", indent + 4, "") <= 0)
369 return 0;
370 } else if (p->years != NULL) {
371 if (BIO_printf(out, "%*sDays of the year: ", indent + 4, "") <= 0)
372 return 0;
373 }
374 } else {
375 if (BIO_printf(out, "%*sDays: ", indent + 4, "") <= 0)
376 return 0;
377 }
378
379 switch (p->days->type) {
380 case (OSSL_TIME_SPEC_DAY_TYPE_INT):
381 for (i = 0; i < sk_ASN1_INTEGER_num(p->days->choice.intDay); i++) {
382 big_val = sk_ASN1_INTEGER_value(p->days->choice.intDay, i);
383 if (!ASN1_INTEGER_get_int64(&small_val, big_val))
384 return 0;
385 if (i > 0 && !BIO_puts(out, ", "))
386 return 0;
387 /* If weeks is defined, then print day of week by name. */
388 if (p->weeks != NULL) {
389 if (!print_int_day_of_week(out, small_val))
390 return 0;
391 } else if (BIO_printf(out, "%lld", (long long int)small_val) <= 0) {
392 return 0;
393 }
394 }
395 break;
396 case (OSSL_TIME_SPEC_DAY_TYPE_BIT):
397 if (!print_day_of_week(out, p->days->choice.bitDay))
398 return 0;
399 break;
400 case (OSSL_TIME_SPEC_DAY_TYPE_DAY_OF):
401 switch (p->days->choice.dayOf->type) {
402 case (OSSL_TIME_SPEC_X_DAY_OF_FIRST):
403 if (!BIO_puts(out, "FIRST "))
404 return 0;
405 nd = p->days->choice.dayOf->choice.first;
406 break;
407 case (OSSL_TIME_SPEC_X_DAY_OF_SECOND):
408 if (!BIO_puts(out, "SECOND "))
409 return 0;
410 nd = p->days->choice.dayOf->choice.second;
411 break;
412 case (OSSL_TIME_SPEC_X_DAY_OF_THIRD):
413 if (!BIO_puts(out, "THIRD "))
414 return 0;
415 nd = p->days->choice.dayOf->choice.third;
416 break;
417 case (OSSL_TIME_SPEC_X_DAY_OF_FOURTH):
418 if (!BIO_puts(out, "FOURTH "))
419 return 0;
420 nd = p->days->choice.dayOf->choice.fourth;
421 break;
422 case (OSSL_TIME_SPEC_X_DAY_OF_FIFTH):
423 if (!BIO_puts(out, "FIFTH "))
424 return 0;
425 nd = p->days->choice.dayOf->choice.fifth;
426 break;
427 default:
428 return 0;
429 }
430 switch (nd->type) {
431 case (OSSL_NAMED_DAY_TYPE_INT):
432 if (!ASN1_INTEGER_get_int64(&small_val, nd->choice.intNamedDays))
433 return 0;
434 if (!print_int_named_day(out, small_val))
435 return 0;
436 break;
437 case (OSSL_NAMED_DAY_TYPE_BIT):
438 if (!print_bit_named_day(out, nd->choice.bitNamedDays))
439 return 0;
440 break;
441 default:
442 return 0;
443 }
444 break;
445 default:
446 return 0;
447 }
448 if (!BIO_puts(out, "\n"))
449 return 0;
450 }
451 if (p->weeks) {
452 if (p->weeks->type == OSSL_TIME_SPEC_WEEKS_TYPE_INT) {
453 if (p->months != NULL) {
454 if (BIO_printf(out, "%*sWeeks of the month: ", indent + 4, "") <= 0)
455 return 0;
456 } else if (p->years != NULL) {
457 if (BIO_printf(out, "%*sWeeks of the year: ", indent + 4, "") <= 0)
458 return 0;
459 }
460 } else {
461 if (BIO_printf(out, "%*sWeeks: ", indent + 4, "") <= 0)
462 return 0;
463 }
464
465 switch (p->weeks->type) {
466 case (OSSL_TIME_SPEC_WEEKS_TYPE_ALL):
467 if (!BIO_puts(out, "ALL"))
468 return 0;
469 break;
470 case (OSSL_TIME_SPEC_WEEKS_TYPE_INT):
471 for (i = 0; i < sk_ASN1_INTEGER_num(p->weeks->choice.intWeek); i++) {
472 big_val = sk_ASN1_INTEGER_value(p->weeks->choice.intWeek, i);
473 if (!ASN1_INTEGER_get_int64(&small_val, big_val))
474 return 0;
475 if (i > 0 && !BIO_puts(out, ", "))
476 return 0;
477 if (!BIO_printf(out, "%lld", (long long int)small_val))
478 return 0;
479 }
480 break;
481 case (OSSL_TIME_SPEC_WEEKS_TYPE_BIT):
482 if (!print_bit_week(out, p->weeks->choice.bitWeek))
483 return 0;
484 break;
485 default:
486 return 0;
487 }
488 if (!BIO_puts(out, "\n"))
489 return 0;
490 }
491 if (p->months) {
492 if (BIO_printf(out, "%*sMonths: ", indent + 4, "") <= 0)
493 return 0;
494 switch (p->months->type) {
495 case (OSSL_TIME_SPEC_MONTH_TYPE_ALL):
496 if (!BIO_puts(out, "ALL"))
497 return 0;
498 break;
499 case (OSSL_TIME_SPEC_MONTH_TYPE_INT):
500 for (i = 0; i < sk_ASN1_INTEGER_num(p->months->choice.intMonth); i++) {
501 big_val = sk_ASN1_INTEGER_value(p->months->choice.intMonth, i);
502 if (!ASN1_INTEGER_get_int64(&small_val, big_val))
503 return 0;
504 if (i > 0 && !BIO_puts(out, ", "))
505 return 0;
506 if (!print_int_month(out, small_val))
507 return 0;
508 }
509 break;
510 case (OSSL_TIME_SPEC_MONTH_TYPE_BIT):
511 if (!print_bit_month(out, p->months->choice.bitMonth))
512 return 0;
513 break;
514 default:
515 return 0;
516 }
517 if (!BIO_puts(out, "\n"))
518 return 0;
519 }
520 if (p->years) {
521 if (BIO_printf(out, "%*sYears: ", indent + 4, "") <= 0)
522 return 0;
523 for (i = 0; i < sk_ASN1_INTEGER_num(p->years); i++) {
524 big_val = sk_ASN1_INTEGER_value(p->years, i);
525 if (!ASN1_INTEGER_get_int64(&small_val, big_val))
526 return 0;
527 if (i > 0 && !BIO_puts(out, ", "))
528 return 0;
529 if (BIO_printf(out, "%04lld", (long long int)small_val) <= 0)
530 return 0;
531 }
532 }
533 return 1;
534 }
535
i2r_OSSL_TIME_SPEC_TIME(X509V3_EXT_METHOD * method,OSSL_TIME_SPEC_TIME * time,BIO * out,int indent)536 static int i2r_OSSL_TIME_SPEC_TIME(X509V3_EXT_METHOD *method,
537 OSSL_TIME_SPEC_TIME *time,
538 BIO *out, int indent)
539 {
540 OSSL_TIME_PERIOD *tp;
541 int i;
542
543 switch (time->type) {
544 case (OSSL_TIME_SPEC_TIME_TYPE_ABSOLUTE):
545 if (BIO_printf(out, "%*sAbsolute: ", indent, "") <= 0)
546 return 0;
547 if (i2r_OSSL_TIME_SPEC_ABSOLUTE(method, time->choice.absolute, out, indent + 4) <= 0)
548 return 0;
549 return BIO_puts(out, "\n");
550 case (OSSL_TIME_SPEC_TIME_TYPE_PERIODIC):
551 if (BIO_printf(out, "%*sPeriodic:\n", indent, "") <= 0)
552 return 0;
553 for (i = 0; i < sk_OSSL_TIME_PERIOD_num(time->choice.periodic); i++) {
554 if (i > 0 && !BIO_puts(out, "\n"))
555 return 0;
556 tp = sk_OSSL_TIME_PERIOD_value(time->choice.periodic, i);
557 if (!i2r_OSSL_PERIOD(method, tp, out, indent + 4))
558 return 0;
559 }
560 return BIO_puts(out, "\n");
561 default:
562 return 0;
563 }
564 return 0;
565 }
566
i2r_OSSL_TIME_SPEC(X509V3_EXT_METHOD * method,OSSL_TIME_SPEC * time,BIO * out,int indent)567 static int i2r_OSSL_TIME_SPEC(X509V3_EXT_METHOD *method,
568 OSSL_TIME_SPEC *time,
569 BIO *out, int indent)
570 {
571 int64_t tz;
572
573 if (time->timeZone) {
574 if (ASN1_INTEGER_get_int64(&tz, time->timeZone) != 1)
575 return 0;
576 if (BIO_printf(out, "%*sTimezone: UTC%+03lld:00\n", indent, "", (long long int)tz) <= 0)
577 return 0;
578 }
579 if (time->notThisTime > 0) {
580 if (BIO_printf(out, "%*sNOT this time:\n", indent, "") <= 0)
581 return 0;
582 } else if (BIO_printf(out, "%*sTime:\n", indent, "") <= 0) {
583 return 0;
584 }
585 return i2r_OSSL_TIME_SPEC_TIME(method, time->time, out, indent + 4);
586 }
587
588 const X509V3_EXT_METHOD ossl_v3_time_specification = {
589 NID_time_specification, X509V3_EXT_MULTILINE,
590 ASN1_ITEM_ref(OSSL_TIME_SPEC),
591 0, 0, 0, 0,
592 0, 0,
593 0,
594 0,
595 (X509V3_EXT_I2R)i2r_OSSL_TIME_SPEC,
596 NULL,
597 NULL
598 };
599