diff options
| author | kkadosh | 2018-05-29 19:34:16 +0000 |
|---|---|---|
| committer | jvoisin | 2018-05-29 19:34:16 +0000 |
| commit | 7832438b7abedf567ce6376f99949f419abcdff1 (patch) | |
| tree | 560e43918d1dc36ce4cf760a5b27aed0c563bc1c /src/sp_crypt.c | |
| parent | 9eebe8c67e03e3041d454ea28e93996f7a67740b (diff) | |
Support session encryption
Implement session encryption.
Diffstat (limited to 'src/sp_crypt.c')
| -rw-r--r-- | src/sp_crypt.c | 52 |
1 files changed, 34 insertions, 18 deletions
diff --git a/src/sp_crypt.c b/src/sp_crypt.c index 0c40f1f..55ae37b 100644 --- a/src/sp_crypt.c +++ b/src/sp_crypt.c | |||
| @@ -4,9 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) | 5 | ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) |
| 6 | 6 | ||
| 7 | static zend_long nonce_d = 0; | 7 | void generate_key(unsigned char *key) { |
| 8 | |||
| 9 | static void generate_key(unsigned char *key) { | ||
| 10 | PHP_SHA256_CTX ctx; | 8 | PHP_SHA256_CTX ctx; |
| 11 | const char *user_agent = getenv("HTTP_USER_AGENT"); | 9 | const char *user_agent = getenv("HTTP_USER_AGENT"); |
| 12 | const char *env_var = | 10 | const char *env_var = |
| @@ -50,14 +48,13 @@ int decrypt_zval(zval *pDest, bool simulation, zend_hash_key *hash_key) { | |||
| 50 | debase64 = php_base64_decode((unsigned char *)(Z_STRVAL_P(pDest)), | 48 | debase64 = php_base64_decode((unsigned char *)(Z_STRVAL_P(pDest)), |
| 51 | Z_STRLEN_P(pDest)); | 49 | Z_STRLEN_P(pDest)); |
| 52 | 50 | ||
| 53 | if (ZSTR_LEN(debase64) < | 51 | if (ZSTR_LEN(debase64) < crypto_secretbox_NONCEBYTES) { |
| 54 | crypto_secretbox_NONCEBYTES + crypto_secretbox_ZEROBYTES) { | ||
| 55 | if (true == simulation) { | 52 | if (true == simulation) { |
| 56 | sp_log_msg( | 53 | sp_log_msg( |
| 57 | "cookie_encryption", SP_LOG_SIMULATION, | 54 | "cookie_encryption", SP_LOG_SIMULATION, |
| 58 | "Buffer underflow tentative detected in cookie encryption handling " | 55 | "Buffer underflow tentative detected in cookie encryption handling " |
| 59 | "for %s. Using the cookie 'as it' instead of decrypting it.", | 56 | "for %s. Using the cookie 'as it' instead of decrypting it.", |
| 60 | ZSTR_VAL(hash_key->key)); | 57 | hash_key ? ZSTR_VAL(hash_key->key) : "the session"); |
| 61 | return ZEND_HASH_APPLY_KEEP; | 58 | return ZEND_HASH_APPLY_KEEP; |
| 62 | } else { | 59 | } else { |
| 63 | sp_log_msg( | 60 | sp_log_msg( |
| @@ -67,9 +64,26 @@ int decrypt_zval(zval *pDest, bool simulation, zend_hash_key *hash_key) { | |||
| 67 | } | 64 | } |
| 68 | } | 65 | } |
| 69 | 66 | ||
| 67 | |||
| 68 | if (ZSTR_LEN(debase64) + (size_t)crypto_secretbox_ZEROBYTES < ZSTR_LEN(debase64)) { | ||
| 69 | if (true == simulation) { | ||
| 70 | sp_log_msg( | ||
| 71 | "cookie_encryption", SP_LOG_SIMULATION, | ||
| 72 | "Integer overflow tentative detected in cookie encryption handling " | ||
| 73 | "for %s. Using the cookie 'as it' instead of decrypting it.", | ||
| 74 | hash_key ? ZSTR_VAL(hash_key->key) : "the session"); | ||
| 75 | return ZEND_HASH_APPLY_KEEP; | ||
| 76 | } else { | ||
| 77 | sp_log_msg( | ||
| 78 | "cookie_encryption", SP_LOG_DROP, | ||
| 79 | "Integer overflow tentative detected in cookie encryption handling."); | ||
| 80 | return ZEND_HASH_APPLY_REMOVE; | ||
| 81 | } | ||
| 82 | } | ||
| 83 | |||
| 70 | generate_key(key); | 84 | generate_key(key); |
| 71 | 85 | ||
| 72 | decrypted = ecalloc(ZSTR_LEN(debase64), 1); | 86 | decrypted = ecalloc(ZSTR_LEN(debase64) + crypto_secretbox_ZEROBYTES, 1); |
| 73 | 87 | ||
| 74 | ret = crypto_secretbox_open( | 88 | ret = crypto_secretbox_open( |
| 75 | decrypted, | 89 | decrypted, |
| @@ -83,12 +97,12 @@ int decrypt_zval(zval *pDest, bool simulation, zend_hash_key *hash_key) { | |||
| 83 | "cookie_encryption", SP_LOG_SIMULATION, | 97 | "cookie_encryption", SP_LOG_SIMULATION, |
| 84 | "Something went wrong with the decryption of %s. Using the cookie " | 98 | "Something went wrong with the decryption of %s. Using the cookie " |
| 85 | "'as it' instead of decrypting it", | 99 | "'as it' instead of decrypting it", |
| 86 | ZSTR_VAL(hash_key->key)); | 100 | hash_key ? ZSTR_VAL(hash_key->key) : "the session"); |
| 87 | return ZEND_HASH_APPLY_KEEP; | 101 | return ZEND_HASH_APPLY_KEEP; |
| 88 | } else { | 102 | } else { |
| 89 | sp_log_msg("cookie_encryption", SP_LOG_DROP, | 103 | sp_log_msg("cookie_encryption", SP_LOG_DROP, |
| 90 | "Something went wrong with the decryption of %s.", | 104 | "Something went wrong with the decryption of %s.", |
| 91 | ZSTR_VAL(hash_key->key)); | 105 | hash_key ? ZSTR_VAL(hash_key->key) : "the session"); |
| 92 | return ZEND_HASH_APPLY_REMOVE; | 106 | return ZEND_HASH_APPLY_REMOVE; |
| 93 | } | 107 | } |
| 94 | } | 108 | } |
| @@ -100,8 +114,14 @@ int decrypt_zval(zval *pDest, bool simulation, zend_hash_key *hash_key) { | |||
| 100 | return ZEND_HASH_APPLY_KEEP; | 114 | return ZEND_HASH_APPLY_KEEP; |
| 101 | } | 115 | } |
| 102 | 116 | ||
| 117 | /* | ||
| 118 | ** This function will return the `data` of length `data_len` encrypted in the | ||
| 119 | ** form `base64(nonce | encrypted_data)` (with `|` being the concatenation | ||
| 120 | ** operation). | ||
| 121 | */ | ||
| 103 | zend_string *encrypt_zval(char *data, unsigned long long data_len) { | 122 | zend_string *encrypt_zval(char *data, unsigned long long data_len) { |
| 104 | const size_t encrypted_msg_len = crypto_secretbox_ZEROBYTES + data_len + 1; | 123 | const size_t encrypted_msg_len = crypto_secretbox_ZEROBYTES + data_len + 1; |
| 124 | // FIXME : We know that this len is too long | ||
| 105 | const size_t emsg_and_nonce_len = | 125 | const size_t emsg_and_nonce_len = |
| 106 | encrypted_msg_len + crypto_secretbox_NONCEBYTES; | 126 | encrypted_msg_len + crypto_secretbox_NONCEBYTES; |
| 107 | 127 | ||
| @@ -112,25 +132,21 @@ zend_string *encrypt_zval(char *data, unsigned long long data_len) { | |||
| 112 | 132 | ||
| 113 | generate_key(key); | 133 | generate_key(key); |
| 114 | 134 | ||
| 135 | // Put random bytes in the nonce | ||
| 136 | php_random_bytes(nonce, sizeof(nonce), 0); | ||
| 137 | |||
| 115 | /* tweetnacl's API requires the message to be padded with | 138 | /* tweetnacl's API requires the message to be padded with |
| 116 | crypto_secretbox_ZEROBYTES zeroes. */ | 139 | crypto_secretbox_ZEROBYTES zeroes. */ |
| 117 | memcpy(data_to_encrypt + crypto_secretbox_ZEROBYTES, data, data_len); | 140 | memcpy(data_to_encrypt + crypto_secretbox_ZEROBYTES, data, data_len); |
| 118 | 141 | ||
| 119 | assert(sizeof(zend_long) <= crypto_secretbox_NONCEBYTES); | 142 | assert(sizeof(zend_long) <= crypto_secretbox_NONCEBYTES); |
| 120 | 143 | ||
| 121 | if (0 == nonce_d) { | ||
| 122 | /* A zend_long should be enough to avoid collisions */ | ||
| 123 | if (php_random_int_throw(0, ZEND_LONG_MAX, &nonce_d) == FAILURE) { | ||
| 124 | return NULL; // LCOV_EXCL_LINE | ||
| 125 | } | ||
| 126 | } | ||
| 127 | nonce_d++; | ||
| 128 | sscanf((char *)nonce, "%ld", &nonce_d); | ||
| 129 | |||
| 130 | memcpy(encrypted_data, nonce, crypto_secretbox_NONCEBYTES); | 144 | memcpy(encrypted_data, nonce, crypto_secretbox_NONCEBYTES); |
| 145 | |||
| 131 | crypto_secretbox(encrypted_data + crypto_secretbox_NONCEBYTES, | 146 | crypto_secretbox(encrypted_data + crypto_secretbox_NONCEBYTES, |
| 132 | data_to_encrypt, encrypted_msg_len, nonce, key); | 147 | data_to_encrypt, encrypted_msg_len, nonce, key); |
| 133 | 148 | ||
| 134 | zend_string *z = php_base64_encode(encrypted_data, emsg_and_nonce_len); | 149 | zend_string *z = php_base64_encode(encrypted_data, emsg_and_nonce_len); |
| 150 | |||
| 135 | return z; | 151 | return z; |
| 136 | } \ No newline at end of file | 152 | } \ No newline at end of file |
