2 * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
10 #define S390X_CCM_AAD_FLAG 0x40
12 static int s390x_aes_ccm_init_key(PROV_CCM_CTX
*ctx
,
13 const unsigned char *key
, size_t keylen
)
15 PROV_AES_CCM_CTX
*sctx
= (PROV_AES_CCM_CTX
*)ctx
;
17 sctx
->ccm
.s390x
.fc
= S390X_AES_FC(keylen
);
18 memcpy(&sctx
->ccm
.s390x
.kmac
.k
, key
, keylen
);
19 /* Store encoded m and l. */
20 sctx
->ccm
.s390x
.nonce
.b
[0] = ((ctx
->l
- 1) & 0x7)
21 | (((ctx
->m
- 2) >> 1) & 0x7) << 3;
22 memset(sctx
->ccm
.s390x
.nonce
.b
+ 1, 0, sizeof(sctx
->ccm
.s390x
.nonce
.b
));
23 sctx
->ccm
.s390x
.blocks
= 0;
28 static int s390x_aes_ccm_setiv(PROV_CCM_CTX
*ctx
,
29 const unsigned char *nonce
, size_t noncelen
,
32 PROV_AES_CCM_CTX
*sctx
= (PROV_AES_CCM_CTX
*)ctx
;
34 sctx
->ccm
.s390x
.nonce
.b
[0] &= ~S390X_CCM_AAD_FLAG
;
35 sctx
->ccm
.s390x
.nonce
.g
[1] = mlen
;
36 memcpy(sctx
->ccm
.s390x
.nonce
.b
+ 1, nonce
, 15 - ctx
->l
);
41 * Process additional authenticated data. Code is big-endian.
43 static int s390x_aes_ccm_setaad(PROV_CCM_CTX
*ctx
,
44 const unsigned char *aad
, size_t alen
)
46 PROV_AES_CCM_CTX
*sctx
= (PROV_AES_CCM_CTX
*)ctx
;
53 sctx
->ccm
.s390x
.nonce
.b
[0] |= S390X_CCM_AAD_FLAG
;
55 /* Suppress 'type-punned pointer dereference' warning. */
56 ptr
= sctx
->ccm
.s390x
.buf
.b
;
58 if (alen
< ((1 << 16) - (1 << 8))) {
59 *(uint16_t *)ptr
= alen
;
61 } else if (sizeof(alen
) == 8
62 && alen
>= (size_t)1 << (32 % (sizeof(alen
) * 8))) {
63 *(uint16_t *)ptr
= 0xffff;
64 *(uint64_t *)(ptr
+ 2) = alen
;
67 *(uint16_t *)ptr
= 0xfffe;
68 *(uint32_t *)(ptr
+ 2) = alen
;
72 while (i
< 16 && alen
) {
73 sctx
->ccm
.s390x
.buf
.b
[i
] = *aad
;
79 sctx
->ccm
.s390x
.buf
.b
[i
] = 0;
83 sctx
->ccm
.s390x
.kmac
.icv
.g
[0] = 0;
84 sctx
->ccm
.s390x
.kmac
.icv
.g
[1] = 0;
85 s390x_kmac(sctx
->ccm
.s390x
.nonce
.b
, 32, sctx
->ccm
.s390x
.fc
,
86 &sctx
->ccm
.s390x
.kmac
);
87 sctx
->ccm
.s390x
.blocks
+= 2;
92 s390x_kmac(aad
, alen
, sctx
->ccm
.s390x
.fc
, &sctx
->ccm
.s390x
.kmac
);
93 sctx
->ccm
.s390x
.blocks
+= alen
>> 4;
97 for (i
= 0; i
< rem
; i
++)
98 sctx
->ccm
.s390x
.kmac
.icv
.b
[i
] ^= aad
[i
];
100 s390x_km(sctx
->ccm
.s390x
.kmac
.icv
.b
, 16,
101 sctx
->ccm
.s390x
.kmac
.icv
.b
, sctx
->ccm
.s390x
.fc
,
102 sctx
->ccm
.s390x
.kmac
.k
);
103 sctx
->ccm
.s390x
.blocks
++;
109 * En/de-crypt plain/cipher-text. Compute tag from plaintext. Returns 1 for
112 static int s390x_aes_ccm_auth_encdec(PROV_CCM_CTX
*ctx
,
113 const unsigned char *in
,
114 unsigned char *out
, size_t len
, int enc
)
116 PROV_AES_CCM_CTX
*sctx
= (PROV_AES_CCM_CTX
*)ctx
;
118 unsigned int i
, l
, num
;
121 flags
= sctx
->ccm
.s390x
.nonce
.b
[0];
122 if (!(flags
& S390X_CCM_AAD_FLAG
)) {
123 s390x_km(sctx
->ccm
.s390x
.nonce
.b
, 16, sctx
->ccm
.s390x
.kmac
.icv
.b
,
124 sctx
->ccm
.s390x
.fc
, sctx
->ccm
.s390x
.kmac
.k
);
125 sctx
->ccm
.s390x
.blocks
++;
128 sctx
->ccm
.s390x
.nonce
.b
[0] = l
;
131 * Reconstruct length from encoded length field
132 * and initialize it with counter value.
135 for (i
= 15 - l
; i
< 15; i
++) {
136 n
|= sctx
->ccm
.s390x
.nonce
.b
[i
];
137 sctx
->ccm
.s390x
.nonce
.b
[i
] = 0;
140 n
|= sctx
->ccm
.s390x
.nonce
.b
[15];
141 sctx
->ccm
.s390x
.nonce
.b
[15] = 1;
144 return 0; /* length mismatch */
147 /* Two operations per block plus one for tag encryption */
148 sctx
->ccm
.s390x
.blocks
+= (((len
+ 15) >> 4) << 1) + 1;
149 if (sctx
->ccm
.s390x
.blocks
> (1ULL << 61))
150 return 0; /* too much data */
158 /* mac-then-encrypt */
160 s390x_kmac(in
, len
, sctx
->ccm
.s390x
.fc
, &sctx
->ccm
.s390x
.kmac
);
162 for (i
= 0; i
< rem
; i
++)
163 sctx
->ccm
.s390x
.kmac
.icv
.b
[i
] ^= in
[len
+ i
];
165 s390x_km(sctx
->ccm
.s390x
.kmac
.icv
.b
, 16,
166 sctx
->ccm
.s390x
.kmac
.icv
.b
,
167 sctx
->ccm
.s390x
.fc
, sctx
->ccm
.s390x
.kmac
.k
);
170 CRYPTO_ctr128_encrypt_ctr32(in
, out
, len
+ rem
, &sctx
->ccm
.ks
.ks
,
171 sctx
->ccm
.s390x
.nonce
.b
, sctx
->ccm
.s390x
.buf
.b
,
172 &num
, (ctr128_f
)AES_ctr32_encrypt
);
174 /* decrypt-then-mac */
175 CRYPTO_ctr128_encrypt_ctr32(in
, out
, len
+ rem
, &sctx
->ccm
.ks
.ks
,
176 sctx
->ccm
.s390x
.nonce
.b
, sctx
->ccm
.s390x
.buf
.b
,
177 &num
, (ctr128_f
)AES_ctr32_encrypt
);
180 s390x_kmac(out
, len
, sctx
->ccm
.s390x
.fc
, &sctx
->ccm
.s390x
.kmac
);
182 for (i
= 0; i
< rem
; i
++)
183 sctx
->ccm
.s390x
.kmac
.icv
.b
[i
] ^= out
[len
+ i
];
185 s390x_km(sctx
->ccm
.s390x
.kmac
.icv
.b
, 16,
186 sctx
->ccm
.s390x
.kmac
.icv
.b
,
187 sctx
->ccm
.s390x
.fc
, sctx
->ccm
.s390x
.kmac
.k
);
191 for (i
= 15 - l
; i
< 16; i
++)
192 sctx
->ccm
.s390x
.nonce
.b
[i
] = 0;
194 s390x_km(sctx
->ccm
.s390x
.nonce
.b
, 16, sctx
->ccm
.s390x
.buf
.b
,
195 sctx
->ccm
.s390x
.fc
, sctx
->ccm
.s390x
.kmac
.k
);
196 sctx
->ccm
.s390x
.kmac
.icv
.g
[0] ^= sctx
->ccm
.s390x
.buf
.g
[0];
197 sctx
->ccm
.s390x
.kmac
.icv
.g
[1] ^= sctx
->ccm
.s390x
.buf
.g
[1];
199 sctx
->ccm
.s390x
.nonce
.b
[0] = flags
; /* restore flags field */
204 static int s390x_aes_ccm_gettag(PROV_CCM_CTX
*ctx
,
205 unsigned char *tag
, size_t tlen
)
207 PROV_AES_CCM_CTX
*sctx
= (PROV_AES_CCM_CTX
*)ctx
;
211 memcpy(tag
, sctx
->ccm
.s390x
.kmac
.icv
.b
, tlen
);
215 static int s390x_aes_ccm_auth_encrypt(PROV_CCM_CTX
*ctx
,
216 const unsigned char *in
,
217 unsigned char *out
, size_t len
,
218 unsigned char *tag
, size_t taglen
)
222 rv
= s390x_aes_ccm_auth_encdec(ctx
, in
, out
, len
, 1);
223 if (rv
&& tag
!= NULL
)
224 rv
= s390x_aes_ccm_gettag(ctx
, tag
, taglen
);
228 static int s390x_aes_ccm_auth_decrypt(PROV_CCM_CTX
*ctx
,
229 const unsigned char *in
,
230 unsigned char *out
, size_t len
,
231 unsigned char *expected_tag
,
235 PROV_AES_CCM_CTX
*sctx
= (PROV_AES_CCM_CTX
*)ctx
;
237 rv
= s390x_aes_ccm_auth_encdec(ctx
, in
, out
, len
, 0);
239 if (CRYPTO_memcmp(sctx
->ccm
.s390x
.kmac
.icv
.b
, expected_tag
, ctx
->m
) != 0)
243 OPENSSL_cleanse(out
, len
);
247 static const PROV_CCM_HW s390x_aes_ccm
= {
248 s390x_aes_ccm_init_key
,
250 s390x_aes_ccm_setaad
,
251 s390x_aes_ccm_auth_encrypt
,
252 s390x_aes_ccm_auth_decrypt
,
256 const PROV_CCM_HW
*PROV_AES_HW_ccm(size_t keybits
)
258 if ((keybits
== 128 && S390X_aes_128_ccm_CAPABLE
)
259 || (keybits
== 192 && S390X_aes_192_ccm_CAPABLE
)
260 || (keybits
== 256 && S390X_aes_256_ccm_CAPABLE
))
261 return &s390x_aes_ccm
;