Skip to content

Commit

Permalink
Add gcm ciphers (aes and aria) to providers.
Browse files Browse the repository at this point in the history
The code has been modularized so that it can be shared by algorithms.

A fixed size IV is now used instead of being allocated.
The IV is not set into the low level struct now until the update (it uses an
iv_state for this purpose).

Hardware specific methods have been added to a PROV_GCM_HW object.

The S390 code has been changed to just contain methods that can be accessed in
a modular way. There are equivalent generic methods also for the other
platforms.

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Patrick Steuer <patrick.steuer@de.ibm.com>
(Merged from #9231)
  • Loading branch information
slontis committed Jul 31, 2019
1 parent f5b7f99 commit a672a02
Show file tree
Hide file tree
Showing 18 changed files with 1,467 additions and 59 deletions.
3 changes: 3 additions & 0 deletions crypto/err/openssl.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2694,7 +2694,10 @@ PROV_R_BAD_DECRYPT:100:bad decrypt
PROV_R_CIPHER_OPERATION_FAILED:102:cipher operation failed
PROV_R_FAILED_TO_GET_PARAMETER:103:failed to get parameter
PROV_R_FAILED_TO_SET_PARAMETER:104:failed to set parameter
PROV_R_INVALID_AAD:108:invalid aad
PROV_R_INVALID_IVLEN:109:invalid ivlen
PROV_R_INVALID_KEYLEN:105:invalid keylen
PROV_R_INVALID_TAG:110:invalid tag
PROV_R_OUTPUT_BUFFER_TOO_SMALL:106:output buffer too small
PROV_R_WRONG_FINAL_BLOCK_LENGTH:107:wrong final block length
RAND_R_ADDITIONAL_INPUT_TOO_LONG:102:additional input too long
Expand Down
8 changes: 7 additions & 1 deletion crypto/evp/evp_enc.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2019 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
Expand Down Expand Up @@ -163,6 +163,12 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
case NID_aes_256_ctr:
case NID_aes_192_ctr:
case NID_aes_128_ctr:
case NID_aes_256_gcm:
case NID_aes_192_gcm:
case NID_aes_128_gcm:
case NID_aria_256_gcm:
case NID_aria_192_gcm:
case NID_aria_128_gcm:
break;
default:
goto legacy;
Expand Down
8 changes: 7 additions & 1 deletion crypto/evp/evp_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,13 @@ int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher)

int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx)
{
return EVP_CIPHER_iv_length(ctx->cipher);
int ok, v = EVP_CIPHER_iv_length(ctx->cipher);
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };

params[0] = OSSL_PARAM_construct_int(OSSL_CIPHER_PARAM_IVLEN, &v);
ok = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->provctx, params);

return ok != 0 ? v : -1;
}

const unsigned char *EVP_CIPHER_CTX_original_iv(const EVP_CIPHER_CTX *ctx)
Expand Down
4 changes: 2 additions & 2 deletions crypto/modes/build.info
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ IF[{- !$disabled{asm} -}]
ENDIF
ENDIF

$COMMON=cbc128.c ctr128.c cfb128.c ofb128.c $MODESASM
$COMMON=cbc128.c ctr128.c cfb128.c ofb128.c gcm128.c $MODESASM
SOURCE[../../libcrypto]=$COMMON \
cts128.c gcm128.c ccm128.c xts128.c wrap128.c ocb128.c siv128.c
cts128.c ccm128.c xts128.c wrap128.c ocb128.c siv128.c
DEFINE[../../libcrypto]=$MODESDEF
SOURCE[../../providers/fips]=$COMMON
DEFINE[../../providers/fips]=$MODESDEF
Expand Down
2 changes: 2 additions & 0 deletions doc/man3/EVP_EncryptInit.pod
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ all parameters to NULL except B<type> in an initial call and supply
the remaining parameters in subsequent calls, all of which have B<type>
set to NULL. This is done when the default cipher parameters are not
appropriate.
For EVP_CIPH_GCM_MODE the IV will be generated internally if it is not
specified.

EVP_EncryptUpdate() encrypts B<inl> bytes from the buffer B<in> and
writes the encrypted version to B<out>. This function can be called
Expand Down
107 changes: 63 additions & 44 deletions providers/common/ciphers/aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <openssl/core_names.h>
#include <openssl/evp.h>
#include <openssl/params.h>
#include <openssl/rand.h>
#include "internal/cryptlib.h"
#include "internal/provider_algs.h"
#include "ciphers_locl.h"
Expand Down Expand Up @@ -248,50 +249,63 @@ static int aes_cipher(void *vctx,
return 1;
}

#define IMPLEMENT_cipher(lcmode, UCMODE, flags, kbits, blkbits, ivbits) \
static OSSL_OP_cipher_get_params_fn aes_##kbits##_##lcmode##_get_params; \
static int aes_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \
{ \
OSSL_PARAM *p; \
\
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_MODE); \
if (p != NULL) { \
if (!OSSL_PARAM_set_int(p, EVP_CIPH_##UCMODE##_MODE)) \
return 0; \
} \
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_FLAGS); \
if (p != NULL) { \
if (!OSSL_PARAM_set_ulong(p, (flags))) \
return 0; \
} \
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); \
if (p != NULL) { \
if (!OSSL_PARAM_set_int(p, (kbits) / 8)) \
return 0; \
} \
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_BLOCK_SIZE); \
if (p != NULL) { \
if (!OSSL_PARAM_set_int(p, (blkbits) / 8)) \
return 0; \
} \
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); \
if (p != NULL) { \
if (!OSSL_PARAM_set_int(p, (ivbits) / 8)) \
return 0; \
} \
\
return 1; \
} \
static OSSL_OP_cipher_newctx_fn aes_##kbits##_##lcmode##_newctx; \
static void *aes_##kbits##_##lcmode##_newctx(void *provctx) \
{ \
PROV_AES_KEY *ctx = OPENSSL_zalloc(sizeof(*ctx)); \
\
ctx->pad = 1; \
ctx->keylen = ((kbits) / 8); \
ctx->ciph = PROV_AES_CIPHER_##lcmode(ctx->keylen); \
ctx->mode = EVP_CIPH_##UCMODE##_MODE; \
return ctx; \
static void *aes_new_ctx(void *provctx, size_t mode, size_t kbits,
const PROV_AES_CIPHER *ciph)
{
PROV_AES_KEY *ctx = OPENSSL_zalloc(sizeof(*ctx));

ctx->pad = 1;
ctx->keylen = kbits / 8;
ctx->ciph = ciph;
ctx->mode = mode;
return ctx;
}

int aes_get_params(OSSL_PARAM params[], int md, unsigned long flags,
int kbits, int blkbits, int ivbits)
{
OSSL_PARAM *p;

p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_MODE);
if (p != NULL) {
if (!OSSL_PARAM_set_int(p, md))
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_FLAGS);
if (p != NULL) {
if (!OSSL_PARAM_set_ulong(p, flags))
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL) {
if (!OSSL_PARAM_set_int(p, kbits / 8))
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_BLOCK_SIZE);
if (p != NULL) {
if (!OSSL_PARAM_set_int(p, blkbits / 8))
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
if (p != NULL) {
if (!OSSL_PARAM_set_int(p, ivbits / 8))
return 0;
}
return 1;
}

#define IMPLEMENT_cipher(lcmode, UCMODE, flags, kbits, blkbits, ivbits) \
static OSSL_OP_cipher_get_params_fn aes_##kbits##_##lcmode##_get_params; \
static int aes_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \
{ \
return aes_get_params(params, EVP_CIPH_##UCMODE##_MODE, flags, kbits, \
blkbits, ivbits); \
} \
static OSSL_OP_cipher_newctx_fn aes_##kbits##_##lcmode##_newctx; \
static void *aes_##kbits##_##lcmode##_newctx(void *provctx) \
{ \
return aes_new_ctx(provctx, EVP_CIPH_##UCMODE##_MODE, kbits, \
PROV_AES_CIPHER_##lcmode(kbits / 8)); \
}

/* ECB */
Expand Down Expand Up @@ -351,6 +365,11 @@ static int aes_ctx_get_params(void *vctx, OSSL_PARAM params[])
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
OSSL_PARAM *p;

p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
if (p != NULL) {
if (!OSSL_PARAM_set_int(p, AES_BLOCK_SIZE))
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PADDING);
if (p != NULL && !OSSL_PARAM_set_int(p, ctx->pad)) {
PROVerr(PROV_F_AES_CTX_GET_PARAMS, PROV_R_FAILED_TO_SET_PARAMETER);
Expand Down
8 changes: 3 additions & 5 deletions providers/common/ciphers/aes_basic.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,16 @@
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/

#include <string.h>
#include <assert.h>
#include <openssl/opensslconf.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <string.h>
#include <assert.h>
#include <openssl/aes.h>
#include "internal/modes_int.h"
#include "internal/evp_int.h"
#include <openssl/rand.h>
#include <openssl/cmac.h>
#include "ciphers_locl.h"
#include "internal/evp_int.h"
#include "internal/providercommonerr.h"
#include "internal/aes_platform.h"

Expand Down
8 changes: 4 additions & 4 deletions providers/common/ciphers/build.info
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
LIBS=../../../libcrypto
SOURCE[../../../libcrypto]=\
block.c aes.c aes_basic.c
$COMMON=block.c aes.c aes_basic.c gcm.c gcm_hw.c

SOURCE[../../../libcrypto]=$COMMON
INCLUDE[../../../libcrypto]=. ../../../crypto

SOURCE[../../fips]=\
block.c aes.c aes_basic.c
SOURCE[../../fips]=$COMMON
INCLUDE[../../fips]=. ../../../crypto
120 changes: 120 additions & 0 deletions providers/common/ciphers/ciphers_gcm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@

/*
* Copyright 2019 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
*/

#include <openssl/aes.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 64
#define GCM_TAG_MAX_SIZE 16

typedef struct prov_gcm_ctx_st {
int enc; /* Set to 1 if we are encrypting or 0 otherwise */
int mode; /* The mode that we are using */
size_t keylen;
int ivlen;
size_t ivlen_min;
int taglen;
int key_set; /* Set if key initialised */
int iv_state; /* set to one of IV_STATE_XXX */
int iv_gen_rand; /* No IV was specified, so generate a rand IV */
int iv_gen; /* It is OK to generate IVs */
int tls_aad_pad_sz;
int 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 pad : 1; /* Whether padding should be used or not */

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 */

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

typedef struct prov_aes_gcm_ctx_st {
PROV_GCM_CTX base; /* must be first entry in struct */
union {
OSSL_UNION_ALIGN;
AES_KEY ks;
} ks; /* AES key schedule to use */

/* Platform specific data */
union {
int dummy;
#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
struct {
union {
OSSL_UNION_ALIGN;
S390X_KMA_PARAMS kma;
} param;
unsigned int fc;
unsigned char ares[16];
unsigned char mres[16];
unsigned char kres[16];
int areslen;
int mreslen;
int kreslen;
int res;
} s390x;
#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */
} plat;
} PROV_AES_GCM_CTX;

OSSL_CIPHER_FUNC(int, GCM_setkey, (PROV_GCM_CTX *ctx, const unsigned char *key,
size_t keylen));
OSSL_CIPHER_FUNC(int, GCM_setiv, (PROV_GCM_CTX *dat, const unsigned char *iv,
size_t ivlen));
OSSL_CIPHER_FUNC(int, GCM_aadupdate, (PROV_GCM_CTX *ctx,
const unsigned char *aad, size_t aadlen));
OSSL_CIPHER_FUNC(int, GCM_cipherupdate, (PROV_GCM_CTX *ctx,
const unsigned char *in, size_t len,
unsigned char *out));
OSSL_CIPHER_FUNC(int, GCM_cipherfinal, (PROV_GCM_CTX *ctx, unsigned char *tag));
OSSL_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;
};
const PROV_GCM_HW *PROV_AES_HW_gcm(size_t keybits);

#if !defined(OPENSSL_NO_ARIA) && !defined(FIPS_MODE)

#include "internal/aria.h"

typedef struct prov_aria_gcm_ctx_st {
PROV_GCM_CTX base; /* must be first entry in struct */
union {
OSSL_UNION_ALIGN;
ARIA_KEY ks;
} ks;
} PROV_ARIA_GCM_CTX;
const PROV_GCM_HW *PROV_ARIA_HW_gcm(size_t keybits);

#endif /* !defined(OPENSSL_NO_ARIA) && !defined(FIPS_MODE) */

0 comments on commit a672a02

Please sign in to comment.