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

Configure Feed

Select the types of activity you want to include in your feed.

crypto: s390 - Add selftest support for phmac

Add key preparation code in case of selftest running to the phmac
setkey function:

As long as crypto_ahash_tested() returns with false, all setkey()
invocations are assumed to carry sheer hmac clear key values and thus
need some preparation to work with the phmac implementation. Thus it
is possible to use the already available hmac test vectors implemented
in the testmanager to test the phmac code.

When crypto_ahash_tested() returns true (that is after larval state)
the phmac code assumes the key material is a blob digestible by the
pkey kernel module which converts the blob into a working key for the
phmac code.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Harald Freudenberger and committed by
Herbert Xu
d48b2f5e d0da164b

+137
+137
arch/s390/crypto/phmac_s390.c
··· 177 177 }; 178 178 179 179 /* 180 + * Pkey 'token' struct used to derive a protected key value from a clear key. 181 + */ 182 + struct hmac_clrkey_token { 183 + u8 type; 184 + u8 res0[3]; 185 + u8 version; 186 + u8 res1[3]; 187 + u32 keytype; 188 + u32 len; 189 + u8 key[]; 190 + } __packed; 191 + 192 + static int hash_key(const u8 *in, unsigned int inlen, 193 + u8 *digest, unsigned int digestsize) 194 + { 195 + unsigned long func; 196 + union { 197 + struct sha256_paramblock { 198 + u32 h[8]; 199 + u64 mbl; 200 + } sha256; 201 + struct sha512_paramblock { 202 + u64 h[8]; 203 + u128 mbl; 204 + } sha512; 205 + } __packed param; 206 + 207 + #define PARAM_INIT(x, y, z) \ 208 + param.sha##x.h[0] = SHA##y ## _H0; \ 209 + param.sha##x.h[1] = SHA##y ## _H1; \ 210 + param.sha##x.h[2] = SHA##y ## _H2; \ 211 + param.sha##x.h[3] = SHA##y ## _H3; \ 212 + param.sha##x.h[4] = SHA##y ## _H4; \ 213 + param.sha##x.h[5] = SHA##y ## _H5; \ 214 + param.sha##x.h[6] = SHA##y ## _H6; \ 215 + param.sha##x.h[7] = SHA##y ## _H7; \ 216 + param.sha##x.mbl = (z) 217 + 218 + switch (digestsize) { 219 + case SHA224_DIGEST_SIZE: 220 + func = CPACF_KLMD_SHA_256; 221 + PARAM_INIT(256, 224, inlen * 8); 222 + break; 223 + case SHA256_DIGEST_SIZE: 224 + func = CPACF_KLMD_SHA_256; 225 + PARAM_INIT(256, 256, inlen * 8); 226 + break; 227 + case SHA384_DIGEST_SIZE: 228 + func = CPACF_KLMD_SHA_512; 229 + PARAM_INIT(512, 384, inlen * 8); 230 + break; 231 + case SHA512_DIGEST_SIZE: 232 + func = CPACF_KLMD_SHA_512; 233 + PARAM_INIT(512, 512, inlen * 8); 234 + break; 235 + default: 236 + return -EINVAL; 237 + } 238 + 239 + #undef PARAM_INIT 240 + 241 + cpacf_klmd(func, &param, in, inlen); 242 + 243 + memcpy(digest, &param, digestsize); 244 + 245 + return 0; 246 + } 247 + 248 + /* 249 + * make_clrkey_token() - wrap the clear key into a pkey clearkey token. 250 + */ 251 + static inline int make_clrkey_token(const u8 *clrkey, size_t clrkeylen, 252 + unsigned int digestsize, u8 *dest) 253 + { 254 + struct hmac_clrkey_token *token = (struct hmac_clrkey_token *)dest; 255 + unsigned int blocksize; 256 + int rc; 257 + 258 + token->type = 0x00; 259 + token->version = 0x02; 260 + switch (digestsize) { 261 + case SHA224_DIGEST_SIZE: 262 + case SHA256_DIGEST_SIZE: 263 + token->keytype = PKEY_KEYTYPE_HMAC_512; 264 + blocksize = 64; 265 + break; 266 + case SHA384_DIGEST_SIZE: 267 + case SHA512_DIGEST_SIZE: 268 + token->keytype = PKEY_KEYTYPE_HMAC_1024; 269 + blocksize = 128; 270 + break; 271 + default: 272 + return -EINVAL; 273 + } 274 + token->len = blocksize; 275 + 276 + if (clrkeylen > blocksize) { 277 + rc = hash_key(clrkey, clrkeylen, token->key, digestsize); 278 + if (rc) 279 + return rc; 280 + } else { 281 + memcpy(token->key, clrkey, clrkeylen); 282 + } 283 + 284 + return 0; 285 + } 286 + 287 + /* 180 288 * phmac_tfm_ctx_setkey() - Set key value into tfm context, maybe construct 181 289 * a clear key token digestible by pkey from a clear key value. 182 290 */ ··· 731 623 { 732 624 struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm); 733 625 unsigned int ds = crypto_ahash_digestsize(tfm); 626 + unsigned int bs = crypto_ahash_blocksize(tfm); 627 + unsigned int tmpkeylen; 628 + u8 *tmpkey = NULL; 734 629 int rc = 0; 630 + 631 + if (!crypto_ahash_tested(tfm)) { 632 + /* 633 + * selftest running: key is a raw hmac clear key and needs 634 + * to get embedded into a 'clear key token' in order to have 635 + * it correctly processed by the pkey module. 636 + */ 637 + tmpkeylen = sizeof(struct hmac_clrkey_token) + bs; 638 + tmpkey = kzalloc(tmpkeylen, GFP_KERNEL); 639 + if (!tmpkey) { 640 + rc = -ENOMEM; 641 + goto out; 642 + } 643 + rc = make_clrkey_token(key, keylen, ds, tmpkey); 644 + if (rc) 645 + goto out; 646 + keylen = tmpkeylen; 647 + key = tmpkey; 648 + } 735 649 736 650 /* copy raw key into tfm context */ 737 651 rc = phmac_tfm_ctx_setkey(tfm_ctx, key, keylen); ··· 797 667 } 798 668 799 669 out: 670 + kfree(tmpkey); 800 671 pr_debug("rc=%d\n", rc); 801 672 return rc; 802 673 } ··· 991 860 { 992 861 struct phmac_alg *phmac; 993 862 int i, rc; 863 + 864 + /* for selftest cpacf klmd subfunction is needed */ 865 + if (!cpacf_query_func(CPACF_KLMD, CPACF_KLMD_SHA_256)) 866 + return -ENODEV; 867 + if (!cpacf_query_func(CPACF_KLMD, CPACF_KLMD_SHA_512)) 868 + return -ENODEV; 994 869 995 870 /* register a simple phmac pseudo misc device */ 996 871 rc = misc_register(&phmac_dev);