summaryrefslogtreecommitdiffstats
path: root/providers/implementations/include/prov/ciphercommon_gcm.h
blob: ee0b23b92785da99e6bbdfc27ceb3581316ddbeb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
 * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the Apache License 2.0 (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

#ifndef OSSL_PROV_CIPHERCOMMON_GCM_H
# define OSSL_PROV_CIPHERCOMMON_GCM_H
# pragma once

# include <openssl/aes.h>
# include "ciphercommon_aead.h"

typedef struct prov_gcm_hw_st PROV_GCM_HW;

# define GCM_IV_DEFAULT_SIZE 12 /* IV's for AES_GCM should normally be 12 bytes */
# define GCM_IV_MAX_SIZE     (1024 / 8)
# define GCM_TAG_MAX_SIZE    16

# if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
/*-
 * KMA-GCM-AES parameter block - begin
 * (see z/Architecture Principles of Operation >= SA22-7832-11)
 */
typedef struct S390X_kma_params_st {
    unsigned char reserved[12];
    union {
        unsigned int w;
        unsigned char b[4];
    } cv; /* 32 bit counter value */
    union {
        unsigned long long g[2];
        unsigned char b[16];
    } t; /* tag */
    unsigned char h[16]; /* hash subkey */
    unsigned long long taadl; /* total AAD length */
    unsigned long long tpcl; /* total plaintxt/ciphertxt len */
    union {
        unsigned long long g[2];
        unsigned int w[4];
    } j0;                   /* initial counter value */
    unsigned char k[32];    /* key */
} S390X_KMA_PARAMS;

# endif

typedef struct prov_gcm_ctx_st {
    unsigned int mode;          /* The mode that we are using */
    size_t keylen;
    size_t ivlen;
    size_t taglen;
    size_t tls_aad_pad_sz;
    size_t tls_aad_len;         /* TLS AAD length */
    uint64_t tls_enc_records;   /* Number of TLS records encrypted */

    /*
     * num contains the number of bytes of |iv| which are valid for modes that
     * manage partial blocks themselves.
     */
    size_t num;
    size_t bufsz;               /* Number of bytes in buf */
    uint64_t flags;

    unsigned int iv_state;      /* set to one of IV_STATE_XXX */
    unsigned int enc:1;         /* Set to 1 if we are encrypting or 0 otherwise */
    unsigned int pad:1;         /* Whether padding should be used or not */
    unsigned int key_set:1;     /* Set if key initialised */
    unsigned int iv_gen_rand:1; /* No IV was specified, so generate a rand IV */
    unsigned int iv_gen:1;      /* It is OK to generate IVs */

    unsigned char iv[GCM_IV_MAX_SIZE]; /* Buffer to use for IV's */
    unsigned char buf[AES_BLOCK_SIZE]; /* Buffer of partial blocks processed via update calls */

    OSSL_LIB_CTX *libctx;    /* needed for rand calls */
    const PROV_GCM_HW *hw;  /* hardware specific methods */
    GCM128_CONTEXT gcm;
    ctr128_f ctr;
} PROV_GCM_CTX;

PROV_CIPHER_FUNC(int, GCM_setkey, (PROV_GCM_CTX *ctx, const unsigned char *key,
                                   size_t keylen));
PROV_CIPHER_FUNC(int, GCM_setiv, (PROV_GCM_CTX *dat, const unsigned char *iv,
                                  size_t ivlen));
PROV_CIPHER_FUNC(int, GCM_aadupdate, (PROV_GCM_CTX *ctx,
                                      const unsigned char *aad, size_t aadlen));
PROV_CIPHER_FUNC(int, GCM_cipherupdate, (PROV_GCM_CTX *ctx,
                                         const unsigned char *in, size_t len,
                                         unsigned char *out));
PROV_CIPHER_FUNC(int, GCM_cipherfinal, (PROV_GCM_CTX *ctx, unsigned char *tag));
PROV_CIPHER_FUNC(int, GCM_oneshot, (PROV_GCM_CTX *ctx, unsigned char *aad,
                                    size_t aad_len, const unsigned char *in,
                                    size_t in_len, unsigned char *out,
                                    unsigned char *tag, size_t taglen));
struct prov_gcm_hw_st {
  OSSL_GCM_setkey_fn setkey;
  OSSL_GCM_setiv_fn setiv;
  OSSL_GCM_aadupdate_fn aadupdate;
  OSSL_GCM_cipherupdate_fn cipherupdate;
  OSSL_GCM_cipherfinal_fn cipherfinal;
  OSSL_GCM_oneshot_fn oneshot;
};

OSSL_FUNC_cipher_encrypt_init_fn ossl_gcm_einit;
OSSL_FUNC_cipher_decrypt_init_fn ossl_gcm_dinit;
OSSL_FUNC_cipher_get_ctx_params_fn ossl_gcm_get_ctx_params;
OSSL_FUNC_cipher_set_ctx_params_fn ossl_gcm_set_ctx_params;
OSSL_FUNC_cipher_cipher_fn ossl_gcm_cipher;
OSSL_FUNC_cipher_update_fn ossl_gcm_stream_update;
OSSL_FUNC_cipher_final_fn ossl_gcm_stream_final;
void ossl_gcm_initctx(void *provctx, PROV_GCM_CTX *ctx, size_t keybits,
                      const PROV_GCM_HW *hw);

int ossl_gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv, size_t ivlen);
int ossl_gcm_aad_update(PROV_GCM_CTX *ctx, const unsigned char *aad,
                        size_t aad_len);
int ossl_gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag);
int ossl_gcm_one_shot(PROV_GCM_CTX *ctx, unsigned char *aad, size_t aad_len,
                      const unsigned char *in, size_t in_len,
                      unsigned char *out, unsigned char *tag, size_t tag_len);
int ossl_gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in,
                           size_t len, unsigned char *out);

# define GCM_HW_SET_KEY_CTR_FN(ks, fn_set_enc_key, fn_block, fn_ctr)            \
    fn_set_enc_key(key, keylen * 8, ks);                                       \
    CRYPTO_gcm128_init(&ctx->gcm, ks, (block128_f)fn_block);                   \
    ctx->ctr = (ctr128_f)fn_ctr;                                               \
    ctx->key_set = 1;

#endif