1 // Copyright Joyent, Inc. and other Node contributors.
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
22 #ifndef SRC_NODE_CRYPTO_H_
23 #define SRC_NODE_CRYPTO_H_
26 #include "node_crypto_clienthello.h" // ClientHelloParser
27 #include "node_crypto_clienthello-inl.h"
29 #ifdef OPENSSL_NPN_NEGOTIATED
30 #include "node_buffer.h"
34 #include "async-wrap.h"
35 #include "async-wrap-inl.h"
36 #include "base-object.h"
37 #include "base-object-inl.h"
41 #include <openssl/ssl.h>
42 #ifndef OPENSSL_NO_ENGINE
43 # include <openssl/engine.h>
44 #endif // !OPENSSL_NO_ENGINE
45 #include <openssl/err.h>
46 #include <openssl/evp.h>
47 #include <openssl/pem.h>
48 #include <openssl/x509.h>
49 #include <openssl/x509v3.h>
50 #include <openssl/hmac.h>
51 #include <openssl/rand.h>
52 #include <openssl/pkcs12.h>
54 #define EVP_F_EVP_DECRYPTFINAL 101
60 extern int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx);
62 extern X509_STORE* root_cert_store;
64 // Forward declaration
67 class SecureContext : public BaseObject {
73 static void Initialize(Environment* env, v8::Handle<v8::Object> target);
75 X509_STORE* ca_store_;
78 static const int kMaxSessionSize = 10 * 1024;
82 static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
83 static void Init(const v8::FunctionCallbackInfo<v8::Value>& args);
84 static void SetKey(const v8::FunctionCallbackInfo<v8::Value>& args);
85 static void SetCert(const v8::FunctionCallbackInfo<v8::Value>& args);
86 static void AddCACert(const v8::FunctionCallbackInfo<v8::Value>& args);
87 static void AddCRL(const v8::FunctionCallbackInfo<v8::Value>& args);
88 static void AddRootCerts(const v8::FunctionCallbackInfo<v8::Value>& args);
89 static void SetCiphers(const v8::FunctionCallbackInfo<v8::Value>& args);
90 static void SetECDHCurve(const v8::FunctionCallbackInfo<v8::Value>& args);
91 static void SetOptions(const v8::FunctionCallbackInfo<v8::Value>& args);
92 static void SetSessionIdContext(
93 const v8::FunctionCallbackInfo<v8::Value>& args);
94 static void SetSessionTimeout(
95 const v8::FunctionCallbackInfo<v8::Value>& args);
96 static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
97 static void LoadPKCS12(const v8::FunctionCallbackInfo<v8::Value>& args);
98 static void GetTicketKeys(const v8::FunctionCallbackInfo<v8::Value>& args);
99 static void SetTicketKeys(const v8::FunctionCallbackInfo<v8::Value>& args);
101 SecureContext(Environment* env, v8::Local<v8::Object> wrap)
102 : BaseObject(env, wrap),
105 MakeWeak<SecureContext>(this);
110 if (ctx_->cert_store == root_cert_store) {
111 // SSL_CTX_free() will attempt to free the cert_store as well.
112 // Since we want our root_cert_store to stay around forever
113 // we just clear the field. Hopefully OpenSSL will not modify this
114 // struct in future versions.
115 ctx_->cert_store = NULL;
121 assert(ca_store_ == NULL);
126 // SSLWrap implicitly depends on the inheriting class' handle having an
127 // internal pointer to the Base class.
128 template <class Base>
136 SSLWrap(Environment* env, SecureContext* sc, Kind kind)
140 session_callbacks_(false),
141 new_session_wait_(false) {
142 ssl_ = SSL_new(sc->ctx_);
143 assert(ssl_ != NULL);
151 if (next_sess_ != NULL) {
152 SSL_SESSION_free(next_sess_);
156 #ifdef OPENSSL_NPN_NEGOTIATED
158 selected_npn_proto_.Reset();
162 inline SSL* ssl() const { return ssl_; }
163 inline void enable_session_callbacks() { session_callbacks_ = true; }
164 inline bool is_server() const { return kind_ == kServer; }
165 inline bool is_client() const { return kind_ == kClient; }
166 inline bool is_waiting_new_session() const { return new_session_wait_; }
169 static void InitNPN(SecureContext* sc, Base* base);
170 static void AddMethods(Environment* env, v8::Handle<v8::FunctionTemplate> t);
172 static SSL_SESSION* GetSessionCallback(SSL* s,
176 static int NewSessionCallback(SSL* s, SSL_SESSION* sess);
177 static void OnClientHello(void* arg,
178 const ClientHelloParser::ClientHello& hello);
180 static void GetPeerCertificate(
181 const v8::FunctionCallbackInfo<v8::Value>& args);
182 static void GetSession(const v8::FunctionCallbackInfo<v8::Value>& args);
183 static void SetSession(const v8::FunctionCallbackInfo<v8::Value>& args);
184 static void LoadSession(const v8::FunctionCallbackInfo<v8::Value>& args);
185 static void IsSessionReused(const v8::FunctionCallbackInfo<v8::Value>& args);
186 static void IsInitFinished(const v8::FunctionCallbackInfo<v8::Value>& args);
187 static void VerifyError(const v8::FunctionCallbackInfo<v8::Value>& args);
188 static void GetCurrentCipher(const v8::FunctionCallbackInfo<v8::Value>& args);
189 static void EndParser(const v8::FunctionCallbackInfo<v8::Value>& args);
190 static void Renegotiate(const v8::FunctionCallbackInfo<v8::Value>& args);
191 static void Shutdown(const v8::FunctionCallbackInfo<v8::Value>& args);
192 static void GetTLSTicket(const v8::FunctionCallbackInfo<v8::Value>& args);
193 static void NewSessionDone(const v8::FunctionCallbackInfo<v8::Value>& args);
195 #ifdef SSL_set_max_send_fragment
196 static void SetMaxSendFragment(
197 const v8::FunctionCallbackInfo<v8::Value>& args);
198 #endif // SSL_set_max_send_fragment
200 #ifdef OPENSSL_NPN_NEGOTIATED
201 static void GetNegotiatedProto(
202 const v8::FunctionCallbackInfo<v8::Value>& args);
203 static void SetNPNProtocols(const v8::FunctionCallbackInfo<v8::Value>& args);
204 static int AdvertiseNextProtoCallback(SSL* s,
205 const unsigned char** data,
208 static int SelectNextProtoCallback(SSL* s,
210 unsigned char* outlen,
211 const unsigned char* in,
214 #endif // OPENSSL_NPN_NEGOTIATED
216 inline Environment* ssl_env() const {
220 Environment* const env_;
222 SSL_SESSION* next_sess_;
224 bool session_callbacks_;
225 bool new_session_wait_;
226 ClientHelloParser hello_parser_;
228 #ifdef OPENSSL_NPN_NEGOTIATED
229 v8::Persistent<v8::Object> npn_protos_;
230 v8::Persistent<v8::Value> selected_npn_proto_;
231 #endif // OPENSSL_NPN_NEGOTIATED
233 friend class SecureContext;
236 // Connection inherits from AsyncWrap because SSLWrap makes calls to
237 // MakeCallback, but SSLWrap doesn't store the handle itself. Instead it
238 // assumes that any args.This() called will be the handle from Connection.
239 class Connection : public SSLWrap<Connection>, public AsyncWrap {
242 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
249 static void Initialize(Environment* env, v8::Handle<v8::Object> target);
250 void NewSessionDoneCb();
252 #ifdef OPENSSL_NPN_NEGOTIATED
253 v8::Persistent<v8::Object> npnProtos_;
254 v8::Persistent<v8::Value> selectedNPNProto_;
257 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
258 v8::Persistent<v8::Object> sniObject_;
259 v8::Persistent<v8::Value> sniContext_;
260 v8::Persistent<v8::String> servername_;
264 static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
265 static void EncIn(const v8::FunctionCallbackInfo<v8::Value>& args);
266 static void ClearOut(const v8::FunctionCallbackInfo<v8::Value>& args);
267 static void ClearPending(const v8::FunctionCallbackInfo<v8::Value>& args);
268 static void EncPending(const v8::FunctionCallbackInfo<v8::Value>& args);
269 static void EncOut(const v8::FunctionCallbackInfo<v8::Value>& args);
270 static void ClearIn(const v8::FunctionCallbackInfo<v8::Value>& args);
271 static void Start(const v8::FunctionCallbackInfo<v8::Value>& args);
272 static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
274 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
276 static void GetServername(const v8::FunctionCallbackInfo<v8::Value>& args);
277 static void SetSNICallback(const v8::FunctionCallbackInfo<v8::Value>& args);
278 static int SelectSNIContextCallback_(SSL* s, int* ad, void* arg);
281 static void OnClientHelloParseEnd(void* arg);
283 int HandleBIOError(BIO* bio, const char* func, int rv);
295 int HandleSSLError(const char* func, int rv, ZeroStatus zs, SyscallStatus ss);
298 void SetShutdownFlags();
300 Connection(Environment* env,
301 v8::Local<v8::Object> wrap,
303 SSLWrap<Connection>::Kind kind)
304 : SSLWrap<Connection>(env, sc, kind),
305 AsyncWrap(env, wrap, AsyncWrap::PROVIDER_CRYPTO),
309 MakeWeak<Connection>(this);
310 hello_parser_.Start(SSLWrap<Connection>::OnClientHello,
311 OnClientHelloParseEnd,
313 enable_session_callbacks();
317 static void SSLInfoCallback(const SSL *ssl, int where, int ret);
322 uint8_t hello_data_[18432];
323 size_t hello_offset_;
325 friend class ClientHelloParser;
326 friend class SecureContext;
329 class CipherBase : public BaseObject {
335 EVP_CIPHER_CTX_cleanup(&ctx_);
338 static void Initialize(Environment* env, v8::Handle<v8::Object> target);
346 void Init(const char* cipher_type, const char* key_buf, int key_buf_len);
347 void InitIv(const char* cipher_type,
352 bool Update(const char* data, int len, unsigned char** out, int* out_len);
353 bool Final(unsigned char** out, int *out_len);
354 bool SetAutoPadding(bool auto_padding);
356 bool IsAuthenticatedMode() const;
357 bool GetAuthTag(char** out, unsigned int* out_len) const;
358 bool SetAuthTag(const char* data, unsigned int len);
359 bool SetAAD(const char* data, unsigned int len);
361 static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
362 static void Init(const v8::FunctionCallbackInfo<v8::Value>& args);
363 static void InitIv(const v8::FunctionCallbackInfo<v8::Value>& args);
364 static void Update(const v8::FunctionCallbackInfo<v8::Value>& args);
365 static void Final(const v8::FunctionCallbackInfo<v8::Value>& args);
366 static void SetAutoPadding(const v8::FunctionCallbackInfo<v8::Value>& args);
368 static void GetAuthTag(const v8::FunctionCallbackInfo<v8::Value>& args);
369 static void SetAuthTag(const v8::FunctionCallbackInfo<v8::Value>& args);
370 static void SetAAD(const v8::FunctionCallbackInfo<v8::Value>& args);
372 CipherBase(Environment* env,
373 v8::Local<v8::Object> wrap,
375 : BaseObject(env, wrap),
381 MakeWeak<CipherBase>(this);
385 EVP_CIPHER_CTX ctx_; /* coverity[member_decl] */
386 const EVP_CIPHER* cipher_; /* coverity[member_decl] */
390 unsigned int auth_tag_len_;
393 class Hmac : public BaseObject {
398 HMAC_CTX_cleanup(&ctx_);
401 static void Initialize(Environment* env, v8::Handle<v8::Object> target);
404 void HmacInit(const char* hash_type, const char* key, int key_len);
405 bool HmacUpdate(const char* data, int len);
406 bool HmacDigest(unsigned char** md_value, unsigned int* md_len);
408 static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
409 static void HmacInit(const v8::FunctionCallbackInfo<v8::Value>& args);
410 static void HmacUpdate(const v8::FunctionCallbackInfo<v8::Value>& args);
411 static void HmacDigest(const v8::FunctionCallbackInfo<v8::Value>& args);
413 Hmac(Environment* env, v8::Local<v8::Object> wrap)
414 : BaseObject(env, wrap),
416 initialised_(false) {
417 MakeWeak<Hmac>(this);
421 HMAC_CTX ctx_; /* coverity[member_decl] */
422 const EVP_MD* md_; /* coverity[member_decl] */
426 class Hash : public BaseObject {
431 EVP_MD_CTX_cleanup(&mdctx_);
434 static void Initialize(Environment* env, v8::Handle<v8::Object> target);
436 bool HashInit(const char* hash_type);
437 bool HashUpdate(const char* data, int len);
440 static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
441 static void HashUpdate(const v8::FunctionCallbackInfo<v8::Value>& args);
442 static void HashDigest(const v8::FunctionCallbackInfo<v8::Value>& args);
444 Hash(Environment* env, v8::Local<v8::Object> wrap)
445 : BaseObject(env, wrap),
447 initialised_(false) {
448 MakeWeak<Hash>(this);
452 EVP_MD_CTX mdctx_; /* coverity[member_decl] */
453 const EVP_MD* md_; /* coverity[member_decl] */
457 class SignBase : public BaseObject {
469 SignBase(Environment* env, v8::Local<v8::Object> wrap)
470 : BaseObject(env, wrap),
472 initialised_(false) {
478 EVP_MD_CTX_cleanup(&mdctx_);
482 void CheckThrow(Error error);
484 EVP_MD_CTX mdctx_; /* coverity[member_decl] */
485 const EVP_MD* md_; /* coverity[member_decl] */
489 class Sign : public SignBase {
492 static void Initialize(Environment* env, v8::Handle<v8::Object> target);
494 Error SignInit(const char* sign_type);
495 Error SignUpdate(const char* data, int len);
496 Error SignFinal(const char* key_pem,
498 const char* passphrase,
500 unsigned int *sig_len);
503 static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
504 static void SignInit(const v8::FunctionCallbackInfo<v8::Value>& args);
505 static void SignUpdate(const v8::FunctionCallbackInfo<v8::Value>& args);
506 static void SignFinal(const v8::FunctionCallbackInfo<v8::Value>& args);
508 Sign(Environment* env, v8::Local<v8::Object> wrap) : SignBase(env, wrap) {
509 MakeWeak<Sign>(this);
513 class Verify : public SignBase {
515 static void Initialize(Environment* env, v8::Handle<v8::Object> target);
517 Error VerifyInit(const char* verify_type);
518 Error VerifyUpdate(const char* data, int len);
519 Error VerifyFinal(const char* key_pem,
523 bool* verify_result);
526 static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
527 static void VerifyInit(const v8::FunctionCallbackInfo<v8::Value>& args);
528 static void VerifyUpdate(const v8::FunctionCallbackInfo<v8::Value>& args);
529 static void VerifyFinal(const v8::FunctionCallbackInfo<v8::Value>& args);
531 Verify(Environment* env, v8::Local<v8::Object> wrap) : SignBase(env, wrap) {
532 MakeWeak<Verify>(this);
536 class DiffieHellman : public BaseObject {
544 static void Initialize(Environment* env, v8::Handle<v8::Object> target);
546 bool Init(int primeLength, int g);
547 bool Init(const char* p, int p_len, int g);
548 bool Init(const char* p, int p_len, const char* g, int g_len);
551 static void DiffieHellmanGroup(
552 const v8::FunctionCallbackInfo<v8::Value>& args);
553 static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
554 static void GenerateKeys(const v8::FunctionCallbackInfo<v8::Value>& args);
555 static void GetPrime(const v8::FunctionCallbackInfo<v8::Value>& args);
556 static void GetGenerator(const v8::FunctionCallbackInfo<v8::Value>& args);
557 static void GetPublicKey(const v8::FunctionCallbackInfo<v8::Value>& args);
558 static void GetPrivateKey(const v8::FunctionCallbackInfo<v8::Value>& args);
559 static void ComputeSecret(const v8::FunctionCallbackInfo<v8::Value>& args);
560 static void SetPublicKey(const v8::FunctionCallbackInfo<v8::Value>& args);
561 static void SetPrivateKey(const v8::FunctionCallbackInfo<v8::Value>& args);
562 static void VerifyErrorGetter(
563 v8::Local<v8::String> property,
564 const v8::PropertyCallbackInfo<v8::Value>& args);
566 DiffieHellman(Environment* env, v8::Local<v8::Object> wrap)
567 : BaseObject(env, wrap),
571 MakeWeak<DiffieHellman>(this);
575 bool VerifyContext();
582 class Certificate : public AsyncWrap {
584 static void Initialize(Environment* env, v8::Handle<v8::Object> target);
586 v8::Handle<v8::Value> CertificateInit(const char* sign_type);
587 bool VerifySpkac(const char* data, unsigned int len);
588 const char* ExportPublicKey(const char* data, int len);
589 const char* ExportChallenge(const char* data, int len);
592 static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
593 static void VerifySpkac(const v8::FunctionCallbackInfo<v8::Value>& args);
594 static void ExportPublicKey(const v8::FunctionCallbackInfo<v8::Value>& args);
595 static void ExportChallenge(const v8::FunctionCallbackInfo<v8::Value>& args);
597 Certificate(Environment* env, v8::Local<v8::Object> wrap)
598 : AsyncWrap(env, wrap, AsyncWrap::PROVIDER_CRYPTO) {
599 MakeWeak<Certificate>(this);
603 bool EntropySource(unsigned char* buffer, size_t length);
604 #ifndef OPENSSL_NO_ENGINE
605 void SetEngine(const v8::FunctionCallbackInfo<v8::Value>& args);
606 #endif // !OPENSSL_NO_ENGINE
607 void InitCrypto(v8::Handle<v8::Object> target);
609 } // namespace crypto
612 #endif // SRC_NODE_CRYPTO_H_