Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/zcrypt: Support for CCA APKA master keys

Support for CCA APKA (used for CCA ECC keys) master keys.
The existing mkvps sysfs attribute for each queue for cards
in CCA mode is extended to show the APKA master key register
states and verification pattern:

Improve the mkvps sysfs attribute to display the APKA
master key verification patterns for old, current and new
master key registers. The APKA master key is used to
encrypt CCA ECC secure keys. The syntax is analog to the
existing AES mk verification patterns:

APKA NEW: <new_apka_mk_state> <new_apka_mk_mkvp>
APKA CUR: <cur_apka_mk_state> <cur_apka_mk_mkvp>
APKA OLD: <old_apka_mk_state> <old_apka_mk_mkvp>
with
<new_apka_mk_state>: 'empty' or 'partial' or 'full'
<cur_apka_mk_state>: 'valid' or 'invalid'
<old_apka_mk_state>: 'valid' or 'invalid'
<new_apka_mk_mkvp>, <cur_apka_mk_mkvp>, <old_apka_mk_mkvp>
8 byte hex string with leading 0x

MKVP means Master Key Verification Pattern and is a folded hash over
the key value. Only the states 'full' and 'valid' result in displaying
a useful mkvp, otherwise a mkvp of all bytes zero is shown. If for any
reason the FQ fails and the (cached) information is not available, the
state '-' will be shown with the mkvp value also '-'. The values shown
here are the very same as the cca panel tools displays.

The internal function cca_findcard2() also supports to match
against the APKA master key verification patterns and the pkey
kernel module which uses this function needed compatible rewrite
of these invocations.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>

authored by

Harald Freudenberger and committed by
Vasily Gorbik
32ca04bb 5596c4c1

+154 -57
+11 -7
drivers/s390/crypto/pkey_api.c
··· 661 661 *ksize = (enum pkey_key_size) t->bitsize; 662 662 663 663 rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 664 - ZCRYPT_CEX3C, t->mkvp, 0, 1); 664 + ZCRYPT_CEX3C, AES_MK_SET, t->mkvp, 0, 1); 665 665 if (rc == 0 && flags) 666 666 *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 667 667 if (rc == -ENODEV) { 668 668 rc = cca_findcard2(&_apqns, &_nr_apqns, 669 669 *cardnr, *domain, 670 - ZCRYPT_CEX3C, 0, t->mkvp, 1); 670 + ZCRYPT_CEX3C, AES_MK_SET, 671 + 0, t->mkvp, 1); 671 672 if (rc == 0 && flags) 672 673 *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 673 674 } ··· 698 697 } 699 698 700 699 rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 701 - ZCRYPT_CEX6, t->mkvp0, 0, 1); 700 + ZCRYPT_CEX6, AES_MK_SET, t->mkvp0, 0, 1); 702 701 if (rc == 0 && flags) 703 702 *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 704 703 if (rc == -ENODEV) { 705 704 rc = cca_findcard2(&_apqns, &_nr_apqns, 706 705 *cardnr, *domain, 707 - ZCRYPT_CEX6, 0, t->mkvp0, 1); 706 + ZCRYPT_CEX6, AES_MK_SET, 707 + 0, t->mkvp0, 1); 708 708 if (rc == 0 && flags) 709 709 *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 710 710 } ··· 865 863 return -EINVAL; 866 864 } 867 865 rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 868 - minhwtype, cur_mkvp, old_mkvp, 1); 866 + minhwtype, AES_MK_SET, 867 + cur_mkvp, old_mkvp, 1); 869 868 if (rc) 870 869 goto out; 871 870 } else ··· 903 900 if (ktype == PKEY_TYPE_CCA_CIPHER) 904 901 minhwtype = ZCRYPT_CEX6; 905 902 rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 906 - minhwtype, cur_mkvp, old_mkvp, 1); 903 + minhwtype, AES_MK_SET, 904 + cur_mkvp, old_mkvp, 1); 907 905 if (rc) 908 906 goto out; 909 907 } else if (ktype == PKEY_TYPE_EP11) { ··· 1593 1589 1594 1590 /* build a list of apqns able to generate an cipher key */ 1595 1591 rc = cca_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 1596 - ZCRYPT_CEX6, 0, 0, 0); 1592 + ZCRYPT_CEX6, 0, 0, 0, 0); 1597 1593 if (rc) 1598 1594 return rc; 1599 1595
+56 -29
drivers/s390/crypto/zcrypt_ccamisc.c
··· 1506 1506 rarray, &rlen, varray, &vlen); 1507 1507 if (rc == 0 && rlen >= 10*8 && vlen >= 204) { 1508 1508 memcpy(ci->serial, rarray, 8); 1509 - ci->new_mk_state = (char) rarray[7*8]; 1510 - ci->cur_mk_state = (char) rarray[8*8]; 1511 - ci->old_mk_state = (char) rarray[9*8]; 1512 - if (ci->old_mk_state == '2') 1513 - memcpy(&ci->old_mkvp, varray + 172, 8); 1514 - if (ci->cur_mk_state == '2') 1515 - memcpy(&ci->cur_mkvp, varray + 184, 8); 1516 - if (ci->new_mk_state == '3') 1517 - memcpy(&ci->new_mkvp, varray + 196, 8); 1518 - found = 1; 1509 + ci->new_aes_mk_state = (char) rarray[7*8]; 1510 + ci->cur_aes_mk_state = (char) rarray[8*8]; 1511 + ci->old_aes_mk_state = (char) rarray[9*8]; 1512 + if (ci->old_aes_mk_state == '2') 1513 + memcpy(&ci->old_aes_mkvp, varray + 172, 8); 1514 + if (ci->cur_aes_mk_state == '2') 1515 + memcpy(&ci->cur_aes_mkvp, varray + 184, 8); 1516 + if (ci->new_aes_mk_state == '3') 1517 + memcpy(&ci->new_aes_mkvp, varray + 196, 8); 1518 + found++; 1519 + } 1520 + if (!found) 1521 + goto out; 1522 + rlen = vlen = PAGE_SIZE/2; 1523 + rc = cca_query_crypto_facility(cardnr, domain, "STATICSB", 1524 + rarray, &rlen, varray, &vlen); 1525 + if (rc == 0 && rlen >= 10*8 && vlen >= 240) { 1526 + ci->new_apka_mk_state = (char) rarray[7*8]; 1527 + ci->cur_apka_mk_state = (char) rarray[8*8]; 1528 + ci->old_apka_mk_state = (char) rarray[9*8]; 1529 + if (ci->old_apka_mk_state == '2') 1530 + memcpy(&ci->old_apka_mkvp, varray + 208, 8); 1531 + if (ci->cur_apka_mk_state == '2') 1532 + memcpy(&ci->cur_apka_mkvp, varray + 220, 8); 1533 + if (ci->new_apka_mk_state == '3') 1534 + memcpy(&ci->new_apka_mkvp, varray + 232, 8); 1535 + found++; 1519 1536 } 1520 1537 1538 + out: 1521 1539 free_page((unsigned long) pg); 1522 - 1523 - return found ? 0 : -ENOENT; 1540 + return found == 2 ? 0 : -ENOENT; 1524 1541 } 1525 1542 1526 1543 /* ··· 1591 1574 /* enabled CCA card, check current mkvp from cache */ 1592 1575 if (cca_info_cache_fetch(card, dom, &ci) == 0 && 1593 1576 ci.hwtype >= minhwtype && 1594 - ci.cur_mk_state == '2' && 1595 - ci.cur_mkvp == mkvp) { 1577 + ci.cur_aes_mk_state == '2' && 1578 + ci.cur_aes_mkvp == mkvp) { 1596 1579 if (!verify) 1597 1580 break; 1598 1581 /* verify: refresh card info */ 1599 1582 if (fetch_cca_info(card, dom, &ci) == 0) { 1600 1583 cca_info_cache_update(card, dom, &ci); 1601 1584 if (ci.hwtype >= minhwtype && 1602 - ci.cur_mk_state == '2' && 1603 - ci.cur_mkvp == mkvp) 1585 + ci.cur_aes_mk_state == '2' && 1586 + ci.cur_aes_mkvp == mkvp) 1604 1587 break; 1605 1588 } 1606 1589 } ··· 1622 1605 if (fetch_cca_info(card, dom, &ci) == 0) { 1623 1606 cca_info_cache_update(card, dom, &ci); 1624 1607 if (ci.hwtype >= minhwtype && 1625 - ci.cur_mk_state == '2' && 1626 - ci.cur_mkvp == mkvp) 1608 + ci.cur_aes_mk_state == '2' && 1609 + ci.cur_aes_mkvp == mkvp) 1627 1610 break; 1628 1611 if (ci.hwtype >= minhwtype && 1629 - ci.old_mk_state == '2' && 1630 - ci.old_mkvp == mkvp && 1612 + ci.old_aes_mk_state == '2' && 1613 + ci.old_aes_mkvp == mkvp && 1631 1614 oi < 0) 1632 1615 oi = i; 1633 1616 } ··· 1681 1664 EXPORT_SYMBOL(cca_findcard); 1682 1665 1683 1666 int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain, 1684 - int minhwtype, u64 cur_mkvp, u64 old_mkvp, int verify) 1667 + int minhwtype, int mktype, u64 cur_mkvp, u64 old_mkvp, 1668 + int verify) 1685 1669 { 1686 1670 struct zcrypt_device_status_ext *device_status; 1687 1671 u32 *_apqns = NULL, _nr_apqns = 0; ··· 1724 1706 if (cca_get_info(card, dom, &ci, verify)) 1725 1707 continue; 1726 1708 /* current master key needs to be valid */ 1727 - if (ci.cur_mk_state != '2') 1709 + if (mktype == AES_MK_SET && ci.cur_aes_mk_state != '2') 1710 + continue; 1711 + if (mktype == APKA_MK_SET && ci.cur_apka_mk_state != '2') 1728 1712 continue; 1729 1713 /* check min hardware type */ 1730 1714 if (minhwtype > 0 && minhwtype > ci.hwtype) ··· 1734 1714 if (cur_mkvp || old_mkvp) { 1735 1715 /* check mkvps */ 1736 1716 curmatch = oldmatch = 0; 1737 - if (cur_mkvp && cur_mkvp == ci.cur_mkvp) 1738 - curmatch = 1; 1739 - if (old_mkvp && ci.old_mk_state == '2' && 1740 - old_mkvp == ci.old_mkvp) 1741 - oldmatch = 1; 1742 - if ((cur_mkvp || old_mkvp) && 1743 - (curmatch + oldmatch < 1)) 1717 + if (mktype == AES_MK_SET) { 1718 + if (cur_mkvp && cur_mkvp == ci.cur_aes_mkvp) 1719 + curmatch = 1; 1720 + if (old_mkvp && ci.old_aes_mk_state == '2' && 1721 + old_mkvp == ci.old_aes_mkvp) 1722 + oldmatch = 1; 1723 + } else { 1724 + if (cur_mkvp && cur_mkvp == ci.cur_apka_mkvp) 1725 + curmatch = 1; 1726 + if (old_mkvp && ci.old_apka_mk_state == '2' && 1727 + old_mkvp == ci.old_apka_mkvp) 1728 + oldmatch = 1; 1729 + } 1730 + if (curmatch + oldmatch < 1) 1744 1731 continue; 1745 1732 } 1746 1733 /* apqn passed all filtering criterons, add to the array */
+21 -9
drivers/s390/crypto/zcrypt_ccamisc.h
··· 186 186 * - if verify is enabled and a cur_mkvp and/or old_mkvp 187 187 * value is given, then refetch the cca_info and make sure the current 188 188 * cur_mkvp or old_mkvp values of the apqn are used. 189 + * The mktype determines which set of master keys to use: 190 + * 0 = AES_MK_SET - AES MK set, 1 = APKA MK_SET - APKA MK set 189 191 * The array of apqn entries is allocated with kmalloc and returned in *apqns; 190 192 * the number of apqns stored into the list is returned in *nr_apqns. One apqn 191 193 * entry is simple a 32 bit value with 16 bit cardnr and 16 bit domain nr and ··· 196 194 * -ENODEV is returned. 197 195 */ 198 196 int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain, 199 - int minhwtype, u64 cur_mkvp, u64 old_mkvp, int verify); 197 + int minhwtype, int mktype, u64 cur_mkvp, u64 old_mkvp, 198 + int verify); 199 + 200 + #define AES_MK_SET 0 201 + #define APKA_MK_SET 1 200 202 201 203 /* struct to hold info for each CCA queue */ 202 204 struct cca_info { 203 - int hwtype; /* one of the defined AP_DEVICE_TYPE_* */ 204 - char new_mk_state; /* '1' empty, '2' partially full, '3' full */ 205 - char cur_mk_state; /* '1' invalid, '2' valid */ 206 - char old_mk_state; /* '1' invalid, '2' valid */ 207 - u64 new_mkvp; /* truncated sha256 hash of new master key */ 208 - u64 cur_mkvp; /* truncated sha256 hash of current master key */ 209 - u64 old_mkvp; /* truncated sha256 hash of old master key */ 210 - char serial[9]; /* serial number string (8 ascii numbers + 0x00) */ 205 + int hwtype; /* one of the defined AP_DEVICE_TYPE_* */ 206 + char new_aes_mk_state; /* '1' empty, '2' partially full, '3' full */ 207 + char cur_aes_mk_state; /* '1' invalid, '2' valid */ 208 + char old_aes_mk_state; /* '1' invalid, '2' valid */ 209 + char new_apka_mk_state; /* '1' empty, '2' partially full, '3' full */ 210 + char cur_apka_mk_state; /* '1' invalid, '2' valid */ 211 + char old_apka_mk_state; /* '1' invalid, '2' valid */ 212 + u64 new_aes_mkvp; /* truncated sha256 of new aes master key */ 213 + u64 cur_aes_mkvp; /* truncated sha256 of current aes master key */ 214 + u64 old_aes_mkvp; /* truncated sha256 of old aes master key */ 215 + u64 new_apka_mkvp; /* truncated sha256 of new apka master key */ 216 + u64 cur_apka_mkvp; /* truncated sha256 of current apka mk */ 217 + u64 old_apka_mkvp; /* truncated sha256 of old apka mk */ 218 + char serial[9]; /* serial number (8 ascii numbers + 0x00) */ 211 219 }; 212 220 213 221 /*
+33 -6
drivers/s390/crypto/zcrypt_cex2c.c
··· 109 109 AP_QID_QUEUE(zq->queue->qid), 110 110 &ci, zq->online); 111 111 112 - if (ci.new_mk_state >= '1' && ci.new_mk_state <= '3') 112 + if (ci.new_aes_mk_state >= '1' && ci.new_aes_mk_state <= '3') 113 113 n = scnprintf(buf, PAGE_SIZE, "AES NEW: %s 0x%016llx\n", 114 - new_state[ci.new_mk_state - '1'], ci.new_mkvp); 114 + new_state[ci.new_aes_mk_state - '1'], 115 + ci.new_aes_mkvp); 115 116 else 116 117 n = scnprintf(buf, PAGE_SIZE, "AES NEW: - -\n"); 117 118 118 - if (ci.cur_mk_state >= '1' && ci.cur_mk_state <= '2') 119 + if (ci.cur_aes_mk_state >= '1' && ci.cur_aes_mk_state <= '2') 119 120 n += scnprintf(buf + n, PAGE_SIZE - n, 120 121 "AES CUR: %s 0x%016llx\n", 121 - cao_state[ci.cur_mk_state - '1'], ci.cur_mkvp); 122 + cao_state[ci.cur_aes_mk_state - '1'], 123 + ci.cur_aes_mkvp); 122 124 else 123 125 n += scnprintf(buf + n, PAGE_SIZE - n, "AES CUR: - -\n"); 124 126 125 - if (ci.old_mk_state >= '1' && ci.old_mk_state <= '2') 127 + if (ci.old_aes_mk_state >= '1' && ci.old_aes_mk_state <= '2') 126 128 n += scnprintf(buf + n, PAGE_SIZE - n, 127 129 "AES OLD: %s 0x%016llx\n", 128 - cao_state[ci.old_mk_state - '1'], ci.old_mkvp); 130 + cao_state[ci.old_aes_mk_state - '1'], 131 + ci.old_aes_mkvp); 129 132 else 130 133 n += scnprintf(buf + n, PAGE_SIZE - n, "AES OLD: - -\n"); 134 + 135 + if (ci.new_apka_mk_state >= '1' && ci.new_apka_mk_state <= '3') 136 + n += scnprintf(buf + n, PAGE_SIZE - n, 137 + "APKA NEW: %s 0x%016llx\n", 138 + new_state[ci.new_apka_mk_state - '1'], 139 + ci.new_apka_mkvp); 140 + else 141 + n += scnprintf(buf + n, PAGE_SIZE - n, "APKA NEW: - -\n"); 142 + 143 + if (ci.cur_apka_mk_state >= '1' && ci.cur_apka_mk_state <= '2') 144 + n += scnprintf(buf + n, PAGE_SIZE - n, 145 + "APKA CUR: %s 0x%016llx\n", 146 + cao_state[ci.cur_apka_mk_state - '1'], 147 + ci.cur_apka_mkvp); 148 + else 149 + n += scnprintf(buf + n, PAGE_SIZE - n, "APKA CUR: - -\n"); 150 + 151 + if (ci.old_apka_mk_state >= '1' && ci.old_apka_mk_state <= '2') 152 + n += scnprintf(buf + n, PAGE_SIZE - n, 153 + "APKA OLD: %s 0x%016llx\n", 154 + cao_state[ci.old_apka_mk_state - '1'], 155 + ci.old_apka_mkvp); 156 + else 157 + n += scnprintf(buf + n, PAGE_SIZE - n, "APKA OLD: - -\n"); 131 158 132 159 return n; 133 160 }
+33 -6
drivers/s390/crypto/zcrypt_cex4.c
··· 121 121 AP_QID_QUEUE(zq->queue->qid), 122 122 &ci, zq->online); 123 123 124 - if (ci.new_mk_state >= '1' && ci.new_mk_state <= '3') 124 + if (ci.new_aes_mk_state >= '1' && ci.new_aes_mk_state <= '3') 125 125 n = scnprintf(buf, PAGE_SIZE, "AES NEW: %s 0x%016llx\n", 126 - new_state[ci.new_mk_state - '1'], ci.new_mkvp); 126 + new_state[ci.new_aes_mk_state - '1'], 127 + ci.new_aes_mkvp); 127 128 else 128 129 n = scnprintf(buf, PAGE_SIZE, "AES NEW: - -\n"); 129 130 130 - if (ci.cur_mk_state >= '1' && ci.cur_mk_state <= '2') 131 + if (ci.cur_aes_mk_state >= '1' && ci.cur_aes_mk_state <= '2') 131 132 n += scnprintf(buf + n, PAGE_SIZE - n, 132 133 "AES CUR: %s 0x%016llx\n", 133 - cao_state[ci.cur_mk_state - '1'], ci.cur_mkvp); 134 + cao_state[ci.cur_aes_mk_state - '1'], 135 + ci.cur_aes_mkvp); 134 136 else 135 137 n += scnprintf(buf + n, PAGE_SIZE - n, "AES CUR: - -\n"); 136 138 137 - if (ci.old_mk_state >= '1' && ci.old_mk_state <= '2') 139 + if (ci.old_aes_mk_state >= '1' && ci.old_aes_mk_state <= '2') 138 140 n += scnprintf(buf + n, PAGE_SIZE - n, 139 141 "AES OLD: %s 0x%016llx\n", 140 - cao_state[ci.old_mk_state - '1'], ci.old_mkvp); 142 + cao_state[ci.old_aes_mk_state - '1'], 143 + ci.old_aes_mkvp); 141 144 else 142 145 n += scnprintf(buf + n, PAGE_SIZE - n, "AES OLD: - -\n"); 146 + 147 + if (ci.new_apka_mk_state >= '1' && ci.new_apka_mk_state <= '3') 148 + n += scnprintf(buf + n, PAGE_SIZE - n, 149 + "APKA NEW: %s 0x%016llx\n", 150 + new_state[ci.new_apka_mk_state - '1'], 151 + ci.new_apka_mkvp); 152 + else 153 + n += scnprintf(buf + n, PAGE_SIZE - n, "APKA NEW: - -\n"); 154 + 155 + if (ci.cur_apka_mk_state >= '1' && ci.cur_apka_mk_state <= '2') 156 + n += scnprintf(buf + n, PAGE_SIZE - n, 157 + "APKA CUR: %s 0x%016llx\n", 158 + cao_state[ci.cur_apka_mk_state - '1'], 159 + ci.cur_apka_mkvp); 160 + else 161 + n += scnprintf(buf + n, PAGE_SIZE - n, "APKA CUR: - -\n"); 162 + 163 + if (ci.old_apka_mk_state >= '1' && ci.old_apka_mk_state <= '2') 164 + n += scnprintf(buf + n, PAGE_SIZE - n, 165 + "APKA OLD: %s 0x%016llx\n", 166 + cao_state[ci.old_apka_mk_state - '1'], 167 + ci.old_apka_mkvp); 168 + else 169 + n += scnprintf(buf + n, PAGE_SIZE - n, "APKA OLD: - -\n"); 143 170 144 171 return n; 145 172 }