2017-01-03 13:16:48 -08:00
|
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
// copy of this software and associated documentation files (the
|
|
|
|
// "Software"), to deal in the Software without restriction, including
|
|
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
|
|
// following conditions:
|
|
|
|
//
|
|
|
|
// The above copyright notice and this permission notice shall be included
|
|
|
|
// in all copies or substantial portions of the Software.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
2015-05-19 13:00:06 +02:00
|
|
|
'use strict';
|
2016-11-26 09:34:43 +01:00
|
|
|
const common = require('../common');
|
2010-05-03 23:37:49 +01:00
|
|
|
|
2015-03-04 12:11:21 +11:00
|
|
|
if (!common.hasCrypto) {
|
2016-05-11 15:34:52 -04:00
|
|
|
common.skip('missing crypto');
|
2015-07-07 20:55:55 +05:30
|
|
|
return;
|
2010-06-29 23:12:46 -07:00
|
|
|
}
|
2010-05-03 23:37:49 +01:00
|
|
|
|
2016-11-26 09:34:43 +01:00
|
|
|
const assert = require('assert');
|
|
|
|
const crypto = require('crypto');
|
|
|
|
const fs = require('fs');
|
|
|
|
const tls = require('tls');
|
2012-10-22 10:37:20 -07:00
|
|
|
|
2016-11-26 09:34:43 +01:00
|
|
|
crypto.DEFAULT_ENCODING = 'buffer';
|
2010-06-18 19:42:58 +10:00
|
|
|
|
|
|
|
// Test Certificates
|
2016-11-26 09:34:43 +01:00
|
|
|
const caPem = fs.readFileSync(common.fixturesDir + '/test_ca.pem', 'ascii');
|
|
|
|
const certPem = fs.readFileSync(common.fixturesDir + '/test_cert.pem', 'ascii');
|
|
|
|
const certPfx = fs.readFileSync(common.fixturesDir + '/test_cert.pfx');
|
|
|
|
const keyPem = fs.readFileSync(common.fixturesDir + '/test_key.pem', 'ascii');
|
2010-05-03 23:37:49 +01:00
|
|
|
|
2014-03-06 15:44:18 -05:00
|
|
|
// 'this' safety
|
|
|
|
// https://github.com/joyent/node/issues/6690
|
|
|
|
assert.throws(function() {
|
2016-11-26 09:34:43 +01:00
|
|
|
const options = {key: keyPem, cert: certPem, ca: caPem};
|
|
|
|
const credentials = tls.createSecureContext(options);
|
|
|
|
const context = credentials.context;
|
|
|
|
const notcontext = { setOptions: context.setOptions, setKey: context.setKey };
|
|
|
|
tls.createSecureContext({ secureOptions: 1 }, notcontext);
|
|
|
|
}, /^TypeError: Illegal invocation$/);
|
2014-03-06 15:44:18 -05:00
|
|
|
|
2012-05-14 01:08:23 +05:30
|
|
|
// PFX tests
|
|
|
|
assert.doesNotThrow(function() {
|
2016-05-04 22:20:27 -07:00
|
|
|
tls.createSecureContext({pfx: certPfx, passphrase: 'sample'});
|
2012-05-14 01:08:23 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
assert.throws(function() {
|
2016-05-04 22:20:27 -07:00
|
|
|
tls.createSecureContext({pfx: certPfx});
|
2016-11-26 09:34:43 +01:00
|
|
|
}, /^Error: mac verify failure$/);
|
2012-05-14 01:08:23 +05:30
|
|
|
|
|
|
|
assert.throws(function() {
|
2016-05-04 22:20:27 -07:00
|
|
|
tls.createSecureContext({pfx: certPfx, passphrase: 'test'});
|
2016-11-26 09:34:43 +01:00
|
|
|
}, /^Error: mac verify failure$/);
|
2010-12-05 22:15:30 +03:00
|
|
|
|
2012-05-14 01:08:23 +05:30
|
|
|
assert.throws(function() {
|
2016-05-04 22:20:27 -07:00
|
|
|
tls.createSecureContext({pfx: 'sample', passphrase: 'test'});
|
2016-11-26 09:34:43 +01:00
|
|
|
}, /^Error: not enough data$/);
|
2012-05-14 01:08:23 +05:30
|
|
|
|
2010-05-03 23:37:49 +01:00
|
|
|
|
2011-03-14 11:16:35 +01:00
|
|
|
// update() should only take buffers / strings
|
|
|
|
assert.throws(function() {
|
|
|
|
crypto.createHash('sha1').update({foo: 'bar'});
|
2016-11-26 09:34:43 +01:00
|
|
|
}, /^TypeError: Data must be a string or a buffer$/);
|
2011-01-19 02:00:38 +01:00
|
|
|
|
2011-06-08 18:20:17 -07:00
|
|
|
|
2017-01-12 22:16:21 -08:00
|
|
|
function validateList(list) {
|
|
|
|
// The list must not be empty
|
|
|
|
assert(list.length > 0);
|
|
|
|
|
|
|
|
// The list should be sorted.
|
2013-11-21 13:23:43 +01:00
|
|
|
// Array#sort() modifies the list in place so make a copy.
|
2017-01-12 22:16:21 -08:00
|
|
|
const sorted = [...list].sort();
|
2016-04-19 15:37:45 -07:00
|
|
|
assert.deepStrictEqual(list, sorted);
|
2017-01-12 22:16:21 -08:00
|
|
|
|
|
|
|
// Each element should be unique.
|
|
|
|
assert.strictEqual([...new Set(list)].length, list.length);
|
|
|
|
|
|
|
|
// Each element should be a string.
|
|
|
|
assert(list.every((value) => typeof value === 'string'));
|
2012-10-13 02:49:53 +02:00
|
|
|
}
|
|
|
|
|
2013-03-19 00:16:55 +01:00
|
|
|
// Assume that we have at least AES-128-CBC.
|
2017-01-12 22:16:21 -08:00
|
|
|
const cryptoCiphers = crypto.getCiphers();
|
2016-11-26 09:34:43 +01:00
|
|
|
assert(crypto.getCiphers().includes('aes-128-cbc'));
|
2017-01-12 22:16:21 -08:00
|
|
|
validateList(cryptoCiphers);
|
2012-10-13 02:44:11 +02:00
|
|
|
|
2013-03-19 00:16:55 +01:00
|
|
|
// Assume that we have at least AES256-SHA.
|
2017-01-12 22:16:21 -08:00
|
|
|
const tlsCiphers = tls.getCiphers();
|
2016-11-26 09:34:43 +01:00
|
|
|
assert(tls.getCiphers().includes('aes256-sha'));
|
2017-01-12 22:16:21 -08:00
|
|
|
// There should be no capital letters in any element.
|
|
|
|
assert(tlsCiphers.every((value) => /^[^A-Z]+$/.test(value)));
|
|
|
|
validateList(tlsCiphers);
|
2013-03-19 00:16:55 +01:00
|
|
|
|
2012-10-13 02:44:11 +02:00
|
|
|
// Assert that we have sha and sha1 but not SHA and SHA1.
|
2016-11-26 09:34:43 +01:00
|
|
|
assert.notStrictEqual(0, crypto.getHashes().length);
|
|
|
|
assert(crypto.getHashes().includes('sha1'));
|
|
|
|
assert(crypto.getHashes().includes('sha'));
|
|
|
|
assert(!crypto.getHashes().includes('SHA1'));
|
|
|
|
assert(!crypto.getHashes().includes('SHA'));
|
|
|
|
assert(crypto.getHashes().includes('RSA-SHA1'));
|
|
|
|
assert(!crypto.getHashes().includes('rsa-sha1'));
|
2017-01-12 22:16:21 -08:00
|
|
|
validateList(crypto.getHashes());
|
2013-02-11 21:22:34 +01:00
|
|
|
|
2015-06-08 12:26:16 -04:00
|
|
|
// Assume that we have at least secp384r1.
|
2016-11-26 09:34:43 +01:00
|
|
|
assert.notStrictEqual(0, crypto.getCurves().length);
|
|
|
|
assert(crypto.getCurves().includes('secp384r1'));
|
|
|
|
assert(!crypto.getCurves().includes('SECP384R1'));
|
2017-01-12 22:16:21 -08:00
|
|
|
validateList(crypto.getCurves());
|
2015-06-08 12:26:16 -04:00
|
|
|
|
2017-01-13 14:28:35 -08:00
|
|
|
// Modifying return value from get* functions should not mutate subsequent
|
|
|
|
// return values.
|
|
|
|
function testImmutability(fn) {
|
|
|
|
const list = fn();
|
|
|
|
const copy = [...list];
|
|
|
|
list.push('some-arbitrary-value');
|
|
|
|
assert.deepStrictEqual(fn(), copy);
|
|
|
|
}
|
|
|
|
|
|
|
|
testImmutability(crypto.getCiphers);
|
|
|
|
testImmutability(tls.getCiphers);
|
|
|
|
testImmutability(crypto.getHashes);
|
|
|
|
testImmutability(crypto.getCurves);
|
|
|
|
|
2013-07-30 14:27:13 +02:00
|
|
|
// Regression tests for #5725: hex input that's not a power of two should
|
|
|
|
// throw, not assert in C++ land.
|
|
|
|
assert.throws(function() {
|
|
|
|
crypto.createCipher('aes192', 'test').update('0', 'hex');
|
2015-11-09 00:00:56 -05:00
|
|
|
}, common.hasFipsCrypto ? /not supported in FIPS mode/ : /Bad input string/);
|
2013-07-30 14:27:13 +02:00
|
|
|
|
|
|
|
assert.throws(function() {
|
|
|
|
crypto.createDecipher('aes192', 'test').update('0', 'hex');
|
2015-11-09 00:00:56 -05:00
|
|
|
}, common.hasFipsCrypto ? /not supported in FIPS mode/ : /Bad input string/);
|
2013-07-30 14:27:13 +02:00
|
|
|
|
|
|
|
assert.throws(function() {
|
|
|
|
crypto.createHash('sha1').update('0', 'hex');
|
2016-11-26 09:34:43 +01:00
|
|
|
}, /^TypeError: Bad input string$/);
|
2013-07-30 14:27:13 +02:00
|
|
|
|
|
|
|
assert.throws(function() {
|
|
|
|
crypto.createSign('RSA-SHA1').update('0', 'hex');
|
2016-11-26 09:34:43 +01:00
|
|
|
}, /^TypeError: Bad input string$/);
|
2013-07-30 14:27:13 +02:00
|
|
|
|
|
|
|
assert.throws(function() {
|
|
|
|
crypto.createVerify('RSA-SHA1').update('0', 'hex');
|
2016-11-26 09:34:43 +01:00
|
|
|
}, /^TypeError: Bad input string$/);
|
2013-09-28 23:33:29 -07:00
|
|
|
|
2014-01-26 20:09:14 +04:00
|
|
|
assert.throws(function() {
|
2016-11-26 09:34:43 +01:00
|
|
|
const priv = [
|
2014-01-26 20:09:14 +04:00
|
|
|
'-----BEGIN RSA PRIVATE KEY-----',
|
|
|
|
'MIGrAgEAAiEA+3z+1QNF2/unumadiwEr+C5vfhezsb3hp4jAnCNRpPcCAwEAAQIgQNriSQK4',
|
|
|
|
'EFwczDhMZp2dvbcz7OUUyt36z3S4usFPHSECEQD/41K7SujrstBfoCPzwC1xAhEA+5kt4BJy',
|
|
|
|
'eKN7LggbF3Dk5wIQN6SL+fQ5H/+7NgARsVBp0QIRANxYRukavs4QvuyNhMx+vrkCEQCbf6j/',
|
|
|
|
'Ig6/HueCK/0Jkmp+',
|
|
|
|
'-----END RSA PRIVATE KEY-----',
|
|
|
|
''
|
|
|
|
].join('\n');
|
2015-05-19 13:00:06 +02:00
|
|
|
crypto.createSign('RSA-SHA256').update('test').sign(priv);
|
2016-11-26 09:34:43 +01:00
|
|
|
}, /digest too big for rsa key$/);
|
2014-01-27 11:02:59 -08:00
|
|
|
|
2015-08-18 10:32:21 +08:00
|
|
|
assert.throws(function() {
|
|
|
|
// The correct header inside `test_bad_rsa_privkey.pem` should have been
|
|
|
|
// -----BEGIN PRIVATE KEY----- and -----END PRIVATE KEY-----
|
|
|
|
// instead of
|
|
|
|
// -----BEGIN RSA PRIVATE KEY----- and -----END RSA PRIVATE KEY-----
|
|
|
|
// It is generated in this way:
|
|
|
|
// $ openssl genrsa -out mykey.pem 512;
|
|
|
|
// $ openssl pkcs8 -topk8 -inform PEM -outform PEM -in mykey.pem \
|
|
|
|
// -out private_key.pem -nocrypt;
|
|
|
|
// Then open private_key.pem and change its header and footer.
|
2016-11-26 09:34:43 +01:00
|
|
|
const sha1_privateKey = fs.readFileSync(common.fixturesDir +
|
2015-08-18 10:32:21 +08:00
|
|
|
'/test_bad_rsa_privkey.pem', 'ascii');
|
|
|
|
// this would inject errors onto OpenSSL's error stack
|
|
|
|
crypto.createSign('sha1').sign(sha1_privateKey);
|
|
|
|
}, /asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag/);
|
|
|
|
|
2013-09-28 23:33:29 -07:00
|
|
|
// Make sure memory isn't released before being returned
|
|
|
|
console.log(crypto.randomBytes(16));
|
2016-10-30 13:22:50 -07:00
|
|
|
|
|
|
|
assert.throws(function() {
|
|
|
|
tls.createSecureContext({ crl: 'not a CRL' });
|
2016-11-26 09:34:43 +01:00
|
|
|
}, /^Error: Failed to parse CRL$/);
|