Skip to content
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

AES_GCM_SIV does not accept empty plaintexts. #10808

Open
bleichenbacher-daniel opened this issue Apr 13, 2024 · 5 comments
Open

AES_GCM_SIV does not accept empty plaintexts. #10808

bleichenbacher-daniel opened this issue Apr 13, 2024 · 5 comments

Comments

@bleichenbacher-daniel
Copy link

A test I have started failing recently when using AES-GCM-SIV with empty plaintexts.

The failing test is

from cryptography.hazmat.primitives.ciphers import aead
import cryptography
import sys

def test_empty_pt():
    key = bytes(range(16))
    nonce = bytes(range(12))
    pt = b""
    aad = b"associated data"
    crypter = aead.AESGCMSIV(key)
    ct = crypter.encrypt(nonce, pt, aad)

if __name__ == "__main__":
    print(f"{sys.version=}")
    print(f"{cryptography.__version__=}")
    test_empty_pt()

This gives the following output

sys.version='3.12.3 (tags/v3.12.3:f6650f9, Apr 9 2024, 14:05:25) [MSC v.1938 64 bit (AMD64)]'
cryptography.version='42.0.5'
Traceback (most recent call last):
File "...pyca/aesgcmsiv.py", line 16, in
test_empty_pt()
File "...pyca/aesgcmsiv.py", line 11, in test_empty_pt
ct = crypter.encrypt(nonce, pt, aad)
ValueError: data must not be zero length

The exception is thrown for all supported key sizes of AES-GCM-SIV. No other AEAD mode seems to be affected. Other parameter sizes give the expected results. The test passed before updating to the Python version 3.12.3 and cryptography version 42.0.5.

@reaperhulk
Copy link
Member

We only added AES-GCM-SIV support in cryptography 42.0.0, so you were seeing empty PT succeed in 42.0.x but failing in 42.0.5?

@bleichenbacher-daniel
Copy link
Author

You are probably right. I can't find a test log where AES-GCM-SIV did run and all tests passed.

@reaperhulk
Copy link
Member

I don't see a reason why we shouldn't support empty PT so I'll put in a PR to improve this 😄

@reaperhulk
Copy link
Member

It looks like OpenSSL doesn't support 0 length PT (see reproducer below). I'll file an upstream issue soon.

#include <assert.h>
#include <stdio.h>
#include <openssl/evp.h>

int main() {
    EVP_CIPHER_CTX *ctx;
    unsigned char key[16] = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    unsigned char nonce[12] = {3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    unsigned char pt[12] = {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    int pt_len = 12;
    unsigned char aad[1] = {1};
    int aad_len = 1;
    unsigned char tag[16];
    unsigned char outbuf[16];
    int outlen;

    ctx = EVP_CIPHER_CTX_new();
    EVP_CIPHER *ciph = EVP_CIPHER_fetch(NULL, "aes-128-gcm-siv", NULL);
    assert(ciph != NULL);
    assert(EVP_EncryptInit_ex(ctx, ciph, NULL, key, nonce) == 1);
    assert(EVP_EncryptUpdate(ctx, NULL, &outlen, aad, aad_len) == 1);
    assert(EVP_EncryptUpdate(ctx, outbuf, &outlen, pt, pt_len) == 1);
//    assert(EVP_EncryptUpdate(ctx, outbuf, &outlen, NULL, 0) == 1); // uncomment this and it will not fail
    assert(EVP_EncryptFinal_ex(ctx, outbuf, &outlen) == 1);
    assert(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, tag) == 1);
    EVP_CIPHER_CTX_free(ctx);

    printf("Tag: ");
    for (int i = 0; i < 16; i++) {
        printf("%02x", tag[i]);
    }
    printf("\n");

    return 0;
}

@alex
Copy link
Member

alex commented Jul 20, 2024

Note: Someone should file an upstream bug with OpenSSL for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

3 participants