-
Notifications
You must be signed in to change notification settings - Fork 8.1k
ext/sodium: Add crypto_kem (X-Wing) and crypto_kem_mlkem768 bindings #23420
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
46748b5
724c76c
a62cfd7
ef1f78b
8743476
83d9421
4e5c949
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4830,3 +4830,311 @@ PHP_FUNCTION(sodium_crypto_xof_turboshake256_squeeze) | |
| RETURN_NEW_STR(out); | ||
| } | ||
| #endif | ||
|
|
||
| #ifdef crypto_kem_PUBLICKEYBYTES | ||
| PHP_FUNCTION(sodium_crypto_kem_keypair) | ||
| { | ||
| zend_string *keypair; | ||
| size_t keypair_len; | ||
|
|
||
| ZEND_PARSE_PARAMETERS_NONE(); | ||
|
|
||
| keypair_len = crypto_kem_SECRETKEYBYTES + crypto_kem_PUBLICKEYBYTES; | ||
| keypair = zend_string_alloc(keypair_len, 0); | ||
| if (crypto_kem_keypair((unsigned char *) ZSTR_VAL(keypair) + | ||
| crypto_kem_SECRETKEYBYTES, | ||
| (unsigned char *) ZSTR_VAL(keypair)) != 0) { | ||
| sodium_memzero(ZSTR_VAL(keypair), keypair_len); | ||
| zend_string_efree(keypair); | ||
| zend_throw_exception(sodium_exception_ce, "internal error", 0); | ||
| RETURN_THROWS(); | ||
| } | ||
| ZSTR_VAL(keypair)[keypair_len] = 0; | ||
|
|
||
| RETURN_NEW_STR(keypair); | ||
| } | ||
|
|
||
| PHP_FUNCTION(sodium_crypto_kem_seed_keypair) | ||
| { | ||
| zend_string *keypair; | ||
| unsigned char *seed; | ||
| size_t keypair_len; | ||
| size_t seed_len; | ||
|
|
||
| if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", | ||
| &seed, &seed_len) == FAILURE) { | ||
| sodium_remove_param_values_from_backtrace(EG(exception)); | ||
| RETURN_THROWS(); | ||
| } | ||
| if (seed_len != crypto_kem_SEEDBYTES) { | ||
| zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_KEM_SEEDBYTES bytes long"); | ||
| RETURN_THROWS(); | ||
| } | ||
| keypair_len = crypto_kem_SECRETKEYBYTES + crypto_kem_PUBLICKEYBYTES; | ||
| keypair = zend_string_alloc(keypair_len, 0); | ||
| if (crypto_kem_seed_keypair((unsigned char *) ZSTR_VAL(keypair) + | ||
| crypto_kem_SECRETKEYBYTES, | ||
| (unsigned char *) ZSTR_VAL(keypair), | ||
| seed) != 0) { | ||
| sodium_memzero(ZSTR_VAL(keypair), keypair_len); | ||
| zend_string_efree(keypair); | ||
| zend_throw_exception(sodium_exception_ce, "internal error", 0); | ||
| RETURN_THROWS(); | ||
| } | ||
| ZSTR_VAL(keypair)[keypair_len] = 0; | ||
|
|
||
| RETURN_NEW_STR(keypair); | ||
| } | ||
|
|
||
| PHP_FUNCTION(sodium_crypto_kem_secretkey) | ||
| { | ||
| unsigned char *keypair; | ||
| size_t keypair_len; | ||
|
|
||
| if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", | ||
| &keypair, &keypair_len) == FAILURE) { | ||
| sodium_remove_param_values_from_backtrace(EG(exception)); | ||
| RETURN_THROWS(); | ||
| } | ||
| if (keypair_len != | ||
| crypto_kem_SECRETKEYBYTES + crypto_kem_PUBLICKEYBYTES) { | ||
| zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_KEM_KEYPAIRBYTES bytes long"); | ||
| RETURN_THROWS(); | ||
| } | ||
| RETURN_STRINGL((const char *) keypair, crypto_kem_SECRETKEYBYTES); | ||
| } | ||
|
|
||
| PHP_FUNCTION(sodium_crypto_kem_publickey) | ||
| { | ||
| unsigned char *keypair; | ||
| size_t keypair_len; | ||
|
|
||
| if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", | ||
| &keypair, &keypair_len) == FAILURE) { | ||
| sodium_remove_param_values_from_backtrace(EG(exception)); | ||
| RETURN_THROWS(); | ||
| } | ||
| if (keypair_len != | ||
| crypto_kem_SECRETKEYBYTES + crypto_kem_PUBLICKEYBYTES) { | ||
| zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_KEM_KEYPAIRBYTES bytes long"); | ||
| RETURN_THROWS(); | ||
| } | ||
| RETURN_STRINGL((const char *) keypair + crypto_kem_SECRETKEYBYTES, crypto_kem_PUBLICKEYBYTES); | ||
| } | ||
|
|
||
| PHP_FUNCTION(sodium_crypto_kem_enc) | ||
| { | ||
| unsigned char ciphertext[crypto_kem_CIPHERTEXTBYTES]; | ||
| unsigned char shared_secret[crypto_kem_SHAREDSECRETBYTES]; | ||
| unsigned char *publickey; | ||
| size_t publickey_len; | ||
|
|
||
| if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", | ||
| &publickey, &publickey_len) == FAILURE) { | ||
| sodium_remove_param_values_from_backtrace(EG(exception)); | ||
| RETURN_THROWS(); | ||
| } | ||
| if (publickey_len != crypto_kem_PUBLICKEYBYTES) { | ||
| zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_KEM_PUBLICKEYBYTES bytes long"); | ||
| RETURN_THROWS(); | ||
| } | ||
| if (crypto_kem_enc(ciphertext, shared_secret, publickey) != 0) { | ||
| sodium_memzero(shared_secret, sizeof shared_secret); | ||
| zend_throw_exception(sodium_exception_ce, "internal error", 0); | ||
| RETURN_THROWS(); | ||
| } | ||
| array_init(return_value); | ||
| add_next_index_stringl(return_value, (const char *) ciphertext, sizeof ciphertext); | ||
| add_next_index_stringl(return_value, (const char *) shared_secret, sizeof shared_secret); | ||
| sodium_memzero(shared_secret, sizeof shared_secret); | ||
| } | ||
|
|
||
| PHP_FUNCTION(sodium_crypto_kem_dec) | ||
| { | ||
| zend_string *shared_secret; | ||
| unsigned char *ciphertext; | ||
| unsigned char *secretkey; | ||
| size_t ciphertext_len; | ||
| size_t secretkey_len; | ||
|
|
||
| if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", | ||
| &ciphertext, &ciphertext_len, | ||
| &secretkey, &secretkey_len) == FAILURE) { | ||
| sodium_remove_param_values_from_backtrace(EG(exception)); | ||
| RETURN_THROWS(); | ||
| } | ||
| if (ciphertext_len != crypto_kem_CIPHERTEXTBYTES) { | ||
| zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_KEM_CIPHERTEXTBYTES bytes long"); | ||
| RETURN_THROWS(); | ||
| } | ||
| if (secretkey_len != crypto_kem_SECRETKEYBYTES) { | ||
| zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_KEM_SECRETKEYBYTES bytes long"); | ||
| RETURN_THROWS(); | ||
| } | ||
| shared_secret = zend_string_alloc(crypto_kem_SHAREDSECRETBYTES, 0); | ||
| if (crypto_kem_dec((unsigned char *) ZSTR_VAL(shared_secret), | ||
| ciphertext, secretkey) != 0) { | ||
| sodium_memzero(ZSTR_VAL(shared_secret), crypto_kem_SHAREDSECRETBYTES); | ||
| zend_string_efree(shared_secret); | ||
| zend_throw_exception(sodium_exception_ce, "internal error", 0); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe you want to assert this.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Want to make sure I read "assert this" right — I took it as "add test coverage for these failure branches." so I did added that. Let me know if you meant something different. Thanks!
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's what I meant, and this and the other tests lgtm now. :) |
||
| RETURN_THROWS(); | ||
| } | ||
| ZSTR_VAL(shared_secret)[crypto_kem_SHAREDSECRETBYTES] = 0; | ||
|
|
||
| RETURN_NEW_STR(shared_secret); | ||
| } | ||
| #endif | ||
|
|
||
| #ifdef crypto_kem_mlkem768_PUBLICKEYBYTES | ||
| PHP_FUNCTION(sodium_crypto_kem_mlkem768_keypair) | ||
| { | ||
| zend_string *keypair; | ||
| size_t keypair_len; | ||
|
|
||
| ZEND_PARSE_PARAMETERS_NONE(); | ||
|
|
||
| keypair_len = crypto_kem_mlkem768_SECRETKEYBYTES + crypto_kem_mlkem768_PUBLICKEYBYTES; | ||
| keypair = zend_string_alloc(keypair_len, 0); | ||
| if (crypto_kem_mlkem768_keypair((unsigned char *) ZSTR_VAL(keypair) + | ||
| crypto_kem_mlkem768_SECRETKEYBYTES, | ||
| (unsigned char *) ZSTR_VAL(keypair)) != 0) { | ||
| sodium_memzero(ZSTR_VAL(keypair), keypair_len); | ||
| zend_string_efree(keypair); | ||
| zend_throw_exception(sodium_exception_ce, "internal error", 0); | ||
| RETURN_THROWS(); | ||
| } | ||
| ZSTR_VAL(keypair)[keypair_len] = 0; | ||
|
|
||
| RETURN_NEW_STR(keypair); | ||
| } | ||
|
|
||
| PHP_FUNCTION(sodium_crypto_kem_mlkem768_seed_keypair) | ||
| { | ||
| zend_string *keypair; | ||
| unsigned char *seed; | ||
| size_t keypair_len; | ||
| size_t seed_len; | ||
|
|
||
| if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", | ||
| &seed, &seed_len) == FAILURE) { | ||
| sodium_remove_param_values_from_backtrace(EG(exception)); | ||
| RETURN_THROWS(); | ||
| } | ||
| if (seed_len != crypto_kem_mlkem768_SEEDBYTES) { | ||
| zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_KEM_MLKEM768_SEEDBYTES bytes long"); | ||
| RETURN_THROWS(); | ||
| } | ||
| keypair_len = crypto_kem_mlkem768_SECRETKEYBYTES + crypto_kem_mlkem768_PUBLICKEYBYTES; | ||
| keypair = zend_string_alloc(keypair_len, 0); | ||
| if (crypto_kem_mlkem768_seed_keypair((unsigned char *) ZSTR_VAL(keypair) + | ||
| crypto_kem_mlkem768_SECRETKEYBYTES, | ||
| (unsigned char *) ZSTR_VAL(keypair), | ||
| seed) != 0) { | ||
| sodium_memzero(ZSTR_VAL(keypair), keypair_len); | ||
| zend_string_efree(keypair); | ||
| zend_throw_exception(sodium_exception_ce, "internal error", 0); | ||
| RETURN_THROWS(); | ||
| } | ||
| ZSTR_VAL(keypair)[keypair_len] = 0; | ||
|
|
||
| RETURN_NEW_STR(keypair); | ||
| } | ||
|
|
||
| PHP_FUNCTION(sodium_crypto_kem_mlkem768_secretkey) | ||
| { | ||
| unsigned char *keypair; | ||
| size_t keypair_len; | ||
|
|
||
| if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", | ||
| &keypair, &keypair_len) == FAILURE) { | ||
| sodium_remove_param_values_from_backtrace(EG(exception)); | ||
| RETURN_THROWS(); | ||
| } | ||
| if (keypair_len != | ||
| crypto_kem_mlkem768_SECRETKEYBYTES + crypto_kem_mlkem768_PUBLICKEYBYTES) { | ||
| zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_KEM_MLKEM768_KEYPAIRBYTES bytes long"); | ||
| RETURN_THROWS(); | ||
| } | ||
| RETURN_STRINGL((const char *) keypair, crypto_kem_mlkem768_SECRETKEYBYTES); | ||
| } | ||
|
|
||
| PHP_FUNCTION(sodium_crypto_kem_mlkem768_publickey) | ||
| { | ||
| unsigned char *keypair; | ||
| size_t keypair_len; | ||
|
|
||
| if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", | ||
| &keypair, &keypair_len) == FAILURE) { | ||
| sodium_remove_param_values_from_backtrace(EG(exception)); | ||
| RETURN_THROWS(); | ||
| } | ||
| if (keypair_len != | ||
| crypto_kem_mlkem768_SECRETKEYBYTES + crypto_kem_mlkem768_PUBLICKEYBYTES) { | ||
| zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_KEM_MLKEM768_KEYPAIRBYTES bytes long"); | ||
| RETURN_THROWS(); | ||
| } | ||
| RETURN_STRINGL((const char *) keypair + crypto_kem_mlkem768_SECRETKEYBYTES, crypto_kem_mlkem768_PUBLICKEYBYTES); | ||
| } | ||
|
|
||
| PHP_FUNCTION(sodium_crypto_kem_mlkem768_enc) | ||
| { | ||
| unsigned char ciphertext[crypto_kem_mlkem768_CIPHERTEXTBYTES]; | ||
| unsigned char shared_secret[crypto_kem_mlkem768_SHAREDSECRETBYTES]; | ||
| unsigned char *publickey; | ||
| size_t publickey_len; | ||
|
|
||
| if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", | ||
| &publickey, &publickey_len) == FAILURE) { | ||
| sodium_remove_param_values_from_backtrace(EG(exception)); | ||
| RETURN_THROWS(); | ||
| } | ||
| if (publickey_len != crypto_kem_mlkem768_PUBLICKEYBYTES) { | ||
| zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_KEM_MLKEM768_PUBLICKEYBYTES bytes long"); | ||
| RETURN_THROWS(); | ||
| } | ||
| if (crypto_kem_mlkem768_enc(ciphertext, shared_secret, publickey) != 0) { | ||
| sodium_memzero(shared_secret, sizeof shared_secret); | ||
| zend_throw_exception(sodium_exception_ce, "internal error", 0); | ||
|
ZacharyDuBois marked this conversation as resolved.
|
||
| RETURN_THROWS(); | ||
| } | ||
| array_init(return_value); | ||
| add_next_index_stringl(return_value, (const char *) ciphertext, sizeof ciphertext); | ||
| add_next_index_stringl(return_value, (const char *) shared_secret, sizeof shared_secret); | ||
| sodium_memzero(shared_secret, sizeof shared_secret); | ||
| } | ||
|
|
||
| PHP_FUNCTION(sodium_crypto_kem_mlkem768_dec) | ||
| { | ||
| zend_string *shared_secret; | ||
| unsigned char *ciphertext; | ||
| unsigned char *secretkey; | ||
| size_t ciphertext_len; | ||
| size_t secretkey_len; | ||
|
|
||
| if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", | ||
| &ciphertext, &ciphertext_len, | ||
| &secretkey, &secretkey_len) == FAILURE) { | ||
| sodium_remove_param_values_from_backtrace(EG(exception)); | ||
| RETURN_THROWS(); | ||
| } | ||
| if (ciphertext_len != crypto_kem_mlkem768_CIPHERTEXTBYTES) { | ||
| zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_KEM_MLKEM768_CIPHERTEXTBYTES bytes long"); | ||
| RETURN_THROWS(); | ||
| } | ||
| if (secretkey_len != crypto_kem_mlkem768_SECRETKEYBYTES) { | ||
| zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_KEM_MLKEM768_SECRETKEYBYTES bytes long"); | ||
| RETURN_THROWS(); | ||
| } | ||
| shared_secret = zend_string_alloc(crypto_kem_mlkem768_SHAREDSECRETBYTES, 0); | ||
| if (crypto_kem_mlkem768_dec((unsigned char *) ZSTR_VAL(shared_secret), | ||
| ciphertext, secretkey) != 0) { | ||
| sodium_memzero(ZSTR_VAL(shared_secret), crypto_kem_mlkem768_SHAREDSECRETBYTES); | ||
| zend_string_efree(shared_secret); | ||
| zend_throw_exception(sodium_exception_ce, "internal error", 0); | ||
| RETURN_THROWS(); | ||
| } | ||
| ZSTR_VAL(shared_secret)[crypto_kem_mlkem768_SHAREDSECRETBYTES] = 0; | ||
|
|
||
| RETURN_NEW_STR(shared_secret); | ||
| } | ||
| #endif | ||
Uh oh!
There was an error while loading. Please reload this page.