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
>

Reply via email to