Commit 64adf9aa authored by Matt Caswell's avatar Matt Caswell
Browse files

Fix the S390X support for the basic AES ciphers

parent 3a7b15e4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -231,7 +231,7 @@ static int aes_cipher(void *vctx, unsigned char *out, const unsigned char *in,
    \
        ctx->pad = 1; \
        ctx->keylen = (len / 8); \
        ctx->ciph = PROV_AES_CIPHER_##lcmode(); \
        ctx->ciph = PROV_AES_CIPHER_##lcmode(ctx->keylen); \
        ctx->mode = EVP_CIPH_##UCMODE##_MODE; \
        return ctx; \
    }
+113 −207
Original line number Diff line number Diff line
@@ -186,7 +186,7 @@ static const PROV_AES_CIPHER aesni_##mode = { \
static const PROV_AES_CIPHER aes_##mode = { \
        aes_init_key,                   \
        aes_##mode##_cipher}; \
const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(void) \
const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(size_t keylen) \
{ return AESNI_CAPABLE?&aesni_##mode:&aes_##mode; }


@@ -358,7 +358,7 @@ static const PROV_AES_CIPHER aes_t4_##mode = { \
static const PROV_AES_CIPHER aes_##mode = { \
        aes_init_key,                   \
        aes_##mode##_cipher}; \
const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(void) \
const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(size_t keylen) \
{ return SPARC_AES_CAPABLE?&aes_t4_##mode:&aes_##mode; }


@@ -368,57 +368,6 @@ const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(void) \
 */
# include "s390x_arch.h"

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

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

    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;

/* Convert key size to function code: [16,24,32] -> [18,19,20]. */
# define S390X_AES_FC(keylen)  (S390X_AES_128 + ((((keylen) << 3) - 128) >> 6))

@@ -431,8 +380,8 @@ typedef struct {
                                S390X_CAPBIT(S390X_AES_256))

# define s390x_aes_init_key aes_init_key
static int s390x_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                              const unsigned char *iv, int enc);
static int s390x_aes_init_key(PROV_AES_KEY *dat, const unsigned char *key,
                              size_t keylen);

# define S390X_aes_128_cbc_CAPABLE  1	/* checked by callee */
# define S390X_aes_192_cbc_CAPABLE  1
@@ -442,34 +391,29 @@ static int s390x_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
# define s390x_aes_cbc_init_key aes_init_key

# define s390x_aes_cbc_cipher aes_cbc_cipher
static int s390x_aes_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static int s390x_aes_cbc_cipher(PROV_AES_KEY *dat, unsigned char *out,
                                const unsigned char *in, size_t len);

# define S390X_aes_128_ecb_CAPABLE  S390X_aes_128_CAPABLE
# define S390X_aes_192_ecb_CAPABLE  S390X_aes_192_CAPABLE
# define S390X_aes_256_ecb_CAPABLE  S390X_aes_256_CAPABLE

static int s390x_aes_ecb_init_key(EVP_CIPHER_CTX *ctx,
                                  const unsigned char *key,
                                  const unsigned char *iv, int enc)
static int s390x_aes_ecb_init_key(PROV_AES_KEY *dat, const unsigned char *key,
                                  size_t keylen)
{
    S390X_AES_ECB_CTX *cctx = EVP_C_DATA(S390X_AES_ECB_CTX, ctx);
    const int keylen = EVP_CIPHER_CTX_key_length(ctx);
    dat->plat.s390x.fc = S390X_AES_FC(keylen);
    if (!dat->enc)
        dat->plat.s390x.fc |= S390X_DECRYPT;

    cctx->fc = S390X_AES_FC(keylen);
    if (!enc)
        cctx->fc |= S390X_DECRYPT;

    memcpy(cctx->km.param.k, key, keylen);
    memcpy(dat->plat.s390x.param.km.k, key, keylen);
    return 1;
}

static int s390x_aes_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static int s390x_aes_ecb_cipher(PROV_AES_KEY *dat, unsigned char *out,
                                const unsigned char *in, size_t len)
{
    S390X_AES_ECB_CTX *cctx = EVP_C_DATA(S390X_AES_ECB_CTX, ctx);

    s390x_km(in, len, out, cctx->fc, &cctx->km.param);
    s390x_km(in, len, out, dat->plat.s390x.fc,
             &dat->plat.s390x.param.km);
    return 1;
}

@@ -483,31 +427,24 @@ static int s390x_aes_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
                                    (OPENSSL_s390xcap_P.kmo[0] &    \
                                     S390X_CAPBIT(S390X_AES_256)))

static int s390x_aes_ofb_init_key(EVP_CIPHER_CTX *ctx,
                                  const unsigned char *key,
                                  const unsigned char *ivec, int enc)
static int s390x_aes_ofb_init_key(PROV_AES_KEY *dat, const unsigned char *key,
                                  size_t keylen)
{
    S390X_AES_OFB_CTX *cctx = EVP_C_DATA(S390X_AES_OFB_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);

    memcpy(cctx->kmo.param.cv, iv, ivlen);
    memcpy(cctx->kmo.param.k, key, keylen);
    cctx->fc = S390X_AES_FC(keylen);
    cctx->res = 0;
    memcpy(dat->plat.s390x.param.kmo_kmf.cv, dat->iv, AES_BLOCK_SIZE);
    memcpy(dat->plat.s390x.param.kmo_kmf.k, key, keylen);
    dat->plat.s390x.fc = S390X_AES_FC(keylen);
    dat->plat.s390x.res = 0;
    return 1;
}

static int s390x_aes_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static int s390x_aes_ofb_cipher(PROV_AES_KEY *dat, unsigned char *out,
                                const unsigned char *in, size_t len)
{
    S390X_AES_OFB_CTX *cctx = EVP_C_DATA(S390X_AES_OFB_CTX, ctx);
    int n = cctx->res;
    int n = dat->plat.s390x.res;
    int rem;

    while (n && len) {
        *out = *in ^ cctx->kmo.param.cv[n];
        *out = *in ^ dat->plat.s390x.param.kmo_kmf.cv[n];
        n = (n + 1) & 0xf;
        --len;
        ++in;
@@ -518,23 +455,25 @@ static int s390x_aes_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,

    len &= ~(size_t)0xf;
    if (len) {
        s390x_kmo(in, len, out, cctx->fc, &cctx->kmo.param);
        s390x_kmo(in, len, out, dat->plat.s390x.fc,
                  &dat->plat.s390x.param.kmo_kmf);

        out += len;
        in += len;
    }

    if (rem) {
        s390x_km(cctx->kmo.param.cv, 16, cctx->kmo.param.cv, cctx->fc,
                 cctx->kmo.param.k);
        s390x_km(dat->plat.s390x.param.kmo_kmf.cv, 16,
                 dat->plat.s390x.param.kmo_kmf.cv, dat->plat.s390x.fc,
                 dat->plat.s390x.param.kmo_kmf.k);

        while (rem--) {
            out[n] = in[n] ^ cctx->kmo.param.cv[n];
            out[n] = in[n] ^ dat->plat.s390x.param.kmo_kmf.cv[n];
            ++n;
        }
    }

    cctx->res = n;
    dat->plat.s390x.res = n;
    return 1;
}

@@ -548,40 +487,31 @@ static int s390x_aes_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
                                    (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)
static int s390x_aes_cfb_init_key(PROV_AES_KEY *dat, const unsigned char *key,
                                  size_t keylen)
{
    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;

    cctx->res = 0;
    memcpy(cctx->kmf.param.cv, iv, ivlen);
    memcpy(cctx->kmf.param.k, key, keylen);
    dat->plat.s390x.fc = S390X_AES_FC(keylen);
    dat->plat.s390x.fc |= 16 << 24;   /* 16 bytes cipher feedback */
    if (!dat->enc)
        dat->plat.s390x.fc |= S390X_DECRYPT;

    dat->plat.s390x.res = 0;
    memcpy(dat->plat.s390x.param.kmo_kmf.cv, dat->iv, AES_BLOCK_SIZE);
    memcpy(dat->plat.s390x.param.kmo_kmf.k, key, keylen);
    return 1;
}

static int s390x_aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static int s390x_aes_cfb_cipher(PROV_AES_KEY *dat, unsigned char *out,
                                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 n = dat->plat.s390x.res;
    int rem;
    unsigned char tmp;

    while (n && len) {
        tmp = *in;
        *out = cctx->kmf.param.cv[n] ^ tmp;
        cctx->kmf.param.cv[n] = enc ? *out : tmp;
        *out = dat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
        dat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? *out : tmp;
        n = (n + 1) & 0xf;
        --len;
        ++in;
@@ -592,25 +522,27 @@ static int s390x_aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,

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

        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);
        s390x_km(dat->plat.s390x.param.kmo_kmf.cv, 16,
                 dat->plat.s390x.param.kmo_kmf.cv,
                 S390X_AES_FC(dat->keylen), dat->plat.s390x.param.kmo_kmf.k);

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

    cctx->res = n;
    dat->plat.s390x.res = n;
    return 1;
}

@@ -621,31 +553,24 @@ static int s390x_aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
# 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)
static int s390x_aes_cfb8_init_key(PROV_AES_KEY *dat, const unsigned char *key,
                                  size_t keylen)
{
    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);
    dat->plat.s390x.fc = S390X_AES_FC(keylen);
    dat->plat.s390x.fc |= 1 << 24;   /* 1 byte cipher feedback */
    if (!dat->enc)
        dat->plat.s390x.fc |= S390X_DECRYPT;

    memcpy(dat->plat.s390x.param.kmo_kmf.cv, dat->iv, AES_BLOCK_SIZE);
    memcpy(dat->plat.s390x.param.kmo_kmf.k, key, keylen);
    return 1;
}

static int s390x_aes_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static int s390x_aes_cfb8_cipher(PROV_AES_KEY *dat, unsigned char *out,
                                 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);
    s390x_kmf(in, len, out, dat->plat.s390x.fc,
              &dat->plat.s390x.param.kmo_kmf);
    return 1;
}

@@ -656,7 +581,7 @@ static int s390x_aes_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
# define s390x_aes_cfb1_init_key aes_init_key

# define s390x_aes_cfb1_cipher aes_cfb1_cipher
static int s390x_aes_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static int s390x_aes_cfb1_cipher(PROV_AES_KEY *dat, unsigned char *out,
                                 const unsigned char *in, size_t len);

# define S390X_aes_128_ctr_CAPABLE  1	/* checked by callee */
@@ -667,45 +592,26 @@ static int s390x_aes_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
# define s390x_aes_ctr_init_key aes_init_key

# define s390x_aes_ctr_cipher aes_ctr_cipher
static int s390x_aes_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static int s390x_aes_ctr_cipher(PROV_AES_KEY *dat, unsigned char *out,
                                const unsigned char *in, size_t len);


# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,	\
                              MODE,flags)				\
static const EVP_CIPHER s390x_aes_##keylen##_##mode = {			\
    nid##_##keylen##_##nmode,blocksize,					\
    keylen / 8,								\
    ivlen,								\
    flags | EVP_CIPH_##MODE##_MODE,					\
# define BLOCK_CIPHER_generic_prov(mode) \
static const PROV_AES_CIPHER s390x_aes_##mode = { \
        s390x_aes_##mode##_init_key,    \
    s390x_aes_##mode##_cipher,						\
    NULL,								\
    sizeof(S390X_AES_##MODE##_CTX),					\
    NULL,								\
    NULL,								\
    NULL,								\
    NULL								\
        s390x_aes_##mode##_cipher       \
};  \
static const EVP_CIPHER aes_##keylen##_##mode = {			\
    nid##_##keylen##_##nmode,						\
    blocksize,								\
    keylen / 8,								\
    ivlen,								\
    flags | EVP_CIPH_##MODE##_MODE,					\
static const PROV_AES_CIPHER aes_##mode = { \
        aes_init_key,           \
    aes_##mode##_cipher,						\
    NULL,								\
    sizeof(PROV_AES_KEY),						\
    NULL,								\
    NULL,								\
    NULL,								\
    NULL								\
        aes_##mode##_cipher     \
}; \
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void)			\
const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(size_t keylen) \
{   \
    return S390X_aes_##keylen##_##mode##_CAPABLE ?			\
           &s390x_aes_##keylen##_##mode : &aes_##keylen##_##mode;	\
    if ((keylen == 128 && S390X_aes_128_##mode##_CAPABLE)           \
            || (keylen == 192 && S390X_aes_192_##mode##_CAPABLE)    \
            || (keylen == 256 && S390X_aes_256_##mode##_CAPABLE))   \
        return &s390x_aes_##mode;   \
    \
    return &aes_##mode; \
}

#else
@@ -714,7 +620,7 @@ const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
static const PROV_AES_CIPHER aes_##mode = { \
        aes_init_key,                   \
        aes_##mode##_cipher}; \
const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(void) \
const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(size_t keylen) \
{ return &aes_##mode; }

#endif
+38 −7
Original line number Diff line number Diff line
@@ -23,6 +23,37 @@ typedef struct prov_aes_key_st {
        ctr128_f ctr;
    } stream;

    /* Platform specific data */
    union {
        int dummy;
#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
        struct {
            union {
                double align;
                /*-
                 * KM-AES parameter block - begin
                 * (see z/Architecture Principles of Operation >= SA22-7832-06)
                 */
                struct {
                    unsigned char k[32];
                } km;
                /* KM-AES parameter block - end */
                /*-
                 * KMO-AES/KMF-AES parameter block - begin
                 * (see z/Architecture Principles of Operation >= SA22-7832-08)
                 */
                struct {
                    unsigned char cv[16];
                    unsigned char k[32];
                } kmo_kmf;
                /* KMO-AES/KMF-AES parameter block - end */
            } param;
            unsigned int fc;
            int res;
        } s390x;
#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */
    } plat;

    /* The cipher functions we are going to use */
    const PROV_AES_CIPHER *ciph;

@@ -60,13 +91,13 @@ struct prov_aes_cipher_st {
                size_t inl);
};

const PROV_AES_CIPHER *PROV_AES_CIPHER_ecb(void);
const PROV_AES_CIPHER *PROV_AES_CIPHER_cbc(void);
const PROV_AES_CIPHER *PROV_AES_CIPHER_ofb(void);
const PROV_AES_CIPHER *PROV_AES_CIPHER_cfb(void);
const PROV_AES_CIPHER *PROV_AES_CIPHER_cfb1(void);
const PROV_AES_CIPHER *PROV_AES_CIPHER_cfb8(void);
const PROV_AES_CIPHER *PROV_AES_CIPHER_ctr(void);
const PROV_AES_CIPHER *PROV_AES_CIPHER_ecb(size_t keylen);
const PROV_AES_CIPHER *PROV_AES_CIPHER_cbc(size_t keylen);
const PROV_AES_CIPHER *PROV_AES_CIPHER_ofb(size_t keylen);
const PROV_AES_CIPHER *PROV_AES_CIPHER_cfb(size_t keylen);
const PROV_AES_CIPHER *PROV_AES_CIPHER_cfb1(size_t keylen);
const PROV_AES_CIPHER *PROV_AES_CIPHER_cfb8(size_t keylen);
const PROV_AES_CIPHER *PROV_AES_CIPHER_ctr(size_t keylen);

size_t fillblock(unsigned char *buf, size_t *buflen, size_t blocksize,
                 const unsigned char **in, size_t *inlen);