Allow using IV and tags longer than the minimum lengths
This commit is contained in:
parent
63fa0c4e94
commit
da9ffc9b93
@ -47,24 +47,25 @@ Encrypted communication
|
|||||||
|
|
||||||
.. versionadded:: 0.26.0
|
.. versionadded:: 0.26.0
|
||||||
|
|
||||||
When using the :opt:`remote_control_password` option communication to the terminal is
|
When using the :opt:`remote_control_password` option communication to the
|
||||||
encrypted to keep the password secure. A public key is used from the
|
terminal is encrypted to keep the password secure. A public key is used from
|
||||||
:envvar:`KITTY_PUBLIC_KEY` environment variable. Currently, only one encryption
|
the :envvar:`KITTY_PUBLIC_KEY` environment variable. Currently, only one
|
||||||
protocol is supported. The protocol number is present in
|
encryption protocol is supported. The protocol number is present in
|
||||||
:envvar:`KITTY_PUBLIC_KEY` as ``1``. The key data in this environment variable is
|
:envvar:`KITTY_PUBLIC_KEY` as ``1``. The key data in this environment variable
|
||||||
`Base-85 <https://github.com/git/git/blob/master/base85.c>`__ encoded.
|
is `Base-85 <https://github.com/git/git/blob/master/base85.c>`__ encoded. The
|
||||||
The algorithm used is `Elliptic Curve Diffie Helman
|
algorithm used is `Elliptic Curve Diffie Helman
|
||||||
<https://en.wikipedia.org/wiki/Elliptic-curve_Diffie–Hellman>`__ with the
|
<https://en.wikipedia.org/wiki/Elliptic-curve_Diffie–Hellman>`__ with the
|
||||||
`X25519 curve <https://en.wikipedia.org/wiki/Curve25519>`__. A
|
`X25519 curve <https://en.wikipedia.org/wiki/Curve25519>`__. A time based nonce
|
||||||
time based nonce is used to minimise replay attacks. The original JSON command has
|
is used to minimise replay attacks. The original JSON command has the fields:
|
||||||
the fields: ``password`` and ``timestamp`` added. The timestamp is the number
|
``password`` and ``timestamp`` added. The timestamp is the number of
|
||||||
of nanoseconds since the epoch, excluding leap seconds. Commands with a
|
nanoseconds since the epoch, excluding leap seconds. Commands with a timestamp
|
||||||
timestamp more than 5 minutes from the current time are rejected. The command is then
|
more than 5 minutes from the current time are rejected. The command is then
|
||||||
encrypted using AES-256-GCM in authenticated encryption mode, with a symmetric key that
|
encrypted using AES-256-GCM in authenticated encryption mode, with a symmetric
|
||||||
is derived from the ECDH key-pair by running the shared secret through SHA-256 hashing, once.
|
key that is derived from the ECDH key-pair by running the shared secret through
|
||||||
An IV of 96 bits of CSPRNG data is used. The tag for authenticated encryption **must** be 128 bits long.
|
SHA-256 hashing, once. An IV of at least 96 bits of CSPRNG data is used. The
|
||||||
The tag **must** authenticate only the value of the ``encrypted`` field. A new
|
tag for authenticated encryption **must** be at least 128 bits long. The tag
|
||||||
command is created and transmitted that contains the fields:
|
**must** authenticate only the value of the ``encrypted`` field. A new command
|
||||||
|
is created and transmitted that contains the fields:
|
||||||
|
|
||||||
.. code-block:: json
|
.. code-block:: json
|
||||||
|
|
||||||
|
|||||||
@ -371,15 +371,19 @@ new_aes256gcmdecrypt(PyTypeObject *type, PyObject *args, PyObject *kwds UNUSED)
|
|||||||
if (!PyArg_ParseTuple(args, "O!y#y#", &Secret_Type, &key, &iv, &iv_len, &tag, &tag_len)) return NULL;
|
if (!PyArg_ParseTuple(args, "O!y#y#", &Secret_Type, &key, &iv, &iv_len, &tag, &tag_len)) return NULL;
|
||||||
const EVP_CIPHER *cipher = EVP_get_cipherbynid(NID_aes_256_gcm);
|
const EVP_CIPHER *cipher = EVP_get_cipherbynid(NID_aes_256_gcm);
|
||||||
if (key->secret_len != (size_t)EVP_CIPHER_key_length(cipher)) { PyErr_Format(PyExc_ValueError, "The key for AES 256 GCM must be %d bytes long", EVP_CIPHER_key_length(cipher)); return NULL; }
|
if (key->secret_len != (size_t)EVP_CIPHER_key_length(cipher)) { PyErr_Format(PyExc_ValueError, "The key for AES 256 GCM must be %d bytes long", EVP_CIPHER_key_length(cipher)); return NULL; }
|
||||||
if (iv_len != EVP_CIPHER_iv_length(cipher)) { PyErr_Format(PyExc_ValueError, "The iv for AES 256 GCM must be %d bytes long", EVP_CIPHER_iv_length(cipher)); return NULL; }
|
if (iv_len < EVP_CIPHER_iv_length(cipher)) { PyErr_Format(PyExc_ValueError, "The iv for AES 256 GCM must be at least %d bytes long", EVP_CIPHER_iv_length(cipher)); return NULL; }
|
||||||
AES256GCMDecrypt *self = (AES256GCMDecrypt *)type->tp_alloc(type, 0);
|
AES256GCMDecrypt *self = (AES256GCMDecrypt *)type->tp_alloc(type, 0);
|
||||||
if (!self) return NULL;
|
if (!self) return NULL;
|
||||||
if (!(self->ctx = EVP_CIPHER_CTX_new())) { Py_CLEAR(self); return set_error_from_openssl("Failed to allocate decryption context"); }
|
if (!(self->ctx = EVP_CIPHER_CTX_new())) { Py_CLEAR(self); return set_error_from_openssl("Failed to allocate decryption context"); }
|
||||||
|
if (iv_len > EVP_CIPHER_iv_length(cipher)) {
|
||||||
|
if (!EVP_CIPHER_CTX_ctrl(self->ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL)) { Py_CLEAR(self); return set_error_from_openssl("Failed to set the IV length"); }
|
||||||
|
}
|
||||||
if (1 != EVP_DecryptInit_ex(self->ctx, cipher, NULL, key->secret, iv)) {
|
if (1 != EVP_DecryptInit_ex(self->ctx, cipher, NULL, key->secret, iv)) {
|
||||||
Py_CLEAR(self); return set_error_from_openssl("Failed to initialize encryption context"); }
|
Py_CLEAR(self); return set_error_from_openssl("Failed to initialize encryption context"); }
|
||||||
// Ensure tag length is 16 because the OpenSSL verification routines will happily pass even if you set a truncated tag.
|
// Ensure tag length is 16 because the OpenSSL verification routines will happily pass even if you set a truncated tag.
|
||||||
if (tag_len != cipher_ctx_tag_length(self->ctx)) { PyErr_Format(PyExc_ValueError, "Tag length for AES 256 GCM must be %d", cipher_ctx_tag_length(self->ctx)); return NULL; }
|
if (tag_len < cipher_ctx_tag_length(self->ctx)) { PyErr_Format(PyExc_ValueError, "Tag length for AES 256 GCM must be at least %d", cipher_ctx_tag_length(self->ctx)); return NULL; }
|
||||||
if (!EVP_CIPHER_CTX_ctrl(self->ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, tag)) { Py_CLEAR(self); return set_error_from_openssl("Failed to set the tag"); }
|
if (!EVP_CIPHER_CTX_ctrl(self->ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, tag)) { Py_CLEAR(self); return set_error_from_openssl("Failed to set the tag"); }
|
||||||
|
|
||||||
return (PyObject*)self;
|
return (PyObject*)self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user