diff options
author | William Ahern <william@server.local> | 2012-10-02 17:10:16 -0700 |
---|---|---|
committer | William Ahern <william@server.local> | 2012-10-02 17:10:16 -0700 |
commit | ee1f51dd7a1aaa12e0857a698ac99a5d55c897f0 (patch) | |
tree | 0e8e464f2853c910aa7b0f41dc916a7cbf7a74cf | |
parent | bc29b5bd1989ae5c222c18d0e124f50b5dcb400d (diff) | |
download | luaossl-ee1f51dd7a1aaa12e0857a698ac99a5d55c897f0.tar.gz luaossl-ee1f51dd7a1aaa12e0857a698ac99a5d55c897f0.tar.bz2 luaossl-ee1f51dd7a1aaa12e0857a698ac99a5d55c897f0.zip |
-n
commit lots of time conversion work
-rw-r--r-- | openssl.c | 288 |
1 files changed, 240 insertions, 48 deletions
@@ -28,12 +28,14 @@ | |||
28 | 28 | ||
29 | #include <limits.h> /* INT_MAX INT_MIN */ | 29 | #include <limits.h> /* INT_MAX INT_MIN */ |
30 | #include <string.h> /* memset(3) */ | 30 | #include <string.h> /* memset(3) */ |
31 | #include <math.h> /* fabs(3) floor(3) round(3) isfinite(3) */ | 31 | #include <math.h> /* INFINITY fabs(3) floor(3) frexp(3) fmod(3) round(3) isfinite(3) */ |
32 | #include <time.h> /* struct tm time_t strptime(3) */ | ||
32 | 33 | ||
33 | #include <openssl/err.h> | 34 | #include <openssl/err.h> |
34 | #include <openssl/bn.h> | 35 | #include <openssl/bn.h> |
35 | #include <openssl/x509.h> | 36 | #include <openssl/x509.h> |
36 | #include <openssl/x509v3.h> | 37 | #include <openssl/x509v3.h> |
38 | #include <openssl/evp.h> | ||
37 | 39 | ||
38 | #include <lua.h> | 40 | #include <lua.h> |
39 | #include <lualib.h> | 41 | #include <lualib.h> |
@@ -48,6 +50,8 @@ | |||
48 | #define countof(a) (sizeof (a) / sizeof *(a)) | 50 | #define countof(a) (sizeof (a) / sizeof *(a)) |
49 | #define endof(a) (&(a)[countof(a)]) | 51 | #define endof(a) (&(a)[countof(a)]) |
50 | 52 | ||
53 | #define CLAMP(i, min, max) (((i) < (min))? (min) : ((i) > (max))? (max) : (i)) | ||
54 | |||
51 | 55 | ||
52 | static void *prepudata(lua_State *L, const char *tname, size_t size) { | 56 | static void *prepudata(lua_State *L, const char *tname, size_t size) { |
53 | void *p = memset(lua_newuserdata(L, size), 0, size); | 57 | void *p = memset(lua_newuserdata(L, size), 0, size); |
@@ -124,10 +128,24 @@ static BIGNUM *bn_push(lua_State *L) { | |||
124 | } /* bn_push() */ | 128 | } /* bn_push() */ |
125 | 129 | ||
126 | 130 | ||
131 | #define checkbig_(a, b, c, ...) checkbig((a), (b), (c)) | ||
132 | #define checkbig(...) checkbig_(__VA_ARGS__, &(_Bool){ 0 }) | ||
133 | |||
134 | static BIGNUM *(checkbig)(lua_State *, int, _Bool *); | ||
135 | |||
127 | static int bn_new(lua_State *L) { | 136 | static int bn_new(lua_State *L) { |
128 | bn_push(L); | 137 | int i, n; |
129 | 138 | ||
130 | return 1; | 139 | if ((n = lua_gettop(L)) > 0) { |
140 | for (i = 1; i <= n; i++) | ||
141 | checkbig(L, i); | ||
142 | |||
143 | return n; | ||
144 | } else { | ||
145 | bn_push(L); | ||
146 | |||
147 | return 1; | ||
148 | } | ||
131 | } /* bn_new() */ | 149 | } /* bn_new() */ |
132 | 150 | ||
133 | 151 | ||
@@ -204,7 +222,7 @@ static _Bool f2bn(BIGNUM **bn, double f) { | |||
204 | } /* f2bn() */ | 222 | } /* f2bn() */ |
205 | 223 | ||
206 | 224 | ||
207 | static BIGNUM *checkbig(lua_State *L, int index, _Bool *lvalue) { | 225 | static BIGNUM *(checkbig)(lua_State *L, int index, _Bool *lvalue) { |
208 | BIGNUM **bn; | 226 | BIGNUM **bn; |
209 | const char *dec; | 227 | const char *dec; |
210 | size_t len; | 228 | size_t len; |
@@ -385,6 +403,15 @@ static int bn__pow(lua_State *L) { | |||
385 | } /* bn__pow() */ | 403 | } /* bn__pow() */ |
386 | 404 | ||
387 | 405 | ||
406 | static int bn__unm(lua_State *L) { | ||
407 | BIGNUM *a = checksimple(L, 1, BIGNUM_CLASS); | ||
408 | |||
409 | BN_set_negative(a, !BN_is_negative(a)); | ||
410 | |||
411 | return 1; | ||
412 | } /* bn__unm() */ | ||
413 | |||
414 | |||
388 | static int bn__eq(lua_State *L) { | 415 | static int bn__eq(lua_State *L) { |
389 | BIGNUM *a = checksimple(L, 1, BIGNUM_CLASS); | 416 | BIGNUM *a = checksimple(L, 1, BIGNUM_CLASS); |
390 | BIGNUM *b = checksimple(L, 2, BIGNUM_CLASS); | 417 | BIGNUM *b = checksimple(L, 2, BIGNUM_CLASS); |
@@ -451,6 +478,7 @@ static const luaL_Reg bn_metatable[] = { | |||
451 | { "__div", &bn__div }, | 478 | { "__div", &bn__div }, |
452 | { "__mod", &bn__mod }, | 479 | { "__mod", &bn__mod }, |
453 | { "__pow", &bn__pow }, | 480 | { "__pow", &bn__pow }, |
481 | { "__unm", &bn__unm }, | ||
454 | { "__eq", &bn__eq }, | 482 | { "__eq", &bn__eq }, |
455 | { "__lt", &bn__lt }, | 483 | { "__lt", &bn__lt }, |
456 | { "__le", &bn__le }, | 484 | { "__le", &bn__le }, |
@@ -622,12 +650,12 @@ static int xc_setVersion(lua_State *L) { | |||
622 | 650 | ||
623 | static int xc_getSerialNumber(lua_State *L) { | 651 | static int xc_getSerialNumber(lua_State *L) { |
624 | X509 *crt = checksimple(L, 1, X509_CERT_CLASS); | 652 | X509 *crt = checksimple(L, 1, X509_CERT_CLASS); |
625 | BIGNUM *srl = bn_push(L); | 653 | BIGNUM *serial = bn_push(L); |
626 | ASN1_INTEGER *num; | 654 | ASN1_INTEGER *i; |
627 | 655 | ||
628 | if ((num = X509_get_serialNumber(crt))) { | 656 | if ((i = X509_get_serialNumber(crt))) { |
629 | if (!ASN1_INTEGER_to_BN(num, srl)) | 657 | if (!ASN1_INTEGER_to_BN(i, serial)) |
630 | return throwssl(L, "x509.cert.getSerialNumber"); | 658 | return throwssl(L, "x509.cert:getSerialNumber"); |
631 | } | 659 | } |
632 | 660 | ||
633 | return 1; | 661 | return 1; |
@@ -636,69 +664,233 @@ static int xc_getSerialNumber(lua_State *L) { | |||
636 | 664 | ||
637 | static int xc_setSerialNumber(lua_State *L) { | 665 | static int xc_setSerialNumber(lua_State *L) { |
638 | X509 *crt = checksimple(L, 1, X509_CERT_CLASS); | 666 | X509 *crt = checksimple(L, 1, X509_CERT_CLASS); |
639 | ASN1_INTEGER *srl = NULL; | 667 | ASN1_INTEGER *serial; |
640 | int ok; | ||
641 | |||
642 | luaL_checkany(L, 2); | ||
643 | |||
644 | if (lua_isstring(L, 2)) { | ||
645 | BIGNUM *num = NULL; | ||
646 | |||
647 | if (!BN_dec2bn(&num, lua_tostring(L, 2))) | ||
648 | goto error; | ||
649 | 668 | ||
650 | if (!(srl = ASN1_INTEGER_new()) || !(BN_to_ASN1_INTEGER(num, srl))) | 669 | if (!(serial = BN_to_ASN1_INTEGER(checkbig(L, 2), NULL))) |
651 | goto error; | 670 | goto error; |
652 | 671 | ||
653 | ok = X509_set_serialNumber(crt, srl); | 672 | if (!X509_set_serialNumber(crt, serial)) |
654 | ASN1_INTEGER_free(srl); | 673 | goto error; |
655 | 674 | ||
656 | if (!ok) | 675 | ASN1_INTEGER_free(serial); |
657 | goto error; | ||
658 | } else { | ||
659 | BIGNUM *num = checksimple(L, 2, BIGNUM_CLASS); | ||
660 | |||
661 | if (!(srl = ASN1_INTEGER_new()) || !(BN_to_ASN1_INTEGER(num, srl))) | ||
662 | goto error; | ||
663 | |||
664 | ok = X509_set_serialNumber(crt, srl); | ||
665 | ASN1_INTEGER_free(srl); | ||
666 | |||
667 | if (!ok) | ||
668 | goto error; | ||
669 | } | ||
670 | 676 | ||
671 | lua_pushboolean(L, 1); | 677 | lua_pushboolean(L, 1); |
672 | 678 | ||
673 | return 1; | 679 | return 1; |
674 | error: | 680 | error: |
675 | return throwssl(L, "x509.cert.setSerialNumber"); | 681 | ASN1_INTEGER_free(serial); |
682 | |||
683 | return throwssl(L, "x509.cert:setSerialNumber"); | ||
676 | } /* xc_setSerialNumber() */ | 684 | } /* xc_setSerialNumber() */ |
677 | 685 | ||
678 | 686 | ||
679 | #if 0 | ||
680 | static int xc_digest(lua_State *L) { | 687 | static int xc_digest(lua_State *L) { |
681 | X509 *crt = checksimple(L, 1, X509_CERT_CLASS); | 688 | X509 *crt = checksimple(L, 1, X509_CERT_CLASS); |
682 | const char *type = luaL_optstring(L, 2, "sha1"); | 689 | const char *type = luaL_optstring(L, 2, "sha1"); |
683 | const EVP_MD *dgst; | 690 | int format = luaL_checkoption(L, 3, "*s", (const char *[]){ "*s", "*x", "*n", NULL }); |
691 | const EVP_MD *ctx; | ||
684 | unsigned char md[EVP_MAX_MD_SIZE]; | 692 | unsigned char md[EVP_MAX_MD_SIZE]; |
685 | unsigned int len; | 693 | unsigned len; |
694 | |||
695 | lua_settop(L, 3); /* self, type, hex */ | ||
686 | 696 | ||
687 | if (!(dgst = EVP_getdigestbyname(type))) | 697 | if (!(ctx = EVP_get_digestbyname(type))) |
688 | return luaL_error(L, "x509.cert:digest: %s: invalid digest type", type); | 698 | return luaL_error(L, "x509.cert:digest: %s: invalid digest type", type); |
689 | 699 | ||
690 | X509_digest(crt, dgst, md, &len); | 700 | X509_digest(crt, ctx, md, &len); |
701 | |||
702 | switch (format) { | ||
703 | case 2: { | ||
704 | BIGNUM *bn = bn_push(L); | ||
705 | |||
706 | if (!BN_bin2bn(md, len, bn)) | ||
707 | return throwssl(L, "x509.cert:digest"); | ||
708 | |||
709 | break; | ||
710 | } | ||
711 | case 1: { | ||
712 | static const unsigned char x[16] = "0123456789abcdef"; | ||
713 | luaL_Buffer B; | ||
714 | |||
715 | luaL_buffinitsize(L, &B, 2 * len); | ||
716 | |||
717 | for (unsigned i = 0; i < len; i++) { | ||
718 | luaL_addchar(&B, x[0x0f & (md[i] >> 4)]); | ||
719 | luaL_addchar(&B, x[0x0f & (md[i] >> 0)]); | ||
720 | } | ||
721 | |||
722 | luaL_pushresult(&B); | ||
691 | 723 | ||
692 | lua_pushlstring(L, md, len); | 724 | break; |
725 | } | ||
726 | default: | ||
727 | lua_pushlstring(L, (const char *)md, len); | ||
728 | |||
729 | break; | ||
730 | } /* switch() */ | ||
693 | 731 | ||
694 | return 1; | 732 | return 1; |
695 | } /* xc_digest() */ | 733 | } /* xc_digest() */ |
696 | #endif | ||
697 | 734 | ||
698 | static int xc_lifetime(lua_State *L) { | 735 | |
736 | static _Bool isleap(int year) { | ||
737 | if (year >= 0) | ||
738 | return !(year % 4) && ((year % 100) || !(year % 400)); | ||
739 | else | ||
740 | return isleap(-(year + 1)); | ||
741 | } /* isleap() */ | ||
742 | |||
743 | |||
744 | static int yday(int year, int mon, int mday) { | ||
745 | static const int past[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; | ||
746 | int yday = past[CLAMP(mon, 0, 11)] + CLAMP(mday, 1, 31) - 1; | ||
747 | |||
748 | return yday + (isleap(year) && mon > 1); | ||
749 | } /* yday() */ | ||
750 | |||
751 | |||
752 | static int leaps(int year) { | ||
753 | if (year >= 0) | ||
754 | return (year / 400) + (year / 4) - (year / 100); | ||
755 | else | ||
756 | return -(leaps(-(year + 1)) + 1); | ||
757 | } /* leaps() */ | ||
758 | |||
759 | |||
760 | static _Bool scan(int *i, char **cp, int n, int signok) { | ||
761 | int sign = 1; | ||
762 | |||
763 | *i = 0; | ||
764 | |||
765 | if (signok) { | ||
766 | if (**cp == '-') { | ||
767 | sign = -1; | ||
768 | ++*cp; | ||
769 | } else if (**cp == '+') { | ||
770 | ++*cp; | ||
771 | } | ||
772 | } | ||
773 | |||
774 | while (n-- > 0) { | ||
775 | if (**cp < '0' || **cp > '9') | ||
776 | return 0; | ||
777 | |||
778 | *i *= 10; | ||
779 | *i += *(*cp)++ - '0'; | ||
780 | } | ||
781 | |||
782 | *i *= sign; | ||
783 | |||
784 | return 1; | ||
785 | } /* scan() */ | ||
786 | |||
787 | |||
788 | static double timeutc(ASN1_TIME *time) { | ||
789 | char buf[32] = "", *cp; | ||
790 | struct tm tm; | ||
791 | int gmtoff, year, i; | ||
792 | double ts; | ||
793 | |||
794 | if (!ASN1_TIME_check(time)) | ||
795 | return 0; | ||
796 | |||
797 | cp = strncpy(buf, (const char *)ASN1_STRING_data((ASN1_STRING *)time), sizeof buf - 1); | ||
798 | |||
799 | if (ASN1_STRING_type(time) == V_ASN1_GENERALIZEDTIME) { | ||
800 | if (!scan(&year, &cp, 4, 1)) | ||
801 | goto badfmt; | ||
802 | } else { | ||
803 | if (!scan(&year, &cp, 2, 0)) | ||
804 | goto badfmt; | ||
805 | year += (year < 50)? 2000 : 1999; | ||
806 | } | ||
807 | |||
808 | tm.tm_year = year - 1900; | ||
809 | |||
810 | if (!scan(&i, &cp, 2, 0)) | ||
811 | goto badfmt; | ||
812 | |||
813 | tm.tm_mon = CLAMP(i, 1, 12) - 1; | ||
814 | |||
815 | if (!scan(&i, &cp, 2, 0)) | ||
816 | goto badfmt; | ||
817 | |||
818 | tm.tm_mday = CLAMP(i, 1, 31); | ||
819 | |||
820 | tm.tm_yday = yday(year, tm.tm_mon, tm.tm_mday); | ||
821 | |||
822 | if (!scan(&i, &cp, 2, 0)) | ||
823 | goto badfmt; | ||
824 | |||
825 | tm.tm_hour = CLAMP(i, 0, 23); | ||
826 | |||
827 | if (!scan(&i, &cp, 2, 0)) | ||
828 | goto badfmt; | ||
829 | |||
830 | tm.tm_min = CLAMP(i, 0, 59); | ||
831 | |||
832 | if (*cp >= '0' && *cp <= '9') { | ||
833 | if (!scan(&i, &cp, 2, 0)) | ||
834 | goto badfmt; | ||
835 | |||
836 | tm.tm_sec = CLAMP(i, 0, 59); | ||
837 | } | ||
838 | |||
839 | if (*cp == '+' || *cp == '-') { | ||
840 | int sign = (*cp++ == '-')? -1 : 1; | ||
841 | int hh, mm; | ||
842 | |||
843 | if (!scan(&hh, &cp, 2, 0) || !scan(&mm, &cp, 2, 0)) | ||
844 | goto badfmt; | ||
845 | |||
846 | gmtoff = (CLAMP(hh, 0, 23) * 3600) | ||
847 | + (CLAMP(mm, 0, 59) * 60); | ||
848 | |||
849 | gmtoff *= sign; | ||
850 | } | ||
851 | |||
852 | ts = 86400.0 * 365.0 * (year - 1970); | ||
853 | ts += 86400.0 * (leaps(year - 1) - leaps(1969)); | ||
854 | ts += 86400 * tm.tm_yday; | ||
855 | ts += 3600 * tm.tm_hour; | ||
856 | ts += 60 * tm.tm_min; | ||
857 | ts += tm.tm_sec; | ||
858 | ts += (year < 1970)? gmtoff : -gmtoff; | ||
859 | |||
860 | return ts; | ||
861 | badfmt: | ||
862 | return INFINITY; | ||
863 | } /* timeutc() */ | ||
864 | |||
865 | |||
866 | static int xc_getLifetime(lua_State *L) { | ||
699 | X509 *crt = checksimple(L, 1, X509_CERT_CLASS); | 867 | X509 *crt = checksimple(L, 1, X509_CERT_CLASS); |
700 | return 0; | 868 | double begin = INFINITY, end = INFINITY; |
701 | } /* xc_lifetime() */ | 869 | ASN1_TIME *time; |
870 | |||
871 | if ((time = X509_get_notBefore(crt))) | ||
872 | begin = timeutc(time); | ||
873 | |||
874 | if ((time = X509_get_notAfter(crt))) | ||
875 | end = timeutc(time); | ||
876 | |||
877 | if (isfinite(begin)) | ||
878 | lua_pushnumber(L, begin); | ||
879 | else | ||
880 | lua_pushnil(L); | ||
881 | |||
882 | if (isfinite(end)) | ||
883 | lua_pushnumber(L, end); | ||
884 | else | ||
885 | lua_pushnil(L); | ||
886 | |||
887 | if (isfinite(begin) && isfinite(end) && begin <= end) | ||
888 | lua_pushnumber(L, fabs(end - begin)); | ||
889 | else | ||
890 | lua_pushnumber(L, 0.0); | ||
891 | |||
892 | return 3; | ||
893 | } /* xc_getLifetime() */ | ||
702 | 894 | ||
703 | 895 | ||
704 | static int xc_issuer(lua_State *L) { | 896 | static int xc_issuer(lua_State *L) { |