提交 57127645 编写于 作者: H Harald Freudenberger 提交者: Martin Schwidefsky

s390/zcrypt: Introduce new SHA-512 based Pseudo Random Generator.

Rework of the prandom device with introduction of a new SHA-512 based
NIST SP 800-90 conform deterministic random bit generator.
Signed-off-by: NHarald Freudenberger <freude@linux.vnet.ibm.com>
Signed-off-by: NMartin Schwidefsky <schwidefsky@de.ibm.com>
上级 a1c843b8
...@@ -3,9 +3,10 @@ ...@@ -3,9 +3,10 @@
* *
* Support for s390 cryptographic instructions. * Support for s390 cryptographic instructions.
* *
* Copyright IBM Corp. 2003, 2007 * Copyright IBM Corp. 2003, 2015
* Author(s): Thomas Spatzier * Author(s): Thomas Spatzier
* Jan Glauber (jan.glauber@de.ibm.com) * Jan Glauber (jan.glauber@de.ibm.com)
* Harald Freudenberger (freude@de.ibm.com)
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free * under the terms of the GNU General Public License as published by the Free
...@@ -28,15 +29,17 @@ ...@@ -28,15 +29,17 @@
#define CRYPT_S390_MSA 0x1 #define CRYPT_S390_MSA 0x1
#define CRYPT_S390_MSA3 0x2 #define CRYPT_S390_MSA3 0x2
#define CRYPT_S390_MSA4 0x4 #define CRYPT_S390_MSA4 0x4
#define CRYPT_S390_MSA5 0x8
/* s390 cryptographic operations */ /* s390 cryptographic operations */
enum crypt_s390_operations { enum crypt_s390_operations {
CRYPT_S390_KM = 0x0100, CRYPT_S390_KM = 0x0100,
CRYPT_S390_KMC = 0x0200, CRYPT_S390_KMC = 0x0200,
CRYPT_S390_KIMD = 0x0300, CRYPT_S390_KIMD = 0x0300,
CRYPT_S390_KLMD = 0x0400, CRYPT_S390_KLMD = 0x0400,
CRYPT_S390_KMAC = 0x0500, CRYPT_S390_KMAC = 0x0500,
CRYPT_S390_KMCTR = 0x0600 CRYPT_S390_KMCTR = 0x0600,
CRYPT_S390_PPNO = 0x0700
}; };
/* /*
...@@ -138,6 +141,16 @@ enum crypt_s390_kmac_func { ...@@ -138,6 +141,16 @@ enum crypt_s390_kmac_func {
KMAC_TDEA_192 = CRYPT_S390_KMAC | 3 KMAC_TDEA_192 = CRYPT_S390_KMAC | 3
}; };
/*
* function codes for PPNO (PERFORM PSEUDORANDOM NUMBER
* OPERATION) instruction
*/
enum crypt_s390_ppno_func {
PPNO_QUERY = CRYPT_S390_PPNO | 0,
PPNO_SHA512_DRNG_GEN = CRYPT_S390_PPNO | 3,
PPNO_SHA512_DRNG_SEED = CRYPT_S390_PPNO | 0x83
};
/** /**
* crypt_s390_km: * crypt_s390_km:
* @func: the function code passed to KM; see crypt_s390_km_func * @func: the function code passed to KM; see crypt_s390_km_func
...@@ -162,11 +175,11 @@ static inline int crypt_s390_km(long func, void *param, ...@@ -162,11 +175,11 @@ static inline int crypt_s390_km(long func, void *param,
int ret; int ret;
asm volatile( asm volatile(
"0: .insn rre,0xb92e0000,%3,%1 \n" /* KM opcode */ "0: .insn rre,0xb92e0000,%3,%1\n" /* KM opcode */
"1: brc 1,0b \n" /* handle partial completion */ "1: brc 1,0b\n" /* handle partial completion */
" la %0,0\n" " la %0,0\n"
"2:\n" "2:\n"
EX_TABLE(0b,2b) EX_TABLE(1b,2b) EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
: "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest) : "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest)
: "d" (__func), "a" (__param), "0" (-1) : "cc", "memory"); : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
if (ret < 0) if (ret < 0)
...@@ -198,11 +211,11 @@ static inline int crypt_s390_kmc(long func, void *param, ...@@ -198,11 +211,11 @@ static inline int crypt_s390_kmc(long func, void *param,
int ret; int ret;
asm volatile( asm volatile(
"0: .insn rre,0xb92f0000,%3,%1 \n" /* KMC opcode */ "0: .insn rre,0xb92f0000,%3,%1\n" /* KMC opcode */
"1: brc 1,0b \n" /* handle partial completion */ "1: brc 1,0b\n" /* handle partial completion */
" la %0,0\n" " la %0,0\n"
"2:\n" "2:\n"
EX_TABLE(0b,2b) EX_TABLE(1b,2b) EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
: "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest) : "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest)
: "d" (__func), "a" (__param), "0" (-1) : "cc", "memory"); : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
if (ret < 0) if (ret < 0)
...@@ -233,11 +246,11 @@ static inline int crypt_s390_kimd(long func, void *param, ...@@ -233,11 +246,11 @@ static inline int crypt_s390_kimd(long func, void *param,
int ret; int ret;
asm volatile( asm volatile(
"0: .insn rre,0xb93e0000,%1,%1 \n" /* KIMD opcode */ "0: .insn rre,0xb93e0000,%1,%1\n" /* KIMD opcode */
"1: brc 1,0b \n" /* handle partial completion */ "1: brc 1,0b\n" /* handle partial completion */
" la %0,0\n" " la %0,0\n"
"2:\n" "2:\n"
EX_TABLE(0b,2b) EX_TABLE(1b,2b) EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
: "=d" (ret), "+a" (__src), "+d" (__src_len) : "=d" (ret), "+a" (__src), "+d" (__src_len)
: "d" (__func), "a" (__param), "0" (-1) : "cc", "memory"); : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
if (ret < 0) if (ret < 0)
...@@ -267,11 +280,11 @@ static inline int crypt_s390_klmd(long func, void *param, ...@@ -267,11 +280,11 @@ static inline int crypt_s390_klmd(long func, void *param,
int ret; int ret;
asm volatile( asm volatile(
"0: .insn rre,0xb93f0000,%1,%1 \n" /* KLMD opcode */ "0: .insn rre,0xb93f0000,%1,%1\n" /* KLMD opcode */
"1: brc 1,0b \n" /* handle partial completion */ "1: brc 1,0b\n" /* handle partial completion */
" la %0,0\n" " la %0,0\n"
"2:\n" "2:\n"
EX_TABLE(0b,2b) EX_TABLE(1b,2b) EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
: "=d" (ret), "+a" (__src), "+d" (__src_len) : "=d" (ret), "+a" (__src), "+d" (__src_len)
: "d" (__func), "a" (__param), "0" (-1) : "cc", "memory"); : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
if (ret < 0) if (ret < 0)
...@@ -302,11 +315,11 @@ static inline int crypt_s390_kmac(long func, void *param, ...@@ -302,11 +315,11 @@ static inline int crypt_s390_kmac(long func, void *param,
int ret; int ret;
asm volatile( asm volatile(
"0: .insn rre,0xb91e0000,%1,%1 \n" /* KLAC opcode */ "0: .insn rre,0xb91e0000,%1,%1\n" /* KLAC opcode */
"1: brc 1,0b \n" /* handle partial completion */ "1: brc 1,0b\n" /* handle partial completion */
" la %0,0\n" " la %0,0\n"
"2:\n" "2:\n"
EX_TABLE(0b,2b) EX_TABLE(1b,2b) EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
: "=d" (ret), "+a" (__src), "+d" (__src_len) : "=d" (ret), "+a" (__src), "+d" (__src_len)
: "d" (__func), "a" (__param), "0" (-1) : "cc", "memory"); : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
if (ret < 0) if (ret < 0)
...@@ -340,11 +353,11 @@ static inline int crypt_s390_kmctr(long func, void *param, u8 *dest, ...@@ -340,11 +353,11 @@ static inline int crypt_s390_kmctr(long func, void *param, u8 *dest,
int ret = -1; int ret = -1;
asm volatile( asm volatile(
"0: .insn rrf,0xb92d0000,%3,%1,%4,0 \n" /* KMCTR opcode */ "0: .insn rrf,0xb92d0000,%3,%1,%4,0\n" /* KMCTR opcode */
"1: brc 1,0b \n" /* handle partial completion */ "1: brc 1,0b\n" /* handle partial completion */
" la %0,0\n" " la %0,0\n"
"2:\n" "2:\n"
EX_TABLE(0b,2b) EX_TABLE(1b,2b) EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
: "+d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest), : "+d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest),
"+a" (__ctr) "+a" (__ctr)
: "d" (__func), "a" (__param) : "cc", "memory"); : "d" (__func), "a" (__param) : "cc", "memory");
...@@ -353,6 +366,47 @@ static inline int crypt_s390_kmctr(long func, void *param, u8 *dest, ...@@ -353,6 +366,47 @@ static inline int crypt_s390_kmctr(long func, void *param, u8 *dest,
return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len; return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
} }
/**
* crypt_s390_ppno:
* @func: the function code passed to PPNO; see crypt_s390_ppno_func
* @param: address of parameter block; see POP for details on each func
* @dest: address of destination memory area
* @dest_len: size of destination memory area in bytes
* @seed: address of seed data
* @seed_len: size of seed data in bytes
*
* Executes the PPNO (PERFORM PSEUDORANDOM NUMBER OPERATION)
* operation of the CPU.
*
* Returns -1 for failure, 0 for the query func, number of random
* bytes stored in dest buffer for generate function
*/
static inline int crypt_s390_ppno(long func, void *param,
u8 *dest, long dest_len,
const u8 *seed, long seed_len)
{
register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
register void *__param asm("1") = param; /* param block (240 bytes) */
register u8 *__dest asm("2") = dest; /* buf for recv random bytes */
register long __dest_len asm("3") = dest_len; /* requested random bytes */
register const u8 *__seed asm("4") = seed; /* buf with seed data */
register long __seed_len asm("5") = seed_len; /* bytes in seed buf */
int ret = -1;
asm volatile (
"0: .insn rre,0xb93c0000,%1,%5\n" /* PPNO opcode */
"1: brc 1,0b\n" /* handle partial completion */
" la %0,0\n"
"2:\n"
EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
: "+d" (ret), "+a"(__dest), "+d"(__dest_len)
: "d"(__func), "a"(__param), "a"(__seed), "d"(__seed_len)
: "cc", "memory");
if (ret < 0)
return ret;
return (func & CRYPT_S390_FUNC_MASK) ? dest_len - __dest_len : 0;
}
/** /**
* crypt_s390_func_available: * crypt_s390_func_available:
* @func: the function code of the specific function; 0 if op in general * @func: the function code of the specific function; 0 if op in general
...@@ -373,6 +427,9 @@ static inline int crypt_s390_func_available(int func, ...@@ -373,6 +427,9 @@ static inline int crypt_s390_func_available(int func,
return 0; return 0;
if (facility_mask & CRYPT_S390_MSA4 && !test_facility(77)) if (facility_mask & CRYPT_S390_MSA4 && !test_facility(77))
return 0; return 0;
if (facility_mask & CRYPT_S390_MSA5 && !test_facility(57))
return 0;
switch (func & CRYPT_S390_OP_MASK) { switch (func & CRYPT_S390_OP_MASK) {
case CRYPT_S390_KM: case CRYPT_S390_KM:
ret = crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0); ret = crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0);
...@@ -390,8 +447,12 @@ static inline int crypt_s390_func_available(int func, ...@@ -390,8 +447,12 @@ static inline int crypt_s390_func_available(int func,
ret = crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0); ret = crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0);
break; break;
case CRYPT_S390_KMCTR: case CRYPT_S390_KMCTR:
ret = crypt_s390_kmctr(KMCTR_QUERY, &status, NULL, NULL, 0, ret = crypt_s390_kmctr(KMCTR_QUERY, &status,
NULL); NULL, NULL, 0, NULL);
break;
case CRYPT_S390_PPNO:
ret = crypt_s390_ppno(PPNO_QUERY, &status,
NULL, 0, NULL, 0);
break; break;
default: default:
return 0; return 0;
...@@ -419,15 +480,14 @@ static inline int crypt_s390_pcc(long func, void *param) ...@@ -419,15 +480,14 @@ static inline int crypt_s390_pcc(long func, void *param)
int ret = -1; int ret = -1;
asm volatile( asm volatile(
"0: .insn rre,0xb92c0000,0,0 \n" /* PCC opcode */ "0: .insn rre,0xb92c0000,0,0\n" /* PCC opcode */
"1: brc 1,0b \n" /* handle partial completion */ "1: brc 1,0b\n" /* handle partial completion */
" la %0,0\n" " la %0,0\n"
"2:\n" "2:\n"
EX_TABLE(0b,2b) EX_TABLE(1b,2b) EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
: "+d" (ret) : "+d" (ret)
: "d" (__func), "a" (__param) : "cc", "memory"); : "d" (__func), "a" (__param) : "cc", "memory");
return ret; return ret;
} }
#endif /* _CRYPTO_ARCH_S390_CRYPT_S390_H */ #endif /* _CRYPTO_ARCH_S390_CRYPT_S390_H */
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册