diff options
| -rw-r--r-- | openssl.c | 744 |
1 files changed, 723 insertions, 21 deletions
| @@ -48,10 +48,12 @@ | |||
| 48 | #include <lauxlib.h> | 48 | #include <lauxlib.h> |
| 49 | 49 | ||
| 50 | 50 | ||
| 51 | #define BIGNUM_CLASS "OpenSSL BN" | ||
| 52 | #define PUBKEY_CLASS "OpenSSL PK" | ||
| 51 | #define X509_NAME_CLASS "OpenSSL X.509 Name" | 53 | #define X509_NAME_CLASS "OpenSSL X.509 Name" |
| 52 | #define X509_GENS_CLASS "OpenSSL X.509 AltName" | 54 | #define X509_GENS_CLASS "OpenSSL X.509 AltName" |
| 53 | #define X509_CERT_CLASS "OpenSSL X.509 Cert" | 55 | #define X509_CERT_CLASS "OpenSSL X.509 Cert" |
| 54 | #define BIGNUM_CLASS "OpenSSL BN" | 56 | #define X509_CSR_CLASS "OpenSSL X.509 Request" |
| 55 | 57 | ||
| 56 | 58 | ||
| 57 | #define countof(a) (sizeof (a) / sizeof *(a)) | 59 | #define countof(a) (sizeof (a) / sizeof *(a)) |
| @@ -109,13 +111,32 @@ static void *checksimple(lua_State *L, int index, const char *tname) { | |||
| 109 | } /* checksimple() */ | 111 | } /* checksimple() */ |
| 110 | 112 | ||
| 111 | 113 | ||
| 114 | static void *testsimple(lua_State *L, int index, const char *tname) { | ||
| 115 | void **p; | ||
| 116 | |||
| 117 | if (tname) { | ||
| 118 | p = luaL_testudata(L, index, tname); | ||
| 119 | } else { | ||
| 120 | luaL_checktype(L, index, LUA_TUSERDATA); | ||
| 121 | p = lua_touserdata(L, index); | ||
| 122 | } | ||
| 123 | |||
| 124 | return *p; | ||
| 125 | } /* testsimple() */ | ||
| 126 | |||
| 127 | |||
| 112 | static int throwssl(lua_State *L, const char *fun) { | 128 | static int throwssl(lua_State *L, const char *fun) { |
| 113 | unsigned long code; | 129 | unsigned long code; |
| 114 | const char *file; | 130 | const char *path, *file; |
| 115 | int line; | 131 | int line; |
| 116 | char txt[256]; | 132 | char txt[256]; |
| 117 | 133 | ||
| 118 | code = ERR_get_error_line(&file, &line); | 134 | code = ERR_get_error_line(&path, &line); |
| 135 | if ((file = strrchr(path, '/'))) | ||
| 136 | ++file; | ||
| 137 | else | ||
| 138 | file = path; | ||
| 139 | |||
| 119 | ERR_clear_error(); | 140 | ERR_clear_error(); |
| 120 | 141 | ||
| 121 | ERR_error_string_n(code, txt, sizeof txt); | 142 | ERR_error_string_n(code, txt, sizeof txt); |
| @@ -167,6 +188,63 @@ static int checkoption(struct lua_State *L, int index, const char *def, const ch | |||
| 167 | } /* checkoption() */ | 188 | } /* checkoption() */ |
| 168 | 189 | ||
| 169 | 190 | ||
| 191 | static _Bool getfield(lua_State *L, int index, const char *k) { | ||
| 192 | lua_getfield(L, index, k); | ||
| 193 | |||
| 194 | if (lua_isnil(L, -1)) { | ||
| 195 | lua_pop(L, 1); | ||
| 196 | |||
| 197 | return 0; | ||
| 198 | } else { | ||
| 199 | return 1; | ||
| 200 | } | ||
| 201 | } /* getfield() */ | ||
| 202 | |||
| 203 | |||
| 204 | static _Bool loadfield(lua_State *L, int index, const char *k, int type, void *p) { | ||
| 205 | if (!getfield(L, index, k)) | ||
| 206 | return 0; | ||
| 207 | |||
| 208 | switch (type) { | ||
| 209 | case LUA_TSTRING: | ||
| 210 | *(const char **)p = luaL_checkstring(L, -1); | ||
| 211 | break; | ||
| 212 | case LUA_TNUMBER: | ||
| 213 | *(lua_Number *)p = luaL_checknumber(L, -1); | ||
| 214 | break; | ||
| 215 | default: | ||
| 216 | luaL_error(L, "loadfield(type=%d): invalid type", type); | ||
| 217 | break; | ||
| 218 | } /* switch() */ | ||
| 219 | |||
| 220 | lua_pop(L, 1); /* table keeps reference */ | ||
| 221 | |||
| 222 | return 1; | ||
| 223 | } /* loadfield() */ | ||
| 224 | |||
| 225 | |||
| 226 | const char *pushnid(lua_State *L, int nid) { | ||
| 227 | const char *txt; | ||
| 228 | ASN1_OBJECT *obj; | ||
| 229 | char buf[256]; | ||
| 230 | int len; | ||
| 231 | |||
| 232 | if ((txt = OBJ_nid2sn(nid)) || (txt = OBJ_nid2ln(nid))) { | ||
| 233 | lua_pushstring(L, txt); | ||
| 234 | } else { | ||
| 235 | if (!(obj = OBJ_nid2obj(nid))) | ||
| 236 | luaL_error(L, "%d: unknown ASN.1 NID", nid); | ||
| 237 | |||
| 238 | if (-1 == (len = OBJ_obj2txt(buf, sizeof buf, obj, 1))) | ||
| 239 | luaL_error(L, "%d: invalid ASN.1 NID", nid); | ||
| 240 | |||
| 241 | lua_pushlstring(L, buf, len); | ||
| 242 | } | ||
| 243 | |||
| 244 | return lua_tostring(L, -1); | ||
| 245 | } /* pushnid() */ | ||
| 246 | |||
| 247 | |||
| 170 | static void initall(lua_State *L); | 248 | static void initall(lua_State *L); |
| 171 | 249 | ||
| 172 | 250 | ||
| @@ -369,7 +447,6 @@ static BN_CTX *getctx(lua_State *L) { | |||
| 369 | lua_pushcfunction(L, &ctx__gc); | 447 | lua_pushcfunction(L, &ctx__gc); |
| 370 | lua_pushvalue(L, -2); | 448 | lua_pushvalue(L, -2); |
| 371 | lua_settable(L, LUA_REGISTRYINDEX); | 449 | lua_settable(L, LUA_REGISTRYINDEX); |
| 372 | |||
| 373 | } | 450 | } |
| 374 | 451 | ||
| 375 | ctx = lua_touserdata(L, -1); | 452 | ctx = lua_touserdata(L, -1); |
| @@ -555,6 +632,454 @@ int luaopen__openssl_bignum(lua_State *L) { | |||
| 555 | 632 | ||
| 556 | 633 | ||
| 557 | /* | 634 | /* |
| 635 | * EVP_PKEY - openssl.pubkey | ||
| 636 | * | ||
| 637 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | ||
| 638 | |||
| 639 | static int bio__gc(lua_State *L) { | ||
| 640 | BIO **bio = lua_touserdata(L, 1); | ||
| 641 | |||
| 642 | BIO_free(*bio); | ||
| 643 | *bio = NULL; | ||
| 644 | |||
| 645 | return 0; | ||
| 646 | } /* bio__gc() */ | ||
| 647 | |||
| 648 | static BIO *getbio(lua_State *L) { | ||
| 649 | BIO **bio; | ||
| 650 | |||
| 651 | lua_pushcfunction(L, &bio__gc); | ||
| 652 | lua_gettable(L, LUA_REGISTRYINDEX); | ||
| 653 | |||
| 654 | if (lua_isnil(L, -1)) { | ||
| 655 | lua_pop(L, 1); | ||
| 656 | |||
| 657 | bio = prepsimple(L, NULL, &bio__gc); | ||
| 658 | |||
| 659 | if (!(*bio = BIO_new(BIO_s_mem()))) | ||
| 660 | throwssl(L, "BIO_new"); | ||
| 661 | |||
| 662 | lua_pushcfunction(L, &bio__gc); | ||
| 663 | lua_pushvalue(L, -2); | ||
| 664 | lua_settable(L, LUA_REGISTRYINDEX); | ||
| 665 | } | ||
| 666 | |||
| 667 | bio = lua_touserdata(L, -1); | ||
| 668 | lua_pop(L, 1); | ||
| 669 | |||
| 670 | BIO_reset(*bio); | ||
| 671 | |||
| 672 | return *bio; | ||
| 673 | } /* getbio() */ | ||
| 674 | |||
| 675 | |||
| 676 | static int pk_new(lua_State *L) { | ||
| 677 | EVP_PKEY **ud; | ||
| 678 | |||
| 679 | lua_settop(L, 1); | ||
| 680 | |||
| 681 | ud = prepsimple(L, PUBKEY_CLASS); | ||
| 682 | |||
| 683 | if (lua_istable(L, 1)) { | ||
| 684 | int type = EVP_PKEY_RSA; | ||
| 685 | unsigned bits = 1024; | ||
| 686 | unsigned exp = 65537; | ||
| 687 | int curve = NID_X9_62_prime192v1; | ||
| 688 | const char *id; | ||
| 689 | lua_Number n; | ||
| 690 | |||
| 691 | if (!lua_istable(L, 1)) | ||
| 692 | goto creat; | ||
| 693 | |||
| 694 | if (loadfield(L, 1, "type", LUA_TSTRING, &id)) { | ||
| 695 | static const struct { int nid; const char *sn; } types[] = { | ||
| 696 | { EVP_PKEY_RSA, "RSA" }, | ||
| 697 | { EVP_PKEY_DSA, "DSA" }, | ||
| 698 | { EVP_PKEY_DH, "DH" }, | ||
| 699 | { EVP_PKEY_EC, "EC" }, | ||
| 700 | }; | ||
| 701 | unsigned i; | ||
| 702 | |||
| 703 | type = OBJ_sn2nid(id); | ||
| 704 | |||
| 705 | if (NID_undef == (type = EVP_PKEY_type(OBJ_sn2nid(id)))) { | ||
| 706 | for (i = 0; i < countof(types); i++) { | ||
| 707 | if (strieq(id, types[i].sn)) { | ||
| 708 | type = types[i].nid; | ||
| 709 | break; | ||
| 710 | } | ||
| 711 | } | ||
| 712 | } | ||
| 713 | |||
| 714 | luaL_argcheck(L, type != NID_undef, 1, lua_pushfstring(L, "%s: invalid key type", id)); | ||
| 715 | } | ||
| 716 | |||
| 717 | if (loadfield(L, 1, "bits", LUA_TNUMBER, &n)) { | ||
| 718 | luaL_argcheck(L, n > 0 && n < UINT_MAX, 1, lua_pushfstring(L, "%f: `bits' invalid", n)); | ||
| 719 | bits = (unsigned)n; | ||
| 720 | } | ||
| 721 | |||
| 722 | if (loadfield(L, 1, "exp", LUA_TNUMBER, &n)) { | ||
| 723 | luaL_argcheck(L, n > 0 && n < UINT_MAX, 1, lua_pushfstring(L, "%f: `exp' invalid", n)); | ||
| 724 | exp = (unsigned)n; | ||
| 725 | } | ||
| 726 | |||
| 727 | if (loadfield(L, 1, "curve", LUA_TSTRING, &id)) { | ||
| 728 | curve = OBJ_sn2nid(id); | ||
| 729 | luaL_argcheck(L, curve != NID_undef, 1, lua_pushfstring(L, "%s: invalid curve", id)); | ||
| 730 | } | ||
| 731 | |||
| 732 | creat: | ||
| 733 | if (!(*ud = EVP_PKEY_new())) | ||
| 734 | return throwssl(L, "pubkey.new"); | ||
| 735 | |||
| 736 | switch (EVP_PKEY_type(type)) { | ||
| 737 | case EVP_PKEY_RSA: { | ||
| 738 | RSA *rsa; | ||
| 739 | |||
| 740 | if (!(rsa = RSA_generate_key(bits, exp, 0, 0))) | ||
| 741 | return throwssl(L, "pubkey.new"); | ||
| 742 | |||
| 743 | EVP_PKEY_set1_RSA(*ud, rsa); | ||
| 744 | |||
| 745 | RSA_free(rsa); | ||
| 746 | |||
| 747 | break; | ||
| 748 | } | ||
| 749 | case EVP_PKEY_DSA: { | ||
| 750 | DSA *dsa; | ||
| 751 | |||
| 752 | if (!(dsa = DSA_generate_parameters(bits, 0, 0, 0, 0, 0, 0))) | ||
| 753 | return throwssl(L, "pubkey.new"); | ||
| 754 | |||
| 755 | if (!DSA_generate_key(dsa)) { | ||
| 756 | DSA_free(dsa); | ||
| 757 | return throwssl(L, "pubkey.new"); | ||
| 758 | } | ||
| 759 | |||
| 760 | EVP_PKEY_set1_DSA(*ud, dsa); | ||
| 761 | |||
| 762 | DSA_free(dsa); | ||
| 763 | |||
| 764 | break; | ||
| 765 | } | ||
| 766 | case EVP_PKEY_DH: { | ||
| 767 | DH *dh; | ||
| 768 | |||
| 769 | if (!(dh = DH_generate_parameters(bits, exp, 0, 0))) | ||
| 770 | return throwssl(L, "pubkey.new"); | ||
| 771 | |||
| 772 | if (!DH_generate_key(dh)) { | ||
| 773 | DH_free(dh); | ||
| 774 | return throwssl(L, "pubkey.new"); | ||
| 775 | } | ||
| 776 | |||
| 777 | EVP_PKEY_set1_DH(*ud, dh); | ||
| 778 | |||
| 779 | DH_free(dh); | ||
| 780 | |||
| 781 | break; | ||
| 782 | } | ||
| 783 | case EVP_PKEY_EC: { | ||
| 784 | EC_GROUP *grp; | ||
| 785 | EC_KEY *key; | ||
| 786 | |||
| 787 | if (!(grp = EC_GROUP_new_by_curve_name(curve))) | ||
| 788 | return throwssl(L, "pubkey.new"); | ||
| 789 | |||
| 790 | EC_GROUP_set_asn1_flag(grp, OPENSSL_EC_NAMED_CURVE); | ||
| 791 | |||
| 792 | /* compressed points patented */ | ||
| 793 | EC_GROUP_set_point_conversion_form(grp, POINT_CONVERSION_UNCOMPRESSED); | ||
| 794 | |||
| 795 | if (!(key = EC_KEY_new())) { | ||
| 796 | EC_GROUP_free(grp); | ||
| 797 | return throwssl(L, "pubkey.new"); | ||
| 798 | } | ||
| 799 | |||
| 800 | EC_KEY_set_group(key, grp); | ||
| 801 | |||
| 802 | EC_GROUP_free(grp); | ||
| 803 | |||
| 804 | if (!EC_KEY_generate_key(key)) { | ||
| 805 | EC_KEY_free(key); | ||
| 806 | return throwssl(L, "pubkey.new"); | ||
| 807 | } | ||
| 808 | |||
| 809 | EVP_PKEY_set1_EC_KEY(*ud, key); | ||
| 810 | |||
| 811 | EC_KEY_free(key); | ||
| 812 | |||
| 813 | break; | ||
| 814 | } | ||
| 815 | default: | ||
| 816 | return luaL_error(L, "%d: unknown EVP base type (%d)", EVP_PKEY_type(type), type); | ||
| 817 | } /* switch() */ | ||
| 818 | } else { | ||
| 819 | const char *pem; | ||
| 820 | size_t len; | ||
| 821 | BIO *bio; | ||
| 822 | int ok; | ||
| 823 | |||
| 824 | if (!(*ud = EVP_PKEY_new())) | ||
| 825 | return throwssl(L, "pubkey.new"); | ||
| 826 | |||
| 827 | switch (lua_type(L, 1)) { | ||
| 828 | case LUA_TSTRING: | ||
| 829 | pem = luaL_checklstring(L, 1, &len); | ||
| 830 | |||
| 831 | if (!(bio = BIO_new_mem_buf((void *)pem, len))) | ||
| 832 | return throwssl(L, "pubkey.new"); | ||
| 833 | |||
| 834 | if (strstr(pem, "PUBLIC KEY")) { | ||
| 835 | ok = !!PEM_read_bio_PUBKEY(bio, ud, 0, 0); | ||
| 836 | } else { | ||
| 837 | ok = !!PEM_read_bio_PrivateKey(bio, ud, 0, 0); | ||
| 838 | } | ||
| 839 | |||
| 840 | BIO_free(bio); | ||
| 841 | |||
| 842 | if (!ok) | ||
| 843 | return throwssl(L, "pubkey.new"); | ||
| 844 | |||
| 845 | break; | ||
| 846 | default: | ||
| 847 | return luaL_error(L, "%s: unknown key initializer", lua_typename(L, lua_type(L, 1))); | ||
| 848 | } /* switch() */ | ||
| 849 | } | ||
| 850 | |||
| 851 | return 1; | ||
| 852 | } /* pk_new() */ | ||
| 853 | |||
| 854 | |||
| 855 | static int pk_interpose(lua_State *L) { | ||
| 856 | return interpose(L, X509_NAME_CLASS); | ||
| 857 | } /* pk_interpose() */ | ||
| 858 | |||
| 859 | |||
| 860 | static int pk_type(lua_State *L) { | ||
| 861 | EVP_PKEY *key = checksimple(L, 1, PUBKEY_CLASS); | ||
| 862 | int nid = key->type; | ||
| 863 | |||
| 864 | pushnid(L, nid); | ||
| 865 | |||
| 866 | return 1; | ||
| 867 | } /* pk_type() */ | ||
| 868 | |||
| 869 | |||
| 870 | static int pk_setPublicKey(lua_State *L) { | ||
| 871 | EVP_PKEY **key = luaL_checkudata(L, 1, PUBKEY_CLASS); | ||
| 872 | const char *pem; | ||
| 873 | size_t len; | ||
| 874 | BIO *bio; | ||
| 875 | int ok; | ||
| 876 | |||
| 877 | lua_settop(L, 2); | ||
| 878 | |||
| 879 | pem = luaL_checklstring(L, 2, &len); | ||
| 880 | |||
| 881 | if (!(bio = BIO_new_mem_buf((void *)pem, len))) | ||
| 882 | return throwssl(L, "pubkey.new"); | ||
| 883 | |||
| 884 | ok = !!PEM_read_bio_PUBKEY(bio, key, 0, 0); | ||
| 885 | |||
| 886 | BIO_free(bio); | ||
| 887 | |||
| 888 | if (!ok) | ||
| 889 | return throwssl(L, "pubkey.new"); | ||
| 890 | |||
| 891 | lua_pushboolean(L, 1); | ||
| 892 | |||
| 893 | return 1; | ||
| 894 | } /* pk_setPublicKey() */ | ||
| 895 | |||
| 896 | |||
| 897 | static int pk_setPrivateKey(lua_State *L) { | ||
| 898 | EVP_PKEY **key = luaL_checkudata(L, 1, PUBKEY_CLASS); | ||
| 899 | const char *pem; | ||
| 900 | size_t len; | ||
| 901 | BIO *bio; | ||
| 902 | int ok; | ||
| 903 | |||
| 904 | lua_settop(L, 2); | ||
| 905 | |||
| 906 | pem = luaL_checklstring(L, 2, &len); | ||
| 907 | |||
| 908 | if (!(bio = BIO_new_mem_buf((void *)pem, len))) | ||
| 909 | return throwssl(L, "pubkey.new"); | ||
| 910 | |||
| 911 | ok = !!PEM_read_bio_PrivateKey(bio, key, 0, 0); | ||
| 912 | |||
| 913 | BIO_free(bio); | ||
| 914 | |||
| 915 | if (!ok) | ||
| 916 | return throwssl(L, "pubkey.new"); | ||
| 917 | |||
| 918 | lua_pushboolean(L, 1); | ||
| 919 | |||
| 920 | return 1; | ||
| 921 | } /* pk_setPrivateKEY() */ | ||
| 922 | |||
| 923 | |||
| 924 | static int pk_toPEM(lua_State *L) { | ||
| 925 | EVP_PKEY *key = checksimple(L, 1, PUBKEY_CLASS); | ||
| 926 | int top, i, ok; | ||
| 927 | BIO *bio; | ||
| 928 | char *pem; | ||
| 929 | long len; | ||
| 930 | |||
| 931 | if (1 == (top = lua_gettop(L))) { | ||
| 932 | lua_pushstring(L, "publickey"); | ||
| 933 | ++top; | ||
| 934 | } | ||
| 935 | |||
| 936 | bio = getbio(L); | ||
| 937 | |||
| 938 | for (i = 2; i <= top; i++) { | ||
| 939 | static const char *opts[] = { | ||
| 940 | "public", "PublicKey", | ||
| 941 | "private", "PrivateKey", | ||
| 942 | // "params", "Parameters", | ||
| 943 | }; | ||
| 944 | |||
| 945 | switch (checkoption(L, i, NULL, opts)) { | ||
| 946 | case 0: case 1: | ||
| 947 | if (!PEM_write_bio_PUBKEY(bio, key)) | ||
| 948 | return throwssl(L, "pubkey:__tostring"); | ||
| 949 | |||
| 950 | len = BIO_get_mem_data(bio, &pem); | ||
| 951 | lua_pushlstring(L, pem, len); | ||
| 952 | |||
| 953 | BIO_reset(bio); | ||
| 954 | break; | ||
| 955 | case 2: case 3: | ||
| 956 | if (!PEM_write_bio_PrivateKey(bio, key, 0, 0, 0, 0, 0)) | ||
| 957 | throwssl(L, "pubkey:__tostring"); | ||
| 958 | |||
| 959 | len = BIO_get_mem_data(bio, &pem); | ||
| 960 | lua_pushlstring(L, pem, len); | ||
| 961 | |||
| 962 | break; | ||
| 963 | case 4: case 5: | ||
| 964 | /* EVP_PKEY_base_id not in OS X */ | ||
| 965 | switch (EVP_PKEY_type(key->type)) { | ||
| 966 | case EVP_PKEY_RSA: | ||
| 967 | break; | ||
| 968 | case EVP_PKEY_DSA: { | ||
| 969 | DSA *dsa = EVP_PKEY_get1_DSA(key); | ||
| 970 | |||
| 971 | ok = !!PEM_write_bio_DSAparams(bio, dsa); | ||
| 972 | |||
| 973 | DSA_free(dsa); | ||
| 974 | |||
| 975 | if (!ok) | ||
| 976 | return throwssl(L, "pubkey:__tostring"); | ||
| 977 | |||
| 978 | break; | ||
| 979 | } | ||
| 980 | case EVP_PKEY_DH: { | ||
| 981 | DH *dh = EVP_PKEY_get1_DH(key); | ||
| 982 | |||
| 983 | ok = !!PEM_write_bio_DHparams(bio, dh); | ||
| 984 | |||
| 985 | DH_free(dh); | ||
| 986 | |||
| 987 | if (!ok) | ||
| 988 | return throwssl(L, "pubkey:__tostring"); | ||
| 989 | |||
| 990 | break; | ||
| 991 | } | ||
| 992 | case EVP_PKEY_EC: { | ||
| 993 | EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key); | ||
| 994 | const EC_GROUP *grp = EC_KEY_get0_group(ec); | ||
| 995 | |||
| 996 | ok = !!PEM_write_bio_ECPKParameters(bio, grp); | ||
| 997 | |||
| 998 | EC_KEY_free(ec); | ||
| 999 | |||
| 1000 | if (!ok) | ||
| 1001 | return throwssl(L, "pubkey:__tostring"); | ||
| 1002 | |||
| 1003 | break; | ||
| 1004 | } | ||
| 1005 | default: | ||
| 1006 | return luaL_error(L, "%d: unknown EVP base type", EVP_PKEY_type(key->type)); | ||
| 1007 | } | ||
| 1008 | |||
| 1009 | lua_pushlstring(L, pem, len); | ||
| 1010 | |||
| 1011 | BIO_reset(bio); | ||
| 1012 | |||
| 1013 | break; | ||
| 1014 | default: | ||
| 1015 | lua_pushnil(L); | ||
| 1016 | |||
| 1017 | break; | ||
| 1018 | } /* switch() */ | ||
| 1019 | } /* for() */ | ||
| 1020 | |||
| 1021 | return lua_gettop(L) - top; | ||
| 1022 | } /* pk_toPEM() */ | ||
| 1023 | |||
| 1024 | |||
| 1025 | static int pk__tostring(lua_State *L) { | ||
| 1026 | EVP_PKEY *key = checksimple(L, 1, PUBKEY_CLASS); | ||
| 1027 | BIO *bio = getbio(L); | ||
| 1028 | char *pem; | ||
| 1029 | long len; | ||
| 1030 | int ok; | ||
| 1031 | |||
| 1032 | if (!PEM_write_bio_PUBKEY(bio, key)) | ||
| 1033 | return throwssl(L, "pubkey:__tostring"); | ||
| 1034 | |||
| 1035 | len = BIO_get_mem_data(bio, &pem); | ||
| 1036 | lua_pushlstring(L, pem, len); | ||
| 1037 | |||
| 1038 | return 1; | ||
| 1039 | } /* pk__tostring() */ | ||
| 1040 | |||
| 1041 | |||
| 1042 | static int pk__gc(lua_State *L) { | ||
| 1043 | EVP_PKEY **ud = luaL_checkudata(L, 1, PUBKEY_CLASS); | ||
| 1044 | |||
| 1045 | EVP_PKEY_free(*ud); | ||
| 1046 | *ud = NULL; | ||
| 1047 | |||
| 1048 | return 0; | ||
| 1049 | } /* pk__gc() */ | ||
| 1050 | |||
| 1051 | |||
| 1052 | static const luaL_Reg pk_methods[] = { | ||
| 1053 | { "type", &pk_type }, | ||
| 1054 | { "setPublicKey", &pk_setPublicKey }, | ||
| 1055 | { "setPrivateKey", &pk_setPrivateKey }, | ||
| 1056 | { "toPEM", &pk_toPEM }, | ||
| 1057 | { NULL, NULL }, | ||
| 1058 | }; | ||
| 1059 | |||
| 1060 | static const luaL_Reg pk_metatable[] = { | ||
| 1061 | { "__tostring", &pk__tostring }, | ||
| 1062 | { "__gc", &pk__gc }, | ||
| 1063 | { NULL, NULL }, | ||
| 1064 | }; | ||
| 1065 | |||
| 1066 | |||
| 1067 | static const luaL_Reg pk_globals[] = { | ||
| 1068 | { "new", &pk_new }, | ||
| 1069 | { "interpose", &pk_interpose }, | ||
| 1070 | { NULL, NULL }, | ||
| 1071 | }; | ||
| 1072 | |||
| 1073 | int luaopen__openssl_pubkey(lua_State *L) { | ||
| 1074 | initall(L); | ||
| 1075 | |||
| 1076 | luaL_newlib(L, pk_globals); | ||
| 1077 | |||
| 1078 | return 1; | ||
| 1079 | } /* luaopen__openssl_pubkey() */ | ||
| 1080 | |||
| 1081 | |||
| 1082 | /* | ||
| 558 | * X509_NAME - openssl.x509.name | 1083 | * X509_NAME - openssl.x509.name |
| 559 | * | 1084 | * |
| 560 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | 1085 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
| @@ -1365,7 +1890,9 @@ static int xc_getIssuer(lua_State *L) { | |||
| 1365 | if ((name = X509_get_issuer_name(crt))) | 1890 | if ((name = X509_get_issuer_name(crt))) |
| 1366 | xn_dup(L, name); | 1891 | xn_dup(L, name); |
| 1367 | 1892 | ||
| 1368 | return !!name; | 1893 | lua_pushboolean(L, 1); |
| 1894 | |||
| 1895 | return 1; | ||
| 1369 | } /* xc_getIssuer() */ | 1896 | } /* xc_getIssuer() */ |
| 1370 | 1897 | ||
| 1371 | 1898 | ||
| @@ -1376,7 +1903,9 @@ static int xc_setIssuer(lua_State *L) { | |||
| 1376 | if (!X509_set_issuer_name(crt, name)) | 1903 | if (!X509_set_issuer_name(crt, name)) |
| 1377 | return throwssl(L, "x509.cert:setIssuer"); | 1904 | return throwssl(L, "x509.cert:setIssuer"); |
| 1378 | 1905 | ||
| 1379 | return !!name; | 1906 | lua_pushboolean(L, 1); |
| 1907 | |||
| 1908 | return 1; | ||
| 1380 | } /* xc_setIssuer() */ | 1909 | } /* xc_setIssuer() */ |
| 1381 | 1910 | ||
| 1382 | 1911 | ||
| @@ -1387,7 +1916,9 @@ static int xc_getSubject(lua_State *L) { | |||
| 1387 | if ((name = X509_get_subject_name(crt))) | 1916 | if ((name = X509_get_subject_name(crt))) |
| 1388 | xn_dup(L, name); | 1917 | xn_dup(L, name); |
| 1389 | 1918 | ||
| 1390 | return !!name; | 1919 | lua_pushboolean(L, 1); |
| 1920 | |||
| 1921 | return 1; | ||
| 1391 | } /* xc_getSubject() */ | 1922 | } /* xc_getSubject() */ |
| 1392 | 1923 | ||
| 1393 | 1924 | ||
| @@ -1398,7 +1929,9 @@ static int xc_setSubject(lua_State *L) { | |||
| 1398 | if (!X509_set_subject_name(crt, name)) | 1929 | if (!X509_set_subject_name(crt, name)) |
| 1399 | return throwssl(L, "x509.cert:setSubject"); | 1930 | return throwssl(L, "x509.cert:setSubject"); |
| 1400 | 1931 | ||
| 1401 | return !!name; | 1932 | lua_pushboolean(L, 1); |
| 1933 | |||
| 1934 | return 1; | ||
| 1402 | } /* xc_setSubject() */ | 1935 | } /* xc_setSubject() */ |
| 1403 | 1936 | ||
| 1404 | 1937 | ||
| @@ -1669,30 +2202,44 @@ static int xc_setBasicConstraintsCritical(lua_State *L) { | |||
| 1669 | } /* xc_setBasicConstraintsCritical() */ | 2202 | } /* xc_setBasicConstraintsCritical() */ |
| 1670 | 2203 | ||
| 1671 | 2204 | ||
| 2205 | static int xc_getPublicKey(lua_State *L) { | ||
| 2206 | X509 *crt = checksimple(L, 1, X509_CERT_CLASS); | ||
| 2207 | EVP_PKEY **key = prepsimple(L, PUBKEY_CLASS); | ||
| 2208 | |||
| 2209 | if (!(*key = X509_get_pubkey(crt))) | ||
| 2210 | return throwssl(L, "x509.cert:getPublicKey"); | ||
| 2211 | |||
| 2212 | return 1; | ||
| 2213 | } /* xc_getPublicKey() */ | ||
| 2214 | |||
| 2215 | |||
| 2216 | static int xc_setPublicKey(lua_State *L) { | ||
| 2217 | X509 *crt = checksimple(L, 1, X509_CERT_CLASS); | ||
| 2218 | EVP_PKEY *key = checksimple(L, 2, PUBKEY_CLASS); | ||
| 2219 | |||
| 2220 | if (!X509_set_pubkey(crt, key)) | ||
| 2221 | return throwssl(L, "x509.cert:setPublicKey"); | ||
| 2222 | |||
| 2223 | lua_pushboolean(L, 1); | ||
| 2224 | |||
| 2225 | return 1; | ||
| 2226 | } /* xc_setPublicKey() */ | ||
| 2227 | |||
| 2228 | |||
| 1672 | static int xc__tostring(lua_State *L) { | 2229 | static int xc__tostring(lua_State *L) { |
| 1673 | X509 *crt = checksimple(L, 1, X509_CERT_CLASS); | 2230 | X509 *crt = checksimple(L, 1, X509_CERT_CLASS); |
| 1674 | int fmt = checkoption(L, 2, "pem", (const char *[]){ "pem", 0 }); | 2231 | int fmt = checkoption(L, 2, "pem", (const char *[]){ "pem", 0 }); |
| 1675 | BIO *tmp; | 2232 | BIO *bio = getbio(L); |
| 1676 | char *pem; | 2233 | char *pem; |
| 1677 | long len; | 2234 | long len; |
| 1678 | 2235 | ||
| 1679 | if (!(tmp = BIO_new(BIO_s_mem()))) | 2236 | if (!PEM_write_bio_X509(bio, crt)) |
| 1680 | return throwssl(L, "x509.cert:__tostring"); | ||
| 1681 | |||
| 1682 | if (!PEM_write_bio_X509(tmp, crt)) { | ||
| 1683 | BIO_free(tmp); | ||
| 1684 | |||
| 1685 | return throwssl(L, "x509.cert:__tostring"); | 2237 | return throwssl(L, "x509.cert:__tostring"); |
| 1686 | } | ||
| 1687 | 2238 | ||
| 1688 | len = BIO_get_mem_data(tmp, &pem); | 2239 | len = BIO_get_mem_data(bio, &pem); |
| 1689 | |||
| 1690 | /* FIXME: leaks on panic */ | ||
| 1691 | 2240 | ||
| 1692 | lua_pushlstring(L, pem, len); | 2241 | lua_pushlstring(L, pem, len); |
| 1693 | 2242 | ||
| 1694 | BIO_free(tmp); | ||
| 1695 | |||
| 1696 | return 1; | 2243 | return 1; |
| 1697 | } /* xc__tostring() */ | 2244 | } /* xc__tostring() */ |
| 1698 | 2245 | ||
| @@ -1733,6 +2280,8 @@ static const luaL_Reg xc_methods[] = { | |||
| 1733 | { "setBasicConstraint", &xc_setBasicConstraint }, | 2280 | { "setBasicConstraint", &xc_setBasicConstraint }, |
| 1734 | { "getBasicConstraintsCritical", &xc_getBasicConstraintsCritical }, | 2281 | { "getBasicConstraintsCritical", &xc_getBasicConstraintsCritical }, |
| 1735 | { "setBasicConstraintsCritical", &xc_setBasicConstraintsCritical }, | 2282 | { "setBasicConstraintsCritical", &xc_setBasicConstraintsCritical }, |
| 2283 | { "getPublicKey", &xc_getPublicKey }, | ||
| 2284 | { "setPublicKey", &xc_setPublicKey }, | ||
| 1736 | { NULL, NULL }, | 2285 | { NULL, NULL }, |
| 1737 | }; | 2286 | }; |
| 1738 | 2287 | ||
| @@ -1758,14 +2307,167 @@ int luaopen__openssl_x509_cert(lua_State *L) { | |||
| 1758 | } /* luaopen__openssl_x509_cert() */ | 2307 | } /* luaopen__openssl_x509_cert() */ |
| 1759 | 2308 | ||
| 1760 | 2309 | ||
| 2310 | /* | ||
| 2311 | * X509_REQ - openssl.x509.csr | ||
| 2312 | * | ||
| 2313 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | ||
| 2314 | |||
| 2315 | static int xr_new(lua_State *L) { | ||
| 2316 | const char *pem; | ||
| 2317 | size_t len; | ||
| 2318 | X509_REQ **ud; | ||
| 2319 | X509 *crt; | ||
| 2320 | |||
| 2321 | lua_settop(L, 1); | ||
| 2322 | |||
| 2323 | ud = prepsimple(L, X509_CSR_CLASS); | ||
| 2324 | |||
| 2325 | if ((crt = testsimple(L, 1, X509_CERT_CLASS))) { | ||
| 2326 | if (!(*ud = X509_to_X509_REQ(crt, 0, 0))) | ||
| 2327 | return throwssl(L, "x509.csr.new"); | ||
| 2328 | } else if ((pem = luaL_optlstring(L, 1, NULL, &len))) { | ||
| 2329 | BIO *tmp; | ||
| 2330 | int ok; | ||
| 2331 | |||
| 2332 | if (!(tmp = BIO_new_mem_buf((char *)pem, len))) | ||
| 2333 | return throwssl(L, "x509.csr.new"); | ||
| 2334 | |||
| 2335 | ok = !!PEM_read_bio_X509_REQ(tmp, ud, 0, ""); /* no password */ | ||
| 2336 | |||
| 2337 | BIO_free(tmp); | ||
| 2338 | |||
| 2339 | if (!ok) | ||
| 2340 | return throwssl(L, "x509.csr.new"); | ||
| 2341 | } else { | ||
| 2342 | if (!(*ud = X509_REQ_new())) | ||
| 2343 | return throwssl(L, "x509.csr.new"); | ||
| 2344 | } | ||
| 2345 | |||
| 2346 | return 1; | ||
| 2347 | } /* xr_new() */ | ||
| 2348 | |||
| 2349 | |||
| 2350 | static int xr_interpose(lua_State *L) { | ||
| 2351 | return interpose(L, X509_CSR_CLASS); | ||
| 2352 | } /* xr_interpose() */ | ||
| 2353 | |||
| 2354 | |||
| 2355 | static int xr_getVersion(lua_State *L) { | ||
| 2356 | X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS); | ||
| 2357 | |||
| 2358 | lua_pushinteger(L, X509_REQ_get_version(csr) + 1); | ||
| 2359 | |||
| 2360 | return 1; | ||
| 2361 | } /* xr_getVersion() */ | ||
| 2362 | |||
| 2363 | |||
| 2364 | static int xr_setVersion(lua_State *L) { | ||
| 2365 | X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS); | ||
| 2366 | int version = luaL_checkint(L, 2); | ||
| 2367 | |||
| 2368 | if (!X509_REQ_set_version(csr, version - 1)) | ||
| 2369 | return luaL_error(L, "x509.csr:setVersion: %d: invalid version", version); | ||
| 2370 | |||
| 2371 | lua_pushboolean(L, 1); | ||
| 2372 | |||
| 2373 | return 1; | ||
| 2374 | } /* xr_setVersion() */ | ||
| 2375 | |||
| 2376 | |||
| 2377 | static int xr_setSubjectName(lua_State *L) { | ||
| 2378 | X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS); | ||
| 2379 | X509_NAME *name = checksimple(L, 2, X509_NAME_CLASS); | ||
| 2380 | |||
| 2381 | if (!X509_REQ_set_subject_name(csr, name)) | ||
| 2382 | return throwssl(L, "x509.csr:setSubject"); | ||
| 2383 | |||
| 2384 | lua_pushboolean(L, 1); | ||
| 2385 | |||
| 2386 | return 1; | ||
| 2387 | } /* xr_setSubjectName() */ | ||
| 2388 | |||
| 2389 | |||
| 2390 | static int xr_setPublicKey(lua_State *L) { | ||
| 2391 | X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS); | ||
| 2392 | EVP_PKEY *key = checksimple(L, 2, PUBKEY_CLASS); | ||
| 2393 | |||
| 2394 | if (!X509_REQ_set_pubkey(csr, key)) | ||
| 2395 | return throwssl(L, "x509.csr:setPublicKey"); | ||
| 2396 | |||
| 2397 | lua_pushboolean(L, 1); | ||
| 2398 | |||
| 2399 | return 1; | ||
| 2400 | } /* xr_setPublicKey() */ | ||
| 2401 | |||
| 2402 | |||
| 2403 | static int xr__tostring(lua_State *L) { | ||
| 2404 | X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS); | ||
| 2405 | int fmt = checkoption(L, 2, "pem", (const char *[]){ "pem", 0 }); | ||
| 2406 | BIO *bio = getbio(L); | ||
| 2407 | char *pem; | ||
| 2408 | long len; | ||
| 2409 | |||
| 2410 | if (!PEM_write_bio_X509_REQ(bio, csr)) | ||
| 2411 | return throwssl(L, "x509.csr:__tostring"); | ||
| 2412 | |||
| 2413 | len = BIO_get_mem_data(bio, &pem); | ||
| 2414 | |||
| 2415 | lua_pushlstring(L, pem, len); | ||
| 2416 | |||
| 2417 | return 1; | ||
| 2418 | } /* xr__tostring() */ | ||
| 2419 | |||
| 2420 | |||
| 2421 | static int xr__gc(lua_State *L) { | ||
| 2422 | X509_REQ **ud = luaL_checkudata(L, 1, X509_CSR_CLASS); | ||
| 2423 | |||
| 2424 | X509_REQ_free(*ud); | ||
| 2425 | *ud = NULL; | ||
| 2426 | |||
| 2427 | return 0; | ||
| 2428 | } /* xr__gc() */ | ||
| 2429 | |||
| 2430 | static const luaL_Reg xr_methods[] = { | ||
| 2431 | { "getVersion", &xr_getVersion }, | ||
| 2432 | { "setVersion", &xr_setVersion }, | ||
| 2433 | { "setSubjectName", &xr_setSubjectName }, | ||
| 2434 | { "setPublicKey", &xr_setPublicKey }, | ||
| 2435 | { NULL, NULL }, | ||
| 2436 | }; | ||
| 2437 | |||
| 2438 | static const luaL_Reg xr_metatable[] = { | ||
| 2439 | { "__tostring", &xr__tostring }, | ||
| 2440 | { "__gc", &xr__gc }, | ||
| 2441 | { NULL, NULL }, | ||
| 2442 | }; | ||
| 2443 | |||
| 2444 | |||
| 2445 | static const luaL_Reg xr_globals[] = { | ||
| 2446 | { "new", &xr_new }, | ||
| 2447 | { "interpose", &xr_interpose }, | ||
| 2448 | { NULL, NULL }, | ||
| 2449 | }; | ||
| 2450 | |||
| 2451 | int luaopen__openssl_x509_csr(lua_State *L) { | ||
| 2452 | initall(L); | ||
| 2453 | |||
| 2454 | luaL_newlib(L, xr_globals); | ||
| 2455 | |||
| 2456 | return 1; | ||
| 2457 | } /* luaopen__openssl_x509_csr() */ | ||
| 2458 | |||
| 2459 | |||
| 2460 | |||
| 1761 | static void initall(lua_State *L) { | 2461 | static void initall(lua_State *L) { |
| 1762 | ERR_load_crypto_strings(); | 2462 | ERR_load_crypto_strings(); |
| 1763 | OpenSSL_add_all_algorithms(); | 2463 | OpenSSL_add_all_algorithms(); |
| 1764 | 2464 | ||
| 1765 | addclass(L, BIGNUM_CLASS, bn_methods, bn_metatable); | 2465 | addclass(L, BIGNUM_CLASS, bn_methods, bn_metatable); |
| 2466 | addclass(L, PUBKEY_CLASS, pk_methods, pk_metatable); | ||
| 1766 | addclass(L, X509_NAME_CLASS, xn_methods, xn_metatable); | 2467 | addclass(L, X509_NAME_CLASS, xn_methods, xn_metatable); |
| 1767 | addclass(L, X509_GENS_CLASS, gn_methods, gn_metatable); | 2468 | addclass(L, X509_GENS_CLASS, gn_methods, gn_metatable); |
| 1768 | addclass(L, X509_CERT_CLASS, xc_methods, xc_metatable); | 2469 | addclass(L, X509_CERT_CLASS, xc_methods, xc_metatable); |
| 2470 | addclass(L, X509_CSR_CLASS, xr_methods, xr_metatable); | ||
| 1769 | } /* initall() */ | 2471 | } /* initall() */ |
| 1770 | 2472 | ||
| 1771 | 2473 | ||
