OASIS PKCS 11 TC

 View Only
  • 1.  Private values for ML-DSA and similar

    Posted 10-31-2024 15:11
    So prompted by a discussion on the PQC Forum I was looking at our
    definition of CKA_VALUE for ML-DSA and it says:

    Big Integer: Private value as defined in [FIPS 204]


    However FIPS 204 does not define "Private Value" in the glossary.
    and mentions private values only in the part that explains ML-DSA
    construction to define two private values (S1, S2) that constitute the
    private key.

    In order to ensure maximum interoperability the implementation should
    definitely be able to get as input (on import) a Seed value that is
    used to then reconstitute the full private key, and be able to always
    export a seed value.

    There is quite a lot of people that think private keys should always be
    stored as seed values and reconstructed when read into memory.

    In any case the current text is not clear enough and needs improvement
    to avoid interoperability issues.


    We should discuss this at the next meeting if possible.

    Simo.

    --
    Simo Sorce
    Distinguished Engineer
    RHEL Crypto Team
    Red Hat, Inc


  • 2.  RE: Private values for ML-DSA and similar

    Posted 10-31-2024 17:10

    THALES GROUP LIMITED DISTRIBUTION to email recipients

     

    Hi

    Agreed that we need to discuss this.  The IETF world may be moving in a direction that is different than the one we took.

     

    The Big Integer text in the current working draft is outdated.

     

    the latest version of "kem_algs" has an updated description where CKA_VALUE is defined as a byte array, as defined in FIPS 203.  The intent of the new text was to map CKA_VALUE to the serialized key format that is defined in FIPS 203. So that we could use the specifications format and remove any interoperability issues.  This was decided a bit before the whole seed discussions started (or maybe it was decided after the initial seed discussions died off).  If we keep our definition the way it is, we should add a few more words to make it more clear what it means.

     

    But I also agree that if the IETF world decides to adopt the seed(s) as a format (this applies for ML-KEM and ML-DSA), we would need to try and support what they support. 

     

    Thanks

    Darren

     






  • 3.  RE: Private values for ML-DSA and similar

    Posted 10-31-2024 17:22
    [Simo Sorce]
    > There is quite a lot of people that think private keys should always be
    > stored as seed values and reconstructed when read into memory.

    I'd rephrase that as there is a very small group of people that are pushing the concept that private keys should never be encoded and should always be derived from an input seed.

    The concept of requiring a seed value to always be present is simply not generally supportable and makes little sense when you work through all the possible contexts of usage.

    Those who are pushing that concept are doing so in the context of keys being ephemeral and mostly in the context of ML-KEM and to not have to define a persistent key format and that the "generation" cost is trivial. This isn't generally applicable.

    And to be exceedingly clear, there is absolutely no requirement or suggesting within any of the NIST specifications that implementations should operate off a SEED value and see that as the private key - and in fact the concept of an externally provided seed does not universally exist in the NIST docs. Basically you end up seeing a "seed" as the PRNG output values in some algorithms and they are not defined as an alternate input key generation mechanism.

    FIPS-203 (allows for the concept that implementations might choose to store the seed in place of the private key but does not require that this be supported - and it is clear it is a SEED not a private key value format)

    There is also an explicit note: As prescribed in Section 3.3, the interfaces specified in this section should not be made available to applications other than for testing purposes, and the random seeds (as specified in ML-KEM.KeyGen and ML-KEM.Encaps in Section 7) shall be generated by the cryptographic module.

    FIPS-204 (no seed input defined, you are changing the internal algorithm RNG output)

    FIPS-205 (no seed input defined, you are changing the internal algorithm RNG output)

    Tim.







  • 4.  RE: Private values for ML-DSA and similar

    Posted 11-01-2024 10:30
    Some comments on Tim's reply follow, but the reason we are raising
    this is that there is a good chance some protocols will want to
    define at least ML-KEM and ML-DSA import/export methods to use seeds
    for storage/transmission.

    Specifically PKCS#12 files have been explicitly metioned.

    And the fact is you can always seed -> private-key and you can never
    private-key -> seed. So storing the seeds to be able to properly
    export keys *should* definitely be a strong consideration here.


    On Thu, 2024-10-31 at 21:21 +0000, Tim Hudson via OASIS wrote:
    > I'd rephrase that as there is a very small group of people
    > that are pushing the concept that private keys should never
    > be encoded and should always be derived from an input seed.

    Not sure it matters if they are relatively many or a few, there are
    influential people in IETF that lean that way. And I think they have
    reasonable arguments too.

    > The concept of requiring a seed value to always be present
    > is simply not generally supportable and makes little sense
    > when you work through all the possible contexts of usage.

    I am not sure I understand this point, given the seed you can
    always regenerate the key, so it should be generally supportable.
    Of course some implementations may want to permanently store the
    expanded keys as well for performance reasons, but if you can
    store the expanded key, storing along side it the generation seed
    to be used as an export format is not a big deal.

    > Those who are pushing that concept are doing so in the context
    > of keys being ephemeral and mostly in the context of ML-KEM
    > and to not have to define a persistent key format and that the
    > "generation" cost is trivial. This isn't generally applicable.

    What part is not generally applicable? That generation cost is high?

    In any case that is not the only argument. Many make the argument that
    storing seeds is much simpler for small devices as it reduces the size
    of permanent storage and regenerating the key doubles as a test that
    the key is well formed which is an operation you need to do for FIPS
    certified modules.
    Storing seeds also reduces ambiguity and allows implementations to
    organize the expanded format as they see fit.

    > And to be exceedingly clear, there is absolutely no requirement
    > or suggesting within any of the NIST specifications that
    > implementations should operate off a SEED value and see that
    > as the private key

    I have seen no one make this argument, so I do not see the relevance
    TBH.

    > - and in fact the concept of an externally provided seed does not
    > universally exist in the NIST docs. Basically you end up seeing a
    > "seed" as the PRNG output values in some algorithms and they are
    > not defined as an alternate input key generation mechanism.

    I this case it would be key re-constitution, and not generation.
    The key generation happened the first time when the seed was
    actually generated.

    > FIPS-203 (allows for the concept that implementations might
    > choose to store the seed in place of the private key but does
    > not require that this be supported - and it is clear it is a
    > SEED not a private key value format)

    It is clear the SEED is a seed, it is also clear it is as sensitive
    and equivalent to the private key. if you have access to the seed
    you know the private key.

    > There is also an explicit note: As prescribed in Section 3.3,
    > the interfaces specified in this section should not be made
    > available to applications other than for testing purposes,

    I do not see the relevance of this, private key re-computation
    from a seed would be an internal operation anyway.

    > and the random seeds (as specified in ML-KEM.KeyGen and
    > ML-KEM.Encaps in Section 7) shall be generated by the
    > cryptographic module.

    And so they shall, I do not get what point you are trying to
    make here? Care to elaborate ?

    > FIPS-204 (no seed input defined, you are changing the
    > internal algorithm RNG output)

    Look at Algorithm 6. The first line is:

    Input: Seed 𝜉 ∈ 𝔹32


    So input seed is clearly defined.

    > FIPS-205 (no seed input defined, you are changing the
    > internal algorithm RNG output)

    In 205 there isn't a single seed indeed, but there is a seed and a prf
    for public keys and a seed and root for the public key, but then again
    I have seen nobody claiming we need to use seed storage for SLH-DSA,
    only for ML-DSA and ML-KEM.


    HTH,
    Simo.


    Simo Sorce
    Distinguished Engineer
    RHEL Crypto Team
    Red Hat, Inc




  • 5.  RE: Private values for ML-DSA and similar

    Posted 11-01-2024 12:24
    Also this is just in from PQC-Froum:

    For both FIPS 203 and FIPS 204, a KeyGen seed is considered an
    acceptable alternative format for the private (i.e., decapsulation
    or signing) key. In particular, generating the seed in one
    cryptographic module and then importing it into another
    cryptographic module is allowed.


    So I would say there is no "normative" issue here.


    On Fri, 2024-11-01 at 10:29 -0400, Simo Sorce wrote:
    > Some comments on Tim's reply follow, but the reason we are raising
    > this is that there is a good chance some protocols will want to
    > define at least ML-KEM and ML-DSA import/export methods to use seeds
    > for storage/transmission.
    >
    > Specifically PKCS#12 files have been explicitly metioned.
    >
    > And the fact is you can always seed -> private-key and you can never
    > private-key -> seed. So storing the seeds to be able to properly
    > export keys *should* definitely be a strong consideration here.
    >
    >
    > On Thu, 2024-10-31 at 21:21 +0000, Tim Hudson via OASIS wrote:
    > > I'd rephrase that as there is a very small group of people
    > > that are pushing the concept that private keys should never
    > > be encoded and should always be derived from an input seed.
    >
    > Not sure it matters if they are relatively many or a few, there are
    > influential people in IETF that lean that way. And I think they have
    > reasonable arguments too.
    >
    > > The concept of requiring a seed value to always be present
    > > is simply not generally supportable and makes little sense
    > > when you work through all the possible contexts of usage.
    >
    > I am not sure I understand this point, given the seed you can
    > always regenerate the key, so it should be generally supportable.
    > Of course some implementations may want to permanently store the
    > expanded keys as well for performance reasons, but if you can
    > store the expanded key, storing along side it the generation seed
    > to be used as an export format is not a big deal.
    >
    > > Those who are pushing that concept are doing so in the context
    > > of keys being ephemeral and mostly in the context of ML-KEM
    > > and to not have to define a persistent key format and that the
    > > "generation" cost is trivial. This isn't generally applicable.
    >
    > What part is not generally applicable? That generation cost is high?
    >
    > In any case that is not the only argument. Many make the argument that
    > storing seeds is much simpler for small devices as it reduces the size
    > of permanent storage and regenerating the key doubles as a test that
    > the key is well formed which is an operation you need to do for FIPS
    > certified modules.
    > Storing seeds also reduces ambiguity and allows implementations to
    > organize the expanded format as they see fit.
    >
    > > And to be exceedingly clear, there is absolutely no requirement
    > > or suggesting within any of the NIST specifications that
    > > implementations should operate off a SEED value and see that
    > > as the private key
    >
    > I have seen no one make this argument, so I do not see the relevance
    > TBH.
    >
    > > - and in fact the concept of an externally provided seed does not
    > > universally exist in the NIST docs. Basically you end up seeing a
    > > "seed" as the PRNG output values in some algorithms and they are
    > > not defined as an alternate input key generation mechanism.
    >
    > I this case it would be key re-constitution, and not generation.
    > The key generation happened the first time when the seed was
    > actually generated.
    >
    > > FIPS-203 (allows for the concept that implementations might
    > > choose to store the seed in place of the private key but does
    > > not require that this be supported - and it is clear it is a
    > > SEED not a private key value format)
    >
    > It is clear the SEED is a seed, it is also clear it is as sensitive
    > and equivalent to the private key. if you have access to the seed
    > you know the private key.
    >
    > > There is also an explicit note: As prescribed in Section 3.3,
    > > the interfaces specified in this section should not be made
    > > available to applications other than for testing purposes,
    >
    > I do not see the relevance of this, private key re-computation
    > from a seed would be an internal operation anyway.
    >
    > > and the random seeds (as specified in ML-KEM.KeyGen and
    > > ML-KEM.Encaps in Section 7) shall be generated by the
    > > cryptographic module.
    >
    > And so they shall, I do not get what point you are trying to
    > make here? Care to elaborate ?
    >
    > > FIPS-204 (no seed input defined, you are changing the
    > > internal algorithm RNG output)
    >
    > Look at Algorithm 6. The first line is:
    >
    > Input: Seed 𝜉 ∈ 𝔹32
    >
    >
    > So input seed is clearly defined.
    >
    > > FIPS-205 (no seed input defined, you are changing the
    > > internal algorithm RNG output)
    >
    > In 205 there isn't a single seed indeed, but there is a seed and a prf
    > for public keys and a seed and root for the public key, but then again
    > I have seen nobody claiming we need to use seed storage for SLH-DSA,
    > only for ML-DSA and ML-KEM.
    >
    >
    > HTH,
    > Simo.
    >
    >
    > Simo Sorce
    > Distinguished Engineer
    > RHEL Crypto Team
    > Red Hat, Inc

    --
    Simo Sorce
    Distinguished Engineer
    RHEL Crypto Team
    Red Hat, Inc




  • 6.  RE: Private values for ML-DSA and similar

    Posted 11-07-2024 15:34

    THALES GROUP LIMITED DISTRIBUTION to email recipients

     

    Hi,

    I started to write up response to the IETF group about what we discussed today to get some early feedback from them but hit a bit of a problem with the C_Wrap/C_Unwrap use case.  I'll put a big caveat on what I send over there that it is pre-draft and is subject to change.

     

    Here is what I have so far.

     

    Currently we define a CKA_VALUE attribute for ML-DSA and ML-KEM private keys that contains the encoded private key value as defined in FIPS 203 and FIPS 204.  Based on today's discussion, we will be adding an additional attribute CKA_SEED that will store the seed(s) values.  This attribute will be 32-bytes for ML-DSA and 64-bytes for ML-KEM.   I don't think there is any need to have the two ML-KEM seeds stored as two separate attributes. IETF is treating them the same.

     

    When an ML-KEM or ML-DSA private key is generated using C_GenerateKeyPair, both CKA_VALUE and CKA_SEED attributes will be populated.

     

    The CKA_SEED attribute is a sensitive attribute just like CKA_VALUE.  The ability to read CKA_SEED via the C_GetAttributeValue API depends on the key's attributes and any vendor specific security policies of the token.  So if CKA_VALUE can be read, CKA_SEED can be read.

     

    When creating a ML-KEM or ML-DSA private key object using C_CreateObject, an application will be able to specify only CKA_VALUE, only CKA_SEED, or both CKA_VALUE and CKA_SEED. The reasoning for the flexibility in this use case is to support use-cases where an application ONLY has the encoded private key and does not have a seed, or only has a seed.  This allows them to still be able to create the object in the token and use it.  If an application creates a private key with out a CKA_SEED, then the CKA_SEED attribute will not be populated on the private key.  This should be fine as any application that is creating private keys without a seed shouldn't expect/need to read back the seed.  And if only the SEED is provided, a token could recompute the expanded key immediately or on depend, depending on their internal design.

     

    But I'm still struggling with the C_Wrap/C_Unwrap use-case though. Currently when wrapping/unwrapping private keys, we only support PKCS#8 formatted private keys. IETF hasn't finalized on their plans yet.  I would say they are in the early stages at best.  The initial proposal is something like this:

    ML-*PrivateKeySeed ::= OCTET STRING (SIZE X) -- X is 32 for ML-DSA and 64 for ML-KEM

    ML-*PrivateKeyFull ::= OCTET STRING

    ML-*PrivateKey ::= CHOICE {
              ML-*PrivateKeySeed,
          [0] ML-*PrivateKeyFull }

    (where ML-* means ML-DSA or ML-KEM)

    And they define the default/preferred format as being ML-*PrivateKeySeed.  So we are saying that for C_UnwrapKey, we can support both formats similar to how we support them for C_CreateObject.  But for C_WrapKey we don't have a deterministic way to define what is returned other than to say that we always use ML-*PrivateKeySeed if we can, otherwise we use ML-*PrivateKeyFull.  T

     

    Is this how we want to proceed?

     

     






  • 7.  RE: Private values for ML-DSA and similar

    Posted 11-07-2024 17:55

    Nit:

    " And if only the SEED is provided, a token could recompute the expanded key immediately or on depend, depending on their internal design."

    on depend -> on demand

    I think we should propose a different ML-*PrivateKey like the following:

    ML-*PrivateKey ::= SEQUENCE {
      seed          [0] OCTET_STRING (SIZE X) OPTIONAL,
      privateKey    [1] OCTET_STRING OPTIONAL,
    }

    Where seed should always be preferred.

    But both can be provided for convenience.

    This way we can always provide all we have (or just the seed if we default to that).

    As for the behavior of C_Wrap() I think we can do what you propose as the default, and if ever turns out we need a specific behavior we'll simply have to add a CKM_ML_*_WRAP_BEHAVIOR mechanism to a future spec that will do what is needed ...



    ------------------------------
    Simo Sorce
    Red Hat
    ------------------------------



  • 8.  RE: Private values for ML-DSA and similar

    Posted 11-07-2024 18:42
    On 11/7/24 12:35 PM, Darren Johnson via OASIS wrote:
    0100019308573b34-f61cb5f6-e27f-4b7c-8317-67129ad4b733-000000@email.amazonses.com">
    THALES GROUP LIMITED DISTRIBUTION to email recipients Hi, I started to write up response to the IETF group about what we discussed today... -posted to the "OASIS PKCS 11 TC" community

    Hi,

    I started to write up response to the IETF group about what we discussed today to get some early feedback from them but hit a bit of a problem with the C_Wrap/C_Unwrap use case.  I'll put a big caveat on what I send over there that it is pre-draft and is subject to change.

    C_Wrap and C_Unwrap expects pkcs8 data, so however the IETF defines it. This is the primary way I would expect keys to be transferred between tokens. If the data doesn't have all the components (the IETF makes Seed or the generated key optional), it may not be importable into all devices.

     

    Here is what I have so far.

     

    Currently we define a CKA_VALUE attribute for ML-DSA and ML-KEM private keys that contains the encoded private key value as defined in FIPS 203 and FIPS 204.  Based on today's discussion, we will be adding an additional attribute CKA_SEED that will store the seed(s) values.  This attribute will be 32-bytes for ML-DSA and 64-bytes for ML-KEM.   I don't think there is any need to have the two ML-KEM seeds stored as two separate attributes. IETF is treating them the same.

     

    When an ML-KEM or ML-DSA private key is generated using C_GenerateKeyPair, both CKA_VALUE and CKA_SEED attributes will be populated.

    I thought we decided this was token specific. Not all tokens could handle both values? But I'm ok with making both mandatory.

     

    The CKA_SEED attribute is a sensitive attribute just like CKA_VALUE.  The ability to read CKA_SEED via the C_GetAttributeValue API depends on the key's attributes and any vendor specific security policies of the token.  So if CKA_VALUE can be read, CKA_SEED can be read.

     

    When creating a ML-KEM or ML-DSA private key object using C_CreateObject, an application will be able to specify only CKA_VALUE, only CKA_SEED, or both CKA_VALUE and CKA_SEED. The reasoning for the flexibility in this use case is to support use-cases where an application ONLY has the encoded private key and does not have a seed, or only has a seed.  This allows them to still be able to create the object in the token and use it.  If an application creates a private key with out a CKA_SEED, then the CKA_SEED attribute will not be populated on the private key.  This should be fine as any application that is creating private keys without a seed shouldn't expect/need to read back the seed.  And if only the SEED is provided, a token could recompute the expanded key immediately or on depend, depending on their internal design.

    So we definitely decided that the token could reject one or the other of these cases. A slow token may not regenerate CKA_VALUE and fail if CKA_VALUE is not specified. A token with limitted space may require CKA_SEED. If the application supplies both it is guarrenteed to work.

     

    But I'm still struggling with the C_Wrap/C_Unwrap use-case though. Currently when wrapping/unwrapping private keys, we only support PKCS#8 formatted private keys. IETF hasn't finalized on their plans yet.  I would say they are in the early stages at best.  The initial proposal is something like this:

    ML-*PrivateKeySeed ::= OCTET STRING (SIZE X) -- X is 32 for ML-DSA and 64 for ML-KEM

    ML-*PrivateKeyFull ::= OCTET STRING

    ML-*PrivateKey ::= CHOICE {
              ML-*PrivateKeySeed,
          [0] ML-*PrivateKeyFull }

    (where ML-* means ML-DSA or ML-KEM)

    And they define the default/preferred format as being ML-*PrivateKeySeed.  So we are saying that for C_UnwrapKey, we can support both formats similar to how we support them for C_CreateObject.  But for C_WrapKey we don't have a deterministic way to define what is returned other than to say that we always use ML-*PrivateKeySeed if we can, otherwise we use ML-*PrivateKeyFull.  T

     

    Is this how we want to proceed?

    They don't have an option to return both? That at would be the prefered, and what is returned is token specific. If the token doesn't have the seed, it can't return it.

    bob