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_CIPHER_H
20 #define PHP_CRYPTO_CIPHER_H
21 
22 #include "php.h"
23 #include "php_crypto.h"
24 
25 #include <openssl/evp.h>
26 
27 
28 typedef enum {
29 	PHP_CRYPTO_CIPHER_STATUS_CLEAR,
30 	PHP_CRYPTO_CIPHER_STATUS_ENCRYPT_INIT,
31 	PHP_CRYPTO_CIPHER_STATUS_ENCRYPT_UPDATE,
32 	PHP_CRYPTO_CIPHER_STATUS_ENCRYPT_FINAL,
33 	PHP_CRYPTO_CIPHER_STATUS_DECRYPT_INIT,
34 	PHP_CRYPTO_CIPHER_STATUS_DECRYPT_UPDATE,
35 	PHP_CRYPTO_CIPHER_STATUS_DECRYPT_FINAL
36 } php_crypto_cipher_status;
37 
38 PHPC_OBJ_STRUCT_BEGIN(crypto_cipher)
39 	php_crypto_cipher_status status;
40 	const EVP_CIPHER *alg;
41 	EVP_CIPHER_CTX *cipher;
42 	unsigned char *aad;
43 	int aad_len;
44 	unsigned char *tag;
45 	int tag_len;
46 PHPC_OBJ_STRUCT_END()
47 
48 /* Cipher status accessors */
49 #define PHP_CRYPTO_CIPHER_IS_IN_INIT_STATE(pobj) \
50 	((pobj)->status == PHP_CRYPTO_CIPHER_STATUS_ENCRYPT_INIT || \
51 	(pobj)->status == PHP_CRYPTO_CIPHER_STATUS_DECRYPT_INIT)
52 #define PHP_CRYPTO_CIPHER_IS_INITIALIZED_FOR_ENCRYPTION(pobj) \
53 	((pobj)->status == PHP_CRYPTO_CIPHER_STATUS_ENCRYPT_INIT || \
54 	(pobj)->status == PHP_CRYPTO_CIPHER_STATUS_ENCRYPT_UPDATE)
55 #define PHP_CRYPTO_CIPHER_IS_INITIALIZED_FOR_DECRYPTION(pobj) \
56 	((pobj)->status == PHP_CRYPTO_CIPHER_STATUS_DECRYPT_INIT || \
57 	(pobj)->status == PHP_CRYPTO_CIPHER_STATUS_DECRYPT_UPDATE)
58 #define PHP_CRYPTO_CIPHER_SET_STATUS(pobj, is_enc, status_name) \
59 	(pobj)->status = ((is_enc) ? \
60 		PHP_CRYPTO_CIPHER_STATUS_ENCRYPT_ ## status_name : \
61 		PHP_CRYPTO_CIPHER_STATUS_DECRYPT_ ## status_name)
62 
63 /* Algorithm object accessors */
64 #define PHP_CRYPTO_CIPHER_CTX(pobj)     (pobj)->cipher
65 #define PHP_CRYPTO_CIPHER_ALG(pobj)     (pobj)->alg
66 #define PHP_CRYPTO_CIPHER_AAD(pobj)     (pobj)->aad
67 #define PHP_CRYPTO_CIPHER_AAD_LEN(pobj) (pobj)->aad_len
68 #define PHP_CRYPTO_CIPHER_TAG(pobj)     (pobj)->tag
69 #define PHP_CRYPTO_CIPHER_TAG_LEN(pobj) (pobj)->tag_len
70 
71 /* Exception */
72 PHP_CRYPTO_EXCEPTION_EXPORT(Cipher)
73 /* Error info */
74 PHP_CRYPTO_ERROR_INFO_EXPORT(Cipher)
75 
76 /* Maximal algorithm length of the cipher algorithm name */
77 #define PHP_CRYPTO_CIPHER_ALGORITHM_LEN_MAX 1024
78 
79 /* Mode string length */
80 #define PHP_CRYPTO_CIPHER_MODE_LEN 3
81 
82 /* Cipher mode lookup table entry struct */
83 typedef struct {
84 	const char name[PHP_CRYPTO_CIPHER_MODE_LEN+1];
85 	const char constant[PHP_CRYPTO_CIPHER_MODE_LEN+6];
86 	long value;
87 	zend_bool auth_enc; /* authenticated encryption */
88 	zend_bool auth_inlen_init;
89 	int auth_ivlen_flag;
90 	int auth_set_tag_flag;
91 	int auth_get_tag_flag;
92 } php_crypto_cipher_mode;
93 
94 /* Constant value for cipher mode that is not implemented
95  * (when using old version of OpenSSL) */
96 #define PHP_CRYPTO_CIPHER_MODE_NOT_DEFINED -1
97 
98 /* Cipher mode value (EVP code) */
99 #define PHP_CRYPTO_CIPHER_MODE_VALUE(pobj) \
100 	EVP_CIPHER_mode(PHP_CRYPTO_CIPHER_ALG(pobj))
101 
102 /* Macros for cipher mode lookup table */
103 #define PHP_CRYPTO_CIPHER_MODE_ENTRY_EX( \
104 	mode_name, \
105 	mode_auth_enc, \
106 	mode_auth_inlen_init, \
107 	mode_auth_ivlen_flag, \
108 	mode_auth_stag_flag, \
109 	mode_auth_gtag_flag) \
110 	{ \
111 		#mode_name, \
112 		"MODE_" #mode_name, \
113 		EVP_CIPH_ ## mode_name ## _MODE, \
114 		mode_auth_enc, \
115 		mode_auth_inlen_init, \
116 		mode_auth_ivlen_flag, \
117 		mode_auth_stag_flag, \
118 		mode_auth_gtag_flag \
119 	},
120 #define PHP_CRYPTO_CIPHER_MODE_ENTRY(mode_name) \
121 	PHP_CRYPTO_CIPHER_MODE_ENTRY_EX(mode_name, 0, 0, 0, 0, 0)
122 #define PHP_CRYPTO_CIPHER_MODE_ENTRY_NOT_DEFINED(mode_name) \
123 	{ \
124 		#mode_name, \
125 		"MODE_" \
126 		#mode_name, \
127 		PHP_CRYPTO_CIPHER_MODE_NOT_DEFINED, \
128 		0, 0, 0, 0, 0 \
129 	},
130 #define PHP_CRYPTO_CIPHER_MODE_ENTRY_END \
131 	{ "", "", 0, 0, 0, 0, 0, 0 }
132 
133 /* Cipher authentication tag length max, min and default */
134 #define PHP_CRYPTO_CIPHER_AUTH_TAG_LENGTH_MIN      4
135 #define PHP_CRYPTO_CIPHER_AUTH_TAG_LENGTH_MAX     16
136 #define PHP_CRYPTO_CIPHER_AUTH_TAG_LENGTH_DEFAULT 16
137 
138 
139 /* CLASSES */
140 
141 /* Class entry */
142 extern PHP_CRYPTO_API zend_class_entry *php_crypto_cipher_ce;
143 
144 
145 /* USER METHODS */
146 
147 /* Module init for Crypto Cipher */
148 PHP_MINIT_FUNCTION(crypto_cipher);
149 
150 /* Methods */
151 PHP_CRYPTO_METHOD(Cipher, getAlgorithms);
152 PHP_CRYPTO_METHOD(Cipher, hasAlgorithm);
153 PHP_CRYPTO_METHOD(Cipher, hasMode);
154 PHP_CRYPTO_METHOD(Cipher, __callStatic);
155 PHP_CRYPTO_METHOD(Cipher, __construct);
156 PHP_CRYPTO_METHOD(Cipher, getAlgorithmName);
157 PHP_CRYPTO_METHOD(Cipher, encryptInit);
158 PHP_CRYPTO_METHOD(Cipher, encryptUpdate);
159 PHP_CRYPTO_METHOD(Cipher, encryptFinish);
160 PHP_CRYPTO_METHOD(Cipher, encrypt);
161 PHP_CRYPTO_METHOD(Cipher, decryptInit);
162 PHP_CRYPTO_METHOD(Cipher, decryptUpdate);
163 PHP_CRYPTO_METHOD(Cipher, decryptFinish);
164 PHP_CRYPTO_METHOD(Cipher, decrypt);
165 PHP_CRYPTO_METHOD(Cipher, getBlockSize);
166 PHP_CRYPTO_METHOD(Cipher, getKeyLength);
167 PHP_CRYPTO_METHOD(Cipher, getIVLength);
168 PHP_CRYPTO_METHOD(Cipher, getMode);
169 PHP_CRYPTO_METHOD(Cipher, getTag);
170 PHP_CRYPTO_METHOD(Cipher, setTag);
171 PHP_CRYPTO_METHOD(Cipher, setTagLength);
172 PHP_CRYPTO_METHOD(Cipher, getAAD);
173 PHP_CRYPTO_METHOD(Cipher, setAAD);
174 
175 /* API FUNCTIONS */
176 PHP_CRYPTO_API const EVP_CIPHER *php_crypto_get_cipher_algorithm(
177 		char *algorithm,
178 		phpc_str_size_t algorithm_len);
179 
180 PHP_CRYPTO_API const EVP_CIPHER *php_crypto_get_cipher_algorithm_from_params(
181 		char *algorithm,
182 		phpc_str_size_t algorithm_len,
183 		zval *pz_mode,
184 		zval *pz_key_size TSRMLS_DC);
185 
186 PHP_CRYPTO_API const php_crypto_cipher_mode *php_crypto_get_cipher_mode_ex(
187 		long mode_value);
188 
189 PHP_CRYPTO_API const php_crypto_cipher_mode *php_crypto_get_cipher_mode(
190 		const EVP_CIPHER *cipher);
191 
192 PHP_CRYPTO_API int php_crypto_cipher_set_tag(
193 		EVP_CIPHER_CTX *cipher_ctx,
194 		const php_crypto_cipher_mode *mode,
195 		unsigned char *tag,
196 		int tag_len TSRMLS_DC);
197 
198 PHP_CRYPTO_API int php_crypto_cipher_write_aad(
199 		EVP_CIPHER_CTX *cipher_ctx,
200 		unsigned char *aad,
201 		int aad_len TSRMLS_DC);
202 
203 
204 #endif	/* PHP_CRYPTO_CIPHER_H */
205 
206 /*
207  * Local variables:
208  * tab-width: 4
209  * c-basic-offset: 4
210  * End:
211  * vim600: noet sw=4 ts=4 fdm=marker
212  * vim<600: noet sw=4 ts=4
213  */
214