Blame crypto/modes/gcm128.c

Packit Service 084de1
/*
Packit Service 084de1
 * Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved.
Packit Service 084de1
 *
Packit Service 084de1
 * Licensed under the OpenSSL license (the "License").  You may not use
Packit Service 084de1
 * this file except in compliance with the License.  You can obtain a copy
Packit Service 084de1
 * in the file LICENSE in the source distribution or at
Packit Service 084de1
 * https://www.openssl.org/source/license.html
Packit Service 084de1
 */
Packit Service 084de1
Packit Service 084de1
#include <openssl/crypto.h>
Packit Service 084de1
#include "modes_local.h"
Packit Service 084de1
#include <string.h>
Packit Service 084de1
Packit Service 084de1
#if defined(BSWAP4) && defined(STRICT_ALIGNMENT)
Packit Service 084de1
/* redefine, because alignment is ensured */
Packit Service 084de1
# undef  GETU32
Packit Service 084de1
# define GETU32(p)       BSWAP4(*(const u32 *)(p))
Packit Service 084de1
# undef  PUTU32
Packit Service 084de1
# define PUTU32(p,v)     *(u32 *)(p) = BSWAP4(v)
Packit Service 084de1
#endif
Packit Service 084de1
Packit Service 084de1
#define PACK(s)         ((size_t)(s)<<(sizeof(size_t)*8-16))
Packit Service 084de1
#define REDUCE1BIT(V)   do { \
Packit Service 084de1
        if (sizeof(size_t)==8) { \
Packit Service 084de1
                u64 T = U64(0xe100000000000000) & (0-(V.lo&1)); \
Packit Service 084de1
                V.lo  = (V.hi<<63)|(V.lo>>1); \
Packit Service 084de1
                V.hi  = (V.hi>>1 )^T; \
Packit Service 084de1
        } \
Packit Service 084de1
        else { \
Packit Service 084de1
                u32 T = 0xe1000000U & (0-(u32)(V.lo&1)); \
Packit Service 084de1
                V.lo  = (V.hi<<63)|(V.lo>>1); \
Packit Service 084de1
                V.hi  = (V.hi>>1 )^((u64)T<<32); \
Packit Service 084de1
        } \
Packit Service 084de1
} while(0)
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * Even though permitted values for TABLE_BITS are 8, 4 and 1, it should
Packit Service 084de1
 * never be set to 8. 8 is effectively reserved for testing purposes.
Packit Service 084de1
 * TABLE_BITS>1 are lookup-table-driven implementations referred to as
Packit Service 084de1
 * "Shoup's" in GCM specification. In other words OpenSSL does not cover
Packit Service 084de1
 * whole spectrum of possible table driven implementations. Why? In
Packit Service 084de1
 * non-"Shoup's" case memory access pattern is segmented in such manner,
Packit Service 084de1
 * that it's trivial to see that cache timing information can reveal
Packit Service 084de1
 * fair portion of intermediate hash value. Given that ciphertext is
Packit Service 084de1
 * always available to attacker, it's possible for him to attempt to
Packit Service 084de1
 * deduce secret parameter H and if successful, tamper with messages
Packit Service 084de1
 * [which is nothing but trivial in CTR mode]. In "Shoup's" case it's
Packit Service 084de1
 * not as trivial, but there is no reason to believe that it's resistant
Packit Service 084de1
 * to cache-timing attack. And the thing about "8-bit" implementation is
Packit Service 084de1
 * that it consumes 16 (sixteen) times more memory, 4KB per individual
Packit Service 084de1
 * key + 1KB shared. Well, on pros side it should be twice as fast as
Packit Service 084de1
 * "4-bit" version. And for gcc-generated x86[_64] code, "8-bit" version
Packit Service 084de1
 * was observed to run ~75% faster, closer to 100% for commercial
Packit Service 084de1
 * compilers... Yet "4-bit" procedure is preferred, because it's
Packit Service 084de1
 * believed to provide better security-performance balance and adequate
Packit Service 084de1
 * all-round performance. "All-round" refers to things like:
Packit Service 084de1
 *
Packit Service 084de1
 * - shorter setup time effectively improves overall timing for
Packit Service 084de1
 *   handling short messages;
Packit Service 084de1
 * - larger table allocation can become unbearable because of VM
Packit Service 084de1
 *   subsystem penalties (for example on Windows large enough free
Packit Service 084de1
 *   results in VM working set trimming, meaning that consequent
Packit Service 084de1
 *   malloc would immediately incur working set expansion);
Packit Service 084de1
 * - larger table has larger cache footprint, which can affect
Packit Service 084de1
 *   performance of other code paths (not necessarily even from same
Packit Service 084de1
 *   thread in Hyper-Threading world);
Packit Service 084de1
 *
Packit Service 084de1
 * Value of 1 is not appropriate for performance reasons.
Packit Service 084de1
 */
Packit Service 084de1
#if     TABLE_BITS==8
Packit Service 084de1
Packit Service 084de1
static void gcm_init_8bit(u128 Htable[256], u64 H[2])
Packit Service 084de1
{
Packit Service 084de1
    int i, j;
Packit Service 084de1
    u128 V;
Packit Service 084de1
Packit Service 084de1
    Htable[0].hi = 0;
Packit Service 084de1
    Htable[0].lo = 0;
Packit Service 084de1
    V.hi = H[0];
Packit Service 084de1
    V.lo = H[1];
Packit Service 084de1
Packit Service 084de1
    for (Htable[128] = V, i = 64; i > 0; i >>= 1) {
Packit Service 084de1
        REDUCE1BIT(V);
Packit Service 084de1
        Htable[i] = V;
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    for (i = 2; i < 256; i <<= 1) {
Packit Service 084de1
        u128 *Hi = Htable + i, H0 = *Hi;
Packit Service 084de1
        for (j = 1; j < i; ++j) {
Packit Service 084de1
            Hi[j].hi = H0.hi ^ Htable[j].hi;
Packit Service 084de1
            Hi[j].lo = H0.lo ^ Htable[j].lo;
Packit Service 084de1
        }
Packit Service 084de1
    }
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
static void gcm_gmult_8bit(u64 Xi[2], const u128 Htable[256])
Packit Service 084de1
{
Packit Service 084de1
    u128 Z = { 0, 0 };
Packit Service 084de1
    const u8 *xi = (const u8 *)Xi + 15;
Packit Service 084de1
    size_t rem, n = *xi;
Packit Service 084de1
    const union {
Packit Service 084de1
        long one;
Packit Service 084de1
        char little;
Packit Service 084de1
    } is_endian = { 1 };
Packit Service 084de1
    static const size_t rem_8bit[256] = {
Packit Service 084de1
        PACK(0x0000), PACK(0x01C2), PACK(0x0384), PACK(0x0246),
Packit Service 084de1
        PACK(0x0708), PACK(0x06CA), PACK(0x048C), PACK(0x054E),
Packit Service 084de1
        PACK(0x0E10), PACK(0x0FD2), PACK(0x0D94), PACK(0x0C56),
Packit Service 084de1
        PACK(0x0918), PACK(0x08DA), PACK(0x0A9C), PACK(0x0B5E),
Packit Service 084de1
        PACK(0x1C20), PACK(0x1DE2), PACK(0x1FA4), PACK(0x1E66),
Packit Service 084de1
        PACK(0x1B28), PACK(0x1AEA), PACK(0x18AC), PACK(0x196E),
Packit Service 084de1
        PACK(0x1230), PACK(0x13F2), PACK(0x11B4), PACK(0x1076),
Packit Service 084de1
        PACK(0x1538), PACK(0x14FA), PACK(0x16BC), PACK(0x177E),
Packit Service 084de1
        PACK(0x3840), PACK(0x3982), PACK(0x3BC4), PACK(0x3A06),
Packit Service 084de1
        PACK(0x3F48), PACK(0x3E8A), PACK(0x3CCC), PACK(0x3D0E),
Packit Service 084de1
        PACK(0x3650), PACK(0x3792), PACK(0x35D4), PACK(0x3416),
Packit Service 084de1
        PACK(0x3158), PACK(0x309A), PACK(0x32DC), PACK(0x331E),
Packit Service 084de1
        PACK(0x2460), PACK(0x25A2), PACK(0x27E4), PACK(0x2626),
Packit Service 084de1
        PACK(0x2368), PACK(0x22AA), PACK(0x20EC), PACK(0x212E),
Packit Service 084de1
        PACK(0x2A70), PACK(0x2BB2), PACK(0x29F4), PACK(0x2836),
Packit Service 084de1
        PACK(0x2D78), PACK(0x2CBA), PACK(0x2EFC), PACK(0x2F3E),
Packit Service 084de1
        PACK(0x7080), PACK(0x7142), PACK(0x7304), PACK(0x72C6),
Packit Service 084de1
        PACK(0x7788), PACK(0x764A), PACK(0x740C), PACK(0x75CE),
Packit Service 084de1
        PACK(0x7E90), PACK(0x7F52), PACK(0x7D14), PACK(0x7CD6),
Packit Service 084de1
        PACK(0x7998), PACK(0x785A), PACK(0x7A1C), PACK(0x7BDE),
Packit Service 084de1
        PACK(0x6CA0), PACK(0x6D62), PACK(0x6F24), PACK(0x6EE6),
Packit Service 084de1
        PACK(0x6BA8), PACK(0x6A6A), PACK(0x682C), PACK(0x69EE),
Packit Service 084de1
        PACK(0x62B0), PACK(0x6372), PACK(0x6134), PACK(0x60F6),
Packit Service 084de1
        PACK(0x65B8), PACK(0x647A), PACK(0x663C), PACK(0x67FE),
Packit Service 084de1
        PACK(0x48C0), PACK(0x4902), PACK(0x4B44), PACK(0x4A86),
Packit Service 084de1
        PACK(0x4FC8), PACK(0x4E0A), PACK(0x4C4C), PACK(0x4D8E),
Packit Service 084de1
        PACK(0x46D0), PACK(0x4712), PACK(0x4554), PACK(0x4496),
Packit Service 084de1
        PACK(0x41D8), PACK(0x401A), PACK(0x425C), PACK(0x439E),
Packit Service 084de1
        PACK(0x54E0), PACK(0x5522), PACK(0x5764), PACK(0x56A6),
Packit Service 084de1
        PACK(0x53E8), PACK(0x522A), PACK(0x506C), PACK(0x51AE),
Packit Service 084de1
        PACK(0x5AF0), PACK(0x5B32), PACK(0x5974), PACK(0x58B6),
Packit Service 084de1
        PACK(0x5DF8), PACK(0x5C3A), PACK(0x5E7C), PACK(0x5FBE),
Packit Service 084de1
        PACK(0xE100), PACK(0xE0C2), PACK(0xE284), PACK(0xE346),
Packit Service 084de1
        PACK(0xE608), PACK(0xE7CA), PACK(0xE58C), PACK(0xE44E),
Packit Service 084de1
        PACK(0xEF10), PACK(0xEED2), PACK(0xEC94), PACK(0xED56),
Packit Service 084de1
        PACK(0xE818), PACK(0xE9DA), PACK(0xEB9C), PACK(0xEA5E),
Packit Service 084de1
        PACK(0xFD20), PACK(0xFCE2), PACK(0xFEA4), PACK(0xFF66),
Packit Service 084de1
        PACK(0xFA28), PACK(0xFBEA), PACK(0xF9AC), PACK(0xF86E),
Packit Service 084de1
        PACK(0xF330), PACK(0xF2F2), PACK(0xF0B4), PACK(0xF176),
Packit Service 084de1
        PACK(0xF438), PACK(0xF5FA), PACK(0xF7BC), PACK(0xF67E),
Packit Service 084de1
        PACK(0xD940), PACK(0xD882), PACK(0xDAC4), PACK(0xDB06),
Packit Service 084de1
        PACK(0xDE48), PACK(0xDF8A), PACK(0xDDCC), PACK(0xDC0E),
Packit Service 084de1
        PACK(0xD750), PACK(0xD692), PACK(0xD4D4), PACK(0xD516),
Packit Service 084de1
        PACK(0xD058), PACK(0xD19A), PACK(0xD3DC), PACK(0xD21E),
Packit Service 084de1
        PACK(0xC560), PACK(0xC4A2), PACK(0xC6E4), PACK(0xC726),
Packit Service 084de1
        PACK(0xC268), PACK(0xC3AA), PACK(0xC1EC), PACK(0xC02E),
Packit Service 084de1
        PACK(0xCB70), PACK(0xCAB2), PACK(0xC8F4), PACK(0xC936),
Packit Service 084de1
        PACK(0xCC78), PACK(0xCDBA), PACK(0xCFFC), PACK(0xCE3E),
Packit Service 084de1
        PACK(0x9180), PACK(0x9042), PACK(0x9204), PACK(0x93C6),
Packit Service 084de1
        PACK(0x9688), PACK(0x974A), PACK(0x950C), PACK(0x94CE),
Packit Service 084de1
        PACK(0x9F90), PACK(0x9E52), PACK(0x9C14), PACK(0x9DD6),
Packit Service 084de1
        PACK(0x9898), PACK(0x995A), PACK(0x9B1C), PACK(0x9ADE),
Packit Service 084de1
        PACK(0x8DA0), PACK(0x8C62), PACK(0x8E24), PACK(0x8FE6),
Packit Service 084de1
        PACK(0x8AA8), PACK(0x8B6A), PACK(0x892C), PACK(0x88EE),
Packit Service 084de1
        PACK(0x83B0), PACK(0x8272), PACK(0x8034), PACK(0x81F6),
Packit Service 084de1
        PACK(0x84B8), PACK(0x857A), PACK(0x873C), PACK(0x86FE),
Packit Service 084de1
        PACK(0xA9C0), PACK(0xA802), PACK(0xAA44), PACK(0xAB86),
Packit Service 084de1
        PACK(0xAEC8), PACK(0xAF0A), PACK(0xAD4C), PACK(0xAC8E),
Packit Service 084de1
        PACK(0xA7D0), PACK(0xA612), PACK(0xA454), PACK(0xA596),
Packit Service 084de1
        PACK(0xA0D8), PACK(0xA11A), PACK(0xA35C), PACK(0xA29E),
Packit Service 084de1
        PACK(0xB5E0), PACK(0xB422), PACK(0xB664), PACK(0xB7A6),
Packit Service 084de1
        PACK(0xB2E8), PACK(0xB32A), PACK(0xB16C), PACK(0xB0AE),
Packit Service 084de1
        PACK(0xBBF0), PACK(0xBA32), PACK(0xB874), PACK(0xB9B6),
Packit Service 084de1
        PACK(0xBCF8), PACK(0xBD3A), PACK(0xBF7C), PACK(0xBEBE)
Packit Service 084de1
    };
Packit Service 084de1
Packit Service 084de1
    while (1) {
Packit Service 084de1
        Z.hi ^= Htable[n].hi;
Packit Service 084de1
        Z.lo ^= Htable[n].lo;
Packit Service 084de1
Packit Service 084de1
        if ((u8 *)Xi == xi)
Packit Service 084de1
            break;
Packit Service 084de1
Packit Service 084de1
        n = *(--xi);
Packit Service 084de1
Packit Service 084de1
        rem = (size_t)Z.lo & 0xff;
Packit Service 084de1
        Z.lo = (Z.hi << 56) | (Z.lo >> 8);
Packit Service 084de1
        Z.hi = (Z.hi >> 8);
Packit Service 084de1
        if (sizeof(size_t) == 8)
Packit Service 084de1
            Z.hi ^= rem_8bit[rem];
Packit Service 084de1
        else
Packit Service 084de1
            Z.hi ^= (u64)rem_8bit[rem] << 32;
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    if (is_endian.little) {
Packit Service 084de1
# ifdef BSWAP8
Packit Service 084de1
        Xi[0] = BSWAP8(Z.hi);
Packit Service 084de1
        Xi[1] = BSWAP8(Z.lo);
Packit Service 084de1
# else
Packit Service 084de1
        u8 *p = (u8 *)Xi;
Packit Service 084de1
        u32 v;
Packit Service 084de1
        v = (u32)(Z.hi >> 32);
Packit Service 084de1
        PUTU32(p, v);
Packit Service 084de1
        v = (u32)(Z.hi);
Packit Service 084de1
        PUTU32(p + 4, v);
Packit Service 084de1
        v = (u32)(Z.lo >> 32);
Packit Service 084de1
        PUTU32(p + 8, v);
Packit Service 084de1
        v = (u32)(Z.lo);
Packit Service 084de1
        PUTU32(p + 12, v);
Packit Service 084de1
# endif
Packit Service 084de1
    } else {
Packit Service 084de1
        Xi[0] = Z.hi;
Packit Service 084de1
        Xi[1] = Z.lo;
Packit Service 084de1
    }
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
# define GCM_MUL(ctx)      gcm_gmult_8bit(ctx->Xi.u,ctx->Htable)
Packit Service 084de1
Packit Service 084de1
#elif   TABLE_BITS==4
Packit Service 084de1
Packit Service 084de1
static void gcm_init_4bit(u128 Htable[16], u64 H[2])
Packit Service 084de1
{
Packit Service 084de1
    u128 V;
Packit Service 084de1
# if defined(OPENSSL_SMALL_FOOTPRINT)
Packit Service 084de1
    int i;
Packit Service 084de1
# endif
Packit Service 084de1
Packit Service 084de1
    Htable[0].hi = 0;
Packit Service 084de1
    Htable[0].lo = 0;
Packit Service 084de1
    V.hi = H[0];
Packit Service 084de1
    V.lo = H[1];
Packit Service 084de1
Packit Service 084de1
# if defined(OPENSSL_SMALL_FOOTPRINT)
Packit Service 084de1
    for (Htable[8] = V, i = 4; i > 0; i >>= 1) {
Packit Service 084de1
        REDUCE1BIT(V);
Packit Service 084de1
        Htable[i] = V;
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    for (i = 2; i < 16; i <<= 1) {
Packit Service 084de1
        u128 *Hi = Htable + i;
Packit Service 084de1
        int j;
Packit Service 084de1
        for (V = *Hi, j = 1; j < i; ++j) {
Packit Service 084de1
            Hi[j].hi = V.hi ^ Htable[j].hi;
Packit Service 084de1
            Hi[j].lo = V.lo ^ Htable[j].lo;
Packit Service 084de1
        }
Packit Service 084de1
    }
Packit Service 084de1
# else
Packit Service 084de1
    Htable[8] = V;
Packit Service 084de1
    REDUCE1BIT(V);
Packit Service 084de1
    Htable[4] = V;
Packit Service 084de1
    REDUCE1BIT(V);
Packit Service 084de1
    Htable[2] = V;
Packit Service 084de1
    REDUCE1BIT(V);
Packit Service 084de1
    Htable[1] = V;
Packit Service 084de1
    Htable[3].hi = V.hi ^ Htable[2].hi, Htable[3].lo = V.lo ^ Htable[2].lo;
Packit Service 084de1
    V = Htable[4];
Packit Service 084de1
    Htable[5].hi = V.hi ^ Htable[1].hi, Htable[5].lo = V.lo ^ Htable[1].lo;
Packit Service 084de1
    Htable[6].hi = V.hi ^ Htable[2].hi, Htable[6].lo = V.lo ^ Htable[2].lo;
Packit Service 084de1
    Htable[7].hi = V.hi ^ Htable[3].hi, Htable[7].lo = V.lo ^ Htable[3].lo;
Packit Service 084de1
    V = Htable[8];
Packit Service 084de1
    Htable[9].hi = V.hi ^ Htable[1].hi, Htable[9].lo = V.lo ^ Htable[1].lo;
Packit Service 084de1
    Htable[10].hi = V.hi ^ Htable[2].hi, Htable[10].lo = V.lo ^ Htable[2].lo;
Packit Service 084de1
    Htable[11].hi = V.hi ^ Htable[3].hi, Htable[11].lo = V.lo ^ Htable[3].lo;
Packit Service 084de1
    Htable[12].hi = V.hi ^ Htable[4].hi, Htable[12].lo = V.lo ^ Htable[4].lo;
Packit Service 084de1
    Htable[13].hi = V.hi ^ Htable[5].hi, Htable[13].lo = V.lo ^ Htable[5].lo;
Packit Service 084de1
    Htable[14].hi = V.hi ^ Htable[6].hi, Htable[14].lo = V.lo ^ Htable[6].lo;
Packit Service 084de1
    Htable[15].hi = V.hi ^ Htable[7].hi, Htable[15].lo = V.lo ^ Htable[7].lo;
Packit Service 084de1
# endif
Packit Service 084de1
# if defined(GHASH_ASM) && (defined(__arm__) || defined(__arm))
Packit Service 084de1
    /*
Packit Service 084de1
     * ARM assembler expects specific dword order in Htable.
Packit Service 084de1
     */
Packit Service 084de1
    {
Packit Service 084de1
        int j;
Packit Service 084de1
        const union {
Packit Service 084de1
            long one;
Packit Service 084de1
            char little;
Packit Service 084de1
        } is_endian = { 1 };
Packit Service 084de1
Packit Service 084de1
        if (is_endian.little)
Packit Service 084de1
            for (j = 0; j < 16; ++j) {
Packit Service 084de1
                V = Htable[j];
Packit Service 084de1
                Htable[j].hi = V.lo;
Packit Service 084de1
                Htable[j].lo = V.hi;
Packit Service 084de1
        } else
Packit Service 084de1
            for (j = 0; j < 16; ++j) {
Packit Service 084de1
                V = Htable[j];
Packit Service 084de1
                Htable[j].hi = V.lo << 32 | V.lo >> 32;
Packit Service 084de1
                Htable[j].lo = V.hi << 32 | V.hi >> 32;
Packit Service 084de1
            }
Packit Service 084de1
    }
Packit Service 084de1
# endif
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
# ifndef GHASH_ASM
Packit Service 084de1
static const size_t rem_4bit[16] = {
Packit Service 084de1
    PACK(0x0000), PACK(0x1C20), PACK(0x3840), PACK(0x2460),
Packit Service 084de1
    PACK(0x7080), PACK(0x6CA0), PACK(0x48C0), PACK(0x54E0),
Packit Service 084de1
    PACK(0xE100), PACK(0xFD20), PACK(0xD940), PACK(0xC560),
Packit Service 084de1
    PACK(0x9180), PACK(0x8DA0), PACK(0xA9C0), PACK(0xB5E0)
Packit Service 084de1
};
Packit Service 084de1
Packit Service 084de1
static void gcm_gmult_4bit(u64 Xi[2], const u128 Htable[16])
Packit Service 084de1
{
Packit Service 084de1
    u128 Z;
Packit Service 084de1
    int cnt = 15;
Packit Service 084de1
    size_t rem, nlo, nhi;
Packit Service 084de1
    const union {
Packit Service 084de1
        long one;
Packit Service 084de1
        char little;
Packit Service 084de1
    } is_endian = { 1 };
Packit Service 084de1
Packit Service 084de1
    nlo = ((const u8 *)Xi)[15];
Packit Service 084de1
    nhi = nlo >> 4;
Packit Service 084de1
    nlo &= 0xf;
Packit Service 084de1
Packit Service 084de1
    Z.hi = Htable[nlo].hi;
Packit Service 084de1
    Z.lo = Htable[nlo].lo;
Packit Service 084de1
Packit Service 084de1
    while (1) {
Packit Service 084de1
        rem = (size_t)Z.lo & 0xf;
Packit Service 084de1
        Z.lo = (Z.hi << 60) | (Z.lo >> 4);
Packit Service 084de1
        Z.hi = (Z.hi >> 4);
Packit Service 084de1
        if (sizeof(size_t) == 8)
Packit Service 084de1
            Z.hi ^= rem_4bit[rem];
Packit Service 084de1
        else
Packit Service 084de1
            Z.hi ^= (u64)rem_4bit[rem] << 32;
Packit Service 084de1
Packit Service 084de1
        Z.hi ^= Htable[nhi].hi;
Packit Service 084de1
        Z.lo ^= Htable[nhi].lo;
Packit Service 084de1
Packit Service 084de1
        if (--cnt < 0)
Packit Service 084de1
            break;
Packit Service 084de1
Packit Service 084de1
        nlo = ((const u8 *)Xi)[cnt];
Packit Service 084de1
        nhi = nlo >> 4;
Packit Service 084de1
        nlo &= 0xf;
Packit Service 084de1
Packit Service 084de1
        rem = (size_t)Z.lo & 0xf;
Packit Service 084de1
        Z.lo = (Z.hi << 60) | (Z.lo >> 4);
Packit Service 084de1
        Z.hi = (Z.hi >> 4);
Packit Service 084de1
        if (sizeof(size_t) == 8)
Packit Service 084de1
            Z.hi ^= rem_4bit[rem];
Packit Service 084de1
        else
Packit Service 084de1
            Z.hi ^= (u64)rem_4bit[rem] << 32;
Packit Service 084de1
Packit Service 084de1
        Z.hi ^= Htable[nlo].hi;
Packit Service 084de1
        Z.lo ^= Htable[nlo].lo;
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    if (is_endian.little) {
Packit Service 084de1
#  ifdef BSWAP8
Packit Service 084de1
        Xi[0] = BSWAP8(Z.hi);
Packit Service 084de1
        Xi[1] = BSWAP8(Z.lo);
Packit Service 084de1
#  else
Packit Service 084de1
        u8 *p = (u8 *)Xi;
Packit Service 084de1
        u32 v;
Packit Service 084de1
        v = (u32)(Z.hi >> 32);
Packit Service 084de1
        PUTU32(p, v);
Packit Service 084de1
        v = (u32)(Z.hi);
Packit Service 084de1
        PUTU32(p + 4, v);
Packit Service 084de1
        v = (u32)(Z.lo >> 32);
Packit Service 084de1
        PUTU32(p + 8, v);
Packit Service 084de1
        v = (u32)(Z.lo);
Packit Service 084de1
        PUTU32(p + 12, v);
Packit Service 084de1
#  endif
Packit Service 084de1
    } else {
Packit Service 084de1
        Xi[0] = Z.hi;
Packit Service 084de1
        Xi[1] = Z.lo;
Packit Service 084de1
    }
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
#  if !defined(OPENSSL_SMALL_FOOTPRINT)
Packit Service 084de1
/*
Packit Service 084de1
 * Streamed gcm_mult_4bit, see CRYPTO_gcm128_[en|de]crypt for
Packit Service 084de1
 * details... Compiler-generated code doesn't seem to give any
Packit Service 084de1
 * performance improvement, at least not on x86[_64]. It's here
Packit Service 084de1
 * mostly as reference and a placeholder for possible future
Packit Service 084de1
 * non-trivial optimization[s]...
Packit Service 084de1
 */
Packit Service 084de1
static void gcm_ghash_4bit(u64 Xi[2], const u128 Htable[16],
Packit Service 084de1
                           const u8 *inp, size_t len)
Packit Service 084de1
{
Packit Service 084de1
    u128 Z;
Packit Service 084de1
    int cnt;
Packit Service 084de1
    size_t rem, nlo, nhi;
Packit Service 084de1
    const union {
Packit Service 084de1
        long one;
Packit Service 084de1
        char little;
Packit Service 084de1
    } is_endian = { 1 };
Packit Service 084de1
Packit Service 084de1
#   if 1
Packit Service 084de1
    do {
Packit Service 084de1
        cnt = 15;
Packit Service 084de1
        nlo = ((const u8 *)Xi)[15];
Packit Service 084de1
        nlo ^= inp[15];
Packit Service 084de1
        nhi = nlo >> 4;
Packit Service 084de1
        nlo &= 0xf;
Packit Service 084de1
Packit Service 084de1
        Z.hi = Htable[nlo].hi;
Packit Service 084de1
        Z.lo = Htable[nlo].lo;
Packit Service 084de1
Packit Service 084de1
        while (1) {
Packit Service 084de1
            rem = (size_t)Z.lo & 0xf;
Packit Service 084de1
            Z.lo = (Z.hi << 60) | (Z.lo >> 4);
Packit Service 084de1
            Z.hi = (Z.hi >> 4);
Packit Service 084de1
            if (sizeof(size_t) == 8)
Packit Service 084de1
                Z.hi ^= rem_4bit[rem];
Packit Service 084de1
            else
Packit Service 084de1
                Z.hi ^= (u64)rem_4bit[rem] << 32;
Packit Service 084de1
Packit Service 084de1
            Z.hi ^= Htable[nhi].hi;
Packit Service 084de1
            Z.lo ^= Htable[nhi].lo;
Packit Service 084de1
Packit Service 084de1
            if (--cnt < 0)
Packit Service 084de1
                break;
Packit Service 084de1
Packit Service 084de1
            nlo = ((const u8 *)Xi)[cnt];
Packit Service 084de1
            nlo ^= inp[cnt];
Packit Service 084de1
            nhi = nlo >> 4;
Packit Service 084de1
            nlo &= 0xf;
Packit Service 084de1
Packit Service 084de1
            rem = (size_t)Z.lo & 0xf;
Packit Service 084de1
            Z.lo = (Z.hi << 60) | (Z.lo >> 4);
Packit Service 084de1
            Z.hi = (Z.hi >> 4);
Packit Service 084de1
            if (sizeof(size_t) == 8)
Packit Service 084de1
                Z.hi ^= rem_4bit[rem];
Packit Service 084de1
            else
Packit Service 084de1
                Z.hi ^= (u64)rem_4bit[rem] << 32;
Packit Service 084de1
Packit Service 084de1
            Z.hi ^= Htable[nlo].hi;
Packit Service 084de1
            Z.lo ^= Htable[nlo].lo;
Packit Service 084de1
        }
Packit Service 084de1
#   else
Packit Service 084de1
    /*
Packit Service 084de1
     * Extra 256+16 bytes per-key plus 512 bytes shared tables
Packit Service 084de1
     * [should] give ~50% improvement... One could have PACK()-ed
Packit Service 084de1
     * the rem_8bit even here, but the priority is to minimize
Packit Service 084de1
     * cache footprint...
Packit Service 084de1
     */
Packit Service 084de1
    u128 Hshr4[16];             /* Htable shifted right by 4 bits */
Packit Service 084de1
    u8 Hshl4[16];               /* Htable shifted left by 4 bits */
Packit Service 084de1
    static const unsigned short rem_8bit[256] = {
Packit Service 084de1
        0x0000, 0x01C2, 0x0384, 0x0246, 0x0708, 0x06CA, 0x048C, 0x054E,
Packit Service 084de1
        0x0E10, 0x0FD2, 0x0D94, 0x0C56, 0x0918, 0x08DA, 0x0A9C, 0x0B5E,
Packit Service 084de1
        0x1C20, 0x1DE2, 0x1FA4, 0x1E66, 0x1B28, 0x1AEA, 0x18AC, 0x196E,
Packit Service 084de1
        0x1230, 0x13F2, 0x11B4, 0x1076, 0x1538, 0x14FA, 0x16BC, 0x177E,
Packit Service 084de1
        0x3840, 0x3982, 0x3BC4, 0x3A06, 0x3F48, 0x3E8A, 0x3CCC, 0x3D0E,
Packit Service 084de1
        0x3650, 0x3792, 0x35D4, 0x3416, 0x3158, 0x309A, 0x32DC, 0x331E,
Packit Service 084de1
        0x2460, 0x25A2, 0x27E4, 0x2626, 0x2368, 0x22AA, 0x20EC, 0x212E,
Packit Service 084de1
        0x2A70, 0x2BB2, 0x29F4, 0x2836, 0x2D78, 0x2CBA, 0x2EFC, 0x2F3E,
Packit Service 084de1
        0x7080, 0x7142, 0x7304, 0x72C6, 0x7788, 0x764A, 0x740C, 0x75CE,
Packit Service 084de1
        0x7E90, 0x7F52, 0x7D14, 0x7CD6, 0x7998, 0x785A, 0x7A1C, 0x7BDE,
Packit Service 084de1
        0x6CA0, 0x6D62, 0x6F24, 0x6EE6, 0x6BA8, 0x6A6A, 0x682C, 0x69EE,
Packit Service 084de1
        0x62B0, 0x6372, 0x6134, 0x60F6, 0x65B8, 0x647A, 0x663C, 0x67FE,
Packit Service 084de1
        0x48C0, 0x4902, 0x4B44, 0x4A86, 0x4FC8, 0x4E0A, 0x4C4C, 0x4D8E,
Packit Service 084de1
        0x46D0, 0x4712, 0x4554, 0x4496, 0x41D8, 0x401A, 0x425C, 0x439E,
Packit Service 084de1
        0x54E0, 0x5522, 0x5764, 0x56A6, 0x53E8, 0x522A, 0x506C, 0x51AE,
Packit Service 084de1
        0x5AF0, 0x5B32, 0x5974, 0x58B6, 0x5DF8, 0x5C3A, 0x5E7C, 0x5FBE,
Packit Service 084de1
        0xE100, 0xE0C2, 0xE284, 0xE346, 0xE608, 0xE7CA, 0xE58C, 0xE44E,
Packit Service 084de1
        0xEF10, 0xEED2, 0xEC94, 0xED56, 0xE818, 0xE9DA, 0xEB9C, 0xEA5E,
Packit Service 084de1
        0xFD20, 0xFCE2, 0xFEA4, 0xFF66, 0xFA28, 0xFBEA, 0xF9AC, 0xF86E,
Packit Service 084de1
        0xF330, 0xF2F2, 0xF0B4, 0xF176, 0xF438, 0xF5FA, 0xF7BC, 0xF67E,
Packit Service 084de1
        0xD940, 0xD882, 0xDAC4, 0xDB06, 0xDE48, 0xDF8A, 0xDDCC, 0xDC0E,
Packit Service 084de1
        0xD750, 0xD692, 0xD4D4, 0xD516, 0xD058, 0xD19A, 0xD3DC, 0xD21E,
Packit Service 084de1
        0xC560, 0xC4A2, 0xC6E4, 0xC726, 0xC268, 0xC3AA, 0xC1EC, 0xC02E,
Packit Service 084de1
        0xCB70, 0xCAB2, 0xC8F4, 0xC936, 0xCC78, 0xCDBA, 0xCFFC, 0xCE3E,
Packit Service 084de1
        0x9180, 0x9042, 0x9204, 0x93C6, 0x9688, 0x974A, 0x950C, 0x94CE,
Packit Service 084de1
        0x9F90, 0x9E52, 0x9C14, 0x9DD6, 0x9898, 0x995A, 0x9B1C, 0x9ADE,
Packit Service 084de1
        0x8DA0, 0x8C62, 0x8E24, 0x8FE6, 0x8AA8, 0x8B6A, 0x892C, 0x88EE,
Packit Service 084de1
        0x83B0, 0x8272, 0x8034, 0x81F6, 0x84B8, 0x857A, 0x873C, 0x86FE,
Packit Service 084de1
        0xA9C0, 0xA802, 0xAA44, 0xAB86, 0xAEC8, 0xAF0A, 0xAD4C, 0xAC8E,
Packit Service 084de1
        0xA7D0, 0xA612, 0xA454, 0xA596, 0xA0D8, 0xA11A, 0xA35C, 0xA29E,
Packit Service 084de1
        0xB5E0, 0xB422, 0xB664, 0xB7A6, 0xB2E8, 0xB32A, 0xB16C, 0xB0AE,
Packit Service 084de1
        0xBBF0, 0xBA32, 0xB874, 0xB9B6, 0xBCF8, 0xBD3A, 0xBF7C, 0xBEBE
Packit Service 084de1
    };
Packit Service 084de1
    /*
Packit Service 084de1
     * This pre-processing phase slows down procedure by approximately
Packit Service 084de1
     * same time as it makes each loop spin faster. In other words
Packit Service 084de1
     * single block performance is approximately same as straightforward
Packit Service 084de1
     * "4-bit" implementation, and then it goes only faster...
Packit Service 084de1
     */
Packit Service 084de1
    for (cnt = 0; cnt < 16; ++cnt) {
Packit Service 084de1
        Z.hi = Htable[cnt].hi;
Packit Service 084de1
        Z.lo = Htable[cnt].lo;
Packit Service 084de1
        Hshr4[cnt].lo = (Z.hi << 60) | (Z.lo >> 4);
Packit Service 084de1
        Hshr4[cnt].hi = (Z.hi >> 4);
Packit Service 084de1
        Hshl4[cnt] = (u8)(Z.lo << 4);
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    do {
Packit Service 084de1
        for (Z.lo = 0, Z.hi = 0, cnt = 15; cnt; --cnt) {
Packit Service 084de1
            nlo = ((const u8 *)Xi)[cnt];
Packit Service 084de1
            nlo ^= inp[cnt];
Packit Service 084de1
            nhi = nlo >> 4;
Packit Service 084de1
            nlo &= 0xf;
Packit Service 084de1
Packit Service 084de1
            Z.hi ^= Htable[nlo].hi;
Packit Service 084de1
            Z.lo ^= Htable[nlo].lo;
Packit Service 084de1
Packit Service 084de1
            rem = (size_t)Z.lo & 0xff;
Packit Service 084de1
Packit Service 084de1
            Z.lo = (Z.hi << 56) | (Z.lo >> 8);
Packit Service 084de1
            Z.hi = (Z.hi >> 8);
Packit Service 084de1
Packit Service 084de1
            Z.hi ^= Hshr4[nhi].hi;
Packit Service 084de1
            Z.lo ^= Hshr4[nhi].lo;
Packit Service 084de1
            Z.hi ^= (u64)rem_8bit[rem ^ Hshl4[nhi]] << 48;
Packit Service 084de1
        }
Packit Service 084de1
Packit Service 084de1
        nlo = ((const u8 *)Xi)[0];
Packit Service 084de1
        nlo ^= inp[0];
Packit Service 084de1
        nhi = nlo >> 4;
Packit Service 084de1
        nlo &= 0xf;
Packit Service 084de1
Packit Service 084de1
        Z.hi ^= Htable[nlo].hi;
Packit Service 084de1
        Z.lo ^= Htable[nlo].lo;
Packit Service 084de1
Packit Service 084de1
        rem = (size_t)Z.lo & 0xf;
Packit Service 084de1
Packit Service 084de1
        Z.lo = (Z.hi << 60) | (Z.lo >> 4);
Packit Service 084de1
        Z.hi = (Z.hi >> 4);
Packit Service 084de1
Packit Service 084de1
        Z.hi ^= Htable[nhi].hi;
Packit Service 084de1
        Z.lo ^= Htable[nhi].lo;
Packit Service 084de1
        Z.hi ^= ((u64)rem_8bit[rem << 4]) << 48;
Packit Service 084de1
#   endif
Packit Service 084de1
Packit Service 084de1
        if (is_endian.little) {
Packit Service 084de1
#   ifdef BSWAP8
Packit Service 084de1
            Xi[0] = BSWAP8(Z.hi);
Packit Service 084de1
            Xi[1] = BSWAP8(Z.lo);
Packit Service 084de1
#   else
Packit Service 084de1
            u8 *p = (u8 *)Xi;
Packit Service 084de1
            u32 v;
Packit Service 084de1
            v = (u32)(Z.hi >> 32);
Packit Service 084de1
            PUTU32(p, v);
Packit Service 084de1
            v = (u32)(Z.hi);
Packit Service 084de1
            PUTU32(p + 4, v);
Packit Service 084de1
            v = (u32)(Z.lo >> 32);
Packit Service 084de1
            PUTU32(p + 8, v);
Packit Service 084de1
            v = (u32)(Z.lo);
Packit Service 084de1
            PUTU32(p + 12, v);
Packit Service 084de1
#   endif
Packit Service 084de1
        } else {
Packit Service 084de1
            Xi[0] = Z.hi;
Packit Service 084de1
            Xi[1] = Z.lo;
Packit Service 084de1
        }
Packit Service 084de1
    } while (inp += 16, len -= 16);
Packit Service 084de1
}
Packit Service 084de1
#  endif
Packit Service 084de1
# else
Packit Service 084de1
void gcm_gmult_4bit(u64 Xi[2], const u128 Htable[16]);
Packit Service 084de1
void gcm_ghash_4bit(u64 Xi[2], const u128 Htable[16], const u8 *inp,
Packit Service 084de1
                    size_t len);
Packit Service 084de1
# endif
Packit Service 084de1
Packit Service 084de1
# define GCM_MUL(ctx)      gcm_gmult_4bit(ctx->Xi.u,ctx->Htable)
Packit Service 084de1
# if defined(GHASH_ASM) || !defined(OPENSSL_SMALL_FOOTPRINT)
Packit Service 084de1
#  define GHASH(ctx,in,len) gcm_ghash_4bit((ctx)->Xi.u,(ctx)->Htable,in,len)
Packit Service 084de1
/*
Packit Service 084de1
 * GHASH_CHUNK is "stride parameter" missioned to mitigate cache trashing
Packit Service 084de1
 * effect. In other words idea is to hash data while it's still in L1 cache
Packit Service 084de1
 * after encryption pass...
Packit Service 084de1
 */
Packit Service 084de1
#  define GHASH_CHUNK       (3*1024)
Packit Service 084de1
# endif
Packit Service 084de1
Packit Service 084de1
#else                           /* TABLE_BITS */
Packit Service 084de1
Packit Service 084de1
static void gcm_gmult_1bit(u64 Xi[2], const u64 H[2])
Packit Service 084de1
{
Packit Service 084de1
    u128 V, Z = { 0, 0 };
Packit Service 084de1
    long X;
Packit Service 084de1
    int i, j;
Packit Service 084de1
    const long *xi = (const long *)Xi;
Packit Service 084de1
    const union {
Packit Service 084de1
        long one;
Packit Service 084de1
        char little;
Packit Service 084de1
    } is_endian = { 1 };
Packit Service 084de1
Packit Service 084de1
    V.hi = H[0];                /* H is in host byte order, no byte swapping */
Packit Service 084de1
    V.lo = H[1];
Packit Service 084de1
Packit Service 084de1
    for (j = 0; j < 16 / sizeof(long); ++j) {
Packit Service 084de1
        if (is_endian.little) {
Packit Service 084de1
            if (sizeof(long) == 8) {
Packit Service 084de1
# ifdef BSWAP8
Packit Service 084de1
                X = (long)(BSWAP8(xi[j]));
Packit Service 084de1
# else
Packit Service 084de1
                const u8 *p = (const u8 *)(xi + j);
Packit Service 084de1
                X = (long)((u64)GETU32(p) << 32 | GETU32(p + 4));
Packit Service 084de1
# endif
Packit Service 084de1
            } else {
Packit Service 084de1
                const u8 *p = (const u8 *)(xi + j);
Packit Service 084de1
                X = (long)GETU32(p);
Packit Service 084de1
            }
Packit Service 084de1
        } else
Packit Service 084de1
            X = xi[j];
Packit Service 084de1
Packit Service 084de1
        for (i = 0; i < 8 * sizeof(long); ++i, X <<= 1) {
Packit Service 084de1
            u64 M = (u64)(X >> (8 * sizeof(long) - 1));
Packit Service 084de1
            Z.hi ^= V.hi & M;
Packit Service 084de1
            Z.lo ^= V.lo & M;
Packit Service 084de1
Packit Service 084de1
            REDUCE1BIT(V);
Packit Service 084de1
        }
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    if (is_endian.little) {
Packit Service 084de1
# ifdef BSWAP8
Packit Service 084de1
        Xi[0] = BSWAP8(Z.hi);
Packit Service 084de1
        Xi[1] = BSWAP8(Z.lo);
Packit Service 084de1
# else
Packit Service 084de1
        u8 *p = (u8 *)Xi;
Packit Service 084de1
        u32 v;
Packit Service 084de1
        v = (u32)(Z.hi >> 32);
Packit Service 084de1
        PUTU32(p, v);
Packit Service 084de1
        v = (u32)(Z.hi);
Packit Service 084de1
        PUTU32(p + 4, v);
Packit Service 084de1
        v = (u32)(Z.lo >> 32);
Packit Service 084de1
        PUTU32(p + 8, v);
Packit Service 084de1
        v = (u32)(Z.lo);
Packit Service 084de1
        PUTU32(p + 12, v);
Packit Service 084de1
# endif
Packit Service 084de1
    } else {
Packit Service 084de1
        Xi[0] = Z.hi;
Packit Service 084de1
        Xi[1] = Z.lo;
Packit Service 084de1
    }
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
# define GCM_MUL(ctx)      gcm_gmult_1bit(ctx->Xi.u,ctx->H.u)
Packit Service 084de1
Packit Service 084de1
#endif
Packit Service 084de1
Packit Service 084de1
#if     TABLE_BITS==4 && (defined(GHASH_ASM) || defined(OPENSSL_CPUID_OBJ))
Packit Service 084de1
# if    !defined(I386_ONLY) && \
Packit Service 084de1
        (defined(__i386)        || defined(__i386__)    || \
Packit Service 084de1
         defined(__x86_64)      || defined(__x86_64__)  || \
Packit Service 084de1
         defined(_M_IX86)       || defined(_M_AMD64)    || defined(_M_X64))
Packit Service 084de1
#  define GHASH_ASM_X86_OR_64
Packit Service 084de1
#  define GCM_FUNCREF_4BIT
Packit Service 084de1
extern unsigned int OPENSSL_ia32cap_P[];
Packit Service 084de1
Packit Service 084de1
void gcm_init_clmul(u128 Htable[16], const u64 Xi[2]);
Packit Service 084de1
void gcm_gmult_clmul(u64 Xi[2], const u128 Htable[16]);
Packit Service 084de1
void gcm_ghash_clmul(u64 Xi[2], const u128 Htable[16], const u8 *inp,
Packit Service 084de1
                     size_t len);
Packit Service 084de1
Packit Service 084de1
#  if defined(__i386) || defined(__i386__) || defined(_M_IX86)
Packit Service 084de1
#   define gcm_init_avx   gcm_init_clmul
Packit Service 084de1
#   define gcm_gmult_avx  gcm_gmult_clmul
Packit Service 084de1
#   define gcm_ghash_avx  gcm_ghash_clmul
Packit Service 084de1
#  else
Packit Service 084de1
void gcm_init_avx(u128 Htable[16], const u64 Xi[2]);
Packit Service 084de1
void gcm_gmult_avx(u64 Xi[2], const u128 Htable[16]);
Packit Service 084de1
void gcm_ghash_avx(u64 Xi[2], const u128 Htable[16], const u8 *inp,
Packit Service 084de1
                   size_t len);
Packit Service 084de1
#  endif
Packit Service 084de1
Packit Service 084de1
#  if   defined(__i386) || defined(__i386__) || defined(_M_IX86)
Packit Service 084de1
#   define GHASH_ASM_X86
Packit Service 084de1
void gcm_gmult_4bit_mmx(u64 Xi[2], const u128 Htable[16]);
Packit Service 084de1
void gcm_ghash_4bit_mmx(u64 Xi[2], const u128 Htable[16], const u8 *inp,
Packit Service 084de1
                        size_t len);
Packit Service 084de1
Packit Service 084de1
void gcm_gmult_4bit_x86(u64 Xi[2], const u128 Htable[16]);
Packit Service 084de1
void gcm_ghash_4bit_x86(u64 Xi[2], const u128 Htable[16], const u8 *inp,
Packit Service 084de1
                        size_t len);
Packit Service 084de1
#  endif
Packit Service 084de1
# elif defined(__arm__) || defined(__arm) || defined(__aarch64__)
Packit Service 084de1
#  include "arm_arch.h"
Packit Service 084de1
#  if __ARM_MAX_ARCH__>=7
Packit Service 084de1
#   define GHASH_ASM_ARM
Packit Service 084de1
#   define GCM_FUNCREF_4BIT
Packit Service 084de1
#   define PMULL_CAPABLE        (OPENSSL_armcap_P & ARMV8_PMULL)
Packit Service 084de1
#   if defined(__arm__) || defined(__arm)
Packit Service 084de1
#    define NEON_CAPABLE        (OPENSSL_armcap_P & ARMV7_NEON)
Packit Service 084de1
#   endif
Packit Service 084de1
void gcm_init_neon(u128 Htable[16], const u64 Xi[2]);
Packit Service 084de1
void gcm_gmult_neon(u64 Xi[2], const u128 Htable[16]);
Packit Service 084de1
void gcm_ghash_neon(u64 Xi[2], const u128 Htable[16], const u8 *inp,
Packit Service 084de1
                    size_t len);
Packit Service 084de1
void gcm_init_v8(u128 Htable[16], const u64 Xi[2]);
Packit Service 084de1
void gcm_gmult_v8(u64 Xi[2], const u128 Htable[16]);
Packit Service 084de1
void gcm_ghash_v8(u64 Xi[2], const u128 Htable[16], const u8 *inp,
Packit Service 084de1
                  size_t len);
Packit Service 084de1
#  endif
Packit Service 084de1
# elif defined(__sparc__) || defined(__sparc)
Packit Service 084de1
#  include "sparc_arch.h"
Packit Service 084de1
#  define GHASH_ASM_SPARC
Packit Service 084de1
#  define GCM_FUNCREF_4BIT
Packit Service 084de1
extern unsigned int OPENSSL_sparcv9cap_P[];
Packit Service 084de1
void gcm_init_vis3(u128 Htable[16], const u64 Xi[2]);
Packit Service 084de1
void gcm_gmult_vis3(u64 Xi[2], const u128 Htable[16]);
Packit Service 084de1
void gcm_ghash_vis3(u64 Xi[2], const u128 Htable[16], const u8 *inp,
Packit Service 084de1
                    size_t len);
Packit Service 084de1
# elif defined(OPENSSL_CPUID_OBJ) && (defined(__powerpc__) || defined(__ppc__) || defined(_ARCH_PPC))
Packit Service 084de1
#  include "ppc_arch.h"
Packit Service 084de1
#  define GHASH_ASM_PPC
Packit Service 084de1
#  define GCM_FUNCREF_4BIT
Packit Service 084de1
void gcm_init_p8(u128 Htable[16], const u64 Xi[2]);
Packit Service 084de1
void gcm_gmult_p8(u64 Xi[2], const u128 Htable[16]);
Packit Service 084de1
void gcm_ghash_p8(u64 Xi[2], const u128 Htable[16], const u8 *inp,
Packit Service 084de1
                  size_t len);
Packit Service 084de1
# endif
Packit Service 084de1
#endif
Packit Service 084de1
Packit Service 084de1
#ifdef GCM_FUNCREF_4BIT
Packit Service 084de1
# undef  GCM_MUL
Packit Service 084de1
# define GCM_MUL(ctx)           (*gcm_gmult_p)(ctx->Xi.u,ctx->Htable)
Packit Service 084de1
# ifdef GHASH
Packit Service 084de1
#  undef  GHASH
Packit Service 084de1
#  define GHASH(ctx,in,len)     (*gcm_ghash_p)(ctx->Xi.u,ctx->Htable,in,len)
Packit Service 084de1
# endif
Packit Service 084de1
#endif
Packit Service 084de1
Packit Service 084de1
void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, void *key, block128_f block)
Packit Service 084de1
{
Packit Service 084de1
    const union {
Packit Service 084de1
        long one;
Packit Service 084de1
        char little;
Packit Service 084de1
    } is_endian = { 1 };
Packit Service 084de1
Packit Service 084de1
    memset(ctx, 0, sizeof(*ctx));
Packit Service 084de1
    ctx->block = block;
Packit Service 084de1
    ctx->key = key;
Packit Service 084de1
Packit Service 084de1
    (*block) (ctx->H.c, ctx->H.c, key);
Packit Service 084de1
Packit Service 084de1
    if (is_endian.little) {
Packit Service 084de1
        /* H is stored in host byte order */
Packit Service 084de1
#ifdef BSWAP8
Packit Service 084de1
        ctx->H.u[0] = BSWAP8(ctx->H.u[0]);
Packit Service 084de1
        ctx->H.u[1] = BSWAP8(ctx->H.u[1]);
Packit Service 084de1
#else
Packit Service 084de1
        u8 *p = ctx->H.c;
Packit Service 084de1
        u64 hi, lo;
Packit Service 084de1
        hi = (u64)GETU32(p) << 32 | GETU32(p + 4);
Packit Service 084de1
        lo = (u64)GETU32(p + 8) << 32 | GETU32(p + 12);
Packit Service 084de1
        ctx->H.u[0] = hi;
Packit Service 084de1
        ctx->H.u[1] = lo;
Packit Service 084de1
#endif
Packit Service 084de1
    }
Packit Service 084de1
#if     TABLE_BITS==8
Packit Service 084de1
    gcm_init_8bit(ctx->Htable, ctx->H.u);
Packit Service 084de1
#elif   TABLE_BITS==4
Packit Service 084de1
# if    defined(GHASH)
Packit Service 084de1
#  define CTX__GHASH(f) (ctx->ghash = (f))
Packit Service 084de1
# else
Packit Service 084de1
#  define CTX__GHASH(f) (ctx->ghash = NULL)
Packit Service 084de1
# endif
Packit Service 084de1
# if    defined(GHASH_ASM_X86_OR_64)
Packit Service 084de1
#  if   !defined(GHASH_ASM_X86) || defined(OPENSSL_IA32_SSE2)
Packit Service 084de1
    if (OPENSSL_ia32cap_P[1] & (1 << 1)) { /* check PCLMULQDQ bit */
Packit Service 084de1
        if (((OPENSSL_ia32cap_P[1] >> 22) & 0x41) == 0x41) { /* AVX+MOVBE */
Packit Service 084de1
            gcm_init_avx(ctx->Htable, ctx->H.u);
Packit Service 084de1
            ctx->gmult = gcm_gmult_avx;
Packit Service 084de1
            CTX__GHASH(gcm_ghash_avx);
Packit Service 084de1
        } else {
Packit Service 084de1
            gcm_init_clmul(ctx->Htable, ctx->H.u);
Packit Service 084de1
            ctx->gmult = gcm_gmult_clmul;
Packit Service 084de1
            CTX__GHASH(gcm_ghash_clmul);
Packit Service 084de1
        }
Packit Service 084de1
        return;
Packit Service 084de1
    }
Packit Service 084de1
#  endif
Packit Service 084de1
    gcm_init_4bit(ctx->Htable, ctx->H.u);
Packit Service 084de1
#  if   defined(GHASH_ASM_X86)  /* x86 only */
Packit Service 084de1
#   if  defined(OPENSSL_IA32_SSE2)
Packit Service 084de1
    if (OPENSSL_ia32cap_P[0] & (1 << 25)) { /* check SSE bit */
Packit Service 084de1
#   else
Packit Service 084de1
    if (OPENSSL_ia32cap_P[0] & (1 << 23)) { /* check MMX bit */
Packit Service 084de1
#   endif
Packit Service 084de1
        ctx->gmult = gcm_gmult_4bit_mmx;
Packit Service 084de1
        CTX__GHASH(gcm_ghash_4bit_mmx);
Packit Service 084de1
    } else {
Packit Service 084de1
        ctx->gmult = gcm_gmult_4bit_x86;
Packit Service 084de1
        CTX__GHASH(gcm_ghash_4bit_x86);
Packit Service 084de1
    }
Packit Service 084de1
#  else
Packit Service 084de1
    ctx->gmult = gcm_gmult_4bit;
Packit Service 084de1
    CTX__GHASH(gcm_ghash_4bit);
Packit Service 084de1
#  endif
Packit Service 084de1
# elif  defined(GHASH_ASM_ARM)
Packit Service 084de1
#  ifdef PMULL_CAPABLE
Packit Service 084de1
    if (PMULL_CAPABLE) {
Packit Service 084de1
        gcm_init_v8(ctx->Htable, ctx->H.u);
Packit Service 084de1
        ctx->gmult = gcm_gmult_v8;
Packit Service 084de1
        CTX__GHASH(gcm_ghash_v8);
Packit Service 084de1
    } else
Packit Service 084de1
#  endif
Packit Service 084de1
#  ifdef NEON_CAPABLE
Packit Service 084de1
    if (NEON_CAPABLE) {
Packit Service 084de1
        gcm_init_neon(ctx->Htable, ctx->H.u);
Packit Service 084de1
        ctx->gmult = gcm_gmult_neon;
Packit Service 084de1
        CTX__GHASH(gcm_ghash_neon);
Packit Service 084de1
    } else
Packit Service 084de1
#  endif
Packit Service 084de1
    {
Packit Service 084de1
        gcm_init_4bit(ctx->Htable, ctx->H.u);
Packit Service 084de1
        ctx->gmult = gcm_gmult_4bit;
Packit Service 084de1
        CTX__GHASH(gcm_ghash_4bit);
Packit Service 084de1
    }
Packit Service 084de1
# elif  defined(GHASH_ASM_SPARC)
Packit Service 084de1
    if (OPENSSL_sparcv9cap_P[0] & SPARCV9_VIS3) {
Packit Service 084de1
        gcm_init_vis3(ctx->Htable, ctx->H.u);
Packit Service 084de1
        ctx->gmult = gcm_gmult_vis3;
Packit Service 084de1
        CTX__GHASH(gcm_ghash_vis3);
Packit Service 084de1
    } else {
Packit Service 084de1
        gcm_init_4bit(ctx->Htable, ctx->H.u);
Packit Service 084de1
        ctx->gmult = gcm_gmult_4bit;
Packit Service 084de1
        CTX__GHASH(gcm_ghash_4bit);
Packit Service 084de1
    }
Packit Service 084de1
# elif  defined(GHASH_ASM_PPC)
Packit Service 084de1
    if (OPENSSL_ppccap_P & PPC_CRYPTO207) {
Packit Service 084de1
        gcm_init_p8(ctx->Htable, ctx->H.u);
Packit Service 084de1
        ctx->gmult = gcm_gmult_p8;
Packit Service 084de1
        CTX__GHASH(gcm_ghash_p8);
Packit Service 084de1
    } else {
Packit Service 084de1
        gcm_init_4bit(ctx->Htable, ctx->H.u);
Packit Service 084de1
        ctx->gmult = gcm_gmult_4bit;
Packit Service 084de1
        CTX__GHASH(gcm_ghash_4bit);
Packit Service 084de1
    }
Packit Service 084de1
# else
Packit Service 084de1
    gcm_init_4bit(ctx->Htable, ctx->H.u);
Packit Service 084de1
# endif
Packit Service 084de1
# undef CTX__GHASH
Packit Service 084de1
#endif
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const unsigned char *iv,
Packit Service 084de1
                         size_t len)
Packit Service 084de1
{
Packit Service 084de1
    const union {
Packit Service 084de1
        long one;
Packit Service 084de1
        char little;
Packit Service 084de1
    } is_endian = { 1 };
Packit Service 084de1
    unsigned int ctr;
Packit Service 084de1
#ifdef GCM_FUNCREF_4BIT
Packit Service 084de1
    void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult;
Packit Service 084de1
#endif
Packit Service 084de1
Packit Service 084de1
    ctx->len.u[0] = 0;          /* AAD length */
Packit Service 084de1
    ctx->len.u[1] = 0;          /* message length */
Packit Service 084de1
    ctx->ares = 0;
Packit Service 084de1
    ctx->mres = 0;
Packit Service 084de1
Packit Service 084de1
    if (len == 12) {
Packit Service 084de1
        memcpy(ctx->Yi.c, iv, 12);
Packit Service 084de1
        ctx->Yi.c[12] = 0;
Packit Service 084de1
        ctx->Yi.c[13] = 0;
Packit Service 084de1
        ctx->Yi.c[14] = 0;
Packit Service 084de1
        ctx->Yi.c[15] = 1;
Packit Service 084de1
        ctr = 1;
Packit Service 084de1
    } else {
Packit Service 084de1
        size_t i;
Packit Service 084de1
        u64 len0 = len;
Packit Service 084de1
Packit Service 084de1
        /* Borrow ctx->Xi to calculate initial Yi */
Packit Service 084de1
        ctx->Xi.u[0] = 0;
Packit Service 084de1
        ctx->Xi.u[1] = 0;
Packit Service 084de1
Packit Service 084de1
        while (len >= 16) {
Packit Service 084de1
            for (i = 0; i < 16; ++i)
Packit Service 084de1
                ctx->Xi.c[i] ^= iv[i];
Packit Service 084de1
            GCM_MUL(ctx);
Packit Service 084de1
            iv += 16;
Packit Service 084de1
            len -= 16;
Packit Service 084de1
        }
Packit Service 084de1
        if (len) {
Packit Service 084de1
            for (i = 0; i < len; ++i)
Packit Service 084de1
                ctx->Xi.c[i] ^= iv[i];
Packit Service 084de1
            GCM_MUL(ctx);
Packit Service 084de1
        }
Packit Service 084de1
        len0 <<= 3;
Packit Service 084de1
        if (is_endian.little) {
Packit Service 084de1
#ifdef BSWAP8
Packit Service 084de1
            ctx->Xi.u[1] ^= BSWAP8(len0);
Packit Service 084de1
#else
Packit Service 084de1
            ctx->Xi.c[8] ^= (u8)(len0 >> 56);
Packit Service 084de1
            ctx->Xi.c[9] ^= (u8)(len0 >> 48);
Packit Service 084de1
            ctx->Xi.c[10] ^= (u8)(len0 >> 40);
Packit Service 084de1
            ctx->Xi.c[11] ^= (u8)(len0 >> 32);
Packit Service 084de1
            ctx->Xi.c[12] ^= (u8)(len0 >> 24);
Packit Service 084de1
            ctx->Xi.c[13] ^= (u8)(len0 >> 16);
Packit Service 084de1
            ctx->Xi.c[14] ^= (u8)(len0 >> 8);
Packit Service 084de1
            ctx->Xi.c[15] ^= (u8)(len0);
Packit Service 084de1
#endif
Packit Service 084de1
        } else {
Packit Service 084de1
            ctx->Xi.u[1] ^= len0;
Packit Service 084de1
        }
Packit Service 084de1
Packit Service 084de1
        GCM_MUL(ctx);
Packit Service 084de1
Packit Service 084de1
        if (is_endian.little)
Packit Service 084de1
#ifdef BSWAP4
Packit Service 084de1
            ctr = BSWAP4(ctx->Xi.d[3]);
Packit Service 084de1
#else
Packit Service 084de1
            ctr = GETU32(ctx->Xi.c + 12);
Packit Service 084de1
#endif
Packit Service 084de1
        else
Packit Service 084de1
            ctr = ctx->Xi.d[3];
Packit Service 084de1
Packit Service 084de1
        /* Copy borrowed Xi to Yi */
Packit Service 084de1
        ctx->Yi.u[0] = ctx->Xi.u[0];
Packit Service 084de1
        ctx->Yi.u[1] = ctx->Xi.u[1];
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    ctx->Xi.u[0] = 0;
Packit Service 084de1
    ctx->Xi.u[1] = 0;
Packit Service 084de1
Packit Service 084de1
    (*ctx->block) (ctx->Yi.c, ctx->EK0.c, ctx->key);
Packit Service 084de1
    ++ctr;
Packit Service 084de1
    if (is_endian.little)
Packit Service 084de1
#ifdef BSWAP4
Packit Service 084de1
        ctx->Yi.d[3] = BSWAP4(ctr);
Packit Service 084de1
#else
Packit Service 084de1
        PUTU32(ctx->Yi.c + 12, ctr);
Packit Service 084de1
#endif
Packit Service 084de1
    else
Packit Service 084de1
        ctx->Yi.d[3] = ctr;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const unsigned char *aad,
Packit Service 084de1
                      size_t len)
Packit Service 084de1
{
Packit Service 084de1
    size_t i;
Packit Service 084de1
    unsigned int n;
Packit Service 084de1
    u64 alen = ctx->len.u[0];
Packit Service 084de1
#ifdef GCM_FUNCREF_4BIT
Packit Service 084de1
    void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult;
Packit Service 084de1
# ifdef GHASH
Packit Service 084de1
    void (*gcm_ghash_p) (u64 Xi[2], const u128 Htable[16],
Packit Service 084de1
                         const u8 *inp, size_t len) = ctx->ghash;
Packit Service 084de1
# endif
Packit Service 084de1
#endif
Packit Service 084de1
Packit Service 084de1
    if (ctx->len.u[1])
Packit Service 084de1
        return -2;
Packit Service 084de1
Packit Service 084de1
    alen += len;
Packit Service 084de1
    if (alen > (U64(1) << 61) || (sizeof(len) == 8 && alen < len))
Packit Service 084de1
        return -1;
Packit Service 084de1
    ctx->len.u[0] = alen;
Packit Service 084de1
Packit Service 084de1
    n = ctx->ares;
Packit Service 084de1
    if (n) {
Packit Service 084de1
        while (n && len) {
Packit Service 084de1
            ctx->Xi.c[n] ^= *(aad++);
Packit Service 084de1
            --len;
Packit Service 084de1
            n = (n + 1) % 16;
Packit Service 084de1
        }
Packit Service 084de1
        if (n == 0)
Packit Service 084de1
            GCM_MUL(ctx);
Packit Service 084de1
        else {
Packit Service 084de1
            ctx->ares = n;
Packit Service 084de1
            return 0;
Packit Service 084de1
        }
Packit Service 084de1
    }
Packit Service 084de1
#ifdef GHASH
Packit Service 084de1
    if ((i = (len & (size_t)-16))) {
Packit Service 084de1
        GHASH(ctx, aad, i);
Packit Service 084de1
        aad += i;
Packit Service 084de1
        len -= i;
Packit Service 084de1
    }
Packit Service 084de1
#else
Packit Service 084de1
    while (len >= 16) {
Packit Service 084de1
        for (i = 0; i < 16; ++i)
Packit Service 084de1
            ctx->Xi.c[i] ^= aad[i];
Packit Service 084de1
        GCM_MUL(ctx);
Packit Service 084de1
        aad += 16;
Packit Service 084de1
        len -= 16;
Packit Service 084de1
    }
Packit Service 084de1
#endif
Packit Service 084de1
    if (len) {
Packit Service 084de1
        n = (unsigned int)len;
Packit Service 084de1
        for (i = 0; i < len; ++i)
Packit Service 084de1
            ctx->Xi.c[i] ^= aad[i];
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    ctx->ares = n;
Packit Service 084de1
    return 0;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx,
Packit Service 084de1
                          const unsigned char *in, unsigned char *out,
Packit Service 084de1
                          size_t len)
Packit Service 084de1
{
Packit Service 084de1
    const union {
Packit Service 084de1
        long one;
Packit Service 084de1
        char little;
Packit Service 084de1
    } is_endian = { 1 };
Packit Service 084de1
    unsigned int n, ctr, mres;
Packit Service 084de1
    size_t i;
Packit Service 084de1
    u64 mlen = ctx->len.u[1];
Packit Service 084de1
    block128_f block = ctx->block;
Packit Service 084de1
    void *key = ctx->key;
Packit Service 084de1
#ifdef GCM_FUNCREF_4BIT
Packit Service 084de1
    void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult;
Packit Service 084de1
# if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT)
Packit Service 084de1
    void (*gcm_ghash_p) (u64 Xi[2], const u128 Htable[16],
Packit Service 084de1
                         const u8 *inp, size_t len) = ctx->ghash;
Packit Service 084de1
# endif
Packit Service 084de1
#endif
Packit Service 084de1
Packit Service 084de1
    mlen += len;
Packit Service 084de1
    if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len))
Packit Service 084de1
        return -1;
Packit Service 084de1
    ctx->len.u[1] = mlen;
Packit Service 084de1
Packit Service 084de1
    mres = ctx->mres;
Packit Service 084de1
Packit Service 084de1
    if (ctx->ares) {
Packit Service 084de1
        /* First call to encrypt finalizes GHASH(AAD) */
Packit Service 084de1
#if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT)
Packit Service 084de1
        if (len == 0) {
Packit Service 084de1
            GCM_MUL(ctx);
Packit Service 084de1
            ctx->ares = 0;
Packit Service 084de1
            return 0;
Packit Service 084de1
        }
Packit Service 084de1
        memcpy(ctx->Xn, ctx->Xi.c, sizeof(ctx->Xi));
Packit Service 084de1
        ctx->Xi.u[0] = 0;
Packit Service 084de1
        ctx->Xi.u[1] = 0;
Packit Service 084de1
        mres = sizeof(ctx->Xi);
Packit Service 084de1
#else
Packit Service 084de1
        GCM_MUL(ctx);
Packit Service 084de1
#endif
Packit Service 084de1
        ctx->ares = 0;
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    if (is_endian.little)
Packit Service 084de1
#ifdef BSWAP4
Packit Service 084de1
        ctr = BSWAP4(ctx->Yi.d[3]);
Packit Service 084de1
#else
Packit Service 084de1
        ctr = GETU32(ctx->Yi.c + 12);
Packit Service 084de1
#endif
Packit Service 084de1
    else
Packit Service 084de1
        ctr = ctx->Yi.d[3];
Packit Service 084de1
Packit Service 084de1
    n = mres % 16;
Packit Service 084de1
#if !defined(OPENSSL_SMALL_FOOTPRINT)
Packit Service 084de1
    if (16 % sizeof(size_t) == 0) { /* always true actually */
Packit Service 084de1
        do {
Packit Service 084de1
            if (n) {
Packit Service 084de1
# if defined(GHASH)
Packit Service 084de1
                while (n && len) {
Packit Service 084de1
                    ctx->Xn[mres++] = *(out++) = *(in++) ^ ctx->EKi.c[n];
Packit Service 084de1
                    --len;
Packit Service 084de1
                    n = (n + 1) % 16;
Packit Service 084de1
                }
Packit Service 084de1
                if (n == 0) {
Packit Service 084de1
                    GHASH(ctx, ctx->Xn, mres);
Packit Service 084de1
                    mres = 0;
Packit Service 084de1
                } else {
Packit Service 084de1
                    ctx->mres = mres;
Packit Service 084de1
                    return 0;
Packit Service 084de1
                }
Packit Service 084de1
# else
Packit Service 084de1
                while (n && len) {
Packit Service 084de1
                    ctx->Xi.c[n] ^= *(out++) = *(in++) ^ ctx->EKi.c[n];
Packit Service 084de1
                    --len;
Packit Service 084de1
                    n = (n + 1) % 16;
Packit Service 084de1
                }
Packit Service 084de1
                if (n == 0) {
Packit Service 084de1
                    GCM_MUL(ctx);
Packit Service 084de1
                    mres = 0;
Packit Service 084de1
                } else {
Packit Service 084de1
                    ctx->mres = n;
Packit Service 084de1
                    return 0;
Packit Service 084de1
                }
Packit Service 084de1
# endif
Packit Service 084de1
            }
Packit Service 084de1
# if defined(STRICT_ALIGNMENT)
Packit Service 084de1
            if (((size_t)in | (size_t)out) % sizeof(size_t) != 0)
Packit Service 084de1
                break;
Packit Service 084de1
# endif
Packit Service 084de1
# if defined(GHASH)
Packit Service 084de1
            if (len >= 16 && mres) {
Packit Service 084de1
                GHASH(ctx, ctx->Xn, mres);
Packit Service 084de1
                mres = 0;
Packit Service 084de1
            }
Packit Service 084de1
#  if defined(GHASH_CHUNK)
Packit Service 084de1
            while (len >= GHASH_CHUNK) {
Packit Service 084de1
                size_t j = GHASH_CHUNK;
Packit Service 084de1
Packit Service 084de1
                while (j) {
Packit Service 084de1
                    size_t *out_t = (size_t *)out;
Packit Service 084de1
                    const size_t *in_t = (const size_t *)in;
Packit Service 084de1
Packit Service 084de1
                    (*block) (ctx->Yi.c, ctx->EKi.c, key);
Packit Service 084de1
                    ++ctr;
Packit Service 084de1
                    if (is_endian.little)
Packit Service 084de1
#   ifdef BSWAP4
Packit Service 084de1
                        ctx->Yi.d[3] = BSWAP4(ctr);
Packit Service 084de1
#   else
Packit Service 084de1
                        PUTU32(ctx->Yi.c + 12, ctr);
Packit Service 084de1
#   endif
Packit Service 084de1
                    else
Packit Service 084de1
                        ctx->Yi.d[3] = ctr;
Packit Service 084de1
                    for (i = 0; i < 16 / sizeof(size_t); ++i)
Packit Service 084de1
                        out_t[i] = in_t[i] ^ ctx->EKi.t[i];
Packit Service 084de1
                    out += 16;
Packit Service 084de1
                    in += 16;
Packit Service 084de1
                    j -= 16;
Packit Service 084de1
                }
Packit Service 084de1
                GHASH(ctx, out - GHASH_CHUNK, GHASH_CHUNK);
Packit Service 084de1
                len -= GHASH_CHUNK;
Packit Service 084de1
            }
Packit Service 084de1
#  endif
Packit Service 084de1
            if ((i = (len & (size_t)-16))) {
Packit Service 084de1
                size_t j = i;
Packit Service 084de1
Packit Service 084de1
                while (len >= 16) {
Packit Service 084de1
                    size_t *out_t = (size_t *)out;
Packit Service 084de1
                    const size_t *in_t = (const size_t *)in;
Packit Service 084de1
Packit Service 084de1
                    (*block) (ctx->Yi.c, ctx->EKi.c, key);
Packit Service 084de1
                    ++ctr;
Packit Service 084de1
                    if (is_endian.little)
Packit Service 084de1
#  ifdef BSWAP4
Packit Service 084de1
                        ctx->Yi.d[3] = BSWAP4(ctr);
Packit Service 084de1
#  else
Packit Service 084de1
                        PUTU32(ctx->Yi.c + 12, ctr);
Packit Service 084de1
#  endif
Packit Service 084de1
                    else
Packit Service 084de1
                        ctx->Yi.d[3] = ctr;
Packit Service 084de1
                    for (i = 0; i < 16 / sizeof(size_t); ++i)
Packit Service 084de1
                        out_t[i] = in_t[i] ^ ctx->EKi.t[i];
Packit Service 084de1
                    out += 16;
Packit Service 084de1
                    in += 16;
Packit Service 084de1
                    len -= 16;
Packit Service 084de1
                }
Packit Service 084de1
                GHASH(ctx, out - j, j);
Packit Service 084de1
            }
Packit Service 084de1
# else
Packit Service 084de1
            while (len >= 16) {
Packit Service 084de1
                size_t *out_t = (size_t *)out;
Packit Service 084de1
                const size_t *in_t = (const size_t *)in;
Packit Service 084de1
Packit Service 084de1
                (*block) (ctx->Yi.c, ctx->EKi.c, key);
Packit Service 084de1
                ++ctr;
Packit Service 084de1
                if (is_endian.little)
Packit Service 084de1
#  ifdef BSWAP4
Packit Service 084de1
                    ctx->Yi.d[3] = BSWAP4(ctr);
Packit Service 084de1
#  else
Packit Service 084de1
                    PUTU32(ctx->Yi.c + 12, ctr);
Packit Service 084de1
#  endif
Packit Service 084de1
                else
Packit Service 084de1
                    ctx->Yi.d[3] = ctr;
Packit Service 084de1
                for (i = 0; i < 16 / sizeof(size_t); ++i)
Packit Service 084de1
                    ctx->Xi.t[i] ^= out_t[i] = in_t[i] ^ ctx->EKi.t[i];
Packit Service 084de1
                GCM_MUL(ctx);
Packit Service 084de1
                out += 16;
Packit Service 084de1
                in += 16;
Packit Service 084de1
                len -= 16;
Packit Service 084de1
            }
Packit Service 084de1
# endif
Packit Service 084de1
            if (len) {
Packit Service 084de1
                (*block) (ctx->Yi.c, ctx->EKi.c, key);
Packit Service 084de1
                ++ctr;
Packit Service 084de1
                if (is_endian.little)
Packit Service 084de1
# ifdef BSWAP4
Packit Service 084de1
                    ctx->Yi.d[3] = BSWAP4(ctr);
Packit Service 084de1
# else
Packit Service 084de1
                    PUTU32(ctx->Yi.c + 12, ctr);
Packit Service 084de1
# endif
Packit Service 084de1
                else
Packit Service 084de1
                    ctx->Yi.d[3] = ctr;
Packit Service 084de1
# if defined(GHASH)
Packit Service 084de1
                while (len--) {
Packit Service 084de1
                    ctx->Xn[mres++] = out[n] = in[n] ^ ctx->EKi.c[n];
Packit Service 084de1
                    ++n;
Packit Service 084de1
                }
Packit Service 084de1
# else
Packit Service 084de1
                while (len--) {
Packit Service 084de1
                    ctx->Xi.c[n] ^= out[n] = in[n] ^ ctx->EKi.c[n];
Packit Service 084de1
                    ++n;
Packit Service 084de1
                }
Packit Service 084de1
                mres = n;
Packit Service 084de1
# endif
Packit Service 084de1
            }
Packit Service 084de1
Packit Service 084de1
            ctx->mres = mres;
Packit Service 084de1
            return 0;
Packit Service 084de1
        } while (0);
Packit Service 084de1
    }
Packit Service 084de1
#endif
Packit Service 084de1
    for (i = 0; i < len; ++i) {
Packit Service 084de1
        if (n == 0) {
Packit Service 084de1
            (*block) (ctx->Yi.c, ctx->EKi.c, key);
Packit Service 084de1
            ++ctr;
Packit Service 084de1
            if (is_endian.little)
Packit Service 084de1
#ifdef BSWAP4
Packit Service 084de1
                ctx->Yi.d[3] = BSWAP4(ctr);
Packit Service 084de1
#else
Packit Service 084de1
                PUTU32(ctx->Yi.c + 12, ctr);
Packit Service 084de1
#endif
Packit Service 084de1
            else
Packit Service 084de1
                ctx->Yi.d[3] = ctr;
Packit Service 084de1
        }
Packit Service 084de1
#if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT)
Packit Service 084de1
        ctx->Xn[mres++] = out[i] = in[i] ^ ctx->EKi.c[n];
Packit Service 084de1
        n = (n + 1) % 16;
Packit Service 084de1
        if (mres == sizeof(ctx->Xn)) {
Packit Service 084de1
            GHASH(ctx,ctx->Xn,sizeof(ctx->Xn));
Packit Service 084de1
            mres = 0;
Packit Service 084de1
        }
Packit Service 084de1
#else
Packit Service 084de1
        ctx->Xi.c[n] ^= out[i] = in[i] ^ ctx->EKi.c[n];
Packit Service 084de1
        mres = n = (n + 1) % 16;
Packit Service 084de1
        if (n == 0)
Packit Service 084de1
            GCM_MUL(ctx);
Packit Service 084de1
#endif
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    ctx->mres = mres;
Packit Service 084de1
    return 0;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx,
Packit Service 084de1
                          const unsigned char *in, unsigned char *out,
Packit Service 084de1
                          size_t len)
Packit Service 084de1
{
Packit Service 084de1
    const union {
Packit Service 084de1
        long one;
Packit Service 084de1
        char little;
Packit Service 084de1
    } is_endian = { 1 };
Packit Service 084de1
    unsigned int n, ctr, mres;
Packit Service 084de1
    size_t i;
Packit Service 084de1
    u64 mlen = ctx->len.u[1];
Packit Service 084de1
    block128_f block = ctx->block;
Packit Service 084de1
    void *key = ctx->key;
Packit Service 084de1
#ifdef GCM_FUNCREF_4BIT
Packit Service 084de1
    void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult;
Packit Service 084de1
# if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT)
Packit Service 084de1
    void (*gcm_ghash_p) (u64 Xi[2], const u128 Htable[16],
Packit Service 084de1
                         const u8 *inp, size_t len) = ctx->ghash;
Packit Service 084de1
# endif
Packit Service 084de1
#endif
Packit Service 084de1
Packit Service 084de1
    mlen += len;
Packit Service 084de1
    if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len))
Packit Service 084de1
        return -1;
Packit Service 084de1
    ctx->len.u[1] = mlen;
Packit Service 084de1
Packit Service 084de1
    mres = ctx->mres;
Packit Service 084de1
Packit Service 084de1
    if (ctx->ares) {
Packit Service 084de1
        /* First call to decrypt finalizes GHASH(AAD) */
Packit Service 084de1
#if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT)
Packit Service 084de1
        if (len == 0) {
Packit Service 084de1
            GCM_MUL(ctx);
Packit Service 084de1
            ctx->ares = 0;
Packit Service 084de1
            return 0;
Packit Service 084de1
        }
Packit Service 084de1
        memcpy(ctx->Xn, ctx->Xi.c, sizeof(ctx->Xi));
Packit Service 084de1
        ctx->Xi.u[0] = 0;
Packit Service 084de1
        ctx->Xi.u[1] = 0;
Packit Service 084de1
        mres = sizeof(ctx->Xi);
Packit Service 084de1
#else
Packit Service 084de1
        GCM_MUL(ctx);
Packit Service 084de1
#endif
Packit Service 084de1
        ctx->ares = 0;
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    if (is_endian.little)
Packit Service 084de1
#ifdef BSWAP4
Packit Service 084de1
        ctr = BSWAP4(ctx->Yi.d[3]);
Packit Service 084de1
#else
Packit Service 084de1
        ctr = GETU32(ctx->Yi.c + 12);
Packit Service 084de1
#endif
Packit Service 084de1
    else
Packit Service 084de1
        ctr = ctx->Yi.d[3];
Packit Service 084de1
Packit Service 084de1
    n = mres % 16;
Packit Service 084de1
#if !defined(OPENSSL_SMALL_FOOTPRINT)
Packit Service 084de1
    if (16 % sizeof(size_t) == 0) { /* always true actually */
Packit Service 084de1
        do {
Packit Service 084de1
            if (n) {
Packit Service 084de1
# if defined(GHASH)
Packit Service 084de1
                while (n && len) {
Packit Service 084de1
                    *(out++) = (ctx->Xn[mres++] = *(in++)) ^ ctx->EKi.c[n];
Packit Service 084de1
                    --len;
Packit Service 084de1
                    n = (n + 1) % 16;
Packit Service 084de1
                }
Packit Service 084de1
                if (n == 0) {
Packit Service 084de1
                    GHASH(ctx, ctx->Xn, mres);
Packit Service 084de1
                    mres = 0;
Packit Service 084de1
                } else {
Packit Service 084de1
                    ctx->mres = mres;
Packit Service 084de1
                    return 0;
Packit Service 084de1
                }
Packit Service 084de1
# else
Packit Service 084de1
                while (n && len) {
Packit Service 084de1
                    u8 c = *(in++);
Packit Service 084de1
                    *(out++) = c ^ ctx->EKi.c[n];
Packit Service 084de1
                    ctx->Xi.c[n] ^= c;
Packit Service 084de1
                    --len;
Packit Service 084de1
                    n = (n + 1) % 16;
Packit Service 084de1
                }
Packit Service 084de1
                if (n == 0) {
Packit Service 084de1
                    GCM_MUL(ctx);
Packit Service 084de1
                    mres = 0;
Packit Service 084de1
                } else {
Packit Service 084de1
                    ctx->mres = n;
Packit Service 084de1
                    return 0;
Packit Service 084de1
                }
Packit Service 084de1
# endif
Packit Service 084de1
            }
Packit Service 084de1
# if defined(STRICT_ALIGNMENT)
Packit Service 084de1
            if (((size_t)in | (size_t)out) % sizeof(size_t) != 0)
Packit Service 084de1
                break;
Packit Service 084de1
# endif
Packit Service 084de1
# if defined(GHASH)
Packit Service 084de1
            if (len >= 16 && mres) {
Packit Service 084de1
                GHASH(ctx, ctx->Xn, mres);
Packit Service 084de1
                mres = 0;
Packit Service 084de1
            }
Packit Service 084de1
#  if defined(GHASH_CHUNK)
Packit Service 084de1
            while (len >= GHASH_CHUNK) {
Packit Service 084de1
                size_t j = GHASH_CHUNK;
Packit Service 084de1
Packit Service 084de1
                GHASH(ctx, in, GHASH_CHUNK);
Packit Service 084de1
                while (j) {
Packit Service 084de1
                    size_t *out_t = (size_t *)out;
Packit Service 084de1
                    const size_t *in_t = (const size_t *)in;
Packit Service 084de1
Packit Service 084de1
                    (*block) (ctx->Yi.c, ctx->EKi.c, key);
Packit Service 084de1
                    ++ctr;
Packit Service 084de1
                    if (is_endian.little)
Packit Service 084de1
#   ifdef BSWAP4
Packit Service 084de1
                        ctx->Yi.d[3] = BSWAP4(ctr);
Packit Service 084de1
#   else
Packit Service 084de1
                        PUTU32(ctx->Yi.c + 12, ctr);
Packit Service 084de1
#   endif
Packit Service 084de1
                    else
Packit Service 084de1
                        ctx->Yi.d[3] = ctr;
Packit Service 084de1
                    for (i = 0; i < 16 / sizeof(size_t); ++i)
Packit Service 084de1
                        out_t[i] = in_t[i] ^ ctx->EKi.t[i];
Packit Service 084de1
                    out += 16;
Packit Service 084de1
                    in += 16;
Packit Service 084de1
                    j -= 16;
Packit Service 084de1
                }
Packit Service 084de1
                len -= GHASH_CHUNK;
Packit Service 084de1
            }
Packit Service 084de1
#  endif
Packit Service 084de1
            if ((i = (len & (size_t)-16))) {
Packit Service 084de1
                GHASH(ctx, in, i);
Packit Service 084de1
                while (len >= 16) {
Packit Service 084de1
                    size_t *out_t = (size_t *)out;
Packit Service 084de1
                    const size_t *in_t = (const size_t *)in;
Packit Service 084de1
Packit Service 084de1
                    (*block) (ctx->Yi.c, ctx->EKi.c, key);
Packit Service 084de1
                    ++ctr;
Packit Service 084de1
                    if (is_endian.little)
Packit Service 084de1
#  ifdef BSWAP4
Packit Service 084de1
                        ctx->Yi.d[3] = BSWAP4(ctr);
Packit Service 084de1
#  else
Packit Service 084de1
                        PUTU32(ctx->Yi.c + 12, ctr);
Packit Service 084de1
#  endif
Packit Service 084de1
                    else
Packit Service 084de1
                        ctx->Yi.d[3] = ctr;
Packit Service 084de1
                    for (i = 0; i < 16 / sizeof(size_t); ++i)
Packit Service 084de1
                        out_t[i] = in_t[i] ^ ctx->EKi.t[i];
Packit Service 084de1
                    out += 16;
Packit Service 084de1
                    in += 16;
Packit Service 084de1
                    len -= 16;
Packit Service 084de1
                }
Packit Service 084de1
            }
Packit Service 084de1
# else
Packit Service 084de1
            while (len >= 16) {
Packit Service 084de1
                size_t *out_t = (size_t *)out;
Packit Service 084de1
                const size_t *in_t = (const size_t *)in;
Packit Service 084de1
Packit Service 084de1
                (*block) (ctx->Yi.c, ctx->EKi.c, key);
Packit Service 084de1
                ++ctr;
Packit Service 084de1
                if (is_endian.little)
Packit Service 084de1
#  ifdef BSWAP4
Packit Service 084de1
                    ctx->Yi.d[3] = BSWAP4(ctr);
Packit Service 084de1
#  else
Packit Service 084de1
                    PUTU32(ctx->Yi.c + 12, ctr);
Packit Service 084de1
#  endif
Packit Service 084de1
                else
Packit Service 084de1
                    ctx->Yi.d[3] = ctr;
Packit Service 084de1
                for (i = 0; i < 16 / sizeof(size_t); ++i) {
Packit Service 084de1
                    size_t c = in[i];
Packit Service 084de1
                    out[i] = c ^ ctx->EKi.t[i];
Packit Service 084de1
                    ctx->Xi.t[i] ^= c;
Packit Service 084de1
                }
Packit Service 084de1
                GCM_MUL(ctx);
Packit Service 084de1
                out += 16;
Packit Service 084de1
                in += 16;
Packit Service 084de1
                len -= 16;
Packit Service 084de1
            }
Packit Service 084de1
# endif
Packit Service 084de1
            if (len) {
Packit Service 084de1
                (*block) (ctx->Yi.c, ctx->EKi.c, key);
Packit Service 084de1
                ++ctr;
Packit Service 084de1
                if (is_endian.little)
Packit Service 084de1
# ifdef BSWAP4
Packit Service 084de1
                    ctx->Yi.d[3] = BSWAP4(ctr);
Packit Service 084de1
# else
Packit Service 084de1
                    PUTU32(ctx->Yi.c + 12, ctr);
Packit Service 084de1
# endif
Packit Service 084de1
                else
Packit Service 084de1
                    ctx->Yi.d[3] = ctr;
Packit Service 084de1
# if defined(GHASH)
Packit Service 084de1
                while (len--) {
Packit Service 084de1
                    out[n] = (ctx->Xn[mres++] = in[n]) ^ ctx->EKi.c[n];
Packit Service 084de1
                    ++n;
Packit Service 084de1
                }
Packit Service 084de1
# else
Packit Service 084de1
                while (len--) {
Packit Service 084de1
                    u8 c = in[n];
Packit Service 084de1
                    ctx->Xi.c[n] ^= c;
Packit Service 084de1
                    out[n] = c ^ ctx->EKi.c[n];
Packit Service 084de1
                    ++n;
Packit Service 084de1
                }
Packit Service 084de1
                mres = n;
Packit Service 084de1
# endif
Packit Service 084de1
            }
Packit Service 084de1
Packit Service 084de1
            ctx->mres = mres;
Packit Service 084de1
            return 0;
Packit Service 084de1
        } while (0);
Packit Service 084de1
    }
Packit Service 084de1
#endif
Packit Service 084de1
    for (i = 0; i < len; ++i) {
Packit Service 084de1
        u8 c;
Packit Service 084de1
        if (n == 0) {
Packit Service 084de1
            (*block) (ctx->Yi.c, ctx->EKi.c, key);
Packit Service 084de1
            ++ctr;
Packit Service 084de1
            if (is_endian.little)
Packit Service 084de1
#ifdef BSWAP4
Packit Service 084de1
                ctx->Yi.d[3] = BSWAP4(ctr);
Packit Service 084de1
#else
Packit Service 084de1
                PUTU32(ctx->Yi.c + 12, ctr);
Packit Service 084de1
#endif
Packit Service 084de1
            else
Packit Service 084de1
                ctx->Yi.d[3] = ctr;
Packit Service 084de1
        }
Packit Service 084de1
#if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT)
Packit Service 084de1
        out[i] = (ctx->Xn[mres++] = c = in[i]) ^ ctx->EKi.c[n];
Packit Service 084de1
        n = (n + 1) % 16;
Packit Service 084de1
        if (mres == sizeof(ctx->Xn)) {
Packit Service 084de1
            GHASH(ctx,ctx->Xn,sizeof(ctx->Xn));
Packit Service 084de1
            mres = 0;
Packit Service 084de1
        }
Packit Service 084de1
#else
Packit Service 084de1
        c = in[i];
Packit Service 084de1
        out[i] = c ^ ctx->EKi.c[n];
Packit Service 084de1
        ctx->Xi.c[n] ^= c;
Packit Service 084de1
        mres = n = (n + 1) % 16;
Packit Service 084de1
        if (n == 0)
Packit Service 084de1
            GCM_MUL(ctx);
Packit Service 084de1
#endif
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    ctx->mres = mres;
Packit Service 084de1
    return 0;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx,
Packit Service 084de1
                                const unsigned char *in, unsigned char *out,
Packit Service 084de1
                                size_t len, ctr128_f stream)
Packit Service 084de1
{
Packit Service 084de1
#if defined(OPENSSL_SMALL_FOOTPRINT)
Packit Service 084de1
    return CRYPTO_gcm128_encrypt(ctx, in, out, len);
Packit Service 084de1
#else
Packit Service 084de1
    const union {
Packit Service 084de1
        long one;
Packit Service 084de1
        char little;
Packit Service 084de1
    } is_endian = { 1 };
Packit Service 084de1
    unsigned int n, ctr, mres;
Packit Service 084de1
    size_t i;
Packit Service 084de1
    u64 mlen = ctx->len.u[1];
Packit Service 084de1
    void *key = ctx->key;
Packit Service 084de1
# ifdef GCM_FUNCREF_4BIT
Packit Service 084de1
    void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult;
Packit Service 084de1
#  ifdef GHASH
Packit Service 084de1
    void (*gcm_ghash_p) (u64 Xi[2], const u128 Htable[16],
Packit Service 084de1
                         const u8 *inp, size_t len) = ctx->ghash;
Packit Service 084de1
#  endif
Packit Service 084de1
# endif
Packit Service 084de1
Packit Service 084de1
    mlen += len;
Packit Service 084de1
    if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len))
Packit Service 084de1
        return -1;
Packit Service 084de1
    ctx->len.u[1] = mlen;
Packit Service 084de1
Packit Service 084de1
    mres = ctx->mres;
Packit Service 084de1
Packit Service 084de1
    if (ctx->ares) {
Packit Service 084de1
        /* First call to encrypt finalizes GHASH(AAD) */
Packit Service 084de1
#if defined(GHASH)
Packit Service 084de1
        if (len == 0) {
Packit Service 084de1
            GCM_MUL(ctx);
Packit Service 084de1
            ctx->ares = 0;
Packit Service 084de1
            return 0;
Packit Service 084de1
        }
Packit Service 084de1
        memcpy(ctx->Xn, ctx->Xi.c, sizeof(ctx->Xi));
Packit Service 084de1
        ctx->Xi.u[0] = 0;
Packit Service 084de1
        ctx->Xi.u[1] = 0;
Packit Service 084de1
        mres = sizeof(ctx->Xi);
Packit Service 084de1
#else
Packit Service 084de1
        GCM_MUL(ctx);
Packit Service 084de1
#endif
Packit Service 084de1
        ctx->ares = 0;
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    if (is_endian.little)
Packit Service 084de1
# ifdef BSWAP4
Packit Service 084de1
        ctr = BSWAP4(ctx->Yi.d[3]);
Packit Service 084de1
# else
Packit Service 084de1
        ctr = GETU32(ctx->Yi.c + 12);
Packit Service 084de1
# endif
Packit Service 084de1
    else
Packit Service 084de1
        ctr = ctx->Yi.d[3];
Packit Service 084de1
Packit Service 084de1
    n = mres % 16;
Packit Service 084de1
    if (n) {
Packit Service 084de1
# if defined(GHASH)
Packit Service 084de1
        while (n && len) {
Packit Service 084de1
            ctx->Xn[mres++] = *(out++) = *(in++) ^ ctx->EKi.c[n];
Packit Service 084de1
            --len;
Packit Service 084de1
            n = (n + 1) % 16;
Packit Service 084de1
        }
Packit Service 084de1
        if (n == 0) {
Packit Service 084de1
            GHASH(ctx, ctx->Xn, mres);
Packit Service 084de1
            mres = 0;
Packit Service 084de1
        } else {
Packit Service 084de1
            ctx->mres = mres;
Packit Service 084de1
            return 0;
Packit Service 084de1
        }
Packit Service 084de1
# else
Packit Service 084de1
        while (n && len) {
Packit Service 084de1
            ctx->Xi.c[n] ^= *(out++) = *(in++) ^ ctx->EKi.c[n];
Packit Service 084de1
            --len;
Packit Service 084de1
            n = (n + 1) % 16;
Packit Service 084de1
        }
Packit Service 084de1
        if (n == 0) {
Packit Service 084de1
            GCM_MUL(ctx);
Packit Service 084de1
            mres = 0;
Packit Service 084de1
        } else {
Packit Service 084de1
            ctx->mres = n;
Packit Service 084de1
            return 0;
Packit Service 084de1
        }
Packit Service 084de1
# endif
Packit Service 084de1
    }
Packit Service 084de1
# if defined(GHASH)
Packit Service 084de1
        if (len >= 16 && mres) {
Packit Service 084de1
            GHASH(ctx, ctx->Xn, mres);
Packit Service 084de1
            mres = 0;
Packit Service 084de1
        }
Packit Service 084de1
#  if defined(GHASH_CHUNK)
Packit Service 084de1
    while (len >= GHASH_CHUNK) {
Packit Service 084de1
        (*stream) (in, out, GHASH_CHUNK / 16, key, ctx->Yi.c);
Packit Service 084de1
        ctr += GHASH_CHUNK / 16;
Packit Service 084de1
        if (is_endian.little)
Packit Service 084de1
#   ifdef BSWAP4
Packit Service 084de1
            ctx->Yi.d[3] = BSWAP4(ctr);
Packit Service 084de1
#   else
Packit Service 084de1
            PUTU32(ctx->Yi.c + 12, ctr);
Packit Service 084de1
#   endif
Packit Service 084de1
        else
Packit Service 084de1
            ctx->Yi.d[3] = ctr;
Packit Service 084de1
        GHASH(ctx, out, GHASH_CHUNK);
Packit Service 084de1
        out += GHASH_CHUNK;
Packit Service 084de1
        in += GHASH_CHUNK;
Packit Service 084de1
        len -= GHASH_CHUNK;
Packit Service 084de1
    }
Packit Service 084de1
#  endif
Packit Service 084de1
# endif
Packit Service 084de1
    if ((i = (len & (size_t)-16))) {
Packit Service 084de1
        size_t j = i / 16;
Packit Service 084de1
Packit Service 084de1
        (*stream) (in, out, j, key, ctx->Yi.c);
Packit Service 084de1
        ctr += (unsigned int)j;
Packit Service 084de1
        if (is_endian.little)
Packit Service 084de1
# ifdef BSWAP4
Packit Service 084de1
            ctx->Yi.d[3] = BSWAP4(ctr);
Packit Service 084de1
# else
Packit Service 084de1
            PUTU32(ctx->Yi.c + 12, ctr);
Packit Service 084de1
# endif
Packit Service 084de1
        else
Packit Service 084de1
            ctx->Yi.d[3] = ctr;
Packit Service 084de1
        in += i;
Packit Service 084de1
        len -= i;
Packit Service 084de1
# if defined(GHASH)
Packit Service 084de1
        GHASH(ctx, out, i);
Packit Service 084de1
        out += i;
Packit Service 084de1
# else
Packit Service 084de1
        while (j--) {
Packit Service 084de1
            for (i = 0; i < 16; ++i)
Packit Service 084de1
                ctx->Xi.c[i] ^= out[i];
Packit Service 084de1
            GCM_MUL(ctx);
Packit Service 084de1
            out += 16;
Packit Service 084de1
        }
Packit Service 084de1
# endif
Packit Service 084de1
    }
Packit Service 084de1
    if (len) {
Packit Service 084de1
        (*ctx->block) (ctx->Yi.c, ctx->EKi.c, key);
Packit Service 084de1
        ++ctr;
Packit Service 084de1
        if (is_endian.little)
Packit Service 084de1
# ifdef BSWAP4
Packit Service 084de1
            ctx->Yi.d[3] = BSWAP4(ctr);
Packit Service 084de1
# else
Packit Service 084de1
            PUTU32(ctx->Yi.c + 12, ctr);
Packit Service 084de1
# endif
Packit Service 084de1
        else
Packit Service 084de1
            ctx->Yi.d[3] = ctr;
Packit Service 084de1
        while (len--) {
Packit Service 084de1
# if defined(GHASH)
Packit Service 084de1
            ctx->Xn[mres++] = out[n] = in[n] ^ ctx->EKi.c[n];
Packit Service 084de1
# else
Packit Service 084de1
            ctx->Xi.c[mres++] ^= out[n] = in[n] ^ ctx->EKi.c[n];
Packit Service 084de1
# endif
Packit Service 084de1
            ++n;
Packit Service 084de1
        }
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    ctx->mres = mres;
Packit Service 084de1
    return 0;
Packit Service 084de1
#endif
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx,
Packit Service 084de1
                                const unsigned char *in, unsigned char *out,
Packit Service 084de1
                                size_t len, ctr128_f stream)
Packit Service 084de1
{
Packit Service 084de1
#if defined(OPENSSL_SMALL_FOOTPRINT)
Packit Service 084de1
    return CRYPTO_gcm128_decrypt(ctx, in, out, len);
Packit Service 084de1
#else
Packit Service 084de1
    const union {
Packit Service 084de1
        long one;
Packit Service 084de1
        char little;
Packit Service 084de1
    } is_endian = { 1 };
Packit Service 084de1
    unsigned int n, ctr, mres;
Packit Service 084de1
    size_t i;
Packit Service 084de1
    u64 mlen = ctx->len.u[1];
Packit Service 084de1
    void *key = ctx->key;
Packit Service 084de1
# ifdef GCM_FUNCREF_4BIT
Packit Service 084de1
    void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult;
Packit Service 084de1
#  ifdef GHASH
Packit Service 084de1
    void (*gcm_ghash_p) (u64 Xi[2], const u128 Htable[16],
Packit Service 084de1
                         const u8 *inp, size_t len) = ctx->ghash;
Packit Service 084de1
#  endif
Packit Service 084de1
# endif
Packit Service 084de1
Packit Service 084de1
    mlen += len;
Packit Service 084de1
    if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len))
Packit Service 084de1
        return -1;
Packit Service 084de1
    ctx->len.u[1] = mlen;
Packit Service 084de1
Packit Service 084de1
    mres = ctx->mres;
Packit Service 084de1
Packit Service 084de1
    if (ctx->ares) {
Packit Service 084de1
        /* First call to decrypt finalizes GHASH(AAD) */
Packit Service 084de1
# if defined(GHASH)
Packit Service 084de1
        if (len == 0) {
Packit Service 084de1
            GCM_MUL(ctx);
Packit Service 084de1
            ctx->ares = 0;
Packit Service 084de1
            return 0;
Packit Service 084de1
        }
Packit Service 084de1
        memcpy(ctx->Xn, ctx->Xi.c, sizeof(ctx->Xi));
Packit Service 084de1
        ctx->Xi.u[0] = 0;
Packit Service 084de1
        ctx->Xi.u[1] = 0;
Packit Service 084de1
        mres = sizeof(ctx->Xi);
Packit Service 084de1
# else
Packit Service 084de1
        GCM_MUL(ctx);
Packit Service 084de1
# endif
Packit Service 084de1
        ctx->ares = 0;
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    if (is_endian.little)
Packit Service 084de1
# ifdef BSWAP4
Packit Service 084de1
        ctr = BSWAP4(ctx->Yi.d[3]);
Packit Service 084de1
# else
Packit Service 084de1
        ctr = GETU32(ctx->Yi.c + 12);
Packit Service 084de1
# endif
Packit Service 084de1
    else
Packit Service 084de1
        ctr = ctx->Yi.d[3];
Packit Service 084de1
Packit Service 084de1
    n = mres % 16;
Packit Service 084de1
    if (n) {
Packit Service 084de1
# if defined(GHASH)
Packit Service 084de1
        while (n && len) {
Packit Service 084de1
            *(out++) = (ctx->Xn[mres++] = *(in++)) ^ ctx->EKi.c[n];
Packit Service 084de1
            --len;
Packit Service 084de1
            n = (n + 1) % 16;
Packit Service 084de1
        }
Packit Service 084de1
        if (n == 0) {
Packit Service 084de1
            GHASH(ctx, ctx->Xn, mres);
Packit Service 084de1
            mres = 0;
Packit Service 084de1
        } else {
Packit Service 084de1
            ctx->mres = mres;
Packit Service 084de1
            return 0;
Packit Service 084de1
        }
Packit Service 084de1
# else
Packit Service 084de1
        while (n && len) {
Packit Service 084de1
            u8 c = *(in++);
Packit Service 084de1
            *(out++) = c ^ ctx->EKi.c[n];
Packit Service 084de1
            ctx->Xi.c[n] ^= c;
Packit Service 084de1
            --len;
Packit Service 084de1
            n = (n + 1) % 16;
Packit Service 084de1
        }
Packit Service 084de1
        if (n == 0) {
Packit Service 084de1
            GCM_MUL(ctx);
Packit Service 084de1
            mres = 0;
Packit Service 084de1
        } else {
Packit Service 084de1
            ctx->mres = n;
Packit Service 084de1
            return 0;
Packit Service 084de1
        }
Packit Service 084de1
# endif
Packit Service 084de1
    }
Packit Service 084de1
# if defined(GHASH)
Packit Service 084de1
    if (len >= 16 && mres) {
Packit Service 084de1
        GHASH(ctx, ctx->Xn, mres);
Packit Service 084de1
        mres = 0;
Packit Service 084de1
    }
Packit Service 084de1
#  if defined(GHASH_CHUNK)
Packit Service 084de1
    while (len >= GHASH_CHUNK) {
Packit Service 084de1
        GHASH(ctx, in, GHASH_CHUNK);
Packit Service 084de1
        (*stream) (in, out, GHASH_CHUNK / 16, key, ctx->Yi.c);
Packit Service 084de1
        ctr += GHASH_CHUNK / 16;
Packit Service 084de1
        if (is_endian.little)
Packit Service 084de1
#   ifdef BSWAP4
Packit Service 084de1
            ctx->Yi.d[3] = BSWAP4(ctr);
Packit Service 084de1
#   else
Packit Service 084de1
            PUTU32(ctx->Yi.c + 12, ctr);
Packit Service 084de1
#   endif
Packit Service 084de1
        else
Packit Service 084de1
            ctx->Yi.d[3] = ctr;
Packit Service 084de1
        out += GHASH_CHUNK;
Packit Service 084de1
        in += GHASH_CHUNK;
Packit Service 084de1
        len -= GHASH_CHUNK;
Packit Service 084de1
    }
Packit Service 084de1
#  endif
Packit Service 084de1
# endif
Packit Service 084de1
    if ((i = (len & (size_t)-16))) {
Packit Service 084de1
        size_t j = i / 16;
Packit Service 084de1
Packit Service 084de1
# if defined(GHASH)
Packit Service 084de1
        GHASH(ctx, in, i);
Packit Service 084de1
# else
Packit Service 084de1
        while (j--) {
Packit Service 084de1
            size_t k;
Packit Service 084de1
            for (k = 0; k < 16; ++k)
Packit Service 084de1
                ctx->Xi.c[k] ^= in[k];
Packit Service 084de1
            GCM_MUL(ctx);
Packit Service 084de1
            in += 16;
Packit Service 084de1
        }
Packit Service 084de1
        j = i / 16;
Packit Service 084de1
        in -= i;
Packit Service 084de1
# endif
Packit Service 084de1
        (*stream) (in, out, j, key, ctx->Yi.c);
Packit Service 084de1
        ctr += (unsigned int)j;
Packit Service 084de1
        if (is_endian.little)
Packit Service 084de1
# ifdef BSWAP4
Packit Service 084de1
            ctx->Yi.d[3] = BSWAP4(ctr);
Packit Service 084de1
# else
Packit Service 084de1
            PUTU32(ctx->Yi.c + 12, ctr);
Packit Service 084de1
# endif
Packit Service 084de1
        else
Packit Service 084de1
            ctx->Yi.d[3] = ctr;
Packit Service 084de1
        out += i;
Packit Service 084de1
        in += i;
Packit Service 084de1
        len -= i;
Packit Service 084de1
    }
Packit Service 084de1
    if (len) {
Packit Service 084de1
        (*ctx->block) (ctx->Yi.c, ctx->EKi.c, key);
Packit Service 084de1
        ++ctr;
Packit Service 084de1
        if (is_endian.little)
Packit Service 084de1
# ifdef BSWAP4
Packit Service 084de1
            ctx->Yi.d[3] = BSWAP4(ctr);
Packit Service 084de1
# else
Packit Service 084de1
            PUTU32(ctx->Yi.c + 12, ctr);
Packit Service 084de1
# endif
Packit Service 084de1
        else
Packit Service 084de1
            ctx->Yi.d[3] = ctr;
Packit Service 084de1
        while (len--) {
Packit Service 084de1
# if defined(GHASH)
Packit Service 084de1
            out[n] = (ctx->Xn[mres++] = in[n]) ^ ctx->EKi.c[n];
Packit Service 084de1
# else
Packit Service 084de1
            u8 c = in[n];
Packit Service 084de1
            ctx->Xi.c[mres++] ^= c;
Packit Service 084de1
            out[n] = c ^ ctx->EKi.c[n];
Packit Service 084de1
# endif
Packit Service 084de1
            ++n;
Packit Service 084de1
        }
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    ctx->mres = mres;
Packit Service 084de1
    return 0;
Packit Service 084de1
#endif
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const unsigned char *tag,
Packit Service 084de1
                         size_t len)
Packit Service 084de1
{
Packit Service 084de1
    const union {
Packit Service 084de1
        long one;
Packit Service 084de1
        char little;
Packit Service 084de1
    } is_endian = { 1 };
Packit Service 084de1
    u64 alen = ctx->len.u[0] << 3;
Packit Service 084de1
    u64 clen = ctx->len.u[1] << 3;
Packit Service 084de1
#ifdef GCM_FUNCREF_4BIT
Packit Service 084de1
    void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult;
Packit Service 084de1
# if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT)
Packit Service 084de1
    void (*gcm_ghash_p) (u64 Xi[2], const u128 Htable[16],
Packit Service 084de1
                         const u8 *inp, size_t len) = ctx->ghash;
Packit Service 084de1
# endif
Packit Service 084de1
#endif
Packit Service 084de1
Packit Service 084de1
#if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT)
Packit Service 084de1
    u128 bitlen;
Packit Service 084de1
    unsigned int mres = ctx->mres;
Packit Service 084de1
Packit Service 084de1
    if (mres) {
Packit Service 084de1
        unsigned blocks = (mres + 15) & -16;
Packit Service 084de1
Packit Service 084de1
        memset(ctx->Xn + mres, 0, blocks - mres);
Packit Service 084de1
        mres = blocks;
Packit Service 084de1
        if (mres == sizeof(ctx->Xn)) {
Packit Service 084de1
            GHASH(ctx, ctx->Xn, mres);
Packit Service 084de1
            mres = 0;
Packit Service 084de1
        }
Packit Service 084de1
    } else if (ctx->ares) {
Packit Service 084de1
        GCM_MUL(ctx);
Packit Service 084de1
    }
Packit Service 084de1
#else
Packit Service 084de1
    if (ctx->mres || ctx->ares)
Packit Service 084de1
        GCM_MUL(ctx);
Packit Service 084de1
#endif
Packit Service 084de1
Packit Service 084de1
    if (is_endian.little) {
Packit Service 084de1
#ifdef BSWAP8
Packit Service 084de1
        alen = BSWAP8(alen);
Packit Service 084de1
        clen = BSWAP8(clen);
Packit Service 084de1
#else
Packit Service 084de1
        u8 *p = ctx->len.c;
Packit Service 084de1
Packit Service 084de1
        ctx->len.u[0] = alen;
Packit Service 084de1
        ctx->len.u[1] = clen;
Packit Service 084de1
Packit Service 084de1
        alen = (u64)GETU32(p) << 32 | GETU32(p + 4);
Packit Service 084de1
        clen = (u64)GETU32(p + 8) << 32 | GETU32(p + 12);
Packit Service 084de1
#endif
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
#if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT)
Packit Service 084de1
    bitlen.hi = alen;
Packit Service 084de1
    bitlen.lo = clen;
Packit Service 084de1
    memcpy(ctx->Xn + mres, &bitlen, sizeof(bitlen));
Packit Service 084de1
    mres += sizeof(bitlen);
Packit Service 084de1
    GHASH(ctx, ctx->Xn, mres);
Packit Service 084de1
#else
Packit Service 084de1
    ctx->Xi.u[0] ^= alen;
Packit Service 084de1
    ctx->Xi.u[1] ^= clen;
Packit Service 084de1
    GCM_MUL(ctx);
Packit Service 084de1
#endif
Packit Service 084de1
Packit Service 084de1
    ctx->Xi.u[0] ^= ctx->EK0.u[0];
Packit Service 084de1
    ctx->Xi.u[1] ^= ctx->EK0.u[1];
Packit Service 084de1
Packit Service 084de1
    if (tag && len <= sizeof(ctx->Xi))
Packit Service 084de1
        return CRYPTO_memcmp(ctx->Xi.c, tag, len);
Packit Service 084de1
    else
Packit Service 084de1
        return -1;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, unsigned char *tag, size_t len)
Packit Service 084de1
{
Packit Service 084de1
    CRYPTO_gcm128_finish(ctx, NULL, 0);
Packit Service 084de1
    memcpy(tag, ctx->Xi.c,
Packit Service 084de1
           len <= sizeof(ctx->Xi.c) ? len : sizeof(ctx->Xi.c));
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
GCM128_CONTEXT *CRYPTO_gcm128_new(void *key, block128_f block)
Packit Service 084de1
{
Packit Service 084de1
    GCM128_CONTEXT *ret;
Packit Service 084de1
Packit Service 084de1
    if ((ret = OPENSSL_malloc(sizeof(*ret))) != NULL)
Packit Service 084de1
        CRYPTO_gcm128_init(ret, key, block);
Packit Service 084de1
Packit Service 084de1
    return ret;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
void CRYPTO_gcm128_release(GCM128_CONTEXT *ctx)
Packit Service 084de1
{
Packit Service 084de1
    OPENSSL_clear_free(ctx, sizeof(*ctx));
Packit Service 084de1
}