xref: /optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c (revision 8411e6ad673d20c4742ed30c785e3f5cdea54dfa)
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 /**
6   @file der_encode_utctime.c
7   ASN.1 DER, encode a GeneralizedTime, Steffen Jaeckel
8   Based on der_encode_utctime.c
9 */
10 
11 #ifdef LTC_DER
12 
13 static const char * const baseten = "0123456789";
14 
15 #define STORE_V(y) do {\
16     out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \
17     out[x++] = der_ia5_char_encode(baseten[y % 10]); \
18 } while(0)
19 
20 #define STORE_V4(y) do {\
21     out[x++] = der_ia5_char_encode(baseten[(y/1000) % 10]); \
22     out[x++] = der_ia5_char_encode(baseten[(y/100) % 10]); \
23     out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \
24     out[x++] = der_ia5_char_encode(baseten[y % 10]); \
25 } while(0)
26 
27 /**
28   Encodes a Generalized time structure in DER format
29   @param gtime        The GeneralizedTime structure to encode
30   @param out          The destination of the DER encoding of the GeneralizedTime structure
31   @param outlen       [in/out] The length of the DER encoding
32   @return CRYPT_OK if successful
33 */
der_encode_generalizedtime(const ltc_generalizedtime * gtime,unsigned char * out,unsigned long * outlen)34 int der_encode_generalizedtime(const ltc_generalizedtime *gtime,
35                                      unsigned char       *out, unsigned long *outlen)
36 {
37     unsigned long x, tmplen;
38     int           err;
39 
40     LTC_ARGCHK(gtime != NULL);
41     LTC_ARGCHK(out     != NULL);
42     LTC_ARGCHK(outlen  != NULL);
43 
44     if ((err = der_length_generalizedtime(gtime, &tmplen)) != CRYPT_OK) {
45        return err;
46     }
47     if (tmplen > *outlen) {
48         *outlen = tmplen;
49         return CRYPT_BUFFER_OVERFLOW;
50     }
51 
52     /* store header */
53     out[0] = 0x18;
54 
55     /* store values */
56     x = 2;
57     STORE_V4(gtime->YYYY);
58     STORE_V(gtime->MM);
59     STORE_V(gtime->DD);
60     STORE_V(gtime->hh);
61     STORE_V(gtime->mm);
62     STORE_V(gtime->ss);
63 
64     if (gtime->fs) {
65        unsigned long divisor;
66        unsigned fs = gtime->fs;
67        unsigned len = 0;
68        out[x++] = der_ia5_char_encode('.');
69        divisor = 1;
70        do {
71           fs /= 10;
72           divisor *= 10;
73           len++;
74        } while(fs != 0);
75        while (len-- > 1) {
76           divisor /= 10;
77           out[x++] = der_ia5_char_encode(baseten[(gtime->fs/divisor) % 10]);
78        }
79        out[x++] = der_ia5_char_encode(baseten[gtime->fs % 10]);
80     }
81 
82     if (gtime->off_mm || gtime->off_hh) {
83        out[x++] = der_ia5_char_encode(gtime->off_dir ? '-' : '+');
84        STORE_V(gtime->off_hh);
85        STORE_V(gtime->off_mm);
86     } else {
87        out[x++] = der_ia5_char_encode('Z');
88     }
89 
90     /* store length */
91     out[1] = (unsigned char)(x - 2);
92 
93     /* all good let's return */
94     *outlen = x;
95     return CRYPT_OK;
96 }
97 
98 #endif
99