Home | History | Annotate | Line # | Download | only in ciphers
      1 /*
      2  * Copyright 2001-2024 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5  * this file except in compliance with the License.  You can obtain a copy
      6  * in the file LICENSE in the source distribution or at
      7  * https://www.openssl.org/source/license.html
      8  */
      9 
     10 /*
     11  * IBM S390X support for AES modes ecb, cbc, ofb, cfb, ctr.
     12  * This file is included by cipher_aes_hw.c
     13  */
     14 
     15 #include "s390x_arch.h"
     16 
     17 #include <stdio.h>
     18 
     19 #define s390x_aes_cbc_initkey    cipher_hw_aes_initkey
     20 #define s390x_aes_cfb1_initkey   cipher_hw_aes_initkey
     21 #define s390x_aes_ctr_initkey    cipher_hw_aes_initkey
     22 #define s390x_aes_cbc_cipher_hw  ossl_cipher_hw_generic_cbc
     23 #define s390x_aes_cfb1_cipher_hw ossl_cipher_hw_generic_cfb1
     24 #define s390x_aes_ctr_cipher_hw  ossl_cipher_hw_generic_ctr
     25 
     26 #define S390X_aes_128_ofb128_CAPABLE S390X_aes_128_ofb_CAPABLE
     27 #define S390X_aes_192_ofb128_CAPABLE S390X_aes_192_ofb_CAPABLE
     28 #define S390X_aes_256_ofb128_CAPABLE S390X_aes_256_ofb_CAPABLE
     29 #define S390X_aes_128_cfb128_CAPABLE S390X_aes_128_cfb_CAPABLE
     30 #define S390X_aes_192_cfb128_CAPABLE S390X_aes_192_cfb_CAPABLE
     31 #define S390X_aes_256_cfb128_CAPABLE S390X_aes_256_cfb_CAPABLE
     32 
     33 static int s390x_aes_ecb_initkey(PROV_CIPHER_CTX *dat,
     34                                  const unsigned char *key, size_t keylen)
     35 {
     36     PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
     37 
     38     adat->plat.s390x.fc = S390X_AES_FC(keylen);
     39     memcpy(adat->plat.s390x.param.km.k, key, keylen);
     40     return 1;
     41 }
     42 
     43 static int s390x_aes_ecb_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
     44                                    const unsigned char *in, size_t len)
     45 {
     46     PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
     47     unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT;
     48 
     49     s390x_km(in, len, out, adat->plat.s390x.fc | modifier,
     50              &adat->plat.s390x.param.km);
     51     return 1;
     52 }
     53 
     54 static int s390x_aes_ofb128_initkey(PROV_CIPHER_CTX *dat,
     55                                     const unsigned char *key, size_t keylen)
     56 {
     57     PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
     58 
     59     memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
     60     adat->plat.s390x.fc = S390X_AES_FC(keylen);
     61     return 1;
     62 }
     63 
     64 static int s390x_aes_ofb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
     65                                       const unsigned char *in, size_t len)
     66 {
     67     PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
     68     int n = dat->num;
     69     int rem;
     70 
     71     memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
     72     while (n && len) {
     73         *out = *in ^ adat->plat.s390x.param.kmo_kmf.cv[n];
     74         n = (n + 1) & 0xf;
     75         --len;
     76         ++in;
     77         ++out;
     78     }
     79 
     80     rem = len & 0xf;
     81 
     82     len &= ~(size_t)0xf;
     83     if (len) {
     84         s390x_kmo(in, len, out, adat->plat.s390x.fc,
     85                   &adat->plat.s390x.param.kmo_kmf);
     86 
     87         out += len;
     88         in += len;
     89     }
     90 
     91     if (rem) {
     92         s390x_km(adat->plat.s390x.param.kmo_kmf.cv, 16,
     93                  adat->plat.s390x.param.kmo_kmf.cv,
     94                  adat->plat.s390x.fc,
     95                  adat->plat.s390x.param.kmo_kmf.k);
     96 
     97         while (rem--) {
     98             out[n] = in[n] ^ adat->plat.s390x.param.kmo_kmf.cv[n];
     99             ++n;
    100         }
    101     }
    102 
    103     memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen);
    104     dat->num = n;
    105     return 1;
    106 }
    107 
    108 static int s390x_aes_cfb128_initkey(PROV_CIPHER_CTX *dat,
    109                                     const unsigned char *key, size_t keylen)
    110 {
    111     PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
    112 
    113     adat->plat.s390x.fc = S390X_AES_FC(keylen);
    114     adat->plat.s390x.fc |= 16 << 24;   /* 16 bytes cipher feedback */
    115     memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
    116     return 1;
    117 }
    118 
    119 static int s390x_aes_cfb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
    120                                       const unsigned char *in, size_t len)
    121 {
    122     PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
    123     unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT;
    124     int n = dat->num;
    125     int rem;
    126     unsigned char tmp;
    127 
    128     memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
    129     while (n && len) {
    130         tmp = *in;
    131         *out = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
    132         adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? *out : tmp;
    133         n = (n + 1) & 0xf;
    134         --len;
    135         ++in;
    136         ++out;
    137     }
    138 
    139     rem = len & 0xf;
    140 
    141     len &= ~(size_t)0xf;
    142     if (len) {
    143         s390x_kmf(in, len, out, adat->plat.s390x.fc | modifier,
    144                   &adat->plat.s390x.param.kmo_kmf);
    145 
    146         out += len;
    147         in += len;
    148     }
    149 
    150     if (rem) {
    151         s390x_km(adat->plat.s390x.param.kmo_kmf.cv, 16,
    152                  adat->plat.s390x.param.kmo_kmf.cv,
    153                  S390X_AES_FC(dat->keylen),
    154                  adat->plat.s390x.param.kmo_kmf.k);
    155 
    156         while (rem--) {
    157             tmp = in[n];
    158             out[n] = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
    159             adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? out[n] : tmp;
    160             ++n;
    161         }
    162     }
    163 
    164     memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen);
    165     dat->num = n;
    166     return 1;
    167 }
    168 
    169 static int s390x_aes_cfb8_initkey(PROV_CIPHER_CTX *dat,
    170                                   const unsigned char *key, size_t keylen)
    171 {
    172     PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
    173 
    174     adat->plat.s390x.fc = S390X_AES_FC(keylen);
    175     adat->plat.s390x.fc |= 1 << 24;   /* 1 byte cipher feedback */
    176     memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
    177     return 1;
    178 }
    179 
    180 static int s390x_aes_cfb8_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
    181                                     const unsigned char *in, size_t len)
    182 {
    183     PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
    184     unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT;
    185 
    186     memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
    187     s390x_kmf(in, len, out, adat->plat.s390x.fc | modifier,
    188               &adat->plat.s390x.param.kmo_kmf);
    189     memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen);
    190     return 1;
    191 }
    192 
    193 #define PROV_CIPHER_HW_declare(mode)                                           \
    194 static const PROV_CIPHER_HW s390x_aes_##mode = {                               \
    195     s390x_aes_##mode##_initkey,                                                \
    196     s390x_aes_##mode##_cipher_hw,                                              \
    197     cipher_hw_aes_copyctx                                                      \
    198 };
    199 #define PROV_CIPHER_HW_select(mode)                                            \
    200 if ((keybits == 128 && S390X_aes_128_##mode##_CAPABLE)                         \
    201      || (keybits == 192 && S390X_aes_192_##mode##_CAPABLE)                     \
    202      || (keybits == 256 && S390X_aes_256_##mode##_CAPABLE))                    \
    203     return &s390x_aes_##mode;
    204 
    205