Commit 74d38a86 authored by Patrick Steuer's avatar Patrick Steuer Committed by Andy Polyakov
Browse files

s390x assembly pack: add KMF code path for aes-cfb/cfb8

parent dacd2a87
Loading
Loading
Loading
Loading
+121 −13
Original line number Diff line number Diff line
@@ -989,6 +989,24 @@ typedef struct {
    int res;
} S390X_AES_OFB_CTX;

typedef struct {
    union {
        double align;
        /*-
         * KMF-AES parameter block - begin
         * (see z/Architecture Principles of Operation >= SA22-7832-08)
         */
        struct {
            unsigned char cv[16];
            unsigned char k[32];
        } param;
        /* KMF-AES parameter block - end */
    } kmf;
    unsigned int fc;

    int res;
} S390X_AES_CFB_CTX;

typedef struct {
    union {
        double align;
@@ -1208,26 +1226,116 @@ static int s390x_aes_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
    return 1;
}

# define S390X_aes_128_cfb_CAPABLE	0
# define S390X_aes_192_cfb_CAPABLE	0
# define S390X_aes_256_cfb_CAPABLE	0
# define S390X_AES_CFB_CTX		EVP_AES_KEY
# define S390X_aes_128_cfb_CAPABLE (S390X_aes_128_CAPABLE &&		\
                                    (OPENSSL_s390xcap_P.kmf[0] &	\
                                     S390X_CAPBIT(S390X_AES_128)))
# define S390X_aes_192_cfb_CAPABLE (S390X_aes_192_CAPABLE &&		\
                                    (OPENSSL_s390xcap_P.kmf[0] &	\
                                     S390X_CAPBIT(S390X_AES_192)))
# define S390X_aes_256_cfb_CAPABLE (S390X_aes_256_CAPABLE &&		\
                                    (OPENSSL_s390xcap_P.kmf[0] &	\
                                     S390X_CAPBIT(S390X_AES_256)))

static int s390x_aes_cfb_init_key(EVP_CIPHER_CTX *ctx,
                                  const unsigned char *key,
                                  const unsigned char *ivec, int enc)
{
    S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx);
    const unsigned char *iv = EVP_CIPHER_CTX_original_iv(ctx);
    const int keylen = EVP_CIPHER_CTX_key_length(ctx);
    const int ivlen = EVP_CIPHER_CTX_iv_length(ctx);

    cctx->fc = S390X_AES_FC(keylen);
    cctx->fc |= 16 << 24;   /* 16 bytes cipher feedback */
    if (!enc)
        cctx->fc |= S390X_DECRYPT;

# define s390x_aes_cfb_init_key aes_init_key
    cctx->res = 0;
    memcpy(cctx->kmf.param.cv, iv, ivlen);
    memcpy(cctx->kmf.param.k, key, keylen);
    return 1;
}

# define s390x_aes_cfb_cipher aes_cfb_cipher
static int s390x_aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
                                const unsigned char *in, size_t len);
                                const unsigned char *in, size_t len)
{
    S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx);
    const int keylen = EVP_CIPHER_CTX_key_length(ctx);
    const int enc = EVP_CIPHER_CTX_encrypting(ctx);
    int n = cctx->res;
    int rem;
    unsigned char tmp;

# define S390X_aes_128_cfb8_CAPABLE	0
# define S390X_aes_192_cfb8_CAPABLE	0
# define S390X_aes_256_cfb8_CAPABLE	0
    while (n && len) {
        tmp = *in;
        *out = cctx->kmf.param.cv[n] ^ tmp;
        cctx->kmf.param.cv[n] = enc ? *out : tmp;
        n = (n + 1) & 0xf;
        --len;
        ++in;
        ++out;
    }

# define s390x_aes_cfb8_init_key aes_init_key
    rem = len & 0xf;

    len &= ~(size_t)0xf;
    if (len) {
        s390x_kmf(in, len, out, cctx->fc, &cctx->kmf.param);

        out += len;
        in += len;
    }

    if (rem) {
        s390x_km(cctx->kmf.param.cv, 16, cctx->kmf.param.cv,
                 S390X_AES_FC(keylen), cctx->kmf.param.k);

        while (rem--) {
            tmp = in[n];
            out[n] = cctx->kmf.param.cv[n] ^ tmp;
            cctx->kmf.param.cv[n] = enc ? out[n] : tmp;
            ++n;
        }
    }

    cctx->res = n;
    return 1;
}

# define S390X_aes_128_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] &	\
                                     S390X_CAPBIT(S390X_AES_128))
# define S390X_aes_192_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] &	\
                                     S390X_CAPBIT(S390X_AES_192))
# define S390X_aes_256_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] &	\
                                     S390X_CAPBIT(S390X_AES_256))

static int s390x_aes_cfb8_init_key(EVP_CIPHER_CTX *ctx,
                                   const unsigned char *key,
                                   const unsigned char *ivec, int enc)
{
    S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx);
    const unsigned char *iv = EVP_CIPHER_CTX_original_iv(ctx);
    const int keylen = EVP_CIPHER_CTX_key_length(ctx);
    const int ivlen = EVP_CIPHER_CTX_iv_length(ctx);

    cctx->fc = S390X_AES_FC(keylen);
    cctx->fc |= 1 << 24;   /* 1 byte cipher feedback */
    if (!enc)
        cctx->fc |= S390X_DECRYPT;

    memcpy(cctx->kmf.param.cv, iv, ivlen);
    memcpy(cctx->kmf.param.k, key, keylen);
    return 1;
}

# define s390x_aes_cfb8_cipher aes_cfb8_cipher
static int s390x_aes_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
                                 const unsigned char *in, size_t len);
                                 const unsigned char *in, size_t len)
{
    S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx);

    s390x_kmf(in, len, out, cctx->fc, &cctx->kmf.param);
    return 1;
}

# define S390X_aes_128_cfb1_CAPABLE	0
# define S390X_aes_192_cfb1_CAPABLE	0
+2 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ void s390x_kmac(const unsigned char *in, size_t len, unsigned int fc,
                void *param);
void s390x_kmo(const unsigned char *in, size_t len, unsigned char *out,
               unsigned int fc, void *param);
void s390x_kmf(const unsigned char *in, size_t len, unsigned char *out,
               unsigned int fc, void *param);
void s390x_kma(const unsigned char *aad, size_t alen, const unsigned char *in,
               size_t len, unsigned char *out, unsigned int fc, void *param);

+21 −0
Original line number Diff line number Diff line
@@ -325,6 +325,27 @@ s390x_kmo:
___
}

################
# void s390x_kmf(const unsigned char *in, size_t len, unsigned char *out,
#                unsigned int fc, void *param)
{
my ($in,$len,$out,$fc,$param) = map("%r$_",(2..6));
$code.=<<___;
.globl	s390x_kmf
.type	s390x_kmf,\@function
.align	16
s390x_kmf:
	lr	%r0,$fc
	l${g}r	%r1,$param

	.long	0xb92a0042	# kmf $out,$in
	brc	1,.-4		# pay attention to "partial completion"

	br	$ra
.size	s390x_kmf,.-s390x_kmf
___
}

################
# void s390x_kma(const unsigned char *aad, size_t alen,
#                const unsigned char *in, size_t len,