summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/sodium/libsodium.c245
-rw-r--r--ext/sodium/php_libsodium.h7
-rw-r--r--ext/sodium/tests/crypto_kx.phpt47
3 files changed, 234 insertions, 65 deletions
diff --git a/ext/sodium/libsodium.c b/ext/sodium/libsodium.c
index 34bf7d4a2e..a176485a8c 100644
--- a/ext/sodium/libsodium.c
+++ b/ext/sodium/libsodium.c
@@ -159,6 +159,16 @@ ZEND_BEGIN_ARG_INFO_EX(AI_MaybeKeyAndLength, 0, 0, 0)
ZEND_ARG_INFO(0, length)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(AI_KXClientSession, 0, 0, 2)
+ ZEND_ARG_INFO(0, client_keypair)
+ ZEND_ARG_INFO(0, server_key)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(AI_KXServerSession, 0, 0, 2)
+ ZEND_ARG_INFO(0, server_keypair)
+ ZEND_ARG_INFO(0, client_key)
+ZEND_END_ARG_INFO()
+
#if defined(HAVE_CRYPTO_AEAD_AES256GCM) && defined(crypto_aead_aes256gcm_KEYBYTES) && \
(defined(__amd64) || defined(__amd64__) || defined(__x86_64__) || defined(__i386__) || \
defined(_M_AMD64) || defined(_M_IX86))
@@ -195,7 +205,12 @@ const zend_function_entry sodium_functions[] = {
PHP_FE(sodium_crypto_box_seal_open, AI_StringAndKey)
#endif
PHP_FE(sodium_crypto_box_secretkey, AI_Key)
- PHP_FE(sodium_crypto_kx, AI_FourStrings)
+ PHP_FE(sodium_crypto_kx_keypair, AI_None)
+ PHP_FE(sodium_crypto_kx_publickey, AI_Key)
+ PHP_FE(sodium_crypto_kx_secretkey, AI_Key)
+ PHP_FE(sodium_crypto_kx_seed_keypair, AI_String)
+ PHP_FE(sodium_crypto_kx_client_session_keys, AI_KXClientSession)
+ PHP_FE(sodium_crypto_kx_server_session_keys, AI_KXServerSession)
PHP_FE(sodium_crypto_generichash, AI_StringAndMaybeKeyAndLength)
PHP_FE(sodium_crypto_generichash_init, AI_MaybeKeyAndLength)
PHP_FE(sodium_crypto_generichash_update, AI_StateByReferenceAndString)
@@ -368,12 +383,23 @@ PHP_MINIT_FUNCTION(sodium)
crypto_box_NONCEBYTES, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_BOX_SEEDBYTES",
crypto_box_SEEDBYTES, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_KX_BYTES",
- crypto_kx_BYTES, CONST_CS | CONST_PERSISTENT);
+#ifndef crypto_kx_SEEDBYTES
+# define crypto_kx_SEEDBYTES 32
+# define crypto_kx_SESSIONKEYBYTES 32
+# define crypto_kx_PUBLICKEYBYTES 32
+# define crypto_kx_SECRETKEYBYTES 32
+#endif
+ REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_KX_SEEDBYTES",
+ crypto_kx_SEEDBYTES, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_KX_SESSIONKEYBYTES",
+ crypto_kx_SESSIONKEYBYTES, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_KX_PUBLICKEYBYTES",
crypto_kx_PUBLICKEYBYTES, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_KX_SECRETKEYBYTES",
crypto_kx_SECRETKEYBYTES, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_KX_KEYPAIRBYTES",
+ crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES,
+ CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_GENERICHASH_BYTES",
crypto_generichash_BYTES, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_GENERICHASH_BYTES_MIN",
@@ -2480,56 +2506,197 @@ PHP_FUNCTION(sodium_crypto_scalarmult)
RETURN_STR(q);
}
-PHP_FUNCTION(sodium_crypto_kx)
+PHP_FUNCTION(sodium_crypto_kx_seed_keypair)
+{
+ unsigned char *sk;
+ unsigned char *pk;
+ unsigned char *seed;
+ size_t seed_len;
+ zend_string *keypair;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
+ &seed, &seed_len) == FAILURE) {
+ return;
+ }
+ if (seed_len != crypto_kx_SEEDBYTES) {
+ zend_throw_exception(sodium_exception_ce, "seed must be CRYPTO_KX_SEEDBYTES bytes", 0);
+ return;
+ }
+ (void) sizeof(int[crypto_scalarmult_SCALARBYTES == crypto_kx_PUBLICKEYBYTES ? 1 : -1]);
+ (void) sizeof(int[crypto_scalarmult_SCALARBYTES == crypto_kx_SECRETKEYBYTES ? 1 : -1]);
+ keypair = zend_string_alloc(crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES, 0);
+ sk = (unsigned char *) ZSTR_VAL(keypair);
+ pk = sk + crypto_kx_SECRETKEYBYTES;
+ crypto_generichash(sk, crypto_kx_SECRETKEYBYTES,
+ seed, crypto_kx_SEEDBYTES, NULL, 0);
+ if (crypto_scalarmult_base(pk, sk) != 0) {
+ zend_throw_exception(sodium_exception_ce, "internal error", 0);
+ return;
+ }
+ ZSTR_VAL(keypair)[crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES] = 0;
+ RETURN_STR(keypair);
+}
+
+PHP_FUNCTION(sodium_crypto_kx_keypair)
+{
+ unsigned char *sk;
+ unsigned char *pk;
+ zend_string *keypair;
+
+ keypair = zend_string_alloc(crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES, 0);
+ sk = (unsigned char *) ZSTR_VAL(keypair);
+ pk = sk + crypto_kx_SECRETKEYBYTES;
+ randombytes_buf(sk, crypto_kx_SECRETKEYBYTES);
+ if (crypto_scalarmult_base(pk, sk) != 0) {
+ zend_throw_exception(sodium_exception_ce, "internal error", 0);
+ return;
+ }
+ RETURN_STR(keypair);
+}
+
+PHP_FUNCTION(sodium_crypto_kx_secretkey)
+{
+ zend_string *secretkey;
+ unsigned char *keypair;
+ size_t keypair_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
+ &keypair, &keypair_len) == FAILURE) {
+ return;
+ }
+ if (keypair_len !=
+ crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES) {
+ zend_throw_exception(sodium_exception_ce,
+ "keypair should be CRYPTO_KX_KEYPAIRBYTES bytes",
+ 0);
+ return;
+ }
+ secretkey = zend_string_alloc(crypto_kx_SECRETKEYBYTES, 0);
+ memcpy(ZSTR_VAL(secretkey), keypair, crypto_kx_SECRETKEYBYTES);
+ ZSTR_VAL(secretkey)[crypto_kx_SECRETKEYBYTES] = 0;
+
+ RETURN_STR(secretkey);
+}
+
+PHP_FUNCTION(sodium_crypto_kx_publickey)
+{
+ zend_string *publickey;
+ unsigned char *keypair;
+ size_t keypair_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
+ &keypair, &keypair_len) == FAILURE) {
+ return;
+ }
+ if (keypair_len !=
+ crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES) {
+ zend_throw_exception(sodium_exception_ce,
+ "keypair should be CRYPTO_KX_KEYPAIRBYTES bytes",
+ 0);
+ return;
+ }
+ publickey = zend_string_alloc(crypto_kx_PUBLICKEYBYTES, 0);
+ memcpy(ZSTR_VAL(publickey), keypair + crypto_kx_SECRETKEYBYTES,
+ crypto_kx_PUBLICKEYBYTES);
+ ZSTR_VAL(publickey)[crypto_kx_PUBLICKEYBYTES] = 0;
+
+ RETURN_STR(publickey);
+}
+
+PHP_FUNCTION(sodium_crypto_kx_client_session_keys)
{
crypto_generichash_state h;
- unsigned char q[crypto_scalarmult_BYTES];
- zend_string *sharedkey;
- unsigned char *client_publickey;
- unsigned char *publickey;
- unsigned char *secretkey;
- unsigned char *server_publickey;
- size_t client_publickey_len;
- size_t publickey_len;
- size_t secretkey_len;
- size_t server_publickey_len;
+ unsigned char q[crypto_scalarmult_BYTES];
+ unsigned char *keypair;
+ unsigned char *client_sk;
+ unsigned char *client_pk;
+ unsigned char *server_pk;
+ unsigned char session_keys[2 * crypto_kx_SESSIONKEYBYTES];
+ size_t keypair_len;
+ size_t server_pk_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssss",
- &secretkey, &secretkey_len,
- &publickey, &publickey_len,
- &client_publickey, &client_publickey_len,
- &server_publickey, &server_publickey_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
+ &keypair, &keypair_len,
+ &server_pk, &server_pk_len) == FAILURE) {
return;
}
- if (secretkey_len != crypto_kx_SECRETKEYBYTES) {
- zend_throw_exception(sodium_exception_ce, "crypto_kx(): secret key must be CRYPTO_KX_SECRETKEY bytes", 0);
+ if (keypair_len != crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES) {
+ zend_throw_exception(sodium_exception_ce, "keypair must be CRYPTO_KX_KEYPAIRBYTES bytes", 0);
return;
}
- if (publickey_len != crypto_kx_PUBLICKEYBYTES ||
- client_publickey_len != crypto_kx_PUBLICKEYBYTES ||
- server_publickey_len != crypto_kx_PUBLICKEYBYTES) {
- zend_throw_exception(sodium_exception_ce, "crypto_kx(): public keys must be CRYPTO_KX_PUBLICKEY bytes", 0);
+ if (server_pk_len != crypto_kx_PUBLICKEYBYTES) {
+ zend_throw_exception(sodium_exception_ce, "public keys must be CRYPTO_KX_PUBLICKEYBYTES bytes", 0);
return;
}
- (void) sizeof(int[crypto_scalarmult_SCALARBYTES ==
- crypto_kx_PUBLICKEYBYTES ? 1 : -1]);
- (void) sizeof(int[crypto_scalarmult_SCALARBYTES ==
- crypto_kx_SECRETKEYBYTES ? 1 : -1]);
- if (crypto_scalarmult(q, secretkey, publickey) != 0) {
- zend_throw_exception(sodium_exception_ce, "crypto_kx(): internal error", 0);
+ client_sk = &keypair[0];
+ client_pk = &keypair[crypto_kx_SECRETKEYBYTES];
+ (void) sizeof(int[crypto_scalarmult_SCALARBYTES == crypto_kx_PUBLICKEYBYTES ? 1 : -1]);
+ (void) sizeof(int[crypto_scalarmult_SCALARBYTES == crypto_kx_SECRETKEYBYTES ? 1 : -1]);
+ if (crypto_scalarmult(q, client_sk, server_pk) != 0) {
+ zend_throw_exception(sodium_exception_ce, "internal error", 0);
return;
}
- sharedkey = zend_string_alloc(crypto_kx_BYTES, 0);
- crypto_generichash_init(&h, NULL, 0U, crypto_generichash_BYTES);
+ crypto_generichash_init(&h, NULL, 0U, 2 * crypto_kx_SESSIONKEYBYTES);
crypto_generichash_update(&h, q, sizeof q);
sodium_memzero(q, sizeof q);
- crypto_generichash_update(&h, client_publickey, client_publickey_len);
- crypto_generichash_update(&h, server_publickey, server_publickey_len);
- crypto_generichash_final(&h, (unsigned char *) ZSTR_VAL(sharedkey),
- crypto_kx_BYTES);
- ZSTR_VAL(sharedkey)[crypto_kx_BYTES] = 0;
+ crypto_generichash_update(&h, client_pk, crypto_kx_PUBLICKEYBYTES);
+ crypto_generichash_update(&h, server_pk, crypto_kx_PUBLICKEYBYTES);
+ crypto_generichash_final(&h, session_keys, 2 * crypto_kx_SESSIONKEYBYTES);
+ array_init(return_value);
+ add_next_index_stringl(return_value,
+ (const char *) session_keys,
+ crypto_kx_SESSIONKEYBYTES);
+ add_next_index_stringl(return_value,
+ (const char *) session_keys + crypto_kx_SESSIONKEYBYTES,
+ crypto_kx_SESSIONKEYBYTES);
+}
- RETURN_STR(sharedkey);
+PHP_FUNCTION(sodium_crypto_kx_server_session_keys)
+{
+ crypto_generichash_state h;
+ unsigned char q[crypto_scalarmult_BYTES];
+ unsigned char *keypair;
+ unsigned char *server_sk;
+ unsigned char *server_pk;
+ unsigned char *client_pk;
+ unsigned char session_keys[2 * crypto_kx_SESSIONKEYBYTES];
+ size_t keypair_len;
+ size_t client_pk_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
+ &keypair, &keypair_len,
+ &client_pk, &client_pk_len) == FAILURE) {
+ return;
+ }
+ if (keypair_len != crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES) {
+ zend_throw_exception(sodium_exception_ce, "keypair must be CRYPTO_KX_KEYPAIRBYTES bytes", 0);
+ return;
+ }
+ if (client_pk_len != crypto_kx_PUBLICKEYBYTES) {
+ zend_throw_exception(sodium_exception_ce, "public keys must be CRYPTO_KX_PUBLICKEYBYTES bytes", 0);
+ return;
+ }
+ server_sk = &keypair[0];
+ server_pk = &keypair[crypto_kx_SECRETKEYBYTES];
+ (void) sizeof(int[crypto_scalarmult_SCALARBYTES == crypto_kx_PUBLICKEYBYTES ? 1 : -1]);
+ (void) sizeof(int[crypto_scalarmult_SCALARBYTES == crypto_kx_SECRETKEYBYTES ? 1 : -1]);
+ if (crypto_scalarmult(q, server_sk, client_pk) != 0) {
+ zend_throw_exception(sodium_exception_ce, "internal error", 0);
+ return;
+ }
+ crypto_generichash_init(&h, NULL, 0U, 2 * crypto_kx_SESSIONKEYBYTES);
+ crypto_generichash_update(&h, q, sizeof q);
+ sodium_memzero(q, sizeof q);
+ crypto_generichash_update(&h, client_pk, crypto_kx_PUBLICKEYBYTES);
+ crypto_generichash_update(&h, server_pk, crypto_kx_PUBLICKEYBYTES);
+ crypto_generichash_final(&h, session_keys, 2 * crypto_kx_SESSIONKEYBYTES);
+ array_init(return_value);
+ add_next_index_stringl(return_value,
+ (const char *) session_keys + crypto_kx_SESSIONKEYBYTES,
+ crypto_kx_SESSIONKEYBYTES);
+ add_next_index_stringl(return_value,
+ (const char *) session_keys,
+ crypto_kx_SESSIONKEYBYTES);
}
PHP_FUNCTION(sodium_crypto_auth)
diff --git a/ext/sodium/php_libsodium.h b/ext/sodium/php_libsodium.h
index 93d92e3e03..6e6e3fbe2d 100644
--- a/ext/sodium/php_libsodium.h
+++ b/ext/sodium/php_libsodium.h
@@ -59,7 +59,12 @@ PHP_FUNCTION(sodium_crypto_generichash);
PHP_FUNCTION(sodium_crypto_generichash_final);
PHP_FUNCTION(sodium_crypto_generichash_init);
PHP_FUNCTION(sodium_crypto_generichash_update);
-PHP_FUNCTION(sodium_crypto_kx);
+PHP_FUNCTION(sodium_crypto_kx_client_session_keys);
+PHP_FUNCTION(sodium_crypto_kx_keypair);
+PHP_FUNCTION(sodium_crypto_kx_publickey);
+PHP_FUNCTION(sodium_crypto_kx_secretkey);
+PHP_FUNCTION(sodium_crypto_kx_seed_keypair);
+PHP_FUNCTION(sodium_crypto_kx_server_session_keys);
PHP_FUNCTION(sodium_crypto_pwhash);
PHP_FUNCTION(sodium_crypto_pwhash_str);
PHP_FUNCTION(sodium_crypto_pwhash_str_verify);
diff --git a/ext/sodium/tests/crypto_kx.phpt b/ext/sodium/tests/crypto_kx.phpt
index ef8c5f7a63..a1dd00a0a7 100644
--- a/ext/sodium/tests/crypto_kx.phpt
+++ b/ext/sodium/tests/crypto_kx.phpt
@@ -4,34 +4,31 @@ Check for libsodium-based key exchange
<?php if (!extension_loaded("sodium")) print "skip"; ?>
--FILE--
<?php
-$client_secretkey = sodium_hex2bin("8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a");
-$client_publickey = sodium_crypto_box_publickey_from_secretkey($client_secretkey);
+$client_seed = sodium_hex2bin('0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef');
+$client_keypair = sodium_crypto_kx_seed_keypair($client_seed);
+$server_seed = sodium_hex2bin('f123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde0');
+$server_keypair = sodium_crypto_kx_seed_keypair($server_seed);
-$server_secretkey = sodium_hex2bin("948f00e90a246fb5909f8648c2ac6f21515771235523266439e0d775ba0c3671");
-$server_publickey = sodium_crypto_box_publickey_from_secretkey($server_secretkey);
+var_dump(sodium_bin2hex($client_keypair));
+var_dump(sodium_bin2hex($server_keypair));
-$shared_key_computed_by_client =
- sodium_crypto_kx($client_secretkey, $server_publickey,
- $client_publickey, $server_publickey);
+$client_session_keys =
+ sodium_crypto_kx_client_session_keys($client_keypair,
+ sodium_crypto_kx_publickey($server_keypair));
-$shared_key_computed_by_server =
- sodium_crypto_kx($server_secretkey, $client_publickey,
- $client_publickey, $server_publickey);
+$server_session_keys =
+ sodium_crypto_kx_server_session_keys($server_keypair,
+ sodium_crypto_kx_publickey($client_keypair));
-var_dump(sodium_bin2hex($shared_key_computed_by_client));
-var_dump(sodium_bin2hex($shared_key_computed_by_server));
-try {
- sodium_crypto_kx(
- substr($client_secretkey, 1),
- $server_publickey,
- $client_publickey,
- $server_publickey
- );
-} catch (SodiumException $ex) {
- var_dump(true);
-}
+var_dump(sodium_bin2hex($client_session_keys[0]));
+var_dump(sodium_bin2hex($server_session_keys[1]));
+var_dump(sodium_bin2hex($client_session_keys[1]));
+var_dump(sodium_bin2hex($server_session_keys[0]));
?>
--EXPECT--
-string(64) "509a1580c2ee30c565317e29e0fea0b1c232e0ef3a7871d91dc64814b19a3bd2"
-string(64) "509a1580c2ee30c565317e29e0fea0b1c232e0ef3a7871d91dc64814b19a3bd2"
-bool(true)
+string(128) "b85c84f9828524519d32b97cd3dda961fdba2dbf407ae4601e2129229aa463c224eaf70f070a925d6d5176f20495d4d90867624d9a10379e2a9aef0955c9bf4e"
+string(128) "016e814c32b8b66225a403db45bf50fdd1966fb802c3115bf8aa90738c6a02de420ccdb534930fed9aaff12188bedc76e66251f399c404f2e4a15678fd4a484a"
+string(64) "99a430e61d718b71979ebcea6735c4648bc828cfb456890aeda4b628b77d5ac7"
+string(64) "99a430e61d718b71979ebcea6735c4648bc828cfb456890aeda4b628b77d5ac7"
+string(64) "876bef865a5ab3f4ae569ea5aaefe5014c3ec22a558c0a2f0274aa9985bd328d"
+string(64) "876bef865a5ab3f4ae569ea5aaefe5014c3ec22a558c0a2f0274aa9985bd328d"