diff options
author | Marcelo Cerri <mhcerri@linux.vnet.ibm.com> | 2013-08-29 10:36:38 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2013-09-02 06:32:55 -0400 |
commit | 41e3173daf4e2d2f2dcc48ae7ffc8d0c4f3ecec9 (patch) | |
tree | 7ed61814485e0d054cc982bf1b9fbf84365582a2 /drivers/crypto | |
parent | 2b188b3b86005ca63eb851a1992f06b9a301f800 (diff) |
crypto: nx - fix XCBC for zero length messages
The NX XCBC implementation doesn't support zero length messages and
because of that NX is currently returning a hard-coded hash for zero
length messages. However this approach is incorrect since the hash value
also depends on which key is used.
This patch removes the hard-coded hash and replace it with an
implementation based on the RFC 3566 using ECB.
Reviewed-by: Joy Latten <jmlatten@linux.vnet.ibm.com>
Signed-off-by: Marcelo Cerri <mhcerri@linux.vnet.ibm.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto')
-rw-r--r-- | drivers/crypto/nx/nx-aes-xcbc.c | 84 |
1 files changed, 77 insertions, 7 deletions
diff --git a/drivers/crypto/nx/nx-aes-xcbc.c b/drivers/crypto/nx/nx-aes-xcbc.c index 1a5d9e372b4e..03c4bf57d066 100644 --- a/drivers/crypto/nx/nx-aes-xcbc.c +++ b/drivers/crypto/nx/nx-aes-xcbc.c | |||
@@ -56,6 +56,77 @@ static int nx_xcbc_set_key(struct crypto_shash *desc, | |||
56 | return 0; | 56 | return 0; |
57 | } | 57 | } |
58 | 58 | ||
59 | /* | ||
60 | * Based on RFC 3566, for a zero-length message: | ||
61 | * | ||
62 | * n = 1 | ||
63 | * K1 = E(K, 0x01010101010101010101010101010101) | ||
64 | * K3 = E(K, 0x03030303030303030303030303030303) | ||
65 | * E[0] = 0x00000000000000000000000000000000 | ||
66 | * M[1] = 0x80000000000000000000000000000000 (0 length message with padding) | ||
67 | * E[1] = (K1, M[1] ^ E[0] ^ K3) | ||
68 | * Tag = M[1] | ||
69 | */ | ||
70 | static int nx_xcbc_empty(struct shash_desc *desc, u8 *out) | ||
71 | { | ||
72 | struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base); | ||
73 | struct nx_csbcpb *csbcpb = nx_ctx->csbcpb; | ||
74 | struct nx_sg *in_sg, *out_sg; | ||
75 | u8 keys[2][AES_BLOCK_SIZE]; | ||
76 | u8 key[32]; | ||
77 | int rc = 0; | ||
78 | |||
79 | /* Change to ECB mode */ | ||
80 | csbcpb->cpb.hdr.mode = NX_MODE_AES_ECB; | ||
81 | memcpy(key, csbcpb->cpb.aes_xcbc.key, AES_BLOCK_SIZE); | ||
82 | memcpy(csbcpb->cpb.aes_ecb.key, key, AES_BLOCK_SIZE); | ||
83 | NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT; | ||
84 | |||
85 | /* K1 and K3 base patterns */ | ||
86 | memset(keys[0], 0x01, sizeof(keys[0])); | ||
87 | memset(keys[1], 0x03, sizeof(keys[1])); | ||
88 | |||
89 | /* Generate K1 and K3 encrypting the patterns */ | ||
90 | in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *) keys, sizeof(keys), | ||
91 | nx_ctx->ap->sglen); | ||
92 | out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *) keys, sizeof(keys), | ||
93 | nx_ctx->ap->sglen); | ||
94 | nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg); | ||
95 | nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg); | ||
96 | |||
97 | rc = nx_hcall_sync(nx_ctx, &nx_ctx->op, | ||
98 | desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP); | ||
99 | if (rc) | ||
100 | goto out; | ||
101 | atomic_inc(&(nx_ctx->stats->aes_ops)); | ||
102 | |||
103 | /* XOr K3 with the padding for a 0 length message */ | ||
104 | keys[1][0] ^= 0x80; | ||
105 | |||
106 | /* Encrypt the final result */ | ||
107 | memcpy(csbcpb->cpb.aes_ecb.key, keys[0], AES_BLOCK_SIZE); | ||
108 | in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *) keys[1], sizeof(keys[1]), | ||
109 | nx_ctx->ap->sglen); | ||
110 | out_sg = nx_build_sg_list(nx_ctx->out_sg, out, AES_BLOCK_SIZE, | ||
111 | nx_ctx->ap->sglen); | ||
112 | nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg); | ||
113 | nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg); | ||
114 | |||
115 | rc = nx_hcall_sync(nx_ctx, &nx_ctx->op, | ||
116 | desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP); | ||
117 | if (rc) | ||
118 | goto out; | ||
119 | atomic_inc(&(nx_ctx->stats->aes_ops)); | ||
120 | |||
121 | out: | ||
122 | /* Restore XCBC mode */ | ||
123 | csbcpb->cpb.hdr.mode = NX_MODE_AES_XCBC_MAC; | ||
124 | memcpy(csbcpb->cpb.aes_xcbc.key, key, AES_BLOCK_SIZE); | ||
125 | NX_CPB_FDM(csbcpb) &= ~NX_FDM_ENDE_ENCRYPT; | ||
126 | |||
127 | return rc; | ||
128 | } | ||
129 | |||
59 | static int nx_xcbc_init(struct shash_desc *desc) | 130 | static int nx_xcbc_init(struct shash_desc *desc) |
60 | { | 131 | { |
61 | struct xcbc_state *sctx = shash_desc_ctx(desc); | 132 | struct xcbc_state *sctx = shash_desc_ctx(desc); |
@@ -201,13 +272,12 @@ static int nx_xcbc_final(struct shash_desc *desc, u8 *out) | |||
201 | memcpy(csbcpb->cpb.aes_xcbc.cv, | 272 | memcpy(csbcpb->cpb.aes_xcbc.cv, |
202 | csbcpb->cpb.aes_xcbc.out_cv_mac, AES_BLOCK_SIZE); | 273 | csbcpb->cpb.aes_xcbc.out_cv_mac, AES_BLOCK_SIZE); |
203 | } else if (sctx->count == 0) { | 274 | } else if (sctx->count == 0) { |
204 | /* we've never seen an update, so this is a 0 byte op. The | 275 | /* |
205 | * hardware cannot handle a 0 byte op, so just copy out the | 276 | * we've never seen an update, so this is a 0 byte op. The |
206 | * known 0 byte result. This is cheaper than allocating a | 277 | * hardware cannot handle a 0 byte op, so just ECB to |
207 | * software context to do a 0 byte op */ | 278 | * generate the hash. |
208 | u8 data[] = { 0x75, 0xf0, 0x25, 0x1d, 0x52, 0x8a, 0xc0, 0x1c, | 279 | */ |
209 | 0x45, 0x73, 0xdf, 0xd5, 0x84, 0xd7, 0x9f, 0x29 }; | 280 | rc = nx_xcbc_empty(desc, out); |
210 | memcpy(out, data, sizeof(data)); | ||
211 | goto out; | 281 | goto out; |
212 | } | 282 | } |
213 | 283 | ||