summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/crypto/pkey_cca.c15
-rw-r--r--drivers/s390/crypto/zcrypt_ccamisc.c64
-rw-r--r--drivers/s390/crypto/zcrypt_ccamisc.h6
3 files changed, 62 insertions, 23 deletions
diff --git a/drivers/s390/crypto/pkey_cca.c b/drivers/s390/crypto/pkey_cca.c
index 4bc47952324e..e8dc2f77c137 100644
--- a/drivers/s390/crypto/pkey_cca.c
+++ b/drivers/s390/crypto/pkey_cca.c
@@ -236,22 +236,16 @@ static int cca_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
if (hdr->type == TOKTYPE_CCA_INTERNAL &&
hdr->version == TOKVER_CCA_AES) {
/* CCA AES data key */
- if (keylen < sizeof(struct secaeskeytoken))
- return -EINVAL;
- if (cca_check_secaeskeytoken(pkey_dbf_info, 3, key, 0))
+ if (cca_check_secaeskeytoken(pkey_dbf_info, 3, key, keylen, 0))
return -EINVAL;
} else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
hdr->version == TOKVER_CCA_VLSC) {
/* CCA AES cipher key */
- if (keylen < hdr->len)
- return -EINVAL;
if (cca_check_secaescipherkey(pkey_dbf_info,
- 3, key, 0, 1))
+ 3, key, keylen, 0, 1))
return -EINVAL;
} else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {
/* CCA ECC (private) key */
- if (keylen < sizeof(struct eccprivkeytoken))
- return -EINVAL;
if (cca_check_sececckeytoken(pkey_dbf_info, 3, key, keylen, 1))
return -EINVAL;
} else {
@@ -484,7 +478,7 @@ static int cca_verifykey(const u8 *key, u32 keylen,
hdr->version == TOKVER_CCA_AES) {
struct secaeskeytoken *t = (struct secaeskeytoken *)key;
- rc = cca_check_secaeskeytoken(pkey_dbf_info, 3, key, 0);
+ rc = cca_check_secaeskeytoken(pkey_dbf_info, 3, key, keylen, 0);
if (rc)
goto out;
*keytype = PKEY_TYPE_CCA_DATA;
@@ -512,7 +506,8 @@ static int cca_verifykey(const u8 *key, u32 keylen,
hdr->version == TOKVER_CCA_VLSC) {
struct cipherkeytoken *t = (struct cipherkeytoken *)key;
- rc = cca_check_secaescipherkey(pkey_dbf_info, 3, key, 0, 1);
+ rc = cca_check_secaescipherkey(pkey_dbf_info, 3,
+ key, keylen, 0, 1);
if (rc)
goto out;
*keytype = PKEY_TYPE_CCA_CIPHER;
diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c
index 322677a8d320..f797786107b9 100644
--- a/drivers/s390/crypto/zcrypt_ccamisc.c
+++ b/drivers/s390/crypto/zcrypt_ccamisc.c
@@ -62,12 +62,18 @@ static DEFINE_MUTEX(dev_status_mem_mutex);
* also checked. Returns 0 on success or errno value on failure.
*/
int cca_check_secaeskeytoken(debug_info_t *dbg, int dbflvl,
- const u8 *token, int keybitsize)
+ const u8 *token, u32 keysize, int keybitsize)
{
struct secaeskeytoken *t = (struct secaeskeytoken *)token;
#define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__)
+ if (keysize < sizeof(*t)) {
+ if (dbg)
+ DBF("%s keysize %u < min token size %zu\n",
+ __func__, keysize, sizeof(*t));
+ return -EINVAL;
+ }
if (t->type != TOKTYPE_CCA_INTERNAL) {
if (dbg)
DBF("%s token check failed, type 0x%02x != 0x%02x\n",
@@ -101,14 +107,20 @@ EXPORT_SYMBOL(cca_check_secaeskeytoken);
* Returns 0 on success or errno value on failure.
*/
int cca_check_secaescipherkey(debug_info_t *dbg, int dbflvl,
- const u8 *token, int keybitsize,
- int checkcpacfexport)
+ const u8 *token, u32 keysize,
+ int keybitsize, int checkcpacfexport)
{
struct cipherkeytoken *t = (struct cipherkeytoken *)token;
bool keybitsizeok = true;
#define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__)
+ if (keysize < sizeof(*t)) {
+ if (dbg)
+ DBF("%s keysize %u < min token size %zu\n",
+ __func__, keysize, sizeof(*t));
+ return -EINVAL;
+ }
if (t->type != TOKTYPE_CCA_INTERNAL) {
if (dbg)
DBF("%s token check failed, type 0x%02x != 0x%02x\n",
@@ -121,6 +133,18 @@ int cca_check_secaescipherkey(debug_info_t *dbg, int dbflvl,
__func__, (int)t->version, TOKVER_CCA_VLSC);
return -EINVAL;
}
+ if (t->len > keysize) {
+ if (dbg)
+ DBF("%s token check failed, len %d > keysize %u\n",
+ __func__, (int)t->len, keysize);
+ return -EINVAL;
+ }
+ if (t->len < sizeof(*t)) {
+ if (dbg)
+ DBF("%s token check failed, len %d < min token size %zu\n",
+ __func__, (int)t->len, sizeof(*t));
+ return -EINVAL;
+ }
if (t->algtype != 0x02) {
if (dbg)
DBF("%s token check failed, algtype 0x%02x != 0x02\n",
@@ -195,6 +219,12 @@ int cca_check_sececckeytoken(debug_info_t *dbg, int dbflvl,
#define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__)
+ if (keysize < sizeof(*t)) {
+ if (dbg)
+ DBF("%s keysize %u < min token size %zu\n",
+ __func__, keysize, sizeof(*t));
+ return -EINVAL;
+ }
if (t->type != TOKTYPE_CCA_INTERNAL_PKA) {
if (dbg)
DBF("%s token check failed, type 0x%02x != 0x%02x\n",
@@ -207,6 +237,12 @@ int cca_check_sececckeytoken(debug_info_t *dbg, int dbflvl,
__func__, (int)t->len, keysize);
return -EINVAL;
}
+ if (t->len < sizeof(*t)) {
+ if (dbg)
+ DBF("%s token check failed, len %d < min token size %zu\n",
+ __func__, (int)t->len, sizeof(*t));
+ return -EINVAL;
+ }
if (t->secid != 0x20) {
if (dbg)
DBF("%s token check failed, secid 0x%02x != 0x20\n",
@@ -443,7 +479,8 @@ int cca_genseckey(u16 cardnr, u16 domain,
/* check secure key token */
rc = cca_check_secaeskeytoken(zcrypt_dbf_info, DBF_ERR,
- prepparm->lv3.keyblock.tok, 8 * keysize);
+ prepparm->lv3.keyblock.tok,
+ seckeysize, 8 * keysize);
if (rc) {
rc = -EIO;
goto out;
@@ -582,7 +619,8 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize,
/* check secure key token */
rc = cca_check_secaeskeytoken(zcrypt_dbf_info, DBF_ERR,
- prepparm->lv3.keyblock.tok, 8 * keysize);
+ prepparm->lv3.keyblock.tok,
+ seckeysize, 8 * keysize);
if (rc) {
rc = -EIO;
goto out;
@@ -842,6 +880,7 @@ int cca_gencipherkey(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags,
} kb;
} __packed * prepparm;
struct cipherkeytoken *t;
+ u32 keybuflen;
/* get already prepared memory for 2 cprbs with param block each */
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
@@ -936,23 +975,28 @@ int cca_gencipherkey(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags,
}
/* and some checks on the generated key */
+ t = (struct cipherkeytoken *)prepparm->kb.tlv1.gen_key;
+ if (prepparm->kb.tlv1.len < 2 * sizeof(uint16_t) + sizeof(*t)) {
+ rc = -EIO;
+ goto out;
+ }
+ keybuflen = prepparm->kb.tlv1.len - 2 * sizeof(uint16_t);
rc = cca_check_secaescipherkey(zcrypt_dbf_info, DBF_ERR,
prepparm->kb.tlv1.gen_key,
- keybitsize, 1);
+ keybuflen, keybitsize, 1);
if (rc) {
rc = -EIO;
goto out;
}
/* copy the generated vlsc key token */
- t = (struct cipherkeytoken *)prepparm->kb.tlv1.gen_key;
if (keybuf) {
- if (*keybufsize >= t->len)
- memcpy(keybuf, t, t->len);
+ if (*keybufsize >= keybuflen)
+ memcpy(keybuf, t, keybuflen);
else
rc = -EINVAL;
}
- *keybufsize = t->len;
+ *keybufsize = keybuflen;
out:
free_cprbmem(mem, PARMBSIZE, false, xflags);
diff --git a/drivers/s390/crypto/zcrypt_ccamisc.h b/drivers/s390/crypto/zcrypt_ccamisc.h
index 07bbb1c20022..a4534f8b2f1d 100644
--- a/drivers/s390/crypto/zcrypt_ccamisc.h
+++ b/drivers/s390/crypto/zcrypt_ccamisc.h
@@ -136,7 +136,7 @@ struct eccprivkeytoken {
* also checked. Returns 0 on success or errno value on failure.
*/
int cca_check_secaeskeytoken(debug_info_t *dbg, int dbflvl,
- const u8 *token, int keybitsize);
+ const u8 *token, u32 keysize, int keybitsize);
/*
* Simple check if the token is a valid CCA secure AES cipher key
@@ -146,8 +146,8 @@ int cca_check_secaeskeytoken(debug_info_t *dbg, int dbflvl,
* Returns 0 on success or errno value on failure.
*/
int cca_check_secaescipherkey(debug_info_t *dbg, int dbflvl,
- const u8 *token, int keybitsize,
- int checkcpacfexport);
+ const u8 *token, u32 keysize,
+ int keybitsize, int checkcpacfexport);
/*
* Simple check if the token is a valid CCA secure ECC private