1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 2013-2016 Jakub Zelenka                                |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 3.01 of the PHP license,      |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.php.net/license/3_01.txt                                  |
11   | If you did not receive a copy of the PHP license and are unable to   |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@php.net so we can mail you a copy immediately.               |
14   +----------------------------------------------------------------------+
15   | Author: Jakub Zelenka <bukka@php.net>                                |
16   +----------------------------------------------------------------------+
17 */
18 
19 #ifndef PHP_CRYPTO_H
20 #define PHP_CRYPTO_H
21 
22 extern zend_module_entry crypto_module_entry;
23 #define phpext_crypto_ptr &crypto_module_entry
24 
25 #ifdef PHP_WIN32
26 #	define PHP_CRYPTO_API __declspec(dllexport)
27 #elif defined(__GNUC__) && __GNUC__ >= 4
28 #	define PHP_CRYPTO_API __attribute__ ((visibility("default")))
29 #else
30 #	define PHP_CRYPTO_API
31 #endif
32 
33 /* always inline even in debug mode */
34 #if defined(__GNUC__) && __GNUC__ >= 3
35 #define php_crypto_always_inline inline __attribute__((always_inline))
36 #else
37 #define php_crypto_always_inline inline
38 #endif
39 
40 #ifdef ZTS
41 #include "TSRM.h"
42 #endif
43 
44 #include "php.h"
45 #include <openssl/evp.h>
46 
47 /* PHP Compatibility layer */
48 #include "phpc/phpc.h"
49 
50 /* Crypto version */
51 #define PHP_CRYPTO_VERSION "0.3.1"
52 
53 
54 /* NAMESPACE */
55 
56 /* Crypto namespace name */
57 #define PHP_CRYPTO_NS_NAME "Crypto"
58 
59 /* Namespace separator */
60 #define PHP_CRYPTO_NS_SEPARATOR "\\"
61 
62 /* Crypto class name (including namespace) */
63 #define PHP_CRYPTO_CLASS_NAME(classname) \
64 	PHP_CRYPTO_NS_NAME PHP_CRYPTO_NS_SEPARATOR #classname
65 
66 /* Crypto method definition */
67 #define PHP_CRYPTO_METHOD(classname, method) \
68 	PHP_METHOD(Crypto_##_##classname, method)
69 
70 /* Crypto method entry */
71 #define PHP_CRYPTO_ME(classname, name, arg_info, flags) \
72 	PHP_ME(Crypto_##_##classname, name, arg_info, flags)
73 
74 /* Crypto abstract method entry */
75 #define PHP_CRYPTO_ABSTRACT_ME(classname, name, arg_info) \
76 	PHP_ABSTRACT_ME(Crypto_##_##classname, name, arg_info)
77 
78 /* Macros for dealing with Crypto sub namespaces (not used yet) */
79 #define PHP_CRYPTO_NS_NAMESPACE(ns) \
80 	PHP_CRYPTO_NS_NAME PHP_CRYPTO_NS_SEPARATOR #ns
81 #define PHP_CRYPTO_NS_CLASS_NAME(ns, classname) \
82 	PHP_CRYPTO_NS_NAMESPACE(ns) PHP_CRYPTO_NS_SEPARATOR #classname
83 #define PHP_CRYPTO_NS_METHOD(ns, classname, method) \
84 	PHP_METHOD(Crypto_##ns##_##classname, method)
85 #define PHP_CRYPTO_NS_ME(ns, classname, name, arg_info, flags) \
86 	PHP_ME(Crypto_##ns##_##classname, name, arg_info, flags)
87 #define PHP_CRYPTO_NS_ABSTRACT_ME(ns, classname, name, arg_info) \
88 	PHP_ABSTRACT_ME(Crypto_##ns##_##classname, name, arg_info)
89 
90 
91 /* NUMERIC CONVERSIONS */
92 PHP_CRYPTO_API int php_crypto_str_size_to_int(
93 		phpc_str_size_t size_len, int *int_len);
94 PHP_CRYPTO_API int php_crypto_long_to_int(
95 		phpc_long_t plv, int *lv);
96 
97 
98 /* ERROR TYPES */
99 
100 /* Errors info structure */
101 typedef struct {
102 	const char *name;
103 	const char *msg;
104 	int level;
105 } php_crypto_error_info;
106 
107 /* Error processing action */
108 typedef enum {
109 	PHP_CRYPTO_ERROR_ACTION_GLOBAL = 0,
110 	PHP_CRYPTO_ERROR_ACTION_SILENT,
111 	PHP_CRYPTO_ERROR_ACTION_EXCEPTION,
112 	PHP_CRYPTO_ERROR_ACTION_ERROR
113 } php_crypto_error_action;
114 
115 /* Processes error msg and either throw exception,
116  * emits error or do nothing (it depends on action) */
117 PHP_CRYPTO_API void php_crypto_verror(
118 		const php_crypto_error_info *info, zend_class_entry *exc_ce,
119 		php_crypto_error_action action, int ignore_args TSRMLS_DC,
120 		const char *name, va_list args);
121 /* Main error function with arguments */
122 PHP_CRYPTO_API void php_crypto_error_ex(
123 		const php_crypto_error_info *info, zend_class_entry *exc_ce,
124 		php_crypto_error_action action, int ignore_args TSRMLS_DC,
125 		const char *name, ...);
126 /* Main error function without arguments */
127 PHP_CRYPTO_API void php_crypto_error(
128 		const php_crypto_error_info *info, zend_class_entry *exc_ce,
129 		php_crypto_error_action action, int ignore_args TSRMLS_DC,
130 		const char *name);
131 
132 /* Macros for crypto exceptions info */
133 
134 #define PHP_CRYPTO_EXCEPTION_CE(ename) \
135 	php_crypto_##ename##Exception_ce
136 
137 #define PHP_CRYPTO_EXCEPTION_EXPORT(ename) \
138 	extern PHP_CRYPTO_API zend_class_entry *PHP_CRYPTO_EXCEPTION_CE(ename);
139 
140 #define PHP_CRYPTO_EXCEPTION_DEFINE(ename) \
141 	PHP_CRYPTO_API zend_class_entry *PHP_CRYPTO_EXCEPTION_CE(ename);
142 
143 #define PHP_CRYPTO_EXCEPTION_REGISTER_CE(ce, ename, epname_ce) \
144 	INIT_CLASS_ENTRY(ce, PHP_CRYPTO_CLASS_NAME(ename ## Exception), NULL); \
145 	PHP_CRYPTO_EXCEPTION_CE(ename) = PHPC_CLASS_REGISTER_EX(ce, epname_ce, NULL)
146 
147 #define PHP_CRYPTO_EXCEPTION_REGISTER_EX(ce, ename, epname) \
148 	PHP_CRYPTO_EXCEPTION_REGISTER_CE(ce, ename, PHP_CRYPTO_EXCEPTION_CE(epname))
149 
150 #define PHP_CRYPTO_EXCEPTION_REGISTER(ce, ename) \
151 	PHP_CRYPTO_EXCEPTION_REGISTER_EX(ce, ename, Crypto)
152 
153 /* Macros for error info */
154 
155 #define PHP_CRYPTO_ERROR_INFO_NAME(ename) \
156 	php_crypto_error_info_##ename
157 
158 #define PHP_CRYPTO_ERROR_INFO_BEGIN(ename) \
159 	php_crypto_error_info PHP_CRYPTO_ERROR_INFO_NAME(ename)[] = {
160 
161 #define PHP_CRYPTO_ERROR_INFO_ENTRY_EX(einame, eimsg, eilevel) \
162 	{ #einame, eimsg, eilevel },
163 
164 #define PHP_CRYPTO_ERROR_INFO_ENTRY(einame, eimsg) \
165 	PHP_CRYPTO_ERROR_INFO_ENTRY_EX(einame, eimsg, E_WARNING)
166 
167 #define PHP_CRYPTO_ERROR_INFO_END() \
168 	{ NULL, NULL, 0} };
169 #define PHP_CRYPTO_ERROR_INFO_EXPORT(ename) \
170 		extern php_crypto_error_info PHP_CRYPTO_ERROR_INFO_NAME(ename)[];
171 
172 #define PHP_CRYPTO_ERROR_INFO_REGISTER(ename) do { \
173 	long code = 1; \
174 	php_crypto_error_info *einfo = PHP_CRYPTO_ERROR_INFO_NAME(ename); \
175 	while (einfo->name != NULL) { \
176 		zend_declare_class_constant_long(PHP_CRYPTO_EXCEPTION_CE(ename), \
177 			einfo->name, strlen(einfo->name), code++ TSRMLS_CC); \
178 		einfo++; \
179 	} } while(0)
180 
181 /* Macros for wrapping error arguments passed to php_crypto_error* */
182 
183 #define PHP_CRYPTO_ERROR_ARGS_EX(ename, eexc, eact, einame) \
184 	PHP_CRYPTO_ERROR_INFO_NAME(ename), eexc, eact, 0 TSRMLS_CC, #einame
185 
186 #define PHP_CRYPTO_ERROR_ARGS(ename, einame) \
187 	PHP_CRYPTO_ERROR_ARGS_EX(ename, PHP_CRYPTO_EXCEPTION_CE(ename), \
188 		PHP_CRYPTO_ERROR_ACTION_GLOBAL, einame)
189 
190 /* Base exception class */
191 PHP_CRYPTO_EXCEPTION_EXPORT(Crypto)
192 
193 
194 /* GLOBALS */
195 
196 ZEND_BEGIN_MODULE_GLOBALS(crypto)
197 	php_crypto_error_action error_action;
198 ZEND_END_MODULE_GLOBALS(crypto)
199 
200 #ifdef ZTS
201 # define PHP_CRYPTO_G(v) TSRMG(crypto_globals_id, zend_crypto_globals *, v)
202 #else
203 # define PHP_CRYPTO_G(v) (crypto_globals.v)
204 #endif
205 
206 
207 /* MODULE FUNCTIONS */
208 
209 PHP_MINIT_FUNCTION(crypto);
210 PHP_GINIT_FUNCTION(crypto);
211 PHP_MSHUTDOWN_FUNCTION(crypto);
212 PHP_MINFO_FUNCTION(crypto);
213 
214 
215 /* COMPATIBILITY */
216 
217 #define PHP_CRYPTO_COPY_ERROR_MESSAGE \
218 	(PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 5 && PHP_RELEASE_VERSION >= 5) \
219 	|| (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 6) \
220 	|| (PHP_MAJOR_VERSION > 5)
221 
222 #if PHP_CRYPTO_COPY_ERROR_MESSAGE
223 #define PHP_CRYPTO_GET_ERROR_MESSAGE(const_msg, tmp_msg) \
224 	(const_msg)
225 #else
226 #define PHP_CRYPTO_GET_ERROR_MESSAGE(const_msg, tmp_msg) \
227 	(tmp_msg = estrdup(const_msg))
228 #endif
229 
230 /* OpenSSL features test */
231 #if OPENSSL_VERSION_NUMBER >= 0x10001000L
232 #define PHP_CRYPTO_HAS_CMAC 1
233 #endif
234 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
235 #define PHP_CRYPTO_HAS_CIPHER_CTX_COPY 1
236 #endif
237 
238 #define PHP_CRYPTO_ADD_CCM_ALGOS \
239 	!defined(OPENSSL_NO_AES) && defined(EVP_CIPH_CCM_MODE) \
240 		&& OPENSSL_VERSION_NUMBER < 0x100020000
241 
242 #endif	/* PHP_CRYPTO_H */
243 
244 /*
245  * Local variables:
246  * tab-width: 4
247  * c-basic-offset: 4
248  * End:
249  * vim600: noet sw=4 ts=4 fdm=marker
250  * vim<600: noet sw=4 ts=4
251  */
252