Skip to content
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

Fix parsing of PKCS#8 encoded Elliptic Curve keys. #1379

Merged
merged 1 commit into from Mar 29, 2018

Conversation

jethrogb
Copy link

@jethrogb jethrogb commented Feb 16, 2018

Description

The relevant ASN.1 definitions for a PKCS#8 encoded Elliptic Curve key are:

PrivateKeyInfo ::= SEQUENCE {
  version                   Version,
  privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,
  privateKey                PrivateKey,
  attributes           [0]  IMPLICIT Attributes OPTIONAL
}

AlgorithmIdentifier  ::=  SEQUENCE  {
  algorithm   OBJECT IDENTIFIER,
  parameters  ANY DEFINED BY algorithm OPTIONAL
}

ECParameters ::= CHOICE {
  namedCurve         OBJECT IDENTIFIER
  -- implicitCurve   NULL
  -- specifiedCurve  SpecifiedECDomain
}

ECPrivateKey ::= SEQUENCE {
  version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
  privateKey     OCTET STRING,
  parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
  publicKey  [1] BIT STRING OPTIONAL
}

Because of the two optional fields, there are 4 possible variants that need to
be parsed: no optional fields, only parameters, only public key, and both
optional fields. Previously mbedTLS was unable to parse keys with "only
parameters". Also, only "only public key" was tested. There was a test for "no
optional fields", but it was labelled incorrectly as SEC.1 and not run because
of a great renaming mixup.

This contribution is submitted under CLA with Fortanix, Inc.

Status

READY

Requires Backporting

YES

Migrations

NO

Todos

Steps to test or reproduce

Run the test suite from this PR without the changes in pkparse.c

@mbed-ci
Copy link

mbed-ci commented Feb 16, 2018

--none--

Copy link
Contributor

@RonEld RonEld left a comment

Choose a reason for hiding this comment

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

No major comments.
However, as in #1135 PR, I would like to ask you to add the key generation commands in tests/data_files/Makefile for proper documentations

@@ -406,10 +406,6 @@ Parse EC Key #1 (SEC1 DER)
depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED
pk_parse_keyfile_ec:"data_files/ec_prv.sec1.der":"NULL":0

Parse EC Key #1a (SEC1 DER, no optional part)
Copy link
Contributor

Choose a reason for hiding this comment

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

why was this removed? Wouldn't it be better to fix the renaming error?

Copy link
Author

Choose a reason for hiding this comment

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

The file is in the same format as test 5a (except PEM vs. DER). I only found out about this after I had already created my test case files. Having both is superfluous, choose one to keep.

# ec_prv.noopt.der
    0:d=0  hl=2 l=  65 cons: SEQUENCE          
    2:d=1  hl=2 l=   1 prim:  INTEGER           :00
    5:d=1  hl=2 l=  19 cons:  SEQUENCE          
    7:d=2  hl=2 l=   7 prim:   OBJECT            :id-ecPublicKey
   16:d=2  hl=2 l=   8 prim:   OBJECT            :prime256v1
   26:d=1  hl=2 l=  39 prim:  OCTET STRING      [HEX DUMP]:30250201010420EBCB4887A86D06F43418A298FCAE9CFD81EA7FF7FB27D45FDCBD902AB10D4F37
# ec_prv.pk8nopub.pem
    0:d=0  hl=2 l=  65 cons: SEQUENCE          
    2:d=1  hl=2 l=   1 prim:  INTEGER           :00
    5:d=1  hl=2 l=  19 cons:  SEQUENCE          
    7:d=2  hl=2 l=   7 prim:   OBJECT            :id-ecPublicKey
   16:d=2  hl=2 l=   8 prim:   OBJECT            :prime256v1
   26:d=1  hl=2 l=  39 prim:  OCTET STRING      [HEX DUMP]:30250201010420C7EFC5D45FE7319933D0D6156461BBB756F05CF5CF3613218A686BE4028D4F93

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for clarification. I would like to have both DER and PEM formats tested though

Copy link
Author

Choose a reason for hiding this comment

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

The PEM to DER conversion is already being tested, but I added the DER versions anyway (one is renamed from the original mislabeled test), as requested.

@jethrogb
Copy link
Author

I created the keys by hand. If you know of a tool that can manipulate ASN.1 based on command line input I'll happily figure out the commands needed to generate these files.

@RonEld
Copy link
Contributor

RonEld commented Feb 22, 2018

@jethrogb I don't understand your comment:

If you know of a tool that can manipulate ASN.1 based on command line input I'll happily figure out the commands needed to generate these files.

Maybe I am missing something.
How did you create the keys by hand? tests/data_files/Makefile is only used to document how the keys were created, not as a tool to create the tool every build.

@jethrogb
Copy link
Author

How did you create the keys by hand?

I took an existing key and manipulated the DER in a hex editor.

@mpg
Copy link
Contributor

mpg commented Mar 22, 2018

Hi @jethrogb,

Thanks for your contribution and for working with us to improve your PR in response to Ron's comments. I just had a look at it and I think it's a good improvement to our current codebase and tests. However, I have a few more requests for you:

  1. Can you please add a ChangeLog entry under the "BugFix" section explaining the bug from a user's perspective and crediting yourself for finding and fixing it? (With a reference to this PR.) Please create a new heading:
= mbed TLS x.x.x branch released xxx-xx-xx

and put your entry under that version.

  1. As Ron said, we're trying to track how files are created better than we did in the past. I understand those files had to be created manually (I don't know of a way to programmatically manipulate ASN.1 either, though I would be very interested), but could you please add comments to tests/data_files/Makefile with the file names in the comment (to make it easy to find) explaining (1) what you used as the base file for your modifications and (2) what modifications you made (eg "remove Parameters", "remove PublicKey"). You can imagine the following scenario: someone wants to make a version of the library that uses only P-384 and they want to create test files similar to yours but using that curve. Your comments should give them enough information to do that efficiently, assuming they're already familiar with Mbed TLS and editing ASN.1 with a hex editor in general, just not with how these particular files were created. I realise you already picked meaningful file names and explicit test description (thanks for that), but I think a comment in test/data_files/Makefile would still be a worthwile addition so that we don't have to hunt around for the information.

Once those steps are done, can you please ping @RonEld and I to give your PR another round of reviews? Based on my preliminary review today, I expect mine should be an approval at this stage.

  1. Ideally if you could prepare a backport for the 2.1 branch that would be great (this branch looks can it can be merge both in development and 2.7, so we don't need a 2.7 backport), otherwise someone from the team can do it - just let us know.

Once the main PR and backport have been reviewed and approved by two members of the team, your PR will be ready to merge.

Thanks again for your interest in Mbed TLS, and I'm looking forward to working with you on finalizing this PR!

@jethrogb
Copy link
Author

@mpg @RonEld Items 1 and 2 done. I'm not sure how to do the backport given I can only target one branch in my PR.

@mpg
Copy link
Contributor

mpg commented Mar 22, 2018

Thanks for the rework!

For the backports, the way we do this is create a new branch based on the target branch (here mbedtls-2.1), then usually cherry-pick commit(s) from the main branch (or any other method that suits you), then open a new PR with this branch, selecting the appropriate target branch (github should show just the commits you added).

As github doesn't offer any special support for marking a PR as a backport of another, what we usually do is give the backport PR the same title as the original, with a "Backport 2.1: " prefix, and include links in the descriptions from one branch to the other. See for example #1486 #1487 #1488

Copy link
Contributor

@mpg mpg left a comment

Choose a reason for hiding this comment

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

The code (including tests and documentation in the Makefile) looks great to me, but there are minor things to fix in the ChangeLog entry.

I notice you didn't credit yourself in the ChangeLog. If that's a conscious decision, of course no problem. Otherwise, don't be shy about adding "Found and fixed by #1379" :)

ChangeLog Outdated
Bugfix
* Fix parsing of PKCS#8 encoded Elliptic Curve keys. Previously mbedTLS was
unable to parse keys with only the optional parameters field of the
ECPrivateKey strucutre.
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo: structure.

ChangeLog Outdated
= mbed TLS x.x.x branch released xxx-xx-xx

Bugfix
* Fix parsing of PKCS#8 encoded Elliptic Curve keys. Previously mbedTLS was
Copy link
Contributor

Choose a reason for hiding this comment

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

Please use the the official spelling "Mbed TLS", thanks!

The relevant ASN.1 definitions for a PKCS#8 encoded Elliptic Curve key are:

PrivateKeyInfo ::= SEQUENCE {
  version                   Version,
  privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,
  privateKey                PrivateKey,
  attributes           [0]  IMPLICIT Attributes OPTIONAL
}

AlgorithmIdentifier  ::=  SEQUENCE  {
  algorithm   OBJECT IDENTIFIER,
  parameters  ANY DEFINED BY algorithm OPTIONAL
}

ECParameters ::= CHOICE {
  namedCurve         OBJECT IDENTIFIER
  -- implicitCurve   NULL
  -- specifiedCurve  SpecifiedECDomain
}

ECPrivateKey ::= SEQUENCE {
  version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
  privateKey     OCTET STRING,
  parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
  publicKey  [1] BIT STRING OPTIONAL
}

Because of the two optional fields, there are 4 possible variants that need to
be parsed: no optional fields, only parameters, only public key, and both
optional fields. Previously mbedTLS was unable to parse keys with "only
parameters". Also, only "only public key" was tested. There was a test for "no
optional fields", but it was labelled incorrectly as SEC.1 and not run because
of a great renaming mixup.
@jethrogb
Copy link
Author

Updated ChangeLog as requested and filed backport PR #1494

Copy link
Contributor

@mpg mpg left a comment

Choose a reason for hiding this comment

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

Thanks for making those changes. I'm happy with the result!

@mpg
Copy link
Contributor

mpg commented Mar 23, 2018

@jethrogb Thanks for the changes and the backport! I took the liberty of editing the description in order to include a link to the backport PR (and vice-versa) and checking the todo boxes as you did everything :)

@RonEld Can you please give this (and the backport PR #1494) another round of review?

Copy link
Contributor

@RonEld RonEld left a comment

Choose a reason for hiding this comment

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

LGTM

@gilles-peskine-arm gilles-peskine-arm added the approved Design and code approved - may be waiting for CI or backports label Mar 26, 2018
@Patater
Copy link
Contributor

Patater commented Mar 26, 2018

This needs a backport for 2.7. This PR as is doesn't apply cleanly to mbedtls-2.7.

@Patater Patater added needs-backports Backports are missing or are pending review and approval. and removed approved Design and code approved - may be waiting for CI or backports labels Mar 26, 2018
@mpg
Copy link
Contributor

mpg commented Mar 26, 2018

Indeed, I guess it has been rebased on top of current development since the time I marked it as suitable for 2.7. @jethrogb would you like to create a 2.7 backport like you did for the 2.1 backport? Otherwise let us know and one of us will take care of it. Thanks!

@mpg
Copy link
Contributor

mpg commented Mar 28, 2018

2.7 backport created: #1529

@@ -1008,10 +1004,34 @@ Parse EC Key #4 (PKCS8 DER)
depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED
pk_parse_keyfile_ec:"data_files/ec_prv.pk8.der":"NULL":0

Parse EC Key #4a (PKCS8 DER, no public key)
depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED

Choose a reason for hiding this comment

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

MBEDTLS_ECP_C is already a dependency of test function pk_parse_keyfile_ec in tests/suites/test_suite_pkparse.function. Hence not required here and at other places.

@mpg mpg added approved Design and code approved - may be waiting for CI or backports approved for design and removed needs-backports Backports are missing or are pending review and approval. labels Mar 29, 2018
@Patater Patater merged commit d2df936 into Mbed-TLS:development Mar 29, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Design and code approved - may be waiting for CI or backports bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants