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