Internet-Draft RSA Implementation Guidance September 2024
Kario Expires 7 March 2025 [Page]
Workgroup:
Internet Engineering Task Force
Internet-Draft:
draft-irtf-cfrg-rsa-guidance-01
Updates:
8017 (if approved)
Published:
Intended Status:
Informational
Expires:
Author:
A. Kario
Red Hat, Inc.

Implementation Guidance for the PKCS #1 RSA Cryptography Specification

Abstract

This document specifies additions and amendments to RFC 8017. Specifically, it provides guidance to implementers of the standard to protect against side-channel attacks. It also deprecates the RSAES-PKCS-v1_5 encryption scheme, but provides an alternative depadding algorithm that protects against side-channel attacks raising from users of vulnerable APIs. The purpose of this specification is to increase security of RSA implementations.

Status of This Memo

This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.

Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.

Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."

This Internet-Draft will expire on 7 March 2025.

Table of Contents

1. Introduction

The PKCS #1 [RFC8017] describes the RSA cryptosystem, providing guidance on implementing encryption schemes and signature schemes.

Unfortunately, straight-forward implementation of the RSA encryption schemes leave it vulnerable to side-channel attacks. Protections against them are not documented in RFC 8017, and attacks are mentioned only in passing.

2. Rationale

The RSAES-PKCS-v1_5 encryption scheme is known to be problematic since 1998, when Daniel Bleichenbacher published his attack [Bleichenbacher98]. Side-channel attacks against public key algorithms, including RSA, are known to be possible since 1996 thanks to work by Paul Kocher [Kocher96].

Despite those results, side-channel attacks against RSA implementations have proliferated for the next 25 years. Including attacks against simple exponentiation implementations [Dhem98][Schindler01], implementations that use the Chinese Remainder Theorem optimisation [Schindler00][Brumley03] [Aciicmez05], and implementations that use either base or exponent blinding exclusively [Aciicmez07][Aciicmez08] [Schindler14].

Similarly, side-channel free handling of the errors from the RSAES-PKCS-v1_5 decryption operation is something that implementations struggle with [Bock18][Kario23].

We thus provide guidance how to implement those algorithms in a way that should be secure against at least the simple timing side channel attacks.

3. Requirements Language

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 [RFC2119].

4. Notation

In this document we reuse the notation from RFC 8017, in addition, we define the following:

AL

alternative message length, non-negative integer, 0 <= AL <= k - 11

AM

alternative encoded message, an octet string

bb

base blinding factor, a positive integer

bbInv

base un-blinding factor, a positive integer,

  bbInv = bb^(-1) mod n
D

octet string representation of d

DH

an octet string of a SHA-256 hash of D

KDK

an octet string containing a Key Derivation Key for a specific ciphertext C

l

length in octets of the message M

b_i

an exponent blinding factor for i-th prime, non-negative integer.

g_i

a modulus blinding factor for the i-th prime, non-negative integer.

5. Side channel attacks

Cryptographic implementations may provide a lot of indirect signals to the attacker that includes information about the secret processed data. Depending on type of information, those leaks can be used to decrypt data or retrieve private keys. Most common side-channels that leak information about secret data are:

  1. Different errors returned

  2. Different processing times of operations

  3. Different patterns of jump instructions and memory accesses

  4. Use of hardware instructions that take different amount time to execute depending on operands or result

Some of those leaks may be detectable over the network, while others may require closer access to the attacked system. With closer access, the attacker may be able to measure power usage, electromagnetic emanations, or sounds and correlate them with specific bits of secret information.

Recent research into network based side channel detection has shown that even very small side channels (of just few clock cycles) can be reliably detected over the network. The detectability depends on the sample size the attacker is able to collect, not on size of the side-channel.

6. General recommendations

As a general rule, all operations that process secret information (be it parts of the private key or parts of encrypted message) MUST be performed with code that doesn't have secret data dependent branch instructions, secret data dependent memory accesses, or uses non-constant time machine instructions (which ones are those is architecture dependant, but division is commonly non-constant time).

Special care should be placed around the code that handles the conversion of the numerical representation to the octet string representation in RSA decryption operations.

All operations that use private keys SHOULD additionally employ both base blinding and exponent blinding as protections against leaks inside modular exponentiation code.

7. Side-channel free modular exponentiation

The underlying modular exponentiation algorithm MUST be constant time with regards to the exponent in all uses of the private key.

For private key decryption the modular exponentiation algorithm MUST be constant time with regards to the output of the exponentiation.

In case the Chinese remainder theorem optimisation is used the modular exponentiation algorithm must also be constant time with regards to the used moduli.

7.1. General recommendations

It's especially important to make sure that all values that are secret to the attacker are stored in memory buffers that have sizes determined by the public modulus.

For example, the private exponents should be stored in memory buffers that have sizes determined by the public modulus value, not the numerical values of the exponents themselves.

Similarly, the size of the output buffer for multiplication should always be equal to the sum of buffer sizes of multiplicands. The output size of the modular reduction operation should similarly be equal to the size of the modulus and not depend on bit size of the output.

7.2. Montgomery ladder

For the modular exponentiation algorithm to be side-channel free every step of the calculation MUST NOT depend on the bits of the exponent. In particular, use of simple square and multiply algorithm will leak information about bits of the exponent through lack of multiplication operation in individual exponentiation steps.

The recommended workaround against it, is the use of the Montgomery ladder construction.

While that approach ensures that both the square and multiply operations are performed, the fact that the results of them are placed in different memory locations based on bits of the secret exponent will provide enough information for an attacker to recover the bits of the exponent. To counteract it, the implementation should ensure that both memory locations are accessed and updated on every step.

7.3. Montgomery reduction in multiplication

As multiplication operations quickly make the intermediate values in modular exponentiation large, performing a modular reduction after every multiplication or squaring operation is a common optimisation.

To further optimise the modular reduction, the Montgomery modular multiplication is used for performing the combined multiply-and-reduce operation. The last step of that operation is conditional on the value of the output. A side-channel free implementation should perfom the subtraction in all cases and then copy the result or the first operand of the subtraction based on sign of the result of the subtraction in side-channel free manner.

8. Base blinding

As a protection against multiple attacks, it's RECOMMENDED to perform all operations involving the private key with the use of blinding [Kocher96].

It should be noted that for decryption operations the unblinding operation MUST be performed using side-channel free code that does not leak information about the result of this multiplication and reduction modulo operation.

To implement base blinding, select a number bb uniformly at random such that it is relatively prime to n and smaller than n.

Compute multiplicative inverse of bb modulo n.

  bbInv = bb^(-1) mod n

In the RSADP() operation, after performing step 1, multiply c by bb mod n. Use the result as new c for all the remaining operations.

Before returning the value m in step 3, multiply it by bbInv mod n.

Note: multiplication by bbInv and reduction modulo n MUST be performed using side-channel free code with respect to value m.

As calculating multiplicative inverse is expensive, implementations MAY calculate new values of bb and bbInv by squaring them:

  new bb = bb^2 mod n
  new bbInv = bbInv^2 mod n

A given pair of blinding factors (bb, bbInv) MUST NOT be used for more than one RSADP() operation.

Unless the multiplication (squaring) and reduction modulo operations are verified to be side-channel free, it's RECOMMENDED to generate completely new blinding parameters every few hundred private key operations.

9. Exponent blinding

To further protect against private key leaks, it's RECOMMENDED to perform the blinding of the used exponents [Kocher96].

When performing the RSADP() operation, the blinding depends on the form of the private key.

If the key is in the first form, the pair (n, d), then the exponent d should be modified by adding a multiple of Euler phi(n): m = c^(d + b*phi(n)) mod n. Where b is a 64 bit long uniform random number.

A new value b MUST be selected for every RSADP() operation.

If the key is the second form, the quintuple (p, q, dP, dQ, qInv) with optional sequence of triplets (r_i, d_i, t_i), i = 3, ..., u, then each exponent used MUST be blinded individually.

  1. The m_1 = c^(dP + b_1 * phi(p)) mod p

  2. The m_2 = c^(dQ + b_2 * phi(q)) mod q

  3. If u > 3, then m_i = c^(d_i + b_i * phi(r_i)) mod (r_i)

Where b_1, b_2, ..., b_i are all uniformly selected random numbers at least 64 bits long (or at least 2 machine word sizes, whichever is greater).

As Euler phi(p) for an argument p that's a prime is equal p - 1, it's simple to calculate in this case.

Note: the selection of random b_i values, multiplication of them by the result of phi() function, and addition to the exponent MUST be performed with side-channel free code.

Use of smaller blinding factor is NOT RECOMMENDED, as values shorter than 64 bits have been shown to still be vulnerable to side-channel attacks[Bauer12][Schindler11].

The b_1, b_2, ..., b_i factors MUST NOT be reused for multiple RSADP() operations.

10. Modulus blinding

To protect against private key leaks, it's RECOMMENDED to perform blinding of the used modulus values in the CRT implementations.

When the key is in the first form, the pair (n, d), then the used modulus is public, thus no blinding is necessary.

If the key is in the second form, the quintuple (p, q, dP, dQ, qInv) with the optional sequence f triplets (r_i, d_i, t_i), i = 3, ..., u, then each modulus used MUST be blinded individually.

  1. The m_1 = c^dP mod (g_1 * p)

  2. The m_2 = c^dQ mod (g_2 * q)

  3. If u > 3, then m_i = c^d_i mod (g_3 * r_i)

Where g_1, g_2, ..., g_i are all uniformely selected random number at least 64 bits long (or at least 2 machine word sizes, whicher is greater).

Before step 3 of the original algorithm, reduce the returned value m mod n.

11. Depadding

In case of RSA-OAEP, the padding is self-verifying, thus the depadding operation needs to follow the standard algorithm to provide a safe API to users.

It MUST ignore the value of the very fist octet of padding and process the remaining bytes as if it was equal zero.

The RSAES-PKCS-v1_5 encryption scheme is considered deprecated, and should be used only to process legacy data. It MUST NOT be used as part of online protocols or API endpoints.

For implementations that can't remove support for this padding mode it's RECOMMENDED to implement an implicit rejection mechanism that completely hides from the calling code whether the padding check failed or not.

It should be noted that the algorithm MUST be implemented as stated, otherwise in case of heteregonous environments where two implementations use the same key but implement the implicit rejection differently, it may be possible for the attacker to compare behaviour between the implementations to guess if the padding check failed or not.

The basic idea of the implicit rejection is to prepare a random but deterministic message to be returned in case the standard RSAES-PKCS-v1_5 padding checks fail. To do that, use the private key and the provided ciphertext to derive a static, but unknown to the attacker, random value. It's a combination of the method documented in the TLS 1.2 (RFC 5246[RFC5246]) and the deterministic (EC)DSA signatures (RFC 6979 [RFC6979]).

11.1. IRPRF

For the calculation of the random message for implicit rejection we define a Pseudo-Random Function (PRF) as follows:

IRPRF( KDK, label, length )

Input:

KDK the key derivation key

label a label making the output unique for a given KDK

length requested length of output in octets

Output: derived key, an octet string

Steps:

  1. If KDK is not 32 octets long, or if length is larger than 8192 return error and stop.

  2. The returned value is created by concatenation of subsequent calls to a SHA-256 HMAC function with the KDK as the HMAC key and following octet string as the message:

      P_i = I || label || bitLength
    
  3. Where the I is an iterator value encoded as two octet long big endian integer, label is the passed in label, and bitLength is the length times 8 (to represent number of bits of output) encoded as two octet big endian integer. The iterator is initialised to 0 on first call, and then incremented by 1 for every subsequent HMAC call.

  4. The HMAC is iterated until the concatenated output is shorter than length

  5. The output is the length left-most octets of the concatenated HMAC output

11.2. Implicit rejection

For implementations that cannot remove support for the RSAES-PKCS-v1_5 encryption scheme nor provide a usage-specific API, it's possible to implement an implicit rejection algorithm as a protection measure. It should be noted that implementing it correctly is hard, thus it's RECOMMENDED instead to disable support for RSAES-PKCS-v1_5 padding instead.

To implement implicit rejection, the RSAES-PKCS1-V1_5-DECRYPT from section 7.2.2 of RFC 8017 needs to be implemented as follows:

  1. Length checking: If the length of the ciphertext C is not k octets (or if k < 11), output "decryption error" and stop.

  2. RSA decryption:

    1. Convert the ciphertext C to an integer ciphertext representative c:

        c = OS2IP (C).
      
    2. Apply the RSADP decryption primitive to the RSA private key (n, d) and the ciphertext representative c to produce an integer message representative m:

        m = RSADP ((n, d), c).
      

      Note: the RSADP MUST be constant-time with respect of message m.

      If RSADP outputs "ciphertext representative out of range" (meaning that c >= n), output "decryption error" and stop.

    3. Convert the message representative m to an encoded message EM of length k octets:

        EM = I2OSP (m, k).
      

      Note: I2OSP MUST be constant-time with respect of m.

  3. Derivation of alternative message

    1. Derive the Key Derivation Key (KDK)

      1. Convert the private exponent d to a string of length k octets:

          D = I2OSP (d, k).
        
      2. Hash the private exponent using the SHA-256 algorithm:

          DH = SHA256 (D).
        

        Note: This value MAY be cached between the decryption operations, but MUST be considered private-key equivalent.

      3. Use the DH as the SHA-256 HMAC key and the provided ciphertext C as the message. If the ciphertext C is not k octets long, it MUST be left padded with octets of value zero.

          KDK = HMAC (DH, C, SHA256).
        
    2. Create the candidate lengths and the random message

      1. Use the IRPRF with key KDK, "length" as six octet label encoded with UTF-8, to generate 256 octet output. Interpret this output as 128 two octet long big-endian numbers.

          CL = IRPRF (KDK, "length", 256).
        
      2. Use the IRPRF with key KDK, "message" as a seven octet label encoded with UTF-8 to generate k octet long output to be used as the alternative message:

          AM = IRPRF (KDK, "message", k).
        
    3. Select the alternative length for the alternative message.

      Note: this must be performed in side-channel free way.

      1. Iterate over the 128 candidate CL lengths. For each zero out high order bits so that they have the same bit length as the maximum valid message size (k - 11).

      2. Select the last length that's not larger than k - 11, use 0 if none are. Save it as AL.

  4. EME-PKCS1-v1_5 decoding: Separate the encoded message EM into an octet string PS consisting of nonzero octets and a message M as

      EM = 0x00 || 0x02 || PS || 0x00 || M.
    

    If the first octet of EM does not have hexadecimal value 0x00, if the second octet of EM does not have hexadecimal value 0x02, if there is no octet with hexadecimal value 0x00 to separate PS from M, or if the length of PS is less than 8 octets, the check variable must remember if any of those checks failed. Irrespective of the check variable value, the code should also return length of message M: L. If there is no octet with hexadecimal value 0x00 to separate PS from M, then L should equal 0.

    Note: All those checks MUST be performed irrespective if previous checks failed or not. A common technique for that is to have a check variable that is OR-ed with the results of subsequent checks.

  5. Decision which message to return: in case the check variable is set, the code should return the last AL octets of AM, in case the check variable is unset the code should return the last L octets of EM.

    Note: The decision which length to use MUST be performed in side-channel free manner. While the length of the returned message is not considered sensitive, the read memory location is. As such, when returning message M both EM and AM memory locations MUST be read.

12. Safe API

Performing all actions in a way that doesn't leak the status of the padding check includes the API provided to 3rd party code. In particular, if the RSA decryption implementation doesn't implement implicit rejection, then all three pieces of information: the padding check, the length of returned message, and the value of the message are sensitive information, useful in mounting an attack. As such, any API that returns an error in substantially different manner than a successful decryption (e.g. raising an exception, returning a null pointer, returning a different type of structure) is vulnerable to side-channel attacks.

13. Non-fixes

While there are infinite ways to implement those algorithms incorrectly few common ideas to work-around side-channel attacks are repeated. We list few of them as examples of approaches that don't work and thus MUST NOT be used.

13.1. Random delays

Commonly proposed workaround for timing attacks is to add a random delay to procesing of encrypted data. For such mitigation to be effective in practice (raise attacker's work factor to gain meaningful safety margin) it would need to be in the order of at least few seconds if not tens of seconds. Effective sizes and distributions of delays have not been subject of extensive study.

It should also be noted that such a delay would need to be applied in addition to the regular mitigation (generate random key, use it in case RSAES-PKCS-v1_5 padding checks). That is, it needs to be implemented in the calling code, not in the depadding code.

At the same time, performing a simple wait masks only the timing side channel. It doesn't mitigate other side-channels, like ones that depend on power usage or memory access pattern.

13.2. Returing random value from API

A simpler variant of the proposed implicit rejection algorithm, where the decryption API returns a random message in case the padding check fails or the decrypted message has unexpected length, as described in [RFC5246], isn't a universal mitigation.

In case of a Bleichenbacher like attack, the attacker is trying to differentiate two classes of ciphertexts: ones that decrypt to message of specific size and ones that have invalid padding or decrypt to a message of unexpected size. That translates to two kind of values being returned to calling code: either the same message always for every decryption, or a different message for every decryption.

If that message is later used in any operation that is not side-channel free (key derivation, symmetric padding removal, message parsing), then the attacker will be able to observe two kinds of behaviour: consistent one for static messages and erratic one for randomly generated messages.

Use of such a message as a key with block cipher modes that require padding, like AES-CBC with PKCS #7 padding, is particularly leaky as it has about 1 in 256 chance of successful decryption with random key.

The simple implicit rejection with random message may be implemented safely in TLS 1.2 because both static messages and randomly generated messages are mixed together with the random nonce generated by the server, thus the attacker is unable to differentiate if the randomness originates in the nonce or in the randomisation of the message.

14. Deprecated Algorithms

Current protocol deployments MUST NOT use encryption with RSAES-PKCS-v1_5 padding. Support for RSAES-PKCS-v1_5 SHOULD be disabled in default configuration of any implementation of RSA cryptosystem. All new protocols MUST NOT specify RSAES-PKCS-v1_5 as a valid encryption padding for RSA keys.

15. IANA Considerations

This memo includes no request to IANA.

16. Security Considerations

This whole document specifies security considerations for RSA implementations.

17. References

17.1. Normative References

[RFC8017]
Moriarty, K., Ed., Kaliski, B., Jonsson, J., and A. Rusch, "PKCS #1: RSA Cryptography Specifications Version 2.2", RFC 8017, DOI 10.17487/RFC8017, , <https://www.rfc-editor.org/info/rfc8017>.

17.2. Informative References

[Aciicmez05]
Acıiçmez, O., Schindler, W., and Ç. K. Koç, "Improving Brumley and Boneh timing attack on unprotected SSL implementations", Proceedings of the 12th ACM conference on Computer and communications security CCS '05, , <https://doi.org/10.1145/1102120.1102140>.
[Aciicmez07]
Acıiçmez, O. and W. Schindler, "A Major Vulnerability in RSA Implementations due to MicroArchitectural Analysis Threat", Cryptology ePrint Archive Paper 2007/336, , <https://eprint.iacr.org/2007/336>.
[Aciicmez08]
Acıiçmez, O. and W. Schindler, "A Vulnerability in RSA Implementations Due to Instruction Cache Analysis and Its Demonstration on OpenSSL", Lecture Notes in Computer Science vol 4964, , <https://doi.org/10.1007/978-3-540-79263-5_16>.
[Bauer12]
Bauer, S., "Attacking Exponent Blinding in RSA without CRT", Lecture Notes in Computer Science vol 7275, , <https://doi.org/10.1007/978-3-642-29912-4_7>.
[Bleichenbacher98]
Bleichenbacher, D., "Chosen Ciphertext Attacks Against Protocols Based on the RSA Encryption Standard PKCS#1", Lecture Notes in Computer Science vol 1462, <https://doi.org/10.1007/BFb0055716>.
[Bock18]
Böck, H., Somorovsky, J., and C. Young, "Return Of Bleichenbacher's Oracle Threat (ROBOT)", 27th USENIX Security Symposium USENIX Security 18, , <https://www.usenix.org/conference/usenixsecurity18/presentation/bock>.
[Brumley03]
Brumley, D. and D. Boneh, "Remote timing attacks are practical", Computer Networks Volume 48, Issue 5, , <https://doi.org/10.1016/j.comnet.2005.01.010>.
[Dhem98]
Dhem, J., Koeune, F., Leroux, P., Mestré, P., Quisquater, J., and J. Willems, "A Practical Implementation of the Timing Attack", Lecture Notes in Computer Science vol 1820, , <https://doi.org/10.1007/10721064_15>.
[Kario23]
Kario, H., "Everlasting ROBOT: the Marvin Attack", 28th European Symposium on Research in Computer Security , , <https://eprint.iacr.org/2023/1442>.
[Kocher96]
Kocher, P. C., "Timing Attacks on Implementations of Diffie-Hellman, RSA, DSS, and Other Systems.", Lecture Notes in Computer Science vol 1109, , <https://doi.org/10.1007/3-540-68697-5_9>.
[RFC2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>.
[RFC5246]
Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.2", RFC 5246, DOI 10.17487/RFC5246, , <https://www.rfc-editor.org/info/rfc5246>.
[RFC6979]
Pornin, T., "Deterministic Usage of the Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA)", RFC 6979, DOI 10.17487/RFC6979, , <https://www.rfc-editor.org/info/rfc6979>.
[Schindler00]
Schindler, W., "A Timing Attack against RSA with the Chinese Remainder Theorem", Lecture Notes in Computer Science vol 1965, , <https://doi.org/10.1007/3-540-44499-8_8>.
[Schindler01]
Schindler, W., Koeune, F., and J. Quisquater, "Improving Divide and Conquer Attacks against Cryptosystems by Better Error Detection / Correction Strategies.", Lecture Notes in Computer Science vol 2260, , <https://doi.org/10.1007/3-540-45325-3_22>.
[Schindler11]
Schindler, W. and K. Itoh, "Exponent Blinding Does Not Always Lift (Partial) Spa Resistance to Higher-Level Security", Lecture Notes in Computer Science vol 6715, , <https://doi.org/10.1007/978-3-642-21554-4_5>.
[Schindler14]
Schindler, W. and A. Wiemers, "Power attacks in the presence of exponent blinding.", Journal of Cryptographic Engineering 4, , <https://doi.org/10.1007/s13389-014-0081-y>.

Appendix A. Test Vectors

A.1. 2048 bit key

«for verification of test vectors see: https://github.com/tlsfuzzer/tlslite-ng/blob/master/unit_tests/test_tlslite_utils_rsakey.py#L1694»

A.1.1. Private key

Private key to use for decryption of following test data

-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDIzIOXFAmNpWyq
I2QPk9yJl8FjcpaPwbDG31ETwclOiyHkitIpfmVBkBG05tj15zsbeLJXQAMh0e9r
YC1OyM6NFByUkF60rTBmOaSSBlNLbn8mB0I+l9/9EzyI1yE5ne+8fpbM3L1/Oq4f
6JJxK/tJKYF9URZmRAofrLeiCPXqFlkQrdij8tSXICNgzLYyAk8NBxacGRjzFveU
sUOu9U7IdSKkwCl4+WiZgL/79knDB+gYGb/4hAljjUi9lL4VK1n/ZJ+gvWKdD/oY
E8Or9LVr08LqVGXf+hRYkpKp2KJK0mvn7gUQdBtjgtQ8g9W/pApGYT0GK+RFUX28
rwy04adpAgMBAAECggEAFFUBDg8tWHZjpmam/xzNu/Dt2BAGRtAqAjkikImSxK05
5VZZKXJu9lCMOnEVjvC2/3UdOdB1gLstLwYyEEQtBgP/UNu9ezX+LJuxmkehr4Wk
wkkB4CyotYt5GbIO3zKqz79RrbS8S2G5t+loyqTVcPcO8Y2AYyKIk+R9Q578p5Ml
m88s0Qij2GiM3weOeseZlp8jOdLB9SK5aWhGKakzuq7CaBYl6rhPTlb0RH6diPua
GZz3ECPg4lexREGzPITTvGfKgDHSYSYYEDp6CkCEQmL3XYiQzWFuUfkDVIj9bgmd
6P9tZaT/EYJUgHyfWNL7uouhUdyMaL40nJd6IE4EwQKBgQD49a1rqCiTG+pFm4o/
bcBB0jSCQJwlcelj8x90hgKiVjcbOIPtRZ7PlwUmRZ7dFuBVIvWkXZR1Gy7C2vJy
x/iBalLADRgIAXFjTaiZ15cyIvUbk3YwVIaWqffYwkpZSXwe/NRVz7l+6G0rbTSX
KzMv2jA/BJmbTra1zAuzPndh3QKBgQDOei47SakLljMKEtxoK9+9+66N1twDthR6
771XV0Pw9tpNhiNQYbca/ZytLTQCXlashrD3dD6zXhrLyiN4lUJEZbcG7SIXXlcY
yMcLZwPqj2tRD5Rb5I5aNrs8PJFzK1id/AXXLYCQMZRFK9ohNIZH7HKUPxGoRuYv
rr6OtTaw/QKBgHb+FfGK4jnN8d9rRFykvGu5aNeIwhkzpPXc0oADPWcSBizAim3y
BMH70L5GMHRD5t1KZFY3VCnU4DjKJW+vHJvekcaxe3b4GZX5HEjLvrx78ONJTAg1
nk6M1qWH17ltYiH9fg+1xVdfCC7ld2l5gHGyu7SjIjgVG0cxS7ZUeQMRAoGBAJmI
SLBVSZoQCcvH0pSzax/98gIObnNkBT6U3hoADck0BYf34nJ29ozfYI11O2M3ewO2
9AhNLAJ8SziWCmIzup7Zc4t28Q6nW+RWB4v3AfZ8xrPz/cGG5kM2x2s3LoCRDsgL
CtzCPQL7muEEhqKCSAdbTqflbd/POILkUVYUcaKRAoGAZDv3RkKffYNmegZTAhNH
77/AXmNR+CGp3rtg4OzN5QBa2ensMeVY9+ksKTKOdFadfO98dMq8KzVe1AGhoJFL
Tjy7BkhOWBlgURae0UyqLvpuoETgVNJhRMwWKcVQEFWKBOEz9Et8JE2sJb+RPFe4
kO5J9UglnNY0BP72hZ3Pl1o=
-----END PRIVATE KEY-----

A.1.2. Valid

Hex encoded ciphertext:

8bfe264e85d3bdeaa6b8851b8e3b956ee3d226fd3f69063a86880173a273d9f2
83b2eebdd1ed35f7e02d91c571981b6737d5320bd8396b0f3ad5b019daec1b0a
ab3cbbc026395f4fd14f13673f2dfc81f9b660ec26ac381e6db3299b4e460b43
fab9955df2b3cfaa20e900e19c856238fd371899c2bf2ce8c868b76754e5db3b
036533fd603746be13c10d4e3e6022ebc905d20c2a7f32b215a4cd53b3f44ca1
c327d2c2b651145821c08396c89071f665349c25e44d2733cd9305985ceef643
0c3cf57af5fa224089221218fa34737c79c446d28a94c41c96e4e92ac53fbcf3
84dea8419ea089f8784445a492c812eb0d409467f75afd7d4d1078886205a066

ASCII encoded decrypted message:

lorem ipsum dolor sit amet

A.1.3. Valid

Hex encoded ciphertext:

443ad9c5f00a1f4e9601717d274aacc93a824cb4d99b3c6a42e2b017e52e0184
43bd77d34a80703cd9b6acf523cd3b2cd1fea31940a68fba828836f1c3ed2fef
071e95e0922ff0f47d0e81dacc13ecdeda3db6476f41e5b3f9ccfcfdf9155800
7b68ffbbe5e93bb088f1e4f0bb39bc7d8600b38930ecd00a341d8cc76955837e
fff0f0797c4b46fb1b375bba49bcdc877f39aaadb045c56b836072383eec6627
ae280ad4f9a45d6e5b4cc7cf61d42b194ff0b9c9167c621e5380d8333e3b7f20
c8d564c9ec6c2805f77c0146adea2f688a943b67ce8889f4a6353e6396d551c3
6a6dbf19359a825d14b69ccc4fd747cf14a1ca8578d7f0a67dc14b37f5e17ca3

The result of decryption is a message of length 0.

A.1.4. Valid with ciphertext starting with a zero byte

Hex encoded ciphertext:

00a2e8f114ea8d05d12dc843e3cc3b2edc8229ff2a028bda29ba9d55e3cd0291
1902fef1f42a075bf05e8016e8567213d6f260fa49e360779dd81aeea3e04c2c
b567e0d72b98bf754014561b7511e083d20e0bfb9cd23f8a0d3c88900c49d2fc
d5843ff0765607b2026f28202a87aa94678aed22a0c20724541394cd8f44e373
eba1d2bae98f516c1e2ba3d86852d064f856b1daf24795e767a2b90396e50743
e3150664afab131fe40ea405dcf572dd1079af1d3f0392ccadcca0a12740dbb2
13b925ca2a06b1bc1383e83a658c82ba2e7427342379084d5f66b544579f0766
4cb26edd4f10fd913fdbc0de05ef887d4d1ec1ac95652397ea7fd4e4759fda8b

ASCII encoded message:

lorem ipsum

A.1.5. Invalid decrypting to empty

Hex encoded ciphertext:

20aaa8adbbc593a924ba1c5c7990b5c2242ae4b99d0fe636a19a4cf754edbcee
774e472fe028160ed42634f8864900cb514006da642cae6ae8c7d087caebcfa6
dad1551301e130344989a1d462d4164505f6393933450c67bc6d39d8f5160907
cabc251b737925a1cf21e5c6aa5781b7769f6a2a583d97cce008c0f8b6add5f0
b2bd80bee60237aa39bb20719fe75749f4bc4e42466ef5a861ae3a92395c7d85
8d430bfe38040f445ea93fa2958b503539800ffa5ce5f8cf51fa8171a91f36cb
4f4575e8de6b4d3f096ee140b938fd2f50ee13f0d050222e2a72b0a3069ff3a6
738e82c87090caa5aed4fcbe882c49646aa250b98f12f83c8d528113614a29e7

The result of decryption is a message of length 0.

A.1.6. Invalid decrypting to max size

Hex encoded ciphertext:

48cceab10f39a4db32f60074feea473cbcdb7accf92e150417f76b44756b190e
843e79ec12aa85083a21f5437e7bad0a60482e601198f9d86923239c8786ee72
8285afd0937f7dde12717f28389843d7375912b07b991f4fdb0190fced8ba665
314367e8c5f9d2981d0f5128feeb46cb50fc237e64438a86df198dd0209364ae
3a842d77532b66b7ef263b83b1541ed671b120dfd660462e2107a4ee7b964e73
4a7bd68d90dda61770658a3c242948532da32648687e0318286473f675b412d6
468f013f14d760a358dfcad3cda2afeec5e268a37d250c37f722f468a70dfd92
d7294c3c1ee1e7f8843b7d16f9f37ef35748c3ae93aa155cdcdfeb4e78567303

Hex encoded decrypted message:

22d850137b9eebe092b24f602dc5bb7918c16bd89ddbf20467b119d205f9c2e4
bd7d2592cf1e532106e0f33557565923c73a02d4f09c0c22bea89148183e6031
7f7028b3aa1f261f91c979393101d7e15f4067e63979b32751658ef769610fe9
7cf9cef3278b3117d384051c3b1d82c251c2305418c8f6840530e631aad63e70
e20e025bcd8efb54c92ec6d3b106a2f8e64eeff7d38495b0fc50c97138af4b1c
0a67a1c4e27b077b8439332edfa8608dfeae653cd6a628ac550395f7e74390e4
2c11682234870925eeaa1fa71b76cf1f2ee3bda69f6717033ff8b7c95c9799e7
a3bea5e7e4a1c359772fb6b1c6e6c516661dfe30c3

A.1.7. Invalid with second to last length

The length of the synthetic message comes from second to last value from the PRF output as the last value is too long for this key size.

Hex encoded ciphertext:

1439e08c3f84c1a7fec74ce07614b20e01f6fa4e8c2a6cffdc3520d8889e5d9a
950c6425798f85d4be38d300ea5695f13ecd4cb389d1ff5b82484b494d6280ab
7fa78e645933981cb934cce8bfcd114cc0e6811eefa47aae20af638a1cd163d2
d3366186d0a07df0c81f6c9f3171cf3561472e98a6006bf75ddb457bed036dcc
e199369de7d94ef2c68e8467ee0604eea2b3009479162a7891ba5c40cab17f49
e1c438cb6eaea4f76ce23cce0e483ff0e96fa790ea15be67671814342d0a23f4
a20262b6182e72f3a67cd289711503c85516a9ed225422f98b116f1ab080a80a
bd6f0216df88d8cfd67c139243be8dd78502a7aaf6bc99d7da71bcdf627e7354

Hex encoded decrypted message:

0f9b

A.1.8. Invalid first byte of padding

Otherwise valid plaintext, but with first byte equal to 0x01 instead of 0x00.

Hex encoded ciphertext:

9b2ec9c0c917c98f1ad3d0119aec6be51ae3106e9af1914d48600ab6a2c0c0c8
ae02a2dc3039906ff3aac904af32ec798fd65f3ad1afa2e69400e7c1de81f572
8f3b3291f38263bc7a90a0563e43ce7a0d4ee9c0d8a716621ca5d3d081188769
ce1b131af7d35b13dea99153579c86db31fe07d5a2c14d621b77854e48a8df41
b5798563af489a291e417b6a334c63222627376118c02c53b6e86310f728734f
fc86ef9d7c8bf56c0c841b24b82b59f51aee4526ba1c4268506d301e4ebc498c
6aebb6fd5258c876bf900bac8ca4d309dd522f6a6343599a8bc3760f422c10c7
2d0ad527ce4af1874124ace3d99bb74db8d69d2528db22c3a37644640f95c05f

Hex encoded message:

a1f8c9255c35cfba403ccc

A.1.9. Invalid second byte of padding

Otherwise valid plaintext, but with the second byte equal to 0x01 instead of 0x02.

Hex encoded ciphertext:

782c2b59a21a511243820acedd567c136f6d3090c115232a82a5efb0b178285f
55b5ec2d2bac96bf00d6592ea7cdc3341610c8fb07e527e5e2d20cfaf2c7f23e
375431f45e998929a02f25fd95354c33838090bca838502259e92d86d568bc2c
db132fab2a399593ca60a015dc2bb1afcd64fef8a3834e17e5358d822980dc44
6e845b3ab4702b1ee41fe5db716d92348d5091c15d35a110555a35deb4650a5a
1d2c98025d42d4544f8b32aa6a5e02dc02deaed9a7313b73b49b0d4772a3768b
0ea0db5846ace6569cae677bf67fb0acf3c255dc01ec8400c963b6e49b106772
8b4e563d7e1e1515664347b92ee64db7efb5452357a02fff7fcb7437abc2e579

Hex encoded decrypted message:

e6d700309ca0ed62452254

A.1.10. Invalid with zero length PS

Hex encoded ciphertext:

0096136621faf36d5290b16bd26295de27f895d1faa51c800dafce73d001d607
96cd4e2ac3fa2162131d859cd9da5a0c8a42281d9a63e5f353971b72e36b5722
e4ac444d77f892a5443deb3dca49fa732fe855727196e23c26eeac55eeced826
7a209ebc0f92f4656d64a6c13f7f7ce544ebeb0f668fe3a6c0f189e4bcd5ea12
b73cf63e0c8350ee130dd62f01e5c97a1e13f52fde96a9a1bc9936ce734fdd61
f27b18216f1d6de87f49cf4f2ea821fb8efd1f92cdad529baf7e31aff9bff407
4f2cad2b4243dd15a711adcf7de900851fbd6bcb53dac399d7c880531d06f25f
7002e1aaf1722765865d2c2b902c7736acd27bc6cbd3e38b560e2eecf7d4b576

Hex encoded decrypted message:

ba27b1842e7c21c0e7ef6a

A.1.11. Invalid with null byte at the eight byte of padding

This creates a plaintext with PS of 7 bytes

Hex encoded ciphertext:

a7a340675a82c30e22219a55bc07cdf36d47d01834c1834f917f18b517419ce9
de2a96460e745024436470ed85e94297b283537d52189c406a3f533cb405cc6a
9dba46b482ce98b6e3dd52d8fce2237425617e38c11fbc46b61897ef200d01e4
f25f5f6c4c5b38cd0de38ba11908b86595a8036a08a42a3d05b79600a97ac18b
a368a08d6cf6ccb624f6e8002afc75599fba4de3d4f3ba7d208391ebe8d21f82
82b18e2c10869eb2702e68f9176b42b0ddc9d763f0c86ba0ff92c957aaeab76d
9ab8da52ea297ec11d92d770146faa1b300e0f91ef969b53e7d2907ffc984e9a
9c9d11fb7d6cba91972059b46506b035efec6575c46d7114a6b935864858445f

Hex encoded decrypted message:

63cb0bf65fc8255dd29e17

A.1.12. Invalid with padding separator missing

Hex encoded ciphertext:

3d1b97e7aa34eaf1f4fc171ceb11dcfffd9a46a5b6961205b10b302818c1fcc9
f4ec78bf18ea0cee7e9fa5b16fb4c611463b368b3312ac11cf9c06b7cf72b54e
284848a508d3f02328c62c2999d0fb60929f81783c7a256891bc2ff4d91df2af
96a24fc5701a1823af939ce6dbdc510608e3d41eec172ad2d51b9fc61b4217c9
23cadcf5bac321355ef8be5e5f090cdc2bd0c697d9058247db3ad613fdce87d2
955a6d1c948a5160f93da21f731d74137f5d1f53a1923adb513d2e6e1589d44c
c079f4c6ddd471d38ac82d20d8b1d21f8d65f3b6907086809f4123e08d86fb38
729585de026a485d8f0e703fd4772f6668febf67df947b82195fa3867e3a3065

Hex encoded decrypted message:

6f09a0b62699337c497b0b

A.2. 2049 bit key

«provide test vectors here

A.3. 3072 bit key

«provide test vectors here»

A.4. 4096 bit key

«provide test vectors here»

Author's Address

Alicja Kario
Red Hat, Inc.
Purkynova 115
61200 Brno
Czech Republic