On Fri, 24 May 2024 11:42:37 GMT, Francisco Ferrari Bihurriet 
<fferr...@openjdk.org> wrote:

>> Hi,
>> 
>> I would like to propose an implementation to support AES CBC with Ciphertext 
>> Stealing (CTS) in SunPKCS11, according to what has been specified in 
>> [JDK-8330843 CSR](https://bugs.openjdk.org/browse/JDK-8330843).
>> 
>> What follows are implementation notes that describe the most relevant 
>> aspects of the proposed change.
>> 
>> ### Buffering
>> 
>> A buffering mechanism was implemented so PKCS #​11 tokens only receive 
>> multipart input updates (`C_EncryptUpdate` or `C_DecryptUpdate`) in 
>> multiples of the block size. This mechanism protects against tokens —such as 
>> NSS— that assume an update with data not multiple of the block size is final 
>> and do variant ordering between the last 2 blocks, returning an incorrect 
>> partial output and resetting state. For example, when encrypting, a token 
>> may receive an update with an input not multiple of the block size and 
>> prematurely finalize the operation returning the last two blocks of 
>> ciphertext according to its ordering. By buffering on the Java side, the 
>> token is not aware of the end of the stream during updates and SunPKCS11 
>> retains full control to do the last two blocks at `C_EncryptFinal` or 
>> `C_DecryptFinal`. A bug in NSS (see 
>> [1823875](https://bugzilla.mozilla.org/show_bug.cgi?id=1823875#c2)) requires 
>> buffering three blocks instead of two. If this bug gets fixed, the three 
>> block b
 uffering will still work and allow it to support old versions of the NSS 
library.
>> 
>> ### `implUpdate` implementation
>> 
>> The code added to `P11Cipher::implUpdate` follows the existing three-stage 
>> strategy: 1) Process data in the `padBuffer`, 2) Process data in the input 
>> and 3) Buffer to `padBuffer`. Stage #​1 for CTS has some additional 
>> complexity that is worth describing in this section.
>> 
>> The stage begins by calculating the total data available (what is already 
>> buffered in `padBuffer` + the new input) and assigning this value to the 
>> variable `totalInLen`. `newPadBufferLen` is the number of bytes that must be 
>> buffered at the end of the update operation, irrespective of where they come 
>> from (`padBuffer` or input). This number of bytes is determined out of 
>> `totalInLen` and based on the fact that each operation must retain bytes 
>> from the last two —or three, for NSS— blocks in `padBuffer`, or retain 
>> whatever is available if less than that. `dataForP11Update` is the number of 
>> bytes to be passed to the token during the operation (`C_EncryptUpdate` or 
>> `C_DecryptUpdate` calls), irrespective of the stage in which they are passed 
>> and of the dat...
>
> Francisco Ferrari Bihurriet has updated the pull request with a new target 
> base due to a merge or a rebase. The incremental webrev excludes the 
> unrelated changes brought in by the merge/rebase. The pull request contains 
> seven additional commits since the last revision:
> 
>  - Revert re-arrangement of native methods parameters
>    
>    This reverts commit 0a777e94229723376e1264e87cbf0ba805dc736f, except for
>    the copyright which is retained as 2024.
>    
>    NOTE: new calls of the same methods are retained in the re-arrangement
>    style, as we didn't introduce this re-arrangement, it was already
>    present in most of the calls inside ::implUpdate() and ::implDoFinal().
>    
>    Co-authored-by: Francisco Ferrari <fferr...@redhat.com>
>    Co-authored-by: Martin Balao <mba...@redhat.com>
>  - Merge 'openjdk/master' into JDK-8330843
>  - 8330842: Add AES CBC with Ciphertext Stealing (CTS) SunPKCS11 tests
>    
>    Co-authored-by: Francisco Ferrari <fferr...@redhat.com>
>    Co-authored-by: Martin Balao <mba...@redhat.com>
>  - 8330842: Support AES CBC with Ciphertext Stealing (CTS) in SunPKCS11
>    
>    Co-authored-by: Francisco Ferrari <fferr...@redhat.com>
>    Co-authored-by: Martin Balao <mba...@redhat.com>
>  - Fix cipher tests logging
>    
>    Co-authored-by: Francisco Ferrari <fferr...@redhat.com>
>    Co-authored-by: Martin Balao <mba...@redhat.com>
>  - Implement integer constants as enum
>    
>    Co-authored-by: Francisco Ferrari <fferr...@redhat.com>
>    Co-authored-by: Martin Balao <mba...@redhat.com>
>  - Arrange parameters of native methods evenly
>    
>    C_EncryptUpdate / C_DecryptUpdate / C_EncryptFinal / C_DecryptFinal
>    
>    If the call doesn't fit on a single line, use the following order:
>         long hSession,
>      [  long directIn,  byte[] in,  int inOfs,  int inLen,  ]
>         long directOut, byte[] out, int outOfs, int outLen
>    
>    [ ]: optional, not present in C_EncryptFinal / C_DecryptFinal
>    
>    Co-authored-by: Francisco Ferrari <fferr...@redhat.com>
>    Co-authored-by: Martin Balao <mba...@redhat.com>

The [PKCS #<wbr/>11 definition of 
`CKM_AES_CTS`](https://docs.oasis-open.org/pkcs11/pkcs11-curr/v3.0/pkcs11-curr-v3.0.html#_Toc30061253)
 refers to the [Addendum to NIST Special Publication 800-38A, "Recommendation 
for Block Cipher Modes of Operation: Three Variants of Ciphertext Stealing for 
CBC Mode"](https://doi.org/10.6028/NIST.SP.800-38A-Add) document. However, the 
standard does not prescribe which of the three CTS variants described by the 
document to use. This left the door open for PKCS #<wbr/>11 implementers to 
make different assumptions and create interoperability issues.

We are aware that the _NSS Software Token_ implemented the CS1 variant (see 
[lib/freebl/cts.c](https://github.com/nss-dev/nss/blob/NSS_3_90_RTM/lib/freebl/cts.c#L64-L65)),
 but [public clarification had to be given in NSS Bug 
373108](https://bugzilla.mozilla.org/show_bug.cgi?id=373108#c7). That's why we 
chose `CS1` as the `cipherTextStealingVariant` default.

> As for the different variations, are you aware of different vendors 
> supporting different variations?

At the moment of developing this enhancement, we were not aware of any other 
variant in use, but we had only evaluated NSS. The standard has a clear 
ambiguity, so there was a latent problem. Now, I have found another open source 
project using CS3 instead (see below).

> This assumes prior knowledge on the variation used by underlying PKCS11 
> library, right?

Unfortunately yes, but it gives the user a chance to adjust for their PKCS11 
library without the need of a _SunPKCS11_ update from our side.

> Are all these variations under "CTS" name?

Yes, they are known as "variants" —according to the mentioned NIST addendum— or 
"formats" —according to 
[Wikipedia](https://en.wikipedia.org/wiki/Ciphertext_stealing#Ciphertext_format 
"Wikipedia: Ciphertext stealing - Ciphertext format")—, always in the context 
of "Cipher Text Stealing".

> Are they generally supported by all?

According to _Wikipedia_, the most popular alternative is CS3. It also happens 
to be the Kerberos choice, and so the one implemented by _SunJCE_'s 
`AES/CTS/NoPadding`. However, NSS chose CS1 as it was the first one described 
in the NIST addendum, referred by the PKCS #<wbr/>11 standard.

In the sake of interoperability, the PKCS #<wbr/>11 standard should choose one 
of the three variants. But since it is too late, PKCS #<wbr/>11 implementers 
supporting `CKM_AES_CTS` have already made their choice.

### OP-TEE provides a PKCS #<wbr/>11 interface, and has chosen CS3

Searching for other open source implementers, I have found that the [OP-TEE 
Trusted Execution Environment (TEE) exposes a PKCS #<wbr/>11 
module](https://optee.readthedocs.io/en/latest/building/userland_integration.html).
 I don't know how widespread this project is, but it works as an example of how 
other implementors might behave.

This PKCS #<wbr/>11 implementation uses CS3 for `CKM_AES_CTS`, contrary to NSS' 
choice of CS1:

1. The `CKM_AES_CTS` constant [has the `0x1089` 
value](https://github.com/openjdk/jdk/blob/jdk-23+24/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Constants.java#L889)
2. `CKM_AES_CTS` is [represented by the `PKCS11_CKM_AES_CTS` 
constant](https://github.com/OP-TEE/optee_os/blob/4.2.0/ta/pkcs11/include/pkcs11_ta.h#L1326)
 in OP-TEE
3. `PKCS11_CKM_AES_CTS` [is mapped to 
`TEE_ALG_AES_CTS`](https://github.com/OP-TEE/optee_os/blob/4.2.0/ta/pkcs11/src/processing_symm.c#L73)
4. When creating a `TEE_ALG_AES_CTS` context, [the `crypto_aes_cts_alloc_ctx()` 
function is 
used](https://github.com/OP-TEE/optee_os/blob/4.2.0/core/crypto/crypto.c#L136-L138)
5. This function [puts in the context a structure with operation callbacks that 
implement 
CTS](https://github.com/OP-TEE/optee_os/blob/4.2.0/core/crypto/aes-cts.c#L249)
6. The `cts_update.update` callback leads to `cts_update()`, which [then calls 
`cbc_cts_update()`](https://github.com/OP-TEE/optee_os/blob/4.2.0/core/crypto/aes-cts.c#L194-L195)
7. In `cbc_cts_update()`, [`len_last_block` is equal to `block_size` when the 
message would not require 
padding](https://github.com/OP-TEE/optee_os/blob/4.2.0/core/crypto/aes-cts.c#L113-L114)
8. Given the previous item fact, [the encryption code unconditionally swaps the 
last two 
blocks](https://github.com/OP-TEE/optee_os/blob/4.2.0/core/crypto/aes-cts.c#L130-L136),
 which corresponds to CS3
9. In addition, [CS3 is mentioned in a previous code 
comment](https://github.com/OP-TEE/optee_os/blob/4.2.0/core/crypto/aes-cts.c#L30)

-------------

PR Comment: https://git.openjdk.org/jdk/pull/18898#issuecomment-2133588824

Reply via email to