I have a PKCS#12 test file with a single entry encrypted with PBES2 (PBEWithHmacSHA256AndAES_256) that is not working inside OpenSSL (but works elsewhere).
So I'm trying to figure out if my file is broken or if OpenSSL is unable to handle PBES2 properly.
The file is attached: test.p12
(pass:test
)
The output from openssl pkcs12
(v.1.0.2p-dev) is:
$ openssl pkcs12 -info -nodes -in out.p12 -passin pass:test
MAC Iteration 100000
MAC verified OK
PKCS7 Data
Shrouded Keybag: PBES2<unsupported parameters>
Bag Attributes
friendlyName: test
localKeyID: 54 69 6D 65 20 31 35 33 30 38 32 31 38 34 39 32 39 39
Error outputting keys and certificates
10564:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:.\crypto\asn1\tasn_dec.c:1220:
10564:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error:.\crypto\asn1\tasn_dec.c:386:Type=X509_ALGOR
10564:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:.\crypto\asn1\tasn_dec.c:720:Field=keyfunc, Type=PBE2PARAM
I've traced it to these lines in pkcs12.c
:
if (pbenid == NID_pbes2) {
PBE2PARAM *pbe2 = NULL;
int encnid;
if (aparamtype == V_ASN1_SEQUENCE)
pbe2 = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBE2PARAM)); // <=== fails here
if (pbe2 == NULL) {
BIO_puts(x, "<unsupported parameters>");
goto done;
}
Hence my main question: what's the best way to debug this further?
I've been thinking about two approaches:
ASN1_item_unpack()
(how?)asn1parse
on it (how?)TLDR: your file is broken.
You can't decrypt that portion of the file because of the error, but you don't need to because the encryption parameters are unencrypted, precisely because the decrypter needs to parse them before it can decrypt, and we can mimic that with commandline asn1parse
. First parse the outer structure:
$ openssl asn1parse -in test.p12 -inform der -i
0:d=0 hl=4 l=2450 cons: SEQUENCE
4:d=1 hl=2 l= 1 prim: INTEGER :03
7:d=1 hl=4 l=2379 cons: SEQUENCE
11:d=2 hl=2 l= 9 prim: OBJECT :pkcs7-data
22:d=2 hl=4 l=2364 cons: cont [ 0 ]
26:d=3 hl=4 l=2360 prim: OCTET STRING [HEX DUMP]:308209343[REDACTED]
2390:d=1 hl=2 l= 62 cons: SEQUENCE
2392:d=2 hl=2 l= 33 cons: SEQUENCE
2394:d=3 hl=2 l= 9 cons: SEQUENCE
2396:d=4 hl=2 l= 5 prim: OBJECT :sha1
2403:d=4 hl=2 l= 0 prim: NULL
2405:d=3 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:17774B593A099F0332A817D2510FE15A0C699159
2427:d=2 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:814F2DB1C2EBCB64D38CD56881BC9AC2FD2936FB
2449:d=2 hl=2 l= 3 prim: INTEGER :0186A0
which correctly matches PFX from rfc2898 section 4. All of the useful content is in the contentinfo, at 26+4=30, so parse that:
$ openssl asn1parse -in test.p12 -inform der -i -strparse 30
0:d=0 hl=4 l=2356 cons: SEQUENCE
4:d=1 hl=4 l=1464 cons: SEQUENCE
8:d=2 hl=2 l= 9 prim: OBJECT :pkcs7-data
19:d=2 hl=4 l=1449 cons: cont [ 0 ]
23:d=3 hl=4 l=1445 prim: OCTET STRING [HEX DUMP]:308205A1[REDACTED]
1472:d=1 hl=4 l= 884 cons: SEQUENCE
1476:d=2 hl=2 l= 9 prim: OBJECT :pkcs7-encryptedData
1487:d=2 hl=4 l= 869 cons: cont [ 0 ]
1491:d=3 hl=4 l= 865 cons: SEQUENCE
1495:d=4 hl=2 l= 1 prim: INTEGER :00
1498:d=4 hl=4 l= 858 cons: SEQUENCE
1502:d=5 hl=2 l= 9 prim: OBJECT :pkcs7-data
1513:d=5 hl=2 l= 41 cons: SEQUENCE
1515:d=6 hl=2 l= 10 prim: OBJECT :pbeWithSHA1And40BitRC2-CBC
1527:d=6 hl=2 l= 27 cons: SEQUENCE
1529:d=7 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:B74DD380AAF9CBE6A327F74BC93C688A5E690AC2
1551:d=7 hl=2 l= 3 prim: INTEGER :C350
1556:d=5 hl=4 l= 800 prim: cont [ 0 ]
This has two 'bags': the Data at 30+4 actually contains the ShroudedKeyBag and the EncryptedData at 30+1472 is the cert bag, which is standard and I ignore. Breaking down the ShroudedKeyBag:
$ openssl asn1parse -in test.p12 -inform der -i -strparse 57
0:d=0 hl=4 l=1441 cons: SEQUENCE
4:d=1 hl=4 l=1437 cons: SEQUENCE
8:d=2 hl=2 l= 11 prim: OBJECT :pkcs8ShroudedKeyBag
21:d=2 hl=4 l=1358 cons: cont [ 0 ]
25:d=3 hl=4 l=1354 cons: SEQUENCE
29:d=4 hl=2 l= 116 cons: SEQUENCE
31:d=5 hl=2 l= 9 prim: OBJECT :PBES2
42:d=5 hl=2 l= 103 cons: SEQUENCE
44:d=6 hl=2 l= 9 prim: OBJECT :PBES2
55:d=6 hl=2 l= 90 cons: SEQUENCE
57:d=7 hl=2 l= 57 cons: SEQUENCE
59:d=8 hl=2 l= 9 prim: OBJECT :PBKDF2
70:d=8 hl=2 l= 44 cons: SEQUENCE
72:d=9 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:547DFCB4975830F2A455BE611128B2188BB237E
94:d=9 hl=2 l= 3 prim: INTEGER :0186A0
99:d=9 hl=2 l= 1 prim: INTEGER :20
102:d=9 hl=2 l= 12 cons: SEQUENCE
104:d=10 hl=2 l= 8 prim: OBJECT :hmacWithSHA256
114:d=10 hl=2 l= 0 prim: NULL
116:d=7 hl=2 l= 29 cons: SEQUENCE
118:d=8 hl=2 l= 9 prim: OBJECT :aes-256-cbc
129:d=8 hl=2 l= 16 prim: OCTET STRING [HEX DUMP]:12A6696B879EFB885F7C979904314FC
147:d=4 hl=4 l=1232 prim: OCTET STRING [HEX DUMP]:[REDACTED]
1383:d=2 hl=2 l= 60 cons: SET
1385:d=3 hl=2 l= 23 cons: SEQUENCE
1387:d=4 hl=2 l= 9 prim: OBJECT :friendlyName
1398:d=4 hl=2 l= 10 cons: SET
1400:d=5 hl=2 l= 8 prim: BMPSTRING
1410:d=3 hl=2 l= 33 cons: SEQUENCE
1412:d=4 hl=2 l= 9 prim: OBJECT :localKeyID
1423:d=4 hl=2 l= 20 cons: SET
1425:d=5 hl=2 l= 18 prim: OCTET STRING :Time 1530821849299
The value (ignoring the attributes, which look okay) of a ShroudedKeyBag (4.2 and 4.2.2) should be a PKCS8 EncryptedPrivateKeyInfo from rfc 5208 section 6:
EncryptedPrivateKeyInfo ::= SEQUENCE {
encryptionAlgorithm EncryptionAlgorithmIdentifier,
encryptedData EncryptedData }
EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
EncryptedData ::= OCTET STRING
And since the identified algorithm is PBES2, its parameters at 30+27+42 should be PBES2-params from rfc2898 appendix A.4:
PBES2-params ::= SEQUENCE {
keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} }
However, you can see what is actually present there is a SEQUENCE containing (OID) PBES2 and the correct PBES2-params structure, i.e. it is nested a level too deep. It appears something actually constructed the PBES2 AlgorithmIdentifier and then used it as the parameters of a second PBES2 AlgorithmIdentifier, which is wrong.
However, since the intent is clear, we can (manually) compute PBKDF2 salt=547DFCB49758030F2A455BE611128B2188BB237E iter=100000 size=32 alg=hmacSHA256 of pass=test giving key 2E896C4F2D9549FD D2BE8B8F895D7C56 DD9008A6D7B7196E 1A30000F7F545B37 and use that with AES-256-CBC (with PKCS7padding) IV=12A6696B879EFCB885F7C979904314FC to decrypt the RSA key:
$ dd if=test.p12 bs=1 skip=208 count=1232 | \
> openssl aes-256-cbc -d -K 2E896C4F2D9549FDD2BE8B8F895D7C56DD9008A6D7B7196E1A30000F7F545B37 -iv 12A6696B879EFCB885F7C979904314FC >test.out
$ openssl pkey -in test.out -inform der -text -noout
Private-Key: (2048 bit)
modulus:
00:d5:a7:ef:74:dd:ab:60:12:69:0d:dd:29:61:f7:
0b:46:27:8d:c6:c3:5c:a6:b0:0e:59:01:d3:ff:65:
[rest redacted]
Since the cert bag is correctly formatted (and encrypted), it can be read with simply:
$ openssl pkcs12 -in test.p12 -passin pass:test -nokeys
MAC verified OK
Bag Attributes
friendlyName: test
localKeyID: 54 69 6D 65 20 31 35 33 30 38 32 31 38 34 39 32 39 39
subject=/CN=test
issuer=/CN=test
-----BEGIN CERTIFICATE-----
MIICrDCCAZSgAwIBAgIBATANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDAR0ZXN0
MB4XDTE4MDcwNTIwMTcyOVoXDTE5MDcwNTIwMTcyOVowDzENMAsGA1UEAwwEdGVz
dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANWn73Tdq2ASaQ3dKWH3
C0YnjcbDXKawDlkB0/9l53T4kQgy/CCsCPbv+LpcOLWIw61rPVzjlWTmg384GqAF
s7Ewn98v8JsxKw7HXeYCvw+li2x3Y+DVtkqWchnsJWnmksXAynQnrhb2ayczM+YR
OGli0Yvs6pQKNDuRKXrL2/cX212wFC42QE0NxfSblUdxrl2x4INqg9ME0fsHc2TO
lt3JItxGK7vQkU/tNIOlhKOWUxt9lVPNaIGFW0w2CkGxV1HYGRy8VCDqAfsI4x18
4WJTPTXjQ+EMl1yu5jPuRNdt7Gzvhll9O6LRUsJ2fNXAeQl7wOG/xZ9Rf73q1aTp
CBECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEA
UL2dfILp69CBPF8DD8Pzso6QIcMDtBltXumv2/NL/YO1SXY3Rt3LZ4EJtrYvb/H3
E3fH8qT9Yhfcrz+0F1aFt0WCdcOWDtZ5s7pn36a3Wye9LoBjPcB36BttzaBku+49
PIOQwQGjc6vg3prFS/OBOpWsa94GZemI4xpfwHE2EXANKN4ufb9fyPRyrXGR8SQD
3EdejRwLuICvxS/u8wO4+SfiHGLuR/i+w74nQeMsyrphWtPs9cDe4NMMN0I6WGKA
u9XeWzxSmEswYmmm2y/KX+fVmeNoKbht5Oiaej9aVFS77hT/OdjO281R/1osIdPi
8EJw1sCq5Tk7jkWxxZh+6Q==
-----END CERTIFICATE-----
QEF.