Nice catch! I didn't noticed that. Actually, when I added the AEAD encrypt/decrypt code, I followed that wiki page.
This is same question to https://github.com/openssl/openssl/issues/1624 Also it looks like the latest docs has been changed. https://www.openssl.org/docs/manmaster/man3/EVP_EncryptInit.html#GCM-and-OCB-Modes - Masaori 2017年11月3日(金) 15:24 Chao Xu <ok...@apache.org>: > Hi dev, > > https://www.openssl.org/docs/man1.1.0/crypto/EVP_CIPHER_CTX_ctrl.html > > EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, taglen, tag); > > Sets the expected tag to taglen bytes from tag. This call is only legal > when decrypting data and must be made before any data is processed (e.g. > before any EVP_DecryptUpdate() call). For OCB mode the taglen must either > be 16 or the value previously set via EVP_CTRL_AEAD_SET_TAG. > According to the openssl 1.1.0 docs, it said the EVP_CTRL_AEAD_SET_TAG is > only legal and must before any data is processed. > > But the sample code within wiki.openssl.org: > https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption > > int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *aad, > int aad_len, unsigned char *tag, unsigned char *key, unsigned char *iv, > int iv_len, unsigned char *plaintext) > { > EVP_CIPHER_CTX *ctx; > int len; > int plaintext_len; > int ret; > > /* Create and initialise the context */ > if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); > > /* Initialise the decryption operation. */ > if(!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) > handleErrors(); > > /* Set IV length. Not necessary if this is 12 bytes (96 bits) */ > if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL)) > handleErrors(); > > /* Initialise key and IV */ > if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors(); > > /* Provide any AAD data. This can be called zero or more times as > * required > */ > if(!EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len)) > handleErrors(); > > /* Provide the message to be decrypted, and obtain the plaintext output. > * EVP_DecryptUpdate can be called multiple times if necessary > */ > if(!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) > handleErrors(); > plaintext_len = len; > > /* Set expected tag value. Works in OpenSSL 1.0.1d and later */ > if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag)) > handleErrors(); > > /* Finalise the decryption. A positive return value indicates success, > * anything else is a failure - the plaintext is not trustworthy. > */ > ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len); > > /* Clean up */ > EVP_CIPHER_CTX_free(ctx); > > if(ret > 0) > { > /* Success */ > plaintext_len += len; > return plaintext_len; > } > else > { > /* Verify failed */ > return -1; > } > } > > > And our AE/AD decrypt function from QUIC: > > ``` > bool > QUICCrypto::_decrypt(uint8_t *plain, size_t &plain_len, size_t > max_plain_len, const uint8_t *cipher, size_t cipher_len, > uint64_t pkt_num, const uint8_t *ad, size_t ad_len, > const uint8_t *key, size_t key_len, const uint8_t *iv, > size_t iv_len, size_t tag_len) const > { > uint8_t nonce[EVP_MAX_IV_LENGTH] = {0}; > size_t nonce_len = 0; > _gen_nonce(nonce, nonce_len, pkt_num, iv, iv_len); > > EVP_CIPHER_CTX *aead_ctx; > int len; > > if (!(aead_ctx = EVP_CIPHER_CTX_new())) { > return false; > } > if (!EVP_DecryptInit_ex(aead_ctx, this->_aead, nullptr, nullptr, > nullptr)) { > return false; > } > if (!EVP_CIPHER_CTX_ctrl(aead_ctx, EVP_CTRL_AEAD_SET_IVLEN, nonce_len, > nullptr)) { > return false; > } > if (!EVP_DecryptInit_ex(aead_ctx, nullptr, nullptr, key, nonce)) { > return false; > } > if (!EVP_DecryptUpdate(aead_ctx, nullptr, &len, ad, ad_len)) { > return false; > } > > if (cipher_len < tag_len) { > return false; > } > cipher_len -= tag_len; > if (!EVP_DecryptUpdate(aead_ctx, plain, &len, cipher, cipher_len)) { > return false; > } > plain_len = len; > > if (!EVP_CIPHER_CTX_ctrl(aead_ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, > const_cast<uint8_t *>(cipher + cipher_len))) { > return false; > } > > int ret = EVP_DecryptFinal_ex(aead_ctx, plain + len, &len); > > EVP_CIPHER_CTX_free(aead_ctx); > > if (ret > 0) { > plain_len += len; > return true; > } else { > Debug(tag, "Failed to decrypt"); > return false; > } > } > ``` > > - Oknet >