From 372dc86af5f17d7a8756df6458c41d2538e03e4e Mon Sep 17 00:00:00 2001 From: Yury Popov Date: Sat, 12 Aug 2017 19:06:35 +0300 Subject: [PATCH] tls: multiple PFX in createSecureContext Add support for multiple PFX files in tls.createSecureContext. Also added support for object-style PFX pass. PR-URL: https://github.com/nodejs/node/pull/14793 Fixes: https://github.com/nodejs/node/issues/14756 Reviewed-By: Ruben Bridgewater Reviewed-By: Fedor Indutny Reviewed-By: James M Snell --- doc/api/tls.md | 12 ++++--- lib/_tls_common.js | 28 +++++++++++----- test/fixtures/keys/Makefile | 8 +++++ test/fixtures/keys/ec-pfx.pem | Bin 0 -> 1006 bytes test/parallel/test-tls-multi-pfx.js | 50 ++++++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 13 deletions(-) create mode 100644 test/fixtures/keys/ec-pfx.pem create mode 100644 test/parallel/test-tls-multi-pfx.js diff --git a/doc/api/tls.md b/doc/api/tls.md index e18bbb62b1..ebcf85438f 100644 --- a/doc/api/tls.md +++ b/doc/api/tls.md @@ -934,10 +934,14 @@ changes: --> * `options` {Object} - * `pfx` {string|Buffer} Optional PFX or PKCS12 encoded private key and - certificate chain. `pfx` is an alternative to providing `key` and `cert` - individually. PFX is usually encrypted, if it is, `passphrase` will be used - to decrypt it. + * `pfx` {string|string[]|Buffer|Buffer[]|Object[]} Optional PFX or PKCS12 + encoded private key and certificate chain. `pfx` is an alternative to + providing `key` and `cert` individually. PFX is usually encrypted, if it is, + `passphrase` will be used to decrypt it. Multiple PFX can be provided either + as an array of unencrypted PFX buffers, or an array of objects in the form + `{buf: [, passphrase: ]}`. The object form can only + occur in an array. `object.passphrase` is optional. Encrypted PFX will be + decrypted with `object.passphrase` if provided, or `options.passphrase` if it is not. * `key` {string|string[]|Buffer|Buffer[]|Object[]} Optional private keys in PEM format. PEM allows the option of private keys being encrypted. Encrypted keys will be decrypted with `options.passphrase`. Multiple keys using diff --git a/lib/_tls_common.js b/lib/_tls_common.js index 92ba45d57e..3c4f2e2bb9 100644 --- a/lib/_tls_common.js +++ b/lib/_tls_common.js @@ -161,19 +161,29 @@ exports.createSecureContext = function createSecureContext(options, context) { } if (options.pfx) { - var pfx = options.pfx; - if (!crypto) crypto = require('crypto'); - pfx = crypto._toBuf(pfx); - if (passphrase) - passphrase = crypto._toBuf(passphrase); - - if (passphrase) { - c.context.loadPKCS12(pfx, passphrase); + if (Array.isArray(options.pfx)) { + for (i = 0; i < options.pfx.length; i++) { + const pfx = options.pfx[i]; + const raw = pfx.buf ? pfx.buf : pfx; + const buf = crypto._toBuf(raw); + const passphrase = pfx.passphrase || options.passphrase; + if (passphrase) { + c.context.loadPKCS12(buf, crypto._toBuf(passphrase)); + } else { + c.context.loadPKCS12(buf); + } + } } else { - c.context.loadPKCS12(pfx); + const buf = crypto._toBuf(options.pfx); + const passphrase = options.passphrase; + if (passphrase) { + c.context.loadPKCS12(buf, crypto._toBuf(passphrase)); + } else { + c.context.loadPKCS12(buf); + } } } diff --git a/test/fixtures/keys/Makefile b/test/fixtures/keys/Makefile index c7390eda0e..27fda1eef2 100644 --- a/test/fixtures/keys/Makefile +++ b/test/fixtures/keys/Makefile @@ -335,6 +335,14 @@ ec-cert.pem: ec-csr.pem ec-key.pem -signkey ec-key.pem \ -out ec-cert.pem +ec-pfx.pem: ec-cert.pem ec-key.pem + openssl pkcs12 -export \ + -descert \ + -in ec-cert.pem \ + -inkey ec-key.pem \ + -out ec-pfx.pem \ + -password pass: + dh512.pem: openssl dhparam -out dh512.pem 512 diff --git a/test/fixtures/keys/ec-pfx.pem b/test/fixtures/keys/ec-pfx.pem new file mode 100644 index 0000000000000000000000000000000000000000..3a4aa7dd696085b04b9a169fb0bfaccb296ee714 GIT binary patch literal 1006 zcmXqLVt&QM$ZXKWyn&5VtIebBJ1-+UqmM z*K!sZ)l})GJH80~Ic=GXHm8%&)%O~bJ0|n3Nx8|Ye$y=3<;wBn$NASS5r`?!`1tk3 zpDF9Ie;$6dXub2{7CmF9kgPBN@45!Jli2gAxf8BJi{rJ+qEyaU)T=Er z+@`r;v%buw-{CXoTOD(Y_)sBs;n<^ha@m!)e;m+PdOqR$jzU;o_O1(lKa)F zPjXtbMCUGD*5vVfkJZ72$A26zxthV>edq4CJ^VpyMS|n@I2qni-d>%3;KQzh)3OfJ zE;I1)*dO>(yYKzI%Z{eAr_8Ky;3{M6E4XGA9X#QL(XLH@tivMjiEywe+Sh4om$r zoVsvJ>eLxre*4&--2XT8g0+}JJa5d;ZMtE%41avu*_it{FnMysx+{01wbtEgESo!5 zXc3ThRE0rSYRd<2!@K*KFLd zB*?|cw4iZ|LE}cuba{I!OQP(WUDrVAlBIEigZbO4A*#k#_LYQq*{n$-l9PA??^zuAyK=GY;>M%L@=i<(+5Lyr zY3iC?^Nbw6eoWo`=DGf3E0N$WLgELz3{?%3;ojpEH56kJ3FMeuv(W$SOwF15I-@mo z-&@}}W@2DyplHC!#;VQ7%p}Fiz#?)*(m`|DvB|efFMWu6r0`Ams?6d|EF2!(#-Bbs J+{^&-EC37!#6