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
56 #if !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_set_tlsext_status_cb)
57 # define NODE__HAVE_TLSEXT_STATUS_CB
58 #endif // !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_set_tlsext_status_cb)
63 extern int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx);
65 extern X509_STORE* root_cert_store;
67 // Forward declaration
70 class SecureContext : public BaseObject {
76 static void Initialize(Environment* env, v8::Handle<v8::Object> target);
78 X509_STORE* ca_store_;
83 static const int kMaxSessionSize = 10 * 1024;
87 static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
88 static void Init(const v8::FunctionCallbackInfo<v8::Value>& args);
89 static void SetKey(const v8::FunctionCallbackInfo<v8::Value>& args);
90 static void SetCert(const v8::FunctionCallbackInfo<v8::Value>& args);
91 static void AddCACert(const v8::FunctionCallbackInfo<v8::Value>& args);
92 static void AddCRL(const v8::FunctionCallbackInfo<v8::Value>& args);
93 static void AddRootCerts(const v8::FunctionCallbackInfo<v8::Value>& args);
94 static void SetCiphers(const v8::FunctionCallbackInfo<v8::Value>& args);
95 static void SetECDHCurve(const v8::FunctionCallbackInfo<v8::Value>& args);
96 static void SetOptions(const v8::FunctionCallbackInfo<v8::Value>& args);
97 static void SetSessionIdContext(
98 const v8::FunctionCallbackInfo<v8::Value>& args);
99 static void SetSessionTimeout(
100 const v8::FunctionCallbackInfo<v8::Value>& args);
101 static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
102 static void LoadPKCS12(const v8::FunctionCallbackInfo<v8::Value>& args);
103 static void GetTicketKeys(const v8::FunctionCallbackInfo<v8::Value>& args);
104 static void SetTicketKeys(const v8::FunctionCallbackInfo<v8::Value>& args);
106 template <bool primary>
107 static void GetCertificate(const v8::FunctionCallbackInfo<v8::Value>& args);
109 SecureContext(Environment* env, v8::Local<v8::Object> wrap)
110 : BaseObject(env, wrap),
115 MakeWeak<SecureContext>(this);
120 if (ctx_->cert_store == root_cert_store) {
121 // SSL_CTX_free() will attempt to free the cert_store as well.
122 // Since we want our root_cert_store to stay around forever
123 // we just clear the field. Hopefully OpenSSL will not modify this
124 // struct in future versions.
125 ctx_->cert_store = NULL;
137 assert(ca_store_ == NULL);
142 // SSLWrap implicitly depends on the inheriting class' handle having an
143 // internal pointer to the Base class.
144 template <class Base>
152 SSLWrap(Environment* env, SecureContext* sc, Kind kind)
156 session_callbacks_(false),
157 new_session_wait_(false) {
158 ssl_ = SSL_new(sc->ctx_);
159 assert(ssl_ != NULL);
167 if (next_sess_ != NULL) {
168 SSL_SESSION_free(next_sess_);
172 #ifdef OPENSSL_NPN_NEGOTIATED
174 selected_npn_proto_.Reset();
176 #ifdef NODE__HAVE_TLSEXT_STATUS_CB
177 ocsp_response_.Reset();
178 #endif // NODE__HAVE_TLSEXT_STATUS_CB
181 inline SSL* ssl() const { return ssl_; }
182 inline void enable_session_callbacks() { session_callbacks_ = true; }
183 inline bool is_server() const { return kind_ == kServer; }
184 inline bool is_client() const { return kind_ == kClient; }
185 inline bool is_waiting_new_session() const { return new_session_wait_; }
188 static void InitNPN(SecureContext* sc, Base* base);
189 static void AddMethods(Environment* env, v8::Handle<v8::FunctionTemplate> t);
191 static SSL_SESSION* GetSessionCallback(SSL* s,
195 static int NewSessionCallback(SSL* s, SSL_SESSION* sess);
196 static void OnClientHello(void* arg,
197 const ClientHelloParser::ClientHello& hello);
199 static void GetPeerCertificate(
200 const v8::FunctionCallbackInfo<v8::Value>& args);
201 static void GetSession(const v8::FunctionCallbackInfo<v8::Value>& args);
202 static void SetSession(const v8::FunctionCallbackInfo<v8::Value>& args);
203 static void LoadSession(const v8::FunctionCallbackInfo<v8::Value>& args);
204 static void IsSessionReused(const v8::FunctionCallbackInfo<v8::Value>& args);
205 static void IsInitFinished(const v8::FunctionCallbackInfo<v8::Value>& args);
206 static void VerifyError(const v8::FunctionCallbackInfo<v8::Value>& args);
207 static void GetCurrentCipher(const v8::FunctionCallbackInfo<v8::Value>& args);
208 static void EndParser(const v8::FunctionCallbackInfo<v8::Value>& args);
209 static void Renegotiate(const v8::FunctionCallbackInfo<v8::Value>& args);
210 static void Shutdown(const v8::FunctionCallbackInfo<v8::Value>& args);
211 static void GetTLSTicket(const v8::FunctionCallbackInfo<v8::Value>& args);
212 static void NewSessionDone(const v8::FunctionCallbackInfo<v8::Value>& args);
213 static void SetOCSPResponse(const v8::FunctionCallbackInfo<v8::Value>& args);
214 static void RequestOCSP(const v8::FunctionCallbackInfo<v8::Value>& args);
216 #ifdef SSL_set_max_send_fragment
217 static void SetMaxSendFragment(
218 const v8::FunctionCallbackInfo<v8::Value>& args);
219 #endif // SSL_set_max_send_fragment
221 #ifdef OPENSSL_NPN_NEGOTIATED
222 static void GetNegotiatedProto(
223 const v8::FunctionCallbackInfo<v8::Value>& args);
224 static void SetNPNProtocols(const v8::FunctionCallbackInfo<v8::Value>& args);
225 static int AdvertiseNextProtoCallback(SSL* s,
226 const unsigned char** data,
229 static int SelectNextProtoCallback(SSL* s,
231 unsigned char* outlen,
232 const unsigned char* in,
235 #endif // OPENSSL_NPN_NEGOTIATED
236 static int TLSExtStatusCallback(SSL* s, void* arg);
238 inline Environment* ssl_env() const {
242 Environment* const env_;
244 SSL_SESSION* next_sess_;
246 bool session_callbacks_;
247 bool new_session_wait_;
248 ClientHelloParser hello_parser_;
250 #ifdef NODE__HAVE_TLSEXT_STATUS_CB
251 v8::Persistent<v8::Object> ocsp_response_;
252 #endif // NODE__HAVE_TLSEXT_STATUS_CB
254 #ifdef OPENSSL_NPN_NEGOTIATED
255 v8::Persistent<v8::Object> npn_protos_;
256 v8::Persistent<v8::Value> selected_npn_proto_;
257 #endif // OPENSSL_NPN_NEGOTIATED
259 friend class SecureContext;
262 // Connection inherits from AsyncWrap because SSLWrap makes calls to
263 // MakeCallback, but SSLWrap doesn't store the handle itself. Instead it
264 // assumes that any args.This() called will be the handle from Connection.
265 class Connection : public SSLWrap<Connection>, public AsyncWrap {
268 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
275 static void Initialize(Environment* env, v8::Handle<v8::Object> target);
276 void NewSessionDoneCb();
278 #ifdef OPENSSL_NPN_NEGOTIATED
279 v8::Persistent<v8::Object> npnProtos_;
280 v8::Persistent<v8::Value> selectedNPNProto_;
283 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
284 v8::Persistent<v8::Object> sniObject_;
285 v8::Persistent<v8::Value> sniContext_;
286 v8::Persistent<v8::String> servername_;
290 static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
291 static void EncIn(const v8::FunctionCallbackInfo<v8::Value>& args);
292 static void ClearOut(const v8::FunctionCallbackInfo<v8::Value>& args);
293 static void ClearPending(const v8::FunctionCallbackInfo<v8::Value>& args);
294 static void EncPending(const v8::FunctionCallbackInfo<v8::Value>& args);
295 static void EncOut(const v8::FunctionCallbackInfo<v8::Value>& args);
296 static void ClearIn(const v8::FunctionCallbackInfo<v8::Value>& args);
297 static void Start(const v8::FunctionCallbackInfo<v8::Value>& args);
298 static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
300 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
302 static void GetServername(const v8::FunctionCallbackInfo<v8::Value>& args);
303 static void SetSNICallback(const v8::FunctionCallbackInfo<v8::Value>& args);
304 static int SelectSNIContextCallback_(SSL* s, int* ad, void* arg);
307 static void OnClientHelloParseEnd(void* arg);
309 int HandleBIOError(BIO* bio, const char* func, int rv);
321 int HandleSSLError(const char* func, int rv, ZeroStatus zs, SyscallStatus ss);
324 void SetShutdownFlags();
326 Connection(Environment* env,
327 v8::Local<v8::Object> wrap,
329 SSLWrap<Connection>::Kind kind)
330 : SSLWrap<Connection>(env, sc, kind),
331 AsyncWrap(env, wrap, AsyncWrap::PROVIDER_CRYPTO),
335 MakeWeak<Connection>(this);
336 hello_parser_.Start(SSLWrap<Connection>::OnClientHello,
337 OnClientHelloParseEnd,
339 enable_session_callbacks();
343 static void SSLInfoCallback(const SSL *ssl, int where, int ret);
348 uint8_t hello_data_[18432];
349 size_t hello_offset_;
351 friend class ClientHelloParser;
352 friend class SecureContext;
355 class CipherBase : public BaseObject {
361 EVP_CIPHER_CTX_cleanup(&ctx_);
364 static void Initialize(Environment* env, v8::Handle<v8::Object> target);
372 void Init(const char* cipher_type, const char* key_buf, int key_buf_len);
373 void InitIv(const char* cipher_type,
378 bool Update(const char* data, int len, unsigned char** out, int* out_len);
379 bool Final(unsigned char** out, int *out_len);
380 bool SetAutoPadding(bool auto_padding);
382 bool IsAuthenticatedMode() const;
383 bool GetAuthTag(char** out, unsigned int* out_len) const;
384 bool SetAuthTag(const char* data, unsigned int len);
385 bool SetAAD(const char* data, unsigned int len);
387 static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
388 static void Init(const v8::FunctionCallbackInfo<v8::Value>& args);
389 static void InitIv(const v8::FunctionCallbackInfo<v8::Value>& args);
390 static void Update(const v8::FunctionCallbackInfo<v8::Value>& args);
391 static void Final(const v8::FunctionCallbackInfo<v8::Value>& args);
392 static void SetAutoPadding(const v8::FunctionCallbackInfo<v8::Value>& args);
394 static void GetAuthTag(const v8::FunctionCallbackInfo<v8::Value>& args);
395 static void SetAuthTag(const v8::FunctionCallbackInfo<v8::Value>& args);
396 static void SetAAD(const v8::FunctionCallbackInfo<v8::Value>& args);
398 CipherBase(Environment* env,
399 v8::Local<v8::Object> wrap,
401 : BaseObject(env, wrap),
407 MakeWeak<CipherBase>(this);
411 EVP_CIPHER_CTX ctx_; /* coverity[member_decl] */
412 const EVP_CIPHER* cipher_; /* coverity[member_decl] */
416 unsigned int auth_tag_len_;
419 class Hmac : public BaseObject {
424 HMAC_CTX_cleanup(&ctx_);
427 static void Initialize(Environment* env, v8::Handle<v8::Object> target);
430 void HmacInit(const char* hash_type, const char* key, int key_len);
431 bool HmacUpdate(const char* data, int len);
432 bool HmacDigest(unsigned char** md_value, unsigned int* md_len);
434 static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
435 static void HmacInit(const v8::FunctionCallbackInfo<v8::Value>& args);
436 static void HmacUpdate(const v8::FunctionCallbackInfo<v8::Value>& args);
437 static void HmacDigest(const v8::FunctionCallbackInfo<v8::Value>& args);
439 Hmac(Environment* env, v8::Local<v8::Object> wrap)
440 : BaseObject(env, wrap),
442 initialised_(false) {
443 MakeWeak<Hmac>(this);
447 HMAC_CTX ctx_; /* coverity[member_decl] */
448 const EVP_MD* md_; /* coverity[member_decl] */
452 class Hash : public BaseObject {
457 EVP_MD_CTX_cleanup(&mdctx_);
460 static void Initialize(Environment* env, v8::Handle<v8::Object> target);
462 bool HashInit(const char* hash_type);
463 bool HashUpdate(const char* data, int len);
466 static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
467 static void HashUpdate(const v8::FunctionCallbackInfo<v8::Value>& args);
468 static void HashDigest(const v8::FunctionCallbackInfo<v8::Value>& args);
470 Hash(Environment* env, v8::Local<v8::Object> wrap)
471 : BaseObject(env, wrap),
473 initialised_(false) {
474 MakeWeak<Hash>(this);
478 EVP_MD_CTX mdctx_; /* coverity[member_decl] */
479 const EVP_MD* md_; /* coverity[member_decl] */
483 class SignBase : public BaseObject {
495 SignBase(Environment* env, v8::Local<v8::Object> wrap)
496 : BaseObject(env, wrap),
498 initialised_(false) {
504 EVP_MD_CTX_cleanup(&mdctx_);
508 void CheckThrow(Error error);
510 EVP_MD_CTX mdctx_; /* coverity[member_decl] */
511 const EVP_MD* md_; /* coverity[member_decl] */
515 class Sign : public SignBase {
518 static void Initialize(Environment* env, v8::Handle<v8::Object> target);
520 Error SignInit(const char* sign_type);
521 Error SignUpdate(const char* data, int len);
522 Error SignFinal(const char* key_pem,
524 const char* passphrase,
526 unsigned int *sig_len);
529 static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
530 static void SignInit(const v8::FunctionCallbackInfo<v8::Value>& args);
531 static void SignUpdate(const v8::FunctionCallbackInfo<v8::Value>& args);
532 static void SignFinal(const v8::FunctionCallbackInfo<v8::Value>& args);
534 Sign(Environment* env, v8::Local<v8::Object> wrap) : SignBase(env, wrap) {
535 MakeWeak<Sign>(this);
539 class Verify : public SignBase {
541 static void Initialize(Environment* env, v8::Handle<v8::Object> target);
543 Error VerifyInit(const char* verify_type);
544 Error VerifyUpdate(const char* data, int len);
545 Error VerifyFinal(const char* key_pem,
549 bool* verify_result);
552 static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
553 static void VerifyInit(const v8::FunctionCallbackInfo<v8::Value>& args);
554 static void VerifyUpdate(const v8::FunctionCallbackInfo<v8::Value>& args);
555 static void VerifyFinal(const v8::FunctionCallbackInfo<v8::Value>& args);
557 Verify(Environment* env, v8::Local<v8::Object> wrap) : SignBase(env, wrap) {
558 MakeWeak<Verify>(this);
562 class PublicKeyCipher {
564 typedef int (*EVP_PKEY_cipher_init_t)(EVP_PKEY_CTX *ctx);
565 typedef int (*EVP_PKEY_cipher_t)(EVP_PKEY_CTX *ctx,
566 unsigned char *out, size_t *outlen,
567 const unsigned char *in, size_t inlen);
574 template <Operation operation,
575 EVP_PKEY_cipher_init_t EVP_PKEY_cipher_init,
576 EVP_PKEY_cipher_t EVP_PKEY_cipher>
577 static bool Cipher(const char* key_pem,
579 const char* passphrase,
580 const unsigned char* data,
585 template <Operation operation,
586 EVP_PKEY_cipher_init_t EVP_PKEY_cipher_init,
587 EVP_PKEY_cipher_t EVP_PKEY_cipher>
588 static void Cipher(const v8::FunctionCallbackInfo<v8::Value>& args);
591 class DiffieHellman : public BaseObject {
599 static void Initialize(Environment* env, v8::Handle<v8::Object> target);
601 bool Init(int primeLength, int g);
602 bool Init(const char* p, int p_len, int g);
603 bool Init(const char* p, int p_len, const char* g, int g_len);
606 static void DiffieHellmanGroup(
607 const v8::FunctionCallbackInfo<v8::Value>& args);
608 static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
609 static void GenerateKeys(const v8::FunctionCallbackInfo<v8::Value>& args);
610 static void GetPrime(const v8::FunctionCallbackInfo<v8::Value>& args);
611 static void GetGenerator(const v8::FunctionCallbackInfo<v8::Value>& args);
612 static void GetPublicKey(const v8::FunctionCallbackInfo<v8::Value>& args);
613 static void GetPrivateKey(const v8::FunctionCallbackInfo<v8::Value>& args);
614 static void ComputeSecret(const v8::FunctionCallbackInfo<v8::Value>& args);
615 static void SetPublicKey(const v8::FunctionCallbackInfo<v8::Value>& args);
616 static void SetPrivateKey(const v8::FunctionCallbackInfo<v8::Value>& args);
617 static void VerifyErrorGetter(
618 v8::Local<v8::String> property,
619 const v8::PropertyCallbackInfo<v8::Value>& args);
621 DiffieHellman(Environment* env, v8::Local<v8::Object> wrap)
622 : BaseObject(env, wrap),
626 MakeWeak<DiffieHellman>(this);
630 bool VerifyContext();
637 class Certificate : public AsyncWrap {
639 static void Initialize(Environment* env, v8::Handle<v8::Object> target);
641 v8::Handle<v8::Value> CertificateInit(const char* sign_type);
642 bool VerifySpkac(const char* data, unsigned int len);
643 const char* ExportPublicKey(const char* data, int len);
644 const char* ExportChallenge(const char* data, int len);
647 static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
648 static void VerifySpkac(const v8::FunctionCallbackInfo<v8::Value>& args);
649 static void ExportPublicKey(const v8::FunctionCallbackInfo<v8::Value>& args);
650 static void ExportChallenge(const v8::FunctionCallbackInfo<v8::Value>& args);
652 Certificate(Environment* env, v8::Local<v8::Object> wrap)
653 : AsyncWrap(env, wrap, AsyncWrap::PROVIDER_CRYPTO) {
654 MakeWeak<Certificate>(this);
658 bool EntropySource(unsigned char* buffer, size_t length);
659 #ifndef OPENSSL_NO_ENGINE
660 void SetEngine(const v8::FunctionCallbackInfo<v8::Value>& args);
661 #endif // !OPENSSL_NO_ENGINE
662 void InitCrypto(v8::Handle<v8::Object> target);
664 } // namespace crypto
667 #endif // SRC_NODE_CRYPTO_H_