1 // SPDX-License-Identifier: BSD-2-Clause 2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis 3 * 4 * LibTomCrypt is a library that provides various cryptographic 5 * algorithms in a highly modular and flexible manner. 6 * 7 * The library is free for all purposes without any express 8 * guarantee it works. 9 */ 10 #include "tomcrypt_private.h" 11 12 /** 13 @file der_encode_utctime.c 14 ASN.1 DER, encode a GeneralizedTime, Steffen Jaeckel 15 Based on der_encode_utctime.c 16 */ 17 18 #ifdef LTC_DER 19 20 static const char * const baseten = "0123456789"; 21 22 #define STORE_V(y) do {\ 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 #define STORE_V4(y) do {\ 28 out[x++] = der_ia5_char_encode(baseten[(y/1000) % 10]); \ 29 out[x++] = der_ia5_char_encode(baseten[(y/100) % 10]); \ 30 out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \ 31 out[x++] = der_ia5_char_encode(baseten[y % 10]); \ 32 } while(0) 33 34 /** 35 Encodes a Generalized time structure in DER format 36 @param gtime The GeneralizedTime structure to encode 37 @param out The destination of the DER encoding of the GeneralizedTime structure 38 @param outlen [in/out] The length of the DER encoding 39 @return CRYPT_OK if successful 40 */ der_encode_generalizedtime(const ltc_generalizedtime * gtime,unsigned char * out,unsigned long * outlen)41int der_encode_generalizedtime(const ltc_generalizedtime *gtime, 42 unsigned char *out, unsigned long *outlen) 43 { 44 unsigned long x, tmplen; 45 int err; 46 47 LTC_ARGCHK(gtime != NULL); 48 LTC_ARGCHK(out != NULL); 49 LTC_ARGCHK(outlen != NULL); 50 51 if ((err = der_length_generalizedtime(gtime, &tmplen)) != CRYPT_OK) { 52 return err; 53 } 54 if (tmplen > *outlen) { 55 *outlen = tmplen; 56 return CRYPT_BUFFER_OVERFLOW; 57 } 58 59 /* store header */ 60 out[0] = 0x18; 61 62 /* store values */ 63 x = 2; 64 STORE_V4(gtime->YYYY); 65 STORE_V(gtime->MM); 66 STORE_V(gtime->DD); 67 STORE_V(gtime->hh); 68 STORE_V(gtime->mm); 69 STORE_V(gtime->ss); 70 71 if (gtime->fs) { 72 unsigned long divisor; 73 unsigned fs = gtime->fs; 74 unsigned len = 0; 75 out[x++] = der_ia5_char_encode('.'); 76 divisor = 1; 77 do { 78 fs /= 10; 79 divisor *= 10; 80 len++; 81 } while(fs != 0); 82 while (len-- > 1) { 83 divisor /= 10; 84 out[x++] = der_ia5_char_encode(baseten[(gtime->fs/divisor) % 10]); 85 } 86 out[x++] = der_ia5_char_encode(baseten[gtime->fs % 10]); 87 } 88 89 if (gtime->off_mm || gtime->off_hh) { 90 out[x++] = der_ia5_char_encode(gtime->off_dir ? '-' : '+'); 91 STORE_V(gtime->off_hh); 92 STORE_V(gtime->off_mm); 93 } else { 94 out[x++] = der_ia5_char_encode('Z'); 95 } 96 97 /* store length */ 98 out[1] = (unsigned char)(x - 2); 99 100 /* all good let's return */ 101 *outlen = x; 102 return CRYPT_OK; 103 } 104 105 #endif 106 107 /* ref: $Format:%D$ */ 108 /* git commit: $Format:%H$ */ 109 /* commit time: $Format:%ai$ */ 110