Skip to content

Simplify RSA and EC public key formats #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jan 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 48 additions & 54 deletions include/psa/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -467,8 +467,32 @@ psa_status_t psa_export_key(psa_key_handle_t handle,
* The output of this function can be passed to psa_import_key() to
* create an object that is equivalent to the public key.
*
* The format is the DER representation defined by RFC 5280 as
* `SubjectPublicKeyInfo`, with the `subjectPublicKey` format
* This specification supports a single format for each key type.
* Implementations may support other formats as long as the standard
* format is supported. Implementations that support other formats
* should ensure that the formats are clearly unambiguous so as to
* minimize the risk that an invalid input is accidentally interpreted
* according to a different format.
*
* For standard key types, the output format is as follows:
* - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the DER encoding of
* the representation defined by RFC 3279 §2.3.1 as `RSAPublicKey`.
* ```
* RSAPublicKey ::= SEQUENCE {
* modulus INTEGER, -- n
* publicExponent INTEGER } -- e
* ```
* - For elliptic curve public keys (key types for which
* #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed
* representation defined by SEC1 §2.3.3 as the content of an ECPoint:
* Let `m` be the bit size associated with the curve, i.e. the bit size of
* `q` for a curve over `F_q`. The representation consists of:
* - The byte 0x04;
* - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
* - `y_P` as a `ceiling(m/8)`-byte string, big-endian.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't specify what implementations should/can do about the y coordinate in the case of PSA_ECC_CURVE_CURVE25519 and PSA_ECC_CURVE_CURVE448. Do we want to? I would assume that implementations simply ignore it, but are they allowed to omit it? Do we want to prescribe what is allowed if there is a parsing error on y?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would we do with y if we had it? If we don't imagine we or any other implementations would have a use for it, we shouldn't require it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some implementations might want to require it to be a specific value for robustness.

But I just realised that Montgomery curves are out of scope for 1.0:
https://github.com/ARMmbed/psa-crypto/issues/101

So we could perhaps make it explicit that Montgomery and Edwards curves are not supported yet.

@gilles-peskine-arm what would be the best way to resolve the ambiguity here?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's in scope for 1.0, but not for 1.0beta1. I think the 1.0 specification should define the format for Montgomery curves (and the reference implementation should support ECDH) and for Edwards curves (even if the reference implementation doesn't support them yet).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case I suggest we define the format according to RFC8032 and RFC7748. (That is x coordinate in little endian byte order in the case of Montgomery and y coordinate in little endian byte order, with the most significant bit of the last byte set to the least significant bit of x.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not changing format in this PR. Agreeing on a format is tracked in ARMmbed/psa-crypto#101

*
* For other public key types, the format is the DER representation defined by
* RFC 5280 as `SubjectPublicKeyInfo`, with the `subjectPublicKey` format
* specified below.
* ```
* SubjectPublicKeyInfo ::= SEQUENCE {
Expand All @@ -478,21 +502,6 @@ psa_status_t psa_export_key(psa_key_handle_t handle,
* algorithm OBJECT IDENTIFIER,
* parameters ANY DEFINED BY algorithm OPTIONAL }
* ```
*
* - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY),
* the `subjectPublicKey` format is defined by RFC 3279 §2.3.1 as
* `RSAPublicKey`,
* with the OID `rsaEncryption`,
* and with the parameters `NULL`.
* ```
* pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
* rsadsi(113549) pkcs(1) 1 }
* rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 }
*
* RSAPublicKey ::= SEQUENCE {
* modulus INTEGER, -- n
* publicExponent INTEGER } -- e
* ```
* - For DSA public keys (#PSA_KEY_TYPE_DSA_PUBLIC_KEY),
* the `subjectPublicKey` format is defined by RFC 3279 §2.3.2 as
* `DSAPublicKey`,
Expand All @@ -508,30 +517,6 @@ psa_status_t psa_export_key(psa_key_handle_t handle,
* g INTEGER }
* DSAPublicKey ::= INTEGER -- public key, Y
* ```
* - For elliptic curve public keys (key types for which
* #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true),
* the `subjectPublicKey` format is defined by RFC 3279 §2.3.5 as
* `ECPoint`, which contains the uncompressed
* representation defined by SEC1 §2.3.3.
* The OID is `id-ecPublicKey`,
* and the parameters must be given as a `namedCurve` OID as specified in
* RFC 5480 §2.1.1.1 or other applicable standards.
* ```
* ansi-X9-62 OBJECT IDENTIFIER ::=
* { iso(1) member-body(2) us(840) 10045 }
* id-public-key-type OBJECT IDENTIFIER ::= { ansi-X9.62 2 }
* id-ecPublicKey OBJECT IDENTIFIER ::= { id-publicKeyType 1 }
*
* ECPoint ::= ...
* -- first 8 bits: 0x04;
* -- then x_P as a `ceiling(m/8)`-byte string, big endian;
* -- then y_P as a `ceiling(m/8)`-byte string, big endian;
* -- where `m` is the bit size associated with the curve,
* -- i.e. the bit size of `q` for a curve over `F_q`.
*
* EcpkParameters ::= CHOICE { -- other choices are not allowed
* namedCurve OBJECT IDENTIFIER }
* ```
*
* \param handle Handle to the key to export.
* \param[out] data Buffer where the key data is to be written.
Expand Down Expand Up @@ -2151,19 +2136,28 @@ psa_status_t psa_key_derivation(psa_crypto_generator_t *generator,
* The resulting generator always has the maximum capacity permitted by
* the algorithm.
*
* \param[in,out] generator The generator object to set up. It must have
* been initialized as per the documentation for
* #psa_crypto_generator_t and not yet in use.
* \param private_key Handle to the private key to use.
* \param[in] peer_key Public key of the peer. It must be
* in the same format that psa_import_key()
* accepts. The standard formats for public
* keys are documented in the documentation
* of psa_export_public_key().
* \param peer_key_length Size of \p peer_key in bytes.
* \param alg The key agreement algorithm to compute
* (\c PSA_ALG_XXX value such that
* #PSA_ALG_IS_KEY_AGREEMENT(\p alg) is true).
* \param[in,out] generator The generator object to set up. It must have been
* initialized as per the documentation for
* #psa_crypto_generator_t and not yet in use.
* \param private_key Handle to the private key to use.
* \param[in] peer_key Public key of the peer. The peer key must be in the
* same format that psa_import_key() accepts for the
* public key type corresponding to the type of
* \p private_key. That is, this function performs the
* equivalent of
* `psa_import_key(internal_public_key_handle,
* PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(private_key_type),
* peer_key, peer_key_length)` where
* `private_key_type` is the type of \p private_key.
* For example, for EC keys, this means that \p
* peer_key is interpreted as a point on the curve
* that the private key is associated with. The
* standard formats for public keys are documented in
* the documentation of psa_export_public_key().
* \param peer_key_length Size of \p peer_key in bytes.
* \param alg The key agreement algorithm to compute

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Very) minor: "algorithm to compute" sounds wrong, but that might just be me as a non-native. What about "The key agreement algorithm to use."?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That formulation is from me. It's copied from psa_key_derivation and will move to psa_key_derivation_setup in https://github.com/ARMmbed/mbedtls-psa/pull/244 . I'm not fond of “use” because it is very generic. “Algorithm to perform”? What do you think @Patater ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, algorithm to compute sounds like you are computing an algorithm. That's second order. Can't have computers programming themselves...

"Algorithm to follow" sounds OK to me.

* (\c PSA_ALG_XXX value such that
* #PSA_ALG_IS_KEY_AGREEMENT(\p alg) is true).
*
* \retval #PSA_SUCCESS
* Success.
Expand Down
39 changes: 10 additions & 29 deletions include/psa/crypto_sizes.h
Original file line number Diff line number Diff line change
Expand Up @@ -417,25 +417,16 @@
/* Maximum size of the export encoding of an RSA public key.
* Assumes that the public exponent is less than 2^32.
*
* SubjectPublicKeyInfo ::= SEQUENCE {
* algorithm AlgorithmIdentifier,
* subjectPublicKey BIT STRING } -- contains RSAPublicKey
* AlgorithmIdentifier ::= SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters NULL }
* RSAPublicKey ::= SEQUENCE {
* modulus INTEGER, -- n
* publicExponent INTEGER } -- e
*
* - 3 * 4 bytes of SEQUENCE overhead;
* - 1 + 1 + 9 bytes of algorithm (RSA OID);
* - 2 bytes of NULL;
* - 4 bytes of BIT STRING overhead;
* - 4 bytes of SEQUENCE overhead;
* - n : INTEGER;
* - 7 bytes for the public exponent.
*/
#define PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) \
(PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 36)
(PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 11)

/* Maximum size of the export encoding of an RSA key pair.
* Assumes thatthe public exponent is less than 2^32 and that the size
Expand Down Expand Up @@ -502,26 +493,16 @@

/* Maximum size of the export encoding of an ECC public key.
*
* SubjectPublicKeyInfo ::= SEQUENCE {
* algorithm AlgorithmIdentifier,
* subjectPublicKey BIT STRING } -- contains ECPoint
* AlgorithmIdentifier ::= SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters OBJECT IDENTIFIER } -- namedCurve
* ECPoint ::= ...
* -- first 8 bits: 0x04;
* -- then x_P as a `ceiling(m/8)`-byte string, big endian;
* -- then y_P as a `ceiling(m/8)`-byte string, big endian;
* -- where `m` is the bit size associated with the curve.
*
* - 2 * 4 bytes of SEQUENCE overhead;
* - 1 + 1 + 7 bytes of algorithm (id-ecPublicKey OID);
* - 1 + 1 + 12 bytes of namedCurve OID;
* - 4 bytes of BIT STRING overhead;
* - 1 byte + 2 * point size in ECPoint.
* The representation of an ECC public key is:
* - The byte 0x04;
* - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
* - `y_P` as a `ceiling(m/8)`-byte string, big-endian;
* - where m is the bit size associated with the curve.
*
* - 1 byte + 2 * point size.
*/
#define PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) \
(2 * PSA_BITS_TO_BYTES(key_bits) + 36)
(2 * PSA_BITS_TO_BYTES(key_bits) + 1)

/* Maximum size of the export encoding of an ECC key pair.
*
Expand Down
Loading