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)34int 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