mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-08-07 12:33:39 +08:00
Update ASN.1 Time
This commit is contained in:
@@ -43,7 +43,6 @@ set(src
|
|||||||
src/ec.c
|
src/ec.c
|
||||||
src/rsa.c
|
src/rsa.c
|
||||||
src/asn1.c
|
src/asn1.c
|
||||||
src/u_time.c
|
|
||||||
src/hex.c
|
src/hex.c
|
||||||
src/base64.c
|
src/base64.c
|
||||||
src/pem.c
|
src/pem.c
|
||||||
|
|||||||
@@ -198,6 +198,9 @@ int asn1_string_print(FILE *fp, int fmt, int ind, const char *label, int tag, co
|
|||||||
#define ASN1_UTC_TIME_LEN (sizeof("YYMMDDHHMMSSZ")-1)
|
#define ASN1_UTC_TIME_LEN (sizeof("YYMMDDHHMMSSZ")-1)
|
||||||
#define ASN1_GENERALIZED_TIME_LEN (sizeof("YYYYMMDDHHMMSSZ")-1)
|
#define ASN1_GENERALIZED_TIME_LEN (sizeof("YYYYMMDDHHMMSSZ")-1)
|
||||||
|
|
||||||
|
int asn1_time_to_str(int utc_time, time_t timestamp, char *str);
|
||||||
|
int asn1_time_from_str(int utc_time, time_t *timestamp, const char *str);
|
||||||
|
|
||||||
int asn1_utc_time_to_der_ex(int tag, time_t tv, uint8_t **out, size_t *outlen);
|
int asn1_utc_time_to_der_ex(int tag, time_t tv, uint8_t **out, size_t *outlen);
|
||||||
int asn1_utc_time_from_der_ex(int tag, time_t *tv, const uint8_t **in, size_t *inlen);
|
int asn1_utc_time_from_der_ex(int tag, time_t *tv, const uint8_t **in, size_t *inlen);
|
||||||
#define asn1_utc_time_to_der(tv,out,outlen) asn1_utc_time_to_der_ex(ASN1_TAG_UTCTime,tv,out,outlen)
|
#define asn1_utc_time_to_der(tv,out,outlen) asn1_utc_time_to_der_ex(ASN1_TAG_UTCTime,tv,out,outlen)
|
||||||
|
|||||||
232
src/asn1.c
232
src/asn1.c
@@ -21,10 +21,7 @@
|
|||||||
#include <gmssl/asn1.h>
|
#include <gmssl/asn1.h>
|
||||||
#include <gmssl/error.h>
|
#include <gmssl/error.h>
|
||||||
#include <gmssl/endian.h>
|
#include <gmssl/endian.h>
|
||||||
#define WIN32 // only for use own time functions
|
|
||||||
#ifdef WIN32
|
|
||||||
#include "u_time.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
@@ -460,6 +457,7 @@ int asn1_integer_to_der_ex(int tag, const uint8_t *a, size_t alen, uint8_t **out
|
|||||||
|
|
||||||
int asn1_int_to_der_ex(int tag, int a, uint8_t **out, size_t *outlen)
|
int asn1_int_to_der_ex(int tag, int a, uint8_t **out, size_t *outlen)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
uint8_t buf[4] = {0};
|
uint8_t buf[4] = {0};
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
|
||||||
@@ -789,34 +787,172 @@ int asn1_ia5_string_to_der_ex(int tag, const char *d, size_t dlen, uint8_t **out
|
|||||||
return asn1_type_to_der(tag, (const uint8_t *)d, dlen, out, outlen);
|
return asn1_type_to_der(tag, (const uint8_t *)d, dlen, out, outlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int is_leap_year(int year) {
|
||||||
|
return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define val(c) ((c)-'0')
|
||||||
|
|
||||||
|
int asn1_time_from_str(int utc_time, time_t *timestamp, const char *str)
|
||||||
|
{
|
||||||
|
int time_str_len[2] = { 15, 13 };
|
||||||
|
int days_per_year[2] = { 365, 366 };
|
||||||
|
int days_per_month[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
|
||||||
|
int year, month, day, hour, minute, second;
|
||||||
|
const char *p = str;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
utc_time &= 1;
|
||||||
|
for (i = 0; i < time_str_len[utc_time] - 1; i++) {
|
||||||
|
if (!isdigit(str[i])) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (str[i] != 'Z') {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (utc_time) {
|
||||||
|
year = val(p[0]) * 10 + val(p[1]);
|
||||||
|
if (year <= 50) {
|
||||||
|
year += 2000;
|
||||||
|
} else {
|
||||||
|
year += 1900;
|
||||||
|
}
|
||||||
|
p += 2;
|
||||||
|
} else {
|
||||||
|
year = val(p[0]) * 1000 + val(str[1]) * 100 + val(str[2]) * 10 + val(str[3]);
|
||||||
|
p += 4;
|
||||||
|
}
|
||||||
|
if (is_leap_year(year)) {
|
||||||
|
days_per_month[2] = 29;
|
||||||
|
}
|
||||||
|
month = val(p[0]) * 10 + val(p[1]); p += 2;
|
||||||
|
day = val(p[0]) * 10 + val(p[1]); p += 2;
|
||||||
|
hour = val(p[0]) * 10 + val(p[1]); p += 2;
|
||||||
|
minute = val(p[0]) * 10 + val(p[1]); p += 2;
|
||||||
|
second = val(p[0]) * 10 + val(p[1]); p += 2;
|
||||||
|
|
||||||
|
if (year < 1970
|
||||||
|
|| month < 1 || month > 12
|
||||||
|
|| day < 1 || day > days_per_month[month]
|
||||||
|
|| hour < 0 || hour > 23
|
||||||
|
|| minute < 0 || minute > 59
|
||||||
|
|| second < 0 || second > 59) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
day--;
|
||||||
|
|
||||||
|
while (year-- > 1970) {
|
||||||
|
day += days_per_year[is_leap_year(year)];
|
||||||
|
}
|
||||||
|
while (month-- > 1) {
|
||||||
|
day += days_per_month[month];
|
||||||
|
}
|
||||||
|
*timestamp = (time_t)day * 86400 + hour * 3600 + minute * 60 + second;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int asn1_time_to_str(int utc_time, time_t timestamp, char *str)
|
||||||
|
{
|
||||||
|
int days_per_month[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
|
||||||
|
int days_per_year[2] = { 365, 366 };
|
||||||
|
int max_year[2] = { 9999, 2050 };
|
||||||
|
int year, month, second, hour, minute;
|
||||||
|
time_t day;
|
||||||
|
char *p = str;
|
||||||
|
|
||||||
|
utc_time &= 1;
|
||||||
|
day = timestamp / 86400;
|
||||||
|
second = timestamp % 86400;
|
||||||
|
|
||||||
|
// In UTCTime, year in [1951, 2050], YY <= 50, year = 20YY; YY > 50, year = 19YY
|
||||||
|
// For Validity, year SHOULD <= 2049 (NOT 2050)
|
||||||
|
for (year = 1970; year <= max_year[utc_time]; year++) {
|
||||||
|
if (day < days_per_year[is_leap_year(year)]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
day -= days_per_year[is_leap_year(year)];
|
||||||
|
}
|
||||||
|
if (year > max_year[utc_time]) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
day++;
|
||||||
|
|
||||||
|
if (is_leap_year(year)) {
|
||||||
|
days_per_month[2] = 29;
|
||||||
|
}
|
||||||
|
for (month = 1; month <= 12; month++) {
|
||||||
|
if (day <= days_per_month[month]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
day -= days_per_month[month];
|
||||||
|
}
|
||||||
|
|
||||||
|
hour = second / 3600;
|
||||||
|
second %= 3600;
|
||||||
|
minute = second / 60;
|
||||||
|
second %= 60;
|
||||||
|
|
||||||
|
if (utc_time) {
|
||||||
|
memset(p, '0', 12);
|
||||||
|
} else {
|
||||||
|
memset(p, '0', 14);
|
||||||
|
p[0] += (year / 100) / 10;
|
||||||
|
p[1] += (year / 100) % 10;
|
||||||
|
p += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
year %= 100;
|
||||||
|
p[0] += year / 10;
|
||||||
|
p[1] += year % 10;
|
||||||
|
p[2] += month / 10;
|
||||||
|
p[3] += month % 10;
|
||||||
|
p[4] += day / 10;
|
||||||
|
p[5] += day % 10;
|
||||||
|
p[6] += hour / 10;
|
||||||
|
p[7] += hour % 10;
|
||||||
|
p[8] += minute / 10;
|
||||||
|
p[9] += minute % 10;
|
||||||
|
p[10] += second / 10;
|
||||||
|
p[11] += second % 10;
|
||||||
|
p[12] = 'Z';
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int asn1_utc_time_to_der_ex(int tag, time_t a, uint8_t **out, size_t *outlen)
|
int asn1_utc_time_to_der_ex(int tag, time_t a, uint8_t **out, size_t *outlen)
|
||||||
{
|
{
|
||||||
struct tm tm_val;
|
struct tm tm_val;
|
||||||
char buf[ASN1_UTC_TIME_LEN + 1] = {0};
|
char buf[ASN1_UTC_TIME_LEN + 1] = {0};
|
||||||
|
int utc_time = 1;
|
||||||
|
|
||||||
if (!outlen) {
|
if (!outlen) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
if (asn1_time_to_str(utc_time, a, buf) != 1) {
|
||||||
GMSSL_gmtime(&a, &tm_val);
|
error_print();
|
||||||
asn1_tm_to_utctime(&tm_val, buf);
|
return -1;
|
||||||
#else
|
}
|
||||||
gmtime_r(&a, &tm_val);
|
|
||||||
strftime(buf, sizeof(buf), "%y%m%d%H%M%SZ", &tm_val);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
if (out && *out)
|
if (out && *out)
|
||||||
*(*out)++ = tag;
|
*(*out)++ = tag;
|
||||||
(*outlen)++;
|
(*outlen)++;
|
||||||
asn1_length_to_der(sizeof(buf)-1, out, outlen);
|
asn1_length_to_der(ASN1_UTC_TIME_LEN, out, outlen);
|
||||||
if (out && *out) {
|
if (out && *out) {
|
||||||
memcpy(*out, buf, sizeof(buf)-1);
|
memcpy(*out, buf, ASN1_UTC_TIME_LEN);
|
||||||
(*out) += sizeof(buf)-1;
|
(*out) += ASN1_UTC_TIME_LEN;
|
||||||
}
|
}
|
||||||
*outlen += sizeof(buf)-1;
|
*outlen += ASN1_UTC_TIME_LEN;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -826,20 +962,17 @@ int asn1_generalized_time_to_der_ex(int tag, time_t a, uint8_t **out, size_t *ou
|
|||||||
{
|
{
|
||||||
struct tm tm_val;
|
struct tm tm_val;
|
||||||
char buf[ASN1_GENERALIZED_TIME_LEN + 1] = {0};
|
char buf[ASN1_GENERALIZED_TIME_LEN + 1] = {0};
|
||||||
|
int utc_time = 0;
|
||||||
|
|
||||||
if (!outlen) {
|
if (!outlen) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
if (asn1_time_to_str(utc_time, a, buf) != 1) {
|
||||||
GMSSL_gmtime(&a, &tm_val);
|
error_print();
|
||||||
asn1_tm_to_generalizedtime(&tm_val, buf);
|
return -1;
|
||||||
#else
|
}
|
||||||
gmtime_r(&a, &tm_val);
|
|
||||||
strftime(buf, sizeof(buf), "%Y%m%d%H%M%SZ", &tm_val);
|
|
||||||
#endif
|
|
||||||
//printf("%s %d: generalized time : %s\n", __FILE__, __LINE__, buf);
|
|
||||||
|
|
||||||
if (out && *out)
|
if (out && *out)
|
||||||
*(*out)++ = tag;
|
*(*out)++ = tag;
|
||||||
@@ -1143,21 +1276,6 @@ int asn1_ia5_string_from_der_ex(int tag, const char **a, size_t *alen, const uin
|
|||||||
return asn1_type_from_der(tag, (const uint8_t **)a, alen, in, inlen);
|
return asn1_type_from_der(tag, (const uint8_t **)a, alen, in, inlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
int hh, mm, ss;
|
|
||||||
struct tm when = {0};
|
|
||||||
|
|
||||||
sscanf_s(date, "%d:%d:%d", &hh, &mm, &ss);
|
|
||||||
|
|
||||||
|
|
||||||
when.tm_hour = hh;
|
|
||||||
when.tm_min = mm;
|
|
||||||
when.tm_sec = ss;
|
|
||||||
|
|
||||||
time_t converted;
|
|
||||||
converted = mktime(&when);
|
|
||||||
*/
|
|
||||||
|
|
||||||
int asn1_utc_time_from_der_ex(int tag, time_t *t, const uint8_t **pin, size_t *pinlen)
|
int asn1_utc_time_from_der_ex(int tag, time_t *t, const uint8_t **pin, size_t *pinlen)
|
||||||
{
|
{
|
||||||
const uint8_t *in = *pin;
|
const uint8_t *in = *pin;
|
||||||
@@ -1178,30 +1296,15 @@ int asn1_utc_time_from_der_ex(int tag, time_t *t, const uint8_t **pin, size_t *p
|
|||||||
|| (len != sizeof("YYMMDDHHMMSSZ")-1 && len != sizeof("YYMMDDHHMMSS+HHMM")-1)) {
|
|| (len != sizeof("YYMMDDHHMMSSZ")-1 && len != sizeof("YYMMDDHHMMSS+HHMM")-1)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(buf + 2, in, len);
|
memcpy(buf, in, len);
|
||||||
|
|
||||||
if (!isdigit(buf[2]) && !isdigit(buf[3])) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
year = (buf[2] - '0') * 10 + (buf[3] - '0');
|
|
||||||
if (year >= 50) {
|
|
||||||
buf[0] = '1';
|
|
||||||
buf[1] = '9';
|
|
||||||
} else {
|
|
||||||
buf[0] = '2';
|
|
||||||
buf[1] = '0';
|
|
||||||
}
|
|
||||||
if (len == sizeof("YYMMDDHHMMSSZ")-1) {
|
if (len == sizeof("YYMMDDHHMMSSZ")-1) {
|
||||||
#ifdef WIN32
|
if (asn1_time_from_str(1, t, buf) != 1) {
|
||||||
asn1_generalizedtime_to_tm(buf, &tm_val);
|
error_print();
|
||||||
*t = GMSSL_timegm(&tm_val);
|
|
||||||
#else
|
|
||||||
if (!strptime(buf, "%Y%m%d%H%M%SZ", &tm_val)) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*t = timegm(&tm_val);
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1234,21 +1337,12 @@ int asn1_generalized_time_from_der_ex(int tag, time_t *t, const uint8_t **pin, s
|
|||||||
memcpy(buf, in, len);
|
memcpy(buf, in, len);
|
||||||
|
|
||||||
if (len == sizeof("YYYYMMDDHHMMSSZ")-1) {
|
if (len == sizeof("YYYYMMDDHHMMSSZ")-1) {
|
||||||
|
if (asn1_time_from_str(0, t, buf) != 1) {
|
||||||
#ifdef WIN32
|
|
||||||
asn1_generalizedtime_to_tm(buf, &tm_val);
|
|
||||||
*t = GMSSL_timegm(&tm_val);
|
|
||||||
#else
|
|
||||||
if (!strptime(buf, "%Y%m%d%H%M%SZ", &tm_val)) {
|
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*t = timegm(&tm_val);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// TODO: 处理这种情况
|
// FIXME: handle "YYYYMMDDHHMMSS+HHMM"
|
||||||
error_print();
|
error_print();
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|||||||
496
src/u_time.c
496
src/u_time.c
@@ -1,496 +0,0 @@
|
|||||||
#include "u_time.h"
|
|
||||||
|
|
||||||
//convert timestamp to struct tm
|
|
||||||
int GMSSL_gmtime(const time_t *timep, struct tm *tm_time)
|
|
||||||
{
|
|
||||||
time_t timestamp = *timep;
|
|
||||||
unsigned int four_year_num;
|
|
||||||
unsigned int one_year_hours;
|
|
||||||
|
|
||||||
const static unsigned char Days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
|
||||||
const static unsigned int ONE_YEAR_HOURS = 8760;
|
|
||||||
const static unsigned int FOUR_YEAR_HOURS = 35064;
|
|
||||||
|
|
||||||
if (timestamp > 0x7FFFFFFF)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tm_time->tm_isdst = 0;
|
|
||||||
|
|
||||||
tm_time->tm_sec = (int)(timestamp % 60);
|
|
||||||
timestamp /= 60;
|
|
||||||
|
|
||||||
tm_time->tm_min = (int)(timestamp % 60);
|
|
||||||
timestamp /= 60;
|
|
||||||
|
|
||||||
tm_time->tm_wday = (int)(timestamp/24 + 4) % 7;
|
|
||||||
|
|
||||||
four_year_num = timestamp / FOUR_YEAR_HOURS;
|
|
||||||
|
|
||||||
tm_time->tm_year=(four_year_num << 2) + 70;
|
|
||||||
|
|
||||||
timestamp %= FOUR_YEAR_HOURS;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
one_year_hours = ONE_YEAR_HOURS;
|
|
||||||
|
|
||||||
if ((tm_time->tm_year & 3) == 0)
|
|
||||||
{
|
|
||||||
one_year_hours += 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timestamp < one_year_hours)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
tm_time->tm_year++;
|
|
||||||
timestamp -= one_year_hours;
|
|
||||||
}
|
|
||||||
|
|
||||||
tm_time->tm_hour=(int)(timestamp % 24);
|
|
||||||
|
|
||||||
timestamp /= 24;
|
|
||||||
timestamp++;
|
|
||||||
|
|
||||||
tm_time->tm_yday = timestamp-1;
|
|
||||||
|
|
||||||
if ((tm_time->tm_year & 3) == 0)
|
|
||||||
{
|
|
||||||
if (timestamp > 60)
|
|
||||||
{
|
|
||||||
timestamp--;
|
|
||||||
}
|
|
||||||
else if (timestamp == 60)
|
|
||||||
{
|
|
||||||
tm_time->tm_mon = 1;
|
|
||||||
tm_time->tm_mday = 29;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (tm_time->tm_mon = 0; Days[tm_time->tm_mon] < timestamp; tm_time->tm_mon++)
|
|
||||||
{
|
|
||||||
timestamp -= Days[tm_time->tm_mon];
|
|
||||||
}
|
|
||||||
|
|
||||||
tm_time->tm_mday = (int)(timestamp);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//convert struct tm to timestamp
|
|
||||||
time_t GMSSL_timegm(struct tm *tm)
|
|
||||||
{
|
|
||||||
static const int msum [2][12] = {
|
|
||||||
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}, /* normal years */
|
|
||||||
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335} /* leap years */
|
|
||||||
};
|
|
||||||
static const int mlen [2][12] = {
|
|
||||||
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
|
|
||||||
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
|
|
||||||
};
|
|
||||||
static const int tmstr_year= 1900; /* base of 'tm_year' in 'struct tm' */
|
|
||||||
static const int epoch_year= 1970; /* unix timestamp epoch */
|
|
||||||
static const int base_year= 1601; /* start of a 400-year period: used to be 1601,
|
|
||||||
but this allows larger range (in 64 bit)
|
|
||||||
mind you, this is proleptic Gregorian */
|
|
||||||
int year, ytmp, dtmp, ytmpe, dtmpe;
|
|
||||||
int isleapyear;
|
|
||||||
long long t;
|
|
||||||
|
|
||||||
if (!tm) return -1;
|
|
||||||
|
|
||||||
year = tm->tm_year + tmstr_year;
|
|
||||||
isleapyear= (year%4==0) - (year%100==0) + (year%400==0);
|
|
||||||
|
|
||||||
/* days between 'current year' and 'epoch_year' has to be calculated
|
|
||||||
in three steps: */
|
|
||||||
|
|
||||||
/* 1. days between current year and 'base_year' */
|
|
||||||
ytmp = year - base_year;
|
|
||||||
dtmp = ytmp*365 + ytmp/4 - ytmp/100 + ytmp/400;
|
|
||||||
|
|
||||||
/* 2. days between 'epoch year' and 'base_year' */
|
|
||||||
ytmpe = epoch_year - base_year;
|
|
||||||
dtmpe = ytmpe*365 + ytmpe/4 - ytmpe/100 + ytmpe/400;
|
|
||||||
|
|
||||||
/* 3. days between 'current year' and 'epoch_year' */
|
|
||||||
t = dtmp - dtmpe;
|
|
||||||
|
|
||||||
t += msum[isleapyear][tm->tm_mon];
|
|
||||||
t += tm->tm_mday-1;
|
|
||||||
|
|
||||||
t = t*24 + tm->tm_hour;
|
|
||||||
t = t*60 + tm->tm_min;
|
|
||||||
t = t*60 + tm->tm_sec;
|
|
||||||
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
//offset to struct tm
|
|
||||||
int GMSSL_gmtime_adj(struct tm *tm, long offset_sec)
|
|
||||||
{
|
|
||||||
time_t t = GMSSL_timegm(tm);
|
|
||||||
if(t == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
t += offset_sec;
|
|
||||||
|
|
||||||
return GMSSL_gmtime(&t,tm) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//convert generalizedtime to tm
|
|
||||||
int asn1_generalizedtime_to_tm(char *gtime,struct tm *tm)
|
|
||||||
{
|
|
||||||
static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 };
|
|
||||||
static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 };
|
|
||||||
char *a;
|
|
||||||
int n, i, l, o;
|
|
||||||
|
|
||||||
l = strlen(gtime);
|
|
||||||
a = gtime;
|
|
||||||
o = 0;
|
|
||||||
/*
|
|
||||||
* GENERALIZEDTIME is similar to UTCTIME except the year is represented
|
|
||||||
* as YYYY. This stuff treats everything as a two digit field so make
|
|
||||||
* first two fields 00 to 99
|
|
||||||
*/
|
|
||||||
if (l < 13)
|
|
||||||
goto err;
|
|
||||||
for (i = 0; i < 7; i++) {
|
|
||||||
if ((i == 6) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
|
|
||||||
i++;
|
|
||||||
if (tm)
|
|
||||||
tm->tm_sec = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((a[o] < '0') || (a[o] > '9'))
|
|
||||||
goto err;
|
|
||||||
n = a[o] - '0';
|
|
||||||
if (++o > l)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
if ((a[o] < '0') || (a[o] > '9'))
|
|
||||||
goto err;
|
|
||||||
n = (n * 10) + a[o] - '0';
|
|
||||||
if (++o > l)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
if ((n < min[i]) || (n > max[i]))
|
|
||||||
goto err;
|
|
||||||
if (tm) {
|
|
||||||
switch (i) {
|
|
||||||
case 0:
|
|
||||||
tm->tm_year = n * 100 - 1900;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
tm->tm_year += n;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
tm->tm_mon = n - 1;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
tm->tm_mday = n;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
tm->tm_hour = n;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
tm->tm_min = n;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
tm->tm_sec = n;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Optional fractional seconds: decimal point followed by one or more
|
|
||||||
* digits.
|
|
||||||
*/
|
|
||||||
if (a[o] == '.') {
|
|
||||||
if (++o > l)
|
|
||||||
goto err;
|
|
||||||
i = o;
|
|
||||||
while ((a[o] >= '0') && (a[o] <= '9') && (o <= l))
|
|
||||||
o++;
|
|
||||||
/* Must have at least one digit after decimal point */
|
|
||||||
if (i == o)
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a[o] == 'Z')
|
|
||||||
o++;
|
|
||||||
else if ((a[o] == '+') || (a[o] == '-')) {
|
|
||||||
int offsign = a[o] == '+' ? -1 : 1, offset = 0;
|
|
||||||
o++;
|
|
||||||
if (o + 4 > l)
|
|
||||||
goto err;
|
|
||||||
for (i = 7; i < 9; i++) {
|
|
||||||
if ((a[o] < '0') || (a[o] > '9'))
|
|
||||||
goto err;
|
|
||||||
n = a[o] - '0';
|
|
||||||
o++;
|
|
||||||
if ((a[o] < '0') || (a[o] > '9'))
|
|
||||||
goto err;
|
|
||||||
n = (n * 10) + a[o] - '0';
|
|
||||||
if ((n < min[i]) || (n > max[i]))
|
|
||||||
goto err;
|
|
||||||
if (tm) {
|
|
||||||
if (i == 7)
|
|
||||||
offset = n * 3600;
|
|
||||||
else if (i == 8)
|
|
||||||
offset += n * 60;
|
|
||||||
}
|
|
||||||
o++;
|
|
||||||
}
|
|
||||||
if (offset && !GMSSL_gmtime_adj(tm, offset * offsign))
|
|
||||||
return 0;
|
|
||||||
} else if (a[o]) {
|
|
||||||
/* Missing time zone information. */
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
return (o == l);
|
|
||||||
err:
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//convert utctime to tm
|
|
||||||
int asn1_utctime_to_tm(struct tm *tm, char *utime)
|
|
||||||
{
|
|
||||||
static const int min[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };
|
|
||||||
static const int max[8] = { 99, 12, 31, 23, 59, 59, 12, 59 };
|
|
||||||
char *a;
|
|
||||||
int n, i, l, o;
|
|
||||||
|
|
||||||
l = strlen(utime);
|
|
||||||
a = utime;
|
|
||||||
o = 0;
|
|
||||||
|
|
||||||
if (l < 11)
|
|
||||||
goto err;
|
|
||||||
for (i = 0; i < 6; i++) {
|
|
||||||
if ((i == 5) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
|
|
||||||
i++;
|
|
||||||
if (tm)
|
|
||||||
tm->tm_sec = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((a[o] < '0') || (a[o] > '9'))
|
|
||||||
goto err;
|
|
||||||
n = a[o] - '0';
|
|
||||||
if (++o > l)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
if ((a[o] < '0') || (a[o] > '9'))
|
|
||||||
goto err;
|
|
||||||
n = (n * 10) + a[o] - '0';
|
|
||||||
if (++o > l)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
if ((n < min[i]) || (n > max[i]))
|
|
||||||
goto err;
|
|
||||||
if (tm) {
|
|
||||||
switch (i) {
|
|
||||||
case 0:
|
|
||||||
tm->tm_year = n < 50 ? n + 100 : n;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
tm->tm_mon = n - 1;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
tm->tm_mday = n;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
tm->tm_hour = n;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
tm->tm_min = n;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
tm->tm_sec = n;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (a[o] == 'Z')
|
|
||||||
o++;
|
|
||||||
else if ((a[o] == '+') || (a[o] == '-')) {
|
|
||||||
int offsign = a[o] == '+' ? -1 : 1, offset = 0;
|
|
||||||
o++;
|
|
||||||
if (o + 4 > l)
|
|
||||||
goto err;
|
|
||||||
for (i = 6; i < 8; i++) {
|
|
||||||
if ((a[o] < '0') || (a[o] > '9'))
|
|
||||||
goto err;
|
|
||||||
n = a[o] - '0';
|
|
||||||
o++;
|
|
||||||
if ((a[o] < '0') || (a[o] > '9'))
|
|
||||||
goto err;
|
|
||||||
n = (n * 10) + a[o] - '0';
|
|
||||||
if ((n < min[i]) || (n > max[i]))
|
|
||||||
goto err;
|
|
||||||
if (tm) {
|
|
||||||
if (i == 6)
|
|
||||||
offset = n * 3600;
|
|
||||||
else if (i == 7)
|
|
||||||
offset += n * 60;
|
|
||||||
}
|
|
||||||
o++;
|
|
||||||
}
|
|
||||||
if (offset && !GMSSL_gmtime_adj(tm, offset * offsign))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return o == l;
|
|
||||||
err:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//convert tm to generalizedtime
|
|
||||||
int asn1_tm_to_generalizedtime(struct tm *tm, char *gtime)
|
|
||||||
{
|
|
||||||
char p[20] = {0};
|
|
||||||
int i = 0, j = 0;
|
|
||||||
static const int min[6] = { 0, 1, 1, 0, 0, 0 };
|
|
||||||
static const int max[6] = { 9999, 12, 31, 23, 59, 59};
|
|
||||||
|
|
||||||
//year
|
|
||||||
int year0 = tm->tm_year + 1900;
|
|
||||||
if(year0 < min[i] || year0 > max[i])
|
|
||||||
goto err;
|
|
||||||
p[j++] = year0 / 1000 + '0';
|
|
||||||
year0 = year0 % 1000;
|
|
||||||
p[j++] = year0 / 100 + '0';
|
|
||||||
year0 = year0 % 100;
|
|
||||||
p[j++] = year0 / 10 + '0';
|
|
||||||
year0 = year0 % 10;
|
|
||||||
p[j++] = year0 + '0';
|
|
||||||
i++;
|
|
||||||
|
|
||||||
//month
|
|
||||||
int mon0 = tm->tm_mon + 1;
|
|
||||||
if(mon0 < min[i] || mon0>max[i])
|
|
||||||
goto err;
|
|
||||||
p[j++] = mon0 /10 + '0';
|
|
||||||
mon0 = mon0%10;
|
|
||||||
p[j++] = mon0 + '0';
|
|
||||||
i++;
|
|
||||||
|
|
||||||
//day
|
|
||||||
int day0 = tm->tm_mday;
|
|
||||||
if(day0 < min[i] || day0>max[i])
|
|
||||||
goto err;
|
|
||||||
p[j++] = day0 /10 + '0';
|
|
||||||
day0 = day0%10;
|
|
||||||
p[j++] = day0 + '0';
|
|
||||||
i++;
|
|
||||||
|
|
||||||
//hour
|
|
||||||
int hour0 = tm->tm_hour;
|
|
||||||
if(hour0 < min[i] || hour0>max[i])
|
|
||||||
goto err;
|
|
||||||
p[j++] = hour0 /10 + '0';
|
|
||||||
hour0 = hour0%10;
|
|
||||||
p[j++] = hour0 + '0';
|
|
||||||
i++;
|
|
||||||
|
|
||||||
//min
|
|
||||||
int min0 = tm->tm_min;
|
|
||||||
if(min0 < min[i] || min0>max[i])
|
|
||||||
goto err;
|
|
||||||
p[j++] = min0 /10 + '0';
|
|
||||||
min0 = min0%10;
|
|
||||||
p[j++] = min0 + '0';
|
|
||||||
i++;
|
|
||||||
|
|
||||||
//sec
|
|
||||||
int sec0 = tm->tm_sec;
|
|
||||||
if(sec0 < min[i] || sec0>max[i])
|
|
||||||
goto err;
|
|
||||||
p[j++] = sec0 /10 + '0';
|
|
||||||
sec0 = sec0%10;
|
|
||||||
p[j++] = sec0 + '0';
|
|
||||||
|
|
||||||
p[j++] = 'Z';
|
|
||||||
|
|
||||||
memcpy(gtime,p,j);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
err:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//convert asn1 tm to utctime
|
|
||||||
int asn1_tm_to_utctime(struct tm *tm, char *utime)
|
|
||||||
{
|
|
||||||
char p[20] = {0};
|
|
||||||
int i = 0, j = 0;
|
|
||||||
static const int min[6] = { 0, 1, 1, 0, 0, 0 };
|
|
||||||
static const int max[6] = { 99, 12, 31, 23, 59, 59};
|
|
||||||
|
|
||||||
//year
|
|
||||||
int year0 = tm->tm_year % 100;
|
|
||||||
if(year0 < min[i] || year0 > max[i])
|
|
||||||
goto err;
|
|
||||||
p[j++] = year0 / 10 + '0';
|
|
||||||
year0 = year0 % 10;
|
|
||||||
p[j++] = year0 + '0';
|
|
||||||
i++;
|
|
||||||
|
|
||||||
//month
|
|
||||||
int mon0 = tm->tm_mon + 1;
|
|
||||||
if(mon0 < min[i] || mon0>max[i])
|
|
||||||
goto err;
|
|
||||||
p[j++] = mon0 /10 + '0';
|
|
||||||
mon0 = mon0%10;
|
|
||||||
p[j++] = mon0 + '0';
|
|
||||||
i++;
|
|
||||||
|
|
||||||
//day
|
|
||||||
int day0 = tm->tm_mday;
|
|
||||||
if(day0 < min[i] || day0>max[i])
|
|
||||||
goto err;
|
|
||||||
p[j++] = day0 /10 + '0';
|
|
||||||
day0 = day0%10;
|
|
||||||
p[j++] = day0 + '0';
|
|
||||||
i++;
|
|
||||||
|
|
||||||
//hour
|
|
||||||
int hour0 = tm->tm_hour;
|
|
||||||
if(hour0 < min[i] || hour0>max[i])
|
|
||||||
goto err;
|
|
||||||
p[j++] = hour0 /10 + '0';
|
|
||||||
hour0 = hour0%10;
|
|
||||||
p[j++] = hour0 + '0';
|
|
||||||
i++;
|
|
||||||
|
|
||||||
//min
|
|
||||||
int min0 = tm->tm_min;
|
|
||||||
if(min0 < min[i] || min0>max[i])
|
|
||||||
goto err;
|
|
||||||
p[j++] = min0 /10 + '0';
|
|
||||||
min0 = min0%10;
|
|
||||||
p[j++] = min0 + '0';
|
|
||||||
i++;
|
|
||||||
|
|
||||||
//sec
|
|
||||||
int sec0 = tm->tm_sec;
|
|
||||||
if(sec0 < min[i] || sec0>max[i])
|
|
||||||
goto err;
|
|
||||||
p[j++] = sec0 /10 + '0';
|
|
||||||
sec0 = sec0%10;
|
|
||||||
p[j++] = sec0 + '0';
|
|
||||||
|
|
||||||
p[j++] = 'Z';
|
|
||||||
memcpy(utime,p,j);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
err:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
26
src/u_time.h
26
src/u_time.h
@@ -1,26 +0,0 @@
|
|||||||
#ifndef GMSSL_U_TIME_H
|
|
||||||
#define GMSSL_U_TIME_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#define SECS_PER_DAY (24 * 60 * 60)
|
|
||||||
|
|
||||||
int GMSSL_gmtime(const time_t *timep, struct tm *tm_time);
|
|
||||||
time_t GMSSL_timegm(struct tm *tm);
|
|
||||||
int GMSSL_gmtime_adj(struct tm *tm, long offset_sec);
|
|
||||||
int asn1_generalizedtime_to_tm(char *gtime,struct tm *tm);
|
|
||||||
int asn1_utctime_to_tm(struct tm *tm, char *utime);
|
|
||||||
int asn1_tm_to_generalizedtime(struct tm *tm, char *gtime);
|
|
||||||
int asn1_tm_to_utctime(struct tm *tm, char *utime);
|
|
||||||
|
|
||||||
#if __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
@@ -497,6 +497,62 @@ static int test_time(void)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int test_asn1_time(void)
|
||||||
|
{
|
||||||
|
time_t tests[] = {
|
||||||
|
0,
|
||||||
|
31*86400,
|
||||||
|
(31+28)*86400,
|
||||||
|
};
|
||||||
|
char *utc_time[] = {
|
||||||
|
"700101000000Z",
|
||||||
|
"700201000000Z",
|
||||||
|
"700301000000Z",
|
||||||
|
};
|
||||||
|
char *gen_time[] = {
|
||||||
|
"19700101000000Z",
|
||||||
|
"19700201000000Z",
|
||||||
|
"19700301000000Z",
|
||||||
|
};
|
||||||
|
time_t cur = time(NULL);
|
||||||
|
time_t ts;
|
||||||
|
char str[16] = {0};
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (asn1_time_to_str(0, cur, str) != 1
|
||||||
|
|| asn1_time_from_str(0, &ts, str) != 1
|
||||||
|
|| ts != cur) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (asn1_time_to_str(1, cur, str) != 1
|
||||||
|
|| asn1_time_from_str(1, &ts, str) != 1
|
||||||
|
|| ts != cur) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
|
||||||
|
memset(str, 0, sizeof(str));
|
||||||
|
if (asn1_time_to_str(1, tests[i], str) != 1
|
||||||
|
|| strcmp(str, utc_time[i]) != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(str, 0, sizeof(str));
|
||||||
|
if (asn1_time_to_str(0, tests[i], str) != 1
|
||||||
|
|| strcmp(str, gen_time[i]) != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int test_asn1_utc_time(void)
|
static int test_asn1_utc_time(void)
|
||||||
{
|
{
|
||||||
time_t tests[] = {
|
time_t tests[] = {
|
||||||
@@ -588,6 +644,7 @@ int main(void)
|
|||||||
if (test_asn1_printable_string() != 1) goto err;
|
if (test_asn1_printable_string() != 1) goto err;
|
||||||
if (test_asn1_utf8_string() != 1) goto err;
|
if (test_asn1_utf8_string() != 1) goto err;
|
||||||
if (test_asn1_ia5_string() != 1) goto err;
|
if (test_asn1_ia5_string() != 1) goto err;
|
||||||
|
if (test_asn1_time() != 1) goto err;
|
||||||
if (test_asn1_utc_time() != 1) goto err;
|
if (test_asn1_utc_time() != 1) goto err;
|
||||||
if (test_asn1_generalized_time() != 1) goto err;
|
if (test_asn1_generalized_time() != 1) goto err;
|
||||||
printf("%s all tests passed\n", __FILE__);
|
printf("%s all tests passed\n", __FILE__);
|
||||||
|
|||||||
Reference in New Issue
Block a user