Project

General

Profile

Bug #4450

macOS Keychain does not support PKCS8 keys created with a PBKDF2 PRF other than HMAC-SHA1 (was: Security/Tpm/TestBackEnd/ImportExport fails with openssl 1.1)

Added by Davide Pesavento about 3 years ago. Updated 9 months ago.

Status:
Closed
Priority:
Normal
Category:
Security
Target version:
Start date:
Due date:
% Done:

100%

Estimated time:

Description

macOS 10.12, OpenSSL 1.1.0g, https://travis-ci.org/named-data/ndn-cxx/jobs/326925215

../tests/unit-tests/security/tpm/back-end.t.cpp:178: Entering test case "ImportExport<ndn__security__tpm__tests__BackEndWrapperOsx>"
../src/security/tpm/back-end-osx.cpp:509: fatal error: in "virtual void ndn::security::tpm::BackEndOsx::doImportKey(const ndn::Name &, const uint8_t *, size_t, const char *, size_t)": boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<ndn::security::tpm::BackEndOsx::Error> >: Cannot import the private key
../tests/unit-tests/security/tpm/back-end.t.cpp:212: last checkpoint
../tests/unit-tests/security/tpm/back-end.t.cpp:178: Leaving test case "ImportExport<ndn__security__tpm__tests__BackEndWrapperOsx>"; testing time: 24876us
#1

Updated by Davide Pesavento over 2 years ago

  • Subject changed from Security/Tpm/TestBackEnd/ImportExport fails with openssl 1.1 to macOS Keychain does not support PKCS8-encoded keys with .. other than SHA-1 (was: Security/Tpm/TestBackEnd/ImportExport fails with openssl 1.1)
  • Status changed from New to In Progress
  • Assignee set to Davide Pesavento
  • Target version set to v0.7
  • % Done changed from 0 to 30

I analyzed the ASN.1 structure produced by our PKCS #8 encoding (PrivateKey::toPkcs8), which is then fed to macOS's SecItemImport, and I discovered that openssl 1.1 and later defaults to HMAC-SHA256 as the underlying PRF for PBKDF2, while earlier versions used HMAC-SHA1(*). Sadly, macOS doesn't seem to support anything other than HMAC-SHA1, so it fails to import a private key encrypted by a recent openssl with default settings.

(*) In fact, older openssl generates an ASN.1 encoding without a "prf" object under "PBKDF2-params". According to RFC 8018, if a "prf" value is not specified, the default is algid-hmacWithSHA1.

#2

Updated by Davide Pesavento over 2 years ago

  • Subject changed from macOS Keychain does not support PKCS8-encoded keys with .. other than SHA-1 (was: Security/Tpm/TestBackEnd/ImportExport fails with openssl 1.1) to macOS Keychain does not support PKCS8 keys created with a PBKDF2 PRF other than HMAC-SHA1 (was: Security/Tpm/TestBackEnd/ImportExport fails with openssl 1.1)
#3

Updated by Davide Pesavento over 2 years ago

Davide Pesavento wrote:

Sadly, macOS doesn't seem to support anything other than HMAC-SHA1, so it fails to import a private key encrypted by a recent openssl with default settings.

I just realized that Apple's Security library is open source, so I looked directly at the code, which confirmed my previous analysis.

From https://opensource.apple.com/source/Security/Security-58286.41.2/OSX/libsecurity_keychain/lib/SecImportExportPkcs8.cpp.auto.html

    /* prf optional, but if it's there it better be CSSMOID_PKCS5_HMAC_SHA1 */
    if(pbkdf2Params.prf.Data) {
        if(!nssCompareCssmData(&pbkdf2Params.prf, &CSSMOID_PKCS5_HMAC_SHA1)) {
            SecPkcs8Dbg("PKCS8: PKCS5 v2 unexpected prf OID");
            return errSecUnknownFormat;
        }
    }
    prf = CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1;

Later in the same function, we can also see that Apple support only DES, DES_EDE3, RC2, and RC5 as encryption algorithms for the key :(

#4

Updated by Davide Pesavento over 2 years ago

I see two ways to resolve this:

  1. In transform::PrivateKey::toPkcs8, force the usage of HMAC-SHA1 as PRF, restoring compatibility with macOS's SecItemImport. This can be done by using a combination of 3 low(er)-level (and undocumented) openssl functions instead of i2d_PKCS8PrivateKey_bio.
  2. Keep using the (more secure) openssl default, but change tpm::BackEndOsx::doImportKey to unwrap and decrypt the key using openssl functions before importing it into macOS keychain.

I'm not sure which way is best. I've tried (1) and it seems to work. On the other hand, (2) would give us more flexibility in the long run, because we're not constrained by what macOS does or does not support, and would also allow us to switch key encryption to AES (which isn't supported by macOS) from the current 3DES.

#5

Updated by Alex Afanasyev over 2 years ago

I am leaning towards option 2, if it is feasible to implement and implementation complexity is reasonable.

#6

Updated by Davide Pesavento over 2 years ago

  • Status changed from In Progress to Code review
  • % Done changed from 30 to 100
#7

Updated by Davide Pesavento over 2 years ago

  • Status changed from Code review to Closed
#8

Updated by Davide Pesavento 9 months ago

  • Tags set to macOS, security

Also available in: Atom PDF