Browse Source

crypto: improve error messages

1) ThrowCryptoTypeErrors was not actually used for
   type-related errors. Removed it.
2) For AEAD modes, OpenSSL does not set any internal
   error information if Final does not complete suc-
   cessfully. Therefore, "TypeError:error:00000000:l
   ib(0):func(0):reason(0)" would be the error mess-
   age. Use a default message for these cases.

Signed-off-by: Fedor Indutny <fedor@indutny.com>
v0.11.13-release
Ingmar Runge 11 years ago
committed by Fedor Indutny
parent
commit
26a1b712ec
  1. 37
      src/node_crypto.cc
  2. 12
      test/simple/test-crypto-authenticated.js

37
src/node_crypto.cc

@ -195,26 +195,17 @@ static int CryptoPemCallback(char *buf, int size, int rwflag, void *u) {
}
void ThrowCryptoErrorHelper(Environment* env,
void ThrowCryptoError(Environment* env,
unsigned long err,
bool is_type_error) {
const char* default_message = NULL) {
HandleScope scope(env->isolate());
char errmsg[128];
if (err != 0 || default_message == NULL) {
char errmsg[128] = { 0 };
ERR_error_string_n(err, errmsg, sizeof(errmsg));
if (is_type_error)
env->ThrowTypeError(errmsg);
else
env->ThrowError(errmsg);
} else {
env->ThrowError(default_message);
}
void ThrowCryptoError(Environment* env, unsigned long err) {
ThrowCryptoErrorHelper(env, err, false);
}
void ThrowCryptoTypeError(Environment* env, unsigned long err) {
ThrowCryptoErrorHelper(env, err, true);
}
@ -2689,7 +2680,6 @@ bool CipherBase::SetAAD(const char* data, unsigned int len) {
&outlen,
reinterpret_cast<const unsigned char*>(data),
len)) {
ThrowCryptoTypeError(env(), ERR_get_error());
return false;
}
return true;
@ -2771,7 +2761,9 @@ void CipherBase::Update(const FunctionCallbackInfo<Value>& args) {
if (!r) {
delete[] out;
return ThrowCryptoTypeError(env, ERR_get_error());
return ThrowCryptoError(env,
ERR_get_error(),
"Trying to add data in unsupported state");
}
Local<Object> buf = Buffer::New(env, reinterpret_cast<char*>(out), out_len);
@ -2840,8 +2832,15 @@ void CipherBase::Final(const FunctionCallbackInfo<Value>& args) {
delete[] out_value;
out_value = NULL;
out_len = 0;
if (!r)
return ThrowCryptoTypeError(env, ERR_get_error());
if (!r) {
const char* msg = cipher->IsAuthenticatedMode() ?
"Unsupported state or unable to authenticate data" :
"Unsupported state";
return ThrowCryptoError(env,
ERR_get_error(),
msg);
}
}
args.GetReturnValue().Set(

12
test/simple/test-crypto-authenticated.js

@ -98,7 +98,7 @@ for (var i in TEST_CASES) {
assert.equal(msg, test.plain);
} else {
// assert that final throws if input data could not be verified!
assert.throws(function() { decrypt.final('ascii'); });
assert.throws(function() { decrypt.final('ascii'); }, / auth/);
}
})();
@ -115,26 +115,28 @@ for (var i in TEST_CASES) {
'ipxp9a6i1Mb4USb4', '6fKjEjR3Vl30EUYC');
encrypt.update('blah', 'ascii');
encrypt.final();
assert.throws(function() { encrypt.getAuthTag(); });
assert.throws(function() { encrypt.getAuthTag(); }, / state/);
assert.throws(function() {
encrypt.setAAD(new Buffer('123', 'ascii')); }, / state/);
})();
(function() {
// trying to get tag before inputting all data:
var encrypt = crypto.createCipheriv(test.algo, test.key, test.iv);
encrypt.update('blah', 'ascii');
assert.throws(function() { encrypt.getAuthTag(); });
assert.throws(function() { encrypt.getAuthTag(); }, / state/);
})();
(function() {
// trying to set tag on encryption object:
var encrypt = crypto.createCipheriv(test.algo, test.key, test.iv);
assert.throws(function() {
encrypt.setAuthTag(new Buffer(test.tag, 'hex')); });
encrypt.setAuthTag(new Buffer(test.tag, 'hex')); }, / state/);
})();
(function() {
// trying to read tag from decryption object:
var decrypt = crypto.createDecipheriv(test.algo, test.key, test.iv);
assert.throws(function() { decrypt.getAuthTag(); });
assert.throws(function() { decrypt.getAuthTag(); }, / state/);
})();
}

Loading…
Cancel
Save