1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4
5 /**
6 @file der_decode_utctime.c
7 ASN.1 DER, decode a UTCTIME, Tom St Denis
8 */
9
10 #ifdef LTC_DER
11
s_char_to_int(unsigned char x)12 static int s_char_to_int(unsigned char x)
13 {
14 switch (x) {
15 case '0': return 0;
16 case '1': return 1;
17 case '2': return 2;
18 case '3': return 3;
19 case '4': return 4;
20 case '5': return 5;
21 case '6': return 6;
22 case '7': return 7;
23 case '8': return 8;
24 case '9': return 9;
25 default: return 100;
26 }
27 }
28
29 #define DECODE_V(y, max) \
30 y = s_char_to_int(buf[x])*10 + s_char_to_int(buf[x+1]); \
31 if (y >= max) return CRYPT_INVALID_PACKET; \
32 x += 2;
33
34 /**
35 Decodes a UTC time structure in DER format (reads all 6 valid encoding formats)
36 @param in Input buffer
37 @param inlen Length of input buffer in octets
38 @param out [out] Destination of UTC time structure
39 @return CRYPT_OK if successful
40 */
der_decode_utctime(const unsigned char * in,unsigned long * inlen,ltc_utctime * out)41 int der_decode_utctime(const unsigned char *in, unsigned long *inlen,
42 ltc_utctime *out)
43 {
44 unsigned char buf[32] = { 0 }; /* initialize as all zeroes */
45 unsigned long x;
46 int y;
47
48 LTC_ARGCHK(in != NULL);
49 LTC_ARGCHK(inlen != NULL);
50 LTC_ARGCHK(out != NULL);
51
52 /* check header */
53 if (*inlen < 2UL || (in[1] >= sizeof(buf)) || ((in[1] + 2UL) > *inlen)) {
54 return CRYPT_INVALID_PACKET;
55 }
56
57 /* decode the string */
58 for (x = 0; x < in[1]; x++) {
59 y = der_ia5_value_decode(in[x+2]);
60 if (y == -1) {
61 return CRYPT_INVALID_PACKET;
62 }
63 buf[x] = y;
64 }
65 *inlen = 2 + x;
66
67
68 /* possible encodings are
69 YYMMDDhhmmZ
70 YYMMDDhhmm+hh'mm'
71 YYMMDDhhmm-hh'mm'
72 YYMMDDhhmmssZ
73 YYMMDDhhmmss+hh'mm'
74 YYMMDDhhmmss-hh'mm'
75
76 So let's do a trivial decode upto [including] mm
77 */
78
79 x = 0;
80 DECODE_V(out->YY, 100);
81 DECODE_V(out->MM, 13);
82 DECODE_V(out->DD, 32);
83 DECODE_V(out->hh, 24);
84 DECODE_V(out->mm, 60);
85
86 /* clear timezone and seconds info */
87 out->off_dir = out->off_hh = out->off_mm = out->ss = 0;
88
89 /* now is it Z, +, - or 0-9 */
90 if (buf[x] == 'Z') {
91 return CRYPT_OK;
92 }
93 if (buf[x] == '+' || buf[x] == '-') {
94 out->off_dir = (buf[x++] == '+') ? 0 : 1;
95 DECODE_V(out->off_hh, 24);
96 DECODE_V(out->off_mm, 60);
97 return CRYPT_OK;
98 }
99
100 /* decode seconds */
101 DECODE_V(out->ss, 60);
102
103 /* now is it Z, +, - */
104 if (buf[x] == 'Z') {
105 return CRYPT_OK;
106 }
107 if (buf[x] == '+' || buf[x] == '-') {
108 out->off_dir = (buf[x++] == '+') ? 0 : 1;
109 DECODE_V(out->off_hh, 24);
110 DECODE_V(out->off_mm, 60);
111 return CRYPT_OK;
112 }
113 return CRYPT_INVALID_PACKET;
114 }
115
116 #endif
117