From ee1f51dd7a1aaa12e0857a698ac99a5d55c897f0 Mon Sep 17 00:00:00 2001 From: William Ahern Date: Tue, 2 Oct 2012 17:10:16 -0700 Subject: -n commit lots of time conversion work --- openssl.c | 288 +++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 240 insertions(+), 48 deletions(-) diff --git a/openssl.c b/openssl.c index 949176a..2c4c032 100644 --- a/openssl.c +++ b/openssl.c @@ -28,12 +28,14 @@ #include /* INT_MAX INT_MIN */ #include /* memset(3) */ -#include /* fabs(3) floor(3) round(3) isfinite(3) */ +#include /* INFINITY fabs(3) floor(3) frexp(3) fmod(3) round(3) isfinite(3) */ +#include /* struct tm time_t strptime(3) */ #include #include #include #include +#include #include #include @@ -48,6 +50,8 @@ #define countof(a) (sizeof (a) / sizeof *(a)) #define endof(a) (&(a)[countof(a)]) +#define CLAMP(i, min, max) (((i) < (min))? (min) : ((i) > (max))? (max) : (i)) + static void *prepudata(lua_State *L, const char *tname, size_t size) { void *p = memset(lua_newuserdata(L, size), 0, size); @@ -124,10 +128,24 @@ static BIGNUM *bn_push(lua_State *L) { } /* bn_push() */ +#define checkbig_(a, b, c, ...) checkbig((a), (b), (c)) +#define checkbig(...) checkbig_(__VA_ARGS__, &(_Bool){ 0 }) + +static BIGNUM *(checkbig)(lua_State *, int, _Bool *); + static int bn_new(lua_State *L) { - bn_push(L); + int i, n; - return 1; + if ((n = lua_gettop(L)) > 0) { + for (i = 1; i <= n; i++) + checkbig(L, i); + + return n; + } else { + bn_push(L); + + return 1; + } } /* bn_new() */ @@ -204,7 +222,7 @@ static _Bool f2bn(BIGNUM **bn, double f) { } /* f2bn() */ -static BIGNUM *checkbig(lua_State *L, int index, _Bool *lvalue) { +static BIGNUM *(checkbig)(lua_State *L, int index, _Bool *lvalue) { BIGNUM **bn; const char *dec; size_t len; @@ -385,6 +403,15 @@ static int bn__pow(lua_State *L) { } /* bn__pow() */ +static int bn__unm(lua_State *L) { + BIGNUM *a = checksimple(L, 1, BIGNUM_CLASS); + + BN_set_negative(a, !BN_is_negative(a)); + + return 1; +} /* bn__unm() */ + + static int bn__eq(lua_State *L) { BIGNUM *a = checksimple(L, 1, BIGNUM_CLASS); BIGNUM *b = checksimple(L, 2, BIGNUM_CLASS); @@ -451,6 +478,7 @@ static const luaL_Reg bn_metatable[] = { { "__div", &bn__div }, { "__mod", &bn__mod }, { "__pow", &bn__pow }, + { "__unm", &bn__unm }, { "__eq", &bn__eq }, { "__lt", &bn__lt }, { "__le", &bn__le }, @@ -622,12 +650,12 @@ static int xc_setVersion(lua_State *L) { static int xc_getSerialNumber(lua_State *L) { X509 *crt = checksimple(L, 1, X509_CERT_CLASS); - BIGNUM *srl = bn_push(L); - ASN1_INTEGER *num; + BIGNUM *serial = bn_push(L); + ASN1_INTEGER *i; - if ((num = X509_get_serialNumber(crt))) { - if (!ASN1_INTEGER_to_BN(num, srl)) - return throwssl(L, "x509.cert.getSerialNumber"); + if ((i = X509_get_serialNumber(crt))) { + if (!ASN1_INTEGER_to_BN(i, serial)) + return throwssl(L, "x509.cert:getSerialNumber"); } return 1; @@ -636,69 +664,233 @@ static int xc_getSerialNumber(lua_State *L) { static int xc_setSerialNumber(lua_State *L) { X509 *crt = checksimple(L, 1, X509_CERT_CLASS); - ASN1_INTEGER *srl = NULL; - int ok; - - luaL_checkany(L, 2); - - if (lua_isstring(L, 2)) { - BIGNUM *num = NULL; - - if (!BN_dec2bn(&num, lua_tostring(L, 2))) - goto error; + ASN1_INTEGER *serial; - if (!(srl = ASN1_INTEGER_new()) || !(BN_to_ASN1_INTEGER(num, srl))) - goto error; + if (!(serial = BN_to_ASN1_INTEGER(checkbig(L, 2), NULL))) + goto error; - ok = X509_set_serialNumber(crt, srl); - ASN1_INTEGER_free(srl); + if (!X509_set_serialNumber(crt, serial)) + goto error; - if (!ok) - goto error; - } else { - BIGNUM *num = checksimple(L, 2, BIGNUM_CLASS); - - if (!(srl = ASN1_INTEGER_new()) || !(BN_to_ASN1_INTEGER(num, srl))) - goto error; - - ok = X509_set_serialNumber(crt, srl); - ASN1_INTEGER_free(srl); - - if (!ok) - goto error; - } + ASN1_INTEGER_free(serial); lua_pushboolean(L, 1); return 1; error: - return throwssl(L, "x509.cert.setSerialNumber"); + ASN1_INTEGER_free(serial); + + return throwssl(L, "x509.cert:setSerialNumber"); } /* xc_setSerialNumber() */ -#if 0 static int xc_digest(lua_State *L) { X509 *crt = checksimple(L, 1, X509_CERT_CLASS); const char *type = luaL_optstring(L, 2, "sha1"); - const EVP_MD *dgst; + int format = luaL_checkoption(L, 3, "*s", (const char *[]){ "*s", "*x", "*n", NULL }); + const EVP_MD *ctx; unsigned char md[EVP_MAX_MD_SIZE]; - unsigned int len; + unsigned len; + + lua_settop(L, 3); /* self, type, hex */ - if (!(dgst = EVP_getdigestbyname(type))) + if (!(ctx = EVP_get_digestbyname(type))) return luaL_error(L, "x509.cert:digest: %s: invalid digest type", type); - X509_digest(crt, dgst, md, &len); + X509_digest(crt, ctx, md, &len); + + switch (format) { + case 2: { + BIGNUM *bn = bn_push(L); + + if (!BN_bin2bn(md, len, bn)) + return throwssl(L, "x509.cert:digest"); + + break; + } + case 1: { + static const unsigned char x[16] = "0123456789abcdef"; + luaL_Buffer B; + + luaL_buffinitsize(L, &B, 2 * len); + + for (unsigned i = 0; i < len; i++) { + luaL_addchar(&B, x[0x0f & (md[i] >> 4)]); + luaL_addchar(&B, x[0x0f & (md[i] >> 0)]); + } + + luaL_pushresult(&B); - lua_pushlstring(L, md, len); + break; + } + default: + lua_pushlstring(L, (const char *)md, len); + + break; + } /* switch() */ return 1; } /* xc_digest() */ -#endif -static int xc_lifetime(lua_State *L) { + +static _Bool isleap(int year) { + if (year >= 0) + return !(year % 4) && ((year % 100) || !(year % 400)); + else + return isleap(-(year + 1)); +} /* isleap() */ + + +static int yday(int year, int mon, int mday) { + static const int past[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; + int yday = past[CLAMP(mon, 0, 11)] + CLAMP(mday, 1, 31) - 1; + + return yday + (isleap(year) && mon > 1); +} /* yday() */ + + +static int leaps(int year) { + if (year >= 0) + return (year / 400) + (year / 4) - (year / 100); + else + return -(leaps(-(year + 1)) + 1); +} /* leaps() */ + + +static _Bool scan(int *i, char **cp, int n, int signok) { + int sign = 1; + + *i = 0; + + if (signok) { + if (**cp == '-') { + sign = -1; + ++*cp; + } else if (**cp == '+') { + ++*cp; + } + } + + while (n-- > 0) { + if (**cp < '0' || **cp > '9') + return 0; + + *i *= 10; + *i += *(*cp)++ - '0'; + } + + *i *= sign; + + return 1; +} /* scan() */ + + +static double timeutc(ASN1_TIME *time) { + char buf[32] = "", *cp; + struct tm tm; + int gmtoff, year, i; + double ts; + + if (!ASN1_TIME_check(time)) + return 0; + + cp = strncpy(buf, (const char *)ASN1_STRING_data((ASN1_STRING *)time), sizeof buf - 1); + + if (ASN1_STRING_type(time) == V_ASN1_GENERALIZEDTIME) { + if (!scan(&year, &cp, 4, 1)) + goto badfmt; + } else { + if (!scan(&year, &cp, 2, 0)) + goto badfmt; + year += (year < 50)? 2000 : 1999; + } + + tm.tm_year = year - 1900; + + if (!scan(&i, &cp, 2, 0)) + goto badfmt; + + tm.tm_mon = CLAMP(i, 1, 12) - 1; + + if (!scan(&i, &cp, 2, 0)) + goto badfmt; + + tm.tm_mday = CLAMP(i, 1, 31); + + tm.tm_yday = yday(year, tm.tm_mon, tm.tm_mday); + + if (!scan(&i, &cp, 2, 0)) + goto badfmt; + + tm.tm_hour = CLAMP(i, 0, 23); + + if (!scan(&i, &cp, 2, 0)) + goto badfmt; + + tm.tm_min = CLAMP(i, 0, 59); + + if (*cp >= '0' && *cp <= '9') { + if (!scan(&i, &cp, 2, 0)) + goto badfmt; + + tm.tm_sec = CLAMP(i, 0, 59); + } + + if (*cp == '+' || *cp == '-') { + int sign = (*cp++ == '-')? -1 : 1; + int hh, mm; + + if (!scan(&hh, &cp, 2, 0) || !scan(&mm, &cp, 2, 0)) + goto badfmt; + + gmtoff = (CLAMP(hh, 0, 23) * 3600) + + (CLAMP(mm, 0, 59) * 60); + + gmtoff *= sign; + } + + ts = 86400.0 * 365.0 * (year - 1970); + ts += 86400.0 * (leaps(year - 1) - leaps(1969)); + ts += 86400 * tm.tm_yday; + ts += 3600 * tm.tm_hour; + ts += 60 * tm.tm_min; + ts += tm.tm_sec; + ts += (year < 1970)? gmtoff : -gmtoff; + + return ts; +badfmt: + return INFINITY; +} /* timeutc() */ + + +static int xc_getLifetime(lua_State *L) { X509 *crt = checksimple(L, 1, X509_CERT_CLASS); - return 0; -} /* xc_lifetime() */ + double begin = INFINITY, end = INFINITY; + ASN1_TIME *time; + + if ((time = X509_get_notBefore(crt))) + begin = timeutc(time); + + if ((time = X509_get_notAfter(crt))) + end = timeutc(time); + + if (isfinite(begin)) + lua_pushnumber(L, begin); + else + lua_pushnil(L); + + if (isfinite(end)) + lua_pushnumber(L, end); + else + lua_pushnil(L); + + if (isfinite(begin) && isfinite(end) && begin <= end) + lua_pushnumber(L, fabs(end - begin)); + else + lua_pushnumber(L, 0.0); + + return 3; +} /* xc_getLifetime() */ static int xc_issuer(lua_State *L) { -- cgit v1.2.3-59-g8ed1b