int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
{
    EVP_CIPHER_CTX *ctx;
    unsigned char iv[EVP_MAX_IV_LENGTH];
    size_t ivlen, taglen, offset, loop;
    unsigned char *staticiv;
    unsigned char *seq;
    int lenu, lenf;
    SSL3_RECORD *rec = &recs[0];
    uint32_t alg_enc;
    if (n_recs != 1) {
        return -1;
    }
    if (sending) {
        ctx = s->enc_write_ctx;
        staticiv = s->write_iv;
        seq = RECORD_LAYER_get_write_sequence(&s->rlayer);
    } else {
        ctx = s->enc_read_ctx;
        staticiv = s->read_iv;
        seq = RECORD_LAYER_get_read_sequence(&s->rlayer);
    }
    if (ctx == NULL) {
        memmove(rec->data, rec->input, rec->length);
        rec->input = rec->data;
        return 1;
    }
    ivlen = EVP_CIPHER_CTX_iv_length(ctx);
    if (s->early_data_state == SSL_EARLY_DATA_WRITING
            || s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {
        alg_enc = s->session->cipher->algorithm_enc;
    } else {
        assert(s->s3->tmp.new_cipher != NULL);
        if (s->s3->tmp.new_cipher == NULL)
            return -1;
        alg_enc = s->s3->tmp.new_cipher->algorithm_enc;
    }
    if (alg_enc & SSL_AESCCM) {
        if (alg_enc & (SSL_AES128CCM8 | SSL_AES256CCM8))
            taglen = EVP_CCM8_TLS_TAG_LEN;
         else
            taglen = EVP_CCM_TLS_TAG_LEN;
         if (sending && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, taglen,
                                         NULL) <= 0)
            return -1;
    } else if (alg_enc & SSL_AESGCM) {
        taglen = EVP_GCM_TLS_TAG_LEN;
    } else if (alg_enc & SSL_CHACHA20) {
        taglen = EVP_CHACHAPOLY_TLS_TAG_LEN;
    } else {
        return -1;
    }
    if (!sending) {
        if (rec->length < taglen + 1)
            return 0;
        rec->length -= taglen;
    }
    if (ivlen < SEQ_NUM_SIZE) {
        return -1;
    }
    offset = ivlen - SEQ_NUM_SIZE;
    memcpy(iv, staticiv, offset);
    for (loop = 0; loop < SEQ_NUM_SIZE; loop++)
        iv[offset + loop] = staticiv[offset + loop] ^ seq[loop];
    for (loop = SEQ_NUM_SIZE; loop > 0; loop--) {
        ++seq[loop - 1];
        if (seq[loop - 1] != 0)
            break;
    }
    if (loop == 0) {
        return -1;
    }
    if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, sending) <= 0
            || (!sending && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
                                             taglen,
                                             rec->data + rec->length) <= 0)
            || EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input,
                                (unsigned int)rec->length) <= 0
            || EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0
            || (size_t)(lenu + lenf) != rec->length) {
        return -1;
    }
    if (sending) {
        if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, taglen,
                                rec->data + rec->length) <= 0)
            return -1;
        rec->length += taglen;
    }
    return 1;
}
['static int test_tls13_encryption(void)\n{\n    SSL_CTX *ctx = NULL;\n    SSL *s = NULL;\n    SSL3_RECORD rec;\n    unsigned char *key = NULL, *iv = NULL, *seq = NULL;\n    const EVP_CIPHER *ciph = EVP_aes_128_gcm();\n    int ret = 0;\n    size_t ivlen, ctr;\n    rec.data = NULL;\n    ctx = SSL_CTX_new(TLS_method());\n    if (!TEST_ptr(ctx)) {\n        TEST_info("Failed creating SSL_CTX");\n        goto err;\n    }\n    s = SSL_new(ctx);\n    if (!TEST_ptr(s)) {\n        TEST_info("Failed creating SSL");\n        goto err;\n    }\n    s->enc_read_ctx = EVP_CIPHER_CTX_new();\n    if (!TEST_ptr(s->enc_read_ctx))\n        goto err;\n    s->enc_write_ctx = EVP_CIPHER_CTX_new();\n    if (!TEST_ptr(s->enc_write_ctx))\n        goto err;\n    s->s3->tmp.new_cipher = SSL_CIPHER_find(s, TLS13_AES_128_GCM_SHA256_BYTES);\n    if (!TEST_ptr(s->s3->tmp.new_cipher)) {\n        TEST_info("Failed to find cipher");\n        goto err;\n    }\n    for (ctr = 0; ctr < OSSL_NELEM(refdata); ctr++) {\n        ivlen = EVP_CIPHER_iv_length(ciph);\n        if (!load_record(&rec, &refdata[ctr], &key, s->read_iv, ivlen,\n                         RECORD_LAYER_get_read_sequence(&s->rlayer))) {\n            TEST_error("Failed loading key into EVP_CIPHER_CTX");\n            goto err;\n        }\n        memcpy(RECORD_LAYER_get_write_sequence(&s->rlayer),\n               RECORD_LAYER_get_read_sequence(&s->rlayer), SEQ_NUM_SIZE);\n        memcpy(s->write_iv, s->read_iv, ivlen);\n        if (EVP_CipherInit_ex(s->enc_write_ctx, ciph, NULL, key, NULL, 1) <= 0\n                || EVP_CipherInit_ex(s->enc_read_ctx, ciph, NULL, key, NULL, 0)\n                   <= 0) {\n            TEST_error("Failed loading key into EVP_CIPHER_CTX\\n");\n            goto err;\n        }\n        if (!TEST_size_t_eq(tls13_enc(s, &rec, 1, 1), 1)) {\n            TEST_info("Failed to encrypt record %"OSSLzu"", ctr);\n            goto err;\n        }\n        if (!TEST_true(test_record(&rec, &refdata[ctr], 1))) {\n            TEST_info("Record %"OSSLzu" encryption test failed", ctr);\n            goto err;\n        }\n        if (!TEST_int_eq(tls13_enc(s, &rec, 1, 0), 1)) {\n            TEST_info("Failed to decrypt record %"OSSLzu"", ctr);\n            goto err;\n        }\n        if (!TEST_true(test_record(&rec, &refdata[ctr], 0))) {\n            TEST_info("Record %"OSSLzu" decryption test failed", ctr);\n            goto err;\n        }\n        OPENSSL_free(rec.data);\n        OPENSSL_free(key);\n        OPENSSL_free(iv);\n        OPENSSL_free(seq);\n        rec.data = NULL;\n        key = NULL;\n        iv = NULL;\n        seq = NULL;\n    }\n    fprintf(stderr, "PASS: %"OSSLzu" records tested\\n", ctr);\n    ret = 1;\n err:\n    OPENSSL_free(rec.data);\n    OPENSSL_free(key);\n    OPENSSL_free(iv);\n    OPENSSL_free(seq);\n    SSL_free(s);\n    SSL_CTX_free(ctx);\n    return ret;\n}', 'static int load_record(SSL3_RECORD *rec, RECORD_DATA *recd, unsigned char **key,\n                       unsigned char *iv, size_t ivlen, unsigned char *seq)\n{\n    unsigned char *pt = NULL, *sq = NULL, *ivtmp = NULL;\n    size_t ptlen;\n    *key = OPENSSL_hexstr2buf(recd->key, NULL);\n    ivtmp = OPENSSL_hexstr2buf(recd->iv, NULL);\n    sq = OPENSSL_hexstr2buf(recd->seq, NULL);\n    pt = multihexstr2buf(recd->plaintext, &ptlen);\n    if (*key == NULL || ivtmp == NULL || sq == NULL || pt == NULL)\n        goto err;\n    rec->data = rec->input = OPENSSL_malloc(ptlen + EVP_GCM_TLS_TAG_LEN);\n    if (rec->data == NULL)\n        goto err;\n    rec->length = ptlen;\n    memcpy(rec->data, pt, ptlen);\n    OPENSSL_free(pt);\n    memcpy(seq, sq, SEQ_NUM_SIZE);\n    OPENSSL_free(sq);\n    memcpy(iv, ivtmp, ivlen);\n    OPENSSL_free(ivtmp);\n    return 1;\n err:\n    OPENSSL_free(*key);\n    *key = NULL;\n    OPENSSL_free(ivtmp);\n    OPENSSL_free(sq);\n    OPENSSL_free(pt);\n    return 0;\n}', 'int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)\n{\n    EVP_CIPHER_CTX *ctx;\n    unsigned char iv[EVP_MAX_IV_LENGTH];\n    size_t ivlen, taglen, offset, loop;\n    unsigned char *staticiv;\n    unsigned char *seq;\n    int lenu, lenf;\n    SSL3_RECORD *rec = &recs[0];\n    uint32_t alg_enc;\n    if (n_recs != 1) {\n        return -1;\n    }\n    if (sending) {\n        ctx = s->enc_write_ctx;\n        staticiv = s->write_iv;\n        seq = RECORD_LAYER_get_write_sequence(&s->rlayer);\n    } else {\n        ctx = s->enc_read_ctx;\n        staticiv = s->read_iv;\n        seq = RECORD_LAYER_get_read_sequence(&s->rlayer);\n    }\n    if (ctx == NULL) {\n        memmove(rec->data, rec->input, rec->length);\n        rec->input = rec->data;\n        return 1;\n    }\n    ivlen = EVP_CIPHER_CTX_iv_length(ctx);\n    if (s->early_data_state == SSL_EARLY_DATA_WRITING\n            || s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {\n        alg_enc = s->session->cipher->algorithm_enc;\n    } else {\n        assert(s->s3->tmp.new_cipher != NULL);\n        if (s->s3->tmp.new_cipher == NULL)\n            return -1;\n        alg_enc = s->s3->tmp.new_cipher->algorithm_enc;\n    }\n    if (alg_enc & SSL_AESCCM) {\n        if (alg_enc & (SSL_AES128CCM8 | SSL_AES256CCM8))\n            taglen = EVP_CCM8_TLS_TAG_LEN;\n         else\n            taglen = EVP_CCM_TLS_TAG_LEN;\n         if (sending && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, taglen,\n                                         NULL) <= 0)\n            return -1;\n    } else if (alg_enc & SSL_AESGCM) {\n        taglen = EVP_GCM_TLS_TAG_LEN;\n    } else if (alg_enc & SSL_CHACHA20) {\n        taglen = EVP_CHACHAPOLY_TLS_TAG_LEN;\n    } else {\n        return -1;\n    }\n    if (!sending) {\n        if (rec->length < taglen + 1)\n            return 0;\n        rec->length -= taglen;\n    }\n    if (ivlen < SEQ_NUM_SIZE) {\n        return -1;\n    }\n    offset = ivlen - SEQ_NUM_SIZE;\n    memcpy(iv, staticiv, offset);\n    for (loop = 0; loop < SEQ_NUM_SIZE; loop++)\n        iv[offset + loop] = staticiv[offset + loop] ^ seq[loop];\n    for (loop = SEQ_NUM_SIZE; loop > 0; loop--) {\n        ++seq[loop - 1];\n        if (seq[loop - 1] != 0)\n            break;\n    }\n    if (loop == 0) {\n        return -1;\n    }\n    if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, sending) <= 0\n            || (!sending && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,\n                                             taglen,\n                                             rec->data + rec->length) <= 0)\n            || EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input,\n                                (unsigned int)rec->length) <= 0\n            || EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0\n            || (size_t)(lenu + lenf) != rec->length) {\n        return -1;\n    }\n    if (sending) {\n        if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, taglen,\n                                rec->data + rec->length) <= 0)\n            return -1;\n        rec->length += taglen;\n    }\n    return 1;\n}']